elfdump.c revision 2766:897bcb036a29
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		    (shdr->sh_type != SHT_SUNW_LDYNSYM))
1082			continue;
1083		if (name && strcmp(name, secname))
1084			continue;
1085
1086		/*
1087		 * Determine the symbol data and number.
1088		 */
1089		if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
1090			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1091			    file, secname);
1092			continue;
1093		}
1094		/* LINTED */
1095		symn = (Word)(shdr->sh_size / shdr->sh_entsize);
1096		sym = (Sym *)_cache->c_data->d_buf;
1097
1098		/*
1099		 * Get the associated string table section.
1100		 */
1101		if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
1102			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
1103			    file, secname, EC_WORD(shdr->sh_link));
1104			continue;
1105		}
1106
1107		/*
1108		 * Determine if there is a associated Versym section
1109		 * with this Symbol Table.
1110		 */
1111		if (versymcache && (versymcache->c_shdr->sh_link == seccnt))
1112			versym = versymcache->c_data->d_buf;
1113		else
1114			versym = 0;
1115
1116		/*
1117		 * Loop through the symbol tables entries.
1118		 */
1119		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1120		dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), secname);
1121		Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
1122
1123		shxndx = 0;
1124		noshxndx = 0;
1125		symnshxndx = 0;
1126		for (symcnt = 0; symcnt < symn; sym++, symcnt++) {
1127			char		index[MAXNDXSIZE], *sec;
1128			const char	*symname;
1129			int		verndx;
1130			uchar_t		type;
1131			Shdr		*tshdr;
1132			Word		shndx;
1133
1134			/*
1135			 * If we are using extended symbol indexes, find the
1136			 * corresponding SHN_SYMTAB_SHNDX table.
1137			 */
1138			if ((sym->st_shndx == SHN_XINDEX) &&
1139			    (shxndx == 0) && (noshxndx == 0))
1140				noshxndx = symbols_getxindex(cache, shnum,
1141				    seccnt, &shxndx, &symnshxndx);
1142
1143			/* LINTED */
1144			symname = string(_cache, symcnt, &cache[shdr->sh_link],
1145			    file, sym->st_name);
1146
1147			tshdr = 0;
1148			sec = NULL;
1149
1150			if (is_core)
1151				sec = (char *)MSG_INTL(MSG_STR_UNKNOWN);
1152			else if ((sym->st_shndx < SHN_LORESERVE) &&
1153			    (sym->st_shndx < shnum)) {
1154				shndx = sym->st_shndx;
1155				tshdr = cache[shndx].c_shdr;
1156				sec = cache[shndx].c_name;
1157			} else if (sym->st_shndx == SHN_XINDEX) {
1158				if (shxndx) {
1159					Word	_shxndx;
1160
1161					if (symcnt > symnshxndx) {
1162					    (void) fprintf(stderr,
1163						MSG_INTL(MSG_ERR_BADSYMXINDEX1),
1164						file, secname, EC_WORD(symcnt));
1165					} else if ((_shxndx =
1166					    shxndx[symcnt]) > shnum) {
1167					    (void) fprintf(stderr,
1168						MSG_INTL(MSG_ERR_BADSYMXINDEX2),
1169						file, secname, EC_WORD(symcnt),
1170						EC_WORD(_shxndx));
1171					} else {
1172					    shndx = _shxndx;
1173					    tshdr = cache[shndx].c_shdr;
1174					    sec = cache[shndx].c_name;
1175					}
1176				} else {
1177					(void) fprintf(stderr,
1178					    MSG_INTL(MSG_ERR_BADSYMXINDEX3),
1179					    file, secname, EC_WORD(symcnt));
1180				}
1181			} else if ((sym->st_shndx < SHN_LORESERVE) &&
1182			    (sym->st_shndx >= shnum)) {
1183				(void) fprintf(stderr,
1184				    MSG_INTL(MSG_ERR_BADSYM5), file,
1185				    secname, demangle(symname, flags),
1186				    sym->st_shndx);
1187			}
1188
1189			/*
1190			 * If versioning is available display the
1191			 * version index.
1192			 */
1193			if (versym)
1194				verndx = (int)versym[symcnt];
1195			else
1196				verndx = 0;
1197
1198			/*
1199			 * Error checking for TLS.
1200			 */
1201			type = ELF_ST_TYPE(sym->st_info);
1202			if (type == STT_TLS) {
1203				if (tshdr &&
1204				    (sym->st_shndx != SHN_UNDEF) &&
1205				    ((tshdr->sh_flags & SHF_TLS) == 0)) {
1206					(void) fprintf(stderr,
1207					    MSG_INTL(MSG_ERR_BADSYM3), file,
1208					    secname, demangle(symname, flags));
1209				}
1210			} else if ((type != STT_SECTION) && sym->st_size &&
1211			    tshdr && (tshdr->sh_flags & SHF_TLS)) {
1212				(void) fprintf(stderr,
1213				    MSG_INTL(MSG_ERR_BADSYM4), file,
1214				    secname, demangle(symname, flags));
1215			}
1216
1217			/*
1218			 * If a symbol has size, then make sure the section it
1219			 * references is appropriate.  Note, UNDEF symbols that
1220			 * have a size, have been known to exist - ignore them.
1221			 */
1222			if (sym->st_size && shndx && tshdr &&
1223			    (tshdr->sh_size < sym->st_size)) {
1224				(void) fprintf(stderr,
1225				    MSG_INTL(MSG_ERR_BADSYM6), file,
1226				    secname, demangle(symname, flags),
1227				    EC_WORD(shndx), EC_XWORD(tshdr->sh_size),
1228				    EC_XWORD(sym->st_size));
1229			}
1230
1231			(void) snprintf(index, MAXNDXSIZE,
1232			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symcnt));
1233			Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index,
1234			    ehdr->e_machine, sym, verndx, sec, symname);
1235		}
1236	}
1237}
1238
1239/*
1240 * Search for and process any relocation sections.
1241 */
1242static void
1243reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, const char *file,
1244    uint_t flags)
1245{
1246	Word	cnt;
1247
1248	for (cnt = 1; cnt < shnum; cnt++) {
1249		Word		type, symnum;
1250		Xword		relndx, relnum, relsize;
1251		void		*rels;
1252		Sym		*syms;
1253		Cache		*symsec, *strsec;
1254		Cache		*_cache = &cache[cnt];
1255		Shdr		*shdr = _cache->c_shdr;
1256		char		*relname = _cache->c_name;
1257
1258		if (((type = shdr->sh_type) != SHT_RELA) &&
1259		    (type != SHT_REL))
1260			continue;
1261		if (name && strcmp(name, relname))
1262			continue;
1263
1264		/*
1265		 * Decide entry size.
1266		 */
1267		if (((relsize = shdr->sh_entsize) == 0) ||
1268		    (relsize > shdr->sh_size)) {
1269			if (type == SHT_RELA)
1270				relsize = sizeof (Rela);
1271			else
1272				relsize = sizeof (Rel);
1273		}
1274
1275		/*
1276		 * Determine the number of relocations available.
1277		 */
1278		if (shdr->sh_size == 0) {
1279			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1280			    file, relname);
1281			continue;
1282		}
1283		rels = _cache->c_data->d_buf;
1284		relnum = shdr->sh_size / relsize;
1285
1286		/*
1287		 * Get the data buffer for the associated symbol table and
1288		 * string table.
1289		 */
1290		if (stringtbl(cache, 1, cnt, shnum, file,
1291		    &symnum, &symsec, &strsec) == 0)
1292			continue;
1293
1294		syms = symsec->c_data->d_buf;
1295
1296		/*
1297		 * Loop through the relocation entries.
1298		 */
1299		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1300		dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name);
1301		Elf_reloc_title(0, ELF_DBG_ELFDUMP, type);
1302
1303		for (relndx = 0; relndx < relnum; relndx++,
1304		    rels = (void *)((char *)rels + relsize)) {
1305			char		section[BUFSIZ];
1306			const char	*symname;
1307			Word		symndx, reltype;
1308			Rela		*rela;
1309			Rel		*rel;
1310
1311			/*
1312			 * Unravel the relocation and determine the symbol with
1313			 * which this relocation is associated.
1314			 */
1315			if (type == SHT_RELA) {
1316				rela = (Rela *)rels;
1317				symndx = ELF_R_SYM(rela->r_info);
1318				reltype = ELF_R_TYPE(rela->r_info);
1319			} else {
1320				rel = (Rel *)rels;
1321				symndx = ELF_R_SYM(rel->r_info);
1322				reltype = ELF_R_TYPE(rel->r_info);
1323			}
1324
1325			symname = relsymname(cache, _cache, strsec, symndx,
1326			    symnum, relndx, syms, section, BUFSIZ, file,
1327			    flags);
1328
1329			/*
1330			 * A zero symbol index is only valid for a few
1331			 * relocations.
1332			 */
1333			if (symndx == 0) {
1334				Half	mach = ehdr->e_machine;
1335				int	badrel = 0;
1336
1337				if ((mach == EM_SPARC) ||
1338				    (mach == EM_SPARC32PLUS) ||
1339				    (mach == EM_SPARCV9)) {
1340					if ((reltype != R_SPARC_NONE) &&
1341					    (reltype != R_SPARC_REGISTER) &&
1342					    (reltype != R_SPARC_RELATIVE))
1343						badrel++;
1344				} else if (mach == EM_386) {
1345					if ((reltype != R_386_NONE) &&
1346					    (reltype != R_386_RELATIVE))
1347						badrel++;
1348				} else if (mach == EM_AMD64) {
1349					if ((reltype != R_AMD64_NONE) &&
1350					    (reltype != R_AMD64_RELATIVE))
1351						badrel++;
1352				}
1353
1354				if (badrel) {
1355					(void) fprintf(stderr,
1356					    MSG_INTL(MSG_ERR_BADREL1), file,
1357					    conv_reloc_type(mach, reltype, 0));
1358				}
1359			}
1360
1361			Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP,
1362			    MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type,
1363			    rels, relname, symname, 0);
1364		}
1365	}
1366}
1367
1368/*
1369 * Search for and process a .dynamic section.
1370 */
1371static void
1372dynamic(Cache *cache, Word shnum, Ehdr *ehdr, const char *file)
1373{
1374	Word	cnt;
1375
1376	for (cnt = 1; cnt < shnum; cnt++) {
1377		Dyn	*dyn;
1378		ulong_t	numdyn;
1379		int	ndx;
1380		Cache	*_cache = &cache[cnt], *strsec;
1381		Shdr	*shdr = _cache->c_shdr;
1382
1383		if (shdr->sh_type != SHT_DYNAMIC)
1384			continue;
1385
1386		/*
1387		 * Verify the associated string table section.
1388		 */
1389		if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0)
1390			continue;
1391
1392		numdyn = shdr->sh_size / shdr->sh_entsize;
1393		dyn = (Dyn *)_cache->c_data->d_buf;
1394
1395		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1396		dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name);
1397
1398		Elf_dyn_title(0);
1399
1400		for (ndx = 0; ndx < numdyn; dyn++, ndx++) {
1401			const char	*name;
1402
1403			/*
1404			 * Print the information numerically, and if possible
1405			 * as a string.
1406			 */
1407			if ((dyn->d_tag == DT_NEEDED) ||
1408			    (dyn->d_tag == DT_SONAME) ||
1409			    (dyn->d_tag == DT_FILTER) ||
1410			    (dyn->d_tag == DT_AUXILIARY) ||
1411			    (dyn->d_tag == DT_CONFIG) ||
1412			    (dyn->d_tag == DT_RPATH) ||
1413			    (dyn->d_tag == DT_RUNPATH) ||
1414			    (dyn->d_tag == DT_USED) ||
1415			    (dyn->d_tag == DT_DEPAUDIT) ||
1416			    (dyn->d_tag == DT_AUDIT) ||
1417			    (dyn->d_tag == DT_SUNW_AUXILIARY) ||
1418			    (dyn->d_tag == DT_SUNW_FILTER))
1419				name = string(_cache, ndx, strsec,
1420				    file, dyn->d_un.d_ptr);
1421			else if (dyn->d_tag == DT_FLAGS)
1422				name = conv_dyn_flag(dyn->d_un.d_val, 0);
1423			else if (dyn->d_tag == DT_FLAGS_1)
1424				name = conv_dyn_flag1(dyn->d_un.d_val);
1425			else if (dyn->d_tag == DT_POSFLAG_1)
1426				name = conv_dyn_posflag1(dyn->d_un.d_val, 0);
1427			else if (dyn->d_tag == DT_FEATURE_1)
1428				name = conv_dyn_feature1(dyn->d_un.d_val, 0);
1429			else if (dyn->d_tag == DT_DEPRECATED_SPARC_REGISTER)
1430				name = MSG_INTL(MSG_STR_DEPRECATED);
1431			else
1432				name = MSG_ORIG(MSG_STR_EMPTY);
1433
1434			Elf_dyn_entry(0, dyn, ndx, name, ehdr->e_machine);
1435		}
1436	}
1437}
1438
1439/*
1440 * Search for and process a MOVE section.
1441 */
1442static void
1443move(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags)
1444{
1445	Word		cnt;
1446	const char	*fmt = 0;
1447
1448	for (cnt = 1; cnt < shnum; cnt++) {
1449		Word	movenum, symnum, ndx;
1450		Sym	*syms;
1451		Cache	*_cache = &cache[cnt];
1452		Shdr	*shdr = _cache->c_shdr;
1453		Cache	*symsec, *strsec;
1454		Move	*move;
1455
1456		if (shdr->sh_type != SHT_SUNW_move)
1457			continue;
1458		if (name && strcmp(name, _cache->c_name))
1459			continue;
1460
1461		/*
1462		 * Determine the move data and number.
1463		 */
1464		if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
1465			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1466			    file, _cache->c_name);
1467			continue;
1468		}
1469		move = (Move *)_cache->c_data->d_buf;
1470		movenum = shdr->sh_size / shdr->sh_entsize;
1471
1472		/*
1473		 * Get the data buffer for the associated symbol table and
1474		 * string table.
1475		 */
1476		if (stringtbl(cache, 1, cnt, shnum, file,
1477		    &symnum, &symsec, &strsec) == 0)
1478			return;
1479
1480		syms = (Sym *)symsec->c_data->d_buf;
1481
1482		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1483		dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name);
1484		dbg_print(0, MSG_INTL(MSG_MOVE_TITLE));
1485
1486		if (fmt == 0)
1487			fmt = MSG_INTL(MSG_MOVE_ENTRY);
1488
1489		for (ndx = 0; ndx < movenum; move++, ndx++) {
1490			const char	*symname;
1491			char		index[MAXNDXSIZE], section[BUFSIZ];
1492			Word		symndx, shndx;
1493			Sym		*sym;
1494
1495			/*
1496			 * Check for null entries
1497			 */
1498			if ((move->m_info == 0) && (move->m_value == 0) &&
1499			    (move->m_poffset == 0) && (move->m_repeat == 0) &&
1500			    (move->m_stride == 0)) {
1501				dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY),
1502				    EC_XWORD(move->m_poffset), 0, 0, 0,
1503				    EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY));
1504				continue;
1505			}
1506			if (((symndx = ELF_M_SYM(move->m_info)) == 0) ||
1507			    (symndx >= symnum)) {
1508				(void) fprintf(stderr,
1509				    MSG_INTL(MSG_ERR_BADMINFO), file,
1510				    _cache->c_name, EC_XWORD(move->m_info));
1511
1512				(void) snprintf(index, MAXNDXSIZE,
1513				    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx));
1514				dbg_print(0, fmt, index,
1515				    EC_XWORD(move->m_poffset),
1516				    ELF_M_SIZE(move->m_info), move->m_repeat,
1517				    move->m_stride, move->m_value,
1518				    MSG_INTL(MSG_STR_UNKNOWN));
1519				continue;
1520			}
1521
1522			symname = relsymname(cache, _cache, strsec,
1523			    symndx, symnum, ndx, syms, section, BUFSIZ, file,
1524			    flags);
1525			sym = (Sym *)(syms + symndx);
1526
1527			/*
1528			 * Additional sanity check.
1529			 */
1530			shndx = sym->st_shndx;
1531			if (!((shndx == SHN_COMMON) ||
1532			    (((shndx >= 1) && (shndx <= shnum)) &&
1533			    (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) {
1534				(void) fprintf(stderr,
1535				    MSG_INTL(MSG_ERR_BADSYM2), file,
1536				    _cache->c_name, demangle(symname, flags));
1537			}
1538
1539			(void) snprintf(index, MAXNDXSIZE,
1540			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx));
1541			dbg_print(0, fmt, index, EC_XWORD(move->m_poffset),
1542			    ELF_M_SIZE(move->m_info), move->m_repeat,
1543			    move->m_stride, move->m_value,
1544			    demangle(symname, flags));
1545		}
1546	}
1547}
1548
1549/*
1550 * Traverse a note section analyzing each note information block.
1551 * The data buffers size is used to validate references before they are made,
1552 * and is decremented as each element is processed.
1553 */
1554void
1555note_entry(Cache *cache, Word *data, size_t size, const char *file)
1556{
1557	size_t	bsize = size;
1558
1559	/*
1560	 * Print out a single `note' information block.
1561	 */
1562	while (size > 0) {
1563		size_t	namesz, descsz, type, pad, noteoff;
1564
1565		noteoff = bsize - size;
1566		/*
1567		 * Make sure we can at least reference the 3 initial entries
1568		 * (4-byte words) of the note information block.
1569		 */
1570		if (size >= (sizeof (Word) * 3))
1571			size -= (sizeof (Word) * 3);
1572		else {
1573			(void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ),
1574			    file, cache->c_name, EC_WORD(noteoff));
1575			return;
1576		}
1577
1578		/*
1579		 * Make sure any specified name string can be referenced.
1580		 */
1581		if ((namesz = *data++) != 0) {
1582			if (size >= namesz)
1583				size -= namesz;
1584			else {
1585				(void) fprintf(stderr,
1586				    MSG_INTL(MSG_NOTE_BADNMSZ), file,
1587				    cache->c_name, EC_WORD(noteoff),
1588				    EC_WORD(namesz));
1589				return;
1590			}
1591		}
1592
1593		/*
1594		 * Make sure any specified descriptor can be referenced.
1595		 */
1596		if ((descsz = *data++) != 0) {
1597			/*
1598			 * If namesz isn't a 4-byte multiple, account for any
1599			 * padding that must exist before the descriptor.
1600			 */
1601			if ((pad = (namesz & (sizeof (Word) - 1))) != 0) {
1602				pad = sizeof (Word) - pad;
1603				size -= pad;
1604			}
1605			if (size >= descsz)
1606				size -= descsz;
1607			else {
1608				(void) fprintf(stderr,
1609				    MSG_INTL(MSG_NOTE_BADDESZ), file,
1610				    cache->c_name, EC_WORD(noteoff),
1611				    EC_WORD(namesz));
1612				return;
1613			}
1614		}
1615
1616		type = *data++;
1617
1618		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1619		dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE), EC_WORD(type));
1620
1621		dbg_print(0, MSG_ORIG(MSG_NOTE_NAMESZ), EC_WORD(namesz));
1622		if (namesz) {
1623			char	*name = (char *)data;
1624
1625			/*
1626			 * Since the name string may have 'null' bytes
1627			 * in it (ia32 .string) - we just write the
1628			 * whole stream in a single fwrite.
1629			 */
1630			(void) fwrite(name, namesz, 1, stdout);
1631			name = name + ((namesz + (sizeof (Word) - 1)) &
1632			    ~(sizeof (Word) - 1));
1633			/* LINTED */
1634			data = (Word *)name;
1635			dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1636		}
1637
1638		/*
1639		 * If multiple information blocks exist within a .note section
1640		 * account for any padding that must exist before the next
1641		 * information block.
1642		 */
1643		if ((pad = (descsz & (sizeof (Word) - 1))) != 0) {
1644			pad = sizeof (Word) - pad;
1645			if (size > pad)
1646				size -= pad;
1647		}
1648
1649		dbg_print(0, MSG_ORIG(MSG_NOTE_DESCSZ), EC_WORD(descsz));
1650		if (descsz) {
1651			int		ndx, byte, word;
1652			char		string[58], *str = string;
1653			uchar_t		*desc = (uchar_t *)data;
1654
1655			/*
1656			 * Dump descriptor bytes.
1657			 */
1658			for (ndx = byte = word = 0; descsz; descsz--, desc++) {
1659				int	tok = *desc;
1660
1661				(void) snprintf(str, 58, MSG_ORIG(MSG_NOTE_TOK),
1662				    tok);
1663				str += 3;
1664
1665				if (++byte == 4) {
1666					*str++ = ' ', *str++ = ' ';
1667					word++;
1668					byte = 0;
1669				}
1670				if (word == 4) {
1671					*str = '\0';
1672					dbg_print(0, MSG_ORIG(MSG_NOTE_DESC),
1673					    ndx, string);
1674					word = 0;
1675					ndx += 16;
1676					str = string;
1677				}
1678			}
1679			if (byte || word) {
1680				*str = '\0';
1681				dbg_print(0, MSG_ORIG(MSG_NOTE_DESC),
1682				    ndx, string);
1683			}
1684
1685			desc += pad;
1686			/* LINTED */
1687			data = (Word *)desc;
1688		}
1689	}
1690}
1691
1692/*
1693 * Search for and process a .note section.
1694 */
1695static void
1696note(Cache *cache, Word shnum, const char *name, const char *file)
1697{
1698	Word	cnt;
1699
1700	/*
1701	 * Otherwise look for any .note sections.
1702	 */
1703	for (cnt = 1; cnt < shnum; cnt++) {
1704		Cache	*_cache = &cache[cnt];
1705		Shdr	*shdr = _cache->c_shdr;
1706
1707		if (shdr->sh_type != SHT_NOTE)
1708			continue;
1709		if (name && strcmp(name, _cache->c_name))
1710			continue;
1711
1712		/*
1713		 * As these sections are often hand rolled, make sure they're
1714		 * properly aligned before proceeding.
1715		 */
1716		if (shdr->sh_offset & (sizeof (Word) - 1)) {
1717			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN),
1718			    file, _cache->c_name);
1719			continue;
1720		}
1721
1722		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1723		dbg_print(0, MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name);
1724		note_entry(_cache, (Word *)_cache->c_data->d_buf,
1725		/* LINTED */
1726		    (Word)_cache->c_data->d_size, file);
1727	}
1728}
1729
1730/*
1731 * Determine an individual hash entry.  This may be the initial hash entry,
1732 * or an associated chain entry.
1733 */
1734static void
1735hash_entry(Cache *refsec, Cache *strsec, const char *hsecname, Word hashndx,
1736    Word symndx, Word symn, Sym *syms, const char *file, ulong_t bkts,
1737    uint_t flags, int chain)
1738{
1739	Sym		*sym;
1740	const char	*symname, *str;
1741	char		_bucket[MAXNDXSIZE], _symndx[MAXNDXSIZE];
1742	ulong_t		nbkt, nhash;
1743
1744	if (symndx > symn) {
1745		(void) fprintf(stderr, MSG_INTL(MSG_ERR_HSBADSYMNDX), file,
1746		    EC_WORD(symndx), EC_WORD(hashndx));
1747		symname = MSG_INTL(MSG_STR_UNKNOWN);
1748	} else {
1749		sym = (Sym *)(syms + symndx);
1750		symname = string(refsec, symndx, strsec, file, sym->st_name);
1751	}
1752
1753	if (chain == 0) {
1754		(void) snprintf(_bucket, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER),
1755		    hashndx);
1756		str = (const char *)_bucket;
1757	} else
1758		str = MSG_ORIG(MSG_STR_EMPTY);
1759
1760	(void) snprintf(_symndx, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX2),
1761	    EC_WORD(symndx));
1762	dbg_print(0, MSG_ORIG(MSG_FMT_HASH_INFO), str, _symndx,
1763	    demangle(symname, flags));
1764
1765	/*
1766	 * Determine if this string is in the correct bucket.
1767	 */
1768	nhash = elf_hash(symname);
1769	nbkt = nhash % bkts;
1770
1771	if (nbkt != hashndx) {
1772		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADHASH), file,
1773		    hsecname, symname, EC_WORD(hashndx), nbkt);
1774	}
1775}
1776
1777#define	MAXCOUNT	500
1778
1779static void
1780hash(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags)
1781{
1782	static int	count[MAXCOUNT];
1783	Word		cnt;
1784	ulong_t		ndx, bkts;
1785	char		number[MAXNDXSIZE];
1786
1787	for (cnt = 1; cnt < shnum; cnt++) {
1788		uint_t		*hash, *chain;
1789		Cache		*_cache = &cache[cnt];
1790		Shdr		*sshdr, *hshdr = _cache->c_shdr;
1791		char		*ssecname, *hsecname = _cache->c_name;
1792		Sym		*syms;
1793		Word		symn;
1794
1795		if (hshdr->sh_type != SHT_HASH)
1796			continue;
1797		if (name && strcmp(name, hsecname))
1798			continue;
1799
1800		/*
1801		 * Determine the hash table data and size.
1802		 */
1803		if ((hshdr->sh_entsize == 0) || (hshdr->sh_size == 0)) {
1804			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1805			    file, hsecname);
1806			continue;
1807		}
1808		hash = (uint_t *)_cache->c_data->d_buf;
1809		bkts = *hash;
1810		chain = hash + 2 + bkts;
1811		hash += 2;
1812
1813		/*
1814		 * Get the data buffer for the associated symbol table.
1815		 */
1816		if ((hshdr->sh_link == 0) || (hshdr->sh_link >= shnum)) {
1817			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
1818			    file, hsecname, EC_WORD(hshdr->sh_link));
1819			continue;
1820		}
1821
1822		_cache = &cache[hshdr->sh_link];
1823		ssecname = _cache->c_name;
1824
1825		if ((syms = (Sym *)_cache->c_data->d_buf) == 0) {
1826			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1827			    file, ssecname);
1828			continue;
1829		}
1830
1831		sshdr = _cache->c_shdr;
1832		/* LINTED */
1833		symn = (Word)(sshdr->sh_size / sshdr->sh_entsize);
1834
1835		/*
1836		 * Get the associated string table section.
1837		 */
1838		if ((sshdr->sh_link == 0) || (sshdr->sh_link >= shnum)) {
1839			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
1840			    file, ssecname, EC_WORD(sshdr->sh_link));
1841			continue;
1842		}
1843
1844		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1845		dbg_print(0, MSG_INTL(MSG_ELF_SCN_HASH), hsecname);
1846		dbg_print(0, MSG_INTL(MSG_ELF_HASH_INFO));
1847
1848		/*
1849		 * Loop through the hash buckets, printing the appropriate
1850		 * symbols.
1851		 */
1852		for (ndx = 0; ndx < bkts; ndx++, hash++) {
1853			Word	_ndx, _cnt;
1854
1855			if (*hash == 0) {
1856				count[0]++;
1857				continue;
1858			}
1859
1860			hash_entry(_cache, &cache[sshdr->sh_link], hsecname,
1861			    ndx, *hash, symn, syms, file, bkts, flags, 0);
1862
1863			/*
1864			 * Determine if any other symbols are chained to this
1865			 * bucket.
1866			 */
1867			_ndx = chain[*hash];
1868			_cnt = 1;
1869			while (_ndx) {
1870				hash_entry(_cache, &cache[sshdr->sh_link],
1871				    hsecname, ndx, _ndx, symn, syms, file,
1872				    bkts, flags, 1);
1873				_ndx = chain[_ndx];
1874				_cnt++;
1875			}
1876
1877			if (_cnt >= MAXCOUNT) {
1878				(void) fprintf(stderr,
1879				    MSG_INTL(MSG_HASH_OVERFLW), file,
1880				    _cache->c_name, EC_WORD(ndx),
1881				    EC_WORD(_cnt));
1882			} else
1883				count[_cnt]++;
1884		}
1885		break;
1886	}
1887
1888	/*
1889	 * Print out the count information.
1890	 */
1891	bkts = cnt = 0;
1892	dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1893
1894	for (ndx = 0; ndx < MAXCOUNT; ndx++) {
1895		Word	_cnt;
1896
1897		if ((_cnt = count[ndx]) == 0)
1898			continue;
1899
1900		(void) snprintf(number, MAXNDXSIZE,
1901		    MSG_ORIG(MSG_FMT_INTEGER), _cnt);
1902		dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS1), number,
1903		    EC_WORD(ndx));
1904		bkts += _cnt;
1905		cnt += (Word)(ndx * _cnt);
1906	}
1907	if (cnt) {
1908		(void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER),
1909		    bkts);
1910		dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS2), number,
1911		    EC_WORD(cnt));
1912	}
1913}
1914
1915static void
1916group(Cache *cache, Word shnum, const char *name, const char *file,
1917    uint_t flags)
1918{
1919	Word	scnt;
1920
1921	for (scnt = 1; scnt < shnum; scnt++) {
1922		Cache	*_cache = &cache[scnt];
1923		Shdr	*shdr = _cache->c_shdr;
1924		Word	*grpdata, gcnt, grpcnt, symnum, unknown;
1925		Cache	*symsec, *strsec;
1926		Sym	*syms, *sym;
1927		char	flgstrbuf[MSG_GRP_COMDAT_SIZE + 10];
1928
1929		if (shdr->sh_type != SHT_GROUP)
1930			continue;
1931		if (name && strcmp(name, _cache->c_name))
1932			continue;
1933		if ((_cache->c_data == 0) ||
1934		    ((grpdata = (Word *)_cache->c_data->d_buf) == 0))
1935			continue;
1936		grpcnt = shdr->sh_size / sizeof (Word);
1937
1938		/*
1939		 * Get the data buffer for the associated symbol table and
1940		 * string table.
1941		 */
1942		if (stringtbl(cache, 1, scnt, shnum, file,
1943		    &symnum, &symsec, &strsec) == 0)
1944			return;
1945
1946		syms = symsec->c_data->d_buf;
1947
1948		dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1949		dbg_print(0, MSG_INTL(MSG_ELF_SCN_GRP), _cache->c_name);
1950		dbg_print(0, MSG_INTL(MSG_GRP_TITLE));
1951
1952		/*
1953		 * The first element of the group defines the group.  The
1954		 * associated symbol is defined by the sh_link field.
1955		 */
1956		if ((shdr->sh_info == SHN_UNDEF) || (shdr->sh_info > symnum)) {
1957			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO),
1958			    file, _cache->c_name, EC_WORD(shdr->sh_info));
1959			return;
1960		}
1961
1962		(void) strcpy(flgstrbuf, MSG_ORIG(MSG_STR_OSQBRKT));
1963		if (grpdata[0] & GRP_COMDAT) {
1964			(void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_COMDAT));
1965		}
1966		if ((unknown = (grpdata[0] & ~GRP_COMDAT)) != 0) {
1967			size_t	len = strlen(flgstrbuf);
1968
1969			(void) snprintf(&flgstrbuf[len],
1970			    (MSG_GRP_COMDAT_SIZE + 10 - len),
1971			    MSG_ORIG(MSG_GRP_UNKNOWN), unknown);
1972		}
1973		(void) strcat(flgstrbuf, MSG_ORIG(MSG_STR_CSQBRKT));
1974		sym = (Sym *)(syms + shdr->sh_info);
1975
1976		dbg_print(0, MSG_INTL(MSG_GRP_SIGNATURE), flgstrbuf,
1977		    demangle(string(_cache, 0, strsec, file, sym->st_name),
1978		    flags));
1979
1980		for (gcnt = 1; gcnt < grpcnt; gcnt++) {
1981			char		index[MAXNDXSIZE];
1982			const char	*name;
1983
1984			(void) snprintf(index, MAXNDXSIZE,
1985			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(gcnt));
1986
1987			if (grpdata[gcnt] >= shnum)
1988				name = MSG_INTL(MSG_GRP_INVALSCN);
1989			else
1990				name = cache[grpdata[gcnt]].c_name;
1991
1992			(void) printf(MSG_ORIG(MSG_GRP_ENTRY), index, name,
1993				EC_XWORD(grpdata[gcnt]));
1994		}
1995	}
1996}
1997
1998static void
1999got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, uint_t flags)
2000{
2001	Cache		*gotcache = 0, *symtab = 0, *_cache;
2002	Addr		gotbgn, gotend;
2003	Shdr		*gotshdr;
2004	Word		cnt, gotents, gotndx;
2005	size_t		gentsize;
2006	Got_info	*gottable;
2007	char		*gotdata;
2008	Sym		*gotsym;
2009	Xword		gotsymaddr;
2010
2011	/*
2012	 * First, find the got.
2013	 */
2014	for (cnt = 1; cnt < shnum; cnt++) {
2015		_cache = &cache[cnt];
2016		if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT),
2017		    MSG_ELF_GOT_SIZE) == 0) {
2018			gotcache = _cache;
2019			break;
2020		}
2021	}
2022	if (gotcache == 0)
2023		return;
2024
2025	/*
2026	 * A got section within a relocatable object is suspicious.
2027	 */
2028	if (ehdr->e_type == ET_REL) {
2029		(void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file,
2030		    _cache->c_name);
2031	}
2032
2033	gotshdr = gotcache->c_shdr;
2034	if (gotshdr->sh_size == 0) {
2035		(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
2036		    file, gotcache->c_name);
2037		return;
2038	}
2039
2040	gotbgn = gotshdr->sh_addr;
2041	gotend = gotbgn + gotshdr->sh_size;
2042
2043	/*
2044	 * Some architectures don't properly set the sh_entsize for the GOT
2045	 * table.  If it's not set, default to a size of a pointer.
2046	 */
2047	if ((gentsize = gotshdr->sh_entsize) == 0)
2048		gentsize = sizeof (Xword);
2049
2050	/* LINTED */
2051	gotents = (Word)(gotshdr->sh_size / gentsize);
2052	gotdata = gotcache->c_data->d_buf;
2053
2054	if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) {
2055		int err = errno;
2056		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), file,
2057		    strerror(err));
2058		return;
2059	}
2060
2061	/*
2062	 * Now we scan through all the sections looking for any relocations
2063	 * that may be against the GOT.  Since these may not be isolated to a
2064	 * .rel[a].got section we check them all.
2065	 * While scanning sections save the symbol table entry (a symtab
2066	 * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_.
2067	 */
2068	for (cnt = 1; cnt < shnum; cnt++) {
2069		Word		type, symnum;
2070		Xword		relndx, relnum, relsize;
2071		void		*rels;
2072		Sym		*syms;
2073		Cache		*symsec, *strsec;
2074		Cache		*_cache = &cache[cnt];
2075		Shdr		*shdr;
2076
2077		shdr = _cache->c_shdr;
2078		type = shdr->sh_type;
2079
2080		if ((symtab == 0) && (type == SHT_DYNSYM)) {
2081			symtab = _cache;
2082			continue;
2083		}
2084		if (type == SHT_SYMTAB) {
2085			symtab = _cache;
2086			continue;
2087		}
2088		if ((type != SHT_RELA) && (type != SHT_REL))
2089			continue;
2090
2091		/*
2092		 * Decide entry size.
2093		 */
2094		if (((relsize = shdr->sh_entsize) == 0) ||
2095		    (relsize > shdr->sh_size)) {
2096			if (type == SHT_RELA)
2097				relsize = sizeof (Rela);
2098			else
2099				relsize = sizeof (Rel);
2100		}
2101
2102		/*
2103		 * Determine the number of relocations available.
2104		 */
2105		if (shdr->sh_size == 0) {
2106			(void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
2107			    file, _cache->c_name);
2108			continue;
2109		}
2110		rels = _cache->c_data->d_buf;
2111		relnum = shdr->sh_size / relsize;
2112
2113		/*
2114		 * Get the data buffer for the associated symbol table and
2115		 * string table.
2116		 */
2117		if (stringtbl(cache, 1, cnt, shnum, file,
2118		    &symnum, &symsec, &strsec) == 0)
2119			continue;
2120
2121		syms = symsec->c_data->d_buf;
2122
2123		/*
2124		 * Loop through the relocation entries.
2125		 */
2126		for (relndx = 0; relndx < relnum; relndx++,
2127		    rels = (void *)((char *)rels + relsize)) {
2128			char		section[BUFSIZ];
2129			Addr		offset;
2130			Got_info	*gip;
2131			Word		symndx, reltype;
2132			Rela		*rela;
2133			Rel		*rel;
2134
2135			/*
2136			 * Unravel the relocation.
2137			 */
2138			if (type == SHT_RELA) {
2139				rela = (Rela *)rels;
2140				symndx = ELF_R_SYM(rela->r_info);
2141				reltype = ELF_R_TYPE(rela->r_info);
2142				offset = rela->r_offset;
2143			} else {
2144				rel = (Rel *)rels;
2145				symndx = ELF_R_SYM(rel->r_info);
2146				reltype = ELF_R_TYPE(rel->r_info);
2147				offset = rel->r_offset;
2148			}
2149
2150			/*
2151			 * Only pay attention to relocations against the GOT.
2152			 */
2153			if ((offset < gotbgn) || (offset > gotend))
2154				continue;
2155
2156			/* LINTED */
2157			gotndx = (Word)((offset - gotbgn) /
2158			    gotshdr->sh_entsize);
2159			gip = &gottable[gotndx];
2160
2161			if (gip->g_reltype != 0) {
2162				(void) fprintf(stderr,
2163				    MSG_INTL(MSG_GOT_MULTIPLE), file,
2164				    EC_WORD(gotndx), EC_ADDR(offset));
2165				continue;
2166			}
2167
2168			if (symndx)
2169				gip->g_symname = relsymname(cache, _cache,
2170				    strsec, symndx, symnum, relndx, syms,
2171				    section, BUFSIZ, file, flags);
2172			gip->g_reltype = reltype;
2173			gip->g_rel = rels;
2174		}
2175	}
2176
2177	if (symlookup(MSG_ORIG(MSG_GOT_SYM), cache, shnum, &gotsym, symtab,
2178	    file))
2179		gotsymaddr = gotsym->st_value;
2180	else
2181		gotsymaddr = gotbgn;
2182
2183	dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2184	dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name);
2185	Elf_got_title(0);
2186
2187	for (gotndx = 0; gotndx < gotents; gotndx++) {
2188		Got_info	*gip;
2189		Sword		gindex;
2190		Addr		gaddr;
2191		Xword		gotentry;
2192
2193		gip = &gottable[gotndx];
2194
2195		gaddr = gotbgn + (gotndx * gentsize);
2196		gindex = (Sword)(gaddr - gotsymaddr) / (Sword)gentsize;
2197
2198		if (gentsize == sizeof (Word))
2199			/* LINTED */
2200			gotentry = (Xword)(*((Word *)(gotdata) + gotndx));
2201		else
2202			/* LINTED */
2203			gotentry = *((Xword *)(gotdata) + gotndx);
2204
2205		Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine,
2206		    gip->g_reltype, gip->g_rel, gip->g_symname);
2207	}
2208	free(gottable);
2209}
2210
2211void
2212checksum(Elf *elf)
2213{
2214	dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2215	dbg_print(0, MSG_INTL(MSG_STR_CHECKSUM), elf_checksum(elf));
2216}
2217
2218void
2219regular(const char *file, Elf *elf, uint_t flags, char *Nname, int wfd)
2220{
2221	Elf_Scn		*scn;
2222	Ehdr		*ehdr;
2223	Elf_Data	*data;
2224	size_t		cnt, shstrndx, shnum, phnum;
2225	Shdr		*nameshdr, *shdr;
2226	char		*names = 0;
2227	Cache		*cache, *_cache;
2228	Cache		*versymcache = 0;
2229
2230	if ((ehdr = elf_getehdr(elf)) == NULL) {
2231		failure(file, MSG_ORIG(MSG_ELF_GETEHDR));
2232		return;
2233	}
2234
2235	if (elf_getshnum(elf, &shnum) == 0) {
2236		failure(file, MSG_ORIG(MSG_ELF_GETSHNUM));
2237		return;
2238	}
2239
2240	if (elf_getshstrndx(elf, &shstrndx) == 0) {
2241		failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX));
2242		return;
2243	}
2244
2245	if (elf_getphnum(elf, &phnum) == 0) {
2246		failure(file, MSG_ORIG(MSG_ELF_GETPHNUM));
2247		return;
2248	}
2249
2250	if ((scn = elf_getscn(elf, 0)) != NULL) {
2251		if ((shdr = elf_getshdr(scn)) == NULL) {
2252			failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
2253			(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0);
2254			return;
2255		}
2256	} else
2257		shdr = 0;
2258
2259	/*
2260	 * Print the elf header.
2261	 */
2262	if (flags & FLG_EHDR)
2263		Elf_ehdr(0, ehdr, shdr);
2264
2265	/*
2266	 * Print the program headers.
2267	 */
2268	if ((flags & FLG_PHDR) && (phnum != 0)) {
2269		Phdr *phdr;
2270
2271		if ((phdr = elf_getphdr(elf)) == NULL) {
2272			failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
2273			return;
2274		}
2275
2276		for (cnt = 0; cnt < phnum; phdr++, cnt++) {
2277			dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2278			dbg_print(0, MSG_INTL(MSG_ELF_PHDR), EC_WORD(cnt));
2279			Elf_phdr(0, ehdr->e_machine, phdr);
2280		}
2281	}
2282
2283
2284	/*
2285	 * Return now if there are no section, if there's just one section to
2286	 * act as an extension of the ELF header, or if on section information
2287	 * was requested.
2288	 */
2289	if ((shnum <= 1) || (flags && (flags & ~(FLG_EHDR | FLG_PHDR)) == 0)) {
2290		if ((ehdr->e_type == ET_CORE) && (flags & FLG_NOTE))
2291			note(0, shnum, 0, file);
2292		return;
2293	}
2294
2295
2296	/*
2297	 * Obtain the .shstrtab data buffer to provide the required section
2298	 * name strings.
2299	 */
2300	if ((scn = elf_getscn(elf, shstrndx)) == NULL) {
2301		failure(file, MSG_ORIG(MSG_ELF_GETSCN));
2302		(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR),
2303		    EC_XWORD(shstrndx));
2304
2305	} else if ((data = elf_getdata(scn, NULL)) == NULL) {
2306		failure(file, MSG_ORIG(MSG_ELF_GETDATA));
2307		(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA),
2308		    EC_XWORD(shstrndx));
2309
2310	} else if ((nameshdr = elf_getshdr(scn)) == NULL) {
2311		failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
2312		(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN),
2313		    /* LINTED */
2314		    (int)elf_ndxscn(scn));
2315
2316	} else if ((names = data->d_buf) == 0)
2317		(void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file);
2318
2319	/*
2320	 * Fill in the cache descriptor with information for each section.
2321	 */
2322	if ((cache = malloc(shnum * sizeof (Cache))) == 0) {
2323		int err = errno;
2324		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
2325		    file, strerror(err));
2326		return;
2327	}
2328
2329	*cache = cache_init;
2330	_cache = cache;
2331	_cache++;
2332
2333	for (cnt = 1, scn = NULL; scn = elf_nextscn(elf, scn);
2334	    cnt++, _cache++) {
2335		if ((_cache->c_shdr = elf_getshdr(scn)) == NULL) {
2336			failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
2337			(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN),
2338			    /* LINTED */
2339			    (int)elf_ndxscn(scn));
2340		}
2341
2342		if (names && _cache->c_shdr->sh_name &&
2343		    /* LINTED */
2344		    (nameshdr->sh_size > _cache->c_shdr->sh_name))
2345			_cache->c_name = names + _cache->c_shdr->sh_name;
2346		else {
2347			/*
2348			 * If there exists no shstrtab data, or a section header
2349			 * has no name (an invalid index of 0), then compose a
2350			 * name for each section.
2351			 */
2352			char	scnndxnm[100];
2353
2354			(void) snprintf(scnndxnm, 100, MSG_INTL(MSG_FMT_SCNNDX),
2355			    cnt);
2356
2357			/*
2358			 * Although we have a valid shstrtab section inform the
2359			 * user if this section name index exceeds the shstrtab
2360			 * data.
2361			 */
2362			if (names &&
2363			    /* LINTED */
2364			    (nameshdr->sh_size <= _cache->c_shdr->sh_name)) {
2365				(void) fprintf(stderr,
2366				    MSG_INTL(MSG_ERR_BADSHNAME), file,
2367				    _cache->c_name,
2368				    EC_XWORD(_cache->c_shdr->sh_name));
2369			}
2370
2371			if ((_cache->c_name =
2372			    malloc(strlen(scnndxnm) + 1)) == 0) {
2373				int err = errno;
2374				(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
2375				    file, strerror(err));
2376				return;
2377			}
2378			(void) strcpy(_cache->c_name, scnndxnm);
2379		}
2380
2381		if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) {
2382			failure(file, MSG_ORIG(MSG_ELF_GETDATA));
2383			(void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA),
2384			    /* LINTED */
2385			    (int)elf_ndxscn(scn));
2386		}
2387
2388		/*
2389		 * Do we wish to write the section out?
2390		 */
2391		if (wfd && Nname && (strcmp(Nname, _cache->c_name) == 0)) {
2392			(void) write(wfd, _cache->c_data->d_buf,
2393			    _cache->c_data->d_size);
2394		}
2395	}
2396
2397	if (flags & FLG_SHDR)
2398		sections(file, cache, shnum, ehdr, Nname);
2399
2400	if (flags & FLG_INTERP)
2401		interp(file, cache, shnum, phnum, elf);
2402
2403	versymcache = versions(cache, shnum, file, flags);
2404
2405	if (flags & FLG_SYMBOLS)
2406		symbols(cache, shnum, ehdr, Nname, versymcache, file, flags);
2407
2408	if (flags & FLG_HASH)
2409		hash(cache, shnum, Nname, file, flags);
2410
2411	if (flags & FLG_GOT)
2412		got(cache, shnum, ehdr, file, flags);
2413
2414	if (flags & FLG_GROUP)
2415		group(cache, shnum, Nname, file, flags);
2416
2417	if (flags & FLG_SYMINFO)
2418		syminfo(cache, shnum, file);
2419
2420	if (flags & FLG_RELOC)
2421		reloc(cache, shnum, ehdr, Nname, file, flags);
2422
2423	if (flags & FLG_DYNAMIC)
2424		dynamic(cache, shnum, ehdr, file);
2425
2426	if (flags & FLG_NOTE)
2427		note(cache, shnum, Nname, file);
2428
2429	if (flags & FLG_MOVE)
2430		move(cache, shnum, Nname, file, flags);
2431
2432	if (flags & FLG_CHECKSUM)
2433		checksum(elf);
2434
2435	if (flags & FLG_CAP)
2436		cap(file, cache, shnum, phnum, ehdr, elf);
2437
2438	if (flags & FLG_UNWIND)
2439		unwind(cache, shnum, phnum, ehdr, Nname, file, elf);
2440
2441	free(cache);
2442}
2443