xref: /aosp_15_r20/external/elfutils/src/objdump.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Print information from ELF file in human-readable form.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2005, 2006, 2007, 2009, 2011, 2012, 2014, 2015 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker    Written by Ulrich Drepper <[email protected]>, 2005.
5*7304104dSAndroid Build Coastguard Worker 
6*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker    it under the terms of the GNU General Public License as published by
8*7304104dSAndroid Build Coastguard Worker    the Free Software Foundation; either version 3 of the License, or
9*7304104dSAndroid Build Coastguard Worker    (at your option) any later version.
10*7304104dSAndroid Build Coastguard Worker 
11*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
12*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
13*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*7304104dSAndroid Build Coastguard Worker    GNU General Public License for more details.
15*7304104dSAndroid Build Coastguard Worker 
16*7304104dSAndroid Build Coastguard Worker    You should have received a copy of the GNU General Public License
17*7304104dSAndroid Build Coastguard Worker    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18*7304104dSAndroid Build Coastguard Worker 
19*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
20*7304104dSAndroid Build Coastguard Worker # include <config.h>
21*7304104dSAndroid Build Coastguard Worker #endif
22*7304104dSAndroid Build Coastguard Worker 
23*7304104dSAndroid Build Coastguard Worker #include <argp.h>
24*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
25*7304104dSAndroid Build Coastguard Worker #include <inttypes.h>
26*7304104dSAndroid Build Coastguard Worker #include <locale.h>
27*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
28*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
29*7304104dSAndroid Build Coastguard Worker #include <stdio_ext.h>
30*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
31*7304104dSAndroid Build Coastguard Worker #include <string.h>
32*7304104dSAndroid Build Coastguard Worker #include <unistd.h>
33*7304104dSAndroid Build Coastguard Worker 
34*7304104dSAndroid Build Coastguard Worker #include <libeu.h>
35*7304104dSAndroid Build Coastguard Worker #include <system.h>
36*7304104dSAndroid Build Coastguard Worker #include <color.h>
37*7304104dSAndroid Build Coastguard Worker #include <printversion.h>
38*7304104dSAndroid Build Coastguard Worker #include "../libebl/libeblP.h"
39*7304104dSAndroid Build Coastguard Worker 
40*7304104dSAndroid Build Coastguard Worker 
41*7304104dSAndroid Build Coastguard Worker /* Name and version of program.  */
42*7304104dSAndroid Build Coastguard Worker ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
43*7304104dSAndroid Build Coastguard Worker 
44*7304104dSAndroid Build Coastguard Worker /* Bug report address.  */
45*7304104dSAndroid Build Coastguard Worker ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
46*7304104dSAndroid Build Coastguard Worker 
47*7304104dSAndroid Build Coastguard Worker 
48*7304104dSAndroid Build Coastguard Worker /* Definitions of arguments for argp functions.  */
49*7304104dSAndroid Build Coastguard Worker static const struct argp_option options[] =
50*7304104dSAndroid Build Coastguard Worker {
51*7304104dSAndroid Build Coastguard Worker   { NULL, 0, NULL, 0, N_("Mode selection:"), 0 },
52*7304104dSAndroid Build Coastguard Worker   { "reloc", 'r', NULL, 0, N_("Display relocation information."), 0 },
53*7304104dSAndroid Build Coastguard Worker   { "full-contents", 's', NULL, 0,
54*7304104dSAndroid Build Coastguard Worker     N_("Display the full contents of all sections requested"), 0 },
55*7304104dSAndroid Build Coastguard Worker   { "disassemble", 'd', NULL, 0,
56*7304104dSAndroid Build Coastguard Worker     N_("Display assembler code of executable sections"), 0 },
57*7304104dSAndroid Build Coastguard Worker 
58*7304104dSAndroid Build Coastguard Worker   { NULL, 0, NULL, 0, N_("Output content selection:"), 0 },
59*7304104dSAndroid Build Coastguard Worker   { "section", 'j', "NAME", 0,
60*7304104dSAndroid Build Coastguard Worker     N_("Only display information for section NAME."), 0 },
61*7304104dSAndroid Build Coastguard Worker 
62*7304104dSAndroid Build Coastguard Worker   { NULL, 0, NULL, 0, NULL, 0 }
63*7304104dSAndroid Build Coastguard Worker };
64*7304104dSAndroid Build Coastguard Worker 
65*7304104dSAndroid Build Coastguard Worker /* Short description of program.  */
66*7304104dSAndroid Build Coastguard Worker static const char doc[] = N_("\
67*7304104dSAndroid Build Coastguard Worker Show information from FILEs (a.out by default).");
68*7304104dSAndroid Build Coastguard Worker 
69*7304104dSAndroid Build Coastguard Worker /* Strings for arguments in help texts.  */
70*7304104dSAndroid Build Coastguard Worker static const char args_doc[] = N_("[FILE...]");
71*7304104dSAndroid Build Coastguard Worker 
72*7304104dSAndroid Build Coastguard Worker /* Prototype for option handler.  */
73*7304104dSAndroid Build Coastguard Worker static error_t parse_opt (int key, char *arg, struct argp_state *state);
74*7304104dSAndroid Build Coastguard Worker 
75*7304104dSAndroid Build Coastguard Worker /* Parser children.  */
76*7304104dSAndroid Build Coastguard Worker static struct argp_child argp_children[] =
77*7304104dSAndroid Build Coastguard Worker   {
78*7304104dSAndroid Build Coastguard Worker     { &color_argp, 0, N_("Output formatting"), 2 },
79*7304104dSAndroid Build Coastguard Worker     { NULL, 0, NULL, 0}
80*7304104dSAndroid Build Coastguard Worker   };
81*7304104dSAndroid Build Coastguard Worker 
82*7304104dSAndroid Build Coastguard Worker /* Data structure to communicate with argp functions.  */
83*7304104dSAndroid Build Coastguard Worker static const struct argp argp =
84*7304104dSAndroid Build Coastguard Worker {
85*7304104dSAndroid Build Coastguard Worker   options, parse_opt, args_doc, doc, argp_children, NULL, NULL
86*7304104dSAndroid Build Coastguard Worker };
87*7304104dSAndroid Build Coastguard Worker 
88*7304104dSAndroid Build Coastguard Worker 
89*7304104dSAndroid Build Coastguard Worker /* Print symbols in file named FNAME.  */
90*7304104dSAndroid Build Coastguard Worker static int process_file (const char *fname, bool more_than_one);
91*7304104dSAndroid Build Coastguard Worker 
92*7304104dSAndroid Build Coastguard Worker /* Handle content of archive.  */
93*7304104dSAndroid Build Coastguard Worker static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
94*7304104dSAndroid Build Coastguard Worker 		      const char *suffix);
95*7304104dSAndroid Build Coastguard Worker 
96*7304104dSAndroid Build Coastguard Worker /* Handle ELF file.  */
97*7304104dSAndroid Build Coastguard Worker static int handle_elf (Elf *elf, const char *prefix, const char *fname,
98*7304104dSAndroid Build Coastguard Worker 		       const char *suffix);
99*7304104dSAndroid Build Coastguard Worker 
100*7304104dSAndroid Build Coastguard Worker 
101*7304104dSAndroid Build Coastguard Worker #define INTERNAL_ERROR(fname) \
102*7304104dSAndroid Build Coastguard Worker   error_exit (0, _("%s: INTERNAL ERROR %d (%s): %s"),      \
103*7304104dSAndroid Build Coastguard Worker 	      fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
104*7304104dSAndroid Build Coastguard Worker 
105*7304104dSAndroid Build Coastguard Worker 
106*7304104dSAndroid Build Coastguard Worker /* List of sections which should be used.  */
107*7304104dSAndroid Build Coastguard Worker static struct section_list
108*7304104dSAndroid Build Coastguard Worker {
109*7304104dSAndroid Build Coastguard Worker   bool is_name;
110*7304104dSAndroid Build Coastguard Worker   union
111*7304104dSAndroid Build Coastguard Worker   {
112*7304104dSAndroid Build Coastguard Worker     const char *name;
113*7304104dSAndroid Build Coastguard Worker     uint32_t scnndx;
114*7304104dSAndroid Build Coastguard Worker   };
115*7304104dSAndroid Build Coastguard Worker   struct section_list *next;
116*7304104dSAndroid Build Coastguard Worker } *section_list;
117*7304104dSAndroid Build Coastguard Worker 
118*7304104dSAndroid Build Coastguard Worker 
119*7304104dSAndroid Build Coastguard Worker /* If true print archive index.  */
120*7304104dSAndroid Build Coastguard Worker static bool print_relocs;
121*7304104dSAndroid Build Coastguard Worker 
122*7304104dSAndroid Build Coastguard Worker /* If true print full contents of requested sections.  */
123*7304104dSAndroid Build Coastguard Worker static bool print_full_content;
124*7304104dSAndroid Build Coastguard Worker 
125*7304104dSAndroid Build Coastguard Worker /* If true print disassembled output..  */
126*7304104dSAndroid Build Coastguard Worker static bool print_disasm;
127*7304104dSAndroid Build Coastguard Worker 
128*7304104dSAndroid Build Coastguard Worker 
129*7304104dSAndroid Build Coastguard Worker int
main(int argc,char * argv[])130*7304104dSAndroid Build Coastguard Worker main (int argc, char *argv[])
131*7304104dSAndroid Build Coastguard Worker {
132*7304104dSAndroid Build Coastguard Worker   /* We use no threads here which can interfere with handling a stream.  */
133*7304104dSAndroid Build Coastguard Worker   (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
134*7304104dSAndroid Build Coastguard Worker   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
135*7304104dSAndroid Build Coastguard Worker   (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
136*7304104dSAndroid Build Coastguard Worker 
137*7304104dSAndroid Build Coastguard Worker   /* Set locale.  */
138*7304104dSAndroid Build Coastguard Worker   (void) setlocale (LC_ALL, "");
139*7304104dSAndroid Build Coastguard Worker 
140*7304104dSAndroid Build Coastguard Worker   /* Make sure the message catalog can be found.  */
141*7304104dSAndroid Build Coastguard Worker   (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
142*7304104dSAndroid Build Coastguard Worker 
143*7304104dSAndroid Build Coastguard Worker   /* Initialize the message catalog.  */
144*7304104dSAndroid Build Coastguard Worker   (void) textdomain (PACKAGE_TARNAME);
145*7304104dSAndroid Build Coastguard Worker 
146*7304104dSAndroid Build Coastguard Worker   /* Parse and process arguments.  */
147*7304104dSAndroid Build Coastguard Worker   int remaining;
148*7304104dSAndroid Build Coastguard Worker   (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
149*7304104dSAndroid Build Coastguard Worker 
150*7304104dSAndroid Build Coastguard Worker   /* Tell the library which version we are expecting.  */
151*7304104dSAndroid Build Coastguard Worker   (void) elf_version (EV_CURRENT);
152*7304104dSAndroid Build Coastguard Worker 
153*7304104dSAndroid Build Coastguard Worker   int result = 0;
154*7304104dSAndroid Build Coastguard Worker   if (remaining == argc)
155*7304104dSAndroid Build Coastguard Worker     /* The user didn't specify a name so we use a.out.  */
156*7304104dSAndroid Build Coastguard Worker     result = process_file ("a.out", false);
157*7304104dSAndroid Build Coastguard Worker   else
158*7304104dSAndroid Build Coastguard Worker     {
159*7304104dSAndroid Build Coastguard Worker       /* Process all the remaining files.  */
160*7304104dSAndroid Build Coastguard Worker       const bool more_than_one = remaining + 1 < argc;
161*7304104dSAndroid Build Coastguard Worker 
162*7304104dSAndroid Build Coastguard Worker       do
163*7304104dSAndroid Build Coastguard Worker 	result |= process_file (argv[remaining], more_than_one);
164*7304104dSAndroid Build Coastguard Worker       while (++remaining < argc);
165*7304104dSAndroid Build Coastguard Worker     }
166*7304104dSAndroid Build Coastguard Worker 
167*7304104dSAndroid Build Coastguard Worker   return result;
168*7304104dSAndroid Build Coastguard Worker }
169*7304104dSAndroid Build Coastguard Worker 
170*7304104dSAndroid Build Coastguard Worker 
171*7304104dSAndroid Build Coastguard Worker /* Handle program arguments.  */
172*7304104dSAndroid Build Coastguard Worker static error_t
parse_opt(int key,char * arg,struct argp_state * state)173*7304104dSAndroid Build Coastguard Worker parse_opt (int key, char *arg,
174*7304104dSAndroid Build Coastguard Worker 	   struct argp_state *state __attribute__ ((unused)))
175*7304104dSAndroid Build Coastguard Worker {
176*7304104dSAndroid Build Coastguard Worker   /* True if any of the control options is set.  */
177*7304104dSAndroid Build Coastguard Worker   static bool any_control_option;
178*7304104dSAndroid Build Coastguard Worker 
179*7304104dSAndroid Build Coastguard Worker   switch (key)
180*7304104dSAndroid Build Coastguard Worker     {
181*7304104dSAndroid Build Coastguard Worker     case 'j':
182*7304104dSAndroid Build Coastguard Worker       {
183*7304104dSAndroid Build Coastguard Worker 	struct section_list *newp = xmalloc (sizeof (*newp));
184*7304104dSAndroid Build Coastguard Worker 	char *endp;
185*7304104dSAndroid Build Coastguard Worker 	newp->scnndx = strtoul (arg, &endp, 0);
186*7304104dSAndroid Build Coastguard Worker 	if (*endp == 0)
187*7304104dSAndroid Build Coastguard Worker 	  newp->is_name = false;
188*7304104dSAndroid Build Coastguard Worker 	else
189*7304104dSAndroid Build Coastguard Worker 	  {
190*7304104dSAndroid Build Coastguard Worker 	    newp->name = arg;
191*7304104dSAndroid Build Coastguard Worker 	    newp->is_name = true;
192*7304104dSAndroid Build Coastguard Worker 	  }
193*7304104dSAndroid Build Coastguard Worker 	newp->next = section_list;
194*7304104dSAndroid Build Coastguard Worker 	section_list = newp;
195*7304104dSAndroid Build Coastguard Worker       }
196*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
197*7304104dSAndroid Build Coastguard Worker       break;
198*7304104dSAndroid Build Coastguard Worker 
199*7304104dSAndroid Build Coastguard Worker     case 'd':
200*7304104dSAndroid Build Coastguard Worker       print_disasm = true;
201*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
202*7304104dSAndroid Build Coastguard Worker       break;
203*7304104dSAndroid Build Coastguard Worker 
204*7304104dSAndroid Build Coastguard Worker     case 'r':
205*7304104dSAndroid Build Coastguard Worker       print_relocs = true;
206*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
207*7304104dSAndroid Build Coastguard Worker       break;
208*7304104dSAndroid Build Coastguard Worker 
209*7304104dSAndroid Build Coastguard Worker     case 's':
210*7304104dSAndroid Build Coastguard Worker       print_full_content = true;
211*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
212*7304104dSAndroid Build Coastguard Worker       break;
213*7304104dSAndroid Build Coastguard Worker 
214*7304104dSAndroid Build Coastguard Worker     case ARGP_KEY_FINI:
215*7304104dSAndroid Build Coastguard Worker       if (! any_control_option)
216*7304104dSAndroid Build Coastguard Worker 	{
217*7304104dSAndroid Build Coastguard Worker 	  fputs (_("No operation specified.\n"), stderr);
218*7304104dSAndroid Build Coastguard Worker 	  argp_help (&argp, stderr, ARGP_HELP_SEE,
219*7304104dSAndroid Build Coastguard Worker 		     program_invocation_short_name);
220*7304104dSAndroid Build Coastguard Worker 	  exit (EXIT_FAILURE);
221*7304104dSAndroid Build Coastguard Worker 	}
222*7304104dSAndroid Build Coastguard Worker       /* We only use this for checking the number of arguments, we don't
223*7304104dSAndroid Build Coastguard Worker 	 actually want to consume them.  */
224*7304104dSAndroid Build Coastguard Worker       FALLTHROUGH;
225*7304104dSAndroid Build Coastguard Worker     default:
226*7304104dSAndroid Build Coastguard Worker       return ARGP_ERR_UNKNOWN;
227*7304104dSAndroid Build Coastguard Worker     }
228*7304104dSAndroid Build Coastguard Worker   return 0;
229*7304104dSAndroid Build Coastguard Worker }
230*7304104dSAndroid Build Coastguard Worker 
231*7304104dSAndroid Build Coastguard Worker 
232*7304104dSAndroid Build Coastguard Worker /* Open the file and determine the type.  */
233*7304104dSAndroid Build Coastguard Worker static int
process_file(const char * fname,bool more_than_one)234*7304104dSAndroid Build Coastguard Worker process_file (const char *fname, bool more_than_one)
235*7304104dSAndroid Build Coastguard Worker {
236*7304104dSAndroid Build Coastguard Worker   /* Open the file.  */
237*7304104dSAndroid Build Coastguard Worker   int fd = open (fname, O_RDONLY);
238*7304104dSAndroid Build Coastguard Worker   if (fd == -1)
239*7304104dSAndroid Build Coastguard Worker     {
240*7304104dSAndroid Build Coastguard Worker       error (0, errno, _("cannot open %s"), fname);
241*7304104dSAndroid Build Coastguard Worker       return 1;
242*7304104dSAndroid Build Coastguard Worker     }
243*7304104dSAndroid Build Coastguard Worker 
244*7304104dSAndroid Build Coastguard Worker   /* Now get the ELF descriptor.  */
245*7304104dSAndroid Build Coastguard Worker   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
246*7304104dSAndroid Build Coastguard Worker   if (elf != NULL)
247*7304104dSAndroid Build Coastguard Worker     {
248*7304104dSAndroid Build Coastguard Worker       if (elf_kind (elf) == ELF_K_ELF)
249*7304104dSAndroid Build Coastguard Worker 	{
250*7304104dSAndroid Build Coastguard Worker 	  int result = handle_elf (elf, more_than_one ? "" : NULL,
251*7304104dSAndroid Build Coastguard Worker 				   fname, NULL);
252*7304104dSAndroid Build Coastguard Worker 
253*7304104dSAndroid Build Coastguard Worker 	  if (elf_end (elf) != 0)
254*7304104dSAndroid Build Coastguard Worker 	    INTERNAL_ERROR (fname);
255*7304104dSAndroid Build Coastguard Worker 
256*7304104dSAndroid Build Coastguard Worker 	  if (close (fd) != 0)
257*7304104dSAndroid Build Coastguard Worker 	    error_exit (errno, _("while close `%s'"), fname);
258*7304104dSAndroid Build Coastguard Worker 
259*7304104dSAndroid Build Coastguard Worker 	  return result;
260*7304104dSAndroid Build Coastguard Worker 	}
261*7304104dSAndroid Build Coastguard Worker       else if (elf_kind (elf) == ELF_K_AR)
262*7304104dSAndroid Build Coastguard Worker 	{
263*7304104dSAndroid Build Coastguard Worker 	  int result = handle_ar (fd, elf, NULL, fname, NULL);
264*7304104dSAndroid Build Coastguard Worker 
265*7304104dSAndroid Build Coastguard Worker 	  if (elf_end (elf) != 0)
266*7304104dSAndroid Build Coastguard Worker 	    INTERNAL_ERROR (fname);
267*7304104dSAndroid Build Coastguard Worker 
268*7304104dSAndroid Build Coastguard Worker 	  if (close (fd) != 0)
269*7304104dSAndroid Build Coastguard Worker 	    error_exit (errno, _("while close `%s'"), fname);
270*7304104dSAndroid Build Coastguard Worker 
271*7304104dSAndroid Build Coastguard Worker 	  return result;
272*7304104dSAndroid Build Coastguard Worker 	}
273*7304104dSAndroid Build Coastguard Worker 
274*7304104dSAndroid Build Coastguard Worker       /* We cannot handle this type.  Close the descriptor anyway.  */
275*7304104dSAndroid Build Coastguard Worker       if (elf_end (elf) != 0)
276*7304104dSAndroid Build Coastguard Worker 	INTERNAL_ERROR (fname);
277*7304104dSAndroid Build Coastguard Worker     }
278*7304104dSAndroid Build Coastguard Worker 
279*7304104dSAndroid Build Coastguard Worker   error (0, 0, _("%s: File format not recognized"), fname);
280*7304104dSAndroid Build Coastguard Worker 
281*7304104dSAndroid Build Coastguard Worker   return 1;
282*7304104dSAndroid Build Coastguard Worker }
283*7304104dSAndroid Build Coastguard Worker 
284*7304104dSAndroid Build Coastguard Worker 
285*7304104dSAndroid Build Coastguard Worker static int
handle_ar(int fd,Elf * elf,const char * prefix,const char * fname,const char * suffix)286*7304104dSAndroid Build Coastguard Worker handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
287*7304104dSAndroid Build Coastguard Worker 	   const char *suffix)
288*7304104dSAndroid Build Coastguard Worker {
289*7304104dSAndroid Build Coastguard Worker   size_t fname_len = strlen (fname) + 1;
290*7304104dSAndroid Build Coastguard Worker   size_t prefix_len = prefix != NULL ? strlen (prefix) : 0;
291*7304104dSAndroid Build Coastguard Worker   char new_prefix[prefix_len + fname_len + 2];
292*7304104dSAndroid Build Coastguard Worker   size_t suffix_len = suffix != NULL ? strlen (suffix) : 0;
293*7304104dSAndroid Build Coastguard Worker   char new_suffix[suffix_len + 2];
294*7304104dSAndroid Build Coastguard Worker   Elf *subelf;
295*7304104dSAndroid Build Coastguard Worker   Elf_Cmd cmd = ELF_C_READ_MMAP;
296*7304104dSAndroid Build Coastguard Worker   int result = 0;
297*7304104dSAndroid Build Coastguard Worker 
298*7304104dSAndroid Build Coastguard Worker   char *cp = new_prefix;
299*7304104dSAndroid Build Coastguard Worker   if (prefix != NULL)
300*7304104dSAndroid Build Coastguard Worker     cp = stpcpy (cp, prefix);
301*7304104dSAndroid Build Coastguard Worker   cp = stpcpy (cp, fname);
302*7304104dSAndroid Build Coastguard Worker   stpcpy (cp, "[");
303*7304104dSAndroid Build Coastguard Worker 
304*7304104dSAndroid Build Coastguard Worker   cp = new_suffix;
305*7304104dSAndroid Build Coastguard Worker   if (suffix != NULL)
306*7304104dSAndroid Build Coastguard Worker     cp = stpcpy (cp, suffix);
307*7304104dSAndroid Build Coastguard Worker   stpcpy (cp, "]");
308*7304104dSAndroid Build Coastguard Worker 
309*7304104dSAndroid Build Coastguard Worker   /* Process all the files contained in the archive.  */
310*7304104dSAndroid Build Coastguard Worker   while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
311*7304104dSAndroid Build Coastguard Worker     {
312*7304104dSAndroid Build Coastguard Worker       /* The the header for this element.  */
313*7304104dSAndroid Build Coastguard Worker       Elf_Arhdr *arhdr = elf_getarhdr (subelf);
314*7304104dSAndroid Build Coastguard Worker 
315*7304104dSAndroid Build Coastguard Worker       /* Skip over the index entries.  */
316*7304104dSAndroid Build Coastguard Worker       if (strcmp (arhdr->ar_name, "/") != 0
317*7304104dSAndroid Build Coastguard Worker 	  && strcmp (arhdr->ar_name, "//") != 0)
318*7304104dSAndroid Build Coastguard Worker 	{
319*7304104dSAndroid Build Coastguard Worker 	  if (elf_kind (subelf) == ELF_K_ELF)
320*7304104dSAndroid Build Coastguard Worker 	    result |= handle_elf (subelf, new_prefix, arhdr->ar_name,
321*7304104dSAndroid Build Coastguard Worker 				  new_suffix);
322*7304104dSAndroid Build Coastguard Worker 	  else if (elf_kind (subelf) == ELF_K_AR)
323*7304104dSAndroid Build Coastguard Worker 	    result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
324*7304104dSAndroid Build Coastguard Worker 				 new_suffix);
325*7304104dSAndroid Build Coastguard Worker 	  else
326*7304104dSAndroid Build Coastguard Worker 	    {
327*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, _("%s%s%s: file format not recognized"),
328*7304104dSAndroid Build Coastguard Worker 		     new_prefix, arhdr->ar_name, new_suffix);
329*7304104dSAndroid Build Coastguard Worker 	      result = 1;
330*7304104dSAndroid Build Coastguard Worker 	    }
331*7304104dSAndroid Build Coastguard Worker 	}
332*7304104dSAndroid Build Coastguard Worker 
333*7304104dSAndroid Build Coastguard Worker       /* Get next archive element.  */
334*7304104dSAndroid Build Coastguard Worker       cmd = elf_next (subelf);
335*7304104dSAndroid Build Coastguard Worker       if (elf_end (subelf) != 0)
336*7304104dSAndroid Build Coastguard Worker 	INTERNAL_ERROR (fname);
337*7304104dSAndroid Build Coastguard Worker     }
338*7304104dSAndroid Build Coastguard Worker 
339*7304104dSAndroid Build Coastguard Worker   return result;
340*7304104dSAndroid Build Coastguard Worker }
341*7304104dSAndroid Build Coastguard Worker 
342*7304104dSAndroid Build Coastguard Worker 
343*7304104dSAndroid Build Coastguard Worker static void
show_relocs_x(Ebl * ebl,GElf_Shdr * shdr,Elf_Data * symdata,Elf_Data * xndxdata,size_t symstrndx,size_t shstrndx,GElf_Addr r_offset,GElf_Xword r_info,GElf_Sxword r_addend)344*7304104dSAndroid Build Coastguard Worker show_relocs_x (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *symdata,
345*7304104dSAndroid Build Coastguard Worker 	       Elf_Data *xndxdata, size_t symstrndx, size_t shstrndx,
346*7304104dSAndroid Build Coastguard Worker 	       GElf_Addr r_offset, GElf_Xword r_info, GElf_Sxword r_addend)
347*7304104dSAndroid Build Coastguard Worker {
348*7304104dSAndroid Build Coastguard Worker   int elfclass = gelf_getclass (ebl->elf);
349*7304104dSAndroid Build Coastguard Worker   char buf[128];
350*7304104dSAndroid Build Coastguard Worker 
351*7304104dSAndroid Build Coastguard Worker   printf ("%0*" PRIx64 " %-20s ",
352*7304104dSAndroid Build Coastguard Worker 	  elfclass == ELFCLASS32 ? 8 : 16, r_offset,
353*7304104dSAndroid Build Coastguard Worker 	  ebl_reloc_type_name (ebl, GELF_R_TYPE (r_info), buf, sizeof (buf)));
354*7304104dSAndroid Build Coastguard Worker 
355*7304104dSAndroid Build Coastguard Worker   Elf32_Word xndx;
356*7304104dSAndroid Build Coastguard Worker   GElf_Sym symmem;
357*7304104dSAndroid Build Coastguard Worker   GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (r_info),
358*7304104dSAndroid Build Coastguard Worker 				    &symmem, &xndx);
359*7304104dSAndroid Build Coastguard Worker 
360*7304104dSAndroid Build Coastguard Worker   if (sym == NULL)
361*7304104dSAndroid Build Coastguard Worker     printf ("<%s %ld>",
362*7304104dSAndroid Build Coastguard Worker 	    _("INVALID SYMBOL"), (long int) GELF_R_SYM (r_info));
363*7304104dSAndroid Build Coastguard Worker   else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
364*7304104dSAndroid Build Coastguard Worker     printf ("%s",
365*7304104dSAndroid Build Coastguard Worker 	    elf_strptr (ebl->elf, symstrndx, sym->st_name));
366*7304104dSAndroid Build Coastguard Worker   else
367*7304104dSAndroid Build Coastguard Worker     {
368*7304104dSAndroid Build Coastguard Worker       GElf_Shdr destshdr_mem;
369*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *destshdr;
370*7304104dSAndroid Build Coastguard Worker       destshdr = gelf_getshdr (elf_getscn (ebl->elf,
371*7304104dSAndroid Build Coastguard Worker 					   sym->st_shndx == SHN_XINDEX
372*7304104dSAndroid Build Coastguard Worker 					   ? xndx : sym->st_shndx),
373*7304104dSAndroid Build Coastguard Worker 			       &destshdr_mem);
374*7304104dSAndroid Build Coastguard Worker 
375*7304104dSAndroid Build Coastguard Worker       if (shdr == NULL || destshdr == NULL)
376*7304104dSAndroid Build Coastguard Worker 	printf ("<%s %ld>",
377*7304104dSAndroid Build Coastguard Worker 		_("INVALID SECTION"),
378*7304104dSAndroid Build Coastguard Worker 		(long int) (sym->st_shndx == SHN_XINDEX
379*7304104dSAndroid Build Coastguard Worker 			    ? xndx : sym->st_shndx));
380*7304104dSAndroid Build Coastguard Worker       else
381*7304104dSAndroid Build Coastguard Worker 	printf ("%s",
382*7304104dSAndroid Build Coastguard Worker 		elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
383*7304104dSAndroid Build Coastguard Worker     }
384*7304104dSAndroid Build Coastguard Worker 
385*7304104dSAndroid Build Coastguard Worker   if (r_addend != 0)
386*7304104dSAndroid Build Coastguard Worker     {
387*7304104dSAndroid Build Coastguard Worker       char sign = '+';
388*7304104dSAndroid Build Coastguard Worker       if (r_addend < 0)
389*7304104dSAndroid Build Coastguard Worker 	{
390*7304104dSAndroid Build Coastguard Worker 	  sign = '-';
391*7304104dSAndroid Build Coastguard Worker 	  r_addend = -r_addend;
392*7304104dSAndroid Build Coastguard Worker 	}
393*7304104dSAndroid Build Coastguard Worker       printf ("%c%#" PRIx64, sign, r_addend);
394*7304104dSAndroid Build Coastguard Worker     }
395*7304104dSAndroid Build Coastguard Worker   putchar ('\n');
396*7304104dSAndroid Build Coastguard Worker }
397*7304104dSAndroid Build Coastguard Worker 
398*7304104dSAndroid Build Coastguard Worker 
399*7304104dSAndroid Build Coastguard Worker static void
show_relocs_rel(Ebl * ebl,GElf_Shdr * shdr,Elf_Data * data,Elf_Data * symdata,Elf_Data * xndxdata,size_t symstrndx,size_t shstrndx)400*7304104dSAndroid Build Coastguard Worker show_relocs_rel (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
401*7304104dSAndroid Build Coastguard Worker 		 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
402*7304104dSAndroid Build Coastguard Worker 		 size_t shstrndx)
403*7304104dSAndroid Build Coastguard Worker {
404*7304104dSAndroid Build Coastguard Worker   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
405*7304104dSAndroid Build Coastguard Worker   int nentries = shdr->sh_size / sh_entsize;
406*7304104dSAndroid Build Coastguard Worker 
407*7304104dSAndroid Build Coastguard Worker   for (int cnt = 0; cnt < nentries; ++cnt)
408*7304104dSAndroid Build Coastguard Worker     {
409*7304104dSAndroid Build Coastguard Worker       GElf_Rel relmem;
410*7304104dSAndroid Build Coastguard Worker       GElf_Rel *rel;
411*7304104dSAndroid Build Coastguard Worker 
412*7304104dSAndroid Build Coastguard Worker       rel = gelf_getrel (data, cnt, &relmem);
413*7304104dSAndroid Build Coastguard Worker       if (rel != NULL)
414*7304104dSAndroid Build Coastguard Worker 	show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
415*7304104dSAndroid Build Coastguard Worker 		       rel->r_offset, rel->r_info, 0);
416*7304104dSAndroid Build Coastguard Worker     }
417*7304104dSAndroid Build Coastguard Worker }
418*7304104dSAndroid Build Coastguard Worker 
419*7304104dSAndroid Build Coastguard Worker 
420*7304104dSAndroid Build Coastguard Worker static void
show_relocs_rela(Ebl * ebl,GElf_Shdr * shdr,Elf_Data * data,Elf_Data * symdata,Elf_Data * xndxdata,size_t symstrndx,size_t shstrndx)421*7304104dSAndroid Build Coastguard Worker show_relocs_rela (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
422*7304104dSAndroid Build Coastguard Worker 		  Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
423*7304104dSAndroid Build Coastguard Worker 		  size_t shstrndx)
424*7304104dSAndroid Build Coastguard Worker {
425*7304104dSAndroid Build Coastguard Worker   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
426*7304104dSAndroid Build Coastguard Worker   int nentries = shdr->sh_size / sh_entsize;
427*7304104dSAndroid Build Coastguard Worker 
428*7304104dSAndroid Build Coastguard Worker   for (int cnt = 0; cnt < nentries; ++cnt)
429*7304104dSAndroid Build Coastguard Worker     {
430*7304104dSAndroid Build Coastguard Worker       GElf_Rela relmem;
431*7304104dSAndroid Build Coastguard Worker       GElf_Rela *rel;
432*7304104dSAndroid Build Coastguard Worker 
433*7304104dSAndroid Build Coastguard Worker       rel = gelf_getrela (data, cnt, &relmem);
434*7304104dSAndroid Build Coastguard Worker       if (rel != NULL)
435*7304104dSAndroid Build Coastguard Worker 	show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
436*7304104dSAndroid Build Coastguard Worker 		       rel->r_offset, rel->r_info, rel->r_addend);
437*7304104dSAndroid Build Coastguard Worker     }
438*7304104dSAndroid Build Coastguard Worker }
439*7304104dSAndroid Build Coastguard Worker 
440*7304104dSAndroid Build Coastguard Worker 
441*7304104dSAndroid Build Coastguard Worker static bool
section_match(Elf * elf,uint32_t scnndx,GElf_Shdr * shdr,size_t shstrndx)442*7304104dSAndroid Build Coastguard Worker section_match (Elf *elf, uint32_t scnndx, GElf_Shdr *shdr, size_t shstrndx)
443*7304104dSAndroid Build Coastguard Worker {
444*7304104dSAndroid Build Coastguard Worker   if (section_list == NULL)
445*7304104dSAndroid Build Coastguard Worker     return true;
446*7304104dSAndroid Build Coastguard Worker 
447*7304104dSAndroid Build Coastguard Worker   struct section_list *runp = section_list;
448*7304104dSAndroid Build Coastguard Worker   const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
449*7304104dSAndroid Build Coastguard Worker 
450*7304104dSAndroid Build Coastguard Worker   do
451*7304104dSAndroid Build Coastguard Worker     {
452*7304104dSAndroid Build Coastguard Worker       if (runp->is_name)
453*7304104dSAndroid Build Coastguard Worker 	{
454*7304104dSAndroid Build Coastguard Worker 	  if (name && strcmp (runp->name, name) == 0)
455*7304104dSAndroid Build Coastguard Worker 	    return true;
456*7304104dSAndroid Build Coastguard Worker 	}
457*7304104dSAndroid Build Coastguard Worker       else
458*7304104dSAndroid Build Coastguard Worker 	{
459*7304104dSAndroid Build Coastguard Worker 	  if (runp->scnndx == scnndx)
460*7304104dSAndroid Build Coastguard Worker 	    return true;
461*7304104dSAndroid Build Coastguard Worker 	}
462*7304104dSAndroid Build Coastguard Worker 
463*7304104dSAndroid Build Coastguard Worker       runp = runp->next;
464*7304104dSAndroid Build Coastguard Worker     }
465*7304104dSAndroid Build Coastguard Worker   while (runp != NULL);
466*7304104dSAndroid Build Coastguard Worker 
467*7304104dSAndroid Build Coastguard Worker   return false;
468*7304104dSAndroid Build Coastguard Worker }
469*7304104dSAndroid Build Coastguard Worker 
470*7304104dSAndroid Build Coastguard Worker 
471*7304104dSAndroid Build Coastguard Worker static int
show_relocs(Ebl * ebl,const char * fname,uint32_t shstrndx)472*7304104dSAndroid Build Coastguard Worker show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx)
473*7304104dSAndroid Build Coastguard Worker {
474*7304104dSAndroid Build Coastguard Worker   int elfclass = gelf_getclass (ebl->elf);
475*7304104dSAndroid Build Coastguard Worker 
476*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
477*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
478*7304104dSAndroid Build Coastguard Worker     {
479*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
480*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
481*7304104dSAndroid Build Coastguard Worker 
482*7304104dSAndroid Build Coastguard Worker       if (shdr == NULL)
483*7304104dSAndroid Build Coastguard Worker 	INTERNAL_ERROR (fname);
484*7304104dSAndroid Build Coastguard Worker 
485*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
486*7304104dSAndroid Build Coastguard Worker 	{
487*7304104dSAndroid Build Coastguard Worker 	  if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
488*7304104dSAndroid Build Coastguard Worker 	    continue;
489*7304104dSAndroid Build Coastguard Worker 
490*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr destshdr_mem;
491*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf,
492*7304104dSAndroid Build Coastguard Worker 							  shdr->sh_info),
493*7304104dSAndroid Build Coastguard Worker 					      &destshdr_mem);
494*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (destshdr == NULL))
495*7304104dSAndroid Build Coastguard Worker 	    continue;
496*7304104dSAndroid Build Coastguard Worker 
497*7304104dSAndroid Build Coastguard Worker 	  printf (_("\nRELOCATION RECORDS FOR [%s]:\n"
498*7304104dSAndroid Build Coastguard Worker 			   "%-*s TYPE                 VALUE\n"),
499*7304104dSAndroid Build Coastguard Worker 		  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
500*7304104dSAndroid Build Coastguard Worker 		  elfclass == ELFCLASS32 ? 8 : 16, _("OFFSET"));
501*7304104dSAndroid Build Coastguard Worker 
502*7304104dSAndroid Build Coastguard Worker 	  /* Get the data of the section.  */
503*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *data = elf_getdata (scn, NULL);
504*7304104dSAndroid Build Coastguard Worker 	  if (data == NULL)
505*7304104dSAndroid Build Coastguard Worker 	    continue;
506*7304104dSAndroid Build Coastguard Worker 
507*7304104dSAndroid Build Coastguard Worker 	  /* Get the symbol table information.  */
508*7304104dSAndroid Build Coastguard Worker 	  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
509*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr symshdr_mem;
510*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
511*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *symdata = elf_getdata (symscn, NULL);
512*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (symshdr == NULL || symdata == NULL))
513*7304104dSAndroid Build Coastguard Worker 	    continue;
514*7304104dSAndroid Build Coastguard Worker 
515*7304104dSAndroid Build Coastguard Worker 	  /* Search for the optional extended section index table.  */
516*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *xndxdata = NULL;
517*7304104dSAndroid Build Coastguard Worker 	  Elf_Scn *xndxscn = NULL;
518*7304104dSAndroid Build Coastguard Worker 	  while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
519*7304104dSAndroid Build Coastguard Worker 	    {
520*7304104dSAndroid Build Coastguard Worker 	      GElf_Shdr xndxshdr_mem;
521*7304104dSAndroid Build Coastguard Worker 	      GElf_Shdr *xndxshdr;
522*7304104dSAndroid Build Coastguard Worker 
523*7304104dSAndroid Build Coastguard Worker 	      xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
524*7304104dSAndroid Build Coastguard Worker 	      if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
525*7304104dSAndroid Build Coastguard Worker 		  && xndxshdr->sh_link == elf_ndxscn (symscn))
526*7304104dSAndroid Build Coastguard Worker 		{
527*7304104dSAndroid Build Coastguard Worker 		  /* Found it.  */
528*7304104dSAndroid Build Coastguard Worker 		  xndxdata = elf_getdata (xndxscn, NULL);
529*7304104dSAndroid Build Coastguard Worker 		  break;
530*7304104dSAndroid Build Coastguard Worker 		}
531*7304104dSAndroid Build Coastguard Worker 	    }
532*7304104dSAndroid Build Coastguard Worker 
533*7304104dSAndroid Build Coastguard Worker 	  if (shdr->sh_type == SHT_REL)
534*7304104dSAndroid Build Coastguard Worker 	    show_relocs_rel (ebl, shdr, data, symdata, xndxdata,
535*7304104dSAndroid Build Coastguard Worker 			     symshdr->sh_link, shstrndx);
536*7304104dSAndroid Build Coastguard Worker 	  else
537*7304104dSAndroid Build Coastguard Worker 	    show_relocs_rela (ebl, shdr, data, symdata, xndxdata,
538*7304104dSAndroid Build Coastguard Worker 			      symshdr->sh_link, shstrndx);
539*7304104dSAndroid Build Coastguard Worker 
540*7304104dSAndroid Build Coastguard Worker 	  putchar ('\n');
541*7304104dSAndroid Build Coastguard Worker 	}
542*7304104dSAndroid Build Coastguard Worker     }
543*7304104dSAndroid Build Coastguard Worker 
544*7304104dSAndroid Build Coastguard Worker   return 0;
545*7304104dSAndroid Build Coastguard Worker }
546*7304104dSAndroid Build Coastguard Worker 
547*7304104dSAndroid Build Coastguard Worker 
548*7304104dSAndroid Build Coastguard Worker static int
show_full_content(Ebl * ebl,const char * fname,uint32_t shstrndx)549*7304104dSAndroid Build Coastguard Worker show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx)
550*7304104dSAndroid Build Coastguard Worker {
551*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
552*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
553*7304104dSAndroid Build Coastguard Worker     {
554*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
555*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
556*7304104dSAndroid Build Coastguard Worker 
557*7304104dSAndroid Build Coastguard Worker       if (shdr == NULL)
558*7304104dSAndroid Build Coastguard Worker 	INTERNAL_ERROR (fname);
559*7304104dSAndroid Build Coastguard Worker 
560*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0)
561*7304104dSAndroid Build Coastguard Worker 	{
562*7304104dSAndroid Build Coastguard Worker 	  if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
563*7304104dSAndroid Build Coastguard Worker 	    continue;
564*7304104dSAndroid Build Coastguard Worker 
565*7304104dSAndroid Build Coastguard Worker 	  printf (_("Contents of section %s:\n"),
566*7304104dSAndroid Build Coastguard Worker 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
567*7304104dSAndroid Build Coastguard Worker 
568*7304104dSAndroid Build Coastguard Worker 	  /* Get the data of the section.  */
569*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *data = elf_getdata (scn, NULL);
570*7304104dSAndroid Build Coastguard Worker 	  if (data == NULL)
571*7304104dSAndroid Build Coastguard Worker 	    continue;
572*7304104dSAndroid Build Coastguard Worker 
573*7304104dSAndroid Build Coastguard Worker 	  unsigned char *cp = data->d_buf;
574*7304104dSAndroid Build Coastguard Worker 	  size_t cnt;
575*7304104dSAndroid Build Coastguard Worker 	  for (cnt = 0; cnt + 16 < data->d_size; cp += 16, cnt += 16)
576*7304104dSAndroid Build Coastguard Worker 	    {
577*7304104dSAndroid Build Coastguard Worker 	      printf (" %04zx ", cnt);
578*7304104dSAndroid Build Coastguard Worker 
579*7304104dSAndroid Build Coastguard Worker 	      for (size_t inner = 0; inner < 16; inner += 4)
580*7304104dSAndroid Build Coastguard Worker 		printf ("%02hhx%02hhx%02hhx%02hhx ",
581*7304104dSAndroid Build Coastguard Worker 			cp[inner], cp[inner + 1], cp[inner + 2],
582*7304104dSAndroid Build Coastguard Worker 			cp[inner + 3]);
583*7304104dSAndroid Build Coastguard Worker 	      fputc_unlocked (' ', stdout);
584*7304104dSAndroid Build Coastguard Worker 
585*7304104dSAndroid Build Coastguard Worker 	      for (size_t inner = 0; inner < 16; ++inner)
586*7304104dSAndroid Build Coastguard Worker 		fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
587*7304104dSAndroid Build Coastguard Worker 				? cp[inner] : '.', stdout);
588*7304104dSAndroid Build Coastguard Worker 	      fputc_unlocked ('\n', stdout);
589*7304104dSAndroid Build Coastguard Worker 	    }
590*7304104dSAndroid Build Coastguard Worker 
591*7304104dSAndroid Build Coastguard Worker 	  printf (" %04zx ", cnt);
592*7304104dSAndroid Build Coastguard Worker 
593*7304104dSAndroid Build Coastguard Worker 	  size_t remaining = data->d_size - cnt;
594*7304104dSAndroid Build Coastguard Worker 	  size_t inner;
595*7304104dSAndroid Build Coastguard Worker 	  for (inner = 0; inner + 4 <= remaining; inner += 4)
596*7304104dSAndroid Build Coastguard Worker 	    printf ("%02hhx%02hhx%02hhx%02hhx ",
597*7304104dSAndroid Build Coastguard Worker 		    cp[inner], cp[inner + 1], cp[inner + 2], cp[inner + 3]);
598*7304104dSAndroid Build Coastguard Worker 
599*7304104dSAndroid Build Coastguard Worker 	  for (; inner < remaining; ++inner)
600*7304104dSAndroid Build Coastguard Worker 	    printf ("%02hhx", cp[inner]);
601*7304104dSAndroid Build Coastguard Worker 
602*7304104dSAndroid Build Coastguard Worker 	  for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0;
603*7304104dSAndroid Build Coastguard Worker 	       --inner)
604*7304104dSAndroid Build Coastguard Worker 	    fputc_unlocked (' ', stdout);
605*7304104dSAndroid Build Coastguard Worker 
606*7304104dSAndroid Build Coastguard Worker 	  for (inner = 0; inner < remaining; ++inner)
607*7304104dSAndroid Build Coastguard Worker 	    fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
608*7304104dSAndroid Build Coastguard Worker 			    ? cp[inner] : '.', stdout);
609*7304104dSAndroid Build Coastguard Worker 	  fputc_unlocked ('\n', stdout);
610*7304104dSAndroid Build Coastguard Worker 
611*7304104dSAndroid Build Coastguard Worker 	  fputc_unlocked ('\n', stdout);
612*7304104dSAndroid Build Coastguard Worker 	}
613*7304104dSAndroid Build Coastguard Worker     }
614*7304104dSAndroid Build Coastguard Worker 
615*7304104dSAndroid Build Coastguard Worker   return 0;
616*7304104dSAndroid Build Coastguard Worker }
617*7304104dSAndroid Build Coastguard Worker 
618*7304104dSAndroid Build Coastguard Worker 
619*7304104dSAndroid Build Coastguard Worker struct disasm_info
620*7304104dSAndroid Build Coastguard Worker {
621*7304104dSAndroid Build Coastguard Worker   GElf_Addr addr;
622*7304104dSAndroid Build Coastguard Worker   const uint8_t *cur;
623*7304104dSAndroid Build Coastguard Worker   const uint8_t *last_end;
624*7304104dSAndroid Build Coastguard Worker   const char *address_color;
625*7304104dSAndroid Build Coastguard Worker   const char *bytes_color;
626*7304104dSAndroid Build Coastguard Worker };
627*7304104dSAndroid Build Coastguard Worker 
628*7304104dSAndroid Build Coastguard Worker 
629*7304104dSAndroid Build Coastguard Worker // XXX This is not the preferred output for all architectures.  Needs
630*7304104dSAndroid Build Coastguard Worker // XXX customization, too.
631*7304104dSAndroid Build Coastguard Worker static int
disasm_output(char * buf,size_t buflen,void * arg)632*7304104dSAndroid Build Coastguard Worker disasm_output (char *buf, size_t buflen, void *arg)
633*7304104dSAndroid Build Coastguard Worker {
634*7304104dSAndroid Build Coastguard Worker   struct disasm_info *info = (struct disasm_info *) arg;
635*7304104dSAndroid Build Coastguard Worker 
636*7304104dSAndroid Build Coastguard Worker   if (info->address_color != NULL)
637*7304104dSAndroid Build Coastguard Worker     printf ("%s%8" PRIx64 "%s:   ",
638*7304104dSAndroid Build Coastguard Worker 	    info->address_color, (uint64_t) info->addr, color_off);
639*7304104dSAndroid Build Coastguard Worker   else
640*7304104dSAndroid Build Coastguard Worker     printf ("%8" PRIx64 ":   ", (uint64_t) info->addr);
641*7304104dSAndroid Build Coastguard Worker 
642*7304104dSAndroid Build Coastguard Worker   if (info->bytes_color != NULL)
643*7304104dSAndroid Build Coastguard Worker     fputs_unlocked (info->bytes_color, stdout);
644*7304104dSAndroid Build Coastguard Worker   size_t cnt;
645*7304104dSAndroid Build Coastguard Worker   for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt)
646*7304104dSAndroid Build Coastguard Worker     printf (" %02" PRIx8, info->last_end[cnt]);
647*7304104dSAndroid Build Coastguard Worker   if (info->bytes_color != NULL)
648*7304104dSAndroid Build Coastguard Worker     fputs_unlocked (color_off, stdout);
649*7304104dSAndroid Build Coastguard Worker 
650*7304104dSAndroid Build Coastguard Worker   printf ("%*s %.*s\n",
651*7304104dSAndroid Build Coastguard Worker 	  (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf);
652*7304104dSAndroid Build Coastguard Worker 
653*7304104dSAndroid Build Coastguard Worker   info->addr += cnt;
654*7304104dSAndroid Build Coastguard Worker 
655*7304104dSAndroid Build Coastguard Worker   /* We limit the number of bytes printed before the mnemonic to 8.
656*7304104dSAndroid Build Coastguard Worker      Print the rest on a separate, following line.  */
657*7304104dSAndroid Build Coastguard Worker   if (info->cur - info->last_end > 8)
658*7304104dSAndroid Build Coastguard Worker     {
659*7304104dSAndroid Build Coastguard Worker       if (info->address_color != NULL)
660*7304104dSAndroid Build Coastguard Worker 	printf ("%s%8" PRIx64 "%s:   ",
661*7304104dSAndroid Build Coastguard Worker 		info->address_color, (uint64_t) info->addr, color_off);
662*7304104dSAndroid Build Coastguard Worker       else
663*7304104dSAndroid Build Coastguard Worker 	printf ("%8" PRIx64 ":   ", (uint64_t) info->addr);
664*7304104dSAndroid Build Coastguard Worker 
665*7304104dSAndroid Build Coastguard Worker       if (info->bytes_color != NULL)
666*7304104dSAndroid Build Coastguard Worker 	fputs_unlocked (info->bytes_color, stdout);
667*7304104dSAndroid Build Coastguard Worker       for (; cnt < (size_t) (info->cur - info->last_end); ++cnt)
668*7304104dSAndroid Build Coastguard Worker 	printf (" %02" PRIx8, info->last_end[cnt]);
669*7304104dSAndroid Build Coastguard Worker       if (info->bytes_color != NULL)
670*7304104dSAndroid Build Coastguard Worker 	fputs_unlocked (color_off, stdout);
671*7304104dSAndroid Build Coastguard Worker       putchar_unlocked ('\n');
672*7304104dSAndroid Build Coastguard Worker       info->addr += info->cur - info->last_end - 8;
673*7304104dSAndroid Build Coastguard Worker     }
674*7304104dSAndroid Build Coastguard Worker 
675*7304104dSAndroid Build Coastguard Worker   info->last_end = info->cur;
676*7304104dSAndroid Build Coastguard Worker 
677*7304104dSAndroid Build Coastguard Worker   return 0;
678*7304104dSAndroid Build Coastguard Worker }
679*7304104dSAndroid Build Coastguard Worker 
680*7304104dSAndroid Build Coastguard Worker 
681*7304104dSAndroid Build Coastguard Worker static int
show_disasm(Ebl * ebl,const char * fname,uint32_t shstrndx)682*7304104dSAndroid Build Coastguard Worker show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx)
683*7304104dSAndroid Build Coastguard Worker {
684*7304104dSAndroid Build Coastguard Worker   DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */);
685*7304104dSAndroid Build Coastguard Worker   if (ctx == NULL)
686*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot disassemble"));
687*7304104dSAndroid Build Coastguard Worker 
688*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
689*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
690*7304104dSAndroid Build Coastguard Worker     {
691*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
692*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
693*7304104dSAndroid Build Coastguard Worker 
694*7304104dSAndroid Build Coastguard Worker       if (shdr == NULL)
695*7304104dSAndroid Build Coastguard Worker 	INTERNAL_ERROR (fname);
696*7304104dSAndroid Build Coastguard Worker 
697*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0
698*7304104dSAndroid Build Coastguard Worker 	  && (shdr->sh_flags & SHF_EXECINSTR) != 0)
699*7304104dSAndroid Build Coastguard Worker 	{
700*7304104dSAndroid Build Coastguard Worker 	  if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
701*7304104dSAndroid Build Coastguard Worker 	    continue;
702*7304104dSAndroid Build Coastguard Worker 
703*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *data = elf_getdata (scn, NULL);
704*7304104dSAndroid Build Coastguard Worker 	  if (data == NULL)
705*7304104dSAndroid Build Coastguard Worker 	    continue;
706*7304104dSAndroid Build Coastguard Worker 
707*7304104dSAndroid Build Coastguard Worker 	  printf ("Disassembly of section %s:\n\n",
708*7304104dSAndroid Build Coastguard Worker 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
709*7304104dSAndroid Build Coastguard Worker 
710*7304104dSAndroid Build Coastguard Worker 	  struct disasm_info info;
711*7304104dSAndroid Build Coastguard Worker 	  info.addr = shdr->sh_addr;
712*7304104dSAndroid Build Coastguard Worker 	  info.last_end = info.cur = data->d_buf;
713*7304104dSAndroid Build Coastguard Worker 	  char *fmt;
714*7304104dSAndroid Build Coastguard Worker 	  if (color_mode)
715*7304104dSAndroid Build Coastguard Worker 	    {
716*7304104dSAndroid Build Coastguard Worker 	      info.address_color = color_address;
717*7304104dSAndroid Build Coastguard Worker 	      info.bytes_color = color_bytes;
718*7304104dSAndroid Build Coastguard Worker 
719*7304104dSAndroid Build Coastguard Worker 	      fmt = xasprintf ("%s%%7m %s%%.1o,%s%%.2o,%s%%.3o,,%s%%.4o%s%%.5o%%34a %s%%l",
720*7304104dSAndroid Build Coastguard Worker 			       color_mnemonic ?: "",
721*7304104dSAndroid Build Coastguard Worker 			       color_operand1 ?: "",
722*7304104dSAndroid Build Coastguard Worker 			       color_operand2 ?: "",
723*7304104dSAndroid Build Coastguard Worker 			       color_operand3 ?: "",
724*7304104dSAndroid Build Coastguard Worker 			       color_operand4 ?: "",
725*7304104dSAndroid Build Coastguard Worker 			       color_operand5 ?: "",
726*7304104dSAndroid Build Coastguard Worker 			       color_label ?: "");
727*7304104dSAndroid Build Coastguard Worker 	    }
728*7304104dSAndroid Build Coastguard Worker 	  else
729*7304104dSAndroid Build Coastguard Worker 	    {
730*7304104dSAndroid Build Coastguard Worker 	      info.address_color = info.bytes_color = NULL;
731*7304104dSAndroid Build Coastguard Worker 
732*7304104dSAndroid Build Coastguard Worker 	      fmt = "%7m %.1o,%.2o,%.3o,%.4o,%.5o%34a %l";
733*7304104dSAndroid Build Coastguard Worker 	    }
734*7304104dSAndroid Build Coastguard Worker 
735*7304104dSAndroid Build Coastguard Worker 	  disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr,
736*7304104dSAndroid Build Coastguard Worker 		     fmt, disasm_output, &info, NULL /* XXX */);
737*7304104dSAndroid Build Coastguard Worker 
738*7304104dSAndroid Build Coastguard Worker 	  if (color_mode)
739*7304104dSAndroid Build Coastguard Worker 	    free (fmt);
740*7304104dSAndroid Build Coastguard Worker 	}
741*7304104dSAndroid Build Coastguard Worker     }
742*7304104dSAndroid Build Coastguard Worker 
743*7304104dSAndroid Build Coastguard Worker   (void) disasm_end (ctx);
744*7304104dSAndroid Build Coastguard Worker 
745*7304104dSAndroid Build Coastguard Worker   return 0;
746*7304104dSAndroid Build Coastguard Worker }
747*7304104dSAndroid Build Coastguard Worker 
748*7304104dSAndroid Build Coastguard Worker 
749*7304104dSAndroid Build Coastguard Worker static int
handle_elf(Elf * elf,const char * prefix,const char * fname,const char * suffix)750*7304104dSAndroid Build Coastguard Worker handle_elf (Elf *elf, const char *prefix, const char *fname,
751*7304104dSAndroid Build Coastguard Worker 	    const char *suffix)
752*7304104dSAndroid Build Coastguard Worker {
753*7304104dSAndroid Build Coastguard Worker 
754*7304104dSAndroid Build Coastguard Worker   /* Get the backend for this object file type.  */
755*7304104dSAndroid Build Coastguard Worker   Ebl *ebl = ebl_openbackend (elf);
756*7304104dSAndroid Build Coastguard Worker   if (ebl == NULL)
757*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot create backend for elf file"));
758*7304104dSAndroid Build Coastguard Worker 
759*7304104dSAndroid Build Coastguard Worker   printf ("%s: elf%d-%s\n\n",
760*7304104dSAndroid Build Coastguard Worker 	  fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64,
761*7304104dSAndroid Build Coastguard Worker 	  ebl_backend_name (ebl));
762*7304104dSAndroid Build Coastguard Worker 
763*7304104dSAndroid Build Coastguard Worker   /* Create the full name of the file.  */
764*7304104dSAndroid Build Coastguard Worker   size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
765*7304104dSAndroid Build Coastguard Worker   size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
766*7304104dSAndroid Build Coastguard Worker   size_t fname_len = strlen (fname) + 1;
767*7304104dSAndroid Build Coastguard Worker   char fullname[prefix_len + 1 + fname_len + suffix_len];
768*7304104dSAndroid Build Coastguard Worker   char *cp = fullname;
769*7304104dSAndroid Build Coastguard Worker   if (prefix != NULL)
770*7304104dSAndroid Build Coastguard Worker     cp = mempcpy (cp, prefix, prefix_len);
771*7304104dSAndroid Build Coastguard Worker   cp = mempcpy (cp, fname, fname_len);
772*7304104dSAndroid Build Coastguard Worker   if (suffix != NULL)
773*7304104dSAndroid Build Coastguard Worker     memcpy (cp - 1, suffix, suffix_len + 1);
774*7304104dSAndroid Build Coastguard Worker 
775*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
776*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
777*7304104dSAndroid Build Coastguard Worker   if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
778*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
779*7304104dSAndroid Build Coastguard Worker 
780*7304104dSAndroid Build Coastguard Worker   int result = 0;
781*7304104dSAndroid Build Coastguard Worker   if (print_disasm)
782*7304104dSAndroid Build Coastguard Worker     result = show_disasm (ebl, fullname, shstrndx);
783*7304104dSAndroid Build Coastguard Worker   if (print_relocs && !print_disasm)
784*7304104dSAndroid Build Coastguard Worker     result = show_relocs (ebl, fullname, shstrndx);
785*7304104dSAndroid Build Coastguard Worker   if (print_full_content)
786*7304104dSAndroid Build Coastguard Worker     result = show_full_content (ebl, fullname, shstrndx);
787*7304104dSAndroid Build Coastguard Worker 
788*7304104dSAndroid Build Coastguard Worker   /* Close the ELF backend library descriptor.  */
789*7304104dSAndroid Build Coastguard Worker   ebl_closebackend (ebl);
790*7304104dSAndroid Build Coastguard Worker 
791*7304104dSAndroid Build Coastguard Worker   return result;
792*7304104dSAndroid Build Coastguard Worker }
793*7304104dSAndroid Build Coastguard Worker 
794*7304104dSAndroid Build Coastguard Worker 
795*7304104dSAndroid Build Coastguard Worker #include "debugpred.h"
796