How to find the offset of the section header string table of an elf file?
Solution 1
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);
}
// ...
}
Solution 2
Here is how you would get to section name string table:
- The
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. - The
e_shentsize
field of the EHDR specifies the size in bytes of each section header table entry. - The
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.
Solution 3
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?
Admin
Updated on July 23, 2022Comments
-
Admin almost 2 years
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?
-
Floris about 11 yearsThen the string table would be at 17436 bytes into the file? It should be easy to check whether either of these is correct.