2

I am writing a simplified version of the Linux readelf command.

I want to print section information, so I need the names of the sections. In the Elf64_Shdr struct, the sh_name variable only points me to an index in the shstrtab. But this does not seem to be an index in the shstrtab header. It is an index into its associated data.

I am wondering how to get there, since the ELF header only points me to the shstrtab section header, but not to its associated data. From what I can see in the hex dump of the file, the structure of the file is as follows:

ELF HEADER 
phdr1
phdr2
segment1
segment2
shstrtab strings (i want this address, to make use of the sh_name indices)
shdr1
shdr2
shdr3 (this is the shstrtab section)

Am I thinking this wrong? Can anybody please guide me in getting to the section names?

ib.
  • 27,830
  • 11
  • 80
  • 100
Alexander Grass
  • 384
  • 2
  • 11

2 Answers2

2

I just found the solution myself!

To get to the associated data of a section one just use the sh_offset in the Elf64_Shdr struct. If you add sh_offset to the start address of the file, you get directly to the section data.

ib.
  • 27,830
  • 11
  • 80
  • 100
Alexander Grass
  • 384
  • 2
  • 11
  • hi its the solution but can any one explain why it work ? i am adding `sh_name ` and we see the name – Ahmad Oct 16 '22 at 18:00
2

The code below can list the section header names.

int main()
{
    const char *file_name = "a.out";
    char *strtable, *sh_name;
    size_t file_size;
    struct stat st;
    void *data;
    Elf64_Ehdr hdr;
    Elf64_Shdr shdr;
    int i, fd, idx, strndx, stroff, spot;

    if ((fd = open(file_name, O_RDONLY)) < 0) {
        printf("fail to open %s\n", file_name);
        exit(EXIT_FAILURE);
    }

    data = MAP_FAILED;
    if (fstat(fd, &st) == 0) {
        file_size = st.st_size;
        data = mmap(0, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
    }
    close(fd);

    if (data == MAP_FAILED) {
        printf("Unable map\n");
        exit(EXIT_FAILURE);
    }

    // read elf header
    memcpy(&hdr, data, sizeof(hdr));

    // read section header string table header
    spot = hdr.e_shoff; // section header table file offset
    strndx = hdr.e_shstrndx; // section header string table index
    stroff = spot + strndx * hdr.e_shentsize;
    memcpy(&shdr, (char *)data + stroff, hdr.e_shentsize);

    // read section string table
    strtable = (char *)malloc(shdr.sh_size);
    memcpy(strtable, (char *)data + shdr.sh_offset, shdr.sh_size);

    for (i = 0; i < hdr.e_shnum; ++i) {
        memcpy(&shdr, (char *)data + spot, hdr.e_shentsize);
        spot += hdr.e_shentsize;
        sh_name = &strtable[shdr.sh_name];
        printf("[%d] %s\n", i, sh_name);
    }
}

Its output is as follows:

[0] 
[1] .interp
[2] .note.ABI-tag
[3] .gnu.hash
[4] .dynsym
[5] .dynstr
[6] .gnu.version
...
lylhw13
  • 101
  • 2
  • 6