xref: /onnv-gate/usr/src/cmd/sgs/elfdump/common/main.c (revision 12792:1f56a791e275)
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 /*
23*12792SAli.Bahrami@Oracle.COM  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
241618Srie  */
251618Srie 
261618Srie /*
271618Srie  * Dump an elf file.
281618Srie  */
291618Srie #include	<sys/param.h>
301618Srie #include	<fcntl.h>
311618Srie #include	<stdio.h>
324168Sab196087 #include	<stdlib.h>
334168Sab196087 #include	<ctype.h>
34*12792SAli.Bahrami@Oracle.COM #include	<_libelf.h>
351618Srie #include	<link.h>
361618Srie #include	<stdarg.h>
371618Srie #include	<unistd.h>
381618Srie #include	<libgen.h>
391618Srie #include	<libintl.h>
401618Srie #include	<locale.h>
411618Srie #include	<errno.h>
421618Srie #include	<strings.h>
431618Srie #include	<debug.h>
441618Srie #include	<conv.h>
451618Srie #include	<msg.h>
461618Srie #include	<_elfdump.h>
475411Sab196087 #include	<sys/elf_SPARC.h>
485411Sab196087 #include	<sys/elf_amd64.h>
495411Sab196087 
501618Srie 
514063Sab196087 const Cache	cache_init = {NULL, NULL, NULL, NULL, 0};
521618Srie 
534168Sab196087 
544168Sab196087 
555411Sab196087 /*
565411Sab196087  * The -I, -N, and -T options are called "match options", because
575411Sab196087  * they allow selecting the items to be displayed based on matching
585411Sab196087  * their index, name, or type.
595411Sab196087  *
605411Sab196087  * The ELF information to which -I, -N, or -T are applied in
615411Sab196087  * the current invocation is called the "match item".
625411Sab196087  */
634168Sab196087 typedef enum {
645411Sab196087 	MATCH_ITEM_PT,		/* Program header (PT_) */
655411Sab196087 	MATCH_ITEM_SHT		/* Section header (SHT_) */
665411Sab196087 } match_item_t;
675411Sab196087 
685411Sab196087 /* match_opt_t is  used to note which match option was used */
695411Sab196087 typedef enum {
705411Sab196087 	MATCH_OPT_NAME,		/* Record contains a name */
715411Sab196087 	MATCH_OPT_NDX,		/* Record contains a single index */
725411Sab196087 	MATCH_OPT_RANGE,	/* Record contains an index range */
735411Sab196087 	MATCH_OPT_TYPE,		/* Record contains a type (shdr or phdr) */
745411Sab196087 } match_opt_t;
754168Sab196087 
764168Sab196087 typedef struct _match {
774168Sab196087 	struct _match	*next;		/* Pointer to next item in list */
785411Sab196087 	match_opt_t	opt_type;
794168Sab196087 	union {
805411Sab196087 		const char	*name;	/* MATCH_OPT_NAME */
815411Sab196087 		struct {		/* MATCH_OPT_NDX and MATCH_OPT_RANGE */
824168Sab196087 			int	start;
835411Sab196087 			int	end;	/* Only for MATCH_OPT_RANGE */
844168Sab196087 		} ndx;
855411Sab196087 		uint32_t	type;	/* MATCH_OPT_TYPE */
864168Sab196087 	} value;
875411Sab196087 } match_rec_t;
885411Sab196087 
895411Sab196087 static struct {
905411Sab196087 	match_item_t	item_type;	/* Type of item being matched */
915411Sab196087 	match_rec_t	*list;		/* Records for (-I, -N, -T) options */
925411Sab196087 } match_state;
935411Sab196087 
945411Sab196087 
955411Sab196087 
961618Srie const char *
_elfdump_msg(Msg mid)971618Srie _elfdump_msg(Msg mid)
981618Srie {
991618Srie 	return (gettext(MSG_ORIG(mid)));
1001618Srie }
1011618Srie 
1021618Srie /*
1031618Srie  * Determine whether a symbol name should be demangled.
1041618Srie  */
1051618Srie const char *
demangle(const char * name,uint_t flags)1061618Srie demangle(const char *name, uint_t flags)
1071618Srie {
1085411Sab196087 	if (flags & FLG_CTL_DEMANGLE)
1091618Srie 		return (Elf_demangle_name(name));
1101618Srie 	else
1111618Srie 		return ((char *)name);
1121618Srie }
1131618Srie 
1141618Srie /*
1151618Srie  * Define our own standard error routine.
1161618Srie  */
1171618Srie void
failure(const char * file,const char * func)1181618Srie failure(const char *file, const char *func)
1191618Srie {
1201618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_ERR_FAILURE),
1211618Srie 	    file, func, elf_errmsg(elf_errno()));
1221618Srie }
1231618Srie 
1241618Srie /*
1251618Srie  * The full usage message
1261618Srie  */
1271618Srie static void
detail_usage()1281618Srie detail_usage()
1291618Srie {
1301618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL1));
1311618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL2));
1321618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL3));
1331618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL4));
1341618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL5));
1351618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL6));
1361618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL7));
1371618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL8));
1381618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9));
1391618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL10));
1401618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL11));
1411618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL12));
1421618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL13));
1431618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL14));
1441618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL15));
1451618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL16));
1461618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL17));
1471618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL18));
1481618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL19));
1491618Srie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL20));
1503492Sab196087 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL21));
1514168Sab196087 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL22));
1524168Sab196087 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL23));
1534665Sab196087 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL24));
1545411Sab196087 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL25));
1559273SAli.Bahrami@Sun.COM 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL26));
1564168Sab196087 }
1574168Sab196087 
1584168Sab196087 /*
1596635Sab196087  * Output a block of raw data as hex bytes. Each row is given
1606635Sab196087  * the index of the first byte in the row.
1616635Sab196087  *
1626635Sab196087  * entry:
1636635Sab196087  *	data - Pointer to first byte of data to be displayed
1646635Sab196087  *	n - # of bytes of data
1656635Sab196087  *	prefix - String to be output before each line. Useful
1666635Sab196087  *		for indenting output.
1676635Sab196087  *	bytes_per_col - # of space separated bytes to output
1686635Sab196087  *		in each column.
1696635Sab196087  *	col_per_row - # of columns to output per row
1706635Sab196087  *
1716635Sab196087  * exit:
1726635Sab196087  *	The formatted data has been sent to stdout. Each row of output
1736635Sab196087  *	shows (bytes_per_col * col_per_row) bytes of data.
1746635Sab196087  */
1756635Sab196087 void
dump_hex_bytes(const void * data,size_t n,int indent,int bytes_per_col,int col_per_row)1769085SAli.Bahrami@Sun.COM dump_hex_bytes(const void *data, size_t n, int indent,
1776635Sab196087 	int bytes_per_col, int col_per_row)
1786635Sab196087 {
1799085SAli.Bahrami@Sun.COM 	const uchar_t *ldata = data;
1806635Sab196087 	int	bytes_per_row = bytes_per_col * col_per_row;
1816635Sab196087 	int	ndx, byte, word;
1826635Sab196087 	char	string[128], *str = string;
1836635Sab196087 	char	index[MAXNDXSIZE];
1846635Sab196087 	int	index_width;
1856635Sab196087 	int	sp_prefix = 0;
1866635Sab196087 
1876635Sab196087 
1886635Sab196087 	/*
1896635Sab196087 	 * Determine the width to use for the index string. We follow
1906635Sab196087 	 * 8-byte tab rules, but don't use an actual \t character so
1916635Sab196087 	 * that the output can be arbitrarily shifted without odd
1926635Sab196087 	 * tab effects, and so that all the columns line up no matter
1936635Sab196087 	 * how many lines of output are produced.
1946635Sab196087 	 */
1956635Sab196087 	ndx = n / bytes_per_row;
1966635Sab196087 	(void) snprintf(index, sizeof (index),
1976635Sab196087 	    MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx));
1986635Sab196087 	index_width = strlen(index);
1996635Sab196087 	index_width = S_ROUND(index_width, 8);
2006635Sab196087 
2019085SAli.Bahrami@Sun.COM 	for (ndx = byte = word = 0; n > 0; n--, ldata++) {
2026635Sab196087 		while (sp_prefix-- > 0)
2036635Sab196087 			*str++ = ' ';
2046635Sab196087 
2056635Sab196087 		(void) snprintf(str, sizeof (string),
2069085SAli.Bahrami@Sun.COM 		    MSG_ORIG(MSG_HEXDUMP_TOK), (int)*ldata);
2076635Sab196087 		str += 2;
2086635Sab196087 		sp_prefix = 1;
2096635Sab196087 
2106635Sab196087 		if (++byte == bytes_per_col) {
2116635Sab196087 			sp_prefix += 2;
2126635Sab196087 			word++;
2136635Sab196087 			byte = 0;
2146635Sab196087 		}
2156635Sab196087 		if (word == col_per_row) {
2166635Sab196087 			*str = '\0';
2176635Sab196087 			(void) snprintf(index, sizeof (index),
2186635Sab196087 			    MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx));
2196635Sab196087 			dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW),
2206635Sab196087 			    indent, MSG_ORIG(MSG_STR_EMPTY),
2216635Sab196087 			    index_width, index, string);
2226635Sab196087 			sp_prefix = 0;
2236635Sab196087 			word = 0;
2246635Sab196087 			ndx += bytes_per_row;
2256635Sab196087 			str = string;
2266635Sab196087 		}
2276635Sab196087 	}
2286635Sab196087 	if (byte || word) {
2296635Sab196087 		*str = '\0';	/*  */
2306635Sab196087 		(void) snprintf(index, sizeof (index),
2316635Sab196087 		    MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx));
2326635Sab196087 		dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW), indent,
2336635Sab196087 		    MSG_ORIG(MSG_STR_EMPTY), index_width, index, string);
2346635Sab196087 	}
2356635Sab196087 }
2366635Sab196087 
2376635Sab196087 /*
2384168Sab196087  * Convert the ASCII representation of an index, or index range, into
2394168Sab196087  * binary form, and store it in rec:
2404168Sab196087  *
2414168Sab196087  *	index: An positive or 0 valued integer
2424168Sab196087  *	range: Two indexes, separated by a ':' character, denoting
2434168Sab196087  *		a range of allowed values. If the second value is omitted,
2444168Sab196087  *		any values equal to or greater than the first will match.
2454168Sab196087  *
2464168Sab196087  * exit:
2475411Sab196087  *	On success, *rec is filled in with a MATCH_OPT_NDX or MATCH_OPT_RANGE
2484168Sab196087  *	value, and this function returns (1). On failure, the contents
2494168Sab196087  *	of *rec are undefined, and (0) is returned.
2504168Sab196087  */
2514168Sab196087 int
process_index_opt(const char * str,match_rec_t * rec)2525411Sab196087 process_index_opt(const char *str, match_rec_t *rec)
2534168Sab196087 {
2544168Sab196087 #define	SKIP_BLANK for (; *str && isspace(*str); str++)
2554168Sab196087 
2564168Sab196087 	char	*endptr;
2574168Sab196087 
2584168Sab196087 	rec->value.ndx.start = strtol(str, &endptr, 10);
2594168Sab196087 	/* Value must use some of the input, and be 0 or positive */
2604168Sab196087 	if ((str == endptr) || (rec->value.ndx.start < 0))
2614168Sab196087 		return (0);
2624168Sab196087 	str = endptr;
2634168Sab196087 
2644168Sab196087 	SKIP_BLANK;
2654168Sab196087 	if (*str != ':') {
2665411Sab196087 		rec->opt_type = MATCH_OPT_NDX;
2674168Sab196087 	} else {
2684168Sab196087 		str++;					/* Skip the ':' */
2695411Sab196087 		rec->opt_type = MATCH_OPT_RANGE;
2704168Sab196087 		SKIP_BLANK;
2714168Sab196087 		if (*str == '\0') {
2724168Sab196087 			rec->value.ndx.end = -1;	/* Indicates "to end" */
2734168Sab196087 		} else {
2744168Sab196087 			rec->value.ndx.end = strtol(str, &endptr, 10);
2754168Sab196087 			if ((str == endptr) || (rec->value.ndx.end < 0))
2764168Sab196087 				return (0);
2774168Sab196087 			str = endptr;
2784168Sab196087 			SKIP_BLANK;
2794168Sab196087 		}
2804168Sab196087 	}
2814168Sab196087 
2824168Sab196087 	/* Syntax error if anything is left over */
2834168Sab196087 	if (*str != '\0')
2844168Sab196087 		return (0);
2854168Sab196087 
2864168Sab196087 	return (1);
2874168Sab196087 
2884168Sab196087 #undef	SKIP_BLANK
2894168Sab196087 }
2904168Sab196087 
2914168Sab196087 /*
2929273SAli.Bahrami@Sun.COM  * Convert a string containing a specific type of ELF constant, or an ASCII
2939273SAli.Bahrami@Sun.COM  * representation of a number, to an integer. Strings starting with '0'
2945411Sab196087  * are taken to be octal, those staring with '0x' are hex, and all
2955411Sab196087  * others are decimal.
2965411Sab196087  *
2975411Sab196087  * entry:
2985411Sab196087  *	str - String to be converted
2999273SAli.Bahrami@Sun.COM  *	ctype - Constant type
3005411Sab196087  *	v - Address of variable to receive resulting value.
3015411Sab196087  *
3025411Sab196087  * exit:
3035411Sab196087  *	On success, returns True (1) and *v is set to the value.
3045411Sab196087  *	On failure, returns False (0) and *v is undefined.
3055411Sab196087  */
3069273SAli.Bahrami@Sun.COM typedef enum {
3079273SAli.Bahrami@Sun.COM 	ATOUI_PT,
3089273SAli.Bahrami@Sun.COM 	ATOUI_SHT,
3099273SAli.Bahrami@Sun.COM 	ATOUI_OSABI
3109273SAli.Bahrami@Sun.COM } atoui_type_t;
3119273SAli.Bahrami@Sun.COM 
3125411Sab196087 static int
atoui(const char * str,atoui_type_t type,uint32_t * v)3139273SAli.Bahrami@Sun.COM atoui(const char *str, atoui_type_t type, uint32_t *v)
3145411Sab196087 {
3159273SAli.Bahrami@Sun.COM 	conv_strtol_uvalue_t	uvalue;
3169273SAli.Bahrami@Sun.COM 	char			*endptr;
3175411Sab196087 
3189273SAli.Bahrami@Sun.COM 	if (conv_iter_strtol_init(str, &uvalue) != 0) {
3199273SAli.Bahrami@Sun.COM 		switch (type) {
3209273SAli.Bahrami@Sun.COM 		case ATOUI_PT:
3219273SAli.Bahrami@Sun.COM 			if (conv_iter_phdr_type(CONV_OSABI_ALL, CONV_FMT_ALT_CF,
3229273SAli.Bahrami@Sun.COM 			    conv_iter_strtol, &uvalue) == CONV_ITER_DONE)
3239273SAli.Bahrami@Sun.COM 				break;
3249273SAli.Bahrami@Sun.COM 			(void) conv_iter_phdr_type(CONV_OSABI_ALL,
3259273SAli.Bahrami@Sun.COM 			    CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue);
3269273SAli.Bahrami@Sun.COM 			break;
3279273SAli.Bahrami@Sun.COM 		case ATOUI_SHT:
3289273SAli.Bahrami@Sun.COM 			if (conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL,
3299273SAli.Bahrami@Sun.COM 			    CONV_FMT_ALT_CF, conv_iter_strtol, &uvalue) ==
3309273SAli.Bahrami@Sun.COM 			    CONV_ITER_DONE)
3319273SAli.Bahrami@Sun.COM 				break;
3329273SAli.Bahrami@Sun.COM 			(void) conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL,
3339273SAli.Bahrami@Sun.COM 			    CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue);
3349273SAli.Bahrami@Sun.COM 			break;
3359273SAli.Bahrami@Sun.COM 		case ATOUI_OSABI:
3369273SAli.Bahrami@Sun.COM 			if (conv_iter_ehdr_osabi(CONV_FMT_ALT_CF,
3379273SAli.Bahrami@Sun.COM 			    conv_iter_strtol, &uvalue) == CONV_ITER_DONE)
3389273SAli.Bahrami@Sun.COM 				break;
3399273SAli.Bahrami@Sun.COM 			(void) conv_iter_ehdr_osabi(CONV_FMT_ALT_NF,
3409273SAli.Bahrami@Sun.COM 			    conv_iter_strtol, &uvalue);
3419273SAli.Bahrami@Sun.COM 			break;
3429273SAli.Bahrami@Sun.COM 		}
3439273SAli.Bahrami@Sun.COM 		if (uvalue.csl_found) {
3449273SAli.Bahrami@Sun.COM 			*v = uvalue.csl_value;
3459273SAli.Bahrami@Sun.COM 			return (1);
3469273SAli.Bahrami@Sun.COM 		}
3479273SAli.Bahrami@Sun.COM 	}
3485411Sab196087 
3495411Sab196087 	*v = strtoull(str, &endptr, 0);
3505411Sab196087 
3515411Sab196087 	/* If the left over part contains anything but whitespace, fail */
3525411Sab196087 	for (; *endptr; endptr++)
3535411Sab196087 		if (!isspace(*endptr))
3545411Sab196087 			return (0);
3555411Sab196087 	return (1);
3565411Sab196087 }
3575411Sab196087 
3585411Sab196087 /*
3595411Sab196087  * Called after getopt() processing is finished if there is a non-empty
3605411Sab196087  * match list. Prepares the matching code for use.
3615411Sab196087  *
3625411Sab196087  * exit:
3635411Sab196087  *	Returns True (1) if no errors are encountered. Writes an
3645411Sab196087  *	error string to stderr and returns False (0) otherwise.
3655411Sab196087  */
3665411Sab196087 static int
match_prepare(char * argv0,uint_t flags)3675411Sab196087 match_prepare(char *argv0, uint_t flags)
3685411Sab196087 {
3695411Sab196087 	match_rec_t	*list;
3705411Sab196087 	const char	*str;
3715411Sab196087 	int		minus_p = (flags & FLG_SHOW_PHDR) != 0;
3729273SAli.Bahrami@Sun.COM 	atoui_type_t	atoui_type;
3735411Sab196087 
3745411Sab196087 	/*
3755411Sab196087 	 * Flag ambiguous attempt to use match option with both -p and
3765411Sab196087 	 * and one or more section SHOW options. In this case, we
3775411Sab196087 	 * can't tell what type of item we're supposed to match against.
3785411Sab196087 	 */
3795411Sab196087 	if (minus_p && (flags & FLG_MASK_SHOW_SHDR)) {
3805411Sab196087 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_AMBIG_MATCH),
3815411Sab196087 		    basename(argv0));
3825411Sab196087 		return (0);
3835411Sab196087 	}
3845411Sab196087 
3855411Sab196087 	/* Set the match type, based on the presence of the -p option */
3865411Sab196087 	if (minus_p) {
3875411Sab196087 		match_state.item_type = MATCH_ITEM_PT;
3889273SAli.Bahrami@Sun.COM 		atoui_type = ATOUI_PT;
3895411Sab196087 	} else {
3905411Sab196087 		match_state.item_type = MATCH_ITEM_SHT;
3919273SAli.Bahrami@Sun.COM 		atoui_type = ATOUI_SHT;
3925411Sab196087 	}
3935411Sab196087 
3945411Sab196087 	/*
3955411Sab196087 	 * Scan match list and perform any necessary fixups:
3965411Sab196087 	 *
3975411Sab196087 	 * MATCH_OPT_NAME: If -p is specified, convert MATCH_OPT_NAME (-N)
3985411Sab196087 	 *	requests into MATCH_OPT_TYPE (-T).
3995411Sab196087 	 *
4005411Sab196087 	 * MATCH_OPT_TYPE: Now that we know item type we are matching
4015411Sab196087 	 *	against, we can convert the string saved in the name
4025411Sab196087 	 *	field during getopt() processing into an integer and
4035411Sab196087 	 *	write it into the type field.
4045411Sab196087 	 */
4055411Sab196087 	for (list = match_state.list; list; list = list->next) {
4065411Sab196087 		if ((list->opt_type == MATCH_OPT_NAME) && minus_p)
4075411Sab196087 			list->opt_type = MATCH_OPT_TYPE;
4085411Sab196087 
4095411Sab196087 		if (list->opt_type != MATCH_OPT_TYPE)
4105411Sab196087 			continue;
4115411Sab196087 
4125411Sab196087 		str = list->value.name;
4139273SAli.Bahrami@Sun.COM 		if (atoui(str, atoui_type, &list->value.type) == 0) {
4145411Sab196087 			const char *fmt = minus_p ?
4155411Sab196087 			    MSG_INTL(MSG_ERR_BAD_T_PT) :
4165411Sab196087 			    MSG_INTL(MSG_ERR_BAD_T_SHT);
4175411Sab196087 
4185411Sab196087 			(void) fprintf(stderr, fmt, basename(argv0), str);
4195411Sab196087 			return (0);
4205411Sab196087 		}
4215411Sab196087 	}
4225411Sab196087 
4235411Sab196087 	return (1);
4245411Sab196087 }
4255411Sab196087 
4265411Sab196087 
4275411Sab196087 /*
4284168Sab196087  * Returns True (1) if the item with the given name or index should
4294168Sab196087  * be displayed, and False (0) if it should not be.
4304168Sab196087  *
4314168Sab196087  * entry:
4325411Sab196087  *	match_flags - Bitmask specifying matching options, as described
4335411Sab196087  *		in _elfdump.h.
4345411Sab196087  *	name - If MATCH_F_NAME flag is set, name of item under
4355411Sab196087  *		consideration. Otherwise ignored.
4364168Sab196087  *		should not be considered.
4375411Sab196087  *	ndx - If MATCH_F_NDX flag is set, index of item under consideration.
4385411Sab196087  *	type - If MATCH_F_TYPE is set, type of item under consideration.
4395411Sab196087  *		If MATCH_F_PHDR is set, this would be a program
4405411Sab196087  *		header type (PT_). Otherwise, a section header type (SHT_).
4414168Sab196087  *
4424168Sab196087  * exit:
4434168Sab196087  *	True will be returned if the given name/index matches those given
4445411Sab196087  *	by one of the (-I, -N -T) command line options, or if no such option
4455411Sab196087  *	was used in the command invocation and MATCH_F_STRICT is not
4465411Sab196087  *	set.
4474168Sab196087  */
4484168Sab196087 int
match(match_flags_t match_flags,const char * name,uint_t ndx,uint_t type)4495411Sab196087 match(match_flags_t match_flags, const char *name, uint_t ndx, uint_t type)
4504168Sab196087 {
4515411Sab196087 	match_item_t item_type = (match_flags & MATCH_F_PHDR) ?
4525411Sab196087 	    MATCH_ITEM_PT  : MATCH_ITEM_SHT;
4535411Sab196087 	match_rec_t *list;
4544168Sab196087 
4555411Sab196087 	/*
4565411Sab196087 	 * If there is no match list, then we use the MATCH_F_STRICT
4575411Sab196087 	 * flag to decide what to return. In the strict case, we return
4585411Sab196087 	 * False (0), in the normal case, True (1).
4595411Sab196087 	 */
4605411Sab196087 	if (match_state.list == NULL)
4615411Sab196087 		return ((match_flags & MATCH_F_STRICT) == 0);
4625411Sab196087 
4635411Sab196087 	/*
4645411Sab196087 	 * If item being checked is not the current match type,
4655411Sab196087 	 * then allow it.
4665411Sab196087 	 */
4675411Sab196087 	if (item_type != match_state.item_type)
4684168Sab196087 		return (1);
4694168Sab196087 
4704168Sab196087 	/* Run through the match records and check for a hit */
4715411Sab196087 	for (list = match_state.list; list; list = list->next) {
4725411Sab196087 		switch (list->opt_type) {
4735411Sab196087 		case MATCH_OPT_NAME:
4745411Sab196087 			if (((match_flags & MATCH_F_NAME) == 0) ||
4755411Sab196087 			    (name == NULL))
4765411Sab196087 				break;
4775411Sab196087 			if (strcmp(list->value.name, name) == 0)
4784168Sab196087 				return (1);
4794168Sab196087 			break;
4805411Sab196087 		case MATCH_OPT_NDX:
4815411Sab196087 			if ((match_flags & MATCH_F_NDX) &&
4825411Sab196087 			    (ndx == list->value.ndx.start))
4834168Sab196087 				return (1);
4844168Sab196087 			break;
4855411Sab196087 		case MATCH_OPT_RANGE:
4864168Sab196087 			/*
4874168Sab196087 			 * A range end value less than 0 means that any value
4884168Sab196087 			 * above the start is acceptible.
4894168Sab196087 			 */
4905411Sab196087 			if ((match_flags & MATCH_F_NDX) &&
4915411Sab196087 			    (ndx >= list->value.ndx.start) &&
4924168Sab196087 			    ((list->value.ndx.end < 0) ||
4934168Sab196087 			    (ndx <= list->value.ndx.end)))
4944168Sab196087 				return (1);
4954168Sab196087 			break;
4965411Sab196087 
4975411Sab196087 		case MATCH_OPT_TYPE:
4985411Sab196087 			if ((match_flags & MATCH_F_TYPE) &&
4995411Sab196087 			    (type == list->value.type))
5005411Sab196087 				return (1);
5015411Sab196087 			break;
5024168Sab196087 		}
5034168Sab196087 	}
5044168Sab196087 
5054168Sab196087 	/* Nothing matched */
5064168Sab196087 	return (0);
5074168Sab196087 }
5084168Sab196087 
5094168Sab196087 /*
5105411Sab196087  * Add an entry to match_state.list for use by match(). This routine is for
5115411Sab196087  * use during getopt() processing. It should not be called once
5125411Sab196087  * match_prepare() has been called.
5134168Sab196087  *
5144168Sab196087  * Return True (1) for success. On failure, an error is written
5154168Sab196087  * to stderr, and False (0) is returned.
5164168Sab196087  */
5174168Sab196087 static int
add_match_record(char * argv0,match_rec_t * data)5185411Sab196087 add_match_record(char *argv0, match_rec_t *data)
5194168Sab196087 {
5205411Sab196087 	match_rec_t	*rec;
5215411Sab196087 	match_rec_t	*list;
5224168Sab196087 
5234168Sab196087 	if ((rec = malloc(sizeof (*rec))) == NULL) {
5244168Sab196087 		int err = errno;
5254168Sab196087 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
5264168Sab196087 		    basename(argv0), strerror(err));
5274168Sab196087 		return (0);
5284168Sab196087 	}
5294168Sab196087 
5304168Sab196087 	*rec = *data;
5314168Sab196087 
5325411Sab196087 	/* Insert at end of match_state.list */
5335411Sab196087 	if (match_state.list == NULL) {
5345411Sab196087 		match_state.list = rec;
5354168Sab196087 	} else {
5365411Sab196087 		for (list = match_state.list; list->next != NULL;
5375411Sab196087 		    list = list->next)
5384168Sab196087 			;
5394168Sab196087 		list->next = rec;
5404168Sab196087 	}
5414168Sab196087 
5424168Sab196087 	rec->next = NULL;
5434168Sab196087 	return (1);
5441618Srie }
5451618Srie 
5465411Sab196087 static int
decide(const char * file,int fd,Elf * elf,uint_t flags,const char * wname,int wfd,uchar_t osabi)5475411Sab196087 decide(const char *file, int fd, Elf *elf, uint_t flags,
5489273SAli.Bahrami@Sun.COM     const char *wname, int wfd, uchar_t osabi)
5491618Srie {
5505411Sab196087 	int r;
5515411Sab196087 
5521618Srie 	if (gelf_getclass(elf) == ELFCLASS64)
5539273SAli.Bahrami@Sun.COM 		r = regular64(file, fd, elf, flags, wname, wfd, osabi);
5541618Srie 	else
5559273SAli.Bahrami@Sun.COM 		r = regular32(file, fd, elf, flags, wname, wfd, osabi);
5565411Sab196087 
5575411Sab196087 	return (r);
5581618Srie }
5591618Srie 
5605411Sab196087 static int
archive(const char * file,int fd,Elf * elf,uint_t flags,const char * wname,int wfd,uchar_t osabi)5615411Sab196087 archive(const char *file, int fd, Elf *elf, uint_t flags,
5629273SAli.Bahrami@Sun.COM     const char *wname, int wfd, uchar_t osabi)
5631618Srie {
5641618Srie 	Elf_Cmd		cmd = ELF_C_READ;
5651618Srie 	Elf_Arhdr	*arhdr;
5669085SAli.Bahrami@Sun.COM 	Elf		*_elf = NULL;
5671618Srie 	size_t		ptr;
5689085SAli.Bahrami@Sun.COM 	Elf_Arsym	*arsym = NULL;
5691618Srie 
5701618Srie 	/*
5713492Sab196087 	 * Determine if the archive symbol table itself is required.
5721618Srie 	 */
5735411Sab196087 	if ((flags & FLG_SHOW_SYMBOLS) &&
5745411Sab196087 	    match(MATCH_F_NAME, MSG_ORIG(MSG_ELF_ARSYM), 0, 0)) {
5751618Srie 		/*
5761618Srie 		 * Get the archive symbol table.
5771618Srie 		 */
5781618Srie 		if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) {
5791618Srie 			/*
5801618Srie 			 * The arsym could be 0 even though there was no error.
5811618Srie 			 * Print the error message only when there was
5821618Srie 			 * real error from elf_getarsym().
5831618Srie 			 */
5841618Srie 			failure(file, MSG_ORIG(MSG_ELF_GETARSYM));
5855411Sab196087 			return (0);
5861618Srie 		}
5871618Srie 	}
5881618Srie 
5891618Srie 	/*
5901618Srie 	 * Print the archive symbol table only when the archive symbol
5911618Srie 	 * table exists and it was requested to print.
5921618Srie 	 */
5931618Srie 	if (arsym) {
5941618Srie 		size_t		cnt;
5951618Srie 		char		index[MAXNDXSIZE];
5961618Srie 		size_t		offset = 0, _offset = 0;
597*12792SAli.Bahrami@Oracle.COM 		const char	*fmt_arsym1, *fmt_arsym2;
5981618Srie 
5991618Srie 		/*
600*12792SAli.Bahrami@Oracle.COM 		 * Print out all the symbol entries. The format width used
601*12792SAli.Bahrami@Oracle.COM 		 * corresponds to whether the archive symbol table is 32
602*12792SAli.Bahrami@Oracle.COM 		 * or 64-bit. We see them via Elf_Arhdr as size_t values
603*12792SAli.Bahrami@Oracle.COM 		 * in either case with no information loss (see the comments
604*12792SAli.Bahrami@Oracle.COM 		 * in libelf/getarsym.c) so this is done simply to improve
605*12792SAli.Bahrami@Oracle.COM 		 * the user presentation.
6061618Srie 		 */
607*12792SAli.Bahrami@Oracle.COM 		if (_elf_getarsymwordsize(elf) == 8) {
608*12792SAli.Bahrami@Oracle.COM 			dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_64));
609*12792SAli.Bahrami@Oracle.COM 			dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_64));
610*12792SAli.Bahrami@Oracle.COM 
611*12792SAli.Bahrami@Oracle.COM 			fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_64);
612*12792SAli.Bahrami@Oracle.COM 			fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_64);
613*12792SAli.Bahrami@Oracle.COM 		} else {
614*12792SAli.Bahrami@Oracle.COM 			dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_32));
615*12792SAli.Bahrami@Oracle.COM 			dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_32));
616*12792SAli.Bahrami@Oracle.COM 
617*12792SAli.Bahrami@Oracle.COM 			fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_32);
618*12792SAli.Bahrami@Oracle.COM 			fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_32);
619*12792SAli.Bahrami@Oracle.COM 		}
6201618Srie 
6211618Srie 		for (cnt = 0; cnt < ptr; cnt++, arsym++) {
6221618Srie 			/*
6231618Srie 			 * For each object obtain an elf descriptor so that we
6241618Srie 			 * can establish the members name.  Note, we have had
6251618Srie 			 * archives where the archive header has not been
6261618Srie 			 * obtainable so be lenient with errors.
6271618Srie 			 */
6281618Srie 			if ((offset == 0) || ((arsym->as_off != 0) &&
6291618Srie 			    (arsym->as_off != _offset))) {
6301618Srie 
6311618Srie 				if (_elf)
6321618Srie 					(void) elf_end(_elf);
6331618Srie 
6341618Srie 				if (elf_rand(elf, arsym->as_off) !=
6351618Srie 				    arsym->as_off) {
6361618Srie 					failure(file, MSG_ORIG(MSG_ELF_RAND));
6379085SAli.Bahrami@Sun.COM 					arhdr = NULL;
6381618Srie 				} else if ((_elf = elf_begin(fd,
6391618Srie 				    ELF_C_READ, elf)) == 0) {
6401618Srie 					failure(file, MSG_ORIG(MSG_ELF_BEGIN));
6419085SAli.Bahrami@Sun.COM 					arhdr = NULL;
6421618Srie 				} else if ((arhdr = elf_getarhdr(_elf)) == 0) {
6431618Srie 					failure(file,
6441618Srie 					    MSG_ORIG(MSG_ELF_GETARHDR));
6459085SAli.Bahrami@Sun.COM 					arhdr = NULL;
6461618Srie 				}
6471618Srie 
6481618Srie 				_offset = arsym->as_off;
6491618Srie 				if (offset == 0)
6501618Srie 					offset = _offset;
6511618Srie 			}
6521618Srie 
6531618Srie 			(void) snprintf(index, MAXNDXSIZE,
6541618Srie 			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt));
6551618Srie 			if (arsym->as_off)
656*12792SAli.Bahrami@Oracle.COM 				dbg_print(0, fmt_arsym1, index,
657*12792SAli.Bahrami@Oracle.COM 				    EC_XWORD(arsym->as_off),
658*12792SAli.Bahrami@Oracle.COM 				    arhdr ? arhdr->ar_name :
6591618Srie 				    MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ?
6601618Srie 				    demangle(arsym->as_name, flags) :
6611618Srie 				    MSG_INTL(MSG_STR_NULL)));
6621618Srie 			else
663*12792SAli.Bahrami@Oracle.COM 				dbg_print(0, fmt_arsym2, index,
664*12792SAli.Bahrami@Oracle.COM 				    EC_XWORD(arsym->as_off));
6651618Srie 		}
6661618Srie 
6671618Srie 		if (_elf)
6681618Srie 			(void) elf_end(_elf);
6691618Srie 
6701618Srie 		/*
6711618Srie 		 * If we only need the archive symbol table return.
6721618Srie 		 */
6735411Sab196087 		if ((flags & FLG_SHOW_SYMBOLS) &&
6745411Sab196087 		    match(MATCH_F_STRICT | MATCH_F_NAME,
6755411Sab196087 		    MSG_ORIG(MSG_ELF_ARSYM), -1, -1))
6765411Sab196087 			return (0);
6771618Srie 
6781618Srie 		/*
6791618Srie 		 * Reset elf descriptor in preparation for processing each
6801618Srie 		 * member.
6811618Srie 		 */
6821618Srie 		if (offset)
6831618Srie 			(void) elf_rand(elf, offset);
6841618Srie 	}
6851618Srie 
6861618Srie 	/*
6871618Srie 	 * Process each object within the archive.
6881618Srie 	 */
6891618Srie 	while ((_elf = elf_begin(fd, cmd, elf)) != NULL) {
6901618Srie 		char	name[MAXPATHLEN];
6911618Srie 
6921618Srie 		if ((arhdr = elf_getarhdr(_elf)) == NULL) {
6931618Srie 			failure(file, MSG_ORIG(MSG_ELF_GETARHDR));
6945411Sab196087 			return (0);
6951618Srie 		}
6961618Srie 		if (*arhdr->ar_name != '/') {
6971618Srie 			(void) snprintf(name, MAXPATHLEN,
6981618Srie 			    MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name);
6991618Srie 			dbg_print(0, MSG_ORIG(MSG_FMT_NLSTR), name);
7001618Srie 
7011618Srie 			switch (elf_kind(_elf)) {
7021618Srie 			case ELF_K_AR:
7035411Sab196087 				if (archive(name, fd, _elf, flags,
7049273SAli.Bahrami@Sun.COM 				    wname, wfd, osabi) == 1)
7055411Sab196087 					return (1);
7061618Srie 				break;
7071618Srie 			case ELF_K_ELF:
7085411Sab196087 				if (decide(name, fd, _elf, flags,
7099273SAli.Bahrami@Sun.COM 				    wname, wfd, osabi) == 1)
7105411Sab196087 					return (1);
7111618Srie 				break;
7121618Srie 			default:
7131618Srie 				(void) fprintf(stderr,
7141618Srie 				    MSG_INTL(MSG_ERR_BADFILE), name);
7151618Srie 				break;
7161618Srie 			}
7171618Srie 		}
7181618Srie 
7191618Srie 		cmd = elf_next(_elf);
7201618Srie 		(void) elf_end(_elf);
7211618Srie 	}
7225411Sab196087 
7235411Sab196087 	return (0);
7241618Srie }
7251618Srie 
7261618Srie int
main(int argc,char ** argv,char ** envp)7271618Srie main(int argc, char **argv, char **envp)
7281618Srie {
7291618Srie 	Elf		*elf;
7301618Srie 	int		var, fd, wfd = 0;
7315411Sab196087 	char		*wname = NULL;
7321618Srie 	uint_t		flags = 0;
7335411Sab196087 	match_rec_t	match_data;
7345411Sab196087 	int		ret;
7359273SAli.Bahrami@Sun.COM 	uchar_t		osabi;
7361618Srie 
7371618Srie 	/*
7381618Srie 	 * If we're on a 64-bit kernel, try to exec a full 64-bit version of
7391618Srie 	 * the binary.  If successful, conv_check_native() won't return.
7401618Srie 	 */
7412647Srie 	(void) conv_check_native(argv, envp);
7421618Srie 
7431618Srie 	/*
7441618Srie 	 * Establish locale.
7451618Srie 	 */
7461618Srie 	(void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY));
7471618Srie 	(void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS));
7481618Srie 
7491618Srie 	(void) setvbuf(stdout, NULL, _IOLBF, 0);
7501618Srie 	(void) setvbuf(stderr, NULL, _IOLBF, 0);
7511618Srie 
7521618Srie 	opterr = 0;
7531618Srie 	while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) {
7541618Srie 		switch (var) {
7551618Srie 		case 'C':
7565411Sab196087 			flags |= FLG_CTL_DEMANGLE;
7571618Srie 			break;
7581618Srie 		case 'c':
7595411Sab196087 			flags |= FLG_SHOW_SHDR;
7601618Srie 			break;
7611618Srie 		case 'd':
7625411Sab196087 			flags |= FLG_SHOW_DYNAMIC;
7631618Srie 			break;
7641618Srie 		case 'e':
7655411Sab196087 			flags |= FLG_SHOW_EHDR;
7661618Srie 			break;
7671618Srie 		case 'G':
7685411Sab196087 			flags |= FLG_SHOW_GOT;
7691618Srie 			break;
7701618Srie 		case 'g':
7715411Sab196087 			flags |= FLG_SHOW_GROUP;
7721618Srie 			break;
7731618Srie 		case 'H':
7745411Sab196087 			flags |= FLG_SHOW_CAP;
7751618Srie 			break;
7761618Srie 		case 'h':
7775411Sab196087 			flags |= FLG_SHOW_HASH;
7781618Srie 			break;
7794168Sab196087 		case 'I':
7805411Sab196087 			if (!process_index_opt(optarg, &match_data))
7815411Sab196087 				goto usage_brief;
7824168Sab196087 			if (!add_match_record(argv[0], &match_data))
7834168Sab196087 				return (1);
7845411Sab196087 			flags |= FLG_CTL_MATCH;
7854168Sab196087 			break;
7861618Srie 		case 'i':
7875411Sab196087 			flags |= FLG_SHOW_INTERP;
7881618Srie 			break;
7891618Srie 		case 'k':
7905411Sab196087 			flags |= FLG_CALC_CHECKSUM;
7911618Srie 			break;
7921618Srie 		case 'l':
7935411Sab196087 			flags |= FLG_CTL_LONGNAME;
7941618Srie 			break;
7951618Srie 		case 'm':
7965411Sab196087 			flags |= FLG_SHOW_MOVE;
7971618Srie 			break;
7981618Srie 		case 'N':
7995411Sab196087 			match_data.opt_type = MATCH_OPT_NAME;
8004168Sab196087 			match_data.value.name = optarg;
8014168Sab196087 			if (!add_match_record(argv[0], &match_data))
8024168Sab196087 				return (1);
8035411Sab196087 			flags |= FLG_CTL_MATCH;
8041618Srie 			break;
8051618Srie 		case 'n':
8065411Sab196087 			flags |= FLG_SHOW_NOTE;
8071618Srie 			break;
8089273SAli.Bahrami@Sun.COM 		case 'O':
8099273SAli.Bahrami@Sun.COM 			{
8109273SAli.Bahrami@Sun.COM 				uint32_t val;
8119273SAli.Bahrami@Sun.COM 
8129273SAli.Bahrami@Sun.COM 				/*
8139273SAli.Bahrami@Sun.COM 				 * osabi is a uchar_t in the ELF header.
8149273SAli.Bahrami@Sun.COM 				 * Don't accept any value that exceeds
8159273SAli.Bahrami@Sun.COM 				 * that range.
8169273SAli.Bahrami@Sun.COM 				 */
8179273SAli.Bahrami@Sun.COM 				if ((atoui(optarg, ATOUI_OSABI, &val) == 0) ||
8189273SAli.Bahrami@Sun.COM 				    (val > 255)) {
8199273SAli.Bahrami@Sun.COM 					(void) fprintf(stderr,
8209273SAli.Bahrami@Sun.COM 					    MSG_INTL(MSG_ERR_BAD_T_OSABI),
8219273SAli.Bahrami@Sun.COM 					    basename(argv[0]), optarg);
8229273SAli.Bahrami@Sun.COM 					return (1);
8239273SAli.Bahrami@Sun.COM 				}
8249273SAli.Bahrami@Sun.COM 				osabi = val;
8259273SAli.Bahrami@Sun.COM 			}
8269273SAli.Bahrami@Sun.COM 			flags |= FLG_CTL_OSABI;
8279273SAli.Bahrami@Sun.COM 			break;
8284665Sab196087 		case 'P':
8295411Sab196087 			flags |= FLG_CTL_FAKESHDR;
8304665Sab196087 			break;
8311618Srie 		case 'p':
8325411Sab196087 			flags |= FLG_SHOW_PHDR;
8331618Srie 			break;
8341618Srie 		case 'r':
8355411Sab196087 			flags |= FLG_SHOW_RELOC;
8361618Srie 			break;
8373492Sab196087 		case 'S':
8385411Sab196087 			flags |= FLG_SHOW_SORT;
8393492Sab196087 			break;
8401618Srie 		case 's':
8415411Sab196087 			flags |= FLG_SHOW_SYMBOLS;
8425411Sab196087 			break;
8435411Sab196087 		case 'T':
8445411Sab196087 			/*
8455411Sab196087 			 * We can't evaluate the value yet, because
8465411Sab196087 			 * we need to know if -p is used or not in
8475411Sab196087 			 * order to tell if we're seeing section header
8485411Sab196087 			 * or program header types. So, we save the
8495411Sab196087 			 * string in the name field, and then convert
8505411Sab196087 			 * it to a type integer in a following pass.
8515411Sab196087 			 */
8525411Sab196087 			match_data.opt_type = MATCH_OPT_TYPE;
8535411Sab196087 			match_data.value.name = optarg;
8545411Sab196087 			if (!add_match_record(argv[0], &match_data))
8555411Sab196087 				return (1);
8565411Sab196087 			flags |= FLG_CTL_MATCH;
8571618Srie 			break;
8581618Srie 		case 'u':
8595411Sab196087 			flags |= FLG_SHOW_UNWIND;
8601618Srie 			break;
8611618Srie 		case 'v':
8625411Sab196087 			flags |= FLG_SHOW_VERSIONS;
8631618Srie 			break;
8641618Srie 		case 'w':
8651618Srie 			wname = optarg;
8661618Srie 			break;
8671618Srie 		case 'y':
8685411Sab196087 			flags |= FLG_SHOW_SYMINFO;
8691618Srie 			break;
8701618Srie 		case '?':
8711618Srie 			(void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF),
8721618Srie 			    basename(argv[0]));
8731618Srie 			detail_usage();
8741618Srie 			return (1);
8751618Srie 		default:
8761618Srie 			break;
8771618Srie 		}
8781618Srie 	}
8791618Srie 
8805411Sab196087 	/* -p and -w are mutually exclusive. -w only works with sections */
8815411Sab196087 	if (((flags & FLG_SHOW_PHDR) != 0) && (wname != NULL))
8825411Sab196087 		goto usage_brief;
8835411Sab196087 
8845411Sab196087 	/* If a match argument is present, prepare the match state */
8855411Sab196087 	if ((match_state.list != NULL) && (match_prepare(argv[0], flags) == 0))
8865411Sab196087 		return (1);
8875411Sab196087 
8881618Srie 	/*
8895411Sab196087 	 * Decide what to do if no options specifying something to
8905411Sab196087 	 * show or do are present.
8915411Sab196087 	 *
8925411Sab196087 	 * If there is no -w and no match options, then we will set all
8935411Sab196087 	 * the show flags, causing a full display of everything in the
8945411Sab196087 	 * file that we know how to handle.
8955411Sab196087 	 *
8965411Sab196087 	 * Otherwise, if there is no match list, we generate a usage
8975411Sab196087 	 * error and quit.
8985411Sab196087 	 *
8995411Sab196087 	 * In the case where there is a match list, we go ahead and call
9005411Sab196087 	 * regular() anyway, leaving it to decide what to do. If -w is
9015411Sab196087 	 * present, regular() will use the match list to handle it.
9025411Sab196087 	 * In addition, in the absence of explicit show/calc flags, regular()
9035411Sab196087 	 * will compare the section headers to the match list and use
9045411Sab196087 	 * that to generate the FLG_ bits that will display the information
9055411Sab196087 	 * specified by the match list.
9061618Srie 	 */
9075411Sab196087 	if ((flags & ~FLG_MASK_CTL) == 0) {
9085411Sab196087 		if (!wname && (match_state.list == NULL))
9095411Sab196087 			flags |= FLG_MASK_SHOW;
9105411Sab196087 		else if (match_state.list == NULL)
9115411Sab196087 			goto usage_brief;
9121618Srie 	}
9131618Srie 
9145411Sab196087 	/* There needs to be at least 1 filename left following the options */
9155411Sab196087 	if ((var = argc - optind) == 0)
9165411Sab196087 		goto usage_brief;
9171618Srie 
9181618Srie 	/*
9191618Srie 	 * If the -l/-C option is specified, set up the liblddbg.so.
9201618Srie 	 */
9215411Sab196087 	if (flags & FLG_CTL_LONGNAME)
9221618Srie 		dbg_desc->d_extra |= DBG_E_LONG;
9235411Sab196087 	if (flags & FLG_CTL_DEMANGLE)
9241618Srie 		dbg_desc->d_extra |= DBG_E_DEMANGLE;
9251618Srie 
9261618Srie 	/*
9271618Srie 	 * If the -w option has indicated an output file open it.  It's
9281618Srie 	 * arguable whether this option has much use when multiple files are
9291618Srie 	 * being processed.
9305411Sab196087 	 *
9315411Sab196087 	 * If wname is non-NULL, we know that -p was not specified, due
9325411Sab196087 	 * to the test above.
9331618Srie 	 */
9341618Srie 	if (wname) {
9351618Srie 		if ((wfd = open(wname, (O_RDWR | O_CREAT | O_TRUNC),
9361618Srie 		    0666)) < 0) {
9371618Srie 			int err = errno;
9381618Srie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN),
9391618Srie 			    wname, strerror(err));
9405411Sab196087 			return (1);
9411618Srie 		}
9421618Srie 	}
9431618Srie 
9441618Srie 	/*
9455411Sab196087 	 * Open the input file, initialize the elf interface, and
9465411Sab196087 	 * process it.
9471618Srie 	 */
9485411Sab196087 	ret = 0;
9495411Sab196087 	for (; (optind < argc) && (ret == 0); optind++) {
9501618Srie 		const char	*file = argv[optind];
9511618Srie 
9521618Srie 		if ((fd = open(argv[optind], O_RDONLY)) == -1) {
9531618Srie 			int err = errno;
9541618Srie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN),
9551618Srie 			    file, strerror(err));
9561618Srie 			continue;
9571618Srie 		}
9581618Srie 		(void) elf_version(EV_CURRENT);
9591618Srie 		if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
9601618Srie 			failure(file, MSG_ORIG(MSG_ELF_BEGIN));
9611618Srie 			(void) close(fd);
9621618Srie 			continue;
9631618Srie 		}
9641618Srie 
9651618Srie 		if (var > 1)
9661618Srie 			dbg_print(0, MSG_ORIG(MSG_FMT_NLSTRNL), file);
9671618Srie 
9681618Srie 		switch (elf_kind(elf)) {
9691618Srie 		case ELF_K_AR:
9709273SAli.Bahrami@Sun.COM 			ret = archive(file, fd, elf, flags, wname, wfd, osabi);
9711618Srie 			break;
9721618Srie 		case ELF_K_ELF:
9739273SAli.Bahrami@Sun.COM 			ret = decide(file, fd, elf, flags, wname, wfd, osabi);
9741618Srie 			break;
9751618Srie 		default:
9761618Srie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADFILE), file);
9771618Srie 			break;
9781618Srie 		}
9791618Srie 
9801618Srie 		(void) close(fd);
9811618Srie 		(void) elf_end(elf);
9821618Srie 	}
9831618Srie 
9841618Srie 	if (wfd)
9851618Srie 		(void) close(wfd);
9865411Sab196087 	return (ret);
9875411Sab196087 
9885411Sab196087 usage_brief:
9895411Sab196087 	/* Control comes here for a simple usage message and exit */
9905411Sab196087 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF),
9915411Sab196087 	    basename(argv[0]));
9925411Sab196087 	return (1);
9935411Sab196087 
9941618Srie }
995