xref: /titanic_41/usr/src/cmd/sgs/dump/common/dump.c (revision e49962a00eea60555f3c78ebf58a9a641590802c)
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 					if (p_dyn.d_un.d_val & DF_1_NORELOC)
1735 					    (void) strcat(value,
1736 						(const char *)"NORELOC ");
1737 				}
1738 				if (v_flag && strlen(value))
1739 					(void) printf("%s", value);
1740 				else
1741 					(void) printf(Fmtptr,
1742 						EC_ADDR(p_dyn.d_un.d_ptr));
1743 				break;
1744 			case (DT_VERSYM):
1745 				(void) printf(Fmttag, (const char *)"VERSYM");
1746 				(void) printf(Fmtptr,
1747 					EC_ADDR(p_dyn.d_un.d_ptr));
1748 				break;
1749 			case (DT_VERDEF):
1750 				(void) printf(Fmttag, (const char *)"VERDEF");
1751 				(void) printf(Fmtptr,
1752 					EC_ADDR(p_dyn.d_un.d_ptr));
1753 				break;
1754 			case (DT_VERDEFNUM):
1755 				(void) printf(Fmttag,
1756 				    (const char *)"VERDEFNUM");
1757 				(void) printf(Fmtptr,
1758 					EC_XWORD(p_dyn.d_un.d_val));
1759 				break;
1760 			case (DT_VERNEED):
1761 				(void) printf(Fmttag, (const char *)"VERNEED");
1762 				(void) printf(Fmtptr,
1763 					EC_ADDR(p_dyn.d_un.d_ptr));
1764 				break;
1765 			case (DT_VERNEEDNUM):
1766 				(void) printf(Fmttag,
1767 				    (const char *)"VERNEEDNUM");
1768 				(void) printf(Fmtptr,
1769 					EC_XWORD(p_dyn.d_un.d_val));
1770 				break;
1771 			case (DT_AUXILIARY):
1772 				(void) printf(Fmttag,
1773 					(const char *)"AUXILIARY");
1774 				if (v_flag)
1775 					dt_name = (char *)elf_strptr(elf_file,
1776 					    link, p_dyn.d_un.d_ptr);
1777 				if (dt_name == NULL)
1778 					dt_name = (char *)UNKNOWN;
1779 				if (v_flag && strlen(dt_name))
1780 					(void) printf("%s", dt_name);
1781 				else
1782 					(void) printf(Fmtptr,
1783 						EC_ADDR(p_dyn.d_un.d_ptr));
1784 				break;
1785 			case (DT_USED):
1786 				(void) printf(Fmttag, (const char *)"USED");
1787 				if (v_flag)
1788 					dt_name = (char *)elf_strptr(elf_file,
1789 					    link, p_dyn.d_un.d_ptr);
1790 				if (dt_name == NULL)
1791 					dt_name = (char *)UNKNOWN;
1792 				if (v_flag && strlen(dt_name))
1793 					(void) printf("%s", dt_name);
1794 				else
1795 					(void) printf(Fmtptr,
1796 						EC_ADDR(p_dyn.d_un.d_ptr));
1797 				break;
1798 			case (DT_FILTER):
1799 				(void) printf(Fmttag, (const char *)"FILTER");
1800 				if (v_flag)
1801 					dt_name = (char *)elf_strptr(elf_file,
1802 					    link, p_dyn.d_un.d_ptr);
1803 				if (dt_name == NULL)
1804 					dt_name = (char *)UNKNOWN;
1805 				if (v_flag && strlen(dt_name))
1806 					(void) printf("%s", dt_name);
1807 				else
1808 					(void) printf(Fmtptr,
1809 						EC_ADDR(p_dyn.d_un.d_ptr));
1810 				break;
1811 
1812 			/*
1813 			 * SUNW: machine specific range.
1814 			 */
1815 			case (DT_SPARC_REGISTER):
1816 				(void) printf(Fmttag,
1817 					(const char *)"REGISTER");
1818 				(void) printf(Fmtptr,
1819 					EC_XWORD(p_dyn.d_un.d_val));
1820 				break;
1821 			case (DT_DEPRECATED_SPARC_REGISTER):
1822 				(void) printf(Fmttag,
1823 					(const char *)"REGISTER");
1824 				(void) printf("%#llx  (deprecated value)",
1825 					EC_XWORD(p_dyn.d_un.d_val));
1826 				break;
1827 			default:
1828 				(void) printf("%lld", EC_XWORD(p_dyn.d_tag));
1829 				break;
1830 			}
1831 			(void) printf("\n");
1832 			(void) gelf_getdyn(dyn_data, ii++, &p_dyn);
1833 		}
1834 	}
1835 
1836 	/*
1837 	 * Check for existence of static shared library information.
1838 	 */
1839 	(void) gelf_getehdr(elf_file, &p_ehdr);
1840 	while (header_num < p_ehdr.e_phnum) {
1841 		(void) gelf_getphdr(elf_file, header_num, &p_phdr);
1842 		if (p_phdr.p_type == PT_SHLIB) {
1843 			while (--lib_scns > 0) {
1844 				if (strcmp(l_scns->scn_name, ".lib") == 0) {
1845 					print_static(l_scns, filename);
1846 				}
1847 				l_scns++;
1848 			}
1849 		}
1850 		header_num++;
1851 	}
1852 }
1853 
1854 /*
1855  * Print the ELF header.  Input is an ELF file descriptor
1856  * and the filename.  If f_flag is set, the ELF header is
1857  * printed to stdout, otherwise the function returns after
1858  * setting the pointer to the ELF header.  Any values which
1859  * are not known are printed in decimal.  Fields must be updated
1860  * as new values are added.
1861  */
1862 static GElf_Ehdr *
1863 dump_elf_header(Elf *elf_file, char *filename, GElf_Ehdr * elf_head_p)
1864 {
1865 	int class, data;
1866 	int field;
1867 
1868 	if (gelf_getehdr(elf_file, elf_head_p) == NULL) {
1869 		(void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename,
1870 		    elf_errmsg(-1));
1871 		return (NULL);
1872 	}
1873 
1874 	class = (int)elf_head_p->e_ident[4];
1875 
1876 	if (class == ELFCLASS64)
1877 		field = 21;
1878 	else
1879 		field = 13;
1880 
1881 	if (!f_flag)
1882 		return (elf_head_p);
1883 
1884 	if (!p_flag) {
1885 		(void) printf("\n                    **** ELF HEADER ****\n");
1886 		(void) printf("%-*s%-11s%-*sMachine     Version\n",
1887 		    field, "Class", "Data", field, "Type");
1888 		(void) printf("%-*s%-11s%-*sFlags       Ehsize\n",
1889 		    field, "Entry", "Phoff", field, "Shoff");
1890 		(void) printf("%-*s%-11s%-*sShnum       Shstrndx\n\n",
1891 		    field, "Phentsize", "Phnum", field, "Shentsz");
1892 	}
1893 
1894 	if (!v_flag) {
1895 		(void) printf("%-*d%-11d%-*d%-12d%d\n",
1896 			field, elf_head_p->e_ident[4],
1897 			elf_head_p->e_ident[5],
1898 			field, (int)elf_head_p->e_type,
1899 			(int)elf_head_p->e_machine,
1900 			elf_head_p->e_version);
1901 	} else {
1902 		data = elf_head_p->e_ident[5];
1903 
1904 		switch (class) {
1905 		case ELFCLASSNONE:
1906 			(void) printf("%-*s", field, "None");
1907 			break;
1908 		case ELFCLASS32:
1909 			(void) printf("%-*s", field, "32-bit");
1910 			break;
1911 		case ELFCLASS64:
1912 			(void) printf("%-*s", field, "64-bit");
1913 			break;
1914 		default:
1915 			(void) printf("%-*d", field, class);
1916 			break;
1917 		}
1918 		switch (data) {
1919 		case ELFDATANONE:
1920 			(void) printf("%-11s", "None   ");
1921 			break;
1922 		case ELFDATA2LSB:
1923 			(void) printf("%-11s", "2LSB   ");
1924 			break;
1925 		case ELFDATA2MSB:
1926 			(void) printf("%-11s", "2MSB   ");
1927 			break;
1928 		default:
1929 			(void) printf("%-11d", data);
1930 			break;
1931 		}
1932 
1933 		switch (elf_head_p->e_type) {
1934 		case ET_NONE:
1935 			(void) printf("%-*s", field, "None");
1936 			break;
1937 		case ET_REL:
1938 			(void) printf("%-*s", field, "Reloc");
1939 			break;
1940 		case ET_EXEC:
1941 			(void) printf("%-*s", field, "Exec");
1942 			break;
1943 		case ET_DYN:
1944 			(void) printf("%-*s", field, "Dyn");
1945 			break;
1946 		case ET_CORE:
1947 			(void) printf("%-*s", field, "Core");
1948 			break;
1949 		default:
1950 			(void) printf("%-*d", field,
1951 				EC_WORD(elf_head_p->e_type));
1952 			break;
1953 		}
1954 		switch (elf_head_p->e_machine) {
1955 		case EM_NONE:
1956 			(void) printf("%-12s", "No mach");
1957 			break;
1958 		case EM_M32:
1959 			(void) printf("%-12s", "WE32100");
1960 			break;
1961 		case EM_SPARC:
1962 			(void) printf("%-12s", "SPARC");
1963 			break;
1964 		case EM_SPARCV9:
1965 			(void) printf("%-12s", "SPARCV9");
1966 			break;
1967 		case EM_386:
1968 			(void) printf("%-12s", "80386");
1969 			break;
1970 		case EM_68K:
1971 			(void) printf("%-12s", "68000");
1972 			break;
1973 		case EM_88K:
1974 			(void) printf("%-12s", "88000");
1975 			break;
1976 		case EM_486:
1977 			(void) printf("%-12s", "80486");
1978 			break;
1979 		case EM_860:
1980 			(void) printf("%-12s", "i860");
1981 			break;
1982 		case EM_MIPS:
1983 			(void) printf("%-12s", "RS3000_BE");
1984 			break;
1985 		case EM_MIPS_RS3_LE:
1986 			(void) printf("%-12s", "RS3000_LE");
1987 			break;
1988 		case EM_RS6000:
1989 			(void) printf("%-12s", "RS6000");
1990 			break;
1991 		case EM_PA_RISC:
1992 			(void) printf("%-12s", "PA_RISC");
1993 			break;
1994 		case EM_nCUBE:
1995 			(void) printf("%-12s", "nCUBE");
1996 			break;
1997 		case EM_VPP500:
1998 			(void) printf("%-12s", "VPP500");
1999 			break;
2000 		case EM_SPARC32PLUS:
2001 			(void) printf("%-12s", "SPARC32PLUS");
2002 			break;
2003 		case EM_PPC:
2004 			(void) printf("%-12s", "PowerPC");
2005 			break;
2006 		case EM_IA_64:
2007 			(void) printf("%-12s", "IA64");
2008 			break;
2009 		default:
2010 			(void) printf("%-12d", EC_WORD(elf_head_p->e_machine));
2011 		}
2012 		switch (elf_head_p->e_version) {
2013 		case EV_NONE:
2014 			(void) printf("Invalid\n");
2015 			break;
2016 		case EV_CURRENT:
2017 			(void) printf("Current\n");
2018 			break;
2019 		default:
2020 			(void) printf("%d\n", elf_head_p->e_version);
2021 		}
2022 	}
2023 	(void) printf("%-#*llx%-#11llx%-#*llx%-#12x%#x\n",
2024 		field, EC_ADDR(elf_head_p->e_entry),
2025 		EC_OFF(elf_head_p->e_phoff),
2026 		field, EC_OFF(elf_head_p->e_shoff),
2027 		EC_WORD(elf_head_p->e_flags),
2028 		EC_WORD(elf_head_p->e_ehsize));
2029 	if (!v_flag || (elf_head_p->e_shstrndx != SHN_XINDEX)) {
2030 		(void) printf("%-#*x%-11u%-#*x%-12u%u\n",
2031 			field, EC_WORD(elf_head_p->e_phentsize),
2032 			EC_WORD(elf_head_p->e_phnum),
2033 			field, EC_WORD(elf_head_p->e_shentsize),
2034 			EC_WORD(elf_head_p->e_shnum),
2035 			EC_WORD(elf_head_p->e_shstrndx));
2036 	} else {
2037 		(void) printf("%-#*x%-11u%-#*x%-12uXINDEX\n",
2038 			field, EC_WORD(elf_head_p->e_phentsize),
2039 			EC_WORD(elf_head_p->e_phnum),
2040 			field, EC_WORD(elf_head_p->e_shentsize),
2041 			EC_WORD(elf_head_p->e_shnum));
2042 	}
2043 	if ((elf_head_p->e_shnum == 0) && (elf_head_p->e_shoff > 0)) {
2044 		Elf_Scn		*scn;
2045 		GElf_Shdr	shdr0;
2046 		int		field;
2047 
2048 		if (gelf_getclass(elf_file) == ELFCLASS64)
2049 			field = 21;
2050 		else
2051 			field = 13;
2052 		if (!p_flag) {
2053 			(void) printf("\n	   **** SECTION HEADER[0] "
2054 			    "{Elf Extensions} ****\n");
2055 			(void) printf(
2056 			    "[No]\tType\tFlags\t%-*s %-*s%-*s%sName\n",
2057 			    field, "Addr", field, "Offset", field,
2058 			    "Size(shnum)",
2059 			    /* compatibility:  tab for elf32 */
2060 			    (field == 13) ? "\t" : "  ");
2061 			(void) printf("\tLn(strndx) Info\t%-*s Entsize\n",
2062 			    field, "Adralgn");
2063 		}
2064 		if ((scn = elf_getscn(elf_file, 0)) == NULL) {
2065 			(void) fprintf(stderr,
2066 				"%s: %s: elf_getscn failed: %s\n",
2067 				prog_name, filename, elf_errmsg(-1));
2068 			return (NULL);
2069 		}
2070 		if (gelf_getshdr(scn, &shdr0) == 0) {
2071 			(void) fprintf(stderr,
2072 				"%s: %s: gelf_getshdr: %s\n",
2073 				prog_name, filename, elf_errmsg(-1));
2074 			return (NULL);
2075 		}
2076 		(void) printf("[0]\t%u\t%llu\t", EC_WORD(shdr0.sh_type),
2077 			EC_XWORD(shdr0.sh_flags));
2078 
2079 		/*
2080 		 * LINTED - field and EC_XWORD cause -#*llu complaints that
2081 		 * even this comment can't shutup.
2082 		 */
2083 		(void) printf("%-#*llx %-#*llx%-#*llu%s%-#*u\n",
2084 			field, EC_ADDR(shdr0.sh_addr),
2085 			field, EC_OFF(shdr0.sh_offset),
2086 			field, EC_XWORD(shdr0.sh_size),
2087 			/* compatibility:  tab for elf32 */
2088 			((field == 13) ? "\t" : "  "),
2089 			field, EC_WORD(shdr0.sh_name));
2090 
2091 		(void) printf("\t%u\t%u\t%-#*llx %-#*llx\n",
2092 			EC_WORD(shdr0.sh_link),
2093 			EC_WORD(shdr0.sh_info),
2094 			field, EC_XWORD(shdr0.sh_addralign),
2095 			field, EC_XWORD(shdr0.sh_entsize));
2096 	}
2097 	(void) printf("\n");
2098 
2099 	return (elf_head_p);
2100 }
2101 
2102 /*
2103  * Print section contents.  Input is an ELF file descriptor,
2104  * the ELF header, the SCNTAB structure,
2105  * the number of symbols, and the filename.
2106  * The number of sections,
2107  * and the offset into the SCNTAB structure will be
2108  * set in dump_section if d_flag or n_flag are set.
2109  * If v_flag is set, sections which can be interpreted will
2110  * be interpreted, otherwise raw data will be output in hexidecimal.
2111  */
2112 static void
2113 print_section(Elf *elf_file,
2114 	GElf_Ehdr *p_ehdr, SCNTAB *p, int num_scns, char *filename)
2115 {
2116 	unsigned char    *p_sec;
2117 	int	i;
2118 	size_t	size;
2119 
2120 	for (i = 0; i < num_scns; i++, p++) {
2121 		GElf_Shdr shdr;
2122 
2123 		size = 0;
2124 		if (s_flag && !v_flag)
2125 			p_sec = (unsigned char *)get_rawscn(p->p_sd, &size);
2126 		else
2127 			p_sec = (unsigned char *)get_scndata(p->p_sd, &size);
2128 
2129 		if ((gelf_getshdr(p->p_sd, &shdr) != NULL) &&
2130 		    (shdr.sh_type == SHT_NOBITS)) {
2131 			continue;
2132 		}
2133 		if (s_flag && !v_flag) {
2134 			(void) printf("\n%s:\n", p->scn_name);
2135 			print_rawdata(p_sec, size);
2136 			continue;
2137 		}
2138 		if (shdr.sh_type == SHT_SYMTAB) {
2139 			dump_symbol_table(elf_file, p, filename);
2140 			continue;
2141 		}
2142 		if (shdr.sh_type == SHT_DYNSYM) {
2143 			dump_symbol_table(elf_file, p, filename);
2144 			continue;
2145 		}
2146 		if (shdr.sh_type == SHT_STRTAB) {
2147 			dump_string_table(p, 1);
2148 			continue;
2149 		}
2150 		if (shdr.sh_type == SHT_RELA) {
2151 			dump_reloc_table(elf_file, p_ehdr, p, 1, filename);
2152 			continue;
2153 		}
2154 		if (shdr.sh_type == SHT_REL) {
2155 			dump_reloc_table(elf_file, p_ehdr, p, 1, filename);
2156 			continue;
2157 		}
2158 		if (shdr.sh_type == SHT_DYNAMIC) {
2159 			dump_dynamic(elf_file, p, 1, filename);
2160 			continue;
2161 		}
2162 
2163 		(void) printf("\n%s:\n", p->scn_name);
2164 		print_rawdata(p_sec, size);
2165 	}
2166 	(void) printf("\n");
2167 }
2168 
2169 /*
2170  * Print section contents. This function does not print the contents
2171  * of the sections but sets up the parameters and then calls
2172  * print_section to print the contents.  Calling another function to print
2173  * the contents allows both -d and -n to work correctly
2174  * simultaneously. Input is an ELF file descriptor, the ELF header,
2175  * the SCNTAB structure, the number of sections, and the filename.
2176  * Set the range of sections if d_flag, and set section name if
2177  * n_flag.
2178  */
2179 static void
2180 dump_section(Elf *elf_file,
2181 	GElf_Ehdr *p_ehdr, SCNTAB *s, int num_scns, char *filename)
2182 {
2183 	SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */
2184 	int i;
2185 	int found_it = 0;  /* for use with -n section_name */
2186 
2187 	if (n_flag) {
2188 		n_range = s;
2189 
2190 		for (i = 0; i < num_scns; i++, n_range++) {
2191 			if ((strcmp(name, n_range->scn_name)) != 0)
2192 				continue;
2193 			else {
2194 				found_it = 1;
2195 				print_section(elf_file, p_ehdr,
2196 					n_range, 1, filename);
2197 			}
2198 		}
2199 
2200 		if (!found_it) {
2201 			(void) fprintf(stderr, "%s: %s: %s not found\n",
2202 				prog_name, filename, name);
2203 		}
2204 	} /* end n_flag */
2205 
2206 	if (d_flag) {
2207 		d_range = s;
2208 		d_num = check_range(d_low, d_hi, num_scns, filename);
2209 		if (d_num < 0)
2210 			return;
2211 		d_range += d_low - 1;
2212 
2213 		print_section(elf_file, p_ehdr, d_range, d_num, filename);
2214 	}	/* end d_flag */
2215 
2216 	if (!n_flag && !d_flag)
2217 		print_section(elf_file, p_ehdr, s, num_scns, filename);
2218 }
2219 
2220 /*
2221  * Print the section header table. This function does not print the contents
2222  * of the section headers but sets up the parameters and then calls
2223  * print_shdr to print the contents.  Calling another function to print
2224  * the contents allows both -d and -n to work correctly
2225  * simultaneously.  Input is the SCNTAB structure,
2226  * the number of sections from the ELF header, and the filename.
2227  * Set the range of section headers to print if d_flag, and set
2228  * name of section header to print if n_flag.
2229  */
2230 static void
2231 dump_shdr(Elf *elf_file, SCNTAB *s, int num_scns, char *filename)
2232 {
2233 
2234 	SCNTAB *n_range, *d_range;	/* for use with -n and -d modifiers */
2235 	int field;
2236 	int i;
2237 	int found_it = 0;  /* for use with -n section_name */
2238 
2239 	if (gelf_getclass(elf_file) == ELFCLASS64)
2240 		field = 21;
2241 	else
2242 		field = 13;
2243 
2244 	if (!p_flag) {
2245 		(void) printf("\n	   **** SECTION HEADER TABLE ****\n");
2246 		(void) printf("[No]\tType\tFlags\t%-*s %-*s %-*s%sName\n",
2247 		    field, "Addr", field, "Offset", field, "Size",
2248 		    /* compatibility:  tab for elf32 */
2249 		    (field == 13) ? "\t" : "  ");
2250 		(void) printf("\tLink\tInfo\t%-*s Entsize\n\n",
2251 		    field, "Adralgn");
2252 	}
2253 
2254 	if (n_flag) {
2255 		n_range = s;
2256 
2257 		for (i = 1; i <= num_scns; i++, n_range++) {
2258 			if ((strcmp(name, n_range->scn_name)) != 0)
2259 				continue;
2260 			else {
2261 				found_it = 1;
2262 				print_shdr(elf_file, n_range, 1, i);
2263 			}
2264 		}
2265 
2266 		if (!found_it) {
2267 			(void) fprintf(stderr, "%s: %s: %s not found\n",
2268 				prog_name, filename, name);
2269 		}
2270 	} /* end n_flag */
2271 
2272 	if (d_flag) {
2273 		d_range = s;
2274 		d_num = check_range(d_low, d_hi, num_scns, filename);
2275 		if (d_num < 0)
2276 			return;
2277 		d_range += d_low - 1;
2278 
2279 		print_shdr(elf_file, d_range, d_num, d_low);
2280 	}	/* end d_flag */
2281 
2282 	if (!n_flag && !d_flag)
2283 		print_shdr(elf_file, s, num_scns, 1);
2284 }
2285 
2286 /*
2287  * Process all of the command line options (except
2288  * for -a, -g, -f, and -o).  All of the options processed
2289  * by this function require the presence of the section
2290  * header table and will not be processed if it is not present.
2291  * Set up a buffer containing section name, section header,
2292  * and section descriptor for each section in the file.  This
2293  * structure is used to avoid duplicate calls to libelf functions.
2294  * Structure members for the symbol table, the debugging information,
2295  * and the line number information are global.  All of the
2296  * rest are local.
2297  */
2298 static void
2299 dump_section_table(Elf *elf_file, GElf_Ehdr *elf_head_p, char *filename)
2300 {
2301 
2302 	static SCNTAB	*buffer, *p_scns;
2303 	Elf_Scn		*scn = 0;
2304 	char		*s_name = NULL;
2305 	int		found = 0;
2306 	unsigned int	num_scns;
2307 	size_t		shstrndx;
2308 	size_t		shnum;
2309 
2310 
2311 	if (elf_getshnum(elf_file, &shnum) == 0) {
2312 		(void) fprintf(stderr,
2313 			"%s: %s: elf_getshnum failed: %s\n",
2314 			prog_name, filename, elf_errmsg(-1));
2315 		return;
2316 	}
2317 	if (elf_getshstrndx(elf_file, &shstrndx) == 0) {
2318 		(void) fprintf(stderr,
2319 			"%s: %s: elf_getshstrndx failed: %s\n",
2320 			prog_name, filename, elf_errmsg(-1));
2321 		return;
2322 	}
2323 
2324 	if ((buffer = calloc(shnum, sizeof (SCNTAB))) == NULL) {
2325 		(void) fprintf(stderr, "%s: %s: cannot calloc space\n",
2326 			prog_name, filename);
2327 		return;
2328 	}
2329 	/* LINTED */
2330 	num_scns = (int)shnum - 1;
2331 
2332 	p_symtab = (SCNTAB *)0;
2333 	p_dynsym = (SCNTAB *)0;
2334 	p_scns = buffer;
2335 	p_head_scns = buffer;
2336 
2337 	while ((scn = elf_nextscn(elf_file, scn)) != 0) {
2338 		if ((gelf_getshdr(scn, &buffer->p_shdr)) == 0) {
2339 			(void) fprintf(stderr,
2340 			"%s: %s: %s\n", prog_name, filename, elf_errmsg(-1));
2341 			return;
2342 		}
2343 		s_name = (char *)elf_strptr(elf_file,
2344 			shstrndx, buffer->p_shdr.sh_name);
2345 		buffer->scn_name = s_name ? s_name : (char *)UNKNOWN;
2346 		buffer->p_sd   =  scn;
2347 
2348 		if (buffer->p_shdr.sh_type == SHT_SYMTAB) {
2349 			found += 1;
2350 			p_symtab = buffer;
2351 		}
2352 		if (buffer->p_shdr.sh_type == SHT_DYNSYM)
2353 			p_dynsym = buffer;
2354 		buffer++;
2355 	}
2356 
2357 	/*
2358 	 * These functions depend upon the presence of the section header table
2359 	 * and will not be invoked in its absence
2360 	 */
2361 	if (h_flag) {
2362 		dump_shdr(elf_file, p_scns, num_scns, filename);
2363 	}
2364 	if (p_symtab && (t_flag || T_flag)) {
2365 		dump_symbol_table(elf_file, p_symtab, filename);
2366 	}
2367 	if (c_flag) {
2368 		dump_string_table(p_scns, num_scns);
2369 	}
2370 	if (r_flag) {
2371 		dump_reloc_table(elf_file, elf_head_p,
2372 			p_scns, num_scns, filename);
2373 	}
2374 	if (L_flag) {
2375 		dump_dynamic(elf_file, p_scns, num_scns, filename);
2376 	}
2377 	if (s_flag) {
2378 		dump_section(elf_file, elf_head_p, p_scns,
2379 			num_scns, filename);
2380 	}
2381 }
2382 
2383 /*
2384  * Load the archive string table(s) (for extended-length strings)
2385  * into an in-core table/list
2386  */
2387 static struct stab_list_s *
2388 load_arstring_table(struct stab_list_s *STabList,
2389 	int fd, Elf *elf_file, Elf_Arhdr *p_ar, char *filename)
2390 {
2391 	off_t here;
2392 	struct stab_list_s *STL_entry, *STL_next;
2393 
2394 	if (p_ar) {
2395 		STL_entry = malloc(sizeof (struct stab_list_s));
2396 		STL_entry->next    = 0;
2397 		STL_entry->strings = 0;
2398 		STL_entry->size    = 0;
2399 
2400 		if (!STabList)
2401 			STabList = STL_entry;
2402 		else {
2403 			STL_next = STabList;
2404 			while (STL_next->next != (void *)0)
2405 				STL_next = STL_next->next;
2406 			STL_next->next = STL_entry;
2407 		}
2408 
2409 		STL_entry->size    = p_ar->ar_size;
2410 		STL_entry->strings = malloc(p_ar->ar_size);
2411 		here = elf_getbase(elf_file);
2412 		if ((lseek(fd, here, 0)) != here) {
2413 			(void) fprintf(stderr,
2414 			"%s: %s: could not lseek\n", prog_name, filename);
2415 		}
2416 
2417 		if ((read(fd, STL_entry->strings, p_ar->ar_size)) == -1) {
2418 			(void) fprintf(stderr,
2419 			"%s: %s: could not read\n", prog_name, filename);
2420 		}
2421 	}
2422 	return (STabList);
2423 }
2424 
2425 /*
2426  * Print the archive header for each member of an archive.
2427  * Also call ar_sym_read to print the symbols in the
2428  * archive symbol table if g_flag.  Input is a file descriptor,
2429  * an ELF file descriptor, and the filename.  Putting the call
2430  * to dump the archive symbol table in this function is more
2431  * efficient since it is necessary to examine the archive member
2432  * name in the archive header to determine which member is the
2433  * symbol table.
2434  */
2435 static void
2436 dump_ar_hdr(int fd, Elf *elf_file, char *filename)
2437 {
2438 	extern int v_flag, g_flag, a_flag, p_flag;
2439 	Elf_Arhdr  *p_ar;
2440 	Elf *arf;
2441 	Elf_Cmd cmd;
2442 	int title = 0;
2443 	int err = 0;
2444 
2445 	char buf[DATESIZE];
2446 
2447 	cmd = ELF_C_READ;
2448 	while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
2449 		p_ar = elf_getarhdr(arf);
2450 		if (p_ar == NULL) {
2451 			(void) fprintf(stderr,
2452 			"%s: %s: %s\n", prog_name, filename, elf_errmsg(-1));
2453 			continue;
2454 		}
2455 		if (strcmp(p_ar->ar_name, "/") == 0) {
2456 			if (g_flag)
2457 				ar_sym_read(elf_file, filename);
2458 		} else if (strcmp(p_ar->ar_name, "//") == 0) {
2459 			StringTableList = load_arstring_table(
2460 				StringTableList, fd, arf, p_ar,
2461 				filename);
2462 			cmd = elf_next(arf);
2463 			(void) elf_end(arf);
2464 			continue;
2465 		} else {
2466 			if (a_flag) {
2467 				(void) printf("%s[%s]:\n", filename,
2468 					p_ar->ar_name);
2469 				if (!p_flag && title == 0) {
2470 					if (!v_flag)
2471 						(void) printf(
2472 "\n\n\t\t\t***ARCHIVE HEADER***"
2473 "\n	Date          Uid     Gid    Mode      Size	 Member Name\n\n");
2474 					else
2475 						(void) printf(
2476 "\n\n\t\t\t***ARCHIVE HEADER***"
2477 "\n	Date                   Uid    Gid   Mode     Size     Member Name\n\n");
2478 					title = 1;
2479 				}
2480 				if (!v_flag) {
2481 					(void) printf(
2482 "\t0x%.8lx  %6d  %6d  0%.6ho  0x%.8lx  %-s\n\n",
2483 						p_ar->ar_date,
2484 						(int)p_ar->ar_uid,
2485 						(int)p_ar->ar_gid,
2486 						(int)p_ar->ar_mode,
2487 						p_ar->ar_size,
2488 						p_ar->ar_name);
2489 				} else {
2490 					if ((strftime(buf, DATESIZE,
2491 					    "%b %d %H:%M:%S %Y",
2492 					    localtime(
2493 					    &(p_ar->ar_date)))) == 0) {
2494 						(void) fprintf(stderr,
2495 "%s: %s: don't have enough space to store the date\n", prog_name, filename);
2496 						exit(1);
2497 					}
2498 					(void) printf(
2499 					"\t%s %6d %6d 0%.6ho 0x%.8lx %-s\n\n",
2500 						buf,
2501 						(int)p_ar->ar_uid,
2502 						(int)p_ar->ar_gid,
2503 						(int)p_ar->ar_mode,
2504 						p_ar->ar_size,
2505 						p_ar->ar_name);
2506 				}
2507 			}
2508 		}
2509 		cmd = elf_next(arf);
2510 		(void) elf_end(arf);
2511 	} /* end while */
2512 
2513 	err = elf_errno();
2514 	if (err != 0) {
2515 		(void) fprintf(stderr,
2516 		"%s: %s: %s\n", prog_name, filename, elf_errmsg(err));
2517 	}
2518 }
2519 
2520 /*
2521  * Process member files of an archive.  This function provides
2522  * a loop through an archive equivalent the processing of
2523  * each_file for individual object files.
2524  */
2525 static void
2526 dump_ar_files(int fd, Elf *elf_file, char *filename)
2527 {
2528 	Elf_Arhdr  *p_ar;
2529 	Elf *arf;
2530 	Elf_Cmd cmd;
2531 	Elf_Kind file_type;
2532 	GElf_Ehdr elf_head;
2533 	char *fullname;
2534 
2535 	cmd = ELF_C_READ;
2536 	while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
2537 		size_t	len;
2538 
2539 		p_ar = elf_getarhdr(arf);
2540 		if (p_ar == NULL) {
2541 			(void) fprintf(stderr,
2542 				"%s: %s: %s\n",
2543 				prog_name, filename, elf_errmsg(-1));
2544 			return;
2545 		}
2546 		if ((strcmp(p_ar->ar_name, "/") == 0) ||
2547 			(strcmp(p_ar->ar_name, "//") == 0)) {
2548 			cmd = elf_next(arf);
2549 			(void) elf_end(arf);
2550 			continue;
2551 		}
2552 
2553 		len = strlen(filename) + strlen(p_ar->ar_name) + 3;
2554 		if ((fullname = malloc(len)) == NULL)
2555 			return;
2556 		(void) snprintf(fullname, len, "%s[%s]", filename,
2557 		    p_ar->ar_name);
2558 		(void) printf("\n%s:\n", fullname);
2559 		file_type = elf_kind(arf);
2560 		if (file_type == ELF_K_ELF) {
2561 			if (dump_elf_header(arf, fullname, &elf_head) == NULL)
2562 				return;
2563 			if (o_flag)
2564 				dump_exec_header(arf,
2565 					(unsigned)elf_head.e_phnum, fullname);
2566 			if (x_flag)
2567 				dump_section_table(arf, &elf_head, fullname);
2568 		} else {
2569 			(void) fprintf(stderr,
2570 				"%s: %s: invalid file type\n",
2571 				prog_name, fullname);
2572 			cmd = elf_next(arf);
2573 			(void) elf_end(arf);
2574 			continue;
2575 		}
2576 
2577 		cmd = elf_next(arf);
2578 		(void) elf_end(arf);
2579 	} /* end while */
2580 }
2581 
2582 /*
2583  * Takes a filename as input.  Test first for a valid version
2584  * of libelf.a and exit on error.  Process each valid file
2585  * or archive given as input on the command line.  Check
2586  * for file type.  If it is an archive, process the archive-
2587  * specific options first, then files within the archive.
2588  * If it is an ELF object file, process it; otherwise
2589  * warn that it is an invalid file type.
2590  * All options except the archive-specific and program
2591  * execution header are processed in the function, dump_section_table.
2592  */
2593 static void
2594 each_file(char *filename)
2595 {
2596 	Elf *elf_file;
2597 	GElf_Ehdr elf_head;
2598 	int fd;
2599 	Elf_Kind   file_type;
2600 
2601 	struct stat buf;
2602 
2603 	Elf_Cmd cmd;
2604 	errno = 0;
2605 
2606 	if (stat(filename, &buf) == -1) {
2607 		int	err = errno;
2608 		(void) fprintf(stderr, "%s: %s: %s", prog_name, filename,
2609 		    strerror(err));
2610 		return;
2611 	}
2612 
2613 	if ((fd = open((filename), O_RDONLY)) == -1) {
2614 		(void) fprintf(stderr, "%s: %s: cannot read\n", prog_name,
2615 		    filename);
2616 		return;
2617 	}
2618 	cmd = ELF_C_READ;
2619 	if ((elf_file = elf_begin(fd, cmd, (Elf *)0)) == NULL) {
2620 		(void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename,
2621 		    elf_errmsg(-1));
2622 		return;
2623 	}
2624 
2625 	file_type = elf_kind(elf_file);
2626 	if (file_type == ELF_K_AR) {
2627 		if (a_flag || g_flag) {
2628 			dump_ar_hdr(fd, elf_file, filename);
2629 			elf_file = elf_begin(fd, cmd, (Elf *)0);
2630 		}
2631 		if (z_flag)
2632 			dump_ar_files(fd, elf_file, filename);
2633 	} else {
2634 		if (file_type == ELF_K_ELF) {
2635 			(void) printf("\n%s:\n", filename);
2636 			if (dump_elf_header(elf_file, filename, &elf_head)) {
2637 				if (o_flag)
2638 					dump_exec_header(elf_file,
2639 					    (unsigned)elf_head.e_phnum,
2640 					    filename);
2641 				if (x_flag)
2642 					dump_section_table(elf_file,
2643 					    &elf_head, filename);
2644 			}
2645 		} else {
2646 			(void) fprintf(stderr, "%s: %s: invalid file type\n",
2647 			    prog_name, filename);
2648 		}
2649 	}
2650 	(void) elf_end(elf_file);
2651 	(void) close(fd);
2652 }
2653 
2654 /*
2655  * Sets up flags for command line options given and then
2656  * calls each_file() to process each file.
2657  */
2658 int
2659 main(int argc, char *argv[], char *envp[])
2660 {
2661 	char *optstr = OPTSTR; /* option string used by getopt() */
2662 	int optchar;
2663 
2664 	/*
2665 	 * Check for a binary that better fits this architecture.
2666 	 */
2667 	conv_check_native(argv, envp);
2668 
2669 	prog_name = argv[0];
2670 
2671 	(void) setlocale(LC_ALL, "");
2672 	while ((optchar = getopt(argc, argv, optstr)) != -1) {
2673 		switch (optchar) {
2674 		case 'a':
2675 			a_flag = 1;
2676 			x_flag = 1;
2677 			break;
2678 		case 'g':
2679 			g_flag = 1;
2680 			x_flag = 1;
2681 			break;
2682 		case 'v':
2683 			v_flag = 1;
2684 			break;
2685 		case 'p':
2686 			p_flag = 1;
2687 			break;
2688 		case 'f':
2689 			f_flag = 1;
2690 			z_flag = 1;
2691 			break;
2692 		case 'o':
2693 			o_flag = 1;
2694 			z_flag = 1;
2695 			break;
2696 		case 'h':
2697 			h_flag = 1;
2698 			x_flag = 1;
2699 			z_flag = 1;
2700 			break;
2701 		case 's':
2702 			s_flag = 1;
2703 			x_flag = 1;
2704 			z_flag = 1;
2705 			break;
2706 		case 'd':
2707 			d_flag = 1;
2708 			x_flag = 1;
2709 			z_flag = 1;
2710 			set_range(optarg, &d_low, &d_hi);
2711 			break;
2712 		case 'n':
2713 			n_flag++;
2714 			x_flag = 1;
2715 			z_flag = 1;
2716 			name = optarg;
2717 			break;
2718 		case 'r':
2719 			r_flag = 1;
2720 			x_flag = 1;
2721 			z_flag = 1;
2722 			break;
2723 		case 't':
2724 			t_flag = 1;
2725 			x_flag = 1;
2726 			z_flag = 1;
2727 			break;
2728 		case 'C':
2729 			C_flag = 1;
2730 			t_flag = 1;
2731 			x_flag = 1;
2732 			z_flag = 1;
2733 			break;
2734 		case 'T':
2735 			T_flag = 1;
2736 			x_flag = 1;
2737 			z_flag = 1;
2738 			set_range(optarg, &T_low, &T_hi);
2739 			break;
2740 		case 'c':
2741 			c_flag = 1;
2742 			x_flag = 1;
2743 			z_flag = 1;
2744 			break;
2745 		case 'L':
2746 			L_flag = 1;
2747 			x_flag = 1;
2748 			z_flag = 1;
2749 			break;
2750 		case 'V':
2751 			V_flag = 1;
2752 			(void) fprintf(stderr, "dump: %s %s\n",
2753 			    (const char *)SGU_PKG,
2754 			    (const char *)SGU_REL);
2755 			break;
2756 		case '?':
2757 			errflag += 1;
2758 			break;
2759 		default:
2760 			break;
2761 		}
2762 	}
2763 
2764 	if (errflag || (optind >= argc) || (!z_flag && !x_flag)) {
2765 		if (!(V_flag && (argc == 2))) {
2766 			usage();
2767 			exit(269);
2768 		}
2769 	}
2770 
2771 	if (elf_version(EV_CURRENT) == EV_NONE) {
2772 		(void) fprintf(stderr, "%s: libelf is out of date\n",
2773 		    prog_name);
2774 		exit(101);
2775 	}
2776 
2777 	while (optind < argc) {
2778 		each_file(argv[optind]);
2779 		optind++;
2780 	}
2781 	return (0);
2782 }
2783