For a specific reason i need to place .text
section at the very end of my ELF file.
I've tried to achieve this in this way:
I took default large linker script and moved .text
section to the very end of SECTIONS { ... }
part.
$ readelf -S beronew
[ #] Name Type Address Offset
Size Size.Ent Flags - - Alignment
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .data PROGBITS 00000000006000b0 000000b0
000000000000003b 0000000000000000 WA 0 0 1
[ 2] .text PROGBITS 0000000000a000f0 000000f0
00000000000003e9 0000000000000000 AX 0 0 1
[ 3] .shstrtab STRTAB 0000000000000000 000004d9
0000000000000027 0000000000000000 0 0 1
[ 4] .symtab SYMTAB 0000000000000000 00000680
0000000000000438 0000000000000018 5 41 8
[ 5] .strtab STRTAB 0000000000000000 00000ab8
0000000000000258 0000000000000000 0 0 1
What i see is that ld
added extra sections after my "ending" section. To replace them i used -nostdlib -s
linker option (to not use stdlib (just in case) and omit all symbol information).
Run $ readelf -S beronew
one more time:
[ #] Name Type Address Offset
Size Size.Ent Flags - - Alignment
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .data PROGBITS 00000000006000b0 000000b0
000000000000003b 0000000000000000 WA 0 0 1
[ 2] .text PROGBITS 0000000000a000f0 000000f0
00000000000003e9 0000000000000000 AX 0 0 1
[ 3] .shstrtab STRTAB 0000000000000000 000004d9
0000000000000017 0000000000000000 0 0 1
Section header string table is still there. I've tried $strip -R .shstrtab beronew
. It had no effect, section is still there.
This section is only 0x17 bytes long but i couldn't achieve my goal. Then i looked at hexdump of my file:
$ hexdump beronew
...
00004d0 0060 c748 bfc6 6000 0000 732e 7368 7274
00004e0 6174 0062 642e 7461 0061 742e 7865 0074
00004f0 0000 0000 0000 0000 0000 0000 0000 0000
*
0000530 000b 0000 0001 0000 0003 0000 0000 0000
0000540 00b0 0060 0000 0000 00b0 0000 0000 0000
0000550 003b 0000 0000 0000 0000 0000 0000 0000
...
What i see is that there is another code after sections part. According to ELF structure it is Section header table
at the end of file. So even if i remove somehow .shstrtab
section, there still will be this header at the end.
So my question is how can i place my .text
section at the very end of file? I don't really need to remove all the sections and headers so if You know a (better) way to achieve this, it will be highly appreciated.
.
.
P.S. For those who wonder why do i need this:
This ELF file (beronew
) contains rutime library. It will be used as "header" for another file that generates asm instructions with some logic in opcode form. This opcode will be added to the very end of beronew
. Then i'm gonna patch sh_size
field in .text
's section header to be able to run my recently added 'code'.
(One more question: Is this all that i need to patch in case 'text' section is the last one in file?)
P.P.S. I know that this is a bad architecture but it is my course project - porting an app that was built this way in Win32 to Linux64, and now I'm stuck at the point where i merge runtime library "header" file and "logic" part because i can't place .text
section at the end of ELF.
Thanks one more time!
.
UPD:
Based on fuz's comment i've tried to add PHDRS to simple linker script as this:
PHDRS
{
headers PT_PHDR PHDRS ;
data PT_LOAD ;
bss PT_LOAD ;
text PT_LOAD ;
}
SECTIONS
{
. = 0x200000;
.data : { *(.data) *(COMMON) } :data
.bss : { *(.bss) } :bss
.text : { *(.text) } :text
}
but it doesn't seem to work now.
For someone who wonder how after all I've managed to get this working there is an answer:
I've made a linker script that placed text section after the data section (here is the script). But there were some debugging sections at the end of file like Shstrtab section and so on (picture below). So I've converted this file byte-by-byte into string.
After this I got an elf on a picture below
in a string-of-bytes form. Then I've just read some headers and found out where the section of code ends (right before the Shstrtab section), so I could split this string into 2 pieces. First one contained data for loader. Second one - for linker.
Then I've converted my 'extra' code into opcode form which is also an array (string) of bytes and concatenated it to the original .text
section. Next I've concatenated the ending part to it. So I've got a single file with my extra code in it.
To get this working I've edited values from picture below:
First column is a name of field that needs to be edited (it corresponds to picture of elf structure).
Second column is an offset from the beginning of file to the beginning of the field. Let function s(xxx)
be the the size_of(some_header_structure)
and injSize
be the size of my injected extra code. And values like 0x18, 0x20, 0x28
are the offsets of fields inside their strucures (section_headers, program_headers, elf_headers).
Third one represents the value that should replace that original one.
*note that represented elf is and ELF64 so widths of some fields differ from ELF32's ones.
After I've made all this I've managed to just run this new Elf file and it worked perfectly! Maybe (for sure) it's not the best solution but it works and it was a nice meterial for my research work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With