15aefb655Srie /* 25aefb655Srie * CDDL HEADER START 35aefb655Srie * 45aefb655Srie * The contents of this file are subject to the terms of the 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * You may not use this file except in compliance with the License. 75aefb655Srie * 85aefb655Srie * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95aefb655Srie * or http://www.opensolaris.org/os/licensing. 105aefb655Srie * See the License for the specific language governing permissions 115aefb655Srie * and limitations under the License. 125aefb655Srie * 135aefb655Srie * When distributing Covered Code, include this CDDL HEADER in each 145aefb655Srie * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155aefb655Srie * If applicable, add the following below this CDDL HEADER, with the 165aefb655Srie * fields enclosed by brackets "[]" replaced with your own identifying 175aefb655Srie * information: Portions Copyright [yyyy] [name of copyright owner] 185aefb655Srie * 195aefb655Srie * CDDL HEADER END 205aefb655Srie */ 215aefb655Srie 225aefb655Srie /* 23*ba7866cdSAli Bahrami * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 245aefb655Srie */ 255aefb655Srie 265aefb655Srie /* 275aefb655Srie * Dump an elf file. 285aefb655Srie */ 295aefb655Srie #include <sys/param.h> 305aefb655Srie #include <fcntl.h> 315aefb655Srie #include <stdio.h> 32c809c407Sab196087 #include <stdlib.h> 33c809c407Sab196087 #include <ctype.h> 34*ba7866cdSAli Bahrami #include <_libelf.h> 355aefb655Srie #include <link.h> 365aefb655Srie #include <stdarg.h> 375aefb655Srie #include <unistd.h> 385aefb655Srie #include <libgen.h> 395aefb655Srie #include <libintl.h> 405aefb655Srie #include <locale.h> 415aefb655Srie #include <errno.h> 425aefb655Srie #include <strings.h> 435aefb655Srie #include <debug.h> 445aefb655Srie #include <conv.h> 455aefb655Srie #include <msg.h> 465aefb655Srie #include <_elfdump.h> 47981a172dSab196087 #include <sys/elf_SPARC.h> 48981a172dSab196087 #include <sys/elf_amd64.h> 49981a172dSab196087 505aefb655Srie 5131fdd7caSab196087 const Cache cache_init = {NULL, NULL, NULL, NULL, 0}; 525aefb655Srie 53c809c407Sab196087 54c809c407Sab196087 55981a172dSab196087 /* 56981a172dSab196087 * The -I, -N, and -T options are called "match options", because 57981a172dSab196087 * they allow selecting the items to be displayed based on matching 58981a172dSab196087 * their index, name, or type. 59981a172dSab196087 * 60981a172dSab196087 * The ELF information to which -I, -N, or -T are applied in 61981a172dSab196087 * the current invocation is called the "match item". 62981a172dSab196087 */ 63c809c407Sab196087 typedef enum { 64981a172dSab196087 MATCH_ITEM_PT, /* Program header (PT_) */ 65981a172dSab196087 MATCH_ITEM_SHT /* Section header (SHT_) */ 66981a172dSab196087 } match_item_t; 67981a172dSab196087 68981a172dSab196087 /* match_opt_t is used to note which match option was used */ 69981a172dSab196087 typedef enum { 70981a172dSab196087 MATCH_OPT_NAME, /* Record contains a name */ 71981a172dSab196087 MATCH_OPT_NDX, /* Record contains a single index */ 72981a172dSab196087 MATCH_OPT_RANGE, /* Record contains an index range */ 73981a172dSab196087 MATCH_OPT_TYPE, /* Record contains a type (shdr or phdr) */ 74981a172dSab196087 } match_opt_t; 75c809c407Sab196087 76c809c407Sab196087 typedef struct _match { 77c809c407Sab196087 struct _match *next; /* Pointer to next item in list */ 78981a172dSab196087 match_opt_t opt_type; 79c809c407Sab196087 union { 80981a172dSab196087 const char *name; /* MATCH_OPT_NAME */ 81981a172dSab196087 struct { /* MATCH_OPT_NDX and MATCH_OPT_RANGE */ 82c809c407Sab196087 int start; 83981a172dSab196087 int end; /* Only for MATCH_OPT_RANGE */ 84c809c407Sab196087 } ndx; 85981a172dSab196087 uint32_t type; /* MATCH_OPT_TYPE */ 86c809c407Sab196087 } value; 87981a172dSab196087 } match_rec_t; 88c809c407Sab196087 89981a172dSab196087 static struct { 90981a172dSab196087 match_item_t item_type; /* Type of item being matched */ 91981a172dSab196087 match_rec_t *list; /* Records for (-I, -N, -T) options */ 92981a172dSab196087 } match_state; 93981a172dSab196087 94981a172dSab196087 95981a172dSab196087 965aefb655Srie const char * 975aefb655Srie _elfdump_msg(Msg mid) 985aefb655Srie { 995aefb655Srie return (gettext(MSG_ORIG(mid))); 1005aefb655Srie } 1015aefb655Srie 1025aefb655Srie /* 1035aefb655Srie * Determine whether a symbol name should be demangled. 1045aefb655Srie */ 1055aefb655Srie const char * 1065aefb655Srie demangle(const char *name, uint_t flags) 1075aefb655Srie { 108981a172dSab196087 if (flags & FLG_CTL_DEMANGLE) 1095aefb655Srie return (Elf_demangle_name(name)); 1105aefb655Srie else 1115aefb655Srie return ((char *)name); 1125aefb655Srie } 1135aefb655Srie 1145aefb655Srie /* 1155aefb655Srie * Define our own standard error routine. 1165aefb655Srie */ 1175aefb655Srie void 1185aefb655Srie failure(const char *file, const char *func) 1195aefb655Srie { 1205aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_FAILURE), 1215aefb655Srie file, func, elf_errmsg(elf_errno())); 1225aefb655Srie } 1235aefb655Srie 1245aefb655Srie /* 1255aefb655Srie * The full usage message 1265aefb655Srie */ 1275aefb655Srie static void 1285aefb655Srie detail_usage() 1295aefb655Srie { 1305aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL1)); 1315aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL2)); 1325aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL3)); 1335aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL4)); 1345aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL5)); 1355aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL6)); 1365aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL7)); 1375aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL8)); 1385aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9)); 1395aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL10)); 1405aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL11)); 1415aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL12)); 1425aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL13)); 1435aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL14)); 1445aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL15)); 1455aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL16)); 1465aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL17)); 1475aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL18)); 1485aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL19)); 1495aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL20)); 150d579eb63Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL21)); 151c809c407Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL22)); 152c809c407Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL23)); 15339773e46Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL24)); 154981a172dSab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL25)); 1554f680cc6SAli Bahrami (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL26)); 156c809c407Sab196087 } 157c809c407Sab196087 158c809c407Sab196087 /* 159c6c9aed4Sab196087 * Output a block of raw data as hex bytes. Each row is given 160c6c9aed4Sab196087 * the index of the first byte in the row. 161c6c9aed4Sab196087 * 162c6c9aed4Sab196087 * entry: 163c6c9aed4Sab196087 * data - Pointer to first byte of data to be displayed 164c6c9aed4Sab196087 * n - # of bytes of data 165c6c9aed4Sab196087 * prefix - String to be output before each line. Useful 166c6c9aed4Sab196087 * for indenting output. 167c6c9aed4Sab196087 * bytes_per_col - # of space separated bytes to output 168c6c9aed4Sab196087 * in each column. 169c6c9aed4Sab196087 * col_per_row - # of columns to output per row 170c6c9aed4Sab196087 * 171c6c9aed4Sab196087 * exit: 172c6c9aed4Sab196087 * The formatted data has been sent to stdout. Each row of output 173c6c9aed4Sab196087 * shows (bytes_per_col * col_per_row) bytes of data. 174c6c9aed4Sab196087 */ 175c6c9aed4Sab196087 void 1767e16fca0SAli Bahrami dump_hex_bytes(const void *data, size_t n, int indent, 177c6c9aed4Sab196087 int bytes_per_col, int col_per_row) 178c6c9aed4Sab196087 { 1797e16fca0SAli Bahrami const uchar_t *ldata = data; 180c6c9aed4Sab196087 int bytes_per_row = bytes_per_col * col_per_row; 181c6c9aed4Sab196087 int ndx, byte, word; 182c6c9aed4Sab196087 char string[128], *str = string; 183c6c9aed4Sab196087 char index[MAXNDXSIZE]; 184c6c9aed4Sab196087 int index_width; 185c6c9aed4Sab196087 int sp_prefix = 0; 186c6c9aed4Sab196087 187c6c9aed4Sab196087 188c6c9aed4Sab196087 /* 189c6c9aed4Sab196087 * Determine the width to use for the index string. We follow 190c6c9aed4Sab196087 * 8-byte tab rules, but don't use an actual \t character so 191c6c9aed4Sab196087 * that the output can be arbitrarily shifted without odd 192c6c9aed4Sab196087 * tab effects, and so that all the columns line up no matter 193c6c9aed4Sab196087 * how many lines of output are produced. 194c6c9aed4Sab196087 */ 195c6c9aed4Sab196087 ndx = n / bytes_per_row; 196c6c9aed4Sab196087 (void) snprintf(index, sizeof (index), 197c6c9aed4Sab196087 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx)); 198c6c9aed4Sab196087 index_width = strlen(index); 199c6c9aed4Sab196087 index_width = S_ROUND(index_width, 8); 200c6c9aed4Sab196087 2017e16fca0SAli Bahrami for (ndx = byte = word = 0; n > 0; n--, ldata++) { 202c6c9aed4Sab196087 while (sp_prefix-- > 0) 203c6c9aed4Sab196087 *str++ = ' '; 204c6c9aed4Sab196087 205c6c9aed4Sab196087 (void) snprintf(str, sizeof (string), 2067e16fca0SAli Bahrami MSG_ORIG(MSG_HEXDUMP_TOK), (int)*ldata); 207c6c9aed4Sab196087 str += 2; 208c6c9aed4Sab196087 sp_prefix = 1; 209c6c9aed4Sab196087 210c6c9aed4Sab196087 if (++byte == bytes_per_col) { 211c6c9aed4Sab196087 sp_prefix += 2; 212c6c9aed4Sab196087 word++; 213c6c9aed4Sab196087 byte = 0; 214c6c9aed4Sab196087 } 215c6c9aed4Sab196087 if (word == col_per_row) { 216c6c9aed4Sab196087 *str = '\0'; 217c6c9aed4Sab196087 (void) snprintf(index, sizeof (index), 218c6c9aed4Sab196087 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx)); 219c6c9aed4Sab196087 dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW), 220c6c9aed4Sab196087 indent, MSG_ORIG(MSG_STR_EMPTY), 221c6c9aed4Sab196087 index_width, index, string); 222c6c9aed4Sab196087 sp_prefix = 0; 223c6c9aed4Sab196087 word = 0; 224c6c9aed4Sab196087 ndx += bytes_per_row; 225c6c9aed4Sab196087 str = string; 226c6c9aed4Sab196087 } 227c6c9aed4Sab196087 } 228c6c9aed4Sab196087 if (byte || word) { 229c6c9aed4Sab196087 *str = '\0'; /* */ 230c6c9aed4Sab196087 (void) snprintf(index, sizeof (index), 231c6c9aed4Sab196087 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx)); 232c6c9aed4Sab196087 dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW), indent, 233c6c9aed4Sab196087 MSG_ORIG(MSG_STR_EMPTY), index_width, index, string); 234c6c9aed4Sab196087 } 235c6c9aed4Sab196087 } 236c6c9aed4Sab196087 237c6c9aed4Sab196087 /* 238c809c407Sab196087 * Convert the ASCII representation of an index, or index range, into 239c809c407Sab196087 * binary form, and store it in rec: 240c809c407Sab196087 * 241c809c407Sab196087 * index: An positive or 0 valued integer 242c809c407Sab196087 * range: Two indexes, separated by a ':' character, denoting 243c809c407Sab196087 * a range of allowed values. If the second value is omitted, 244c809c407Sab196087 * any values equal to or greater than the first will match. 245c809c407Sab196087 * 246c809c407Sab196087 * exit: 247981a172dSab196087 * On success, *rec is filled in with a MATCH_OPT_NDX or MATCH_OPT_RANGE 248c809c407Sab196087 * value, and this function returns (1). On failure, the contents 249c809c407Sab196087 * of *rec are undefined, and (0) is returned. 250c809c407Sab196087 */ 251c809c407Sab196087 int 252981a172dSab196087 process_index_opt(const char *str, match_rec_t *rec) 253c809c407Sab196087 { 254c809c407Sab196087 #define SKIP_BLANK for (; *str && isspace(*str); str++) 255c809c407Sab196087 256c809c407Sab196087 char *endptr; 257c809c407Sab196087 258c809c407Sab196087 rec->value.ndx.start = strtol(str, &endptr, 10); 259c809c407Sab196087 /* Value must use some of the input, and be 0 or positive */ 260c809c407Sab196087 if ((str == endptr) || (rec->value.ndx.start < 0)) 261c809c407Sab196087 return (0); 262c809c407Sab196087 str = endptr; 263c809c407Sab196087 264c809c407Sab196087 SKIP_BLANK; 265c809c407Sab196087 if (*str != ':') { 266981a172dSab196087 rec->opt_type = MATCH_OPT_NDX; 267c809c407Sab196087 } else { 268c809c407Sab196087 str++; /* Skip the ':' */ 269981a172dSab196087 rec->opt_type = MATCH_OPT_RANGE; 270c809c407Sab196087 SKIP_BLANK; 271c809c407Sab196087 if (*str == '\0') { 272c809c407Sab196087 rec->value.ndx.end = -1; /* Indicates "to end" */ 273c809c407Sab196087 } else { 274c809c407Sab196087 rec->value.ndx.end = strtol(str, &endptr, 10); 275c809c407Sab196087 if ((str == endptr) || (rec->value.ndx.end < 0)) 276c809c407Sab196087 return (0); 277c809c407Sab196087 str = endptr; 278c809c407Sab196087 SKIP_BLANK; 279c809c407Sab196087 } 280c809c407Sab196087 } 281c809c407Sab196087 282c809c407Sab196087 /* Syntax error if anything is left over */ 283c809c407Sab196087 if (*str != '\0') 284c809c407Sab196087 return (0); 285c809c407Sab196087 286c809c407Sab196087 return (1); 287c809c407Sab196087 288c809c407Sab196087 #undef SKIP_BLANK 289c809c407Sab196087 } 290c809c407Sab196087 291c809c407Sab196087 /* 2924f680cc6SAli Bahrami * Convert a string containing a specific type of ELF constant, or an ASCII 2934f680cc6SAli Bahrami * representation of a number, to an integer. Strings starting with '0' 294981a172dSab196087 * are taken to be octal, those staring with '0x' are hex, and all 295981a172dSab196087 * others are decimal. 296981a172dSab196087 * 297981a172dSab196087 * entry: 298981a172dSab196087 * str - String to be converted 2994f680cc6SAli Bahrami * ctype - Constant type 300981a172dSab196087 * v - Address of variable to receive resulting value. 301981a172dSab196087 * 302981a172dSab196087 * exit: 303981a172dSab196087 * On success, returns True (1) and *v is set to the value. 304981a172dSab196087 * On failure, returns False (0) and *v is undefined. 305981a172dSab196087 */ 3064f680cc6SAli Bahrami typedef enum { 3074f680cc6SAli Bahrami ATOUI_PT, 3084f680cc6SAli Bahrami ATOUI_SHT, 3094f680cc6SAli Bahrami ATOUI_OSABI 3104f680cc6SAli Bahrami } atoui_type_t; 3114f680cc6SAli Bahrami 312981a172dSab196087 static int 3134f680cc6SAli Bahrami atoui(const char *str, atoui_type_t type, uint32_t *v) 314981a172dSab196087 { 3154f680cc6SAli Bahrami conv_strtol_uvalue_t uvalue; 316981a172dSab196087 char *endptr; 317981a172dSab196087 3184f680cc6SAli Bahrami if (conv_iter_strtol_init(str, &uvalue) != 0) { 3194f680cc6SAli Bahrami switch (type) { 3204f680cc6SAli Bahrami case ATOUI_PT: 3214f680cc6SAli Bahrami if (conv_iter_phdr_type(CONV_OSABI_ALL, CONV_FMT_ALT_CF, 3224f680cc6SAli Bahrami conv_iter_strtol, &uvalue) == CONV_ITER_DONE) 3234f680cc6SAli Bahrami break; 3244f680cc6SAli Bahrami (void) conv_iter_phdr_type(CONV_OSABI_ALL, 3254f680cc6SAli Bahrami CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue); 3264f680cc6SAli Bahrami break; 3274f680cc6SAli Bahrami case ATOUI_SHT: 3284f680cc6SAli Bahrami if (conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL, 3294f680cc6SAli Bahrami CONV_FMT_ALT_CF, conv_iter_strtol, &uvalue) == 3304f680cc6SAli Bahrami CONV_ITER_DONE) 3314f680cc6SAli Bahrami break; 3324f680cc6SAli Bahrami (void) conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL, 3334f680cc6SAli Bahrami CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue); 3344f680cc6SAli Bahrami break; 3354f680cc6SAli Bahrami case ATOUI_OSABI: 3364f680cc6SAli Bahrami if (conv_iter_ehdr_osabi(CONV_FMT_ALT_CF, 3374f680cc6SAli Bahrami conv_iter_strtol, &uvalue) == CONV_ITER_DONE) 3384f680cc6SAli Bahrami break; 3394f680cc6SAli Bahrami (void) conv_iter_ehdr_osabi(CONV_FMT_ALT_NF, 3404f680cc6SAli Bahrami conv_iter_strtol, &uvalue); 3414f680cc6SAli Bahrami break; 3424f680cc6SAli Bahrami } 3434f680cc6SAli Bahrami if (uvalue.csl_found) { 3444f680cc6SAli Bahrami *v = uvalue.csl_value; 345981a172dSab196087 return (1); 3464f680cc6SAli Bahrami } 3474f680cc6SAli Bahrami } 348981a172dSab196087 349981a172dSab196087 *v = strtoull(str, &endptr, 0); 350981a172dSab196087 351981a172dSab196087 /* If the left over part contains anything but whitespace, fail */ 352981a172dSab196087 for (; *endptr; endptr++) 353981a172dSab196087 if (!isspace(*endptr)) 354981a172dSab196087 return (0); 355981a172dSab196087 return (1); 356981a172dSab196087 } 357981a172dSab196087 358981a172dSab196087 /* 359981a172dSab196087 * Called after getopt() processing is finished if there is a non-empty 360981a172dSab196087 * match list. Prepares the matching code for use. 361981a172dSab196087 * 362981a172dSab196087 * exit: 363981a172dSab196087 * Returns True (1) if no errors are encountered. Writes an 364981a172dSab196087 * error string to stderr and returns False (0) otherwise. 365981a172dSab196087 */ 366981a172dSab196087 static int 367981a172dSab196087 match_prepare(char *argv0, uint_t flags) 368981a172dSab196087 { 369981a172dSab196087 match_rec_t *list; 370981a172dSab196087 const char *str; 371981a172dSab196087 int minus_p = (flags & FLG_SHOW_PHDR) != 0; 3724f680cc6SAli Bahrami atoui_type_t atoui_type; 373981a172dSab196087 374981a172dSab196087 /* 375981a172dSab196087 * Flag ambiguous attempt to use match option with both -p and 376981a172dSab196087 * and one or more section SHOW options. In this case, we 377981a172dSab196087 * can't tell what type of item we're supposed to match against. 378981a172dSab196087 */ 379981a172dSab196087 if (minus_p && (flags & FLG_MASK_SHOW_SHDR)) { 380981a172dSab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_AMBIG_MATCH), 381981a172dSab196087 basename(argv0)); 382981a172dSab196087 return (0); 383981a172dSab196087 } 384981a172dSab196087 385981a172dSab196087 /* Set the match type, based on the presence of the -p option */ 386981a172dSab196087 if (minus_p) { 387981a172dSab196087 match_state.item_type = MATCH_ITEM_PT; 3884f680cc6SAli Bahrami atoui_type = ATOUI_PT; 389981a172dSab196087 } else { 390981a172dSab196087 match_state.item_type = MATCH_ITEM_SHT; 3914f680cc6SAli Bahrami atoui_type = ATOUI_SHT; 392981a172dSab196087 } 393981a172dSab196087 394981a172dSab196087 /* 395981a172dSab196087 * Scan match list and perform any necessary fixups: 396981a172dSab196087 * 397981a172dSab196087 * MATCH_OPT_NAME: If -p is specified, convert MATCH_OPT_NAME (-N) 398981a172dSab196087 * requests into MATCH_OPT_TYPE (-T). 399981a172dSab196087 * 400981a172dSab196087 * MATCH_OPT_TYPE: Now that we know item type we are matching 401981a172dSab196087 * against, we can convert the string saved in the name 402981a172dSab196087 * field during getopt() processing into an integer and 403981a172dSab196087 * write it into the type field. 404981a172dSab196087 */ 405981a172dSab196087 for (list = match_state.list; list; list = list->next) { 406981a172dSab196087 if ((list->opt_type == MATCH_OPT_NAME) && minus_p) 407981a172dSab196087 list->opt_type = MATCH_OPT_TYPE; 408981a172dSab196087 409981a172dSab196087 if (list->opt_type != MATCH_OPT_TYPE) 410981a172dSab196087 continue; 411981a172dSab196087 412981a172dSab196087 str = list->value.name; 4134f680cc6SAli Bahrami if (atoui(str, atoui_type, &list->value.type) == 0) { 414981a172dSab196087 const char *fmt = minus_p ? 415981a172dSab196087 MSG_INTL(MSG_ERR_BAD_T_PT) : 416981a172dSab196087 MSG_INTL(MSG_ERR_BAD_T_SHT); 417981a172dSab196087 418981a172dSab196087 (void) fprintf(stderr, fmt, basename(argv0), str); 419981a172dSab196087 return (0); 420981a172dSab196087 } 421981a172dSab196087 } 422981a172dSab196087 423981a172dSab196087 return (1); 424981a172dSab196087 } 425981a172dSab196087 426981a172dSab196087 427981a172dSab196087 /* 428c809c407Sab196087 * Returns True (1) if the item with the given name or index should 429c809c407Sab196087 * be displayed, and False (0) if it should not be. 430c809c407Sab196087 * 431c809c407Sab196087 * entry: 432981a172dSab196087 * match_flags - Bitmask specifying matching options, as described 433981a172dSab196087 * in _elfdump.h. 434981a172dSab196087 * name - If MATCH_F_NAME flag is set, name of item under 435981a172dSab196087 * consideration. Otherwise ignored. 436c809c407Sab196087 * should not be considered. 437981a172dSab196087 * ndx - If MATCH_F_NDX flag is set, index of item under consideration. 438981a172dSab196087 * type - If MATCH_F_TYPE is set, type of item under consideration. 439981a172dSab196087 * If MATCH_F_PHDR is set, this would be a program 440981a172dSab196087 * header type (PT_). Otherwise, a section header type (SHT_). 441c809c407Sab196087 * 442c809c407Sab196087 * exit: 443c809c407Sab196087 * True will be returned if the given name/index matches those given 444981a172dSab196087 * by one of the (-I, -N -T) command line options, or if no such option 445981a172dSab196087 * was used in the command invocation and MATCH_F_STRICT is not 446981a172dSab196087 * set. 447c809c407Sab196087 */ 448c809c407Sab196087 int 449981a172dSab196087 match(match_flags_t match_flags, const char *name, uint_t ndx, uint_t type) 450c809c407Sab196087 { 451981a172dSab196087 match_item_t item_type = (match_flags & MATCH_F_PHDR) ? 452981a172dSab196087 MATCH_ITEM_PT : MATCH_ITEM_SHT; 453981a172dSab196087 match_rec_t *list; 454c809c407Sab196087 455981a172dSab196087 /* 456981a172dSab196087 * If there is no match list, then we use the MATCH_F_STRICT 457981a172dSab196087 * flag to decide what to return. In the strict case, we return 458981a172dSab196087 * False (0), in the normal case, True (1). 459981a172dSab196087 */ 460981a172dSab196087 if (match_state.list == NULL) 461981a172dSab196087 return ((match_flags & MATCH_F_STRICT) == 0); 462981a172dSab196087 463981a172dSab196087 /* 464981a172dSab196087 * If item being checked is not the current match type, 465981a172dSab196087 * then allow it. 466981a172dSab196087 */ 467981a172dSab196087 if (item_type != match_state.item_type) 468c809c407Sab196087 return (1); 469c809c407Sab196087 470c809c407Sab196087 /* Run through the match records and check for a hit */ 471981a172dSab196087 for (list = match_state.list; list; list = list->next) { 472981a172dSab196087 switch (list->opt_type) { 473981a172dSab196087 case MATCH_OPT_NAME: 474981a172dSab196087 if (((match_flags & MATCH_F_NAME) == 0) || 475981a172dSab196087 (name == NULL)) 476981a172dSab196087 break; 477981a172dSab196087 if (strcmp(list->value.name, name) == 0) 478c809c407Sab196087 return (1); 479c809c407Sab196087 break; 480981a172dSab196087 case MATCH_OPT_NDX: 481981a172dSab196087 if ((match_flags & MATCH_F_NDX) && 482981a172dSab196087 (ndx == list->value.ndx.start)) 483c809c407Sab196087 return (1); 484c809c407Sab196087 break; 485981a172dSab196087 case MATCH_OPT_RANGE: 486c809c407Sab196087 /* 487c809c407Sab196087 * A range end value less than 0 means that any value 488c809c407Sab196087 * above the start is acceptible. 489c809c407Sab196087 */ 490981a172dSab196087 if ((match_flags & MATCH_F_NDX) && 491981a172dSab196087 (ndx >= list->value.ndx.start) && 492c809c407Sab196087 ((list->value.ndx.end < 0) || 493c809c407Sab196087 (ndx <= list->value.ndx.end))) 494c809c407Sab196087 return (1); 495c809c407Sab196087 break; 496981a172dSab196087 497981a172dSab196087 case MATCH_OPT_TYPE: 498981a172dSab196087 if ((match_flags & MATCH_F_TYPE) && 499981a172dSab196087 (type == list->value.type)) 500981a172dSab196087 return (1); 501981a172dSab196087 break; 502c809c407Sab196087 } 503c809c407Sab196087 } 504c809c407Sab196087 505c809c407Sab196087 /* Nothing matched */ 506c809c407Sab196087 return (0); 507c809c407Sab196087 } 508c809c407Sab196087 509c809c407Sab196087 /* 510981a172dSab196087 * Add an entry to match_state.list for use by match(). This routine is for 511981a172dSab196087 * use during getopt() processing. It should not be called once 512981a172dSab196087 * match_prepare() has been called. 513c809c407Sab196087 * 514c809c407Sab196087 * Return True (1) for success. On failure, an error is written 515c809c407Sab196087 * to stderr, and False (0) is returned. 516c809c407Sab196087 */ 517c809c407Sab196087 static int 518981a172dSab196087 add_match_record(char *argv0, match_rec_t *data) 519c809c407Sab196087 { 520981a172dSab196087 match_rec_t *rec; 521981a172dSab196087 match_rec_t *list; 522c809c407Sab196087 523c809c407Sab196087 if ((rec = malloc(sizeof (*rec))) == NULL) { 524c809c407Sab196087 int err = errno; 525c809c407Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 526c809c407Sab196087 basename(argv0), strerror(err)); 527c809c407Sab196087 return (0); 528c809c407Sab196087 } 529c809c407Sab196087 530c809c407Sab196087 *rec = *data; 531c809c407Sab196087 532981a172dSab196087 /* Insert at end of match_state.list */ 533981a172dSab196087 if (match_state.list == NULL) { 534981a172dSab196087 match_state.list = rec; 535c809c407Sab196087 } else { 536981a172dSab196087 for (list = match_state.list; list->next != NULL; 537981a172dSab196087 list = list->next) 538c809c407Sab196087 ; 539c809c407Sab196087 list->next = rec; 540c809c407Sab196087 } 541c809c407Sab196087 542c809c407Sab196087 rec->next = NULL; 543c809c407Sab196087 return (1); 5445aefb655Srie } 5455aefb655Srie 546981a172dSab196087 static int 547981a172dSab196087 decide(const char *file, int fd, Elf *elf, uint_t flags, 5484f680cc6SAli Bahrami const char *wname, int wfd, uchar_t osabi) 5495aefb655Srie { 550981a172dSab196087 int r; 551981a172dSab196087 5525aefb655Srie if (gelf_getclass(elf) == ELFCLASS64) 5534f680cc6SAli Bahrami r = regular64(file, fd, elf, flags, wname, wfd, osabi); 5545aefb655Srie else 5554f680cc6SAli Bahrami r = regular32(file, fd, elf, flags, wname, wfd, osabi); 556981a172dSab196087 557981a172dSab196087 return (r); 5585aefb655Srie } 5595aefb655Srie 560981a172dSab196087 static int 561981a172dSab196087 archive(const char *file, int fd, Elf *elf, uint_t flags, 5624f680cc6SAli Bahrami const char *wname, int wfd, uchar_t osabi) 5635aefb655Srie { 5645aefb655Srie Elf_Cmd cmd = ELF_C_READ; 5655aefb655Srie Elf_Arhdr *arhdr; 5667e16fca0SAli Bahrami Elf *_elf = NULL; 5675aefb655Srie size_t ptr; 5687e16fca0SAli Bahrami Elf_Arsym *arsym = NULL; 5695aefb655Srie 5705aefb655Srie /* 571d579eb63Sab196087 * Determine if the archive symbol table itself is required. 5725aefb655Srie */ 573981a172dSab196087 if ((flags & FLG_SHOW_SYMBOLS) && 574981a172dSab196087 match(MATCH_F_NAME, MSG_ORIG(MSG_ELF_ARSYM), 0, 0)) { 5755aefb655Srie /* 5765aefb655Srie * Get the archive symbol table. 5775aefb655Srie */ 5785aefb655Srie if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) { 5795aefb655Srie /* 5805aefb655Srie * The arsym could be 0 even though there was no error. 5815aefb655Srie * Print the error message only when there was 5825aefb655Srie * real error from elf_getarsym(). 5835aefb655Srie */ 5845aefb655Srie failure(file, MSG_ORIG(MSG_ELF_GETARSYM)); 585981a172dSab196087 return (0); 5865aefb655Srie } 5875aefb655Srie } 5885aefb655Srie 5895aefb655Srie /* 5905aefb655Srie * Print the archive symbol table only when the archive symbol 5915aefb655Srie * table exists and it was requested to print. 5925aefb655Srie */ 5935aefb655Srie if (arsym) { 5945aefb655Srie size_t cnt; 5955aefb655Srie char index[MAXNDXSIZE]; 5965aefb655Srie size_t offset = 0, _offset = 0; 597*ba7866cdSAli Bahrami const char *fmt_arsym1, *fmt_arsym2; 5985aefb655Srie 5995aefb655Srie /* 600*ba7866cdSAli Bahrami * Print out all the symbol entries. The format width used 601*ba7866cdSAli Bahrami * corresponds to whether the archive symbol table is 32 602*ba7866cdSAli Bahrami * or 64-bit. We see them via Elf_Arhdr as size_t values 603*ba7866cdSAli Bahrami * in either case with no information loss (see the comments 604*ba7866cdSAli Bahrami * in libelf/getarsym.c) so this is done simply to improve 605*ba7866cdSAli Bahrami * the user presentation. 6065aefb655Srie */ 607*ba7866cdSAli Bahrami if (_elf_getarsymwordsize(elf) == 8) { 608*ba7866cdSAli Bahrami dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_64)); 609*ba7866cdSAli Bahrami dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_64)); 610*ba7866cdSAli Bahrami 611*ba7866cdSAli Bahrami fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_64); 612*ba7866cdSAli Bahrami fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_64); 613*ba7866cdSAli Bahrami } else { 614*ba7866cdSAli Bahrami dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_32)); 615*ba7866cdSAli Bahrami dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_32)); 616*ba7866cdSAli Bahrami 617*ba7866cdSAli Bahrami fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_32); 618*ba7866cdSAli Bahrami fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_32); 619*ba7866cdSAli Bahrami } 6205aefb655Srie 6215aefb655Srie for (cnt = 0; cnt < ptr; cnt++, arsym++) { 6225aefb655Srie /* 6235aefb655Srie * For each object obtain an elf descriptor so that we 6245aefb655Srie * can establish the members name. Note, we have had 6255aefb655Srie * archives where the archive header has not been 6265aefb655Srie * obtainable so be lenient with errors. 6275aefb655Srie */ 6285aefb655Srie if ((offset == 0) || ((arsym->as_off != 0) && 6295aefb655Srie (arsym->as_off != _offset))) { 6305aefb655Srie 6315aefb655Srie if (_elf) 6325aefb655Srie (void) elf_end(_elf); 6335aefb655Srie 6345aefb655Srie if (elf_rand(elf, arsym->as_off) != 6355aefb655Srie arsym->as_off) { 6365aefb655Srie failure(file, MSG_ORIG(MSG_ELF_RAND)); 6377e16fca0SAli Bahrami arhdr = NULL; 6385aefb655Srie } else if ((_elf = elf_begin(fd, 6395aefb655Srie ELF_C_READ, elf)) == 0) { 6405aefb655Srie failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 6417e16fca0SAli Bahrami arhdr = NULL; 6425aefb655Srie } else if ((arhdr = elf_getarhdr(_elf)) == 0) { 6435aefb655Srie failure(file, 6445aefb655Srie MSG_ORIG(MSG_ELF_GETARHDR)); 6457e16fca0SAli Bahrami arhdr = NULL; 6465aefb655Srie } 6475aefb655Srie 6485aefb655Srie _offset = arsym->as_off; 6495aefb655Srie if (offset == 0) 6505aefb655Srie offset = _offset; 6515aefb655Srie } 6525aefb655Srie 6535aefb655Srie (void) snprintf(index, MAXNDXSIZE, 6545aefb655Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt)); 6555aefb655Srie if (arsym->as_off) 656*ba7866cdSAli Bahrami dbg_print(0, fmt_arsym1, index, 657*ba7866cdSAli Bahrami EC_XWORD(arsym->as_off), 658*ba7866cdSAli Bahrami arhdr ? arhdr->ar_name : 6595aefb655Srie MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ? 6605aefb655Srie demangle(arsym->as_name, flags) : 6615aefb655Srie MSG_INTL(MSG_STR_NULL))); 6625aefb655Srie else 663*ba7866cdSAli Bahrami dbg_print(0, fmt_arsym2, index, 664*ba7866cdSAli Bahrami EC_XWORD(arsym->as_off)); 6655aefb655Srie } 6665aefb655Srie 6675aefb655Srie if (_elf) 6685aefb655Srie (void) elf_end(_elf); 6695aefb655Srie 6705aefb655Srie /* 6715aefb655Srie * If we only need the archive symbol table return. 6725aefb655Srie */ 673981a172dSab196087 if ((flags & FLG_SHOW_SYMBOLS) && 674981a172dSab196087 match(MATCH_F_STRICT | MATCH_F_NAME, 675981a172dSab196087 MSG_ORIG(MSG_ELF_ARSYM), -1, -1)) 676981a172dSab196087 return (0); 6775aefb655Srie 6785aefb655Srie /* 6795aefb655Srie * Reset elf descriptor in preparation for processing each 6805aefb655Srie * member. 6815aefb655Srie */ 6825aefb655Srie if (offset) 6835aefb655Srie (void) elf_rand(elf, offset); 6845aefb655Srie } 6855aefb655Srie 6865aefb655Srie /* 6875aefb655Srie * Process each object within the archive. 6885aefb655Srie */ 6895aefb655Srie while ((_elf = elf_begin(fd, cmd, elf)) != NULL) { 6905aefb655Srie char name[MAXPATHLEN]; 6915aefb655Srie 6925aefb655Srie if ((arhdr = elf_getarhdr(_elf)) == NULL) { 6935aefb655Srie failure(file, MSG_ORIG(MSG_ELF_GETARHDR)); 694981a172dSab196087 return (0); 6955aefb655Srie } 6965aefb655Srie if (*arhdr->ar_name != '/') { 6975aefb655Srie (void) snprintf(name, MAXPATHLEN, 6985aefb655Srie MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name); 6995aefb655Srie dbg_print(0, MSG_ORIG(MSG_FMT_NLSTR), name); 7005aefb655Srie 7015aefb655Srie switch (elf_kind(_elf)) { 7025aefb655Srie case ELF_K_AR: 703981a172dSab196087 if (archive(name, fd, _elf, flags, 7044f680cc6SAli Bahrami wname, wfd, osabi) == 1) 705981a172dSab196087 return (1); 7065aefb655Srie break; 7075aefb655Srie case ELF_K_ELF: 708981a172dSab196087 if (decide(name, fd, _elf, flags, 7094f680cc6SAli Bahrami wname, wfd, osabi) == 1) 710981a172dSab196087 return (1); 7115aefb655Srie break; 7125aefb655Srie default: 7135aefb655Srie (void) fprintf(stderr, 7145aefb655Srie MSG_INTL(MSG_ERR_BADFILE), name); 7155aefb655Srie break; 7165aefb655Srie } 7175aefb655Srie } 7185aefb655Srie 7195aefb655Srie cmd = elf_next(_elf); 7205aefb655Srie (void) elf_end(_elf); 7215aefb655Srie } 722981a172dSab196087 723981a172dSab196087 return (0); 7245aefb655Srie } 7255aefb655Srie 7265aefb655Srie int 7275aefb655Srie main(int argc, char **argv, char **envp) 7285aefb655Srie { 7295aefb655Srie Elf *elf; 7305aefb655Srie int var, fd, wfd = 0; 731981a172dSab196087 char *wname = NULL; 7325aefb655Srie uint_t flags = 0; 733981a172dSab196087 match_rec_t match_data; 734981a172dSab196087 int ret; 7354f680cc6SAli Bahrami uchar_t osabi; 7365aefb655Srie 7375aefb655Srie /* 7385aefb655Srie * If we're on a 64-bit kernel, try to exec a full 64-bit version of 7395aefb655Srie * the binary. If successful, conv_check_native() won't return. 7405aefb655Srie */ 7417010c12aSrie (void) conv_check_native(argv, envp); 7425aefb655Srie 7435aefb655Srie /* 7445aefb655Srie * Establish locale. 7455aefb655Srie */ 7465aefb655Srie (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 7475aefb655Srie (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 7485aefb655Srie 7495aefb655Srie (void) setvbuf(stdout, NULL, _IOLBF, 0); 7505aefb655Srie (void) setvbuf(stderr, NULL, _IOLBF, 0); 7515aefb655Srie 7525aefb655Srie opterr = 0; 7535aefb655Srie while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) { 7545aefb655Srie switch (var) { 7555aefb655Srie case 'C': 756981a172dSab196087 flags |= FLG_CTL_DEMANGLE; 7575aefb655Srie break; 7585aefb655Srie case 'c': 759981a172dSab196087 flags |= FLG_SHOW_SHDR; 7605aefb655Srie break; 7615aefb655Srie case 'd': 762981a172dSab196087 flags |= FLG_SHOW_DYNAMIC; 7635aefb655Srie break; 7645aefb655Srie case 'e': 765981a172dSab196087 flags |= FLG_SHOW_EHDR; 7665aefb655Srie break; 7675aefb655Srie case 'G': 768981a172dSab196087 flags |= FLG_SHOW_GOT; 7695aefb655Srie break; 7705aefb655Srie case 'g': 771981a172dSab196087 flags |= FLG_SHOW_GROUP; 7725aefb655Srie break; 7735aefb655Srie case 'H': 774981a172dSab196087 flags |= FLG_SHOW_CAP; 7755aefb655Srie break; 7765aefb655Srie case 'h': 777981a172dSab196087 flags |= FLG_SHOW_HASH; 7785aefb655Srie break; 779c809c407Sab196087 case 'I': 780981a172dSab196087 if (!process_index_opt(optarg, &match_data)) 781981a172dSab196087 goto usage_brief; 782c809c407Sab196087 if (!add_match_record(argv[0], &match_data)) 783c809c407Sab196087 return (1); 784981a172dSab196087 flags |= FLG_CTL_MATCH; 785c809c407Sab196087 break; 7865aefb655Srie case 'i': 787981a172dSab196087 flags |= FLG_SHOW_INTERP; 7885aefb655Srie break; 7895aefb655Srie case 'k': 790981a172dSab196087 flags |= FLG_CALC_CHECKSUM; 7915aefb655Srie break; 7925aefb655Srie case 'l': 793981a172dSab196087 flags |= FLG_CTL_LONGNAME; 7945aefb655Srie break; 7955aefb655Srie case 'm': 796981a172dSab196087 flags |= FLG_SHOW_MOVE; 7975aefb655Srie break; 7985aefb655Srie case 'N': 799981a172dSab196087 match_data.opt_type = MATCH_OPT_NAME; 800c809c407Sab196087 match_data.value.name = optarg; 801c809c407Sab196087 if (!add_match_record(argv[0], &match_data)) 802c809c407Sab196087 return (1); 803981a172dSab196087 flags |= FLG_CTL_MATCH; 8045aefb655Srie break; 8055aefb655Srie case 'n': 806981a172dSab196087 flags |= FLG_SHOW_NOTE; 8075aefb655Srie break; 8084f680cc6SAli Bahrami case 'O': 8094f680cc6SAli Bahrami { 8104f680cc6SAli Bahrami uint32_t val; 8114f680cc6SAli Bahrami 8124f680cc6SAli Bahrami /* 8134f680cc6SAli Bahrami * osabi is a uchar_t in the ELF header. 8144f680cc6SAli Bahrami * Don't accept any value that exceeds 8154f680cc6SAli Bahrami * that range. 8164f680cc6SAli Bahrami */ 8174f680cc6SAli Bahrami if ((atoui(optarg, ATOUI_OSABI, &val) == 0) || 8184f680cc6SAli Bahrami (val > 255)) { 8194f680cc6SAli Bahrami (void) fprintf(stderr, 8204f680cc6SAli Bahrami MSG_INTL(MSG_ERR_BAD_T_OSABI), 8214f680cc6SAli Bahrami basename(argv[0]), optarg); 8224f680cc6SAli Bahrami return (1); 8234f680cc6SAli Bahrami } 8244f680cc6SAli Bahrami osabi = val; 8254f680cc6SAli Bahrami } 8264f680cc6SAli Bahrami flags |= FLG_CTL_OSABI; 8274f680cc6SAli Bahrami break; 82839773e46Sab196087 case 'P': 829981a172dSab196087 flags |= FLG_CTL_FAKESHDR; 83039773e46Sab196087 break; 8315aefb655Srie case 'p': 832981a172dSab196087 flags |= FLG_SHOW_PHDR; 8335aefb655Srie break; 8345aefb655Srie case 'r': 835981a172dSab196087 flags |= FLG_SHOW_RELOC; 8365aefb655Srie break; 837d579eb63Sab196087 case 'S': 838981a172dSab196087 flags |= FLG_SHOW_SORT; 839d579eb63Sab196087 break; 8405aefb655Srie case 's': 841981a172dSab196087 flags |= FLG_SHOW_SYMBOLS; 842981a172dSab196087 break; 843981a172dSab196087 case 'T': 844981a172dSab196087 /* 845981a172dSab196087 * We can't evaluate the value yet, because 846981a172dSab196087 * we need to know if -p is used or not in 847981a172dSab196087 * order to tell if we're seeing section header 848981a172dSab196087 * or program header types. So, we save the 849981a172dSab196087 * string in the name field, and then convert 850981a172dSab196087 * it to a type integer in a following pass. 851981a172dSab196087 */ 852981a172dSab196087 match_data.opt_type = MATCH_OPT_TYPE; 853981a172dSab196087 match_data.value.name = optarg; 854981a172dSab196087 if (!add_match_record(argv[0], &match_data)) 855981a172dSab196087 return (1); 856981a172dSab196087 flags |= FLG_CTL_MATCH; 8575aefb655Srie break; 8585aefb655Srie case 'u': 859981a172dSab196087 flags |= FLG_SHOW_UNWIND; 8605aefb655Srie break; 8615aefb655Srie case 'v': 862981a172dSab196087 flags |= FLG_SHOW_VERSIONS; 8635aefb655Srie break; 8645aefb655Srie case 'w': 8655aefb655Srie wname = optarg; 8665aefb655Srie break; 8675aefb655Srie case 'y': 868981a172dSab196087 flags |= FLG_SHOW_SYMINFO; 8695aefb655Srie break; 8705aefb655Srie case '?': 8715aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 8725aefb655Srie basename(argv[0])); 8735aefb655Srie detail_usage(); 8745aefb655Srie return (1); 8755aefb655Srie default: 8765aefb655Srie break; 8775aefb655Srie } 8785aefb655Srie } 8795aefb655Srie 880981a172dSab196087 /* -p and -w are mutually exclusive. -w only works with sections */ 881981a172dSab196087 if (((flags & FLG_SHOW_PHDR) != 0) && (wname != NULL)) 882981a172dSab196087 goto usage_brief; 883981a172dSab196087 884981a172dSab196087 /* If a match argument is present, prepare the match state */ 885981a172dSab196087 if ((match_state.list != NULL) && (match_prepare(argv[0], flags) == 0)) 8865aefb655Srie return (1); 887981a172dSab196087 888981a172dSab196087 /* 889981a172dSab196087 * Decide what to do if no options specifying something to 890981a172dSab196087 * show or do are present. 891981a172dSab196087 * 892981a172dSab196087 * If there is no -w and no match options, then we will set all 893981a172dSab196087 * the show flags, causing a full display of everything in the 894981a172dSab196087 * file that we know how to handle. 895981a172dSab196087 * 896981a172dSab196087 * Otherwise, if there is no match list, we generate a usage 897981a172dSab196087 * error and quit. 898981a172dSab196087 * 899981a172dSab196087 * In the case where there is a match list, we go ahead and call 900981a172dSab196087 * regular() anyway, leaving it to decide what to do. If -w is 901981a172dSab196087 * present, regular() will use the match list to handle it. 902981a172dSab196087 * In addition, in the absence of explicit show/calc flags, regular() 903981a172dSab196087 * will compare the section headers to the match list and use 904981a172dSab196087 * that to generate the FLG_ bits that will display the information 905981a172dSab196087 * specified by the match list. 906981a172dSab196087 */ 907981a172dSab196087 if ((flags & ~FLG_MASK_CTL) == 0) { 908981a172dSab196087 if (!wname && (match_state.list == NULL)) 909981a172dSab196087 flags |= FLG_MASK_SHOW; 910981a172dSab196087 else if (match_state.list == NULL) 911981a172dSab196087 goto usage_brief; 9125aefb655Srie } 9135aefb655Srie 914981a172dSab196087 /* There needs to be at least 1 filename left following the options */ 915981a172dSab196087 if ((var = argc - optind) == 0) 916981a172dSab196087 goto usage_brief; 9175aefb655Srie 9185aefb655Srie /* 9195aefb655Srie * If the -l/-C option is specified, set up the liblddbg.so. 9205aefb655Srie */ 921981a172dSab196087 if (flags & FLG_CTL_LONGNAME) 9225aefb655Srie dbg_desc->d_extra |= DBG_E_LONG; 923981a172dSab196087 if (flags & FLG_CTL_DEMANGLE) 9245aefb655Srie dbg_desc->d_extra |= DBG_E_DEMANGLE; 9255aefb655Srie 9265aefb655Srie /* 9275aefb655Srie * If the -w option has indicated an output file open it. It's 9285aefb655Srie * arguable whether this option has much use when multiple files are 9295aefb655Srie * being processed. 930981a172dSab196087 * 931981a172dSab196087 * If wname is non-NULL, we know that -p was not specified, due 932981a172dSab196087 * to the test above. 9335aefb655Srie */ 9345aefb655Srie if (wname) { 9355aefb655Srie if ((wfd = open(wname, (O_RDWR | O_CREAT | O_TRUNC), 9365aefb655Srie 0666)) < 0) { 9375aefb655Srie int err = errno; 9385aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 9395aefb655Srie wname, strerror(err)); 940981a172dSab196087 return (1); 9415aefb655Srie } 9425aefb655Srie } 9435aefb655Srie 9445aefb655Srie /* 945981a172dSab196087 * Open the input file, initialize the elf interface, and 946981a172dSab196087 * process it. 9475aefb655Srie */ 948981a172dSab196087 ret = 0; 949981a172dSab196087 for (; (optind < argc) && (ret == 0); optind++) { 9505aefb655Srie const char *file = argv[optind]; 9515aefb655Srie 9525aefb655Srie if ((fd = open(argv[optind], O_RDONLY)) == -1) { 9535aefb655Srie int err = errno; 9545aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 9555aefb655Srie file, strerror(err)); 9565aefb655Srie continue; 9575aefb655Srie } 9585aefb655Srie (void) elf_version(EV_CURRENT); 9595aefb655Srie if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 9605aefb655Srie failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 9615aefb655Srie (void) close(fd); 9625aefb655Srie continue; 9635aefb655Srie } 9645aefb655Srie 9655aefb655Srie if (var > 1) 9665aefb655Srie dbg_print(0, MSG_ORIG(MSG_FMT_NLSTRNL), file); 9675aefb655Srie 9685aefb655Srie switch (elf_kind(elf)) { 9695aefb655Srie case ELF_K_AR: 9704f680cc6SAli Bahrami ret = archive(file, fd, elf, flags, wname, wfd, osabi); 9715aefb655Srie break; 9725aefb655Srie case ELF_K_ELF: 9734f680cc6SAli Bahrami ret = decide(file, fd, elf, flags, wname, wfd, osabi); 9745aefb655Srie break; 9755aefb655Srie default: 9765aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADFILE), file); 9775aefb655Srie break; 9785aefb655Srie } 9795aefb655Srie 9805aefb655Srie (void) close(fd); 9815aefb655Srie (void) elf_end(elf); 9825aefb655Srie } 9835aefb655Srie 9845aefb655Srie if (wfd) 9855aefb655Srie (void) close(wfd); 986981a172dSab196087 return (ret); 987981a172dSab196087 988981a172dSab196087 usage_brief: 989981a172dSab196087 /* Control comes here for a simple usage message and exit */ 990981a172dSab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 991981a172dSab196087 basename(argv[0])); 992981a172dSab196087 return (1); 993981a172dSab196087 9945aefb655Srie } 995