xref: /aosp_15_r20/external/elfutils/tests/elf-print-reloc-syms.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1 /* Copyright (C) 2024 Red Hat, Inc.
2    This file is part of elfutils.
3 
4    This file is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8 
9    elfutils is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16 
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20 
21 #include <fcntl.h>
22 #include <gelf.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <assert.h>
26 
27 static void
print_reloc_symnames(Elf * elf,Elf_Scn * scn,GElf_Shdr * shdr,size_t sh_entsize)28 print_reloc_symnames (Elf *elf, Elf_Scn *scn, GElf_Shdr *shdr, size_t sh_entsize)
29 {
30   int nentries = shdr->sh_size / sh_entsize;
31 
32   /* Get the data of the section.  */
33   Elf_Data *data = elf_getdata (scn, NULL);
34   assert (data != NULL);
35 
36   /* Get the symbol table information.  */
37   Elf_Scn *symscn = elf_getscn (elf, shdr->sh_link);
38   GElf_Shdr symshdr_mem;
39   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
40   Elf_Data *symdata = elf_getdata (symscn, NULL);
41   assert (symshdr != NULL);
42   assert (symdata != NULL);
43 
44   /* Search for the optional extended section index table.  */
45   Elf_Data *xndxdata = NULL;
46   int xndxscnidx = elf_scnshndx (scn);
47   if (xndxscnidx)
48     xndxdata = elf_getdata (elf_getscn (elf, xndxscnidx), NULL);
49 
50   /* Get the section header string table index.  */
51   size_t shstrndx;
52   assert (elf_getshdrstrndx (elf, &shstrndx) >= 0);
53 
54   printf("Section: %s\n", elf_strptr (elf, shstrndx, shdr->sh_name));
55   for (int cnt = 0; cnt < nentries; ++cnt)
56     {
57       GElf_Rel relmem;
58       GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
59 
60 
61       if (likely (rel != NULL))
62         {
63           GElf_Sym symmem;
64           Elf32_Word xndx;
65           GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
66                                             GELF_R_SYM (rel->r_info),
67                                             &symmem, &xndx);
68 
69 	  if (sym == NULL)
70 	    {
71 	      printf ("<SYM NOT FOUND>\n");
72 	      continue;
73 	    }
74 
75           if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
76             printf ("%s\n", elf_strptr (elf, symshdr->sh_link, sym->st_name));
77           else
78             {
79               /* This is a relocation against a STT_SECTION symbol.  */
80               GElf_Shdr secshdr_mem;
81               GElf_Shdr *secshdr;
82               secshdr = gelf_getshdr (elf_getscn (elf,
83                                                   sym->st_shndx == SHN_XINDEX
84                                                   ? xndx : sym->st_shndx),
85                                       &secshdr_mem);
86 
87 	      if (secshdr == NULL)
88 		printf("<SECTION NOT FOUND>\n");
89               else
90                 printf ("%s\n",
91 			elf_strptr (elf, shstrndx, secshdr->sh_name));
92             }
93         }
94     }
95 }
96 
97 int
main(int argc,char * argv[])98 main (int argc, char *argv[])
99 {
100   if (argc != 2)
101     {
102       printf ("Usage: elf_print_reloc_syms FILE\n");
103       return -1;
104     }
105 
106   elf_version (EV_CURRENT);
107 
108   int fd = open(argv[1], O_RDONLY);
109   assert (fd != -1);
110 
111   Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
112   assert (elf != NULL);
113 
114   size_t shnums;
115   assert (elf_getshdrnum (elf, &shnums) >= 0);
116 
117   Elf_Scn *scn = NULL;
118   while ((scn = elf_nextscn (elf, scn)) != NULL)
119     {
120       GElf_Shdr shdr_mem;
121       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
122 
123       if (shdr != NULL)
124 	{
125 	  /* Print the names of symbols referred to by relocations.  */
126 	  if (shdr->sh_type == SHT_REL)
127 	    {
128 	      size_t sh_entsize = gelf_fsize (elf, ELF_T_REL, 1, EV_CURRENT);
129 	      print_reloc_symnames (elf, scn, shdr, sh_entsize);
130 	    }
131 	  else if (shdr->sh_type == SHT_RELA)
132 	    {
133 	      size_t sh_entsize = gelf_fsize (elf, ELF_T_RELA, 1, EV_CURRENT);
134 	      print_reloc_symnames (elf, scn, shdr, sh_entsize);
135 	    }
136 	}
137     }
138 
139   elf_end (elf);
140   close (fd);
141   return 0;
142 }
143