1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  *	Copyright (c) 1988 AT&T
24*0Sstevel@tonic-gate  *	  All Rights Reserved
25*0Sstevel@tonic-gate  *
26*0Sstevel@tonic-gate  */
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate /*
29*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
30*0Sstevel@tonic-gate  * Use is subject to license terms.
31*0Sstevel@tonic-gate  */
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include <stdio.h>
36*0Sstevel@tonic-gate #include <stdlib.h>
37*0Sstevel@tonic-gate #include <locale.h>
38*0Sstevel@tonic-gate #include <unistd.h>
39*0Sstevel@tonic-gate #include <libelf.h>
40*0Sstevel@tonic-gate #include <link.h>
41*0Sstevel@tonic-gate #include <sys/elf_M32.h>
42*0Sstevel@tonic-gate #include <sys/elf_386.h>
43*0Sstevel@tonic-gate #include <sys/elf_SPARC.h>
44*0Sstevel@tonic-gate #include <sys/machelf.h>
45*0Sstevel@tonic-gate #include <fcntl.h>
46*0Sstevel@tonic-gate #include <sys/stat.h>
47*0Sstevel@tonic-gate #include <errno.h>
48*0Sstevel@tonic-gate #include <string.h>
49*0Sstevel@tonic-gate #include "sgs.h"
50*0Sstevel@tonic-gate #include "conv.h"
51*0Sstevel@tonic-gate #include "dump.h"
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate #define	OPTSTR	"agcd:fhn:oprstvCLT:V?"		/* option string for getopt() */
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate const char *UNKNOWN = "<unknown>";
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate static SCNTAB *p_symtab, *p_head_scns, *p_dynsym;
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate static int
61*0Sstevel@tonic-gate 	x_flag = 0,	/* option requires section header table */
62*0Sstevel@tonic-gate 	z_flag = 0,	/* process files within an archive */
63*0Sstevel@tonic-gate 	rn_flag = 0;	/* dump named relocation information */
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate static int
66*0Sstevel@tonic-gate 	/* flags: ?_flag corresponds to ? option */
67*0Sstevel@tonic-gate 	a_flag = 0,	/* dump archive header of each member of archive */
68*0Sstevel@tonic-gate 	g_flag = 0,	/* dump archive symbol table */
69*0Sstevel@tonic-gate 	c_flag = 0,	/* dump the string table */
70*0Sstevel@tonic-gate 	d_flag = 0,	/* dump range of sections */
71*0Sstevel@tonic-gate 	f_flag = 0,	/* dump each file header */
72*0Sstevel@tonic-gate 	h_flag = 0,	/* dump section headers */
73*0Sstevel@tonic-gate 	n_flag = 0,	/* dump named section */
74*0Sstevel@tonic-gate 	o_flag = 0,	/* dump each program execution header */
75*0Sstevel@tonic-gate 	r_flag = 0,	/* dump relocation information */
76*0Sstevel@tonic-gate 	s_flag = 0,	/* dump section contents */
77*0Sstevel@tonic-gate 	t_flag = 0,	/* dump symbol table entries */
78*0Sstevel@tonic-gate 	C_flag = 0,	/* dump decoded C++ symbol names */
79*0Sstevel@tonic-gate 	L_flag = 0,	/* dump dynamic linking information */
80*0Sstevel@tonic-gate 	T_flag = 0,	/* dump symbol table range */
81*0Sstevel@tonic-gate 	V_flag = 0;	/* dump version information */
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate int	p_flag = 0,	/* suppress printing of headings */
84*0Sstevel@tonic-gate 	v_flag = 0;	/* print information in verbose form */
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate static int
87*0Sstevel@tonic-gate 	d_low = 0,	/* range for use with -d */
88*0Sstevel@tonic-gate 	d_hi = 0,
89*0Sstevel@tonic-gate 	d_num = 0;
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate static int
92*0Sstevel@tonic-gate 	T_low = 0,	/* range for use with -T */
93*0Sstevel@tonic-gate 	T_hi = 0,
94*0Sstevel@tonic-gate 	T_num = 0;
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate static char *name = NULL; /* for use with -n option */
97*0Sstevel@tonic-gate char *prog_name;
98*0Sstevel@tonic-gate static int errflag = 0;
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate static struct stab_list_s {
101*0Sstevel@tonic-gate 	struct stab_list_s *next;
102*0Sstevel@tonic-gate 	char *strings;
103*0Sstevel@tonic-gate 	size_t size;
104*0Sstevel@tonic-gate } *StringTableList = (void *)0;
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate extern void ar_sym_read();
107*0Sstevel@tonic-gate extern void dump_exec_header();
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate /*
111*0Sstevel@tonic-gate  * Get the section descriptor and set the size of the
112*0Sstevel@tonic-gate  * data returned.  Data is byte-order converted.
113*0Sstevel@tonic-gate  */
114*0Sstevel@tonic-gate void *
115*0Sstevel@tonic-gate get_scndata(Elf_Scn *fd_scn, size_t *size)
116*0Sstevel@tonic-gate {
117*0Sstevel@tonic-gate 	Elf_Data *p_data;
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	p_data = 0;
120*0Sstevel@tonic-gate 	if ((p_data = elf_getdata(fd_scn, p_data)) == 0 ||
121*0Sstevel@tonic-gate 	    p_data->d_size == 0) {
122*0Sstevel@tonic-gate 		return (NULL);
123*0Sstevel@tonic-gate 	}
124*0Sstevel@tonic-gate 	*size = p_data->d_size;
125*0Sstevel@tonic-gate 	return (p_data->d_buf);
126*0Sstevel@tonic-gate }
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate /*
129*0Sstevel@tonic-gate  * Get the section descriptor and set the size of the
130*0Sstevel@tonic-gate  * data returned.  Data is raw (i.e., not byte-order converted).
131*0Sstevel@tonic-gate  */
132*0Sstevel@tonic-gate static void *
133*0Sstevel@tonic-gate get_rawscn(Elf_Scn *fd_scn, size_t *size)
134*0Sstevel@tonic-gate {
135*0Sstevel@tonic-gate 	Elf_Data *p_data;
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 	p_data = 0;
138*0Sstevel@tonic-gate 	if ((p_data = elf_rawdata(fd_scn, p_data)) == 0 ||
139*0Sstevel@tonic-gate 	    p_data->d_size == 0) {
140*0Sstevel@tonic-gate 		return (NULL);
141*0Sstevel@tonic-gate 	}
142*0Sstevel@tonic-gate 
143*0Sstevel@tonic-gate 	*size = p_data->d_size;
144*0Sstevel@tonic-gate 	return (p_data->d_buf);
145*0Sstevel@tonic-gate }
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate /*
148*0Sstevel@tonic-gate  * Print out a usage message in short form when program is invoked
149*0Sstevel@tonic-gate  * with insufficient or no arguments, and in long form when given
150*0Sstevel@tonic-gate  * either a ? or an invalid option.
151*0Sstevel@tonic-gate  */
152*0Sstevel@tonic-gate static void
153*0Sstevel@tonic-gate usage()
154*0Sstevel@tonic-gate {
155*0Sstevel@tonic-gate 	(void) fprintf(stderr,
156*0Sstevel@tonic-gate 	"Usage: %s [-%s] file(s) ...\n", prog_name, OPTSTR);
157*0Sstevel@tonic-gate 	if (errflag) {
158*0Sstevel@tonic-gate 		(void) fprintf(stderr,
159*0Sstevel@tonic-gate 		"\t\t[-a dump archive header of each member of archive]\n\
160*0Sstevel@tonic-gate 		[-g dump archive global symbol table]\n\
161*0Sstevel@tonic-gate 		[-c dump the string table]\n\
162*0Sstevel@tonic-gate 		[-d dump range of sections]\n\
163*0Sstevel@tonic-gate 		[-f dump each file header]\n\
164*0Sstevel@tonic-gate 		[-h dump section headers]\n\
165*0Sstevel@tonic-gate 		[-n dump named section]\n\
166*0Sstevel@tonic-gate 		[-o dump each program execution header]\n\
167*0Sstevel@tonic-gate 		[-p suppress printing of headings]\n\
168*0Sstevel@tonic-gate 		[-r dump relocation information]\n\
169*0Sstevel@tonic-gate 		[-s dump section contents]\n\
170*0Sstevel@tonic-gate 		[-t dump symbol table entries]\n\
171*0Sstevel@tonic-gate 		[-v print information in verbose form]\n\
172*0Sstevel@tonic-gate 		[-C dump decoded C++ symbol names]\n\
173*0Sstevel@tonic-gate 		[-L dump the .dynamic structure]\n\
174*0Sstevel@tonic-gate 		[-T dump symbol table range]\n\
175*0Sstevel@tonic-gate 		[-V dump version information]\n");
176*0Sstevel@tonic-gate 	}
177*0Sstevel@tonic-gate }
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate /*
180*0Sstevel@tonic-gate  * Set a range.  Input is a character string, a lower
181*0Sstevel@tonic-gate  * bound and an upper bound.  This function converts
182*0Sstevel@tonic-gate  * a character string into its correct integer values,
183*0Sstevel@tonic-gate  * setting the first value as the lower bound, and
184*0Sstevel@tonic-gate  * the second value as the upper bound.  If more values
185*0Sstevel@tonic-gate  * are given they are ignored with a warning.
186*0Sstevel@tonic-gate  */
187*0Sstevel@tonic-gate static void
188*0Sstevel@tonic-gate set_range(char *s, int  *low, int  *high)
189*0Sstevel@tonic-gate {
190*0Sstevel@tonic-gate 	char *w;
191*0Sstevel@tonic-gate 	char *lasts;
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate 	while ((w = strtok_r(s, ",", &lasts)) != NULL) {
194*0Sstevel@tonic-gate 		if (!(*low))
195*0Sstevel@tonic-gate 			/* LINTED */
196*0Sstevel@tonic-gate 			*low = (int)atol(w);
197*0Sstevel@tonic-gate 		else
198*0Sstevel@tonic-gate 			if (!(*high))
199*0Sstevel@tonic-gate 				/* LINTED */
200*0Sstevel@tonic-gate 				*high = (int)atol(w);
201*0Sstevel@tonic-gate 			else {
202*0Sstevel@tonic-gate 				(void) fprintf(stderr,
203*0Sstevel@tonic-gate 					"%s: too many arguments - %s ignored\n",
204*0Sstevel@tonic-gate 					prog_name, w);
205*0Sstevel@tonic-gate 				return;
206*0Sstevel@tonic-gate 			}
207*0Sstevel@tonic-gate 		s = NULL;
208*0Sstevel@tonic-gate 	} /* end while */
209*0Sstevel@tonic-gate }
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate /*
213*0Sstevel@tonic-gate  * Print static shared library information.
214*0Sstevel@tonic-gate  */
215*0Sstevel@tonic-gate static void
216*0Sstevel@tonic-gate print_static(SCNTAB *l_scns, char *filename)
217*0Sstevel@tonic-gate {
218*0Sstevel@tonic-gate 	size_t section_size;
219*0Sstevel@tonic-gate 	unsigned char *strtab;
220*0Sstevel@tonic-gate 	unsigned char *path, buf[1024];
221*0Sstevel@tonic-gate 	unsigned long *temp;
222*0Sstevel@tonic-gate 	unsigned long total, topath;
223*0Sstevel@tonic-gate 
224*0Sstevel@tonic-gate 	(void) printf("\n  **** STATIC SHARED LIBRARY INFORMATION ****\n");
225*0Sstevel@tonic-gate 	(void) printf("\n%s:\n", filename);
226*0Sstevel@tonic-gate 	(void) printf("\t");
227*0Sstevel@tonic-gate 	section_size  = 0;
228*0Sstevel@tonic-gate 	if ((strtab = (unsigned char *)
229*0Sstevel@tonic-gate 	    get_scndata(l_scns->p_sd, &section_size)) == NULL) {
230*0Sstevel@tonic-gate 		return;
231*0Sstevel@tonic-gate 	}
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate 	while (section_size != 0) {
234*0Sstevel@tonic-gate 		/* LINTED */
235*0Sstevel@tonic-gate 		temp = (unsigned long *)strtab;
236*0Sstevel@tonic-gate 		total = temp[0];
237*0Sstevel@tonic-gate 		topath = temp[1];
238*0Sstevel@tonic-gate 		path = strtab + (topath*sizeof (long));
239*0Sstevel@tonic-gate 		(void) strncpy((char *)buf, (char *)path,
240*0Sstevel@tonic-gate 			(total - topath)*sizeof (long));
241*0Sstevel@tonic-gate 		(void) fprintf(stdout, "%s\n", buf);
242*0Sstevel@tonic-gate 		strtab += total*sizeof (long);
243*0Sstevel@tonic-gate 		section_size -= (total*sizeof (long));
244*0Sstevel@tonic-gate 	}
245*0Sstevel@tonic-gate }
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate /*
248*0Sstevel@tonic-gate  * Print raw data in hexidecimal.  Input is the section data to
249*0Sstevel@tonic-gate  * be printed out and the size of the data.  Output is relative
250*0Sstevel@tonic-gate  * to a table lookup in dumpmap.h.
251*0Sstevel@tonic-gate  */
252*0Sstevel@tonic-gate static void
253*0Sstevel@tonic-gate print_rawdata(unsigned char *p_sec, size_t size)
254*0Sstevel@tonic-gate {
255*0Sstevel@tonic-gate 	size_t   j;
256*0Sstevel@tonic-gate 	size_t   count;
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 	count = 1;
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 	(void) printf("\t");
261*0Sstevel@tonic-gate 	for (j = size/sizeof (short); j != 0; --j, ++count) {
262*0Sstevel@tonic-gate 		(void) printf("%.2x %.2x ", p_sec[0], p_sec[1]);
263*0Sstevel@tonic-gate 		p_sec += 2;
264*0Sstevel@tonic-gate 		if (count == 12) {
265*0Sstevel@tonic-gate 			(void) printf("\n\t");
266*0Sstevel@tonic-gate 			count = 0;
267*0Sstevel@tonic-gate 		}
268*0Sstevel@tonic-gate 	}
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate 	/*
271*0Sstevel@tonic-gate 	 * take care of last byte if odd byte section
272*0Sstevel@tonic-gate 	 */
273*0Sstevel@tonic-gate 	if ((size & 0x1L) == 1L)
274*0Sstevel@tonic-gate 		(void) printf("%.2x", *p_sec);
275*0Sstevel@tonic-gate 	(void) printf("\n");
276*0Sstevel@tonic-gate }
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate 
280*0Sstevel@tonic-gate /*
281*0Sstevel@tonic-gate  * Print relocation data of type SHT_RELA
282*0Sstevel@tonic-gate  * If d_flag, print data corresponding only to
283*0Sstevel@tonic-gate  * the section or range of sections specified.
284*0Sstevel@tonic-gate  * If n_flag, print data corresponding only to
285*0Sstevel@tonic-gate  * the named section.
286*0Sstevel@tonic-gate  */
287*0Sstevel@tonic-gate static void
288*0Sstevel@tonic-gate print_rela(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data,
289*0Sstevel@tonic-gate 	GElf_Ehdr * p_ehdr, size_t reloc_size, size_t sym_size, char *filename,
290*0Sstevel@tonic-gate 	SCNTAB *reloc_symtab)
291*0Sstevel@tonic-gate {
292*0Sstevel@tonic-gate 	GElf_Rela rela;
293*0Sstevel@tonic-gate 	GElf_Sym sym;
294*0Sstevel@tonic-gate 	size_t no_entries;
295*0Sstevel@tonic-gate 	size_t rel_entsize;
296*0Sstevel@tonic-gate 	size_t no_syms;
297*0Sstevel@tonic-gate 	int type, symid;
298*0Sstevel@tonic-gate 	static int n_title = 0;
299*0Sstevel@tonic-gate 	int ndx = 0;
300*0Sstevel@tonic-gate 	char *sym_name;
301*0Sstevel@tonic-gate 	int adj = 0;
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 	if (gelf_getclass(elf_file) == ELFCLASS64)
304*0Sstevel@tonic-gate 		adj = 4;
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate 	rel_entsize = p_scns->p_shdr.sh_entsize;
307*0Sstevel@tonic-gate 	if ((rel_entsize == 0) ||
308*0Sstevel@tonic-gate 	    (rel_entsize > p_scns->p_shdr.sh_size)) {
309*0Sstevel@tonic-gate 		rel_entsize = gelf_fsize(elf_file, ELF_T_RELA, 1,
310*0Sstevel@tonic-gate 		    EV_CURRENT);
311*0Sstevel@tonic-gate 	}
312*0Sstevel@tonic-gate 	no_entries = reloc_size / rel_entsize;
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate 	no_syms = sym_size / gelf_fsize(elf_file, ELF_T_SYM, 1, EV_CURRENT);
315*0Sstevel@tonic-gate 	while (no_entries--) {
316*0Sstevel@tonic-gate 		(void) gelf_getrela(rdata, ndx, &rela);
317*0Sstevel@tonic-gate 		/* LINTED */
318*0Sstevel@tonic-gate 		type = (int)GELF_R_TYPE(rela.r_info);
319*0Sstevel@tonic-gate 		/* LINTED */
320*0Sstevel@tonic-gate 		symid = (int)GELF_R_SYM(rela.r_info);
321*0Sstevel@tonic-gate 		/* LINTED */
322*0Sstevel@tonic-gate 		if ((symid > (no_syms - 1)) || (symid < 0)) {
323*0Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: %s: invalid symbol table "
324*0Sstevel@tonic-gate 			    "offset - %d - in %s\n", prog_name, filename,
325*0Sstevel@tonic-gate 			    symid, p_scns->scn_name);
326*0Sstevel@tonic-gate 			ndx++;
327*0Sstevel@tonic-gate 			continue;
328*0Sstevel@tonic-gate 		}
329*0Sstevel@tonic-gate 		(void) gelf_getsym(sym_data, symid, &sym);
330*0Sstevel@tonic-gate 		sym_name = (char *)elf_strptr(elf_file,
331*0Sstevel@tonic-gate 			reloc_symtab->p_shdr.sh_link, sym.st_name);
332*0Sstevel@tonic-gate 		if (sym_name == NULL)
333*0Sstevel@tonic-gate 			sym_name = (char *)UNKNOWN;
334*0Sstevel@tonic-gate 		if (r_flag && rn_flag) {
335*0Sstevel@tonic-gate 			if (strcmp(name, p_scns->scn_name) != 0) {
336*0Sstevel@tonic-gate 				ndx++;
337*0Sstevel@tonic-gate 				continue;
338*0Sstevel@tonic-gate 			}
339*0Sstevel@tonic-gate 			if (!n_title) {
340*0Sstevel@tonic-gate 				(void) printf("\n%s:\n", p_scns->scn_name);
341*0Sstevel@tonic-gate 				(void) printf("%-*s%-*s%-*s%s\n\n",
342*0Sstevel@tonic-gate 				    12 + adj, "Offset", 22, "Symndx",
343*0Sstevel@tonic-gate 				    16, "Type", "Addend");
344*0Sstevel@tonic-gate 				n_title = 1;
345*0Sstevel@tonic-gate 			}
346*0Sstevel@tonic-gate 		}
347*0Sstevel@tonic-gate 		if (d_flag) {
348*0Sstevel@tonic-gate 			if (!d_hi)
349*0Sstevel@tonic-gate 				d_hi = d_low;
350*0Sstevel@tonic-gate 			if ((symid < d_low) || (symid > d_hi)) {
351*0Sstevel@tonic-gate 				ndx++;
352*0Sstevel@tonic-gate 				continue;
353*0Sstevel@tonic-gate 			}
354*0Sstevel@tonic-gate 		}
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate 		(void) printf("%-#*llx", 12 + adj, EC_XWORD(rela.r_offset));
357*0Sstevel@tonic-gate 		if (!v_flag) {
358*0Sstevel@tonic-gate 			(void) printf("%-22d%-18d", symid, type);
359*0Sstevel@tonic-gate 		} else {
360*0Sstevel@tonic-gate 			if (strlen(sym_name)) {
361*0Sstevel@tonic-gate 				size_t len = strlen(sym_name) + 1;
362*0Sstevel@tonic-gate 				char tmpstr[10];
363*0Sstevel@tonic-gate 				if (len > 22) {
364*0Sstevel@tonic-gate 					(void) sprintf(tmpstr, "%%-%ds",
365*0Sstevel@tonic-gate 						/* LINTED */
366*0Sstevel@tonic-gate 						(int)len);
367*0Sstevel@tonic-gate 					(void) printf(tmpstr, sym_name);
368*0Sstevel@tonic-gate 				} else
369*0Sstevel@tonic-gate 					(void) printf("%-22s", sym_name);
370*0Sstevel@tonic-gate 			} else
371*0Sstevel@tonic-gate 				(void) printf("%-22d", symid);
372*0Sstevel@tonic-gate 			print_reloc_type(p_ehdr->e_machine, type);
373*0Sstevel@tonic-gate 		}
374*0Sstevel@tonic-gate 		(void) printf("%lld\n", EC_SXWORD(rela.r_addend));
375*0Sstevel@tonic-gate 		ndx++;
376*0Sstevel@tonic-gate 	}
377*0Sstevel@tonic-gate }
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate /*
380*0Sstevel@tonic-gate  * Print relocation data of type SHT_REL.
381*0Sstevel@tonic-gate  * If d_flag, print data corresponding only to
382*0Sstevel@tonic-gate  * the section or range of sections specified.
383*0Sstevel@tonic-gate  * If n_flag, print data corresponding only to
384*0Sstevel@tonic-gate  * the named section.
385*0Sstevel@tonic-gate  */
386*0Sstevel@tonic-gate static void
387*0Sstevel@tonic-gate print_rel(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data,
388*0Sstevel@tonic-gate 	GElf_Ehdr *p_ehdr, size_t reloc_size, size_t sym_size, char *filename,
389*0Sstevel@tonic-gate 	SCNTAB *reloc_symtab)
390*0Sstevel@tonic-gate {
391*0Sstevel@tonic-gate 	GElf_Rel rel;
392*0Sstevel@tonic-gate 	GElf_Sym sym;
393*0Sstevel@tonic-gate 	size_t no_entries;
394*0Sstevel@tonic-gate 	size_t rel_entsize;
395*0Sstevel@tonic-gate 	int type, symid;
396*0Sstevel@tonic-gate 	size_t no_syms;
397*0Sstevel@tonic-gate 	static int n_title = 0;
398*0Sstevel@tonic-gate 	int ndx = 0;
399*0Sstevel@tonic-gate 	char *sym_name;
400*0Sstevel@tonic-gate 	int adj = 0;
401*0Sstevel@tonic-gate 
402*0Sstevel@tonic-gate 	if (gelf_getclass(elf_file) == ELFCLASS64)
403*0Sstevel@tonic-gate 		adj = 4;
404*0Sstevel@tonic-gate 
405*0Sstevel@tonic-gate 	rel_entsize = p_scns->p_shdr.sh_entsize;
406*0Sstevel@tonic-gate 	if ((rel_entsize == 0) ||
407*0Sstevel@tonic-gate 	    (rel_entsize > p_scns->p_shdr.sh_size)) {
408*0Sstevel@tonic-gate 		rel_entsize = gelf_fsize(elf_file, ELF_T_REL, 1,
409*0Sstevel@tonic-gate 		    EV_CURRENT);
410*0Sstevel@tonic-gate 	}
411*0Sstevel@tonic-gate 	no_entries = reloc_size / rel_entsize;
412*0Sstevel@tonic-gate 
413*0Sstevel@tonic-gate 	no_syms = sym_size / gelf_fsize(elf_file, ELF_T_SYM, 1, EV_CURRENT);
414*0Sstevel@tonic-gate 	while (no_entries--) {
415*0Sstevel@tonic-gate 		(void) gelf_getrel(rdata, ndx, &rel);
416*0Sstevel@tonic-gate 		/* LINTED */
417*0Sstevel@tonic-gate 		type = (int)GELF_R_TYPE(rel.r_info);
418*0Sstevel@tonic-gate 		/* LINTED */
419*0Sstevel@tonic-gate 		symid = (int)GELF_R_SYM(rel.r_info);
420*0Sstevel@tonic-gate 		/* LINTED */
421*0Sstevel@tonic-gate 		if ((symid > (no_syms - 1)) || (symid < 0)) {
422*0Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: %s: invalid symbol table "
423*0Sstevel@tonic-gate 			    "offset - %d - in %s\n", prog_name, filename,
424*0Sstevel@tonic-gate 			    symid, p_scns->scn_name);
425*0Sstevel@tonic-gate 			ndx++;
426*0Sstevel@tonic-gate 			continue;
427*0Sstevel@tonic-gate 		}
428*0Sstevel@tonic-gate 		(void) gelf_getsym(sym_data, symid, &sym);
429*0Sstevel@tonic-gate 		sym_name = (char *)elf_strptr(elf_file,
430*0Sstevel@tonic-gate 			reloc_symtab->p_shdr.sh_link, sym.st_name);
431*0Sstevel@tonic-gate 		if (sym_name == NULL)
432*0Sstevel@tonic-gate 			sym_name = (char *)UNKNOWN;
433*0Sstevel@tonic-gate 		if (r_flag && rn_flag) {
434*0Sstevel@tonic-gate 			if (strcmp(name, p_scns->scn_name) != 0) {
435*0Sstevel@tonic-gate 				ndx++;
436*0Sstevel@tonic-gate 				continue;
437*0Sstevel@tonic-gate 			}
438*0Sstevel@tonic-gate 			if (!n_title) {
439*0Sstevel@tonic-gate 				(void) printf("\n%s:\n", p_scns->scn_name);
440*0Sstevel@tonic-gate 				(void) printf("%-*s%-*s%s\n\n",
441*0Sstevel@tonic-gate 				    12 + adj, "Offset", 20, "Symndx", "Type");
442*0Sstevel@tonic-gate 				n_title = 1;
443*0Sstevel@tonic-gate 			}
444*0Sstevel@tonic-gate 		}
445*0Sstevel@tonic-gate 		if (d_flag) {
446*0Sstevel@tonic-gate 			if (!d_hi)
447*0Sstevel@tonic-gate 				d_hi = d_low;
448*0Sstevel@tonic-gate 			if ((symid < d_low) || (symid > d_hi)) {
449*0Sstevel@tonic-gate 				ndx++;
450*0Sstevel@tonic-gate 				continue;
451*0Sstevel@tonic-gate 			}
452*0Sstevel@tonic-gate 		}
453*0Sstevel@tonic-gate 
454*0Sstevel@tonic-gate 		(void) printf("%-#*llx", 12 + adj, EC_ADDR(rel.r_offset));
455*0Sstevel@tonic-gate 		if (!v_flag) {
456*0Sstevel@tonic-gate 			(void) printf("%-20d%-18d", symid, type);
457*0Sstevel@tonic-gate 		} else {
458*0Sstevel@tonic-gate 			if (strlen(sym_name))
459*0Sstevel@tonic-gate 				(void) printf("%-20s", sym_name);
460*0Sstevel@tonic-gate 			else
461*0Sstevel@tonic-gate 				(void) printf("%-20d", sym.st_name);
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate 			print_reloc_type(p_ehdr->e_machine, type);
464*0Sstevel@tonic-gate 		}
465*0Sstevel@tonic-gate 		(void) printf("\n");
466*0Sstevel@tonic-gate 		ndx++;
467*0Sstevel@tonic-gate 	}
468*0Sstevel@tonic-gate }
469*0Sstevel@tonic-gate 
470*0Sstevel@tonic-gate /* demangle C++ names */
471*0Sstevel@tonic-gate static char *format = "%s\t[%s]";
472*0Sstevel@tonic-gate static char *
473*0Sstevel@tonic-gate demangled_name(char *s)
474*0Sstevel@tonic-gate {
475*0Sstevel@tonic-gate 	char *dn;
476*0Sstevel@tonic-gate 	static char *buf;
477*0Sstevel@tonic-gate 
478*0Sstevel@tonic-gate 	dn = sgs_demangle(s);
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate 	/*
481*0Sstevel@tonic-gate 	 * If not demangled, just return the symbol name
482*0Sstevel@tonic-gate 	 */
483*0Sstevel@tonic-gate 	if (strcmp(s, dn) == 0)
484*0Sstevel@tonic-gate 		return (s);
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate 	/*
487*0Sstevel@tonic-gate 	 * Demangled. Format it
488*0Sstevel@tonic-gate 	 */
489*0Sstevel@tonic-gate 	if (buf != NULL)
490*0Sstevel@tonic-gate 		free(buf);
491*0Sstevel@tonic-gate 
492*0Sstevel@tonic-gate 	buf = malloc(strlen(dn) + 1 + 1 + strlen(s) + 1 + 1);
493*0Sstevel@tonic-gate 	if (buf == NULL)
494*0Sstevel@tonic-gate 		return (s);
495*0Sstevel@tonic-gate 
496*0Sstevel@tonic-gate 	(void) sprintf(buf, format, dn, s);
497*0Sstevel@tonic-gate 	return (buf);
498*0Sstevel@tonic-gate }
499*0Sstevel@tonic-gate 
500*0Sstevel@tonic-gate /*
501*0Sstevel@tonic-gate  * Print the symbol table.  Input is an ELF file descriptor, a
502*0Sstevel@tonic-gate  * pointer to the symbol table SCNTAB structure,
503*0Sstevel@tonic-gate  * the number of symbols, a range of symbols to print,
504*0Sstevel@tonic-gate  * an index which is the number of the
505*0Sstevel@tonic-gate  * section in the file, and the filename.  The number of sections,
506*0Sstevel@tonic-gate  * the range, and the index are set in
507*0Sstevel@tonic-gate  * dump_symbol_table, depending on whether -n or -T were set.
508*0Sstevel@tonic-gate  */
509*0Sstevel@tonic-gate static void
510*0Sstevel@tonic-gate print_symtab(Elf *elf_file, SCNTAB *p_symtab, Elf_Data *sym_data,
511*0Sstevel@tonic-gate 	long range, int index)
512*0Sstevel@tonic-gate {
513*0Sstevel@tonic-gate 	GElf_Sym sym;
514*0Sstevel@tonic-gate 	int adj = 0;		/* field adjustment for elf64 */
515*0Sstevel@tonic-gate 	Elf32_Word	*symshndx = 0;
516*0Sstevel@tonic-gate 	unsigned int	nosymshndx = 0;
517*0Sstevel@tonic-gate 
518*0Sstevel@tonic-gate 	if (gelf_getclass(elf_file) == ELFCLASS64)
519*0Sstevel@tonic-gate 		adj = 4;
520*0Sstevel@tonic-gate 
521*0Sstevel@tonic-gate 	while (range > 0) {
522*0Sstevel@tonic-gate 		char		*sym_name = (char *)0;
523*0Sstevel@tonic-gate 		int		type, bind;
524*0Sstevel@tonic-gate 		int		specsec;
525*0Sstevel@tonic-gate 		unsigned int	shndx;
526*0Sstevel@tonic-gate 
527*0Sstevel@tonic-gate 		(void) gelf_getsym(sym_data, index, &sym);
528*0Sstevel@tonic-gate 		type = (int)GELF_ST_TYPE(sym.st_info);
529*0Sstevel@tonic-gate 		bind = (int)GELF_ST_BIND(sym.st_info);
530*0Sstevel@tonic-gate 
531*0Sstevel@tonic-gate 		if ((sym.st_shndx == SHN_XINDEX) &&
532*0Sstevel@tonic-gate 		    (symshndx == 0) && (nosymshndx == 0)) {
533*0Sstevel@tonic-gate 			Elf_Scn		*_scn;
534*0Sstevel@tonic-gate 			GElf_Shdr	_shdr;
535*0Sstevel@tonic-gate 			size_t		symscnndx;
536*0Sstevel@tonic-gate 
537*0Sstevel@tonic-gate 			symscnndx = elf_ndxscn(p_symtab->p_sd);
538*0Sstevel@tonic-gate 			_scn = 0;
539*0Sstevel@tonic-gate 			while ((_scn = elf_nextscn(elf_file, _scn)) != 0) {
540*0Sstevel@tonic-gate 				if (gelf_getshdr(_scn, &_shdr) == 0)
541*0Sstevel@tonic-gate 					break;
542*0Sstevel@tonic-gate 				if ((_shdr.sh_type == SHT_SYMTAB_SHNDX) &&
543*0Sstevel@tonic-gate 				    /* LINTED */
544*0Sstevel@tonic-gate 				    (_shdr.sh_link == (GElf_Word)symscnndx)) {
545*0Sstevel@tonic-gate 					Elf_Data	*_data;
546*0Sstevel@tonic-gate 
547*0Sstevel@tonic-gate 					if ((_data = elf_getdata(_scn, 0)) == 0)
548*0Sstevel@tonic-gate 						continue;
549*0Sstevel@tonic-gate 
550*0Sstevel@tonic-gate 					symshndx = (Elf32_Word *)_data->d_buf;
551*0Sstevel@tonic-gate 					nosymshndx = 0;
552*0Sstevel@tonic-gate 					break;
553*0Sstevel@tonic-gate 				}
554*0Sstevel@tonic-gate 			}
555*0Sstevel@tonic-gate 			nosymshndx = 1;
556*0Sstevel@tonic-gate 		}
557*0Sstevel@tonic-gate 
558*0Sstevel@tonic-gate 		if ((symshndx) && (sym.st_shndx == SHN_XINDEX)) {
559*0Sstevel@tonic-gate 			shndx = symshndx[index];
560*0Sstevel@tonic-gate 			specsec = 0;
561*0Sstevel@tonic-gate 		} else {
562*0Sstevel@tonic-gate 			shndx = sym.st_shndx;
563*0Sstevel@tonic-gate 			if ((sym.st_shndx == SHN_UNDEF) ||
564*0Sstevel@tonic-gate 			    (sym.st_shndx >= SHN_LORESERVE))
565*0Sstevel@tonic-gate 				specsec = 1;
566*0Sstevel@tonic-gate 			else
567*0Sstevel@tonic-gate 				specsec = 0;
568*0Sstevel@tonic-gate 		}
569*0Sstevel@tonic-gate 
570*0Sstevel@tonic-gate 
571*0Sstevel@tonic-gate 		(void) printf("[%d]\t ", index++);
572*0Sstevel@tonic-gate 
573*0Sstevel@tonic-gate 		if (v_flag && (type == STT_SPARC_REGISTER)) {
574*0Sstevel@tonic-gate 			/*
575*0Sstevel@tonic-gate 			 *  The strings "REG_G1" through "REG_G7" are intended
576*0Sstevel@tonic-gate 			 *  to be consistent with output from elfdump(1).
577*0Sstevel@tonic-gate 			 */
578*0Sstevel@tonic-gate 			switch (sym.st_value) {
579*0Sstevel@tonic-gate 			case STO_SPARC_REGISTER_G1:
580*0Sstevel@tonic-gate 				(void) printf("%-*s", 12 + adj, "REG_G1");
581*0Sstevel@tonic-gate 				break;
582*0Sstevel@tonic-gate 			case STO_SPARC_REGISTER_G2:
583*0Sstevel@tonic-gate 				(void) printf("%-*s", 12 + adj, "REG_G2");
584*0Sstevel@tonic-gate 				break;
585*0Sstevel@tonic-gate 			case STO_SPARC_REGISTER_G3:
586*0Sstevel@tonic-gate 				(void) printf("%-*s", 12 + adj, "REG_G3");
587*0Sstevel@tonic-gate 				break;
588*0Sstevel@tonic-gate 			case STO_SPARC_REGISTER_G4:
589*0Sstevel@tonic-gate 				(void) printf("%-*s", 12 + adj, "REG_G4");
590*0Sstevel@tonic-gate 				break;
591*0Sstevel@tonic-gate 			case STO_SPARC_REGISTER_G5:
592*0Sstevel@tonic-gate 				(void) printf("%-*s", 12 + adj, "REG_G5");
593*0Sstevel@tonic-gate 				break;
594*0Sstevel@tonic-gate 			case STO_SPARC_REGISTER_G6:
595*0Sstevel@tonic-gate 				(void) printf("%-*s", 12 + adj, "REG_G6");
596*0Sstevel@tonic-gate 				break;
597*0Sstevel@tonic-gate 			case STO_SPARC_REGISTER_G7:
598*0Sstevel@tonic-gate 				(void) printf("%-*s", 12 + adj, "REG_G7");
599*0Sstevel@tonic-gate 				break;
600*0Sstevel@tonic-gate 			default:
601*0Sstevel@tonic-gate 				(void) printf("0x%-*llx", 10 + adj,
602*0Sstevel@tonic-gate 				    EC_ADDR(sym.st_value));
603*0Sstevel@tonic-gate 			}
604*0Sstevel@tonic-gate 		} else
605*0Sstevel@tonic-gate 			(void) printf("0x%-*llx", 10 + adj,
606*0Sstevel@tonic-gate 			    EC_ADDR(sym.st_value));
607*0Sstevel@tonic-gate 
608*0Sstevel@tonic-gate 		(void) printf("%-*lld", 9 + adj, EC_XWORD(sym.st_size));
609*0Sstevel@tonic-gate 
610*0Sstevel@tonic-gate 		if (!v_flag) {
611*0Sstevel@tonic-gate 			(void) printf("%d\t\t%d\t%d\t%#x\t",
612*0Sstevel@tonic-gate 			    type, bind, (int)sym.st_other, (int)shndx);
613*0Sstevel@tonic-gate 		} else {
614*0Sstevel@tonic-gate 			switch (type) {
615*0Sstevel@tonic-gate 			case STT_NOTYPE:
616*0Sstevel@tonic-gate 				(void) printf("%s\t", "NOTY");
617*0Sstevel@tonic-gate 				break;
618*0Sstevel@tonic-gate 			case STT_OBJECT:
619*0Sstevel@tonic-gate 				(void) printf("%s\t", "OBJT");
620*0Sstevel@tonic-gate 				break;
621*0Sstevel@tonic-gate 			case STT_FUNC:
622*0Sstevel@tonic-gate 				(void) printf("%s\t", "FUNC");
623*0Sstevel@tonic-gate 				break;
624*0Sstevel@tonic-gate 			case STT_SECTION:
625*0Sstevel@tonic-gate 				(void) printf("%s\t", "SECT");
626*0Sstevel@tonic-gate 				break;
627*0Sstevel@tonic-gate 			case STT_FILE:
628*0Sstevel@tonic-gate 				(void) printf("%s\t", "FILE");
629*0Sstevel@tonic-gate 				break;
630*0Sstevel@tonic-gate 			case STT_SPARC_REGISTER:
631*0Sstevel@tonic-gate 				(void) printf("%s\t", "REGI");
632*0Sstevel@tonic-gate 				break;
633*0Sstevel@tonic-gate 			case STT_COMMON:
634*0Sstevel@tonic-gate 				(void) printf("%s\t", "COMM");
635*0Sstevel@tonic-gate 				break;
636*0Sstevel@tonic-gate 			case STT_TLS:
637*0Sstevel@tonic-gate 				(void) printf("%s\t", "TLS ");
638*0Sstevel@tonic-gate 				break;
639*0Sstevel@tonic-gate 			default:
640*0Sstevel@tonic-gate 				(void) printf("%d\t", type);
641*0Sstevel@tonic-gate 			}
642*0Sstevel@tonic-gate 			switch (bind) {
643*0Sstevel@tonic-gate 			case STB_LOCAL:
644*0Sstevel@tonic-gate 				(void) printf("LOCL");
645*0Sstevel@tonic-gate 				break;
646*0Sstevel@tonic-gate 			case STB_GLOBAL:
647*0Sstevel@tonic-gate 				(void) printf("GLOB");
648*0Sstevel@tonic-gate 				break;
649*0Sstevel@tonic-gate 			case STB_WEAK:
650*0Sstevel@tonic-gate 				(void) printf("WEAK");
651*0Sstevel@tonic-gate 				break;
652*0Sstevel@tonic-gate 			default:
653*0Sstevel@tonic-gate 				(void) printf("%d", bind);
654*0Sstevel@tonic-gate 			}
655*0Sstevel@tonic-gate 			(void) printf("\t  %d\t", EC_WORD(sym.st_other));
656*0Sstevel@tonic-gate 
657*0Sstevel@tonic-gate 			if (specsec) {
658*0Sstevel@tonic-gate 				switch (shndx) {
659*0Sstevel@tonic-gate 				case SHN_UNDEF:
660*0Sstevel@tonic-gate 					(void) printf("UNDEF");
661*0Sstevel@tonic-gate 					break;
662*0Sstevel@tonic-gate 				case SHN_ABS:
663*0Sstevel@tonic-gate 					(void) printf("ABS");
664*0Sstevel@tonic-gate 					break;
665*0Sstevel@tonic-gate 				case SHN_COMMON:
666*0Sstevel@tonic-gate 					(void) printf("COMMON");
667*0Sstevel@tonic-gate 					break;
668*0Sstevel@tonic-gate 				case SHN_XINDEX:
669*0Sstevel@tonic-gate 					(void) printf("XINDEX");
670*0Sstevel@tonic-gate 					break;
671*0Sstevel@tonic-gate 				default:
672*0Sstevel@tonic-gate 					(void) printf("%d", EC_WORD(shndx));
673*0Sstevel@tonic-gate 				}
674*0Sstevel@tonic-gate 			} else
675*0Sstevel@tonic-gate 				(void) printf("%d", EC_WORD(shndx));
676*0Sstevel@tonic-gate 			(void) printf("\t");
677*0Sstevel@tonic-gate 		}
678*0Sstevel@tonic-gate 
679*0Sstevel@tonic-gate 		/* support machines where NULL-deref causes core dump */
680*0Sstevel@tonic-gate 		if (sym.st_name == 0)
681*0Sstevel@tonic-gate 			sym_name = (char *)UNKNOWN;
682*0Sstevel@tonic-gate 		else
683*0Sstevel@tonic-gate 			if (C_flag)
684*0Sstevel@tonic-gate 				sym_name = demangled_name(
685*0Sstevel@tonic-gate 					(char *)elf_strptr(elf_file,
686*0Sstevel@tonic-gate 					p_symtab->p_shdr.sh_link,
687*0Sstevel@tonic-gate 					sym.st_name));
688*0Sstevel@tonic-gate 		else
689*0Sstevel@tonic-gate 			sym_name = (char *)elf_strptr(elf_file,
690*0Sstevel@tonic-gate 				p_symtab->p_shdr.sh_link,
691*0Sstevel@tonic-gate 				sym.st_name);
692*0Sstevel@tonic-gate 		if (sym_name == NULL)
693*0Sstevel@tonic-gate 			sym_name = (char *)UNKNOWN;
694*0Sstevel@tonic-gate 		(void) printf("%s\n", sym_name);
695*0Sstevel@tonic-gate 
696*0Sstevel@tonic-gate 		range--;
697*0Sstevel@tonic-gate 	}	/* end while */
698*0Sstevel@tonic-gate }
699*0Sstevel@tonic-gate 
700*0Sstevel@tonic-gate /*
701*0Sstevel@tonic-gate  * Print the section header table.  Input is the SCNTAB structure,
702*0Sstevel@tonic-gate  * the number of sections, an index which is the number of the
703*0Sstevel@tonic-gate  * section in the file, and the filename.  The values of the SCNTAB
704*0Sstevel@tonic-gate  * structure, the number of sections, and the index are set in
705*0Sstevel@tonic-gate  * dump_shdr depending on whether the -n or -d modifiers were set.
706*0Sstevel@tonic-gate  */
707*0Sstevel@tonic-gate static void
708*0Sstevel@tonic-gate print_shdr(Elf *elf_file, SCNTAB *s, int num_scns, int index)
709*0Sstevel@tonic-gate {
710*0Sstevel@tonic-gate 	SCNTAB *p;
711*0Sstevel@tonic-gate 	int num;
712*0Sstevel@tonic-gate 	int field;
713*0Sstevel@tonic-gate 
714*0Sstevel@tonic-gate 	if (gelf_getclass(elf_file) == ELFCLASS64)
715*0Sstevel@tonic-gate 		field = 15;
716*0Sstevel@tonic-gate 	else
717*0Sstevel@tonic-gate 		field = 13;
718*0Sstevel@tonic-gate 
719*0Sstevel@tonic-gate 	p = s;
720*0Sstevel@tonic-gate 
721*0Sstevel@tonic-gate 	for (num = 0; num < num_scns; num++, p++) {
722*0Sstevel@tonic-gate 		(void) printf("[%d]\t", index++);
723*0Sstevel@tonic-gate 		if (!v_flag) {
724*0Sstevel@tonic-gate 			(void) printf("%u\t%llu\t",
725*0Sstevel@tonic-gate 			EC_WORD(p->p_shdr.sh_type),
726*0Sstevel@tonic-gate 			EC_XWORD(p->p_shdr.sh_flags));
727*0Sstevel@tonic-gate 		} else {
728*0Sstevel@tonic-gate 			switch (p->p_shdr.sh_type) {
729*0Sstevel@tonic-gate 			case SHT_NULL:
730*0Sstevel@tonic-gate 				(void) printf("NULL");
731*0Sstevel@tonic-gate 				break;
732*0Sstevel@tonic-gate 			case SHT_PROGBITS:
733*0Sstevel@tonic-gate 				(void) printf("PBIT");
734*0Sstevel@tonic-gate 				break;
735*0Sstevel@tonic-gate 			case SHT_SYMTAB:
736*0Sstevel@tonic-gate 				(void) printf("SYMT");
737*0Sstevel@tonic-gate 				break;
738*0Sstevel@tonic-gate 			case SHT_STRTAB:
739*0Sstevel@tonic-gate 				(void) printf("STRT");
740*0Sstevel@tonic-gate 				break;
741*0Sstevel@tonic-gate 			case SHT_RELA:
742*0Sstevel@tonic-gate 				(void) printf("RELA");
743*0Sstevel@tonic-gate 				break;
744*0Sstevel@tonic-gate 			case SHT_HASH:
745*0Sstevel@tonic-gate 				(void) printf("HASH");
746*0Sstevel@tonic-gate 				break;
747*0Sstevel@tonic-gate 			case SHT_DYNAMIC:
748*0Sstevel@tonic-gate 				(void) printf("DYNM");
749*0Sstevel@tonic-gate 				break;
750*0Sstevel@tonic-gate 			case SHT_NOTE:
751*0Sstevel@tonic-gate 				(void) printf("NOTE");
752*0Sstevel@tonic-gate 				break;
753*0Sstevel@tonic-gate 			case SHT_NOBITS:
754*0Sstevel@tonic-gate 				(void) printf("NOBI");
755*0Sstevel@tonic-gate 				break;
756*0Sstevel@tonic-gate 			case SHT_REL:
757*0Sstevel@tonic-gate 				(void) printf("REL ");
758*0Sstevel@tonic-gate 				break;
759*0Sstevel@tonic-gate 			case SHT_DYNSYM:
760*0Sstevel@tonic-gate 				(void) printf("DYNS");
761*0Sstevel@tonic-gate 				break;
762*0Sstevel@tonic-gate 			case ((GElf_Word) SHT_LOUSER):
763*0Sstevel@tonic-gate 				(void) printf("LUSR");
764*0Sstevel@tonic-gate 				break;
765*0Sstevel@tonic-gate 			case ((GElf_Word) SHT_HIUSER):
766*0Sstevel@tonic-gate 				(void) printf("HUSR");
767*0Sstevel@tonic-gate 				break;
768*0Sstevel@tonic-gate 			case SHT_SHLIB:
769*0Sstevel@tonic-gate 				(void) printf("SHLB");
770*0Sstevel@tonic-gate 				break;
771*0Sstevel@tonic-gate 			case SHT_SUNW_SIGNATURE:
772*0Sstevel@tonic-gate 				(void) printf("SIGN");
773*0Sstevel@tonic-gate 				break;
774*0Sstevel@tonic-gate 			case SHT_SUNW_ANNOTATE:
775*0Sstevel@tonic-gate 				(void) printf("ANOT");
776*0Sstevel@tonic-gate 				break;
777*0Sstevel@tonic-gate 			case SHT_SUNW_DEBUGSTR:
778*0Sstevel@tonic-gate 				(void) printf("DBGS");
779*0Sstevel@tonic-gate 				break;
780*0Sstevel@tonic-gate 			case SHT_SUNW_DEBUG:
781*0Sstevel@tonic-gate 				(void) printf("DBG ");
782*0Sstevel@tonic-gate 				break;
783*0Sstevel@tonic-gate 			case SHT_SUNW_move:
784*0Sstevel@tonic-gate 				(void) printf("MOVE");
785*0Sstevel@tonic-gate 				break;
786*0Sstevel@tonic-gate 			case SHT_SUNW_verdef:
787*0Sstevel@tonic-gate 				(void) printf("VERD");
788*0Sstevel@tonic-gate 				break;
789*0Sstevel@tonic-gate 			case SHT_SUNW_verneed:
790*0Sstevel@tonic-gate 				(void) printf("VERN");
791*0Sstevel@tonic-gate 				break;
792*0Sstevel@tonic-gate 			case SHT_SUNW_versym:
793*0Sstevel@tonic-gate 				(void) printf("VERS");
794*0Sstevel@tonic-gate 				break;
795*0Sstevel@tonic-gate 			case SHT_SUNW_syminfo:
796*0Sstevel@tonic-gate 				(void) printf("SYMI");
797*0Sstevel@tonic-gate 				break;
798*0Sstevel@tonic-gate 			case SHT_SUNW_COMDAT:
799*0Sstevel@tonic-gate 				(void) printf("COMD");
800*0Sstevel@tonic-gate 				break;
801*0Sstevel@tonic-gate 			default:
802*0Sstevel@tonic-gate 				(void) printf("%u", EC_WORD(p->p_shdr.sh_type));
803*0Sstevel@tonic-gate 				break;
804*0Sstevel@tonic-gate 			}
805*0Sstevel@tonic-gate 			(void) printf("    ");
806*0Sstevel@tonic-gate 
807*0Sstevel@tonic-gate 			if (p->p_shdr.sh_flags & SHF_WRITE)
808*0Sstevel@tonic-gate 				(void) printf("W");
809*0Sstevel@tonic-gate 			else
810*0Sstevel@tonic-gate 				(void) printf("-");
811*0Sstevel@tonic-gate 			if (p->p_shdr.sh_flags & SHF_ALLOC)
812*0Sstevel@tonic-gate 				(void) printf("A");
813*0Sstevel@tonic-gate 			else
814*0Sstevel@tonic-gate 				(void) printf("-");
815*0Sstevel@tonic-gate 			if (p->p_shdr.sh_flags & SHF_EXECINSTR)
816*0Sstevel@tonic-gate 				(void) printf("I");
817*0Sstevel@tonic-gate 			else
818*0Sstevel@tonic-gate 				(void) printf("-");
819*0Sstevel@tonic-gate 
820*0Sstevel@tonic-gate 			if (p->p_shdr.sh_flags & SHF_ORDERED)
821*0Sstevel@tonic-gate 				(void) printf("O");
822*0Sstevel@tonic-gate 			if (p->p_shdr.sh_flags & SHF_EXCLUDE)
823*0Sstevel@tonic-gate 				(void) printf("E");
824*0Sstevel@tonic-gate 
825*0Sstevel@tonic-gate 			(void) printf("\t");
826*0Sstevel@tonic-gate 
827*0Sstevel@tonic-gate 		}
828*0Sstevel@tonic-gate 		(void) printf("%-#*llx%-#*llx%-#*llx%s%s\n",
829*0Sstevel@tonic-gate 			field, EC_ADDR(p->p_shdr.sh_addr),
830*0Sstevel@tonic-gate 			field, EC_OFF(p->p_shdr.sh_offset),
831*0Sstevel@tonic-gate 			field, EC_XWORD(p->p_shdr.sh_size),
832*0Sstevel@tonic-gate 			/* compatibility:  tab for elf32 */
833*0Sstevel@tonic-gate 			(field == 13) ? "\t" : " ", p->scn_name);
834*0Sstevel@tonic-gate 
835*0Sstevel@tonic-gate 		(void) printf("\t%u\t%u\t%-#*llx%-#*llx\n\n",
836*0Sstevel@tonic-gate 			EC_WORD(p->p_shdr.sh_link),
837*0Sstevel@tonic-gate 			EC_WORD(p->p_shdr.sh_info),
838*0Sstevel@tonic-gate 			field, EC_XWORD(p->p_shdr.sh_addralign),
839*0Sstevel@tonic-gate 			field, EC_XWORD(p->p_shdr.sh_entsize));
840*0Sstevel@tonic-gate 	}
841*0Sstevel@tonic-gate }
842*0Sstevel@tonic-gate 
843*0Sstevel@tonic-gate /*
844*0Sstevel@tonic-gate  * Check that a range of numbers is valid.  Input is
845*0Sstevel@tonic-gate  * a lower bound, an upper bound, a boundary condition,
846*0Sstevel@tonic-gate  * and the filename.  Negative numbers and numbers greater
847*0Sstevel@tonic-gate  * than the bound are invalid.  low must be smaller than hi.
848*0Sstevel@tonic-gate  * The returned integer is the number of items in the
849*0Sstevel@tonic-gate  * range if it is valid and -1 otherwise.
850*0Sstevel@tonic-gate  */
851*0Sstevel@tonic-gate static int
852*0Sstevel@tonic-gate check_range(int low, int hi, size_t bound, char *filename)
853*0Sstevel@tonic-gate {
854*0Sstevel@tonic-gate 	if (((size_t)low > bound) || (low <= 0)) {
855*0Sstevel@tonic-gate 		(void) fprintf(stderr,
856*0Sstevel@tonic-gate 			"%s: %s: number out of range, %d\n",
857*0Sstevel@tonic-gate 			prog_name, filename, low);
858*0Sstevel@tonic-gate 		return (-1);
859*0Sstevel@tonic-gate 	}
860*0Sstevel@tonic-gate 	if (((size_t)hi > bound) || (hi < 0)) {
861*0Sstevel@tonic-gate 		(void) fprintf(stderr,
862*0Sstevel@tonic-gate 			"%s: %s: number out of range, %d\n",
863*0Sstevel@tonic-gate 			prog_name, filename, hi);
864*0Sstevel@tonic-gate 			return (-1);
865*0Sstevel@tonic-gate 	}
866*0Sstevel@tonic-gate 
867*0Sstevel@tonic-gate 	if (hi && (low > hi)) {
868*0Sstevel@tonic-gate 		(void) fprintf(stderr,
869*0Sstevel@tonic-gate 			"%s: %s: invalid range, %d,%d\n",
870*0Sstevel@tonic-gate 			prog_name, filename, low, hi);
871*0Sstevel@tonic-gate 		return (-1);
872*0Sstevel@tonic-gate 	}
873*0Sstevel@tonic-gate 	if (hi)
874*0Sstevel@tonic-gate 		return (hi - low + 1);
875*0Sstevel@tonic-gate 	else
876*0Sstevel@tonic-gate 		return (1);
877*0Sstevel@tonic-gate }
878*0Sstevel@tonic-gate 
879*0Sstevel@tonic-gate /*
880*0Sstevel@tonic-gate  * Print relocation information.  Since this information is
881*0Sstevel@tonic-gate  * machine dependent, new sections must be added for each machine
882*0Sstevel@tonic-gate  * that is supported.  Input is an ELF file descriptor, the ELF header,
883*0Sstevel@tonic-gate  * the SCNTAB structure, the number of sections, and a filename.
884*0Sstevel@tonic-gate  * Set up necessary information to print relocation information
885*0Sstevel@tonic-gate  * and call the appropriate print function depending on the
886*0Sstevel@tonic-gate  * type of relocation information.  If the symbol table is
887*0Sstevel@tonic-gate  * absent, no relocation data is processed.  Input is an
888*0Sstevel@tonic-gate  * ELF file descriptor, the ELF header, the SCNTAB structure,
889*0Sstevel@tonic-gate  * and the filename.  Set range of d_flag and name if n_flag.
890*0Sstevel@tonic-gate  */
891*0Sstevel@tonic-gate static void
892*0Sstevel@tonic-gate dump_reloc_table(Elf *elf_file, GElf_Ehdr *p_ehdr,
893*0Sstevel@tonic-gate 	SCNTAB *p_scns, int num_scns, char *filename)
894*0Sstevel@tonic-gate {
895*0Sstevel@tonic-gate 	Elf_Data *rel_data;
896*0Sstevel@tonic-gate 	Elf_Data *sym_data;
897*0Sstevel@tonic-gate 	size_t    sym_size;
898*0Sstevel@tonic-gate 	size_t    reloc_size;
899*0Sstevel@tonic-gate 	SCNTAB *reloc_symtab;
900*0Sstevel@tonic-gate 	SCNTAB *head_scns;
901*0Sstevel@tonic-gate 	int r_title = 0;
902*0Sstevel@tonic-gate 	int adj = 0;
903*0Sstevel@tonic-gate 	size_t shnum;
904*0Sstevel@tonic-gate 
905*0Sstevel@tonic-gate 	if (gelf_getclass(elf_file) == ELFCLASS64)
906*0Sstevel@tonic-gate 		adj = 4;
907*0Sstevel@tonic-gate 
908*0Sstevel@tonic-gate 	if ((!p_flag) && (!r_title)) {
909*0Sstevel@tonic-gate 		(void) printf("\n    **** RELOCATION INFORMATION ****\n");
910*0Sstevel@tonic-gate 		r_title = 1;
911*0Sstevel@tonic-gate 	}
912*0Sstevel@tonic-gate 
913*0Sstevel@tonic-gate 	while (num_scns-- > 0) {
914*0Sstevel@tonic-gate 		if ((p_scns->p_shdr.sh_type != SHT_RELA) &&
915*0Sstevel@tonic-gate 		    (p_scns->p_shdr.sh_type != SHT_REL)) {
916*0Sstevel@tonic-gate 			p_scns++;
917*0Sstevel@tonic-gate 			continue;
918*0Sstevel@tonic-gate 		}
919*0Sstevel@tonic-gate 
920*0Sstevel@tonic-gate 	head_scns = p_head_scns;
921*0Sstevel@tonic-gate 
922*0Sstevel@tonic-gate 	if (elf_getshnum(elf_file, &shnum) == 0) {
923*0Sstevel@tonic-gate 		(void) fprintf(stderr,
924*0Sstevel@tonic-gate 			"%s: %s: elf_getshnum failed: %s\n",
925*0Sstevel@tonic-gate 			prog_name, filename, elf_errmsg(-1));
926*0Sstevel@tonic-gate 		return;
927*0Sstevel@tonic-gate 	}
928*0Sstevel@tonic-gate 
929*0Sstevel@tonic-gate 	if ((p_scns->p_shdr.sh_link == 0) ||
930*0Sstevel@tonic-gate 	    /* LINTED */
931*0Sstevel@tonic-gate 	    (p_scns->p_shdr.sh_link >= (GElf_Word)shnum)) {
932*0Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: %s: invalid sh_link field: "
933*0Sstevel@tonic-gate 			"section #: %d sh_link: %d\n",
934*0Sstevel@tonic-gate 			/* LINTED */
935*0Sstevel@tonic-gate 			prog_name, filename, (int)elf_ndxscn(p_scns->p_sd),
936*0Sstevel@tonic-gate 			(int)p_scns->p_shdr.sh_link);
937*0Sstevel@tonic-gate 		return;
938*0Sstevel@tonic-gate 	}
939*0Sstevel@tonic-gate 	head_scns += (p_scns->p_shdr.sh_link -1);
940*0Sstevel@tonic-gate 
941*0Sstevel@tonic-gate 	if (head_scns->p_shdr.sh_type == SHT_SYMTAB) {
942*0Sstevel@tonic-gate 		reloc_symtab = p_symtab;
943*0Sstevel@tonic-gate 	} else if (head_scns->p_shdr.sh_type  == SHT_DYNSYM) {
944*0Sstevel@tonic-gate 		reloc_symtab = p_dynsym;
945*0Sstevel@tonic-gate 	} else {
946*0Sstevel@tonic-gate 		(void) fprintf(stderr,
947*0Sstevel@tonic-gate "%s: %s: could not get symbol table\n", prog_name, filename);
948*0Sstevel@tonic-gate 		return;
949*0Sstevel@tonic-gate 	}
950*0Sstevel@tonic-gate 
951*0Sstevel@tonic-gate 	sym_data = NULL;
952*0Sstevel@tonic-gate 	sym_size = 0;
953*0Sstevel@tonic-gate 	reloc_size = 0;
954*0Sstevel@tonic-gate 
955*0Sstevel@tonic-gate 	if ((sym_data = elf_getdata(reloc_symtab->p_sd, NULL)) == NULL) {
956*0Sstevel@tonic-gate 		(void) fprintf(stderr,
957*0Sstevel@tonic-gate 		"%s: %s: no symbol table data\n", prog_name, filename);
958*0Sstevel@tonic-gate 		return;
959*0Sstevel@tonic-gate 	}
960*0Sstevel@tonic-gate 	sym_size = sym_data->d_size;
961*0Sstevel@tonic-gate 
962*0Sstevel@tonic-gate 	if (p_scns == NULL) {
963*0Sstevel@tonic-gate 		(void) fprintf(stderr,
964*0Sstevel@tonic-gate 		"%s: %s: no section table data\n", prog_name, filename);
965*0Sstevel@tonic-gate 		return;
966*0Sstevel@tonic-gate 	}
967*0Sstevel@tonic-gate 
968*0Sstevel@tonic-gate 	if (p_scns->p_shdr.sh_type == SHT_RELA) {
969*0Sstevel@tonic-gate 		if (!n_flag && r_flag)
970*0Sstevel@tonic-gate 			(void) printf("\n%s:\n", p_scns->scn_name);
971*0Sstevel@tonic-gate 		if (!p_flag && (!n_flag && r_flag))
972*0Sstevel@tonic-gate 			(void) printf("%-*s%-*s%-*s%s\n\n",
973*0Sstevel@tonic-gate 			    12 + adj, "Offset", 22, "Symndx",
974*0Sstevel@tonic-gate 			    18, "Type", "Addend");
975*0Sstevel@tonic-gate 		if ((rel_data = elf_getdata(p_scns->p_sd, NULL)) == NULL) {
976*0Sstevel@tonic-gate 			(void) fprintf(stderr,
977*0Sstevel@tonic-gate "%s: %s: no relocation information\n", prog_name, filename);
978*0Sstevel@tonic-gate 			return;
979*0Sstevel@tonic-gate 		}
980*0Sstevel@tonic-gate 		reloc_size = rel_data->d_size;
981*0Sstevel@tonic-gate 
982*0Sstevel@tonic-gate 		if (n_flag) {
983*0Sstevel@tonic-gate 			rn_flag = 1;
984*0Sstevel@tonic-gate 			print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr,
985*0Sstevel@tonic-gate 				reloc_size, sym_size, filename, reloc_symtab);
986*0Sstevel@tonic-gate 		}
987*0Sstevel@tonic-gate 		if (d_flag) {
988*0Sstevel@tonic-gate 			rn_flag = 0;
989*0Sstevel@tonic-gate 			print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr,
990*0Sstevel@tonic-gate 				reloc_size, sym_size, filename, reloc_symtab);
991*0Sstevel@tonic-gate 		}
992*0Sstevel@tonic-gate 		if (!n_flag && !d_flag)
993*0Sstevel@tonic-gate 			print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr,
994*0Sstevel@tonic-gate 				reloc_size, sym_size, filename, reloc_symtab);
995*0Sstevel@tonic-gate 	} else {
996*0Sstevel@tonic-gate 		if (p_scns->p_shdr.sh_type == SHT_REL) {
997*0Sstevel@tonic-gate 			if (!n_flag && r_flag)
998*0Sstevel@tonic-gate 				(void) printf("\n%s:\n", p_scns->scn_name);
999*0Sstevel@tonic-gate 			if (!p_flag && (!n_flag && r_flag)) {
1000*0Sstevel@tonic-gate 				(void) printf("%-*s%-*s%s\n\n",
1001*0Sstevel@tonic-gate 				    12 + adj, "Offset", 20, "Symndx", "Type");
1002*0Sstevel@tonic-gate 			}
1003*0Sstevel@tonic-gate 			if ((rel_data = elf_getdata(p_scns->p_sd, NULL))
1004*0Sstevel@tonic-gate 			    == NULL) {
1005*0Sstevel@tonic-gate 				(void) fprintf(stderr,
1006*0Sstevel@tonic-gate "%s: %s: no relocation information\n", prog_name, filename);
1007*0Sstevel@tonic-gate 				return;
1008*0Sstevel@tonic-gate 			}
1009*0Sstevel@tonic-gate 			reloc_size = rel_data->d_size;
1010*0Sstevel@tonic-gate 			if (n_flag) {
1011*0Sstevel@tonic-gate 				rn_flag = 1;
1012*0Sstevel@tonic-gate 				print_rel(elf_file, p_scns, rel_data, sym_data,
1013*0Sstevel@tonic-gate 					p_ehdr, reloc_size, sym_size,
1014*0Sstevel@tonic-gate 					filename, reloc_symtab);
1015*0Sstevel@tonic-gate 			}
1016*0Sstevel@tonic-gate 			if (d_flag) {
1017*0Sstevel@tonic-gate 				rn_flag = 0;
1018*0Sstevel@tonic-gate 				print_rel(elf_file, p_scns, rel_data, sym_data,
1019*0Sstevel@tonic-gate 					p_ehdr, reloc_size, sym_size,
1020*0Sstevel@tonic-gate 					filename, reloc_symtab);
1021*0Sstevel@tonic-gate 			}
1022*0Sstevel@tonic-gate 			if (!n_flag && !d_flag)
1023*0Sstevel@tonic-gate 				print_rel(elf_file, p_scns, rel_data, sym_data,
1024*0Sstevel@tonic-gate 					p_ehdr, reloc_size, sym_size,
1025*0Sstevel@tonic-gate 					filename, reloc_symtab);
1026*0Sstevel@tonic-gate 		}
1027*0Sstevel@tonic-gate 	}
1028*0Sstevel@tonic-gate 	p_scns++;
1029*0Sstevel@tonic-gate 	}
1030*0Sstevel@tonic-gate }
1031*0Sstevel@tonic-gate 
1032*0Sstevel@tonic-gate /*
1033*0Sstevel@tonic-gate  * Print out the string tables.  Input is an opened ELF file,
1034*0Sstevel@tonic-gate  * the SCNTAB structure, the number of sections, and the filename.
1035*0Sstevel@tonic-gate  * Since there can be more than one string table, all sections are
1036*0Sstevel@tonic-gate  * examined and any with the correct type are printed out.
1037*0Sstevel@tonic-gate  */
1038*0Sstevel@tonic-gate static void
1039*0Sstevel@tonic-gate dump_string_table(SCNTAB *s, int num_scns)
1040*0Sstevel@tonic-gate {
1041*0Sstevel@tonic-gate 	size_t section_size;
1042*0Sstevel@tonic-gate 	unsigned char *strtab;
1043*0Sstevel@tonic-gate 	int beg_of_string;
1044*0Sstevel@tonic-gate 	int counter = 0;
1045*0Sstevel@tonic-gate 	int str_off;
1046*0Sstevel@tonic-gate 	int i;
1047*0Sstevel@tonic-gate 
1048*0Sstevel@tonic-gate 	if (!p_flag) {
1049*0Sstevel@tonic-gate 		(void) printf("\n     **** STRING TABLE INFORMATION ****\n");
1050*0Sstevel@tonic-gate 	}
1051*0Sstevel@tonic-gate 
1052*0Sstevel@tonic-gate 	for (i = 0; i < num_scns; i++, s++) {
1053*0Sstevel@tonic-gate 		if (s->p_shdr.sh_type != SHT_STRTAB)
1054*0Sstevel@tonic-gate 			continue;
1055*0Sstevel@tonic-gate 
1056*0Sstevel@tonic-gate 		str_off = 0;
1057*0Sstevel@tonic-gate 
1058*0Sstevel@tonic-gate 		if (!p_flag) {
1059*0Sstevel@tonic-gate 			(void) printf("\n%s:\n", s->scn_name);
1060*0Sstevel@tonic-gate 			(void) printf("   <offset>  \tName\n");
1061*0Sstevel@tonic-gate 		}
1062*0Sstevel@tonic-gate 		section_size = 0;
1063*0Sstevel@tonic-gate 		if ((strtab = (unsigned char *)
1064*0Sstevel@tonic-gate 		    get_scndata(s->p_sd, &section_size)) == NULL) {
1065*0Sstevel@tonic-gate 			continue;
1066*0Sstevel@tonic-gate 		}
1067*0Sstevel@tonic-gate 
1068*0Sstevel@tonic-gate 		if (section_size != 0) {
1069*0Sstevel@tonic-gate 			(void) printf("   <%d>  \t", str_off);
1070*0Sstevel@tonic-gate 			beg_of_string = 0;
1071*0Sstevel@tonic-gate 			while (section_size--) {
1072*0Sstevel@tonic-gate 				unsigned char c = *strtab++;
1073*0Sstevel@tonic-gate 
1074*0Sstevel@tonic-gate 				if (beg_of_string) {
1075*0Sstevel@tonic-gate 					(void) printf("   <%d>  \t", str_off);
1076*0Sstevel@tonic-gate 					counter++;
1077*0Sstevel@tonic-gate 					beg_of_string = 0;
1078*0Sstevel@tonic-gate 				}
1079*0Sstevel@tonic-gate 				str_off++;
1080*0Sstevel@tonic-gate 				switch (c) {
1081*0Sstevel@tonic-gate 				case '\0':
1082*0Sstevel@tonic-gate 					(void) printf("\n");
1083*0Sstevel@tonic-gate 					beg_of_string = 1;
1084*0Sstevel@tonic-gate 					break;
1085*0Sstevel@tonic-gate 				default:
1086*0Sstevel@tonic-gate 					(void) putchar(c);
1087*0Sstevel@tonic-gate 				}
1088*0Sstevel@tonic-gate 			}
1089*0Sstevel@tonic-gate 		}
1090*0Sstevel@tonic-gate 	}
1091*0Sstevel@tonic-gate 	(void) printf("\n");
1092*0Sstevel@tonic-gate }
1093*0Sstevel@tonic-gate 
1094*0Sstevel@tonic-gate /*
1095*0Sstevel@tonic-gate  * Print the symbol table.  This function does not print the contents
1096*0Sstevel@tonic-gate  * of the symbol table but sets up the parameters and then calls
1097*0Sstevel@tonic-gate  * print_symtab to print the symbols.  Calling another function to print
1098*0Sstevel@tonic-gate  * the symbols allows both -T and -n to work correctly
1099*0Sstevel@tonic-gate  * simultaneously.  Input is an opened ELF file, a pointer to the
1100*0Sstevel@tonic-gate  * symbol table SCNTAB structure, and the filename.
1101*0Sstevel@tonic-gate  * Set the range of symbols to print if T_flag, and set
1102*0Sstevel@tonic-gate  * name of symbol to print if n_flag.
1103*0Sstevel@tonic-gate  */
1104*0Sstevel@tonic-gate static void
1105*0Sstevel@tonic-gate dump_symbol_table(Elf *elf_file, SCNTAB *p_symtab, char *filename)
1106*0Sstevel@tonic-gate {
1107*0Sstevel@tonic-gate 	Elf_Data  *sym_data;
1108*0Sstevel@tonic-gate 	GElf_Sym  T_range, n_range;	/* for use with -T and -n */
1109*0Sstevel@tonic-gate 	size_t count = 0;
1110*0Sstevel@tonic-gate 	size_t sym_size;
1111*0Sstevel@tonic-gate 	int index = 1;
1112*0Sstevel@tonic-gate 	int found_it = 0;
1113*0Sstevel@tonic-gate 	int i;
1114*0Sstevel@tonic-gate 	int adj = 0;			/*  field adjustment for elf64 */
1115*0Sstevel@tonic-gate 
1116*0Sstevel@tonic-gate 	if (gelf_getclass(elf_file) == ELFCLASS64)
1117*0Sstevel@tonic-gate 		adj = 4;
1118*0Sstevel@tonic-gate 
1119*0Sstevel@tonic-gate 	if (p_symtab == NULL) {
1120*0Sstevel@tonic-gate 		(void) fprintf(stderr,
1121*0Sstevel@tonic-gate 		"%s: %s: could not get symbol table\n", prog_name, filename);
1122*0Sstevel@tonic-gate 		return;
1123*0Sstevel@tonic-gate 	}
1124*0Sstevel@tonic-gate 
1125*0Sstevel@tonic-gate 	/* get symbol table data */
1126*0Sstevel@tonic-gate 	sym_data = NULL;
1127*0Sstevel@tonic-gate 	sym_size = 0;
1128*0Sstevel@tonic-gate 	if ((sym_data =
1129*0Sstevel@tonic-gate 	    elf_getdata(p_symtab->p_sd, NULL)) == NULL) {
1130*0Sstevel@tonic-gate 		(void) printf("\n%s:\n", p_symtab->scn_name);
1131*0Sstevel@tonic-gate 		(void) printf("No symbol table data\n");
1132*0Sstevel@tonic-gate 		return;
1133*0Sstevel@tonic-gate 	}
1134*0Sstevel@tonic-gate 	sym_size = sym_data->d_size;
1135*0Sstevel@tonic-gate 
1136*0Sstevel@tonic-gate 	count = sym_size / p_symtab->p_shdr.sh_entsize;
1137*0Sstevel@tonic-gate 
1138*0Sstevel@tonic-gate 	if (n_flag && t_flag && !T_flag) {
1139*0Sstevel@tonic-gate 		/* LINTED */
1140*0Sstevel@tonic-gate 		for (i = 1; i < count; i++) {
1141*0Sstevel@tonic-gate 			(void) gelf_getsym(sym_data, i, &n_range);
1142*0Sstevel@tonic-gate 			if (strcmp(name, (char *)
1143*0Sstevel@tonic-gate 			    elf_strptr(elf_file,
1144*0Sstevel@tonic-gate 			    p_symtab->p_shdr.sh_link,
1145*0Sstevel@tonic-gate 			    n_range.st_name)) != 0) {
1146*0Sstevel@tonic-gate 				continue;
1147*0Sstevel@tonic-gate 			} else {
1148*0Sstevel@tonic-gate 				found_it = 1;
1149*0Sstevel@tonic-gate 				if (!p_flag) {
1150*0Sstevel@tonic-gate 					(void) printf(
1151*0Sstevel@tonic-gate "\n              ***** SYMBOL TABLE INFORMATION *****\n");
1152*0Sstevel@tonic-gate 					(void) printf(
1153*0Sstevel@tonic-gate "[Index]  %-*s%-*sType\tBind\tOther\tShndx\tName",
1154*0Sstevel@tonic-gate 			    12 + adj, "Value", 9 + adj, "Size");
1155*0Sstevel@tonic-gate 				}
1156*0Sstevel@tonic-gate 				(void) printf("\n%s:\n", p_symtab->scn_name);
1157*0Sstevel@tonic-gate 				print_symtab(elf_file, p_symtab, sym_data,
1158*0Sstevel@tonic-gate 				    1, i);
1159*0Sstevel@tonic-gate 			}
1160*0Sstevel@tonic-gate 		}   /* end for */
1161*0Sstevel@tonic-gate 		if (!found_it) {
1162*0Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: %s: %s not found\n",
1163*0Sstevel@tonic-gate 			prog_name, filename, name);
1164*0Sstevel@tonic-gate 		}
1165*0Sstevel@tonic-gate 	} else if (T_flag) {
1166*0Sstevel@tonic-gate 		T_num = check_range(T_low, T_hi, count, filename);
1167*0Sstevel@tonic-gate 		if (T_num < 0)
1168*0Sstevel@tonic-gate 			return;
1169*0Sstevel@tonic-gate 
1170*0Sstevel@tonic-gate 		(void) gelf_getsym(sym_data, T_low-1, &T_range);
1171*0Sstevel@tonic-gate 		index = T_low;
1172*0Sstevel@tonic-gate 
1173*0Sstevel@tonic-gate 		if (!p_flag) {
1174*0Sstevel@tonic-gate 			(void) printf(
1175*0Sstevel@tonic-gate "\n              ***** SYMBOL TABLE INFORMATION *****\n");
1176*0Sstevel@tonic-gate 			(void) printf(
1177*0Sstevel@tonic-gate "[Index]  %-*s%-*sType\tBind\tOther\tShndx\tName",
1178*0Sstevel@tonic-gate 			    12 + adj, "Value", 9 + adj, "Size");
1179*0Sstevel@tonic-gate 		}
1180*0Sstevel@tonic-gate 		(void) printf("\n%s:\n", p_symtab->scn_name);
1181*0Sstevel@tonic-gate 		print_symtab(elf_file, p_symtab, sym_data, T_num, index);
1182*0Sstevel@tonic-gate 	} else {
1183*0Sstevel@tonic-gate 		if (!p_flag) {
1184*0Sstevel@tonic-gate 			(void) printf(
1185*0Sstevel@tonic-gate "\n              ***** SYMBOL TABLE INFORMATION *****\n");
1186*0Sstevel@tonic-gate 			(void) printf(
1187*0Sstevel@tonic-gate "[Index]  %-*s%-*sType\tBind\tOther\tShndx\tName",
1188*0Sstevel@tonic-gate 			    12 + adj, "Value", 9 + adj, "Size");
1189*0Sstevel@tonic-gate 		}
1190*0Sstevel@tonic-gate 		(void) printf("\n%s:\n", p_symtab->scn_name);
1191*0Sstevel@tonic-gate 		print_symtab(elf_file, p_symtab, sym_data, count-1, 1);
1192*0Sstevel@tonic-gate 	}
1193*0Sstevel@tonic-gate }
1194*0Sstevel@tonic-gate 
1195*0Sstevel@tonic-gate /*
1196*0Sstevel@tonic-gate  * Print dynamic linking information.  Input is an ELF
1197*0Sstevel@tonic-gate  * file descriptor, the SCNTAB structure, the number of
1198*0Sstevel@tonic-gate  * sections, and the filename.
1199*0Sstevel@tonic-gate  */
1200*0Sstevel@tonic-gate static void
1201*0Sstevel@tonic-gate dump_dynamic(Elf *elf_file, SCNTAB *p_scns, int num_scns, char *filename)
1202*0Sstevel@tonic-gate {
1203*0Sstevel@tonic-gate 	Elf_Data	*dyn_data;
1204*0Sstevel@tonic-gate 	GElf_Dyn	p_dyn;
1205*0Sstevel@tonic-gate 	GElf_Phdr	p_phdr;
1206*0Sstevel@tonic-gate 	GElf_Ehdr	p_ehdr;
1207*0Sstevel@tonic-gate 	char		*dt_name;
1208*0Sstevel@tonic-gate 	int		index = 1;
1209*0Sstevel@tonic-gate 	int		lib_scns = num_scns;
1210*0Sstevel@tonic-gate 	SCNTAB		*l_scns = p_scns;
1211*0Sstevel@tonic-gate 	int		header_num = 0;
1212*0Sstevel@tonic-gate #define	Fmttag		"%-15.15s "
1213*0Sstevel@tonic-gate #define	Fmtptr		"%#llx"
1214*0Sstevel@tonic-gate 
1215*0Sstevel@tonic-gate 	if (!p_flag)
1216*0Sstevel@tonic-gate 		(void) printf("\n  **** DYNAMIC SECTION INFORMATION ****\n");
1217*0Sstevel@tonic-gate 
1218*0Sstevel@tonic-gate 	for (; num_scns > 0; num_scns--, p_scns++) {
1219*0Sstevel@tonic-gate 		GElf_Word	link;
1220*0Sstevel@tonic-gate 		int		ii;
1221*0Sstevel@tonic-gate 
1222*0Sstevel@tonic-gate 
1223*0Sstevel@tonic-gate 		if (p_scns->p_shdr.sh_type != SHT_DYNAMIC)
1224*0Sstevel@tonic-gate 			continue;
1225*0Sstevel@tonic-gate 
1226*0Sstevel@tonic-gate 		if (!p_flag) {
1227*0Sstevel@tonic-gate 			(void) printf("%s:\n", p_scns->scn_name);
1228*0Sstevel@tonic-gate 			(void) printf("[INDEX]\tTag         Value\n");
1229*0Sstevel@tonic-gate 		}
1230*0Sstevel@tonic-gate 
1231*0Sstevel@tonic-gate 		if ((dyn_data = elf_getdata(p_scns->p_sd, NULL)) == 0) {
1232*0Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: %s: no data in "
1233*0Sstevel@tonic-gate 			    "%s section\n", prog_name, filename,
1234*0Sstevel@tonic-gate 			    p_scns->scn_name);
1235*0Sstevel@tonic-gate 			return;
1236*0Sstevel@tonic-gate 		}
1237*0Sstevel@tonic-gate 
1238*0Sstevel@tonic-gate 		link = p_scns->p_shdr.sh_link;
1239*0Sstevel@tonic-gate 		ii = 0;
1240*0Sstevel@tonic-gate 
1241*0Sstevel@tonic-gate 		(void) gelf_getdyn(dyn_data, ii++, &p_dyn);
1242*0Sstevel@tonic-gate 		while (p_dyn.d_tag != DT_NULL) {
1243*0Sstevel@tonic-gate 			char	value[256];
1244*0Sstevel@tonic-gate 
1245*0Sstevel@tonic-gate 			(void) printf("[%d]\t", index++);
1246*0Sstevel@tonic-gate 
1247*0Sstevel@tonic-gate 			switch (p_dyn.d_tag) {
1248*0Sstevel@tonic-gate 			/*
1249*0Sstevel@tonic-gate 			 * Start of generic flags.
1250*0Sstevel@tonic-gate 			 */
1251*0Sstevel@tonic-gate 			case (DT_NEEDED):
1252*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"NEEDED");
1253*0Sstevel@tonic-gate 				if (v_flag)
1254*0Sstevel@tonic-gate 					dt_name = (char *)elf_strptr(elf_file,
1255*0Sstevel@tonic-gate 					    link, p_dyn.d_un.d_ptr);
1256*0Sstevel@tonic-gate 				if (dt_name == NULL)
1257*0Sstevel@tonic-gate 					dt_name = (char *)UNKNOWN;
1258*0Sstevel@tonic-gate 				if (v_flag && strlen(dt_name))
1259*0Sstevel@tonic-gate 					(void) printf("%s", dt_name);
1260*0Sstevel@tonic-gate 				else
1261*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1262*0Sstevel@tonic-gate 					    EC_ADDR(p_dyn.d_un.d_ptr));
1263*0Sstevel@tonic-gate 				break;
1264*0Sstevel@tonic-gate 			case (DT_PLTRELSZ):
1265*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"PLTSZ");
1266*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1267*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1268*0Sstevel@tonic-gate 				break;
1269*0Sstevel@tonic-gate 			case (DT_PLTGOT):
1270*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"PLTGOT");
1271*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1272*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1273*0Sstevel@tonic-gate 				break;
1274*0Sstevel@tonic-gate 			case (DT_HASH):
1275*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"HASH");
1276*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1277*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1278*0Sstevel@tonic-gate 				break;
1279*0Sstevel@tonic-gate 			case (DT_STRTAB):
1280*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"STRTAB");
1281*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1282*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1283*0Sstevel@tonic-gate 				break;
1284*0Sstevel@tonic-gate 			case (DT_SYMTAB):
1285*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"SYMTAB");
1286*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1287*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1288*0Sstevel@tonic-gate 				break;
1289*0Sstevel@tonic-gate 			case (DT_RELA):
1290*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"RELA");
1291*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1292*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1293*0Sstevel@tonic-gate 				break;
1294*0Sstevel@tonic-gate 			case (DT_RELASZ):
1295*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"RELASZ");
1296*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1297*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1298*0Sstevel@tonic-gate 				break;
1299*0Sstevel@tonic-gate 			case (DT_RELAENT):
1300*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"RELAENT");
1301*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1302*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1303*0Sstevel@tonic-gate 				break;
1304*0Sstevel@tonic-gate 			case (DT_STRSZ):
1305*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"STRSZ");
1306*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1307*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1308*0Sstevel@tonic-gate 				break;
1309*0Sstevel@tonic-gate 			case (DT_SYMENT):
1310*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"SYMENT");
1311*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1312*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1313*0Sstevel@tonic-gate 				break;
1314*0Sstevel@tonic-gate 			case (DT_INIT):
1315*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"INIT");
1316*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1317*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1318*0Sstevel@tonic-gate 				break;
1319*0Sstevel@tonic-gate 			case (DT_FINI):
1320*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"FINI");
1321*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1322*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1323*0Sstevel@tonic-gate 				break;
1324*0Sstevel@tonic-gate 			case (DT_SONAME):
1325*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"SONAME");
1326*0Sstevel@tonic-gate 				if (v_flag)
1327*0Sstevel@tonic-gate 					dt_name = (char *)elf_strptr(elf_file,
1328*0Sstevel@tonic-gate 					    link, p_dyn.d_un.d_ptr);
1329*0Sstevel@tonic-gate 				if (dt_name == NULL)
1330*0Sstevel@tonic-gate 					dt_name = (char *)UNKNOWN;
1331*0Sstevel@tonic-gate 				if (v_flag && strlen(dt_name))
1332*0Sstevel@tonic-gate 					(void) printf("%s", dt_name);
1333*0Sstevel@tonic-gate 				else
1334*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1335*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1336*0Sstevel@tonic-gate 				break;
1337*0Sstevel@tonic-gate 			case (DT_RPATH):
1338*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"RPATH");
1339*0Sstevel@tonic-gate 				if (v_flag)
1340*0Sstevel@tonic-gate 					dt_name = (char *)elf_strptr(elf_file,
1341*0Sstevel@tonic-gate 					    link, p_dyn.d_un.d_ptr);
1342*0Sstevel@tonic-gate 				if (dt_name == NULL)
1343*0Sstevel@tonic-gate 					dt_name = (char *)UNKNOWN;
1344*0Sstevel@tonic-gate 				if (v_flag && strlen(dt_name))
1345*0Sstevel@tonic-gate 					(void) printf("%s", dt_name);
1346*0Sstevel@tonic-gate 				else
1347*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1348*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1349*0Sstevel@tonic-gate 				break;
1350*0Sstevel@tonic-gate 			case (DT_SYMBOLIC):
1351*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"SYMB");
1352*0Sstevel@tonic-gate 				(void) printf("%s", (const char *)"(ignored)");
1353*0Sstevel@tonic-gate 				break;
1354*0Sstevel@tonic-gate 			case (DT_REL):
1355*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"REL");
1356*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1357*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1358*0Sstevel@tonic-gate 				break;
1359*0Sstevel@tonic-gate 			case (DT_RELSZ):
1360*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"RELSZ");
1361*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1362*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1363*0Sstevel@tonic-gate 				break;
1364*0Sstevel@tonic-gate 			case (DT_RELENT):
1365*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"RELENT");
1366*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1367*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1368*0Sstevel@tonic-gate 				break;
1369*0Sstevel@tonic-gate 			case (DT_PLTREL):
1370*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"PLTREL");
1371*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1372*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1373*0Sstevel@tonic-gate 				break;
1374*0Sstevel@tonic-gate 			case (DT_DEBUG):
1375*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"DEBUG");
1376*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1377*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1378*0Sstevel@tonic-gate 				break;
1379*0Sstevel@tonic-gate 			case (DT_TEXTREL):
1380*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"TEXTREL");
1381*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1382*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_val));
1383*0Sstevel@tonic-gate 				break;
1384*0Sstevel@tonic-gate 			case (DT_JMPREL):
1385*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"JMPREL");
1386*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1387*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1388*0Sstevel@tonic-gate 				break;
1389*0Sstevel@tonic-gate 			case (DT_BIND_NOW):
1390*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"BIND_NOW");
1391*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1392*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_val));
1393*0Sstevel@tonic-gate 				break;
1394*0Sstevel@tonic-gate 			case (DT_INIT_ARRAY):
1395*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1396*0Sstevel@tonic-gate 					(const char *)"INIT_ARRAY");
1397*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1398*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1399*0Sstevel@tonic-gate 				break;
1400*0Sstevel@tonic-gate 			case (DT_FINI_ARRAY):
1401*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1402*0Sstevel@tonic-gate 					(const char *)"FINI_ARRAY");
1403*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1404*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1405*0Sstevel@tonic-gate 				break;
1406*0Sstevel@tonic-gate 			case (DT_INIT_ARRAYSZ):
1407*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1408*0Sstevel@tonic-gate 					(const char *)"INIT_ARRAYSZ");
1409*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1410*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1411*0Sstevel@tonic-gate 				break;
1412*0Sstevel@tonic-gate 			case (DT_FINI_ARRAYSZ):
1413*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1414*0Sstevel@tonic-gate 					(const char *)"FINI_ARRAYSZ");
1415*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1416*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1417*0Sstevel@tonic-gate 				break;
1418*0Sstevel@tonic-gate 			case (DT_RUNPATH):
1419*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"RUNPATH");
1420*0Sstevel@tonic-gate 				if (v_flag)
1421*0Sstevel@tonic-gate 					dt_name = (char *)elf_strptr(elf_file,
1422*0Sstevel@tonic-gate 					    link, p_dyn.d_un.d_ptr);
1423*0Sstevel@tonic-gate 				if (dt_name == NULL)
1424*0Sstevel@tonic-gate 					dt_name = (char *)UNKNOWN;
1425*0Sstevel@tonic-gate 				if (v_flag && strlen(dt_name))
1426*0Sstevel@tonic-gate 					(void) printf("%s", dt_name);
1427*0Sstevel@tonic-gate 				else
1428*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1429*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1430*0Sstevel@tonic-gate 				break;
1431*0Sstevel@tonic-gate 			case (DT_FLAGS):
1432*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1433*0Sstevel@tonic-gate 				    (const char *)"FLAGS");
1434*0Sstevel@tonic-gate 				value[0] = '\0';
1435*0Sstevel@tonic-gate 				if (v_flag) {
1436*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_ORIGIN)
1437*0Sstevel@tonic-gate 					    (void) strcat(value,
1438*0Sstevel@tonic-gate 						(const char *)"ORIGIN ");
1439*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_SYMBOLIC)
1440*0Sstevel@tonic-gate 					    (void) strcat(value,
1441*0Sstevel@tonic-gate 						(const char *)"SYMBOLIC ");
1442*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_TEXTREL)
1443*0Sstevel@tonic-gate 					    (void) strcat(value,
1444*0Sstevel@tonic-gate 						(const char *)"TEXTREL ");
1445*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_BIND_NOW)
1446*0Sstevel@tonic-gate 					    (void) strcat(value,
1447*0Sstevel@tonic-gate 						(const char *)"BIND_NOW ");
1448*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_STATIC_TLS)
1449*0Sstevel@tonic-gate 					    (void) strcat(value,
1450*0Sstevel@tonic-gate 						(const char *)"STATIC_TLS ");
1451*0Sstevel@tonic-gate 				}
1452*0Sstevel@tonic-gate 				if (v_flag && strlen(value))
1453*0Sstevel@tonic-gate 					(void) printf("%s", value);
1454*0Sstevel@tonic-gate 				else
1455*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1456*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1457*0Sstevel@tonic-gate 				break;
1458*0Sstevel@tonic-gate 			case (DT_PREINIT_ARRAY):
1459*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1460*0Sstevel@tonic-gate 					(const char *)"PRINIT_ARRAY");
1461*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1462*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1463*0Sstevel@tonic-gate 				break;
1464*0Sstevel@tonic-gate 			case (DT_PREINIT_ARRAYSZ):
1465*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1466*0Sstevel@tonic-gate 					(const char *)"PRINIT_ARRAYSZ");
1467*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1468*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1469*0Sstevel@tonic-gate 				break;
1470*0Sstevel@tonic-gate 			/*
1471*0Sstevel@tonic-gate 			 * DT_LOOS - DT_HIOS range.
1472*0Sstevel@tonic-gate 			 */
1473*0Sstevel@tonic-gate 			case (DT_SUNW_AUXILIARY):
1474*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1475*0Sstevel@tonic-gate 					(const char *)"SUNW_AUXILIARY");
1476*0Sstevel@tonic-gate 				if (v_flag)
1477*0Sstevel@tonic-gate 					dt_name = (char *)elf_strptr(elf_file,
1478*0Sstevel@tonic-gate 					    link, p_dyn.d_un.d_ptr);
1479*0Sstevel@tonic-gate 				if (dt_name == NULL)
1480*0Sstevel@tonic-gate 					dt_name = (char *)UNKNOWN;
1481*0Sstevel@tonic-gate 				if (v_flag && strlen(dt_name))
1482*0Sstevel@tonic-gate 					(void) printf("%s", dt_name);
1483*0Sstevel@tonic-gate 				else
1484*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1485*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1486*0Sstevel@tonic-gate 				break;
1487*0Sstevel@tonic-gate 			case (DT_SUNW_RTLDINF):
1488*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1489*0Sstevel@tonic-gate 					(const char *)"SUNW_RTLDINF");
1490*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1491*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1492*0Sstevel@tonic-gate 				break;
1493*0Sstevel@tonic-gate 			case (DT_SUNW_FILTER):
1494*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1495*0Sstevel@tonic-gate 					(const char *)"SUNW_FILTER");
1496*0Sstevel@tonic-gate 				if (v_flag)
1497*0Sstevel@tonic-gate 					dt_name = (char *)elf_strptr(elf_file,
1498*0Sstevel@tonic-gate 					    link, p_dyn.d_un.d_ptr);
1499*0Sstevel@tonic-gate 				if (dt_name == NULL)
1500*0Sstevel@tonic-gate 					dt_name = (char *)UNKNOWN;
1501*0Sstevel@tonic-gate 				if (v_flag && strlen(dt_name))
1502*0Sstevel@tonic-gate 					(void) printf("%s", dt_name);
1503*0Sstevel@tonic-gate 				else
1504*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1505*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1506*0Sstevel@tonic-gate 				break;
1507*0Sstevel@tonic-gate 			case (DT_SUNW_CAP):
1508*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1509*0Sstevel@tonic-gate 					(const char *)"SUNW_CAP");
1510*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1511*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1512*0Sstevel@tonic-gate 				break;
1513*0Sstevel@tonic-gate 
1514*0Sstevel@tonic-gate 			/*
1515*0Sstevel@tonic-gate 			 * SUNW: DT_VALRNGLO - DT_VALRNGHI range.
1516*0Sstevel@tonic-gate 			 */
1517*0Sstevel@tonic-gate 			case (DT_CHECKSUM):
1518*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1519*0Sstevel@tonic-gate 					(const char *)"CHECKSUM");
1520*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1521*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1522*0Sstevel@tonic-gate 				break;
1523*0Sstevel@tonic-gate 			case (DT_PLTPADSZ):
1524*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1525*0Sstevel@tonic-gate 					(const char *)"PLTPADSZ");
1526*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1527*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1528*0Sstevel@tonic-gate 				break;
1529*0Sstevel@tonic-gate 			case (DT_MOVEENT):
1530*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1531*0Sstevel@tonic-gate 					(const char *)"MOVEENT");
1532*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1533*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1534*0Sstevel@tonic-gate 				break;
1535*0Sstevel@tonic-gate 			case (DT_MOVESZ):
1536*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1537*0Sstevel@tonic-gate 					(const char *)"MOVESZ");
1538*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1539*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1540*0Sstevel@tonic-gate 				break;
1541*0Sstevel@tonic-gate 			case (DT_FEATURE_1):
1542*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1543*0Sstevel@tonic-gate 					(const char *)"FEATURE_1");
1544*0Sstevel@tonic-gate 				value[0] = '\0';
1545*0Sstevel@tonic-gate 				if (v_flag) {
1546*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DTF_1_PARINIT)
1547*0Sstevel@tonic-gate 					    (void) strcat(value,
1548*0Sstevel@tonic-gate 						(const char *)"PARINIT ");
1549*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DTF_1_CONFEXP)
1550*0Sstevel@tonic-gate 					    (void) strcat(value,
1551*0Sstevel@tonic-gate 						(const char *)"CONFEXP ");
1552*0Sstevel@tonic-gate 				}
1553*0Sstevel@tonic-gate 				if (v_flag && strlen(value))
1554*0Sstevel@tonic-gate 					(void) printf("%s", value);
1555*0Sstevel@tonic-gate 				else
1556*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1557*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1558*0Sstevel@tonic-gate 				break;
1559*0Sstevel@tonic-gate 			case (DT_POSFLAG_1):
1560*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1561*0Sstevel@tonic-gate 					(const char *)"POSFLAG_1");
1562*0Sstevel@tonic-gate 				value[0] = '\0';
1563*0Sstevel@tonic-gate 				if (v_flag) {
1564*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_P1_LAZYLOAD)
1565*0Sstevel@tonic-gate 					    (void) strcat(value,
1566*0Sstevel@tonic-gate 						(const char *)"LAZYLOAD ");
1567*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_P1_GROUPPERM)
1568*0Sstevel@tonic-gate 					    (void) strcat(value,
1569*0Sstevel@tonic-gate 						(const char *)"GROUPPERM ");
1570*0Sstevel@tonic-gate 				}
1571*0Sstevel@tonic-gate 				if (v_flag && strlen(value))
1572*0Sstevel@tonic-gate 					(void) printf("%s", value);
1573*0Sstevel@tonic-gate 				else
1574*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1575*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1576*0Sstevel@tonic-gate 				break;
1577*0Sstevel@tonic-gate 			case (DT_SYMINSZ):
1578*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1579*0Sstevel@tonic-gate 					(const char *)"SYMINSZ");
1580*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1581*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1582*0Sstevel@tonic-gate 				break;
1583*0Sstevel@tonic-gate 			case (DT_SYMINENT):
1584*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1585*0Sstevel@tonic-gate 					(const char *)"SYMINENT");
1586*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1587*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1588*0Sstevel@tonic-gate 				break;
1589*0Sstevel@tonic-gate 
1590*0Sstevel@tonic-gate 			/*
1591*0Sstevel@tonic-gate 			 * SUNW: DT_ADDRRNGLO - DT_ADDRRNGHI range.
1592*0Sstevel@tonic-gate 			 */
1593*0Sstevel@tonic-gate 			case (DT_CONFIG):
1594*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"CONFIG");
1595*0Sstevel@tonic-gate 				if (v_flag)
1596*0Sstevel@tonic-gate 					dt_name = (char *)elf_strptr(elf_file,
1597*0Sstevel@tonic-gate 					    link, p_dyn.d_un.d_ptr);
1598*0Sstevel@tonic-gate 				if (dt_name == NULL)
1599*0Sstevel@tonic-gate 					dt_name = (char *)UNKNOWN;
1600*0Sstevel@tonic-gate 				if (v_flag && strlen(dt_name))
1601*0Sstevel@tonic-gate 					(void) printf("%s", dt_name);
1602*0Sstevel@tonic-gate 				else
1603*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1604*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1605*0Sstevel@tonic-gate 				break;
1606*0Sstevel@tonic-gate 			case (DT_DEPAUDIT):
1607*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1608*0Sstevel@tonic-gate 					(const char *)"DEPAUDIT");
1609*0Sstevel@tonic-gate 				if (v_flag)
1610*0Sstevel@tonic-gate 					dt_name = (char *)elf_strptr(elf_file,
1611*0Sstevel@tonic-gate 					    link, p_dyn.d_un.d_ptr);
1612*0Sstevel@tonic-gate 				if (dt_name == NULL)
1613*0Sstevel@tonic-gate 					dt_name = (char *)UNKNOWN;
1614*0Sstevel@tonic-gate 				if (v_flag && strlen(dt_name))
1615*0Sstevel@tonic-gate 					(void) printf("%s", dt_name);
1616*0Sstevel@tonic-gate 				else
1617*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1618*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1619*0Sstevel@tonic-gate 				break;
1620*0Sstevel@tonic-gate 			case (DT_AUDIT):
1621*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1622*0Sstevel@tonic-gate 					(const char *)"AUDIT");
1623*0Sstevel@tonic-gate 				if (v_flag)
1624*0Sstevel@tonic-gate 					dt_name = (char *)elf_strptr(elf_file,
1625*0Sstevel@tonic-gate 					    link, p_dyn.d_un.d_ptr);
1626*0Sstevel@tonic-gate 				if (dt_name == NULL)
1627*0Sstevel@tonic-gate 					dt_name = (char *)UNKNOWN;
1628*0Sstevel@tonic-gate 				if (v_flag && strlen(dt_name))
1629*0Sstevel@tonic-gate 					(void) printf("%s", dt_name);
1630*0Sstevel@tonic-gate 				else
1631*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1632*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1633*0Sstevel@tonic-gate 				break;
1634*0Sstevel@tonic-gate 			case (DT_PLTPAD):
1635*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1636*0Sstevel@tonic-gate 					(const char *)"PLTPAD");
1637*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1638*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1639*0Sstevel@tonic-gate 				break;
1640*0Sstevel@tonic-gate 			case (DT_MOVETAB):
1641*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1642*0Sstevel@tonic-gate 					(const char *)"MOVETAB");
1643*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1644*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1645*0Sstevel@tonic-gate 				break;
1646*0Sstevel@tonic-gate 			case (DT_SYMINFO):
1647*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1648*0Sstevel@tonic-gate 					(const char *)"SYMINFO");
1649*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1650*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1651*0Sstevel@tonic-gate 				break;
1652*0Sstevel@tonic-gate 
1653*0Sstevel@tonic-gate 			/*
1654*0Sstevel@tonic-gate 			 * SUNW: generic range.
1655*0Sstevel@tonic-gate 			 */
1656*0Sstevel@tonic-gate 			case (DT_RELACOUNT):
1657*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1658*0Sstevel@tonic-gate 					(const char *)"RELACOUNT");
1659*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1660*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1661*0Sstevel@tonic-gate 				break;
1662*0Sstevel@tonic-gate 			case (DT_RELCOUNT):
1663*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1664*0Sstevel@tonic-gate 					(const char *)"RELCOUNT");
1665*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1666*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1667*0Sstevel@tonic-gate 				break;
1668*0Sstevel@tonic-gate 			case (DT_FLAGS_1):
1669*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1670*0Sstevel@tonic-gate 				    (const char *)"FLAGS_1");
1671*0Sstevel@tonic-gate 				value[0] = '\0';
1672*0Sstevel@tonic-gate 				if (v_flag) {
1673*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_NOW)
1674*0Sstevel@tonic-gate 					    (void) strcat(value,
1675*0Sstevel@tonic-gate 						(const char *)"NOW ");
1676*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_GLOBAL)
1677*0Sstevel@tonic-gate 					    (void) strcat(value,
1678*0Sstevel@tonic-gate 						(const char *)"GLOBAL ");
1679*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_GROUP)
1680*0Sstevel@tonic-gate 					    (void) strcat(value,
1681*0Sstevel@tonic-gate 						(const char *)"GROUP ");
1682*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_NODELETE)
1683*0Sstevel@tonic-gate 					    (void) strcat(value,
1684*0Sstevel@tonic-gate 						(const char *)"NODELETE ");
1685*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_LOADFLTR)
1686*0Sstevel@tonic-gate 					    (void) strcat(value,
1687*0Sstevel@tonic-gate 						(const char *)"LOADFLTR ");
1688*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_INITFIRST)
1689*0Sstevel@tonic-gate 					    (void) strcat(value,
1690*0Sstevel@tonic-gate 						(const char *)"INITFIRST ");
1691*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_NOOPEN)
1692*0Sstevel@tonic-gate 					    (void) strcat(value,
1693*0Sstevel@tonic-gate 						(const char *)"NOOPEN ");
1694*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_ORIGIN)
1695*0Sstevel@tonic-gate 					    (void) strcat(value,
1696*0Sstevel@tonic-gate 						(const char *)"ORIGIN ");
1697*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_DIRECT)
1698*0Sstevel@tonic-gate 					    (void) strcat(value,
1699*0Sstevel@tonic-gate 						(const char *)"DIRECT ");
1700*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_TRANS)
1701*0Sstevel@tonic-gate 					    (void) strcat(value,
1702*0Sstevel@tonic-gate 						(const char *)"TRANS ");
1703*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_INTERPOSE)
1704*0Sstevel@tonic-gate 					    (void) strcat(value,
1705*0Sstevel@tonic-gate 						(const char *)"INTERPOSE ");
1706*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_NODEFLIB)
1707*0Sstevel@tonic-gate 					    (void) strcat(value,
1708*0Sstevel@tonic-gate 						(const char *)"NODEFLIB ");
1709*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_NODUMP)
1710*0Sstevel@tonic-gate 					    (void) strcat(value,
1711*0Sstevel@tonic-gate 						(const char *)"NODUMP ");
1712*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_CONFALT)
1713*0Sstevel@tonic-gate 					    (void) strcat(value,
1714*0Sstevel@tonic-gate 						(const char *)"CONFALT ");
1715*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_ENDFILTEE)
1716*0Sstevel@tonic-gate 					    (void) strcat(value,
1717*0Sstevel@tonic-gate 						(const char *)"ENDFILTEE ");
1718*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_DISPRELDNE)
1719*0Sstevel@tonic-gate 					    (void) strcat(value,
1720*0Sstevel@tonic-gate 						(const char *)"DISPRELDONE ");
1721*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_DISPRELPND)
1722*0Sstevel@tonic-gate 					    (void) strcat(value,
1723*0Sstevel@tonic-gate 						(const char *)"DISPRELPND ");
1724*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_IGNMULDEF)
1725*0Sstevel@tonic-gate 					    (void) strcat(value,
1726*0Sstevel@tonic-gate 						(const char *)"IGNMULDEF ");
1727*0Sstevel@tonic-gate 					if (p_dyn.d_un.d_val & DF_1_NOKSYMS)
1728*0Sstevel@tonic-gate 					    (void) strcat(value,
1729*0Sstevel@tonic-gate 						(const char *)"NOKSYMS ");
1730*0Sstevel@tonic-gate 				}
1731*0Sstevel@tonic-gate 				if (v_flag && strlen(value))
1732*0Sstevel@tonic-gate 					(void) printf("%s", value);
1733*0Sstevel@tonic-gate 				else
1734*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1735*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1736*0Sstevel@tonic-gate 				break;
1737*0Sstevel@tonic-gate 			case (DT_VERSYM):
1738*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"VERSYM");
1739*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1740*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1741*0Sstevel@tonic-gate 				break;
1742*0Sstevel@tonic-gate 			case (DT_VERDEF):
1743*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"VERDEF");
1744*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1745*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1746*0Sstevel@tonic-gate 				break;
1747*0Sstevel@tonic-gate 			case (DT_VERDEFNUM):
1748*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1749*0Sstevel@tonic-gate 				    (const char *)"VERDEFNUM");
1750*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1751*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1752*0Sstevel@tonic-gate 				break;
1753*0Sstevel@tonic-gate 			case (DT_VERNEED):
1754*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"VERNEED");
1755*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1756*0Sstevel@tonic-gate 					EC_ADDR(p_dyn.d_un.d_ptr));
1757*0Sstevel@tonic-gate 				break;
1758*0Sstevel@tonic-gate 			case (DT_VERNEEDNUM):
1759*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1760*0Sstevel@tonic-gate 				    (const char *)"VERNEEDNUM");
1761*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1762*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1763*0Sstevel@tonic-gate 				break;
1764*0Sstevel@tonic-gate 			case (DT_AUXILIARY):
1765*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1766*0Sstevel@tonic-gate 					(const char *)"AUXILIARY");
1767*0Sstevel@tonic-gate 				if (v_flag)
1768*0Sstevel@tonic-gate 					dt_name = (char *)elf_strptr(elf_file,
1769*0Sstevel@tonic-gate 					    link, p_dyn.d_un.d_ptr);
1770*0Sstevel@tonic-gate 				if (dt_name == NULL)
1771*0Sstevel@tonic-gate 					dt_name = (char *)UNKNOWN;
1772*0Sstevel@tonic-gate 				if (v_flag && strlen(dt_name))
1773*0Sstevel@tonic-gate 					(void) printf("%s", dt_name);
1774*0Sstevel@tonic-gate 				else
1775*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1776*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1777*0Sstevel@tonic-gate 				break;
1778*0Sstevel@tonic-gate 			case (DT_USED):
1779*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"USED");
1780*0Sstevel@tonic-gate 				if (v_flag)
1781*0Sstevel@tonic-gate 					dt_name = (char *)elf_strptr(elf_file,
1782*0Sstevel@tonic-gate 					    link, p_dyn.d_un.d_ptr);
1783*0Sstevel@tonic-gate 				if (dt_name == NULL)
1784*0Sstevel@tonic-gate 					dt_name = (char *)UNKNOWN;
1785*0Sstevel@tonic-gate 				if (v_flag && strlen(dt_name))
1786*0Sstevel@tonic-gate 					(void) printf("%s", dt_name);
1787*0Sstevel@tonic-gate 				else
1788*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1789*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1790*0Sstevel@tonic-gate 				break;
1791*0Sstevel@tonic-gate 			case (DT_FILTER):
1792*0Sstevel@tonic-gate 				(void) printf(Fmttag, (const char *)"FILTER");
1793*0Sstevel@tonic-gate 				if (v_flag)
1794*0Sstevel@tonic-gate 					dt_name = (char *)elf_strptr(elf_file,
1795*0Sstevel@tonic-gate 					    link, p_dyn.d_un.d_ptr);
1796*0Sstevel@tonic-gate 				if (dt_name == NULL)
1797*0Sstevel@tonic-gate 					dt_name = (char *)UNKNOWN;
1798*0Sstevel@tonic-gate 				if (v_flag && strlen(dt_name))
1799*0Sstevel@tonic-gate 					(void) printf("%s", dt_name);
1800*0Sstevel@tonic-gate 				else
1801*0Sstevel@tonic-gate 					(void) printf(Fmtptr,
1802*0Sstevel@tonic-gate 						EC_ADDR(p_dyn.d_un.d_ptr));
1803*0Sstevel@tonic-gate 				break;
1804*0Sstevel@tonic-gate 
1805*0Sstevel@tonic-gate 			/*
1806*0Sstevel@tonic-gate 			 * SUNW: machine specific range.
1807*0Sstevel@tonic-gate 			 */
1808*0Sstevel@tonic-gate 			case (DT_SPARC_REGISTER):
1809*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1810*0Sstevel@tonic-gate 					(const char *)"REGISTER");
1811*0Sstevel@tonic-gate 				(void) printf(Fmtptr,
1812*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1813*0Sstevel@tonic-gate 				break;
1814*0Sstevel@tonic-gate 			case (DT_DEPRECATED_SPARC_REGISTER):
1815*0Sstevel@tonic-gate 				(void) printf(Fmttag,
1816*0Sstevel@tonic-gate 					(const char *)"REGISTER");
1817*0Sstevel@tonic-gate 				(void) printf("%#llx  (deprecated value)",
1818*0Sstevel@tonic-gate 					EC_XWORD(p_dyn.d_un.d_val));
1819*0Sstevel@tonic-gate 				break;
1820*0Sstevel@tonic-gate 			default:
1821*0Sstevel@tonic-gate 				(void) printf("%lld", EC_XWORD(p_dyn.d_tag));
1822*0Sstevel@tonic-gate 				break;
1823*0Sstevel@tonic-gate 			}
1824*0Sstevel@tonic-gate 			(void) printf("\n");
1825*0Sstevel@tonic-gate 			(void) gelf_getdyn(dyn_data, ii++, &p_dyn);
1826*0Sstevel@tonic-gate 		}
1827*0Sstevel@tonic-gate 	}
1828*0Sstevel@tonic-gate 
1829*0Sstevel@tonic-gate 	/*
1830*0Sstevel@tonic-gate 	 * Check for existence of static shared library information.
1831*0Sstevel@tonic-gate 	 */
1832*0Sstevel@tonic-gate 	(void) gelf_getehdr(elf_file, &p_ehdr);
1833*0Sstevel@tonic-gate 	while (header_num < p_ehdr.e_phnum) {
1834*0Sstevel@tonic-gate 		(void) gelf_getphdr(elf_file, header_num, &p_phdr);
1835*0Sstevel@tonic-gate 		if (p_phdr.p_type == PT_SHLIB) {
1836*0Sstevel@tonic-gate 			while (--lib_scns > 0) {
1837*0Sstevel@tonic-gate 				if (strcmp(l_scns->scn_name, ".lib") == 0) {
1838*0Sstevel@tonic-gate 					print_static(l_scns, filename);
1839*0Sstevel@tonic-gate 				}
1840*0Sstevel@tonic-gate 				l_scns++;
1841*0Sstevel@tonic-gate 			}
1842*0Sstevel@tonic-gate 		}
1843*0Sstevel@tonic-gate 		header_num++;
1844*0Sstevel@tonic-gate 	}
1845*0Sstevel@tonic-gate }
1846*0Sstevel@tonic-gate 
1847*0Sstevel@tonic-gate /*
1848*0Sstevel@tonic-gate  * Print the ELF header.  Input is an ELF file descriptor
1849*0Sstevel@tonic-gate  * and the filename.  If f_flag is set, the ELF header is
1850*0Sstevel@tonic-gate  * printed to stdout, otherwise the function returns after
1851*0Sstevel@tonic-gate  * setting the pointer to the ELF header.  Any values which
1852*0Sstevel@tonic-gate  * are not known are printed in decimal.  Fields must be updated
1853*0Sstevel@tonic-gate  * as new values are added.
1854*0Sstevel@tonic-gate  */
1855*0Sstevel@tonic-gate static GElf_Ehdr *
1856*0Sstevel@tonic-gate dump_elf_header(Elf *elf_file, char *filename, GElf_Ehdr * elf_head_p)
1857*0Sstevel@tonic-gate {
1858*0Sstevel@tonic-gate 	int class, data;
1859*0Sstevel@tonic-gate 	int field;
1860*0Sstevel@tonic-gate 
1861*0Sstevel@tonic-gate 	if (gelf_getehdr(elf_file, elf_head_p) == NULL) {
1862*0Sstevel@tonic-gate 		(void) fprintf(stderr,
1863*0Sstevel@tonic-gate 		"%s: %s: %s\n", prog_name, filename, elf_errmsg(-1));
1864*0Sstevel@tonic-gate 		return (NULL);
1865*0Sstevel@tonic-gate 	}
1866*0Sstevel@tonic-gate 
1867*0Sstevel@tonic-gate 	class = (int)elf_head_p->e_ident[4];
1868*0Sstevel@tonic-gate 
1869*0Sstevel@tonic-gate 	if (class == ELFCLASS64)
1870*0Sstevel@tonic-gate 		field = 17;
1871*0Sstevel@tonic-gate 	else
1872*0Sstevel@tonic-gate 		field = 13;
1873*0Sstevel@tonic-gate 
1874*0Sstevel@tonic-gate 	if (!f_flag)
1875*0Sstevel@tonic-gate 		return (elf_head_p);
1876*0Sstevel@tonic-gate 
1877*0Sstevel@tonic-gate 	if (!p_flag) {
1878*0Sstevel@tonic-gate 	(void) printf(
1879*0Sstevel@tonic-gate 		"\n                    **** ELF HEADER ****\n");
1880*0Sstevel@tonic-gate 	(void) printf("%-*s%-11s%-*sMachine     Version\n",
1881*0Sstevel@tonic-gate 	    field, "Class", "Data", field, "Type");
1882*0Sstevel@tonic-gate 	(void) printf("%-*s%-11s%-*sFlags       Ehsize\n",
1883*0Sstevel@tonic-gate 	    field, "Entry", "Phoff", field, "Shoff");
1884*0Sstevel@tonic-gate 	(void) printf("%-*s%-11s%-*sShnum       Shstrndx\n\n",
1885*0Sstevel@tonic-gate 	    field, "Phentsize", "Phnum", field, "Shentsz");
1886*0Sstevel@tonic-gate 	}
1887*0Sstevel@tonic-gate 
1888*0Sstevel@tonic-gate 	if (!v_flag) {
1889*0Sstevel@tonic-gate 		(void) printf("%-*d%-11d%-*d%-12d%d\n",
1890*0Sstevel@tonic-gate 			field, elf_head_p->e_ident[4],
1891*0Sstevel@tonic-gate 			elf_head_p->e_ident[5],
1892*0Sstevel@tonic-gate 			field, (int)elf_head_p->e_type,
1893*0Sstevel@tonic-gate 			(int)elf_head_p->e_machine,
1894*0Sstevel@tonic-gate 			elf_head_p->e_version);
1895*0Sstevel@tonic-gate 	} else {
1896*0Sstevel@tonic-gate 		data = elf_head_p->e_ident[5];
1897*0Sstevel@tonic-gate 
1898*0Sstevel@tonic-gate 		switch (class) {
1899*0Sstevel@tonic-gate 		case ELFCLASSNONE:
1900*0Sstevel@tonic-gate 			(void) printf("%-*s", field, "None");
1901*0Sstevel@tonic-gate 			break;
1902*0Sstevel@tonic-gate 		case ELFCLASS32:
1903*0Sstevel@tonic-gate 			(void) printf("%-*s", field, "32-bit");
1904*0Sstevel@tonic-gate 			break;
1905*0Sstevel@tonic-gate 		case ELFCLASS64:
1906*0Sstevel@tonic-gate 			(void) printf("%-*s", field, "64-bit");
1907*0Sstevel@tonic-gate 			break;
1908*0Sstevel@tonic-gate 		default:
1909*0Sstevel@tonic-gate 			(void) printf("%-*d", field, class);
1910*0Sstevel@tonic-gate 			break;
1911*0Sstevel@tonic-gate 		}
1912*0Sstevel@tonic-gate 		switch (data) {
1913*0Sstevel@tonic-gate 		case ELFDATANONE:
1914*0Sstevel@tonic-gate 			(void) printf("%-11s", "None   ");
1915*0Sstevel@tonic-gate 			break;
1916*0Sstevel@tonic-gate 		case ELFDATA2LSB:
1917*0Sstevel@tonic-gate 			(void) printf("%-11s", "2LSB   ");
1918*0Sstevel@tonic-gate 			break;
1919*0Sstevel@tonic-gate 		case ELFDATA2MSB:
1920*0Sstevel@tonic-gate 			(void) printf("%-11s", "2MSB   ");
1921*0Sstevel@tonic-gate 			break;
1922*0Sstevel@tonic-gate 		default:
1923*0Sstevel@tonic-gate 			(void) printf("%-11d", data);
1924*0Sstevel@tonic-gate 			break;
1925*0Sstevel@tonic-gate 		}
1926*0Sstevel@tonic-gate 
1927*0Sstevel@tonic-gate 		switch (elf_head_p->e_type) {
1928*0Sstevel@tonic-gate 		case ET_NONE:
1929*0Sstevel@tonic-gate 			(void) printf("%-*s", field, "None");
1930*0Sstevel@tonic-gate 			break;
1931*0Sstevel@tonic-gate 		case ET_REL:
1932*0Sstevel@tonic-gate 			(void) printf("%-*s", field, "Reloc");
1933*0Sstevel@tonic-gate 			break;
1934*0Sstevel@tonic-gate 		case ET_EXEC:
1935*0Sstevel@tonic-gate 			(void) printf("%-*s", field, "Exec");
1936*0Sstevel@tonic-gate 			break;
1937*0Sstevel@tonic-gate 		case ET_DYN:
1938*0Sstevel@tonic-gate 			(void) printf("%-*s", field, "Dyn");
1939*0Sstevel@tonic-gate 			break;
1940*0Sstevel@tonic-gate 		case ET_CORE:
1941*0Sstevel@tonic-gate 			(void) printf("%-*s", field, "Core");
1942*0Sstevel@tonic-gate 			break;
1943*0Sstevel@tonic-gate 		default:
1944*0Sstevel@tonic-gate 			(void) printf("%-*d", field,
1945*0Sstevel@tonic-gate 				EC_WORD(elf_head_p->e_type));
1946*0Sstevel@tonic-gate 			break;
1947*0Sstevel@tonic-gate 		}
1948*0Sstevel@tonic-gate 		switch (elf_head_p->e_machine) {
1949*0Sstevel@tonic-gate 		case EM_NONE:
1950*0Sstevel@tonic-gate 			(void) printf("%-12s", "No mach");
1951*0Sstevel@tonic-gate 			break;
1952*0Sstevel@tonic-gate 		case EM_M32:
1953*0Sstevel@tonic-gate 			(void) printf("%-12s", "WE32100");
1954*0Sstevel@tonic-gate 			break;
1955*0Sstevel@tonic-gate 		case EM_SPARC:
1956*0Sstevel@tonic-gate 			(void) printf("%-12s", "SPARC");
1957*0Sstevel@tonic-gate 			break;
1958*0Sstevel@tonic-gate 		case EM_SPARCV9:
1959*0Sstevel@tonic-gate 			(void) printf("%-12s", "SPARCV9");
1960*0Sstevel@tonic-gate 			break;
1961*0Sstevel@tonic-gate 		case EM_386:
1962*0Sstevel@tonic-gate 			(void) printf("%-12s", "80386");
1963*0Sstevel@tonic-gate 			break;
1964*0Sstevel@tonic-gate 		case EM_68K:
1965*0Sstevel@tonic-gate 			(void) printf("%-12s", "68000");
1966*0Sstevel@tonic-gate 			break;
1967*0Sstevel@tonic-gate 		case EM_88K:
1968*0Sstevel@tonic-gate 			(void) printf("%-12s", "88000");
1969*0Sstevel@tonic-gate 			break;
1970*0Sstevel@tonic-gate 		case EM_486:
1971*0Sstevel@tonic-gate 			(void) printf("%-12s", "80486");
1972*0Sstevel@tonic-gate 			break;
1973*0Sstevel@tonic-gate 		case EM_860:
1974*0Sstevel@tonic-gate 			(void) printf("%-12s", "i860");
1975*0Sstevel@tonic-gate 			break;
1976*0Sstevel@tonic-gate 		case EM_MIPS:
1977*0Sstevel@tonic-gate 			(void) printf("%-12s", "RS3000_BE");
1978*0Sstevel@tonic-gate 			break;
1979*0Sstevel@tonic-gate 		case EM_MIPS_RS3_LE:
1980*0Sstevel@tonic-gate 			(void) printf("%-12s", "RS3000_LE");
1981*0Sstevel@tonic-gate 			break;
1982*0Sstevel@tonic-gate 		case EM_RS6000:
1983*0Sstevel@tonic-gate 			(void) printf("%-12s", "RS6000");
1984*0Sstevel@tonic-gate 			break;
1985*0Sstevel@tonic-gate 		case EM_PA_RISC:
1986*0Sstevel@tonic-gate 			(void) printf("%-12s", "PA_RISC");
1987*0Sstevel@tonic-gate 			break;
1988*0Sstevel@tonic-gate 		case EM_nCUBE:
1989*0Sstevel@tonic-gate 			(void) printf("%-12s", "nCUBE");
1990*0Sstevel@tonic-gate 			break;
1991*0Sstevel@tonic-gate 		case EM_VPP500:
1992*0Sstevel@tonic-gate 			(void) printf("%-12s", "VPP500");
1993*0Sstevel@tonic-gate 			break;
1994*0Sstevel@tonic-gate 		case EM_SPARC32PLUS:
1995*0Sstevel@tonic-gate 			(void) printf("%-12s", "SPARC32PLUS");
1996*0Sstevel@tonic-gate 			break;
1997*0Sstevel@tonic-gate 		case EM_PPC:
1998*0Sstevel@tonic-gate 			(void) printf("%-12s", "PowerPC");
1999*0Sstevel@tonic-gate 			break;
2000*0Sstevel@tonic-gate 		case EM_IA_64:
2001*0Sstevel@tonic-gate 			(void) printf("%-12s", "IA64");
2002*0Sstevel@tonic-gate 			break;
2003*0Sstevel@tonic-gate 		default:
2004*0Sstevel@tonic-gate 			(void) printf("%-12d", EC_WORD(elf_head_p->e_machine));
2005*0Sstevel@tonic-gate 		}
2006*0Sstevel@tonic-gate 		switch (elf_head_p->e_version) {
2007*0Sstevel@tonic-gate 		case EV_NONE:
2008*0Sstevel@tonic-gate 			(void) printf("Invalid\n");
2009*0Sstevel@tonic-gate 			break;
2010*0Sstevel@tonic-gate 		case EV_CURRENT:
2011*0Sstevel@tonic-gate 			(void) printf("Current\n");
2012*0Sstevel@tonic-gate 			break;
2013*0Sstevel@tonic-gate 		default:
2014*0Sstevel@tonic-gate 			(void) printf("%d\n", elf_head_p->e_version);
2015*0Sstevel@tonic-gate 		}
2016*0Sstevel@tonic-gate 	}
2017*0Sstevel@tonic-gate 	(void) printf("%-#*llx%-#11llx%-#*llx%-#12x%#x\n",
2018*0Sstevel@tonic-gate 		field, EC_ADDR(elf_head_p->e_entry),
2019*0Sstevel@tonic-gate 		EC_OFF(elf_head_p->e_phoff),
2020*0Sstevel@tonic-gate 		field, EC_OFF(elf_head_p->e_shoff),
2021*0Sstevel@tonic-gate 		EC_WORD(elf_head_p->e_flags),
2022*0Sstevel@tonic-gate 		EC_WORD(elf_head_p->e_ehsize));
2023*0Sstevel@tonic-gate 	if (!v_flag || (elf_head_p->e_shstrndx != SHN_XINDEX)) {
2024*0Sstevel@tonic-gate 		(void) printf("%-#*x%-11u%-#*x%-12u%u\n",
2025*0Sstevel@tonic-gate 			field, EC_WORD(elf_head_p->e_phentsize),
2026*0Sstevel@tonic-gate 			EC_WORD(elf_head_p->e_phnum),
2027*0Sstevel@tonic-gate 			field, EC_WORD(elf_head_p->e_shentsize),
2028*0Sstevel@tonic-gate 			EC_WORD(elf_head_p->e_shnum),
2029*0Sstevel@tonic-gate 			EC_WORD(elf_head_p->e_shstrndx));
2030*0Sstevel@tonic-gate 	} else {
2031*0Sstevel@tonic-gate 		(void) printf("%-#*x%-11u%-#*x%-12uXINDEX\n",
2032*0Sstevel@tonic-gate 			field, EC_WORD(elf_head_p->e_phentsize),
2033*0Sstevel@tonic-gate 			EC_WORD(elf_head_p->e_phnum),
2034*0Sstevel@tonic-gate 			field, EC_WORD(elf_head_p->e_shentsize),
2035*0Sstevel@tonic-gate 			EC_WORD(elf_head_p->e_shnum));
2036*0Sstevel@tonic-gate 	}
2037*0Sstevel@tonic-gate 	if ((elf_head_p->e_shnum == 0) && (elf_head_p->e_shoff > 0)) {
2038*0Sstevel@tonic-gate 		Elf_Scn		*scn;
2039*0Sstevel@tonic-gate 		GElf_Shdr	shdr0;
2040*0Sstevel@tonic-gate 		int		field;
2041*0Sstevel@tonic-gate 
2042*0Sstevel@tonic-gate 		if (gelf_getclass(elf_file) == ELFCLASS64)
2043*0Sstevel@tonic-gate 			field = 14;
2044*0Sstevel@tonic-gate 		else
2045*0Sstevel@tonic-gate 			field = 12;
2046*0Sstevel@tonic-gate 		if (!p_flag) {
2047*0Sstevel@tonic-gate 			(void) printf("\n	   **** SECTION HEADER[0] "
2048*0Sstevel@tonic-gate 			    "{Elf Extensions} ****\n");
2049*0Sstevel@tonic-gate 			(void) printf(
2050*0Sstevel@tonic-gate 			    "[No]\tType\tFlags\t%-*s %-*s%-*s%sName\n",
2051*0Sstevel@tonic-gate 			    field, "Addr", field, "Offset", field,
2052*0Sstevel@tonic-gate 			    "Size(shnum)",
2053*0Sstevel@tonic-gate 			    /* compatibility:  tab for elf32 */
2054*0Sstevel@tonic-gate 			    (field == 12) ? "\t" : "  ");
2055*0Sstevel@tonic-gate 			(void) printf("\tLn(strndx) Info\t%-*s Entsize\n",
2056*0Sstevel@tonic-gate 			    field, "Adralgn");
2057*0Sstevel@tonic-gate 		}
2058*0Sstevel@tonic-gate 		if ((scn = elf_getscn(elf_file, 0)) == NULL) {
2059*0Sstevel@tonic-gate 			(void) fprintf(stderr,
2060*0Sstevel@tonic-gate 				"%s: %s: elf_getscn failed: %s\n",
2061*0Sstevel@tonic-gate 				prog_name, filename, elf_errmsg(-1));
2062*0Sstevel@tonic-gate 			return (NULL);
2063*0Sstevel@tonic-gate 		}
2064*0Sstevel@tonic-gate 		if (gelf_getshdr(scn, &shdr0) == 0) {
2065*0Sstevel@tonic-gate 			(void) fprintf(stderr,
2066*0Sstevel@tonic-gate 				"%s: %s: gelf_getshdr: %s\n",
2067*0Sstevel@tonic-gate 				prog_name, filename, elf_errmsg(-1));
2068*0Sstevel@tonic-gate 			return (NULL);
2069*0Sstevel@tonic-gate 		}
2070*0Sstevel@tonic-gate 		(void) printf("[0]\t%u\t%llu\t", EC_WORD(shdr0.sh_type),
2071*0Sstevel@tonic-gate 			EC_XWORD(shdr0.sh_flags));
2072*0Sstevel@tonic-gate 
2073*0Sstevel@tonic-gate 		/*
2074*0Sstevel@tonic-gate 		 * LINTED - field and EC_XWORD cause -#*llu complaints that
2075*0Sstevel@tonic-gate 		 * even this comment can't shutup.
2076*0Sstevel@tonic-gate 		 */
2077*0Sstevel@tonic-gate 		(void) printf("%-#*llx %-#*llx%-#*llu%s%-#*u\n",
2078*0Sstevel@tonic-gate 			field, EC_ADDR(shdr0.sh_addr),
2079*0Sstevel@tonic-gate 			field, EC_OFF(shdr0.sh_offset),
2080*0Sstevel@tonic-gate 			field, EC_XWORD(shdr0.sh_size),
2081*0Sstevel@tonic-gate 			/* compatibility:  tab for elf32 */
2082*0Sstevel@tonic-gate 			((field == 12) ? "\t" : "  "),
2083*0Sstevel@tonic-gate 			field, EC_WORD(shdr0.sh_name));
2084*0Sstevel@tonic-gate 
2085*0Sstevel@tonic-gate 		(void) printf("\t%u\t%u\t%-#*llx %-#*llx\n",
2086*0Sstevel@tonic-gate 			EC_WORD(shdr0.sh_link),
2087*0Sstevel@tonic-gate 			EC_WORD(shdr0.sh_info),
2088*0Sstevel@tonic-gate 			field, EC_XWORD(shdr0.sh_addralign),
2089*0Sstevel@tonic-gate 			field, EC_XWORD(shdr0.sh_entsize));
2090*0Sstevel@tonic-gate 	}
2091*0Sstevel@tonic-gate 	(void) printf("\n");
2092*0Sstevel@tonic-gate 
2093*0Sstevel@tonic-gate 	return (elf_head_p);
2094*0Sstevel@tonic-gate }
2095*0Sstevel@tonic-gate 
2096*0Sstevel@tonic-gate /*
2097*0Sstevel@tonic-gate  * Print section contents.  Input is an ELF file descriptor,
2098*0Sstevel@tonic-gate  * the ELF header, the SCNTAB structure,
2099*0Sstevel@tonic-gate  * the number of symbols, and the filename.
2100*0Sstevel@tonic-gate  * The number of sections,
2101*0Sstevel@tonic-gate  * and the offset into the SCNTAB structure will be
2102*0Sstevel@tonic-gate  * set in dump_section if d_flag or n_flag are set.
2103*0Sstevel@tonic-gate  * If v_flag is set, sections which can be interpreted will
2104*0Sstevel@tonic-gate  * be interpreted, otherwise raw data will be output in hexidecimal.
2105*0Sstevel@tonic-gate  */
2106*0Sstevel@tonic-gate static void
2107*0Sstevel@tonic-gate print_section(Elf *elf_file,
2108*0Sstevel@tonic-gate 	GElf_Ehdr *p_ehdr, SCNTAB *p, int num_scns, char *filename)
2109*0Sstevel@tonic-gate {
2110*0Sstevel@tonic-gate 	unsigned char    *p_sec;
2111*0Sstevel@tonic-gate 	int	i;
2112*0Sstevel@tonic-gate 	size_t	size;
2113*0Sstevel@tonic-gate 
2114*0Sstevel@tonic-gate 	for (i = 0; i < num_scns; i++, p++) {
2115*0Sstevel@tonic-gate 		GElf_Shdr shdr;
2116*0Sstevel@tonic-gate 
2117*0Sstevel@tonic-gate 		size = 0;
2118*0Sstevel@tonic-gate 		if (s_flag && !v_flag)
2119*0Sstevel@tonic-gate 			p_sec = (unsigned char *)get_rawscn(p->p_sd, &size);
2120*0Sstevel@tonic-gate 		else
2121*0Sstevel@tonic-gate 			p_sec = (unsigned char *)get_scndata(p->p_sd, &size);
2122*0Sstevel@tonic-gate 
2123*0Sstevel@tonic-gate 		if ((gelf_getshdr(p->p_sd, &shdr) != NULL) &&
2124*0Sstevel@tonic-gate 		    (shdr.sh_type == SHT_NOBITS)) {
2125*0Sstevel@tonic-gate 			continue;
2126*0Sstevel@tonic-gate 		}
2127*0Sstevel@tonic-gate 		if (s_flag && !v_flag) {
2128*0Sstevel@tonic-gate 			(void) printf("\n%s:\n", p->scn_name);
2129*0Sstevel@tonic-gate 			print_rawdata(p_sec, size);
2130*0Sstevel@tonic-gate 			continue;
2131*0Sstevel@tonic-gate 		}
2132*0Sstevel@tonic-gate 		if (shdr.sh_type == SHT_SYMTAB) {
2133*0Sstevel@tonic-gate 			dump_symbol_table(elf_file, p, filename);
2134*0Sstevel@tonic-gate 			continue;
2135*0Sstevel@tonic-gate 		}
2136*0Sstevel@tonic-gate 		if (shdr.sh_type == SHT_DYNSYM) {
2137*0Sstevel@tonic-gate 			dump_symbol_table(elf_file, p, filename);
2138*0Sstevel@tonic-gate 			continue;
2139*0Sstevel@tonic-gate 		}
2140*0Sstevel@tonic-gate 		if (shdr.sh_type == SHT_STRTAB) {
2141*0Sstevel@tonic-gate 			dump_string_table(p, 1);
2142*0Sstevel@tonic-gate 			continue;
2143*0Sstevel@tonic-gate 		}
2144*0Sstevel@tonic-gate 		if (shdr.sh_type == SHT_RELA) {
2145*0Sstevel@tonic-gate 			dump_reloc_table(elf_file, p_ehdr, p, 1, filename);
2146*0Sstevel@tonic-gate 			continue;
2147*0Sstevel@tonic-gate 		}
2148*0Sstevel@tonic-gate 		if (shdr.sh_type == SHT_REL) {
2149*0Sstevel@tonic-gate 			dump_reloc_table(elf_file, p_ehdr, p, 1, filename);
2150*0Sstevel@tonic-gate 			continue;
2151*0Sstevel@tonic-gate 		}
2152*0Sstevel@tonic-gate 		if (shdr.sh_type == SHT_DYNAMIC) {
2153*0Sstevel@tonic-gate 			dump_dynamic(elf_file, p, 1, filename);
2154*0Sstevel@tonic-gate 			continue;
2155*0Sstevel@tonic-gate 		}
2156*0Sstevel@tonic-gate 
2157*0Sstevel@tonic-gate 		(void) printf("\n%s:\n", p->scn_name);
2158*0Sstevel@tonic-gate 		print_rawdata(p_sec, size);
2159*0Sstevel@tonic-gate 	}
2160*0Sstevel@tonic-gate 	(void) printf("\n");
2161*0Sstevel@tonic-gate }
2162*0Sstevel@tonic-gate 
2163*0Sstevel@tonic-gate /*
2164*0Sstevel@tonic-gate  * Print section contents. This function does not print the contents
2165*0Sstevel@tonic-gate  * of the sections but sets up the parameters and then calls
2166*0Sstevel@tonic-gate  * print_section to print the contents.  Calling another function to print
2167*0Sstevel@tonic-gate  * the contents allows both -d and -n to work correctly
2168*0Sstevel@tonic-gate  * simultaneously. Input is an ELF file descriptor, the ELF header,
2169*0Sstevel@tonic-gate  * the SCNTAB structure, the number of sections, and the filename.
2170*0Sstevel@tonic-gate  * Set the range of sections if d_flag, and set section name if
2171*0Sstevel@tonic-gate  * n_flag.
2172*0Sstevel@tonic-gate  */
2173*0Sstevel@tonic-gate static void
2174*0Sstevel@tonic-gate dump_section(Elf *elf_file,
2175*0Sstevel@tonic-gate 	GElf_Ehdr *p_ehdr, SCNTAB *s, int num_scns, char *filename)
2176*0Sstevel@tonic-gate {
2177*0Sstevel@tonic-gate 	SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */
2178*0Sstevel@tonic-gate 	int i;
2179*0Sstevel@tonic-gate 	int found_it = 0;  /* for use with -n section_name */
2180*0Sstevel@tonic-gate 
2181*0Sstevel@tonic-gate 	if (n_flag) {
2182*0Sstevel@tonic-gate 		n_range = s;
2183*0Sstevel@tonic-gate 
2184*0Sstevel@tonic-gate 		for (i = 0; i < num_scns; i++, n_range++) {
2185*0Sstevel@tonic-gate 			if ((strcmp(name, n_range->scn_name)) != 0)
2186*0Sstevel@tonic-gate 				continue;
2187*0Sstevel@tonic-gate 			else {
2188*0Sstevel@tonic-gate 				found_it = 1;
2189*0Sstevel@tonic-gate 				print_section(elf_file, p_ehdr,
2190*0Sstevel@tonic-gate 					n_range, 1, filename);
2191*0Sstevel@tonic-gate 			}
2192*0Sstevel@tonic-gate 		}
2193*0Sstevel@tonic-gate 
2194*0Sstevel@tonic-gate 		if (!found_it) {
2195*0Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: %s: %s not found\n",
2196*0Sstevel@tonic-gate 				prog_name, filename, name);
2197*0Sstevel@tonic-gate 		}
2198*0Sstevel@tonic-gate 	} /* end n_flag */
2199*0Sstevel@tonic-gate 
2200*0Sstevel@tonic-gate 	if (d_flag) {
2201*0Sstevel@tonic-gate 		d_range = s;
2202*0Sstevel@tonic-gate 		d_num = check_range(d_low, d_hi, num_scns, filename);
2203*0Sstevel@tonic-gate 		if (d_num < 0)
2204*0Sstevel@tonic-gate 			return;
2205*0Sstevel@tonic-gate 		d_range += d_low - 1;
2206*0Sstevel@tonic-gate 
2207*0Sstevel@tonic-gate 		print_section(elf_file, p_ehdr, d_range, d_num, filename);
2208*0Sstevel@tonic-gate 	}	/* end d_flag */
2209*0Sstevel@tonic-gate 
2210*0Sstevel@tonic-gate 	if (!n_flag && !d_flag)
2211*0Sstevel@tonic-gate 		print_section(elf_file, p_ehdr, s, num_scns, filename);
2212*0Sstevel@tonic-gate }
2213*0Sstevel@tonic-gate 
2214*0Sstevel@tonic-gate /*
2215*0Sstevel@tonic-gate  * Print the section header table. This function does not print the contents
2216*0Sstevel@tonic-gate  * of the section headers but sets up the parameters and then calls
2217*0Sstevel@tonic-gate  * print_shdr to print the contents.  Calling another function to print
2218*0Sstevel@tonic-gate  * the contents allows both -d and -n to work correctly
2219*0Sstevel@tonic-gate  * simultaneously.  Input is the SCNTAB structure,
2220*0Sstevel@tonic-gate  * the number of sections from the ELF header, and the filename.
2221*0Sstevel@tonic-gate  * Set the range of section headers to print if d_flag, and set
2222*0Sstevel@tonic-gate  * name of section header to print if n_flag.
2223*0Sstevel@tonic-gate  */
2224*0Sstevel@tonic-gate static void
2225*0Sstevel@tonic-gate dump_shdr(Elf *elf_file, SCNTAB *s, int num_scns, char *filename)
2226*0Sstevel@tonic-gate {
2227*0Sstevel@tonic-gate 
2228*0Sstevel@tonic-gate 	SCNTAB *n_range, *d_range;	/* for use with -n and -d modifiers */
2229*0Sstevel@tonic-gate 	int field;
2230*0Sstevel@tonic-gate 	int i;
2231*0Sstevel@tonic-gate 	int found_it = 0;  /* for use with -n section_name */
2232*0Sstevel@tonic-gate 
2233*0Sstevel@tonic-gate 	if (gelf_getclass(elf_file) == ELFCLASS64)
2234*0Sstevel@tonic-gate 		field = 14;
2235*0Sstevel@tonic-gate 	else
2236*0Sstevel@tonic-gate 		field = 12;
2237*0Sstevel@tonic-gate 
2238*0Sstevel@tonic-gate 	if (!p_flag) {
2239*0Sstevel@tonic-gate 		(void) printf("\n	   **** SECTION HEADER TABLE ****\n");
2240*0Sstevel@tonic-gate 		(void) printf("[No]\tType\tFlags\t%-*s %-*s %-*s%sName\n",
2241*0Sstevel@tonic-gate 		    field, "Addr", field, "Offset", field, "Size",
2242*0Sstevel@tonic-gate 		    /* compatibility:  tab for elf32 */
2243*0Sstevel@tonic-gate 		    (field == 12) ? "\t" : "  ");
2244*0Sstevel@tonic-gate 		(void) printf("\tLink\tInfo\t%-*s Entsize\n\n",
2245*0Sstevel@tonic-gate 		    field, "Adralgn");
2246*0Sstevel@tonic-gate 	}
2247*0Sstevel@tonic-gate 
2248*0Sstevel@tonic-gate 	if (n_flag) {
2249*0Sstevel@tonic-gate 		n_range = s;
2250*0Sstevel@tonic-gate 
2251*0Sstevel@tonic-gate 		for (i = 1; i <= num_scns; i++, n_range++) {
2252*0Sstevel@tonic-gate 			if ((strcmp(name, n_range->scn_name)) != 0)
2253*0Sstevel@tonic-gate 				continue;
2254*0Sstevel@tonic-gate 			else {
2255*0Sstevel@tonic-gate 				found_it = 1;
2256*0Sstevel@tonic-gate 				print_shdr(elf_file, n_range, 1, i);
2257*0Sstevel@tonic-gate 			}
2258*0Sstevel@tonic-gate 		}
2259*0Sstevel@tonic-gate 
2260*0Sstevel@tonic-gate 		if (!found_it) {
2261*0Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: %s: %s not found\n",
2262*0Sstevel@tonic-gate 				prog_name, filename, name);
2263*0Sstevel@tonic-gate 		}
2264*0Sstevel@tonic-gate 	} /* end n_flag */
2265*0Sstevel@tonic-gate 
2266*0Sstevel@tonic-gate 	if (d_flag) {
2267*0Sstevel@tonic-gate 		d_range = s;
2268*0Sstevel@tonic-gate 		d_num = check_range(d_low, d_hi, num_scns, filename);
2269*0Sstevel@tonic-gate 		if (d_num < 0)
2270*0Sstevel@tonic-gate 			return;
2271*0Sstevel@tonic-gate 		d_range += d_low - 1;
2272*0Sstevel@tonic-gate 
2273*0Sstevel@tonic-gate 		print_shdr(elf_file, d_range, d_num, d_low);
2274*0Sstevel@tonic-gate 	}	/* end d_flag */
2275*0Sstevel@tonic-gate 
2276*0Sstevel@tonic-gate 	if (!n_flag && !d_flag)
2277*0Sstevel@tonic-gate 		print_shdr(elf_file, s, num_scns, 1);
2278*0Sstevel@tonic-gate }
2279*0Sstevel@tonic-gate 
2280*0Sstevel@tonic-gate /*
2281*0Sstevel@tonic-gate  * Process all of the command line options (except
2282*0Sstevel@tonic-gate  * for -a, -g, -f, and -o).  All of the options processed
2283*0Sstevel@tonic-gate  * by this function require the presence of the section
2284*0Sstevel@tonic-gate  * header table and will not be processed if it is not present.
2285*0Sstevel@tonic-gate  * Set up a buffer containing section name, section header,
2286*0Sstevel@tonic-gate  * and section descriptor for each section in the file.  This
2287*0Sstevel@tonic-gate  * structure is used to avoid duplicate calls to libelf functions.
2288*0Sstevel@tonic-gate  * Structure members for the symbol table, the debugging information,
2289*0Sstevel@tonic-gate  * and the line number information are global.  All of the
2290*0Sstevel@tonic-gate  * rest are local.
2291*0Sstevel@tonic-gate  */
2292*0Sstevel@tonic-gate static void
2293*0Sstevel@tonic-gate dump_section_table(Elf *elf_file, GElf_Ehdr *elf_head_p, char *filename)
2294*0Sstevel@tonic-gate {
2295*0Sstevel@tonic-gate 
2296*0Sstevel@tonic-gate 	static SCNTAB	*buffer, *p_scns;
2297*0Sstevel@tonic-gate 	Elf_Scn		*scn = 0;
2298*0Sstevel@tonic-gate 	char		*s_name = NULL;
2299*0Sstevel@tonic-gate 	int		found = 0;
2300*0Sstevel@tonic-gate 	unsigned int	num_scns;
2301*0Sstevel@tonic-gate 	size_t		shstrndx;
2302*0Sstevel@tonic-gate 	size_t		shnum;
2303*0Sstevel@tonic-gate 
2304*0Sstevel@tonic-gate 
2305*0Sstevel@tonic-gate 	if (elf_getshnum(elf_file, &shnum) == 0) {
2306*0Sstevel@tonic-gate 		(void) fprintf(stderr,
2307*0Sstevel@tonic-gate 			"%s: %s: elf_getshnum failed: %s\n",
2308*0Sstevel@tonic-gate 			prog_name, filename, elf_errmsg(-1));
2309*0Sstevel@tonic-gate 		return;
2310*0Sstevel@tonic-gate 	}
2311*0Sstevel@tonic-gate 	if (elf_getshstrndx(elf_file, &shstrndx) == 0) {
2312*0Sstevel@tonic-gate 		(void) fprintf(stderr,
2313*0Sstevel@tonic-gate 			"%s: %s: elf_getshstrndx failed: %s\n",
2314*0Sstevel@tonic-gate 			prog_name, filename, elf_errmsg(-1));
2315*0Sstevel@tonic-gate 		return;
2316*0Sstevel@tonic-gate 	}
2317*0Sstevel@tonic-gate 
2318*0Sstevel@tonic-gate 	if ((buffer = calloc(shnum, sizeof (SCNTAB))) == NULL) {
2319*0Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: %s: cannot calloc space\n",
2320*0Sstevel@tonic-gate 			prog_name, filename);
2321*0Sstevel@tonic-gate 		return;
2322*0Sstevel@tonic-gate 	}
2323*0Sstevel@tonic-gate 	/* LINTED */
2324*0Sstevel@tonic-gate 	num_scns = (int)shnum - 1;
2325*0Sstevel@tonic-gate 
2326*0Sstevel@tonic-gate 	p_symtab = (SCNTAB *)0;
2327*0Sstevel@tonic-gate 	p_dynsym = (SCNTAB *)0;
2328*0Sstevel@tonic-gate 	p_scns = buffer;
2329*0Sstevel@tonic-gate 	p_head_scns = buffer;
2330*0Sstevel@tonic-gate 
2331*0Sstevel@tonic-gate 	while ((scn = elf_nextscn(elf_file, scn)) != 0) {
2332*0Sstevel@tonic-gate 		if ((gelf_getshdr(scn, &buffer->p_shdr)) == 0) {
2333*0Sstevel@tonic-gate 			(void) fprintf(stderr,
2334*0Sstevel@tonic-gate 			"%s: %s: %s\n", prog_name, filename, elf_errmsg(-1));
2335*0Sstevel@tonic-gate 			return;
2336*0Sstevel@tonic-gate 		}
2337*0Sstevel@tonic-gate 		s_name = (char *)elf_strptr(elf_file,
2338*0Sstevel@tonic-gate 			shstrndx, buffer->p_shdr.sh_name);
2339*0Sstevel@tonic-gate 		buffer->scn_name = s_name ? s_name : (char *)UNKNOWN;
2340*0Sstevel@tonic-gate 		buffer->p_sd   =  scn;
2341*0Sstevel@tonic-gate 
2342*0Sstevel@tonic-gate 		if (buffer->p_shdr.sh_type == SHT_SYMTAB) {
2343*0Sstevel@tonic-gate 			found += 1;
2344*0Sstevel@tonic-gate 			p_symtab = buffer;
2345*0Sstevel@tonic-gate 		}
2346*0Sstevel@tonic-gate 		if (buffer->p_shdr.sh_type == SHT_DYNSYM)
2347*0Sstevel@tonic-gate 			p_dynsym = buffer;
2348*0Sstevel@tonic-gate 		buffer++;
2349*0Sstevel@tonic-gate 	}
2350*0Sstevel@tonic-gate 
2351*0Sstevel@tonic-gate 	/*
2352*0Sstevel@tonic-gate 	 * These functions depend upon the presence of the section header table
2353*0Sstevel@tonic-gate 	 * and will not be invoked in its absence
2354*0Sstevel@tonic-gate 	 */
2355*0Sstevel@tonic-gate 	if (h_flag) {
2356*0Sstevel@tonic-gate 		dump_shdr(elf_file, p_scns, num_scns, filename);
2357*0Sstevel@tonic-gate 	}
2358*0Sstevel@tonic-gate 	if (p_symtab && (t_flag || T_flag)) {
2359*0Sstevel@tonic-gate 		dump_symbol_table(elf_file, p_symtab, filename);
2360*0Sstevel@tonic-gate 	}
2361*0Sstevel@tonic-gate 	if (c_flag) {
2362*0Sstevel@tonic-gate 		dump_string_table(p_scns, num_scns);
2363*0Sstevel@tonic-gate 	}
2364*0Sstevel@tonic-gate 	if (r_flag) {
2365*0Sstevel@tonic-gate 		dump_reloc_table(elf_file, elf_head_p,
2366*0Sstevel@tonic-gate 			p_scns, num_scns, filename);
2367*0Sstevel@tonic-gate 	}
2368*0Sstevel@tonic-gate 	if (L_flag) {
2369*0Sstevel@tonic-gate 		dump_dynamic(elf_file, p_scns, num_scns, filename);
2370*0Sstevel@tonic-gate 	}
2371*0Sstevel@tonic-gate 	if (s_flag) {
2372*0Sstevel@tonic-gate 		dump_section(elf_file, elf_head_p, p_scns,
2373*0Sstevel@tonic-gate 			num_scns, filename);
2374*0Sstevel@tonic-gate 	}
2375*0Sstevel@tonic-gate }
2376*0Sstevel@tonic-gate 
2377*0Sstevel@tonic-gate /*
2378*0Sstevel@tonic-gate  * Load the archive string table(s) (for extended-length strings)
2379*0Sstevel@tonic-gate  * into an in-core table/list
2380*0Sstevel@tonic-gate  */
2381*0Sstevel@tonic-gate static struct stab_list_s *
2382*0Sstevel@tonic-gate load_arstring_table(struct stab_list_s *STabList,
2383*0Sstevel@tonic-gate 	int fd, Elf *elf_file, Elf_Arhdr *p_ar, char *filename)
2384*0Sstevel@tonic-gate {
2385*0Sstevel@tonic-gate 	off_t here;
2386*0Sstevel@tonic-gate 	struct stab_list_s *STL_entry, *STL_next;
2387*0Sstevel@tonic-gate 
2388*0Sstevel@tonic-gate 	if (p_ar) {
2389*0Sstevel@tonic-gate 		STL_entry = malloc(sizeof (struct stab_list_s));
2390*0Sstevel@tonic-gate 		STL_entry->next    = 0;
2391*0Sstevel@tonic-gate 		STL_entry->strings = 0;
2392*0Sstevel@tonic-gate 		STL_entry->size    = 0;
2393*0Sstevel@tonic-gate 
2394*0Sstevel@tonic-gate 		if (!STabList)
2395*0Sstevel@tonic-gate 			STabList = STL_entry;
2396*0Sstevel@tonic-gate 		else {
2397*0Sstevel@tonic-gate 			STL_next = STabList;
2398*0Sstevel@tonic-gate 			while (STL_next->next != (void *)0)
2399*0Sstevel@tonic-gate 				STL_next = STL_next->next;
2400*0Sstevel@tonic-gate 			STL_next->next = STL_entry;
2401*0Sstevel@tonic-gate 		}
2402*0Sstevel@tonic-gate 
2403*0Sstevel@tonic-gate 		STL_entry->size    = p_ar->ar_size;
2404*0Sstevel@tonic-gate 		STL_entry->strings = malloc(p_ar->ar_size);
2405*0Sstevel@tonic-gate 		here = elf_getbase(elf_file);
2406*0Sstevel@tonic-gate 		if ((lseek(fd, here, 0)) != here) {
2407*0Sstevel@tonic-gate 			(void) fprintf(stderr,
2408*0Sstevel@tonic-gate 			"%s: %s: could not lseek\n", prog_name, filename);
2409*0Sstevel@tonic-gate 		}
2410*0Sstevel@tonic-gate 
2411*0Sstevel@tonic-gate 		if ((read(fd, STL_entry->strings, p_ar->ar_size)) == -1) {
2412*0Sstevel@tonic-gate 			(void) fprintf(stderr,
2413*0Sstevel@tonic-gate 			"%s: %s: could not read\n", prog_name, filename);
2414*0Sstevel@tonic-gate 		}
2415*0Sstevel@tonic-gate 	}
2416*0Sstevel@tonic-gate 	return (STabList);
2417*0Sstevel@tonic-gate }
2418*0Sstevel@tonic-gate 
2419*0Sstevel@tonic-gate /*
2420*0Sstevel@tonic-gate  * Print the archive header for each member of an archive.
2421*0Sstevel@tonic-gate  * Also call ar_sym_read to print the symbols in the
2422*0Sstevel@tonic-gate  * archive symbol table if g_flag.  Input is a file descriptor,
2423*0Sstevel@tonic-gate  * an ELF file descriptor, and the filename.  Putting the call
2424*0Sstevel@tonic-gate  * to dump the archive symbol table in this function is more
2425*0Sstevel@tonic-gate  * efficient since it is necessary to examine the archive member
2426*0Sstevel@tonic-gate  * name in the archive header to determine which member is the
2427*0Sstevel@tonic-gate  * symbol table.
2428*0Sstevel@tonic-gate  */
2429*0Sstevel@tonic-gate static void
2430*0Sstevel@tonic-gate dump_ar_hdr(int fd, Elf *elf_file, char *filename)
2431*0Sstevel@tonic-gate {
2432*0Sstevel@tonic-gate 	extern int v_flag, g_flag, a_flag, p_flag;
2433*0Sstevel@tonic-gate 	Elf_Arhdr  *p_ar;
2434*0Sstevel@tonic-gate 	Elf *arf;
2435*0Sstevel@tonic-gate 	Elf_Cmd cmd;
2436*0Sstevel@tonic-gate 	int title = 0;
2437*0Sstevel@tonic-gate 	int err = 0;
2438*0Sstevel@tonic-gate 
2439*0Sstevel@tonic-gate 	char buf[DATESIZE];
2440*0Sstevel@tonic-gate 
2441*0Sstevel@tonic-gate 	cmd = ELF_C_READ;
2442*0Sstevel@tonic-gate 	while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
2443*0Sstevel@tonic-gate 		p_ar = elf_getarhdr(arf);
2444*0Sstevel@tonic-gate 		if (p_ar == NULL) {
2445*0Sstevel@tonic-gate 			(void) fprintf(stderr,
2446*0Sstevel@tonic-gate 			"%s: %s: %s\n", prog_name, filename, elf_errmsg(-1));
2447*0Sstevel@tonic-gate 			continue;
2448*0Sstevel@tonic-gate 		}
2449*0Sstevel@tonic-gate 		if (strcmp(p_ar->ar_name, "/") == 0) {
2450*0Sstevel@tonic-gate 			if (g_flag)
2451*0Sstevel@tonic-gate 				ar_sym_read(elf_file, filename);
2452*0Sstevel@tonic-gate 		} else if (strcmp(p_ar->ar_name, "//") == 0) {
2453*0Sstevel@tonic-gate 			StringTableList = load_arstring_table(
2454*0Sstevel@tonic-gate 				StringTableList, fd, arf, p_ar,
2455*0Sstevel@tonic-gate 				filename);
2456*0Sstevel@tonic-gate 			cmd = elf_next(arf);
2457*0Sstevel@tonic-gate 			(void) elf_end(arf);
2458*0Sstevel@tonic-gate 			continue;
2459*0Sstevel@tonic-gate 		} else {
2460*0Sstevel@tonic-gate 			if (a_flag) {
2461*0Sstevel@tonic-gate 				(void) printf("%s[%s]:\n", filename,
2462*0Sstevel@tonic-gate 					p_ar->ar_name);
2463*0Sstevel@tonic-gate 				if (!p_flag && title == 0) {
2464*0Sstevel@tonic-gate 					if (!v_flag)
2465*0Sstevel@tonic-gate 						(void) printf(
2466*0Sstevel@tonic-gate "\n\n\t\t\t***ARCHIVE HEADER***"
2467*0Sstevel@tonic-gate "\n	Date          Uid     Gid    Mode      Size	 Member Name\n\n");
2468*0Sstevel@tonic-gate 					else
2469*0Sstevel@tonic-gate 						(void) printf(
2470*0Sstevel@tonic-gate "\n\n\t\t\t***ARCHIVE HEADER***"
2471*0Sstevel@tonic-gate "\n	Date                   Uid    Gid   Mode     Size     Member Name\n\n");
2472*0Sstevel@tonic-gate 					title = 1;
2473*0Sstevel@tonic-gate 				}
2474*0Sstevel@tonic-gate 				if (!v_flag) {
2475*0Sstevel@tonic-gate 					(void) printf(
2476*0Sstevel@tonic-gate "\t0x%.8lx  %6d  %6d  0%.6ho  0x%.8lx  %-s\n\n",
2477*0Sstevel@tonic-gate 						p_ar->ar_date,
2478*0Sstevel@tonic-gate 						(int)p_ar->ar_uid,
2479*0Sstevel@tonic-gate 						(int)p_ar->ar_gid,
2480*0Sstevel@tonic-gate 						(int)p_ar->ar_mode,
2481*0Sstevel@tonic-gate 						p_ar->ar_size,
2482*0Sstevel@tonic-gate 						p_ar->ar_name);
2483*0Sstevel@tonic-gate 				} else {
2484*0Sstevel@tonic-gate 					if ((strftime(buf, DATESIZE,
2485*0Sstevel@tonic-gate 					    "%b %d %H:%M:%S %Y",
2486*0Sstevel@tonic-gate 					    localtime(
2487*0Sstevel@tonic-gate 					    &(p_ar->ar_date)))) == 0) {
2488*0Sstevel@tonic-gate 						(void) fprintf(stderr,
2489*0Sstevel@tonic-gate "%s: %s: don't have enough space to store the date\n", prog_name, filename);
2490*0Sstevel@tonic-gate 						exit(1);
2491*0Sstevel@tonic-gate 					}
2492*0Sstevel@tonic-gate 					(void) printf(
2493*0Sstevel@tonic-gate 					"\t%s %6d %6d 0%.6ho 0x%.8lx %-s\n\n",
2494*0Sstevel@tonic-gate 						buf,
2495*0Sstevel@tonic-gate 						(int)p_ar->ar_uid,
2496*0Sstevel@tonic-gate 						(int)p_ar->ar_gid,
2497*0Sstevel@tonic-gate 						(int)p_ar->ar_mode,
2498*0Sstevel@tonic-gate 						p_ar->ar_size,
2499*0Sstevel@tonic-gate 						p_ar->ar_name);
2500*0Sstevel@tonic-gate 				}
2501*0Sstevel@tonic-gate 			}
2502*0Sstevel@tonic-gate 		}
2503*0Sstevel@tonic-gate 		cmd = elf_next(arf);
2504*0Sstevel@tonic-gate 		(void) elf_end(arf);
2505*0Sstevel@tonic-gate 	} /* end while */
2506*0Sstevel@tonic-gate 
2507*0Sstevel@tonic-gate 	err = elf_errno();
2508*0Sstevel@tonic-gate 	if (err != 0) {
2509*0Sstevel@tonic-gate 		(void) fprintf(stderr,
2510*0Sstevel@tonic-gate 		"%s: %s: %s\n", prog_name, filename, elf_errmsg(err));
2511*0Sstevel@tonic-gate 	}
2512*0Sstevel@tonic-gate }
2513*0Sstevel@tonic-gate 
2514*0Sstevel@tonic-gate /*
2515*0Sstevel@tonic-gate  * Process member files of an archive.  This function provides
2516*0Sstevel@tonic-gate  * a loop through an archive equivalent the processing of
2517*0Sstevel@tonic-gate  * each_file for individual object files.
2518*0Sstevel@tonic-gate  */
2519*0Sstevel@tonic-gate static void
2520*0Sstevel@tonic-gate dump_ar_files(int fd, Elf *elf_file, char *filename)
2521*0Sstevel@tonic-gate {
2522*0Sstevel@tonic-gate 	Elf_Arhdr  *p_ar;
2523*0Sstevel@tonic-gate 	Elf *arf;
2524*0Sstevel@tonic-gate 	Elf_Cmd cmd;
2525*0Sstevel@tonic-gate 	Elf_Kind file_type;
2526*0Sstevel@tonic-gate 	GElf_Ehdr elf_head;
2527*0Sstevel@tonic-gate 	char *fullname;
2528*0Sstevel@tonic-gate 
2529*0Sstevel@tonic-gate 	cmd = ELF_C_READ;
2530*0Sstevel@tonic-gate 	while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
2531*0Sstevel@tonic-gate 		p_ar = elf_getarhdr(arf);
2532*0Sstevel@tonic-gate 		if (p_ar == NULL) {
2533*0Sstevel@tonic-gate 			(void) fprintf(stderr,
2534*0Sstevel@tonic-gate 				"%s: %s: %s\n",
2535*0Sstevel@tonic-gate 				prog_name, filename, elf_errmsg(-1));
2536*0Sstevel@tonic-gate 			return;
2537*0Sstevel@tonic-gate 		}
2538*0Sstevel@tonic-gate 		if ((strcmp(p_ar->ar_name, "/") == 0) ||
2539*0Sstevel@tonic-gate 			(strcmp(p_ar->ar_name, "//") == 0)) {
2540*0Sstevel@tonic-gate 			cmd = elf_next(arf);
2541*0Sstevel@tonic-gate 			(void) elf_end(arf);
2542*0Sstevel@tonic-gate 			continue;
2543*0Sstevel@tonic-gate 		}
2544*0Sstevel@tonic-gate 
2545*0Sstevel@tonic-gate 		fullname = malloc(strlen(filename) + strlen(p_ar->ar_name) + 3);
2546*0Sstevel@tonic-gate 		(void) sprintf(fullname, "%s[%s]", filename, p_ar->ar_name);
2547*0Sstevel@tonic-gate 		(void) printf("\n%s:\n", fullname);
2548*0Sstevel@tonic-gate 		file_type = elf_kind(arf);
2549*0Sstevel@tonic-gate 		if (file_type == ELF_K_ELF) {
2550*0Sstevel@tonic-gate 			if (dump_elf_header(arf, fullname, &elf_head) == NULL)
2551*0Sstevel@tonic-gate 				return;
2552*0Sstevel@tonic-gate 			if (o_flag)
2553*0Sstevel@tonic-gate 				dump_exec_header(arf,
2554*0Sstevel@tonic-gate 					(unsigned)elf_head.e_phnum, fullname);
2555*0Sstevel@tonic-gate 			if (x_flag)
2556*0Sstevel@tonic-gate 				dump_section_table(arf, &elf_head, fullname);
2557*0Sstevel@tonic-gate 		} else {
2558*0Sstevel@tonic-gate 			(void) fprintf(stderr,
2559*0Sstevel@tonic-gate 				"%s: %s: invalid file type\n",
2560*0Sstevel@tonic-gate 				prog_name, fullname);
2561*0Sstevel@tonic-gate 			cmd = elf_next(arf);
2562*0Sstevel@tonic-gate 			(void) elf_end(arf);
2563*0Sstevel@tonic-gate 			continue;
2564*0Sstevel@tonic-gate 		}
2565*0Sstevel@tonic-gate 
2566*0Sstevel@tonic-gate 		cmd = elf_next(arf);
2567*0Sstevel@tonic-gate 		(void) elf_end(arf);
2568*0Sstevel@tonic-gate 	} /* end while */
2569*0Sstevel@tonic-gate }
2570*0Sstevel@tonic-gate 
2571*0Sstevel@tonic-gate /*
2572*0Sstevel@tonic-gate  * Takes a filename as input.  Test first for a valid version
2573*0Sstevel@tonic-gate  * of libelf.a and exit on error.  Process each valid file
2574*0Sstevel@tonic-gate  * or archive given as input on the command line.  Check
2575*0Sstevel@tonic-gate  * for file type.  If it is an archive, process the archive-
2576*0Sstevel@tonic-gate  * specific options first, then files within the archive.
2577*0Sstevel@tonic-gate  * If it is an ELF object file, process it; otherwise
2578*0Sstevel@tonic-gate  * warn that it is an invalid file type.
2579*0Sstevel@tonic-gate  * All options except the archive-specific and program
2580*0Sstevel@tonic-gate  * execution header are processed in the function, dump_section_table.
2581*0Sstevel@tonic-gate  */
2582*0Sstevel@tonic-gate static void
2583*0Sstevel@tonic-gate each_file(char *filename)
2584*0Sstevel@tonic-gate {
2585*0Sstevel@tonic-gate 	Elf *elf_file;
2586*0Sstevel@tonic-gate 	GElf_Ehdr elf_head;
2587*0Sstevel@tonic-gate 	int fd;
2588*0Sstevel@tonic-gate 	Elf_Kind   file_type;
2589*0Sstevel@tonic-gate 
2590*0Sstevel@tonic-gate 	struct stat buf;
2591*0Sstevel@tonic-gate 
2592*0Sstevel@tonic-gate 	Elf_Cmd cmd;
2593*0Sstevel@tonic-gate 	errno = 0;
2594*0Sstevel@tonic-gate 
2595*0Sstevel@tonic-gate 	if (stat(filename, &buf) == -1) {
2596*0Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: ", prog_name);
2597*0Sstevel@tonic-gate 		perror(filename);
2598*0Sstevel@tonic-gate 		return;
2599*0Sstevel@tonic-gate 	}
2600*0Sstevel@tonic-gate 
2601*0Sstevel@tonic-gate 	if (elf_version(EV_CURRENT) == EV_NONE) {
2602*0Sstevel@tonic-gate 		(void) fprintf(stderr,
2603*0Sstevel@tonic-gate 		"%s: Libelf is out of date\n", prog_name);
2604*0Sstevel@tonic-gate 		exit(101);
2605*0Sstevel@tonic-gate 	}
2606*0Sstevel@tonic-gate 
2607*0Sstevel@tonic-gate 	if ((fd = open((filename), O_RDONLY)) == -1) {
2608*0Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: %s: cannot read\n",
2609*0Sstevel@tonic-gate 			prog_name, filename);
2610*0Sstevel@tonic-gate 		return;
2611*0Sstevel@tonic-gate 	}
2612*0Sstevel@tonic-gate 	cmd = ELF_C_READ;
2613*0Sstevel@tonic-gate 	if ((elf_file = elf_begin(fd, cmd, (Elf *)0)) == NULL) {
2614*0Sstevel@tonic-gate 		(void) fprintf(stderr,
2615*0Sstevel@tonic-gate 		"%s: %s: %s\n", prog_name, filename, elf_errmsg(-1));
2616*0Sstevel@tonic-gate 		return;
2617*0Sstevel@tonic-gate 	}
2618*0Sstevel@tonic-gate 
2619*0Sstevel@tonic-gate 	file_type = elf_kind(elf_file);
2620*0Sstevel@tonic-gate 	if (file_type == ELF_K_AR) {
2621*0Sstevel@tonic-gate 		if (a_flag || g_flag) {
2622*0Sstevel@tonic-gate 			dump_ar_hdr(fd, elf_file, filename);
2623*0Sstevel@tonic-gate 			elf_file = elf_begin(fd, cmd, (Elf *)0);
2624*0Sstevel@tonic-gate 		}
2625*0Sstevel@tonic-gate 		if (z_flag)
2626*0Sstevel@tonic-gate 			dump_ar_files(fd, elf_file, filename);
2627*0Sstevel@tonic-gate 	} else {
2628*0Sstevel@tonic-gate 		if (file_type == ELF_K_ELF) {
2629*0Sstevel@tonic-gate 			(void) printf("\n%s:\n", filename);
2630*0Sstevel@tonic-gate 			if (dump_elf_header(elf_file, filename, &elf_head)
2631*0Sstevel@tonic-gate 			    == (GElf_Ehdr *)0) {
2632*0Sstevel@tonic-gate 					(void) elf_end(elf_file);
2633*0Sstevel@tonic-gate 					(void) close(fd);
2634*0Sstevel@tonic-gate 					return;
2635*0Sstevel@tonic-gate 			}
2636*0Sstevel@tonic-gate 			if (o_flag)
2637*0Sstevel@tonic-gate 				dump_exec_header(elf_file,
2638*0Sstevel@tonic-gate 					(unsigned)elf_head.e_phnum, filename);
2639*0Sstevel@tonic-gate 			if (x_flag)
2640*0Sstevel@tonic-gate 				dump_section_table(elf_file,
2641*0Sstevel@tonic-gate 					&elf_head, filename);
2642*0Sstevel@tonic-gate 		} else {
2643*0Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: %s: invalid file type\n",
2644*0Sstevel@tonic-gate 				prog_name, filename);
2645*0Sstevel@tonic-gate 			(void) elf_end(elf_file);
2646*0Sstevel@tonic-gate 			(void) close(fd);
2647*0Sstevel@tonic-gate 			return;
2648*0Sstevel@tonic-gate 		}
2649*0Sstevel@tonic-gate 	}
2650*0Sstevel@tonic-gate 	(void) elf_end(elf_file);
2651*0Sstevel@tonic-gate 	(void) close(fd);
2652*0Sstevel@tonic-gate }
2653*0Sstevel@tonic-gate 
2654*0Sstevel@tonic-gate /*
2655*0Sstevel@tonic-gate  * Sets up flags for command line options given and then
2656*0Sstevel@tonic-gate  * calls each_file() to process each file.
2657*0Sstevel@tonic-gate  */
2658*0Sstevel@tonic-gate int
2659*0Sstevel@tonic-gate main(int argc, char *argv[], char *envp[])
2660*0Sstevel@tonic-gate {
2661*0Sstevel@tonic-gate 	char *optstr = OPTSTR; /* option string used by getopt() */
2662*0Sstevel@tonic-gate 	int optchar;
2663*0Sstevel@tonic-gate 
2664*0Sstevel@tonic-gate 
2665*0Sstevel@tonic-gate 	/*
2666*0Sstevel@tonic-gate 	 * Check for a binary that better fits this architecture.
2667*0Sstevel@tonic-gate 	 */
2668*0Sstevel@tonic-gate 	conv_check_native(argv, envp);
2669*0Sstevel@tonic-gate 
2670*0Sstevel@tonic-gate 	prog_name = argv[0];
2671*0Sstevel@tonic-gate 
2672*0Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2673*0Sstevel@tonic-gate 	while ((optchar = getopt(argc, argv, optstr)) != -1) {
2674*0Sstevel@tonic-gate 		switch (optchar) {
2675*0Sstevel@tonic-gate 		case 'a':
2676*0Sstevel@tonic-gate 			a_flag = 1;
2677*0Sstevel@tonic-gate 			x_flag = 1;
2678*0Sstevel@tonic-gate 			break;
2679*0Sstevel@tonic-gate 		case 'g':
2680*0Sstevel@tonic-gate 			g_flag = 1;
2681*0Sstevel@tonic-gate 			x_flag = 1;
2682*0Sstevel@tonic-gate 			break;
2683*0Sstevel@tonic-gate 		case 'v':
2684*0Sstevel@tonic-gate 			v_flag = 1;
2685*0Sstevel@tonic-gate 			break;
2686*0Sstevel@tonic-gate 		case 'p':
2687*0Sstevel@tonic-gate 			p_flag = 1;
2688*0Sstevel@tonic-gate 			break;
2689*0Sstevel@tonic-gate 		case 'f':
2690*0Sstevel@tonic-gate 			f_flag = 1;
2691*0Sstevel@tonic-gate 			z_flag = 1;
2692*0Sstevel@tonic-gate 			break;
2693*0Sstevel@tonic-gate 		case 'o':
2694*0Sstevel@tonic-gate 			o_flag = 1;
2695*0Sstevel@tonic-gate 			z_flag = 1;
2696*0Sstevel@tonic-gate 			break;
2697*0Sstevel@tonic-gate 		case 'h':
2698*0Sstevel@tonic-gate 			h_flag = 1;
2699*0Sstevel@tonic-gate 			x_flag = 1;
2700*0Sstevel@tonic-gate 			z_flag = 1;
2701*0Sstevel@tonic-gate 			break;
2702*0Sstevel@tonic-gate 		case 's':
2703*0Sstevel@tonic-gate 			s_flag = 1;
2704*0Sstevel@tonic-gate 			x_flag = 1;
2705*0Sstevel@tonic-gate 			z_flag = 1;
2706*0Sstevel@tonic-gate 			break;
2707*0Sstevel@tonic-gate 		case 'd':
2708*0Sstevel@tonic-gate 			d_flag = 1;
2709*0Sstevel@tonic-gate 			x_flag = 1;
2710*0Sstevel@tonic-gate 			z_flag = 1;
2711*0Sstevel@tonic-gate 			set_range(optarg, &d_low, &d_hi);
2712*0Sstevel@tonic-gate 			break;
2713*0Sstevel@tonic-gate 		case 'n':
2714*0Sstevel@tonic-gate 			n_flag++;
2715*0Sstevel@tonic-gate 			x_flag = 1;
2716*0Sstevel@tonic-gate 			z_flag = 1;
2717*0Sstevel@tonic-gate 			name = optarg;
2718*0Sstevel@tonic-gate 			break;
2719*0Sstevel@tonic-gate 		case 'r':
2720*0Sstevel@tonic-gate 			r_flag = 1;
2721*0Sstevel@tonic-gate 			x_flag = 1;
2722*0Sstevel@tonic-gate 			z_flag = 1;
2723*0Sstevel@tonic-gate 			break;
2724*0Sstevel@tonic-gate 		case 't':
2725*0Sstevel@tonic-gate 			t_flag = 1;
2726*0Sstevel@tonic-gate 			x_flag = 1;
2727*0Sstevel@tonic-gate 			z_flag = 1;
2728*0Sstevel@tonic-gate 			break;
2729*0Sstevel@tonic-gate 		case 'C':
2730*0Sstevel@tonic-gate 			C_flag = 1;
2731*0Sstevel@tonic-gate 			t_flag = 1;
2732*0Sstevel@tonic-gate 			x_flag = 1;
2733*0Sstevel@tonic-gate 			z_flag = 1;
2734*0Sstevel@tonic-gate 			break;
2735*0Sstevel@tonic-gate 		case 'T':
2736*0Sstevel@tonic-gate 			T_flag = 1;
2737*0Sstevel@tonic-gate 			x_flag = 1;
2738*0Sstevel@tonic-gate 			z_flag = 1;
2739*0Sstevel@tonic-gate 			set_range(optarg, &T_low, &T_hi);
2740*0Sstevel@tonic-gate 			break;
2741*0Sstevel@tonic-gate 		case 'c':
2742*0Sstevel@tonic-gate 			c_flag = 1;
2743*0Sstevel@tonic-gate 			x_flag = 1;
2744*0Sstevel@tonic-gate 			z_flag = 1;
2745*0Sstevel@tonic-gate 			break;
2746*0Sstevel@tonic-gate 		case 'L':
2747*0Sstevel@tonic-gate 			L_flag = 1;
2748*0Sstevel@tonic-gate 			x_flag = 1;
2749*0Sstevel@tonic-gate 			z_flag = 1;
2750*0Sstevel@tonic-gate 			break;
2751*0Sstevel@tonic-gate 		case 'V':
2752*0Sstevel@tonic-gate 			V_flag = 1;
2753*0Sstevel@tonic-gate 			(void) fprintf(stderr, "dump: %s %s\n",
2754*0Sstevel@tonic-gate 			    (const char *)SGU_PKG,
2755*0Sstevel@tonic-gate 			    (const char *)SGU_REL);
2756*0Sstevel@tonic-gate 			break;
2757*0Sstevel@tonic-gate 		case '?':
2758*0Sstevel@tonic-gate 			errflag += 1;
2759*0Sstevel@tonic-gate 			break;
2760*0Sstevel@tonic-gate 		default:
2761*0Sstevel@tonic-gate 			break;
2762*0Sstevel@tonic-gate 		}
2763*0Sstevel@tonic-gate 	}
2764*0Sstevel@tonic-gate 
2765*0Sstevel@tonic-gate 	if (errflag || (optind >= argc) || (!z_flag && !x_flag)) {
2766*0Sstevel@tonic-gate 		if (!(V_flag && (argc == 2))) {
2767*0Sstevel@tonic-gate 			usage();
2768*0Sstevel@tonic-gate 			exit(269);
2769*0Sstevel@tonic-gate 		}
2770*0Sstevel@tonic-gate 	}
2771*0Sstevel@tonic-gate 
2772*0Sstevel@tonic-gate 	while (optind < argc) {
2773*0Sstevel@tonic-gate 		each_file(argv[optind]);
2774*0Sstevel@tonic-gate 		optind++;
2775*0Sstevel@tonic-gate 	}
2776*0Sstevel@tonic-gate 	return (0);
2777*0Sstevel@tonic-gate }
2778