xref: /titanic_51/usr/src/cmd/sgs/elfdump/common/elfdump.c (revision b811a51ae52cf3dd141a03c928fdcfbd6160c008)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Dump an elf file.
29  */
30 #include	<sys/elf_386.h>
31 #include	<sys/elf_amd64.h>
32 #include	<sys/elf_SPARC.h>
33 #include	<_libelf.h>
34 #include	<dwarf.h>
35 #include	<stdio.h>
36 #include	<unistd.h>
37 #include	<errno.h>
38 #include	<strings.h>
39 #include	<debug.h>
40 #include	<conv.h>
41 #include	<msg.h>
42 #include	<_elfdump.h>
43 
44 
45 /*
46  * VERSYM_STATE is used to maintain information about the VERSYM section
47  * in the object being analyzed. It is filled in by versions(), and used
48  * by init_symtbl_state() when displaying symbol information.
49  *
50  * max_verndx contains the largest version index that can appear
51  * in a Versym entry. This can never be less than 1: In the case where
52  * there is no verdef/verneed sections, the [0] index is reserved
53  * for local symbols, and the [1] index for globals. If Solaris versioning
54  * rules are in effect and there is a verdef section, then the number
55  * of defined versions provides this number. If GNU versioning is in effect,
56  * then:
57  *	- If there is no verneed section, it is the same as for
58  *		Solaris versioning.
59  *	- If there is a verneed section, the vna_other field of the
60  *		Vernaux structs contain versions, and max_verndx is the
61  *		largest such index.
62  *
63  * The value of the gnu field is based on the presence of
64  * a DT_VERSYM entry in the dynamic section: GNU ld produces these, and
65  * Solaris ld does not.
66  */
67 typedef struct {
68 	Cache	*cache;		/* Pointer to cache entry for VERSYM */
69 	Versym	*data;		/* Pointer to versym array */
70 	int	gnu;		/* True if object uses GNU versioning rules */
71 	int	max_verndx;	/* largest versym index value */
72 } VERSYM_STATE;
73 
74 /*
75  * SYMTBL_STATE is used to maintain information about a single symbol
76  * table section, for use by the routines that display symbol information.
77  */
78 typedef struct {
79 	const char	*file;		/* Name of file */
80 	Ehdr		*ehdr;		/* ELF header for file */
81 	Cache		*cache;		/* Cache of all section headers */
82 	Word		shnum;		/* # of sections in cache */
83 	Cache		*seccache;	/* Cache of symbol table section hdr */
84 	Word		secndx;		/* Index of symbol table section hdr */
85 	const char	*secname;	/* Name of section */
86 	uint_t		flags;		/* Command line option flags */
87 	struct {			/* Extended section index data */
88 		int	checked;	/* TRUE if already checked for shxndx */
89 		Word	*data;		/* NULL, or extended section index */
90 					/*	used for symbol table entries */
91 		uint_t	n;		/* # items in shxndx.data */
92 	} shxndx;
93 	VERSYM_STATE	*versym;	/* NULL, or associated VERSYM section */
94 	Sym 		*sym;		/* Array of symbols */
95 	Word		symn;		/* # of symbols */
96 } SYMTBL_STATE;
97 
98 
99 
100 /*
101  * Focal point for verifying symbol names.
102  */
103 static const char *
104 string(Cache *refsec, Word ndx, Cache *strsec, const char *file, Word name)
105 {
106 	/*
107 	 * If an error in this routine is due to a property of the string
108 	 * section, as opposed to a bad offset into the section (a property of
109 	 * the referencing section), then we will detect the same error on
110 	 * every call involving those sections. We use these static variables
111 	 * to retain the information needed to only issue each such error once.
112 	 */
113 	static Cache	*last_refsec;	/* Last referencing section seen */
114 	static int	strsec_err;	/* True if error issued */
115 
116 	const char	*strs;
117 	Word		strn;
118 
119 	if (strsec->c_data == NULL)
120 		return (NULL);
121 
122 	strs = (char *)strsec->c_data->d_buf;
123 	strn = strsec->c_data->d_size;
124 
125 	/*
126 	 * We only print a diagnostic regarding a bad string table once per
127 	 * input section being processed. If the refsec has changed, reset
128 	 * our retained error state.
129 	 */
130 	if (last_refsec != refsec) {
131 		last_refsec = refsec;
132 		strsec_err = 0;
133 	}
134 
135 	/* Verify that strsec really is a string table */
136 	if (strsec->c_shdr->sh_type != SHT_STRTAB) {
137 		if (!strsec_err) {
138 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_NOTSTRTAB),
139 			    file, strsec->c_ndx, refsec->c_ndx);
140 			strsec_err = 1;
141 		}
142 		return (MSG_INTL(MSG_STR_UNKNOWN));
143 	}
144 
145 	/*
146 	 * Is the string table offset within range of the available strings?
147 	 */
148 	if (name >= strn) {
149 		/*
150 		 * Do we have a empty string table?
151 		 */
152 		if (strs == 0) {
153 			if (!strsec_err) {
154 				(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
155 				    file, strsec->c_name);
156 				strsec_err = 1;
157 			}
158 		} else {
159 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSTOFF),
160 			    file, refsec->c_name, EC_WORD(ndx), strsec->c_name,
161 			    EC_WORD(name), EC_WORD(strn - 1));
162 		}
163 
164 		/*
165 		 * Return the empty string so that the calling function can
166 		 * continue it's output diagnostics.
167 		 */
168 		return (MSG_INTL(MSG_STR_UNKNOWN));
169 	}
170 	return (strs + name);
171 }
172 
173 /*
174  * Relocations can reference section symbols and standard symbols.  If the
175  * former, establish the section name.
176  */
177 static const char *
178 relsymname(Cache *cache, Cache *csec, Cache *strsec, Word symndx, Word symnum,
179     Word relndx, Sym *syms, char *secstr, size_t secsz, const char *file)
180 {
181 	Sym		*sym;
182 	const char	*name;
183 
184 	if (symndx >= symnum) {
185 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_RELBADSYMNDX),
186 		    file, EC_WORD(symndx), EC_WORD(relndx));
187 		return (MSG_INTL(MSG_STR_UNKNOWN));
188 	}
189 
190 	sym = (Sym *)(syms + symndx);
191 	name = string(csec, symndx, strsec, file, sym->st_name);
192 
193 	/*
194 	 * If the symbol represents a section offset construct an appropriate
195 	 * string.  Note, although section symbol table entries typically have
196 	 * a NULL name pointer, entries do exist that point into the string
197 	 * table to their own NULL strings.
198 	 */
199 	if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) &&
200 	    ((sym->st_name == 0) || (*name == '\0'))) {
201 		(void) snprintf(secstr, secsz, MSG_INTL(MSG_STR_SECTION),
202 		    cache[sym->st_shndx].c_name);
203 		return ((const char *)secstr);
204 	}
205 
206 	return (name);
207 }
208 
209 /*
210  * Focal point for establishing a string table section.  Data such as the
211  * dynamic information simply points to a string table.  Data such as
212  * relocations, reference a symbol table, which in turn is associated with a
213  * string table.
214  */
215 static int
216 stringtbl(Cache *cache, int symtab, Word ndx, Word shnum, const char *file,
217     Word *symnum, Cache **symsec, Cache **strsec)
218 {
219 	Shdr	*shdr = cache[ndx].c_shdr;
220 
221 	if (symtab) {
222 		/*
223 		 * Validate the symbol table section.
224 		 */
225 		if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
226 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
227 			    file, cache[ndx].c_name, EC_WORD(shdr->sh_link));
228 			return (0);
229 		}
230 		if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
231 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
232 			    file, cache[ndx].c_name);
233 			return (0);
234 		}
235 
236 		/*
237 		 * Obtain, and verify the symbol table data.
238 		 */
239 		if ((cache[ndx].c_data == NULL) ||
240 		    (cache[ndx].c_data->d_buf == NULL)) {
241 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
242 			    file, cache[ndx].c_name);
243 			return (0);
244 		}
245 
246 		/*
247 		 * Establish the string table index.
248 		 */
249 		ndx = shdr->sh_link;
250 		shdr = cache[ndx].c_shdr;
251 
252 		/*
253 		 * Return symbol table information.
254 		 */
255 		if (symnum)
256 			*symnum = (shdr->sh_size / shdr->sh_entsize);
257 		if (symsec)
258 			*symsec = &cache[ndx];
259 	}
260 
261 	/*
262 	 * Validate the associated string table section.
263 	 */
264 	if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
265 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
266 		    file, cache[ndx].c_name, EC_WORD(shdr->sh_link));
267 		return (0);
268 	}
269 
270 	if (strsec)
271 		*strsec = &cache[shdr->sh_link];
272 
273 	return (1);
274 }
275 
276 /*
277  * Lookup a symbol and set Sym accordingly.
278  */
279 static int
280 symlookup(const char *name, Cache *cache, Word shnum, Sym **sym,
281     Cache *symtab, const char *file)
282 {
283 	Shdr	*shdr;
284 	Word	symn, cnt;
285 	Sym	*syms;
286 
287 	if (symtab == 0)
288 		return (0);
289 
290 	shdr = symtab->c_shdr;
291 
292 	/*
293 	 * Determine the symbol data and number.
294 	 */
295 	if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
296 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
297 		    file, symtab->c_name);
298 		return (0);
299 	}
300 	if (symtab->c_data == NULL)
301 		return (0);
302 
303 	/* LINTED */
304 	symn = (Word)(shdr->sh_size / shdr->sh_entsize);
305 	syms = (Sym *)symtab->c_data->d_buf;
306 
307 	/*
308 	 * Get the associated string table section.
309 	 */
310 	if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
311 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
312 		    file, symtab->c_name, EC_WORD(shdr->sh_link));
313 		return (0);
314 	}
315 
316 	/*
317 	 * Loop through the symbol table to find a match.
318 	 */
319 	for (cnt = 0; cnt < symn; syms++, cnt++) {
320 		const char	*symname;
321 
322 		symname = string(symtab, cnt, &cache[shdr->sh_link], file,
323 		    syms->st_name);
324 
325 		if (symname && (strcmp(name, symname) == 0)) {
326 			*sym = syms;
327 			return (1);
328 		}
329 	}
330 	return (0);
331 }
332 
333 /*
334  * Print section headers.
335  */
336 static void
337 sections(const char *file, Cache *cache, Word shnum, Ehdr *ehdr)
338 {
339 	size_t	seccnt;
340 
341 	for (seccnt = 1; seccnt < shnum; seccnt++) {
342 		Cache		*_cache = &cache[seccnt];
343 		Shdr		*shdr = _cache->c_shdr;
344 		const char	*secname = _cache->c_name;
345 
346 		/*
347 		 * Although numerous section header entries can be zero, it's
348 		 * usually a sign of trouble if the type is zero.
349 		 */
350 		if (shdr->sh_type == 0) {
351 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE),
352 			    file, secname, EC_WORD(shdr->sh_type));
353 		}
354 
355 		if (!match(MATCH_F_ALL, secname, seccnt, shdr->sh_type))
356 			continue;
357 
358 		/*
359 		 * Identify any sections that are suspicious.  A .got section
360 		 * shouldn't exist in a relocatable object.
361 		 */
362 		if (ehdr->e_type == ET_REL) {
363 			if (strncmp(secname, MSG_ORIG(MSG_ELF_GOT),
364 			    MSG_ELF_GOT_SIZE) == 0) {
365 				(void) fprintf(stderr,
366 				    MSG_INTL(MSG_GOT_UNEXPECTED), file,
367 				    secname);
368 			}
369 		}
370 
371 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
372 		dbg_print(0, MSG_INTL(MSG_ELF_SHDR), EC_WORD(seccnt), secname);
373 		Elf_shdr(0, ehdr->e_machine, shdr);
374 	}
375 }
376 
377 /*
378  * A couple of instances of unwind data are printed as tables of 8 data items
379  * expressed as 0x?? integers.
380  */
381 #define	UNWINDTBLSZ	10 + (8 * 5) + 1
382 
383 static void
384 unwindtbl(uint64_t *ndx, uint_t len, uchar_t *data, uint64_t doff,
385     const char *msg, const char *pre, size_t plen)
386 {
387 	char	buffer[UNWINDTBLSZ];
388 	uint_t	boff = plen, cnt = 0;
389 
390 	dbg_print(0, msg);
391 	(void) strncpy(buffer, pre, UNWINDTBLSZ);
392 
393 	while (*ndx < (len + 4)) {
394 		if (cnt == 8) {
395 			dbg_print(0, buffer);
396 			boff = plen;
397 			cnt = 0;
398 		}
399 		(void) snprintf(&buffer[boff], UNWINDTBLSZ - boff,
400 		    MSG_ORIG(MSG_UNW_TBLENTRY), data[doff + (*ndx)++]);
401 		boff += 5;
402 		cnt++;
403 	}
404 	if (cnt)
405 		dbg_print(0, buffer);
406 }
407 
408 /*
409  * Obtain a specified Phdr entry.
410  */
411 static Phdr *
412 getphdr(Word phnum, Word type, const char *file, Elf *elf)
413 {
414 	Word	cnt;
415 	Phdr	*phdr;
416 
417 	if ((phdr = elf_getphdr(elf)) == NULL) {
418 		failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
419 		return (0);
420 	}
421 
422 	for (cnt = 0; cnt < phnum; phdr++, cnt++) {
423 		if (phdr->p_type == type)
424 			return (phdr);
425 	}
426 	return (0);
427 }
428 
429 static void
430 unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *file,
431     Elf *elf)
432 {
433 	Conv_dwarf_ehe_buf_t	dwarf_ehe_buf;
434 	Word	cnt;
435 	Phdr	*uphdr = 0;
436 
437 	/*
438 	 * For the moment - UNWIND is only relevant for a AMD64 object.
439 	 */
440 	if (ehdr->e_machine != EM_AMD64)
441 		return;
442 
443 	if (phnum)
444 		uphdr = getphdr(phnum, PT_SUNW_UNWIND, file, elf);
445 
446 	for (cnt = 1; cnt < shnum; cnt++) {
447 		Cache		*_cache = &cache[cnt];
448 		Shdr		*shdr = _cache->c_shdr;
449 		uchar_t		*data;
450 		size_t		datasize;
451 		uint64_t	off, ndx, frame_ptr, fde_cnt, tabndx;
452 		uint_t		vers, frame_ptr_enc, fde_cnt_enc, table_enc;
453 
454 		/*
455 		 * AMD64 - this is a strmcp() just to find the gcc produced
456 		 * sections.  Soon gcc should be setting the section type - and
457 		 * we'll not need this strcmp().
458 		 */
459 		if ((shdr->sh_type != SHT_AMD64_UNWIND) &&
460 		    (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM),
461 		    MSG_SCN_FRM_SIZE) != 0) &&
462 		    (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR),
463 		    MSG_SCN_FRMHDR_SIZE) != 0))
464 			continue;
465 
466 		if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type))
467 			continue;
468 
469 		if (_cache->c_data == NULL)
470 			continue;
471 
472 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
473 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name);
474 
475 		data = (uchar_t *)(_cache->c_data->d_buf);
476 		datasize = _cache->c_data->d_size;
477 		off = 0;
478 
479 		/*
480 		 * Is this a .eh_frame_hdr
481 		 */
482 		if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) ||
483 		    (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR),
484 		    MSG_SCN_FRMHDR_SIZE) == 0)) {
485 			dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR));
486 			ndx = 0;
487 
488 			vers = data[ndx++];
489 			frame_ptr_enc = data[ndx++];
490 			fde_cnt_enc = data[ndx++];
491 			table_enc = data[ndx++];
492 
493 			dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers);
494 
495 			frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc,
496 			    ehdr->e_ident, shdr->sh_addr + ndx);
497 
498 			dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC),
499 			    conv_dwarf_ehe(frame_ptr_enc, &dwarf_ehe_buf),
500 			    EC_XWORD(frame_ptr));
501 
502 			fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc,
503 			    ehdr->e_ident, shdr->sh_addr + ndx);
504 
505 			dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC),
506 			    conv_dwarf_ehe(fde_cnt_enc, &dwarf_ehe_buf),
507 			    EC_XWORD(fde_cnt));
508 			dbg_print(0, MSG_ORIG(MSG_UNW_TABENC),
509 			    conv_dwarf_ehe(table_enc, &dwarf_ehe_buf));
510 			dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1));
511 			dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2));
512 
513 			for (tabndx = 0; tabndx < fde_cnt; tabndx++) {
514 				dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT),
515 				    EC_XWORD(dwarf_ehe_extract(data, &ndx,
516 				    table_enc, ehdr->e_ident, shdr->sh_addr)),
517 				    EC_XWORD(dwarf_ehe_extract(data, &ndx,
518 				    table_enc, ehdr->e_ident, shdr->sh_addr)));
519 			}
520 			continue;
521 		}
522 
523 		/*
524 		 * Walk the Eh_frame's
525 		 */
526 		while (off < datasize) {
527 			uint_t		cieid, cielength, cieversion;
528 			uint_t		cieretaddr;
529 			int		cieRflag, cieLflag, ciePflag, cieZflag;
530 			uint_t		cieaugndx, length, id;
531 			uint64_t	ciecalign, ciedalign;
532 			char		*cieaugstr;
533 
534 			ndx = 0;
535 			/*
536 			 * Extract length in lsb format.  A zero length
537 			 * indicates that this CIE is a terminator and that
538 			 * processing for this unwind information should end.
539 			 * However, skip this entry and keep processing, just
540 			 * in case there is any other information remaining in
541 			 * this section.  Note, ld(1) will terminate the
542 			 * processing of the .eh_frame contents for this file
543 			 * after a zero length CIE, thus any information that
544 			 * does follow is ignored by ld(1), and is therefore
545 			 * questionable.
546 			 */
547 			if ((length = LSB32EXTRACT(data + off + ndx)) == 0) {
548 				dbg_print(0, MSG_ORIG(MSG_UNW_ZEROTERM));
549 				off += 4;
550 				continue;
551 			}
552 			ndx += 4;
553 
554 			/*
555 			 * extract CIE id in lsb format
556 			 */
557 			id = LSB32EXTRACT(data + off + ndx);
558 			ndx += 4;
559 
560 			/*
561 			 * A CIE record has a id of '0', otherwise this is a
562 			 * FDE entry and the 'id' is the CIE pointer.
563 			 */
564 			if (id == 0) {
565 				uint64_t    persVal;
566 
567 				cielength = length;
568 				cieid = id;
569 				cieLflag = ciePflag = cieRflag = cieZflag = 0;
570 
571 				dbg_print(0, MSG_ORIG(MSG_UNW_CIE),
572 				    EC_XWORD(shdr->sh_addr + off));
573 				dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH),
574 				    cielength, cieid);
575 
576 				cieversion = data[off + ndx];
577 				ndx += 1;
578 				cieaugstr = (char *)(&data[off + ndx]);
579 				ndx += strlen(cieaugstr) + 1;
580 
581 				dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS),
582 				    cieversion, cieaugstr);
583 
584 				ciecalign = uleb_extract(&data[off], &ndx);
585 				ciedalign = sleb_extract(&data[off], &ndx);
586 				cieretaddr = data[off + ndx];
587 				ndx += 1;
588 
589 				dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN),
590 				    EC_XWORD(ciecalign), EC_XWORD(ciedalign),
591 				    cieretaddr);
592 
593 				if (cieaugstr[0])
594 					dbg_print(0,
595 					    MSG_ORIG(MSG_UNW_CIEAXVAL));
596 
597 				for (cieaugndx = 0; cieaugstr[cieaugndx];
598 				    cieaugndx++) {
599 					uint_t	val;
600 
601 					switch (cieaugstr[cieaugndx]) {
602 					case 'z':
603 						val = uleb_extract(&data[off],
604 						    &ndx);
605 						dbg_print(0,
606 						    MSG_ORIG(MSG_UNW_CIEAXSIZ),
607 						    val);
608 						cieZflag = 1;
609 						break;
610 					case 'P':
611 						ciePflag = data[off + ndx];
612 						ndx += 1;
613 
614 						persVal = dwarf_ehe_extract(
615 						    &data[off], &ndx, ciePflag,
616 						    ehdr->e_ident,
617 						    shdr->sh_addr + off + ndx);
618 						dbg_print(0,
619 						    MSG_ORIG(MSG_UNW_CIEAXPERS),
620 						    ciePflag,
621 						    conv_dwarf_ehe(ciePflag,
622 						    &dwarf_ehe_buf),
623 						    EC_XWORD(persVal));
624 						break;
625 					case 'R':
626 						val = data[off + ndx];
627 						ndx += 1;
628 						dbg_print(0,
629 						    MSG_ORIG(MSG_UNW_CIEAXCENC),
630 						    val, conv_dwarf_ehe(val,
631 						    &dwarf_ehe_buf));
632 						cieRflag = val;
633 						break;
634 					case 'L':
635 						val = data[off + ndx];
636 						ndx += 1;
637 						dbg_print(0,
638 						    MSG_ORIG(MSG_UNW_CIEAXLSDA),
639 						    val, conv_dwarf_ehe(val,
640 						    &dwarf_ehe_buf));
641 						cieLflag = val;
642 						break;
643 					default:
644 						dbg_print(0,
645 						    MSG_ORIG(MSG_UNW_CIEAXUNEC),
646 						    cieaugstr[cieaugndx]);
647 						break;
648 					}
649 				}
650 				if ((cielength + 4) > ndx)
651 					unwindtbl(&ndx, cielength, data, off,
652 					    MSG_ORIG(MSG_UNW_CIECFI),
653 					    MSG_ORIG(MSG_UNW_CIEPRE),
654 					    MSG_UNW_CIEPRE_SIZE);
655 				off += cielength + 4;
656 
657 			} else {
658 				uint_t	    fdelength = length;
659 				int	    fdecieptr = id;
660 				uint64_t    fdeinitloc, fdeaddrrange;
661 
662 				dbg_print(0, MSG_ORIG(MSG_UNW_FDE),
663 				    EC_XWORD(shdr->sh_addr + off));
664 				dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH),
665 				    fdelength, fdecieptr);
666 
667 				fdeinitloc = dwarf_ehe_extract(&data[off],
668 				    &ndx, cieRflag, ehdr->e_ident,
669 				    shdr->sh_addr + off + ndx);
670 				fdeaddrrange = dwarf_ehe_extract(&data[off],
671 				    &ndx, (cieRflag & ~DW_EH_PE_pcrel),
672 				    ehdr->e_ident,
673 				    shdr->sh_addr + off + ndx);
674 
675 				dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC),
676 				    EC_XWORD(fdeinitloc),
677 				    EC_XWORD(fdeaddrrange));
678 
679 				if (cieaugstr[0])
680 					dbg_print(0,
681 					    MSG_ORIG(MSG_UNW_FDEAXVAL));
682 				if (cieZflag) {
683 					uint64_t    val;
684 					val = uleb_extract(&data[off], &ndx);
685 					dbg_print(0,
686 					    MSG_ORIG(MSG_UNW_FDEAXSIZE),
687 					    EC_XWORD(val));
688 					if (val & cieLflag) {
689 						fdeinitloc = dwarf_ehe_extract(
690 						    &data[off], &ndx, cieLflag,
691 						    ehdr->e_ident,
692 						    shdr->sh_addr + off + ndx);
693 						dbg_print(0,
694 						    MSG_ORIG(MSG_UNW_FDEAXLSDA),
695 						    EC_XWORD(val));
696 					}
697 				}
698 				if ((fdelength + 4) > ndx)
699 					unwindtbl(&ndx, fdelength, data, off,
700 					    MSG_ORIG(MSG_UNW_FDECFI),
701 					    MSG_ORIG(MSG_UNW_FDEPRE),
702 					    MSG_UNW_FDEPRE_SIZE);
703 				off += fdelength + 4;
704 			}
705 		}
706 	}
707 }
708 
709 /*
710  * Print the hardware/software capabilities.  For executables and shared objects
711  * this should be accompanied with a program header.
712  */
713 static void
714 cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr,
715     Elf *elf)
716 {
717 	Word		cnt;
718 	Shdr		*cshdr = 0;
719 	Cache		*ccache;
720 	Off		cphdr_off = 0;
721 	Xword		cphdr_sz;
722 
723 	/*
724 	 * Determine if a hardware/software capabilities header exists.
725 	 */
726 	if (phnum) {
727 		Phdr	*phdr;
728 
729 		if ((phdr = elf_getphdr(elf)) == NULL) {
730 			failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
731 			return;
732 		}
733 
734 		for (cnt = 0; cnt < phnum; phdr++, cnt++) {
735 			if (phdr->p_type == PT_SUNWCAP) {
736 				cphdr_off = phdr->p_offset;
737 				cphdr_sz = phdr->p_filesz;
738 				break;
739 			}
740 		}
741 	}
742 
743 	/*
744 	 * Determine if a hardware/software capabilities section exists.
745 	 */
746 	for (cnt = 1; cnt < shnum; cnt++) {
747 		Cache	*_cache = &cache[cnt];
748 		Shdr	*shdr = _cache->c_shdr;
749 
750 		if (shdr->sh_type != SHT_SUNW_cap)
751 			continue;
752 
753 		if (cphdr_off && ((cphdr_off < shdr->sh_offset) ||
754 		    (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size)))
755 			continue;
756 
757 		if (_cache->c_data == NULL)
758 			continue;
759 
760 		ccache = _cache;
761 		cshdr = shdr;
762 		break;
763 	}
764 
765 	if ((cshdr == 0) && (cphdr_off == 0))
766 		return;
767 
768 	/*
769 	 * Print the hardware/software capabilities section.
770 	 */
771 	if (cshdr) {
772 		Word	ndx, capn;
773 		Cap	*cap = (Cap *)ccache->c_data->d_buf;
774 
775 		if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) {
776 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
777 			    file, ccache->c_name);
778 			return;
779 		}
780 
781 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
782 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name);
783 
784 		Elf_cap_title(0);
785 
786 		capn = (Word)(cshdr->sh_size / cshdr->sh_entsize);
787 
788 		for (ndx = 0; ndx < capn; cap++, ndx++) {
789 			if (cap->c_tag != CA_SUNW_NULL)
790 				Elf_cap_entry(0, cap, ndx, ehdr->e_machine);
791 		}
792 	} else
793 		(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file);
794 
795 	/*
796 	 * If this object is an executable or shared object, then the
797 	 * hardware/software capabilities section should have an accompanying
798 	 * program header.
799 	 */
800 	if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) {
801 		if (cphdr_off == 0)
802 			(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2),
803 			    file, ccache->c_name);
804 		else if ((cphdr_off != cshdr->sh_offset) ||
805 		    (cphdr_sz != cshdr->sh_size))
806 			(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3),
807 			    file, ccache->c_name);
808 	}
809 }
810 
811 /*
812  * Print the interpretor.
813  */
814 static void
815 interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf)
816 {
817 	Word	cnt;
818 	Shdr	*ishdr = 0;
819 	Cache	*icache;
820 	Off	iphdr_off = 0;
821 	Xword	iphdr_fsz;
822 
823 	/*
824 	 * Determine if an interp header exists.
825 	 */
826 	if (phnum) {
827 		Phdr	*phdr;
828 
829 		if ((phdr = getphdr(phnum, PT_INTERP, file, elf)) != 0) {
830 			iphdr_off = phdr->p_offset;
831 			iphdr_fsz = phdr->p_filesz;
832 		}
833 	}
834 
835 	if (iphdr_off == 0)
836 		return;
837 
838 	/*
839 	 * Determine if an interp section exists.
840 	 */
841 	for (cnt = 1; cnt < shnum; cnt++) {
842 		Cache	*_cache = &cache[cnt];
843 		Shdr	*shdr = _cache->c_shdr;
844 
845 		/*
846 		 * Scan sections to find a section which contains the PT_INTERP
847 		 * string.  The target section can't be in a NOBITS section.
848 		 */
849 		if ((shdr->sh_type == SHT_NOBITS) ||
850 		    (iphdr_off < shdr->sh_offset) ||
851 		    (iphdr_off + iphdr_fsz) > (shdr->sh_offset + shdr->sh_size))
852 			continue;
853 
854 		icache = _cache;
855 		ishdr = shdr;
856 		break;
857 	}
858 
859 	/*
860 	 * Print the interpreter string based on the offset defined in the
861 	 * program header, as this is the offset used by the kernel.
862 	 */
863 	if (ishdr && icache->c_data) {
864 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
865 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name);
866 		dbg_print(0, MSG_ORIG(MSG_FMT_INDENT),
867 		    (char *)icache->c_data->d_buf +
868 		    (iphdr_off - ishdr->sh_offset));
869 	} else
870 		(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file);
871 
872 	/*
873 	 * If there are any inconsistences between the program header and
874 	 * section information, flag them.
875 	 */
876 	if (ishdr && ((iphdr_off != ishdr->sh_offset) ||
877 	    (iphdr_fsz != ishdr->sh_size))) {
878 		(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file,
879 		    icache->c_name);
880 	}
881 }
882 
883 /*
884  * Print the syminfo section.
885  */
886 static void
887 syminfo(Cache *cache, Word shnum, const char *file)
888 {
889 	Shdr		*infoshdr;
890 	Syminfo		*info;
891 	Sym		*syms;
892 	Dyn		*dyns;
893 	Word		infonum, cnt, ndx, symnum;
894 	Cache		*infocache = 0, *symsec, *strsec;
895 
896 	for (cnt = 1; cnt < shnum; cnt++) {
897 		if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) {
898 			infocache = &cache[cnt];
899 			break;
900 		}
901 	}
902 	if (infocache == 0)
903 		return;
904 
905 	infoshdr = infocache->c_shdr;
906 	if ((infoshdr->sh_entsize == 0) || (infoshdr->sh_size == 0)) {
907 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
908 		    file, infocache->c_name);
909 		return;
910 	}
911 	if (infocache->c_data == NULL)
912 		return;
913 
914 	infonum = (Word)(infoshdr->sh_size / infoshdr->sh_entsize);
915 	info = (Syminfo *)infocache->c_data->d_buf;
916 
917 	/*
918 	 * Get the data buffer of the associated dynamic section.
919 	 */
920 	if ((infoshdr->sh_info == 0) || (infoshdr->sh_info >= shnum)) {
921 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO),
922 		    file, infocache->c_name, EC_WORD(infoshdr->sh_info));
923 		return;
924 	}
925 	if (cache[infoshdr->sh_info].c_data == NULL)
926 		return;
927 
928 	dyns = cache[infoshdr->sh_info].c_data->d_buf;
929 	if (dyns == 0) {
930 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
931 		    file, cache[infoshdr->sh_info].c_name);
932 		return;
933 	}
934 
935 	/*
936 	 * Get the data buffer for the associated symbol table and string table.
937 	 */
938 	if (stringtbl(cache, 1, cnt, shnum, file,
939 	    &symnum, &symsec, &strsec) == 0)
940 		return;
941 
942 	syms = symsec->c_data->d_buf;
943 
944 	/*
945 	 * Loop through the syminfo entries.
946 	 */
947 	dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
948 	dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMINFO), infocache->c_name);
949 	Elf_syminfo_title(0);
950 
951 	for (ndx = 1, info++; ndx < infonum; ndx++, info++) {
952 		Sym 		*sym;
953 		const char	*needed = 0, *name;
954 
955 		if ((info->si_flags == 0) && (info->si_boundto == 0))
956 			continue;
957 
958 		sym = &syms[ndx];
959 		name = string(infocache, ndx, strsec, file, sym->st_name);
960 
961 		if (info->si_boundto < SYMINFO_BT_LOWRESERVE) {
962 			Dyn	*dyn = &dyns[info->si_boundto];
963 
964 			needed = string(infocache, info->si_boundto,
965 			    strsec, file, dyn->d_un.d_val);
966 		}
967 		Elf_syminfo_entry(0, ndx, info, name, needed);
968 	}
969 }
970 
971 /*
972  * Print version definition section entries.
973  */
974 static void
975 version_def(Verdef *vdf, Word vdf_num, Cache *vcache, Cache *scache,
976     const char *file)
977 {
978 	Word	cnt;
979 	char	index[MAXNDXSIZE];
980 
981 	Elf_ver_def_title(0);
982 
983 	for (cnt = 1; cnt <= vdf_num; cnt++,
984 	    vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) {
985 		const char	*name, *dep;
986 		Half		vcnt = vdf->vd_cnt - 1;
987 		Half		ndx = vdf->vd_ndx;
988 		Verdaux *vdap = (Verdaux *)((uintptr_t)vdf + vdf->vd_aux);
989 
990 		/*
991 		 * Obtain the name and first dependency (if any).
992 		 */
993 		name = string(vcache, cnt, scache, file, vdap->vda_name);
994 		vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
995 		if (vcnt)
996 			dep = string(vcache, cnt, scache, file, vdap->vda_name);
997 		else
998 			dep = MSG_ORIG(MSG_STR_EMPTY);
999 
1000 		(void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX),
1001 		    EC_XWORD(ndx));
1002 		Elf_ver_line_1(0, index, name, dep,
1003 		    conv_ver_flags(vdf->vd_flags));
1004 
1005 		/*
1006 		 * Print any additional dependencies.
1007 		 */
1008 		if (vcnt) {
1009 			vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
1010 			for (vcnt--; vcnt; vcnt--,
1011 			    vdap = (Verdaux *)((uintptr_t)vdap +
1012 			    vdap->vda_next)) {
1013 				dep = string(vcache, cnt, scache, file,
1014 				    vdap->vda_name);
1015 				Elf_ver_line_2(0, MSG_ORIG(MSG_STR_EMPTY), dep);
1016 			}
1017 		}
1018 	}
1019 }
1020 
1021 /*
1022  * Print version needed section entries.
1023  *
1024  * entry:
1025  *	vnd - Address of verneed data
1026  *	vnd_num - # of Verneed entries
1027  *	vcache - Cache of verneed section being processed
1028  *	scache - Cache of associated string table section
1029  *	file - Name of object being processed.
1030  *	versym - Information about versym section
1031  *
1032  * exit:
1033  *	The versions have been printed. If GNU style versioning
1034  *	is in effect, versym->max_verndx has been updated to
1035  *	contain the largest version index seen.
1036  */
1037 static void
1038 version_need(Verneed *vnd, Word vnd_num, Cache *vcache, Cache *scache,
1039     const char *file, VERSYM_STATE *versym)
1040 {
1041 	Word		cnt;
1042 	char		index[MAXNDXSIZE];
1043 	const char	*index_str;
1044 
1045 	Elf_ver_need_title(0, versym->gnu);
1046 
1047 	/*
1048 	 * The versym section in an object that follows Solaris versioning
1049 	 * rules contains indexes into the verdef section. Symbols defined
1050 	 * in other objects (UNDEF) are given a version of 0, indicating that
1051 	 * they are not defined by this file, and the Verneed entries do not
1052 	 * have associated version indexes. For these reasons, we do not
1053 	 * display a version index for Solaris Verneed sections.
1054 	 *
1055 	 * The GNU versioning rules are different: Symbols defined in other
1056 	 * objects receive a version index in the range above those defined
1057 	 * by the Verdef section, and the vna_other field of the Vernaux
1058 	 * structs inside the Verneed section contain the version index for
1059 	 * that item. We therefore  display the index when showing the
1060 	 * contents of a GNU Verneed section. You should not expect these
1061 	 * indexes to appear in sorted order --- it seems that the GNU ld
1062 	 * assigns the versions as symbols are encountered during linking,
1063 	 * and then the results are assembled into the Verneed section
1064 	 * afterwards.
1065 	 */
1066 	if (versym->gnu) {
1067 		index_str = index;
1068 	} else {
1069 		/* For Solaris versioning, display a NULL string */
1070 		index_str = MSG_ORIG(MSG_STR_EMPTY);
1071 	}
1072 
1073 	for (cnt = 1; cnt <= vnd_num; cnt++,
1074 	    vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) {
1075 		const char	*name, *dep;
1076 		Half		vcnt = vnd->vn_cnt;
1077 		Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + vnd->vn_aux);
1078 
1079 		/*
1080 		 * Obtain the name of the needed file and the version name
1081 		 * within it that we're dependent on.  Note that the count
1082 		 * should be at least one, otherwise this is a pretty bogus
1083 		 * entry.
1084 		 */
1085 		name = string(vcache, cnt, scache, file, vnd->vn_file);
1086 		if (vcnt)
1087 			dep = string(vcache, cnt, scache, file, vnap->vna_name);
1088 		else
1089 			dep = MSG_INTL(MSG_STR_NULL);
1090 
1091 		if (versym->gnu) {
1092 			/* Format the version index value */
1093 			(void) snprintf(index, MAXNDXSIZE,
1094 			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(vnap->vna_other));
1095 			if (vnap->vna_other > versym->max_verndx)
1096 				versym->max_verndx = vnap->vna_other;
1097 		}
1098 		Elf_ver_line_1(0, index_str, name, dep,
1099 		    conv_ver_flags(vnap->vna_flags));
1100 
1101 		/*
1102 		 * Print any additional version dependencies.
1103 		 */
1104 		if (vcnt) {
1105 			vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next);
1106 			for (vcnt--; vcnt; vcnt--,
1107 			    vnap = (Vernaux *)((uintptr_t)vnap +
1108 			    vnap->vna_next)) {
1109 				dep = string(vcache, cnt, scache, file,
1110 				    vnap->vna_name);
1111 				if (versym->gnu) {
1112 					/* Format the next index value */
1113 					(void) snprintf(index, MAXNDXSIZE,
1114 					    MSG_ORIG(MSG_FMT_INDEX),
1115 					    EC_XWORD(vnap->vna_other));
1116 					Elf_ver_line_1(0, index_str,
1117 					    MSG_ORIG(MSG_STR_EMPTY), dep,
1118 					    conv_ver_flags(vnap->vna_flags));
1119 					if (vnap->vna_other >
1120 					    versym->max_verndx)
1121 						versym->max_verndx =
1122 						    vnap->vna_other;
1123 				} else {
1124 					Elf_ver_line_3(0,
1125 					    MSG_ORIG(MSG_STR_EMPTY), dep,
1126 					    conv_ver_flags(vnap->vna_flags));
1127 				}
1128 			}
1129 		}
1130 	}
1131 }
1132 
1133 /*
1134  * Compute the max_verndx value for a GNU style object with
1135  * a Verneed section. This is only needed if version_need() is not
1136  * called.
1137  *
1138  * entry:
1139  *	vnd - Address of verneed data
1140  *	vnd_num - # of Verneed entries
1141  *	versym - Information about versym section
1142  *
1143  * exit:
1144  *	versym->max_verndx has been updated to contain the largest
1145  *	version index seen.
1146  */
1147 static void
1148 update_gnu_max_verndx(Verneed *vnd, Word vnd_num, VERSYM_STATE *versym)
1149 {
1150 	Word		cnt;
1151 
1152 	for (cnt = 1; cnt <= vnd_num; cnt++,
1153 	    vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) {
1154 		Half	vcnt = vnd->vn_cnt;
1155 		Vernaux	*vnap = (Vernaux *)((uintptr_t)vnd + vnd->vn_aux);
1156 
1157 		if (vnap->vna_other > versym->max_verndx)
1158 			versym->max_verndx = vnap->vna_other;
1159 
1160 		/*
1161 		 * Check any additional version dependencies.
1162 		 */
1163 		if (vcnt) {
1164 			vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next);
1165 			for (vcnt--; vcnt; vcnt--,
1166 			    vnap = (Vernaux *)((uintptr_t)vnap +
1167 			    vnap->vna_next)) {
1168 				if (vnap->vna_other > versym->max_verndx)
1169 					versym->max_verndx = vnap->vna_other;
1170 			}
1171 		}
1172 	}
1173 }
1174 
1175 /*
1176  * Display version section information if the flags require it.
1177  * Return version information needed by other output.
1178  *
1179  * entry:
1180  *	cache - Cache of all section headers
1181  *	shnum - # of sections in cache
1182  *	file - Name of file
1183  *	flags - Command line option flags
1184  *	versym - VERSYM_STATE block to be filled in.
1185  */
1186 static void
1187 versions(Cache *cache, Word shnum, const char *file, uint_t flags,
1188     VERSYM_STATE *versym)
1189 {
1190 	GElf_Word	cnt;
1191 	Cache		*verdef_cache = NULL, *verneed_cache = NULL;
1192 
1193 
1194 	/* Gather information about the version sections */
1195 	bzero(versym, sizeof (*versym));
1196 	versym->max_verndx = 1;
1197 	for (cnt = 1; cnt < shnum; cnt++) {
1198 		Cache		*_cache = &cache[cnt];
1199 		Shdr		*shdr = _cache->c_shdr;
1200 		Dyn		*dyn;
1201 		ulong_t		numdyn;
1202 
1203 		switch (shdr->sh_type) {
1204 		case SHT_DYNAMIC:
1205 			/*
1206 			 * The GNU ld puts a DT_VERSYM entry in the dynamic
1207 			 * section so that the runtime linker can use it to
1208 			 * implement their versioning rules. They allow multiple
1209 			 * incompatible functions with the same name to exist
1210 			 * in different versions. The Solaris ld does not
1211 			 * support this mechanism, and as such, does not
1212 			 * produce DT_VERSYM. We use this fact to determine
1213 			 * which ld produced this object, and how to interpret
1214 			 * the version values.
1215 			 */
1216 			if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0) ||
1217 			    (_cache->c_data == NULL))
1218 				continue;
1219 			numdyn = shdr->sh_size / shdr->sh_entsize;
1220 			dyn = (Dyn *)_cache->c_data->d_buf;
1221 			for (; numdyn-- > 0; dyn++)
1222 				if (dyn->d_tag == DT_VERSYM) {
1223 					versym->gnu = 1;
1224 					break;
1225 				}
1226 			break;
1227 
1228 		case SHT_SUNW_versym:
1229 			/* Record data address for later symbol processing */
1230 			if (_cache->c_data != NULL) {
1231 				versym->cache = _cache;
1232 				versym->data = _cache->c_data->d_buf;
1233 				continue;
1234 			}
1235 			break;
1236 
1237 		case SHT_SUNW_verdef:
1238 		case SHT_SUNW_verneed:
1239 			/*
1240 			 * Ensure the data is non-NULL and the number
1241 			 * of items is non-zero. Otherwise, we don't
1242 			 * understand the section, and will not use it.
1243 			 */
1244 			if ((_cache->c_data == NULL) ||
1245 			    (_cache->c_data->d_buf == NULL)) {
1246 				(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1247 				    file, _cache->c_name);
1248 				continue;
1249 			}
1250 			if (shdr->sh_info == 0) {
1251 				(void) fprintf(stderr,
1252 				    MSG_INTL(MSG_ERR_BADSHINFO),
1253 				    file, _cache->c_name,
1254 				    EC_WORD(shdr->sh_info));
1255 				continue;
1256 			}
1257 
1258 			/* Make sure the string table index is in range */
1259 			if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
1260 				(void) fprintf(stderr,
1261 				    MSG_INTL(MSG_ERR_BADSHLINK), file,
1262 				    _cache->c_name, EC_WORD(shdr->sh_link));
1263 				continue;
1264 			}
1265 
1266 			/*
1267 			 * The section is usable. Save the cache entry.
1268 			 */
1269 			if (shdr->sh_type == SHT_SUNW_verdef) {
1270 				verdef_cache = _cache;
1271 				/*
1272 				 * Under Solaris rules, if there is a verdef
1273 				 * section, the max versym index is number
1274 				 * of version definitions it supplies.
1275 				 */
1276 				versym->max_verndx = shdr->sh_info;
1277 			} else {
1278 				verneed_cache = _cache;
1279 			}
1280 			break;
1281 		}
1282 	}
1283 
1284 	if ((flags & FLG_SHOW_VERSIONS) == 0) {
1285 		/*
1286 		 * If GNU versioning applies to this object, and there
1287 		 * is a Verneed section, then examine it to determine
1288 		 * the maximum Versym version index for this file.
1289 		 */
1290 		if ((versym->gnu) && (verneed_cache != NULL))
1291 			update_gnu_max_verndx(
1292 			    (Verneed *)verneed_cache->c_data->d_buf,
1293 			    verneed_cache->c_shdr->sh_info, versym);
1294 		return;
1295 	}
1296 
1297 	/*
1298 	 * Now that all the information is available, display the
1299 	 * Verdef and Verneed section contents.
1300 	 */
1301 	if (verdef_cache != NULL) {
1302 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1303 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERDEF),
1304 		    verdef_cache->c_name);
1305 		version_def((Verdef *)verdef_cache->c_data->d_buf,
1306 		    verdef_cache->c_shdr->sh_info, verdef_cache,
1307 		    &cache[verdef_cache->c_shdr->sh_link], file);
1308 	}
1309 	if (verneed_cache != NULL) {
1310 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1311 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERNEED),
1312 		    verneed_cache->c_name);
1313 		/*
1314 		 * If GNU versioning applies to this object, version_need()
1315 		 * will update versym->max_verndx, and it is not
1316 		 * necessary to call update_gnu_max_verndx().
1317 		 */
1318 		version_need((Verneed *)verneed_cache->c_data->d_buf,
1319 		    verneed_cache->c_shdr->sh_info, verneed_cache,
1320 		    &cache[verneed_cache->c_shdr->sh_link], file, versym);
1321 	}
1322 }
1323 
1324 /*
1325  * Initialize a symbol table state structure
1326  *
1327  * entry:
1328  *	state - State structure to be initialized
1329  *	cache - Cache of all section headers
1330  *	shnum - # of sections in cache
1331  *	secndx - Index of symbol table section
1332  *	ehdr - ELF header for file
1333  *	versym - Information about versym section
1334  *	file - Name of file
1335  *	flags - Command line option flags
1336  */
1337 static int
1338 init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx,
1339     Ehdr *ehdr, VERSYM_STATE *versym, const char *file, uint_t flags)
1340 {
1341 	Shdr *shdr;
1342 
1343 	state->file = file;
1344 	state->ehdr = ehdr;
1345 	state->cache = cache;
1346 	state->shnum = shnum;
1347 	state->seccache = &cache[secndx];
1348 	state->secndx = secndx;
1349 	state->secname = state->seccache->c_name;
1350 	state->flags = flags;
1351 	state->shxndx.checked = 0;
1352 	state->shxndx.data = NULL;
1353 	state->shxndx.n = 0;
1354 
1355 	shdr = state->seccache->c_shdr;
1356 
1357 	/*
1358 	 * Check the symbol data and per-item size.
1359 	 */
1360 	if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
1361 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1362 		    file, state->secname);
1363 		return (0);
1364 	}
1365 	if (state->seccache->c_data == NULL)
1366 		return (0);
1367 
1368 	/* LINTED */
1369 	state->symn = (Word)(shdr->sh_size / shdr->sh_entsize);
1370 	state->sym = (Sym *)state->seccache->c_data->d_buf;
1371 
1372 	/*
1373 	 * Check associated string table section.
1374 	 */
1375 	if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
1376 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
1377 		    file, state->secname, EC_WORD(shdr->sh_link));
1378 		return (0);
1379 	}
1380 
1381 	/*
1382 	 * Determine if there is a associated Versym section
1383 	 * with this Symbol Table.
1384 	 */
1385 	if (versym->cache &&
1386 	    (versym->cache->c_shdr->sh_link == state->secndx))
1387 		state->versym = versym;
1388 	else
1389 		state->versym = NULL;
1390 
1391 
1392 	return (1);
1393 }
1394 
1395 /*
1396  * Determine the extended section index used for symbol tables entries.
1397  */
1398 static void
1399 symbols_getxindex(SYMTBL_STATE *state)
1400 {
1401 	uint_t	symn;
1402 	Word	symcnt;
1403 
1404 	state->shxndx.checked = 1;   /* Note that we've been called */
1405 	for (symcnt = 1; symcnt < state->shnum; symcnt++) {
1406 		Cache	*_cache = &state->cache[symcnt];
1407 		Shdr	*shdr = _cache->c_shdr;
1408 
1409 		if ((shdr->sh_type != SHT_SYMTAB_SHNDX) ||
1410 		    (shdr->sh_link != state->secndx))
1411 			continue;
1412 
1413 		if ((shdr->sh_entsize) &&
1414 		    /* LINTED */
1415 		    ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0))
1416 			continue;
1417 
1418 		if (_cache->c_data == NULL)
1419 			continue;
1420 
1421 		state->shxndx.data = _cache->c_data->d_buf;
1422 		state->shxndx.n = symn;
1423 		return;
1424 	}
1425 }
1426 
1427 /*
1428  * Produce a line of output for the given symbol
1429  *
1430  * entry:
1431  *	state - Symbol table state
1432  *	symndx - Index of symbol within the table
1433  *	info - Value of st_info (indicates local/global range)
1434  *	symndx_disp - Index to display. This may not be the same
1435  *		as symndx if the display is relative to the logical
1436  *		combination of the SUNW_ldynsym/dynsym tables.
1437  *	sym - Symbol to display
1438  */
1439 static void
1440 output_symbol(SYMTBL_STATE *state, Word symndx, Word info, Word disp_symndx,
1441     Sym *sym)
1442 {
1443 	/*
1444 	 * Symbol types for which we check that the specified
1445 	 * address/size land inside the target section.
1446 	 */
1447 	static const int addr_symtype[STT_NUM] = {
1448 		0,			/* STT_NOTYPE */
1449 		1,			/* STT_OBJECT */
1450 		1,			/* STT_FUNC */
1451 		0,			/* STT_SECTION */
1452 		0,			/* STT_FILE */
1453 		1,			/* STT_COMMON */
1454 		0,			/* STT_TLS */
1455 	};
1456 #if STT_NUM != (STT_TLS + 1)
1457 #error "STT_NUM has grown. Update addr_symtype[]"
1458 #endif
1459 
1460 	char		index[MAXNDXSIZE];
1461 	const char	*symname, *sec;
1462 	Versym		verndx;
1463 	int		gnuver;
1464 	uchar_t		type;
1465 	Shdr		*tshdr;
1466 	Word		shndx;
1467 	Conv_inv_buf_t	inv_buf;
1468 
1469 	/* Ensure symbol index is in range */
1470 	if (symndx >= state->symn) {
1471 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORTNDX),
1472 		    state->file, state->secname, EC_WORD(symndx));
1473 		return;
1474 	}
1475 
1476 	/*
1477 	 * If we are using extended symbol indexes, find the
1478 	 * corresponding SHN_SYMTAB_SHNDX table.
1479 	 */
1480 	if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0))
1481 		symbols_getxindex(state);
1482 
1483 	/* LINTED */
1484 	symname = string(state->seccache, symndx,
1485 	    &state->cache[state->seccache->c_shdr->sh_link], state->file,
1486 	    sym->st_name);
1487 
1488 	tshdr = 0;
1489 	sec = NULL;
1490 
1491 	if (state->ehdr->e_type == ET_CORE) {
1492 		sec = (char *)MSG_INTL(MSG_STR_UNKNOWN);
1493 	} else if (state->flags & FLG_CTL_FAKESHDR) {
1494 		/*
1495 		 * If we are using fake section headers derived from
1496 		 * the program headers, then the section indexes
1497 		 * in the symbols do not correspond to these headers.
1498 		 * The section names are not available, so all we can
1499 		 * do is to display them in numeric form.
1500 		 */
1501 		sec = conv_sym_shndx(sym->st_shndx, &inv_buf);
1502 	} else if ((sym->st_shndx < SHN_LORESERVE) &&
1503 	    (sym->st_shndx < state->shnum)) {
1504 		shndx = sym->st_shndx;
1505 		tshdr = state->cache[shndx].c_shdr;
1506 		sec = state->cache[shndx].c_name;
1507 	} else if (sym->st_shndx == SHN_XINDEX) {
1508 		if (state->shxndx.data) {
1509 			Word	_shxndx;
1510 
1511 			if (symndx > state->shxndx.n) {
1512 				(void) fprintf(stderr,
1513 				    MSG_INTL(MSG_ERR_BADSYMXINDEX1),
1514 				    state->file, state->secname,
1515 				    EC_WORD(symndx));
1516 			} else if ((_shxndx =
1517 			    state->shxndx.data[symndx]) > state->shnum) {
1518 				(void) fprintf(stderr,
1519 				    MSG_INTL(MSG_ERR_BADSYMXINDEX2),
1520 				    state->file, state->secname,
1521 				    EC_WORD(symndx), EC_WORD(_shxndx));
1522 			} else {
1523 				shndx = _shxndx;
1524 				tshdr = state->cache[shndx].c_shdr;
1525 				sec = state->cache[shndx].c_name;
1526 			}
1527 		} else {
1528 			(void) fprintf(stderr,
1529 			    MSG_INTL(MSG_ERR_BADSYMXINDEX3),
1530 			    state->file, state->secname, EC_WORD(symndx));
1531 		}
1532 	} else if ((sym->st_shndx < SHN_LORESERVE) &&
1533 	    (sym->st_shndx >= state->shnum)) {
1534 		(void) fprintf(stderr,
1535 		    MSG_INTL(MSG_ERR_BADSYM5), state->file,
1536 		    state->secname, EC_WORD(symndx),
1537 		    demangle(symname, state->flags), sym->st_shndx);
1538 	}
1539 
1540 	/*
1541 	 * If versioning is available display the
1542 	 * version index. If not, then use 0.
1543 	 */
1544 	if (state->versym) {
1545 		Versym test_verndx;
1546 
1547 		verndx = test_verndx = state->versym->data[symndx];
1548 		gnuver = state->versym->gnu;
1549 
1550 		/*
1551 		 * Check to see if this is a defined symbol with a
1552 		 * version index that is outside the valid range for
1553 		 * the file. The interpretation of this depends on
1554 		 * the style of versioning used by the object.
1555 		 *
1556 		 * Versions >= VER_NDX_LORESERVE have special meanings,
1557 		 * and are exempt from this checking.
1558 		 *
1559 		 * GNU style version indexes use the top bit of the
1560 		 * 16-bit index value (0x8000) as the "hidden bit".
1561 		 * We must mask off this bit in order to compare
1562 		 * the version against the maximum value.
1563 		 */
1564 		if (gnuver)
1565 			test_verndx &= ~0x8000;
1566 
1567 		if ((test_verndx > state->versym->max_verndx) &&
1568 		    (verndx < VER_NDX_LORESERVE))
1569 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADVER),
1570 			    state->file, state->secname, EC_WORD(symndx),
1571 			    EC_HALF(test_verndx), state->versym->max_verndx);
1572 	} else {
1573 		verndx = 0;
1574 		gnuver = 0;
1575 	}
1576 
1577 	/*
1578 	 * Error checking for TLS.
1579 	 */
1580 	type = ELF_ST_TYPE(sym->st_info);
1581 	if (type == STT_TLS) {
1582 		if (tshdr &&
1583 		    (sym->st_shndx != SHN_UNDEF) &&
1584 		    ((tshdr->sh_flags & SHF_TLS) == 0)) {
1585 			(void) fprintf(stderr,
1586 			    MSG_INTL(MSG_ERR_BADSYM3), state->file,
1587 			    state->secname, EC_WORD(symndx),
1588 			    demangle(symname, state->flags));
1589 		}
1590 	} else if ((type != STT_SECTION) && sym->st_size &&
1591 	    tshdr && (tshdr->sh_flags & SHF_TLS)) {
1592 		(void) fprintf(stderr,
1593 		    MSG_INTL(MSG_ERR_BADSYM4), state->file,
1594 		    state->secname, EC_WORD(symndx),
1595 		    demangle(symname, state->flags));
1596 	}
1597 
1598 	/*
1599 	 * If a symbol with non-zero size has a type that
1600 	 * specifies an address, then make sure the location
1601 	 * it references is actually contained within the
1602 	 * section.  UNDEF symbols don't count in this case,
1603 	 * so we ignore them.
1604 	 *
1605 	 * The meaning of the st_value field in a symbol
1606 	 * depends on the type of object. For a relocatable
1607 	 * object, it is the offset within the section.
1608 	 * For sharable objects, it is the offset relative to
1609 	 * the base of the object, and for other types, it is
1610 	 * the virtual address. To get an offset within the
1611 	 * section for non-ET_REL files, we subtract the
1612 	 * base address of the section.
1613 	 */
1614 	if (addr_symtype[type] && (sym->st_size > 0) &&
1615 	    (sym->st_shndx != SHN_UNDEF) && ((sym->st_shndx < SHN_LORESERVE) ||
1616 	    (sym->st_shndx == SHN_XINDEX)) && (tshdr != NULL)) {
1617 		Word v = sym->st_value;
1618 			if (state->ehdr->e_type != ET_REL)
1619 				v -= tshdr->sh_addr;
1620 		if (((v + sym->st_size) > tshdr->sh_size)) {
1621 			(void) fprintf(stderr,
1622 			    MSG_INTL(MSG_ERR_BADSYM6), state->file,
1623 			    state->secname, EC_WORD(symndx),
1624 			    demangle(symname, state->flags),
1625 			    EC_WORD(shndx), EC_XWORD(tshdr->sh_size),
1626 			    EC_XWORD(sym->st_value), EC_XWORD(sym->st_size));
1627 		}
1628 	}
1629 
1630 	/*
1631 	 * A typical symbol table uses the sh_info field to indicate one greater
1632 	 * than the symbol table index of the last local symbol, STB_LOCAL.
1633 	 * Therefore, symbol indexes less than sh_info should have local
1634 	 * binding.  Symbol indexes greater than, or equal to sh_info, should
1635 	 * have global binding.  Note, we exclude UNDEF/NOTY symbols with zero
1636 	 * value and size, as these symbols may be the result of an mcs(1)
1637 	 * section deletion.
1638 	 */
1639 	if (info) {
1640 		uchar_t	bind = ELF_ST_BIND(sym->st_info);
1641 
1642 		if ((symndx < info) && (bind != STB_LOCAL)) {
1643 			(void) fprintf(stderr,
1644 			    MSG_INTL(MSG_ERR_BADSYM7), state->file,
1645 			    state->secname, EC_WORD(symndx),
1646 			    demangle(symname, state->flags), EC_XWORD(info));
1647 
1648 		} else if ((symndx >= info) && (bind == STB_LOCAL) &&
1649 		    ((sym->st_shndx != SHN_UNDEF) ||
1650 		    (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) ||
1651 		    (sym->st_size != 0) || (sym->st_value != 0))) {
1652 			(void) fprintf(stderr,
1653 			    MSG_INTL(MSG_ERR_BADSYM8), state->file,
1654 			    state->secname, EC_WORD(symndx),
1655 			    demangle(symname, state->flags), EC_XWORD(info));
1656 		}
1657 	}
1658 
1659 	(void) snprintf(index, MAXNDXSIZE,
1660 	    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(disp_symndx));
1661 	Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index,
1662 	    state->ehdr->e_machine, sym, verndx, gnuver, sec, symname);
1663 }
1664 
1665 /*
1666  * Search for and process any symbol tables.
1667  */
1668 void
1669 symbols(Cache *cache, Word shnum, Ehdr *ehdr, VERSYM_STATE *versym,
1670     const char *file, uint_t flags)
1671 {
1672 	SYMTBL_STATE state;
1673 	Cache *_cache;
1674 	Word secndx;
1675 
1676 	for (secndx = 1; secndx < shnum; secndx++) {
1677 		Word		symcnt;
1678 		Shdr		*shdr;
1679 
1680 		_cache = &cache[secndx];
1681 		shdr = _cache->c_shdr;
1682 
1683 		if ((shdr->sh_type != SHT_SYMTAB) &&
1684 		    (shdr->sh_type != SHT_DYNSYM) &&
1685 		    (shdr->sh_type != SHT_SUNW_LDYNSYM))
1686 			continue;
1687 		if (!match(MATCH_F_ALL, _cache->c_name, secndx, shdr->sh_type))
1688 			continue;
1689 
1690 		if (!init_symtbl_state(&state, cache, shnum, secndx, ehdr,
1691 		    versym, file, flags))
1692 			continue;
1693 		/*
1694 		 * Loop through the symbol tables entries.
1695 		 */
1696 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1697 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), state.secname);
1698 		Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
1699 
1700 		for (symcnt = 0; symcnt < state.symn; symcnt++)
1701 			output_symbol(&state, symcnt, shdr->sh_info, symcnt,
1702 			    state.sym + symcnt);
1703 	}
1704 }
1705 
1706 /*
1707  * Search for and process any SHT_SUNW_symsort or SHT_SUNW_tlssort sections.
1708  * These sections are always associated with the .SUNW_ldynsym./.dynsym pair.
1709  */
1710 static void
1711 sunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, VERSYM_STATE *versym,
1712     const char *file, uint_t flags)
1713 {
1714 	SYMTBL_STATE	ldynsym_state,	dynsym_state;
1715 	Cache		*sortcache,	*symcache;
1716 	Shdr		*sortshdr,	*symshdr;
1717 	Word		sortsecndx,	symsecndx;
1718 	Word		ldynsym_cnt;
1719 	Word		*ndx;
1720 	Word		ndxn;
1721 	int		output_cnt = 0;
1722 	Conv_inv_buf_t	inv_buf;
1723 
1724 	for (sortsecndx = 1; sortsecndx < shnum; sortsecndx++) {
1725 
1726 		sortcache = &cache[sortsecndx];
1727 		sortshdr = sortcache->c_shdr;
1728 
1729 		if ((sortshdr->sh_type != SHT_SUNW_symsort) &&
1730 		    (sortshdr->sh_type != SHT_SUNW_tlssort))
1731 			continue;
1732 		if (!match(MATCH_F_ALL, sortcache->c_name, sortsecndx,
1733 		    sortshdr->sh_type))
1734 			continue;
1735 
1736 		/*
1737 		 * If the section references a SUNW_ldynsym, then we
1738 		 * expect to see the associated .dynsym immediately
1739 		 * following. If it references a .dynsym, there is no
1740 		 * SUNW_ldynsym. If it is any other type, then we don't
1741 		 * know what to do with it.
1742 		 */
1743 		if ((sortshdr->sh_link == 0) || (sortshdr->sh_link >= shnum)) {
1744 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
1745 			    file, sortcache->c_name,
1746 			    EC_WORD(sortshdr->sh_link));
1747 			continue;
1748 		}
1749 		symcache = &cache[sortshdr->sh_link];
1750 		symshdr = symcache->c_shdr;
1751 		symsecndx = sortshdr->sh_link;
1752 		ldynsym_cnt = 0;
1753 		switch (symshdr->sh_type) {
1754 		case SHT_SUNW_LDYNSYM:
1755 			if (!init_symtbl_state(&ldynsym_state, cache, shnum,
1756 			    symsecndx, ehdr, versym, file, flags))
1757 				continue;
1758 			ldynsym_cnt = ldynsym_state.symn;
1759 			/*
1760 			 * We know that the dynsym follows immediately
1761 			 * after the SUNW_ldynsym, and so, should be at
1762 			 * (sortshdr->sh_link + 1). However, elfdump is a
1763 			 * diagnostic tool, so we do the full paranoid
1764 			 * search instead.
1765 			 */
1766 			for (symsecndx = 1; symsecndx < shnum; symsecndx++) {
1767 				symcache = &cache[symsecndx];
1768 				symshdr = symcache->c_shdr;
1769 				if (symshdr->sh_type == SHT_DYNSYM)
1770 					break;
1771 			}
1772 			if (symsecndx >= shnum) {	/* Dynsym not found! */
1773 				(void) fprintf(stderr,
1774 				    MSG_INTL(MSG_ERR_NODYNSYM),
1775 				    file, sortcache->c_name);
1776 				continue;
1777 			}
1778 			/* Fallthrough to process associated dynsym */
1779 			/* FALLTHROUGH */
1780 		case SHT_DYNSYM:
1781 			if (!init_symtbl_state(&dynsym_state, cache, shnum,
1782 			    symsecndx, ehdr, versym, file, flags))
1783 				continue;
1784 			break;
1785 		default:
1786 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADNDXSEC),
1787 			    file, sortcache->c_name, conv_sec_type(
1788 			    ehdr->e_machine, symshdr->sh_type, 0, &inv_buf));
1789 			continue;
1790 		}
1791 
1792 		/*
1793 		 * Output header
1794 		 */
1795 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1796 		if (ldynsym_cnt > 0) {
1797 			dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT2),
1798 			    sortcache->c_name, ldynsym_state.secname,
1799 			    dynsym_state.secname);
1800 			/*
1801 			 * The data for .SUNW_ldynsym and dynsym sections
1802 			 * is supposed to be adjacent with SUNW_ldynsym coming
1803 			 * first. Check, and issue a warning if it isn't so.
1804 			 */
1805 			if (((ldynsym_state.sym + ldynsym_state.symn)
1806 			    != dynsym_state.sym) &&
1807 			    ((flags & FLG_CTL_FAKESHDR) == 0))
1808 				(void) fprintf(stderr,
1809 				    MSG_INTL(MSG_ERR_LDYNNOTADJ), file,
1810 				    ldynsym_state.secname,
1811 				    dynsym_state.secname);
1812 		} else {
1813 			dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT1),
1814 			    sortcache->c_name, dynsym_state.secname);
1815 		}
1816 		Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
1817 
1818 		/* If not first one, insert a line of whitespace */
1819 		if (output_cnt++ > 0)
1820 			dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1821 
1822 		/*
1823 		 * SUNW_dynsymsort and SUNW_dyntlssort are arrays of
1824 		 * symbol indices. Iterate over the array entries,
1825 		 * dispaying the referenced symbols.
1826 		 */
1827 		ndxn = sortshdr->sh_size / sortshdr->sh_entsize;
1828 		ndx = (Word *)sortcache->c_data->d_buf;
1829 		for (; ndxn-- > 0; ndx++) {
1830 			if (*ndx >= ldynsym_cnt) {
1831 				Word sec_ndx = *ndx - ldynsym_cnt;
1832 
1833 				output_symbol(&dynsym_state, sec_ndx, 0,
1834 				    *ndx, dynsym_state.sym + sec_ndx);
1835 			} else {
1836 				output_symbol(&ldynsym_state, *ndx, 0,
1837 				    *ndx, ldynsym_state.sym + *ndx);
1838 			}
1839 		}
1840 	}
1841 }
1842 
1843 /*
1844  * Search for and process any relocation sections.
1845  */
1846 static void
1847 reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *file)
1848 {
1849 	Word	cnt;
1850 
1851 	for (cnt = 1; cnt < shnum; cnt++) {
1852 		Word		type, symnum;
1853 		Xword		relndx, relnum, relsize;
1854 		void		*rels;
1855 		Sym		*syms;
1856 		Cache		*symsec, *strsec;
1857 		Cache		*_cache = &cache[cnt];
1858 		Shdr		*shdr = _cache->c_shdr;
1859 		char		*relname = _cache->c_name;
1860 		Conv_inv_buf_t	inv_buf;
1861 
1862 		if (((type = shdr->sh_type) != SHT_RELA) &&
1863 		    (type != SHT_REL))
1864 			continue;
1865 		if (!match(MATCH_F_ALL, relname, cnt, type))
1866 			continue;
1867 
1868 		/*
1869 		 * Decide entry size.
1870 		 */
1871 		if (((relsize = shdr->sh_entsize) == 0) ||
1872 		    (relsize > shdr->sh_size)) {
1873 			if (type == SHT_RELA)
1874 				relsize = sizeof (Rela);
1875 			else
1876 				relsize = sizeof (Rel);
1877 		}
1878 
1879 		/*
1880 		 * Determine the number of relocations available.
1881 		 */
1882 		if (shdr->sh_size == 0) {
1883 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1884 			    file, relname);
1885 			continue;
1886 		}
1887 		if (_cache->c_data == NULL)
1888 			continue;
1889 
1890 		rels = _cache->c_data->d_buf;
1891 		relnum = shdr->sh_size / relsize;
1892 
1893 		/*
1894 		 * Get the data buffer for the associated symbol table and
1895 		 * string table.
1896 		 */
1897 		if (stringtbl(cache, 1, cnt, shnum, file,
1898 		    &symnum, &symsec, &strsec) == 0)
1899 			continue;
1900 
1901 		syms = symsec->c_data->d_buf;
1902 
1903 		/*
1904 		 * Loop through the relocation entries.
1905 		 */
1906 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1907 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name);
1908 		Elf_reloc_title(0, ELF_DBG_ELFDUMP, type);
1909 
1910 		for (relndx = 0; relndx < relnum; relndx++,
1911 		    rels = (void *)((char *)rels + relsize)) {
1912 			Half		mach = ehdr->e_machine;
1913 			char		section[BUFSIZ];
1914 			const char	*symname;
1915 			Word		symndx, reltype;
1916 			Rela		*rela;
1917 			Rel		*rel;
1918 
1919 			/*
1920 			 * Unravel the relocation and determine the symbol with
1921 			 * which this relocation is associated.
1922 			 */
1923 			if (type == SHT_RELA) {
1924 				rela = (Rela *)rels;
1925 				symndx = ELF_R_SYM(rela->r_info);
1926 				reltype = ELF_R_TYPE(rela->r_info, mach);
1927 			} else {
1928 				rel = (Rel *)rels;
1929 				symndx = ELF_R_SYM(rel->r_info);
1930 				reltype = ELF_R_TYPE(rel->r_info, mach);
1931 			}
1932 
1933 			symname = relsymname(cache, _cache, strsec, symndx,
1934 			    symnum, relndx, syms, section, BUFSIZ, file);
1935 
1936 			/*
1937 			 * A zero symbol index is only valid for a few
1938 			 * relocations.
1939 			 */
1940 			if (symndx == 0) {
1941 				int	badrel = 0;
1942 
1943 				if ((mach == EM_SPARC) ||
1944 				    (mach == EM_SPARC32PLUS) ||
1945 				    (mach == EM_SPARCV9)) {
1946 					if ((reltype != R_SPARC_NONE) &&
1947 					    (reltype != R_SPARC_REGISTER) &&
1948 					    (reltype != R_SPARC_RELATIVE))
1949 						badrel++;
1950 				} else if (mach == EM_386) {
1951 					if ((reltype != R_386_NONE) &&
1952 					    (reltype != R_386_RELATIVE))
1953 						badrel++;
1954 				} else if (mach == EM_AMD64) {
1955 					if ((reltype != R_AMD64_NONE) &&
1956 					    (reltype != R_AMD64_RELATIVE))
1957 						badrel++;
1958 				}
1959 
1960 				if (badrel) {
1961 					(void) fprintf(stderr,
1962 					    MSG_INTL(MSG_ERR_BADREL1), file,
1963 					    conv_reloc_type(mach, reltype,
1964 					    0, &inv_buf));
1965 				}
1966 			}
1967 
1968 			Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP,
1969 			    MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type,
1970 			    rels, relname, symname, 0);
1971 		}
1972 	}
1973 }
1974 
1975 
1976 /*
1977  * This value controls which test dyn_test() performs.
1978  */
1979 typedef enum { DYN_TEST_ADDR, DYN_TEST_SIZE, DYN_TEST_ENTSIZE } dyn_test_t;
1980 
1981 /*
1982  * Used by dynamic() to compare the value of a dynamic element against
1983  * the starting address of the section it references.
1984  *
1985  * entry:
1986  *	test_type - Specify which dyn item is being tested.
1987  *	sh_type - SHT_* type value for required section.
1988  *	sec_cache - Cache entry for section, or NULL if the object lacks
1989  *		a section of this type.
1990  *	dyn - Dyn entry to be tested
1991  *	dynsec_cnt - # of dynamic section being examined. The first
1992  *		dynamic section is 1, the next is 2, and so on...
1993  *	ehdr - ELF header for file
1994  *	file - Name of file
1995  */
1996 static void
1997 dyn_test(dyn_test_t test_type, Word sh_type, Cache *sec_cache, Dyn *dyn,
1998     Word dynsec_cnt, Ehdr *ehdr, const char *file)
1999 {
2000 	Conv_inv_buf_t	buf1, buf2;
2001 
2002 	/*
2003 	 * These tests are based around the implicit assumption that
2004 	 * there is only one dynamic section in an object, and also only
2005 	 * one of the sections it references. We have therefore gathered
2006 	 * all of the necessary information to test this in a single pass
2007 	 * over the section headers, which is very efficient. We are not
2008 	 * aware of any case where more than one dynamic section would
2009 	 * be meaningful in an ELF object, so this is a reasonable solution.
2010 	 *
2011 	 * To test multiple dynamic sections correctly would be more
2012 	 * expensive in code and time. We would have to build a data structure
2013 	 * containing all the dynamic elements. Then, we would use the address
2014 	 * to locate the section it references and ensure the section is of
2015 	 * the right type and that the address in the dynamic element is
2016 	 * to the start of the section. Then, we could check the size and
2017 	 * entsize values against those same sections. This is O(n^2), and
2018 	 * also complicated.
2019 	 *
2020 	 * In the highly unlikely case that there is more than one dynamic
2021 	 * section, we only test the first one, and simply allow the values
2022 	 * of the subsequent one to be displayed unchallenged.
2023 	 */
2024 	if (dynsec_cnt != 1)
2025 		return;
2026 
2027 	/*
2028 	 * A DT_ item that references a section address should always find
2029 	 * the section in the file.
2030 	 */
2031 	if (sec_cache == NULL) {
2032 		const char *name;
2033 
2034 		/*
2035 		 * Supply section names instead of section types for
2036 		 * things that reference progbits so that the error
2037 		 * message will make more sense.
2038 		 */
2039 		switch (dyn->d_tag) {
2040 		case DT_INIT:
2041 			name = MSG_ORIG(MSG_ELF_INIT);
2042 			break;
2043 		case DT_FINI:
2044 			name = MSG_ORIG(MSG_ELF_FINI);
2045 			break;
2046 		default:
2047 			name = conv_sec_type(ehdr->e_machine, sh_type,
2048 			    0, &buf1);
2049 			break;
2050 		}
2051 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_DYNNOBCKSEC), file,
2052 		    name, conv_dyn_tag(dyn->d_tag, ehdr->e_machine, 0, &buf2));
2053 		return;
2054 	}
2055 
2056 
2057 	switch (test_type) {
2058 	case DYN_TEST_ADDR:
2059 		/* The section address should match the DT_ item value */
2060 		if (dyn->d_un.d_val != sec_cache->c_shdr->sh_addr)
2061 			(void) fprintf(stderr,
2062 			    MSG_INTL(MSG_ERR_DYNBADADDR), file,
2063 			    conv_dyn_tag(dyn->d_tag, ehdr->e_machine, 0, &buf1),
2064 			    EC_ADDR(dyn->d_un.d_val), sec_cache->c_ndx,
2065 			    sec_cache->c_name,
2066 			    EC_ADDR(sec_cache->c_shdr->sh_addr));
2067 		break;
2068 
2069 	case DYN_TEST_SIZE:
2070 		/* The section size should match the DT_ item value */
2071 		if (dyn->d_un.d_val != sec_cache->c_shdr->sh_size)
2072 			(void) fprintf(stderr,
2073 			    MSG_INTL(MSG_ERR_DYNBADSIZE), file,
2074 			    conv_dyn_tag(dyn->d_tag, ehdr->e_machine, 0, &buf1),
2075 			    EC_XWORD(dyn->d_un.d_val),
2076 			    sec_cache->c_ndx, sec_cache->c_name,
2077 			    EC_XWORD(sec_cache->c_shdr->sh_size));
2078 		break;
2079 
2080 	case DYN_TEST_ENTSIZE:
2081 		/* The sh_entsize value should match the DT_ item value */
2082 		if (dyn->d_un.d_val != sec_cache->c_shdr->sh_entsize)
2083 			(void) fprintf(stderr,
2084 			    MSG_INTL(MSG_ERR_DYNBADENTSIZE), file,
2085 			    conv_dyn_tag(dyn->d_tag, ehdr->e_machine, 0, &buf1),
2086 			    EC_XWORD(dyn->d_un.d_val),
2087 			    sec_cache->c_ndx, sec_cache->c_name,
2088 			    EC_XWORD(sec_cache->c_shdr->sh_entsize));
2089 		break;
2090 	}
2091 }
2092 
2093 
2094 /*
2095  * There are some DT_ entries that have corresponding symbols
2096  * (e.g. DT_INIT and _init). It is expected that these items will
2097  * both have the same value if both are present. This routine
2098  * examines the well known symbol tables for such symbols and
2099  * issues warnings for any that don't match.
2100  *
2101  * entry:
2102  *	dyn - Dyn entry to be tested
2103  *	symname - Name of symbol that corresponds to dyn
2104  *	symtab_cache, dynsym_cache, ldynsym_cache - Symbol tables to check
2105  *	cache - Cache of all section headers
2106  *	shnum - # of sections in cache
2107  *	ehdr - ELF header for file
2108  *	file - Name of file
2109  */
2110 static void
2111 dyn_symtest(Dyn *dyn, const char *symname, Cache *symtab_cache,
2112     Cache *dynsym_cache, Cache *ldynsym_cache, Cache *cache,
2113     Word shnum, Ehdr *ehdr, const char *file)
2114 {
2115 	Conv_inv_buf_t	buf;
2116 	int		i;
2117 	Sym		*sym;
2118 	Cache		*_cache;
2119 
2120 	for (i = 0; i < 3; i++) {
2121 		switch (i) {
2122 		case 0:
2123 			_cache = symtab_cache;
2124 			break;
2125 		case 1:
2126 			_cache = dynsym_cache;
2127 			break;
2128 		case 2:
2129 			_cache = ldynsym_cache;
2130 			break;
2131 		}
2132 
2133 		if ((_cache != NULL) &&
2134 		    symlookup(symname, cache, shnum, &sym, _cache, file) &&
2135 		    (sym->st_value != dyn->d_un.d_val))
2136 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_DYNSYMVAL),
2137 			    file, _cache->c_name,
2138 			    conv_dyn_tag(dyn->d_tag, ehdr->e_machine, 0, &buf),
2139 			    symname, EC_ADDR(sym->st_value));
2140 	}
2141 }
2142 
2143 
2144 /*
2145  * Search for and process a .dynamic section.
2146  */
2147 static void
2148 dynamic(Cache *cache, Word shnum, Ehdr *ehdr, const char *file)
2149 {
2150 	struct {
2151 		Cache	*symtab;
2152 		Cache	*dynstr;
2153 		Cache	*dynsym;
2154 		Cache	*hash;
2155 		Cache	*fini;
2156 		Cache	*fini_array;
2157 		Cache	*init;
2158 		Cache	*init_array;
2159 		Cache	*preinit_array;
2160 		Cache	*rel;
2161 		Cache	*rela;
2162 		Cache	*sunw_cap;
2163 		Cache	*sunw_ldynsym;
2164 		Cache	*sunw_move;
2165 		Cache	*sunw_syminfo;
2166 		Cache	*sunw_symsort;
2167 		Cache	*sunw_tlssort;
2168 		Cache	*sunw_verdef;
2169 		Cache	*sunw_verneed;
2170 		Cache	*sunw_versym;
2171 	} sec;
2172 	Word	dynsec_ndx;
2173 	Word	dynsec_num;
2174 	int	dynsec_cnt;
2175 	Word	cnt;
2176 
2177 	/*
2178 	 * Make a pass over all the sections, gathering section information
2179 	 * we'll need below.
2180 	 */
2181 	dynsec_num = 0;
2182 	bzero(&sec, sizeof (sec));
2183 	for (cnt = 1; cnt < shnum; cnt++) {
2184 		Cache	*_cache = &cache[cnt];
2185 
2186 		switch (_cache->c_shdr->sh_type) {
2187 		case SHT_DYNAMIC:
2188 			if (dynsec_num == 0) {
2189 				dynsec_ndx = cnt;
2190 
2191 				/* Does it have a valid string table? */
2192 				(void) stringtbl(cache, 0, cnt, shnum, file,
2193 				    0, 0, &sec.dynstr);
2194 			}
2195 			dynsec_num++;
2196 			break;
2197 
2198 
2199 		case SHT_PROGBITS:
2200 			/*
2201 			 * We want to detect the .init and .fini sections,
2202 			 * if present. These are SHT_PROGBITS, so all we
2203 			 * have to go on is the section name. Normally comparing
2204 			 * names is a bad idea, but there are some special
2205 			 * names (i.e. .init/.fini/.interp) that are very
2206 			 * difficult to use in any other context, and for
2207 			 * these symbols, we do the heuristic match.
2208 			 */
2209 			if (strcmp(_cache->c_name,
2210 			    MSG_ORIG(MSG_ELF_INIT)) == 0) {
2211 				if (sec.init == NULL)
2212 					sec.init = _cache;
2213 			} else if (strcmp(_cache->c_name,
2214 			    MSG_ORIG(MSG_ELF_FINI)) == 0) {
2215 				if (sec.fini == NULL)
2216 					sec.fini = _cache;
2217 			}
2218 			break;
2219 
2220 		case SHT_REL:
2221 			/*
2222 			 * We want the SHT_REL section with the lowest
2223 			 * offset. The linker gathers them together,
2224 			 * and puts the address of the first one
2225 			 * into the DT_REL dynamic element.
2226 			 */
2227 			if ((sec.rel == NULL) ||
2228 			    (_cache->c_shdr->sh_offset <
2229 			    sec.rel->c_shdr->sh_offset))
2230 				sec.rel = _cache;
2231 			break;
2232 
2233 		case SHT_RELA:
2234 			/* RELA is handled just like RELA above */
2235 			if ((sec.rela == NULL) ||
2236 			    (_cache->c_shdr->sh_offset <
2237 			    sec.rela->c_shdr->sh_offset))
2238 				sec.rela = _cache;
2239 			break;
2240 
2241 		/*
2242 		 * The GRAB macro is used for the simple case in which
2243 		 * we simply grab the first section of the desired type.
2244 		 */
2245 #define	GRAB(_sec_type, _sec_field) \
2246 		case _sec_type: \
2247 			if (sec._sec_field == NULL) \
2248 				sec._sec_field = _cache; \
2249 				break
2250 		GRAB(SHT_SYMTAB,	symtab);
2251 		GRAB(SHT_DYNSYM,	dynsym);
2252 		GRAB(SHT_FINI_ARRAY,	fini_array);
2253 		GRAB(SHT_HASH,		hash);
2254 		GRAB(SHT_INIT_ARRAY,	init_array);
2255 		GRAB(SHT_SUNW_move,	sunw_move);
2256 		GRAB(SHT_PREINIT_ARRAY,	preinit_array);
2257 		GRAB(SHT_SUNW_cap,	sunw_cap);
2258 		GRAB(SHT_SUNW_LDYNSYM,	sunw_ldynsym);
2259 		GRAB(SHT_SUNW_syminfo,	sunw_syminfo);
2260 		GRAB(SHT_SUNW_symsort,	sunw_symsort);
2261 		GRAB(SHT_SUNW_tlssort,	sunw_tlssort);
2262 		GRAB(SHT_SUNW_verdef,	sunw_verdef);
2263 		GRAB(SHT_SUNW_verneed,	sunw_verneed);
2264 		GRAB(SHT_SUNW_versym,	sunw_versym);
2265 #undef GRAB
2266 		}
2267 	}
2268 
2269 	/*
2270 	 * If no dynamic section, return immediately. If more than one
2271 	 * dynamic section, then something odd is going on and an error
2272 	 * is in order, but then continue on and display them all.
2273 	 */
2274 	if (dynsec_num == 0)
2275 		return;
2276 	if (dynsec_num > 1)
2277 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MULTDYN),
2278 		    file, EC_WORD(dynsec_num));
2279 
2280 
2281 	dynsec_cnt = 0;
2282 	for (cnt = dynsec_ndx; (cnt < shnum) && (dynsec_cnt < dynsec_num);
2283 	    cnt++) {
2284 		Dyn	*dyn;
2285 		ulong_t	numdyn;
2286 		int	ndx, end_ndx;
2287 		Cache	*_cache = &cache[cnt], *strsec;
2288 		Shdr	*shdr = _cache->c_shdr;
2289 		int	dumped = 0;
2290 
2291 		if (shdr->sh_type != SHT_DYNAMIC)
2292 			continue;
2293 		dynsec_cnt++;
2294 
2295 		/*
2296 		 * Verify the associated string table section.
2297 		 */
2298 		if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0)
2299 			continue;
2300 
2301 		if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
2302 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
2303 			    file, _cache->c_name);
2304 			continue;
2305 		}
2306 		if (_cache->c_data == NULL)
2307 			continue;
2308 
2309 		numdyn = shdr->sh_size / shdr->sh_entsize;
2310 		dyn = (Dyn *)_cache->c_data->d_buf;
2311 
2312 		/*
2313 		 * We expect the REL/RELA entries to reference the reloc
2314 		 * section with the lowest address. However, this is
2315 		 * not true for dumped objects. Detect if this object has
2316 		 * been dumped so that we can skip the reloc address test
2317 		 * in that case.
2318 		 */
2319 		for (ndx = 0; ndx < numdyn; dyn++, ndx++) {
2320 			if (dyn->d_tag == DT_FLAGS_1) {
2321 				dumped = (dyn->d_un.d_val & DF_1_CONFALT) != 0;
2322 				break;
2323 			}
2324 		}
2325 		dyn = (Dyn *)_cache->c_data->d_buf;
2326 
2327 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2328 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name);
2329 
2330 		Elf_dyn_title(0);
2331 
2332 		for (ndx = 0; ndx < numdyn; dyn++, ndx++) {
2333 			union {
2334 				Conv_inv_buf_t		inv;
2335 				Conv_dyn_flag_buf_t	flag;
2336 				Conv_dyn_flag1_buf_t	flag1;
2337 				Conv_dyn_posflag1_buf_t	posflag1;
2338 				Conv_dyn_feature1_buf_t	feature1;
2339 			} c_buf;
2340 			const char	*name = NULL;
2341 
2342 			/*
2343 			 * Print the information numerically, and if possible
2344 			 * as a string. If a string is available, name is
2345 			 * set to reference it.
2346 			 *
2347 			 * Also, take this opportunity to sanity check
2348 			 * the values of DT elements. In the code above,
2349 			 * we gathered information on sections that are
2350 			 * referenced by the dynamic section. Here, we
2351 			 * compare the attributes of those sections to
2352 			 * the DT_ items that reference them and report
2353 			 * on inconsistencies.
2354 			 *
2355 			 * Things not currently tested that could be improved
2356 			 * in later revisions include:
2357 			 *	- We don't check PLT or GOT related items
2358 			 *	- We don't handle computing the lengths of
2359 			 *		relocation arrays. To handle this
2360 			 *		requires examining data that spans
2361 			 *		across sections, in a contiguous span
2362 			 *		within a single segment.
2363 			 *	- DT_VERDEFNUM and DT_VERNEEDNUM can't be
2364 			 *		verified without parsing the sections.
2365 			 *	- We don't handle DT_SUNW_SYMSZ, which would
2366 			 *		be the sum of the lengths of .dynsym and
2367 			 *		.SUNW_ldynsym
2368 			 *	- DT_SUNW_STRPAD can't be verified other than
2369 			 *		to check that it's not larger than
2370 			 *		the string table.
2371 			 *	- Some items come in "all or none" clusters
2372 			 *		that give an address, element size,
2373 			 *		and data length in bytes. We don't
2374 			 *		verify that there are no missing items
2375 			 *		in such groups.
2376 			 */
2377 			switch (dyn->d_tag) {
2378 			case DT_NULL:
2379 				/*
2380 				 * Special case: DT_NULLs can come in groups
2381 				 * that we prefer to reduce to a single line.
2382 				 */
2383 				end_ndx = ndx;
2384 				while ((end_ndx < (numdyn - 1)) &&
2385 				    ((dyn + 1)->d_tag == DT_NULL)) {
2386 					dyn++;
2387 					end_ndx++;
2388 				}
2389 				Elf_dyn_null_entry(0, dyn, ndx, end_ndx);
2390 				ndx = end_ndx;
2391 				continue;
2392 
2393 			/*
2394 			 * String items all reference the dynstr. The string()
2395 			 * function does the necessary sanity checking.
2396 			 */
2397 			case DT_NEEDED:
2398 			case DT_SONAME:
2399 			case DT_FILTER:
2400 			case DT_AUXILIARY:
2401 			case DT_CONFIG:
2402 			case DT_RPATH:
2403 			case DT_RUNPATH:
2404 			case DT_USED:
2405 			case DT_DEPAUDIT:
2406 			case DT_AUDIT:
2407 			case DT_SUNW_AUXILIARY:
2408 			case DT_SUNW_FILTER:
2409 				name = string(_cache, ndx, strsec,
2410 				    file, dyn->d_un.d_ptr);
2411 				break;
2412 
2413 			case DT_FLAGS:
2414 				name = conv_dyn_flag(dyn->d_un.d_val,
2415 				    0, &c_buf.flag);
2416 				break;
2417 			case DT_FLAGS_1:
2418 				name = conv_dyn_flag1(dyn->d_un.d_val, 0,
2419 				    &c_buf.flag1);
2420 				break;
2421 			case DT_POSFLAG_1:
2422 				name = conv_dyn_posflag1(dyn->d_un.d_val, 0,
2423 				    &c_buf.posflag1);
2424 				break;
2425 			case DT_FEATURE_1:
2426 				name = conv_dyn_feature1(dyn->d_un.d_val, 0,
2427 				    &c_buf.feature1);
2428 				break;
2429 			case DT_DEPRECATED_SPARC_REGISTER:
2430 				name = MSG_INTL(MSG_STR_DEPRECATED);
2431 				break;
2432 
2433 			case DT_SUNW_LDMACH:
2434 				name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0,
2435 				    &c_buf.inv);
2436 				break;
2437 
2438 			/*
2439 			 * Cases below this point are strictly sanity checking,
2440 			 * and do not generate a name string. The TEST_ macros
2441 			 * are used to hide the boilerplate arguments neeeded
2442 			 * by dyn_test().
2443 			 */
2444 #define	TEST_ADDR(_sh_type, _sec_field) \
2445 				dyn_test(DYN_TEST_ADDR, _sh_type, \
2446 				    sec._sec_field, dyn, dynsec_cnt, ehdr, file)
2447 #define	TEST_SIZE(_sh_type, _sec_field) \
2448 				dyn_test(DYN_TEST_SIZE, _sh_type, \
2449 				    sec._sec_field, dyn, dynsec_cnt, ehdr, file)
2450 #define	TEST_ENTSIZE(_sh_type, _sec_field) \
2451 				dyn_test(DYN_TEST_ENTSIZE, _sh_type, \
2452 				    sec._sec_field, dyn, dynsec_cnt, ehdr, file)
2453 
2454 			case DT_FINI:
2455 				dyn_symtest(dyn, MSG_ORIG(MSG_SYM_FINI),
2456 				    sec.symtab, sec.dynsym, sec.sunw_ldynsym,
2457 				    cache, shnum, ehdr, file);
2458 				TEST_ADDR(SHT_PROGBITS, fini);
2459 				break;
2460 
2461 			case DT_FINI_ARRAY:
2462 				TEST_ADDR(SHT_FINI_ARRAY, fini_array);
2463 				break;
2464 
2465 			case DT_FINI_ARRAYSZ:
2466 				TEST_SIZE(SHT_FINI_ARRAY, fini_array);
2467 				break;
2468 
2469 			case DT_HASH:
2470 				TEST_ADDR(SHT_HASH, hash);
2471 				break;
2472 
2473 			case DT_INIT:
2474 				dyn_symtest(dyn, MSG_ORIG(MSG_SYM_INIT),
2475 				    sec.symtab, sec.dynsym, sec.sunw_ldynsym,
2476 				    cache, shnum, ehdr, file);
2477 				TEST_ADDR(SHT_PROGBITS, init);
2478 				break;
2479 
2480 			case DT_INIT_ARRAY:
2481 				TEST_ADDR(SHT_INIT_ARRAY, init_array);
2482 				break;
2483 
2484 			case DT_INIT_ARRAYSZ:
2485 				TEST_SIZE(SHT_INIT_ARRAY, init_array);
2486 				break;
2487 
2488 			case DT_MOVEENT:
2489 				TEST_ENTSIZE(SHT_SUNW_move, sunw_move);
2490 				break;
2491 
2492 			case DT_MOVESZ:
2493 				TEST_SIZE(SHT_SUNW_move, sunw_move);
2494 				break;
2495 
2496 			case DT_MOVETAB:
2497 				TEST_ADDR(SHT_SUNW_move, sunw_move);
2498 				break;
2499 
2500 			case DT_PREINIT_ARRAY:
2501 				TEST_ADDR(SHT_PREINIT_ARRAY, preinit_array);
2502 				break;
2503 
2504 			case DT_PREINIT_ARRAYSZ:
2505 				TEST_SIZE(SHT_PREINIT_ARRAY, preinit_array);
2506 				break;
2507 
2508 			case DT_REL:
2509 				if (!dumped)
2510 					TEST_ADDR(SHT_REL, rel);
2511 				break;
2512 
2513 			case DT_RELENT:
2514 				TEST_ENTSIZE(SHT_REL, rel);
2515 				break;
2516 
2517 			case DT_RELA:
2518 				if (!dumped)
2519 					TEST_ADDR(SHT_RELA, rela);
2520 				break;
2521 
2522 			case DT_RELAENT:
2523 				TEST_ENTSIZE(SHT_RELA, rela);
2524 				break;
2525 
2526 			case DT_STRTAB:
2527 				TEST_ADDR(SHT_STRTAB, dynstr);
2528 				break;
2529 
2530 			case DT_STRSZ:
2531 				TEST_SIZE(SHT_STRTAB, dynstr);
2532 				break;
2533 
2534 			case DT_SUNW_CAP:
2535 				TEST_ADDR(SHT_SUNW_cap, sunw_cap);
2536 				break;
2537 
2538 			case DT_SUNW_SYMTAB:
2539 				TEST_ADDR(SHT_SUNW_LDYNSYM, sunw_ldynsym);
2540 				break;
2541 
2542 			case DT_SYMENT:
2543 				TEST_ENTSIZE(SHT_DYNSYM, dynsym);
2544 				break;
2545 
2546 			case DT_SYMINENT:
2547 				TEST_ENTSIZE(SHT_SUNW_syminfo, sunw_syminfo);
2548 				break;
2549 
2550 			case DT_SYMINFO:
2551 				TEST_ADDR(SHT_SUNW_syminfo, sunw_syminfo);
2552 				break;
2553 
2554 			case DT_SYMINSZ:
2555 				TEST_SIZE(SHT_SUNW_syminfo, sunw_syminfo);
2556 				break;
2557 
2558 			case DT_SYMTAB:
2559 				TEST_ADDR(SHT_DYNSYM, dynsym);
2560 				break;
2561 
2562 			case DT_SUNW_SORTENT:
2563 				/*
2564 				 * This entry is related to both the symsort and
2565 				 * tlssort sections.
2566 				 */
2567 				{
2568 					int test_tls =
2569 					    (sec.sunw_tlssort != NULL);
2570 					int test_sym =
2571 					    (sec.sunw_symsort != NULL) ||
2572 					    !test_tls;
2573 					if (test_sym)
2574 						TEST_ENTSIZE(SHT_SUNW_symsort,
2575 						    sunw_symsort);
2576 					if (test_tls)
2577 						TEST_ENTSIZE(SHT_SUNW_tlssort,
2578 						    sunw_tlssort);
2579 				}
2580 				break;
2581 
2582 
2583 			case DT_SUNW_SYMSORT:
2584 				TEST_ADDR(SHT_SUNW_symsort, sunw_symsort);
2585 				break;
2586 
2587 			case DT_SUNW_SYMSORTSZ:
2588 				TEST_SIZE(SHT_SUNW_symsort, sunw_symsort);
2589 				break;
2590 
2591 			case DT_SUNW_TLSSORT:
2592 				TEST_ADDR(SHT_SUNW_tlssort, sunw_tlssort);
2593 				break;
2594 
2595 			case DT_SUNW_TLSSORTSZ:
2596 				TEST_SIZE(SHT_SUNW_tlssort, sunw_tlssort);
2597 				break;
2598 
2599 			case DT_VERDEF:
2600 				TEST_ADDR(SHT_SUNW_verdef, sunw_verdef);
2601 				break;
2602 
2603 			case DT_VERNEED:
2604 				TEST_ADDR(SHT_SUNW_verneed, sunw_verneed);
2605 				break;
2606 
2607 			case DT_VERSYM:
2608 				TEST_ADDR(SHT_SUNW_versym, sunw_versym);
2609 				break;
2610 #undef TEST_ADDR
2611 #undef TEST_SIZE
2612 #undef TEST_ENTSIZE
2613 			}
2614 
2615 			if (name == NULL)
2616 				name = MSG_ORIG(MSG_STR_EMPTY);
2617 			Elf_dyn_entry(0, dyn, ndx, name, ehdr->e_machine);
2618 		}
2619 	}
2620 }
2621 
2622 /*
2623  * Search for and process a MOVE section.
2624  */
2625 static void
2626 move(Cache *cache, Word shnum, const char *file, uint_t flags)
2627 {
2628 	Word		cnt;
2629 	const char	*fmt = 0;
2630 
2631 	for (cnt = 1; cnt < shnum; cnt++) {
2632 		Word	movenum, symnum, ndx;
2633 		Sym	*syms;
2634 		Cache	*_cache = &cache[cnt];
2635 		Shdr	*shdr = _cache->c_shdr;
2636 		Cache	*symsec, *strsec;
2637 		Move	*move;
2638 
2639 		if (shdr->sh_type != SHT_SUNW_move)
2640 			continue;
2641 		if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type))
2642 			continue;
2643 
2644 		/*
2645 		 * Determine the move data and number.
2646 		 */
2647 		if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
2648 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
2649 			    file, _cache->c_name);
2650 			continue;
2651 		}
2652 		if (_cache->c_data == NULL)
2653 			continue;
2654 
2655 		move = (Move *)_cache->c_data->d_buf;
2656 		movenum = shdr->sh_size / shdr->sh_entsize;
2657 
2658 		/*
2659 		 * Get the data buffer for the associated symbol table and
2660 		 * string table.
2661 		 */
2662 		if (stringtbl(cache, 1, cnt, shnum, file,
2663 		    &symnum, &symsec, &strsec) == 0)
2664 			return;
2665 
2666 		syms = (Sym *)symsec->c_data->d_buf;
2667 
2668 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2669 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name);
2670 		dbg_print(0, MSG_INTL(MSG_MOVE_TITLE));
2671 
2672 		if (fmt == 0)
2673 			fmt = MSG_INTL(MSG_MOVE_ENTRY);
2674 
2675 		for (ndx = 0; ndx < movenum; move++, ndx++) {
2676 			const char	*symname;
2677 			char		index[MAXNDXSIZE], section[BUFSIZ];
2678 			Word		symndx, shndx;
2679 			Sym		*sym;
2680 
2681 			/*
2682 			 * Check for null entries
2683 			 */
2684 			if ((move->m_info == 0) && (move->m_value == 0) &&
2685 			    (move->m_poffset == 0) && (move->m_repeat == 0) &&
2686 			    (move->m_stride == 0)) {
2687 				dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY),
2688 				    EC_XWORD(move->m_poffset), 0, 0, 0,
2689 				    EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY));
2690 				continue;
2691 			}
2692 			if (((symndx = ELF_M_SYM(move->m_info)) == 0) ||
2693 			    (symndx >= symnum)) {
2694 				(void) fprintf(stderr,
2695 				    MSG_INTL(MSG_ERR_BADMINFO), file,
2696 				    _cache->c_name, EC_XWORD(move->m_info));
2697 
2698 				(void) snprintf(index, MAXNDXSIZE,
2699 				    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx));
2700 				dbg_print(0, fmt, index,
2701 				    EC_XWORD(move->m_poffset),
2702 				    ELF_M_SIZE(move->m_info), move->m_repeat,
2703 				    move->m_stride, move->m_value,
2704 				    MSG_INTL(MSG_STR_UNKNOWN));
2705 				continue;
2706 			}
2707 
2708 			symname = relsymname(cache, _cache, strsec,
2709 			    symndx, symnum, ndx, syms, section, BUFSIZ, file);
2710 			sym = (Sym *)(syms + symndx);
2711 
2712 			/*
2713 			 * Additional sanity check.
2714 			 */
2715 			shndx = sym->st_shndx;
2716 			if (!((shndx == SHN_COMMON) ||
2717 			    (((shndx >= 1) && (shndx <= shnum)) &&
2718 			    (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) {
2719 				(void) fprintf(stderr,
2720 				    MSG_INTL(MSG_ERR_BADSYM2), file,
2721 				    _cache->c_name, EC_WORD(symndx),
2722 				    demangle(symname, flags));
2723 			}
2724 
2725 			(void) snprintf(index, MAXNDXSIZE,
2726 			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx));
2727 			dbg_print(0, fmt, index, EC_XWORD(move->m_poffset),
2728 			    ELF_M_SIZE(move->m_info), move->m_repeat,
2729 			    move->m_stride, move->m_value,
2730 			    demangle(symname, flags));
2731 		}
2732 	}
2733 }
2734 
2735 /*
2736  * Callback function for use with conv_str_to_c_literal() below.
2737  */
2738 /*ARGSUSED2*/
2739 static void
2740 c_literal_cb(const void *ptr, size_t size, void *uvalue)
2741 {
2742 	(void) fwrite(ptr, size, 1, stdout);
2743 }
2744 
2745 /*
2746  * Traverse a note section analyzing each note information block.
2747  * The data buffers size is used to validate references before they are made,
2748  * and is decremented as each element is processed.
2749  */
2750 void
2751 note_entry(Cache *cache, Word *data, size_t size, Ehdr *ehdr, const char *file)
2752 {
2753 	size_t		bsize = size;
2754 	int		cnt = 0;
2755 	int		is_corenote;
2756 	int		do_swap;
2757 	Conv_inv_buf_t	inv_buf;
2758 
2759 	do_swap =  _elf_sys_encoding() != ehdr->e_ident[EI_DATA];
2760 
2761 	/*
2762 	 * Print out a single `note' information block.
2763 	 */
2764 	while (size > 0) {
2765 		size_t	namesz, descsz, type, pad, noteoff;
2766 
2767 		noteoff = bsize - size;
2768 		/*
2769 		 * Make sure we can at least reference the 3 initial entries
2770 		 * (4-byte words) of the note information block.
2771 		 */
2772 		if (size >= (sizeof (Word) * 3))
2773 			size -= (sizeof (Word) * 3);
2774 		else {
2775 			(void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ),
2776 			    file, cache->c_name, EC_WORD(noteoff));
2777 			return;
2778 		}
2779 
2780 		/*
2781 		 * Make sure any specified name string can be referenced.
2782 		 */
2783 		if ((namesz = *data++) != 0) {
2784 			if (size >= namesz)
2785 				size -= namesz;
2786 			else {
2787 				(void) fprintf(stderr,
2788 				    MSG_INTL(MSG_NOTE_BADNMSZ), file,
2789 				    cache->c_name, EC_WORD(noteoff),
2790 				    EC_WORD(namesz));
2791 				return;
2792 			}
2793 		}
2794 
2795 		/*
2796 		 * Make sure any specified descriptor can be referenced.
2797 		 */
2798 		if ((descsz = *data++) != 0) {
2799 			/*
2800 			 * If namesz isn't a 4-byte multiple, account for any
2801 			 * padding that must exist before the descriptor.
2802 			 */
2803 			if ((pad = (namesz & (sizeof (Word) - 1))) != 0) {
2804 				pad = sizeof (Word) - pad;
2805 				size -= pad;
2806 			}
2807 			if (size >= descsz)
2808 				size -= descsz;
2809 			else {
2810 				(void) fprintf(stderr,
2811 				    MSG_INTL(MSG_NOTE_BADDESZ), file,
2812 				    cache->c_name, EC_WORD(noteoff),
2813 				    EC_WORD(namesz));
2814 				return;
2815 			}
2816 		}
2817 
2818 		type = *data++;
2819 
2820 		/*
2821 		 * Is this a Solaris core note? Such notes all have
2822 		 * the name "CORE".
2823 		 */
2824 		is_corenote = (ehdr->e_type == ET_CORE) &&
2825 		    (namesz == (MSG_STR_CORE_SIZE + 1)) &&
2826 		    (strncmp(MSG_ORIG(MSG_STR_CORE), (char *)data,
2827 		    MSG_STR_CORE_SIZE + 1) == 0);
2828 
2829 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2830 		dbg_print(0, MSG_INTL(MSG_FMT_NOTEENTNDX), EC_WORD(cnt));
2831 		cnt++;
2832 		dbg_print(0, MSG_ORIG(MSG_NOTE_NAMESZ), EC_WORD(namesz));
2833 		dbg_print(0, MSG_ORIG(MSG_NOTE_DESCSZ), EC_WORD(descsz));
2834 
2835 		if (is_corenote)
2836 			dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE_STR),
2837 			    conv_cnote_type(type, 0, &inv_buf));
2838 		else
2839 			dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE), EC_WORD(type));
2840 		if (namesz) {
2841 			char	*name = (char *)data;
2842 
2843 
2844 			dbg_print(0, MSG_ORIG(MSG_NOTE_NAME));
2845 			/*
2846 			 * The name string can contain embedded 'null'
2847 			 * bytes and/or unprintable characters. Also,
2848 			 * the final NULL is documented in the ELF ABI
2849 			 * as being included in the namesz. So, display
2850 			 * the name using C literal string notation, and
2851 			 * include the terminating NULL in the output.
2852 			 * We don't show surrounding double quotes, as
2853 			 * that implies the termination that we are showing
2854 			 * explicitly.
2855 			 */
2856 			(void) fwrite(MSG_ORIG(MSG_STR_8SP),
2857 			    MSG_STR_8SP_SIZE, 1, stdout);
2858 			conv_str_to_c_literal(name, namesz, c_literal_cb, NULL);
2859 			name = name + ((namesz + (sizeof (Word) - 1)) &
2860 			    ~(sizeof (Word) - 1));
2861 			/* LINTED */
2862 			data = (Word *)name;
2863 			dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2864 		}
2865 
2866 		/*
2867 		 * If multiple information blocks exist within a .note section
2868 		 * account for any padding that must exist before the next
2869 		 * information block.
2870 		 */
2871 		if ((pad = (descsz & (sizeof (Word) - 1))) != 0) {
2872 			pad = sizeof (Word) - pad;
2873 			if (size > pad)
2874 				size -= pad;
2875 		}
2876 
2877 		if (descsz) {
2878 			int		hexdump = 1;
2879 			const char	*desc = (const char *)data;
2880 
2881 			/*
2882 			 * If this is a core note, let the corenote()
2883 			 * function handle it.
2884 			 */
2885 			if (is_corenote) {
2886 				/* We only issue the bad arch error once */
2887 				static int	badnote_done = 0;
2888 				corenote_ret_t	corenote_ret;
2889 
2890 				corenote_ret = corenote(ehdr->e_machine,
2891 				    do_swap, type, desc, descsz);
2892 				switch (corenote_ret) {
2893 				case CORENOTE_R_OK:
2894 					hexdump = 0;
2895 					break;
2896 				case CORENOTE_R_BADDATA:
2897 					(void) fprintf(stderr,
2898 					    MSG_INTL(MSG_NOTE_BADCOREDATA),
2899 					    file);
2900 					break;
2901 				case CORENOTE_R_BADARCH:
2902 					if (badnote_done)
2903 						break;
2904 					(void) fprintf(stderr,
2905 					    MSG_INTL(MSG_NOTE_BADCOREARCH),
2906 					    file,
2907 					    conv_ehdr_mach(ehdr->e_machine,
2908 					    0, &inv_buf));
2909 					break;
2910 				}
2911 			}
2912 
2913 			/*
2914 			 * The default thing when we don't understand
2915 			 * the note data is to display it as hex bytes.
2916 			 */
2917 			if (hexdump) {
2918 				dbg_print(0, MSG_ORIG(MSG_NOTE_DESC));
2919 				dump_hex_bytes(desc, descsz, 8, 4, 4);
2920 			}
2921 			desc += descsz + pad;
2922 
2923 			/* LINTED */
2924 			data = (Word *)desc;
2925 		}
2926 	}
2927 }
2928 
2929 /*
2930  * Search for and process .note sections.
2931  *
2932  * Returns the number of note sections seen.
2933  */
2934 static Word
2935 note(Cache *cache, Word shnum, Ehdr *ehdr, const char *file)
2936 {
2937 	Word	cnt, note_cnt = 0;
2938 
2939 	/*
2940 	 * Otherwise look for any .note sections.
2941 	 */
2942 	for (cnt = 1; cnt < shnum; cnt++) {
2943 		Cache	*_cache = &cache[cnt];
2944 		Shdr	*shdr = _cache->c_shdr;
2945 
2946 		if (shdr->sh_type != SHT_NOTE)
2947 			continue;
2948 		note_cnt++;
2949 		if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type))
2950 			continue;
2951 
2952 		/*
2953 		 * As these sections are often hand rolled, make sure they're
2954 		 * properly aligned before proceeding, and issue an error
2955 		 * as necessary.
2956 		 *
2957 		 * Note that we will continue on to display the note even
2958 		 * if it has bad alignment. We can do this safely, because
2959 		 * libelf knows the alignment required for SHT_NOTE, and
2960 		 * takes steps to deliver a properly aligned buffer to us
2961 		 * even if the actual file is misaligned.
2962 		 */
2963 		if (shdr->sh_offset & (sizeof (Word) - 1))
2964 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN),
2965 			    file, _cache->c_name);
2966 
2967 		if (_cache->c_data == NULL)
2968 			continue;
2969 
2970 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2971 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name);
2972 		note_entry(_cache, (Word *)_cache->c_data->d_buf,
2973 		/* LINTED */
2974 		    (Word)_cache->c_data->d_size, ehdr, file);
2975 	}
2976 
2977 	return (note_cnt);
2978 }
2979 
2980 /*
2981  * Determine an individual hash entry.  This may be the initial hash entry,
2982  * or an associated chain entry.
2983  */
2984 static void
2985 hash_entry(Cache *refsec, Cache *strsec, const char *hsecname, Word hashndx,
2986     Word symndx, Word symn, Sym *syms, const char *file, ulong_t bkts,
2987     uint_t flags, int chain)
2988 {
2989 	Sym		*sym;
2990 	const char	*symname, *str;
2991 	char		_bucket[MAXNDXSIZE], _symndx[MAXNDXSIZE];
2992 	ulong_t		nbkt, nhash;
2993 
2994 	if (symndx > symn) {
2995 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_HSBADSYMNDX), file,
2996 		    EC_WORD(symndx), EC_WORD(hashndx));
2997 		symname = MSG_INTL(MSG_STR_UNKNOWN);
2998 	} else {
2999 		sym = (Sym *)(syms + symndx);
3000 		symname = string(refsec, symndx, strsec, file, sym->st_name);
3001 	}
3002 
3003 	if (chain == 0) {
3004 		(void) snprintf(_bucket, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER),
3005 		    hashndx);
3006 		str = (const char *)_bucket;
3007 	} else
3008 		str = MSG_ORIG(MSG_STR_EMPTY);
3009 
3010 	(void) snprintf(_symndx, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX2),
3011 	    EC_WORD(symndx));
3012 	dbg_print(0, MSG_ORIG(MSG_FMT_HASH_INFO), str, _symndx,
3013 	    demangle(symname, flags));
3014 
3015 	/*
3016 	 * Determine if this string is in the correct bucket.
3017 	 */
3018 	nhash = elf_hash(symname);
3019 	nbkt = nhash % bkts;
3020 
3021 	if (nbkt != hashndx) {
3022 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADHASH), file,
3023 		    hsecname, symname, EC_WORD(hashndx), nbkt);
3024 	}
3025 }
3026 
3027 #define	MAXCOUNT	500
3028 
3029 static void
3030 hash(Cache *cache, Word shnum, const char *file, uint_t flags)
3031 {
3032 	static int	count[MAXCOUNT];
3033 	Word		cnt;
3034 	ulong_t		ndx, bkts;
3035 	char		number[MAXNDXSIZE];
3036 
3037 	for (cnt = 1; cnt < shnum; cnt++) {
3038 		uint_t		*hash, *chain;
3039 		Cache		*_cache = &cache[cnt];
3040 		Shdr		*sshdr, *hshdr = _cache->c_shdr;
3041 		char		*ssecname, *hsecname = _cache->c_name;
3042 		Sym		*syms;
3043 		Word		symn;
3044 
3045 		if (hshdr->sh_type != SHT_HASH)
3046 			continue;
3047 
3048 		/*
3049 		 * Determine the hash table data and size.
3050 		 */
3051 		if ((hshdr->sh_entsize == 0) || (hshdr->sh_size == 0)) {
3052 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
3053 			    file, hsecname);
3054 			continue;
3055 		}
3056 		if (_cache->c_data == NULL)
3057 			continue;
3058 
3059 		hash = (uint_t *)_cache->c_data->d_buf;
3060 		bkts = *hash;
3061 		chain = hash + 2 + bkts;
3062 		hash += 2;
3063 
3064 		/*
3065 		 * Get the data buffer for the associated symbol table.
3066 		 */
3067 		if ((hshdr->sh_link == 0) || (hshdr->sh_link >= shnum)) {
3068 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
3069 			    file, hsecname, EC_WORD(hshdr->sh_link));
3070 			continue;
3071 		}
3072 
3073 		_cache = &cache[hshdr->sh_link];
3074 		ssecname = _cache->c_name;
3075 
3076 		if (_cache->c_data == NULL)
3077 			continue;
3078 
3079 		if ((syms = (Sym *)_cache->c_data->d_buf) == NULL) {
3080 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
3081 			    file, ssecname);
3082 			continue;
3083 		}
3084 
3085 		sshdr = _cache->c_shdr;
3086 		/* LINTED */
3087 		symn = (Word)(sshdr->sh_size / sshdr->sh_entsize);
3088 
3089 		/*
3090 		 * Get the associated string table section.
3091 		 */
3092 		if ((sshdr->sh_link == 0) || (sshdr->sh_link >= shnum)) {
3093 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
3094 			    file, ssecname, EC_WORD(sshdr->sh_link));
3095 			continue;
3096 		}
3097 
3098 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3099 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_HASH), hsecname);
3100 		dbg_print(0, MSG_INTL(MSG_ELF_HASH_INFO));
3101 
3102 		/*
3103 		 * Loop through the hash buckets, printing the appropriate
3104 		 * symbols.
3105 		 */
3106 		for (ndx = 0; ndx < bkts; ndx++, hash++) {
3107 			Word	_ndx, _cnt;
3108 
3109 			if (*hash == 0) {
3110 				count[0]++;
3111 				continue;
3112 			}
3113 
3114 			hash_entry(_cache, &cache[sshdr->sh_link], hsecname,
3115 			    ndx, *hash, symn, syms, file, bkts, flags, 0);
3116 
3117 			/*
3118 			 * Determine if any other symbols are chained to this
3119 			 * bucket.
3120 			 */
3121 			_ndx = chain[*hash];
3122 			_cnt = 1;
3123 			while (_ndx) {
3124 				hash_entry(_cache, &cache[sshdr->sh_link],
3125 				    hsecname, ndx, _ndx, symn, syms, file,
3126 				    bkts, flags, 1);
3127 				_ndx = chain[_ndx];
3128 				_cnt++;
3129 			}
3130 
3131 			if (_cnt >= MAXCOUNT) {
3132 				(void) fprintf(stderr,
3133 				    MSG_INTL(MSG_HASH_OVERFLW), file,
3134 				    _cache->c_name, EC_WORD(ndx),
3135 				    EC_WORD(_cnt));
3136 			} else
3137 				count[_cnt]++;
3138 		}
3139 		break;
3140 	}
3141 
3142 	/*
3143 	 * Print out the count information.
3144 	 */
3145 	bkts = cnt = 0;
3146 	dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3147 
3148 	for (ndx = 0; ndx < MAXCOUNT; ndx++) {
3149 		Word	_cnt;
3150 
3151 		if ((_cnt = count[ndx]) == 0)
3152 			continue;
3153 
3154 		(void) snprintf(number, MAXNDXSIZE,
3155 		    MSG_ORIG(MSG_FMT_INTEGER), _cnt);
3156 		dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS1), number,
3157 		    EC_WORD(ndx));
3158 		bkts += _cnt;
3159 		cnt += (Word)(ndx * _cnt);
3160 	}
3161 	if (cnt) {
3162 		(void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER),
3163 		    bkts);
3164 		dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS2), number,
3165 		    EC_WORD(cnt));
3166 	}
3167 }
3168 
3169 static void
3170 group(Cache *cache, Word shnum, const char *file, uint_t flags)
3171 {
3172 	Word	scnt;
3173 
3174 	for (scnt = 1; scnt < shnum; scnt++) {
3175 		Cache	*_cache = &cache[scnt];
3176 		Shdr	*shdr = _cache->c_shdr;
3177 		Word	*grpdata, gcnt, grpcnt, symnum, unknown;
3178 		Cache	*symsec, *strsec;
3179 		Sym	*syms, *sym;
3180 		char	flgstrbuf[MSG_GRP_COMDAT_SIZE + 10];
3181 
3182 		if (shdr->sh_type != SHT_GROUP)
3183 			continue;
3184 		if (!match(MATCH_F_ALL, _cache->c_name, scnt, shdr->sh_type))
3185 			continue;
3186 		if ((_cache->c_data == NULL) ||
3187 		    ((grpdata = (Word *)_cache->c_data->d_buf) == NULL))
3188 			continue;
3189 		grpcnt = shdr->sh_size / sizeof (Word);
3190 
3191 		/*
3192 		 * Get the data buffer for the associated symbol table and
3193 		 * string table.
3194 		 */
3195 		if (stringtbl(cache, 1, scnt, shnum, file,
3196 		    &symnum, &symsec, &strsec) == 0)
3197 			return;
3198 
3199 		syms = symsec->c_data->d_buf;
3200 
3201 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3202 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_GRP), _cache->c_name);
3203 		dbg_print(0, MSG_INTL(MSG_GRP_TITLE));
3204 
3205 		/*
3206 		 * The first element of the group defines the group.  The
3207 		 * associated symbol is defined by the sh_link field.
3208 		 */
3209 		if ((shdr->sh_info == SHN_UNDEF) || (shdr->sh_info > symnum)) {
3210 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO),
3211 			    file, _cache->c_name, EC_WORD(shdr->sh_info));
3212 			return;
3213 		}
3214 
3215 		(void) strcpy(flgstrbuf, MSG_ORIG(MSG_STR_OSQBRKT));
3216 		if (grpdata[0] & GRP_COMDAT) {
3217 			(void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_COMDAT));
3218 		}
3219 		if ((unknown = (grpdata[0] & ~GRP_COMDAT)) != 0) {
3220 			size_t	len = strlen(flgstrbuf);
3221 
3222 			(void) snprintf(&flgstrbuf[len],
3223 			    (MSG_GRP_COMDAT_SIZE + 10 - len),
3224 			    MSG_ORIG(MSG_GRP_UNKNOWN), unknown);
3225 		}
3226 		(void) strcat(flgstrbuf, MSG_ORIG(MSG_STR_CSQBRKT));
3227 		sym = (Sym *)(syms + shdr->sh_info);
3228 
3229 		dbg_print(0, MSG_INTL(MSG_GRP_SIGNATURE), flgstrbuf,
3230 		    demangle(string(_cache, 0, strsec, file, sym->st_name),
3231 		    flags));
3232 
3233 		for (gcnt = 1; gcnt < grpcnt; gcnt++) {
3234 			char		index[MAXNDXSIZE];
3235 			const char	*name;
3236 
3237 			(void) snprintf(index, MAXNDXSIZE,
3238 			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(gcnt));
3239 
3240 			if (grpdata[gcnt] >= shnum)
3241 				name = MSG_INTL(MSG_GRP_INVALSCN);
3242 			else
3243 				name = cache[grpdata[gcnt]].c_name;
3244 
3245 			(void) printf(MSG_ORIG(MSG_GRP_ENTRY), index, name,
3246 			    EC_XWORD(grpdata[gcnt]));
3247 		}
3248 	}
3249 }
3250 
3251 static void
3252 got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file)
3253 {
3254 	Cache		*gotcache = NULL, *symtab = NULL;
3255 	Addr		gotbgn, gotend;
3256 	Shdr		*gotshdr;
3257 	Word		cnt, gotents, gotndx;
3258 	size_t		gentsize;
3259 	Got_info	*gottable;
3260 	char		*gotdata;
3261 	Sym		*gotsym;
3262 	Xword		gotsymaddr;
3263 	uint_t		sys_encoding;
3264 
3265 	/*
3266 	 * First, find the got.
3267 	 */
3268 	for (cnt = 1; cnt < shnum; cnt++) {
3269 		if (strncmp(cache[cnt].c_name, MSG_ORIG(MSG_ELF_GOT),
3270 		    MSG_ELF_GOT_SIZE) == 0) {
3271 			gotcache = &cache[cnt];
3272 			break;
3273 		}
3274 	}
3275 	if (gotcache == NULL)
3276 		return;
3277 
3278 	/*
3279 	 * A got section within a relocatable object is suspicious.
3280 	 */
3281 	if (ehdr->e_type == ET_REL) {
3282 		(void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file,
3283 		    gotcache->c_name);
3284 	}
3285 
3286 	gotshdr = gotcache->c_shdr;
3287 	if (gotshdr->sh_size == 0) {
3288 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
3289 		    file, gotcache->c_name);
3290 		return;
3291 	}
3292 
3293 	gotbgn = gotshdr->sh_addr;
3294 	gotend = gotbgn + gotshdr->sh_size;
3295 
3296 	/*
3297 	 * Some architectures don't properly set the sh_entsize for the GOT
3298 	 * table.  If it's not set, default to a size of a pointer.
3299 	 */
3300 	if ((gentsize = gotshdr->sh_entsize) == 0)
3301 		gentsize = sizeof (Xword);
3302 
3303 	if (gotcache->c_data == NULL)
3304 		return;
3305 
3306 	/* LINTED */
3307 	gotents = (Word)(gotshdr->sh_size / gentsize);
3308 	gotdata = gotcache->c_data->d_buf;
3309 
3310 	if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) {
3311 		int err = errno;
3312 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), file,
3313 		    strerror(err));
3314 		return;
3315 	}
3316 
3317 	/*
3318 	 * Now we scan through all the sections looking for any relocations
3319 	 * that may be against the GOT.  Since these may not be isolated to a
3320 	 * .rel[a].got section we check them all.
3321 	 * While scanning sections save the symbol table entry (a symtab
3322 	 * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_.
3323 	 */
3324 	for (cnt = 1; cnt < shnum; cnt++) {
3325 		Word		type, symnum;
3326 		Xword		relndx, relnum, relsize;
3327 		void		*rels;
3328 		Sym		*syms;
3329 		Cache		*symsec, *strsec;
3330 		Cache		*_cache = &cache[cnt];
3331 		Shdr		*shdr;
3332 
3333 		shdr = _cache->c_shdr;
3334 		type = shdr->sh_type;
3335 
3336 		if ((symtab == 0) && (type == SHT_DYNSYM)) {
3337 			symtab = _cache;
3338 			continue;
3339 		}
3340 		if (type == SHT_SYMTAB) {
3341 			symtab = _cache;
3342 			continue;
3343 		}
3344 		if ((type != SHT_RELA) && (type != SHT_REL))
3345 			continue;
3346 
3347 		/*
3348 		 * Decide entry size.
3349 		 */
3350 		if (((relsize = shdr->sh_entsize) == 0) ||
3351 		    (relsize > shdr->sh_size)) {
3352 			if (type == SHT_RELA)
3353 				relsize = sizeof (Rela);
3354 			else
3355 				relsize = sizeof (Rel);
3356 		}
3357 
3358 		/*
3359 		 * Determine the number of relocations available.
3360 		 */
3361 		if (shdr->sh_size == 0) {
3362 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
3363 			    file, _cache->c_name);
3364 			continue;
3365 		}
3366 		if (_cache->c_data == NULL)
3367 			continue;
3368 
3369 		rels = _cache->c_data->d_buf;
3370 		relnum = shdr->sh_size / relsize;
3371 
3372 		/*
3373 		 * Get the data buffer for the associated symbol table and
3374 		 * string table.
3375 		 */
3376 		if (stringtbl(cache, 1, cnt, shnum, file,
3377 		    &symnum, &symsec, &strsec) == 0)
3378 			continue;
3379 
3380 		syms = symsec->c_data->d_buf;
3381 
3382 		/*
3383 		 * Loop through the relocation entries.
3384 		 */
3385 		for (relndx = 0; relndx < relnum; relndx++,
3386 		    rels = (void *)((char *)rels + relsize)) {
3387 			char		section[BUFSIZ];
3388 			Addr		offset;
3389 			Got_info	*gip;
3390 			Word		symndx, reltype;
3391 			Rela		*rela;
3392 			Rel		*rel;
3393 
3394 			/*
3395 			 * Unravel the relocation.
3396 			 */
3397 			if (type == SHT_RELA) {
3398 				rela = (Rela *)rels;
3399 				symndx = ELF_R_SYM(rela->r_info);
3400 				reltype = ELF_R_TYPE(rela->r_info,
3401 				    ehdr->e_machine);
3402 				offset = rela->r_offset;
3403 			} else {
3404 				rel = (Rel *)rels;
3405 				symndx = ELF_R_SYM(rel->r_info);
3406 				reltype = ELF_R_TYPE(rel->r_info,
3407 				    ehdr->e_machine);
3408 				offset = rel->r_offset;
3409 			}
3410 
3411 			/*
3412 			 * Only pay attention to relocations against the GOT.
3413 			 */
3414 			if ((offset < gotbgn) || (offset >= gotend))
3415 				continue;
3416 
3417 			/* LINTED */
3418 			gotndx = (Word)((offset - gotbgn) /
3419 			    gotshdr->sh_entsize);
3420 			gip = &gottable[gotndx];
3421 
3422 			if (gip->g_reltype != 0) {
3423 				(void) fprintf(stderr,
3424 				    MSG_INTL(MSG_GOT_MULTIPLE), file,
3425 				    EC_WORD(gotndx), EC_ADDR(offset));
3426 				continue;
3427 			}
3428 
3429 			if (symndx)
3430 				gip->g_symname = relsymname(cache, _cache,
3431 				    strsec, symndx, symnum, relndx, syms,
3432 				    section, BUFSIZ, file);
3433 			gip->g_reltype = reltype;
3434 			gip->g_rel = rels;
3435 		}
3436 	}
3437 
3438 	if (symlookup(MSG_ORIG(MSG_SYM_GOT), cache, shnum, &gotsym, symtab,
3439 	    file))
3440 		gotsymaddr = gotsym->st_value;
3441 	else
3442 		gotsymaddr = gotbgn;
3443 
3444 	dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3445 	dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name);
3446 	Elf_got_title(0);
3447 
3448 	sys_encoding = _elf_sys_encoding();
3449 	for (gotndx = 0; gotndx < gotents; gotndx++) {
3450 		Got_info	*gip;
3451 		Sword		gindex;
3452 		Addr		gaddr;
3453 		Xword		gotentry;
3454 
3455 		gip = &gottable[gotndx];
3456 
3457 		gaddr = gotbgn + (gotndx * gentsize);
3458 		gindex = (Sword)(gaddr - gotsymaddr) / (Sword)gentsize;
3459 
3460 		if (gentsize == sizeof (Word))
3461 			/* LINTED */
3462 			gotentry = (Xword)(*((Word *)(gotdata) + gotndx));
3463 		else
3464 			/* LINTED */
3465 			gotentry = *((Xword *)(gotdata) + gotndx);
3466 
3467 		Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine,
3468 		    ehdr->e_ident[EI_DATA], sys_encoding,
3469 		    gip->g_reltype, gip->g_rel, gip->g_symname);
3470 	}
3471 	free(gottable);
3472 }
3473 
3474 void
3475 checksum(Elf *elf)
3476 {
3477 	dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3478 	dbg_print(0, MSG_INTL(MSG_STR_CHECKSUM), elf_checksum(elf));
3479 }
3480 
3481 /*
3482  * This variable is used by regular() to communicate the address of
3483  * the section header cache to sort_shdr_ndx_arr(). Unfortunately,
3484  * the qsort() interface does not include a userdata argument by which
3485  * such arbitrary data can be passed, so we are stuck using global data.
3486  */
3487 static Cache *sort_shdr_ndx_arr_cache;
3488 
3489 
3490 /*
3491  * Used with qsort() to sort the section indices so that they can be
3492  * used to access the section headers in order of increasing data offset.
3493  *
3494  * entry:
3495  *	sort_shdr_ndx_arr_cache - Contains address of
3496  *		section header cache.
3497  *	v1, v2 - Point at elements of sort_shdr_bits array to be compared.
3498  *
3499  * exit:
3500  *	Returns -1 (less than), 0 (equal) or 1 (greater than).
3501  */
3502 static int
3503 sort_shdr_ndx_arr(const void *v1, const void *v2)
3504 {
3505 	Cache	*cache1 = sort_shdr_ndx_arr_cache + *((size_t *)v1);
3506 	Cache	*cache2 = sort_shdr_ndx_arr_cache + *((size_t *)v2);
3507 
3508 	if (cache1->c_shdr->sh_offset < cache2->c_shdr->sh_offset)
3509 		return (-1);
3510 
3511 	if (cache1->c_shdr->sh_offset > cache2->c_shdr->sh_offset)
3512 		return (1);
3513 
3514 	return (0);
3515 }
3516 
3517 
3518 static int
3519 shdr_cache(const char *file, Elf *elf, Ehdr *ehdr, size_t shstrndx,
3520     size_t shnum, Cache **cache_ret, Word flags)
3521 {
3522 	Elf_Scn		*scn;
3523 	Elf_Data	*data;
3524 	size_t		ndx;
3525 	Shdr		*nameshdr;
3526 	char		*names = 0;
3527 	Cache		*cache, *_cache;
3528 	size_t		*shdr_ndx_arr, shdr_ndx_arr_cnt;
3529 
3530 
3531 	/*
3532 	 * Obtain the .shstrtab data buffer to provide the required section
3533 	 * name strings.
3534 	 */
3535 	if (shstrndx == SHN_UNDEF) {
3536 		/*
3537 		 * It is rare, but legal, for an object to lack a
3538 		 * header string table section.
3539 		 */
3540 		names = NULL;
3541 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_NOSHSTRSEC), file);
3542 	} else if ((scn = elf_getscn(elf, shstrndx)) == NULL) {
3543 		failure(file, MSG_ORIG(MSG_ELF_GETSCN));
3544 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR),
3545 		    EC_XWORD(shstrndx));
3546 
3547 	} else if ((data = elf_getdata(scn, NULL)) == NULL) {
3548 		failure(file, MSG_ORIG(MSG_ELF_GETDATA));
3549 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA),
3550 		    EC_XWORD(shstrndx));
3551 
3552 	} else if ((nameshdr = elf_getshdr(scn)) == NULL) {
3553 		failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
3554 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN),
3555 		    EC_WORD(elf_ndxscn(scn)));
3556 
3557 	} else if ((names = data->d_buf) == 0)
3558 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file);
3559 
3560 	/*
3561 	 * Allocate a cache to maintain a descriptor for each section.
3562 	 */
3563 	if ((*cache_ret = cache = malloc(shnum * sizeof (Cache))) == NULL) {
3564 		int err = errno;
3565 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
3566 		    file, strerror(err));
3567 		return (0);
3568 	}
3569 
3570 	*cache = cache_init;
3571 	_cache = cache;
3572 	_cache++;
3573 
3574 	/*
3575 	 * Allocate an array that will hold the section index for
3576 	 * each section that has data in the ELF file:
3577 	 *
3578 	 *	- Is not a NOBITS section
3579 	 *	- Data has non-zero length
3580 	 *
3581 	 * Note that shnum is an upper bound on the size required. It
3582 	 * is likely that we won't use a few of these array elements.
3583 	 * Allocating a modest amount of extra memory in this case means
3584 	 * that we can avoid an extra loop to count the number of needed
3585 	 * items, and can fill this array immediately in the first loop
3586 	 * below.
3587 	 */
3588 	if ((shdr_ndx_arr = malloc(shnum * sizeof (*shdr_ndx_arr))) == NULL) {
3589 		int err = errno;
3590 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
3591 		    file, strerror(err));
3592 		return (0);
3593 	}
3594 	shdr_ndx_arr_cnt = 0;
3595 
3596 	/*
3597 	 * Traverse the sections of the file.  This gathering of data is
3598 	 * carried out in two passes.  First, the section headers are captured
3599 	 * and the section header names are evaluated.  A verification pass is
3600 	 * then carried out over the section information.  Files have been
3601 	 * known to exhibit overlapping (and hence erroneous) section header
3602 	 * information.
3603 	 *
3604 	 * Finally, the data for each section is obtained.  This processing is
3605 	 * carried out after section verification because should any section
3606 	 * header overlap occur, and a file needs translating (ie. xlate'ing
3607 	 * information from a non-native architecture file), then the process
3608 	 * of translation can corrupt the section header information.  Of
3609 	 * course, if there is any section overlap, the data related to the
3610 	 * sections is going to be compromised.  However, it is the translation
3611 	 * of this data that has caused problems with elfdump()'s ability to
3612 	 * extract the data.
3613 	 */
3614 	for (ndx = 1, scn = NULL; scn = elf_nextscn(elf, scn);
3615 	    ndx++, _cache++) {
3616 		char	scnndxnm[100];
3617 
3618 		_cache->c_ndx = ndx;
3619 		_cache->c_scn = scn;
3620 
3621 		if ((_cache->c_shdr = elf_getshdr(scn)) == NULL) {
3622 			failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
3623 			(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN),
3624 			    EC_WORD(elf_ndxscn(scn)));
3625 		}
3626 
3627 		/*
3628 		 * If this section has data in the file, include it in
3629 		 * the array of sections to check for address overlap.
3630 		 */
3631 		if ((_cache->c_shdr->sh_size != 0) &&
3632 		    (_cache->c_shdr->sh_type != SHT_NOBITS))
3633 			shdr_ndx_arr[shdr_ndx_arr_cnt++] = ndx;
3634 
3635 		/*
3636 		 * If a shstrtab exists, assign the section name.
3637 		 */
3638 		if (names && _cache->c_shdr) {
3639 			if (_cache->c_shdr->sh_name &&
3640 			    /* LINTED */
3641 			    (nameshdr->sh_size > _cache->c_shdr->sh_name)) {
3642 				const char	*symname;
3643 				char		*secname;
3644 
3645 				secname = names + _cache->c_shdr->sh_name;
3646 
3647 				/*
3648 				 * A SUN naming convention employs a "%" within
3649 				 * a section name to indicate a section/symbol
3650 				 * name.  This originated from the compilers
3651 				 * -xF option, that places functions into their
3652 				 * own sections.  This convention (which has no
3653 				 * formal standard) has also been followed for
3654 				 * COMDAT sections.  To demangle the symbol
3655 				 * name, the name must be separated from the
3656 				 * section name.
3657 				 */
3658 				if (((flags & FLG_CTL_DEMANGLE) == 0) ||
3659 				    ((symname = strchr(secname, '%')) == NULL))
3660 					_cache->c_name = secname;
3661 				else {
3662 					size_t	secsz = ++symname - secname;
3663 					size_t	strsz;
3664 
3665 					symname = demangle(symname, flags);
3666 					strsz = secsz + strlen(symname) + 1;
3667 
3668 					if ((_cache->c_name =
3669 					    malloc(strsz)) == NULL) {
3670 						int err = errno;
3671 						(void) fprintf(stderr,
3672 						    MSG_INTL(MSG_ERR_MALLOC),
3673 						    file, strerror(err));
3674 						return (0);
3675 					}
3676 					(void) snprintf(_cache->c_name, strsz,
3677 					    MSG_ORIG(MSG_FMT_SECSYM),
3678 					    EC_WORD(secsz), secname, symname);
3679 				}
3680 				continue;
3681 			}
3682 
3683 			/*
3684 			 * Generate an error if the section name index is zero
3685 			 * or exceeds the shstrtab data.  Fall through to
3686 			 * fabricate a section name.
3687 			 */
3688 			if ((_cache->c_shdr->sh_name == 0) ||
3689 			    /* LINTED */
3690 			    (nameshdr->sh_size <= _cache->c_shdr->sh_name)) {
3691 				(void) fprintf(stderr,
3692 				    MSG_INTL(MSG_ERR_BADSHNAME), file,
3693 				    EC_WORD(ndx),
3694 				    EC_XWORD(_cache->c_shdr->sh_name));
3695 			}
3696 		}
3697 
3698 		/*
3699 		 * If there exists no shstrtab data, or a section header has no
3700 		 * name (an invalid index of 0), then compose a name for the
3701 		 * section.
3702 		 */
3703 		(void) snprintf(scnndxnm, sizeof (scnndxnm),
3704 		    MSG_INTL(MSG_FMT_SCNNDX), ndx);
3705 
3706 		if ((_cache->c_name = malloc(strlen(scnndxnm) + 1)) == NULL) {
3707 			int err = errno;
3708 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
3709 			    file, strerror(err));
3710 			return (0);
3711 		}
3712 		(void) strcpy(_cache->c_name, scnndxnm);
3713 	}
3714 
3715 	/*
3716 	 * Having collected all the sections, validate their address range.
3717 	 * Cases have existed where the section information has been invalid.
3718 	 * This can lead to all sorts of other, hard to diagnose errors, as
3719 	 * each section is processed individually (ie. with elf_getdata()).
3720 	 * Here, we carry out some address comparisons to catch a family of
3721 	 * overlapping memory issues we have observed (likely, there are others
3722 	 * that we have yet to discover).
3723 	 *
3724 	 * Note, should any memory overlap occur, obtaining any additional
3725 	 * data from the file is questionable.  However, it might still be
3726 	 * possible to inspect the ELF header, Programs headers, or individual
3727 	 * sections, so rather than bailing on an error condition, continue
3728 	 * processing to see if any data can be salvaged.
3729 	 */
3730 	if (shdr_ndx_arr_cnt > 1) {
3731 		sort_shdr_ndx_arr_cache = cache;
3732 		qsort(shdr_ndx_arr, shdr_ndx_arr_cnt,
3733 		    sizeof (*shdr_ndx_arr), sort_shdr_ndx_arr);
3734 	}
3735 	for (ndx = 0; ndx < shdr_ndx_arr_cnt; ndx++) {
3736 		Cache	*_cache = cache + shdr_ndx_arr[ndx];
3737 		Shdr	*shdr = _cache->c_shdr;
3738 		Off	bgn1, bgn = shdr->sh_offset;
3739 		Off	end1, end = shdr->sh_offset + shdr->sh_size;
3740 		size_t	ndx1;
3741 
3742 		/*
3743 		 * Check the section against all following ones, reporting
3744 		 * any overlaps. Since we've sorted the sections by offset,
3745 		 * we can stop after the first comparison that fails. There
3746 		 * are no overlaps in a properly formed ELF file, in which
3747 		 * case this algorithm runs in O(n) time. This will degenerate
3748 		 * to O(n^2) for a completely broken file. Such a file is
3749 		 * (1) highly unlikely, and (2) unusable, so it is reasonable
3750 		 * for the analysis to take longer.
3751 		 */
3752 		for (ndx1 = ndx + 1; ndx1 < shdr_ndx_arr_cnt; ndx1++) {
3753 			Cache	*_cache1 = cache + shdr_ndx_arr[ndx1];
3754 			Shdr	*shdr1 = _cache1->c_shdr;
3755 
3756 			bgn1 = shdr1->sh_offset;
3757 			end1 = shdr1->sh_offset + shdr1->sh_size;
3758 
3759 			if (((bgn1 <= bgn) && (end1 > bgn)) ||
3760 			    ((bgn1 < end) && (end1 >= end))) {
3761 				(void) fprintf(stderr,
3762 				    MSG_INTL(MSG_ERR_SECMEMOVER), file,
3763 				    EC_WORD(elf_ndxscn(_cache->c_scn)),
3764 				    _cache->c_name, EC_OFF(bgn), EC_OFF(end),
3765 				    EC_WORD(elf_ndxscn(_cache1->c_scn)),
3766 				    _cache1->c_name, EC_OFF(bgn1),
3767 				    EC_OFF(end1));
3768 			} else {	/* No overlap, so can stop */
3769 				break;
3770 			}
3771 		}
3772 
3773 		/*
3774 		 * In addition to checking for sections overlapping
3775 		 * each other (done above), we should also make sure
3776 		 * the section doesn't overlap the section header array.
3777 		 */
3778 		bgn1 = ehdr->e_shoff;
3779 		end1 = ehdr->e_shoff + (ehdr->e_shentsize * ehdr->e_shnum);
3780 
3781 		if (((bgn1 <= bgn) && (end1 > bgn)) ||
3782 		    ((bgn1 < end) && (end1 >= end))) {
3783 			(void) fprintf(stderr,
3784 			    MSG_INTL(MSG_ERR_SHDRMEMOVER), file, EC_OFF(bgn1),
3785 			    EC_OFF(end1),
3786 			    EC_WORD(elf_ndxscn(_cache->c_scn)),
3787 			    _cache->c_name, EC_OFF(bgn), EC_OFF(end));
3788 		}
3789 	}
3790 
3791 	/*
3792 	 * Obtain the data for each section.
3793 	 */
3794 	for (ndx = 1; ndx < shnum; ndx++) {
3795 		Cache	*_cache = &cache[ndx];
3796 		Elf_Scn	*scn = _cache->c_scn;
3797 
3798 		if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) {
3799 			failure(file, MSG_ORIG(MSG_ELF_GETDATA));
3800 			(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA),
3801 			    EC_WORD(elf_ndxscn(scn)));
3802 		}
3803 	}
3804 
3805 	return (1);
3806 }
3807 
3808 
3809 
3810 int
3811 regular(const char *file, int fd, Elf *elf, uint_t flags,
3812     const char *wname, int wfd)
3813 {
3814 	Elf_Scn		*scn;
3815 	Ehdr		*ehdr;
3816 	size_t		ndx, shstrndx, shnum, phnum;
3817 	Shdr		*shdr;
3818 	Cache		*cache;
3819 	VERSYM_STATE	versym;
3820 	int		ret = 0;
3821 	int		addr_align;
3822 
3823 	if ((ehdr = elf_getehdr(elf)) == NULL) {
3824 		failure(file, MSG_ORIG(MSG_ELF_GETEHDR));
3825 		return (ret);
3826 	}
3827 
3828 	if (elf_getshnum(elf, &shnum) == 0) {
3829 		failure(file, MSG_ORIG(MSG_ELF_GETSHNUM));
3830 		return (ret);
3831 	}
3832 
3833 	if (elf_getshstrndx(elf, &shstrndx) == 0) {
3834 		failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX));
3835 		return (ret);
3836 	}
3837 
3838 	if (elf_getphnum(elf, &phnum) == 0) {
3839 		failure(file, MSG_ORIG(MSG_ELF_GETPHNUM));
3840 		return (ret);
3841 	}
3842 	/*
3843 	 * If the user requested section headers derived from the
3844 	 * program headers (-P option) and this file doesn't have
3845 	 * any program headers (i.e. ET_REL), then we can't do it.
3846 	 */
3847 	if ((phnum == 0) && (flags & FLG_CTL_FAKESHDR)) {
3848 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_PNEEDSPH), file);
3849 		return (ret);
3850 	}
3851 
3852 
3853 	if ((scn = elf_getscn(elf, 0)) != NULL) {
3854 		if ((shdr = elf_getshdr(scn)) == NULL) {
3855 			failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
3856 			(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0);
3857 			return (ret);
3858 		}
3859 	} else
3860 		shdr = 0;
3861 
3862 	/*
3863 	 * Print the elf header.
3864 	 */
3865 	if (flags & FLG_SHOW_EHDR)
3866 		Elf_ehdr(0, ehdr, shdr);
3867 
3868 	/*
3869 	 * If the section headers or program headers have inadequate
3870 	 * alignment for the class of object, print a warning. libelf
3871 	 * can handle such files, but programs that use them can crash
3872 	 * when they dereference unaligned items.
3873 	 *
3874 	 * Note that the AMD64 ABI, although it is a 64-bit architecture,
3875 	 * allows access to data types smaller than 128-bits to be on
3876 	 * word alignment.
3877 	 */
3878 	if (ehdr->e_machine == EM_AMD64)
3879 		addr_align = sizeof (Word);
3880 	else
3881 		addr_align = sizeof (Addr);
3882 
3883 	if (ehdr->e_phoff & (addr_align - 1))
3884 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADPHDRALIGN), file);
3885 	if (ehdr->e_shoff & (addr_align - 1))
3886 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHDRALIGN), file);
3887 
3888 	/*
3889 	 * Print the program headers.
3890 	 */
3891 	if ((flags & FLG_SHOW_PHDR) && (phnum != 0)) {
3892 		Phdr	*phdr;
3893 
3894 		if ((phdr = elf_getphdr(elf)) == NULL) {
3895 			failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
3896 			return (ret);
3897 		}
3898 
3899 		for (ndx = 0; ndx < phnum; phdr++, ndx++) {
3900 			if (!match(MATCH_F_PHDR| MATCH_F_NDX | MATCH_F_TYPE,
3901 			    NULL, ndx, phdr->p_type))
3902 				continue;
3903 
3904 			dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3905 			dbg_print(0, MSG_INTL(MSG_ELF_PHDR), EC_WORD(ndx));
3906 			Elf_phdr(0, ehdr->e_machine, phdr);
3907 		}
3908 	}
3909 
3910 	/*
3911 	 * If we have flag bits set that explicitly require a show or calc
3912 	 * operation, but none of them require the section headers, then
3913 	 * we are done and can return now.
3914 	 */
3915 	if (((flags & (FLG_MASK_SHOW | FLG_MASK_CALC)) != 0) &&
3916 	    ((flags & (FLG_MASK_SHOW_SHDR | FLG_MASK_CALC_SHDR)) == 0))
3917 		return (ret);
3918 
3919 	/*
3920 	 * If there are no section headers, then resort to synthesizing
3921 	 * section headers from the program headers. This is normally
3922 	 * only done by explicit request, but in this case there's no
3923 	 * reason not to go ahead, since the alternative is simply to quit.
3924 	 */
3925 	if ((shnum <= 1) && ((flags & FLG_CTL_FAKESHDR) == 0)) {
3926 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_NOSHDR), file);
3927 		flags |= FLG_CTL_FAKESHDR;
3928 	}
3929 
3930 	/*
3931 	 * Generate a cache of section headers and related information
3932 	 * for use by the rest of elfdump. If requested (or the file
3933 	 * contains no section headers), we generate a fake set of
3934 	 * headers from the information accessible from the program headers.
3935 	 * Otherwise, we use the real section headers contained in the file.
3936 	 */
3937 
3938 	if (flags & FLG_CTL_FAKESHDR) {
3939 		if (fake_shdr_cache(file, fd, elf, ehdr, &cache, &shnum) == 0)
3940 			return (ret);
3941 	} else {
3942 		if (shdr_cache(file, elf, ehdr, shstrndx, shnum,
3943 		    &cache, flags) == 0)
3944 			return (ret);
3945 	}
3946 
3947 	/*
3948 	 * Everything from this point on requires section headers.
3949 	 * If we have no section headers, there is no reason to continue.
3950 	 */
3951 	if (shnum <= 1)
3952 		goto done;
3953 
3954 	/*
3955 	 * If -w was specified, find and write out the section(s) data.
3956 	 */
3957 	if (wfd) {
3958 		for (ndx = 1; ndx < shnum; ndx++) {
3959 			Cache	*_cache = &cache[ndx];
3960 
3961 			if (match(MATCH_F_STRICT | MATCH_F_ALL, _cache->c_name,
3962 			    ndx, _cache->c_shdr->sh_type) &&
3963 			    _cache->c_data && _cache->c_data->d_buf) {
3964 				if (write(wfd, _cache->c_data->d_buf,
3965 				    _cache->c_data->d_size) !=
3966 				    _cache->c_data->d_size) {
3967 					int err = errno;
3968 					(void) fprintf(stderr,
3969 					    MSG_INTL(MSG_ERR_WRITE), wname,
3970 					    strerror(err));
3971 					/*
3972 					 * Return an exit status of 1, because
3973 					 * the failure is not related to the
3974 					 * ELF file, but by system resources.
3975 					 */
3976 					ret = 1;
3977 					goto done;
3978 				}
3979 			}
3980 		}
3981 	}
3982 
3983 	/*
3984 	 * If we have no flag bits set that explicitly require a show or calc
3985 	 * operation, but match options (-I, -N, -T) were used, then run
3986 	 * through the section headers and see if we can't deduce show flags
3987 	 * from the match options given.
3988 	 *
3989 	 * We don't do this if -w was specified, because (-I, -N, -T) used
3990 	 * with -w in lieu of some other option is supposed to be quiet.
3991 	 */
3992 	if ((wfd == 0) && (flags & FLG_CTL_MATCH) &&
3993 	    ((flags & (FLG_MASK_SHOW | FLG_MASK_CALC)) == 0)) {
3994 		for (ndx = 1; ndx < shnum; ndx++) {
3995 			Cache	*_cache = &cache[ndx];
3996 
3997 			if (!match(MATCH_F_STRICT | MATCH_F_ALL, _cache->c_name,
3998 			    ndx, _cache->c_shdr->sh_type))
3999 				continue;
4000 
4001 			switch (_cache->c_shdr->sh_type) {
4002 			case SHT_PROGBITS:
4003 				/*
4004 				 * Heuristic time: It is usually bad form
4005 				 * to assume that specific section names
4006 				 * have a given meaning. However, the
4007 				 * ELF ABI does specify a few such names. Try
4008 				 * to match them:
4009 				 */
4010 				if (strcmp(_cache->c_name,
4011 				    MSG_ORIG(MSG_ELF_INTERP)) == 0)
4012 					flags |= FLG_SHOW_INTERP;
4013 				else if (strcmp(_cache->c_name,
4014 				    MSG_ORIG(MSG_ELF_GOT)) == 0)
4015 					flags |= FLG_SHOW_GOT;
4016 				break;
4017 
4018 			case SHT_SYMTAB:
4019 			case SHT_DYNSYM:
4020 			case SHT_SUNW_LDYNSYM:
4021 			case SHT_SUNW_versym:
4022 			case SHT_SYMTAB_SHNDX:
4023 				flags |= FLG_SHOW_SYMBOLS;
4024 				break;
4025 
4026 			case SHT_RELA:
4027 			case SHT_REL:
4028 				flags |= FLG_SHOW_RELOC;
4029 				break;
4030 
4031 			case SHT_HASH:
4032 				flags |= FLG_SHOW_HASH;
4033 				break;
4034 
4035 			case SHT_DYNAMIC:
4036 				flags |= FLG_SHOW_DYNAMIC;
4037 				break;
4038 
4039 			case SHT_NOTE:
4040 				flags |= FLG_SHOW_NOTE;
4041 				break;
4042 
4043 			case SHT_GROUP:
4044 				flags |= FLG_SHOW_GROUP;
4045 				break;
4046 
4047 			case SHT_SUNW_symsort:
4048 			case SHT_SUNW_tlssort:
4049 				flags |= FLG_SHOW_SORT;
4050 				break;
4051 
4052 			case SHT_SUNW_cap:
4053 				flags |= FLG_SHOW_CAP;
4054 				break;
4055 
4056 			case SHT_SUNW_move:
4057 				flags |= FLG_SHOW_MOVE;
4058 				break;
4059 
4060 			case SHT_SUNW_syminfo:
4061 				flags |= FLG_SHOW_SYMINFO;
4062 				break;
4063 
4064 			case SHT_SUNW_verdef:
4065 			case SHT_SUNW_verneed:
4066 				flags |= FLG_SHOW_VERSIONS;
4067 				break;
4068 
4069 			case SHT_AMD64_UNWIND:
4070 				flags |= FLG_SHOW_UNWIND;
4071 				break;
4072 			}
4073 		}
4074 	}
4075 
4076 
4077 	if (flags & FLG_SHOW_SHDR)
4078 		sections(file, cache, shnum, ehdr);
4079 
4080 	if (flags & FLG_SHOW_INTERP)
4081 		interp(file, cache, shnum, phnum, elf);
4082 
4083 	versions(cache, shnum, file, flags, &versym);
4084 
4085 	if (flags & FLG_SHOW_SYMBOLS)
4086 		symbols(cache, shnum, ehdr, &versym, file, flags);
4087 
4088 	if (flags & FLG_SHOW_SORT)
4089 		sunw_sort(cache, shnum, ehdr, &versym, file, flags);
4090 
4091 	if (flags & FLG_SHOW_HASH)
4092 		hash(cache, shnum, file, flags);
4093 
4094 	if (flags & FLG_SHOW_GOT)
4095 		got(cache, shnum, ehdr, file);
4096 
4097 	if (flags & FLG_SHOW_GROUP)
4098 		group(cache, shnum, file, flags);
4099 
4100 	if (flags & FLG_SHOW_SYMINFO)
4101 		syminfo(cache, shnum, file);
4102 
4103 	if (flags & FLG_SHOW_RELOC)
4104 		reloc(cache, shnum, ehdr, file);
4105 
4106 	if (flags & FLG_SHOW_DYNAMIC)
4107 		dynamic(cache, shnum, ehdr, file);
4108 
4109 	if (flags & FLG_SHOW_NOTE) {
4110 		Word	note_cnt;
4111 		size_t	note_shnum;
4112 		Cache	*note_cache;
4113 
4114 		note_cnt = note(cache, shnum, ehdr, file);
4115 
4116 		/*
4117 		 * Solaris core files have section headers, but these
4118 		 * headers do not include SHT_NOTE sections that reference
4119 		 * the core note sections. This means that note() won't
4120 		 * find the core notes. Fake section headers (-P option)
4121 		 * recover these sections, but it is inconvenient to require
4122 		 * users to specify -P in this situation. If the following
4123 		 * are all true:
4124 		 *
4125 		 *	- No note sections were found
4126 		 *	- This is a core file
4127 		 *	- We are not already using fake section headers
4128 		 *
4129 		 * then we will automatically generate fake section headers
4130 		 * and then process them in a second call to note().
4131 		 */
4132 		if ((note_cnt == 0) && (ehdr->e_type == ET_CORE) &&
4133 		    !(flags & FLG_CTL_FAKESHDR) &&
4134 		    (fake_shdr_cache(file, fd, elf, ehdr,
4135 		    &note_cache, &note_shnum) != 0)) {
4136 			(void) note(note_cache, note_shnum, ehdr, file);
4137 			fake_shdr_cache_free(note_cache, note_shnum);
4138 		}
4139 	}
4140 
4141 	if (flags & FLG_SHOW_MOVE)
4142 		move(cache, shnum, file, flags);
4143 
4144 	if (flags & FLG_CALC_CHECKSUM)
4145 		checksum(elf);
4146 
4147 	if (flags & FLG_SHOW_CAP)
4148 		cap(file, cache, shnum, phnum, ehdr, elf);
4149 
4150 	if (flags & FLG_SHOW_UNWIND)
4151 		unwind(cache, shnum, phnum, ehdr, file, elf);
4152 
4153 
4154 	/* Release the memory used to cache section headers */
4155 done:
4156 	if (flags & FLG_CTL_FAKESHDR)
4157 		fake_shdr_cache_free(cache, shnum);
4158 	else
4159 		free(cache);
4160 
4161 	return (ret);
4162 }
4163