Reputation: 1461
I'm writing a small tool for experimenting with ELF-64 object code which is intended to parse and load ELF-64 object code for execution in the parent process. I believe I'm on the right track for now, but I need some pointers for the last steps.
Step 1: I parse the object file and extract all necessary information. I've verified this to be correct using the readelf
tool.
Step 2: I loop through all section headers with the SHF_ALLOC
-bit set and mmap
memory.
Step 3: This seemingly simple and useless object consisting of only a main
-routine and a return statement, requires no symbol relocating as far as I know (I've double-checked with readelf
). I've compiled with TinyCC to avoid .eh_frame
and its relocation entries from being emitted.
But at this point I need to load the sections with SHF_ALLOC
-bit set into memory, and this is where I suspect I'm doing wrong.
offset = 0
foreach section in sections
if section.flags & SHF_ALLOC
memcpy(memory_address + offset, object_code + section.offset, section.size)
offset += section_size
Step 4: The last step which I'm unsure of also. I need to call into the allocated memory which I've marked as executable.
typedef int (main_t)(int argc, char* argv[]);
((main_t)object->address)(0, NULL);
I'd very much appreciate some input on this. I believe it boils down to lack of understanding what exactly .text
-segment contains and how they are intended to be stored in memory.
Some thoughts:
main
located at offset 0x0
in the .text
-segment?Anything to point me in the right direction will help immensely! Thanks!
PS. I intend to learn about relocating symbols shortly. One step at a time. :-)
Upvotes: 4
Views: 1154
Reputation: 1461
I managed to pull this off after a good night's sleep.
I first disassembled the object file using objdump
which produced:
/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
This output ensured me the location of main
to be at 0x0
, meaning if I copy the .text
-segment correctly into memory at the address returned by mmap
, I should be able to call it with the snippet found in the question (which I was unsure about). It'll use the stack of the calling thread.
I then found a small error when copying the sections to memory where section.offset
was the offset from the beginning of the file, which I mistakenly assumed was the offset from the beginning of the section header entry.
It'll be much simpler to experiment when I know the basics work. :-)
Upvotes: 0
Reputation: 43748
You should use program headers for that, not section headers. Section headers are for the linker, program headers are for the loader.
Allocated segments are intended to go to their preferred VirtAddr
, if they have one (non-prelinked libraries may have a base virtual address of 0, which means the loader will assign them random addresses).
The ELF header has an entry point field. This is not main
, it's typically some libc initialization code that ... does initialization ... and then calls main
. You should have setup everything conforming to the ELF ABI prior to passing control to the entry point (put argc
, argv
, envp
, auxv
on the stack, clear some registers, I think that's it).
Upvotes: 2