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