我正在编写一个裸机 aarch64 程序(工具链 aarch64-unknown-elf-),我使用以下链接器脚本构建该程序:
SECTIONS {
.text : {
*(.text*)
}
.rodata ALIGN(CONSTANT(COMMONPAGESIZE)) : {
*(.rodata*)
}
.data ALIGN(CONSTANT(COMMONPAGESIZE)) : {
*(.data .data.*)
}
.bss (NOLOAD) : {
__bss_start = .;
*(.bss*)
*(COMMON)
__bss_end = .;
}
}
Run Code Online (Sandbox Code Playgroud)
使用 readelf 分析最终的可执行文件,我得到以下部分和段(即程序头):
There are 19 section headers, starting at offset 0xa4f58:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 010000 00f600 …Run Code Online (Sandbox Code Playgroud) 我正在编写一个ELF加载程序并研究ELF格式。我有一个简单的 hello world 二进制文件,是在 Fedora 38 中使用 Clang 16 创建的,它可以工作,并且 I\xe2\x80\x99ve 未编译\\链接到任何特定选项 ( clang hello.c -o hello)。我检查了程序头readelf,发现一些与我对 LOAD 和 DYNAMIC 头的理解不相符的东西。
例如:
\n\nProgram Headers:\n Type Offset VirtAddr PhysAddr\n FileSiz MemSiz Flags Align\n\xe2\x80\xa6\n LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000\n 0x00000000000004f0 0x00000000000004f0 R 0x1000\n LOAD 0x0000000000001000 0x0000000000401000 0x0000000000401000\n 0x000000000000016d 0x000000000000016d R E 0x1000\n LOAD 0x0000000000002000 0x0000000000402000 0x0000000000402000\n 0x00000000000000dc 0x00000000000000dc R 0x1000\n LOAD 0x0000000000002df8 0x0000000000403df8 0x0000000000403df8\n 0x0000000000000214 0x0000000000000218 RW 0x1000\n DYNAMIC 0x0000000000002e08 0x0000000000403e08 0x0000000000403e08\n 0x00000000000001d0 0x00000000000001d0 RW 0x8\nRun Code Online (Sandbox Code Playgroud)\n有两个问题我无法解决。请注意前三个 …
是否有可能获得.so使用调试信息(gcc .. -g)编译的linux共享库()的源代码?感谢您的时间.
我有一个要求,我想将索引与文件(以某种格式)相关联.我想知道我是否可以进行任何ELF操作并仍然确保保持一致性,因此,该文件在linux上运行良好.这里的想法是创建一个文件格式,可以通过某个API [自定义]查询以获取索引.
a)是否可以修改ELF头来存储索引(如上所述).
b)如果是,那么过程是什么?
最近我试着自己在linux平台上编写一个简单的编译器.
当谈到编译器的后端时,我决定在不使用第三方库的情况下生成ELF格式的二进制文件,例如libelf.
相反,我想通过使用该write()函数并控制ELF文件的所有细节,尝试将机器代码直接写入与ELF ABI 相对应的文件中.
这种方法的优点是我可以控制编译器的所有内容.
但我犹豫了.考虑到ELF ABI的详细程度,这种方式是否可行?
我希望有任何建议和指向现有的可用资源.
从该问题的第二个答案中可以看出,使用节的名称从内部获取指向程序特定节的指针非常简单。使用libelf,只需打开程序自己的文件,循环访问其中的所有节(由Elf64_Shdrstruct 表示),当节名称与所需的节名称匹配时停止,并使用存储在struct sh_addr元素中的指针Elf64_Shdr。在这种情况下,获取所需的指针非常简单,因为它是在ELF可执行文件中定义的。
但是,假设您有一个使用动态库的程序,并且需要获取指向该动态库的一部分的指针。由于其节的地址是在运行时定义的,如何获得指向动态库节的指针?
顺便说一句,动态库和主程序本身每个都有一个具有相同名称的部分(这是我需要获得的指针所在的部分)。因此,在这种情况下,这两个同名的段是否可能相邻存储在内存中,所以我只需要获取指向主文件段的指针(如我在第一段中所述)并添加偏移量即可到达动态库部分?
我正在使用binutils-2.21.53.0.1-6.fc16.x86_64.
我有一个小的目标文件,hello.o只有足够的"东西"来包含所有部分的内容:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040
000000000000005d 0000000000000000 AX 0 0 4
[ 2] .rela.text RELA 0000000000000000 00000808
0000000000000060 0000000000000018 15 1 8
[ 3] .data PROGBITS 0000000000000000 000000a0
0000000000000000 0000000000000000 WA 0 0 4
[ 4] .bss NOBITS 0000000000000000 000000a0
0000000000000053 0000000000000000 WA 0 0 32
[ 5] .rodata PROGBITS …Run Code Online (Sandbox Code Playgroud) 我正在使用gcc版本4.8.2(Debian 4.8.2-21)在x86_64机器上的Debian 7系统上静态编译一个非常简单的hello-world单行程序:
gcc test.c -static -o test
Run Code Online (Sandbox Code Playgroud)
我得到一个可执行的ELF文件,其中包括以下部分:
[17] .tdata PROGBITS 00000000006b4000 000b4000
0000000000000020 0000000000000000 WAT 0 0 8
[18] .tbss NOBITS 00000000006b4020 000b4020
0000000000000030 0000000000000000 WAT 0 0 8
[19] .init_array INIT_ARRAY 00000000006b4020 000b4020
0000000000000010 0000000000000000 WA 0 0 8
[20] .fini_array FINI_ARRAY 00000000006b4030 000b4030
0000000000000010 0000000000000000 WA 0 0 8
[21] .jcr PROGBITS 00000000006b4040 000b4040
0000000000000008 0000000000000000 WA 0 0 8
[22] .data.rel.ro PROGBITS 00000000006b4060 000b4060
00000000000000e4 0000000000000000 WA 0 0 32
Run Code Online (Sandbox Code Playgroud)
注意,该.tbss部分分配在地址0x6b4020..0x6b4050(0x30字节),它与.init_array0x6b4020..0x6b4030(0x10字节) …
我已经拆解了一个程序.我在开始时看到一个AND带ESP和的指令0xFFFFFFF0.
这个面具是什么意思?这是对齐问题吗?
它是32位x86的ELF可执行文件.
我正试图通过e_entry字段直接修补ELF文件的入口点:
Elf64_Ehdr *ehdr = NULL;
Elf64_Phdr *phdr = NULL;
Elf64_Shdr *shdr = NULL;
if (argc < 2)
{
printf("Usage: %s <executable>\n", argv[0]);
exit(EXIT_SUCCESS);
}
fd = open(argv[1], O_RDWR);
if (fd < 0)
{
perror("open");
exit(EXIT_FAILURE);
}
if (fstat(fd, &st) < 0)
{
perror("fstat");
exit(EXIT_FAILURE);
}
/* map whole executable into memory */
mapped_file = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mapped_file < 0)
{
perror("mmap");
exit(EXIT_FAILURE);
}
// check for an ELF file
check_elf(mapped_file, argv); …Run Code Online (Sandbox Code Playgroud)