11618Srie /* 21618Srie * CDDL HEADER START 31618Srie * 41618Srie * The contents of this file are subject to the terms of the 51618Srie * Common Development and Distribution License (the "License"). 61618Srie * You may not use this file except in compliance with the License. 71618Srie * 81618Srie * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91618Srie * or http://www.opensolaris.org/os/licensing. 101618Srie * See the License for the specific language governing permissions 111618Srie * and limitations under the License. 121618Srie * 131618Srie * When distributing Covered Code, include this CDDL HEADER in each 141618Srie * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151618Srie * If applicable, add the following below this CDDL HEADER, with the 161618Srie * fields enclosed by brackets "[]" replaced with your own identifying 171618Srie * information: Portions Copyright [yyyy] [name of copyright owner] 181618Srie * 191618Srie * CDDL HEADER END 201618Srie */ 211618Srie 221618Srie /* 233492Sab196087 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 241618Srie * Use is subject to license terms. 251618Srie */ 261618Srie #pragma ident "%Z%%M% %I% %E% SMI" 271618Srie 281618Srie /* 291618Srie * Dump an elf file. 301618Srie */ 311618Srie #include <sys/param.h> 321618Srie #include <fcntl.h> 331618Srie #include <stdio.h> 344168Sab196087 #include <stdlib.h> 354168Sab196087 #include <ctype.h> 361618Srie #include <libelf.h> 371618Srie #include <link.h> 381618Srie #include <stdarg.h> 391618Srie #include <unistd.h> 401618Srie #include <libgen.h> 411618Srie #include <libintl.h> 421618Srie #include <locale.h> 431618Srie #include <errno.h> 441618Srie #include <strings.h> 451618Srie #include <debug.h> 461618Srie #include <conv.h> 471618Srie #include <msg.h> 481618Srie #include <_elfdump.h> 49*5411Sab196087 #include <sys/elf_SPARC.h> 50*5411Sab196087 #include <sys/elf_amd64.h> 51*5411Sab196087 521618Srie 534063Sab196087 const Cache cache_init = {NULL, NULL, NULL, NULL, 0}; 541618Srie 554168Sab196087 564168Sab196087 57*5411Sab196087 /* 58*5411Sab196087 * The -I, -N, and -T options are called "match options", because 59*5411Sab196087 * they allow selecting the items to be displayed based on matching 60*5411Sab196087 * their index, name, or type. 61*5411Sab196087 * 62*5411Sab196087 * The ELF information to which -I, -N, or -T are applied in 63*5411Sab196087 * the current invocation is called the "match item". 64*5411Sab196087 */ 654168Sab196087 typedef enum { 66*5411Sab196087 MATCH_ITEM_PT, /* Program header (PT_) */ 67*5411Sab196087 MATCH_ITEM_SHT /* Section header (SHT_) */ 68*5411Sab196087 } match_item_t; 69*5411Sab196087 70*5411Sab196087 /* match_opt_t is used to note which match option was used */ 71*5411Sab196087 typedef enum { 72*5411Sab196087 MATCH_OPT_NAME, /* Record contains a name */ 73*5411Sab196087 MATCH_OPT_NDX, /* Record contains a single index */ 74*5411Sab196087 MATCH_OPT_RANGE, /* Record contains an index range */ 75*5411Sab196087 MATCH_OPT_TYPE, /* Record contains a type (shdr or phdr) */ 76*5411Sab196087 } match_opt_t; 774168Sab196087 784168Sab196087 typedef struct _match { 794168Sab196087 struct _match *next; /* Pointer to next item in list */ 80*5411Sab196087 match_opt_t opt_type; 814168Sab196087 union { 82*5411Sab196087 const char *name; /* MATCH_OPT_NAME */ 83*5411Sab196087 struct { /* MATCH_OPT_NDX and MATCH_OPT_RANGE */ 844168Sab196087 int start; 85*5411Sab196087 int end; /* Only for MATCH_OPT_RANGE */ 864168Sab196087 } ndx; 87*5411Sab196087 uint32_t type; /* MATCH_OPT_TYPE */ 884168Sab196087 } value; 89*5411Sab196087 } match_rec_t; 90*5411Sab196087 91*5411Sab196087 static struct { 92*5411Sab196087 match_item_t item_type; /* Type of item being matched */ 93*5411Sab196087 match_rec_t *list; /* Records for (-I, -N, -T) options */ 94*5411Sab196087 } match_state; 95*5411Sab196087 96*5411Sab196087 97*5411Sab196087 98*5411Sab196087 /* Map names to their integer value */ 99*5411Sab196087 typedef struct { 100*5411Sab196087 const char *sym_name; 101*5411Sab196087 uint32_t sym_value; 102*5411Sab196087 } atoui_sym_t; 103*5411Sab196087 104*5411Sab196087 /* 105*5411Sab196087 * ELF section types. 106*5411Sab196087 */ 107*5411Sab196087 static atoui_sym_t sym_sht[] = { 108*5411Sab196087 { MSG_ORIG(MSG_SHT_NULL), SHT_NULL }, 109*5411Sab196087 { MSG_ORIG(MSG_SHT_NULL_ALT1), SHT_NULL }, 110*5411Sab196087 111*5411Sab196087 { MSG_ORIG(MSG_SHT_PROGBITS), SHT_PROGBITS }, 112*5411Sab196087 { MSG_ORIG(MSG_SHT_PROGBITS_ALT1), SHT_PROGBITS }, 113*5411Sab196087 114*5411Sab196087 { MSG_ORIG(MSG_SHT_SYMTAB), SHT_SYMTAB }, 115*5411Sab196087 { MSG_ORIG(MSG_SHT_SYMTAB_ALT1), SHT_SYMTAB }, 116*5411Sab196087 117*5411Sab196087 { MSG_ORIG(MSG_SHT_STRTAB), SHT_STRTAB }, 118*5411Sab196087 { MSG_ORIG(MSG_SHT_STRTAB_ALT1), SHT_STRTAB }, 119*5411Sab196087 120*5411Sab196087 { MSG_ORIG(MSG_SHT_RELA), SHT_RELA }, 121*5411Sab196087 { MSG_ORIG(MSG_SHT_RELA_ALT1), SHT_RELA }, 122*5411Sab196087 123*5411Sab196087 { MSG_ORIG(MSG_SHT_HASH), SHT_HASH }, 124*5411Sab196087 { MSG_ORIG(MSG_SHT_HASH_ALT1), SHT_HASH }, 125*5411Sab196087 126*5411Sab196087 { MSG_ORIG(MSG_SHT_DYNAMIC), SHT_DYNAMIC }, 127*5411Sab196087 { MSG_ORIG(MSG_SHT_DYNAMIC_ALT1), SHT_DYNAMIC }, 128*5411Sab196087 129*5411Sab196087 { MSG_ORIG(MSG_SHT_NOTE), SHT_NOTE }, 130*5411Sab196087 { MSG_ORIG(MSG_SHT_NOTE_ALT1), SHT_NOTE }, 131*5411Sab196087 132*5411Sab196087 { MSG_ORIG(MSG_SHT_NOBITS), SHT_NOBITS }, 133*5411Sab196087 { MSG_ORIG(MSG_SHT_NOBITS_ALT1), SHT_NOBITS }, 134*5411Sab196087 135*5411Sab196087 { MSG_ORIG(MSG_SHT_REL), SHT_REL }, 136*5411Sab196087 { MSG_ORIG(MSG_SHT_REL_ALT1), SHT_REL }, 137*5411Sab196087 138*5411Sab196087 { MSG_ORIG(MSG_SHT_SHLIB), SHT_SHLIB }, 139*5411Sab196087 { MSG_ORIG(MSG_SHT_SHLIB_ALT1), SHT_SHLIB }, 140*5411Sab196087 141*5411Sab196087 { MSG_ORIG(MSG_SHT_DYNSYM), SHT_DYNSYM }, 142*5411Sab196087 { MSG_ORIG(MSG_SHT_DYNSYM_ALT1), SHT_DYNSYM }, 143*5411Sab196087 144*5411Sab196087 { MSG_ORIG(MSG_SHT_INIT_ARRAY), SHT_INIT_ARRAY }, 145*5411Sab196087 { MSG_ORIG(MSG_SHT_INIT_ARRAY_ALT1), SHT_INIT_ARRAY }, 146*5411Sab196087 147*5411Sab196087 { MSG_ORIG(MSG_SHT_FINI_ARRAY), SHT_FINI_ARRAY }, 148*5411Sab196087 { MSG_ORIG(MSG_SHT_FINI_ARRAY_ALT1), SHT_FINI_ARRAY }, 149*5411Sab196087 150*5411Sab196087 { MSG_ORIG(MSG_SHT_PREINIT_ARRAY), SHT_PREINIT_ARRAY }, 151*5411Sab196087 { MSG_ORIG(MSG_SHT_PREINIT_ARRAY_ALT1), SHT_PREINIT_ARRAY }, 152*5411Sab196087 153*5411Sab196087 { MSG_ORIG(MSG_SHT_GROUP), SHT_GROUP }, 154*5411Sab196087 { MSG_ORIG(MSG_SHT_GROUP_ALT1), SHT_GROUP }, 155*5411Sab196087 156*5411Sab196087 { MSG_ORIG(MSG_SHT_SYMTAB_SHNDX), SHT_SYMTAB_SHNDX }, 157*5411Sab196087 { MSG_ORIG(MSG_SHT_SYMTAB_SHNDX_ALT1), SHT_SYMTAB_SHNDX }, 158*5411Sab196087 159*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_SYMSORT), SHT_SUNW_symsort }, 160*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_SYMSORT_ALT1), SHT_SUNW_symsort }, 161*5411Sab196087 162*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_TLSSORT), SHT_SUNW_tlssort }, 163*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_TLSSORT_ALT1), SHT_SUNW_tlssort }, 164*5411Sab196087 165*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_LDYNSYM), SHT_SUNW_LDYNSYM }, 166*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_LDYNSYM_ALT1), SHT_SUNW_LDYNSYM }, 167*5411Sab196087 168*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_DOF), SHT_SUNW_dof }, 169*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_DOF_ALT1), SHT_SUNW_dof }, 170*5411Sab196087 171*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_CAP), SHT_SUNW_cap }, 172*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_CAP_ALT1), SHT_SUNW_cap }, 173*5411Sab196087 174*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_SIGNATURE), SHT_SUNW_SIGNATURE }, 175*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_SIGNATURE_ALT1), SHT_SUNW_SIGNATURE }, 176*5411Sab196087 177*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_ANNOTATE), SHT_SUNW_ANNOTATE }, 178*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_ANNOTATE_ALT1), SHT_SUNW_ANNOTATE }, 1794168Sab196087 180*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_DEBUGSTR), SHT_SUNW_DEBUGSTR }, 181*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_DEBUGSTR_ALT1), SHT_SUNW_DEBUGSTR }, 182*5411Sab196087 183*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_DEBUG), SHT_SUNW_DEBUG }, 184*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_DEBUG_ALT1), SHT_SUNW_DEBUG }, 185*5411Sab196087 186*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_MOVE), SHT_SUNW_move }, 187*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_MOVE_ALT1), SHT_SUNW_move }, 188*5411Sab196087 189*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_COMDAT), SHT_SUNW_COMDAT }, 190*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_COMDAT_ALT1), SHT_SUNW_COMDAT }, 191*5411Sab196087 192*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_SYMINFO), SHT_SUNW_syminfo }, 193*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_SYMINFO_ALT1), SHT_SUNW_syminfo }, 194*5411Sab196087 195*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_VERDEF), SHT_SUNW_verdef }, 196*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_VERDEF_ALT1), SHT_SUNW_verdef }, 197*5411Sab196087 198*5411Sab196087 { MSG_ORIG(MSG_SHT_GNU_VERDEF), SHT_GNU_verdef }, 199*5411Sab196087 { MSG_ORIG(MSG_SHT_GNU_VERDEF_ALT1), SHT_GNU_verdef }, 200*5411Sab196087 201*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_VERNEED), SHT_SUNW_verneed }, 202*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_VERNEED_ALT1), SHT_SUNW_verneed }, 203*5411Sab196087 204*5411Sab196087 { MSG_ORIG(MSG_SHT_GNU_VERNEED), SHT_GNU_verneed }, 205*5411Sab196087 { MSG_ORIG(MSG_SHT_GNU_VERNEED_ALT1), SHT_GNU_verneed }, 206*5411Sab196087 207*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_VERSYM), SHT_SUNW_versym }, 208*5411Sab196087 { MSG_ORIG(MSG_SHT_SUNW_VERSYM_ALT1), SHT_SUNW_versym }, 209*5411Sab196087 210*5411Sab196087 { MSG_ORIG(MSG_SHT_GNU_VERSYM), SHT_GNU_versym }, 211*5411Sab196087 { MSG_ORIG(MSG_SHT_GNU_VERSYM_ALT1), SHT_GNU_versym }, 212*5411Sab196087 213*5411Sab196087 { MSG_ORIG(MSG_SHT_SPARC_GOTDATA), SHT_SPARC_GOTDATA }, 214*5411Sab196087 { MSG_ORIG(MSG_SHT_SPARC_GOTDATA_ALT1), SHT_SPARC_GOTDATA }, 215*5411Sab196087 216*5411Sab196087 { MSG_ORIG(MSG_SHT_AMD64_UNWIND), SHT_AMD64_UNWIND }, 217*5411Sab196087 { MSG_ORIG(MSG_SHT_AMD64_UNWIND_ALT1), SHT_AMD64_UNWIND }, 218*5411Sab196087 219*5411Sab196087 { NULL } 220*5411Sab196087 }; 221*5411Sab196087 222*5411Sab196087 /* 223*5411Sab196087 * Program header PT_* type values 224*5411Sab196087 */ 225*5411Sab196087 static atoui_sym_t sym_pt[] = { 226*5411Sab196087 { MSG_ORIG(MSG_PT_NULL), PT_NULL }, 227*5411Sab196087 { MSG_ORIG(MSG_PT_NULL_ALT1), PT_NULL }, 228*5411Sab196087 229*5411Sab196087 { MSG_ORIG(MSG_PT_LOAD), PT_LOAD }, 230*5411Sab196087 { MSG_ORIG(MSG_PT_LOAD_ALT1), PT_LOAD }, 231*5411Sab196087 232*5411Sab196087 { MSG_ORIG(MSG_PT_DYNAMIC), PT_DYNAMIC }, 233*5411Sab196087 { MSG_ORIG(MSG_PT_DYNAMIC_ALT1), PT_DYNAMIC }, 234*5411Sab196087 235*5411Sab196087 { MSG_ORIG(MSG_PT_INTERP), PT_INTERP }, 236*5411Sab196087 { MSG_ORIG(MSG_PT_INTERP_ALT1), PT_INTERP }, 237*5411Sab196087 238*5411Sab196087 { MSG_ORIG(MSG_PT_NOTE), PT_NOTE }, 239*5411Sab196087 { MSG_ORIG(MSG_PT_NOTE_ALT1), PT_NOTE }, 240*5411Sab196087 241*5411Sab196087 { MSG_ORIG(MSG_PT_SHLIB), PT_SHLIB }, 242*5411Sab196087 { MSG_ORIG(MSG_PT_SHLIB_ALT1), PT_SHLIB }, 243*5411Sab196087 244*5411Sab196087 { MSG_ORIG(MSG_PT_PHDR), PT_PHDR }, 245*5411Sab196087 { MSG_ORIG(MSG_PT_PHDR_ALT1), PT_PHDR }, 246*5411Sab196087 247*5411Sab196087 { MSG_ORIG(MSG_PT_TLS), PT_TLS }, 248*5411Sab196087 { MSG_ORIG(MSG_PT_TLS_ALT1), PT_TLS }, 249*5411Sab196087 250*5411Sab196087 { MSG_ORIG(MSG_PT_SUNW_UNWIND), PT_SUNW_UNWIND }, 251*5411Sab196087 { MSG_ORIG(MSG_PT_SUNW_UNWIND_ALT1), PT_SUNW_UNWIND }, 252*5411Sab196087 253*5411Sab196087 { MSG_ORIG(MSG_PT_SUNWBSS), PT_SUNWBSS }, 254*5411Sab196087 { MSG_ORIG(MSG_PT_SUNWBSS_ALT1), PT_SUNWBSS }, 255*5411Sab196087 256*5411Sab196087 { MSG_ORIG(MSG_PT_SUNWSTACK), PT_SUNWSTACK }, 257*5411Sab196087 { MSG_ORIG(MSG_PT_SUNWSTACK_ALT1), PT_SUNWSTACK }, 258*5411Sab196087 259*5411Sab196087 { MSG_ORIG(MSG_PT_SUNWDTRACE), PT_SUNWDTRACE }, 260*5411Sab196087 { MSG_ORIG(MSG_PT_SUNWDTRACE_ALT1), PT_SUNWDTRACE }, 261*5411Sab196087 262*5411Sab196087 { MSG_ORIG(MSG_PT_SUNWCAP), PT_SUNWCAP }, 263*5411Sab196087 { MSG_ORIG(MSG_PT_SUNWCAP_ALT1), PT_SUNWCAP }, 264*5411Sab196087 265*5411Sab196087 { NULL } 266*5411Sab196087 }; 267*5411Sab196087 268*5411Sab196087 269*5411Sab196087 270*5411Sab196087 2714168Sab196087 2721618Srie const char * 2731618Srie _elfdump_msg(Msg mid) 2741618Srie { 2751618Srie return (gettext(MSG_ORIG(mid))); 2761618Srie } 2771618Srie 2781618Srie /* 2791618Srie * Determine whether a symbol name should be demangled. 2801618Srie */ 2811618Srie const char * 2821618Srie demangle(const char *name, uint_t flags) 2831618Srie { 284*5411Sab196087 if (flags & FLG_CTL_DEMANGLE) 2851618Srie return (Elf_demangle_name(name)); 2861618Srie else 2871618Srie return ((char *)name); 2881618Srie } 2891618Srie 2901618Srie /* 2911618Srie * Define our own standard error routine. 2921618Srie */ 2931618Srie void 2941618Srie failure(const char *file, const char *func) 2951618Srie { 2961618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_FAILURE), 2971618Srie file, func, elf_errmsg(elf_errno())); 2981618Srie } 2991618Srie 3001618Srie /* 3011618Srie * The full usage message 3021618Srie */ 3031618Srie static void 3041618Srie detail_usage() 3051618Srie { 3061618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL1)); 3071618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL2)); 3081618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL3)); 3091618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL4)); 3101618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL5)); 3111618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL6)); 3121618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL7)); 3131618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL8)); 3141618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9)); 3151618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL10)); 3161618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL11)); 3171618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL12)); 3181618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL13)); 3191618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL14)); 3201618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL15)); 3211618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL16)); 3221618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL17)); 3231618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL18)); 3241618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL19)); 3251618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL20)); 3263492Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL21)); 3274168Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL22)); 3284168Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL23)); 3294665Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL24)); 330*5411Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL25)); 3314168Sab196087 } 3324168Sab196087 3334168Sab196087 /* 3344168Sab196087 * Convert the ASCII representation of an index, or index range, into 3354168Sab196087 * binary form, and store it in rec: 3364168Sab196087 * 3374168Sab196087 * index: An positive or 0 valued integer 3384168Sab196087 * range: Two indexes, separated by a ':' character, denoting 3394168Sab196087 * a range of allowed values. If the second value is omitted, 3404168Sab196087 * any values equal to or greater than the first will match. 3414168Sab196087 * 3424168Sab196087 * exit: 343*5411Sab196087 * On success, *rec is filled in with a MATCH_OPT_NDX or MATCH_OPT_RANGE 3444168Sab196087 * value, and this function returns (1). On failure, the contents 3454168Sab196087 * of *rec are undefined, and (0) is returned. 3464168Sab196087 */ 3474168Sab196087 int 348*5411Sab196087 process_index_opt(const char *str, match_rec_t *rec) 3494168Sab196087 { 3504168Sab196087 #define SKIP_BLANK for (; *str && isspace(*str); str++) 3514168Sab196087 3524168Sab196087 char *endptr; 3534168Sab196087 3544168Sab196087 rec->value.ndx.start = strtol(str, &endptr, 10); 3554168Sab196087 /* Value must use some of the input, and be 0 or positive */ 3564168Sab196087 if ((str == endptr) || (rec->value.ndx.start < 0)) 3574168Sab196087 return (0); 3584168Sab196087 str = endptr; 3594168Sab196087 3604168Sab196087 SKIP_BLANK; 3614168Sab196087 if (*str != ':') { 362*5411Sab196087 rec->opt_type = MATCH_OPT_NDX; 3634168Sab196087 } else { 3644168Sab196087 str++; /* Skip the ':' */ 365*5411Sab196087 rec->opt_type = MATCH_OPT_RANGE; 3664168Sab196087 SKIP_BLANK; 3674168Sab196087 if (*str == '\0') { 3684168Sab196087 rec->value.ndx.end = -1; /* Indicates "to end" */ 3694168Sab196087 } else { 3704168Sab196087 rec->value.ndx.end = strtol(str, &endptr, 10); 3714168Sab196087 if ((str == endptr) || (rec->value.ndx.end < 0)) 3724168Sab196087 return (0); 3734168Sab196087 str = endptr; 3744168Sab196087 SKIP_BLANK; 3754168Sab196087 } 3764168Sab196087 } 3774168Sab196087 3784168Sab196087 /* Syntax error if anything is left over */ 3794168Sab196087 if (*str != '\0') 3804168Sab196087 return (0); 3814168Sab196087 3824168Sab196087 return (1); 3834168Sab196087 3844168Sab196087 #undef SKIP_BLANK 3854168Sab196087 } 3864168Sab196087 3874168Sab196087 /* 388*5411Sab196087 * Process the symbolic name to value mappings passed to the 389*5411Sab196087 * atoui() function. 390*5411Sab196087 * 391*5411Sab196087 * entry: 392*5411Sab196087 * sym - NULL terminated array of name->value mappings. 393*5411Sab196087 * value - Address of variable to receive corresponding value. 394*5411Sab196087 * 395*5411Sab196087 * exit: 396*5411Sab196087 * If a mapping is found, *value is set to it, and True is returned. 397*5411Sab196087 * Otherwise False is returned. 398*5411Sab196087 */ 399*5411Sab196087 static int 400*5411Sab196087 atoui_sym_process(const char *str, const atoui_sym_t *sym, uint32_t *value) 401*5411Sab196087 { 402*5411Sab196087 size_t cmp_len; 403*5411Sab196087 const char *tail; 404*5411Sab196087 405*5411Sab196087 while (isspace(*str)) 406*5411Sab196087 str++; 407*5411Sab196087 408*5411Sab196087 tail = str + strlen(str); 409*5411Sab196087 while ((tail > str) && isspace(*(tail - 1))) 410*5411Sab196087 tail--; 411*5411Sab196087 412*5411Sab196087 cmp_len = tail - str; 413*5411Sab196087 414*5411Sab196087 for (; sym->sym_name != NULL; sym++) { 415*5411Sab196087 if ((strlen(sym->sym_name) == cmp_len) && 416*5411Sab196087 (strncasecmp(sym->sym_name, str, cmp_len) == 0)) { 417*5411Sab196087 *value = sym->sym_value; 418*5411Sab196087 return (1); 419*5411Sab196087 } 420*5411Sab196087 } 421*5411Sab196087 422*5411Sab196087 /* No symbolic mapping was found */ 423*5411Sab196087 return (0); 424*5411Sab196087 } 425*5411Sab196087 426*5411Sab196087 427*5411Sab196087 /* 428*5411Sab196087 * Convert a string to a numeric value. Strings starting with '0' 429*5411Sab196087 * are taken to be octal, those staring with '0x' are hex, and all 430*5411Sab196087 * others are decimal. 431*5411Sab196087 * 432*5411Sab196087 * entry: 433*5411Sab196087 * str - String to be converted 434*5411Sab196087 * sym - NULL, or NULL terminated array of name/value pairs. 435*5411Sab196087 * v - Address of variable to receive resulting value. 436*5411Sab196087 * 437*5411Sab196087 * exit: 438*5411Sab196087 * On success, returns True (1) and *v is set to the value. 439*5411Sab196087 * On failure, returns False (0) and *v is undefined. 440*5411Sab196087 */ 441*5411Sab196087 static int 442*5411Sab196087 atoui(const char *str, const atoui_sym_t *sym, uint32_t *v) 443*5411Sab196087 { 444*5411Sab196087 char *endptr; 445*5411Sab196087 446*5411Sab196087 if (sym && atoui_sym_process(str, sym, v)) 447*5411Sab196087 return (1); 448*5411Sab196087 449*5411Sab196087 *v = strtoull(str, &endptr, 0); 450*5411Sab196087 451*5411Sab196087 /* If the left over part contains anything but whitespace, fail */ 452*5411Sab196087 for (; *endptr; endptr++) 453*5411Sab196087 if (!isspace(*endptr)) 454*5411Sab196087 return (0); 455*5411Sab196087 return (1); 456*5411Sab196087 } 457*5411Sab196087 458*5411Sab196087 /* 459*5411Sab196087 * Called after getopt() processing is finished if there is a non-empty 460*5411Sab196087 * match list. Prepares the matching code for use. 461*5411Sab196087 * 462*5411Sab196087 * exit: 463*5411Sab196087 * Returns True (1) if no errors are encountered. Writes an 464*5411Sab196087 * error string to stderr and returns False (0) otherwise. 465*5411Sab196087 */ 466*5411Sab196087 static int 467*5411Sab196087 match_prepare(char *argv0, uint_t flags) 468*5411Sab196087 { 469*5411Sab196087 atoui_sym_t *sym; 470*5411Sab196087 match_rec_t *list; 471*5411Sab196087 const char *str; 472*5411Sab196087 int minus_p = (flags & FLG_SHOW_PHDR) != 0; 473*5411Sab196087 474*5411Sab196087 /* 475*5411Sab196087 * Flag ambiguous attempt to use match option with both -p and 476*5411Sab196087 * and one or more section SHOW options. In this case, we 477*5411Sab196087 * can't tell what type of item we're supposed to match against. 478*5411Sab196087 */ 479*5411Sab196087 if (minus_p && (flags & FLG_MASK_SHOW_SHDR)) { 480*5411Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_AMBIG_MATCH), 481*5411Sab196087 basename(argv0)); 482*5411Sab196087 return (0); 483*5411Sab196087 } 484*5411Sab196087 485*5411Sab196087 /* Set the match type, based on the presence of the -p option */ 486*5411Sab196087 if (minus_p) { 487*5411Sab196087 match_state.item_type = MATCH_ITEM_PT; 488*5411Sab196087 sym = sym_pt; 489*5411Sab196087 } else { 490*5411Sab196087 match_state.item_type = MATCH_ITEM_SHT; 491*5411Sab196087 sym = sym_sht; 492*5411Sab196087 } 493*5411Sab196087 494*5411Sab196087 /* 495*5411Sab196087 * Scan match list and perform any necessary fixups: 496*5411Sab196087 * 497*5411Sab196087 * MATCH_OPT_NAME: If -p is specified, convert MATCH_OPT_NAME (-N) 498*5411Sab196087 * requests into MATCH_OPT_TYPE (-T). 499*5411Sab196087 * 500*5411Sab196087 * MATCH_OPT_TYPE: Now that we know item type we are matching 501*5411Sab196087 * against, we can convert the string saved in the name 502*5411Sab196087 * field during getopt() processing into an integer and 503*5411Sab196087 * write it into the type field. 504*5411Sab196087 */ 505*5411Sab196087 for (list = match_state.list; list; list = list->next) { 506*5411Sab196087 if ((list->opt_type == MATCH_OPT_NAME) && minus_p) 507*5411Sab196087 list->opt_type = MATCH_OPT_TYPE; 508*5411Sab196087 509*5411Sab196087 if (list->opt_type != MATCH_OPT_TYPE) 510*5411Sab196087 continue; 511*5411Sab196087 512*5411Sab196087 str = list->value.name; 513*5411Sab196087 if (atoui(str, sym, &list->value.type) == 0) { 514*5411Sab196087 const char *fmt = minus_p ? 515*5411Sab196087 MSG_INTL(MSG_ERR_BAD_T_PT) : 516*5411Sab196087 MSG_INTL(MSG_ERR_BAD_T_SHT); 517*5411Sab196087 518*5411Sab196087 (void) fprintf(stderr, fmt, basename(argv0), str); 519*5411Sab196087 return (0); 520*5411Sab196087 } 521*5411Sab196087 } 522*5411Sab196087 523*5411Sab196087 return (1); 524*5411Sab196087 } 525*5411Sab196087 526*5411Sab196087 527*5411Sab196087 /* 5284168Sab196087 * Returns True (1) if the item with the given name or index should 5294168Sab196087 * be displayed, and False (0) if it should not be. 5304168Sab196087 * 5314168Sab196087 * entry: 532*5411Sab196087 * match_flags - Bitmask specifying matching options, as described 533*5411Sab196087 * in _elfdump.h. 534*5411Sab196087 * name - If MATCH_F_NAME flag is set, name of item under 535*5411Sab196087 * consideration. Otherwise ignored. 5364168Sab196087 * should not be considered. 537*5411Sab196087 * ndx - If MATCH_F_NDX flag is set, index of item under consideration. 538*5411Sab196087 * type - If MATCH_F_TYPE is set, type of item under consideration. 539*5411Sab196087 * If MATCH_F_PHDR is set, this would be a program 540*5411Sab196087 * header type (PT_). Otherwise, a section header type (SHT_). 5414168Sab196087 * 5424168Sab196087 * exit: 5434168Sab196087 * True will be returned if the given name/index matches those given 544*5411Sab196087 * by one of the (-I, -N -T) command line options, or if no such option 545*5411Sab196087 * was used in the command invocation and MATCH_F_STRICT is not 546*5411Sab196087 * set. 5474168Sab196087 */ 5484168Sab196087 int 549*5411Sab196087 match(match_flags_t match_flags, const char *name, uint_t ndx, uint_t type) 5504168Sab196087 { 551*5411Sab196087 match_item_t item_type = (match_flags & MATCH_F_PHDR) ? 552*5411Sab196087 MATCH_ITEM_PT : MATCH_ITEM_SHT; 553*5411Sab196087 match_rec_t *list; 5544168Sab196087 555*5411Sab196087 /* 556*5411Sab196087 * If there is no match list, then we use the MATCH_F_STRICT 557*5411Sab196087 * flag to decide what to return. In the strict case, we return 558*5411Sab196087 * False (0), in the normal case, True (1). 559*5411Sab196087 */ 560*5411Sab196087 if (match_state.list == NULL) 561*5411Sab196087 return ((match_flags & MATCH_F_STRICT) == 0); 562*5411Sab196087 563*5411Sab196087 /* 564*5411Sab196087 * If item being checked is not the current match type, 565*5411Sab196087 * then allow it. 566*5411Sab196087 */ 567*5411Sab196087 if (item_type != match_state.item_type) 5684168Sab196087 return (1); 5694168Sab196087 5704168Sab196087 /* Run through the match records and check for a hit */ 571*5411Sab196087 for (list = match_state.list; list; list = list->next) { 572*5411Sab196087 switch (list->opt_type) { 573*5411Sab196087 case MATCH_OPT_NAME: 574*5411Sab196087 if (((match_flags & MATCH_F_NAME) == 0) || 575*5411Sab196087 (name == NULL)) 576*5411Sab196087 break; 577*5411Sab196087 if (strcmp(list->value.name, name) == 0) 5784168Sab196087 return (1); 5794168Sab196087 break; 580*5411Sab196087 case MATCH_OPT_NDX: 581*5411Sab196087 if ((match_flags & MATCH_F_NDX) && 582*5411Sab196087 (ndx == list->value.ndx.start)) 5834168Sab196087 return (1); 5844168Sab196087 break; 585*5411Sab196087 case MATCH_OPT_RANGE: 5864168Sab196087 /* 5874168Sab196087 * A range end value less than 0 means that any value 5884168Sab196087 * above the start is acceptible. 5894168Sab196087 */ 590*5411Sab196087 if ((match_flags & MATCH_F_NDX) && 591*5411Sab196087 (ndx >= list->value.ndx.start) && 5924168Sab196087 ((list->value.ndx.end < 0) || 5934168Sab196087 (ndx <= list->value.ndx.end))) 5944168Sab196087 return (1); 5954168Sab196087 break; 596*5411Sab196087 597*5411Sab196087 case MATCH_OPT_TYPE: 598*5411Sab196087 if ((match_flags & MATCH_F_TYPE) && 599*5411Sab196087 (type == list->value.type)) 600*5411Sab196087 return (1); 601*5411Sab196087 break; 6024168Sab196087 } 6034168Sab196087 } 6044168Sab196087 6054168Sab196087 /* Nothing matched */ 6064168Sab196087 return (0); 6074168Sab196087 } 6084168Sab196087 6094168Sab196087 /* 610*5411Sab196087 * Add an entry to match_state.list for use by match(). This routine is for 611*5411Sab196087 * use during getopt() processing. It should not be called once 612*5411Sab196087 * match_prepare() has been called. 6134168Sab196087 * 6144168Sab196087 * Return True (1) for success. On failure, an error is written 6154168Sab196087 * to stderr, and False (0) is returned. 6164168Sab196087 */ 6174168Sab196087 static int 618*5411Sab196087 add_match_record(char *argv0, match_rec_t *data) 6194168Sab196087 { 620*5411Sab196087 match_rec_t *rec; 621*5411Sab196087 match_rec_t *list; 6224168Sab196087 6234168Sab196087 if ((rec = malloc(sizeof (*rec))) == NULL) { 6244168Sab196087 int err = errno; 6254168Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 6264168Sab196087 basename(argv0), strerror(err)); 6274168Sab196087 return (0); 6284168Sab196087 } 6294168Sab196087 6304168Sab196087 *rec = *data; 6314168Sab196087 632*5411Sab196087 /* Insert at end of match_state.list */ 633*5411Sab196087 if (match_state.list == NULL) { 634*5411Sab196087 match_state.list = rec; 6354168Sab196087 } else { 636*5411Sab196087 for (list = match_state.list; list->next != NULL; 637*5411Sab196087 list = list->next) 6384168Sab196087 ; 6394168Sab196087 list->next = rec; 6404168Sab196087 } 6414168Sab196087 6424168Sab196087 rec->next = NULL; 6434168Sab196087 return (1); 6441618Srie } 6451618Srie 646*5411Sab196087 static int 647*5411Sab196087 decide(const char *file, int fd, Elf *elf, uint_t flags, 648*5411Sab196087 const char *wname, int wfd) 6491618Srie { 650*5411Sab196087 int r; 651*5411Sab196087 6521618Srie if (gelf_getclass(elf) == ELFCLASS64) 653*5411Sab196087 r = regular64(file, fd, elf, flags, wname, wfd); 6541618Srie else 655*5411Sab196087 r = regular32(file, fd, elf, flags, wname, wfd); 656*5411Sab196087 657*5411Sab196087 return (r); 6581618Srie } 6591618Srie 660*5411Sab196087 static int 661*5411Sab196087 archive(const char *file, int fd, Elf *elf, uint_t flags, 662*5411Sab196087 const char *wname, int wfd) 6631618Srie { 6641618Srie Elf_Cmd cmd = ELF_C_READ; 6651618Srie Elf_Arhdr *arhdr; 6661618Srie Elf *_elf = 0; 6671618Srie size_t ptr; 6681618Srie Elf_Arsym *arsym = 0; 6691618Srie 6701618Srie /* 6713492Sab196087 * Determine if the archive symbol table itself is required. 6721618Srie */ 673*5411Sab196087 if ((flags & FLG_SHOW_SYMBOLS) && 674*5411Sab196087 match(MATCH_F_NAME, MSG_ORIG(MSG_ELF_ARSYM), 0, 0)) { 6751618Srie /* 6761618Srie * Get the archive symbol table. 6771618Srie */ 6781618Srie if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) { 6791618Srie /* 6801618Srie * The arsym could be 0 even though there was no error. 6811618Srie * Print the error message only when there was 6821618Srie * real error from elf_getarsym(). 6831618Srie */ 6841618Srie failure(file, MSG_ORIG(MSG_ELF_GETARSYM)); 685*5411Sab196087 return (0); 6861618Srie } 6871618Srie } 6881618Srie 6891618Srie /* 6901618Srie * Print the archive symbol table only when the archive symbol 6911618Srie * table exists and it was requested to print. 6921618Srie */ 6931618Srie if (arsym) { 6941618Srie size_t cnt; 6951618Srie char index[MAXNDXSIZE]; 6961618Srie size_t offset = 0, _offset = 0; 6971618Srie 6981618Srie /* 6991618Srie * Print out all the symbol entries. 7001618Srie */ 7011618Srie dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB)); 7021618Srie dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS)); 7031618Srie 7041618Srie for (cnt = 0; cnt < ptr; cnt++, arsym++) { 7051618Srie /* 7061618Srie * For each object obtain an elf descriptor so that we 7071618Srie * can establish the members name. Note, we have had 7081618Srie * archives where the archive header has not been 7091618Srie * obtainable so be lenient with errors. 7101618Srie */ 7111618Srie if ((offset == 0) || ((arsym->as_off != 0) && 7121618Srie (arsym->as_off != _offset))) { 7131618Srie 7141618Srie if (_elf) 7151618Srie (void) elf_end(_elf); 7161618Srie 7171618Srie if (elf_rand(elf, arsym->as_off) != 7181618Srie arsym->as_off) { 7191618Srie failure(file, MSG_ORIG(MSG_ELF_RAND)); 7201618Srie arhdr = 0; 7211618Srie } else if ((_elf = elf_begin(fd, 7221618Srie ELF_C_READ, elf)) == 0) { 7231618Srie failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 7241618Srie arhdr = 0; 7251618Srie } else if ((arhdr = elf_getarhdr(_elf)) == 0) { 7261618Srie failure(file, 7271618Srie MSG_ORIG(MSG_ELF_GETARHDR)); 7281618Srie arhdr = 0; 7291618Srie } 7301618Srie 7311618Srie _offset = arsym->as_off; 7321618Srie if (offset == 0) 7331618Srie offset = _offset; 7341618Srie } 7351618Srie 7361618Srie (void) snprintf(index, MAXNDXSIZE, 7371618Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt)); 7381618Srie if (arsym->as_off) 7391618Srie dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM1), index, 7401618Srie /* LINTED */ 7411618Srie (int)arsym->as_off, arhdr ? arhdr->ar_name : 7421618Srie MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ? 7431618Srie demangle(arsym->as_name, flags) : 7441618Srie MSG_INTL(MSG_STR_NULL))); 7451618Srie else 7461618Srie dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM2), index, 7471618Srie /* LINTED */ 7481618Srie (int)arsym->as_off); 7491618Srie } 7501618Srie 7511618Srie if (_elf) 7521618Srie (void) elf_end(_elf); 7531618Srie 7541618Srie /* 7551618Srie * If we only need the archive symbol table return. 7561618Srie */ 757*5411Sab196087 if ((flags & FLG_SHOW_SYMBOLS) && 758*5411Sab196087 match(MATCH_F_STRICT | MATCH_F_NAME, 759*5411Sab196087 MSG_ORIG(MSG_ELF_ARSYM), -1, -1)) 760*5411Sab196087 return (0); 7611618Srie 7621618Srie /* 7631618Srie * Reset elf descriptor in preparation for processing each 7641618Srie * member. 7651618Srie */ 7661618Srie if (offset) 7671618Srie (void) elf_rand(elf, offset); 7681618Srie } 7691618Srie 7701618Srie /* 7711618Srie * Process each object within the archive. 7721618Srie */ 7731618Srie while ((_elf = elf_begin(fd, cmd, elf)) != NULL) { 7741618Srie char name[MAXPATHLEN]; 7751618Srie 7761618Srie if ((arhdr = elf_getarhdr(_elf)) == NULL) { 7771618Srie failure(file, MSG_ORIG(MSG_ELF_GETARHDR)); 778*5411Sab196087 return (0); 7791618Srie } 7801618Srie if (*arhdr->ar_name != '/') { 7811618Srie (void) snprintf(name, MAXPATHLEN, 7821618Srie MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name); 7831618Srie dbg_print(0, MSG_ORIG(MSG_FMT_NLSTR), name); 7841618Srie 7851618Srie switch (elf_kind(_elf)) { 7861618Srie case ELF_K_AR: 787*5411Sab196087 if (archive(name, fd, _elf, flags, 788*5411Sab196087 wname, wfd) == 1) 789*5411Sab196087 return (1); 7901618Srie break; 7911618Srie case ELF_K_ELF: 792*5411Sab196087 if (decide(name, fd, _elf, flags, 793*5411Sab196087 wname, wfd) == 1) 794*5411Sab196087 return (1); 7951618Srie break; 7961618Srie default: 7971618Srie (void) fprintf(stderr, 7981618Srie MSG_INTL(MSG_ERR_BADFILE), name); 7991618Srie break; 8001618Srie } 8011618Srie } 8021618Srie 8031618Srie cmd = elf_next(_elf); 8041618Srie (void) elf_end(_elf); 8051618Srie } 806*5411Sab196087 807*5411Sab196087 return (0); 8081618Srie } 8091618Srie 8101618Srie int 8111618Srie main(int argc, char **argv, char **envp) 8121618Srie { 8131618Srie Elf *elf; 8141618Srie int var, fd, wfd = 0; 815*5411Sab196087 char *wname = NULL; 8161618Srie uint_t flags = 0; 817*5411Sab196087 match_rec_t match_data; 818*5411Sab196087 int ret; 8191618Srie 8201618Srie /* 8211618Srie * If we're on a 64-bit kernel, try to exec a full 64-bit version of 8221618Srie * the binary. If successful, conv_check_native() won't return. 8231618Srie */ 8242647Srie (void) conv_check_native(argv, envp); 8251618Srie 8261618Srie /* 8271618Srie * Establish locale. 8281618Srie */ 8291618Srie (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 8301618Srie (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 8311618Srie 8321618Srie (void) setvbuf(stdout, NULL, _IOLBF, 0); 8331618Srie (void) setvbuf(stderr, NULL, _IOLBF, 0); 8341618Srie 8351618Srie opterr = 0; 8361618Srie while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) { 8371618Srie switch (var) { 8381618Srie case 'C': 839*5411Sab196087 flags |= FLG_CTL_DEMANGLE; 8401618Srie break; 8411618Srie case 'c': 842*5411Sab196087 flags |= FLG_SHOW_SHDR; 8431618Srie break; 8441618Srie case 'd': 845*5411Sab196087 flags |= FLG_SHOW_DYNAMIC; 8461618Srie break; 8471618Srie case 'e': 848*5411Sab196087 flags |= FLG_SHOW_EHDR; 8491618Srie break; 8501618Srie case 'G': 851*5411Sab196087 flags |= FLG_SHOW_GOT; 8521618Srie break; 8531618Srie case 'g': 854*5411Sab196087 flags |= FLG_SHOW_GROUP; 8551618Srie break; 8561618Srie case 'H': 857*5411Sab196087 flags |= FLG_SHOW_CAP; 8581618Srie break; 8591618Srie case 'h': 860*5411Sab196087 flags |= FLG_SHOW_HASH; 8611618Srie break; 8624168Sab196087 case 'I': 863*5411Sab196087 if (!process_index_opt(optarg, &match_data)) 864*5411Sab196087 goto usage_brief; 8654168Sab196087 if (!add_match_record(argv[0], &match_data)) 8664168Sab196087 return (1); 867*5411Sab196087 flags |= FLG_CTL_MATCH; 8684168Sab196087 break; 8691618Srie case 'i': 870*5411Sab196087 flags |= FLG_SHOW_INTERP; 8711618Srie break; 8721618Srie case 'k': 873*5411Sab196087 flags |= FLG_CALC_CHECKSUM; 8741618Srie break; 8751618Srie case 'l': 876*5411Sab196087 flags |= FLG_CTL_LONGNAME; 8771618Srie break; 8781618Srie case 'm': 879*5411Sab196087 flags |= FLG_SHOW_MOVE; 8801618Srie break; 8811618Srie case 'N': 882*5411Sab196087 match_data.opt_type = MATCH_OPT_NAME; 8834168Sab196087 match_data.value.name = optarg; 8844168Sab196087 if (!add_match_record(argv[0], &match_data)) 8854168Sab196087 return (1); 886*5411Sab196087 flags |= FLG_CTL_MATCH; 8871618Srie break; 8881618Srie case 'n': 889*5411Sab196087 flags |= FLG_SHOW_NOTE; 8901618Srie break; 8914665Sab196087 case 'P': 892*5411Sab196087 flags |= FLG_CTL_FAKESHDR; 8934665Sab196087 break; 8941618Srie case 'p': 895*5411Sab196087 flags |= FLG_SHOW_PHDR; 8961618Srie break; 8971618Srie case 'r': 898*5411Sab196087 flags |= FLG_SHOW_RELOC; 8991618Srie break; 9003492Sab196087 case 'S': 901*5411Sab196087 flags |= FLG_SHOW_SORT; 9023492Sab196087 break; 9031618Srie case 's': 904*5411Sab196087 flags |= FLG_SHOW_SYMBOLS; 905*5411Sab196087 break; 906*5411Sab196087 case 'T': 907*5411Sab196087 /* 908*5411Sab196087 * We can't evaluate the value yet, because 909*5411Sab196087 * we need to know if -p is used or not in 910*5411Sab196087 * order to tell if we're seeing section header 911*5411Sab196087 * or program header types. So, we save the 912*5411Sab196087 * string in the name field, and then convert 913*5411Sab196087 * it to a type integer in a following pass. 914*5411Sab196087 */ 915*5411Sab196087 match_data.opt_type = MATCH_OPT_TYPE; 916*5411Sab196087 match_data.value.name = optarg; 917*5411Sab196087 if (!add_match_record(argv[0], &match_data)) 918*5411Sab196087 return (1); 919*5411Sab196087 flags |= FLG_CTL_MATCH; 9201618Srie break; 9211618Srie case 'u': 922*5411Sab196087 flags |= FLG_SHOW_UNWIND; 9231618Srie break; 9241618Srie case 'v': 925*5411Sab196087 flags |= FLG_SHOW_VERSIONS; 9261618Srie break; 9271618Srie case 'w': 9281618Srie wname = optarg; 9291618Srie break; 9301618Srie case 'y': 931*5411Sab196087 flags |= FLG_SHOW_SYMINFO; 9321618Srie break; 9331618Srie case '?': 9341618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 9351618Srie basename(argv[0])); 9361618Srie detail_usage(); 9371618Srie return (1); 9381618Srie default: 9391618Srie break; 9401618Srie } 9411618Srie } 9421618Srie 943*5411Sab196087 /* -p and -w are mutually exclusive. -w only works with sections */ 944*5411Sab196087 if (((flags & FLG_SHOW_PHDR) != 0) && (wname != NULL)) 945*5411Sab196087 goto usage_brief; 946*5411Sab196087 947*5411Sab196087 /* If a match argument is present, prepare the match state */ 948*5411Sab196087 if ((match_state.list != NULL) && (match_prepare(argv[0], flags) == 0)) 949*5411Sab196087 return (1); 950*5411Sab196087 9511618Srie /* 952*5411Sab196087 * Decide what to do if no options specifying something to 953*5411Sab196087 * show or do are present. 954*5411Sab196087 * 955*5411Sab196087 * If there is no -w and no match options, then we will set all 956*5411Sab196087 * the show flags, causing a full display of everything in the 957*5411Sab196087 * file that we know how to handle. 958*5411Sab196087 * 959*5411Sab196087 * Otherwise, if there is no match list, we generate a usage 960*5411Sab196087 * error and quit. 961*5411Sab196087 * 962*5411Sab196087 * In the case where there is a match list, we go ahead and call 963*5411Sab196087 * regular() anyway, leaving it to decide what to do. If -w is 964*5411Sab196087 * present, regular() will use the match list to handle it. 965*5411Sab196087 * In addition, in the absence of explicit show/calc flags, regular() 966*5411Sab196087 * will compare the section headers to the match list and use 967*5411Sab196087 * that to generate the FLG_ bits that will display the information 968*5411Sab196087 * specified by the match list. 9691618Srie */ 970*5411Sab196087 if ((flags & ~FLG_MASK_CTL) == 0) { 971*5411Sab196087 if (!wname && (match_state.list == NULL)) 972*5411Sab196087 flags |= FLG_MASK_SHOW; 973*5411Sab196087 else if (match_state.list == NULL) 974*5411Sab196087 goto usage_brief; 9751618Srie } 9761618Srie 977*5411Sab196087 /* There needs to be at least 1 filename left following the options */ 978*5411Sab196087 if ((var = argc - optind) == 0) 979*5411Sab196087 goto usage_brief; 9801618Srie 9811618Srie /* 9821618Srie * If the -l/-C option is specified, set up the liblddbg.so. 9831618Srie */ 984*5411Sab196087 if (flags & FLG_CTL_LONGNAME) 9851618Srie dbg_desc->d_extra |= DBG_E_LONG; 986*5411Sab196087 if (flags & FLG_CTL_DEMANGLE) 9871618Srie dbg_desc->d_extra |= DBG_E_DEMANGLE; 9881618Srie 9891618Srie /* 9901618Srie * If the -w option has indicated an output file open it. It's 9911618Srie * arguable whether this option has much use when multiple files are 9921618Srie * being processed. 993*5411Sab196087 * 994*5411Sab196087 * If wname is non-NULL, we know that -p was not specified, due 995*5411Sab196087 * to the test above. 9961618Srie */ 9971618Srie if (wname) { 9981618Srie if ((wfd = open(wname, (O_RDWR | O_CREAT | O_TRUNC), 9991618Srie 0666)) < 0) { 10001618Srie int err = errno; 10011618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 10021618Srie wname, strerror(err)); 1003*5411Sab196087 return (1); 10041618Srie } 10051618Srie } 10061618Srie 10071618Srie /* 1008*5411Sab196087 * Open the input file, initialize the elf interface, and 1009*5411Sab196087 * process it. 10101618Srie */ 1011*5411Sab196087 ret = 0; 1012*5411Sab196087 for (; (optind < argc) && (ret == 0); optind++) { 10131618Srie const char *file = argv[optind]; 10141618Srie 10151618Srie if ((fd = open(argv[optind], O_RDONLY)) == -1) { 10161618Srie int err = errno; 10171618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 10181618Srie file, strerror(err)); 10191618Srie continue; 10201618Srie } 10211618Srie (void) elf_version(EV_CURRENT); 10221618Srie if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 10231618Srie failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 10241618Srie (void) close(fd); 10251618Srie continue; 10261618Srie } 10271618Srie 10281618Srie if (var > 1) 10291618Srie dbg_print(0, MSG_ORIG(MSG_FMT_NLSTRNL), file); 10301618Srie 10311618Srie switch (elf_kind(elf)) { 10321618Srie case ELF_K_AR: 1033*5411Sab196087 ret = archive(file, fd, elf, flags, wname, wfd); 10341618Srie break; 10351618Srie case ELF_K_ELF: 1036*5411Sab196087 ret = decide(file, fd, elf, flags, wname, wfd); 10371618Srie break; 10381618Srie default: 10391618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADFILE), file); 10401618Srie break; 10411618Srie } 10421618Srie 10431618Srie (void) close(fd); 10441618Srie (void) elf_end(elf); 10451618Srie } 10461618Srie 10471618Srie if (wfd) 10481618Srie (void) close(wfd); 1049*5411Sab196087 return (ret); 1050*5411Sab196087 1051*5411Sab196087 usage_brief: 1052*5411Sab196087 /* Control comes here for a simple usage message and exit */ 1053*5411Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 1054*5411Sab196087 basename(argv[0])); 1055*5411Sab196087 return (1); 1056*5411Sab196087 10571618Srie } 1058