C 加载和执行ELF-64目标代码--不确定最后的步骤

C 加载和执行ELF-64目标代码--不确定最后的步骤,c,loader,elf,C,Loader,Elf,我正在编写一个用于试验ELF-64对象代码的小工具,用于解析和加载ELF-64对象代码,以便在父进程中执行。我相信我现在在正确的轨道上,但我需要一些最后步骤的指针 步骤1:我解析对象文件并提取所有必要的信息。我已经使用readelf工具验证了这一点 步骤2:我使用SHF_ALLOC位设置和mmap内存循环遍历所有节头 第3步:这个看似简单而无用的对象只包含一个main-例程和一个return语句,据我所知,不需要重新定位符号(我已经用readelf仔细检查过)。我使用TinyCC编译,以避免发出

我正在编写一个用于试验ELF-64对象代码的小工具,用于解析和加载ELF-64对象代码,以便在父进程中执行。我相信我现在在正确的轨道上,但我需要一些最后步骤的指针

步骤1:我解析对象文件并提取所有必要的信息。我已经使用
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
是从文件开始的偏移量,我错误地认为是从节头条目开始的偏移量


当我知道基本原理时,实验会简单得多。:-)

谢谢你的回答。尽管我的问题似乎过于专注于通过节头加载目标代码,不管是出于什么不正当的原因,但我还是成功地做到了这一点。详情请参阅我的答覆。下一步是更复杂的目标代码…:-)