Home | History | Annotate | Download | only in common
      1  1618       rie /*
      2  1618       rie  * CDDL HEADER START
      3  1618       rie  *
      4  1618       rie  * The contents of this file are subject to the terms of the
      5  1618       rie  * Common Development and Distribution License (the "License").
      6  1618       rie  * You may not use this file except in compliance with the License.
      7  1618       rie  *
      8  1618       rie  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  1618       rie  * or http://www.opensolaris.org/os/licensing.
     10  1618       rie  * See the License for the specific language governing permissions
     11  1618       rie  * and limitations under the License.
     12  1618       rie  *
     13  1618       rie  * When distributing Covered Code, include this CDDL HEADER in each
     14  1618       rie  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  1618       rie  * If applicable, add the following below this CDDL HEADER, with the
     16  1618       rie  * fields enclosed by brackets "[]" replaced with your own identifying
     17  1618       rie  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  1618       rie  *
     19  1618       rie  * CDDL HEADER END
     20  1618       rie  */
     21  1618       rie 
     22  1618       rie /*
     23  9085       Ali  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  1618       rie  * Use is subject to license terms.
     25  1618       rie  */
     26  1618       rie 
     27  1618       rie /*
     28  1618       rie  * Dump an elf file.
     29  1618       rie  */
     30  1618       rie #include	<sys/param.h>
     31  1618       rie #include	<fcntl.h>
     32  1618       rie #include	<stdio.h>
     33  4168  ab196087 #include	<stdlib.h>
     34  4168  ab196087 #include	<ctype.h>
     35  1618       rie #include	<libelf.h>
     36  1618       rie #include	<link.h>
     37  1618       rie #include	<stdarg.h>
     38  1618       rie #include	<unistd.h>
     39  1618       rie #include	<libgen.h>
     40  1618       rie #include	<libintl.h>
     41  1618       rie #include	<locale.h>
     42  1618       rie #include	<errno.h>
     43  1618       rie #include	<strings.h>
     44  1618       rie #include	<debug.h>
     45  1618       rie #include	<conv.h>
     46  1618       rie #include	<msg.h>
     47  1618       rie #include	<_elfdump.h>
     48  5411  ab196087 #include	<sys/elf_SPARC.h>
     49  5411  ab196087 #include	<sys/elf_amd64.h>
     50  5411  ab196087 
     51  1618       rie 
     52  4063  ab196087 const Cache	cache_init = {NULL, NULL, NULL, NULL, 0};
     53  4168  ab196087 
     54  4168  ab196087 
     55  4168  ab196087 
     56  5411  ab196087 /*
     57  5411  ab196087  * The -I, -N, and -T options are called "match options", because
     58  5411  ab196087  * they allow selecting the items to be displayed based on matching
     59  5411  ab196087  * their index, name, or type.
     60  5411  ab196087  *
     61  5411  ab196087  * The ELF information to which -I, -N, or -T are applied in
     62  5411  ab196087  * the current invocation is called the "match item".
     63  5411  ab196087  */
     64  4168  ab196087 typedef enum {
     65  5411  ab196087 	MATCH_ITEM_PT,		/* Program header (PT_) */
     66  5411  ab196087 	MATCH_ITEM_SHT		/* Section header (SHT_) */
     67  5411  ab196087 } match_item_t;
     68  5411  ab196087 
     69  5411  ab196087 /* match_opt_t is  used to note which match option was used */
     70  5411  ab196087 typedef enum {
     71  5411  ab196087 	MATCH_OPT_NAME,		/* Record contains a name */
     72  5411  ab196087 	MATCH_OPT_NDX,		/* Record contains a single index */
     73  5411  ab196087 	MATCH_OPT_RANGE,	/* Record contains an index range */
     74  5411  ab196087 	MATCH_OPT_TYPE,		/* Record contains a type (shdr or phdr) */
     75  5411  ab196087 } match_opt_t;
     76  4168  ab196087 
     77  4168  ab196087 typedef struct _match {
     78  4168  ab196087 	struct _match	*next;		/* Pointer to next item in list */
     79  5411  ab196087 	match_opt_t	opt_type;
     80  4168  ab196087 	union {
     81  5411  ab196087 		const char	*name;	/* MATCH_OPT_NAME */
     82  5411  ab196087 		struct {		/* MATCH_OPT_NDX and MATCH_OPT_RANGE */
     83  4168  ab196087 			int	start;
     84  5411  ab196087 			int	end;	/* Only for MATCH_OPT_RANGE */
     85  4168  ab196087 		} ndx;
     86  5411  ab196087 		uint32_t	type;	/* MATCH_OPT_TYPE */
     87  4168  ab196087 	} value;
     88  5411  ab196087 } match_rec_t;
     89  4168  ab196087 
     90  5411  ab196087 static struct {
     91  5411  ab196087 	match_item_t	item_type;	/* Type of item being matched */
     92  5411  ab196087 	match_rec_t	*list;		/* Records for (-I, -N, -T) options */
     93  5411  ab196087 } match_state;
     94  5411  ab196087 
     95  5411  ab196087 
     96  1618       rie 
     97  1618       rie const char *
     98  1618       rie _elfdump_msg(Msg mid)
     99  1618       rie {
    100  1618       rie 	return (gettext(MSG_ORIG(mid)));
    101  1618       rie }
    102  1618       rie 
    103  1618       rie /*
    104  1618       rie  * Determine whether a symbol name should be demangled.
    105  1618       rie  */
    106  1618       rie const char *
    107  1618       rie demangle(const char *name, uint_t flags)
    108  1618       rie {
    109  5411  ab196087 	if (flags & FLG_CTL_DEMANGLE)
    110  1618       rie 		return (Elf_demangle_name(name));
    111  1618       rie 	else
    112  1618       rie 		return ((char *)name);
    113  1618       rie }
    114  1618       rie 
    115  1618       rie /*
    116  1618       rie  * Define our own standard error routine.
    117  1618       rie  */
    118  1618       rie void
    119  1618       rie failure(const char *file, const char *func)
    120  1618       rie {
    121  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_ERR_FAILURE),
    122  1618       rie 	    file, func, elf_errmsg(elf_errno()));
    123  1618       rie }
    124  1618       rie 
    125  1618       rie /*
    126  1618       rie  * The full usage message
    127  1618       rie  */
    128  1618       rie static void
    129  1618       rie detail_usage()
    130  1618       rie {
    131  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL1));
    132  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL2));
    133  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL3));
    134  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL4));
    135  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL5));
    136  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL6));
    137  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL7));
    138  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL8));
    139  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9));
    140  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL10));
    141  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL11));
    142  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL12));
    143  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL13));
    144  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL14));
    145  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL15));
    146  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL16));
    147  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL17));
    148  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL18));
    149  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL19));
    150  1618       rie 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL20));
    151  3492  ab196087 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL21));
    152  4168  ab196087 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL22));
    153  4168  ab196087 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL23));
    154  4665  ab196087 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL24));
    155  5411  ab196087 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL25));
    156  9273       Ali 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL26));
    157  6635  ab196087 }
    158  6635  ab196087 
    159  6635  ab196087 /*
    160  6635  ab196087  * Output a block of raw data as hex bytes. Each row is given
    161  6635  ab196087  * the index of the first byte in the row.
    162  6635  ab196087  *
    163  6635  ab196087  * entry:
    164  6635  ab196087  *	data - Pointer to first byte of data to be displayed
    165  6635  ab196087  *	n - # of bytes of data
    166  6635  ab196087  *	prefix - String to be output before each line. Useful
    167  6635  ab196087  *		for indenting output.
    168  6635  ab196087  *	bytes_per_col - # of space separated bytes to output
    169  6635  ab196087  *		in each column.
    170  6635  ab196087  *	col_per_row - # of columns to output per row
    171  6635  ab196087  *
    172  6635  ab196087  * exit:
    173  6635  ab196087  *	The formatted data has been sent to stdout. Each row of output
    174  6635  ab196087  *	shows (bytes_per_col * col_per_row) bytes of data.
    175  6635  ab196087  */
    176  6635  ab196087 void
    177  9085       Ali dump_hex_bytes(const void *data, size_t n, int indent,
    178  6635  ab196087 	int bytes_per_col, int col_per_row)
    179  6635  ab196087 {
    180  9085       Ali 	const uchar_t *ldata = data;
    181  6635  ab196087 	int	bytes_per_row = bytes_per_col * col_per_row;
    182  6635  ab196087 	int	ndx, byte, word;
    183  6635  ab196087 	char	string[128], *str = string;
    184  6635  ab196087 	char	index[MAXNDXSIZE];
    185  6635  ab196087 	int	index_width;
    186  6635  ab196087 	int	sp_prefix = 0;
    187  6635  ab196087 
    188  6635  ab196087 
    189  6635  ab196087 	/*
    190  6635  ab196087 	 * Determine the width to use for the index string. We follow
    191  6635  ab196087 	 * 8-byte tab rules, but don't use an actual \t character so
    192  6635  ab196087 	 * that the output can be arbitrarily shifted without odd
    193  6635  ab196087 	 * tab effects, and so that all the columns line up no matter
    194  6635  ab196087 	 * how many lines of output are produced.
    195  6635  ab196087 	 */
    196  6635  ab196087 	ndx = n / bytes_per_row;
    197  6635  ab196087 	(void) snprintf(index, sizeof (index),
    198  6635  ab196087 	    MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx));
    199  6635  ab196087 	index_width = strlen(index);
    200  6635  ab196087 	index_width = S_ROUND(index_width, 8);
    201  6635  ab196087 
    202  9085       Ali 	for (ndx = byte = word = 0; n > 0; n--, ldata++) {
    203  6635  ab196087 		while (sp_prefix-- > 0)
    204  6635  ab196087 			*str++ = ' ';
    205  6635  ab196087 
    206  6635  ab196087 		(void) snprintf(str, sizeof (string),
    207  9085       Ali 		    MSG_ORIG(MSG_HEXDUMP_TOK), (int)*ldata);
    208  6635  ab196087 		str += 2;
    209  6635  ab196087 		sp_prefix = 1;
    210  6635  ab196087 
    211  6635  ab196087 		if (++byte == bytes_per_col) {
    212  6635  ab196087 			sp_prefix += 2;
    213  6635  ab196087 			word++;
    214  6635  ab196087 			byte = 0;
    215  6635  ab196087 		}
    216  6635  ab196087 		if (word == col_per_row) {
    217  6635  ab196087 			*str = '\0';
    218  6635  ab196087 			(void) snprintf(index, sizeof (index),
    219  6635  ab196087 			    MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx));
    220  6635  ab196087 			dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW),
    221  6635  ab196087 			    indent, MSG_ORIG(MSG_STR_EMPTY),
    222  6635  ab196087 			    index_width, index, string);
    223  6635  ab196087 			sp_prefix = 0;
    224  6635  ab196087 			word = 0;
    225  6635  ab196087 			ndx += bytes_per_row;
    226  6635  ab196087 			str = string;
    227  6635  ab196087 		}
    228  6635  ab196087 	}
    229  6635  ab196087 	if (byte || word) {
    230  6635  ab196087 		*str = '\0';	/*  */
    231  6635  ab196087 		(void) snprintf(index, sizeof (index),
    232  6635  ab196087 		    MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx));
    233  6635  ab196087 		dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW), indent,
    234  6635  ab196087 		    MSG_ORIG(MSG_STR_EMPTY), index_width, index, string);
    235  6635  ab196087 	}
    236  4168  ab196087 }
    237  4168  ab196087 
    238  4168  ab196087 /*
    239  4168  ab196087  * Convert the ASCII representation of an index, or index range, into
    240  4168  ab196087  * binary form, and store it in rec:
    241  4168  ab196087  *
    242  4168  ab196087  *	index: An positive or 0 valued integer
    243  4168  ab196087  *	range: Two indexes, separated by a ':' character, denoting
    244  4168  ab196087  *		a range of allowed values. If the second value is omitted,
    245  4168  ab196087  *		any values equal to or greater than the first will match.
    246  4168  ab196087  *
    247  4168  ab196087  * exit:
    248  5411  ab196087  *	On success, *rec is filled in with a MATCH_OPT_NDX or MATCH_OPT_RANGE
    249  4168  ab196087  *	value, and this function returns (1). On failure, the contents
    250  4168  ab196087  *	of *rec are undefined, and (0) is returned.
    251  4168  ab196087  */
    252  4168  ab196087 int
    253  5411  ab196087 process_index_opt(const char *str, match_rec_t *rec)
    254  4168  ab196087 {
    255  4168  ab196087 #define	SKIP_BLANK for (; *str && isspace(*str); str++)
    256  4168  ab196087 
    257  4168  ab196087 	char	*endptr;
    258  4168  ab196087 
    259  4168  ab196087 	rec->value.ndx.start = strtol(str, &endptr, 10);
    260  4168  ab196087 	/* Value must use some of the input, and be 0 or positive */
    261  4168  ab196087 	if ((str == endptr) || (rec->value.ndx.start < 0))
    262  4168  ab196087 		return (0);
    263  4168  ab196087 	str = endptr;
    264  4168  ab196087 
    265  4168  ab196087 	SKIP_BLANK;
    266  4168  ab196087 	if (*str != ':') {
    267  5411  ab196087 		rec->opt_type = MATCH_OPT_NDX;
    268  4168  ab196087 	} else {
    269  4168  ab196087 		str++;					/* Skip the ':' */
    270  5411  ab196087 		rec->opt_type = MATCH_OPT_RANGE;
    271  4168  ab196087 		SKIP_BLANK;
    272  4168  ab196087 		if (*str == '\0') {
    273  4168  ab196087 			rec->value.ndx.end = -1;	/* Indicates "to end" */
    274  4168  ab196087 		} else {
    275  4168  ab196087 			rec->value.ndx.end = strtol(str, &endptr, 10);
    276  4168  ab196087 			if ((str == endptr) || (rec->value.ndx.end < 0))
    277  4168  ab196087 				return (0);
    278  4168  ab196087 			str = endptr;
    279  4168  ab196087 			SKIP_BLANK;
    280  4168  ab196087 		}
    281  4168  ab196087 	}
    282  4168  ab196087 
    283  4168  ab196087 	/* Syntax error if anything is left over */
    284  4168  ab196087 	if (*str != '\0')
    285  4168  ab196087 		return (0);
    286  4168  ab196087 
    287  4168  ab196087 	return (1);
    288  4168  ab196087 
    289  4168  ab196087 #undef	SKIP_BLANK
    290  4168  ab196087 }
    291  4168  ab196087 
    292  4168  ab196087 /*
    293  9273       Ali  * Convert a string containing a specific type of ELF constant, or an ASCII
    294  9273       Ali  * representation of a number, to an integer. Strings starting with '0'
    295  5411  ab196087  * are taken to be octal, those staring with '0x' are hex, and all
    296  5411  ab196087  * others are decimal.
    297  5411  ab196087  *
    298  5411  ab196087  * entry:
    299  5411  ab196087  *	str - String to be converted
    300  9273       Ali  *	ctype - Constant type
    301  5411  ab196087  *	v - Address of variable to receive resulting value.
    302  5411  ab196087  *
    303  5411  ab196087  * exit:
    304  5411  ab196087  *	On success, returns True (1) and *v is set to the value.
    305  5411  ab196087  *	On failure, returns False (0) and *v is undefined.
    306  5411  ab196087  */
    307  9273       Ali typedef enum {
    308  9273       Ali 	ATOUI_PT,
    309  9273       Ali 	ATOUI_SHT,
    310  9273       Ali 	ATOUI_OSABI
    311  9273       Ali } atoui_type_t;
    312  9273       Ali 
    313  5411  ab196087 static int
    314  9273       Ali atoui(const char *str, atoui_type_t type, uint32_t *v)
    315  5411  ab196087 {
    316  9273       Ali 	conv_strtol_uvalue_t	uvalue;
    317  9273       Ali 	char			*endptr;
    318  5411  ab196087 
    319  9273       Ali 	if (conv_iter_strtol_init(str, &uvalue) != 0) {
    320  9273       Ali 		switch (type) {
    321  9273       Ali 		case ATOUI_PT:
    322  9273       Ali 			if (conv_iter_phdr_type(CONV_OSABI_ALL, CONV_FMT_ALT_CF,
    323  9273       Ali 			    conv_iter_strtol, &uvalue) == CONV_ITER_DONE)
    324  9273       Ali 				break;
    325  9273       Ali 			(void) conv_iter_phdr_type(CONV_OSABI_ALL,
    326  9273       Ali 			    CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue);
    327  9273       Ali 			break;
    328  9273       Ali 		case ATOUI_SHT:
    329  9273       Ali 			if (conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL,
    330  9273       Ali 			    CONV_FMT_ALT_CF, conv_iter_strtol, &uvalue) ==
    331  9273       Ali 			    CONV_ITER_DONE)
    332  9273       Ali 				break;
    333  9273       Ali 			(void) conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL,
    334  9273       Ali 			    CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue);
    335  9273       Ali 			break;
    336  9273       Ali 		case ATOUI_OSABI:
    337  9273       Ali 			if (conv_iter_ehdr_osabi(CONV_FMT_ALT_CF,
    338  9273       Ali 			    conv_iter_strtol, &uvalue) == CONV_ITER_DONE)
    339  9273       Ali 				break;
    340  9273       Ali 			(void) conv_iter_ehdr_osabi(CONV_FMT_ALT_NF,
    341  9273       Ali 			    conv_iter_strtol, &uvalue);
    342  9273       Ali 			break;
    343  9273       Ali 		}
    344  9273       Ali 		if (uvalue.csl_found) {
    345  9273       Ali 			*v = uvalue.csl_value;
    346  9273       Ali 			return (1);
    347  9273       Ali 		}
    348  9273       Ali 	}
    349  5411  ab196087 
    350  5411  ab196087 	*v = strtoull(str, &endptr, 0);
    351  5411  ab196087 
    352  5411  ab196087 	/* If the left over part contains anything but whitespace, fail */
    353  5411  ab196087 	for (; *endptr; endptr++)
    354  5411  ab196087 		if (!isspace(*endptr))
    355  5411  ab196087 			return (0);
    356  5411  ab196087 	return (1);
    357  5411  ab196087 }
    358  5411  ab196087 
    359  5411  ab196087 /*
    360  5411  ab196087  * Called after getopt() processing is finished if there is a non-empty
    361  5411  ab196087  * match list. Prepares the matching code for use.
    362  5411  ab196087  *
    363  5411  ab196087  * exit:
    364  5411  ab196087  *	Returns True (1) if no errors are encountered. Writes an
    365  5411  ab196087  *	error string to stderr and returns False (0) otherwise.
    366  5411  ab196087  */
    367  5411  ab196087 static int
    368  5411  ab196087 match_prepare(char *argv0, uint_t flags)
    369  5411  ab196087 {
    370  5411  ab196087 	match_rec_t	*list;
    371  5411  ab196087 	const char	*str;
    372  5411  ab196087 	int		minus_p = (flags & FLG_SHOW_PHDR) != 0;
    373  9273       Ali 	atoui_type_t	atoui_type;
    374  5411  ab196087 
    375  5411  ab196087 	/*
    376  5411  ab196087 	 * Flag ambiguous attempt to use match option with both -p and
    377  5411  ab196087 	 * and one or more section SHOW options. In this case, we
    378  5411  ab196087 	 * can't tell what type of item we're supposed to match against.
    379  5411  ab196087 	 */
    380  5411  ab196087 	if (minus_p && (flags & FLG_MASK_SHOW_SHDR)) {
    381  5411  ab196087 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_AMBIG_MATCH),
    382  5411  ab196087 		    basename(argv0));
    383  5411  ab196087 		return (0);
    384  5411  ab196087 	}
    385  5411  ab196087 
    386  5411  ab196087 	/* Set the match type, based on the presence of the -p option */
    387  5411  ab196087 	if (minus_p) {
    388  5411  ab196087 		match_state.item_type = MATCH_ITEM_PT;
    389  9273       Ali 		atoui_type = ATOUI_PT;
    390  5411  ab196087 	} else {
    391  5411  ab196087 		match_state.item_type = MATCH_ITEM_SHT;
    392  9273       Ali 		atoui_type = ATOUI_SHT;
    393  5411  ab196087 	}
    394  5411  ab196087 
    395  5411  ab196087 	/*
    396  5411  ab196087 	 * Scan match list and perform any necessary fixups:
    397  5411  ab196087 	 *
    398  5411  ab196087 	 * MATCH_OPT_NAME: If -p is specified, convert MATCH_OPT_NAME (-N)
    399  5411  ab196087 	 *	requests into MATCH_OPT_TYPE (-T).
    400  5411  ab196087 	 *
    401  5411  ab196087 	 * MATCH_OPT_TYPE: Now that we know item type we are matching
    402  5411  ab196087 	 *	against, we can convert the string saved in the name
    403  5411  ab196087 	 *	field during getopt() processing into an integer and
    404  5411  ab196087 	 *	write it into the type field.
    405  5411  ab196087 	 */
    406  5411  ab196087 	for (list = match_state.list; list; list = list->next) {
    407  5411  ab196087 		if ((list->opt_type == MATCH_OPT_NAME) && minus_p)
    408  5411  ab196087 			list->opt_type = MATCH_OPT_TYPE;
    409  5411  ab196087 
    410  5411  ab196087 		if (list->opt_type != MATCH_OPT_TYPE)
    411  5411  ab196087 			continue;
    412  5411  ab196087 
    413  5411  ab196087 		str = list->value.name;
    414  9273       Ali 		if (atoui(str, atoui_type, &list->value.type) == 0) {
    415  5411  ab196087 			const char *fmt = minus_p ?
    416  5411  ab196087 			    MSG_INTL(MSG_ERR_BAD_T_PT) :
    417  5411  ab196087 			    MSG_INTL(MSG_ERR_BAD_T_SHT);
    418  5411  ab196087 
    419  5411  ab196087 			(void) fprintf(stderr, fmt, basename(argv0), str);
    420  5411  ab196087 			return (0);
    421  5411  ab196087 		}
    422  5411  ab196087 	}
    423  5411  ab196087 
    424  5411  ab196087 	return (1);
    425  5411  ab196087 }
    426  5411  ab196087 
    427  5411  ab196087 
    428  5411  ab196087 /*
    429  4168  ab196087  * Returns True (1) if the item with the given name or index should
    430  4168  ab196087  * be displayed, and False (0) if it should not be.
    431  4168  ab196087  *
    432  4168  ab196087  * entry:
    433  5411  ab196087  *	match_flags - Bitmask specifying matching options, as described
    434  5411  ab196087  *		in _elfdump.h.
    435  5411  ab196087  *	name - If MATCH_F_NAME flag is set, name of item under
    436  5411  ab196087  *		consideration. Otherwise ignored.
    437  4168  ab196087  *		should not be considered.
    438  5411  ab196087  *	ndx - If MATCH_F_NDX flag is set, index of item under consideration.
    439  5411  ab196087  *	type - If MATCH_F_TYPE is set, type of item under consideration.
    440  5411  ab196087  *		If MATCH_F_PHDR is set, this would be a program
    441  5411  ab196087  *		header type (PT_). Otherwise, a section header type (SHT_).
    442  4168  ab196087  *
    443  4168  ab196087  * exit:
    444  4168  ab196087  *	True will be returned if the given name/index matches those given
    445  5411  ab196087  *	by one of the (-I, -N -T) command line options, or if no such option
    446  5411  ab196087  *	was used in the command invocation and MATCH_F_STRICT is not
    447  5411  ab196087  *	set.
    448  4168  ab196087  */
    449  4168  ab196087 int
    450  5411  ab196087 match(match_flags_t match_flags, const char *name, uint_t ndx, uint_t type)
    451  4168  ab196087 {
    452  5411  ab196087 	match_item_t item_type = (match_flags & MATCH_F_PHDR) ?
    453  5411  ab196087 	    MATCH_ITEM_PT  : MATCH_ITEM_SHT;
    454  5411  ab196087 	match_rec_t *list;
    455  4168  ab196087 
    456  5411  ab196087 	/*
    457  5411  ab196087 	 * If there is no match list, then we use the MATCH_F_STRICT
    458  5411  ab196087 	 * flag to decide what to return. In the strict case, we return
    459  5411  ab196087 	 * False (0), in the normal case, True (1).
    460  5411  ab196087 	 */
    461  5411  ab196087 	if (match_state.list == NULL)
    462  5411  ab196087 		return ((match_flags & MATCH_F_STRICT) == 0);
    463  5411  ab196087 
    464  5411  ab196087 	/*
    465  5411  ab196087 	 * If item being checked is not the current match type,
    466  5411  ab196087 	 * then allow it.
    467  5411  ab196087 	 */
    468  5411  ab196087 	if (item_type != match_state.item_type)
    469  4168  ab196087 		return (1);
    470  4168  ab196087 
    471  4168  ab196087 	/* Run through the match records and check for a hit */
    472  5411  ab196087 	for (list = match_state.list; list; list = list->next) {
    473  5411  ab196087 		switch (list->opt_type) {
    474  5411  ab196087 		case MATCH_OPT_NAME:
    475  5411  ab196087 			if (((match_flags & MATCH_F_NAME) == 0) ||
    476  5411  ab196087 			    (name == NULL))
    477  5411  ab196087 				break;
    478  5411  ab196087 			if (strcmp(list->value.name, name) == 0)
    479  4168  ab196087 				return (1);
    480  4168  ab196087 			break;
    481  5411  ab196087 		case MATCH_OPT_NDX:
    482  5411  ab196087 			if ((match_flags & MATCH_F_NDX) &&
    483  5411  ab196087 			    (ndx == list->value.ndx.start))
    484  4168  ab196087 				return (1);
    485  4168  ab196087 			break;
    486  5411  ab196087 		case MATCH_OPT_RANGE:
    487  4168  ab196087 			/*
    488  4168  ab196087 			 * A range end value less than 0 means that any value
    489  4168  ab196087 			 * above the start is acceptible.
    490  4168  ab196087 			 */
    491  5411  ab196087 			if ((match_flags & MATCH_F_NDX) &&
    492  5411  ab196087 			    (ndx >= list->value.ndx.start) &&
    493  4168  ab196087 			    ((list->value.ndx.end < 0) ||
    494  4168  ab196087 			    (ndx <= list->value.ndx.end)))
    495  5411  ab196087 				return (1);
    496  5411  ab196087 			break;
    497  5411  ab196087 
    498  5411  ab196087 		case MATCH_OPT_TYPE:
    499  5411  ab196087 			if ((match_flags & MATCH_F_TYPE) &&
    500  5411  ab196087 			    (type == list->value.type))
    501  4168  ab196087 				return (1);
    502  4168  ab196087 			break;
    503  4168  ab196087 		}
    504  4168  ab196087 	}
    505  4168  ab196087 
    506  4168  ab196087 	/* Nothing matched */
    507  4168  ab196087 	return (0);
    508  4168  ab196087 }
    509  4168  ab196087 
    510  4168  ab196087 /*
    511  5411  ab196087  * Add an entry to match_state.list for use by match(). This routine is for
    512  5411  ab196087  * use during getopt() processing. It should not be called once
    513  5411  ab196087  * match_prepare() has been called.
    514  4168  ab196087  *
    515  4168  ab196087  * Return True (1) for success. On failure, an error is written
    516  4168  ab196087  * to stderr, and False (0) is returned.
    517  4168  ab196087  */
    518  4168  ab196087 static int
    519  5411  ab196087 add_match_record(char *argv0, match_rec_t *data)
    520  4168  ab196087 {
    521  5411  ab196087 	match_rec_t	*rec;
    522  5411  ab196087 	match_rec_t	*list;
    523  4168  ab196087 
    524  4168  ab196087 	if ((rec = malloc(sizeof (*rec))) == NULL) {
    525  4168  ab196087 		int err = errno;
    526  4168  ab196087 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
    527  4168  ab196087 		    basename(argv0), strerror(err));
    528  4168  ab196087 		return (0);
    529  4168  ab196087 	}
    530  4168  ab196087 
    531  4168  ab196087 	*rec = *data;
    532  4168  ab196087 
    533  5411  ab196087 	/* Insert at end of match_state.list */
    534  5411  ab196087 	if (match_state.list == NULL) {
    535  5411  ab196087 		match_state.list = rec;
    536  4168  ab196087 	} else {
    537  5411  ab196087 		for (list = match_state.list; list->next != NULL;
    538  5411  ab196087 		    list = list->next)
    539  4168  ab196087 			;
    540  4168  ab196087 		list->next = rec;
    541  4168  ab196087 	}
    542  4168  ab196087 
    543  4168  ab196087 	rec->next = NULL;
    544  4168  ab196087 	return (1);
    545  1618       rie }
    546  1618       rie 
    547  5411  ab196087 static int
    548  5411  ab196087 decide(const char *file, int fd, Elf *elf, uint_t flags,
    549  9273       Ali     const char *wname, int wfd, uchar_t osabi)
    550  1618       rie {
    551  5411  ab196087 	int r;
    552  5411  ab196087 
    553  1618       rie 	if (gelf_getclass(elf) == ELFCLASS64)
    554  9273       Ali 		r = regular64(file, fd, elf, flags, wname, wfd, osabi);
    555  1618       rie 	else
    556  9273       Ali 		r = regular32(file, fd, elf, flags, wname, wfd, osabi);
    557  5411  ab196087 
    558  5411  ab196087 	return (r);
    559  1618       rie }
    560  1618       rie 
    561  5411  ab196087 static int
    562  5411  ab196087 archive(const char *file, int fd, Elf *elf, uint_t flags,
    563  9273       Ali     const char *wname, int wfd, uchar_t osabi)
    564  1618       rie {
    565  1618       rie 	Elf_Cmd		cmd = ELF_C_READ;
    566  1618       rie 	Elf_Arhdr	*arhdr;
    567  9085       Ali 	Elf		*_elf = NULL;
    568  1618       rie 	size_t		ptr;
    569  9085       Ali 	Elf_Arsym	*arsym = NULL;
    570  1618       rie 
    571  1618       rie 	/*
    572  3492  ab196087 	 * Determine if the archive symbol table itself is required.
    573  1618       rie 	 */
    574  5411  ab196087 	if ((flags & FLG_SHOW_SYMBOLS) &&
    575  5411  ab196087 	    match(MATCH_F_NAME, MSG_ORIG(MSG_ELF_ARSYM), 0, 0)) {
    576  1618       rie 		/*
    577  1618       rie 		 * Get the archive symbol table.
    578  1618       rie 		 */
    579  1618       rie 		if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) {
    580  1618       rie 			/*
    581  1618       rie 			 * The arsym could be 0 even though there was no error.
    582  1618       rie 			 * Print the error message only when there was
    583  1618       rie 			 * real error from elf_getarsym().
    584  1618       rie 			 */
    585  1618       rie 			failure(file, MSG_ORIG(MSG_ELF_GETARSYM));
    586  5411  ab196087 			return (0);
    587  1618       rie 		}
    588  1618       rie 	}
    589  1618       rie 
    590  1618       rie 	/*
    591  1618       rie 	 * Print the archive symbol table only when the archive symbol
    592  1618       rie 	 * table exists and it was requested to print.
    593  1618       rie 	 */
    594  1618       rie 	if (arsym) {
    595  1618       rie 		size_t		cnt;
    596  1618       rie 		char		index[MAXNDXSIZE];
    597  1618       rie 		size_t		offset = 0, _offset = 0;
    598  1618       rie 
    599  1618       rie 		/*
    600  1618       rie 		 * Print out all the symbol entries.
    601  1618       rie 		 */
    602  1618       rie 		dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB));
    603  1618       rie 		dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS));
    604  1618       rie 
    605  1618       rie 		for (cnt = 0; cnt < ptr; cnt++, arsym++) {
    606  1618       rie 			/*
    607  1618       rie 			 * For each object obtain an elf descriptor so that we
    608  1618       rie 			 * can establish the members name.  Note, we have had
    609  1618       rie 			 * archives where the archive header has not been
    610  1618       rie 			 * obtainable so be lenient with errors.
    611  1618       rie 			 */
    612  1618       rie 			if ((offset == 0) || ((arsym->as_off != 0) &&
    613  1618       rie 			    (arsym->as_off != _offset))) {
    614  1618       rie 
    615  1618       rie 				if (_elf)
    616  1618       rie 					(void) elf_end(_elf);
    617  1618       rie 
    618  1618       rie 				if (elf_rand(elf, arsym->as_off) !=
    619  1618       rie 				    arsym->as_off) {
    620  1618       rie 					failure(file, MSG_ORIG(MSG_ELF_RAND));
    621  9085       Ali 					arhdr = NULL;
    622  1618       rie 				} else if ((_elf = elf_begin(fd,
    623  1618       rie 				    ELF_C_READ, elf)) == 0) {
    624  1618       rie 					failure(file, MSG_ORIG(MSG_ELF_BEGIN));
    625  9085       Ali 					arhdr = NULL;
    626  1618       rie 				} else if ((arhdr = elf_getarhdr(_elf)) == 0) {
    627  1618       rie 					failure(file,
    628  1618       rie 					    MSG_ORIG(MSG_ELF_GETARHDR));
    629  9085       Ali 					arhdr = NULL;
    630  1618       rie 				}
    631  1618       rie 
    632  1618       rie 				_offset = arsym->as_off;
    633  1618       rie 				if (offset == 0)
    634  1618       rie 					offset = _offset;
    635  1618       rie 			}
    636  1618       rie 
    637  1618       rie 			(void) snprintf(index, MAXNDXSIZE,
    638  1618       rie 			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt));
    639  1618       rie 			if (arsym->as_off)
    640  1618       rie 				dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM1), index,
    641  1618       rie 				    /* LINTED */
    642  1618       rie 				    (int)arsym->as_off, arhdr ? arhdr->ar_name :
    643  1618       rie 				    MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ?
    644  1618       rie 				    demangle(arsym->as_name, flags) :
    645  1618       rie 				    MSG_INTL(MSG_STR_NULL)));
    646  1618       rie 			else
    647  1618       rie 				dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM2), index,
    648  1618       rie 				    /* LINTED */
    649  1618       rie 				    (int)arsym->as_off);
    650  1618       rie 		}
    651  1618       rie 
    652  1618       rie 		if (_elf)
    653  1618       rie 			(void) elf_end(_elf);
    654  1618       rie 
    655  1618       rie 		/*
    656  1618       rie 		 * If we only need the archive symbol table return.
    657  1618       rie 		 */
    658  5411  ab196087 		if ((flags & FLG_SHOW_SYMBOLS) &&
    659  5411  ab196087 		    match(MATCH_F_STRICT | MATCH_F_NAME,
    660  5411  ab196087 		    MSG_ORIG(MSG_ELF_ARSYM), -1, -1))
    661  5411  ab196087 			return (0);
    662  1618       rie 
    663  1618       rie 		/*
    664  1618       rie 		 * Reset elf descriptor in preparation for processing each
    665  1618       rie 		 * member.
    666  1618       rie 		 */
    667  1618       rie 		if (offset)
    668  1618       rie 			(void) elf_rand(elf, offset);
    669  1618       rie 	}
    670  1618       rie 
    671  1618       rie 	/*
    672  1618       rie 	 * Process each object within the archive.
    673  1618       rie 	 */
    674  1618       rie 	while ((_elf = elf_begin(fd, cmd, elf)) != NULL) {
    675  1618       rie 		char	name[MAXPATHLEN];
    676  1618       rie 
    677  1618       rie 		if ((arhdr = elf_getarhdr(_elf)) == NULL) {
    678  1618       rie 			failure(file, MSG_ORIG(MSG_ELF_GETARHDR));
    679  5411  ab196087 			return (0);
    680  1618       rie 		}
    681  1618       rie 		if (*arhdr->ar_name != '/') {
    682  1618       rie 			(void) snprintf(name, MAXPATHLEN,
    683  1618       rie 			    MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name);
    684  1618       rie 			dbg_print(0, MSG_ORIG(MSG_FMT_NLSTR), name);
    685  1618       rie 
    686  1618       rie 			switch (elf_kind(_elf)) {
    687  1618       rie 			case ELF_K_AR:
    688  5411  ab196087 				if (archive(name, fd, _elf, flags,
    689  9273       Ali 				    wname, wfd, osabi) == 1)
    690  5411  ab196087 					return (1);
    691  1618       rie 				break;
    692  1618       rie 			case ELF_K_ELF:
    693  5411  ab196087 				if (decide(name, fd, _elf, flags,
    694  9273       Ali 				    wname, wfd, osabi) == 1)
    695  5411  ab196087 					return (1);
    696  1618       rie 				break;
    697  1618       rie 			default:
    698  1618       rie 				(void) fprintf(stderr,
    699  1618       rie 				    MSG_INTL(MSG_ERR_BADFILE), name);
    700  1618       rie 				break;
    701  1618       rie 			}
    702  1618       rie 		}
    703  1618       rie 
    704  1618       rie 		cmd = elf_next(_elf);
    705  1618       rie 		(void) elf_end(_elf);
    706  1618       rie 	}
    707  5411  ab196087 
    708  5411  ab196087 	return (0);
    709  1618       rie }
    710  1618       rie 
    711  1618       rie int
    712  1618       rie main(int argc, char **argv, char **envp)
    713  1618       rie {
    714  1618       rie 	Elf		*elf;
    715  1618       rie 	int		var, fd, wfd = 0;
    716  5411  ab196087 	char		*wname = NULL;
    717  1618       rie 	uint_t		flags = 0;
    718  5411  ab196087 	match_rec_t	match_data;
    719  5411  ab196087 	int		ret;
    720  9273       Ali 	uchar_t		osabi;
    721  1618       rie 
    722  1618       rie 	/*
    723  1618       rie 	 * If we're on a 64-bit kernel, try to exec a full 64-bit version of
    724  1618       rie 	 * the binary.  If successful, conv_check_native() won't return.
    725  1618       rie 	 */
    726  2647       rie 	(void) conv_check_native(argv, envp);
    727  1618       rie 
    728  1618       rie 	/*
    729  1618       rie 	 * Establish locale.
    730  1618       rie 	 */
    731  1618       rie 	(void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY));
    732  1618       rie 	(void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS));
    733  1618       rie 
    734  1618       rie 	(void) setvbuf(stdout, NULL, _IOLBF, 0);
    735  1618       rie 	(void) setvbuf(stderr, NULL, _IOLBF, 0);
    736  1618       rie 
    737  1618       rie 	opterr = 0;
    738  1618       rie 	while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) {
    739  1618       rie 		switch (var) {
    740  1618       rie 		case 'C':
    741  5411  ab196087 			flags |= FLG_CTL_DEMANGLE;
    742  1618       rie 			break;
    743  1618       rie 		case 'c':
    744  5411  ab196087 			flags |= FLG_SHOW_SHDR;
    745  1618       rie 			break;
    746  1618       rie 		case 'd':
    747  5411  ab196087 			flags |= FLG_SHOW_DYNAMIC;
    748  1618       rie 			break;
    749  1618       rie 		case 'e':
    750  5411  ab196087 			flags |= FLG_SHOW_EHDR;
    751  1618       rie 			break;
    752  1618       rie 		case 'G':
    753  5411  ab196087 			flags |= FLG_SHOW_GOT;
    754  1618       rie 			break;
    755  1618       rie 		case 'g':
    756  5411  ab196087 			flags |= FLG_SHOW_GROUP;
    757  1618       rie 			break;
    758  1618       rie 		case 'H':
    759  5411  ab196087 			flags |= FLG_SHOW_CAP;
    760  1618       rie 			break;
    761  1618       rie 		case 'h':
    762  5411  ab196087 			flags |= FLG_SHOW_HASH;
    763  1618       rie 			break;
    764  4168  ab196087 		case 'I':
    765  5411  ab196087 			if (!process_index_opt(optarg, &match_data))
    766  5411  ab196087 				goto usage_brief;
    767  4168  ab196087 			if (!add_match_record(argv[0], &match_data))
    768  4168  ab196087 				return (1);
    769  5411  ab196087 			flags |= FLG_CTL_MATCH;
    770  4168  ab196087 			break;
    771  1618       rie 		case 'i':
    772  5411  ab196087 			flags |= FLG_SHOW_INTERP;
    773  1618       rie 			break;
    774  1618       rie 		case 'k':
    775  5411  ab196087 			flags |= FLG_CALC_CHECKSUM;
    776  1618       rie 			break;
    777  1618       rie 		case 'l':
    778  5411  ab196087 			flags |= FLG_CTL_LONGNAME;
    779  1618       rie 			break;
    780  1618       rie 		case 'm':
    781  5411  ab196087 			flags |= FLG_SHOW_MOVE;
    782  1618       rie 			break;
    783  1618       rie 		case 'N':
    784  5411  ab196087 			match_data.opt_type = MATCH_OPT_NAME;
    785  4168  ab196087 			match_data.value.name = optarg;
    786  4168  ab196087 			if (!add_match_record(argv[0], &match_data))
    787  4168  ab196087 				return (1);
    788  5411  ab196087 			flags |= FLG_CTL_MATCH;
    789  1618       rie 			break;
    790  1618       rie 		case 'n':
    791  5411  ab196087 			flags |= FLG_SHOW_NOTE;
    792  9273       Ali 			break;
    793  9273       Ali 		case 'O':
    794  9273       Ali 			{
    795  9273       Ali 				uint32_t val;
    796  9273       Ali 
    797  9273       Ali 				/*
    798  9273       Ali 				 * osabi is a uchar_t in the ELF header.
    799  9273       Ali 				 * Don't accept any value that exceeds
    800  9273       Ali 				 * that range.
    801  9273       Ali 				 */
    802  9273       Ali 				if ((atoui(optarg, ATOUI_OSABI, &val) == 0) ||
    803  9273       Ali 				    (val > 255)) {
    804  9273       Ali 					(void) fprintf(stderr,
    805  9273       Ali 					    MSG_INTL(MSG_ERR_BAD_T_OSABI),
    806  9273       Ali 					    basename(argv[0]), optarg);
    807  9273       Ali 					return (1);
    808  9273       Ali 				}
    809  9273       Ali 				osabi = val;
    810  9273       Ali 			}
    811  9273       Ali 			flags |= FLG_CTL_OSABI;
    812  1618       rie 			break;
    813  4665  ab196087 		case 'P':
    814  5411  ab196087 			flags |= FLG_CTL_FAKESHDR;
    815  4665  ab196087 			break;
    816  1618       rie 		case 'p':
    817  5411  ab196087 			flags |= FLG_SHOW_PHDR;
    818  1618       rie 			break;
    819  1618       rie 		case 'r':
    820  5411  ab196087 			flags |= FLG_SHOW_RELOC;
    821  1618       rie 			break;
    822  3492  ab196087 		case 'S':
    823  5411  ab196087 			flags |= FLG_SHOW_SORT;
    824  3492  ab196087 			break;
    825  1618       rie 		case 's':
    826  5411  ab196087 			flags |= FLG_SHOW_SYMBOLS;
    827  5411  ab196087 			break;
    828  5411  ab196087 		case 'T':
    829  5411  ab196087 			/*
    830  5411  ab196087 			 * We can't evaluate the value yet, because
    831  5411  ab196087 			 * we need to know if -p is used or not in
    832  5411  ab196087 			 * order to tell if we're seeing section header
    833  5411  ab196087 			 * or program header types. So, we save the
    834  5411  ab196087 			 * string in the name field, and then convert
    835  5411  ab196087 			 * it to a type integer in a following pass.
    836  5411  ab196087 			 */
    837  5411  ab196087 			match_data.opt_type = MATCH_OPT_TYPE;
    838  5411  ab196087 			match_data.value.name = optarg;
    839  5411  ab196087 			if (!add_match_record(argv[0], &match_data))
    840  5411  ab196087 				return (1);
    841  5411  ab196087 			flags |= FLG_CTL_MATCH;
    842  1618       rie 			break;
    843  1618       rie 		case 'u':
    844  5411  ab196087 			flags |= FLG_SHOW_UNWIND;
    845  1618       rie 			break;
    846  1618       rie 		case 'v':
    847  5411  ab196087 			flags |= FLG_SHOW_VERSIONS;
    848  1618       rie 			break;
    849  1618       rie 		case 'w':
    850  1618       rie 			wname = optarg;
    851  1618       rie 			break;
    852  1618       rie 		case 'y':
    853  5411  ab196087 			flags |= FLG_SHOW_SYMINFO;
    854  1618       rie 			break;
    855  1618       rie 		case '?':
    856  1618       rie 			(void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF),
    857  1618       rie 			    basename(argv[0]));
    858  1618       rie 			detail_usage();
    859  1618       rie 			return (1);
    860  1618       rie 		default:
    861  1618       rie 			break;
    862  1618       rie 		}
    863  1618       rie 	}
    864  1618       rie 
    865  5411  ab196087 	/* -p and -w are mutually exclusive. -w only works with sections */
    866  5411  ab196087 	if (((flags & FLG_SHOW_PHDR) != 0) && (wname != NULL))
    867  5411  ab196087 		goto usage_brief;
    868  5411  ab196087 
    869  5411  ab196087 	/* If a match argument is present, prepare the match state */
    870  5411  ab196087 	if ((match_state.list != NULL) && (match_prepare(argv[0], flags) == 0))
    871  5411  ab196087 		return (1);
    872  5411  ab196087 
    873  1618       rie 	/*
    874  5411  ab196087 	 * Decide what to do if no options specifying something to
    875  5411  ab196087 	 * show or do are present.
    876  5411  ab196087 	 *
    877  5411  ab196087 	 * If there is no -w and no match options, then we will set all
    878  5411  ab196087 	 * the show flags, causing a full display of everything in the
    879  5411  ab196087 	 * file that we know how to handle.
    880  5411  ab196087 	 *
    881  5411  ab196087 	 * Otherwise, if there is no match list, we generate a usage
    882  5411  ab196087 	 * error and quit.
    883  5411  ab196087 	 *
    884  5411  ab196087 	 * In the case where there is a match list, we go ahead and call
    885  5411  ab196087 	 * regular() anyway, leaving it to decide what to do. If -w is
    886  5411  ab196087 	 * present, regular() will use the match list to handle it.
    887  5411  ab196087 	 * In addition, in the absence of explicit show/calc flags, regular()
    888  5411  ab196087 	 * will compare the section headers to the match list and use
    889  5411  ab196087 	 * that to generate the FLG_ bits that will display the information
    890  5411  ab196087 	 * specified by the match list.
    891  1618       rie 	 */
    892  5411  ab196087 	if ((flags & ~FLG_MASK_CTL) == 0) {
    893  5411  ab196087 		if (!wname && (match_state.list == NULL))
    894  5411  ab196087 			flags |= FLG_MASK_SHOW;
    895  5411  ab196087 		else if (match_state.list == NULL)
    896  5411  ab196087 			goto usage_brief;
    897  1618       rie 	}
    898  1618       rie 
    899  5411  ab196087 	/* There needs to be at least 1 filename left following the options */
    900  5411  ab196087 	if ((var = argc - optind) == 0)
    901  5411  ab196087 		goto usage_brief;
    902  1618       rie 
    903  1618       rie 	/*
    904  1618       rie 	 * If the -l/-C option is specified, set up the liblddbg.so.
    905  1618       rie 	 */
    906  5411  ab196087 	if (flags & FLG_CTL_LONGNAME)
    907  1618       rie 		dbg_desc->d_extra |= DBG_E_LONG;
    908  5411  ab196087 	if (flags & FLG_CTL_DEMANGLE)
    909  1618       rie 		dbg_desc->d_extra |= DBG_E_DEMANGLE;
    910  1618       rie 
    911  1618       rie 	/*
    912  1618       rie 	 * If the -w option has indicated an output file open it.  It's
    913  1618       rie 	 * arguable whether this option has much use when multiple files are
    914  1618       rie 	 * being processed.
    915  5411  ab196087 	 *
    916  5411  ab196087 	 * If wname is non-NULL, we know that -p was not specified, due
    917  5411  ab196087 	 * to the test above.
    918  1618       rie 	 */
    919  1618       rie 	if (wname) {
    920  1618       rie 		if ((wfd = open(wname, (O_RDWR | O_CREAT | O_TRUNC),
    921  1618       rie 		    0666)) < 0) {
    922  1618       rie 			int err = errno;
    923  1618       rie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN),
    924  1618       rie 			    wname, strerror(err));
    925  5411  ab196087 			return (1);
    926  1618       rie 		}
    927  1618       rie 	}
    928  1618       rie 
    929  1618       rie 	/*
    930  5411  ab196087 	 * Open the input file, initialize the elf interface, and
    931  5411  ab196087 	 * process it.
    932  1618       rie 	 */
    933  5411  ab196087 	ret = 0;
    934  5411  ab196087 	for (; (optind < argc) && (ret == 0); optind++) {
    935  1618       rie 		const char	*file = argv[optind];
    936  1618       rie 
    937  1618       rie 		if ((fd = open(argv[optind], O_RDONLY)) == -1) {
    938  1618       rie 			int err = errno;
    939  1618       rie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN),
    940  1618       rie 			    file, strerror(err));
    941  1618       rie 			continue;
    942  1618       rie 		}
    943  1618       rie 		(void) elf_version(EV_CURRENT);
    944  1618       rie 		if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
    945  1618       rie 			failure(file, MSG_ORIG(MSG_ELF_BEGIN));
    946  1618       rie 			(void) close(fd);
    947  1618       rie 			continue;
    948  1618       rie 		}
    949  1618       rie 
    950  1618       rie 		if (var > 1)
    951  1618       rie 			dbg_print(0, MSG_ORIG(MSG_FMT_NLSTRNL), file);
    952  1618       rie 
    953  1618       rie 		switch (elf_kind(elf)) {
    954  1618       rie 		case ELF_K_AR:
    955  9273       Ali 			ret = archive(file, fd, elf, flags, wname, wfd, osabi);
    956  1618       rie 			break;
    957  1618       rie 		case ELF_K_ELF:
    958  9273       Ali 			ret = decide(file, fd, elf, flags, wname, wfd, osabi);
    959  1618       rie 			break;
    960  1618       rie 		default:
    961  1618       rie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADFILE), file);
    962  1618       rie 			break;
    963  1618       rie 		}
    964  1618       rie 
    965  1618       rie 		(void) close(fd);
    966  1618       rie 		(void) elf_end(elf);
    967  1618       rie 	}
    968  1618       rie 
    969  1618       rie 	if (wfd)
    970  1618       rie 		(void) close(wfd);
    971  5411  ab196087 	return (ret);
    972  5411  ab196087 
    973  5411  ab196087 usage_brief:
    974  5411  ab196087 	/* Control comes here for a simple usage message and exit */
    975  5411  ab196087 	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF),
    976  5411  ab196087 	    basename(argv[0]));
    977  5411  ab196087 	return (1);
    978  5411  ab196087 
    979  1618       rie }
    980