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> 34c809c407Sab #include <stdlib.h> 35c809c407Sab #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 52c809c407Sab 53c809c407Sab 54c809c407Sab /* MATCH is used to retain information about -N and -I options */ 55c809c407Sab typedef enum { 56c809c407Sab MATCH_T_NAME, /* Record contains a name */ 57c809c407Sab MATCH_T_NDX, /* Record contains a single index */ 58c809c407Sab MATCH_T_RANGE /* Record contains an index range */ 59c809c407Sab } MATCH_T; 60c809c407Sab 61c809c407Sab typedef struct _match { 62c809c407Sab struct _match *next; /* Pointer to next item in list */ 63c809c407Sab MATCH_T type; 64c809c407Sab union { 65c809c407Sab const char *name; /* MATCH_T_NAME */ 66c809c407Sab struct { /* MATCH_T_NDX and MATCH_T_RANGE */ 67c809c407Sab int start; 68c809c407Sab int end; /* Only for MATCH_T_RANGE */ 69c809c407Sab } ndx; 70c809c407Sab } value; 71c809c407Sab } MATCH; 72c809c407Sab 73c809c407Sab /* List of MATCH records used by match() to implement -N and -I options */ 74c809c407Sab static MATCH *match_list = NULL; 75c809c407Sab 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)); 131c809c407Sab (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL22)); 132c809c407Sab (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL23)); 133*39773e46Sab (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL24)); 134c809c407Sab } 135c809c407Sab 136c809c407Sab /* 137c809c407Sab * Convert the ASCII representation of an index, or index range, into 138c809c407Sab * binary form, and store it in rec: 139c809c407Sab * 140c809c407Sab * index: An positive or 0 valued integer 141c809c407Sab * range: Two indexes, separated by a ':' character, denoting 142c809c407Sab * a range of allowed values. If the second value is omitted, 143c809c407Sab * any values equal to or greater than the first will match. 144c809c407Sab * 145c809c407Sab * exit: 146c809c407Sab * On success, *rec is filled in with a MATCH_T_NDX or MATCH_T_RANGE 147c809c407Sab * value, and this function returns (1). On failure, the contents 148c809c407Sab * of *rec are undefined, and (0) is returned. 149c809c407Sab */ 150c809c407Sab int 151c809c407Sab process_index_opt(const char *str, MATCH *rec) 152c809c407Sab { 153c809c407Sab #define SKIP_BLANK for (; *str && isspace(*str); str++) 154c809c407Sab 155c809c407Sab char *endptr; 156c809c407Sab 157c809c407Sab rec->value.ndx.start = strtol(str, &endptr, 10); 158c809c407Sab /* Value must use some of the input, and be 0 or positive */ 159c809c407Sab if ((str == endptr) || (rec->value.ndx.start < 0)) 160c809c407Sab return (0); 161c809c407Sab str = endptr; 162c809c407Sab 163c809c407Sab SKIP_BLANK; 164c809c407Sab if (*str != ':') { 165c809c407Sab rec->type = MATCH_T_NDX; 166c809c407Sab } else { 167c809c407Sab str++; /* Skip the ':' */ 168c809c407Sab rec->type = MATCH_T_RANGE; 169c809c407Sab SKIP_BLANK; 170c809c407Sab if (*str == '\0') { 171c809c407Sab rec->value.ndx.end = -1; /* Indicates "to end" */ 172c809c407Sab } else { 173c809c407Sab rec->value.ndx.end = strtol(str, &endptr, 10); 174c809c407Sab if ((str == endptr) || (rec->value.ndx.end < 0)) 175c809c407Sab return (0); 176c809c407Sab str = endptr; 177c809c407Sab SKIP_BLANK; 178c809c407Sab } 179c809c407Sab } 180c809c407Sab 181c809c407Sab /* Syntax error if anything is left over */ 182c809c407Sab if (*str != '\0') 183c809c407Sab return (0); 184c809c407Sab 185c809c407Sab return (1); 186c809c407Sab 187c809c407Sab #undef SKIP_BLANK 188c809c407Sab } 189c809c407Sab 190c809c407Sab /* 191c809c407Sab * Returns True (1) if the item with the given name or index should 192c809c407Sab * be displayed, and False (0) if it should not be. 193c809c407Sab * 194c809c407Sab * entry: 195c809c407Sab * strict - A strict match requires an explicit match to 196c809c407Sab * a user specified -I or -N option. A non-strict match 197c809c407Sab * succeeds if the match list is empty. 198c809c407Sab * name - Name of item under consideration, or NULL if the name 199c809c407Sab * should not be considered. 200c809c407Sab * ndx - if (ndx >= 0) index of item under consideration. 201c809c407Sab * A negative value indicates that the item has no index. 202c809c407Sab * 203c809c407Sab * exit: 204c809c407Sab * True will be returned if the given name/index matches those given 205c809c407Sab * by one of the -N or -I command line options, or if no such option 206c809c407Sab * was used in the command invocation. 207c809c407Sab */ 208c809c407Sab int 209c809c407Sab match(int strict, const char *name, int ndx) 210c809c407Sab { 211c809c407Sab MATCH *list; 212c809c407Sab 213c809c407Sab /* If no match options were specified, allow everything */ 214c809c407Sab if (!strict && (match_list == NULL)) 215c809c407Sab return (1); 216c809c407Sab 217c809c407Sab /* Run through the match records and check for a hit */ 218c809c407Sab for (list = match_list; list; list = list->next) { 219c809c407Sab switch (list->type) { 220c809c407Sab case MATCH_T_NAME: 221c809c407Sab if ((name != NULL) && 222c809c407Sab (strcmp(list->value.name, name) == 0)) 223c809c407Sab return (1); 224c809c407Sab break; 225c809c407Sab case MATCH_T_NDX: 226c809c407Sab if (ndx == list->value.ndx.start) 227c809c407Sab return (1); 228c809c407Sab break; 229c809c407Sab case MATCH_T_RANGE: 230c809c407Sab /* 231c809c407Sab * A range end value less than 0 means that any value 232c809c407Sab * above the start is acceptible. 233c809c407Sab */ 234c809c407Sab if ((ndx >= list->value.ndx.start) && 235c809c407Sab ((list->value.ndx.end < 0) || 236c809c407Sab (ndx <= list->value.ndx.end))) 237c809c407Sab return (1); 238c809c407Sab break; 239c809c407Sab } 240c809c407Sab } 241c809c407Sab 242c809c407Sab /* Nothing matched */ 243c809c407Sab return (0); 244c809c407Sab } 245c809c407Sab 246c809c407Sab /* 247c809c407Sab * Add an entry to match_list for use by match(). 248c809c407Sab * 249c809c407Sab * Return True (1) for success. On failure, an error is written 250c809c407Sab * to stderr, and False (0) is returned. 251c809c407Sab */ 252c809c407Sab static int 253c809c407Sab add_match_record(char *argv0, MATCH *data) 254c809c407Sab { 255c809c407Sab MATCH *rec; 256c809c407Sab MATCH *list; 257c809c407Sab 258c809c407Sab if ((rec = malloc(sizeof (*rec))) == NULL) { 259c809c407Sab int err = errno; 260c809c407Sab (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 261c809c407Sab basename(argv0), strerror(err)); 262c809c407Sab return (0); 263c809c407Sab } 264c809c407Sab 265c809c407Sab *rec = *data; 266c809c407Sab 267c809c407Sab /* Insert at end of match_list */ 268c809c407Sab if (match_list == NULL) { 269c809c407Sab match_list = rec; 270c809c407Sab } else { 271c809c407Sab for (list = match_list; list->next != NULL; list = list->next) 272c809c407Sab ; 273c809c407Sab list->next = rec; 274c809c407Sab } 275c809c407Sab 276c809c407Sab rec->next = NULL; 277c809c407Sab return (1); 2785aefb655Srie } 2795aefb655Srie 2805aefb655Srie static void 281*39773e46Sab decide(const char *file, int fd, Elf *elf, uint_t flags, int wfd) 2825aefb655Srie { 2835aefb655Srie if (gelf_getclass(elf) == ELFCLASS64) 284*39773e46Sab regular64(file, fd, elf, flags, wfd); 2855aefb655Srie else 286*39773e46Sab regular32(file, fd, elf, flags, wfd); 2875aefb655Srie } 2885aefb655Srie 2895aefb655Srie static void 290c809c407Sab archive(const char *file, int fd, Elf *elf, uint_t flags, int wfd) 2915aefb655Srie { 2925aefb655Srie Elf_Cmd cmd = ELF_C_READ; 2935aefb655Srie Elf_Arhdr *arhdr; 2945aefb655Srie Elf *_elf = 0; 2955aefb655Srie size_t ptr; 2965aefb655Srie Elf_Arsym *arsym = 0; 2975aefb655Srie 2985aefb655Srie /* 299d579eb63Sab * Determine if the archive symbol table itself is required. 3005aefb655Srie */ 301c809c407Sab if ((flags & FLG_SYMBOLS) && match(0, MSG_ORIG(MSG_ELF_ARSYM), -1)) { 3025aefb655Srie /* 3035aefb655Srie * Get the archive symbol table. 3045aefb655Srie */ 3055aefb655Srie if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) { 3065aefb655Srie /* 3075aefb655Srie * The arsym could be 0 even though there was no error. 3085aefb655Srie * Print the error message only when there was 3095aefb655Srie * real error from elf_getarsym(). 3105aefb655Srie */ 3115aefb655Srie failure(file, MSG_ORIG(MSG_ELF_GETARSYM)); 3125aefb655Srie return; 3135aefb655Srie } 3145aefb655Srie } 3155aefb655Srie 3165aefb655Srie /* 3175aefb655Srie * Print the archive symbol table only when the archive symbol 3185aefb655Srie * table exists and it was requested to print. 3195aefb655Srie */ 3205aefb655Srie if (arsym) { 3215aefb655Srie size_t cnt; 3225aefb655Srie char index[MAXNDXSIZE]; 3235aefb655Srie size_t offset = 0, _offset = 0; 3245aefb655Srie 3255aefb655Srie /* 3265aefb655Srie * Print out all the symbol entries. 3275aefb655Srie */ 3285aefb655Srie dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB)); 3295aefb655Srie dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS)); 3305aefb655Srie 3315aefb655Srie for (cnt = 0; cnt < ptr; cnt++, arsym++) { 3325aefb655Srie /* 3335aefb655Srie * For each object obtain an elf descriptor so that we 3345aefb655Srie * can establish the members name. Note, we have had 3355aefb655Srie * archives where the archive header has not been 3365aefb655Srie * obtainable so be lenient with errors. 3375aefb655Srie */ 3385aefb655Srie if ((offset == 0) || ((arsym->as_off != 0) && 3395aefb655Srie (arsym->as_off != _offset))) { 3405aefb655Srie 3415aefb655Srie if (_elf) 3425aefb655Srie (void) elf_end(_elf); 3435aefb655Srie 3445aefb655Srie if (elf_rand(elf, arsym->as_off) != 3455aefb655Srie arsym->as_off) { 3465aefb655Srie failure(file, MSG_ORIG(MSG_ELF_RAND)); 3475aefb655Srie arhdr = 0; 3485aefb655Srie } else if ((_elf = elf_begin(fd, 3495aefb655Srie ELF_C_READ, elf)) == 0) { 3505aefb655Srie failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 3515aefb655Srie arhdr = 0; 3525aefb655Srie } else if ((arhdr = elf_getarhdr(_elf)) == 0) { 3535aefb655Srie failure(file, 3545aefb655Srie MSG_ORIG(MSG_ELF_GETARHDR)); 3555aefb655Srie arhdr = 0; 3565aefb655Srie } 3575aefb655Srie 3585aefb655Srie _offset = arsym->as_off; 3595aefb655Srie if (offset == 0) 3605aefb655Srie offset = _offset; 3615aefb655Srie } 3625aefb655Srie 3635aefb655Srie (void) snprintf(index, MAXNDXSIZE, 3645aefb655Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt)); 3655aefb655Srie if (arsym->as_off) 3665aefb655Srie dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM1), index, 3675aefb655Srie /* LINTED */ 3685aefb655Srie (int)arsym->as_off, arhdr ? arhdr->ar_name : 3695aefb655Srie MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ? 3705aefb655Srie demangle(arsym->as_name, flags) : 3715aefb655Srie MSG_INTL(MSG_STR_NULL))); 3725aefb655Srie else 3735aefb655Srie dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM2), index, 3745aefb655Srie /* LINTED */ 3755aefb655Srie (int)arsym->as_off); 3765aefb655Srie } 3775aefb655Srie 3785aefb655Srie if (_elf) 3795aefb655Srie (void) elf_end(_elf); 3805aefb655Srie 3815aefb655Srie /* 3825aefb655Srie * If we only need the archive symbol table return. 3835aefb655Srie */ 384c809c407Sab if ((flags & FLG_SYMBOLS) && 385c809c407Sab match(1, MSG_ORIG(MSG_ELF_ARSYM), -1)) 3865aefb655Srie return; 3875aefb655Srie 3885aefb655Srie /* 3895aefb655Srie * Reset elf descriptor in preparation for processing each 3905aefb655Srie * member. 3915aefb655Srie */ 3925aefb655Srie if (offset) 3935aefb655Srie (void) elf_rand(elf, offset); 3945aefb655Srie } 3955aefb655Srie 3965aefb655Srie /* 3975aefb655Srie * Process each object within the archive. 3985aefb655Srie */ 3995aefb655Srie while ((_elf = elf_begin(fd, cmd, elf)) != NULL) { 4005aefb655Srie char name[MAXPATHLEN]; 4015aefb655Srie 4025aefb655Srie if ((arhdr = elf_getarhdr(_elf)) == NULL) { 4035aefb655Srie failure(file, MSG_ORIG(MSG_ELF_GETARHDR)); 4045aefb655Srie return; 4055aefb655Srie } 4065aefb655Srie if (*arhdr->ar_name != '/') { 4075aefb655Srie (void) snprintf(name, MAXPATHLEN, 4085aefb655Srie MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name); 4095aefb655Srie dbg_print(0, MSG_ORIG(MSG_FMT_NLSTR), name); 4105aefb655Srie 4115aefb655Srie switch (elf_kind(_elf)) { 4125aefb655Srie case ELF_K_AR: 413c809c407Sab archive(name, fd, _elf, flags, wfd); 4145aefb655Srie break; 4155aefb655Srie case ELF_K_ELF: 416*39773e46Sab decide(name, fd, _elf, flags, wfd); 4175aefb655Srie break; 4185aefb655Srie default: 4195aefb655Srie (void) fprintf(stderr, 4205aefb655Srie MSG_INTL(MSG_ERR_BADFILE), name); 4215aefb655Srie break; 4225aefb655Srie } 4235aefb655Srie } 4245aefb655Srie 4255aefb655Srie cmd = elf_next(_elf); 4265aefb655Srie (void) elf_end(_elf); 4275aefb655Srie } 4285aefb655Srie } 4295aefb655Srie 4305aefb655Srie int 4315aefb655Srie main(int argc, char **argv, char **envp) 4325aefb655Srie { 4335aefb655Srie Elf *elf; 4345aefb655Srie int var, fd, wfd = 0; 435c809c407Sab char *wname = 0; 4365aefb655Srie uint_t flags = 0; 437c809c407Sab MATCH match_data; 4385aefb655Srie 4395aefb655Srie /* 4405aefb655Srie * If we're on a 64-bit kernel, try to exec a full 64-bit version of 4415aefb655Srie * the binary. If successful, conv_check_native() won't return. 4425aefb655Srie */ 4437010c12aSrie (void) conv_check_native(argv, envp); 4445aefb655Srie 4455aefb655Srie /* 4465aefb655Srie * Establish locale. 4475aefb655Srie */ 4485aefb655Srie (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 4495aefb655Srie (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 4505aefb655Srie 4515aefb655Srie (void) setvbuf(stdout, NULL, _IOLBF, 0); 4525aefb655Srie (void) setvbuf(stderr, NULL, _IOLBF, 0); 4535aefb655Srie 4545aefb655Srie opterr = 0; 4555aefb655Srie while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) { 4565aefb655Srie switch (var) { 4575aefb655Srie case 'C': 4585aefb655Srie flags |= FLG_DEMANGLE; 4595aefb655Srie break; 4605aefb655Srie case 'c': 4615aefb655Srie flags |= FLG_SHDR; 4625aefb655Srie break; 4635aefb655Srie case 'd': 4645aefb655Srie flags |= FLG_DYNAMIC; 4655aefb655Srie break; 4665aefb655Srie case 'e': 4675aefb655Srie flags |= FLG_EHDR; 4685aefb655Srie break; 4695aefb655Srie case 'G': 4705aefb655Srie flags |= FLG_GOT; 4715aefb655Srie break; 4725aefb655Srie case 'g': 4735aefb655Srie flags |= FLG_GROUP; 4745aefb655Srie break; 4755aefb655Srie case 'H': 4765aefb655Srie flags |= FLG_CAP; 4775aefb655Srie break; 4785aefb655Srie case 'h': 4795aefb655Srie flags |= FLG_HASH; 4805aefb655Srie break; 481c809c407Sab case 'I': 482c809c407Sab if (!process_index_opt(optarg, &match_data)) { 483c809c407Sab (void) fprintf(stderr, 484c809c407Sab MSG_INTL(MSG_USAGE_BRIEF), 485c809c407Sab basename(argv[0])); 486c809c407Sab return (1); 487c809c407Sab } 488c809c407Sab if (!add_match_record(argv[0], &match_data)) 489c809c407Sab return (1); 490c809c407Sab break; 4915aefb655Srie case 'i': 4925aefb655Srie flags |= FLG_INTERP; 4935aefb655Srie break; 4945aefb655Srie case 'k': 4955aefb655Srie flags |= FLG_CHECKSUM; 4965aefb655Srie break; 4975aefb655Srie case 'l': 4985aefb655Srie flags |= FLG_LONGNAME; 4995aefb655Srie break; 5005aefb655Srie case 'm': 5015aefb655Srie flags |= FLG_MOVE; 5025aefb655Srie break; 5035aefb655Srie case 'N': 504c809c407Sab match_data.type = MATCH_T_NAME; 505c809c407Sab match_data.value.name = optarg; 506c809c407Sab if (!add_match_record(argv[0], &match_data)) 507c809c407Sab return (1); 5085aefb655Srie break; 5095aefb655Srie case 'n': 5105aefb655Srie flags |= FLG_NOTE; 5115aefb655Srie break; 512*39773e46Sab case 'P': 513*39773e46Sab flags |= FLG_FAKESHDR; 514*39773e46Sab break; 5155aefb655Srie case 'p': 5165aefb655Srie flags |= FLG_PHDR; 5175aefb655Srie break; 5185aefb655Srie case 'r': 5195aefb655Srie flags |= FLG_RELOC; 5205aefb655Srie break; 521d579eb63Sab case 'S': 522d579eb63Sab flags |= FLG_SORT; 523d579eb63Sab break; 5245aefb655Srie case 's': 5255aefb655Srie flags |= FLG_SYMBOLS; 5265aefb655Srie break; 5275aefb655Srie case 'u': 5285aefb655Srie flags |= FLG_UNWIND; 5295aefb655Srie break; 5305aefb655Srie case 'v': 5315aefb655Srie flags |= FLG_VERSIONS; 5325aefb655Srie break; 5335aefb655Srie case 'w': 5345aefb655Srie wname = optarg; 5355aefb655Srie break; 5365aefb655Srie case 'y': 5375aefb655Srie flags |= FLG_SYMINFO; 5385aefb655Srie break; 5395aefb655Srie case '?': 5405aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 5415aefb655Srie basename(argv[0])); 5425aefb655Srie detail_usage(); 5435aefb655Srie return (1); 5445aefb655Srie default: 5455aefb655Srie break; 5465aefb655Srie } 5475aefb655Srie } 5485aefb655Srie 5495aefb655Srie /* 5505aefb655Srie * Validate any arguments. 5515aefb655Srie */ 552*39773e46Sab if ((flags & ~(FLG_DEMANGLE | FLG_LONGNAME| FLG_FAKESHDR)) == 0) { 553c809c407Sab if (!wname && (match_list == NULL)) { 5545aefb655Srie flags |= FLG_EVERYTHING; 555c809c407Sab } else if (!wname || (match_list == NULL)) { 5565aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 5575aefb655Srie basename(argv[0])); 5585aefb655Srie return (1); 5595aefb655Srie } 5605aefb655Srie } 5615aefb655Srie 5625aefb655Srie if ((var = argc - optind) == 0) { 5635aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 5645aefb655Srie basename(argv[0])); 5655aefb655Srie return (1); 5665aefb655Srie } 5675aefb655Srie 5685aefb655Srie /* 5695aefb655Srie * If the -l/-C option is specified, set up the liblddbg.so. 5705aefb655Srie */ 5715aefb655Srie if (flags & FLG_LONGNAME) 5725aefb655Srie dbg_desc->d_extra |= DBG_E_LONG; 5735aefb655Srie if (flags & FLG_DEMANGLE) 5745aefb655Srie dbg_desc->d_extra |= DBG_E_DEMANGLE; 5755aefb655Srie 5765aefb655Srie /* 5775aefb655Srie * If the -w option has indicated an output file open it. It's 5785aefb655Srie * arguable whether this option has much use when multiple files are 5795aefb655Srie * being processed. 5805aefb655Srie */ 5815aefb655Srie if (wname) { 5825aefb655Srie if ((wfd = open(wname, (O_RDWR | O_CREAT | O_TRUNC), 5835aefb655Srie 0666)) < 0) { 5845aefb655Srie int err = errno; 5855aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 5865aefb655Srie wname, strerror(err)); 5875aefb655Srie wfd = 0; 5885aefb655Srie } 5895aefb655Srie } 5905aefb655Srie 5915aefb655Srie /* 5925aefb655Srie * Open the input file and initialize the elf interface. 5935aefb655Srie */ 5945aefb655Srie for (; optind < argc; optind++) { 5955aefb655Srie const char *file = argv[optind]; 5965aefb655Srie 5975aefb655Srie if ((fd = open(argv[optind], O_RDONLY)) == -1) { 5985aefb655Srie int err = errno; 5995aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 6005aefb655Srie file, strerror(err)); 6015aefb655Srie continue; 6025aefb655Srie } 6035aefb655Srie (void) elf_version(EV_CURRENT); 6045aefb655Srie if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 6055aefb655Srie failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 6065aefb655Srie (void) close(fd); 6075aefb655Srie continue; 6085aefb655Srie } 6095aefb655Srie 6105aefb655Srie if (var > 1) 6115aefb655Srie dbg_print(0, MSG_ORIG(MSG_FMT_NLSTRNL), file); 6125aefb655Srie 6135aefb655Srie switch (elf_kind(elf)) { 6145aefb655Srie case ELF_K_AR: 615c809c407Sab archive(file, fd, elf, flags, wfd); 6165aefb655Srie break; 6175aefb655Srie case ELF_K_ELF: 618*39773e46Sab decide(file, fd, elf, flags, wfd); 6195aefb655Srie break; 6205aefb655Srie default: 6215aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADFILE), file); 6225aefb655Srie break; 6235aefb655Srie } 6245aefb655Srie 6255aefb655Srie (void) close(fd); 6265aefb655Srie (void) elf_end(elf); 6275aefb655Srie } 6285aefb655Srie 6295aefb655Srie if (wfd) 6305aefb655Srie (void) close(wfd); 6315aefb655Srie return (0); 6325aefb655Srie } 633