'How to get the strings of shstrtab?
I am writing a simplified version of Linux' readelf.
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 hexdump 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?
Solution 1:[1]
I just found the solution myself!
To get to the associated data of a section one just use the sh_offset in its Elf64_Shdr struct. If you add sh_offset to the start address of the file, you get directly to the section data.
Solution 2:[2]
The code below can list the section header names.
int main()
{
const char *file_name;
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)) {
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);
}
}
result as follow:
[0]
[1] .interp
[2] .note.ABI-tag
[3] .gnu.hash
[4] .dynsym
[5] .dynstr
[6] .gnu.version
...
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | lylhw13 |