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 /* 23d579eb63Sab * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 245aefb655Srie * Use is subject to license terms. 255aefb655Srie */ 265aefb655Srie #pragma ident "%Z%%M% %I% %E% SMI" 275aefb655Srie 285aefb655Srie /* 295aefb655Srie * Dump an elf file. 305aefb655Srie */ 315aefb655Srie #include <sys/param.h> 325aefb655Srie #include <fcntl.h> 335aefb655Srie #include <stdio.h> 34*c809c407Sab #include <stdlib.h> 35*c809c407Sab #include <ctype.h> 365aefb655Srie #include <libelf.h> 375aefb655Srie #include <link.h> 385aefb655Srie #include <stdarg.h> 395aefb655Srie #include <unistd.h> 405aefb655Srie #include <libgen.h> 415aefb655Srie #include <libintl.h> 425aefb655Srie #include <locale.h> 435aefb655Srie #include <errno.h> 445aefb655Srie #include <strings.h> 455aefb655Srie #include <debug.h> 465aefb655Srie #include <conv.h> 475aefb655Srie #include <msg.h> 485aefb655Srie #include <_elfdump.h> 495aefb655Srie 5031fdd7caSab const Cache cache_init = {NULL, NULL, NULL, NULL, 0}; 515aefb655Srie 52*c809c407Sab 53*c809c407Sab 54*c809c407Sab /* MATCH is used to retain information about -N and -I options */ 55*c809c407Sab typedef enum { 56*c809c407Sab MATCH_T_NAME, /* Record contains a name */ 57*c809c407Sab MATCH_T_NDX, /* Record contains a single index */ 58*c809c407Sab MATCH_T_RANGE /* Record contains an index range */ 59*c809c407Sab } MATCH_T; 60*c809c407Sab 61*c809c407Sab typedef struct _match { 62*c809c407Sab struct _match *next; /* Pointer to next item in list */ 63*c809c407Sab MATCH_T type; 64*c809c407Sab union { 65*c809c407Sab const char *name; /* MATCH_T_NAME */ 66*c809c407Sab struct { /* MATCH_T_NDX and MATCH_T_RANGE */ 67*c809c407Sab int start; 68*c809c407Sab int end; /* Only for MATCH_T_RANGE */ 69*c809c407Sab } ndx; 70*c809c407Sab } value; 71*c809c407Sab } MATCH; 72*c809c407Sab 73*c809c407Sab /* List of MATCH records used by match() to implement -N and -I options */ 74*c809c407Sab static MATCH *match_list = NULL; 75*c809c407Sab 765aefb655Srie const char * 775aefb655Srie _elfdump_msg(Msg mid) 785aefb655Srie { 795aefb655Srie return (gettext(MSG_ORIG(mid))); 805aefb655Srie } 815aefb655Srie 825aefb655Srie /* 835aefb655Srie * Determine whether a symbol name should be demangled. 845aefb655Srie */ 855aefb655Srie const char * 865aefb655Srie demangle(const char *name, uint_t flags) 875aefb655Srie { 885aefb655Srie if (flags & FLG_DEMANGLE) 895aefb655Srie return (Elf_demangle_name(name)); 905aefb655Srie else 915aefb655Srie return ((char *)name); 925aefb655Srie } 935aefb655Srie 945aefb655Srie /* 955aefb655Srie * Define our own standard error routine. 965aefb655Srie */ 975aefb655Srie void 985aefb655Srie failure(const char *file, const char *func) 995aefb655Srie { 1005aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_FAILURE), 1015aefb655Srie file, func, elf_errmsg(elf_errno())); 1025aefb655Srie } 1035aefb655Srie 1045aefb655Srie /* 1055aefb655Srie * The full usage message 1065aefb655Srie */ 1075aefb655Srie static void 1085aefb655Srie detail_usage() 1095aefb655Srie { 1105aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL1)); 1115aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL2)); 1125aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL3)); 1135aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL4)); 1145aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL5)); 1155aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL6)); 1165aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL7)); 1175aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL8)); 1185aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9)); 1195aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL10)); 1205aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL11)); 1215aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL12)); 1225aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL13)); 1235aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL14)); 1245aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL15)); 1255aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL16)); 1265aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL17)); 1275aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL18)); 1285aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL19)); 1295aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL20)); 130d579eb63Sab (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL21)); 131*c809c407Sab (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL22)); 132*c809c407Sab (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL23)); 133*c809c407Sab } 134*c809c407Sab 135*c809c407Sab /* 136*c809c407Sab * Convert the ASCII representation of an index, or index range, into 137*c809c407Sab * binary form, and store it in rec: 138*c809c407Sab * 139*c809c407Sab * index: An positive or 0 valued integer 140*c809c407Sab * range: Two indexes, separated by a ':' character, denoting 141*c809c407Sab * a range of allowed values. If the second value is omitted, 142*c809c407Sab * any values equal to or greater than the first will match. 143*c809c407Sab * 144*c809c407Sab * exit: 145*c809c407Sab * On success, *rec is filled in with a MATCH_T_NDX or MATCH_T_RANGE 146*c809c407Sab * value, and this function returns (1). On failure, the contents 147*c809c407Sab * of *rec are undefined, and (0) is returned. 148*c809c407Sab */ 149*c809c407Sab int 150*c809c407Sab process_index_opt(const char *str, MATCH *rec) 151*c809c407Sab { 152*c809c407Sab #define SKIP_BLANK for (; *str && isspace(*str); str++) 153*c809c407Sab 154*c809c407Sab char *endptr; 155*c809c407Sab 156*c809c407Sab rec->value.ndx.start = strtol(str, &endptr, 10); 157*c809c407Sab /* Value must use some of the input, and be 0 or positive */ 158*c809c407Sab if ((str == endptr) || (rec->value.ndx.start < 0)) 159*c809c407Sab return (0); 160*c809c407Sab str = endptr; 161*c809c407Sab 162*c809c407Sab SKIP_BLANK; 163*c809c407Sab if (*str != ':') { 164*c809c407Sab rec->type = MATCH_T_NDX; 165*c809c407Sab } else { 166*c809c407Sab str++; /* Skip the ':' */ 167*c809c407Sab rec->type = MATCH_T_RANGE; 168*c809c407Sab SKIP_BLANK; 169*c809c407Sab if (*str == '\0') { 170*c809c407Sab rec->value.ndx.end = -1; /* Indicates "to end" */ 171*c809c407Sab } else { 172*c809c407Sab rec->value.ndx.end = strtol(str, &endptr, 10); 173*c809c407Sab if ((str == endptr) || (rec->value.ndx.end < 0)) 174*c809c407Sab return (0); 175*c809c407Sab str = endptr; 176*c809c407Sab SKIP_BLANK; 177*c809c407Sab } 178*c809c407Sab } 179*c809c407Sab 180*c809c407Sab /* Syntax error if anything is left over */ 181*c809c407Sab if (*str != '\0') 182*c809c407Sab return (0); 183*c809c407Sab 184*c809c407Sab return (1); 185*c809c407Sab 186*c809c407Sab #undef SKIP_BLANK 187*c809c407Sab } 188*c809c407Sab 189*c809c407Sab /* 190*c809c407Sab * Returns True (1) if the item with the given name or index should 191*c809c407Sab * be displayed, and False (0) if it should not be. 192*c809c407Sab * 193*c809c407Sab * entry: 194*c809c407Sab * strict - A strict match requires an explicit match to 195*c809c407Sab * a user specified -I or -N option. A non-strict match 196*c809c407Sab * succeeds if the match list is empty. 197*c809c407Sab * name - Name of item under consideration, or NULL if the name 198*c809c407Sab * should not be considered. 199*c809c407Sab * ndx - if (ndx >= 0) index of item under consideration. 200*c809c407Sab * A negative value indicates that the item has no index. 201*c809c407Sab * 202*c809c407Sab * exit: 203*c809c407Sab * True will be returned if the given name/index matches those given 204*c809c407Sab * by one of the -N or -I command line options, or if no such option 205*c809c407Sab * was used in the command invocation. 206*c809c407Sab */ 207*c809c407Sab int 208*c809c407Sab match(int strict, const char *name, int ndx) 209*c809c407Sab { 210*c809c407Sab MATCH *list; 211*c809c407Sab 212*c809c407Sab /* If no match options were specified, allow everything */ 213*c809c407Sab if (!strict && (match_list == NULL)) 214*c809c407Sab return (1); 215*c809c407Sab 216*c809c407Sab /* Run through the match records and check for a hit */ 217*c809c407Sab for (list = match_list; list; list = list->next) { 218*c809c407Sab switch (list->type) { 219*c809c407Sab case MATCH_T_NAME: 220*c809c407Sab if ((name != NULL) && 221*c809c407Sab (strcmp(list->value.name, name) == 0)) 222*c809c407Sab return (1); 223*c809c407Sab break; 224*c809c407Sab case MATCH_T_NDX: 225*c809c407Sab if (ndx == list->value.ndx.start) 226*c809c407Sab return (1); 227*c809c407Sab break; 228*c809c407Sab case MATCH_T_RANGE: 229*c809c407Sab /* 230*c809c407Sab * A range end value less than 0 means that any value 231*c809c407Sab * above the start is acceptible. 232*c809c407Sab */ 233*c809c407Sab if ((ndx >= list->value.ndx.start) && 234*c809c407Sab ((list->value.ndx.end < 0) || 235*c809c407Sab (ndx <= list->value.ndx.end))) 236*c809c407Sab return (1); 237*c809c407Sab break; 238*c809c407Sab } 239*c809c407Sab } 240*c809c407Sab 241*c809c407Sab /* Nothing matched */ 242*c809c407Sab return (0); 243*c809c407Sab } 244*c809c407Sab 245*c809c407Sab /* 246*c809c407Sab * Add an entry to match_list for use by match(). 247*c809c407Sab * 248*c809c407Sab * Return True (1) for success. On failure, an error is written 249*c809c407Sab * to stderr, and False (0) is returned. 250*c809c407Sab */ 251*c809c407Sab static int 252*c809c407Sab add_match_record(char *argv0, MATCH *data) 253*c809c407Sab { 254*c809c407Sab MATCH *rec; 255*c809c407Sab MATCH *list; 256*c809c407Sab 257*c809c407Sab if ((rec = malloc(sizeof (*rec))) == NULL) { 258*c809c407Sab int err = errno; 259*c809c407Sab (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 260*c809c407Sab basename(argv0), strerror(err)); 261*c809c407Sab return (0); 262*c809c407Sab } 263*c809c407Sab 264*c809c407Sab *rec = *data; 265*c809c407Sab 266*c809c407Sab /* Insert at end of match_list */ 267*c809c407Sab if (match_list == NULL) { 268*c809c407Sab match_list = rec; 269*c809c407Sab } else { 270*c809c407Sab for (list = match_list; list->next != NULL; list = list->next) 271*c809c407Sab ; 272*c809c407Sab list->next = rec; 273*c809c407Sab } 274*c809c407Sab 275*c809c407Sab rec->next = NULL; 276*c809c407Sab return (1); 2775aefb655Srie } 2785aefb655Srie 2795aefb655Srie static void 280*c809c407Sab decide(const char *file, Elf *elf, uint_t flags, int wfd) 2815aefb655Srie { 2825aefb655Srie if (gelf_getclass(elf) == ELFCLASS64) 283*c809c407Sab regular64(file, elf, flags, wfd); 2845aefb655Srie else 285*c809c407Sab regular32(file, elf, flags, wfd); 2865aefb655Srie } 2875aefb655Srie 2885aefb655Srie static void 289*c809c407Sab archive(const char *file, int fd, Elf *elf, uint_t flags, int wfd) 2905aefb655Srie { 2915aefb655Srie Elf_Cmd cmd = ELF_C_READ; 2925aefb655Srie Elf_Arhdr *arhdr; 2935aefb655Srie Elf *_elf = 0; 2945aefb655Srie size_t ptr; 2955aefb655Srie Elf_Arsym *arsym = 0; 2965aefb655Srie 2975aefb655Srie /* 298d579eb63Sab * Determine if the archive symbol table itself is required. 2995aefb655Srie */ 300*c809c407Sab if ((flags & FLG_SYMBOLS) && match(0, MSG_ORIG(MSG_ELF_ARSYM), -1)) { 3015aefb655Srie /* 3025aefb655Srie * Get the archive symbol table. 3035aefb655Srie */ 3045aefb655Srie if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) { 3055aefb655Srie /* 3065aefb655Srie * The arsym could be 0 even though there was no error. 3075aefb655Srie * Print the error message only when there was 3085aefb655Srie * real error from elf_getarsym(). 3095aefb655Srie */ 3105aefb655Srie failure(file, MSG_ORIG(MSG_ELF_GETARSYM)); 3115aefb655Srie return; 3125aefb655Srie } 3135aefb655Srie } 3145aefb655Srie 3155aefb655Srie /* 3165aefb655Srie * Print the archive symbol table only when the archive symbol 3175aefb655Srie * table exists and it was requested to print. 3185aefb655Srie */ 3195aefb655Srie if (arsym) { 3205aefb655Srie size_t cnt; 3215aefb655Srie char index[MAXNDXSIZE]; 3225aefb655Srie size_t offset = 0, _offset = 0; 3235aefb655Srie 3245aefb655Srie /* 3255aefb655Srie * Print out all the symbol entries. 3265aefb655Srie */ 3275aefb655Srie dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB)); 3285aefb655Srie dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS)); 3295aefb655Srie 3305aefb655Srie for (cnt = 0; cnt < ptr; cnt++, arsym++) { 3315aefb655Srie /* 3325aefb655Srie * For each object obtain an elf descriptor so that we 3335aefb655Srie * can establish the members name. Note, we have had 3345aefb655Srie * archives where the archive header has not been 3355aefb655Srie * obtainable so be lenient with errors. 3365aefb655Srie */ 3375aefb655Srie if ((offset == 0) || ((arsym->as_off != 0) && 3385aefb655Srie (arsym->as_off != _offset))) { 3395aefb655Srie 3405aefb655Srie if (_elf) 3415aefb655Srie (void) elf_end(_elf); 3425aefb655Srie 3435aefb655Srie if (elf_rand(elf, arsym->as_off) != 3445aefb655Srie arsym->as_off) { 3455aefb655Srie failure(file, MSG_ORIG(MSG_ELF_RAND)); 3465aefb655Srie arhdr = 0; 3475aefb655Srie } else if ((_elf = elf_begin(fd, 3485aefb655Srie ELF_C_READ, elf)) == 0) { 3495aefb655Srie failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 3505aefb655Srie arhdr = 0; 3515aefb655Srie } else if ((arhdr = elf_getarhdr(_elf)) == 0) { 3525aefb655Srie failure(file, 3535aefb655Srie MSG_ORIG(MSG_ELF_GETARHDR)); 3545aefb655Srie arhdr = 0; 3555aefb655Srie } 3565aefb655Srie 3575aefb655Srie _offset = arsym->as_off; 3585aefb655Srie if (offset == 0) 3595aefb655Srie offset = _offset; 3605aefb655Srie } 3615aefb655Srie 3625aefb655Srie (void) snprintf(index, MAXNDXSIZE, 3635aefb655Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt)); 3645aefb655Srie if (arsym->as_off) 3655aefb655Srie dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM1), index, 3665aefb655Srie /* LINTED */ 3675aefb655Srie (int)arsym->as_off, arhdr ? arhdr->ar_name : 3685aefb655Srie MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ? 3695aefb655Srie demangle(arsym->as_name, flags) : 3705aefb655Srie MSG_INTL(MSG_STR_NULL))); 3715aefb655Srie else 3725aefb655Srie dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM2), index, 3735aefb655Srie /* LINTED */ 3745aefb655Srie (int)arsym->as_off); 3755aefb655Srie } 3765aefb655Srie 3775aefb655Srie if (_elf) 3785aefb655Srie (void) elf_end(_elf); 3795aefb655Srie 3805aefb655Srie /* 3815aefb655Srie * If we only need the archive symbol table return. 3825aefb655Srie */ 383*c809c407Sab if ((flags & FLG_SYMBOLS) && 384*c809c407Sab match(1, MSG_ORIG(MSG_ELF_ARSYM), -1)) 3855aefb655Srie return; 3865aefb655Srie 3875aefb655Srie /* 3885aefb655Srie * Reset elf descriptor in preparation for processing each 3895aefb655Srie * member. 3905aefb655Srie */ 3915aefb655Srie if (offset) 3925aefb655Srie (void) elf_rand(elf, offset); 3935aefb655Srie } 3945aefb655Srie 3955aefb655Srie /* 3965aefb655Srie * Process each object within the archive. 3975aefb655Srie */ 3985aefb655Srie while ((_elf = elf_begin(fd, cmd, elf)) != NULL) { 3995aefb655Srie char name[MAXPATHLEN]; 4005aefb655Srie 4015aefb655Srie if ((arhdr = elf_getarhdr(_elf)) == NULL) { 4025aefb655Srie failure(file, MSG_ORIG(MSG_ELF_GETARHDR)); 4035aefb655Srie return; 4045aefb655Srie } 4055aefb655Srie if (*arhdr->ar_name != '/') { 4065aefb655Srie (void) snprintf(name, MAXPATHLEN, 4075aefb655Srie MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name); 4085aefb655Srie dbg_print(0, MSG_ORIG(MSG_FMT_NLSTR), name); 4095aefb655Srie 4105aefb655Srie switch (elf_kind(_elf)) { 4115aefb655Srie case ELF_K_AR: 412*c809c407Sab archive(name, fd, _elf, flags, wfd); 4135aefb655Srie break; 4145aefb655Srie case ELF_K_ELF: 415*c809c407Sab decide(name, _elf, flags, wfd); 4165aefb655Srie break; 4175aefb655Srie default: 4185aefb655Srie (void) fprintf(stderr, 4195aefb655Srie MSG_INTL(MSG_ERR_BADFILE), name); 4205aefb655Srie break; 4215aefb655Srie } 4225aefb655Srie } 4235aefb655Srie 4245aefb655Srie cmd = elf_next(_elf); 4255aefb655Srie (void) elf_end(_elf); 4265aefb655Srie } 4275aefb655Srie } 4285aefb655Srie 4295aefb655Srie int 4305aefb655Srie main(int argc, char **argv, char **envp) 4315aefb655Srie { 4325aefb655Srie Elf *elf; 4335aefb655Srie int var, fd, wfd = 0; 434*c809c407Sab char *wname = 0; 4355aefb655Srie uint_t flags = 0; 436*c809c407Sab MATCH match_data; 4375aefb655Srie 4385aefb655Srie /* 4395aefb655Srie * If we're on a 64-bit kernel, try to exec a full 64-bit version of 4405aefb655Srie * the binary. If successful, conv_check_native() won't return. 4415aefb655Srie */ 4427010c12aSrie (void) conv_check_native(argv, envp); 4435aefb655Srie 4445aefb655Srie /* 4455aefb655Srie * Establish locale. 4465aefb655Srie */ 4475aefb655Srie (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 4485aefb655Srie (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 4495aefb655Srie 4505aefb655Srie (void) setvbuf(stdout, NULL, _IOLBF, 0); 4515aefb655Srie (void) setvbuf(stderr, NULL, _IOLBF, 0); 4525aefb655Srie 4535aefb655Srie opterr = 0; 4545aefb655Srie while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) { 4555aefb655Srie switch (var) { 4565aefb655Srie case 'C': 4575aefb655Srie flags |= FLG_DEMANGLE; 4585aefb655Srie break; 4595aefb655Srie case 'c': 4605aefb655Srie flags |= FLG_SHDR; 4615aefb655Srie break; 4625aefb655Srie case 'd': 4635aefb655Srie flags |= FLG_DYNAMIC; 4645aefb655Srie break; 4655aefb655Srie case 'e': 4665aefb655Srie flags |= FLG_EHDR; 4675aefb655Srie break; 4685aefb655Srie case 'G': 4695aefb655Srie flags |= FLG_GOT; 4705aefb655Srie break; 4715aefb655Srie case 'g': 4725aefb655Srie flags |= FLG_GROUP; 4735aefb655Srie break; 4745aefb655Srie case 'H': 4755aefb655Srie flags |= FLG_CAP; 4765aefb655Srie break; 4775aefb655Srie case 'h': 4785aefb655Srie flags |= FLG_HASH; 4795aefb655Srie break; 480*c809c407Sab case 'I': 481*c809c407Sab if (!process_index_opt(optarg, &match_data)) { 482*c809c407Sab (void) fprintf(stderr, 483*c809c407Sab MSG_INTL(MSG_USAGE_BRIEF), 484*c809c407Sab basename(argv[0])); 485*c809c407Sab return (1); 486*c809c407Sab } 487*c809c407Sab if (!add_match_record(argv[0], &match_data)) 488*c809c407Sab return (1); 489*c809c407Sab break; 4905aefb655Srie case 'i': 4915aefb655Srie flags |= FLG_INTERP; 4925aefb655Srie break; 4935aefb655Srie case 'k': 4945aefb655Srie flags |= FLG_CHECKSUM; 4955aefb655Srie break; 4965aefb655Srie case 'l': 4975aefb655Srie flags |= FLG_LONGNAME; 4985aefb655Srie break; 4995aefb655Srie case 'm': 5005aefb655Srie flags |= FLG_MOVE; 5015aefb655Srie break; 5025aefb655Srie case 'N': 503*c809c407Sab match_data.type = MATCH_T_NAME; 504*c809c407Sab match_data.value.name = optarg; 505*c809c407Sab if (!add_match_record(argv[0], &match_data)) 506*c809c407Sab return (1); 5075aefb655Srie break; 5085aefb655Srie case 'n': 5095aefb655Srie flags |= FLG_NOTE; 5105aefb655Srie break; 5115aefb655Srie case 'p': 5125aefb655Srie flags |= FLG_PHDR; 5135aefb655Srie break; 5145aefb655Srie case 'r': 5155aefb655Srie flags |= FLG_RELOC; 5165aefb655Srie break; 517d579eb63Sab case 'S': 518d579eb63Sab flags |= FLG_SORT; 519d579eb63Sab break; 5205aefb655Srie case 's': 5215aefb655Srie flags |= FLG_SYMBOLS; 5225aefb655Srie break; 5235aefb655Srie case 'u': 5245aefb655Srie flags |= FLG_UNWIND; 5255aefb655Srie break; 5265aefb655Srie case 'v': 5275aefb655Srie flags |= FLG_VERSIONS; 5285aefb655Srie break; 5295aefb655Srie case 'w': 5305aefb655Srie wname = optarg; 5315aefb655Srie break; 5325aefb655Srie case 'y': 5335aefb655Srie flags |= FLG_SYMINFO; 5345aefb655Srie break; 5355aefb655Srie case '?': 5365aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 5375aefb655Srie basename(argv[0])); 5385aefb655Srie detail_usage(); 5395aefb655Srie return (1); 5405aefb655Srie default: 5415aefb655Srie break; 5425aefb655Srie } 5435aefb655Srie } 5445aefb655Srie 5455aefb655Srie /* 5465aefb655Srie * Validate any arguments. 5475aefb655Srie */ 5485aefb655Srie if ((flags & ~(FLG_DEMANGLE | FLG_LONGNAME)) == 0) { 549*c809c407Sab if (!wname && (match_list == NULL)) { 5505aefb655Srie flags |= FLG_EVERYTHING; 551*c809c407Sab } else if (!wname || (match_list == NULL)) { 5525aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 5535aefb655Srie basename(argv[0])); 5545aefb655Srie return (1); 5555aefb655Srie } 5565aefb655Srie } 5575aefb655Srie 5585aefb655Srie if ((var = argc - optind) == 0) { 5595aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 5605aefb655Srie basename(argv[0])); 5615aefb655Srie return (1); 5625aefb655Srie } 5635aefb655Srie 5645aefb655Srie /* 5655aefb655Srie * If the -l/-C option is specified, set up the liblddbg.so. 5665aefb655Srie */ 5675aefb655Srie if (flags & FLG_LONGNAME) 5685aefb655Srie dbg_desc->d_extra |= DBG_E_LONG; 5695aefb655Srie if (flags & FLG_DEMANGLE) 5705aefb655Srie dbg_desc->d_extra |= DBG_E_DEMANGLE; 5715aefb655Srie 5725aefb655Srie /* 5735aefb655Srie * If the -w option has indicated an output file open it. It's 5745aefb655Srie * arguable whether this option has much use when multiple files are 5755aefb655Srie * being processed. 5765aefb655Srie */ 5775aefb655Srie if (wname) { 5785aefb655Srie if ((wfd = open(wname, (O_RDWR | O_CREAT | O_TRUNC), 5795aefb655Srie 0666)) < 0) { 5805aefb655Srie int err = errno; 5815aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 5825aefb655Srie wname, strerror(err)); 5835aefb655Srie wfd = 0; 5845aefb655Srie } 5855aefb655Srie } 5865aefb655Srie 5875aefb655Srie /* 5885aefb655Srie * Open the input file and initialize the elf interface. 5895aefb655Srie */ 5905aefb655Srie for (; optind < argc; optind++) { 5915aefb655Srie const char *file = argv[optind]; 5925aefb655Srie 5935aefb655Srie if ((fd = open(argv[optind], O_RDONLY)) == -1) { 5945aefb655Srie int err = errno; 5955aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 5965aefb655Srie file, strerror(err)); 5975aefb655Srie continue; 5985aefb655Srie } 5995aefb655Srie (void) elf_version(EV_CURRENT); 6005aefb655Srie if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 6015aefb655Srie failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 6025aefb655Srie (void) close(fd); 6035aefb655Srie continue; 6045aefb655Srie } 6055aefb655Srie 6065aefb655Srie if (var > 1) 6075aefb655Srie dbg_print(0, MSG_ORIG(MSG_FMT_NLSTRNL), file); 6085aefb655Srie 6095aefb655Srie switch (elf_kind(elf)) { 6105aefb655Srie case ELF_K_AR: 611*c809c407Sab archive(file, fd, elf, flags, wfd); 6125aefb655Srie break; 6135aefb655Srie case ELF_K_ELF: 614*c809c407Sab decide(file, elf, flags, wfd); 6155aefb655Srie break; 6165aefb655Srie default: 6175aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADFILE), file); 6185aefb655Srie break; 6195aefb655Srie } 6205aefb655Srie 6215aefb655Srie (void) close(fd); 6225aefb655Srie (void) elf_end(elf); 6235aefb655Srie } 6245aefb655Srie 6255aefb655Srie if (wfd) 6265aefb655Srie (void) close(wfd); 6275aefb655Srie return (0); 6285aefb655Srie } 629