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> 491618Srie 504063Sab196087 const Cache cache_init = {NULL, NULL, NULL, NULL, 0}; 511618Srie 524168Sab196087 534168Sab196087 544168Sab196087 /* MATCH is used to retain information about -N and -I options */ 554168Sab196087 typedef enum { 564168Sab196087 MATCH_T_NAME, /* Record contains a name */ 574168Sab196087 MATCH_T_NDX, /* Record contains a single index */ 584168Sab196087 MATCH_T_RANGE /* Record contains an index range */ 594168Sab196087 } MATCH_T; 604168Sab196087 614168Sab196087 typedef struct _match { 624168Sab196087 struct _match *next; /* Pointer to next item in list */ 634168Sab196087 MATCH_T type; 644168Sab196087 union { 654168Sab196087 const char *name; /* MATCH_T_NAME */ 664168Sab196087 struct { /* MATCH_T_NDX and MATCH_T_RANGE */ 674168Sab196087 int start; 684168Sab196087 int end; /* Only for MATCH_T_RANGE */ 694168Sab196087 } ndx; 704168Sab196087 } value; 714168Sab196087 } MATCH; 724168Sab196087 734168Sab196087 /* List of MATCH records used by match() to implement -N and -I options */ 744168Sab196087 static MATCH *match_list = NULL; 754168Sab196087 761618Srie const char * 771618Srie _elfdump_msg(Msg mid) 781618Srie { 791618Srie return (gettext(MSG_ORIG(mid))); 801618Srie } 811618Srie 821618Srie /* 831618Srie * Determine whether a symbol name should be demangled. 841618Srie */ 851618Srie const char * 861618Srie demangle(const char *name, uint_t flags) 871618Srie { 881618Srie if (flags & FLG_DEMANGLE) 891618Srie return (Elf_demangle_name(name)); 901618Srie else 911618Srie return ((char *)name); 921618Srie } 931618Srie 941618Srie /* 951618Srie * Define our own standard error routine. 961618Srie */ 971618Srie void 981618Srie failure(const char *file, const char *func) 991618Srie { 1001618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_FAILURE), 1011618Srie file, func, elf_errmsg(elf_errno())); 1021618Srie } 1031618Srie 1041618Srie /* 1051618Srie * The full usage message 1061618Srie */ 1071618Srie static void 1081618Srie detail_usage() 1091618Srie { 1101618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL1)); 1111618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL2)); 1121618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL3)); 1131618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL4)); 1141618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL5)); 1151618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL6)); 1161618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL7)); 1171618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL8)); 1181618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9)); 1191618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL10)); 1201618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL11)); 1211618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL12)); 1221618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL13)); 1231618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL14)); 1241618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL15)); 1251618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL16)); 1261618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL17)); 1271618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL18)); 1281618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL19)); 1291618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL20)); 1303492Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL21)); 1314168Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL22)); 1324168Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL23)); 133*4665Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL24)); 1344168Sab196087 } 1354168Sab196087 1364168Sab196087 /* 1374168Sab196087 * Convert the ASCII representation of an index, or index range, into 1384168Sab196087 * binary form, and store it in rec: 1394168Sab196087 * 1404168Sab196087 * index: An positive or 0 valued integer 1414168Sab196087 * range: Two indexes, separated by a ':' character, denoting 1424168Sab196087 * a range of allowed values. If the second value is omitted, 1434168Sab196087 * any values equal to or greater than the first will match. 1444168Sab196087 * 1454168Sab196087 * exit: 1464168Sab196087 * On success, *rec is filled in with a MATCH_T_NDX or MATCH_T_RANGE 1474168Sab196087 * value, and this function returns (1). On failure, the contents 1484168Sab196087 * of *rec are undefined, and (0) is returned. 1494168Sab196087 */ 1504168Sab196087 int 1514168Sab196087 process_index_opt(const char *str, MATCH *rec) 1524168Sab196087 { 1534168Sab196087 #define SKIP_BLANK for (; *str && isspace(*str); str++) 1544168Sab196087 1554168Sab196087 char *endptr; 1564168Sab196087 1574168Sab196087 rec->value.ndx.start = strtol(str, &endptr, 10); 1584168Sab196087 /* Value must use some of the input, and be 0 or positive */ 1594168Sab196087 if ((str == endptr) || (rec->value.ndx.start < 0)) 1604168Sab196087 return (0); 1614168Sab196087 str = endptr; 1624168Sab196087 1634168Sab196087 SKIP_BLANK; 1644168Sab196087 if (*str != ':') { 1654168Sab196087 rec->type = MATCH_T_NDX; 1664168Sab196087 } else { 1674168Sab196087 str++; /* Skip the ':' */ 1684168Sab196087 rec->type = MATCH_T_RANGE; 1694168Sab196087 SKIP_BLANK; 1704168Sab196087 if (*str == '\0') { 1714168Sab196087 rec->value.ndx.end = -1; /* Indicates "to end" */ 1724168Sab196087 } else { 1734168Sab196087 rec->value.ndx.end = strtol(str, &endptr, 10); 1744168Sab196087 if ((str == endptr) || (rec->value.ndx.end < 0)) 1754168Sab196087 return (0); 1764168Sab196087 str = endptr; 1774168Sab196087 SKIP_BLANK; 1784168Sab196087 } 1794168Sab196087 } 1804168Sab196087 1814168Sab196087 /* Syntax error if anything is left over */ 1824168Sab196087 if (*str != '\0') 1834168Sab196087 return (0); 1844168Sab196087 1854168Sab196087 return (1); 1864168Sab196087 1874168Sab196087 #undef SKIP_BLANK 1884168Sab196087 } 1894168Sab196087 1904168Sab196087 /* 1914168Sab196087 * Returns True (1) if the item with the given name or index should 1924168Sab196087 * be displayed, and False (0) if it should not be. 1934168Sab196087 * 1944168Sab196087 * entry: 1954168Sab196087 * strict - A strict match requires an explicit match to 1964168Sab196087 * a user specified -I or -N option. A non-strict match 1974168Sab196087 * succeeds if the match list is empty. 1984168Sab196087 * name - Name of item under consideration, or NULL if the name 1994168Sab196087 * should not be considered. 2004168Sab196087 * ndx - if (ndx >= 0) index of item under consideration. 2014168Sab196087 * A negative value indicates that the item has no index. 2024168Sab196087 * 2034168Sab196087 * exit: 2044168Sab196087 * True will be returned if the given name/index matches those given 2054168Sab196087 * by one of the -N or -I command line options, or if no such option 2064168Sab196087 * was used in the command invocation. 2074168Sab196087 */ 2084168Sab196087 int 2094168Sab196087 match(int strict, const char *name, int ndx) 2104168Sab196087 { 2114168Sab196087 MATCH *list; 2124168Sab196087 2134168Sab196087 /* If no match options were specified, allow everything */ 2144168Sab196087 if (!strict && (match_list == NULL)) 2154168Sab196087 return (1); 2164168Sab196087 2174168Sab196087 /* Run through the match records and check for a hit */ 2184168Sab196087 for (list = match_list; list; list = list->next) { 2194168Sab196087 switch (list->type) { 2204168Sab196087 case MATCH_T_NAME: 2214168Sab196087 if ((name != NULL) && 2224168Sab196087 (strcmp(list->value.name, name) == 0)) 2234168Sab196087 return (1); 2244168Sab196087 break; 2254168Sab196087 case MATCH_T_NDX: 2264168Sab196087 if (ndx == list->value.ndx.start) 2274168Sab196087 return (1); 2284168Sab196087 break; 2294168Sab196087 case MATCH_T_RANGE: 2304168Sab196087 /* 2314168Sab196087 * A range end value less than 0 means that any value 2324168Sab196087 * above the start is acceptible. 2334168Sab196087 */ 2344168Sab196087 if ((ndx >= list->value.ndx.start) && 2354168Sab196087 ((list->value.ndx.end < 0) || 2364168Sab196087 (ndx <= list->value.ndx.end))) 2374168Sab196087 return (1); 2384168Sab196087 break; 2394168Sab196087 } 2404168Sab196087 } 2414168Sab196087 2424168Sab196087 /* Nothing matched */ 2434168Sab196087 return (0); 2444168Sab196087 } 2454168Sab196087 2464168Sab196087 /* 2474168Sab196087 * Add an entry to match_list for use by match(). 2484168Sab196087 * 2494168Sab196087 * Return True (1) for success. On failure, an error is written 2504168Sab196087 * to stderr, and False (0) is returned. 2514168Sab196087 */ 2524168Sab196087 static int 2534168Sab196087 add_match_record(char *argv0, MATCH *data) 2544168Sab196087 { 2554168Sab196087 MATCH *rec; 2564168Sab196087 MATCH *list; 2574168Sab196087 2584168Sab196087 if ((rec = malloc(sizeof (*rec))) == NULL) { 2594168Sab196087 int err = errno; 2604168Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2614168Sab196087 basename(argv0), strerror(err)); 2624168Sab196087 return (0); 2634168Sab196087 } 2644168Sab196087 2654168Sab196087 *rec = *data; 2664168Sab196087 2674168Sab196087 /* Insert at end of match_list */ 2684168Sab196087 if (match_list == NULL) { 2694168Sab196087 match_list = rec; 2704168Sab196087 } else { 2714168Sab196087 for (list = match_list; list->next != NULL; list = list->next) 2724168Sab196087 ; 2734168Sab196087 list->next = rec; 2744168Sab196087 } 2754168Sab196087 2764168Sab196087 rec->next = NULL; 2774168Sab196087 return (1); 2781618Srie } 2791618Srie 2801618Srie static void 281*4665Sab196087 decide(const char *file, int fd, Elf *elf, uint_t flags, int wfd) 2821618Srie { 2831618Srie if (gelf_getclass(elf) == ELFCLASS64) 284*4665Sab196087 regular64(file, fd, elf, flags, wfd); 2851618Srie else 286*4665Sab196087 regular32(file, fd, elf, flags, wfd); 2871618Srie } 2881618Srie 2891618Srie static void 2904168Sab196087 archive(const char *file, int fd, Elf *elf, uint_t flags, int wfd) 2911618Srie { 2921618Srie Elf_Cmd cmd = ELF_C_READ; 2931618Srie Elf_Arhdr *arhdr; 2941618Srie Elf *_elf = 0; 2951618Srie size_t ptr; 2961618Srie Elf_Arsym *arsym = 0; 2971618Srie 2981618Srie /* 2993492Sab196087 * Determine if the archive symbol table itself is required. 3001618Srie */ 3014168Sab196087 if ((flags & FLG_SYMBOLS) && match(0, MSG_ORIG(MSG_ELF_ARSYM), -1)) { 3021618Srie /* 3031618Srie * Get the archive symbol table. 3041618Srie */ 3051618Srie if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) { 3061618Srie /* 3071618Srie * The arsym could be 0 even though there was no error. 3081618Srie * Print the error message only when there was 3091618Srie * real error from elf_getarsym(). 3101618Srie */ 3111618Srie failure(file, MSG_ORIG(MSG_ELF_GETARSYM)); 3121618Srie return; 3131618Srie } 3141618Srie } 3151618Srie 3161618Srie /* 3171618Srie * Print the archive symbol table only when the archive symbol 3181618Srie * table exists and it was requested to print. 3191618Srie */ 3201618Srie if (arsym) { 3211618Srie size_t cnt; 3221618Srie char index[MAXNDXSIZE]; 3231618Srie size_t offset = 0, _offset = 0; 3241618Srie 3251618Srie /* 3261618Srie * Print out all the symbol entries. 3271618Srie */ 3281618Srie dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB)); 3291618Srie dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS)); 3301618Srie 3311618Srie for (cnt = 0; cnt < ptr; cnt++, arsym++) { 3321618Srie /* 3331618Srie * For each object obtain an elf descriptor so that we 3341618Srie * can establish the members name. Note, we have had 3351618Srie * archives where the archive header has not been 3361618Srie * obtainable so be lenient with errors. 3371618Srie */ 3381618Srie if ((offset == 0) || ((arsym->as_off != 0) && 3391618Srie (arsym->as_off != _offset))) { 3401618Srie 3411618Srie if (_elf) 3421618Srie (void) elf_end(_elf); 3431618Srie 3441618Srie if (elf_rand(elf, arsym->as_off) != 3451618Srie arsym->as_off) { 3461618Srie failure(file, MSG_ORIG(MSG_ELF_RAND)); 3471618Srie arhdr = 0; 3481618Srie } else if ((_elf = elf_begin(fd, 3491618Srie ELF_C_READ, elf)) == 0) { 3501618Srie failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 3511618Srie arhdr = 0; 3521618Srie } else if ((arhdr = elf_getarhdr(_elf)) == 0) { 3531618Srie failure(file, 3541618Srie MSG_ORIG(MSG_ELF_GETARHDR)); 3551618Srie arhdr = 0; 3561618Srie } 3571618Srie 3581618Srie _offset = arsym->as_off; 3591618Srie if (offset == 0) 3601618Srie offset = _offset; 3611618Srie } 3621618Srie 3631618Srie (void) snprintf(index, MAXNDXSIZE, 3641618Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt)); 3651618Srie if (arsym->as_off) 3661618Srie dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM1), index, 3671618Srie /* LINTED */ 3681618Srie (int)arsym->as_off, arhdr ? arhdr->ar_name : 3691618Srie MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ? 3701618Srie demangle(arsym->as_name, flags) : 3711618Srie MSG_INTL(MSG_STR_NULL))); 3721618Srie else 3731618Srie dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM2), index, 3741618Srie /* LINTED */ 3751618Srie (int)arsym->as_off); 3761618Srie } 3771618Srie 3781618Srie if (_elf) 3791618Srie (void) elf_end(_elf); 3801618Srie 3811618Srie /* 3821618Srie * If we only need the archive symbol table return. 3831618Srie */ 3844168Sab196087 if ((flags & FLG_SYMBOLS) && 3854168Sab196087 match(1, MSG_ORIG(MSG_ELF_ARSYM), -1)) 3861618Srie return; 3871618Srie 3881618Srie /* 3891618Srie * Reset elf descriptor in preparation for processing each 3901618Srie * member. 3911618Srie */ 3921618Srie if (offset) 3931618Srie (void) elf_rand(elf, offset); 3941618Srie } 3951618Srie 3961618Srie /* 3971618Srie * Process each object within the archive. 3981618Srie */ 3991618Srie while ((_elf = elf_begin(fd, cmd, elf)) != NULL) { 4001618Srie char name[MAXPATHLEN]; 4011618Srie 4021618Srie if ((arhdr = elf_getarhdr(_elf)) == NULL) { 4031618Srie failure(file, MSG_ORIG(MSG_ELF_GETARHDR)); 4041618Srie return; 4051618Srie } 4061618Srie if (*arhdr->ar_name != '/') { 4071618Srie (void) snprintf(name, MAXPATHLEN, 4081618Srie MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name); 4091618Srie dbg_print(0, MSG_ORIG(MSG_FMT_NLSTR), name); 4101618Srie 4111618Srie switch (elf_kind(_elf)) { 4121618Srie case ELF_K_AR: 4134168Sab196087 archive(name, fd, _elf, flags, wfd); 4141618Srie break; 4151618Srie case ELF_K_ELF: 416*4665Sab196087 decide(name, fd, _elf, flags, wfd); 4171618Srie break; 4181618Srie default: 4191618Srie (void) fprintf(stderr, 4201618Srie MSG_INTL(MSG_ERR_BADFILE), name); 4211618Srie break; 4221618Srie } 4231618Srie } 4241618Srie 4251618Srie cmd = elf_next(_elf); 4261618Srie (void) elf_end(_elf); 4271618Srie } 4281618Srie } 4291618Srie 4301618Srie int 4311618Srie main(int argc, char **argv, char **envp) 4321618Srie { 4331618Srie Elf *elf; 4341618Srie int var, fd, wfd = 0; 4354168Sab196087 char *wname = 0; 4361618Srie uint_t flags = 0; 4374168Sab196087 MATCH match_data; 4381618Srie 4391618Srie /* 4401618Srie * If we're on a 64-bit kernel, try to exec a full 64-bit version of 4411618Srie * the binary. If successful, conv_check_native() won't return. 4421618Srie */ 4432647Srie (void) conv_check_native(argv, envp); 4441618Srie 4451618Srie /* 4461618Srie * Establish locale. 4471618Srie */ 4481618Srie (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 4491618Srie (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 4501618Srie 4511618Srie (void) setvbuf(stdout, NULL, _IOLBF, 0); 4521618Srie (void) setvbuf(stderr, NULL, _IOLBF, 0); 4531618Srie 4541618Srie opterr = 0; 4551618Srie while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) { 4561618Srie switch (var) { 4571618Srie case 'C': 4581618Srie flags |= FLG_DEMANGLE; 4591618Srie break; 4601618Srie case 'c': 4611618Srie flags |= FLG_SHDR; 4621618Srie break; 4631618Srie case 'd': 4641618Srie flags |= FLG_DYNAMIC; 4651618Srie break; 4661618Srie case 'e': 4671618Srie flags |= FLG_EHDR; 4681618Srie break; 4691618Srie case 'G': 4701618Srie flags |= FLG_GOT; 4711618Srie break; 4721618Srie case 'g': 4731618Srie flags |= FLG_GROUP; 4741618Srie break; 4751618Srie case 'H': 4761618Srie flags |= FLG_CAP; 4771618Srie break; 4781618Srie case 'h': 4791618Srie flags |= FLG_HASH; 4801618Srie break; 4814168Sab196087 case 'I': 4824168Sab196087 if (!process_index_opt(optarg, &match_data)) { 4834168Sab196087 (void) fprintf(stderr, 4844168Sab196087 MSG_INTL(MSG_USAGE_BRIEF), 4854168Sab196087 basename(argv[0])); 4864168Sab196087 return (1); 4874168Sab196087 } 4884168Sab196087 if (!add_match_record(argv[0], &match_data)) 4894168Sab196087 return (1); 4904168Sab196087 break; 4911618Srie case 'i': 4921618Srie flags |= FLG_INTERP; 4931618Srie break; 4941618Srie case 'k': 4951618Srie flags |= FLG_CHECKSUM; 4961618Srie break; 4971618Srie case 'l': 4981618Srie flags |= FLG_LONGNAME; 4991618Srie break; 5001618Srie case 'm': 5011618Srie flags |= FLG_MOVE; 5021618Srie break; 5031618Srie case 'N': 5044168Sab196087 match_data.type = MATCH_T_NAME; 5054168Sab196087 match_data.value.name = optarg; 5064168Sab196087 if (!add_match_record(argv[0], &match_data)) 5074168Sab196087 return (1); 5081618Srie break; 5091618Srie case 'n': 5101618Srie flags |= FLG_NOTE; 5111618Srie break; 512*4665Sab196087 case 'P': 513*4665Sab196087 flags |= FLG_FAKESHDR; 514*4665Sab196087 break; 5151618Srie case 'p': 5161618Srie flags |= FLG_PHDR; 5171618Srie break; 5181618Srie case 'r': 5191618Srie flags |= FLG_RELOC; 5201618Srie break; 5213492Sab196087 case 'S': 5223492Sab196087 flags |= FLG_SORT; 5233492Sab196087 break; 5241618Srie case 's': 5251618Srie flags |= FLG_SYMBOLS; 5261618Srie break; 5271618Srie case 'u': 5281618Srie flags |= FLG_UNWIND; 5291618Srie break; 5301618Srie case 'v': 5311618Srie flags |= FLG_VERSIONS; 5321618Srie break; 5331618Srie case 'w': 5341618Srie wname = optarg; 5351618Srie break; 5361618Srie case 'y': 5371618Srie flags |= FLG_SYMINFO; 5381618Srie break; 5391618Srie case '?': 5401618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 5411618Srie basename(argv[0])); 5421618Srie detail_usage(); 5431618Srie return (1); 5441618Srie default: 5451618Srie break; 5461618Srie } 5471618Srie } 5481618Srie 5491618Srie /* 5501618Srie * Validate any arguments. 5511618Srie */ 552*4665Sab196087 if ((flags & ~(FLG_DEMANGLE | FLG_LONGNAME| FLG_FAKESHDR)) == 0) { 5534168Sab196087 if (!wname && (match_list == NULL)) { 5541618Srie flags |= FLG_EVERYTHING; 5554168Sab196087 } else if (!wname || (match_list == NULL)) { 5561618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 5571618Srie basename(argv[0])); 5581618Srie return (1); 5591618Srie } 5601618Srie } 5611618Srie 5621618Srie if ((var = argc - optind) == 0) { 5631618Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 5641618Srie basename(argv[0])); 5651618Srie return (1); 5661618Srie } 5671618Srie 5681618Srie /* 5691618Srie * If the -l/-C option is specified, set up the liblddbg.so. 5701618Srie */ 5711618Srie if (flags & FLG_LONGNAME) 5721618Srie dbg_desc->d_extra |= DBG_E_LONG; 5731618Srie if (flags & FLG_DEMANGLE) 5741618Srie dbg_desc->d_extra |= DBG_E_DEMANGLE; 5751618Srie 5761618Srie /* 5771618Srie * If the -w option has indicated an output file open it. It's 5781618Srie * arguable whether this option has much use when multiple files are 5791618Srie * being processed. 5801618Srie */ 5811618Srie if (wname) { 5821618Srie if ((wfd = open(wname, (O_RDWR | O_CREAT | O_TRUNC), 5831618Srie 0666)) < 0) { 5841618Srie int err = errno; 5851618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 5861618Srie wname, strerror(err)); 5871618Srie wfd = 0; 5881618Srie } 5891618Srie } 5901618Srie 5911618Srie /* 5921618Srie * Open the input file and initialize the elf interface. 5931618Srie */ 5941618Srie for (; optind < argc; optind++) { 5951618Srie const char *file = argv[optind]; 5961618Srie 5971618Srie if ((fd = open(argv[optind], O_RDONLY)) == -1) { 5981618Srie int err = errno; 5991618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 6001618Srie file, strerror(err)); 6011618Srie continue; 6021618Srie } 6031618Srie (void) elf_version(EV_CURRENT); 6041618Srie if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 6051618Srie failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 6061618Srie (void) close(fd); 6071618Srie continue; 6081618Srie } 6091618Srie 6101618Srie if (var > 1) 6111618Srie dbg_print(0, MSG_ORIG(MSG_FMT_NLSTRNL), file); 6121618Srie 6131618Srie switch (elf_kind(elf)) { 6141618Srie case ELF_K_AR: 6154168Sab196087 archive(file, fd, elf, flags, wfd); 6161618Srie break; 6171618Srie case ELF_K_ELF: 618*4665Sab196087 decide(file, fd, elf, flags, wfd); 6191618Srie break; 6201618Srie default: 6211618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADFILE), file); 6221618Srie break; 6231618Srie } 6241618Srie 6251618Srie (void) close(fd); 6261618Srie (void) elf_end(elf); 6271618Srie } 6281618Srie 6291618Srie if (wfd) 6301618Srie (void) close(wfd); 6311618Srie return (0); 6321618Srie } 633