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