ELF section identification - linux

In an ELF executable file, I over-wrote all the section names by zero-valued bytes. Even then, the file can be linked and executed correctly. How does the OS identify various sections like the symbols-table, etc. in the file? I was under the impression that the section names serve this purpose. A related question is that what is the use of section names then?

I over-wrote all the section names ...
... the file can be linked ... correctly.
Unlike the object files used in 32-bit Windows, the section names in ELF object files are ignored if no linker script is used.
Each "PROGBITS" section contains flags that specify if the section is writeable, executable and/or not even part of the image (debug information).
(Actually, the object files used by Windows also have such flags, but they are typically set to 0 and the section name is used to distinguish between code and data sections.)
For other section types (such as symbol tables) it is clear how they have to be handled anyway.
... the file can be ... executed correctly.
For executable files and shared libraries, the sections are ignored anyway. Instead, the "program headers" of the file are used.
A "program header" tells the OS that a certain address range in the file must be loaded to memory. A "program header" may cover multiple sections. And "program headers" don't have names.
Example:
Sections:
Name Address Offset in file Length
.text 0x10100 0x100 0x30 read-only
.rodata 0x10130 0x130 0x20 read-only
.data 0x20250 0x150 0x10 read-write
.sdata 0x20260 0x160 0x10 read-write
Program headers:
Address Offset in file Length
0x10100 0x100 0x50 read-only
0x20250 0x150 0x20 read-write

Related

Modifying contents of data section in ELF

I have a program that initializes an array to 0. I have pointed the value of that array to a custom section using: __attribute__((section(".mysection")))
struct my_struct my_array[1] __attribute__((section(".mysection"))) = {
{0, 0},
};
The above is only so that we have a default and the linker marks the section as loadable and also includes it in the appropriate section list.
Now I wish to edit the generated ELF and modify the contents of that struct as I choose. I already have a binary file which contains the contents that I wish to have for that section.
I tried using --remove-section and --add-section but could not force the new section to be part of the sections.
Not sure if --update-section would help here, but the microcontroller I have doesn't have --update-section in objcopy and when I try the public version of it, that says that it doesnt support the bfd target.
FWIW, the ELF doesnt use any relocatable addresses etc. All addresses are physical addresses in memory.
Is there a way to achieve this? I just need to replace the contents of the section and modify its length.
In case other, more simple ways, are not suitable, you may implement such functionality by using ELFIO library.

Why does gdb on assembly program always start at the same address? [duplicate]

why when i debug asm source in gdb is 0x8048080 the address chosen for the starting entry point into code? this is just a relative offset, not an actual offset of into memory of an instruction, correct?
There is no special significance to address 0x8048080, but there is one for address 0x08048000.
The latter address is the default address, on which ld starts the first PT_LOAD segment on Linux/x86. On Linux/x86_64, the default is 0x400000, and you can change the default by using a "custom" linker script. You can also change where .text section starts with -Wl,-Ttext,0xNNNNNNNN flag.
After ld starts at 0x08048000, it adds space for program headers, and proceeds to link the rest of the executable according to its built-in linker script, which you can see if you pass in -Wl,--verbose to your link line.
For your program, the size of program headers appears to always be 0x80, so your .text section always starts at 0x8048080, but that is by no means universal.
When I link a trivial int main() { return 0; } program, I get &_start == &.text at 0x8048300, 0x8048178 or 0x8048360, depending on which compiler I use.
0×8048080 is the default entry point in virtual memory used by the Linux ld linker. You can change it to whatever you want.
for more details check out: http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints/

Moving the ELF64 relocation table

I'm attempting to move the .rela.plt relocation table of a shared object to the end of the file (Because I'm going to add new relocation entries in the future).
First, I read all entries in the .rela.plt section. The original section is at offset 0x528, and .rela.dyn is at 0x600. Then I copy the contents of .rela.dyn at the end of the file; to the offset 0xa528. I update the section header table entry for .rela.dyn by adding 0xa000 to both the sh_addr and sh_offset fields. I update the DT_RELA entry in the dynamic table with the new address; and finally I add a LOAD segment (with permissions RWX) to the end of the program header table.
As a result, R_X86_64_RELATIVE entries in the relocation table are resolved correctly; but the dynamic linker does not update the addresses for external calls in the GOT, therefore causing a segmentation fault. This does not happen in 32-bit shared objects.
What am I missing?
I solved the problem by adding the .rel.plt table right after the .rel.dyn table. That is, there should not be a single redundant byte in between; no alignment padding, no other sections, no whatever. The dynamic loader expects the relocation segments to be continuous for some reason. The JMPREL entry in the dynamic section seems redundant at x64.

Trouble using Libelf/Elfio libraries : ELF not executable anymore

I'm using Libelf and Elfio to try and add a new section to ELF files. I would like it to be executable, just like .text.
This is my problem : with Libelf, as soon as I load (elf_begin()), update (elf_update()) and release (elf_end()) my ELF, it stops to be executable (seg fault when launching). readelf -S displays the sections but returns also the error :
readelf: Warning: the .dynamic section is not contained within the dynamic segment
I didn't find any function in Libelf to "add" the .dynamic section to the DYNAMIC segment.
But I can do that with Elfio (with the segment->add_section_index() function), but then I have to manually add every other section to every other segment, as Elfio seems to overwrite them when loading the ELF.
Has anyone any experience with those libraries ?
My final goal is to be able to create a new executable section in the ELF, and modify its entry point to jump and execute directly that new section, in order to create a packer.
Libelf does not manage the segments (i. e. the program header entries) of an executable ELF file. It does, however, by default re-layout the sections when you call elf_update().
After the re-layout, the program header entries will most probably contain obsolete offsets.
The loader will then try (or refuse) to load sections from file offsets that were only correct before the edit.
Thus the error message: the .dynamic section is now at another offset in the file, and the loader notices that it is not in the DYNAMIC segment anymore.
You can tell Libelf that you are responsible for the section layout by calling elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT).
But then again, adding a new section will not be so easy anymore...

GNU linker script: Selective Run address(VMA) allocation

Iam writing a GNU linker script file and need a nudge in the right direction for the following problem.
The device for which the linker script is being created has flash for hosting text and rodata. It has also SRAM for hosting Data and BSS.
I have created variants of linker script which has:
- CODE and RODATA loaded into flash while DATA and BSS are in SRAM
- CODE, RODATA, DATA and BSS in SRAM
These work fine.
I must now create a variant of the linker script which has a majority of TEXT in flash. But certain routines with names ending with a well known suffix are to be loaded into SRAM.
For example, I would like Func1IRAMCode() and Func2__IRAMCode() to be loaded into SRAM section while every other function that does not have a IRAMCode suffix must be loaded into flash.
For portability reasons, I wont attach attribute(section) to these SRAM functions.
Here is where am stumbling.
The text section has the following rule:
.text :
{
*(.text .text.* .gnu.linkonce.t.*);
} > FLASH
.Misc :
{
* (.text.*IRAMCode);
} > SRAM
.data and .bss sections are defined seperately.
Problem is that *IRAMCode() are getting assigned flash addresses.
What is the syntax to exclude *IRAMCode from text section?
How have you solved this problem in your projects?
A way to do this, is to put your functions in another section (for example .sram.text ), to do this, use the section attribute of gcc for each specific function ( ex : __attribute__ (( section ".sram.text")) .
Thus, it will be very easy to wildcard the desired section to the SRAM.

Resources