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
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?
The section header table starts at starting point of your file
+ e_shoff
. The elf.h
file already has Elfxx_Shdr
struct and a Elfxx_Ehdr
struct, where xx above is either 32
or 64
for 32 bit or 64 bit respectively.
You can use e_shentsize
from the Elfxx_Ehdr
to get the section header string table index and then use sh_name
and sh_offset
from the Elfxx_Shdr
. sh_name
will give you an index of strtab
in which if you add the sh_offset
. That will give you the full name of the section. Same for the type, flag and others by using sh_type
, sh_flag
etc.
I would suggest you to go over executable and linkable format wikipedia article and the efl.h file man page.
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);
}
// ...
}