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 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Dump an elf file.
30  */
31 #include	<machdep.h>
32 #include	<sys/elf_386.h>
33 #include	<sys/elf_amd64.h>
34 #include	<sys/elf_SPARC.h>
35 #include	<dwarf.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 /*
47  * VERSYM_STATE is used to maintain information about the VERSYM section
48  * in the object being analyzed. It is filled in by versions(), and used
49  * by init_symtbl_state() when displaying symbol information.
50  *
51  * Note that the value of the gnu field is a hueristic guess,
52  * based on the section names.
53  */
54 typedef struct {
55 	Cache	*cache;		/* Pointer to cache entry for VERSYM */
56 	Versym	*data;		/* Pointer to versym array */
57 	int	num_verdef;	/* # of versions defined in object */
58 	int	gnu;		/* True if we think obj produced by GNU tools */
59 } VERSYM_STATE;
60 
61 /*
62  * SYMTBL_STATE is used to maintain information about a single symbol
63  * table section, for use by the routines that display symbol information.
64  */
65 typedef struct {
66 	const char	*file;		/* Name of file */
67 	Ehdr		*ehdr;		/* ELF header for file */
68 	Cache		*cache;		/* Cache of all section headers */
69 	Word		shnum;		/* # of sections in cache */
70 	Cache		*seccache;	/* Cache of symbol table section hdr */
71 	Word		secndx;		/* Index of symbol table section hdr */
72 	const char	*secname;	/* Name of section */
73 	uint_t		flags;		/* Command line option flags */
74 	struct {			/* Extended section index data */
75 		int	checked;	/* TRUE if already checked for shxndx */
76 		Word	*data;		/* NULL, or extended section index */
77 					/*	used for symbol table entries */
78 		uint_t	n;		/* # items in shxndx.data */
79 	} shxndx;
80 	VERSYM_STATE	*versym;	/* NULL, or associated VERSYM section */
81 	Sym 		*sym;		/* Array of symbols */
82 	Word		symn;		/* # of symbols */
83 } SYMTBL_STATE;
84 
85 
86 
87 /*
88  * Focal point for verifying symbol names.
89  */
90 static const char *
91 string(Cache *refsec, Word ndx, Cache *strsec, const char *file, Word name)
92 {
93 	/*
94 	 * If an error in this routine is due to a property of the string
95 	 * section, as opposed to a bad offset into the section (a property of
96 	 * the referencing section), then we will detect the same error on
97 	 * every call involving those sections. We use these static variables
98 	 * to retain the information needed to only issue each such error once.
99 	 */
100 	static Cache	*last_refsec;	/* Last referencing section seen */
101 	static int	strsec_err;	/* True if error issued */
102 
103 	const char	*strs;
104 	Word		strn;
105 
106 	if (strsec->c_data == NULL)
107 		return (NULL);
108 
109 	strs = (char *)strsec->c_data->d_buf;
110 	strn = strsec->c_data->d_size;
111 
112 	/*
113 	 * We only print a diagnostic regarding a bad string table once per
114 	 * input section being processed. If the refsec has changed, reset
115 	 * our retained error state.
116 	 */
117 	if (last_refsec != refsec) {
118 		last_refsec = refsec;
119 		strsec_err = 0;
120 	}
121 
122 	/* Verify that strsec really is a string table */
123 	if (strsec->c_shdr->sh_type != SHT_STRTAB) {
124 		if (!strsec_err) {
125 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_NOTSTRTAB),
126 			    file, strsec->c_ndx, refsec->c_ndx);
127 			strsec_err = 1;
128 		}
129 		return (MSG_INTL(MSG_STR_UNKNOWN));
130 	}
131 
132 	/*
133 	 * Is the string table offset within range of the available strings?
134 	 */
135 	if (name >= strn) {
136 		/*
137 		 * Do we have a empty string table?
138 		 */
139 		if (strs == 0) {
140 			if (!strsec_err) {
141 				(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
142 				    file, strsec->c_name);
143 				strsec_err = 1;
144 			}
145 		} else {
146 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSTOFF),
147 			    file, refsec->c_name, EC_WORD(ndx), strsec->c_name,
148 			    EC_WORD(name), EC_WORD(strn - 1));
149 		}
150 
151 		/*
152 		 * Return the empty string so that the calling function can
153 		 * continue it's output diagnostics.
154 		 */
155 		return (MSG_INTL(MSG_STR_UNKNOWN));
156 	}
157 	return (strs + name);
158 }
159 
160 /*
161  * Relocations can reference section symbols and standard symbols.  If the
162  * former, establish the section name.
163  */
164 static const char *
165 relsymname(Cache *cache, Cache *csec, Cache *strsec, Word symndx, Word symnum,
166     Word relndx, Sym *syms, char *secstr, size_t secsz, const char *file,
167     uint_t flags)
168 {
169 	Sym	*sym;
170 
171 	if (symndx >= symnum) {
172 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_RELBADSYMNDX),
173 		    file, EC_WORD(symndx), EC_WORD(relndx));
174 		return (MSG_INTL(MSG_STR_UNKNOWN));
175 	}
176 
177 	sym = (Sym *)(syms + symndx);
178 
179 	/*
180 	 * If the symbol represents a section offset construct an appropriate
181 	 * string.
182 	 */
183 	if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) && (sym->st_name == 0)) {
184 		if (flags & FLG_LONGNAME)
185 			(void) snprintf(secstr, secsz,
186 			    MSG_INTL(MSG_STR_L_SECTION),
187 			    cache[sym->st_shndx].c_name);
188 		else
189 			(void) snprintf(secstr, secsz,
190 			    MSG_INTL(MSG_STR_SECTION),
191 			    cache[sym->st_shndx].c_name);
192 		return ((const char *)secstr);
193 	}
194 
195 	return (string(csec, symndx, strsec, file, sym->st_name));
196 }
197 
198 /*
199  * Focal point for establishing a string table section.  Data such as the
200  * dynamic information simply points to a string table.  Data such as
201  * relocations, reference a symbol table, which in turn is associated with a
202  * string table.
203  */
204 static int
205 stringtbl(Cache *cache, int symtab, Word ndx, Word shnum, const char *file,
206     Word *symnum, Cache **symsec, Cache **strsec)
207 {
208 	Shdr	*shdr = cache[ndx].c_shdr;
209 
210 	if (symtab) {
211 		/*
212 		 * Validate the symbol table section.
213 		 */
214 		if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
215 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
216 			    file, cache[ndx].c_name, EC_WORD(shdr->sh_link));
217 			return (0);
218 		}
219 		if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
220 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
221 			    file, cache[ndx].c_name);
222 			return (0);
223 		}
224 
225 		/*
226 		 * Obtain, and verify the symbol table data.
227 		 */
228 		if ((cache[ndx].c_data == NULL) ||
229 		    (cache[ndx].c_data->d_buf == NULL)) {
230 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
231 			    file, cache[ndx].c_name);
232 			return (0);
233 		}
234 
235 		/*
236 		 * Establish the string table index.
237 		 */
238 		ndx = shdr->sh_link;
239 		shdr = cache[ndx].c_shdr;
240 
241 		/*
242 		 * Return symbol table information.
243 		 */
244 		if (symnum)
245 			*symnum = (shdr->sh_size / shdr->sh_entsize);
246 		if (symsec)
247 			*symsec = &cache[ndx];
248 	}
249 
250 	/*
251 	 * Validate the associated string table section.
252 	 */
253 	if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
254 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
255 		    file, cache[ndx].c_name, EC_WORD(shdr->sh_link));
256 		return (0);
257 	}
258 
259 	if (strsec)
260 		*strsec = &cache[shdr->sh_link];
261 
262 	return (1);
263 }
264 
265 /*
266  * Lookup a symbol and set Sym accordingly.
267  */
268 static int
269 symlookup(const char *name, Cache *cache, Word shnum, Sym **sym,
270     Cache *symtab, const char *file)
271 {
272 	Shdr	*shdr;
273 	Word	symn, cnt;
274 	Sym	*syms;
275 
276 	if (symtab == 0)
277 		return (0);
278 
279 	shdr = symtab->c_shdr;
280 
281 	/*
282 	 * Determine the symbol data and number.
283 	 */
284 	if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
285 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
286 		    file, symtab->c_name);
287 		return (0);
288 	}
289 	if (symtab->c_data == NULL)
290 		return (0);
291 
292 	/* LINTED */
293 	symn = (Word)(shdr->sh_size / shdr->sh_entsize);
294 	syms = (Sym *)symtab->c_data->d_buf;
295 
296 	/*
297 	 * Get the associated string table section.
298 	 */
299 	if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
300 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
301 		    file, symtab->c_name, EC_WORD(shdr->sh_link));
302 		return (0);
303 	}
304 
305 	/*
306 	 * Loop through the symbol table to find a match.
307 	 */
308 	for (cnt = 0; cnt < symn; syms++, cnt++) {
309 		const char	*symname;
310 
311 		symname = string(symtab, cnt, &cache[shdr->sh_link], file,
312 		    syms->st_name);
313 
314 		if (symname && (strcmp(name, symname) == 0)) {
315 			*sym = syms;
316 			return (1);
317 		}
318 	}
319 	return (0);
320 }
321 
322 /*
323  * Print section headers.
324  */
325 static void
326 sections(const char *file, Cache *cache, Word shnum, Ehdr *ehdr,
327     const char *name)
328 {
329 	size_t	seccnt;
330 
331 	for (seccnt = 1; seccnt < shnum; seccnt++) {
332 		Cache		*_cache = &cache[seccnt];
333 		Shdr		*shdr = _cache->c_shdr;
334 		const char	*secname = _cache->c_name;
335 
336 		/*
337 		 * Although numerous section header entries can be zero, it's
338 		 * usually a sign of trouble if the type is zero.
339 		 */
340 		if (shdr->sh_type == 0) {
341 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE),
342 			    file, secname, EC_WORD(shdr->sh_type));
343 		}
344 
345 		if (name && strcmp(name, secname))
346 			continue;
347 
348 		/*
349 		 * Identify any sections that are suspicious.  A .got section
350 		 * shouldn't exist in a relocatable object.
351 		 */
352 		if (ehdr->e_type == ET_REL) {
353 			if (strncmp(secname, MSG_ORIG(MSG_ELF_GOT),
354 			    MSG_ELF_GOT_SIZE) == 0) {
355 				(void) fprintf(stderr,
356 				    MSG_INTL(MSG_GOT_UNEXPECTED), file,
357 				    secname);
358 			}
359 		}
360 
361 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
362 		dbg_print(0, MSG_INTL(MSG_ELF_SHDR), EC_WORD(seccnt), secname);
363 		Elf_shdr(0, ehdr->e_machine, shdr);
364 	}
365 }
366 
367 /*
368  * A couple of instances of unwind data are printed as tables of 8 data items
369  * expressed as 0x?? integers.
370  */
371 #define	UNWINDTBLSZ	10 + (8 * 5) + 1
372 
373 static void
374 unwindtbl(uint64_t *ndx, uint_t len, uchar_t *data, uint64_t doff,
375     const char *msg, const char *pre, size_t plen)
376 {
377 	char	buffer[UNWINDTBLSZ];
378 	uint_t	boff = plen, cnt = 0;
379 
380 	dbg_print(0, msg);
381 	(void) strncpy(buffer, pre, UNWINDTBLSZ);
382 
383 	while (*ndx < (len + 4)) {
384 		if (cnt == 8) {
385 			dbg_print(0, buffer);
386 			boff = plen;
387 			cnt = 0;
388 		}
389 		(void) snprintf(&buffer[boff], UNWINDTBLSZ - boff,
390 		    MSG_ORIG(MSG_UNW_TBLENTRY), data[doff + (*ndx)++]);
391 		boff += 5;
392 		cnt++;
393 	}
394 	if (cnt)
395 		dbg_print(0, buffer);
396 }
397 
398 /*
399  * Obtain a specified Phdr entry.
400  */
401 static Phdr *
402 getphdr(Word phnum, Word type, const char *file, Elf *elf)
403 {
404 	Word	cnt;
405 	Phdr	*phdr;
406 
407 	if ((phdr = elf_getphdr(elf)) == NULL) {
408 		failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
409 		return (0);
410 	}
411 
412 	for (cnt = 0; cnt < phnum; phdr++, cnt++) {
413 		if (phdr->p_type == type)
414 			return (phdr);
415 	}
416 	return (0);
417 }
418 
419 static void
420 unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *name,
421     const char *file, Elf *elf)
422 {
423 	Word	cnt;
424 	Phdr	*uphdr = 0;
425 
426 	/*
427 	 * For the moment - UNWIND is only relevant for a AMD64 object.
428 	 */
429 	if (ehdr->e_machine != EM_AMD64)
430 		return;
431 
432 	if (phnum)
433 		uphdr = getphdr(phnum, PT_SUNW_UNWIND, file, elf);
434 
435 	for (cnt = 1; cnt < shnum; cnt++) {
436 		Cache		*_cache = &cache[cnt];
437 		Shdr		*shdr = _cache->c_shdr;
438 		uchar_t		*data;
439 		size_t		datasize;
440 		uint64_t	off, ndx, frame_ptr, fde_cnt, tabndx;
441 		uint_t		vers, frame_ptr_enc, fde_cnt_enc, table_enc;
442 
443 		/*
444 		 * AMD64 - this is a strmcp() just to find the gcc produced
445 		 * sections.  Soon gcc should be setting the section type - and
446 		 * we'll not need this strcmp().
447 		 */
448 		if ((shdr->sh_type != SHT_AMD64_UNWIND) &&
449 		    (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM),
450 		    MSG_SCN_FRM_SIZE) != 0) &&
451 		    (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR),
452 		    MSG_SCN_FRMHDR_SIZE) != 0))
453 			continue;
454 		if (name && strcmp(name, _cache->c_name))
455 			continue;
456 
457 		if (_cache->c_data == NULL)
458 			continue;
459 
460 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
461 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name);
462 
463 		data = (uchar_t *)(_cache->c_data->d_buf);
464 		datasize = _cache->c_data->d_size;
465 		off = 0;
466 
467 		/*
468 		 * Is this a .eh_frame_hdr
469 		 */
470 		if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) ||
471 		    (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR),
472 		    MSG_SCN_FRMHDR_SIZE) == 0)) {
473 
474 			dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR));
475 			ndx = 0;
476 
477 			vers = data[ndx++];
478 			frame_ptr_enc = data[ndx++];
479 			fde_cnt_enc = data[ndx++];
480 			table_enc = data[ndx++];
481 
482 			dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers);
483 
484 			frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc,
485 			    ehdr->e_ident, shdr->sh_addr + ndx);
486 
487 			dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC),
488 			    conv_dwarf_ehe(frame_ptr_enc), EC_XWORD(frame_ptr));
489 
490 			fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc,
491 			    ehdr->e_ident, shdr->sh_addr + ndx);
492 
493 			dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC),
494 			    conv_dwarf_ehe(fde_cnt_enc), EC_XWORD(fde_cnt));
495 			dbg_print(0, MSG_ORIG(MSG_UNW_TABENC),
496 			    conv_dwarf_ehe(table_enc));
497 			dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1));
498 			dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2));
499 
500 			for (tabndx = 0; tabndx < fde_cnt; tabndx++) {
501 				dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT),
502 				    EC_XWORD(dwarf_ehe_extract(data, &ndx,
503 				    table_enc, ehdr->e_ident, shdr->sh_addr)),
504 				    EC_XWORD(dwarf_ehe_extract(data, &ndx,
505 				    table_enc, ehdr->e_ident, shdr->sh_addr)));
506 			}
507 			continue;
508 		}
509 
510 		/*
511 		 * Walk the Eh_frame's
512 		 */
513 		while (off < datasize) {
514 			uint_t		cieid, cielength, cieversion,
515 					cieretaddr;
516 			int		cieRflag, cieLflag, ciePflag, cieZflag;
517 			uint_t		cieaugndx, length, id;
518 			uint64_t	ciecalign, ciedalign;
519 			char		*cieaugstr;
520 
521 			ndx = 0;
522 			/*
523 			 * extract length in lsb format
524 			 */
525 			length = LSB32EXTRACT(data + off + ndx);
526 			ndx += 4;
527 
528 			/*
529 			 * extract CIE id in lsb format
530 			 */
531 			id = LSB32EXTRACT(data + off + ndx);
532 			ndx += 4;
533 
534 			/*
535 			 * A CIE record has a id of '0', otherwise this is a
536 			 * FDE entry and the 'id' is the CIE pointer.
537 			 */
538 			if (id == 0) {
539 				uint64_t    persVal;
540 
541 				cielength = length;
542 				cieid = id;
543 				cieLflag = ciePflag = cieRflag = cieZflag = 0;
544 
545 				dbg_print(0, MSG_ORIG(MSG_UNW_CIE),
546 				    EC_XWORD(shdr->sh_addr + off));
547 				dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH),
548 				    cielength, cieid);
549 
550 				cieversion = data[off + ndx];
551 				ndx += 1;
552 				cieaugstr = (char *)(&data[off + ndx]);
553 				ndx += strlen(cieaugstr) + 1;
554 
555 				dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS),
556 				    cieversion, cieaugstr);
557 
558 				ciecalign = uleb_extract(&data[off], &ndx);
559 				ciedalign = sleb_extract(&data[off], &ndx);
560 				cieretaddr = data[off + ndx];
561 				ndx += 1;
562 
563 				dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN),
564 				    EC_XWORD(ciecalign), EC_XWORD(ciedalign),
565 				    cieretaddr);
566 
567 				if (cieaugstr[0])
568 				    dbg_print(0, MSG_ORIG(MSG_UNW_CIEAUXVAL));
569 
570 				for (cieaugndx = 0; cieaugstr[cieaugndx];
571 				    cieaugndx++) {
572 					uint_t	val;
573 
574 					switch (cieaugstr[cieaugndx]) {
575 					case 'z':
576 					    val = uleb_extract(&data[off],
577 						&ndx);
578 					    dbg_print(0,
579 						MSG_ORIG(MSG_UNW_CIEAUXSIZE),
580 						val);
581 					    cieZflag = 1;
582 					    break;
583 					case 'P':
584 					    ciePflag = data[off + ndx];
585 					    ndx += 1;
586 
587 					    persVal = dwarf_ehe_extract(
588 						&data[off],
589 						&ndx, ciePflag, ehdr->e_ident,
590 						shdr->sh_addr + off + ndx);
591 					    dbg_print(0,
592 						MSG_ORIG(MSG_UNW_CIEAUXPERS),
593 						ciePflag,
594 						conv_dwarf_ehe(ciePflag),
595 						EC_XWORD(persVal));
596 					    break;
597 					case 'R':
598 					    val = data[off + ndx];
599 					    ndx += 1;
600 					    dbg_print(0,
601 						MSG_ORIG(MSG_UNW_CIEAUXCENC),
602 						val, conv_dwarf_ehe(val));
603 					    cieRflag = val;
604 					    break;
605 					case 'L':
606 					    val = data[off + ndx];
607 					    ndx += 1;
608 					    dbg_print(0,
609 						MSG_ORIG(MSG_UNW_CIEAUXLSDA),
610 						val, conv_dwarf_ehe(val));
611 					    cieLflag = val;
612 					    break;
613 					default:
614 					    dbg_print(0,
615 						MSG_ORIG(MSG_UNW_CIEAUXUNEC),
616 						cieaugstr[cieaugndx]);
617 					    break;
618 					}
619 				}
620 				if ((cielength + 4) > ndx)
621 					unwindtbl(&ndx, cielength, data, off,
622 					    MSG_ORIG(MSG_UNW_CIECFI),
623 					    MSG_ORIG(MSG_UNW_CIEPRE),
624 					    MSG_UNW_CIEPRE_SIZE);
625 				off += cielength + 4;
626 
627 			} else {
628 				uint_t	    fdelength = length;
629 				int	    fdecieptr = id;
630 				uint64_t    fdeinitloc, fdeaddrrange;
631 
632 				dbg_print(0, MSG_ORIG(MSG_UNW_FDE),
633 				    EC_XWORD(shdr->sh_addr + off));
634 				dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH),
635 				    fdelength, fdecieptr);
636 
637 				fdeinitloc = dwarf_ehe_extract(&data[off],
638 				    &ndx, cieRflag, ehdr->e_ident,
639 				    shdr->sh_addr + off + ndx);
640 				fdeaddrrange = dwarf_ehe_extract(&data[off],
641 				    &ndx, (cieRflag & ~DW_EH_PE_pcrel),
642 				    ehdr->e_ident,
643 				    shdr->sh_addr + off + ndx);
644 
645 				dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC),
646 				    EC_XWORD(fdeinitloc),
647 				    EC_XWORD(fdeaddrrange));
648 
649 				if (cieaugstr[0])
650 					dbg_print(0,
651 					    MSG_ORIG(MSG_UNW_FDEAUXVAL));
652 				if (cieZflag) {
653 					uint64_t    val;
654 					val = uleb_extract(&data[off], &ndx);
655 					dbg_print(0,
656 					    MSG_ORIG(MSG_UNW_FDEAUXSIZE),
657 					    EC_XWORD(val));
658 					if (val & cieLflag) {
659 					    fdeinitloc = dwarf_ehe_extract(
660 						&data[off], &ndx, cieLflag,
661 						ehdr->e_ident,
662 						shdr->sh_addr + off + ndx);
663 					    dbg_print(0,
664 						MSG_ORIG(MSG_UNW_FDEAUXLSDA),
665 						EC_XWORD(val));
666 					}
667 				}
668 				if ((fdelength + 4) > ndx)
669 					unwindtbl(&ndx, fdelength, data, off,
670 					    MSG_ORIG(MSG_UNW_FDECFI),
671 					    MSG_ORIG(MSG_UNW_FDEPRE),
672 					    MSG_UNW_FDEPRE_SIZE);
673 				off += fdelength + 4;
674 			}
675 		}
676 	}
677 }
678 
679 /*
680  * Print the hardware/software capabilities.  For executables and shared objects
681  * this should be accompanied with a program header.
682  */
683 static void
684 cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr,
685     Elf *elf)
686 {
687 	Word		cnt;
688 	Shdr		*cshdr = 0;
689 	Cache		*ccache;
690 	Off		cphdr_off = 0;
691 	Xword		cphdr_sz;
692 
693 	/*
694 	 * Determine if a hardware/software capabilities header exists.
695 	 */
696 	if (phnum) {
697 		Phdr	*phdr;
698 
699 		if ((phdr = elf_getphdr(elf)) == NULL) {
700 			failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
701 			return;
702 		}
703 
704 		for (cnt = 0; cnt < phnum; phdr++, cnt++) {
705 			if (phdr->p_type == PT_SUNWCAP) {
706 				cphdr_off = phdr->p_offset;
707 				cphdr_sz = phdr->p_filesz;
708 				break;
709 			}
710 		}
711 	}
712 
713 	/*
714 	 * Determine if a hardware/software capabilities section exists.
715 	 */
716 	for (cnt = 1; cnt < shnum; cnt++) {
717 		Cache	*_cache = &cache[cnt];
718 		Shdr	*shdr = _cache->c_shdr;
719 
720 		if (shdr->sh_type != SHT_SUNW_cap)
721 			continue;
722 
723 		if (cphdr_off && ((cphdr_off < shdr->sh_offset) ||
724 		    (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size)))
725 			continue;
726 
727 		if (_cache->c_data == NULL)
728 			continue;
729 
730 		ccache = _cache;
731 		cshdr = shdr;
732 		break;
733 	}
734 
735 	if ((cshdr == 0) && (cphdr_off == 0))
736 		return;
737 
738 	if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) {
739 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
740 		    file, ccache->c_name);
741 		return;
742 	}
743 
744 	/*
745 	 * Print the hardware/software capabilities section.
746 	 */
747 	if (cshdr) {
748 		Word	ndx, capn;
749 		Cap	*cap = (Cap *)ccache->c_data->d_buf;
750 
751 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
752 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name);
753 
754 		Elf_cap_title(0);
755 
756 		capn = (Word)(cshdr->sh_size / cshdr->sh_entsize);
757 
758 		for (ndx = 0; ndx < capn; cap++, ndx++) {
759 			if (cap->c_tag != CA_SUNW_NULL)
760 				Elf_cap_entry(0, cap, ndx, ehdr->e_machine);
761 		}
762 	} else
763 		(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file);
764 
765 	/*
766 	 * If this object is an executable or shared object, then the
767 	 * hardware/software capabilities section should have an accompanying
768 	 * program header.
769 	 */
770 	if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) {
771 		if (cphdr_off == 0)
772 			(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2),
773 			    file, ccache->c_name);
774 		else if ((cphdr_off != cshdr->sh_offset) ||
775 		    (cphdr_sz != cshdr->sh_size))
776 			(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3),
777 			    file, ccache->c_name);
778 	}
779 }
780 
781 /*
782  * Print the interpretor.
783  */
784 static void
785 interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf)
786 {
787 	Word	cnt;
788 	Shdr	*ishdr = 0;
789 	Cache	*icache;
790 	Off	iphdr_off = 0;
791 	Xword	iphdr_fsz;
792 
793 	/*
794 	 * Determine if an interp header exists.
795 	 */
796 	if (phnum) {
797 		Phdr	*phdr;
798 
799 		if ((phdr = getphdr(phnum, PT_INTERP, file, elf)) != 0) {
800 			iphdr_off = phdr->p_offset;
801 			iphdr_fsz = phdr->p_filesz;
802 		}
803 	}
804 
805 	if (iphdr_off == 0)
806 		return;
807 
808 	/*
809 	 * Determine if an interp section exists.
810 	 */
811 	for (cnt = 1; cnt < shnum; cnt++) {
812 		Cache	*_cache = &cache[cnt];
813 		Shdr	*shdr = _cache->c_shdr;
814 
815 		/*
816 		 * Scan sections to find a section which contains the PT_INTERP
817 		 * string.  The target section can't be in a NOBITS section.
818 		 */
819 		if ((shdr->sh_type == SHT_NOBITS) ||
820 		    (iphdr_off < shdr->sh_offset) ||
821 		    (iphdr_off + iphdr_fsz) > (shdr->sh_offset + shdr->sh_size))
822 			continue;
823 
824 		icache = _cache;
825 		ishdr = shdr;
826 		break;
827 	}
828 
829 	/*
830 	 * Print the interpreter string based on the offset defined in the
831 	 * program header, as this is the offset used by the kernel.
832 	 */
833 	if (ishdr && icache->c_data) {
834 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
835 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name);
836 		dbg_print(0, MSG_ORIG(MSG_FMT_INDENT),
837 		    (char *)icache->c_data->d_buf +
838 		    (iphdr_off - ishdr->sh_offset));
839 	} else
840 		(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file);
841 
842 	/*
843 	 * If there are any inconsistences between the program header and
844 	 * section information, flag them.
845 	 */
846 	if (ishdr && ((iphdr_off != ishdr->sh_offset) ||
847 	    (iphdr_fsz != ishdr->sh_size))) {
848 		(void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file,
849 		    icache->c_name);
850 	}
851 }
852 
853 /*
854  * Print the syminfo section.
855  */
856 static void
857 syminfo(Cache *cache, Word shnum, const char *file)
858 {
859 	Shdr		*infoshdr;
860 	Syminfo		*info;
861 	Sym		*syms;
862 	Dyn		*dyns;
863 	Word		infonum, cnt, ndx, symnum;
864 	Cache		*infocache = 0, *symsec, *strsec;
865 
866 	for (cnt = 1; cnt < shnum; cnt++) {
867 		if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) {
868 			infocache = &cache[cnt];
869 			break;
870 		}
871 	}
872 	if (infocache == 0)
873 		return;
874 
875 	infoshdr = infocache->c_shdr;
876 	if ((infoshdr->sh_entsize == 0) || (infoshdr->sh_size == 0)) {
877 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
878 		    file, infocache->c_name);
879 		return;
880 	}
881 	if (infocache->c_data == NULL)
882 		return;
883 
884 	infonum = (Word)(infoshdr->sh_size / infoshdr->sh_entsize);
885 	info = (Syminfo *)infocache->c_data->d_buf;
886 
887 	/*
888 	 * Get the data buffer of the associated dynamic section.
889 	 */
890 	if ((infoshdr->sh_info == 0) || (infoshdr->sh_info >= shnum)) {
891 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO),
892 		    file, infocache->c_name, EC_WORD(infoshdr->sh_info));
893 		return;
894 	}
895 	if (cache[infoshdr->sh_info].c_data == NULL)
896 		return;
897 
898 	dyns = cache[infoshdr->sh_info].c_data->d_buf;
899 	if (dyns == 0) {
900 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
901 		    file, cache[infoshdr->sh_info].c_name);
902 		return;
903 	}
904 
905 	/*
906 	 * Get the data buffer for the associated symbol table and string table.
907 	 */
908 	if (stringtbl(cache, 1, cnt, shnum, file,
909 	    &symnum, &symsec, &strsec) == 0)
910 		return;
911 
912 	syms = symsec->c_data->d_buf;
913 
914 	/*
915 	 * Loop through the syminfo entries.
916 	 */
917 	dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
918 	dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMINFO), infocache->c_name);
919 	Elf_syminfo_title(0);
920 
921 	for (ndx = 1, info++; ndx < infonum; ndx++, info++) {
922 		Sym 		*sym;
923 		const char	*needed = 0, *name;
924 
925 		if ((info->si_flags == 0) && (info->si_boundto == 0))
926 			continue;
927 
928 		sym = &syms[ndx];
929 		name = string(infocache, ndx, strsec, file, sym->st_name);
930 
931 		if (info->si_boundto < SYMINFO_BT_LOWRESERVE) {
932 			Dyn	*dyn = &dyns[info->si_boundto];
933 
934 			needed = string(infocache, info->si_boundto,
935 			    strsec, file, dyn->d_un.d_val);
936 		}
937 		Elf_syminfo_entry(0, ndx, info, name, needed);
938 	}
939 }
940 
941 /*
942  * Print version definition section entries.
943  */
944 static void
945 version_def(Verdef *vdf, Word shnum, Cache *vcache, Cache *scache,
946     const char *file)
947 {
948 	Word	cnt;
949 	char	index[MAXNDXSIZE];
950 
951 	Elf_ver_def_title(0);
952 
953 	for (cnt = 1; cnt <= shnum; cnt++,
954 	    vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) {
955 		const char	*name, *dep;
956 		Half		vcnt = vdf->vd_cnt - 1;
957 		Half		ndx = vdf->vd_ndx;
958 		Verdaux		*vdap = (Verdaux *)((uintptr_t)vdf +
959 				    vdf->vd_aux);
960 
961 		/*
962 		 * Obtain the name and first dependency (if any).
963 		 */
964 		name = string(vcache, cnt, scache, file, vdap->vda_name);
965 		vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
966 		if (vcnt)
967 			dep = string(vcache, cnt, scache, file, vdap->vda_name);
968 		else
969 			dep = MSG_ORIG(MSG_STR_EMPTY);
970 
971 		(void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX),
972 		    EC_XWORD(ndx));
973 		Elf_ver_line_1(0, index, name, dep,
974 		    conv_ver_flags(vdf->vd_flags));
975 
976 		/*
977 		 * Print any additional dependencies.
978 		 */
979 		if (vcnt) {
980 			vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
981 			for (vcnt--; vcnt; vcnt--,
982 			    vdap = (Verdaux *)((uintptr_t)vdap +
983 			    vdap->vda_next)) {
984 				dep = string(vcache, cnt, scache, file,
985 				    vdap->vda_name);
986 				Elf_ver_line_2(0, MSG_ORIG(MSG_STR_EMPTY), dep);
987 			}
988 		}
989 	}
990 }
991 
992 /*
993  * Print a version needed section entries.
994  */
995 static void
996 version_need(Verneed *vnd, Word shnum, Cache *vcache, Cache *scache,
997     const char *file)
998 {
999 	Word	cnt;
1000 
1001 	Elf_ver_need_title(0);
1002 
1003 	for (cnt = 1; cnt <= shnum; cnt++,
1004 	    vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) {
1005 		const char	*name, *dep;
1006 		Half		vcnt = vnd->vn_cnt;
1007 		Vernaux		*vnap = (Vernaux *)((uintptr_t)vnd +
1008 					vnd->vn_aux);
1009 
1010 		/*
1011 		 * Obtain the name of the needed file and the version name
1012 		 * within it that we're dependent on.  Note that the count
1013 		 * should be at least one, otherwise this is a pretty bogus
1014 		 * entry.
1015 		 */
1016 		name = string(vcache, cnt, scache, file, vnd->vn_file);
1017 		if (vcnt)
1018 			dep = string(vcache, cnt, scache, file, vnap->vna_name);
1019 		else
1020 			dep = MSG_INTL(MSG_STR_NULL);
1021 
1022 		Elf_ver_line_1(0, MSG_ORIG(MSG_STR_EMPTY), name, dep,
1023 		    conv_ver_flags(vnap->vna_flags));
1024 
1025 		/*
1026 		 * Print any additional version dependencies.
1027 		 */
1028 		if (vcnt) {
1029 			vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next);
1030 			for (vcnt--; vcnt; vcnt--,
1031 			    vnap = (Vernaux *)((uintptr_t)vnap +
1032 			    vnap->vna_next)) {
1033 				dep = string(vcache, cnt, scache, file,
1034 				    vnap->vna_name);
1035 				Elf_ver_line_3(0, MSG_ORIG(MSG_STR_EMPTY), dep,
1036 				    conv_ver_flags(vnap->vna_flags));
1037 			}
1038 		}
1039 	}
1040 }
1041 
1042 /*
1043  * Display version section information if the flags require it.
1044  * Return version information needed by other output.
1045  *
1046  * entry:
1047  *	cache - Cache of all section headers
1048  *	shnum - # of sections in cache
1049  *	file - Name of file
1050  *	flags - Command line option flags
1051  *	versym - VERSYM_STATE block to be filled in.
1052  */
1053 static void
1054 versions(Cache *cache, Word shnum, const char *file, uint_t flags,
1055     VERSYM_STATE *versym)
1056 {
1057 	GElf_Word	cnt;
1058 	const char	*gnu_prefix;
1059 	size_t		gnu_prefix_len;
1060 
1061 	bzero(versym, sizeof (*versym));
1062 	gnu_prefix = MSG_ORIG(MSG_GNU_VERNAMPREFIX);
1063 	gnu_prefix_len = strlen(gnu_prefix);
1064 
1065 	for (cnt = 1; cnt < shnum; cnt++) {
1066 		void		*ver;
1067 		uint_t		num;
1068 		Cache		*_cache = &cache[cnt];
1069 		Shdr		*shdr = _cache->c_shdr;
1070 		const char	*secname = _cache->c_name;
1071 
1072 		/*
1073 		 * If the section names starts with the .gnu.version prefix,
1074 		 * then this object was almost certainly produced by the
1075 		 * GNU ld and not the native Solaris ld.
1076 		 */
1077 		if (strncmp(gnu_prefix, secname, gnu_prefix_len) == 0)
1078 			versym->gnu = 1;
1079 
1080 		/*
1081 		 * If this is the version symbol table record its data
1082 		 * address for later symbol processing.
1083 		 */
1084 		if ((shdr->sh_type == SHT_SUNW_versym) &&
1085 		    (_cache->c_data != NULL)) {
1086 			versym->cache = _cache;
1087 			versym->data = _cache->c_data->d_buf;
1088 			continue;
1089 		}
1090 
1091 		/*
1092 		 * If this is a version definition section, retain # of
1093 		 * version definitions for later symbol processing.
1094 		 */
1095 		if (shdr->sh_type == SHT_SUNW_verdef)
1096 			versym->num_verdef = shdr->sh_info;
1097 
1098 		if ((flags & FLG_VERSIONS) == 0)
1099 			continue;
1100 
1101 		if ((shdr->sh_type != SHT_SUNW_verdef) &&
1102 		    (shdr->sh_type != SHT_SUNW_verneed))
1103 			continue;
1104 
1105 		/*
1106 		 * Determine the version section data and number.
1107 		 */
1108 		if ((_cache->c_data == NULL) ||
1109 		    ((ver = (void *)_cache->c_data->d_buf) == NULL)) {
1110 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1111 			    file, secname);
1112 			continue;
1113 		}
1114 		if ((num = shdr->sh_info) == 0) {
1115 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO),
1116 			    file, secname, EC_WORD(shdr->sh_info));
1117 			continue;
1118 		}
1119 
1120 		/*
1121 		 * Get the data buffer for the associated string table.
1122 		 */
1123 		if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
1124 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
1125 			    file, secname, EC_WORD(shdr->sh_link));
1126 			continue;
1127 		}
1128 
1129 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1130 		if (shdr->sh_type == SHT_SUNW_verdef) {
1131 			dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERDEF), secname);
1132 			version_def((Verdef *)ver, num, _cache,
1133 			    &cache[shdr->sh_link], file);
1134 		} else if (shdr->sh_type == SHT_SUNW_verneed) {
1135 			dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERNEED), secname);
1136 			version_need((Verneed *)ver, num, _cache,
1137 			    &cache[shdr->sh_link], file);
1138 		}
1139 	}
1140 }
1141 
1142 /*
1143  * Initialize a symbol table state structure
1144  *
1145  * entry:
1146  *	state - State structure to be initialized
1147  *	cache - Cache of all section headers
1148  *	shnum - # of sections in cache
1149  *	secndx - Index of symbol table section
1150  *	ehdr - ELF header for file
1151  *	versym - Information about versym section
1152  *	file - Name of file
1153  *	flags - Command line option flags
1154  */
1155 static int
1156 init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx,
1157     Ehdr *ehdr, VERSYM_STATE *versym, const char *file, uint_t flags)
1158 {
1159 	Shdr *shdr;
1160 
1161 	state->file = file;
1162 	state->ehdr = ehdr;
1163 	state->cache = cache;
1164 	state->shnum = shnum;
1165 	state->seccache = &cache[secndx];
1166 	state->secndx = secndx;
1167 	state->secname = state->seccache->c_name;
1168 	state->flags = flags;
1169 	state->shxndx.checked = 0;
1170 	state->shxndx.data = NULL;
1171 	state->shxndx.n = 0;
1172 
1173 	shdr = state->seccache->c_shdr;
1174 
1175 	/*
1176 	 * Check the symbol data and per-item size.
1177 	 */
1178 	if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
1179 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1180 		    file, state->secname);
1181 		return (0);
1182 	}
1183 	if (state->seccache->c_data == NULL)
1184 		return (0);
1185 
1186 	/* LINTED */
1187 	state->symn = (Word)(shdr->sh_size / shdr->sh_entsize);
1188 	state->sym = (Sym *)state->seccache->c_data->d_buf;
1189 
1190 	/*
1191 	 * Check associated string table section.
1192 	 */
1193 	if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
1194 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
1195 		    file, state->secname, EC_WORD(shdr->sh_link));
1196 		return (0);
1197 	}
1198 
1199 	/*
1200 	 * Determine if there is a associated Versym section
1201 	 * with this Symbol Table.
1202 	 */
1203 	if (versym->cache &&
1204 	    (versym->cache->c_shdr->sh_link == state->secndx))
1205 		state->versym = versym;
1206 	else
1207 		state->versym = NULL;
1208 
1209 
1210 	return (1);
1211 }
1212 
1213 /*
1214  * Determine the extended section index used for symbol tables entries.
1215  */
1216 static void
1217 symbols_getxindex(SYMTBL_STATE * state)
1218 {
1219 	uint_t	symn;
1220 	Word	symcnt;
1221 
1222 	state->shxndx.checked = 1;   /* Note that we've been called */
1223 	for (symcnt = 1; symcnt < state->shnum; symcnt++) {
1224 		Cache	*_cache = &state->cache[symcnt];
1225 		Shdr	*shdr = _cache->c_shdr;
1226 
1227 		if ((shdr->sh_type != SHT_SYMTAB_SHNDX) ||
1228 		    (shdr->sh_link != state->secndx))
1229 			continue;
1230 
1231 		if ((shdr->sh_entsize) &&
1232 		    /* LINTED */
1233 		    ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0))
1234 			continue;
1235 
1236 		if (_cache->c_data == NULL)
1237 			continue;
1238 
1239 		state->shxndx.data = _cache->c_data->d_buf;
1240 		state->shxndx.n = symn;
1241 		return;
1242 	}
1243 }
1244 
1245 /*
1246  * Produce a line of output for the given symbol
1247  *
1248  * entry:
1249  *	state - Symbol table state
1250  *	symndx - Index of symbol within the table
1251  *	symndx_disp - Index to display. This may not be the same
1252  *		as symndx if the display is relative to the logical
1253  *		combination of the SUNW_ldynsym/dynsym tables.
1254  *	sym - Symbol to display
1255  */
1256 static void
1257 output_symbol(SYMTBL_STATE *state, Word symndx, Word disp_symndx, Sym *sym)
1258 {
1259 	/*
1260 	 * Symbol types for which we check that the specified
1261 	 * address/size land inside the target section.
1262 	 */
1263 	static const int addr_symtype[STT_NUM] = {
1264 		0,			/* STT_NOTYPE */
1265 		1,			/* STT_OBJECT */
1266 		1,			/* STT_FUNC */
1267 		0,			/* STT_SECTION */
1268 		0,			/* STT_FILE */
1269 		1,			/* STT_COMMON */
1270 		0,			/* STT_TLS */
1271 	};
1272 #if STT_NUM != (STT_TLS + 1)
1273 #error "STT_NUM has grown. Update addr_symtype[]"
1274 #endif
1275 
1276 	char		index[MAXNDXSIZE], *sec;
1277 	const char	*symname;
1278 	Versym		verndx;
1279 	uchar_t		type;
1280 	Shdr		*tshdr;
1281 	Word		shndx;
1282 
1283 	/* Ensure symbol index is in range */
1284 	if (symndx >= state->symn) {
1285 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORTNDX),
1286 		    state->file, state->secname, EC_WORD(symndx));
1287 		return;
1288 	}
1289 
1290 	/*
1291 	 * If we are using extended symbol indexes, find the
1292 	 * corresponding SHN_SYMTAB_SHNDX table.
1293 	 */
1294 	if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0))
1295 		symbols_getxindex(state);
1296 
1297 	/* LINTED */
1298 	symname = string(state->seccache, symndx,
1299 	    &state->cache[state->seccache->c_shdr->sh_link], state->file,
1300 	    sym->st_name);
1301 
1302 	tshdr = 0;
1303 	sec = NULL;
1304 
1305 	if ((state->ehdr->e_type == ET_CORE))
1306 		sec = (char *)MSG_INTL(MSG_STR_UNKNOWN);
1307 	else if ((sym->st_shndx < SHN_LORESERVE) &&
1308 	    (sym->st_shndx < state->shnum)) {
1309 		shndx = sym->st_shndx;
1310 		tshdr = state->cache[shndx].c_shdr;
1311 		sec = state->cache[shndx].c_name;
1312 	} else if (sym->st_shndx == SHN_XINDEX) {
1313 		if (state->shxndx.data) {
1314 			Word	_shxndx;
1315 
1316 			if (symndx > state->shxndx.n) {
1317 			    (void) fprintf(stderr,
1318 				MSG_INTL(MSG_ERR_BADSYMXINDEX1),
1319 				state->file, state->secname, EC_WORD(symndx));
1320 			} else if ((_shxndx =
1321 			    state->shxndx.data[symndx]) > state->shnum) {
1322 			    (void) fprintf(stderr,
1323 				MSG_INTL(MSG_ERR_BADSYMXINDEX2),
1324 				state->file, state->secname, EC_WORD(symndx),
1325 				EC_WORD(_shxndx));
1326 			} else {
1327 			    shndx = _shxndx;
1328 			    tshdr = state->cache[shndx].c_shdr;
1329 			    sec = state->cache[shndx].c_name;
1330 			}
1331 		} else {
1332 			(void) fprintf(stderr,
1333 			    MSG_INTL(MSG_ERR_BADSYMXINDEX3),
1334 			    state->file, state->secname, EC_WORD(symndx));
1335 		}
1336 	} else if ((sym->st_shndx < SHN_LORESERVE) &&
1337 	    (sym->st_shndx >= state->shnum)) {
1338 		(void) fprintf(stderr,
1339 		    MSG_INTL(MSG_ERR_BADSYM5), state->file,
1340 		    state->secname, demangle(symname, state->flags),
1341 		    sym->st_shndx);
1342 	}
1343 
1344 	/*
1345 	 * If versioning is available display the
1346 	 * version index. If not, then use 0.
1347 	 */
1348 	if (state->versym) {
1349 		verndx = state->versym->data[symndx];
1350 
1351 		/*
1352 		 * Check to see if this is a defined symbol with a
1353 		 * version index that is outside the valid range for
1354 		 * the file. If so, then there are two possiblities:
1355 		 *
1356 		 *	- Files produced by the GNU ld use the top (16th) bit
1357 		 *		as a "hidden symbol" marker. If we have
1358 		 *		detected that this object comes from GNU ld,
1359 		 *		then check to see if this is the case and that
1360 		 *		the resulting masked version is in range. If so,
1361 		 *		issue a warning describing it.
1362 		 *	- If this is not a GNU "hidden bit" issue, then
1363 		 *		issue a generic "out of range" error.
1364 		 */
1365 		if (VERNDX_INVALID(sym->st_shndx, state->versym->num_verdef,
1366 		    state->versym->data, verndx)) {
1367 			if (state->versym->gnu && (verndx & 0x8000) &&
1368 			    ((verndx & ~0x8000) <=
1369 			    state->versym->num_verdef)) {
1370 				(void) fprintf(stderr,
1371 				    MSG_INTL(MSG_WARN_GNUVER), state->file,
1372 				    state->secname, EC_WORD(symndx),
1373 				    EC_HALF(verndx & ~0x8000));
1374 			} else {	/* Generic version range error */
1375 				(void) fprintf(stderr,
1376 				    MSG_INTL(MSG_ERR_BADVER), state->file,
1377 				    state->secname, EC_WORD(symndx),
1378 				    EC_HALF(verndx), state->versym->num_verdef);
1379 			}
1380 		}
1381 	} else {
1382 		verndx = 0;
1383 	}
1384 
1385 	/*
1386 	 * Error checking for TLS.
1387 	 */
1388 	type = ELF_ST_TYPE(sym->st_info);
1389 	if (type == STT_TLS) {
1390 		if (tshdr &&
1391 		    (sym->st_shndx != SHN_UNDEF) &&
1392 		    ((tshdr->sh_flags & SHF_TLS) == 0)) {
1393 			(void) fprintf(stderr,
1394 			    MSG_INTL(MSG_ERR_BADSYM3), state->file,
1395 			    state->secname, demangle(symname, state->flags));
1396 		}
1397 	} else if ((type != STT_SECTION) && sym->st_size &&
1398 	    tshdr && (tshdr->sh_flags & SHF_TLS)) {
1399 		(void) fprintf(stderr,
1400 		    MSG_INTL(MSG_ERR_BADSYM4), state->file,
1401 		    state->secname, demangle(symname, state->flags));
1402 	}
1403 
1404 	/*
1405 	 * If a symbol with non-zero size has a type that
1406 	 * specifies an address, then make sure the location
1407 	 * it references is actually contained within the
1408 	 * section.  UNDEF symbols don't count in this case,
1409 	 * so we ignore them.
1410 	 *
1411 	 * The meaning of the st_value field in a symbol
1412 	 * depends on the type of object. For a relocatable
1413 	 * object, it is the offset within the section.
1414 	 * For sharable objects, it is the offset relative to
1415 	 * the base of the object, and for other types, it is
1416 	 * the virtual address. To get an offset within the
1417 	 * section for non-ET_REL files, we subtract the
1418 	 * base address of the section.
1419 	 */
1420 	if (addr_symtype[type] && (sym->st_size > 0) &&
1421 	    (sym->st_shndx != SHN_UNDEF) && ((sym->st_shndx < SHN_LORESERVE) ||
1422 	    (sym->st_shndx == SHN_XINDEX)) && (tshdr != NULL)) {
1423 		Word v = sym->st_value;
1424 			if (state->ehdr->e_type != ET_REL)
1425 			v -= tshdr->sh_addr;
1426 		if (((v + sym->st_size) > tshdr->sh_size)) {
1427 			(void) fprintf(stderr,
1428 			    MSG_INTL(MSG_ERR_BADSYM6), state->file,
1429 			    state->secname, demangle(symname, state->flags),
1430 			    EC_WORD(shndx), EC_XWORD(tshdr->sh_size),
1431 			    EC_XWORD(sym->st_value), EC_XWORD(sym->st_size));
1432 		}
1433 	}
1434 
1435 	(void) snprintf(index, MAXNDXSIZE,
1436 	    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(disp_symndx));
1437 	Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index,
1438 	    state->ehdr->e_machine, sym, verndx, sec, symname);
1439 }
1440 
1441 /*
1442  * Search for and process any symbol tables.
1443  */
1444 void
1445 symbols(Cache *cache, Word shnum, Ehdr *ehdr, const char *name,
1446     VERSYM_STATE *versym, const char *file, uint_t flags)
1447 {
1448 	SYMTBL_STATE state;
1449 	Cache *_cache;
1450 	Word secndx;
1451 
1452 	for (secndx = 1; secndx < shnum; secndx++) {
1453 		Word		symcnt;
1454 		Shdr		*shdr;
1455 
1456 		_cache = &cache[secndx];
1457 		shdr = _cache->c_shdr;
1458 
1459 		if ((shdr->sh_type != SHT_SYMTAB) &&
1460 		    (shdr->sh_type != SHT_DYNSYM) &&
1461 		    (shdr->sh_type != SHT_SUNW_LDYNSYM))
1462 			continue;
1463 		if (name && strcmp(name, _cache->c_name))
1464 			continue;
1465 
1466 		if (!init_symtbl_state(&state, cache, shnum, secndx, ehdr,
1467 		    versym, file, flags))
1468 			continue;
1469 		/*
1470 		 * Loop through the symbol tables entries.
1471 		 */
1472 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1473 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), state.secname);
1474 		Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
1475 
1476 		for (symcnt = 0; symcnt < state.symn; symcnt++)
1477 			output_symbol(&state, symcnt, symcnt,
1478 			    state.sym + symcnt);
1479 	}
1480 }
1481 
1482 /*
1483  * Search for and process any SHT_SUNW_symsort or SHT_SUNW_tlssort sections.
1484  * These sections are always associated with the .SUNW_ldynsym./.dynsym pair.
1485  */
1486 static void
1487 sunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, const char *name,
1488     VERSYM_STATE *versym, const char *file, uint_t flags)
1489 {
1490 	SYMTBL_STATE	ldynsym_state,	dynsym_state;
1491 	Cache		*sortcache,	*symcache;
1492 	Shdr		*sortshdr,	*symshdr;
1493 	Word		sortsecndx,	symsecndx;
1494 	Word		ldynsym_cnt;
1495 	Word		*ndx;
1496 	Word		ndxn;
1497 	int		output_cnt = 0;
1498 
1499 	for (sortsecndx = 1; sortsecndx < shnum; sortsecndx++) {
1500 
1501 		sortcache = &cache[sortsecndx];
1502 		sortshdr = sortcache->c_shdr;
1503 
1504 		if ((sortshdr->sh_type != SHT_SUNW_symsort) &&
1505 		    (sortshdr->sh_type != SHT_SUNW_tlssort))
1506 			continue;
1507 		if (name && strcmp(name, sortcache->c_name))
1508 			continue;
1509 
1510 		/*
1511 		 * If the section references a SUNW_ldynsym, then we
1512 		 * expect to see the associated .dynsym immediately
1513 		 * following. If it references a .dynsym, there is no
1514 		 * SUNW_ldynsym. If it is any other type, then we don't
1515 		 * know what to do with it.
1516 		 */
1517 		if ((sortshdr->sh_link == 0) || (sortshdr->sh_link >= shnum)) {
1518 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
1519 			    file, sortcache->c_name,
1520 			    EC_WORD(sortshdr->sh_link));
1521 			continue;
1522 		}
1523 		symcache = &cache[sortshdr->sh_link];
1524 		symshdr = symcache->c_shdr;
1525 		symsecndx = sortshdr->sh_link;
1526 		ldynsym_cnt = 0;
1527 		switch (symshdr->sh_type) {
1528 		case SHT_SUNW_LDYNSYM:
1529 			if (!init_symtbl_state(&ldynsym_state, cache, shnum,
1530 			    symsecndx, ehdr, versym, file, flags))
1531 				continue;
1532 			ldynsym_cnt = ldynsym_state.symn;
1533 			/*
1534 			 * We know that the dynsym follows immediately
1535 			 * after the SUNW_ldynsym, and so, should be at
1536 			 * (sortshdr->sh_link + 1). However, elfdump is a
1537 			 * diagnostic tool, so we do the full paranoid
1538 			 * search instead.
1539 			 */
1540 			for (symsecndx = 1; symsecndx < shnum; symsecndx++) {
1541 				symcache = &cache[symsecndx];
1542 				symshdr = symcache->c_shdr;
1543 				if (symshdr->sh_type == SHT_DYNSYM)
1544 					break;
1545 			}
1546 			if (symsecndx >= shnum) {	/* Dynsym not found! */
1547 				(void) fprintf(stderr,
1548 				    MSG_INTL(MSG_ERR_NODYNSYM),
1549 				    file, sortcache->c_name);
1550 				continue;
1551 			}
1552 			/* Fallthrough to process associated dynsym */
1553 			/*FALLTHROUGH*/
1554 		case SHT_DYNSYM:
1555 			if (!init_symtbl_state(&dynsym_state, cache, shnum,
1556 			    symsecndx, ehdr, versym, file, flags))
1557 				continue;
1558 			break;
1559 		default:
1560 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADNDXSEC),
1561 			    file, sortcache->c_name, conv_sec_type(
1562 			    ehdr->e_machine, symshdr->sh_type, 0));
1563 			continue;
1564 		}
1565 
1566 		/*
1567 		 * Output header
1568 		 */
1569 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1570 		if (ldynsym_cnt > 0) {
1571 			dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT2),
1572 			    sortcache->c_name, ldynsym_state.secname,
1573 			    dynsym_state.secname);
1574 			/*
1575 			 * The data for .SUNW_ldynsym and dynsym sections
1576 			 * is supposed to be adjacent with SUNW_ldynsym coming
1577 			 * first. Check, and issue a warning if it isn't so.
1578 			 */
1579 			if ((ldynsym_state.sym + ldynsym_state.symn)
1580 			    != dynsym_state.sym)
1581 				(void) fprintf(stderr,
1582 				    MSG_INTL(MSG_ERR_LDYNNOTADJ), file,
1583 				    ldynsym_state.secname,
1584 				    dynsym_state.secname);
1585 		} else {
1586 			dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT1),
1587 			    sortcache->c_name, dynsym_state.secname);
1588 		}
1589 		Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
1590 
1591 		/* If not first one, insert a line of whitespace */
1592 		if (output_cnt++ > 0)
1593 			dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1594 
1595 		/*
1596 		 * SUNW_dynsymsort and SUNW_dyntlssort are arrays of
1597 		 * symbol indices. Iterate over the array entries,
1598 		 * dispaying the referenced symbols.
1599 		 */
1600 		ndxn = sortshdr->sh_size / sortshdr->sh_entsize;
1601 		ndx = (Word *)sortcache->c_data->d_buf;
1602 		for (; ndxn-- > 0; ndx++) {
1603 			if (*ndx >= ldynsym_cnt) {
1604 				Word sec_ndx = *ndx - ldynsym_cnt;
1605 
1606 				output_symbol(&dynsym_state, sec_ndx,
1607 				    *ndx, dynsym_state.sym + sec_ndx);
1608 			} else {
1609 				output_symbol(&ldynsym_state, *ndx,
1610 				    *ndx, ldynsym_state.sym + *ndx);
1611 			}
1612 		}
1613 	}
1614 }
1615 
1616 /*
1617  * Search for and process any relocation sections.
1618  */
1619 static void
1620 reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, const char *file,
1621     uint_t flags)
1622 {
1623 	Word	cnt;
1624 
1625 	for (cnt = 1; cnt < shnum; cnt++) {
1626 		Word		type, symnum;
1627 		Xword		relndx, relnum, relsize;
1628 		void		*rels;
1629 		Sym		*syms;
1630 		Cache		*symsec, *strsec;
1631 		Cache		*_cache = &cache[cnt];
1632 		Shdr		*shdr = _cache->c_shdr;
1633 		char		*relname = _cache->c_name;
1634 
1635 		if (((type = shdr->sh_type) != SHT_RELA) &&
1636 		    (type != SHT_REL))
1637 			continue;
1638 		if (name && strcmp(name, relname))
1639 			continue;
1640 
1641 		/*
1642 		 * Decide entry size.
1643 		 */
1644 		if (((relsize = shdr->sh_entsize) == 0) ||
1645 		    (relsize > shdr->sh_size)) {
1646 			if (type == SHT_RELA)
1647 				relsize = sizeof (Rela);
1648 			else
1649 				relsize = sizeof (Rel);
1650 		}
1651 
1652 		/*
1653 		 * Determine the number of relocations available.
1654 		 */
1655 		if (shdr->sh_size == 0) {
1656 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1657 			    file, relname);
1658 			continue;
1659 		}
1660 		if (_cache->c_data == NULL)
1661 			continue;
1662 
1663 		rels = _cache->c_data->d_buf;
1664 		relnum = shdr->sh_size / relsize;
1665 
1666 		/*
1667 		 * Get the data buffer for the associated symbol table and
1668 		 * string table.
1669 		 */
1670 		if (stringtbl(cache, 1, cnt, shnum, file,
1671 		    &symnum, &symsec, &strsec) == 0)
1672 			continue;
1673 
1674 		syms = symsec->c_data->d_buf;
1675 
1676 		/*
1677 		 * Loop through the relocation entries.
1678 		 */
1679 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1680 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name);
1681 		Elf_reloc_title(0, ELF_DBG_ELFDUMP, type);
1682 
1683 		for (relndx = 0; relndx < relnum; relndx++,
1684 		    rels = (void *)((char *)rels + relsize)) {
1685 			char		section[BUFSIZ];
1686 			const char	*symname;
1687 			Word		symndx, reltype;
1688 			Rela		*rela;
1689 			Rel		*rel;
1690 
1691 			/*
1692 			 * Unravel the relocation and determine the symbol with
1693 			 * which this relocation is associated.
1694 			 */
1695 			if (type == SHT_RELA) {
1696 				rela = (Rela *)rels;
1697 				symndx = ELF_R_SYM(rela->r_info);
1698 				reltype = ELF_R_TYPE(rela->r_info);
1699 			} else {
1700 				rel = (Rel *)rels;
1701 				symndx = ELF_R_SYM(rel->r_info);
1702 				reltype = ELF_R_TYPE(rel->r_info);
1703 			}
1704 
1705 			symname = relsymname(cache, _cache, strsec, symndx,
1706 			    symnum, relndx, syms, section, BUFSIZ, file,
1707 			    flags);
1708 
1709 			/*
1710 			 * A zero symbol index is only valid for a few
1711 			 * relocations.
1712 			 */
1713 			if (symndx == 0) {
1714 				Half	mach = ehdr->e_machine;
1715 				int	badrel = 0;
1716 
1717 				if ((mach == EM_SPARC) ||
1718 				    (mach == EM_SPARC32PLUS) ||
1719 				    (mach == EM_SPARCV9)) {
1720 					if ((reltype != R_SPARC_NONE) &&
1721 					    (reltype != R_SPARC_REGISTER) &&
1722 					    (reltype != R_SPARC_RELATIVE))
1723 						badrel++;
1724 				} else if (mach == EM_386) {
1725 					if ((reltype != R_386_NONE) &&
1726 					    (reltype != R_386_RELATIVE))
1727 						badrel++;
1728 				} else if (mach == EM_AMD64) {
1729 					if ((reltype != R_AMD64_NONE) &&
1730 					    (reltype != R_AMD64_RELATIVE))
1731 						badrel++;
1732 				}
1733 
1734 				if (badrel) {
1735 					(void) fprintf(stderr,
1736 					    MSG_INTL(MSG_ERR_BADREL1), file,
1737 					    conv_reloc_type(mach, reltype, 0));
1738 				}
1739 			}
1740 
1741 			Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP,
1742 			    MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type,
1743 			    rels, relname, symname, 0);
1744 		}
1745 	}
1746 }
1747 
1748 /*
1749  * Search for and process a .dynamic section.
1750  */
1751 static void
1752 dynamic(Cache *cache, Word shnum, Ehdr *ehdr, const char *file)
1753 {
1754 	Word	cnt;
1755 
1756 	for (cnt = 1; cnt < shnum; cnt++) {
1757 		Dyn	*dyn;
1758 		ulong_t	numdyn;
1759 		int	ndx, end_ndx;
1760 		Cache	*_cache = &cache[cnt], *strsec;
1761 		Shdr	*shdr = _cache->c_shdr;
1762 
1763 		if (shdr->sh_type != SHT_DYNAMIC)
1764 			continue;
1765 
1766 		/*
1767 		 * Verify the associated string table section.
1768 		 */
1769 		if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0)
1770 			continue;
1771 
1772 		if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
1773 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1774 			    file, _cache->c_name);
1775 			continue;
1776 		}
1777 		if (_cache->c_data == NULL)
1778 			continue;
1779 
1780 		numdyn = shdr->sh_size / shdr->sh_entsize;
1781 		dyn = (Dyn *)_cache->c_data->d_buf;
1782 
1783 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1784 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name);
1785 
1786 		Elf_dyn_title(0);
1787 
1788 		for (ndx = 0; ndx < numdyn; dyn++, ndx++) {
1789 			const char	*name;
1790 
1791 			/*
1792 			 * Print the information numerically, and if possible
1793 			 * as a string.
1794 			 */
1795 			switch (dyn->d_tag) {
1796 			case DT_NULL:
1797 				/*
1798 				 * Special case: DT_NULLs can come in groups
1799 				 * that we prefer to reduce to a single line.
1800 				 */
1801 				end_ndx = ndx;
1802 				while ((end_ndx < (numdyn - 1)) &&
1803 					((dyn + 1)->d_tag == DT_NULL)) {
1804 					dyn++;
1805 					end_ndx++;
1806 				}
1807 				Elf_dyn_null_entry(0, dyn, ndx, end_ndx);
1808 				ndx = end_ndx;
1809 				continue;
1810 
1811 			/*
1812 			 * Print the information numerically, and if possible
1813 			 * as a string.
1814 			 */
1815 			case DT_NEEDED:
1816 			case DT_SONAME:
1817 			case DT_FILTER:
1818 			case DT_AUXILIARY:
1819 			case DT_CONFIG:
1820 			case DT_RPATH:
1821 			case DT_RUNPATH:
1822 			case DT_USED:
1823 			case DT_DEPAUDIT:
1824 			case DT_AUDIT:
1825 			case DT_SUNW_AUXILIARY:
1826 			case DT_SUNW_FILTER:
1827 				name = string(_cache, ndx, strsec,
1828 				    file, dyn->d_un.d_ptr);
1829 				break;
1830 
1831 			case DT_FLAGS:
1832 				name = conv_dyn_flag(dyn->d_un.d_val, 0);
1833 				break;
1834 			case DT_FLAGS_1:
1835 				name = conv_dyn_flag1(dyn->d_un.d_val);
1836 				break;
1837 			case DT_POSFLAG_1:
1838 				name = conv_dyn_posflag1(dyn->d_un.d_val, 0);
1839 				break;
1840 			case DT_FEATURE_1:
1841 				name = conv_dyn_feature1(dyn->d_un.d_val, 0);
1842 				break;
1843 			case DT_DEPRECATED_SPARC_REGISTER:
1844 				name = MSG_INTL(MSG_STR_DEPRECATED);
1845 				break;
1846 			default:
1847 				name = MSG_ORIG(MSG_STR_EMPTY);
1848 				break;
1849 			}
1850 
1851 			Elf_dyn_entry(0, dyn, ndx, name, ehdr->e_machine);
1852 		}
1853 	}
1854 }
1855 
1856 /*
1857  * Search for and process a MOVE section.
1858  */
1859 static void
1860 move(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags)
1861 {
1862 	Word		cnt;
1863 	const char	*fmt = 0;
1864 
1865 	for (cnt = 1; cnt < shnum; cnt++) {
1866 		Word	movenum, symnum, ndx;
1867 		Sym	*syms;
1868 		Cache	*_cache = &cache[cnt];
1869 		Shdr	*shdr = _cache->c_shdr;
1870 		Cache	*symsec, *strsec;
1871 		Move	*move;
1872 
1873 		if (shdr->sh_type != SHT_SUNW_move)
1874 			continue;
1875 		if (name && strcmp(name, _cache->c_name))
1876 			continue;
1877 
1878 		/*
1879 		 * Determine the move data and number.
1880 		 */
1881 		if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
1882 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1883 			    file, _cache->c_name);
1884 			continue;
1885 		}
1886 		if (_cache->c_data == NULL)
1887 			continue;
1888 
1889 		move = (Move *)_cache->c_data->d_buf;
1890 		movenum = shdr->sh_size / shdr->sh_entsize;
1891 
1892 		/*
1893 		 * Get the data buffer for the associated symbol table and
1894 		 * string table.
1895 		 */
1896 		if (stringtbl(cache, 1, cnt, shnum, file,
1897 		    &symnum, &symsec, &strsec) == 0)
1898 			return;
1899 
1900 		syms = (Sym *)symsec->c_data->d_buf;
1901 
1902 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1903 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name);
1904 		dbg_print(0, MSG_INTL(MSG_MOVE_TITLE));
1905 
1906 		if (fmt == 0)
1907 			fmt = MSG_INTL(MSG_MOVE_ENTRY);
1908 
1909 		for (ndx = 0; ndx < movenum; move++, ndx++) {
1910 			const char	*symname;
1911 			char		index[MAXNDXSIZE], section[BUFSIZ];
1912 			Word		symndx, shndx;
1913 			Sym		*sym;
1914 
1915 			/*
1916 			 * Check for null entries
1917 			 */
1918 			if ((move->m_info == 0) && (move->m_value == 0) &&
1919 			    (move->m_poffset == 0) && (move->m_repeat == 0) &&
1920 			    (move->m_stride == 0)) {
1921 				dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY),
1922 				    EC_XWORD(move->m_poffset), 0, 0, 0,
1923 				    EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY));
1924 				continue;
1925 			}
1926 			if (((symndx = ELF_M_SYM(move->m_info)) == 0) ||
1927 			    (symndx >= symnum)) {
1928 				(void) fprintf(stderr,
1929 				    MSG_INTL(MSG_ERR_BADMINFO), file,
1930 				    _cache->c_name, EC_XWORD(move->m_info));
1931 
1932 				(void) snprintf(index, MAXNDXSIZE,
1933 				    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx));
1934 				dbg_print(0, fmt, index,
1935 				    EC_XWORD(move->m_poffset),
1936 				    ELF_M_SIZE(move->m_info), move->m_repeat,
1937 				    move->m_stride, move->m_value,
1938 				    MSG_INTL(MSG_STR_UNKNOWN));
1939 				continue;
1940 			}
1941 
1942 			symname = relsymname(cache, _cache, strsec,
1943 			    symndx, symnum, ndx, syms, section, BUFSIZ, file,
1944 			    flags);
1945 			sym = (Sym *)(syms + symndx);
1946 
1947 			/*
1948 			 * Additional sanity check.
1949 			 */
1950 			shndx = sym->st_shndx;
1951 			if (!((shndx == SHN_COMMON) ||
1952 			    (((shndx >= 1) && (shndx <= shnum)) &&
1953 			    (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) {
1954 				(void) fprintf(stderr,
1955 				    MSG_INTL(MSG_ERR_BADSYM2), file,
1956 				    _cache->c_name, demangle(symname, flags));
1957 			}
1958 
1959 			(void) snprintf(index, MAXNDXSIZE,
1960 			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx));
1961 			dbg_print(0, fmt, index, EC_XWORD(move->m_poffset),
1962 			    ELF_M_SIZE(move->m_info), move->m_repeat,
1963 			    move->m_stride, move->m_value,
1964 			    demangle(symname, flags));
1965 		}
1966 	}
1967 }
1968 
1969 /*
1970  * Traverse a note section analyzing each note information block.
1971  * The data buffers size is used to validate references before they are made,
1972  * and is decremented as each element is processed.
1973  */
1974 void
1975 note_entry(Cache *cache, Word *data, size_t size, const char *file)
1976 {
1977 	size_t	bsize = size;
1978 
1979 	/*
1980 	 * Print out a single `note' information block.
1981 	 */
1982 	while (size > 0) {
1983 		size_t	namesz, descsz, type, pad, noteoff;
1984 
1985 		noteoff = bsize - size;
1986 		/*
1987 		 * Make sure we can at least reference the 3 initial entries
1988 		 * (4-byte words) of the note information block.
1989 		 */
1990 		if (size >= (sizeof (Word) * 3))
1991 			size -= (sizeof (Word) * 3);
1992 		else {
1993 			(void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ),
1994 			    file, cache->c_name, EC_WORD(noteoff));
1995 			return;
1996 		}
1997 
1998 		/*
1999 		 * Make sure any specified name string can be referenced.
2000 		 */
2001 		if ((namesz = *data++) != 0) {
2002 			if (size >= namesz)
2003 				size -= namesz;
2004 			else {
2005 				(void) fprintf(stderr,
2006 				    MSG_INTL(MSG_NOTE_BADNMSZ), file,
2007 				    cache->c_name, EC_WORD(noteoff),
2008 				    EC_WORD(namesz));
2009 				return;
2010 			}
2011 		}
2012 
2013 		/*
2014 		 * Make sure any specified descriptor can be referenced.
2015 		 */
2016 		if ((descsz = *data++) != 0) {
2017 			/*
2018 			 * If namesz isn't a 4-byte multiple, account for any
2019 			 * padding that must exist before the descriptor.
2020 			 */
2021 			if ((pad = (namesz & (sizeof (Word) - 1))) != 0) {
2022 				pad = sizeof (Word) - pad;
2023 				size -= pad;
2024 			}
2025 			if (size >= descsz)
2026 				size -= descsz;
2027 			else {
2028 				(void) fprintf(stderr,
2029 				    MSG_INTL(MSG_NOTE_BADDESZ), file,
2030 				    cache->c_name, EC_WORD(noteoff),
2031 				    EC_WORD(namesz));
2032 				return;
2033 			}
2034 		}
2035 
2036 		type = *data++;
2037 
2038 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2039 		dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE), EC_WORD(type));
2040 
2041 		dbg_print(0, MSG_ORIG(MSG_NOTE_NAMESZ), EC_WORD(namesz));
2042 		if (namesz) {
2043 			char	*name = (char *)data;
2044 
2045 			/*
2046 			 * Since the name string may have 'null' bytes
2047 			 * in it (ia32 .string) - we just write the
2048 			 * whole stream in a single fwrite.
2049 			 */
2050 			(void) fwrite(name, namesz, 1, stdout);
2051 			name = name + ((namesz + (sizeof (Word) - 1)) &
2052 			    ~(sizeof (Word) - 1));
2053 			/* LINTED */
2054 			data = (Word *)name;
2055 			dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2056 		}
2057 
2058 		/*
2059 		 * If multiple information blocks exist within a .note section
2060 		 * account for any padding that must exist before the next
2061 		 * information block.
2062 		 */
2063 		if ((pad = (descsz & (sizeof (Word) - 1))) != 0) {
2064 			pad = sizeof (Word) - pad;
2065 			if (size > pad)
2066 				size -= pad;
2067 		}
2068 
2069 		dbg_print(0, MSG_ORIG(MSG_NOTE_DESCSZ), EC_WORD(descsz));
2070 		if (descsz) {
2071 			int		ndx, byte, word;
2072 			char		string[58], *str = string;
2073 			uchar_t		*desc = (uchar_t *)data;
2074 
2075 			/*
2076 			 * Dump descriptor bytes.
2077 			 */
2078 			for (ndx = byte = word = 0; descsz; descsz--, desc++) {
2079 				int	tok = *desc;
2080 
2081 				(void) snprintf(str, 58, MSG_ORIG(MSG_NOTE_TOK),
2082 				    tok);
2083 				str += 3;
2084 
2085 				if (++byte == 4) {
2086 					*str++ = ' ', *str++ = ' ';
2087 					word++;
2088 					byte = 0;
2089 				}
2090 				if (word == 4) {
2091 					*str = '\0';
2092 					dbg_print(0, MSG_ORIG(MSG_NOTE_DESC),
2093 					    ndx, string);
2094 					word = 0;
2095 					ndx += 16;
2096 					str = string;
2097 				}
2098 			}
2099 			if (byte || word) {
2100 				*str = '\0';
2101 				dbg_print(0, MSG_ORIG(MSG_NOTE_DESC),
2102 				    ndx, string);
2103 			}
2104 
2105 			desc += pad;
2106 			/* LINTED */
2107 			data = (Word *)desc;
2108 		}
2109 	}
2110 }
2111 
2112 /*
2113  * Search for and process a .note section.
2114  */
2115 static void
2116 note(Cache *cache, Word shnum, const char *name, const char *file)
2117 {
2118 	Word	cnt;
2119 
2120 	/*
2121 	 * Otherwise look for any .note sections.
2122 	 */
2123 	for (cnt = 1; cnt < shnum; cnt++) {
2124 		Cache	*_cache = &cache[cnt];
2125 		Shdr	*shdr = _cache->c_shdr;
2126 
2127 		if (shdr->sh_type != SHT_NOTE)
2128 			continue;
2129 		if (name && strcmp(name, _cache->c_name))
2130 			continue;
2131 
2132 		/*
2133 		 * As these sections are often hand rolled, make sure they're
2134 		 * properly aligned before proceeding.
2135 		 */
2136 		if (shdr->sh_offset & (sizeof (Word) - 1)) {
2137 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN),
2138 			    file, _cache->c_name);
2139 			continue;
2140 		}
2141 		if (_cache->c_data == NULL)
2142 			continue;
2143 
2144 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2145 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name);
2146 		note_entry(_cache, (Word *)_cache->c_data->d_buf,
2147 		/* LINTED */
2148 		    (Word)_cache->c_data->d_size, file);
2149 	}
2150 }
2151 
2152 /*
2153  * Determine an individual hash entry.  This may be the initial hash entry,
2154  * or an associated chain entry.
2155  */
2156 static void
2157 hash_entry(Cache *refsec, Cache *strsec, const char *hsecname, Word hashndx,
2158     Word symndx, Word symn, Sym *syms, const char *file, ulong_t bkts,
2159     uint_t flags, int chain)
2160 {
2161 	Sym		*sym;
2162 	const char	*symname, *str;
2163 	char		_bucket[MAXNDXSIZE], _symndx[MAXNDXSIZE];
2164 	ulong_t		nbkt, nhash;
2165 
2166 	if (symndx > symn) {
2167 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_HSBADSYMNDX), file,
2168 		    EC_WORD(symndx), EC_WORD(hashndx));
2169 		symname = MSG_INTL(MSG_STR_UNKNOWN);
2170 	} else {
2171 		sym = (Sym *)(syms + symndx);
2172 		symname = string(refsec, symndx, strsec, file, sym->st_name);
2173 	}
2174 
2175 	if (chain == 0) {
2176 		(void) snprintf(_bucket, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER),
2177 		    hashndx);
2178 		str = (const char *)_bucket;
2179 	} else
2180 		str = MSG_ORIG(MSG_STR_EMPTY);
2181 
2182 	(void) snprintf(_symndx, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX2),
2183 	    EC_WORD(symndx));
2184 	dbg_print(0, MSG_ORIG(MSG_FMT_HASH_INFO), str, _symndx,
2185 	    demangle(symname, flags));
2186 
2187 	/*
2188 	 * Determine if this string is in the correct bucket.
2189 	 */
2190 	nhash = elf_hash(symname);
2191 	nbkt = nhash % bkts;
2192 
2193 	if (nbkt != hashndx) {
2194 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADHASH), file,
2195 		    hsecname, symname, EC_WORD(hashndx), nbkt);
2196 	}
2197 }
2198 
2199 #define	MAXCOUNT	500
2200 
2201 static void
2202 hash(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags)
2203 {
2204 	static int	count[MAXCOUNT];
2205 	Word		cnt;
2206 	ulong_t		ndx, bkts;
2207 	char		number[MAXNDXSIZE];
2208 
2209 	for (cnt = 1; cnt < shnum; cnt++) {
2210 		uint_t		*hash, *chain;
2211 		Cache		*_cache = &cache[cnt];
2212 		Shdr		*sshdr, *hshdr = _cache->c_shdr;
2213 		char		*ssecname, *hsecname = _cache->c_name;
2214 		Sym		*syms;
2215 		Word		symn;
2216 
2217 		if (hshdr->sh_type != SHT_HASH)
2218 			continue;
2219 		if (name && strcmp(name, hsecname))
2220 			continue;
2221 
2222 		/*
2223 		 * Determine the hash table data and size.
2224 		 */
2225 		if ((hshdr->sh_entsize == 0) || (hshdr->sh_size == 0)) {
2226 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
2227 			    file, hsecname);
2228 			continue;
2229 		}
2230 		if (_cache->c_data == NULL)
2231 			continue;
2232 
2233 		hash = (uint_t *)_cache->c_data->d_buf;
2234 		bkts = *hash;
2235 		chain = hash + 2 + bkts;
2236 		hash += 2;
2237 
2238 		/*
2239 		 * Get the data buffer for the associated symbol table.
2240 		 */
2241 		if ((hshdr->sh_link == 0) || (hshdr->sh_link >= shnum)) {
2242 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
2243 			    file, hsecname, EC_WORD(hshdr->sh_link));
2244 			continue;
2245 		}
2246 
2247 		_cache = &cache[hshdr->sh_link];
2248 		ssecname = _cache->c_name;
2249 
2250 		if (_cache->c_data == NULL)
2251 			continue;
2252 
2253 		if ((syms = (Sym *)_cache->c_data->d_buf) == NULL) {
2254 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
2255 			    file, ssecname);
2256 			continue;
2257 		}
2258 
2259 		sshdr = _cache->c_shdr;
2260 		/* LINTED */
2261 		symn = (Word)(sshdr->sh_size / sshdr->sh_entsize);
2262 
2263 		/*
2264 		 * Get the associated string table section.
2265 		 */
2266 		if ((sshdr->sh_link == 0) || (sshdr->sh_link >= shnum)) {
2267 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
2268 			    file, ssecname, EC_WORD(sshdr->sh_link));
2269 			continue;
2270 		}
2271 
2272 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2273 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_HASH), hsecname);
2274 		dbg_print(0, MSG_INTL(MSG_ELF_HASH_INFO));
2275 
2276 		/*
2277 		 * Loop through the hash buckets, printing the appropriate
2278 		 * symbols.
2279 		 */
2280 		for (ndx = 0; ndx < bkts; ndx++, hash++) {
2281 			Word	_ndx, _cnt;
2282 
2283 			if (*hash == 0) {
2284 				count[0]++;
2285 				continue;
2286 			}
2287 
2288 			hash_entry(_cache, &cache[sshdr->sh_link], hsecname,
2289 			    ndx, *hash, symn, syms, file, bkts, flags, 0);
2290 
2291 			/*
2292 			 * Determine if any other symbols are chained to this
2293 			 * bucket.
2294 			 */
2295 			_ndx = chain[*hash];
2296 			_cnt = 1;
2297 			while (_ndx) {
2298 				hash_entry(_cache, &cache[sshdr->sh_link],
2299 				    hsecname, ndx, _ndx, symn, syms, file,
2300 				    bkts, flags, 1);
2301 				_ndx = chain[_ndx];
2302 				_cnt++;
2303 			}
2304 
2305 			if (_cnt >= MAXCOUNT) {
2306 				(void) fprintf(stderr,
2307 				    MSG_INTL(MSG_HASH_OVERFLW), file,
2308 				    _cache->c_name, EC_WORD(ndx),
2309 				    EC_WORD(_cnt));
2310 			} else
2311 				count[_cnt]++;
2312 		}
2313 		break;
2314 	}
2315 
2316 	/*
2317 	 * Print out the count information.
2318 	 */
2319 	bkts = cnt = 0;
2320 	dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2321 
2322 	for (ndx = 0; ndx < MAXCOUNT; ndx++) {
2323 		Word	_cnt;
2324 
2325 		if ((_cnt = count[ndx]) == 0)
2326 			continue;
2327 
2328 		(void) snprintf(number, MAXNDXSIZE,
2329 		    MSG_ORIG(MSG_FMT_INTEGER), _cnt);
2330 		dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS1), number,
2331 		    EC_WORD(ndx));
2332 		bkts += _cnt;
2333 		cnt += (Word)(ndx * _cnt);
2334 	}
2335 	if (cnt) {
2336 		(void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER),
2337 		    bkts);
2338 		dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS2), number,
2339 		    EC_WORD(cnt));
2340 	}
2341 }
2342 
2343 static void
2344 group(Cache *cache, Word shnum, const char *name, const char *file,
2345     uint_t flags)
2346 {
2347 	Word	scnt;
2348 
2349 	for (scnt = 1; scnt < shnum; scnt++) {
2350 		Cache	*_cache = &cache[scnt];
2351 		Shdr	*shdr = _cache->c_shdr;
2352 		Word	*grpdata, gcnt, grpcnt, symnum, unknown;
2353 		Cache	*symsec, *strsec;
2354 		Sym	*syms, *sym;
2355 		char	flgstrbuf[MSG_GRP_COMDAT_SIZE + 10];
2356 
2357 		if (shdr->sh_type != SHT_GROUP)
2358 			continue;
2359 		if (name && strcmp(name, _cache->c_name))
2360 			continue;
2361 		if ((_cache->c_data == NULL) ||
2362 		    ((grpdata = (Word *)_cache->c_data->d_buf) == NULL))
2363 			continue;
2364 		grpcnt = shdr->sh_size / sizeof (Word);
2365 
2366 		/*
2367 		 * Get the data buffer for the associated symbol table and
2368 		 * string table.
2369 		 */
2370 		if (stringtbl(cache, 1, scnt, shnum, file,
2371 		    &symnum, &symsec, &strsec) == 0)
2372 			return;
2373 
2374 		syms = symsec->c_data->d_buf;
2375 
2376 		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2377 		dbg_print(0, MSG_INTL(MSG_ELF_SCN_GRP), _cache->c_name);
2378 		dbg_print(0, MSG_INTL(MSG_GRP_TITLE));
2379 
2380 		/*
2381 		 * The first element of the group defines the group.  The
2382 		 * associated symbol is defined by the sh_link field.
2383 		 */
2384 		if ((shdr->sh_info == SHN_UNDEF) || (shdr->sh_info > symnum)) {
2385 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO),
2386 			    file, _cache->c_name, EC_WORD(shdr->sh_info));
2387 			return;
2388 		}
2389 
2390 		(void) strcpy(flgstrbuf, MSG_ORIG(MSG_STR_OSQBRKT));
2391 		if (grpdata[0] & GRP_COMDAT) {
2392 			(void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_COMDAT));
2393 		}
2394 		if ((unknown = (grpdata[0] & ~GRP_COMDAT)) != 0) {
2395 			size_t	len = strlen(flgstrbuf);
2396 
2397 			(void) snprintf(&flgstrbuf[len],
2398 			    (MSG_GRP_COMDAT_SIZE + 10 - len),
2399 			    MSG_ORIG(MSG_GRP_UNKNOWN), unknown);
2400 		}
2401 		(void) strcat(flgstrbuf, MSG_ORIG(MSG_STR_CSQBRKT));
2402 		sym = (Sym *)(syms + shdr->sh_info);
2403 
2404 		dbg_print(0, MSG_INTL(MSG_GRP_SIGNATURE), flgstrbuf,
2405 		    demangle(string(_cache, 0, strsec, file, sym->st_name),
2406 		    flags));
2407 
2408 		for (gcnt = 1; gcnt < grpcnt; gcnt++) {
2409 			char		index[MAXNDXSIZE];
2410 			const char	*name;
2411 
2412 			(void) snprintf(index, MAXNDXSIZE,
2413 			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(gcnt));
2414 
2415 			if (grpdata[gcnt] >= shnum)
2416 				name = MSG_INTL(MSG_GRP_INVALSCN);
2417 			else
2418 				name = cache[grpdata[gcnt]].c_name;
2419 
2420 			(void) printf(MSG_ORIG(MSG_GRP_ENTRY), index, name,
2421 				EC_XWORD(grpdata[gcnt]));
2422 		}
2423 	}
2424 }
2425 
2426 static void
2427 got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, uint_t flags)
2428 {
2429 	Cache		*gotcache = 0, *symtab = 0, *_cache;
2430 	Addr		gotbgn, gotend;
2431 	Shdr		*gotshdr;
2432 	Word		cnt, gotents, gotndx;
2433 	size_t		gentsize;
2434 	Got_info	*gottable;
2435 	char		*gotdata;
2436 	Sym		*gotsym;
2437 	Xword		gotsymaddr;
2438 
2439 	/*
2440 	 * First, find the got.
2441 	 */
2442 	for (cnt = 1; cnt < shnum; cnt++) {
2443 		_cache = &cache[cnt];
2444 		if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT),
2445 		    MSG_ELF_GOT_SIZE) == 0) {
2446 			gotcache = _cache;
2447 			break;
2448 		}
2449 	}
2450 	if (gotcache == 0)
2451 		return;
2452 
2453 	/*
2454 	 * A got section within a relocatable object is suspicious.
2455 	 */
2456 	if (ehdr->e_type == ET_REL) {
2457 		(void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file,
2458 		    _cache->c_name);
2459 	}
2460 
2461 	gotshdr = gotcache->c_shdr;
2462 	if (gotshdr->sh_size == 0) {
2463 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
2464 		    file, gotcache->c_name);
2465 		return;
2466 	}
2467 
2468 	gotbgn = gotshdr->sh_addr;
2469 	gotend = gotbgn + gotshdr->sh_size;
2470 
2471 	/*
2472 	 * Some architectures don't properly set the sh_entsize for the GOT
2473 	 * table.  If it's not set, default to a size of a pointer.
2474 	 */
2475 	if ((gentsize = gotshdr->sh_entsize) == 0)
2476 		gentsize = sizeof (Xword);
2477 
2478 	if (gotcache->c_data == NULL)
2479 		return;
2480 
2481 	/* LINTED */
2482 	gotents = (Word)(gotshdr->sh_size / gentsize);
2483 	gotdata = gotcache->c_data->d_buf;
2484 
2485 	if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) {
2486 		int err = errno;
2487 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), file,
2488 		    strerror(err));
2489 		return;
2490 	}
2491 
2492 	/*
2493 	 * Now we scan through all the sections looking for any relocations
2494 	 * that may be against the GOT.  Since these may not be isolated to a
2495 	 * .rel[a].got section we check them all.
2496 	 * While scanning sections save the symbol table entry (a symtab
2497 	 * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_.
2498 	 */
2499 	for (cnt = 1; cnt < shnum; cnt++) {
2500 		Word		type, symnum;
2501 		Xword		relndx, relnum, relsize;
2502 		void		*rels;
2503 		Sym		*syms;
2504 		Cache		*symsec, *strsec;
2505 		Cache		*_cache = &cache[cnt];
2506 		Shdr		*shdr;
2507 
2508 		shdr = _cache->c_shdr;
2509 		type = shdr->sh_type;
2510 
2511 		if ((symtab == 0) && (type == SHT_DYNSYM)) {
2512 			symtab = _cache;
2513 			continue;
2514 		}
2515 		if (type == SHT_SYMTAB) {
2516 			symtab = _cache;
2517 			continue;
2518 		}
2519 		if ((type != SHT_RELA) && (type != SHT_REL))
2520 			continue;
2521 
2522 		/*
2523 		 * Decide entry size.
2524 		 */
2525 		if (((relsize = shdr->sh_entsize) == 0) ||
2526 		    (relsize > shdr->sh_size)) {
2527 			if (type == SHT_RELA)
2528 				relsize = sizeof (Rela);
2529 			else
2530 				relsize = sizeof (Rel);
2531 		}
2532 
2533 		/*
2534 		 * Determine the number of relocations available.
2535 		 */
2536 		if (shdr->sh_size == 0) {
2537 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
2538 			    file, _cache->c_name);
2539 			continue;
2540 		}
2541 		if (_cache->c_data == NULL)
2542 			continue;
2543 
2544 		rels = _cache->c_data->d_buf;
2545 		relnum = shdr->sh_size / relsize;
2546 
2547 		/*
2548 		 * Get the data buffer for the associated symbol table and
2549 		 * string table.
2550 		 */
2551 		if (stringtbl(cache, 1, cnt, shnum, file,
2552 		    &symnum, &symsec, &strsec) == 0)
2553 			continue;
2554 
2555 		syms = symsec->c_data->d_buf;
2556 
2557 		/*
2558 		 * Loop through the relocation entries.
2559 		 */
2560 		for (relndx = 0; relndx < relnum; relndx++,
2561 		    rels = (void *)((char *)rels + relsize)) {
2562 			char		section[BUFSIZ];
2563 			Addr		offset;
2564 			Got_info	*gip;
2565 			Word		symndx, reltype;
2566 			Rela		*rela;
2567 			Rel		*rel;
2568 
2569 			/*
2570 			 * Unravel the relocation.
2571 			 */
2572 			if (type == SHT_RELA) {
2573 				rela = (Rela *)rels;
2574 				symndx = ELF_R_SYM(rela->r_info);
2575 				reltype = ELF_R_TYPE(rela->r_info);
2576 				offset = rela->r_offset;
2577 			} else {
2578 				rel = (Rel *)rels;
2579 				symndx = ELF_R_SYM(rel->r_info);
2580 				reltype = ELF_R_TYPE(rel->r_info);
2581 				offset = rel->r_offset;
2582 			}
2583 
2584 			/*
2585 			 * Only pay attention to relocations against the GOT.
2586 			 */
2587 			if ((offset < gotbgn) || (offset > gotend))
2588 				continue;
2589 
2590 			/* LINTED */
2591 			gotndx = (Word)((offset - gotbgn) /
2592 			    gotshdr->sh_entsize);
2593 			gip = &gottable[gotndx];
2594 
2595 			if (gip->g_reltype != 0) {
2596 				(void) fprintf(stderr,
2597 				    MSG_INTL(MSG_GOT_MULTIPLE), file,
2598 				    EC_WORD(gotndx), EC_ADDR(offset));
2599 				continue;
2600 			}
2601 
2602 			if (symndx)
2603 				gip->g_symname = relsymname(cache, _cache,
2604 				    strsec, symndx, symnum, relndx, syms,
2605 				    section, BUFSIZ, file, flags);
2606 			gip->g_reltype = reltype;
2607 			gip->g_rel = rels;
2608 		}
2609 	}
2610 
2611 	if (symlookup(MSG_ORIG(MSG_GOT_SYM), cache, shnum, &gotsym, symtab,
2612 	    file))
2613 		gotsymaddr = gotsym->st_value;
2614 	else
2615 		gotsymaddr = gotbgn;
2616 
2617 	dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2618 	dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name);
2619 	Elf_got_title(0);
2620 
2621 	for (gotndx = 0; gotndx < gotents; gotndx++) {
2622 		Got_info	*gip;
2623 		Sword		gindex;
2624 		Addr		gaddr;
2625 		Xword		gotentry;
2626 
2627 		gip = &gottable[gotndx];
2628 
2629 		gaddr = gotbgn + (gotndx * gentsize);
2630 		gindex = (Sword)(gaddr - gotsymaddr) / (Sword)gentsize;
2631 
2632 		if (gentsize == sizeof (Word))
2633 			/* LINTED */
2634 			gotentry = (Xword)(*((Word *)(gotdata) + gotndx));
2635 		else
2636 			/* LINTED */
2637 			gotentry = *((Xword *)(gotdata) + gotndx);
2638 
2639 		Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine,
2640 		    gip->g_reltype, gip->g_rel, gip->g_symname);
2641 	}
2642 	free(gottable);
2643 }
2644 
2645 void
2646 checksum(Elf *elf)
2647 {
2648 	dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2649 	dbg_print(0, MSG_INTL(MSG_STR_CHECKSUM), elf_checksum(elf));
2650 }
2651 
2652 void
2653 regular(const char *file, Elf *elf, uint_t flags, char *Nname, int wfd)
2654 {
2655 	Elf_Scn		*scn;
2656 	Ehdr		*ehdr;
2657 	Elf_Data	*data;
2658 	size_t		cnt, shstrndx, shnum, phnum;
2659 	Shdr		*nameshdr, *shdr;
2660 	char		*names = 0;
2661 	Cache		*cache, *_cache;
2662 	VERSYM_STATE	versym;
2663 
2664 	if ((ehdr = elf_getehdr(elf)) == NULL) {
2665 		failure(file, MSG_ORIG(MSG_ELF_GETEHDR));
2666 		return;
2667 	}
2668 
2669 	if (elf_getshnum(elf, &shnum) == 0) {
2670 		failure(file, MSG_ORIG(MSG_ELF_GETSHNUM));
2671 		return;
2672 	}
2673 
2674 	if (elf_getshstrndx(elf, &shstrndx) == 0) {
2675 		failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX));
2676 		return;
2677 	}
2678 
2679 	if (elf_getphnum(elf, &phnum) == 0) {
2680 		failure(file, MSG_ORIG(MSG_ELF_GETPHNUM));
2681 		return;
2682 	}
2683 
2684 	if ((scn = elf_getscn(elf, 0)) != NULL) {
2685 		if ((shdr = elf_getshdr(scn)) == NULL) {
2686 			failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
2687 			(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0);
2688 			return;
2689 		}
2690 	} else
2691 		shdr = 0;
2692 
2693 	/*
2694 	 * Print the elf header.
2695 	 */
2696 	if (flags & FLG_EHDR)
2697 		Elf_ehdr(0, ehdr, shdr);
2698 
2699 	/*
2700 	 * Print the program headers.
2701 	 */
2702 	if ((flags & FLG_PHDR) && (phnum != 0)) {
2703 		Phdr *phdr;
2704 
2705 		if ((phdr = elf_getphdr(elf)) == NULL) {
2706 			failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
2707 			return;
2708 		}
2709 
2710 		for (cnt = 0; cnt < phnum; phdr++, cnt++) {
2711 
2712 			if (Nname &&
2713 			    (strcmp(Nname, conv_phdr_type(ehdr->e_machine,
2714 			    phdr->p_type, CONV_FMT_ALTFILE)) != 0))
2715 				continue;
2716 
2717 			dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2718 			dbg_print(0, MSG_INTL(MSG_ELF_PHDR), EC_WORD(cnt));
2719 			Elf_phdr(0, ehdr->e_machine, phdr);
2720 		}
2721 	}
2722 
2723 	/*
2724 	 * Return now if there are no section, if there's just one section to
2725 	 * act as an extension of the ELF header, or if on section information
2726 	 * was requested.
2727 	 */
2728 	if ((shnum <= 1) || (flags && (flags & ~(FLG_EHDR | FLG_PHDR)) == 0)) {
2729 		if ((ehdr->e_type == ET_CORE) && (flags & FLG_NOTE))
2730 			note(0, shnum, 0, file);
2731 		return;
2732 	}
2733 
2734 	/*
2735 	 * Obtain the .shstrtab data buffer to provide the required section
2736 	 * name strings.
2737 	 */
2738 	if ((scn = elf_getscn(elf, shstrndx)) == NULL) {
2739 		failure(file, MSG_ORIG(MSG_ELF_GETSCN));
2740 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR),
2741 		    EC_XWORD(shstrndx));
2742 
2743 	} else if ((data = elf_getdata(scn, NULL)) == NULL) {
2744 		failure(file, MSG_ORIG(MSG_ELF_GETDATA));
2745 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA),
2746 		    EC_XWORD(shstrndx));
2747 
2748 	} else if ((nameshdr = elf_getshdr(scn)) == NULL) {
2749 		failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
2750 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN),
2751 		    EC_WORD(elf_ndxscn(scn)));
2752 
2753 	} else if ((names = data->d_buf) == 0)
2754 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file);
2755 
2756 	/*
2757 	 * Allocate a cache to maintain a descriptor for each section.
2758 	 */
2759 	if ((cache = malloc(shnum * sizeof (Cache))) == 0) {
2760 		int err = errno;
2761 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
2762 		    file, strerror(err));
2763 		return;
2764 	}
2765 
2766 	*cache = cache_init;
2767 	_cache = cache;
2768 	_cache++;
2769 
2770 	/*
2771 	 * Traverse the sections of the file.  This gathering of data is
2772 	 * carried out in two passes.  First, the section headers are captured
2773 	 * and the section header names are evaluated.  A verification pass is
2774 	 * then carried out over the section information.  Files have been
2775 	 * known to exhibit overlapping (and hence erroneous) section header
2776 	 * information.
2777 	 *
2778 	 * Finally, the data for each section is obtained.  This processing is
2779 	 * carried out after section verification because should any section
2780 	 * header overlap occur, and a file needs translating (ie. xlate'ing
2781 	 * information from a non-native architecture file), then the process
2782 	 * of translation can corrupt the section header information.  Of
2783 	 * course, if there is any section overlap, the data related to the
2784 	 * sections is going to be compromised.  However, it is the translation
2785 	 * of this data that has caused problems with elfdump()'s ability to
2786 	 * extract the data.
2787 	 */
2788 	for (cnt = 1, scn = NULL; scn = elf_nextscn(elf, scn);
2789 	    cnt++, _cache++) {
2790 		char	scnndxnm[100];
2791 
2792 		_cache->c_ndx = cnt;
2793 		_cache->c_scn = scn;
2794 
2795 		if ((_cache->c_shdr = elf_getshdr(scn)) == NULL) {
2796 			failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
2797 			(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN),
2798 			    EC_WORD(elf_ndxscn(scn)));
2799 		}
2800 
2801 		/*
2802 		 * If a shstrtab exists, assign the section name.
2803 		 */
2804 		if (names && _cache->c_shdr) {
2805 			if (_cache->c_shdr->sh_name &&
2806 			    /* LINTED */
2807 			    (nameshdr->sh_size > _cache->c_shdr->sh_name)) {
2808 				_cache->c_name =
2809 				    names + _cache->c_shdr->sh_name;
2810 				continue;
2811 			}
2812 
2813 			/*
2814 			 * Generate an error if the section name index is zero
2815 			 * or exceeds the shstrtab data.  Fall through to
2816 			 * fabricate a section name.
2817 			 */
2818 			if ((_cache->c_shdr->sh_name == 0) ||
2819 			    /* LINTED */
2820 			    (nameshdr->sh_size <= _cache->c_shdr->sh_name)) {
2821 				(void) fprintf(stderr,
2822 				    MSG_INTL(MSG_ERR_BADSHNAME), file,
2823 				    EC_WORD(cnt),
2824 				    EC_XWORD(_cache->c_shdr->sh_name));
2825 			}
2826 		}
2827 
2828 		/*
2829 		 * If there exists no shstrtab data, or a section header has no
2830 		 * name (an invalid index of 0), then compose a name for the
2831 		 * section.
2832 		 */
2833 		(void) snprintf(scnndxnm, sizeof (scnndxnm),
2834 		    MSG_INTL(MSG_FMT_SCNNDX), cnt);
2835 
2836 		if ((_cache->c_name = malloc(strlen(scnndxnm) + 1)) == 0) {
2837 			int err = errno;
2838 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
2839 			    file, strerror(err));
2840 			return;
2841 		}
2842 		(void) strcpy(_cache->c_name, scnndxnm);
2843 	}
2844 
2845 	/*
2846 	 * Having collected all the sections, validate their address range.
2847 	 * Cases have existed where the section information has been invalid.
2848 	 * This can lead to all sorts of other, hard to diagnose errors, as
2849 	 * each section is processed individually (ie. with elf_getdata()).
2850 	 * Here, we carry out some address comparisons to catch a family of
2851 	 * overlapping memory issues we have observed (likely, there are others
2852 	 * that we have yet to discover).
2853 	 *
2854 	 * Note, should any memory overlap occur, obtaining any additional
2855 	 * data from the file is questionable.  However, it might still be
2856 	 * possible to inspect the ELF header, Programs headers, or individual
2857 	 * sections, so rather than bailing on an error condition, continue
2858 	 * processing to see if any data can be salvaged.
2859 	 */
2860 	for (cnt = 1; cnt < shnum; cnt++) {
2861 		Cache	*_cache = &cache[cnt];
2862 		Shdr	*shdr = _cache->c_shdr;
2863 		Off	bgn1, bgn = shdr->sh_offset;
2864 		Off	end1, end = shdr->sh_offset + shdr->sh_size;
2865 		int	cnt1;
2866 
2867 		if ((shdr->sh_size == 0) || (shdr->sh_type == SHT_NOBITS))
2868 			continue;
2869 
2870 		for (cnt1 = 1; cnt1 < shnum; cnt1++) {
2871 			Cache	*_cache1 = &cache[cnt1];
2872 			Shdr	*shdr1 = _cache1->c_shdr;
2873 
2874 			bgn1 = shdr1->sh_offset;
2875 			end1 = shdr1->sh_offset + shdr1->sh_size;
2876 
2877 			if ((cnt1 == cnt) || (shdr->sh_size == 0) ||
2878 			    (shdr1->sh_type == SHT_NOBITS))
2879 				continue;
2880 
2881 			if (((bgn1 <= bgn) && (end1 > bgn)) ||
2882 			    ((bgn1 < end) && (end1 >= end))) {
2883 				(void) fprintf(stderr,
2884 				    MSG_INTL(MSG_ERR_SECMEMOVER), file,
2885 				    EC_WORD(elf_ndxscn(_cache1->c_scn)),
2886 				    _cache1->c_name, EC_OFF(bgn1), EC_OFF(end1),
2887 				    EC_WORD(elf_ndxscn(_cache->c_scn)),
2888 				    _cache->c_name, EC_OFF(bgn), EC_OFF(end));
2889 			}
2890 		}
2891 
2892 		/*
2893 		 * And finally, make sure this section doesn't overlap the
2894 		 * section header itself.
2895 		 */
2896 		bgn1 = ehdr->e_shoff;
2897 		end1 = ehdr->e_shoff + (ehdr->e_shentsize * ehdr->e_shnum);
2898 
2899 		if (((bgn1 <= bgn) && (end1 > bgn)) ||
2900 		    ((bgn1 < end) && (end1 >= end))) {
2901 			(void) fprintf(stderr,
2902 			    MSG_INTL(MSG_ERR_SHDRMEMOVER), file, EC_OFF(bgn1),
2903 			    EC_OFF(end1),
2904 			    EC_WORD(elf_ndxscn(_cache->c_scn)),
2905 			    _cache->c_name, EC_OFF(bgn), EC_OFF(end));
2906 		}
2907 	}
2908 
2909 	/*
2910 	 * Finally, obtain the data for each section.
2911 	 */
2912 	for (cnt = 1; cnt < shnum; cnt++) {
2913 		Cache	*_cache = &cache[cnt];
2914 		Elf_Scn	*scn = _cache->c_scn;
2915 
2916 		if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) {
2917 			failure(file, MSG_ORIG(MSG_ELF_GETDATA));
2918 			(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA),
2919 			    EC_WORD(elf_ndxscn(scn)));
2920 		}
2921 
2922 		/*
2923 		 * Do we wish to write the section out?
2924 		 */
2925 		if (wfd && Nname && (strcmp(Nname, _cache->c_name) == 0) &&
2926 		    _cache->c_data) {
2927 			(void) write(wfd, _cache->c_data->d_buf,
2928 			    _cache->c_data->d_size);
2929 		}
2930 	}
2931 
2932 	if (flags & FLG_SHDR)
2933 		sections(file, cache, shnum, ehdr, Nname);
2934 
2935 	if (flags & FLG_INTERP)
2936 		interp(file, cache, shnum, phnum, elf);
2937 
2938 	versions(cache, shnum, file, flags, &versym);
2939 
2940 	if (flags & FLG_SYMBOLS)
2941 		symbols(cache, shnum, ehdr, Nname, &versym, file, flags);
2942 
2943 	if (flags & FLG_SORT)
2944 		sunw_sort(cache, shnum, ehdr, Nname, &versym, file, flags);
2945 
2946 	if (flags & FLG_HASH)
2947 		hash(cache, shnum, Nname, file, flags);
2948 
2949 	if (flags & FLG_GOT)
2950 		got(cache, shnum, ehdr, file, flags);
2951 
2952 	if (flags & FLG_GROUP)
2953 		group(cache, shnum, Nname, file, flags);
2954 
2955 	if (flags & FLG_SYMINFO)
2956 		syminfo(cache, shnum, file);
2957 
2958 	if (flags & FLG_RELOC)
2959 		reloc(cache, shnum, ehdr, Nname, file, flags);
2960 
2961 	if (flags & FLG_DYNAMIC)
2962 		dynamic(cache, shnum, ehdr, file);
2963 
2964 	if (flags & FLG_NOTE)
2965 		note(cache, shnum, Nname, file);
2966 
2967 	if (flags & FLG_MOVE)
2968 		move(cache, shnum, Nname, file, flags);
2969 
2970 	if (flags & FLG_CHECKSUM)
2971 		checksum(elf);
2972 
2973 	if (flags & FLG_CAP)
2974 		cap(file, cache, shnum, phnum, ehdr, elf);
2975 
2976 	if (flags & FLG_UNWIND)
2977 		unwind(cache, shnum, phnum, ehdr, Nname, file, elf);
2978 
2979 	free(cache);
2980 }
2981