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