user16986383
user16986383

Reputation:

Print the names of the sections headers of an elf file


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(&sectHdr, 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(&sectHdr, 1, sizeof sectHdr, ElfFile);

    // print section name
    if (sectHdr.sh_name);
      name = SectNames + sectHdr.sh_name;
    printf("%2u %s\n", idx, name);
  }

  // ...
}

I am trying to print all the names of the sections header but there is something I don't understand. Why do we need to use : fseek(ElfFile, elfHdr.e_shoff + elfHdr.e_shstrndx * sizeof (sectHdr), SEEK_SET); and not just
fseek(ElfFile, elfHdr.e_shoff, SEEK_SET); I'm just a little confused cuz I don't why it has to be elfHdr.e_shoff + elfHdr.e_shstrndx * sizeof (sectHdr) whereas elfHdr.e_shoff indicate the start of the start of section headers

Upvotes: 0

Views: 1567

Answers (1)

Employed Russian
Employed Russian

Reputation: 213385

Why do we need to use

To read section headers (which are fixed-length records), you need to fseek(..., elfHdr.e_shoff, SEEK_SET).

But that's not where the names (variable-length strings) are.

To read strings, you need to read the header for a particular (shstrndx) section (so you know where to find its contents), and then read the contents of that section. Which is exactly what this code does:

  // first, read its header
  fseek(ElfFile, elfHdr.e_shoff + elfHdr.e_shstrndx * sizeof (sectHdr), SEEK_SET);
  fread(&sectHdr, 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);

Update:

so why do we need to multiply?

In shstrndx you have the index of the section in which strings reside. Suppose this index is 17. So you want to read the contents of 17th section.

To get to the 0th section header, you need to seek to
elfHdr.sh_offset + 0*elfHdr.e_shentsize.

To get the 2nd section header, you need to seek to
elfHdr.sh_offset + 2*elfHdr.e_shentsize.

To get the 17th section header, you need to seek to
elfHdr.sh_offset + 17*elfHdr.e_shentsize.

To get to shstrndxth section header, you need to seek to
elfHdr.sh_offset + elfHdr.e_shstrndx*elfHdr.e_shentsize.

P.S.

Multiplying by sizeof(sectHdr) is technically incorrect -- you should multiply by elfHdr.e_shentsize instead.

This doesn't matter in practice -- I've never seen a machine on which e_shentsize != sizeof(sectHdr), but such a machine could exist.

Upvotes: 1

Related Questions