On Thu, Aug 06, 2015 at 05:14:25PM +0200, Kai Wasserbäch wrote:
> > Could you compile the following with:
> > gcc -g -lelf -o elfrel elfrel.c
>
> this does not work for several reasons:
> 1. I certainly need -std=c99 for the inline initialisation of the
> counter in the for() statement.
Ah, yes, this system has gcc 5.1 which defaults to gnu11.
> 2. *section (first used in »gelf_getshdr(section, §ion_header)«) isn't
> defined/filled anywhere:
> [...]
> Long story short: did you paste the entire/correct code?
Drat, so sorry. I must have copy/pasted an earlier version, that didn't
even compile. Attached is a version I double checked, that includes one
extra check (the size of the .text section). It gives the following output
for me:
$ for i in 794488_elfs/libelf*/*; do ./elfrel $i; done
file: 794488_elfs/libelf1/dump.elf.EL5kJT
.text code size: 24
Nothing found
file: 794488_elfs/libelf1/dump.elf.J4EnbO
.text code size: 11c
symbols: 5
1: not global or undefined
2: not global or undefined
3: not global or undefined
4: not global or undefined
5: 0
relocations: 2
0: 10, SCRATCH_RSRC_DWORD1
1: 2c, SCRATCH_RSRC_DWORD0
file: 794488_elfs/libelfg0/dump.elf.7NnBvc
.text code size: 24
Nothing found
file: 794488_elfs/libelfg0/dump.elf.ahPsJJ
.text code size: 11c
symbols: 5
1: not global or undefined
2: not global or undefined
3: not global or undefined
4: not global or undefined
5: 0
relocations: 2
0: 10, SCRATCH_RSRC_DWORD1
1: 2c, SCRATCH_RSRC_DWORD0
file: 794488_elfs/libelfg0/dump.elf.DYTjdO
.text code size: 28
Nothing found
file: 794488_elfs/libelfg0/dump.elf.Lke6Xg
.text code size: 38
Nothing found
Could you run it against old/new libelf to see if anything is different.
If not, then I am looking for the bug in the wrong place.
Thanks,
Mark
#include <gelf.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int
main (int argc, char **argv)
{
elf_version(EV_CURRENT);
printf ("file: %s\n", argv[1]);
int fd = open (argv[1], O_RDONLY);
Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
size_t section_str_index;
elf_getshdrstrndx(elf, §ion_str_index);
size_t reloc_count, symbol_sh_link, symbol_count;
Elf_Data *relocs, *symbols;
Elf_Scn *section = NULL;
while ((section = elf_nextscn(elf, section)))
{
const char *name;
GElf_Shdr section_header;
if (gelf_getshdr(section, §ion_header) != §ion_header)
{
fprintf(stderr, "Failed to read ELF section header\n");
return -1;
}
name = elf_strptr(elf, section_str_index, section_header.sh_name);
if (strncmp(name, ".symtab", 7) == 0)
{
symbols = elf_getdata(section, NULL);
symbol_sh_link = section_header.sh_link;
symbol_count = section_header.sh_size / section_header.sh_entsize;
}
else if (strcmp (name, ".rel.text") == 0)
{
relocs = elf_getdata(section, NULL);
reloc_count = section_header.sh_size / section_header.sh_entsize;
}
else if (strcmp (name, ".text") == 0)
{
Elf_Data *section_data = elf_getdata(section, NULL);
printf (".text code size: %zx\n", section_data->d_size);
}
}
if (!relocs || !symbols || !reloc_count)
{
printf("Nothing found\n");
return -1;
}
printf ("symbols: %zd\n", symbol_count);
GElf_Sym symbol;
size_t i = 0;
while (gelf_getsym (symbols, i++, &symbol))
{
if (GELF_ST_BIND(symbol.st_info) != STB_GLOBAL
|| symbol.st_shndx == 0)
{
printf ("%zd: not global or undefined\n", i);
continue;
}
printf ("%zd: %" PRIx64 "\n", i, symbol.st_value);
}
printf ("relocations: %zd\n", reloc_count);
for (size_t i = 0; i < reloc_count; i++)
{
GElf_Sym symbol;
GElf_Rel rel;
char *symbol_name;
gelf_getrel(relocs, i, &rel);
gelf_getsym(symbols, GELF_R_SYM(rel.r_info), &symbol);
symbol_name = elf_strptr(elf, symbol_sh_link, symbol.st_name);
printf ("%zd: %" PRIx64 ", %s\n", i, rel.r_offset, symbol_name);
}
return 0;
}