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