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