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