/* Copyright (C) 2024 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
elfutils is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
#include
static void
print_reloc_symnames (Elf *elf, Elf_Scn *scn, GElf_Shdr *shdr, size_t sh_entsize)
{
int nentries = shdr->sh_size / sh_entsize;
/* Get the data of the section. */
Elf_Data *data = elf_getdata (scn, NULL);
assert (data != NULL);
/* Get the symbol table information. */
Elf_Scn *symscn = elf_getscn (elf, shdr->sh_link);
GElf_Shdr symshdr_mem;
GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
Elf_Data *symdata = elf_getdata (symscn, NULL);
assert (symshdr != NULL);
assert (symdata != NULL);
/* Search for the optional extended section index table. */
Elf_Data *xndxdata = NULL;
int xndxscnidx = elf_scnshndx (scn);
if (xndxscnidx)
xndxdata = elf_getdata (elf_getscn (elf, xndxscnidx), NULL);
/* Get the section header string table index. */
size_t shstrndx;
assert (elf_getshdrstrndx (elf, &shstrndx) >= 0);
printf("Section: %s\n", elf_strptr (elf, shstrndx, shdr->sh_name));
for (int cnt = 0; cnt < nentries; ++cnt)
{
GElf_Rel relmem;
GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
if (likely (rel != NULL))
{
GElf_Sym symmem;
Elf32_Word xndx;
GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
GELF_R_SYM (rel->r_info),
&symmem, &xndx);
if (sym == NULL)
{
printf ("\n");
continue;
}
if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
printf ("%s\n", elf_strptr (elf, symshdr->sh_link, sym->st_name));
else
{
/* This is a relocation against a STT_SECTION symbol. */
GElf_Shdr secshdr_mem;
GElf_Shdr *secshdr;
secshdr = gelf_getshdr (elf_getscn (elf,
sym->st_shndx == SHN_XINDEX
? xndx : sym->st_shndx),
&secshdr_mem);
if (secshdr == NULL)
printf("\n");
else
printf ("%s\n",
elf_strptr (elf, shstrndx, secshdr->sh_name));
}
}
}
}
int
main (int argc, char *argv[])
{
if (argc != 2)
{
printf ("Usage: elf_print_reloc_syms FILE\n");
return -1;
}
elf_version (EV_CURRENT);
int fd = open(argv[1], O_RDONLY);
assert (fd != -1);
Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
assert (elf != NULL);
size_t shnums;
assert (elf_getshdrnum (elf, &shnums) >= 0);
Elf_Scn *scn = NULL;
while ((scn = elf_nextscn (elf, scn)) != NULL)
{
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
if (shdr != NULL)
{
/* Print the names of symbols referred to by relocations. */
if (shdr->sh_type == SHT_REL)
{
size_t sh_entsize = gelf_fsize (elf, ELF_T_REL, 1, EV_CURRENT);
print_reloc_symnames (elf, scn, shdr, sh_entsize);
}
else if (shdr->sh_type == SHT_RELA)
{
size_t sh_entsize = gelf_fsize (elf, ELF_T_RELA, 1, EV_CURRENT);
print_reloc_symnames (elf, scn, shdr, sh_entsize);
}
}
}
elf_end (elf);
close (fd);
return 0;
}