我正在构建一个 RISC-V 模拟器,它基本上将整个 ELF 文件加载到内存中。
到目前为止,我使用了 risc-v 基金会提供的预编译测试二进制文件,该二进制文件在本节的开头处方便地有一个入口点.text。
例如:
> riscv32-unknown-elf-objdump ../riscv32i-emulator/tests/simple -d
../riscv32i-emulator/tests/simple: file format elf32-littleriscv
Disassembly of section .text.init:
80000000 <_start>:
80000000: 0480006f j 80000048 <reset_vector>
...
Run Code Online (Sandbox Code Playgroud)
进入这个项目时,我对 ELF 文件了解不多,所以我只是假设每个 ELF 的入口点与该部分的开头完全相同.text。
当我编译自己的二进制文件时出现了问题,我发现实际的入口点并不总是与该部分的开头相同.text,但它可能位于其中的任何位置,如下所示:
> riscv32-unknown-elf-objdump a.out -d
a.out: file format elf32-littleriscv
Disassembly of section .text:
00010074 <register_fini>:
10074: 00000793 li a5,0
10078: 00078863 beqz a5,10088 <register_fini+0x14>
1007c: 00010537 lui a0,0x10
10080: 43850513 addi a0,a0,1080 # 10438 <__libc_fini_array>
10084: 3a00006f j 10424 <atexit> …Run Code Online (Sandbox Code Playgroud) 我在 NASM 中有以下“uppercaser.asm”汇编程序,它将用户输入的所有小写字母转换为大写:
section .bss
Buff resb 1
section .data
section .text
global _start
_start:
nop ; This no-op keeps the debugger happy
Read: mov eax,3 ; Specify sys_read call
mov ebx,0 ; Specify File Descriptor 0: Standard Input
mov ecx,Buff ; Pass offset of the buffer to read to
mov edx,1 ; Tell sys_read to read one char from stdin
int 80h ; Call sys_read
cmp eax,0 ; Look at sys_read's return value in EAX
je Exit ; Jump …Run Code Online (Sandbox Code Playgroud) 环境:linux,用户空间应用程序通过g ++从几个C++文件创建(结果是ELF)
遍历构造函数列表时出现问题(SIGSEGV)
( __CTOR_LIST__ )
(注意:通过此列表调用的代码是每个类的一种系统初始化, 而不是我编写的构造函数代码)
__CTOR_LIST__
当我通过程序通过GDB步进时,问题(SIGSEGV)不存在
为了调试这个我正在寻找一种方法来在调用之前添加自己的代码
"_do_global_ctors_aux"
有什么提示吗?
谢谢,
乌韦
readelf -l /bin/bash 给我这个:
程序标题:
类型偏移VirtAddr PhysAddr
FileSiz MemSiz标志对齐
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 RE 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001a 0x000000000000001a R 1
[请求程序解释器:/lib/ld-linux-x86-64.so.2]
加载0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000aeef4 0x00000000000aeef4稀土200000
加载0x00000000000afde0 0x00000000006afde0 0x00000000006afde0
0x0000000000003cec 0x000000000000d3c8 读写200000
动态0x00000000000afdf8 0x00000000006afdf8 0x00000000006afdf8
0x0000000000000200 0x0000000000000200读写8
注意0x0000000000000254 0x0000000000400254 0x0000000000400254
0x0000000000000044 0x0000000000000044 R 4
GNU_EH_FRAME 0x000000000009dbc0 0x000000000049dbc0 0x000000000049dbc0
0x0000000000002bb4 0x0000000000002bb4 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000读写8
GNU_RELRO 0x00000000000afde0 0x00000000006afde0 0x00000000006afde0
0x0000000000000220 0x0000000000000220 R 1
为什么在某些细分市场中MemSiz不等于?包含但不包含的存储区应该怎么办?FileSizLOADMemSizFileSiz
我有Linux内核并尝试使用objcopy工具生成ELF Header,下面是第一步
objcopy -I binary -B i386 -O elf32-i386 --rename-section .data=.text linux_kernel.bin main.o
Run Code Online (Sandbox Code Playgroud)
在此之后我想使用readelf -s main.o读取符号表,但是输出下面的奇怪符号
Symbol table '.symtab' contains 5 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 SECTION LOCAL DEFAULT 1
2: 00000000 0 NOTYPE GLOBAL DEFAULT 1 _binary_linux_kernel_bin_
3: 004df650 0 NOTYPE GLOBAL DEFAULT 1 _binary_linux_kernel_bin_
4: 004df650 0 NOTYPE GLOBAL DEFAULT ABS _binary_linux_kernel_bin_
Run Code Online (Sandbox Code Playgroud)
现在应该可以看到像这样的符号
_binary_linux_kernel_bin_start
_binary_linux_kernel_bin__end
_binary_linux_kernel_bin_size
Run Code Online (Sandbox Code Playgroud)
任何人都可以让我知道我在哪里做错了吗?还是期待一个?
为什么我想看到正确的符号,因为必须做类似下面的事情
--entry_point=_binary_linux_kernel_bin_start
Run Code Online (Sandbox Code Playgroud) 根据我的理解,C/C++程序在内存中看起来像这样:

我想知道以下内容:
谢谢,
我的环境:
CentOS 6.5
Run Code Online (Sandbox Code Playgroud)
我需要提取ELF文件的一些部分.
当我使用dd如下命令时,我没有问题:
$dd if=a.out of=a.cut1 bs=1 skip=16
Run Code Online (Sandbox Code Playgroud)
另一方面,当我cut按如下方式使用命令时,创建的文件的大小比我预期的要小得多:
$cut --bytes=16- a.out > a.cut2
Run Code Online (Sandbox Code Playgroud)
#include <stdio.h>
int main()
{
printf("Hello world\n");
}
Run Code Online (Sandbox Code Playgroud)
然后,我按上述执行dd和cut命令,我有以下大小的文件:
a.out - 6415 bytes
a.cut1 - 6399 bytes
a.cut2 - 6356 bytes
Run Code Online (Sandbox Code Playgroud)
我想知道为什么cut命令减小了比我指定的更多的大小.
是否可以执行存储在char数组中的原始二进制文件?我尝试这样做:
#include "stdio.h"
int main(int argc, char **argv)
{
FILE *f = fopen(argv[1],"r");
if(!f)
return 1;
fseek(f,0,SEEK_END);
long l=ftell(f);
rewind(f);
char *buf = malloc(l+1);
fread(buf,1,l,f);
fclose(f);
void (*func)() = (void(*))buf;
func();
}
Run Code Online (Sandbox Code Playgroud)
但它只给我的段错误.我正在研究自己的操作系统(从头开始),所以我摆脱了它们.
我有一个elf二进制文件,它具有以下dynsym符号表作为输出readelf:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000400440 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
4: 0000000000400460 0 FUNC GLOBAL DEFAULT UND fgets@GLIBC_2.2.5 (2)
Run Code Online (Sandbox Code Playgroud)
该value栏是什么意思?由于此表有400440for printf,这是否意味着动态链接器必须映射printf到该地址?如果是,这个值是如何决定的?是随机的吗?
编辑:另外,这是带有gcc的linux x86-64
我有一个包含大量C++测试文件的项目.每个测试文件都声明一个这样的类:
// test1.cpp
...
class Foo { void bar() {...} };
...
Run Code Online (Sandbox Code Playgroud)
和
// test2.cpp
...
class Foo { void bar() {...} };
...
Run Code Online (Sandbox Code Playgroud)
等等.
在测试套件变得非常大并且Foo某些测试模块中的类内容变得不同之前,一切都很好.在联系方面出现问题.每个ELF文件中的类的方法被声明为公共弱(nm符号中的"W" )符号,并且它导致调用方法的错误实例,例如来自的tests1.cpp调用.Foo::bar()tests2.cpp
如何将一个实例class Foo与另一个实例隔离开来?
宣布课程__attributes__ ((visibility ("hidden")))没有帮助,符号仍然是公开的.
同样可以肯定的是我可以使用命名空间,但我更愿意避免使用此选项.
有任何想法吗?