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