Home | History | Annotate | Download | only in common
      1     0    stevel /*
      2     0    stevel  * CDDL HEADER START
      3     0    stevel  *
      4     0    stevel  * 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     0    stevel  *
      8     0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0    stevel  * or http://www.opensolaris.org/os/licensing.
     10     0    stevel  * See the License for the specific language governing permissions
     11     0    stevel  * and limitations under the License.
     12     0    stevel  *
     13     0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0    stevel  *
     19     0    stevel  * CDDL HEADER END
     20     0    stevel  */
     21  1324       rie 
     22     0    stevel /*
     23  8747       Ali  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24     0    stevel  * Use is subject to license terms.
     25     0    stevel  */
     26     0    stevel 
     27     0    stevel /*
     28     0    stevel  * Dump an elf file.
     29     0    stevel  */
     30  9406       Ali #include	<stddef.h>
     31  1618       rie #include	<sys/elf_386.h>
     32  1618       rie #include	<sys/elf_amd64.h>
     33  1618       rie #include	<sys/elf_SPARC.h>
     34  6206  ab196087 #include	<_libelf.h>
     35  1618       rie #include	<dwarf.h>
     36  5549       rie #include	<stdio.h>
     37     0    stevel #include	<unistd.h>
     38     0    stevel #include	<errno.h>
     39     0    stevel #include	<strings.h>
     40     0    stevel #include	<debug.h>
     41     0    stevel #include	<conv.h>
     42     0    stevel #include	<msg.h>
     43  1618       rie #include	<_elfdump.h>
     44  3875  ab196087 
     45  3875  ab196087 
     46  3875  ab196087 /*
     47  3875  ab196087  * VERSYM_STATE is used to maintain information about the VERSYM section
     48  3875  ab196087  * in the object being analyzed. It is filled in by versions(), and used
     49  3875  ab196087  * by init_symtbl_state() when displaying symbol information.
     50  3875  ab196087  *
     51  7682       Ali  * There are three forms of symbol versioning known to us:
     52  7682       Ali  *
     53  7682       Ali  * 1) The original form, introduced with Solaris 2.5, in which
     54  7682       Ali  *	the Versym contains indexes to Verdef records, and the
     55  7682       Ali  *	Versym values for UNDEF symbols resolved by other objects
     56  7682       Ali  *	are all set to 0.
     57  7682       Ali  * 2) The GNU form, which is backward compatible with the original
     58  7682       Ali  *	Solaris form, but which adds several extensions:
     59  7682       Ali  *	- The Versym also contains indexes to Verneed records, recording
     60  7682       Ali  *		which object/version contributed the external symbol at
     61  7682       Ali  *		link time. These indexes start with the next value following
     62  7682       Ali  *		the final Verdef index. The index is written to the previously
     63  7682       Ali  *		reserved vna_other field of the ELF Vernaux structure.
     64  7682       Ali  *	- The top bit of the Versym value is no longer part of the index,
     65  7682       Ali  *		but is used as a "hidden bit" to prevent binding to the symbol.
     66  7682       Ali  *	- Multiple implementations of a given symbol, contained in varying
     67  7682       Ali  *		versions are allowed, using special assembler pseudo ops,
     68  7682       Ali  *		and encoded in the symbol name using '@' characters.
     69  7682       Ali  * 3) Modified Solaris form, in which we adopt the first GNU extension
     70  7682       Ali  *	(Versym indexes to Verneed records), but not the others.
     71  7682       Ali  *
     72  7682       Ali  * elfdump can handle any of these cases. The presence of a DT_VERSYM
     73  7682       Ali  * dynamic element indicates a full GNU object. An object that lacks
     74  7682       Ali  * a DT_VERSYM entry, but which has non-zero vna_other fields in the Vernaux
     75  7682       Ali  * structures is a modified Solaris object. An object that has neither of
     76  7682       Ali  * these uses the original form.
     77  7682       Ali  *
     78  4716  ab196087  * max_verndx contains the largest version index that can appear
     79  4716  ab196087  * in a Versym entry. This can never be less than 1: In the case where
     80  4716  ab196087  * there is no verdef/verneed sections, the [0] index is reserved
     81  7682       Ali  * for local symbols, and the [1] index for globals. If the original
     82  7682       Ali  * Solaris versioning rules are in effect and there is a verdef section,
     83  7682       Ali  * then max_verndex is the number of defined versions. If one of the
     84  7682       Ali  * other versioning forms is in effect, then:
     85  7682       Ali  *	1) If there is no verneed section, it is the same as for
     86  7682       Ali  *		original Solaris versioning.
     87  7682       Ali  *	2) If there is a verneed section, the vna_other field of the
     88  4716  ab196087  *		Vernaux structs contain versions, and max_verndx is the
     89  4716  ab196087  *		largest such index.
     90  4716  ab196087  *
     91  7682       Ali  * If gnu_full is True, the object uses the full GNU form of versioning.
     92  7682       Ali  * The value of the gnu_full field is based on the presence of
     93  4716  ab196087  * a DT_VERSYM entry in the dynamic section: GNU ld produces these, and
     94  4716  ab196087  * Solaris ld does not.
     95  7682       Ali  *
     96  7682       Ali  * The gnu_needed field is True if the Versym contains indexes to
     97  7682       Ali  * Verneed records, as indicated by non-zero vna_other fields in the Verneed
     98  7682       Ali  * section. If gnu_full is True, then gnu_needed will always be true.
     99  7682       Ali  * However, gnu_needed can be true without gnu_full. This is the modified
    100  7682       Ali  * Solaris form.
    101  3875  ab196087  */
    102  3875  ab196087 typedef struct {
    103  3875  ab196087 	Cache	*cache;		/* Pointer to cache entry for VERSYM */
    104  3875  ab196087 	Versym	*data;		/* Pointer to versym array */
    105  7682       Ali 	int	gnu_full;	/* True if object uses GNU versioning rules */
    106  7682       Ali 	int	gnu_needed;	/* True if object uses VERSYM indexes for */
    107  7682       Ali 				/*	VERNEED (subset of gnu_full) */
    108  4716  ab196087 	int	max_verndx;	/* largest versym index value */
    109  3875  ab196087 } VERSYM_STATE;
    110  3875  ab196087 
    111  3875  ab196087 /*
    112  3875  ab196087  * SYMTBL_STATE is used to maintain information about a single symbol
    113  3875  ab196087  * table section, for use by the routines that display symbol information.
    114  3875  ab196087  */
    115  3875  ab196087 typedef struct {
    116  3875  ab196087 	const char	*file;		/* Name of file */
    117  3875  ab196087 	Ehdr		*ehdr;		/* ELF header for file */
    118  3875  ab196087 	Cache		*cache;		/* Cache of all section headers */
    119  9273       Ali 	uchar_t		osabi;		/* OSABI to use */
    120  3875  ab196087 	Word		shnum;		/* # of sections in cache */
    121  3875  ab196087 	Cache		*seccache;	/* Cache of symbol table section hdr */
    122  3875  ab196087 	Word		secndx;		/* Index of symbol table section hdr */
    123  3875  ab196087 	const char	*secname;	/* Name of section */
    124  3875  ab196087 	uint_t		flags;		/* Command line option flags */
    125  3875  ab196087 	struct {			/* Extended section index data */
    126  3875  ab196087 		int	checked;	/* TRUE if already checked for shxndx */
    127  3875  ab196087 		Word	*data;		/* NULL, or extended section index */
    128  3875  ab196087 					/*	used for symbol table entries */
    129  3875  ab196087 		uint_t	n;		/* # items in shxndx.data */
    130  3875  ab196087 	} shxndx;
    131  3875  ab196087 	VERSYM_STATE	*versym;	/* NULL, or associated VERSYM section */
    132  3875  ab196087 	Sym 		*sym;		/* Array of symbols */
    133  3875  ab196087 	Word		symn;		/* # of symbols */
    134  3875  ab196087 } SYMTBL_STATE;
    135  3875  ab196087 
    136  9406       Ali /*
    137  9406       Ali  * A variable of this type is used to track information related to
    138  9406       Ali  * .eh_frame and .eh_frame_hdr sections across calls to unwind_eh_frame().
    139  9406       Ali  */
    140  9406       Ali typedef struct {
    141  9406       Ali 	Word		frame_cnt;	/* # .eh_frame sections seen */
    142  9406       Ali 	Word		frame_ndx;	/* Section index of 1st .eh_frame */
    143  9406       Ali 	Word		hdr_cnt;	/* # .eh_frame_hdr sections seen */
    144  9406       Ali 	Word		hdr_ndx;	/* Section index of 1st .eh_frame_hdr */
    145  9406       Ali 	uint64_t	frame_ptr;	/* Value of FramePtr field from first */
    146  9406       Ali 					/*	.eh_frame_hdr section */
    147  9406       Ali 	uint64_t	frame_base;	/* Data addr of 1st .eh_frame  */
    148  9406       Ali } gnu_eh_state_t;
    149  9406       Ali 
    150  9406       Ali /*
    151  9406       Ali  * C++ .exception_ranges entries make use of the signed ptrdiff_t
    152  9406       Ali  * type to record self-relative pointer values. We need a type
    153  9406       Ali  * for this that is matched to the ELFCLASS being processed.
    154  9406       Ali  */
    155  9406       Ali #if	defined(_ELF64)
    156  9406       Ali 	typedef int64_t PTRDIFF_T;
    157  9406       Ali #else
    158  9406       Ali 	typedef int32_t PTRDIFF_T;
    159  9406       Ali #endif
    160  9406       Ali 
    161  9406       Ali /*
    162  9406       Ali  * The Sun C++ ABI uses this struct to define each .exception_ranges
    163  9406       Ali  * entry. From the ABI:
    164  9406       Ali  *
    165  9406       Ali  * The field ret_addr is a self relative pointer to the start of the address
    166  9406       Ali  * range. The name was chosen because in the current implementation the range
    167  9406       Ali  * typically starts at the return address for a call site.
    168  9406       Ali  *
    169  9406       Ali  * The field length is the difference, in bytes, between the pc of the last
    170  9406       Ali  * instruction covered by the exception range and the first. When only a
    171  9406       Ali  * single call site is represented without optimization, this will equal zero.
    172  9406       Ali  *
    173  9406       Ali  * The field handler_addr is a relative pointer which stores the difference
    174  9406       Ali  * between the start of the exception range and the address of all code to
    175  9406       Ali  * catch exceptions and perform the cleanup for stack unwinding.
    176  9406       Ali  *
    177  9406       Ali  * The field type_block is a relative pointer which stores the difference
    178  9406       Ali  * between the start of the exception range and the address of an array used
    179  9406       Ali  * for storing a list of the types of exceptions which can be caught within
    180  9406       Ali  * the exception range.
    181  9406       Ali  */
    182  9406       Ali typedef struct {
    183  9406       Ali 	PTRDIFF_T	ret_addr;
    184  9406       Ali 	Xword		length;
    185  9406       Ali 	PTRDIFF_T	handler_addr;
    186  9406       Ali 	PTRDIFF_T	type_block;
    187  9406       Ali 	Xword		reserved;
    188  9406       Ali } exception_range_entry;
    189     0    stevel 
    190     0    stevel /*
    191     0    stevel  * Focal point for verifying symbol names.
    192     0    stevel  */
    193     0    stevel static const char *
    194  1618       rie string(Cache *refsec, Word ndx, Cache *strsec, const char *file, Word name)
    195     0    stevel {
    196  4063  ab196087 	/*
    197  4063  ab196087 	 * If an error in this routine is due to a property of the string
    198  4063  ab196087 	 * section, as opposed to a bad offset into the section (a property of
    199  4063  ab196087 	 * the referencing section), then we will detect the same error on
    200  4063  ab196087 	 * every call involving those sections. We use these static variables
    201  4063  ab196087 	 * to retain the information needed to only issue each such error once.
    202  4063  ab196087 	 */
    203  4063  ab196087 	static Cache	*last_refsec;	/* Last referencing section seen */
    204  4063  ab196087 	static int	strsec_err;	/* True if error issued */
    205  4063  ab196087 
    206  3492  ab196087 	const char	*strs;
    207  3492  ab196087 	Word		strn;
    208  3466       rie 
    209  3466       rie 	if (strsec->c_data == NULL)
    210  3466       rie 		return (NULL);
    211     0    stevel 
    212  3492  ab196087 	strs = (char *)strsec->c_data->d_buf;
    213  3492  ab196087 	strn = strsec->c_data->d_size;
    214     0    stevel 
    215     0    stevel 	/*
    216  4063  ab196087 	 * We only print a diagnostic regarding a bad string table once per
    217  4063  ab196087 	 * input section being processed. If the refsec has changed, reset
    218  4063  ab196087 	 * our retained error state.
    219     0    stevel 	 */
    220  4063  ab196087 	if (last_refsec != refsec) {
    221  4063  ab196087 		last_refsec = refsec;
    222  4063  ab196087 		strsec_err = 0;
    223  4063  ab196087 	}
    224  4063  ab196087 
    225  4063  ab196087 	/* Verify that strsec really is a string table */
    226  4063  ab196087 	if (strsec->c_shdr->sh_type != SHT_STRTAB) {
    227  4063  ab196087 		if (!strsec_err) {
    228  4063  ab196087 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_NOTSTRTAB),
    229  4063  ab196087 			    file, strsec->c_ndx, refsec->c_ndx);
    230  4063  ab196087 			strsec_err = 1;
    231  4063  ab196087 		}
    232  4063  ab196087 		return (MSG_INTL(MSG_STR_UNKNOWN));
    233     0    stevel 	}
    234     0    stevel 
    235     0    stevel 	/*
    236     0    stevel 	 * Is the string table offset within range of the available strings?
    237     0    stevel 	 */
    238     0    stevel 	if (name >= strn) {
    239     0    stevel 		/*
    240     0    stevel 		 * Do we have a empty string table?
    241     0    stevel 		 */
    242  9085       Ali 		if (strs == NULL) {
    243  4063  ab196087 			if (!strsec_err) {
    244     0    stevel 				(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
    245     0    stevel 				    file, strsec->c_name);
    246  4063  ab196087 				strsec_err = 1;
    247     0    stevel 			}
    248     0    stevel 		} else {
    249     0    stevel 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSTOFF),
    250  1618       rie 			    file, refsec->c_name, EC_WORD(ndx), strsec->c_name,
    251  1618       rie 			    EC_WORD(name), EC_WORD(strn - 1));
    252     0    stevel 		}
    253     0    stevel 
    254     0    stevel 		/*
    255     0    stevel 		 * Return the empty string so that the calling function can
    256     0    stevel 		 * continue it's output diagnostics.
    257     0    stevel 		 */
    258     0    stevel 		return (MSG_INTL(MSG_STR_UNKNOWN));
    259     0    stevel 	}
    260     0    stevel 	return (strs + name);
    261     0    stevel }
    262     0    stevel 
    263     0    stevel /*
    264  1618       rie  * Relocations can reference section symbols and standard symbols.  If the
    265  1618       rie  * former, establish the section name.
    266  1618       rie  */
    267  1618       rie static const char *
    268  1618       rie relsymname(Cache *cache, Cache *csec, Cache *strsec, Word symndx, Word symnum,
    269  7463       Rod     Word relndx, Sym *syms, char *secstr, size_t secsz, const char *file)
    270  7463       Rod {
    271  7463       Rod 	Sym		*sym;
    272  7463       Rod 	const char	*name;
    273  1618       rie 
    274  1618       rie 	if (symndx >= symnum) {
    275  1618       rie 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_RELBADSYMNDX),
    276  1618       rie 		    file, EC_WORD(symndx), EC_WORD(relndx));
    277  1618       rie 		return (MSG_INTL(MSG_STR_UNKNOWN));
    278  1618       rie 	}
    279  1618       rie 
    280  1618       rie 	sym = (Sym *)(syms + symndx);
    281  7463       Rod 	name = string(csec, symndx, strsec, file, sym->st_name);
    282  1618       rie 
    283  1618       rie 	/*
    284  1618       rie 	 * If the symbol represents a section offset construct an appropriate
    285  7463       Rod 	 * string.  Note, although section symbol table entries typically have
    286  7463       Rod 	 * a NULL name pointer, entries do exist that point into the string
    287  7463       Rod 	 * table to their own NULL strings.
    288  7463       Rod 	 */
    289  7463       Rod 	if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) &&
    290  7463       Rod 	    ((sym->st_name == 0) || (*name == '\0'))) {
    291  7463       Rod 		(void) snprintf(secstr, secsz, MSG_INTL(MSG_STR_SECTION),
    292  7463       Rod 		    cache[sym->st_shndx].c_name);
    293  1618       rie 		return ((const char *)secstr);
    294  1618       rie 	}
    295  1618       rie 
    296  7463       Rod 	return (name);
    297  1618       rie }
    298  1618       rie 
    299  1618       rie /*
    300  1618       rie  * Focal point for establishing a string table section.  Data such as the
    301  1618       rie  * dynamic information simply points to a string table.  Data such as
    302  1618       rie  * relocations, reference a symbol table, which in turn is associated with a
    303  1618       rie  * string table.
    304     0    stevel  */
    305     0    stevel static int
    306  1618       rie stringtbl(Cache *cache, int symtab, Word ndx, Word shnum, const char *file,
    307  1618       rie     Word *symnum, Cache **symsec, Cache **strsec)
    308  1618       rie {
    309  1618       rie 	Shdr	*shdr = cache[ndx].c_shdr;
    310  1618       rie 
    311  1618       rie 	if (symtab) {
    312  1618       rie 		/*
    313  1618       rie 		 * Validate the symbol table section.
    314  1618       rie 		 */
    315  1618       rie 		if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
    316  1618       rie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
    317  1618       rie 			    file, cache[ndx].c_name, EC_WORD(shdr->sh_link));
    318  1618       rie 			return (0);
    319  1618       rie 		}
    320  3466       rie 		if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
    321  3466       rie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
    322  3466       rie 			    file, cache[ndx].c_name);
    323  3466       rie 			return (0);
    324  3466       rie 		}
    325  1618       rie 
    326  1618       rie 		/*
    327  1618       rie 		 * Obtain, and verify the symbol table data.
    328  1618       rie 		 */
    329  3466       rie 		if ((cache[ndx].c_data == NULL) ||
    330  3466       rie 		    (cache[ndx].c_data->d_buf == NULL)) {
    331  1618       rie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
    332  1618       rie 			    file, cache[ndx].c_name);
    333  1618       rie 			return (0);
    334  1618       rie 		}
    335  1618       rie 
    336  1618       rie 		/*
    337  1618       rie 		 * Establish the string table index.
    338  1618       rie 		 */
    339  1618       rie 		ndx = shdr->sh_link;
    340  1618       rie 		shdr = cache[ndx].c_shdr;
    341  1618       rie 
    342  1618       rie 		/*
    343  1618       rie 		 * Return symbol table information.
    344  1618       rie 		 */
    345  1618       rie 		if (symnum)
    346  1618       rie 			*symnum = (shdr->sh_size / shdr->sh_entsize);
    347  1618       rie 		if (symsec)
    348  1618       rie 			*symsec = &cache[ndx];
    349  1618       rie 	}
    350  1618       rie 
    351  1618       rie 	/*
    352  1618       rie 	 * Validate the associated string table section.
    353  1618       rie 	 */
    354  1618       rie 	if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
    355  1618       rie 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
    356  1618       rie 		    file, cache[ndx].c_name, EC_WORD(shdr->sh_link));
    357  1618       rie 		return (0);
    358  1618       rie 	}
    359  1618       rie 
    360  1618       rie 	if (strsec)
    361  1618       rie 		*strsec = &cache[shdr->sh_link];
    362  1618       rie 
    363  1618       rie 	return (1);
    364  1618       rie }
    365  1618       rie 
    366  1618       rie /*
    367  1618       rie  * Lookup a symbol and set Sym accordingly.
    368  1618       rie  */
    369  1618       rie static int
    370  1618       rie symlookup(const char *name, Cache *cache, Word shnum, Sym **sym,
    371     0    stevel     Cache *symtab, const char *file)
    372     0    stevel {
    373  1618       rie 	Shdr	*shdr;
    374  1618       rie 	Word	symn, cnt;
    375  1618       rie 	Sym	*syms;
    376     0    stevel 
    377     0    stevel 	if (symtab == 0)
    378     0    stevel 		return (0);
    379     0    stevel 
    380  1618       rie 	shdr = symtab->c_shdr;
    381  1618       rie 
    382     0    stevel 	/*
    383     0    stevel 	 * Determine the symbol data and number.
    384     0    stevel 	 */
    385     0    stevel 	if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
    386     0    stevel 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
    387     0    stevel 		    file, symtab->c_name);
    388     0    stevel 		return (0);
    389     0    stevel 	}
    390  3466       rie 	if (symtab->c_data == NULL)
    391  3466       rie 		return (0);
    392  3466       rie 
    393     0    stevel 	/* LINTED */
    394  1618       rie 	symn = (Word)(shdr->sh_size / shdr->sh_entsize);
    395  1618       rie 	syms = (Sym *)symtab->c_data->d_buf;
    396     0    stevel 
    397     0    stevel 	/*
    398     0    stevel 	 * Get the associated string table section.
    399     0    stevel 	 */
    400     0    stevel 	if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
    401     0    stevel 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
    402  1618       rie 		    file, symtab->c_name, EC_WORD(shdr->sh_link));
    403     0    stevel 		return (0);
    404     0    stevel 	}
    405     0    stevel 
    406     0    stevel 	/*
    407     0    stevel 	 * Loop through the symbol table to find a match.
    408     0    stevel 	 */
    409  1618       rie 	for (cnt = 0; cnt < symn; syms++, cnt++) {
    410  1618       rie 		const char	*symname;
    411     0    stevel 
    412  1618       rie 		symname = string(symtab, cnt, &cache[shdr->sh_link], file,
    413  1618       rie 		    syms->st_name);
    414     0    stevel 
    415  1618       rie 		if (symname && (strcmp(name, symname) == 0)) {
    416  1618       rie 			*sym = syms;
    417     0    stevel 			return (1);
    418     0    stevel 		}
    419     0    stevel 	}
    420     0    stevel 	return (0);
    421     0    stevel }
    422     0    stevel 
    423     0    stevel /*
    424     0    stevel  * Print section headers.
    425     0    stevel  */
    426     0    stevel static void
    427  9273       Ali sections(const char *file, Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi)
    428     0    stevel {
    429  1618       rie 	size_t	seccnt;
    430     0    stevel 
    431  1618       rie 	for (seccnt = 1; seccnt < shnum; seccnt++) {
    432  1618       rie 		Cache		*_cache = &cache[seccnt];
    433  1618       rie 		Shdr		*shdr = _cache->c_shdr;
    434  1618       rie 		const char	*secname = _cache->c_name;
    435     0    stevel 
    436     0    stevel 		/*
    437     0    stevel 		 * Although numerous section header entries can be zero, it's
    438  3862       rie 		 * usually a sign of trouble if the type is zero.
    439     0    stevel 		 */
    440     0    stevel 		if (shdr->sh_type == 0) {
    441     0    stevel 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE),
    442  1618       rie 			    file, secname, EC_WORD(shdr->sh_type));
    443     0    stevel 		}
    444     0    stevel 
    445  5411  ab196087 		if (!match(MATCH_F_ALL, secname, seccnt, shdr->sh_type))
    446  3862       rie 			continue;
    447  1324       rie 
    448  1324       rie 		/*
    449  1324       rie 		 * Identify any sections that are suspicious.  A .got section
    450  1324       rie 		 * shouldn't exist in a relocatable object.
    451  1324       rie 		 */
    452  1324       rie 		if (ehdr->e_type == ET_REL) {
    453  1618       rie 			if (strncmp(secname, MSG_ORIG(MSG_ELF_GOT),
    454  1324       rie 			    MSG_ELF_GOT_SIZE) == 0) {
    455  1324       rie 				(void) fprintf(stderr,
    456  1618       rie 				    MSG_INTL(MSG_GOT_UNEXPECTED), file,
    457  1618       rie 				    secname);
    458  1324       rie 			}
    459     0    stevel 		}
    460     0    stevel 
    461  1618       rie 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
    462  1618       rie 		dbg_print(0, MSG_INTL(MSG_ELF_SHDR), EC_WORD(seccnt), secname);
    463  9273       Ali 		Elf_shdr(0, osabi, ehdr->e_machine, shdr);
    464     0    stevel 	}
    465     0    stevel }
    466     0    stevel 
    467  1618       rie /*
    468  1618       rie  * Obtain a specified Phdr entry.
    469  1618       rie  */
    470  1618       rie static Phdr *
    471  9085       Ali getphdr(Word phnum, Word *type_arr, Word type_cnt, const char *file, Elf *elf)
    472  9085       Ali {
    473  9085       Ali 	Word	cnt, tcnt;
    474  1618       rie 	Phdr	*phdr;
    475  1618       rie 
    476  1618       rie 	if ((phdr = elf_getphdr(elf)) == NULL) {
    477  1618       rie 		failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
    478  9085       Ali 		return (NULL);
    479  1618       rie 	}
    480  1618       rie 
    481  1618       rie 	for (cnt = 0; cnt < phnum; phdr++, cnt++) {
    482  9085       Ali 		for (tcnt = 0; tcnt < type_cnt; tcnt++) {
    483  9085       Ali 			if (phdr->p_type == type_arr[tcnt])
    484  9085       Ali 				return (phdr);
    485  9085       Ali 		}
    486  9085       Ali 	}
    487  9085       Ali 	return (NULL);
    488  1618       rie }
    489  1618       rie 
    490  9406       Ali /*
    491  9406       Ali  * Display the contents of GNU/amd64 .eh_frame and .eh_frame_hdr
    492  9406       Ali  * sections.
    493  9406       Ali  *
    494  9406       Ali  * entry:
    495  9406       Ali  *	cache - Cache of all section headers
    496  9406       Ali  *	shndx - Index of .eh_frame or .eh_frame_hdr section to be displayed
    497  9406       Ali  *	uphdr - NULL, or unwind program header associated with
    498  9406       Ali  *		the .eh_frame_hdr section.
    499  9406       Ali  *	ehdr - ELF header for file
    500  9406       Ali  *	eh_state - Data used across calls to this routine. The
    501  9406       Ali  *		caller should zero it before the first call, and
    502  9406       Ali  *		pass it on every call.
    503  9406       Ali  *	osabi - OSABI to use in displaying information
    504  9406       Ali  *	file - Name of file
    505  9406       Ali  *	flags - Command line option flags
    506  9406       Ali  */
    507  9406       Ali static void
    508  9406       Ali unwind_eh_frame(Cache *cache, Word shndx, Phdr *uphdr, Ehdr *ehdr,
    509  9406       Ali     gnu_eh_state_t *eh_state, uchar_t osabi, const char *file, uint_t flags)
    510  1618       rie {
    511  9085       Ali #if	defined(_ELF64)
    512  9085       Ali #define	MSG_UNW_BINSRTAB2	MSG_UNW_BINSRTAB2_64
    513  9085       Ali #define	MSG_UNW_BINSRTABENT	MSG_UNW_BINSRTABENT_64
    514  9085       Ali #else
    515  9085       Ali #define	MSG_UNW_BINSRTAB2	MSG_UNW_BINSRTAB2_32
    516  9085       Ali #define	MSG_UNW_BINSRTABENT	MSG_UNW_BINSRTABENT_32
    517  9085       Ali #endif
    518  9085       Ali 
    519  9406       Ali 	Cache			*_cache = &cache[shndx];
    520  9406       Ali 	Shdr			*shdr = _cache->c_shdr;
    521  9406       Ali 	uchar_t			*data = (uchar_t *)(_cache->c_data->d_buf);
    522  9406       Ali 	size_t			datasize = _cache->c_data->d_size;
    523  9406       Ali 	Conv_dwarf_ehe_buf_t	dwarf_ehe_buf;
    524  9406       Ali 	uint64_t		ndx, frame_ptr, fde_cnt, tabndx;
    525  9406       Ali 	uint_t			vers, frame_ptr_enc, fde_cnt_enc, table_enc;
    526  9406       Ali 	uint64_t		initloc, initloc0;
    527  9406       Ali 
    528  9406       Ali 
    529  9406       Ali 	/*
    530  9406       Ali 	 * Is this a .eh_frame_hdr?
    531  9406       Ali 	 */
    532  9406       Ali 	if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) ||
    533  9406       Ali 	    (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR),
    534  9406       Ali 	    MSG_SCN_FRMHDR_SIZE) == 0)) {
    535  9406       Ali 		/*
    536  9406       Ali 		 * There can only be a single .eh_frame_hdr.
    537  9406       Ali 		 * Flag duplicates.
    538  9406       Ali 		 */
    539  9406       Ali 		if (++eh_state->hdr_cnt > 1)
    540  9406       Ali 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_MULTEHFRMHDR),
    541  9406       Ali 			    file, EC_WORD(shndx), _cache->c_name);
    542  9406       Ali 
    543  9406       Ali 		dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR));
    544  9406       Ali 		ndx = 0;
    545  9406       Ali 
    546  9406       Ali 		vers = data[ndx++];
    547  9406       Ali 		frame_ptr_enc = data[ndx++];
    548  9406       Ali 		fde_cnt_enc = data[ndx++];
    549  9406       Ali 		table_enc = data[ndx++];
    550  9406       Ali 
    551  9406       Ali 		dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers);
    552  9406       Ali 
    553  9406       Ali 		frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc,
    554  9406       Ali 		    ehdr->e_ident, shdr->sh_addr, ndx);
    555  9406       Ali 		if (eh_state->hdr_cnt == 1) {
    556  9406       Ali 			eh_state->hdr_ndx = shndx;
    557  9406       Ali 			eh_state->frame_ptr = frame_ptr;
    558  9406       Ali 		}
    559  9406       Ali 
    560  9406       Ali 		dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC),
    561  9406       Ali 		    conv_dwarf_ehe(frame_ptr_enc, &dwarf_ehe_buf),
    562  9406       Ali 		    EC_XWORD(frame_ptr));
    563  9406       Ali 
    564  9406       Ali 		fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc,
    565  9406       Ali 		    ehdr->e_ident, shdr->sh_addr, ndx);
    566  9406       Ali 
    567  9406       Ali 		dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC),
    568  9406       Ali 		    conv_dwarf_ehe(fde_cnt_enc, &dwarf_ehe_buf),
    569  9406       Ali 		    EC_XWORD(fde_cnt));
    570  9406       Ali 		dbg_print(0, MSG_ORIG(MSG_UNW_TABENC),
    571  9406       Ali 		    conv_dwarf_ehe(table_enc, &dwarf_ehe_buf));
    572  9406       Ali 		dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1));
    573  9406       Ali 		dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2));
    574  9406       Ali 
    575  9406       Ali 		for (tabndx = 0; tabndx < fde_cnt; tabndx++) {
    576  9406       Ali 			initloc = dwarf_ehe_extract(data, &ndx, table_enc,
    577  9406       Ali 			    ehdr->e_ident, shdr->sh_addr, ndx);
    578  9406       Ali 			/*LINTED:E_VAR_USED_BEFORE_SET*/
    579  9406       Ali 			if ((tabndx != 0) && (initloc0 > initloc))
    580  9615       Ali 				(void) fprintf(stderr,
    581  9615       Ali 				    MSG_INTL(MSG_ERR_BADSORT), file,
    582  9615       Ali 				    _cache->c_name, EC_WORD(tabndx));
    583  9406       Ali 			dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT),
    584  9406       Ali 			    EC_XWORD(initloc),
    585  9406       Ali 			    EC_XWORD(dwarf_ehe_extract(data, &ndx,
    586  9406       Ali 			    table_enc, ehdr->e_ident, shdr->sh_addr,
    587  9406       Ali 			    ndx)));
    588  9406       Ali 			initloc0 = initloc;
    589  9406       Ali 		}
    590  9406       Ali 	} else {		/* Display the .eh_frame section */
    591  9406       Ali 		eh_state->frame_cnt++;
    592  9406       Ali 		if (eh_state->frame_cnt == 1) {
    593  9406       Ali 			eh_state->frame_ndx = shndx;
    594  9406       Ali 			eh_state->frame_base = shdr->sh_addr;
    595  9406       Ali 		} else if ((eh_state->frame_cnt >  1) &&
    596  9406       Ali 		    (ehdr->e_type != ET_REL)) {
    597  9406       Ali 			Conv_inv_buf_t	inv_buf;
    598  9406       Ali 
    599  9406       Ali 			(void) fprintf(stderr, MSG_INTL(MSG_WARN_MULTEHFRM),
    600  9406       Ali 			    file, EC_WORD(shndx), _cache->c_name,
    601  9406       Ali 			    conv_ehdr_type(osabi, ehdr->e_type, 0, &inv_buf));
    602  9406       Ali 		}
    603  9406       Ali 		dump_eh_frame(data, datasize, shdr->sh_addr,
    604  9406       Ali 		    ehdr->e_machine, ehdr->e_ident);
    605  9406       Ali 	}
    606  9406       Ali 
    607  9406       Ali 	/*
    608  9406       Ali 	 * If we've seen the .eh_frame_hdr and the first .eh_frame section,
    609  9406       Ali 	 * compare the header frame_ptr to the address of the actual frame
    610  9406       Ali 	 * section to ensure the link-editor got this right.  Note, this
    611  9406       Ali 	 * diagnostic is only produced when unwind information is explicitly
    612  9406       Ali 	 * asked for, as shared objects built with an older ld(1) may reveal
    613  9406       Ali 	 * this inconsistency.  Although an inconsistency, it doesn't seem to
    614  9406       Ali 	 * have any adverse effect on existing tools.
    615  9406       Ali 	 */
    616  9406       Ali 	if (((flags & FLG_MASK_SHOW) != FLG_MASK_SHOW) &&
    617  9406       Ali 	    (eh_state->hdr_cnt > 0) && (eh_state->frame_cnt > 0) &&
    618  9406       Ali 	    (eh_state->frame_ptr != eh_state->frame_base))
    619  9406       Ali 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADEHFRMPTR),
    620  9406       Ali 		    file, EC_WORD(eh_state->hdr_ndx),
    621  9406       Ali 		    cache[eh_state->hdr_ndx].c_name,
    622  9406       Ali 		    EC_XWORD(eh_state->frame_ptr),
    623  9406       Ali 		    EC_WORD(eh_state->frame_ndx),
    624  9406       Ali 		    cache[eh_state->frame_ndx].c_name,
    625  9406       Ali 		    EC_XWORD(eh_state->frame_base));
    626  9406       Ali #undef MSG_UNW_BINSRTAB2
    627  9406       Ali #undef MSG_UNW_BINSRTABENT
    628  9406       Ali }
    629  9406       Ali 
    630  9406       Ali /*
    631  9406       Ali  * Convert a self relative pointer into an address. A self relative
    632  9406       Ali  * pointer adds the address where the pointer resides to the offset
    633  9406       Ali  * contained in the pointer. The benefit is that the value of the
    634  9406       Ali  * pointer does not require relocation.
    635  9406       Ali  *
    636  9406       Ali  * entry:
    637  9406       Ali  *	base_addr - Address of the pointer.
    638  9406       Ali  *	delta - Offset relative to base_addr giving desired address
    639  9406       Ali  *
    640  9406       Ali  * exit:
    641  9406       Ali  *	The computed address is returned.
    642  9406       Ali  *
    643  9406       Ali  * note:
    644  9406       Ali  *	base_addr is an unsigned value, while ret_addr is signed. This routine
    645  9406       Ali  *	used explicit testing and casting to explicitly control type
    646  9406       Ali  *	conversion, and ensure that we handle the maximum possible range.
    647  9406       Ali  */
    648  9406       Ali static Addr
    649  9406       Ali srelptr(Addr base_addr, PTRDIFF_T delta)
    650  9406       Ali {
    651  9406       Ali 	if (delta < 0)
    652  9406       Ali 		return (base_addr - (Addr) (-delta));
    653  9406       Ali 
    654  9406       Ali 	return (base_addr + (Addr) delta);
    655  9406       Ali }
    656  9406       Ali 
    657  9406       Ali /*
    658  9406       Ali  * Byte swap a PTRDIFF_T value.
    659  9406       Ali  */
    660  9406       Ali static PTRDIFF_T
    661  9406       Ali swap_ptrdiff(PTRDIFF_T value)
    662  9406       Ali {
    663  9406       Ali 	PTRDIFF_T r;
    664  9406       Ali 	uchar_t	*dst = (uchar_t *)&r;
    665  9406       Ali 	uchar_t	*src = (uchar_t *)&value;
    666  9406       Ali 
    667  9406       Ali 	UL_ASSIGN_BSWAP_XWORD(dst, src);
    668  9406       Ali 	return (r);
    669  9406       Ali }
    670  9406       Ali 
    671  9406       Ali /*
    672  9406       Ali  * Display exception_range_entry items from the .exception_ranges section
    673  9406       Ali  * of a Sun C++ object.
    674  9406       Ali  */
    675  9406       Ali static void
    676  9406       Ali unwind_exception_ranges(Cache *_cache, const char *file, int do_swap)
    677  9406       Ali {
    678  9406       Ali 	/*
    679  9406       Ali 	 * Translate a PTRDIFF_T self-relative address field of
    680  9406       Ali 	 * an exception_range_entry struct into an address.
    681  9406       Ali 	 *
    682  9406       Ali 	 * entry:
    683  9406       Ali 	 *	exc_addr - Address of base of exception_range_entry struct
    684  9406       Ali 	 *	cur_ent - Pointer to data in the struct to be translated
    685  9406       Ali 	 *
    686  9406       Ali 	 *	_f - Field of struct to be translated
    687  9406       Ali 	 */
    688  9406       Ali #define	SRELPTR(_f) \
    689  9406       Ali 	srelptr(exc_addr + offsetof(exception_range_entry, _f), cur_ent->_f)
    690  9406       Ali 
    691  9406       Ali #if	defined(_ELF64)
    692  9406       Ali #define	MSG_EXR_TITLE	MSG_EXR_TITLE_64
    693  9406       Ali #define	MSG_EXR_ENTRY	MSG_EXR_ENTRY_64
    694  9406       Ali #else
    695  9406       Ali #define	MSG_EXR_TITLE	MSG_EXR_TITLE_32
    696  9406       Ali #define	MSG_EXR_ENTRY	MSG_EXR_ENTRY_32
    697  9406       Ali #endif
    698  9406       Ali 
    699  9406       Ali 	exception_range_entry	scratch, *ent, *cur_ent = &scratch;
    700  9406       Ali 	char			index[MAXNDXSIZE];
    701  9406       Ali 	Word			i, nelts;
    702  9406       Ali 	Addr			addr, addr0, offset = 0;
    703  9406       Ali 	Addr			exc_addr = _cache->c_shdr->sh_addr;
    704  9406       Ali 
    705  9406       Ali 	dbg_print(0, MSG_INTL(MSG_EXR_TITLE));
    706  9406       Ali 	ent = (exception_range_entry *)(_cache->c_data->d_buf);
    707  9406       Ali 	nelts = _cache->c_data->d_size / sizeof (exception_range_entry);
    708  9406       Ali 
    709  9406       Ali 	for (i = 0; i < nelts; i++, ent++) {
    710  9406       Ali 		if (do_swap) {
    711  9406       Ali 			/*
    712  9406       Ali 			 * Copy byte swapped values into the scratch buffer.
    713  9406       Ali 			 * The reserved field is not used, so we skip it.
    714  9406       Ali 			 */
    715  9406       Ali 			scratch.ret_addr = swap_ptrdiff(ent->ret_addr);
    716  9406       Ali 			scratch.length = BSWAP_XWORD(ent->length);
    717  9406       Ali 			scratch.handler_addr = swap_ptrdiff(ent->handler_addr);
    718  9406       Ali 			scratch.type_block = swap_ptrdiff(ent->type_block);
    719  9406       Ali 		} else {
    720  9406       Ali 			cur_ent = ent;
    721  9406       Ali 		}
    722  9406       Ali 
    723  9406       Ali 		/*
    724  9406       Ali 		 * The table is required to be sorted by the address
    725  9406       Ali 		 * derived from ret_addr, to allow binary searching. Ensure
    726  9406       Ali 		 * that addresses grow monotonically.
    727  9406       Ali 		 */
    728  9406       Ali 		addr = SRELPTR(ret_addr);
    729  9406       Ali 		/*LINTED:E_VAR_USED_BEFORE_SET*/
    730  9406       Ali 		if ((i != 0) && (addr0 > addr))
    731  9615       Ali 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORT),
    732  9406       Ali 			    file, _cache->c_name, EC_WORD(i));
    733  9406       Ali 
    734  9406       Ali 		(void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX),
    735  9406       Ali 		    EC_XWORD(i));
    736  9406       Ali 		dbg_print(0, MSG_INTL(MSG_EXR_ENTRY), index, EC_ADDR(offset),
    737  9406       Ali 		    EC_ADDR(addr), EC_ADDR(cur_ent->length),
    738  9406       Ali 		    EC_ADDR(SRELPTR(handler_addr)),
    739  9406       Ali 		    EC_ADDR(SRELPTR(type_block)));
    740  9406       Ali 
    741  9406       Ali 		addr0 = addr;
    742  9406       Ali 		exc_addr += sizeof (exception_range_entry);
    743  9406       Ali 		offset += sizeof (exception_range_entry);
    744  9406       Ali 	}
    745  9406       Ali 
    746  9406       Ali #undef SRELPTR
    747  9406       Ali #undef MSG_EXR_TITLE
    748  9406       Ali #undef MSG_EXR_ENTRY
    749  9406       Ali }
    750  9406       Ali 
    751  9406       Ali /*
    752  9406       Ali  * Display information from unwind/exception sections:
    753  9406       Ali  *
    754  9406       Ali  * -	GNU/amd64 .eh_frame and .eh_frame_hdr
    755  9406       Ali  * -	Sun C++ .exception_ranges
    756  9406       Ali  *
    757  9406       Ali  */
    758  9406       Ali static void
    759  9406       Ali unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, uchar_t osabi,
    760  9406       Ali     const char *file, Elf *elf, uint_t flags)
    761  9406       Ali {
    762  9085       Ali 	static Word phdr_types[] = { PT_SUNW_UNWIND, PT_SUNW_EH_FRAME };
    763  9085       Ali 
    764  9085       Ali 	Word			cnt;
    765  9085       Ali 	Phdr			*uphdr = NULL;
    766  9406       Ali 	gnu_eh_state_t		eh_state;
    767  9085       Ali 
    768  9085       Ali 	/*
    769  9085       Ali 	 * Historical background: .eh_frame and .eh_frame_hdr sections
    770  9085       Ali 	 * come from the GNU compilers (particularly C++), and are used
    771  9085       Ali 	 * under all architectures. Their format is based on DWARF. When
    772  9085       Ali 	 * the amd64 ABI was defined, these sections were adopted wholesale
    773  9085       Ali 	 * from the existing practice.
    774  9085       Ali 	 *
    775  9085       Ali 	 * When amd64 support was added to Solaris, support for these
    776  9085       Ali 	 * sections was added, using the SHT_AMD64_UNWIND section type
    777  9085       Ali 	 * to identify them. At first, we ignored them in objects for
    778  9085       Ali 	 * non-amd64 targets, but later broadened our support to include
    779  9085       Ali 	 * other architectures in order to better support gcc-generated
    780  9085       Ali 	 * objects.
    781  9085       Ali 	 *
    782  9406       Ali 	 * .exception_ranges implement the same basic concepts, but
    783  9406       Ali 	 * were invented at Sun for the Sun C++ compiler.
    784  9406       Ali 	 *
    785  9085       Ali 	 * We match these sections by name, rather than section type,
    786  9085       Ali 	 * because they can come in as either SHT_AMD64_UNWIND, or as
    787  9406       Ali 	 * SHT_PROGBITS, and because the type isn't enough to determine
    788  9406       Ali 	 * how they should be interprteted.
    789  9406       Ali 	 */
    790  9406       Ali 
    791  9406       Ali 	/* Find the program header for .eh_frame_hdr if present */
    792  1618       rie 	if (phnum)
    793  9085       Ali 		uphdr = getphdr(phnum, phdr_types,
    794  9085       Ali 		    sizeof (phdr_types) / sizeof (*phdr_types), file, elf);
    795     0    stevel 
    796  9406       Ali 	/*
    797  9406       Ali 	 * eh_state is used to retain data used by unwind_eh_frame()
    798  9406       Ali 	 * accross calls.
    799  9406       Ali 	 */
    800  9406       Ali 	bzero(&eh_state, sizeof (eh_state));
    801  9406       Ali 
    802  9406       Ali 	for (cnt = 1; cnt < shnum; cnt++) {
    803  9406       Ali 		Cache		*_cache = &cache[cnt];
    804  9406       Ali 		Shdr		*shdr = _cache->c_shdr;
    805  9406       Ali 		int		is_exrange;
    806  9406       Ali 
    807  9406       Ali 		/*
    808  9406       Ali 		 * Skip sections of the wrong type. On amd64, they
    809  9406       Ali 		 * can be SHT_AMD64_UNWIND. On all platforms, they
    810  9406       Ali 		 * can be SHT_PROGBITS (including amd64, if using
    811  9406       Ali 		 * the GNU compilers).
    812  9273       Ali 		 *
    813  9273       Ali 		 * Skip anything other than these two types. The name
    814  9273       Ali 		 * test below will thin out the SHT_PROGBITS that don't apply.
    815  9273       Ali 		 */
    816  9273       Ali 		if ((shdr->sh_type != SHT_PROGBITS) &&
    817  9273       Ali 		    (shdr->sh_type != SHT_AMD64_UNWIND))
    818  9273       Ali 			continue;
    819  9085       Ali 
    820  9085       Ali 		/*
    821  9406       Ali 		 * Only sections with certain well known names are of interest.
    822  9406       Ali 		 * These are:
    823  9406       Ali 		 *
    824  9406       Ali 		 *	.eh_frame - amd64/GNU-compiler unwind sections
    825  9406       Ali 		 *	.eh_frame_hdr - Sorted table referencing .eh_frame
    826  9406       Ali 		 *	.exception_ranges - Sun C++ unwind sections
    827  9406       Ali 		 *
    828  9406       Ali 		 * We do a prefix comparison, allowing for naming conventions
    829  9406       Ali 		 * like .eh_frame.foo, hence the use of strncmp() rather than
    830  9406       Ali 		 * strcmp(). This means that we only really need to test for
    831  9406       Ali 		 * .eh_frame, as it's a prefix of .eh_frame_hdr.
    832  9406       Ali 		 */
    833  9406       Ali 		is_exrange =  strncmp(_cache->c_name,
    834  9406       Ali 		    MSG_ORIG(MSG_SCN_EXRANGE), MSG_SCN_EXRANGE_SIZE) == 0;
    835  9406       Ali 		if ((strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM),
    836  9406       Ali 		    MSG_SCN_FRM_SIZE) != 0) && !is_exrange)
    837     0    stevel 			continue;
    838  4168  ab196087 
    839  5411  ab196087 		if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type))
    840  3466       rie 			continue;
    841  3466       rie 
    842  3466       rie 		if (_cache->c_data == NULL)
    843     0    stevel 			continue;
    844     0    stevel 
    845  1618       rie 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
    846  1618       rie 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name);
    847     0    stevel 
    848  9406       Ali 		if (is_exrange)
    849  9406       Ali 			unwind_exception_ranges(_cache, file,
    850  9406       Ali 			    _elf_sys_encoding() != ehdr->e_ident[EI_DATA]);
    851  9406       Ali 		else
    852  9406       Ali 			unwind_eh_frame(cache, cnt, uphdr, ehdr, &eh_state,
    853  9406       Ali 			    osabi, file, flags);
    854  9406       Ali 	}
    855     0    stevel }
    856     0    stevel 
    857     0    stevel /*
    858     0    stevel  * Print the hardware/software capabilities.  For executables and shared objects
    859     0    stevel  * this should be accompanied with a program header.
    860     0    stevel  */
    861     0    stevel static void
    862  1618       rie cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr,
    863  1618       rie     Elf *elf)
    864     0    stevel {
    865  1618       rie 	Word		cnt;
    866  7833       Rod 	Shdr		*cshdr = NULL;
    867  3466       rie 	Cache		*ccache;
    868  1618       rie 	Off		cphdr_off = 0;
    869  1618       rie 	Xword		cphdr_sz;
    870     0    stevel 
    871     0    stevel 	/*
    872     0    stevel 	 * Determine if a hardware/software capabilities header exists.
    873     0    stevel 	 */
    874  1618       rie 	if (phnum) {
    875  1618       rie 		Phdr	*phdr;
    876     0    stevel 
    877  1618       rie 		if ((phdr = elf_getphdr(elf)) == NULL) {
    878     0    stevel 			failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
    879     0    stevel 			return;
    880     0    stevel 		}
    881     0    stevel 
    882  1618       rie 		for (cnt = 0; cnt < phnum; phdr++, cnt++) {
    883  1618       rie 			if (phdr->p_type == PT_SUNWCAP) {
    884  1618       rie 				cphdr_off = phdr->p_offset;
    885  1618       rie 				cphdr_sz = phdr->p_filesz;
    886  1618       rie 				break;
    887  1618       rie 			}
    888     0    stevel 		}
    889     0    stevel 	}
    890     0    stevel 
    891     0    stevel 	/*
    892     0    stevel 	 * Determine if a hardware/software capabilities section exists.
    893     0    stevel 	 */
    894     0    stevel 	for (cnt = 1; cnt < shnum; cnt++) {
    895  1618       rie 		Cache	*_cache = &cache[cnt];
    896  1618       rie 		Shdr	*shdr = _cache->c_shdr;
    897     0    stevel 
    898     0    stevel 		if (shdr->sh_type != SHT_SUNW_cap)
    899     0    stevel 			continue;
    900     0    stevel 
    901     0    stevel 		if (cphdr_off && ((cphdr_off < shdr->sh_offset) ||
    902     0    stevel 		    (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size)))
    903     0    stevel 			continue;
    904     0    stevel 
    905  3466       rie 		if (_cache->c_data == NULL)
    906  3466       rie 			continue;
    907  3466       rie 
    908     0    stevel 		ccache = _cache;
    909     0    stevel 		cshdr = shdr;
    910     0    stevel 		break;
    911     0    stevel 	}
    912     0    stevel 
    913  7833       Rod 	if ((cshdr == NULL) && (cphdr_off == 0))
    914     0    stevel 		return;
    915     0    stevel 
    916     0    stevel 	/*
    917     0    stevel 	 * Print the hardware/software capabilities section.
    918     0    stevel 	 */
    919     0    stevel 	if (cshdr) {
    920  1618       rie 		Word	ndx, capn;
    921  3492  ab196087 		Cap	*cap = (Cap *)ccache->c_data->d_buf;
    922  4665  ab196087 
    923  4665  ab196087 		if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) {
    924  4665  ab196087 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
    925  4665  ab196087 			    file, ccache->c_name);
    926  4665  ab196087 			return;
    927  4665  ab196087 		}
    928     0    stevel 
    929  1618       rie 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
    930  1618       rie 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name);
    931     0    stevel 
    932  1618       rie 		Elf_cap_title(0);
    933     0    stevel 
    934  1618       rie 		capn = (Word)(cshdr->sh_size / cshdr->sh_entsize);
    935     0    stevel 
    936  1618       rie 		for (ndx = 0; ndx < capn; cap++, ndx++) {
    937  7833       Rod 			if (cap->c_tag == CA_SUNW_NULL)
    938  7833       Rod 				continue;
    939  7833       Rod 
    940  7833       Rod 			Elf_cap_entry(0, cap, ndx, ehdr->e_machine);
    941  7833       Rod 
    942  7833       Rod 			/*
    943  7833       Rod 			 * An SF1_SUNW_ADDR32 software capability in a 32-bit
    944  7833       Rod 			 * object is suspicious as it has no effect.
    945  7833       Rod 			 */
    946  7833       Rod 			if ((cap->c_tag == CA_SUNW_SF_1) &&
    947  7833       Rod 			    (ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
    948  7833       Rod 			    (cap->c_un.c_val & SF1_SUNW_ADDR32)) {
    949  7833       Rod 				(void) fprintf(stderr,
    950  7833       Rod 				    MSG_INTL(MSG_WARN_INADDR32SF1),
    951  7833       Rod 				    file, ccache->c_name);
    952  7833       Rod 			}
    953     0    stevel 		}
    954     0    stevel 	} else
    955     0    stevel 		(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file);
    956     0    stevel 
    957     0    stevel 	/*
    958     0    stevel 	 * If this object is an executable or shared object, then the
    959     0    stevel 	 * hardware/software capabilities section should have an accompanying
    960     0    stevel 	 * program header.
    961     0    stevel 	 */
    962     0    stevel 	if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) {
    963     0    stevel 		if (cphdr_off == 0)
    964     0    stevel 			(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2),
    965     0    stevel 			    file, ccache->c_name);
    966     0    stevel 		else if ((cphdr_off != cshdr->sh_offset) ||
    967     0    stevel 		    (cphdr_sz != cshdr->sh_size))
    968     0    stevel 			(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3),
    969     0    stevel 			    file, ccache->c_name);
    970     0    stevel 	}
    971     0    stevel }
    972     0    stevel 
    973     0    stevel /*
    974     0    stevel  * Print the interpretor.
    975     0    stevel  */
    976     0    stevel static void
    977  1618       rie interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf)
    978     0    stevel {
    979  9085       Ali 	static Word phdr_types[] = { PT_INTERP };
    980  9085       Ali 
    981  9085       Ali 
    982  1618       rie 	Word	cnt;
    983  9085       Ali 	Shdr	*ishdr = NULL;
    984  1618       rie 	Cache	*icache;
    985  1618       rie 	Off	iphdr_off = 0;
    986  1618       rie 	Xword	iphdr_fsz;
    987     0    stevel 
    988     0    stevel 	/*
    989     0    stevel 	 * Determine if an interp header exists.
    990     0    stevel 	 */
    991  1618       rie 	if (phnum) {
    992  1618       rie 		Phdr	*phdr;
    993     0    stevel 
    994  9085       Ali 		phdr = getphdr(phnum, phdr_types,
    995  9085       Ali 		    sizeof (phdr_types) / sizeof (*phdr_types), file, elf);
    996  9085       Ali 		if (phdr != NULL) {
    997  1618       rie 			iphdr_off = phdr->p_offset;
    998  1618       rie 			iphdr_fsz = phdr->p_filesz;
    999     0    stevel 		}
   1000     0    stevel 	}
   1001     0    stevel 
   1002     0    stevel 	if (iphdr_off == 0)
   1003     0    stevel 		return;
   1004     0    stevel 
   1005     0    stevel 	/*
   1006     0    stevel 	 * Determine if an interp section exists.
   1007     0    stevel 	 */
   1008     0    stevel 	for (cnt = 1; cnt < shnum; cnt++) {
   1009  1618       rie 		Cache	*_cache = &cache[cnt];
   1010  1618       rie 		Shdr	*shdr = _cache->c_shdr;
   1011     0    stevel 
   1012     0    stevel 		/*
   1013     0    stevel 		 * Scan sections to find a section which contains the PT_INTERP
   1014     0    stevel 		 * string.  The target section can't be in a NOBITS section.
   1015     0    stevel 		 */
   1016     0    stevel 		if ((shdr->sh_type == SHT_NOBITS) ||
   1017     0    stevel 		    (iphdr_off < shdr->sh_offset) ||
   1018  1618       rie 		    (iphdr_off + iphdr_fsz) > (shdr->sh_offset + shdr->sh_size))
   1019     0    stevel 			continue;
   1020     0    stevel 
   1021     0    stevel 		icache = _cache;
   1022     0    stevel 		ishdr = shdr;
   1023     0    stevel 		break;
   1024     0    stevel 	}
   1025     0    stevel 
   1026     0    stevel 	/*
   1027     0    stevel 	 * Print the interpreter string based on the offset defined in the
   1028     0    stevel 	 * program header, as this is the offset used by the kernel.
   1029     0    stevel 	 */
   1030  3466       rie 	if (ishdr && icache->c_data) {
   1031  1618       rie 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
   1032  1618       rie 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name);
   1033  1618       rie 		dbg_print(0, MSG_ORIG(MSG_FMT_INDENT),
   1034     0    stevel 		    (char *)icache->c_data->d_buf +
   1035     0    stevel 		    (iphdr_off - ishdr->sh_offset));
   1036     0    stevel 	} else
   1037     0    stevel 		(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file);
   1038     0    stevel 
   1039     0    stevel 	/*
   1040     0    stevel 	 * If there are any inconsistences between the program header and
   1041     0    stevel 	 * section information, flag them.
   1042     0    stevel 	 */
   1043     0    stevel 	if (ishdr && ((iphdr_off != ishdr->sh_offset) ||
   1044  1618       rie 	    (iphdr_fsz != ishdr->sh_size))) {
   1045     0    stevel 		(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file,
   1046     0    stevel 		    icache->c_name);
   1047     0    stevel 	}
   1048     0    stevel }
   1049     0    stevel 
   1050     0    stevel /*
   1051     0    stevel  * Print the syminfo section.
   1052     0    stevel  */
   1053     0    stevel static void
   1054  1618       rie syminfo(Cache *cache, Word shnum, const char *file)
   1055     0    stevel {
   1056  1618       rie 	Shdr		*infoshdr;
   1057  1618       rie 	Syminfo		*info;
   1058  1618       rie 	Sym		*syms;
   1059  1618       rie 	Dyn		*dyns;
   1060  1618       rie 	Word		infonum, cnt, ndx, symnum;
   1061  9085       Ali 	Cache		*infocache = NULL, *symsec, *strsec;
   1062     0    stevel 
   1063     0    stevel 	for (cnt = 1; cnt < shnum; cnt++) {
   1064  1618       rie 		if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) {
   1065  1618       rie 			infocache = &cache[cnt];
   1066     0    stevel 			break;
   1067     0    stevel 		}
   1068     0    stevel 	}
   1069  9085       Ali 	if (infocache == NULL)
   1070     0    stevel 		return;
   1071     0    stevel 
   1072  1618       rie 	infoshdr = infocache->c_shdr;
   1073  1618       rie 	if ((infoshdr->sh_entsize == 0) || (infoshdr->sh_size == 0)) {
   1074     0    stevel 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
   1075  1618       rie 		    file, infocache->c_name);
   1076     0    stevel 		return;
   1077     0    stevel 	}
   1078  3466       rie 	if (infocache->c_data == NULL)
   1079  3466       rie 		return;
   1080  3466       rie 
   1081  1618       rie 	infonum = (Word)(infoshdr->sh_size / infoshdr->sh_entsize);
   1082  1618       rie 	info = (Syminfo *)infocache->c_data->d_buf;
   1083     0    stevel 
   1084     0    stevel 	/*
   1085     0    stevel 	 * Get the data buffer of the associated dynamic section.
   1086     0    stevel 	 */
   1087  1618       rie 	if ((infoshdr->sh_info == 0) || (infoshdr->sh_info >= shnum)) {
   1088     0    stevel 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO),
   1089  1618       rie 		    file, infocache->c_name, EC_WORD(infoshdr->sh_info));
   1090     0    stevel 		return;
   1091     0    stevel 	}
   1092  3466       rie 	if (cache[infoshdr->sh_info].c_data == NULL)
   1093  3466       rie 		return;
   1094  3466       rie 
   1095  1618       rie 	dyns = cache[infoshdr->sh_info].c_data->d_buf;
   1096  9085       Ali 	if (dyns == NULL) {
   1097     0    stevel 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
   1098  1618       rie 		    file, cache[infoshdr->sh_info].c_name);
   1099     0    stevel 		return;
   1100     0    stevel 	}
   1101     0    stevel 
   1102     0    stevel 	/*
   1103  1618       rie 	 * Get the data buffer for the associated symbol table and string table.
   1104     0    stevel 	 */
   1105  1618       rie 	if (stringtbl(cache, 1, cnt, shnum, file,
   1106  1618       rie 	    &symnum, &symsec, &strsec) == 0)
   1107     0    stevel 		return;
   1108     0    stevel 
   1109  1618       rie 	syms = symsec->c_data->d_buf;
   1110  1618       rie 
   1111     0    stevel 	/*
   1112  1618       rie 	 * Loop through the syminfo entries.
   1113     0    stevel 	 */
   1114  1618       rie 	dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
   1115  1618       rie 	dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMINFO), infocache->c_name);
   1116  1618       rie 	Elf_syminfo_title(0);
   1117     0    stevel 
   1118  1618       rie 	for (ndx = 1, info++; ndx < infonum; ndx++, info++) {
   1119  1618       rie 		Sym 		*sym;
   1120  9085       Ali 		const char	*needed = NULL, *name;
   1121     0    stevel 
   1122  1618       rie 		if ((info->si_flags == 0) && (info->si_boundto == 0))
   1123     0    stevel 			continue;
   1124     0    stevel 
   1125  1618       rie 		sym = &syms[ndx];
   1126  1618       rie 		name = string(infocache, ndx, strsec, file, sym->st_name);
   1127  1618       rie 
   1128  1618       rie 		if (info->si_boundto < SYMINFO_BT_LOWRESERVE) {
   1129  1618       rie 			Dyn	*dyn = &dyns[info->si_boundto];
   1130  1618       rie 
   1131  1618       rie 			needed = string(infocache, info->si_boundto,
   1132  1618       rie 			    strsec, file, dyn->d_un.d_val);
   1133     0    stevel 		}
   1134  1618       rie 		Elf_syminfo_entry(0, ndx, info, name, needed);
   1135     0    stevel 	}
   1136     0    stevel }
   1137     0    stevel 
   1138     0    stevel /*
   1139     0    stevel  * Print version definition section entries.
   1140     0    stevel  */
   1141     0    stevel static void
   1142  4716  ab196087 version_def(Verdef *vdf, Word vdf_num, Cache *vcache, Cache *scache,
   1143     0    stevel     const char *file)
   1144     0    stevel {
   1145  1618       rie 	Word	cnt;
   1146  1618       rie 	char	index[MAXNDXSIZE];
   1147     0    stevel 
   1148  1618       rie 	Elf_ver_def_title(0);
   1149     0    stevel 
   1150  4716  ab196087 	for (cnt = 1; cnt <= vdf_num; cnt++,
   1151  1618       rie 	    vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) {
   1152  7682       Ali 		Conv_ver_flags_buf_t	ver_flags_buf;
   1153  7682       Ali 		const char		*name, *dep;
   1154  7682       Ali 		Half			vcnt = vdf->vd_cnt - 1;
   1155  7682       Ali 		Half			ndx = vdf->vd_ndx;
   1156  7682       Ali 		Verdaux	*vdap = (Verdaux *)((uintptr_t)vdf + vdf->vd_aux);
   1157     0    stevel 
   1158     0    stevel 		/*
   1159     0    stevel 		 * Obtain the name and first dependency (if any).
   1160     0    stevel 		 */
   1161     0    stevel 		name = string(vcache, cnt, scache, file, vdap->vda_name);
   1162  1618       rie 		vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
   1163     0    stevel 		if (vcnt)
   1164     0    stevel 			dep = string(vcache, cnt, scache, file, vdap->vda_name);
   1165     0    stevel 		else
   1166     0    stevel 			dep = MSG_ORIG(MSG_STR_EMPTY);
   1167     0    stevel 
   1168     0    stevel 		(void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX),
   1169     0    stevel 		    EC_XWORD(ndx));
   1170  1618       rie 		Elf_ver_line_1(0, index, name, dep,
   1171  7682       Ali 		    conv_ver_flags(vdf->vd_flags, 0, &ver_flags_buf));
   1172     0    stevel 
   1173     0    stevel 		/*
   1174     0    stevel 		 * Print any additional dependencies.
   1175     0    stevel 		 */
   1176     0    stevel 		if (vcnt) {
   1177  1618       rie 			vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
   1178     0    stevel 			for (vcnt--; vcnt; vcnt--,
   1179  1618       rie 			    vdap = (Verdaux *)((uintptr_t)vdap +
   1180     0    stevel 			    vdap->vda_next)) {
   1181     0    stevel 				dep = string(vcache, cnt, scache, file,
   1182     0    stevel 				    vdap->vda_name);
   1183  1618       rie 				Elf_ver_line_2(0, MSG_ORIG(MSG_STR_EMPTY), dep);
   1184     0    stevel 			}
   1185     0    stevel 		}
   1186     0    stevel 	}
   1187     0    stevel }
   1188     0    stevel 
   1189     0    stevel /*
   1190  4716  ab196087  * Print version needed section entries.
   1191  4716  ab196087  *
   1192  4716  ab196087  * entry:
   1193  4716  ab196087  *	vnd - Address of verneed data
   1194  4716  ab196087  *	vnd_num - # of Verneed entries
   1195  4716  ab196087  *	vcache - Cache of verneed section being processed
   1196  4716  ab196087  *	scache - Cache of associated string table section
   1197  4716  ab196087  *	file - Name of object being processed.
   1198  4716  ab196087  *	versym - Information about versym section
   1199  4716  ab196087  *
   1200  4716  ab196087  * exit:
   1201  4716  ab196087  *	The versions have been printed. If GNU style versioning
   1202  4716  ab196087  *	is in effect, versym->max_verndx has been updated to
   1203  4716  ab196087  *	contain the largest version index seen.
   1204  7682       Ali  *
   1205  7682       Ali  * note:
   1206  7682       Ali  * 	The versym section of an object that follows the original
   1207  7682       Ali  *	Solaris versioning rules only contains indexes into the verdef
   1208  7682       Ali  *	section. Symbols defined in other objects (UNDEF) are given
   1209  7682       Ali  *	a version of 0, indicating that they are not defined by
   1210  7682       Ali  *	this file, and the Verneed entries do not have associated version
   1211  7682       Ali  *	indexes. For these reasons, we do not display a version index
   1212  7682       Ali  *	for original-style Verneed sections.
   1213  7682       Ali  *
   1214  7682       Ali  *	The GNU versioning extensions alter this: Symbols defined in other
   1215  7682       Ali  *	objects receive a version index in the range above those defined
   1216  7682       Ali  *	by the Verdef section, and the vna_other field of the Vernaux
   1217  7682       Ali  *	structs inside the Verneed section contain the version index for
   1218  7682       Ali  *	that item. We therefore  display the index when showing the
   1219  7682       Ali  *	contents of a GNU style Verneed section. You should not
   1220  7682       Ali  *	necessarily expect these indexes to appear in sorted
   1221  7682       Ali  *	order --- it seems that the GNU ld assigns the versions as
   1222  7682       Ali  *	symbols are encountered during linking, and then the results
   1223  7682       Ali  *	are assembled into the Verneed section afterwards.
   1224     0    stevel  */
   1225     0    stevel static void
   1226  4716  ab196087 version_need(Verneed *vnd, Word vnd_num, Cache *vcache, Cache *scache,
   1227  4716  ab196087     const char *file, VERSYM_STATE *versym)
   1228     0    stevel {
   1229  4716  ab196087 	Word		cnt;
   1230  4716  ab196087 	char		index[MAXNDXSIZE];
   1231  4716  ab196087 	const char	*index_str;
   1232     0    stevel 
   1233  7682       Ali 	Elf_ver_need_title(0, versym->gnu_needed);
   1234  4716  ab196087 
   1235  4716  ab196087 	for (cnt = 1; cnt <= vnd_num; cnt++,
   1236  1618       rie 	    vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) {
   1237  7682       Ali 		Conv_ver_flags_buf_t	ver_flags_buf;
   1238  7682       Ali 		const char		*name, *dep;
   1239  7682       Ali 		Half			vcnt = vnd->vn_cnt;
   1240  4433  ab196087 		Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + vnd->vn_aux);
   1241     0    stevel 
   1242     0    stevel 		/*
   1243     0    stevel 		 * Obtain the name of the needed file and the version name
   1244     0    stevel 		 * within it that we're dependent on.  Note that the count
   1245     0    stevel 		 * should be at least one, otherwise this is a pretty bogus
   1246     0    stevel 		 * entry.
   1247     0    stevel 		 */
   1248     0    stevel 		name = string(vcache, cnt, scache, file, vnd->vn_file);
   1249     0    stevel 		if (vcnt)
   1250     0    stevel 			dep = string(vcache, cnt, scache, file, vnap->vna_name);
   1251     0    stevel 		else
   1252     0    stevel 			dep = MSG_INTL(MSG_STR_NULL);
   1253     0    stevel 
   1254  7682       Ali 		if (vnap->vna_other == 0) {	/* Traditional form */
   1255  7682       Ali 			index_str = MSG_ORIG(MSG_STR_EMPTY);
   1256  7682       Ali 		} else {			/* GNU form */
   1257  7682       Ali 			index_str = index;
   1258  4716  ab196087 			/* Format the version index value */
   1259  4716  ab196087 			(void) snprintf(index, MAXNDXSIZE,
   1260  4716  ab196087 			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(vnap->vna_other));
   1261  4716  ab196087 			if (vnap->vna_other > versym->max_verndx)
   1262  4716  ab196087 				versym->max_verndx = vnap->vna_other;
   1263  4716  ab196087 		}
   1264  4716  ab196087 		Elf_ver_line_1(0, index_str, name, dep,
   1265  7682       Ali 		    conv_ver_flags(vnap->vna_flags, 0, &ver_flags_buf));
   1266     0    stevel 
   1267     0    stevel 		/*
   1268     0    stevel 		 * Print any additional version dependencies.
   1269     0    stevel 		 */
   1270     0    stevel 		if (vcnt) {
   1271  1618       rie 			vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next);
   1272     0    stevel 			for (vcnt--; vcnt; vcnt--,
   1273  1618       rie 			    vnap = (Vernaux *)((uintptr_t)vnap +
   1274     0    stevel 			    vnap->vna_next)) {
   1275     0    stevel 				dep = string(vcache, cnt, scache, file,
   1276     0    stevel 				    vnap->vna_name);
   1277  7682       Ali 				if (vnap->vna_other > 0) {
   1278  4716  ab196087 					/* Format the next index value */
   1279  4716  ab196087 					(void) snprintf(index, MAXNDXSIZE,
   1280  4716  ab196087 					    MSG_ORIG(MSG_FMT_INDEX),
   1281  4716  ab196087 					    EC_XWORD(vnap->vna_other));
   1282  7682       Ali 					Elf_ver_line_1(0, index,
   1283  4716  ab196087 					    MSG_ORIG(MSG_STR_EMPTY), dep,
   1284  7682       Ali 					    conv_ver_flags(vnap->vna_flags,
   1285  7682       Ali 					    0, &ver_flags_buf));
   1286  4716  ab196087 					if (vnap->vna_other >
   1287  4716  ab196087 					    versym->max_verndx)
   1288  4716  ab196087 						versym->max_verndx =
   1289  4716  ab196087 						    vnap->vna_other;
   1290  4716  ab196087 				} else {
   1291  4716  ab196087 					Elf_ver_line_3(0,
   1292  4716  ab196087 					    MSG_ORIG(MSG_STR_EMPTY), dep,
   1293  7682       Ali 					    conv_ver_flags(vnap->vna_flags,
   1294  7682       Ali 					    0, &ver_flags_buf));
   1295  7682       Ali 				}
   1296  7682       Ali 			}
   1297  7682       Ali 		}
   1298  7682       Ali 	}
   1299  7682       Ali }
   1300  7682       Ali 
   1301  7682       Ali /*
   1302  7682       Ali  * Examine the Verneed section for information related to GNU
   1303  7682       Ali  * style Versym indexing:
   1304  7682       Ali  *	- A non-zero vna_other field indicates that Versym indexes can
   1305  7682       Ali  *		reference Verneed records.
   1306  7682       Ali  *	- If the object uses GNU style Versym indexing, the
   1307  7682       Ali  *	  maximum index value is needed to detect bad Versym entries.
   1308  4716  ab196087  *
   1309  4716  ab196087  * entry:
   1310  4716  ab196087  *	vnd - Address of verneed data
   1311  4716  ab196087  *	vnd_num - # of Verneed entries
   1312  4716  ab196087  *	versym - Information about versym section
   1313  4716  ab196087  *
   1314  4716  ab196087  * exit:
   1315  7682       Ali  *	If a non-zero vna_other field is seen, versym->gnu_needed is set.
   1316  7682       Ali  *
   1317  4716  ab196087  *	versym->max_verndx has been updated to contain the largest
   1318  4716  ab196087  *	version index seen.
   1319  4716  ab196087  */
   1320  4716  ab196087 static void
   1321  7682       Ali update_gnu_verndx(Verneed *vnd, Word vnd_num, VERSYM_STATE *versym)
   1322  4716  ab196087 {
   1323  4716  ab196087 	Word		cnt;
   1324  4716  ab196087 
   1325  4716  ab196087 	for (cnt = 1; cnt <= vnd_num; cnt++,
   1326  4716  ab196087 	    vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) {
   1327  4716  ab196087 		Half	vcnt = vnd->vn_cnt;
   1328  4716  ab196087 		Vernaux	*vnap = (Vernaux *)((uintptr_t)vnd + vnd->vn_aux);
   1329  4716  ab196087 
   1330  7682       Ali 		/*
   1331  7682       Ali 		 * A non-zero value of vna_other indicates that this
   1332  7682       Ali 		 * object references VERNEED items from the VERSYM
   1333  7682       Ali 		 * array.
   1334  7682       Ali 		 */
   1335  7682       Ali 		if (vnap->vna_other != 0) {
   1336  7682       Ali 			versym->gnu_needed = 1;
   1337  7682       Ali 			if (vnap->vna_other > versym->max_verndx)
   1338  7682       Ali 				versym->max_verndx = vnap->vna_other;
   1339  7682       Ali 		}
   1340  4716  ab196087 
   1341  4716  ab196087 		/*
   1342  4716  ab196087 		 * Check any additional version dependencies.
   1343  4716  ab196087 		 */
   1344  4716  ab196087 		if (vcnt) {
   1345  4716  ab196087 			vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next);
   1346  4716  ab196087 			for (vcnt--; vcnt; vcnt--,
   1347  4716  ab196087 			    vnap = (Vernaux *)((uintptr_t)vnap +
   1348  4716  ab196087 			    vnap->vna_next)) {
   1349  7682       Ali 				if (vnap->vna_other == 0)
   1350  7682       Ali 					continue;
   1351  7682       Ali 
   1352  7682       Ali 				versym->gnu_needed = 1;
   1353  4716  ab196087 				if (vnap->vna_other > versym->max_verndx)
   1354  4716  ab196087 					versym->max_verndx = vnap->vna_other;
   1355     0    stevel 			}
   1356     0    stevel 		}
   1357     0    stevel 	}
   1358     0    stevel }
   1359     0    stevel 
   1360     0    stevel /*
   1361  3875  ab196087  * Display version section information if the flags require it.
   1362  3875  ab196087  * Return version information needed by other output.
   1363  3875  ab196087  *
   1364  3875  ab196087  * entry:
   1365  3875  ab196087  *	cache - Cache of all section headers
   1366  3875  ab196087  *	shnum - # of sections in cache
   1367  3875  ab196087  *	file - Name of file
   1368  3875  ab196087  *	flags - Command line option flags
   1369  3875  ab196087  *	versym - VERSYM_STATE block to be filled in.
   1370     0    stevel  */
   1371  3875  ab196087 static void
   1372  3875  ab196087 versions(Cache *cache, Word shnum, const char *file, uint_t flags,
   1373  3875  ab196087     VERSYM_STATE *versym)
   1374     0    stevel {
   1375     0    stevel 	GElf_Word	cnt;
   1376  4716  ab196087 	Cache		*verdef_cache = NULL, *verneed_cache = NULL;
   1377  3875  ab196087 
   1378  4716  ab196087 
   1379  4716  ab196087 	/* Gather information about the version sections */
   1380  3875  ab196087 	bzero(versym, sizeof (*versym));
   1381  4716  ab196087 	versym->max_verndx = 1;
   1382     0    stevel 	for (cnt = 1; cnt < shnum; cnt++) {
   1383  1618       rie 		Cache		*_cache = &cache[cnt];
   1384  1618       rie 		Shdr		*shdr = _cache->c_shdr;
   1385  4716  ab196087 		Dyn		*dyn;
   1386  4716  ab196087 		ulong_t		numdyn;
   1387     0    stevel 
   1388  4716  ab196087 		switch (shdr->sh_type) {
   1389  4716  ab196087 		case SHT_DYNAMIC:
   1390  4716  ab196087 			/*
   1391  4716  ab196087 			 * The GNU ld puts a DT_VERSYM entry in the dynamic
   1392  4716  ab196087 			 * section so that the runtime linker can use it to
   1393  4716  ab196087 			 * implement their versioning rules. They allow multiple
   1394  4716  ab196087 			 * incompatible functions with the same name to exist
   1395  4716  ab196087 			 * in different versions. The Solaris ld does not
   1396  4716  ab196087 			 * support this mechanism, and as such, does not
   1397  4716  ab196087 			 * produce DT_VERSYM. We use this fact to determine
   1398  4716  ab196087 			 * which ld produced this object, and how to interpret
   1399  4716  ab196087 			 * the version values.
   1400  4716  ab196087 			 */
   1401  4716  ab196087 			if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0) ||
   1402  4716  ab196087 			    (_cache->c_data == NULL))
   1403  4716  ab196087 				continue;
   1404  4716  ab196087 			numdyn = shdr->sh_size / shdr->sh_entsize;
   1405  4716  ab196087 			dyn = (Dyn *)_cache->c_data->d_buf;
   1406  4716  ab196087 			for (; numdyn-- > 0; dyn++)
   1407  4716  ab196087 				if (dyn->d_tag == DT_VERSYM) {
   1408  7682       Ali 					versym->gnu_full =
   1409  7682       Ali 					    versym->gnu_needed = 1;
   1410  4716  ab196087 					break;
   1411  4716  ab196087 				}
   1412  4716  ab196087 			break;
   1413  4716  ab196087 
   1414  4716  ab196087 		case SHT_SUNW_versym:
   1415  4716  ab196087 			/* Record data address for later symbol processing */
   1416  4716  ab196087 			if (_cache->c_data != NULL) {
   1417  4716  ab196087 				versym->cache = _cache;
   1418  4716  ab196087 				versym->data = _cache->c_data->d_buf;
   1419  4716  ab196087 				continue;
   1420  4716  ab196087 			}
   1421  4716  ab196087 			break;
   1422  4716  ab196087 
   1423  4716  ab196087 		case SHT_SUNW_verdef:
   1424  4716  ab196087 		case SHT_SUNW_verneed:
   1425  4716  ab196087 			/*
   1426  4716  ab196087 			 * Ensure the data is non-NULL and the number
   1427  4716  ab196087 			 * of items is non-zero. Otherwise, we don't
   1428  4716  ab196087 			 * understand the section, and will not use it.
   1429  4716  ab196087 			 */
   1430  4716  ab196087 			if ((_cache->c_data == NULL) ||
   1431  4716  ab196087 			    (_cache->c_data->d_buf == NULL)) {
   1432  4716  ab196087 				(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
   1433  4716  ab196087 				    file, _cache->c_name);
   1434  4716  ab196087 				continue;
   1435  4716  ab196087 			}
   1436  4716  ab196087 			if (shdr->sh_info == 0) {
   1437  4716  ab196087 				(void) fprintf(stderr,
   1438  4716  ab196087 				    MSG_INTL(MSG_ERR_BADSHINFO),
   1439  4716  ab196087 				    file, _cache->c_name,
   1440  4716  ab196087 				    EC_WORD(shdr->sh_info));
   1441  4716  ab196087 				continue;
   1442  4716  ab196087 			}
   1443  4716  ab196087 
   1444  4716  ab196087 			/* Make sure the string table index is in range */
   1445  4716  ab196087 			if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
   1446  4716  ab196087 				(void) fprintf(stderr,
   1447  4716  ab196087 				    MSG_INTL(MSG_ERR_BADSHLINK), file,
   1448  4716  ab196087 				    _cache->c_name, EC_WORD(shdr->sh_link));
   1449  4716  ab196087 				continue;
   1450  4716  ab196087 			}
   1451  4716  ab196087 
   1452  4716  ab196087 			/*
   1453  4716  ab196087 			 * The section is usable. Save the cache entry.
   1454  4716  ab196087 			 */
   1455  4716  ab196087 			if (shdr->sh_type == SHT_SUNW_verdef) {
   1456  4716  ab196087 				verdef_cache = _cache;
   1457  4716  ab196087 				/*
   1458  4716  ab196087 				 * Under Solaris rules, if there is a verdef
   1459  4716  ab196087 				 * section, the max versym index is number
   1460  4716  ab196087 				 * of version definitions it supplies.
   1461  4716  ab196087 				 */
   1462  4716  ab196087 				versym->max_verndx = shdr->sh_info;
   1463  4716  ab196087 			} else {
   1464  4716  ab196087 				verneed_cache = _cache;
   1465  4716  ab196087 			}
   1466  4716  ab196087 			break;
   1467  4716  ab196087 		}
   1468  4716  ab196087 	}
   1469  4716  ab196087 
   1470  7682       Ali 	/*
   1471  7682       Ali 	 * If there is a Verneed section, examine it for information
   1472  7682       Ali 	 * related to GNU style versioning.
   1473  7682       Ali 	 */
   1474  7682       Ali 	if (verneed_cache != NULL)
   1475  7682       Ali 		update_gnu_verndx((Verneed *)verneed_cache->c_data->d_buf,
   1476  7682       Ali 		    verneed_cache->c_shdr->sh_info, versym);
   1477  3875  ab196087 
   1478  4716  ab196087 	/*
   1479  4716  ab196087 	 * Now that all the information is available, display the
   1480  7682       Ali 	 * Verdef and Verneed section contents, if requested.
   1481  7682       Ali 	 */
   1482  7682       Ali 	if ((flags & FLG_SHOW_VERSIONS) == 0)
   1483  7682       Ali 		return;
   1484  4716  ab196087 	if (verdef_cache != NULL) {
   1485  4716  ab196087 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
   1486  4716  ab196087 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERDEF),
   1487  4716  ab196087 		    verdef_cache->c_name);
   1488  4716  ab196087 		version_def((Verdef *)verdef_cache->c_data->d_buf,
   1489  4716  ab196087 		    verdef_cache->c_shdr->sh_info, verdef_cache,
   1490  4716  ab196087 		    &cache[verdef_cache->c_shdr->sh_link], file);
   1491  4716  ab196087 	}
   1492  4716  ab196087 	if (verneed_cache != NULL) {
   1493  4716  ab196087 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
   1494  4716  ab196087 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERNEED),
   1495  4716  ab196087 		    verneed_cache->c_name);
   1496  3875  ab196087 		/*
   1497  4716  ab196087 		 * If GNU versioning applies to this object, version_need()
   1498  4716  ab196087 		 * will update versym->max_verndx, and it is not
   1499  7682       Ali 		 * necessary to call update_gnu_verndx().
   1500  3875  ab196087 		 */
   1501  4716  ab196087 		version_need((Verneed *)verneed_cache->c_data->d_buf,
   1502  4716  ab196087 		    verneed_cache->c_shdr->sh_info, verneed_cache,
   1503  4716  ab196087 		    &cache[verneed_cache->c_shdr->sh_link], file, versym);
   1504     0    stevel 	}
   1505     0    stevel }
   1506  3492  ab196087 
   1507  3492  ab196087 /*
   1508  3492  ab196087  * Initialize a symbol table state structure
   1509  3492  ab196087  *
   1510  3492  ab196087  * entry:
   1511  3492  ab196087  *	state - State structure to be initialized
   1512  3492  ab196087  *	cache - Cache of all section headers
   1513  3492  ab196087  *	shnum - # of sections in cache
   1514  3492  ab196087  *	secndx - Index of symbol table section
   1515  3492  ab196087  *	ehdr - ELF header for file
   1516  3875  ab196087  *	versym - Information about versym section
   1517  3492  ab196087  *	file - Name of file
   1518  3492  ab196087  *	flags - Command line option flags
   1519  3492  ab196087  */
   1520  3492  ab196087 static int
   1521  3492  ab196087 init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx,
   1522  9273       Ali     Ehdr *ehdr, uchar_t osabi, VERSYM_STATE *versym, const char *file,
   1523  9273       Ali     uint_t flags)
   1524  3492  ab196087 {
   1525  3492  ab196087 	Shdr *shdr;
   1526  3492  ab196087 
   1527  3492  ab196087 	state->file = file;
   1528  3492  ab196087 	state->ehdr = ehdr;
   1529  3492  ab196087 	state->cache = cache;
   1530  9273       Ali 	state->osabi = osabi;
   1531  3492  ab196087 	state->shnum = shnum;
   1532  3492  ab196087 	state->seccache = &cache[secndx];
   1533  3492  ab196087 	state->secndx = secndx;
   1534  3492  ab196087 	state->secname = state->seccache->c_name;
   1535  3492  ab196087 	state->flags = flags;
   1536  3492  ab196087 	state->shxndx.checked = 0;
   1537  3492  ab196087 	state->shxndx.data = NULL;
   1538  3492  ab196087 	state->shxndx.n = 0;
   1539  3492  ab196087 
   1540  3492  ab196087 	shdr = state->seccache->c_shdr;
   1541  3492  ab196087 
   1542  3492  ab196087 	/*
   1543  3492  ab196087 	 * Check the symbol data and per-item size.
   1544  3492  ab196087 	 */
   1545  3492  ab196087 	if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
   1546  3492  ab196087 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
   1547  3492  ab196087 		    file, state->secname);
   1548  3492  ab196087 		return (0);
   1549  3492  ab196087 	}
   1550  3492  ab196087 	if (state->seccache->c_data == NULL)
   1551  3492  ab196087 		return (0);
   1552  3492  ab196087 
   1553  3492  ab196087 	/* LINTED */
   1554  3492  ab196087 	state->symn = (Word)(shdr->sh_size / shdr->sh_entsize);
   1555  3492  ab196087 	state->sym = (Sym *)state->seccache->c_data->d_buf;
   1556  3492  ab196087 
   1557  3492  ab196087 	/*
   1558  3492  ab196087 	 * Check associated string table section.
   1559  3492  ab196087 	 */
   1560  3492  ab196087 	if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
   1561  3492  ab196087 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
   1562  3492  ab196087 		    file, state->secname, EC_WORD(shdr->sh_link));
   1563  3492  ab196087 		return (0);
   1564  3492  ab196087 	}
   1565  3492  ab196087 
   1566  3492  ab196087 	/*
   1567  3492  ab196087 	 * Determine if there is a associated Versym section
   1568  3492  ab196087 	 * with this Symbol Table.
   1569  3492  ab196087 	 */
   1570  3875  ab196087 	if (versym->cache &&
   1571  3875  ab196087 	    (versym->cache->c_shdr->sh_link == state->secndx))
   1572  3875  ab196087 		state->versym = versym;
   1573  3492  ab196087 	else
   1574  3492  ab196087 		state->versym = NULL;
   1575  3492  ab196087 
   1576  3492  ab196087 
   1577  3492  ab196087 	return (1);
   1578  3492  ab196087 }
   1579  3492  ab196087 
   1580  3492  ab196087 /*
   1581  1618       rie  * Determine the extended section index used for symbol tables entries.
   1582  1618       rie  */
   1583  3492  ab196087 static void
   1584  7463       Rod symbols_getxindex(SYMTBL_STATE *state)
   1585  1618       rie {
   1586  1618       rie 	uint_t	symn;
   1587  1618       rie 	Word	symcnt;
   1588  1618       rie 
   1589  3492  ab196087 	state->shxndx.checked = 1;   /* Note that we've been called */
   1590  3492  ab196087 	for (symcnt = 1; symcnt < state->shnum; symcnt++) {
   1591  3492  ab196087 		Cache	*_cache = &state->cache[symcnt];
   1592  1618       rie 		Shdr	*shdr = _cache->c_shdr;
   1593  1618       rie 
   1594  1618       rie 		if ((shdr->sh_type != SHT_SYMTAB_SHNDX) ||
   1595  3492  ab196087 		    (shdr->sh_link != state->secndx))
   1596  1618       rie 			continue;
   1597  1618       rie 
   1598  1618       rie 		if ((shdr->sh_entsize) &&
   1599  1618       rie 		    /* LINTED */
   1600  1618       rie 		    ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0))
   1601  3466       rie 			continue;
   1602  3466       rie 
   1603  3466       rie 		if (_cache->c_data == NULL)
   1604  1618       rie 			continue;
   1605  1618       rie 
   1606  3492  ab196087 		state->shxndx.data = _cache->c_data->d_buf;
   1607  3492  ab196087 		state->shxndx.n = symn;
   1608  3492  ab196087 		return;
   1609  1618       rie 	}
   1610  3492  ab196087 }
   1611  3492  ab196087 
   1612  3492  ab196087 /*
   1613  3492  ab196087  * Produce a line of output for the given symbol
   1614  3492  ab196087  *
   1615  3492  ab196087  * entry:
   1616  3875  ab196087  *	state - Symbol table state
   1617  3492  ab196087  *	symndx - Index of symbol within the table
   1618  4832       rie  *	info - Value of st_info (indicates local/global range)
   1619  3492  ab196087  *	symndx_disp - Index to display. This may not be the same
   1620  3492  ab196087  *		as symndx if the display is relative to the logical
   1621  3492  ab196087  *		combination of the SUNW_ldynsym/dynsym tables.
   1622  3492  ab196087  *	sym - Symbol to display
   1623  3492  ab196087  */
   1624  3492  ab196087 static void
   1625  4832       rie output_symbol(SYMTBL_STATE *state, Word symndx, Word info, Word disp_symndx,
   1626  4832       rie     Sym *sym)
   1627  3492  ab196087 {
   1628  3492  ab196087 	/*
   1629  3492  ab196087 	 * Symbol types for which we check that the specified
   1630  3492  ab196087 	 * address/size land inside the target section.
   1631  3492  ab196087 	 */
   1632  9085       Ali 	static const int addr_symtype[] = {
   1633  3492  ab196087 		0,			/* STT_NOTYPE */
   1634  3492  ab196087 		1,			/* STT_OBJECT */
   1635  3492  ab196087 		1,			/* STT_FUNC */
   1636  3492  ab196087 		0,			/* STT_SECTION */
   1637  3492  ab196087 		0,			/* STT_FILE */
   1638  3492  ab196087 		1,			/* STT_COMMON */
   1639  3492  ab196087 		0,			/* STT_TLS */
   1640  9900       Ali 		0,			/* 7 */
   1641  9085       Ali 		0,			/* 8 */
   1642  9085       Ali 		0,			/* 9 */
   1643  9085       Ali 		0,			/* 10 */
   1644  9085       Ali 		0,			/* 11 */
   1645  9085       Ali 		0,			/* 12 */
   1646  9085       Ali 		0,			/* STT_SPARC_REGISTER */
   1647  9085       Ali 		0,			/* 14 */
   1648  9085       Ali 		0,			/* 15 */
   1649  3492  ab196087 	};
   1650  9900       Ali #if STT_NUM != (STT_TLS + 1)
   1651  3492  ab196087 #error "STT_NUM has grown. Update addr_symtype[]"
   1652  3492  ab196087 #endif
   1653  3492  ab196087 
   1654  4665  ab196087 	char		index[MAXNDXSIZE];
   1655  4665  ab196087 	const char	*symname, *sec;
   1656  3875  ab196087 	Versym		verndx;
   1657  4716  ab196087 	int		gnuver;
   1658  3492  ab196087 	uchar_t		type;
   1659  3492  ab196087 	Shdr		*tshdr;
   1660  3492  ab196087 	Word		shndx;
   1661  4734  ab196087 	Conv_inv_buf_t	inv_buf;
   1662  3492  ab196087 
   1663  3492  ab196087 	/* Ensure symbol index is in range */
   1664  3492  ab196087 	if (symndx >= state->symn) {
   1665  3492  ab196087 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORTNDX),
   1666  3492  ab196087 		    state->file, state->secname, EC_WORD(symndx));
   1667  3492  ab196087 		return;
   1668  3492  ab196087 	}
   1669  3492  ab196087 
   1670  3492  ab196087 	/*
   1671  3492  ab196087 	 * If we are using extended symbol indexes, find the
   1672  3492  ab196087 	 * corresponding SHN_SYMTAB_SHNDX table.
   1673  3492  ab196087 	 */
   1674  3492  ab196087 	if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0))
   1675  3492  ab196087 		symbols_getxindex(state);
   1676  3492  ab196087 
   1677  3492  ab196087 	/* LINTED */
   1678  3492  ab196087 	symname = string(state->seccache, symndx,
   1679  3492  ab196087 	    &state->cache[state->seccache->c_shdr->sh_link], state->file,
   1680  3492  ab196087 	    sym->st_name);
   1681  3492  ab196087 
   1682  9085       Ali 	tshdr = NULL;
   1683  3492  ab196087 	sec = NULL;
   1684  3492  ab196087 
   1685  4665  ab196087 	if (state->ehdr->e_type == ET_CORE) {
   1686  3492  ab196087 		sec = (char *)MSG_INTL(MSG_STR_UNKNOWN);
   1687  5411  ab196087 	} else if (state->flags & FLG_CTL_FAKESHDR) {
   1688  4665  ab196087 		/*
   1689  4665  ab196087 		 * If we are using fake section headers derived from
   1690  4665  ab196087 		 * the program headers, then the section indexes
   1691  4665  ab196087 		 * in the symbols do not correspond to these headers.
   1692  4665  ab196087 		 * The section names are not available, so all we can
   1693  4665  ab196087 		 * do is to display them in numeric form.
   1694  4665  ab196087 		 */
   1695  9273       Ali 		sec = conv_sym_shndx(state->osabi, state->ehdr->e_machine,
   1696  9273       Ali 		    sym->st_shndx, CONV_FMT_DECIMAL, &inv_buf);
   1697  4665  ab196087 	} else if ((sym->st_shndx < SHN_LORESERVE) &&
   1698  3492  ab196087 	    (sym->st_shndx < state->shnum)) {
   1699  3492  ab196087 		shndx = sym->st_shndx;
   1700  3492  ab196087 		tshdr = state->cache[shndx].c_shdr;
   1701  3492  ab196087 		sec = state->cache[shndx].c_name;
   1702  3492  ab196087 	} else if (sym->st_shndx == SHN_XINDEX) {
   1703  3492  ab196087 		if (state->shxndx.data) {
   1704  3492  ab196087 			Word	_shxndx;
   1705  3492  ab196087 
   1706  3492  ab196087 			if (symndx > state->shxndx.n) {
   1707  4433  ab196087 				(void) fprintf(stderr,
   1708  4433  ab196087 				    MSG_INTL(MSG_ERR_BADSYMXINDEX1),
   1709  4433  ab196087 				    state->file, state->secname,
   1710  4433  ab196087 				    EC_WORD(symndx));
   1711  3492  ab196087 			} else if ((_shxndx =
   1712  3492  ab196087 			    state->shxndx.data[symndx]) > state->shnum) {
   1713  4433  ab196087 				(void) fprintf(stderr,
   1714  4433  ab196087 				    MSG_INTL(MSG_ERR_BADSYMXINDEX2),
   1715  4433  ab196087 				    state->file, state->secname,
   1716  4433  ab196087 				    EC_WORD(symndx), EC_WORD(_shxndx));
   1717  3492  ab196087 			} else {
   1718  4433  ab196087 				shndx = _shxndx;
   1719  4433  ab196087 				tshdr = state->cache[shndx].c_shdr;
   1720  4433  ab196087 				sec = state->cache[shndx].c_name;
   1721  3492  ab196087 			}
   1722  3492  ab196087 		} else {
   1723  3492  ab196087 			(void) fprintf(stderr,
   1724  3492  ab196087 			    MSG_INTL(MSG_ERR_BADSYMXINDEX3),
   1725  3492  ab196087 			    state->file, state->secname, EC_WORD(symndx));
   1726  3492  ab196087 		}
   1727  3492  ab196087 	} else if ((sym->st_shndx < SHN_LORESERVE) &&
   1728  3492  ab196087 	    (sym->st_shndx >= state->shnum)) {
   1729  3492  ab196087 		(void) fprintf(stderr,
   1730  3492  ab196087 		    MSG_INTL(MSG_ERR_BADSYM5), state->file,
   1731  6206  ab196087 		    state->secname, EC_WORD(symndx),
   1732  6206  ab196087 		    demangle(symname, state->flags), sym->st_shndx);
   1733  3492  ab196087 	}
   1734  3492  ab196087 
   1735  3492  ab196087 	/*
   1736  3492  ab196087 	 * If versioning is available display the
   1737  3875  ab196087 	 * version index. If not, then use 0.
   1738  3492  ab196087 	 */
   1739  3875  ab196087 	if (state->versym) {
   1740  4716  ab196087 		Versym test_verndx;
   1741  4716  ab196087 
   1742  4716  ab196087 		verndx = test_verndx = state->versym->data[symndx];
   1743  7682       Ali 		gnuver = state->versym->gnu_full;
   1744  3875  ab196087 
   1745  3875  ab196087 		/*
   1746  3875  ab196087 		 * Check to see if this is a defined symbol with a
   1747  3875  ab196087 		 * version index that is outside the valid range for
   1748  4716  ab196087 		 * the file. The interpretation of this depends on
   1749  4716  ab196087 		 * the style of versioning used by the object.
   1750  3875  ab196087 		 *
   1751  4716  ab196087 		 * Versions >= VER_NDX_LORESERVE have special meanings,
   1752  4716  ab196087 		 * and are exempt from this checking.
   1753  4716  ab196087 		 *
   1754  4716  ab196087 		 * GNU style version indexes use the top bit of the
   1755  4716  ab196087 		 * 16-bit index value (0x8000) as the "hidden bit".
   1756  4716  ab196087 		 * We must mask off this bit in order to compare
   1757  4716  ab196087 		 * the version against the maximum value.
   1758  3875  ab196087 		 */
   1759  4716  ab196087 		if (gnuver)
   1760  4716  ab196087 			test_verndx &= ~0x8000;
   1761  4716  ab196087 
   1762  4716  ab196087 		if ((test_verndx > state->versym->max_verndx) &&
   1763  4716  ab196087 		    (verndx < VER_NDX_LORESERVE))
   1764  4716  ab196087 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADVER),
   1765  4716  ab196087 			    state->file, state->secname, EC_WORD(symndx),
   1766  4716  ab196087 			    EC_HALF(test_verndx), state->versym->max_verndx);
   1767  3875  ab196087 	} else {
   1768  3492  ab196087 		verndx = 0;
   1769  4716  ab196087 		gnuver = 0;
   1770  3875  ab196087 	}
   1771  3492  ab196087 
   1772  3492  ab196087 	/*
   1773  3492  ab196087 	 * Error checking for TLS.
   1774  3492  ab196087 	 */
   1775  3492  ab196087 	type = ELF_ST_TYPE(sym->st_info);
   1776  3492  ab196087 	if (type == STT_TLS) {
   1777  3492  ab196087 		if (tshdr &&
   1778  3492  ab196087 		    (sym->st_shndx != SHN_UNDEF) &&
   1779  3492  ab196087 		    ((tshdr->sh_flags & SHF_TLS) == 0)) {
   1780  3492  ab196087 			(void) fprintf(stderr,
   1781  3492  ab196087 			    MSG_INTL(MSG_ERR_BADSYM3), state->file,
   1782  6206  ab196087 			    state->secname, EC_WORD(symndx),
   1783  6206  ab196087 			    demangle(symname, state->flags));
   1784  3492  ab196087 		}
   1785  3492  ab196087 	} else if ((type != STT_SECTION) && sym->st_size &&
   1786  3492  ab196087 	    tshdr && (tshdr->sh_flags & SHF_TLS)) {
   1787  3492  ab196087 		(void) fprintf(stderr,
   1788  3492  ab196087 		    MSG_INTL(MSG_ERR_BADSYM4), state->file,
   1789  6206  ab196087 		    state->secname, EC_WORD(symndx),
   1790  6206  ab196087 		    demangle(symname, state->flags));
   1791  3492  ab196087 	}
   1792  3492  ab196087 
   1793  3492  ab196087 	/*
   1794  3492  ab196087 	 * If a symbol with non-zero size has a type that
   1795  3492  ab196087 	 * specifies an address, then make sure the location
   1796  3492  ab196087 	 * it references is actually contained within the
   1797  3492  ab196087 	 * section.  UNDEF symbols don't count in this case,
   1798  3492  ab196087 	 * so we ignore them.
   1799  3492  ab196087 	 *
   1800  3492  ab196087 	 * The meaning of the st_value field in a symbol
   1801  3492  ab196087 	 * depends on the type of object. For a relocatable
   1802  3492  ab196087 	 * object, it is the offset within the section.
   1803  3492  ab196087 	 * For sharable objects, it is the offset relative to
   1804  3492  ab196087 	 * the base of the object, and for other types, it is
   1805  3492  ab196087 	 * the virtual address. To get an offset within the
   1806  3492  ab196087 	 * section for non-ET_REL files, we subtract the
   1807  3492  ab196087 	 * base address of the section.
   1808  3492  ab196087 	 */
   1809  3492  ab196087 	if (addr_symtype[type] && (sym->st_size > 0) &&
   1810  3492  ab196087 	    (sym->st_shndx != SHN_UNDEF) && ((sym->st_shndx < SHN_LORESERVE) ||
   1811  3492  ab196087 	    (sym->st_shndx == SHN_XINDEX)) && (tshdr != NULL)) {
   1812  3492  ab196087 		Word v = sym->st_value;
   1813  3492  ab196087 			if (state->ehdr->e_type != ET_REL)
   1814  4832       rie 				v -= tshdr->sh_addr;
   1815  3492  ab196087 		if (((v + sym->st_size) > tshdr->sh_size)) {
   1816  3492  ab196087 			(void) fprintf(stderr,
   1817  3492  ab196087 			    MSG_INTL(MSG_ERR_BADSYM6), state->file,
   1818  6206  ab196087 			    state->secname, EC_WORD(symndx),
   1819  6206  ab196087 			    demangle(symname, state->flags),
   1820  3492  ab196087 			    EC_WORD(shndx), EC_XWORD(tshdr->sh_size),
   1821  3492  ab196087 			    EC_XWORD(sym->st_value), EC_XWORD(sym->st_size));
   1822  4832       rie 		}
   1823  4832       rie 	}
   1824  4832       rie 
   1825  4832       rie 	/*
   1826  4832       rie 	 * A typical symbol table uses the sh_info field to indicate one greater
   1827  4832       rie 	 * than the symbol table index of the last local symbol, STB_LOCAL.
   1828  4832       rie 	 * Therefore, symbol indexes less than sh_info should have local
   1829  4832       rie 	 * binding.  Symbol indexes greater than, or equal to sh_info, should
   1830  4832       rie 	 * have global binding.  Note, we exclude UNDEF/NOTY symbols with zero
   1831  4832       rie 	 * value and size, as these symbols may be the result of an mcs(1)
   1832  4832       rie 	 * section deletion.
   1833  4832       rie 	 */
   1834  4832       rie 	if (info) {
   1835  4832       rie 		uchar_t	bind = ELF_ST_BIND(sym->st_info);
   1836  4832       rie 
   1837  4832       rie 		if ((symndx < info) && (bind != STB_LOCAL)) {
   1838  4832       rie 			(void) fprintf(stderr,
   1839  4832       rie 			    MSG_INTL(MSG_ERR_BADSYM7), state->file,
   1840  6206  ab196087 			    state->secname, EC_WORD(symndx),
   1841  6206  ab196087 			    demangle(symname, state->flags), EC_XWORD(info));
   1842  4832       rie 
   1843  4832       rie 		} else if ((symndx >= info) && (bind == STB_LOCAL) &&
   1844  4832       rie 		    ((sym->st_shndx != SHN_UNDEF) ||
   1845  4832       rie 		    (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) ||
   1846  4832       rie 		    (sym->st_size != 0) || (sym->st_value != 0))) {
   1847  4832       rie 			(void) fprintf(stderr,
   1848  4832       rie 			    MSG_INTL(MSG_ERR_BADSYM8), state->file,
   1849  6206  ab196087 			    state->secname, EC_WORD(symndx),
   1850  6206  ab196087 			    demangle(symname, state->flags), EC_XWORD(info));
   1851  3492  ab196087 		}
   1852  3492  ab196087 	}
   1853  3492  ab196087 
   1854  3492  ab196087 	(void) snprintf(index, MAXNDXSIZE,
   1855  3492  ab196087 	    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(disp_symndx));
   1856  9273       Ali 	Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index, state->osabi,
   1857  4716  ab196087 	    state->ehdr->e_machine, sym, verndx, gnuver, sec, symname);
   1858  1618       rie }
   1859  1618       rie 
   1860  1618       rie /*
   1861     0    stevel  * Search for and process any symbol tables.
   1862     0    stevel  */
   1863  1618       rie void
   1864  9273       Ali symbols(Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi,
   1865  9273       Ali     VERSYM_STATE *versym, const char *file, uint_t flags)
   1866     0    stevel {
   1867  3492  ab196087 	SYMTBL_STATE state;
   1868  3492  ab196087 	Cache *_cache;
   1869  3492  ab196087 	Word secndx;
   1870  3118  ab196087 
   1871  3492  ab196087 	for (secndx = 1; secndx < shnum; secndx++) {
   1872  3492  ab196087 		Word		symcnt;
   1873  3492  ab196087 		Shdr		*shdr;
   1874     0    stevel 
   1875  3492  ab196087 		_cache = &cache[secndx];
   1876  3492  ab196087 		shdr = _cache->c_shdr;
   1877     0    stevel 
   1878     0    stevel 		if ((shdr->sh_type != SHT_SYMTAB) &&
   1879  2766  ab196087 		    (shdr->sh_type != SHT_DYNSYM) &&
   1880  9273       Ali 		    ((shdr->sh_type != SHT_SUNW_LDYNSYM) ||
   1881  9273       Ali 		    (osabi != ELFOSABI_SOLARIS)))
   1882     0    stevel 			continue;
   1883  5411  ab196087 		if (!match(MATCH_F_ALL, _cache->c_name, secndx, shdr->sh_type))
   1884  3492  ab196087 			continue;
   1885  3492  ab196087 
   1886  3492  ab196087 		if (!init_symtbl_state(&state, cache, shnum, secndx, ehdr,
   1887  9273       Ali 		    osabi, versym, file, flags))
   1888  3492  ab196087 			continue;
   1889  3492  ab196087 		/*
   1890  3492  ab196087 		 * Loop through the symbol tables entries.
   1891  3492  ab196087 		 */
   1892  3492  ab196087 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
   1893  3492  ab196087 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), state.secname);
   1894  3492  ab196087 		Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
   1895  3492  ab196087 
   1896  3492  ab196087 		for (symcnt = 0; symcnt < state.symn; symcnt++)
   1897  4832       rie 			output_symbol(&state, symcnt, shdr->sh_info, symcnt,
   1898  3492  ab196087 			    state.sym + symcnt);
   1899  3492  ab196087 	}
   1900  3492  ab196087 }
   1901  3492  ab196087 
   1902  3492  ab196087 /*
   1903  3492  ab196087  * Search for and process any SHT_SUNW_symsort or SHT_SUNW_tlssort sections.
   1904  3492  ab196087  * These sections are always associated with the .SUNW_ldynsym./.dynsym pair.
   1905  3492  ab196087  */
   1906  3492  ab196087 static void
   1907  9273       Ali sunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi,
   1908  9273       Ali     VERSYM_STATE *versym, const char *file, uint_t flags)
   1909  3492  ab196087 {
   1910  3492  ab196087 	SYMTBL_STATE	ldynsym_state,	dynsym_state;
   1911  3492  ab196087 	Cache		*sortcache,	*symcache;
   1912  3492  ab196087 	Shdr		*sortshdr,	*symshdr;
   1913  3492  ab196087 	Word		sortsecndx,	symsecndx;
   1914  3492  ab196087 	Word		ldynsym_cnt;
   1915  3492  ab196087 	Word		*ndx;
   1916  3492  ab196087 	Word		ndxn;
   1917  3492  ab196087 	int		output_cnt = 0;
   1918  4734  ab196087 	Conv_inv_buf_t	inv_buf;
   1919  3492  ab196087 
   1920  3492  ab196087 	for (sortsecndx = 1; sortsecndx < shnum; sortsecndx++) {
   1921  3492  ab196087 
   1922  3492  ab196087 		sortcache = &cache[sortsecndx];
   1923  3492  ab196087 		sortshdr = sortcache->c_shdr;
   1924  3492  ab196087 
   1925  3492  ab196087 		if ((sortshdr->sh_type != SHT_SUNW_symsort) &&
   1926  3492  ab196087 		    (sortshdr->sh_type != SHT_SUNW_tlssort))
   1927  3492  ab196087 			continue;
   1928  5411  ab196087 		if (!match(MATCH_F_ALL, sortcache->c_name, sortsecndx,
   1929  5411  ab196087 		    sortshdr->sh_type))
   1930     0    stevel 			continue;
   1931     0    stevel 
   1932     0    stevel 		/*
   1933  3492  ab196087 		 * If the section references a SUNW_ldynsym, then we
   1934  3492  ab196087 		 * expect to see the associated .dynsym immediately
   1935  3492  ab196087 		 * following. If it references a .dynsym, there is no
   1936  3492  ab196087 		 * SUNW_ldynsym. If it is any other type, then we don't
   1937  3492  ab196087 		 * know what to do with it.
   1938     0    stevel 		 */
   1939  3492  ab196087 		if ((sortshdr->sh_link == 0) || (sortshdr->sh_link >= shnum)) {
   1940  3492  ab196087 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
   1941  3492  ab196087 			    file, sortcache->c_name,
   1942  3492  ab196087 			    EC_WORD(sortshdr->sh_link));
   1943     0    stevel 			continue;
   1944     0    stevel 		}
   1945  3492  ab196087 		symcache = &cache[sortshdr->sh_link];
   1946  3492  ab196087 		symshdr = symcache->c_shdr;
   1947  3492  ab196087 		symsecndx = sortshdr->sh_link;
   1948  3492  ab196087 		ldynsym_cnt = 0;
   1949  3492  ab196087 		switch (symshdr->sh_type) {
   1950  3492  ab196087 		case SHT_SUNW_LDYNSYM:
   1951  3492  ab196087 			if (!init_symtbl_state(&ldynsym_state, cache, shnum,
   1952  9273       Ali 			    symsecndx, ehdr, osabi, versym, file, flags))
   1953  3492  ab196087 				continue;
   1954  3492  ab196087 			ldynsym_cnt = ldynsym_state.symn;
   1955  3492  ab196087 			/*
   1956  3492  ab196087 			 * We know that the dynsym follows immediately
   1957  3492  ab196087 			 * after the SUNW_ldynsym, and so, should be at
   1958  3492  ab196087 			 * (sortshdr->sh_link + 1). However, elfdump is a
   1959  3492  ab196087 			 * diagnostic tool, so we do the full paranoid
   1960  3492  ab196087 			 * search instead.
   1961  3492  ab196087 			 */
   1962  3492  ab196087 			for (symsecndx = 1; symsecndx < shnum; symsecndx++) {
   1963  3492  ab196087 				symcache = &cache[symsecndx];
   1964  3492  ab196087 				symshdr = symcache->c_shdr;
   1965  3492  ab196087 				if (symshdr->sh_type == SHT_DYNSYM)
   1966  3492  ab196087 					break;
   1967  3492  ab196087 			}
   1968  3492  ab196087 			if (symsecndx >= shnum) {	/* Dynsym not found! */
   1969  3492  ab196087 				(void) fprintf(stderr,
   1970  3492  ab196087 				    MSG_INTL(MSG_ERR_NODYNSYM),
   1971  3492  ab196087 				    file, sortcache->c_name);
   1972  3492  ab196087 				continue;
   1973  3492  ab196087 			}
   1974  3492  ab196087 			/* Fallthrough to process associated dynsym */
   1975  7463       Rod 			/* FALLTHROUGH */
   1976  3492  ab196087 		case SHT_DYNSYM:
   1977  3492  ab196087 			if (!init_symtbl_state(&dynsym_state, cache, shnum,
   1978  9273       Ali 			    symsecndx, ehdr, osabi, versym, file, flags))
   1979  3492  ab196087 				continue;
   1980  3492  ab196087 			break;
   1981  3492  ab196087 		default:
   1982  3492  ab196087 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADNDXSEC),
   1983  9273       Ali 			    file, sortcache->c_name,
   1984  9273       Ali 			    conv_sec_type(osabi, ehdr->e_machine,
   1985  9273       Ali 			    symshdr->sh_type, 0, &inv_buf));
   1986     0    stevel 			continue;
   1987     0    stevel 		}
   1988     0    stevel 
   1989     0    stevel 		/*
   1990  3492  ab196087 		 * Output header
   1991     0    stevel 		 */
   1992  3492  ab196087 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
   1993  3492  ab196087 		if (ldynsym_cnt > 0) {
   1994  3492  ab196087 			dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT2),
   1995  3492  ab196087 			    sortcache->c_name, ldynsym_state.secname,
   1996  3492  ab196087 			    dynsym_state.secname);
   1997  3492  ab196087 			/*
   1998  3492  ab196087 			 * The data for .SUNW_ldynsym and dynsym sections
   1999  3492  ab196087 			 * is supposed to be adjacent with SUNW_ldynsym coming
   2000  3492  ab196087 			 * first. Check, and issue a warning if it isn't so.
   2001  3492  ab196087 			 */
   2002  4665  ab196087 			if (((ldynsym_state.sym + ldynsym_state.symn)
   2003  4665  ab196087 			    != dynsym_state.sym) &&
   2004  5411  ab196087 			    ((flags & FLG_CTL_FAKESHDR) == 0))
   2005  3492  ab196087 				(void) fprintf(stderr,
   2006  3492  ab196087 				    MSG_INTL(MSG_ERR_LDYNNOTADJ), file,
   2007  3492  ab196087 				    ldynsym_state.secname,
   2008  3492  ab196087 				    dynsym_state.secname);
   2009  3492  ab196087 		} else {
   2010  3492  ab196087 			dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT1),
   2011  3492  ab196087 			    sortcache->c_name, dynsym_state.secname);
   2012  3492  ab196087 		}
   2013  3492  ab196087 		Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
   2014  3492  ab196087 
   2015  3492  ab196087 		/* If not first one, insert a line of whitespace */
   2016  3492  ab196087 		if (output_cnt++ > 0)
   2017  3492  ab196087 			dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
   2018     0    stevel 
   2019     0    stevel 		/*
   2020  3492  ab196087 		 * SUNW_dynsymsort and SUNW_dyntlssort are arrays of
   2021  3492  ab196087 		 * symbol indices. Iterate over the array entries,
   2022  3492  ab196087 		 * dispaying the referenced symbols.
   2023     0    stevel 		 */
   2024  3492  ab196087 		ndxn = sortshdr->sh_size / sortshdr->sh_entsize;
   2025  3492  ab196087 		ndx = (Word *)sortcache->c_data->d_buf;
   2026  3492  ab196087 		for (; ndxn-- > 0; ndx++) {
   2027  3492  ab196087 			if (*ndx >= ldynsym_cnt) {
   2028  3492  ab196087 				Word sec_ndx = *ndx - ldynsym_cnt;
   2029     0    stevel 
   2030  4832       rie 				output_symbol(&dynsym_state, sec_ndx, 0,
   2031  3492  ab196087 				    *ndx, dynsym_state.sym + sec_ndx);
   2032  3492  ab196087 			} else {
   2033  4832       rie 				output_symbol(&ldynsym_state, *ndx, 0,
   2034  3492  ab196087 				    *ndx, ldynsym_state.sym + *ndx);
   2035     0    stevel 			}
   2036     0    stevel 		}
   2037     0    stevel 	}
   2038     0    stevel }
   2039     0    stevel 
   2040     0    stevel /*
   2041     0    stevel  * Search for and process any relocation sections.
   2042     0    stevel  */
   2043     0    stevel static void
   2044  7463       Rod reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *file)
   2045     0    stevel {
   2046  1618       rie 	Word	cnt;
   2047     0    stevel 
   2048     0    stevel 	for (cnt = 1; cnt < shnum; cnt++) {
   2049  1618       rie 		Word		type, symnum;
   2050  1618       rie 		Xword		relndx, relnum, relsize;
   2051  1618       rie 		void		*rels;
   2052  1618       rie 		Sym		*syms;
   2053  1618       rie 		Cache		*symsec, *strsec;
   2054     0    stevel 		Cache		*_cache = &cache[cnt];
   2055  1618       rie 		Shdr		*shdr = _cache->c_shdr;
   2056  1618       rie 		char		*relname = _cache->c_name;
   2057  4734  ab196087 		Conv_inv_buf_t	inv_buf;
   2058     0    stevel 
   2059     0    stevel 		if (((type = shdr->sh_type) != SHT_RELA) &&
   2060     0    stevel 		    (type != SHT_REL))
   2061     0    stevel 			continue;
   2062  5411  ab196087 		if (!match(MATCH_F_ALL, relname, cnt, type))
   2063     0    stevel 			continue;
   2064     0    stevel 
   2065     0    stevel 		/*
   2066  1618       rie 		 * Decide entry size.
   2067     0    stevel 		 */
   2068  1618       rie 		if (((relsize = shdr->sh_entsize) == 0) ||
   2069  1618       rie 		    (relsize > shdr->sh_size)) {
   2070     0    stevel 			if (type == SHT_RELA)
   2071  1618       rie 				relsize = sizeof (Rela);
   2072     0    stevel 			else
   2073  1618       rie 				relsize = sizeof (Rel);
   2074     0    stevel 		}
   2075     0    stevel 
   2076     0    stevel 		/*
   2077     0    stevel 		 * Determine the number of relocations available.
   2078     0    stevel 		 */
   2079     0    stevel 		if (shdr->sh_size == 0) {
   2080     0    stevel 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
   2081  1618       rie 			    file, relname);
   2082     0    stevel 			continue;
   2083     0    stevel 		}
   2084  3466       rie 		if (_cache->c_data == NULL)
   2085  3466       rie 			continue;
   2086  3466       rie 
   2087  1618       rie 		rels = _cache->c_data->d_buf;
   2088  1618       rie 		relnum = shdr->sh_size / relsize;
   2089     0    stevel 
   2090     0    stevel 		/*
   2091  1618       rie 		 * Get the data buffer for the associated symbol table and
   2092  1618       rie 		 * string table.
   2093     0    stevel 		 */
   2094  1618       rie 		if (stringtbl(cache, 1, cnt, shnum, file,
   2095  1618       rie 		    &symnum, &symsec, &strsec) == 0)
   2096     0    stevel 			continue;
   2097     0    stevel 
   2098  1618       rie 		syms = symsec->c_data->d_buf;
   2099     0    stevel 
   2100     0    stevel 		/*
   2101     0    stevel 		 * Loop through the relocation entries.
   2102     0    stevel 		 */
   2103  1618       rie 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
   2104  1618       rie 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name);
   2105  1618       rie 		Elf_reloc_title(0, ELF_DBG_ELFDUMP, type);
   2106     0    stevel 
   2107  1618       rie 		for (relndx = 0; relndx < relnum; relndx++,
   2108  1618       rie 		    rels = (void *)((char *)rels + relsize)) {
   2109  6206  ab196087 			Half		mach = ehdr->e_machine;
   2110     0    stevel 			char		section[BUFSIZ];
   2111  1618       rie 			const char	*symname;
   2112  1618       rie 			Word		symndx, reltype;
   2113  1618       rie 			Rela		*rela;
   2114  1618       rie 			Rel		*rel;
   2115     0    stevel 
   2116     0    stevel 			/*
   2117  1618       rie 			 * Unravel the relocation and determine the symbol with
   2118  1618       rie 			 * which this relocation is associated.
   2119     0    stevel 			 */
   2120     0    stevel 			if (type == SHT_RELA) {
   2121  1618       rie 				rela = (Rela *)rels;
   2122  1618       rie 				symndx = ELF_R_SYM(rela->r_info);
   2123  6206  ab196087 				reltype = ELF_R_TYPE(rela->r_info, mach);
   2124     0    stevel 			} else {
   2125  1618       rie 				rel = (Rel *)rels;
   2126  1618       rie 				symndx = ELF_R_SYM(rel->r_info);
   2127  6206  ab196087 				reltype = ELF_R_TYPE(rel->r_info, mach);
   2128     0    stevel 			}
   2129     0    stevel 
   2130  1618       rie 			symname = relsymname(cache, _cache, strsec, symndx,
   2131  7463       Rod 			    symnum, relndx, syms, section, BUFSIZ, file);
   2132  1618       rie 
   2133  1618       rie 			/*
   2134  1618       rie 			 * A zero symbol index is only valid for a few
   2135  1618       rie 			 * relocations.
   2136  1618       rie 			 */
   2137  1618       rie 			if (symndx == 0) {
   2138  1618       rie 				int	badrel = 0;
   2139  1618       rie 
   2140  1618       rie 				if ((mach == EM_SPARC) ||
   2141  1618       rie 				    (mach == EM_SPARC32PLUS) ||
   2142  1618       rie 				    (mach == EM_SPARCV9)) {
   2143  1618       rie 					if ((reltype != R_SPARC_NONE) &&
   2144  1618       rie 					    (reltype != R_SPARC_REGISTER) &&
   2145  1618       rie 					    (reltype != R_SPARC_RELATIVE))
   2146  1618       rie 						badrel++;
   2147  1618       rie 				} else if (mach == EM_386) {
   2148  1618       rie 					if ((reltype != R_386_NONE) &&
   2149  1618       rie 					    (reltype != R_386_RELATIVE))
   2150  1618       rie 						badrel++;
   2151  1618       rie 				} else if (mach == EM_AMD64) {
   2152  1618       rie 					if ((reltype != R_AMD64_NONE) &&
   2153  1618       rie 					    (reltype != R_AMD64_RELATIVE))
   2154  1618       rie 						badrel++;
   2155  1618       rie 				}
   2156  1618       rie 
   2157  1618       rie 				if (badrel) {
   2158  1618       rie 					(void) fprintf(stderr,
   2159  1618       rie 					    MSG_INTL(MSG_ERR_BADREL1), file,
   2160  4734  ab196087 					    conv_reloc_type(mach, reltype,
   2161  4734  ab196087 					    0, &inv_buf));
   2162     0    stevel 				}
   2163     0    stevel 			}
   2164     0    stevel 
   2165  1618       rie 			Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP,
   2166  1618       rie 			    MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type,
   2167  1618       rie 			    rels, relname, symname, 0);
   2168     0    stevel 		}
   2169     0    stevel 	}
   2170     0    stevel }
   2171     0    stevel 
   2172  5230  ab196087 
   2173  5230  ab196087 /*
   2174  5230  ab196087  * This value controls which test dyn_test() performs.
   2175  5230  ab196087  */
   2176  5230  ab196087 typedef enum { DYN_TEST_ADDR, DYN_TEST_SIZE, DYN_TEST_ENTSIZE } dyn_test_t;
   2177  5230  ab196087 
   2178  5230  ab196087 /*
   2179  5230  ab196087  * Used by dynamic() to compare the value of a dynamic element against
   2180  5230  ab196087  * the starting address of the section it references.
   2181  5230  ab196087  *
   2182  5230  ab196087  * entry:
   2183  5230  ab196087  *	test_type - Specify which dyn item is being tested.
   2184  5230  ab196087  *	sh_type - SHT_* type value for required section.
   2185  5230  ab196087  *	sec_cache - Cache entry for section, or NULL if the object lacks
   2186  5230  ab196087  *		a section of this type.
   2187  5230  ab196087  *	dyn - Dyn entry to be tested
   2188  5230  ab196087  *	dynsec_cnt - # of dynamic section being examined. The first
   2189  5230  ab196087  *		dynamic section is 1, the next is 2, and so on...
   2190  5230  ab196087  *	ehdr - ELF header for file
   2191  5230  ab196087  *	file - Name of file
   2192  5230  ab196087  */
   2193  5230  ab196087 static void
   2194  5230  ab196087 dyn_test(dyn_test_t test_type, Word sh_type, Cache *sec_cache, Dyn *dyn,
   2195  9273       Ali     Word dynsec_cnt, Ehdr *ehdr, uchar_t osabi, const char *file)
   2196  5230  ab196087 {
   2197  5230  ab196087 	Conv_inv_buf_t	buf1, buf2;
   2198  5230  ab196087 
   2199  5230  ab196087 	/*
   2200  5230  ab196087 	 * These tests are based around the implicit assumption that
   2201  5230  ab196087 	 * there is only one dynamic section in an object, and also only
   2202  5230  ab196087 	 * one of the sections it references. We have therefore gathered
   2203  5230  ab196087 	 * all of the necessary information to test this in a single pass
   2204  5230  ab196087 	 * over the section headers, which is very efficient. We are not
   2205  5230  ab196087 	 * aware of any case where more than one dynamic section would
   2206  5230  ab196087 	 * be meaningful in an ELF object, so this is a reasonable solution.
   2207  5230  ab196087 	 *
   2208  5230  ab196087 	 * To test multiple dynamic sections correctly would be more
   2209  5230  ab196087 	 * expensive in code and time. We would have to build a data structure
   2210  5230  ab196087 	 * containing all the dynamic elements. Then, we would use the address
   2211  5230  ab196087 	 * to locate the section it references and ensure the section is of
   2212  5230  ab196087 	 * the right type and that the address in the dynamic element is
   2213  5230  ab196087 	 * to the start of the section. Then, we could check the size and
   2214  5230  ab196087 	 * entsize values against those same sections. This is O(n^2), and
   2215  5230  ab196087 	 * also complicated.
   2216  5230  ab196087 	 *
   2217  5230  ab196087 	 * In the highly unlikely case that there is more than one dynamic
   2218  5230  ab196087 	 * section, we only test the first one, and simply allow the values
   2219  5230  ab196087 	 * of the subsequent one to be displayed unchallenged.
   2220  5230  ab196087 	 */
   2221  5230  ab196087 	if (dynsec_cnt != 1)
   2222  5230  ab196087 		return;
   2223  5230  ab196087 
   2224  5230  ab196087 	/*
   2225  5230  ab196087 	 * A DT_ item that references a section address should always find
   2226  5230  ab196087 	 * the section in the file.
   2227  5230  ab196087 	 */
   2228  5230  ab196087 	if (sec_cache == NULL) {
   2229  6299  ab196087 		const char *name;
   2230  6299  ab196087 
   2231  6299  ab196087 		/*
   2232  6299  ab196087 		 * Supply section names instead of section types for
   2233  6299  ab196087 		 * things that reference progbits so that the error
   2234  6299  ab196087 		 * message will make more sense.
   2235  6299  ab196087 		 */
   2236  6299  ab196087 		switch (dyn->d_tag) {
   2237  6299  ab196087 		case DT_INIT:
   2238  6299  ab196087 			name = MSG_ORIG(MSG_ELF_INIT);
   2239  6299  ab196087 			break;
   2240  6299  ab196087 		case DT_FINI:
   2241  6299  ab196087 			name = MSG_ORIG(MSG_ELF_FINI);
   2242  6299  ab196087 			break;
   2243  6299  ab196087 		default:
   2244  9273       Ali 			name = conv_sec_type(osabi, ehdr->e_machine,
   2245  9273       Ali 			    sh_type, 0, &buf1);
   2246  6299  ab196087 			break;
   2247  6299  ab196087 		}
   2248  5230  ab196087 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_DYNNOBCKSEC), file,
   2249  9273       Ali 		    name, conv_dyn_tag(dyn->d_tag, osabi, ehdr->e_machine,
   2250  9273       Ali 		    0, &buf2));
   2251  5230  ab196087 		return;
   2252  5230  ab196087 	}
   2253  5230  ab196087 
   2254  5230  ab196087 
   2255  5230  ab196087 	switch (test_type) {
   2256  5230  ab196087 	case DYN_TEST_ADDR:
   2257  5230  ab196087 		/* The section address should match the DT_ item value */
   2258  5230  ab196087 		if (dyn->d_un.d_val != sec_cache->c_shdr->sh_addr)
   2259  5230  ab196087 			(void) fprintf(stderr,
   2260  5230  ab196087 			    MSG_INTL(MSG_ERR_DYNBADADDR), file,
   2261  9273       Ali 			    conv_dyn_tag(dyn->d_tag, osabi, ehdr->e_machine,
   2262  9273       Ali 			    0, &buf1), EC_ADDR(dyn->d_un.d_val),
   2263  9273       Ali 			    sec_cache->c_ndx, sec_cache->c_name,
   2264  5230  ab196087 			    EC_ADDR(sec_cache->c_shdr->sh_addr));
   2265  5230  ab196087 		break;
   2266  5230  ab196087 
   2267  5230  ab196087 	case DYN_TEST_SIZE:
   2268  5230  ab196087 		/* The section size should match the DT_ item value */
   2269  5230  ab196087 		if (dyn->d_un.d_val != sec_cache->c_shdr->sh_size)
   2270  5230  ab196087 			(void) fprintf(stderr,
   2271  5230  ab196087 			    MSG_INTL(MSG_ERR_DYNBADSIZE), file,
   2272  9273       Ali 			    conv_dyn_tag(dyn->d_tag, osabi, ehdr->e_machine,
   2273  9273       Ali 			    0, &buf1), EC_XWORD(dyn->d_un.d_val),
   2274  5230  ab196087 			    sec_cache->c_ndx, sec_cache->c_name,
   2275  5230  ab196087 			    EC_XWORD(sec_cache->c_shdr->sh_size));
   2276  5230  ab196087 		break;
   2277  5230  ab196087 
   2278  5230  ab196087 	case DYN_TEST_ENTSIZE:
   2279  5230  ab196087 		/* The sh_entsize value should match the DT_ item value */
   2280  5230  ab196087 		if (dyn->d_un.d_val != sec_cache->c_shdr->sh_entsize)
   2281  5230  ab196087 			(void) fprintf(stderr,
   2282  5230  ab196087 			    MSG_INTL(MSG_ERR_DYNBADENTSIZE), file,
   2283  9273       Ali 			    conv_dyn_tag(dyn->d_tag, osabi, ehdr->e_machine,
   2284  9273       Ali 			    0, &buf1), EC_XWORD(dyn->d_un.d_val),
   2285  5230  ab196087 			    sec_cache->c_ndx, sec_cache->c_name,
   2286  5230  ab196087 			    EC_XWORD(sec_cache->c_shdr->sh_entsize));
   2287  5230  ab196087 		break;
   2288  5230  ab196087 	}
   2289  5230  ab196087 }
   2290  5230  ab196087 
   2291  5230  ab196087 
   2292     0    stevel /*
   2293  6299  ab196087  * There are some DT_ entries that have corresponding symbols
   2294  6299  ab196087  * (e.g. DT_INIT and _init). It is expected that these items will
   2295  6299  ab196087  * both have the same value if both are present. This routine
   2296  6299  ab196087  * examines the well known symbol tables for such symbols and
   2297  6299  ab196087  * issues warnings for any that don't match.
   2298  6299  ab196087  *
   2299  6299  ab196087  * entry:
   2300  6299  ab196087  *	dyn - Dyn entry to be tested
   2301  6299  ab196087  *	symname - Name of symbol that corresponds to dyn
   2302  6299  ab196087  *	symtab_cache, dynsym_cache, ldynsym_cache - Symbol tables to check
   2303  6299  ab196087  *	cache - Cache of all section headers
   2304  6299  ab196087  *	shnum - # of sections in cache
   2305  6299  ab196087  *	ehdr - ELF header for file
   2306  6299  ab196087  *	file - Name of file
   2307  6299  ab196087  */
   2308  6299  ab196087 static void
   2309  6299  ab196087 dyn_symtest(Dyn *dyn, const char *symname, Cache *symtab_cache,
   2310  6299  ab196087     Cache *dynsym_cache, Cache *ldynsym_cache, Cache *cache,
   2311  9273       Ali     Word shnum, Ehdr *ehdr, uchar_t osabi, const char *file)
   2312  6299  ab196087 {
   2313  6299  ab196087 	Conv_inv_buf_t	buf;
   2314  6299  ab196087 	int		i;
   2315  6299  ab196087 	Sym		*sym;
   2316  6299  ab196087 	Cache		*_cache;
   2317  6299  ab196087 
   2318  6299  ab196087 	for (i = 0; i < 3; i++) {
   2319  6299  ab196087 		switch (i) {
   2320  6299  ab196087 		case 0:
   2321  6299  ab196087 			_cache = symtab_cache;
   2322  6299  ab196087 			break;
   2323  6299  ab196087 		case 1:
   2324  6299  ab196087 			_cache = dynsym_cache;
   2325  6299  ab196087 			break;
   2326  6299  ab196087 		case 2:
   2327  6299  ab196087 			_cache = ldynsym_cache;
   2328  6299  ab196087 			break;
   2329  6299  ab196087 		}
   2330  6299  ab196087 
   2331  6299  ab196087 		if ((_cache != NULL) &&
   2332  6299  ab196087 		    symlookup(symname, cache, shnum, &sym, _cache, file) &&
   2333  6299  ab196087 		    (sym->st_value != dyn->d_un.d_val))
   2334  6299  ab196087 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_DYNSYMVAL),
   2335  9273       Ali 			    file, _cache->c_name, conv_dyn_tag(dyn->d_tag,
   2336  9273       Ali 			    osabi, ehdr->e_machine, 0, &buf),
   2337  6299  ab196087 			    symname, EC_ADDR(sym->st_value));
   2338  6299  ab196087 	}
   2339  6299  ab196087 }
   2340  6299  ab196087 
   2341  6299  ab196087 
   2342  6299  ab196087 /*
   2343     0    stevel  * Search for and process a .dynamic section.
   2344     0    stevel  */
   2345     0    stevel static void
   2346  9273       Ali dynamic(Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi, const char *file)
   2347     0    stevel {
   2348  5230  ab196087 	struct {
   2349  6299  ab196087 		Cache	*symtab;
   2350  5230  ab196087 		Cache	*dynstr;
   2351  5230  ab196087 		Cache	*dynsym;
   2352  5230  ab196087 		Cache	*hash;
   2353  5230  ab196087 		Cache	*fini;
   2354  5230  ab196087 		Cache	*fini_array;
   2355  5230  ab196087 		Cache	*init;
   2356  5230  ab196087 		Cache	*init_array;
   2357  5230  ab196087 		Cache	*preinit_array;
   2358  5230  ab196087 		Cache	*rel;
   2359  5230  ab196087 		Cache	*rela;
   2360  5230  ab196087 		Cache	*sunw_cap;
   2361  5230  ab196087 		Cache	*sunw_ldynsym;
   2362  5230  ab196087 		Cache	*sunw_move;
   2363  5230  ab196087 		Cache	*sunw_syminfo;
   2364  5230  ab196087 		Cache	*sunw_symsort;
   2365  5230  ab196087 		Cache	*sunw_tlssort;
   2366  5230  ab196087 		Cache	*sunw_verdef;
   2367  5230  ab196087 		Cache	*sunw_verneed;
   2368  5230  ab196087 		Cache	*sunw_versym;
   2369  5230  ab196087 	} sec;
   2370  5230  ab196087 	Word	dynsec_ndx;
   2371  5230  ab196087 	Word	dynsec_num;
   2372  5230  ab196087 	int	dynsec_cnt;
   2373  1618       rie 	Word	cnt;
   2374  9273       Ali 	int	osabi_solaris = osabi == ELFOSABI_SOLARIS;
   2375     0    stevel 
   2376  5230  ab196087 	/*
   2377  5230  ab196087 	 * Make a pass over all the sections, gathering section information
   2378  5230  ab196087 	 * we'll need below.
   2379  5230  ab196087 	 */
   2380  5230  ab196087 	dynsec_num = 0;
   2381  5230  ab196087 	bzero(&sec, sizeof (sec));
   2382     0    stevel 	for (cnt = 1; cnt < shnum; cnt++) {
   2383  5230  ab196087 		Cache	*_cache = &cache[cnt];
   2384  5230  ab196087 
   2385  5230  ab196087 		switch (_cache->c_shdr->sh_type) {
   2386  5230  ab196087 		case SHT_DYNAMIC:
   2387  5230  ab196087 			if (dynsec_num == 0) {
   2388  5230  ab196087 				dynsec_ndx = cnt;
   2389  5230  ab196087 
   2390  5230  ab196087 				/* Does it have a valid string table? */
   2391  5230  ab196087 				(void) stringtbl(cache, 0, cnt, shnum, file,
   2392  5230  ab196087 				    0, 0, &sec.dynstr);
   2393  5230  ab196087 			}
   2394  5230  ab196087 			dynsec_num++;
   2395  5230  ab196087 			break;
   2396  5230  ab196087 
   2397  5230  ab196087 
   2398  5230  ab196087 		case SHT_PROGBITS:
   2399  5230  ab196087 			/*
   2400  5230  ab196087 			 * We want to detect the .init and .fini sections,
   2401  5230  ab196087 			 * if present. These are SHT_PROGBITS, so all we
   2402  5230  ab196087 			 * have to go on is the section name. Normally comparing
   2403  5230  ab196087 			 * names is a bad idea, but there are some special
   2404  5230  ab196087 			 * names (i.e. .init/.fini/.interp) that are very
   2405  5230  ab196087 			 * difficult to use in any other context, and for
   2406  5230  ab196087 			 * these symbols, we do the heuristic match.
   2407  5230  ab196087 			 */
   2408  5230  ab196087 			if (strcmp(_cache->c_name,
   2409  5230  ab196087 			    MSG_ORIG(MSG_ELF_INIT)) == 0) {
   2410  5230  ab196087 				if (sec.init == NULL)
   2411  5230  ab196087 					sec.init = _cache;
   2412  5230  ab196087 			} else if (strcmp(_cache->c_name,
   2413  5230  ab196087 			    MSG_ORIG(MSG_ELF_FINI)) == 0) {
   2414  5230  ab196087 				if (sec.fini == NULL)
   2415  5230  ab196087 					sec.fini = _cache;
   2416  5230  ab196087 			}
   2417  5230  ab196087 			break;
   2418  5230  ab196087 
   2419  5230  ab196087 		case SHT_REL:
   2420  5230  ab196087 			/*
   2421  5230  ab196087 			 * We want the SHT_REL section with the lowest
   2422  5230  ab196087 			 * offset. The linker gathers them together,
   2423  5230  ab196087 			 * and puts the address of the first one
   2424  5230  ab196087 			 * into the DT_REL dynamic element.
   2425  5230  ab196087 			 */
   2426  5230  ab196087 			if ((sec.rel == NULL) ||
   2427  5230  ab196087 			    (_cache->c_shdr->sh_offset <
   2428  5230  ab196087 			    sec.rel->c_shdr->sh_offset))
   2429  5230  ab196087 				sec.rel = _cache;
   2430  5230  ab196087 			break;
   2431  5230  ab196087 
   2432  5230  ab196087 		case SHT_RELA:
   2433  5230  ab196087 			/* RELA is handled just like RELA above */
   2434  5230  ab196087 			if ((sec.rela == NULL) ||
   2435  5230  ab196087 			    (_cache->c_shdr->sh_offset <
   2436  5230  ab196087 			    sec.rela->c_shdr->sh_offset))
   2437  5230  ab196087 				sec.rela = _cache;
   2438  5230  ab196087 			break;
   2439  5230  ab196087 
   2440  5230  ab196087 		/*
   2441  5230  ab196087 		 * The GRAB macro is used for the simple case in which
   2442  5230  ab196087 		 * we simply grab the first section of the desired type.
   2443  5230  ab196087 		 */
   2444  5230  ab196087 #define	GRAB(_sec_type, _sec_field) \
   2445  5230  ab196087 		case _sec_type: \
   2446  5230  ab196087 			if (sec._sec_field == NULL) \
   2447  5230  ab196087 				sec._sec_field = _cache; \
   2448  5230  ab196087 				break
   2449  6299  ab196087 		GRAB(SHT_SYMTAB,	symtab);
   2450  5230  ab196087 		GRAB(SHT_DYNSYM,	dynsym);
   2451  5230  ab196087 		GRAB(SHT_FINI_ARRAY,	fini_array);
   2452  5230  ab196087 		GRAB(SHT_HASH,		hash);
   2453  5230  ab196087 		GRAB(SHT_INIT_ARRAY,	init_array);
   2454  5230  ab196087 		GRAB(SHT_SUNW_move,	sunw_move);
   2455  5230  ab196087 		GRAB(SHT_PREINIT_ARRAY,	preinit_array);
   2456  5230  ab196087 		GRAB(SHT_SUNW_cap,	sunw_cap);
   2457  5230  ab196087 		GRAB(SHT_SUNW_LDYNSYM,	sunw_ldynsym);
   2458  5230  ab196087 		GRAB(SHT_SUNW_syminfo,	sunw_syminfo);
   2459  5230  ab196087 		GRAB(SHT_SUNW_symsort,	sunw_symsort);
   2460  5230  ab196087 		GRAB(SHT_SUNW_tlssort,	sunw_tlssort);
   2461  5230  ab196087 		GRAB(SHT_SUNW_verdef,	sunw_verdef);
   2462  5230  ab196087 		GRAB(SHT_SUNW_verneed,	sunw_verneed);
   2463  5230  ab196087 		GRAB(SHT_SUNW_versym,	sunw_versym);
   2464  5230  ab196087 #undef GRAB
   2465  5230  ab196087 		}
   2466  5230  ab196087 	}
   2467  5230  ab196087 
   2468  5230  ab196087 	/*
   2469  5230  ab196087 	 * If no dynamic section, return immediately. If more than one
   2470  5230  ab196087 	 * dynamic section, then something odd is going on and an error
   2471  5230  ab196087 	 * is in order, but then continue on and display them all.
   2472  5230  ab196087 	 */
   2473  5230  ab196087 	if (dynsec_num == 0)
   2474  5230  ab196087 		return;
   2475  5230  ab196087 	if (dynsec_num > 1)
   2476  5230  ab196087 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MULTDYN),
   2477  5230  ab196087 		    file, EC_WORD(dynsec_num));
   2478  5230  ab196087 
   2479  5230  ab196087 
   2480  5230  ab196087 	dynsec_cnt = 0;
   2481  5230  ab196087 	for (cnt = dynsec_ndx; (cnt < shnum) && (dynsec_cnt < dynsec_num);
   2482  5230  ab196087 	    cnt++) {
   2483  1618       rie 		Dyn	*dyn;
   2484  1618       rie 		ulong_t	numdyn;
   2485  3850  ab196087 		int	ndx, end_ndx;
   2486  1618       rie 		Cache	*_cache = &cache[cnt], *strsec;
   2487  1618       rie 		Shdr	*shdr = _cache->c_shdr;
   2488  5230  ab196087 		int	dumped = 0;
   2489     0    stevel 
   2490     0    stevel 		if (shdr->sh_type != SHT_DYNAMIC)
   2491     0    stevel 			continue;
   2492  5230  ab196087 		dynsec_cnt++;
   2493     0    stevel 
   2494     0    stevel 		/*
   2495  1618       rie 		 * Verify the associated string table section.
   2496     0    stevel 		 */
   2497  1618       rie 		if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0)
   2498     0    stevel 			continue;
   2499  1618       rie 
   2500  3466       rie 		if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
   2501  3466       rie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
   2502  3466       rie 			    file, _cache->c_name);
   2503  3466       rie 			continue;
   2504  3466       rie 		}
   2505  3466       rie 		if (_cache->c_data == NULL)
   2506  3466       rie 			continue;
   2507  3466       rie 
   2508     0    stevel 		numdyn = shdr->sh_size / shdr->sh_entsize;
   2509  1618       rie 		dyn = (Dyn *)_cache->c_data->d_buf;
   2510     0    stevel 
   2511  5230  ab196087 		/*
   2512  5230  ab196087 		 * We expect the REL/RELA entries to reference the reloc
   2513  5230  ab196087 		 * section with the lowest address. However, this is
   2514  5230  ab196087 		 * not true for dumped objects. Detect if this object has
   2515  5230  ab196087 		 * been dumped so that we can skip the reloc address test
   2516  5230  ab196087 		 * in that case.
   2517  5230  ab196087 		 */
   2518  5230  ab196087 		for (ndx = 0; ndx < numdyn; dyn++, ndx++) {
   2519  5230  ab196087 			if (dyn->d_tag == DT_FLAGS_1) {
   2520  5230  ab196087 				dumped = (dyn->d_un.d_val & DF_1_CONFALT) != 0;
   2521  5230  ab196087 				break;
   2522  5230  ab196087 			}
   2523  5230  ab196087 		}
   2524  5230  ab196087 		dyn = (Dyn *)_cache->c_data->d_buf;
   2525  5230  ab196087 
   2526  1618       rie 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
   2527  1618       rie 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name);
   2528     0    stevel 
   2529  1618       rie 		Elf_dyn_title(0);
   2530     0    stevel 
   2531  1618       rie 		for (ndx = 0; ndx < numdyn; dyn++, ndx++) {
   2532  4734  ab196087 			union {
   2533  6206  ab196087 				Conv_inv_buf_t		inv;
   2534  4734  ab196087 				Conv_dyn_flag_buf_t	flag;
   2535  4734  ab196087 				Conv_dyn_flag1_buf_t	flag1;
   2536  4734  ab196087 				Conv_dyn_posflag1_buf_t	posflag1;
   2537  4734  ab196087 				Conv_dyn_feature1_buf_t	feature1;
   2538  4734  ab196087 			} c_buf;
   2539  5230  ab196087 			const char	*name = NULL;
   2540     0    stevel 
   2541     0    stevel 			/*
   2542     0    stevel 			 * Print the information numerically, and if possible
   2543  5230  ab196087 			 * as a string. If a string is available, name is
   2544  5230  ab196087 			 * set to reference it.
   2545  5230  ab196087 			 *
   2546  5230  ab196087 			 * Also, take this opportunity to sanity check
   2547  5230  ab196087 			 * the values of DT elements. In the code above,
   2548  5230  ab196087 			 * we gathered information on sections that are
   2549  5230  ab196087 			 * referenced by the dynamic section. Here, we
   2550  5230  ab196087 			 * compare the attributes of those sections to
   2551  5230  ab196087 			 * the DT_ items that reference them and report
   2552  5230  ab196087 			 * on inconsistencies.
   2553  5230  ab196087 			 *
   2554  5230  ab196087 			 * Things not currently tested that could be improved
   2555  5230  ab196087 			 * in later revisions include:
   2556  5230  ab196087 			 *	- We don't check PLT or GOT related items
   2557  5230  ab196087 			 *	- We don't handle computing the lengths of
   2558  5230  ab196087 			 *		relocation arrays. To handle this
   2559  5230  ab196087 			 *		requires examining data that spans
   2560  5230  ab196087 			 *		across sections, in a contiguous span
   2561  5230  ab196087 			 *		within a single segment.
   2562  5230  ab196087 			 *	- DT_VERDEFNUM and DT_VERNEEDNUM can't be
   2563  5230  ab196087 			 *		verified without parsing the sections.
   2564  5230  ab196087 			 *	- We don't handle DT_SUNW_SYMSZ, which would
   2565  5230  ab196087 			 *		be the sum of the lengths of .dynsym and
   2566  5230  ab196087 			 *		.SUNW_ldynsym
   2567  5230  ab196087 			 *	- DT_SUNW_STRPAD can't be verified other than
   2568  5230  ab196087 			 *		to check that it's not larger than
   2569  5230  ab196087 			 *		the string table.
   2570  5230  ab196087 			 *	- Some items come in "all or none" clusters
   2571  5230  ab196087 			 *		that give an address, element size,
   2572  5230  ab196087 			 *		and data length in bytes. We don't
   2573  5230  ab196087 			 *		verify that there are no missing items
   2574  5230  ab196087 			 *		in such groups.
   2575     0    stevel 			 */
   2576  3850  ab196087 			switch (dyn->d_tag) {
   2577  3850  ab196087 			case DT_NULL:
   2578  3850  ab196087 				/*
   2579  3850  ab196087 				 * Special case: DT_NULLs can come in groups
   2580  3850  ab196087 				 * that we prefer to reduce to a single line.
   2581  3850  ab196087 				 */
   2582  3850  ab196087 				end_ndx = ndx;
   2583  3850  ab196087 				while ((end_ndx < (numdyn - 1)) &&
   2584  4433  ab196087 				    ((dyn + 1)->d_tag == DT_NULL)) {
   2585  3850  ab196087 					dyn++;
   2586  3850  ab196087 					end_ndx++;
   2587  3850  ab196087 				}
   2588  3850  ab196087 				Elf_dyn_null_entry(0, dyn, ndx, end_ndx);
   2589  3850  ab196087 				ndx = end_ndx;
   2590  3850  ab196087 				continue;
   2591  3850  ab196087 
   2592  3850  ab196087 			/*
   2593  5230  ab196087 			 * String items all reference the dynstr. The string()
   2594  5230  ab196087 			 * function does the necessary sanity checking.
   2595  3850  ab196087 			 */
   2596  3850  ab196087 			case DT_NEEDED:
   2597  3850  ab196087 			case DT_SONAME:
   2598  3850  ab196087 			case DT_FILTER:
   2599  3850  ab196087 			case DT_AUXILIARY:
   2600  3850  ab196087 			case DT_CONFIG:
   2601  3850  ab196087 			case DT_RPATH:
   2602  3850  ab196087 			case DT_RUNPATH:
   2603  3850  ab196087 			case DT_USED:
   2604  3850  ab196087 			case DT_DEPAUDIT:
   2605  3850  ab196087 			case DT_AUDIT:
   2606  9273       Ali 				name = string(_cache, ndx, strsec,
   2607  9273       Ali 				    file, dyn->d_un.d_ptr);
   2608  9273       Ali 				break;
   2609  9273       Ali 
   2610  3850  ab196087 			case DT_SUNW_AUXILIARY:
   2611  3850  ab196087 			case DT_SUNW_FILTER:
   2612  9273       Ali 				if (osabi_solaris)
   2613  9273       Ali 					name = string(_cache, ndx, strsec,
   2614  9273       Ali 					    file, dyn->d_un.d_ptr);
   2615  3850  ab196087 				break;
   2616  3850  ab196087 
   2617  3850  ab196087 			case DT_FLAGS:
   2618  4734  ab196087 				name = conv_dyn_flag(dyn->d_un.d_val,
   2619  4734  ab196087 				    0, &c_buf.flag);
   2620  3850  ab196087 				break;
   2621  3850  ab196087 			case DT_FLAGS_1:
   2622  5088  ab196087 				name = conv_dyn_flag1(dyn->d_un.d_val, 0,
   2623  4734  ab196087 				    &c_buf.flag1);
   2624  3850  ab196087 				break;
   2625  3850  ab196087 			case DT_POSFLAG_1:
   2626  4734  ab196087 				name = conv_dyn_posflag1(dyn->d_un.d_val, 0,
   2627  4734  ab196087 				    &c_buf.posflag1);
   2628  3850  ab196087 				break;
   2629  3850  ab196087 			case DT_FEATURE_1:
   2630  4734  ab196087 				name = conv_dyn_feature1(dyn->d_un.d_val, 0,
   2631  4734  ab196087 				    &c_buf.feature1);
   2632  3850  ab196087 				break;
   2633  3850  ab196087 			case DT_DEPRECATED_SPARC_REGISTER:
   2634  1618       rie 				name = MSG_INTL(MSG_STR_DEPRECATED);
   2635  6206  ab196087 				break;
   2636  6206  ab196087 
   2637  6206  ab196087 			case DT_SUNW_LDMACH:
   2638  9273       Ali 				if (!osabi_solaris)
   2639  9273       Ali 					break;
   2640  9273       Ali 				name = conv_ehdr_mach((Half)dyn->d_un.d_val,
   2641  9273       Ali 				    0, &c_buf.inv);
   2642  3850  ab196087 				break;
   2643  5230  ab196087 
   2644  5230  ab196087 			/*
   2645  5230  ab196087 			 * Cases below this point are strictly sanity checking,
   2646  5230  ab196087 			 * and do not generate a name string. The TEST_ macros
   2647  5230  ab196087 			 * are used to hide the boilerplate arguments neeeded
   2648  5230  ab196087 			 * by dyn_test().
   2649  5230  ab196087 			 */
   2650  5230  ab196087 #define	TEST_ADDR(_sh_type, _sec_field) \
   2651  5230  ab196087 				dyn_test(DYN_TEST_ADDR, _sh_type, \
   2652  9273       Ali 				    sec._sec_field, dyn, dynsec_cnt, ehdr, \
   2653  9273       Ali 				    osabi, file)
   2654  5230  ab196087 #define	TEST_SIZE(_sh_type, _sec_field) \
   2655  5230  ab196087 				dyn_test(DYN_TEST_SIZE, _sh_type, \
   2656  9273       Ali 				    sec._sec_field, dyn, dynsec_cnt, ehdr, \
   2657  9273       Ali 				    osabi, file)
   2658  5230  ab196087 #define	TEST_ENTSIZE(_sh_type, _sec_field) \
   2659  5230  ab196087 				dyn_test(DYN_TEST_ENTSIZE, _sh_type, \
   2660  9273       Ali 				    sec._sec_field, dyn, dynsec_cnt, ehdr, \
   2661  9273       Ali 				    osabi, file)
   2662  5230  ab196087 
   2663  5230  ab196087 			case DT_FINI:
   2664  6299  ab196087 				dyn_symtest(dyn, MSG_ORIG(MSG_SYM_FINI),
   2665  6299  ab196087 				    sec.symtab, sec.dynsym, sec.sunw_ldynsym,
   2666  9273       Ali 				    cache, shnum, ehdr, osabi, file);
   2667  5230  ab196087 				TEST_ADDR(SHT_PROGBITS, fini);
   2668  3850  ab196087 				break;
   2669  5230  ab196087 
   2670  5230  ab196087 			case DT_FINI_ARRAY:
   2671  5230  ab196087 				TEST_ADDR(SHT_FINI_ARRAY, fini_array);
   2672  5230  ab196087 				break;
   2673  5230  ab196087 
   2674  5230  ab196087 			case DT_FINI_ARRAYSZ:
   2675  5230  ab196087 				TEST_SIZE(SHT_FINI_ARRAY, fini_array);
   2676  5230  ab196087 				break;
   2677  5230  ab196087 
   2678  5230  ab196087 			case DT_HASH:
   2679  5230  ab196087 				TEST_ADDR(SHT_HASH, hash);
   2680  5230  ab196087 				break;
   2681  5230  ab196087 
   2682  5230  ab196087 			case DT_INIT:
   2683  6299  ab196087 				dyn_symtest(dyn, MSG_ORIG(MSG_SYM_INIT),
   2684  6299  ab196087 				    sec.symtab, sec.dynsym, sec.sunw_ldynsym,
   2685  9273       Ali 				    cache, shnum, ehdr, osabi, file);
   2686  5230  ab196087 				TEST_ADDR(SHT_PROGBITS, init);
   2687  5230  ab196087 				break;
   2688  5230  ab196087 
   2689  5230  ab196087 			case DT_INIT_ARRAY:
   2690  5230  ab196087 				TEST_ADDR(SHT_INIT_ARRAY, init_array);
   2691  5230  ab196087 				break;
   2692  5230  ab196087 
   2693  5230  ab196087 			case DT_INIT_ARRAYSZ:
   2694  5230  ab196087 				TEST_SIZE(SHT_INIT_ARRAY, init_array);
   2695  5230  ab196087 				break;
   2696  5230  ab196087 
   2697  5230  ab196087 			case DT_MOVEENT:
   2698  5230  ab196087 				TEST_ENTSIZE(SHT_SUNW_move, sunw_move);
   2699  5230  ab196087 				break;
   2700  5230  ab196087 
   2701  5230  ab196087 			case DT_MOVESZ:
   2702  5230  ab196087 				TEST_SIZE(SHT_SUNW_move, sunw_move);
   2703  5230  ab196087 				break;
   2704  5230  ab196087 
   2705  5230  ab196087 			case DT_MOVETAB:
   2706  5230  ab196087 				TEST_ADDR(SHT_SUNW_move, sunw_move);
   2707  5230  ab196087 				break;
   2708  5230  ab196087 
   2709  5230  ab196087 			case DT_PREINIT_ARRAY:
   2710  5230  ab196087 				TEST_ADDR(SHT_PREINIT_ARRAY, preinit_array);
   2711  5230  ab196087 				break;
   2712  5230  ab196087 
   2713  5230  ab196087 			case DT_PREINIT_ARRAYSZ:
   2714  5230  ab196087 				TEST_SIZE(SHT_PREINIT_ARRAY, preinit_array);
   2715  5230  ab196087 				break;
   2716  5230  ab196087 
   2717  5230  ab196087 			case DT_REL:
   2718  5230  ab196087 				if (!dumped)
   2719  5230  ab196087 					TEST_ADDR(SHT_REL, rel);
   2720  5230  ab196087 				break;
   2721  5230  ab196087 
   2722  5230  ab196087 			case DT_RELENT:
   2723  5230  ab196087 				TEST_ENTSIZE(SHT_REL, rel);
   2724  5230  ab196087 				break;
   2725  5230  ab196087 
   2726  5230  ab196087 			case DT_RELA:
   2727  5230  ab196087 				if (!dumped)
   2728  5230  ab196087 					TEST_ADDR(SHT_RELA, rela);
   2729  5230  ab196087 				break;
   2730  5230  ab196087 
   2731  5230  ab196087 			case DT_RELAENT:
   2732  5230  ab196087 				TEST_ENTSIZE(SHT_RELA, rela);
   2733  5230  ab196087 				break;
   2734  5230  ab196087 
   2735  5230  ab196087 			case DT_STRTAB:
   2736  5230  ab196087 				TEST_ADDR(SHT_STRTAB, dynstr);
   2737  5230  ab196087 				break;
   2738  5230  ab196087 
   2739  5230  ab196087 			case DT_STRSZ:
   2740  5230  ab196087 				TEST_SIZE(SHT_STRTAB, dynstr);
   2741  5230  ab196087 				break;
   2742  5230  ab196087 
   2743  5230  ab196087 			case DT_SUNW_CAP:
   2744  5230  ab196087 				TEST_ADDR(SHT_SUNW_cap, sunw_cap);
   2745  5230  ab196087 				break;
   2746  5230  ab196087 
   2747  5230  ab196087 			case DT_SUNW_SYMTAB:
   2748  5230  ab196087 				TEST_ADDR(SHT_SUNW_LDYNSYM, sunw_ldynsym);
   2749  5230  ab196087 				break;
   2750  5230  ab196087 
   2751  5230  ab196087 			case DT_SYMENT:
   2752  5230  ab196087 				TEST_ENTSIZE(SHT_DYNSYM, dynsym);
   2753  5230  ab196087 				break;
   2754  5230  ab196087 
   2755  5230  ab196087 			case DT_SYMINENT:
   2756  5230  ab196087 				TEST_ENTSIZE(SHT_SUNW_syminfo, sunw_syminfo);
   2757  5230  ab196087 				break;
   2758  5230  ab196087 
   2759  5230  ab196087 			case DT_SYMINFO:
   2760  5230  ab196087 				TEST_ADDR(SHT_SUNW_syminfo, sunw_syminfo);
   2761  5230  ab196087 				break;
   2762  5230  ab196087 
   2763  5230  ab196087 			case DT_SYMINSZ:
   2764  5230  ab196087 				TEST_SIZE(SHT_SUNW_syminfo, sunw_syminfo);
   2765  5230  ab196087 				break;
   2766  5230  ab196087 
   2767  5230  ab196087 			case DT_SYMTAB:
   2768  5230  ab196087 				TEST_ADDR(SHT_DYNSYM, dynsym);
   2769  5230  ab196087 				break;
   2770  5230  ab196087 
   2771  5230  ab196087 			case DT_SUNW_SORTENT:
   2772  5230  ab196087 				/*
   2773  5230  ab196087 				 * This entry is related to both the symsort and
   2774  5230  ab196087 				 * tlssort sections.
   2775  5230  ab196087 				 */
   2776  9273       Ali 				if (osabi_solaris) {
   2777  5230  ab196087 					int test_tls =
   2778  5230  ab196087 					    (sec.sunw_tlssort != NULL);
   2779  5230  ab196087 					int test_sym =
   2780  5230  ab196087 					    (sec.sunw_symsort != NULL) ||
   2781  5230  ab196087 					    !test_tls;
   2782  5230  ab196087 					if (test_sym)
   2783  5230  ab196087 						TEST_ENTSIZE(SHT_SUNW_symsort,
   2784  5230  ab196087 						    sunw_symsort);
   2785  5230  ab196087 					if (test_tls)
   2786  5230  ab196087 						TEST_ENTSIZE(SHT_SUNW_tlssort,
   2787  5230  ab196087 						    sunw_tlssort);
   2788  5230  ab196087 				}
   2789  5230  ab196087 				break;
   2790  5230  ab196087 
   2791  5230  ab196087 
   2792  5230  ab196087 			case DT_SUNW_SYMSORT:
   2793  9273       Ali 				if (osabi_solaris)
   2794  9273       Ali 					TEST_ADDR(SHT_SUNW_symsort,
   2795  9273       Ali 					    sunw_symsort);
   2796  5230  ab196087 				break;
   2797  5230  ab196087 
   2798  5230  ab196087 			case DT_SUNW_SYMSORTSZ:
   2799  9273       Ali 				if (osabi_solaris)
   2800  9273       Ali 					TEST_SIZE(SHT_SUNW_symsort,
   2801  9273       Ali 					    sunw_symsort);
   2802  5230  ab196087 				break;
   2803  5230  ab196087 
   2804  5230  ab196087 			case DT_SUNW_TLSSORT:
   2805  9273       Ali 				if (osabi_solaris)
   2806  9273       Ali 					TEST_ADDR(SHT_SUNW_tlssort,
   2807  9273       Ali 					    sunw_tlssort);
   2808  5230  ab196087 				break;
   2809  5230  ab196087 
   2810  5230  ab196087 			case DT_SUNW_TLSSORTSZ:
   2811  9273       Ali 				if (osabi_solaris)
   2812  9273       Ali 					TEST_SIZE(SHT_SUNW_tlssort,
   2813  9273       Ali 					    sunw_tlssort);
   2814  5230  ab196087 				break;
   2815  5230  ab196087 
   2816  5230  ab196087 			case DT_VERDEF:
   2817  5230  ab196087 				TEST_ADDR(SHT_SUNW_verdef, sunw_verdef);
   2818  5230  ab196087 				break;
   2819  5230  ab196087 
   2820  5230  ab196087 			case DT_VERNEED:
   2821  5230  ab196087 				TEST_ADDR(SHT_SUNW_verneed, sunw_verneed);
   2822  5230  ab196087 				break;
   2823  5230  ab196087 
   2824  5230  ab196087 			case DT_VERSYM:
   2825  5230  ab196087 				TEST_ADDR(SHT_SUNW_versym, sunw_versym);
   2826  5230  ab196087 				break;
   2827  5230  ab196087 #undef TEST_ADDR
   2828  5230  ab196087 #undef TEST_SIZE
   2829  5230  ab196087 #undef TEST_ENTSIZE
   2830  3850  ab196087 			}
   2831     0    stevel 
   2832  5230  ab196087 			if (name == NULL)
   2833  5230  ab196087 				name = MSG_ORIG(MSG_STR_EMPTY);
   2834  9273       Ali 			Elf_dyn_entry(0, dyn, ndx, name,
   2835  9273       Ali 			    osabi, ehdr->e_machine);
   2836     0    stevel 		}
   2837     0    stevel 	}
   2838     0    stevel }
   2839     0    stevel 
   2840     0    stevel /*
   2841     0    stevel  * Search for and process a MOVE section.
   2842     0    stevel  */
   2843     0    stevel static void
   2844  4168  ab196087 move(Cache *cache, Word shnum, const char *file, uint_t flags)
   2845     0    stevel {
   2846  1618       rie 	Word		cnt;
   2847  9085       Ali 	const char	*fmt = NULL;
   2848     0    stevel 
   2849     0    stevel 	for (cnt = 1; cnt < shnum; cnt++) {
   2850  1618       rie 		Word	movenum, symnum, ndx;
   2851  1618       rie 		Sym	*syms;
   2852  1618       rie 		Cache	*_cache = &cache[cnt];
   2853  1618       rie 		Shdr	*shdr = _cache->c_shdr;
   2854  1618       rie 		Cache	*symsec, *strsec;
   2855  1618       rie 		Move	*move;
   2856     0    stevel 
   2857     0    stevel 		if (shdr->sh_type != SHT_SUNW_move)
   2858     0    stevel 			continue;
   2859  5411  ab196087 		if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type))
   2860     0    stevel 			continue;
   2861     0    stevel 
   2862     0    stevel 		/*
   2863     0    stevel 		 * Determine the move data and number.
   2864     0    stevel 		 */
   2865     0    stevel 		if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
   2866     0    stevel 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
   2867     0    stevel 			    file, _cache->c_name);
   2868     0    stevel 			continue;
   2869     0    stevel 		}
   2870  3466       rie 		if (_cache->c_data == NULL)
   2871  3466       rie 			continue;
   2872  3466       rie 
   2873  1618       rie 		move = (Move *)_cache->c_data->d_buf;
   2874  1618       rie 		movenum = shdr->sh_size / shdr->sh_entsize;
   2875     0    stevel 
   2876     0    stevel 		/*
   2877  1618       rie 		 * Get the data buffer for the associated symbol table and
   2878  1618       rie 		 * string table.
   2879     0    stevel 		 */
   2880  1618       rie 		if (stringtbl(cache, 1, cnt, shnum, file,
   2881  1618       rie 		    &symnum, &symsec, &strsec) == 0)
   2882  1618       rie 			return;
   2883     0    stevel 
   2884  1618       rie 		syms = (Sym *)symsec->c_data->d_buf;
   2885     0    stevel 
   2886  1618       rie 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
   2887  1618       rie 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name);
   2888  1618       rie 		dbg_print(0, MSG_INTL(MSG_MOVE_TITLE));
   2889     0    stevel 
   2890  9085       Ali 		if (fmt == NULL)
   2891  1618       rie 			fmt = MSG_INTL(MSG_MOVE_ENTRY);
   2892     0    stevel 
   2893  1618       rie 		for (ndx = 0; ndx < movenum; move++, ndx++) {
   2894  1618       rie 			const char	*symname;
   2895  1618       rie 			char		index[MAXNDXSIZE], section[BUFSIZ];
   2896  1618       rie 			Word		symndx, shndx;
   2897  1618       rie 			Sym		*sym;
   2898     0    stevel 
   2899     0    stevel 			/*
   2900     0    stevel 			 * Check for null entries
   2901     0    stevel 			 */
   2902  1618       rie 			if ((move->m_info == 0) && (move->m_value == 0) &&
   2903  1618       rie 			    (move->m_poffset == 0) && (move->m_repeat == 0) &&
   2904  1618       rie 			    (move->m_stride == 0)) {
   2905  1618       rie 				dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY),
   2906  1618       rie 				    EC_XWORD(move->m_poffset), 0, 0, 0,
   2907  1618       rie 				    EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY));
   2908     0    stevel 				continue;
   2909     0    stevel 			}
   2910  1618       rie 			if (((symndx = ELF_M_SYM(move->m_info)) == 0) ||
   2911  1618       rie 			    (symndx >= symnum)) {
   2912     0    stevel 				(void) fprintf(stderr,
   2913     0    stevel 				    MSG_INTL(MSG_ERR_BADMINFO), file,
   2914  1618       rie 				    _cache->c_name, EC_XWORD(move->m_info));
   2915  1618       rie 
   2916  1618       rie 				(void) snprintf(index, MAXNDXSIZE,
   2917  1618       rie 				    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx));
   2918  1618       rie 				dbg_print(0, fmt, index,
   2919  1618       rie 				    EC_XWORD(move->m_poffset),
   2920  1618       rie 				    ELF_M_SIZE(move->m_info), move->m_repeat,
   2921  1618       rie 				    move->m_stride, move->m_value,
   2922     0    stevel 				    MSG_INTL(MSG_STR_UNKNOWN));
   2923     0    stevel 				continue;
   2924     0    stevel 			}
   2925     0    stevel 
   2926  1618       rie 			symname = relsymname(cache, _cache, strsec,
   2927  7463       Rod 			    symndx, symnum, ndx, syms, section, BUFSIZ, file);
   2928  1618       rie 			sym = (Sym *)(syms + symndx);
   2929     0    stevel 
   2930     0    stevel 			/*
   2931     0    stevel 			 * Additional sanity check.
   2932     0    stevel 			 */
   2933  1618       rie 			shndx = sym->st_shndx;
   2934     0    stevel 			if (!((shndx == SHN_COMMON) ||
   2935     0    stevel 			    (((shndx >= 1) && (shndx <= shnum)) &&
   2936  1618       rie 			    (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) {
   2937     0    stevel 				(void) fprintf(stderr,
   2938  1618       rie 				    MSG_INTL(MSG_ERR_BADSYM2), file,
   2939  6206  ab196087 				    _cache->c_name, EC_WORD(symndx),
   2940  6206  ab196087 				    demangle(symname, flags));
   2941     0    stevel 			}
   2942     0    stevel 
   2943  1618       rie 			(void) snprintf(index, MAXNDXSIZE,
   2944  1618       rie 			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx));
   2945  1618       rie 			dbg_print(0, fmt, index, EC_XWORD(move->m_poffset),
   2946  1618       rie 			    ELF_M_SIZE(move->m_info), move->m_repeat,
   2947  1618       rie 			    move->m_stride, move->m_value,
   2948  1618       rie 			    demangle(symname, flags));
   2949     0    stevel 		}
   2950     0    stevel 	}
   2951     0    stevel }
   2952     0    stevel 
   2953     0    stevel /*
   2954  9273       Ali  * parse_note_t is used to track the state used by parse_note_entry()
   2955  9273       Ali  * between calls, and also to return the results of each call.
   2956  9273       Ali  */
   2957  9273       Ali typedef struct {
   2958  9273       Ali 	/* pns_ fields track progress through the data */
   2959  9273       Ali 	const char	*pns_file;	/* File name */
   2960  9273       Ali 	Cache		*pns_cache;	/* Note section cache entry */
   2961  9273       Ali 	size_t		pns_size;	/* # unprocessed data bytes */
   2962  9273       Ali 	Word		*pns_data;	/* # to next unused data byte */
   2963  9273       Ali 
   2964  9273       Ali 	/* pn_ fields return the results for a single call */
   2965  9273       Ali 	Word		pn_namesz;	/* Value of note namesz field */
   2966  9273       Ali 	Word		pn_descsz;	/* Value of note descsz field */
   2967  9273       Ali 	Word		pn_type;	/* Value of note type field */
   2968  9273       Ali 	const char	*pn_name;	/* if (namesz > 0) ptr to name bytes */
   2969  9273       Ali 	const char	*pn_desc;	/* if (descsx > 0) ptr to data bytes */
   2970  9273       Ali } parse_note_t;
   2971  9273       Ali 
   2972  9273       Ali /*
   2973  9273       Ali  * Extract the various sub-parts of a note entry, and advance the
   2974  9273       Ali  * data pointer past it.
   2975  9273       Ali  *
   2976  9273       Ali  * entry:
   2977  9273       Ali  *	The state pns_ fields contain current values for the Note section
   2978  9273       Ali  *
   2979  9273       Ali  * exit:
   2980  9273       Ali  *	On success, True (1) is returned, the state pns_ fields have been
   2981  9273       Ali  *	advanced to point at the start of the next entry, and the information
   2982  9273       Ali  *	for the recovered note entry is found in the state pn_ fields.
   2983  9273       Ali  *
   2984  9273       Ali  *	On failure, False (0) is returned. The values contained in state
   2985  9273       Ali  *	are undefined.
   2986  9273       Ali  */
   2987  9273       Ali static int
   2988  9273       Ali parse_note_entry(parse_note_t *state)
   2989  9273       Ali {
   2990  9273       Ali 	size_t	pad, noteoff;
   2991  9273       Ali 
   2992  9273       Ali 	noteoff = (Word)state->pns_cache->c_data->d_size - state->pns_size;
   2993  9273       Ali 	/*
   2994  9273       Ali 	 * Make sure we can at least reference the 3 initial entries
   2995  9273       Ali 	 * (4-byte words) of the note information block.
   2996  9273       Ali 	 */
   2997  9273       Ali 	if (state->pns_size >= (sizeof (Word) * 3)) {
   2998  9273       Ali 		state->pns_size -= (sizeof (Word) * 3);
   2999  9273       Ali 	} else {
   3000  9273       Ali 		(void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ),
   3001  9273       Ali 		    state->pns_file, state->pns_cache->c_name,
   3002  9273       Ali 		    EC_WORD(noteoff));
   3003  9273       Ali 		return (0);
   3004  9273       Ali 	}
   3005  9273       Ali 
   3006  9273       Ali 	/*
   3007  9273       Ali 	 * Make sure any specified name string can be referenced.
   3008  9273       Ali 	 */
   3009  9273       Ali 	if ((state->pn_namesz = *state->pns_data++) != 0) {
   3010  9273       Ali 		if (state->pns_size >= state->pn_namesz) {
   3011  9273       Ali 			state->pns_size -= state->pn_namesz;
   3012  9273       Ali 		} else {
   3013  9273       Ali 			(void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADNMSZ),
   3014  9273       Ali 			    state->pns_file, state->pns_cache->c_name,
   3015  9273       Ali 			    EC_WORD(noteoff), EC_WORD(state->pn_namesz));
   3016  9273       Ali 			return (0);
   3017  9273       Ali 		}
   3018  9273       Ali 	}
   3019  9273       Ali 
   3020  9273       Ali 	/*
   3021  9273       Ali 	 * Make sure any specified descriptor can be referenced.
   3022  9273       Ali 	 */
   3023