17

I'm trying to get the correct offset to the section name by accessing the sh_name member of an elf file, but it keep giving me zero, or null...

I'm supposed to only use mmap() and the elf.h - no helper functions

So I did:

void* map_start = mmap(0, fd_stat.st_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0))
header = (Elf32_Ehdr *) map_start;  
secoff = header->e_shoff;    
section = (Elf32_Shdr *)(map_start + secoff); 

but when I do:

printf("name offset = %d\n", (section->sh_name));

it keeps giving me 0... what am I doing wrong?

0x90
  • 39,472
  • 36
  • 165
  • 245
user1431301
  • 221
  • 1
  • 2
  • 7

1 Answers1

31

when i do printf("name offset = %d\n", (section->sh_name)); it keeps giving me 0... what am I doiing wrong?

You are not doing anything wrong.

The sh_name is not a pointer, it's an offset into .shstrtab section, which contains the actual section name.

You can find the .shstrtab section from header->e_shstrndx.

Update:

isnt it suppose to print the offset as an int?

It prints 0. What made you believe that 0 is not an int?

but of do i print the name?

Perhaps this example will explain?

#include <sys/stat.h>
#include <sys/mman.h>
#include <elf.h>
#include <stdio.h>
#include <fcntl.h>


int print_shdr(const char *const fname, size_t size) {
  int fd = open(fname, O_RDONLY);
  char *p = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);

  Elf32_Ehdr *ehdr = (Elf32_Ehdr*)p;
  Elf32_Shdr *shdr = (Elf32_Shdr *)(p + ehdr->e_shoff);
  int shnum = ehdr->e_shnum;

  Elf32_Shdr *sh_strtab = &shdr[ehdr->e_shstrndx];
  const char *const sh_strtab_p = p + sh_strtab->sh_offset;

  for (int i = 0; i < shnum; ++i) {
    printf("%2d: %4d '%s'\n", i, shdr[i].sh_name,
           sh_strtab_p + shdr[i].sh_name);
  }

  return 0;
}

int main(int argc, char *argv[])
{
  struct stat st;
  const char *fname = "/proc/self/exe";

  if (argc > 1)
    fname = argv[1];

  if (stat(fname, &st) != 0) {
    perror("stat");
    return 1;
  }
  return print_shdr(fname, st.st_size);
}

$ gcc -g dump_shdr.c -m32 -std=c99
$ ./a.out
 0:    0 ''
 1:   27 '.interp'
 2:   35 '.note.ABI-tag'
 3:   49 '.note.gnu.build-id'
 4:   72 '.hash'
 5:   68 '.gnu.hash'
 6:   78 '.dynsym'
 7:   86 '.dynstr'
 8:   94 '.gnu.version'
 9:  107 '.gnu.version_r'
10:  122 '.rel.dyn'
11:  131 '.rel.plt'
12:  140 '.init'
13:  135 '.plt'
14:  146 '.text'
15:  152 '.fini'
16:  158 '.rodata'
17:  166 '.eh_frame'
18:  176 '.ctors'
19:  183 '.dtors'
20:  190 '.jcr'
21:  195 '.dynamic'
22:  204 '.got'
23:  209 '.got.plt'
24:  218 '.data'
25:  224 '.bss'
26:  229 '.comment'
27:  238 '.debug_aranges'
28:  253 '.debug_pubnames'
29:  269 '.debug_info'
30:  281 '.debug_abbrev'
31:  295 '.debug_line'
32:  307 '.debug_frame'
33:  320 '.debug_str'
34:  331 '.debug_loc'
35:   17 '.shstrtab'
36:    1 '.symtab'
37:    9 '.strtab'
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • i know its suppose to be an offset, but isnt it suppose to print the offset as an int when i put in in printf? how do i print the value - in whatever way its represented ?also, how do i get the actual name - i know i get the offset to the specific section in .shstrtab - but of do i print the name? i mean, how do i refer to the string table? i tried to do something like printf("%s",sction+header.shstrtab[nameoffset]); but that didnt work for me... – user1431301 Jun 03 '12 at 12:38
  • @EmployedRussian: Could you give an example how to do the reverse i.e, a code example how to create the string table and then the section with some values? – The Mask Mar 15 '14 at 16:45
  • @EmployedRussian do we really have to use **mmap** ? Can't we just use **open()** ? – Trey May 19 '18 at 19:21
  • 1
    @Trey you *have to* `open` before you can `mmap`, and my examples does. Your question is probably "can't we just use `read` instead of `mmap`?". Yes, you can. – Employed Russian May 19 '18 at 19:34
  • @EmployedRussian what are the advantages of using both functions then? – Trey May 19 '18 at 19:57
  • @Trey Your question makes no sense to me -- *which* both functions? You could try asking a new question (rather than doing so in the comments). – Employed Russian May 19 '18 at 20:46
  • @EmployedRussian Hey, I know it's been a while, but I was hoping you could help me. I was trying to do the exact same task, and my solution is exactly like yours, but I get a segmentation fault. I tried copying your solution and of course got the same result. When I print `sh_strtab->sh_offset`, I get a huge negative number (minus 800k or something), is that wrong? Could you help me figure out why this solution is not working? Thanks – Barak B Jun 01 '19 at 20:10
  • 1
    @BarakB Are you building this code with `-m32` flag? If you are building it as 64-bit binary, you'll need to replace `Elf32` with `Elf64` everywhere. – Employed Russian Jun 01 '19 at 21:36
  • @EmployedRussian Sorry to bother you, it appears I've made a silly mistake while copy-pasting. This works flawlessly. Thanks alot! – Barak B Jun 01 '19 at 22:52