I have to write a C program that prints an ELF file. I'm having trouble figuring out where the section header string table is.
Let's say I have a file that gave me the following output with:
readelf -h
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 17636 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 23
Section header string table index: 20
and with:
readelf -S:
There are 23 section headers, starting at offset 0x44e4:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000028 00 AX 0 0 4
[ 2] .rel.text REL 00000000 0049d0 000018 08 21 1 4
[ 3] .data PROGBITS 00000000 00005c 000000 00 WA 0 0 4
[ 4] .bss NOBITS 00000000 00005c 000000 00 WA 0 0 4
[ 5] .rodata PROGBITS 00000000 00005c 00000a 00 A 0 0 1
[ 6] .debug_info PROGBITS 00000000 000066 00008f 00 0 0 1
[ 7] .rel.debug_info REL 00000000 0049e8 0000b0 08 21 6 4
[ 8] .debug_abbrev PROGBITS 00000000 0000f5 000041 00 0 0 1
[ 9] .debug_loc PROGBITS 00000000 000136 000038 00 0 0 1
[10] .debug_aranges PROGBITS 00000000 00016e 000020 00 0 0 1
[11] .rel.debug_arange REL 00000000 004a98 000010 08 21 10 4
[12] .debug_line PROGBITS 00000000 00018e 0001b3 00 0 0 1
[13] .rel.debug_line REL 00000000 004aa8 000008 08 21 12 4
[14] .debug_macinfo PROGBITS 00000000 000341 003fb9 00 0 0 1
[15] .debug_str PROGBITS 00000000 0042fa 0000bf 01 MS 0 0 1
[16] .comment PROGBITS 00000000 0043b9 00002b 01 MS 0 0 1
[17] .note.GNU-stack PROGBITS 00000000 0043e4 000000 00 0 0 1
[18] .eh_frame PROGBITS 00000000 0043e4 000038 00 A 0 0 4
[19] .rel.eh_frame REL 00000000 004ab0 000008 08 21 18 4
[20] .shstrtab STRTAB 00000000 00441c 0000c5 00 0 0 1
[21] .symtab SYMTAB 00000000 00487c 000130 10 22 16 4
[22] .strtab STRTAB 00000000 0049ac 000021 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
How would I be able to calculate the location of the section header string table?
The Global Offset Table, or GOT, is a section of a computer program's (executables and shared libraries) memory used to enable computer program code compiled as an ELF file to run correctly, independent of the memory address where the program's code or data is loaded at runtime.
Section header (Shdr) A file's section header table lets one locate all the file's sections. The section header table is an array of Elf32_Shdr or Elf64_Shdr structures. The ELF header's e_shoff member gives the byte offset from the beginning of the file to the section header table.
-S --sections --section-headers Displays the information contained in the file's section headers, if it has any. -g --section-groups Displays the information contained in the file's section groups, if it has any.
To find them the ELF header is used, which is located at the very start of the file. The first bytes contain the elf magic "\x7fELF" , followed by the class ID (32 or 64 bit ELF file), the data format ID (little endian/big endian), the machine type, etc. Finally, the entry point of this file is at address 0x0.
This is what I do:
#pragma pack(push,1)
typedef struct
{
uint8 e_ident[16];
uint16 e_type;
uint16 e_machine;
uint32 e_version;
uint32 e_entry;
uint32 e_phoff;
uint32 e_shoff;
uint32 e_flags;
uint16 e_ehsize;
uint16 e_phentsize;
uint16 e_phnum;
uint16 e_shentsize;
uint16 e_shnum;
uint16 e_shstrndx;
} Elf32Hdr;
typedef struct
{
uint32 sh_name;
uint32 sh_type;
uint32 sh_flags;
uint32 sh_addr;
uint32 sh_offset;
uint32 sh_size;
uint32 sh_link;
uint32 sh_info;
uint32 sh_addralign;
uint32 sh_entsize;
} Elf32SectHdr;
#pragma pack(pop)
{
FILE* ElfFile = NULL;
char* SectNames = NULL;
Elf32Hdr elfHdr;
Elf32SectHdr sectHdr;
uint idx;
// ...
// read ELF header
fread(&elfHdr, 1, sizeof elfHdr, ElfFile);
// read section name string table
// first, read its header
fseek(ElfFile, elfHdr.e_shoff + elfHdr.e_shstrndx * sizeof sectHdr, SEEK_SET);
fread(§Hdr, 1, sizeof sectHdr, ElfFile);
// next, read the section, string data
SectNames = malloc(sectHdr.sh_size);
fseek(ElfFile, sectHdr.sh_offset, SEEK_SET);
fread(SectNames, 1, sectHdr.sh_size, ElfFile);
// read all section headers
for (idx = 0; idx < elfHdr.e_shnum; idx++)
{
const char* name = "";
fseek(ElfFile, elfHdr.e_shoff + idx * sizeof sectHdr, SEEK_SET);
fread(§Hdr, 1, sizeof sectHdr, ElfFile);
// print section name
if (sectHdr.sh_name);
name = SectNames + sectHdr.sh_name;
printf("%2u %s\n", idx, name);
}
// ...
}
Here is how you would get to section name string table:
e_shstrndx
field of the ELF Executable Header (EHDR) specifies the index of the section header table entry describing the string table containing section names.e_shentsize
field of the EHDR specifies the size in bytes of each section header table entry.e_shoff
field of the EHDR specifies the file offset to the start of the section header table.Thus the header entry for the string table will be at file offset:
header_table_entry_offset = (e_shentsize * e_shstrndx) + e_shoff
Depending on the ELF class of the object, this header table entry will be either an Elf32_Shdr
or an Elf64_Shdr
. Note that the file representation of the header table entry may differ from its in-memory representation on the host that your program is running on.
The sh_offset
field in the header entry will specify the starting file offset of the string table, while the sh_size
field will specify its size.
Further reading: The "libelf by Example" tutorial covers the ELF Executable Header and ELF Section Header Table in greater depth.
It seems that the one you want is STRTAB, which has an offset of 0x441c (line [20]). The headers start 17636 bytes into the file (according to
Start of section headers: 17636 (bytes into file)
So I am going to guess that your string table starts at 17636 + 17436 = 35072 bytes from the start of the file.
I could be completely wrong, but that's where I would start. Do you know how to use od
or some such utility to do a dump of file bytes?
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