C 加载和执行ELF-64目标代码--不确定最后的步骤
我正在编写一个用于试验ELF-64对象代码的小工具,用于解析和加载ELF-64对象代码,以便在父进程中执行。我相信我现在在正确的轨道上,但我需要一些最后步骤的指针 步骤1:我解析对象文件并提取所有必要的信息。我已经使用C 加载和执行ELF-64目标代码--不确定最后的步骤,c,loader,elf,C,Loader,Elf,我正在编写一个用于试验ELF-64对象代码的小工具,用于解析和加载ELF-64对象代码,以便在父进程中执行。我相信我现在在正确的轨道上,但我需要一些最后步骤的指针 步骤1:我解析对象文件并提取所有必要的信息。我已经使用readelf工具验证了这一点 步骤2:我使用SHF_ALLOC位设置和mmap内存循环遍历所有节头 第3步:这个看似简单而无用的对象只包含一个main-例程和一个return语句,据我所知,不需要重新定位符号(我已经用readelf仔细检查过)。我使用TinyCC编译,以避免发出
readelf
工具验证了这一点
步骤2:我使用SHF_ALLOC
位设置和mmap
内存循环遍历所有节头
第3步:这个看似简单而无用的对象只包含一个main
-例程和一个return语句,据我所知,不需要重新定位符号(我已经用readelf
仔细检查过)。我使用TinyCC编译,以避免发出.eh_frame
及其重定位项
但此时我需要将SHF_ALLOC
-位设置加载到内存中,这就是我怀疑自己做错的地方
offset = 0
foreach section in sections
if section.flags & SHF_ALLOC
memcpy(memory_address + offset, object_code + section.offset, section.size)
offset += section_size
第4步:我也不确定的最后一步。我需要调用已标记为可执行的分配内存
typedef int (main_t)(int argc, char* argv[]);
((main_t)object->address)(0, NULL);
我非常感谢您在这方面的意见。我认为这归结为对.text
-段到底包含什么以及它们是如何存储在内存中的缺乏理解
一些想法:
是否位于main
-段中的偏移量.text
0x0
- 分配的线段是否按正确的对齐顺序存储
另外,我打算很快了解重新定位符号。一次一步。:-) 您应该使用程序标题,而不是节标题。节头用于链接器,程序头用于加载程序 如果分配的段具有首选的
VirtAddr
(非预链接库的基虚拟地址可能为0,这意味着加载程序将为它们分配随机地址),则分配的段将转到它们的首选VirtAddr
ELF标头有一个入口点字段。这不是
main
,通常是一些libc初始化代码。。。初始化是否。。。然后调用main
。在将控制权传递到入口点之前,您应该设置所有符合ELF ABI的内容(在堆栈上放置argc
,argv
,envp
,auxv
,清除一些寄存器,我想就是这样了)。我在睡了一个好觉后成功地完成了这项操作
我首先使用objdump
反汇编了对象文件,该文件生成:
/tmp/test.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 81 ec 10 00 00 00 sub $0x10,%rsp
b: 48 89 7d f8 mov %rdi,-0x8(%rbp)
f: 48 89 75 f0 mov %rsi,-0x10(%rbp)
13: b8 c8 00 00 00 mov $0xc8,%eax
18: e9 00 00 00 00 jmpq 1d <main+0x1d>
1d: c9 leaveq
1e: c3 retq
/tmp/test.o:文件格式elf64-x86-64
第节的分解。正文:
0000000000000000 :
0:55推送%rbp
1:48 89 e5 mov%rsp,%rbp
4:48 81 ec 10 00 00分$0x10,%rsp
b:48 89 7d f8 mov%rdi,-0x8(%rbp)
f:488975F0MOV%rsi,-0x10(%rbp)
13:b8 c8 00 mov$0xc8,%eax
18:e9 00 jmpq 1d
1d:c9-q
1e:c3 retq
这个输出确保了main
的位置在0x0
,这意味着如果我将.text
-段正确地复制到mmap
返回的地址的内存中,我应该能够用问题中找到的片段调用它(我不确定)。它将使用调用线程的堆栈
然后,我在将节复制到内存时发现了一个小错误,其中节。offset
是从文件开始的偏移量,我错误地认为是从节头条目开始的偏移量
当我知道基本原理时,实验会简单得多。:-) 谢谢你的回答。尽管我的问题似乎过于专注于通过节头加载目标代码,不管是出于什么不正当的原因,但我还是成功地做到了这一点。详情请参阅我的答覆。下一步是更复杂的目标代码…:-)