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