25aefb65rie * CDDL HEADER START
35aefb65rie *
45aefb65rie * The contents of this file are subject to the terms of the
55aefb65rie * Common Development and Distribution License (the "License").
65aefb65rie * You may not use this file except in compliance with the License.
75aefb65rie *
85aefb65rie * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95aefb65rie * or http://www.opensolaris.org/os/licensing.
105aefb65rie * See the License for the specific language governing permissions
115aefb65rie * and limitations under the License.
125aefb65rie *
135aefb65rie * When distributing Covered Code, include this CDDL HEADER in each
145aefb65rie * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155aefb65rie * If applicable, add the following below this CDDL HEADER, with the
165aefb65rie * fields enclosed by brackets "[]" replaced with your own identifying
175aefb65rie * information: Portions Copyright [yyyy] [name of copyright owner]
185aefb65rie *
195aefb65rie * CDDL HEADER END
205aefb65rie */
23ba7866cAli Bahrami * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
245aefb65rie */
275aefb65rie * Dump an elf file.
285aefb65rie */
295aefb65rie#include	<sys/param.h>
305aefb65rie#include	<fcntl.h>
315aefb65rie#include	<stdio.h>
32c809c40ab#include	<stdlib.h>
33c809c40ab#include	<ctype.h>
34ba7866cAli Bahrami#include	<_libelf.h>
355aefb65rie#include	<link.h>
365aefb65rie#include	<stdarg.h>
375aefb65rie#include	<unistd.h>
385aefb65rie#include	<libgen.h>
395aefb65rie#include	<libintl.h>
405aefb65rie#include	<locale.h>
415aefb65rie#include	<errno.h>
425aefb65rie#include	<strings.h>
435aefb65rie#include	<debug.h>
445aefb65rie#include	<conv.h>
455aefb65rie#include	<msg.h>
465aefb65rie#include	<_elfdump.h>
47981a172ab#include	<sys/elf_SPARC.h>
48981a172ab#include	<sys/elf_amd64.h>
5131fdd7cabconst Cache	cache_init = {NULL, NULL, NULL, NULL, 0};
56981a172ab * The -I, -N, and -T options are called "match options", because
57981a172ab * they allow selecting the items to be displayed based on matching
58981a172ab * their index, name, or type.
59981a172ab *
60981a172ab * The ELF information to which -I, -N, or -T are applied in
61981a172ab * the current invocation is called the "match item".
62981a172ab */
63981a172abtypedef enum {
64981a172ab	MATCH_ITEM_PT,		/* Program header (PT_) */
65981a172ab	MATCH_ITEM_SHT		/* Section header (SHT_) */
66981a172ab} match_item_t;
68981a172ab/* match_opt_t is  used to note which match option was used */
69c809c40abtypedef enum {
70981a172ab	MATCH_OPT_NAME,		/* Record contains a name */
71981a172ab	MATCH_OPT_NDX,		/* Record contains a single index */
72981a172ab	MATCH_OPT_RANGE,	/* Record contains an index range */
73981a172ab	MATCH_OPT_TYPE,		/* Record contains a type (shdr or phdr) */
74981a172ab} match_opt_t;
76c809c40abtypedef struct _match {
77c809c40ab	struct _match	*next;		/* Pointer to next item in list */
78981a172ab	match_opt_t	opt_type;
79c809c40ab	union {
80981a172ab		const char	*name;	/* MATCH_OPT_NAME */
81981a172ab		struct {		/* MATCH_OPT_NDX and MATCH_OPT_RANGE */
82c809c40ab			int	start;
83981a172ab			int	end;	/* Only for MATCH_OPT_RANGE */
84c809c40ab		} ndx;
85981a172ab		uint32_t	type;	/* MATCH_OPT_TYPE */
86c809c40ab	} value;
87981a172ab} match_rec_t;
89981a172abstatic struct {
90981a172ab	match_item_t	item_type;	/* Type of item being matched */
91981a172ab	match_rec_t	*list;		/* Records for (-I, -N, -T) options */
92981a172ab} match_state;
965aefb65rieconst char *
975aefb65rie_elfdump_msg(Msg mid)
995aefb65rie	return (gettext(MSG_ORIG(mid)));
1035aefb65rie * Determine whether a symbol name should be demangled.
1045aefb65rie */
1055aefb65rieconst char *
1065aefb65riedemangle(const char *name, uint_t flags)
108981a172ab	if (flags & FLG_CTL_DEMANGLE)
1095aefb65rie		return (Elf_demangle_name(name));
1105aefb65rie	else
1115aefb65rie		return ((char *)name);
1155aefb65rie * Define our own standard error routine.
1165aefb65rie */
1185aefb65riefailure(const char *file, const char *func)
1205aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_ERR_FAILURE),
1215aefb65rie	    file, func, elf_errmsg(elf_errno()));
1255aefb65rie * The full usage message
1265aefb65rie */
1275aefb65riestatic void
1305aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL1));
1315aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL2));
1325aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL3));
1335aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL4));
1345aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL5));
1355aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL6));
1365aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL7));
1375aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL8));
1385aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9));
1395aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL10));
1405aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL11));
1415aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL12));
1425aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL13));
1435aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL14));
1445aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL15));
1455aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL16));
1465aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL17));
1475aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL18));
1485aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL19));
1495aefb65rie	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL20));
150d579eb6ab	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL21));
151c809c40ab	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL22));
152c809c40ab	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL23));
15339773e4ab	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL24));
154981a172ab	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL25));
1554f680ccAli Bahrami	(void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL26));
159c6c9aedab * Output a block of raw data as hex bytes. Each row is given
160c6c9aedab * the index of the first byte in the row.
161c6c9aedab *
162c6c9aedab * entry:
163c6c9aedab *	data - Pointer to first byte of data to be displayed
164c6c9aedab *	n - # of bytes of data
165c6c9aedab *	prefix - String to be output before each line. Useful
166c6c9aedab *		for indenting output.
167c6c9aedab *	bytes_per_col - # of space separated bytes to output
168c6c9aedab *		in each column.
169c6c9aedab *	col_per_row - # of columns to output per row
170c6c9aedab *
171c6c9aedab * exit:
172c6c9aedab *	The formatted data has been sent to stdout. Each row of output
173c6c9aedab *	shows (bytes_per_col * col_per_row) bytes of data.
174c6c9aedab */
1767e16fcaAli Bahramidump_hex_bytes(const void *data, size_t n, int indent,
177c6c9aedab	int bytes_per_col, int col_per_row)
1797e16fcaAli Bahrami	const uchar_t *ldata = data;
180c6c9aedab	int	bytes_per_row = bytes_per_col * col_per_row;
181c6c9aedab	int	ndx, byte, word;
182c6c9aedab	char	string[128], *str = string;
183c6c9aedab	char	index[MAXNDXSIZE];
184c6c9aedab	int	index_width;
185c6c9aedab	int	sp_prefix = 0;
188c6c9aedab	/*
189c6c9aedab	 * Determine the width to use for the index string. We follow
190c6c9aedab	 * 8-byte tab rules, but don't use an actual \t character so
191c6c9aedab	 * that the output can be arbitrarily shifted without odd
192c6c9aedab	 * tab effects, and so that all the columns line up no matter
193c6c9aedab	 * how many lines of output are produced.
194c6c9aedab	 */
195c6c9aedab	ndx = n / bytes_per_row;
196c6c9aedab	(void) snprintf(index, sizeof (index),
197c6c9aedab	    MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx));
198c6c9aedab	index_width = strlen(index);
199c6c9aedab	index_width = S_ROUND(index_width, 8);
2017e16fcaAli Bahrami	for (ndx = byte = word = 0; n > 0; n--, ldata++) {
202c6c9aedab		while (sp_prefix-- > 0)
203c6c9aedab			*str++ = ' ';
205c6c9aedab		(void) snprintf(str, sizeof (string),
2067e16fcaAli Bahrami		    MSG_ORIG(MSG_HEXDUMP_TOK), (int)*ldata);
207c6c9aedab		str += 2;
208c6c9aedab		sp_prefix = 1;
210c6c9aedab		if (++byte == bytes_per_col) {
211c6c9aedab			sp_prefix += 2;
212c6c9aedab			word++;
213c6c9aedab			byte = 0;
214c6c9aedab		}
215c6c9aedab		if (word == col_per_row) {
216c6c9aedab			*str = '\0';
217c6c9aedab			(void) snprintf(index, sizeof (index),
218c6c9aedab			    MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx));
219c6c9aedab			dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW),
220c6c9aedab			    indent, MSG_ORIG(MSG_STR_EMPTY),
221c6c9aedab			    index_width, index, string);
222c6c9aedab			sp_prefix = 0;
223c6c9aedab			word = 0;
224c6c9aedab			ndx += bytes_per_row;
225c6c9aedab			str = string;
226c6c9aedab		}
227c6c9aedab	}
228c6c9aedab	if (byte || word) {
229c6c9aedab		*str = '\0';	/*  */
230c6c9aedab		(void) snprintf(index, sizeof (index),
231c6c9aedab		    MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx));
232c6c9aedab		dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW), indent,
233c6c9aedab		    MSG_ORIG(MSG_STR_EMPTY), index_width, index, string);
234c6c9aedab	}
238c809c40ab * Convert the ASCII representation of an index, or index range, into
239c809c40ab * binary form, and store it in rec:
240c809c40ab *
241c809c40ab *	index: An positive or 0 valued integer
242c809c40ab *	range: Two indexes, separated by a ':' character, denoting
243c809c40ab *		a range of allowed values. If the second value is omitted,
244c809c40ab *		any values equal to or greater than the first will match.
245c809c40ab *
246c809c40ab * exit:
247981a172ab *	On success, *rec is filled in with a MATCH_OPT_NDX or MATCH_OPT_RANGE
248c809c40ab *	value, and this function returns (1). On failure, the contents
249c809c40ab *	of *rec are undefined, and (0) is returned.
250c809c40ab */
252981a172abprocess_index_opt(const char *str, match_rec_t *rec)
254c809c40ab#define	SKIP_BLANK for (; *str && isspace(*str); str++)
256c809c40ab	char	*endptr;
258c809c40ab	rec->value.ndx.start = strtol(str, &endptr, 10);
259c809c40ab	/* Value must use some of the input, and be 0 or positive */
260c809c40ab	if ((str == endptr) || (rec->value.ndx.start < 0))
261c809c40ab		return (0);
262c809c40ab	str = endptr;
264c809c40ab	SKIP_BLANK;
265c809c40ab	if (*str != ':') {
266981a172ab		rec->opt_type = MATCH_OPT_NDX;
267c809c40ab	} else {
268c809c40ab		str++;					/* Skip the ':' */
269981a172ab		rec->opt_type = MATCH_OPT_RANGE;
270c809c40ab		SKIP_BLANK;
271c809c40ab		if (*str == '\0') {
272c809c40ab			rec->value.ndx.end = -1;	/* Indicates "to end" */
273c809c40ab		} else {
274c809c40ab			rec->value.ndx.end = strtol(str, &endptr, 10);
275c809c40ab			if ((str == endptr) || (rec->value.ndx.end < 0))
276c809c40ab				return (0);
277c809c40ab			str = endptr;
278c809c40ab			SKIP_BLANK;
279c809c40ab		}
280c809c40ab	}
282c809c40ab	/* Syntax error if anything is left over */
283c809c40ab	if (*str != '\0')
284c809c40ab		return (0);
286c809c40ab	return (1);
288c809c40ab#undef	SKIP_BLANK
2924f680ccAli Bahrami * Convert a string containing a specific type of ELF constant, or an ASCII
2934f680ccAli Bahrami * representation of a number, to an integer. Strings starting with '0'
294981a172ab * are taken to be octal, those staring with '0x' are hex, and all
295981a172ab * others are decimal.
296981a172ab *
297981a172ab * entry:
298981a172ab *	str - String to be converted
2994f680ccAli Bahrami *	ctype - Constant type
300981a172ab *	v - Address of variable to receive resulting value.
301981a172ab *
302981a172ab * exit:
303981a172ab *	On success, returns True (1) and *v is set to the value.
304981a172ab *	On failure, returns False (0) and *v is undefined.
305981a172ab */
3064f680ccAli Bahramitypedef enum {
3074f680ccAli Bahrami	ATOUI_PT,
3084f680ccAli Bahrami	ATOUI_SHT,
3094f680ccAli Bahrami	ATOUI_OSABI
3104f680ccAli Bahrami} atoui_type_t;
3114f680ccAli Bahrami
312981a172abstatic int
3134f680ccAli Bahramiatoui(const char *str, atoui_type_t type, uint32_t *v)
3154f680ccAli Bahrami	conv_strtol_uvalue_t	uvalue;
3164f680ccAli Bahrami	char			*endptr;
3174f680ccAli Bahrami
3184f680ccAli Bahrami	if (conv_iter_strtol_init(str, &uvalue) != 0) {
3194f680ccAli Bahrami		switch (type) {
3204f680ccAli Bahrami		case ATOUI_PT:
3214f680ccAli Bahrami			if (conv_iter_phdr_type(CONV_OSABI_ALL, CONV_FMT_ALT_CF,
3224f680ccAli Bahrami			    conv_iter_strtol, &uvalue) == CONV_ITER_DONE)
3234f680ccAli Bahrami				break;
3244f680ccAli Bahrami			(void) conv_iter_phdr_type(CONV_OSABI_ALL,
3254f680ccAli Bahrami			    CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue);
3264f680ccAli Bahrami			break;
3274f680ccAli Bahrami		case ATOUI_SHT:
3284f680ccAli Bahrami			if (conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL,
3294f680ccAli Bahrami			    CONV_FMT_ALT_CF, conv_iter_strtol, &uvalue) ==
3304f680ccAli Bahrami			    CONV_ITER_DONE)
3314f680ccAli Bahrami				break;
3324f680ccAli Bahrami			(void) conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL,
3334f680ccAli Bahrami			    CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue);
3344f680ccAli Bahrami			break;
3354f680ccAli Bahrami		case ATOUI_OSABI:
3364f680ccAli Bahrami			if (conv_iter_ehdr_osabi(CONV_FMT_ALT_CF,
3374f680ccAli Bahrami			    conv_iter_strtol, &uvalue) == CONV_ITER_DONE)
3384f680ccAli Bahrami				break;
3394f680ccAli Bahrami			(void) conv_iter_ehdr_osabi(CONV_FMT_ALT_NF,
3404f680ccAli Bahrami			    conv_iter_strtol, &uvalue);
3414f680ccAli Bahrami			break;
3424f680ccAli Bahrami		}
3434f680ccAli Bahrami		if (uvalue.csl_found) {
3444f680ccAli Bahrami			*v = uvalue.csl_value;
3454f680ccAli Bahrami			return (1);
3464f680ccAli Bahrami		}
3474f680ccAli Bahrami	}
349981a172ab	*v = strtoull(str, &endptr, 0);
351981a172ab	/* If the left over part contains anything but whitespace, fail */
352981a172ab	for (; *endptr; endptr++)
353981a172ab		if (!isspace(*endptr))
354981a172ab			return (0);
355981a172ab	return (1);
359981a172ab * Called after getopt() processing is finished if there is a non-empty
360981a172ab * match list. Prepares the matching code for use.
361981a172ab *
362981a172ab * exit:
363981a172ab *	Returns True (1) if no errors are encountered. Writes an
364981a172ab *	error string to stderr and returns False (0) otherwise.
365981a172ab */
366981a172abstatic int
367981a172abmatch_prepare(char *argv0, uint_t flags)
369981a172ab	match_rec_t	*list;
370981a172ab	const char	*str;
371981a172ab	int		minus_p = (flags & FLG_SHOW_PHDR) != 0;
3724f680ccAli Bahrami	atoui_type_t	atoui_type;
374981a172ab	/*
375981a172ab	 * Flag ambiguous attempt to use match option with both -p and
376981a172ab	 * and one or more section SHOW options. In this case, we
377981a172ab	 * can't tell what type of item we're supposed to match against.
378981a172ab	 */
379981a172ab	if (minus_p && (flags & FLG_MASK_SHOW_SHDR)) {
380981a172ab		(void) fprintf(stderr, MSG_INTL(MSG_ERR_AMBIG_MATCH),
381981a172ab		    basename(argv0));
382981a172ab		return (0);
383981a172ab	}
385981a172ab	/* Set the match type, based on the presence of the -p option */
386981a172ab	if (minus_p) {
387981a172ab		match_state.item_type = MATCH_ITEM_PT;
3884f680ccAli Bahrami		atoui_type = ATOUI_PT;
389981a172ab	} else {
390981a172ab		match_state.item_type = MATCH_ITEM_SHT;
3914f680ccAli Bahrami		atoui_type = ATOUI_SHT;
392981a172ab	}
394981a172ab	/*
395981a172ab	 * Scan match list and perform any necessary fixups:
396981a172ab	 *
397981a172ab	 * MATCH_OPT_NAME: If -p is specified, convert MATCH_OPT_NAME (-N)
398981a172ab	 *	requests into MATCH_OPT_TYPE (-T).
399981a172ab	 *
400981a172ab	 * MATCH_OPT_TYPE: Now that we know item type we are matching
401981a172ab	 *	against, we can convert the string saved in the name
402981a172ab	 *	field during getopt() processing into an integer and
403981a172ab	 *	write it into the type field.
404981a172ab	 */
405981a172ab	for (list = match_state.list; list; list = list->next) {
406981a172ab		if ((list->opt_type == MATCH_OPT_NAME) && minus_p)
407981a172ab			list->opt_type = MATCH_OPT_TYPE;
409981a172ab		if (list->opt_type != MATCH_OPT_TYPE)
410981a172ab			continue;
412981a172ab		str = list->value.name;
4134f680ccAli Bahrami		if (atoui(str, atoui_type, &list->value.type) == 0) {
414981a172ab			const char *fmt = minus_p ?
415981a172ab			    MSG_INTL(MSG_ERR_BAD_T_PT) :
416981a172ab			    MSG_INTL(MSG_ERR_BAD_T_SHT);
418981a172ab			(void) fprintf(stderr, fmt, basename(argv0), str);
419981a172ab			return (0);
420981a172ab		}
421981a172ab	}
423981a172ab	return (1);
428c809c40ab * Returns True (1) if the item with the given name or index should
429c809c40ab * be displayed, and False (0) if it should not be.
430c809c40ab *
431c809c40ab * entry:
432981a172ab *	match_flags - Bitmask specifying matching options, as described
433981a172ab *		in _elfdump.h.
434981a172ab *	name - If MATCH_F_NAME flag is set, name of item under
435981a172ab *		consideration. Otherwise ignored.
436c809c40ab *		should not be considered.
437981a172ab *	ndx - If MATCH_F_NDX flag is set, index of item under consideration.
438981a172ab *	type - If MATCH_F_TYPE is set, type of item under consideration.
439981a172ab *		If MATCH_F_PHDR is set, this would be a program
440981a172ab *		header type (PT_). Otherwise, a section header type (SHT_).
441c809c40ab *
442c809c40ab * exit:
443c809c40ab *	True will be returned if the given name/index matches those given
444981a172ab *	by one of the (-I, -N -T) command line options, or if no such option
445981a172ab *	was used in the command invocation and MATCH_F_STRICT is not
446981a172ab *	set.
447c809c40ab */
449981a172abmatch(match_flags_t match_flags, const char *name, uint_t ndx, uint_t type)
451981a172ab	match_item_t item_type = (match_flags & MATCH_F_PHDR) ?
452981a172ab	    MATCH_ITEM_PT  : MATCH_ITEM_SHT;
453981a172ab	match_rec_t *list;
455981a172ab	/*
456981a172ab	 * If there is no match list, then we use the MATCH_F_STRICT
457981a172ab	 * flag to decide what to return. In the strict case, we return
458981a172ab	 * False (0), in the normal case, True (1).
459981a172ab	 */
460981a172ab	if (match_state.list == NULL)
461981a172ab		return ((match_flags & MATCH_F_STRICT) == 0);
463981a172ab	/*
464981a172ab	 * If item being checked is not the current match type,
465981a172ab	 * then allow it.
466981a172ab	 */
467981a172ab	if (item_type != match_state.item_type)
468c809c40ab		return (1);
470c809c40ab	/* Run through the match records and check for a hit */
471981a172ab	for (list = match_state.list; list; list = list->next) {
472981a172ab		switch (list->opt_type) {
473981a172ab		case MATCH_OPT_NAME:
474981a172ab			if (((match_flags & MATCH_F_NAME) == 0) ||
475981a172ab			    (name == NULL))
476981a172ab				break;
477981a172ab			if (strcmp(list->value.name, name) == 0)
478c809c40ab				return (1);
479c809c40ab			break;
480981a172ab		case MATCH_OPT_NDX:
481981a172ab			if ((match_flags & MATCH_F_NDX) &&
482981a172ab			    (ndx == list->value.ndx.start))
483c809c40ab				return (1);
484c809c40ab			break;
485981a172ab		case MATCH_OPT_RANGE:
486c809c40ab			/*
487c809c40ab			 * A range end value less than 0 means that any value
488c809c40ab			 * above the start is acceptible.
489c809c40ab			 */
490981a172ab			if ((match_flags & MATCH_F_NDX) &&
491981a172ab			    (ndx >= list->value.ndx.start) &&
492c809c40ab			    ((list->value.ndx.end < 0) ||
493c809c40ab			    (ndx <= list->value.ndx.end)))
494c809c40ab				return (1);
495c809c40ab			break;
497981a172ab		case MATCH_OPT_TYPE:
498981a172ab			if ((match_flags & MATCH_F_TYPE) &&
499981a172ab			    (type == list->value.type))
500981a172ab				return (1);
501981a172ab			break;
502c809c40ab		}
503c809c40ab	}
505c809c40ab	/* Nothing matched */
506c809c40ab	return (0);
510981a172ab * Add an entry to match_state.list for use by match(). This routine is for
511981a172ab * use during getopt() processing. It should not be called once
512981a172ab * match_prepare() has been called.
513c809c40ab *
514c809c40ab * Return True (1) for success. On failure, an error is written
515c809c40ab * to stderr, and False (0) is returned.
516c809c40ab */
517c809c40abstatic int
518981a172abadd_match_record(char *argv0, match_rec_t *data)
520981a172ab	match_rec_t	*rec;
521981a172ab	match_rec_t	*list;
523c809c40ab	if ((rec = malloc(sizeof (*rec))) == NULL) {
524c809c40ab		int err = errno;
525c809c40ab		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
526c809c40ab		    basename(argv0), strerror(err));
527c809c40ab		return (0);
528c809c40ab	}
530c809c40ab	*rec = *data;
532981a172ab	/* Insert at end of match_state.list */
533981a172ab	if (match_state.list == NULL) {
534981a172ab		match_state.list = rec;
535c809c40ab	} else {
536981a172ab		for (list = match_state.list; list->next != NULL;
537981a172ab		    list = list->next)
538c809c40ab			;
539c809c40ab		list->next = rec;
540c809c40ab	}
542c809c40ab	rec->next = NULL;
543c809c40ab	return (1);
546981a172abstatic int
547981a172abdecide(const char *file, int fd, Elf *elf, uint_t flags,
5484f680ccAli Bahrami    const char *wname, int wfd, uchar_t osabi)
550981a172ab	int r;
5525aefb65rie	if (gelf_getclass(elf) == ELFCLASS64)
5534f680ccAli Bahrami		r = regular64(file, fd, elf, flags, wname, wfd, osabi);
5545aefb65rie	else
5554f680ccAli Bahrami		r = regular32(file, fd, elf, flags, wname, wfd, osabi);
557981a172ab	return (r);
560981a172abstatic int
561981a172abarchive(const char *file, int fd, Elf *elf, uint_t flags,
5624f680ccAli Bahrami    const char *wname, int wfd, uchar_t osabi)
5645aefb65rie	Elf_Cmd		cmd = ELF_C_READ;
5655aefb65rie	Elf_Arhdr	*arhdr;
5667e16fcaAli Bahrami	Elf		*_elf = NULL;
5675aefb65rie	size_t		ptr;
5687e16fcaAli Bahrami	Elf_Arsym	*arsym = NULL;
5705aefb65rie	/*
571d579eb6ab	 * Determine if the archive symbol table itself is required.
5725aefb65rie	 */
573981a172ab	if ((flags & FLG_SHOW_SYMBOLS) &&
574981a172ab	    match(MATCH_F_NAME, MSG_ORIG(MSG_ELF_ARSYM), 0, 0)) {
5755aefb65rie		/*
5765aefb65rie		 * Get the archive symbol table.
5775aefb65rie		 */
5785aefb65rie		if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) {
5795aefb65rie			/*
5805aefb65rie			 * The arsym could be 0 even though there was no error.
5815aefb65rie			 * Print the error message only when there was
5825aefb65rie			 * real error from elf_getarsym().
5835aefb65rie			 */
5845aefb65rie			failure(file, MSG_ORIG(MSG_ELF_GETARSYM));
585981a172ab			return (0);
5865aefb65rie		}
5875aefb65rie	}
5895aefb65rie	/*
5905aefb65rie	 * Print the archive symbol table only when the archive symbol
5915aefb65rie	 * table exists and it was requested to print.
5925aefb65rie	 */
5935aefb65rie	if (arsym) {
5945aefb65rie		size_t		cnt;
5955aefb65rie		char		index[MAXNDXSIZE];
5965aefb65rie		size_t		offset = 0, _offset = 0;
597ba7866cAli Bahrami		const char	*fmt_arsym1, *fmt_arsym2;
5995aefb65rie		/*
600ba7866cAli Bahrami		 * Print out all the symbol entries. The format width used
601ba7866cAli Bahrami		 * corresponds to whether the archive symbol table is 32
602ba7866cAli Bahrami		 * or 64-bit. We see them via Elf_Arhdr as size_t values
603ba7866cAli Bahrami		 * in either case with no information loss (see the comments
604ba7866cAli Bahrami		 * in libelf/getarsym.c) so this is done simply to improve
605ba7866cAli Bahrami		 * the user presentation.
6065aefb65rie		 */
607ba7866cAli Bahrami		if (_elf_getarsymwordsize(elf) == 8) {
608ba7866cAli Bahrami			dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_64));
609ba7866cAli Bahrami			dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_64));
610ba7866cAli Bahrami
611ba7866cAli Bahrami			fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_64);
612ba7866cAli Bahrami			fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_64);
613ba7866cAli Bahrami		} else {
614ba7866cAli Bahrami			dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_32));
615ba7866cAli Bahrami			dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_32));
616ba7866cAli Bahrami
617ba7866cAli Bahrami			fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_32);
618ba7866cAli Bahrami			fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_32);
619ba7866cAli Bahrami		}
6215aefb65rie		for (cnt = 0; cnt < ptr; cnt++, arsym++) {
6225aefb65rie			/*
6235aefb65rie			 * For each object obtain an elf descriptor so that we