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