10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51618Srie * Common Development and Distribution License (the "License"). 61618Srie * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211618Srie 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright (c) 1988 AT&T 240Sstevel@tonic-gate * All Rights Reserved 250Sstevel@tonic-gate * 26*12792SAli.Bahrami@Oracle.COM * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 270Sstevel@tonic-gate */ 280Sstevel@tonic-gate 291976Sab196087 /* Get definitions for the relocation types supported. */ 301976Sab196087 #define ELF_TARGET_ALL 311976Sab196087 320Sstevel@tonic-gate #include <stdio.h> 330Sstevel@tonic-gate #include <stdlib.h> 340Sstevel@tonic-gate #include <locale.h> 350Sstevel@tonic-gate #include <unistd.h> 360Sstevel@tonic-gate #include <libelf.h> 376206Sab196087 #include <sys/link.h> 381976Sab196087 #include <sys/elf.h> 390Sstevel@tonic-gate #include <sys/machelf.h> 400Sstevel@tonic-gate #include <fcntl.h> 410Sstevel@tonic-gate #include <sys/stat.h> 420Sstevel@tonic-gate #include <errno.h> 430Sstevel@tonic-gate #include <string.h> 440Sstevel@tonic-gate #include "sgs.h" 450Sstevel@tonic-gate #include "conv.h" 460Sstevel@tonic-gate #include "dump.h" 470Sstevel@tonic-gate 480Sstevel@tonic-gate 490Sstevel@tonic-gate #define OPTSTR "agcd:fhn:oprstvCLT:V?" /* option string for getopt() */ 500Sstevel@tonic-gate 510Sstevel@tonic-gate const char *UNKNOWN = "<unknown>"; 520Sstevel@tonic-gate 530Sstevel@tonic-gate static SCNTAB *p_symtab, *p_head_scns, *p_dynsym; 540Sstevel@tonic-gate 550Sstevel@tonic-gate static int 560Sstevel@tonic-gate x_flag = 0, /* option requires section header table */ 570Sstevel@tonic-gate z_flag = 0, /* process files within an archive */ 580Sstevel@tonic-gate rn_flag = 0; /* dump named relocation information */ 590Sstevel@tonic-gate 600Sstevel@tonic-gate static int 610Sstevel@tonic-gate /* flags: ?_flag corresponds to ? option */ 620Sstevel@tonic-gate a_flag = 0, /* dump archive header of each member of archive */ 630Sstevel@tonic-gate g_flag = 0, /* dump archive symbol table */ 640Sstevel@tonic-gate c_flag = 0, /* dump the string table */ 650Sstevel@tonic-gate d_flag = 0, /* dump range of sections */ 660Sstevel@tonic-gate f_flag = 0, /* dump each file header */ 670Sstevel@tonic-gate h_flag = 0, /* dump section headers */ 680Sstevel@tonic-gate n_flag = 0, /* dump named section */ 690Sstevel@tonic-gate o_flag = 0, /* dump each program execution header */ 700Sstevel@tonic-gate r_flag = 0, /* dump relocation information */ 710Sstevel@tonic-gate s_flag = 0, /* dump section contents */ 720Sstevel@tonic-gate t_flag = 0, /* dump symbol table entries */ 730Sstevel@tonic-gate C_flag = 0, /* dump decoded C++ symbol names */ 740Sstevel@tonic-gate L_flag = 0, /* dump dynamic linking information */ 750Sstevel@tonic-gate T_flag = 0, /* dump symbol table range */ 760Sstevel@tonic-gate V_flag = 0; /* dump version information */ 770Sstevel@tonic-gate 780Sstevel@tonic-gate int p_flag = 0, /* suppress printing of headings */ 790Sstevel@tonic-gate v_flag = 0; /* print information in verbose form */ 800Sstevel@tonic-gate 810Sstevel@tonic-gate static int 820Sstevel@tonic-gate d_low = 0, /* range for use with -d */ 830Sstevel@tonic-gate d_hi = 0, 840Sstevel@tonic-gate d_num = 0; 850Sstevel@tonic-gate 860Sstevel@tonic-gate static int 870Sstevel@tonic-gate T_low = 0, /* range for use with -T */ 880Sstevel@tonic-gate T_hi = 0, 890Sstevel@tonic-gate T_num = 0; 900Sstevel@tonic-gate 910Sstevel@tonic-gate static char *name = NULL; /* for use with -n option */ 920Sstevel@tonic-gate char *prog_name; 930Sstevel@tonic-gate static int errflag = 0; 940Sstevel@tonic-gate 950Sstevel@tonic-gate static struct stab_list_s { 960Sstevel@tonic-gate struct stab_list_s *next; 970Sstevel@tonic-gate char *strings; 980Sstevel@tonic-gate size_t size; 990Sstevel@tonic-gate } *StringTableList = (void *)0; 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate extern void ar_sym_read(); 1020Sstevel@tonic-gate extern void dump_exec_header(); 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate /* 1060Sstevel@tonic-gate * Get the section descriptor and set the size of the 1070Sstevel@tonic-gate * data returned. Data is byte-order converted. 1080Sstevel@tonic-gate */ 1090Sstevel@tonic-gate void * 1100Sstevel@tonic-gate get_scndata(Elf_Scn *fd_scn, size_t *size) 1110Sstevel@tonic-gate { 1120Sstevel@tonic-gate Elf_Data *p_data; 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate p_data = 0; 1150Sstevel@tonic-gate if ((p_data = elf_getdata(fd_scn, p_data)) == 0 || 1160Sstevel@tonic-gate p_data->d_size == 0) { 1170Sstevel@tonic-gate return (NULL); 1180Sstevel@tonic-gate } 1190Sstevel@tonic-gate *size = p_data->d_size; 1200Sstevel@tonic-gate return (p_data->d_buf); 1210Sstevel@tonic-gate } 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate /* 1240Sstevel@tonic-gate * Get the section descriptor and set the size of the 1250Sstevel@tonic-gate * data returned. Data is raw (i.e., not byte-order converted). 1260Sstevel@tonic-gate */ 1270Sstevel@tonic-gate static void * 1280Sstevel@tonic-gate get_rawscn(Elf_Scn *fd_scn, size_t *size) 1290Sstevel@tonic-gate { 1300Sstevel@tonic-gate Elf_Data *p_data; 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate p_data = 0; 1330Sstevel@tonic-gate if ((p_data = elf_rawdata(fd_scn, p_data)) == 0 || 1340Sstevel@tonic-gate p_data->d_size == 0) { 1350Sstevel@tonic-gate return (NULL); 1360Sstevel@tonic-gate } 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate *size = p_data->d_size; 1390Sstevel@tonic-gate return (p_data->d_buf); 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate /* 1430Sstevel@tonic-gate * Print out a usage message in short form when program is invoked 1440Sstevel@tonic-gate * with insufficient or no arguments, and in long form when given 1450Sstevel@tonic-gate * either a ? or an invalid option. 1460Sstevel@tonic-gate */ 1470Sstevel@tonic-gate static void 1480Sstevel@tonic-gate usage() 1490Sstevel@tonic-gate { 1500Sstevel@tonic-gate (void) fprintf(stderr, 1510Sstevel@tonic-gate "Usage: %s [-%s] file(s) ...\n", prog_name, OPTSTR); 1520Sstevel@tonic-gate if (errflag) { 1530Sstevel@tonic-gate (void) fprintf(stderr, 1540Sstevel@tonic-gate "\t\t[-a dump archive header of each member of archive]\n\ 1550Sstevel@tonic-gate [-g dump archive global symbol table]\n\ 1560Sstevel@tonic-gate [-c dump the string table]\n\ 1570Sstevel@tonic-gate [-d dump range of sections]\n\ 1580Sstevel@tonic-gate [-f dump each file header]\n\ 1590Sstevel@tonic-gate [-h dump section headers]\n\ 1600Sstevel@tonic-gate [-n dump named section]\n\ 1610Sstevel@tonic-gate [-o dump each program execution header]\n\ 1620Sstevel@tonic-gate [-p suppress printing of headings]\n\ 1630Sstevel@tonic-gate [-r dump relocation information]\n\ 1640Sstevel@tonic-gate [-s dump section contents]\n\ 1650Sstevel@tonic-gate [-t dump symbol table entries]\n\ 1660Sstevel@tonic-gate [-v print information in verbose form]\n\ 1670Sstevel@tonic-gate [-C dump decoded C++ symbol names]\n\ 1680Sstevel@tonic-gate [-L dump the .dynamic structure]\n\ 1690Sstevel@tonic-gate [-T dump symbol table range]\n\ 1700Sstevel@tonic-gate [-V dump version information]\n"); 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate /* 1750Sstevel@tonic-gate * Set a range. Input is a character string, a lower 1760Sstevel@tonic-gate * bound and an upper bound. This function converts 1770Sstevel@tonic-gate * a character string into its correct integer values, 1780Sstevel@tonic-gate * setting the first value as the lower bound, and 1790Sstevel@tonic-gate * the second value as the upper bound. If more values 1800Sstevel@tonic-gate * are given they are ignored with a warning. 1810Sstevel@tonic-gate */ 1820Sstevel@tonic-gate static void 1830Sstevel@tonic-gate set_range(char *s, int *low, int *high) 1840Sstevel@tonic-gate { 1850Sstevel@tonic-gate char *w; 1860Sstevel@tonic-gate char *lasts; 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate while ((w = strtok_r(s, ",", &lasts)) != NULL) { 1890Sstevel@tonic-gate if (!(*low)) 1900Sstevel@tonic-gate /* LINTED */ 1910Sstevel@tonic-gate *low = (int)atol(w); 1920Sstevel@tonic-gate else 1930Sstevel@tonic-gate if (!(*high)) 1940Sstevel@tonic-gate /* LINTED */ 1950Sstevel@tonic-gate *high = (int)atol(w); 1960Sstevel@tonic-gate else { 1970Sstevel@tonic-gate (void) fprintf(stderr, 1984734Sab196087 "%s: too many arguments - %s ignored\n", 1994734Sab196087 prog_name, w); 2000Sstevel@tonic-gate return; 2010Sstevel@tonic-gate } 2020Sstevel@tonic-gate s = NULL; 2030Sstevel@tonic-gate } /* end while */ 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate /* 2080Sstevel@tonic-gate * Print static shared library information. 2090Sstevel@tonic-gate */ 2100Sstevel@tonic-gate static void 2110Sstevel@tonic-gate print_static(SCNTAB *l_scns, char *filename) 2120Sstevel@tonic-gate { 2130Sstevel@tonic-gate size_t section_size; 2140Sstevel@tonic-gate unsigned char *strtab; 2150Sstevel@tonic-gate unsigned char *path, buf[1024]; 2160Sstevel@tonic-gate unsigned long *temp; 2170Sstevel@tonic-gate unsigned long total, topath; 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate (void) printf("\n **** STATIC SHARED LIBRARY INFORMATION ****\n"); 2200Sstevel@tonic-gate (void) printf("\n%s:\n", filename); 2210Sstevel@tonic-gate (void) printf("\t"); 2220Sstevel@tonic-gate section_size = 0; 2230Sstevel@tonic-gate if ((strtab = (unsigned char *) 2240Sstevel@tonic-gate get_scndata(l_scns->p_sd, §ion_size)) == NULL) { 2250Sstevel@tonic-gate return; 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate while (section_size != 0) { 2290Sstevel@tonic-gate /* LINTED */ 2300Sstevel@tonic-gate temp = (unsigned long *)strtab; 2310Sstevel@tonic-gate total = temp[0]; 2320Sstevel@tonic-gate topath = temp[1]; 2330Sstevel@tonic-gate path = strtab + (topath*sizeof (long)); 2340Sstevel@tonic-gate (void) strncpy((char *)buf, (char *)path, 2354734Sab196087 (total - topath)*sizeof (long)); 2360Sstevel@tonic-gate (void) fprintf(stdout, "%s\n", buf); 2370Sstevel@tonic-gate strtab += total*sizeof (long); 2380Sstevel@tonic-gate section_size -= (total*sizeof (long)); 2390Sstevel@tonic-gate } 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate /* 2430Sstevel@tonic-gate * Print raw data in hexidecimal. Input is the section data to 2440Sstevel@tonic-gate * be printed out and the size of the data. Output is relative 2450Sstevel@tonic-gate * to a table lookup in dumpmap.h. 2460Sstevel@tonic-gate */ 2470Sstevel@tonic-gate static void 2480Sstevel@tonic-gate print_rawdata(unsigned char *p_sec, size_t size) 2490Sstevel@tonic-gate { 2500Sstevel@tonic-gate size_t j; 2510Sstevel@tonic-gate size_t count; 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate count = 1; 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate (void) printf("\t"); 2560Sstevel@tonic-gate for (j = size/sizeof (short); j != 0; --j, ++count) { 2570Sstevel@tonic-gate (void) printf("%.2x %.2x ", p_sec[0], p_sec[1]); 2580Sstevel@tonic-gate p_sec += 2; 2590Sstevel@tonic-gate if (count == 12) { 2600Sstevel@tonic-gate (void) printf("\n\t"); 2610Sstevel@tonic-gate count = 0; 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate /* 2660Sstevel@tonic-gate * take care of last byte if odd byte section 2670Sstevel@tonic-gate */ 2680Sstevel@tonic-gate if ((size & 0x1L) == 1L) 2690Sstevel@tonic-gate (void) printf("%.2x", *p_sec); 2700Sstevel@tonic-gate (void) printf("\n"); 2710Sstevel@tonic-gate } 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate /* 2760Sstevel@tonic-gate * Print relocation data of type SHT_RELA 2770Sstevel@tonic-gate * If d_flag, print data corresponding only to 2780Sstevel@tonic-gate * the section or range of sections specified. 2790Sstevel@tonic-gate * If n_flag, print data corresponding only to 2800Sstevel@tonic-gate * the named section. 2810Sstevel@tonic-gate */ 2820Sstevel@tonic-gate static void 2830Sstevel@tonic-gate print_rela(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data, 2840Sstevel@tonic-gate GElf_Ehdr * p_ehdr, size_t reloc_size, size_t sym_size, char *filename, 2850Sstevel@tonic-gate SCNTAB *reloc_symtab) 2860Sstevel@tonic-gate { 2870Sstevel@tonic-gate GElf_Rela rela; 2880Sstevel@tonic-gate GElf_Sym sym; 2890Sstevel@tonic-gate size_t no_entries; 2900Sstevel@tonic-gate size_t rel_entsize; 2910Sstevel@tonic-gate size_t no_syms; 2920Sstevel@tonic-gate int type, symid; 2930Sstevel@tonic-gate static int n_title = 0; 2940Sstevel@tonic-gate int ndx = 0; 2950Sstevel@tonic-gate char *sym_name; 2960Sstevel@tonic-gate int adj = 0; 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate if (gelf_getclass(elf_file) == ELFCLASS64) 2991618Srie adj = 8; 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate rel_entsize = p_scns->p_shdr.sh_entsize; 3020Sstevel@tonic-gate if ((rel_entsize == 0) || 3030Sstevel@tonic-gate (rel_entsize > p_scns->p_shdr.sh_size)) { 3040Sstevel@tonic-gate rel_entsize = gelf_fsize(elf_file, ELF_T_RELA, 1, 3050Sstevel@tonic-gate EV_CURRENT); 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate no_entries = reloc_size / rel_entsize; 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate no_syms = sym_size / gelf_fsize(elf_file, ELF_T_SYM, 1, EV_CURRENT); 3100Sstevel@tonic-gate while (no_entries--) { 3110Sstevel@tonic-gate (void) gelf_getrela(rdata, ndx, &rela); 3120Sstevel@tonic-gate /* LINTED */ 3130Sstevel@tonic-gate type = (int)GELF_R_TYPE(rela.r_info); 3140Sstevel@tonic-gate /* LINTED */ 3150Sstevel@tonic-gate symid = (int)GELF_R_SYM(rela.r_info); 3160Sstevel@tonic-gate /* LINTED */ 3170Sstevel@tonic-gate if ((symid > (no_syms - 1)) || (symid < 0)) { 3180Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: invalid symbol table " 3190Sstevel@tonic-gate "offset - %d - in %s\n", prog_name, filename, 3200Sstevel@tonic-gate symid, p_scns->scn_name); 3210Sstevel@tonic-gate ndx++; 3220Sstevel@tonic-gate continue; 3230Sstevel@tonic-gate } 3240Sstevel@tonic-gate (void) gelf_getsym(sym_data, symid, &sym); 3250Sstevel@tonic-gate sym_name = (char *)elf_strptr(elf_file, 3264734Sab196087 reloc_symtab->p_shdr.sh_link, sym.st_name); 3270Sstevel@tonic-gate if (sym_name == NULL) 3280Sstevel@tonic-gate sym_name = (char *)UNKNOWN; 3290Sstevel@tonic-gate if (r_flag && rn_flag) { 3300Sstevel@tonic-gate if (strcmp(name, p_scns->scn_name) != 0) { 3310Sstevel@tonic-gate ndx++; 3320Sstevel@tonic-gate continue; 3330Sstevel@tonic-gate } 3340Sstevel@tonic-gate if (!n_title) { 3350Sstevel@tonic-gate (void) printf("\n%s:\n", p_scns->scn_name); 3360Sstevel@tonic-gate (void) printf("%-*s%-*s%-*s%s\n\n", 3370Sstevel@tonic-gate 12 + adj, "Offset", 22, "Symndx", 3380Sstevel@tonic-gate 16, "Type", "Addend"); 3390Sstevel@tonic-gate n_title = 1; 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate } 3420Sstevel@tonic-gate if (d_flag) { 3430Sstevel@tonic-gate if (!d_hi) 3440Sstevel@tonic-gate d_hi = d_low; 3450Sstevel@tonic-gate if ((symid < d_low) || (symid > d_hi)) { 3460Sstevel@tonic-gate ndx++; 3470Sstevel@tonic-gate continue; 3480Sstevel@tonic-gate } 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate (void) printf("%-#*llx", 12 + adj, EC_XWORD(rela.r_offset)); 3520Sstevel@tonic-gate if (!v_flag) { 3530Sstevel@tonic-gate (void) printf("%-22d%-18d", symid, type); 3540Sstevel@tonic-gate } else { 3554734Sab196087 Conv_inv_buf_t inv_buf; 3564734Sab196087 3570Sstevel@tonic-gate if (strlen(sym_name)) { 3580Sstevel@tonic-gate size_t len = strlen(sym_name) + 1; 3590Sstevel@tonic-gate char tmpstr[10]; 3600Sstevel@tonic-gate if (len > 22) { 3610Sstevel@tonic-gate (void) sprintf(tmpstr, "%%-%ds", 3624734Sab196087 /* LINTED */ 3634734Sab196087 (int)len); 3642352Sab196087 /*LINTED: E_SEC_PRINTF_VAR_FMT*/ 3650Sstevel@tonic-gate (void) printf(tmpstr, sym_name); 3660Sstevel@tonic-gate } else 3670Sstevel@tonic-gate (void) printf("%-22s", sym_name); 3681976Sab196087 } else { 3690Sstevel@tonic-gate (void) printf("%-22d", symid); 3701976Sab196087 } 3711976Sab196087 (void) printf("%-20s", 3724734Sab196087 conv_reloc_type(p_ehdr->e_machine, 3734734Sab196087 type, DUMP_CONVFMT, &inv_buf)); 3740Sstevel@tonic-gate } 3750Sstevel@tonic-gate (void) printf("%lld\n", EC_SXWORD(rela.r_addend)); 3760Sstevel@tonic-gate ndx++; 3770Sstevel@tonic-gate } 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate /* 3810Sstevel@tonic-gate * Print relocation data of type SHT_REL. 3820Sstevel@tonic-gate * If d_flag, print data corresponding only to 3830Sstevel@tonic-gate * the section or range of sections specified. 3840Sstevel@tonic-gate * If n_flag, print data corresponding only to 3850Sstevel@tonic-gate * the named section. 3860Sstevel@tonic-gate */ 3870Sstevel@tonic-gate static void 3880Sstevel@tonic-gate print_rel(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data, 3890Sstevel@tonic-gate GElf_Ehdr *p_ehdr, size_t reloc_size, size_t sym_size, char *filename, 3900Sstevel@tonic-gate SCNTAB *reloc_symtab) 3910Sstevel@tonic-gate { 3920Sstevel@tonic-gate GElf_Rel rel; 3930Sstevel@tonic-gate GElf_Sym sym; 3940Sstevel@tonic-gate size_t no_entries; 3950Sstevel@tonic-gate size_t rel_entsize; 3960Sstevel@tonic-gate int type, symid; 3970Sstevel@tonic-gate size_t no_syms; 3980Sstevel@tonic-gate static int n_title = 0; 3990Sstevel@tonic-gate int ndx = 0; 4000Sstevel@tonic-gate char *sym_name; 4010Sstevel@tonic-gate int adj = 0; 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate if (gelf_getclass(elf_file) == ELFCLASS64) 4041618Srie adj = 8; 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate rel_entsize = p_scns->p_shdr.sh_entsize; 4070Sstevel@tonic-gate if ((rel_entsize == 0) || 4080Sstevel@tonic-gate (rel_entsize > p_scns->p_shdr.sh_size)) { 4090Sstevel@tonic-gate rel_entsize = gelf_fsize(elf_file, ELF_T_REL, 1, 4100Sstevel@tonic-gate EV_CURRENT); 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate no_entries = reloc_size / rel_entsize; 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate no_syms = sym_size / gelf_fsize(elf_file, ELF_T_SYM, 1, EV_CURRENT); 4150Sstevel@tonic-gate while (no_entries--) { 4160Sstevel@tonic-gate (void) gelf_getrel(rdata, ndx, &rel); 4170Sstevel@tonic-gate /* LINTED */ 4180Sstevel@tonic-gate type = (int)GELF_R_TYPE(rel.r_info); 4190Sstevel@tonic-gate /* LINTED */ 4200Sstevel@tonic-gate symid = (int)GELF_R_SYM(rel.r_info); 4210Sstevel@tonic-gate /* LINTED */ 4220Sstevel@tonic-gate if ((symid > (no_syms - 1)) || (symid < 0)) { 4230Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: invalid symbol table " 4240Sstevel@tonic-gate "offset - %d - in %s\n", prog_name, filename, 4250Sstevel@tonic-gate symid, p_scns->scn_name); 4260Sstevel@tonic-gate ndx++; 4270Sstevel@tonic-gate continue; 4280Sstevel@tonic-gate } 4290Sstevel@tonic-gate (void) gelf_getsym(sym_data, symid, &sym); 4300Sstevel@tonic-gate sym_name = (char *)elf_strptr(elf_file, 4314734Sab196087 reloc_symtab->p_shdr.sh_link, sym.st_name); 4320Sstevel@tonic-gate if (sym_name == NULL) 4330Sstevel@tonic-gate sym_name = (char *)UNKNOWN; 4340Sstevel@tonic-gate if (r_flag && rn_flag) { 4350Sstevel@tonic-gate if (strcmp(name, p_scns->scn_name) != 0) { 4360Sstevel@tonic-gate ndx++; 4370Sstevel@tonic-gate continue; 4380Sstevel@tonic-gate } 4390Sstevel@tonic-gate if (!n_title) { 4400Sstevel@tonic-gate (void) printf("\n%s:\n", p_scns->scn_name); 4410Sstevel@tonic-gate (void) printf("%-*s%-*s%s\n\n", 4420Sstevel@tonic-gate 12 + adj, "Offset", 20, "Symndx", "Type"); 4430Sstevel@tonic-gate n_title = 1; 4440Sstevel@tonic-gate } 4450Sstevel@tonic-gate } 4460Sstevel@tonic-gate if (d_flag) { 4470Sstevel@tonic-gate if (!d_hi) 4480Sstevel@tonic-gate d_hi = d_low; 4490Sstevel@tonic-gate if ((symid < d_low) || (symid > d_hi)) { 4500Sstevel@tonic-gate ndx++; 4510Sstevel@tonic-gate continue; 4520Sstevel@tonic-gate } 4530Sstevel@tonic-gate } 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate (void) printf("%-#*llx", 12 + adj, EC_ADDR(rel.r_offset)); 4560Sstevel@tonic-gate if (!v_flag) { 4570Sstevel@tonic-gate (void) printf("%-20d%-18d", symid, type); 4580Sstevel@tonic-gate } else { 4594734Sab196087 Conv_inv_buf_t inv_buf; 4604734Sab196087 4610Sstevel@tonic-gate if (strlen(sym_name)) 4620Sstevel@tonic-gate (void) printf("%-20s", sym_name); 4631976Sab196087 else { 4640Sstevel@tonic-gate (void) printf("%-20d", sym.st_name); 4651976Sab196087 } 4661976Sab196087 (void) printf("%-20s", 4674734Sab196087 conv_reloc_type(p_ehdr->e_machine, 4684734Sab196087 type, DUMP_CONVFMT, &inv_buf)); 4690Sstevel@tonic-gate } 4700Sstevel@tonic-gate (void) printf("\n"); 4710Sstevel@tonic-gate ndx++; 4720Sstevel@tonic-gate } 4730Sstevel@tonic-gate } 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate /* demangle C++ names */ 4760Sstevel@tonic-gate static char * 4770Sstevel@tonic-gate demangled_name(char *s) 4780Sstevel@tonic-gate { 4791618Srie static char *buf = NULL; 4807008Sab196087 const char *dn; 4811618Srie size_t len; 4820Sstevel@tonic-gate 4837008Sab196087 dn = conv_demangle_name(s); 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate /* 4860Sstevel@tonic-gate * If not demangled, just return the symbol name 4870Sstevel@tonic-gate */ 4880Sstevel@tonic-gate if (strcmp(s, dn) == 0) 4890Sstevel@tonic-gate return (s); 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate /* 4920Sstevel@tonic-gate * Demangled. Format it 4930Sstevel@tonic-gate */ 4940Sstevel@tonic-gate if (buf != NULL) 4950Sstevel@tonic-gate free(buf); 4960Sstevel@tonic-gate 4971618Srie len = strlen(dn) + strlen(s) + 4; 4981618Srie if ((buf = malloc(len)) == NULL) 4990Sstevel@tonic-gate return (s); 5000Sstevel@tonic-gate 5011618Srie (void) snprintf(buf, len, "%s\t[%s]", dn, s); 5020Sstevel@tonic-gate return (buf); 5030Sstevel@tonic-gate } 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate /* 5060Sstevel@tonic-gate * Print the symbol table. Input is an ELF file descriptor, a 5070Sstevel@tonic-gate * pointer to the symbol table SCNTAB structure, 5080Sstevel@tonic-gate * the number of symbols, a range of symbols to print, 5090Sstevel@tonic-gate * an index which is the number of the 5100Sstevel@tonic-gate * section in the file, and the filename. The number of sections, 5110Sstevel@tonic-gate * the range, and the index are set in 5120Sstevel@tonic-gate * dump_symbol_table, depending on whether -n or -T were set. 5130Sstevel@tonic-gate */ 5140Sstevel@tonic-gate static void 5150Sstevel@tonic-gate print_symtab(Elf *elf_file, SCNTAB *p_symtab, Elf_Data *sym_data, 5160Sstevel@tonic-gate long range, int index) 5170Sstevel@tonic-gate { 5180Sstevel@tonic-gate GElf_Sym sym; 5190Sstevel@tonic-gate int adj = 0; /* field adjustment for elf64 */ 5200Sstevel@tonic-gate Elf32_Word *symshndx = 0; 5210Sstevel@tonic-gate unsigned int nosymshndx = 0; 5224734Sab196087 Conv_inv_buf_t inv_buf; 5234734Sab196087 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate if (gelf_getclass(elf_file) == ELFCLASS64) 5261618Srie adj = 8; 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate while (range > 0) { 5290Sstevel@tonic-gate char *sym_name = (char *)0; 5300Sstevel@tonic-gate int type, bind; 5310Sstevel@tonic-gate int specsec; 5320Sstevel@tonic-gate unsigned int shndx; 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate (void) gelf_getsym(sym_data, index, &sym); 5350Sstevel@tonic-gate type = (int)GELF_ST_TYPE(sym.st_info); 5360Sstevel@tonic-gate bind = (int)GELF_ST_BIND(sym.st_info); 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate if ((sym.st_shndx == SHN_XINDEX) && 5390Sstevel@tonic-gate (symshndx == 0) && (nosymshndx == 0)) { 5400Sstevel@tonic-gate Elf_Scn *_scn; 5410Sstevel@tonic-gate GElf_Shdr _shdr; 5420Sstevel@tonic-gate size_t symscnndx; 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate symscnndx = elf_ndxscn(p_symtab->p_sd); 5450Sstevel@tonic-gate _scn = 0; 5460Sstevel@tonic-gate while ((_scn = elf_nextscn(elf_file, _scn)) != 0) { 5470Sstevel@tonic-gate if (gelf_getshdr(_scn, &_shdr) == 0) 5480Sstevel@tonic-gate break; 5490Sstevel@tonic-gate if ((_shdr.sh_type == SHT_SYMTAB_SHNDX) && 5500Sstevel@tonic-gate /* LINTED */ 5510Sstevel@tonic-gate (_shdr.sh_link == (GElf_Word)symscnndx)) { 5520Sstevel@tonic-gate Elf_Data *_data; 5530Sstevel@tonic-gate 5540Sstevel@tonic-gate if ((_data = elf_getdata(_scn, 0)) == 0) 5550Sstevel@tonic-gate continue; 5560Sstevel@tonic-gate 5570Sstevel@tonic-gate symshndx = (Elf32_Word *)_data->d_buf; 5580Sstevel@tonic-gate nosymshndx = 0; 5590Sstevel@tonic-gate break; 5600Sstevel@tonic-gate } 5610Sstevel@tonic-gate } 5620Sstevel@tonic-gate nosymshndx = 1; 5630Sstevel@tonic-gate } 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate if ((symshndx) && (sym.st_shndx == SHN_XINDEX)) { 5660Sstevel@tonic-gate shndx = symshndx[index]; 5670Sstevel@tonic-gate specsec = 0; 5680Sstevel@tonic-gate } else { 5690Sstevel@tonic-gate shndx = sym.st_shndx; 5700Sstevel@tonic-gate if ((sym.st_shndx == SHN_UNDEF) || 5710Sstevel@tonic-gate (sym.st_shndx >= SHN_LORESERVE)) 5720Sstevel@tonic-gate specsec = 1; 5730Sstevel@tonic-gate else 5740Sstevel@tonic-gate specsec = 0; 5750Sstevel@tonic-gate } 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate (void) printf("[%d]\t ", index++); 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate if (v_flag && (type == STT_SPARC_REGISTER)) { 5810Sstevel@tonic-gate /* 5820Sstevel@tonic-gate * The strings "REG_G1" through "REG_G7" are intended 5830Sstevel@tonic-gate * to be consistent with output from elfdump(1). 5840Sstevel@tonic-gate */ 5851976Sab196087 (void) printf("%-*s", 12 + adj, 5864734Sab196087 conv_sym_SPARC_value(sym.st_value, 5874734Sab196087 DUMP_CONVFMT, &inv_buf)); 5881976Sab196087 } else { 5890Sstevel@tonic-gate (void) printf("0x%-*llx", 10 + adj, 5900Sstevel@tonic-gate EC_ADDR(sym.st_value)); 5911976Sab196087 } 5920Sstevel@tonic-gate 5930Sstevel@tonic-gate (void) printf("%-*lld", 9 + adj, EC_XWORD(sym.st_size)); 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate if (!v_flag) { 5960Sstevel@tonic-gate (void) printf("%d\t\t%d\t%d\t%#x\t", 5970Sstevel@tonic-gate type, bind, (int)sym.st_other, (int)shndx); 5980Sstevel@tonic-gate } else { 5991976Sab196087 GElf_Ehdr p_ehdr; 6001976Sab196087 (void) gelf_getehdr(elf_file, &p_ehdr); 6011976Sab196087 (void) printf("%s\t", 6024734Sab196087 conv_sym_info_type(p_ehdr.e_machine, type, 6034734Sab196087 DUMP_CONVFMT, &inv_buf)); 6041976Sab196087 (void) printf("%s", 6054734Sab196087 conv_sym_info_bind(bind, DUMP_CONVFMT, &inv_buf)); 6060Sstevel@tonic-gate (void) printf("\t %d\t", EC_WORD(sym.st_other)); 6070Sstevel@tonic-gate 6084734Sab196087 if (specsec) 6094734Sab196087 (void) printf("%s", 6109273SAli.Bahrami@Sun.COM conv_sym_shndx(p_ehdr.e_ident[EI_OSABI], 6119273SAli.Bahrami@Sun.COM p_ehdr.e_machine, shndx, 6129273SAli.Bahrami@Sun.COM CONV_FMT_DECIMAL, &inv_buf)); 6134734Sab196087 else 6140Sstevel@tonic-gate (void) printf("%d", EC_WORD(shndx)); 6150Sstevel@tonic-gate (void) printf("\t"); 6160Sstevel@tonic-gate } 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate /* support machines where NULL-deref causes core dump */ 6190Sstevel@tonic-gate if (sym.st_name == 0) 6200Sstevel@tonic-gate sym_name = (char *)UNKNOWN; 6210Sstevel@tonic-gate else 6220Sstevel@tonic-gate if (C_flag) 6230Sstevel@tonic-gate sym_name = demangled_name( 6244734Sab196087 (char *)elf_strptr(elf_file, 6254734Sab196087 p_symtab->p_shdr.sh_link, 6264734Sab196087 sym.st_name)); 6270Sstevel@tonic-gate else 6280Sstevel@tonic-gate sym_name = (char *)elf_strptr(elf_file, 6294734Sab196087 p_symtab->p_shdr.sh_link, sym.st_name); 6300Sstevel@tonic-gate if (sym_name == NULL) 6310Sstevel@tonic-gate sym_name = (char *)UNKNOWN; 6320Sstevel@tonic-gate (void) printf("%s\n", sym_name); 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate range--; 6350Sstevel@tonic-gate } /* end while */ 6360Sstevel@tonic-gate } 6370Sstevel@tonic-gate 6380Sstevel@tonic-gate /* 6390Sstevel@tonic-gate * Print the section header table. Input is the SCNTAB structure, 6400Sstevel@tonic-gate * the number of sections, an index which is the number of the 6410Sstevel@tonic-gate * section in the file, and the filename. The values of the SCNTAB 6420Sstevel@tonic-gate * structure, the number of sections, and the index are set in 6430Sstevel@tonic-gate * dump_shdr depending on whether the -n or -d modifiers were set. 6440Sstevel@tonic-gate */ 6450Sstevel@tonic-gate static void 6460Sstevel@tonic-gate print_shdr(Elf *elf_file, SCNTAB *s, int num_scns, int index) 6470Sstevel@tonic-gate { 6480Sstevel@tonic-gate SCNTAB *p; 6490Sstevel@tonic-gate int num; 6500Sstevel@tonic-gate int field; 6511976Sab196087 GElf_Ehdr p_ehdr; 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate if (gelf_getclass(elf_file) == ELFCLASS64) 6541618Srie field = 21; 6550Sstevel@tonic-gate else 6560Sstevel@tonic-gate field = 13; 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate p = s; 6591976Sab196087 (void) gelf_getehdr(elf_file, &p_ehdr); 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate for (num = 0; num < num_scns; num++, p++) { 6620Sstevel@tonic-gate (void) printf("[%d]\t", index++); 6630Sstevel@tonic-gate if (!v_flag) { 6640Sstevel@tonic-gate (void) printf("%u\t%llu\t", 6654734Sab196087 EC_WORD(p->p_shdr.sh_type), 6664734Sab196087 EC_XWORD(p->p_shdr.sh_flags)); 6670Sstevel@tonic-gate } else { 6684734Sab196087 Conv_inv_buf_t inv_buf; 6694734Sab196087 6702352Sab196087 /*LINTED: E_SEC_PRINTF_VAR_FMT*/ 6719273SAli.Bahrami@Sun.COM (void) printf(conv_sec_type( 6729273SAli.Bahrami@Sun.COM p_ehdr.e_ident[EI_OSABI], p_ehdr.e_machine, 6734734Sab196087 p->p_shdr.sh_type, DUMP_CONVFMT, &inv_buf)); 6740Sstevel@tonic-gate (void) printf(" "); 6750Sstevel@tonic-gate 6760Sstevel@tonic-gate if (p->p_shdr.sh_flags & SHF_WRITE) 6770Sstevel@tonic-gate (void) printf("W"); 6780Sstevel@tonic-gate else 6790Sstevel@tonic-gate (void) printf("-"); 6800Sstevel@tonic-gate if (p->p_shdr.sh_flags & SHF_ALLOC) 6810Sstevel@tonic-gate (void) printf("A"); 6820Sstevel@tonic-gate else 6830Sstevel@tonic-gate (void) printf("-"); 6840Sstevel@tonic-gate if (p->p_shdr.sh_flags & SHF_EXECINSTR) 6850Sstevel@tonic-gate (void) printf("I"); 6860Sstevel@tonic-gate else 6870Sstevel@tonic-gate (void) printf("-"); 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate if (p->p_shdr.sh_flags & SHF_ORDERED) 6900Sstevel@tonic-gate (void) printf("O"); 6910Sstevel@tonic-gate if (p->p_shdr.sh_flags & SHF_EXCLUDE) 6920Sstevel@tonic-gate (void) printf("E"); 6930Sstevel@tonic-gate 6940Sstevel@tonic-gate (void) printf("\t"); 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate } 6970Sstevel@tonic-gate (void) printf("%-#*llx%-#*llx%-#*llx%s%s\n", 6984734Sab196087 field, EC_ADDR(p->p_shdr.sh_addr), 6994734Sab196087 field, EC_OFF(p->p_shdr.sh_offset), 7004734Sab196087 field, EC_XWORD(p->p_shdr.sh_size), 7014734Sab196087 /* compatibility: tab for elf32 */ 7024734Sab196087 (field == 13) ? "\t" : " ", p->scn_name); 7030Sstevel@tonic-gate 7040Sstevel@tonic-gate (void) printf("\t%u\t%u\t%-#*llx%-#*llx\n\n", 7054734Sab196087 EC_WORD(p->p_shdr.sh_link), 7064734Sab196087 EC_WORD(p->p_shdr.sh_info), 7074734Sab196087 field, EC_XWORD(p->p_shdr.sh_addralign), 7084734Sab196087 field, EC_XWORD(p->p_shdr.sh_entsize)); 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate } 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate /* 7130Sstevel@tonic-gate * Check that a range of numbers is valid. Input is 7140Sstevel@tonic-gate * a lower bound, an upper bound, a boundary condition, 7150Sstevel@tonic-gate * and the filename. Negative numbers and numbers greater 7160Sstevel@tonic-gate * than the bound are invalid. low must be smaller than hi. 7170Sstevel@tonic-gate * The returned integer is the number of items in the 7180Sstevel@tonic-gate * range if it is valid and -1 otherwise. 7190Sstevel@tonic-gate */ 7200Sstevel@tonic-gate static int 7210Sstevel@tonic-gate check_range(int low, int hi, size_t bound, char *filename) 7220Sstevel@tonic-gate { 7230Sstevel@tonic-gate if (((size_t)low > bound) || (low <= 0)) { 7240Sstevel@tonic-gate (void) fprintf(stderr, 7254734Sab196087 "%s: %s: number out of range, %d\n", 7264734Sab196087 prog_name, filename, low); 7270Sstevel@tonic-gate return (-1); 7280Sstevel@tonic-gate } 7290Sstevel@tonic-gate if (((size_t)hi > bound) || (hi < 0)) { 7300Sstevel@tonic-gate (void) fprintf(stderr, 7314734Sab196087 "%s: %s: number out of range, %d\n", 7324734Sab196087 prog_name, filename, hi); 7334734Sab196087 return (-1); 7340Sstevel@tonic-gate } 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate if (hi && (low > hi)) { 7370Sstevel@tonic-gate (void) fprintf(stderr, 7384734Sab196087 "%s: %s: invalid range, %d,%d\n", 7394734Sab196087 prog_name, filename, low, hi); 7400Sstevel@tonic-gate return (-1); 7410Sstevel@tonic-gate } 7420Sstevel@tonic-gate if (hi) 7430Sstevel@tonic-gate return (hi - low + 1); 7440Sstevel@tonic-gate else 7450Sstevel@tonic-gate return (1); 7460Sstevel@tonic-gate } 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate /* 7490Sstevel@tonic-gate * Print relocation information. Since this information is 7500Sstevel@tonic-gate * machine dependent, new sections must be added for each machine 7510Sstevel@tonic-gate * that is supported. Input is an ELF file descriptor, the ELF header, 7520Sstevel@tonic-gate * the SCNTAB structure, the number of sections, and a filename. 7530Sstevel@tonic-gate * Set up necessary information to print relocation information 7540Sstevel@tonic-gate * and call the appropriate print function depending on the 7550Sstevel@tonic-gate * type of relocation information. If the symbol table is 7560Sstevel@tonic-gate * absent, no relocation data is processed. Input is an 7570Sstevel@tonic-gate * ELF file descriptor, the ELF header, the SCNTAB structure, 7580Sstevel@tonic-gate * and the filename. Set range of d_flag and name if n_flag. 7590Sstevel@tonic-gate */ 7600Sstevel@tonic-gate static void 7610Sstevel@tonic-gate dump_reloc_table(Elf *elf_file, GElf_Ehdr *p_ehdr, 7620Sstevel@tonic-gate SCNTAB *p_scns, int num_scns, char *filename) 7630Sstevel@tonic-gate { 7640Sstevel@tonic-gate Elf_Data *rel_data; 7650Sstevel@tonic-gate Elf_Data *sym_data; 7660Sstevel@tonic-gate size_t sym_size; 7670Sstevel@tonic-gate size_t reloc_size; 7680Sstevel@tonic-gate SCNTAB *reloc_symtab; 7690Sstevel@tonic-gate SCNTAB *head_scns; 7700Sstevel@tonic-gate int r_title = 0; 7710Sstevel@tonic-gate int adj = 0; 7720Sstevel@tonic-gate size_t shnum; 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate if (gelf_getclass(elf_file) == ELFCLASS64) 7751618Srie adj = 8; 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate if ((!p_flag) && (!r_title)) { 7780Sstevel@tonic-gate (void) printf("\n **** RELOCATION INFORMATION ****\n"); 7790Sstevel@tonic-gate r_title = 1; 7800Sstevel@tonic-gate } 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate while (num_scns-- > 0) { 7830Sstevel@tonic-gate if ((p_scns->p_shdr.sh_type != SHT_RELA) && 7840Sstevel@tonic-gate (p_scns->p_shdr.sh_type != SHT_REL)) { 7850Sstevel@tonic-gate p_scns++; 7860Sstevel@tonic-gate continue; 7870Sstevel@tonic-gate } 7880Sstevel@tonic-gate 7890Sstevel@tonic-gate head_scns = p_head_scns; 7900Sstevel@tonic-gate 7919900SAli.Bahrami@Sun.COM if (elf_getshdrnum(elf_file, &shnum) == -1) { 7920Sstevel@tonic-gate (void) fprintf(stderr, 7939900SAli.Bahrami@Sun.COM "%s: %s: elf_getshdrnum failed: %s\n", 7944734Sab196087 prog_name, filename, elf_errmsg(-1)); 7950Sstevel@tonic-gate return; 7960Sstevel@tonic-gate } 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate if ((p_scns->p_shdr.sh_link == 0) || 7990Sstevel@tonic-gate /* LINTED */ 8000Sstevel@tonic-gate (p_scns->p_shdr.sh_link >= (GElf_Word)shnum)) { 8010Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: invalid sh_link field: " 8024734Sab196087 "section #: %d sh_link: %d\n", 8034734Sab196087 /* LINTED */ 8044734Sab196087 prog_name, filename, (int)elf_ndxscn(p_scns->p_sd), 8054734Sab196087 (int)p_scns->p_shdr.sh_link); 8060Sstevel@tonic-gate return; 8070Sstevel@tonic-gate } 8080Sstevel@tonic-gate head_scns += (p_scns->p_shdr.sh_link -1); 8090Sstevel@tonic-gate 8100Sstevel@tonic-gate if (head_scns->p_shdr.sh_type == SHT_SYMTAB) { 8110Sstevel@tonic-gate reloc_symtab = p_symtab; 8120Sstevel@tonic-gate } else if (head_scns->p_shdr.sh_type == SHT_DYNSYM) { 8130Sstevel@tonic-gate reloc_symtab = p_dynsym; 8140Sstevel@tonic-gate } else { 8150Sstevel@tonic-gate (void) fprintf(stderr, 8160Sstevel@tonic-gate "%s: %s: could not get symbol table\n", prog_name, filename); 8170Sstevel@tonic-gate return; 8180Sstevel@tonic-gate } 8190Sstevel@tonic-gate 8200Sstevel@tonic-gate sym_data = NULL; 8210Sstevel@tonic-gate sym_size = 0; 8220Sstevel@tonic-gate reloc_size = 0; 8230Sstevel@tonic-gate 8240Sstevel@tonic-gate if ((sym_data = elf_getdata(reloc_symtab->p_sd, NULL)) == NULL) { 8250Sstevel@tonic-gate (void) fprintf(stderr, 8260Sstevel@tonic-gate "%s: %s: no symbol table data\n", prog_name, filename); 8270Sstevel@tonic-gate return; 8280Sstevel@tonic-gate } 8290Sstevel@tonic-gate sym_size = sym_data->d_size; 8300Sstevel@tonic-gate 8310Sstevel@tonic-gate if (p_scns == NULL) { 8320Sstevel@tonic-gate (void) fprintf(stderr, 8330Sstevel@tonic-gate "%s: %s: no section table data\n", prog_name, filename); 8340Sstevel@tonic-gate return; 8350Sstevel@tonic-gate } 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate if (p_scns->p_shdr.sh_type == SHT_RELA) { 8380Sstevel@tonic-gate if (!n_flag && r_flag) 8390Sstevel@tonic-gate (void) printf("\n%s:\n", p_scns->scn_name); 8400Sstevel@tonic-gate if (!p_flag && (!n_flag && r_flag)) 8410Sstevel@tonic-gate (void) printf("%-*s%-*s%-*s%s\n\n", 8420Sstevel@tonic-gate 12 + adj, "Offset", 22, "Symndx", 8430Sstevel@tonic-gate 18, "Type", "Addend"); 8440Sstevel@tonic-gate if ((rel_data = elf_getdata(p_scns->p_sd, NULL)) == NULL) { 8450Sstevel@tonic-gate (void) fprintf(stderr, 8460Sstevel@tonic-gate "%s: %s: no relocation information\n", prog_name, filename); 8470Sstevel@tonic-gate return; 8480Sstevel@tonic-gate } 8490Sstevel@tonic-gate reloc_size = rel_data->d_size; 8500Sstevel@tonic-gate 8510Sstevel@tonic-gate if (n_flag) { 8520Sstevel@tonic-gate rn_flag = 1; 8530Sstevel@tonic-gate print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr, 8544734Sab196087 reloc_size, sym_size, filename, reloc_symtab); 8550Sstevel@tonic-gate } 8560Sstevel@tonic-gate if (d_flag) { 8570Sstevel@tonic-gate rn_flag = 0; 8580Sstevel@tonic-gate print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr, 8594734Sab196087 reloc_size, sym_size, filename, reloc_symtab); 8600Sstevel@tonic-gate } 8610Sstevel@tonic-gate if (!n_flag && !d_flag) 8620Sstevel@tonic-gate print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr, 8634734Sab196087 reloc_size, sym_size, filename, reloc_symtab); 8640Sstevel@tonic-gate } else { 8650Sstevel@tonic-gate if (p_scns->p_shdr.sh_type == SHT_REL) { 8660Sstevel@tonic-gate if (!n_flag && r_flag) 8670Sstevel@tonic-gate (void) printf("\n%s:\n", p_scns->scn_name); 8680Sstevel@tonic-gate if (!p_flag && (!n_flag && r_flag)) { 8690Sstevel@tonic-gate (void) printf("%-*s%-*s%s\n\n", 8700Sstevel@tonic-gate 12 + adj, "Offset", 20, "Symndx", "Type"); 8710Sstevel@tonic-gate } 8720Sstevel@tonic-gate if ((rel_data = elf_getdata(p_scns->p_sd, NULL)) 8730Sstevel@tonic-gate == NULL) { 8740Sstevel@tonic-gate (void) fprintf(stderr, 8750Sstevel@tonic-gate "%s: %s: no relocation information\n", prog_name, filename); 8760Sstevel@tonic-gate return; 8770Sstevel@tonic-gate } 8780Sstevel@tonic-gate reloc_size = rel_data->d_size; 8790Sstevel@tonic-gate if (n_flag) { 8800Sstevel@tonic-gate rn_flag = 1; 8810Sstevel@tonic-gate print_rel(elf_file, p_scns, rel_data, sym_data, 8824734Sab196087 p_ehdr, reloc_size, sym_size, 8834734Sab196087 filename, reloc_symtab); 8840Sstevel@tonic-gate } 8850Sstevel@tonic-gate if (d_flag) { 8860Sstevel@tonic-gate rn_flag = 0; 8870Sstevel@tonic-gate print_rel(elf_file, p_scns, rel_data, sym_data, 8884734Sab196087 p_ehdr, reloc_size, sym_size, 8894734Sab196087 filename, reloc_symtab); 8900Sstevel@tonic-gate } 8910Sstevel@tonic-gate if (!n_flag && !d_flag) 8920Sstevel@tonic-gate print_rel(elf_file, p_scns, rel_data, sym_data, 8934734Sab196087 p_ehdr, reloc_size, sym_size, 8944734Sab196087 filename, reloc_symtab); 8950Sstevel@tonic-gate } 8960Sstevel@tonic-gate } 8970Sstevel@tonic-gate p_scns++; 8980Sstevel@tonic-gate } 8990Sstevel@tonic-gate } 9000Sstevel@tonic-gate 9010Sstevel@tonic-gate /* 9020Sstevel@tonic-gate * Print out the string tables. Input is an opened ELF file, 9030Sstevel@tonic-gate * the SCNTAB structure, the number of sections, and the filename. 9040Sstevel@tonic-gate * Since there can be more than one string table, all sections are 9050Sstevel@tonic-gate * examined and any with the correct type are printed out. 9060Sstevel@tonic-gate */ 9070Sstevel@tonic-gate static void 9080Sstevel@tonic-gate dump_string_table(SCNTAB *s, int num_scns) 9090Sstevel@tonic-gate { 9100Sstevel@tonic-gate size_t section_size; 9110Sstevel@tonic-gate unsigned char *strtab; 9120Sstevel@tonic-gate int beg_of_string; 9130Sstevel@tonic-gate int counter = 0; 9140Sstevel@tonic-gate int str_off; 9150Sstevel@tonic-gate int i; 9160Sstevel@tonic-gate 9170Sstevel@tonic-gate if (!p_flag) { 9180Sstevel@tonic-gate (void) printf("\n **** STRING TABLE INFORMATION ****\n"); 9190Sstevel@tonic-gate } 9200Sstevel@tonic-gate 9210Sstevel@tonic-gate for (i = 0; i < num_scns; i++, s++) { 9220Sstevel@tonic-gate if (s->p_shdr.sh_type != SHT_STRTAB) 9230Sstevel@tonic-gate continue; 9240Sstevel@tonic-gate 9250Sstevel@tonic-gate str_off = 0; 9260Sstevel@tonic-gate 9270Sstevel@tonic-gate if (!p_flag) { 9280Sstevel@tonic-gate (void) printf("\n%s:\n", s->scn_name); 9290Sstevel@tonic-gate (void) printf(" <offset> \tName\n"); 9300Sstevel@tonic-gate } 9310Sstevel@tonic-gate section_size = 0; 9320Sstevel@tonic-gate if ((strtab = (unsigned char *) 9330Sstevel@tonic-gate get_scndata(s->p_sd, §ion_size)) == NULL) { 9340Sstevel@tonic-gate continue; 9350Sstevel@tonic-gate } 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate if (section_size != 0) { 9380Sstevel@tonic-gate (void) printf(" <%d> \t", str_off); 9390Sstevel@tonic-gate beg_of_string = 0; 9400Sstevel@tonic-gate while (section_size--) { 9410Sstevel@tonic-gate unsigned char c = *strtab++; 9420Sstevel@tonic-gate 9430Sstevel@tonic-gate if (beg_of_string) { 9440Sstevel@tonic-gate (void) printf(" <%d> \t", str_off); 9450Sstevel@tonic-gate counter++; 9460Sstevel@tonic-gate beg_of_string = 0; 9470Sstevel@tonic-gate } 9480Sstevel@tonic-gate str_off++; 9490Sstevel@tonic-gate switch (c) { 9500Sstevel@tonic-gate case '\0': 9510Sstevel@tonic-gate (void) printf("\n"); 9520Sstevel@tonic-gate beg_of_string = 1; 9530Sstevel@tonic-gate break; 9540Sstevel@tonic-gate default: 9550Sstevel@tonic-gate (void) putchar(c); 9560Sstevel@tonic-gate } 9570Sstevel@tonic-gate } 9580Sstevel@tonic-gate } 9590Sstevel@tonic-gate } 9600Sstevel@tonic-gate (void) printf("\n"); 9610Sstevel@tonic-gate } 9620Sstevel@tonic-gate 9630Sstevel@tonic-gate /* 9640Sstevel@tonic-gate * Print the symbol table. This function does not print the contents 9650Sstevel@tonic-gate * of the symbol table but sets up the parameters and then calls 9660Sstevel@tonic-gate * print_symtab to print the symbols. Calling another function to print 9670Sstevel@tonic-gate * the symbols allows both -T and -n to work correctly 9680Sstevel@tonic-gate * simultaneously. Input is an opened ELF file, a pointer to the 9690Sstevel@tonic-gate * symbol table SCNTAB structure, and the filename. 9700Sstevel@tonic-gate * Set the range of symbols to print if T_flag, and set 9710Sstevel@tonic-gate * name of symbol to print if n_flag. 9720Sstevel@tonic-gate */ 9730Sstevel@tonic-gate static void 9740Sstevel@tonic-gate dump_symbol_table(Elf *elf_file, SCNTAB *p_symtab, char *filename) 9750Sstevel@tonic-gate { 9760Sstevel@tonic-gate Elf_Data *sym_data; 9770Sstevel@tonic-gate GElf_Sym T_range, n_range; /* for use with -T and -n */ 9780Sstevel@tonic-gate size_t count = 0; 9790Sstevel@tonic-gate size_t sym_size; 9800Sstevel@tonic-gate int index = 1; 9810Sstevel@tonic-gate int found_it = 0; 9820Sstevel@tonic-gate int i; 9830Sstevel@tonic-gate int adj = 0; /* field adjustment for elf64 */ 9840Sstevel@tonic-gate 9850Sstevel@tonic-gate if (gelf_getclass(elf_file) == ELFCLASS64) 9861618Srie adj = 8; 9870Sstevel@tonic-gate 9880Sstevel@tonic-gate if (p_symtab == NULL) { 9890Sstevel@tonic-gate (void) fprintf(stderr, 9900Sstevel@tonic-gate "%s: %s: could not get symbol table\n", prog_name, filename); 9910Sstevel@tonic-gate return; 9920Sstevel@tonic-gate } 9930Sstevel@tonic-gate 9940Sstevel@tonic-gate /* get symbol table data */ 9950Sstevel@tonic-gate sym_data = NULL; 9960Sstevel@tonic-gate sym_size = 0; 9970Sstevel@tonic-gate if ((sym_data = 9980Sstevel@tonic-gate elf_getdata(p_symtab->p_sd, NULL)) == NULL) { 9990Sstevel@tonic-gate (void) printf("\n%s:\n", p_symtab->scn_name); 10000Sstevel@tonic-gate (void) printf("No symbol table data\n"); 10010Sstevel@tonic-gate return; 10020Sstevel@tonic-gate } 10030Sstevel@tonic-gate sym_size = sym_data->d_size; 10040Sstevel@tonic-gate 10050Sstevel@tonic-gate count = sym_size / p_symtab->p_shdr.sh_entsize; 10060Sstevel@tonic-gate 10070Sstevel@tonic-gate if (n_flag && t_flag && !T_flag) { 10080Sstevel@tonic-gate /* LINTED */ 10090Sstevel@tonic-gate for (i = 1; i < count; i++) { 10100Sstevel@tonic-gate (void) gelf_getsym(sym_data, i, &n_range); 10110Sstevel@tonic-gate if (strcmp(name, (char *) 10120Sstevel@tonic-gate elf_strptr(elf_file, 10130Sstevel@tonic-gate p_symtab->p_shdr.sh_link, 10140Sstevel@tonic-gate n_range.st_name)) != 0) { 10150Sstevel@tonic-gate continue; 10160Sstevel@tonic-gate } else { 10170Sstevel@tonic-gate found_it = 1; 10180Sstevel@tonic-gate if (!p_flag) { 10190Sstevel@tonic-gate (void) printf( 10200Sstevel@tonic-gate "\n ***** SYMBOL TABLE INFORMATION *****\n"); 10210Sstevel@tonic-gate (void) printf( 10220Sstevel@tonic-gate "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName", 10234734Sab196087 12 + adj, "Value", 9 + adj, "Size"); 10240Sstevel@tonic-gate } 10250Sstevel@tonic-gate (void) printf("\n%s:\n", p_symtab->scn_name); 10260Sstevel@tonic-gate print_symtab(elf_file, p_symtab, sym_data, 10270Sstevel@tonic-gate 1, i); 10280Sstevel@tonic-gate } 10290Sstevel@tonic-gate } /* end for */ 10300Sstevel@tonic-gate if (!found_it) { 10310Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: %s not found\n", 10324734Sab196087 prog_name, filename, name); 10330Sstevel@tonic-gate } 10340Sstevel@tonic-gate } else if (T_flag) { 10350Sstevel@tonic-gate T_num = check_range(T_low, T_hi, count, filename); 10360Sstevel@tonic-gate if (T_num < 0) 10370Sstevel@tonic-gate return; 10380Sstevel@tonic-gate 10390Sstevel@tonic-gate (void) gelf_getsym(sym_data, T_low-1, &T_range); 10400Sstevel@tonic-gate index = T_low; 10410Sstevel@tonic-gate 10420Sstevel@tonic-gate if (!p_flag) { 10430Sstevel@tonic-gate (void) printf( 10440Sstevel@tonic-gate "\n ***** SYMBOL TABLE INFORMATION *****\n"); 10450Sstevel@tonic-gate (void) printf( 10460Sstevel@tonic-gate "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName", 10470Sstevel@tonic-gate 12 + adj, "Value", 9 + adj, "Size"); 10480Sstevel@tonic-gate } 10490Sstevel@tonic-gate (void) printf("\n%s:\n", p_symtab->scn_name); 10500Sstevel@tonic-gate print_symtab(elf_file, p_symtab, sym_data, T_num, index); 10510Sstevel@tonic-gate } else { 10520Sstevel@tonic-gate if (!p_flag) { 10530Sstevel@tonic-gate (void) printf( 10540Sstevel@tonic-gate "\n ***** SYMBOL TABLE INFORMATION *****\n"); 10550Sstevel@tonic-gate (void) printf( 10560Sstevel@tonic-gate "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName", 10570Sstevel@tonic-gate 12 + adj, "Value", 9 + adj, "Size"); 10580Sstevel@tonic-gate } 10590Sstevel@tonic-gate (void) printf("\n%s:\n", p_symtab->scn_name); 10600Sstevel@tonic-gate print_symtab(elf_file, p_symtab, sym_data, count-1, 1); 10610Sstevel@tonic-gate } 10620Sstevel@tonic-gate } 10630Sstevel@tonic-gate 10641698Sab196087 10651698Sab196087 /* 10660Sstevel@tonic-gate * Print dynamic linking information. Input is an ELF 10670Sstevel@tonic-gate * file descriptor, the SCNTAB structure, the number of 10680Sstevel@tonic-gate * sections, and the filename. 10690Sstevel@tonic-gate */ 10700Sstevel@tonic-gate static void 10710Sstevel@tonic-gate dump_dynamic(Elf *elf_file, SCNTAB *p_scns, int num_scns, char *filename) 10720Sstevel@tonic-gate { 10732352Sab196087 #define pdyn_Fmtptr "%#llx" 10741698Sab196087 10750Sstevel@tonic-gate Elf_Data *dyn_data; 10760Sstevel@tonic-gate GElf_Dyn p_dyn; 10770Sstevel@tonic-gate GElf_Phdr p_phdr; 10780Sstevel@tonic-gate GElf_Ehdr p_ehdr; 10790Sstevel@tonic-gate int index = 1; 10800Sstevel@tonic-gate int lib_scns = num_scns; 10810Sstevel@tonic-gate SCNTAB *l_scns = p_scns; 10820Sstevel@tonic-gate int header_num = 0; 10832352Sab196087 const char *str; 10842352Sab196087 10852352Sab196087 (void) gelf_getehdr(elf_file, &p_ehdr); 10860Sstevel@tonic-gate 10870Sstevel@tonic-gate if (!p_flag) 10880Sstevel@tonic-gate (void) printf("\n **** DYNAMIC SECTION INFORMATION ****\n"); 10890Sstevel@tonic-gate 10900Sstevel@tonic-gate for (; num_scns > 0; num_scns--, p_scns++) { 10910Sstevel@tonic-gate GElf_Word link; 10920Sstevel@tonic-gate int ii; 10930Sstevel@tonic-gate 10940Sstevel@tonic-gate 10950Sstevel@tonic-gate if (p_scns->p_shdr.sh_type != SHT_DYNAMIC) 10960Sstevel@tonic-gate continue; 10970Sstevel@tonic-gate 10980Sstevel@tonic-gate if (!p_flag) { 10990Sstevel@tonic-gate (void) printf("%s:\n", p_scns->scn_name); 11000Sstevel@tonic-gate (void) printf("[INDEX]\tTag Value\n"); 11010Sstevel@tonic-gate } 11020Sstevel@tonic-gate 11030Sstevel@tonic-gate if ((dyn_data = elf_getdata(p_scns->p_sd, NULL)) == 0) { 11040Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: no data in " 11050Sstevel@tonic-gate "%s section\n", prog_name, filename, 11060Sstevel@tonic-gate p_scns->scn_name); 11070Sstevel@tonic-gate return; 11080Sstevel@tonic-gate } 11090Sstevel@tonic-gate 11100Sstevel@tonic-gate link = p_scns->p_shdr.sh_link; 11110Sstevel@tonic-gate ii = 0; 11120Sstevel@tonic-gate 11130Sstevel@tonic-gate (void) gelf_getdyn(dyn_data, ii++, &p_dyn); 11140Sstevel@tonic-gate while (p_dyn.d_tag != DT_NULL) { 11154734Sab196087 union { 11164734Sab196087 Conv_inv_buf_t inv; 11174734Sab196087 Conv_dyn_flag_buf_t dyn_flag; 11184734Sab196087 Conv_dyn_flag1_buf_t dyn_flag1; 11194734Sab196087 Conv_dyn_feature1_buf_t dyn_feature1; 11204734Sab196087 Conv_dyn_posflag1_buf_t dyn_posflag1; 11214734Sab196087 } conv_buf; 11224734Sab196087 11231976Sab196087 (void) printf("[%d]\t%-15.15s ", index++, 11249273SAli.Bahrami@Sun.COM conv_dyn_tag(p_dyn.d_tag, 11259273SAli.Bahrami@Sun.COM p_ehdr.e_ident[EI_OSABI], p_ehdr.e_machine, 11264734Sab196087 DUMP_CONVFMT, &conv_buf.inv)); 11270Sstevel@tonic-gate 11281698Sab196087 /* 11291698Sab196087 * It would be nice to use a table driven loop 11301698Sab196087 * here, but the address space is too sparse 11311698Sab196087 * and irregular. A switch is simple and robust. 11321698Sab196087 */ 11330Sstevel@tonic-gate switch (p_dyn.d_tag) { 11340Sstevel@tonic-gate /* 11351976Sab196087 * Items with an address value 11360Sstevel@tonic-gate */ 11371976Sab196087 case DT_PLTGOT: 11381976Sab196087 case DT_HASH: 11391976Sab196087 case DT_STRTAB: 11401976Sab196087 case DT_RELA: 11411976Sab196087 case DT_SYMTAB: 11421976Sab196087 case DT_INIT: 11431976Sab196087 case DT_FINI: 11441976Sab196087 case DT_REL: 11451976Sab196087 case DT_DEBUG: 11461976Sab196087 case DT_TEXTREL: 11471976Sab196087 case DT_JMPREL: 11481976Sab196087 case DT_INIT_ARRAY: 11491976Sab196087 case DT_FINI_ARRAY: 11501976Sab196087 case DT_INIT_ARRAYSZ: 11511976Sab196087 case DT_FINI_ARRAYSZ: 11521976Sab196087 case DT_PREINIT_ARRAY: 11531976Sab196087 case DT_PREINIT_ARRAYSZ: 11541976Sab196087 case DT_SUNW_RTLDINF: 11551976Sab196087 case DT_SUNW_CAP: 115611827SRod.Evans@Sun.COM case DT_SUNW_CAPINFO: 115711827SRod.Evans@Sun.COM case DT_SUNW_CAPCHAIN: 11582766Sab196087 case DT_SUNW_SYMTAB: 11593492Sab196087 case DT_SUNW_SYMSORT: 11603492Sab196087 case DT_SUNW_TLSSORT: 11611976Sab196087 case DT_PLTPAD: 11621976Sab196087 case DT_MOVETAB: 11631976Sab196087 case DT_SYMINFO: 11641976Sab196087 case DT_RELACOUNT: 11651976Sab196087 case DT_RELCOUNT: 11661976Sab196087 case DT_VERSYM: 11671976Sab196087 case DT_VERDEF: 11681976Sab196087 case DT_VERDEFNUM: 11691976Sab196087 case DT_VERNEED: 11701976Sab196087 (void) printf(pdyn_Fmtptr, 11714734Sab196087 EC_ADDR(p_dyn.d_un.d_ptr)); 11720Sstevel@tonic-gate break; 11730Sstevel@tonic-gate 11740Sstevel@tonic-gate /* 11751976Sab196087 * Items with a string value 11760Sstevel@tonic-gate */ 11771976Sab196087 case DT_NEEDED: 11781976Sab196087 case DT_SONAME: 11791976Sab196087 case DT_RPATH: 11801976Sab196087 case DT_RUNPATH: 11811976Sab196087 case DT_SUNW_AUXILIARY: 11821976Sab196087 case DT_SUNW_FILTER: 11831976Sab196087 case DT_CONFIG: 11841976Sab196087 case DT_DEPAUDIT: 11851976Sab196087 case DT_AUDIT: 11861976Sab196087 case DT_AUXILIARY: 11871976Sab196087 case DT_USED: 11881976Sab196087 case DT_FILTER: 11891976Sab196087 if (v_flag) { /* Look up the string */ 11901976Sab196087 str = (char *)elf_strptr(elf_file, link, 11914734Sab196087 p_dyn.d_un.d_ptr); 11921976Sab196087 if (!(str && *str)) 11931976Sab196087 str = (char *)UNKNOWN; 11941976Sab196087 (void) printf("%s", str); 11951976Sab196087 } else { /* Show the address */ 11961976Sab196087 (void) printf(pdyn_Fmtptr, 11974734Sab196087 EC_ADDR(p_dyn.d_un.d_ptr)); 11981976Sab196087 } 11990Sstevel@tonic-gate break; 12000Sstevel@tonic-gate 12010Sstevel@tonic-gate /* 12021976Sab196087 * Items with a literal value 12030Sstevel@tonic-gate */ 12041976Sab196087 case DT_PLTRELSZ: 12051976Sab196087 case DT_RELASZ: 12061976Sab196087 case DT_RELAENT: 12071976Sab196087 case DT_STRSZ: 12081976Sab196087 case DT_SYMENT: 12091976Sab196087 case DT_RELSZ: 12101976Sab196087 case DT_RELENT: 12111976Sab196087 case DT_PLTREL: 12121976Sab196087 case DT_BIND_NOW: 12131976Sab196087 case DT_CHECKSUM: 12141976Sab196087 case DT_PLTPADSZ: 12151976Sab196087 case DT_MOVEENT: 12161976Sab196087 case DT_MOVESZ: 12171976Sab196087 case DT_SYMINSZ: 12181976Sab196087 case DT_SYMINENT: 12191976Sab196087 case DT_VERNEEDNUM: 12201976Sab196087 case DT_SPARC_REGISTER: 12212766Sab196087 case DT_SUNW_SYMSZ: 12223492Sab196087 case DT_SUNW_SORTENT: 12233492Sab196087 case DT_SUNW_SYMSORTSZ: 12243492Sab196087 case DT_SUNW_TLSSORTSZ: 12253850Sab196087 case DT_SUNW_STRPAD: 122611827SRod.Evans@Sun.COM case DT_SUNW_CAPCHAINENT: 122711827SRod.Evans@Sun.COM case DT_SUNW_CAPCHAINSZ: 12281976Sab196087 (void) printf(pdyn_Fmtptr, 12294734Sab196087 EC_XWORD(p_dyn.d_un.d_val)); 12300Sstevel@tonic-gate break; 12310Sstevel@tonic-gate 12320Sstevel@tonic-gate /* 12336206Sab196087 * Integer items that are bitmasks, or which 12346206Sab196087 * can be otherwise formatted in symbolic form. 12350Sstevel@tonic-gate */ 12361976Sab196087 case DT_FLAGS: 12371976Sab196087 case DT_FEATURE_1: 12381976Sab196087 case DT_POSFLAG_1: 12391976Sab196087 case DT_FLAGS_1: 12406206Sab196087 case DT_SUNW_LDMACH: 12412352Sab196087 str = NULL; 12422352Sab196087 if (v_flag) { 12432352Sab196087 switch (p_dyn.d_tag) { 12442352Sab196087 case DT_FLAGS: 12452352Sab196087 str = conv_dyn_flag( 12464734Sab196087 p_dyn.d_un.d_val, 12474734Sab196087 DUMP_CONVFMT, 12484734Sab196087 &conv_buf.dyn_flag); 12494734Sab196087 break; 12502352Sab196087 case DT_FEATURE_1: 12512352Sab196087 str = conv_dyn_feature1( 12524734Sab196087 p_dyn.d_un.d_val, 12534734Sab196087 DUMP_CONVFMT, 12544734Sab196087 &conv_buf.dyn_feature1); 12552352Sab196087 break; 12562352Sab196087 case DT_POSFLAG_1: 12572352Sab196087 str = conv_dyn_posflag1( 12584734Sab196087 p_dyn.d_un.d_val, 12594734Sab196087 DUMP_CONVFMT, 12604734Sab196087 &conv_buf.dyn_posflag1); 12612352Sab196087 break; 12622352Sab196087 case DT_FLAGS_1: 12632352Sab196087 str = conv_dyn_flag1( 12645088Sab196087 p_dyn.d_un.d_val, 0, 12654734Sab196087 &conv_buf.dyn_flag1); 12662352Sab196087 break; 12676206Sab196087 case DT_SUNW_LDMACH: 12686206Sab196087 str = conv_ehdr_mach( 12696206Sab196087 p_dyn.d_un.d_val, 0, 12706206Sab196087 &conv_buf.inv); 12716206Sab196087 break; 12722352Sab196087 } 12732352Sab196087 } 12742352Sab196087 if (str) { /* Show as string */ 12752352Sab196087 (void) printf("%s", str); 12762352Sab196087 } else { /* Numeric form */ 12772352Sab196087 (void) printf(pdyn_Fmtptr, 12784734Sab196087 EC_ADDR(p_dyn.d_un.d_ptr)); 12792352Sab196087 } 12800Sstevel@tonic-gate break; 12810Sstevel@tonic-gate 12820Sstevel@tonic-gate /* 12831976Sab196087 * Depreciated items with a literal value 12840Sstevel@tonic-gate */ 12851976Sab196087 case DT_DEPRECATED_SPARC_REGISTER: 12861976Sab196087 (void) printf(pdyn_Fmtptr 12874734Sab196087 " (deprecated value)", 12884734Sab196087 EC_XWORD(p_dyn.d_un.d_val)); 12890Sstevel@tonic-gate break; 12901976Sab196087 12911976Sab196087 /* Ignored items */ 12921976Sab196087 case DT_SYMBOLIC: 12931976Sab196087 (void) printf("(ignored)"); 12940Sstevel@tonic-gate break; 12950Sstevel@tonic-gate } 12960Sstevel@tonic-gate (void) printf("\n"); 12970Sstevel@tonic-gate (void) gelf_getdyn(dyn_data, ii++, &p_dyn); 12980Sstevel@tonic-gate } 12990Sstevel@tonic-gate } 13000Sstevel@tonic-gate 13010Sstevel@tonic-gate /* 13020Sstevel@tonic-gate * Check for existence of static shared library information. 13030Sstevel@tonic-gate */ 13040Sstevel@tonic-gate while (header_num < p_ehdr.e_phnum) { 13050Sstevel@tonic-gate (void) gelf_getphdr(elf_file, header_num, &p_phdr); 13060Sstevel@tonic-gate if (p_phdr.p_type == PT_SHLIB) { 13070Sstevel@tonic-gate while (--lib_scns > 0) { 13080Sstevel@tonic-gate if (strcmp(l_scns->scn_name, ".lib") == 0) { 13090Sstevel@tonic-gate print_static(l_scns, filename); 13100Sstevel@tonic-gate } 13110Sstevel@tonic-gate l_scns++; 13120Sstevel@tonic-gate } 13130Sstevel@tonic-gate } 13140Sstevel@tonic-gate header_num++; 13150Sstevel@tonic-gate } 13162352Sab196087 #undef pdyn_Fmtptr 13170Sstevel@tonic-gate } 13180Sstevel@tonic-gate 13190Sstevel@tonic-gate /* 13200Sstevel@tonic-gate * Print the ELF header. Input is an ELF file descriptor 13210Sstevel@tonic-gate * and the filename. If f_flag is set, the ELF header is 13220Sstevel@tonic-gate * printed to stdout, otherwise the function returns after 13230Sstevel@tonic-gate * setting the pointer to the ELF header. Any values which 13240Sstevel@tonic-gate * are not known are printed in decimal. Fields must be updated 13250Sstevel@tonic-gate * as new values are added. 13260Sstevel@tonic-gate */ 13270Sstevel@tonic-gate static GElf_Ehdr * 13280Sstevel@tonic-gate dump_elf_header(Elf *elf_file, char *filename, GElf_Ehdr * elf_head_p) 13290Sstevel@tonic-gate { 13301976Sab196087 int class; 13310Sstevel@tonic-gate int field; 13320Sstevel@tonic-gate 13330Sstevel@tonic-gate if (gelf_getehdr(elf_file, elf_head_p) == NULL) { 13341618Srie (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename, 13351618Srie elf_errmsg(-1)); 13360Sstevel@tonic-gate return (NULL); 13370Sstevel@tonic-gate } 13380Sstevel@tonic-gate 13390Sstevel@tonic-gate class = (int)elf_head_p->e_ident[4]; 13400Sstevel@tonic-gate 13410Sstevel@tonic-gate if (class == ELFCLASS64) 13421618Srie field = 21; 13430Sstevel@tonic-gate else 13440Sstevel@tonic-gate field = 13; 13450Sstevel@tonic-gate 13460Sstevel@tonic-gate if (!f_flag) 13470Sstevel@tonic-gate return (elf_head_p); 13480Sstevel@tonic-gate 13490Sstevel@tonic-gate if (!p_flag) { 13501618Srie (void) printf("\n **** ELF HEADER ****\n"); 13511618Srie (void) printf("%-*s%-11s%-*sMachine Version\n", 13521618Srie field, "Class", "Data", field, "Type"); 13531618Srie (void) printf("%-*s%-11s%-*sFlags Ehsize\n", 13541618Srie field, "Entry", "Phoff", field, "Shoff"); 13551618Srie (void) printf("%-*s%-11s%-*sShnum Shstrndx\n\n", 13561618Srie field, "Phentsize", "Phnum", field, "Shentsz"); 13570Sstevel@tonic-gate } 13580Sstevel@tonic-gate 13590Sstevel@tonic-gate if (!v_flag) { 13600Sstevel@tonic-gate (void) printf("%-*d%-11d%-*d%-12d%d\n", 13614734Sab196087 field, elf_head_p->e_ident[4], elf_head_p->e_ident[5], 13624734Sab196087 field, (int)elf_head_p->e_type, (int)elf_head_p->e_machine, 13634734Sab196087 elf_head_p->e_version); 13640Sstevel@tonic-gate } else { 13654734Sab196087 Conv_inv_buf_t inv_buf; 13664734Sab196087 13671976Sab196087 (void) printf("%-*s", field, 13684734Sab196087 conv_ehdr_class(class, DUMP_CONVFMT, &inv_buf)); 13691976Sab196087 (void) printf("%-11s", 13704734Sab196087 conv_ehdr_data(elf_head_p->e_ident[5], DUMP_CONVFMT, 13714734Sab196087 &inv_buf)); 13721976Sab196087 (void) printf("%-*s", field, 13739273SAli.Bahrami@Sun.COM conv_ehdr_type(elf_head_p->e_ident[EI_OSABI], 13749273SAli.Bahrami@Sun.COM elf_head_p->e_type, DUMP_CONVFMT, &inv_buf)); 13751976Sab196087 (void) printf("%-12s", 13764734Sab196087 conv_ehdr_mach(elf_head_p->e_machine, DUMP_CONVFMT, 13774734Sab196087 &inv_buf)); 13781976Sab196087 (void) printf("%s\n", 13794734Sab196087 conv_ehdr_vers(elf_head_p->e_version, DUMP_CONVFMT, 13804734Sab196087 &inv_buf)); 13810Sstevel@tonic-gate } 13820Sstevel@tonic-gate (void) printf("%-#*llx%-#11llx%-#*llx%-#12x%#x\n", 13834734Sab196087 field, EC_ADDR(elf_head_p->e_entry), EC_OFF(elf_head_p->e_phoff), 13844734Sab196087 field, EC_OFF(elf_head_p->e_shoff), EC_WORD(elf_head_p->e_flags), 13854734Sab196087 EC_WORD(elf_head_p->e_ehsize)); 13860Sstevel@tonic-gate if (!v_flag || (elf_head_p->e_shstrndx != SHN_XINDEX)) { 13870Sstevel@tonic-gate (void) printf("%-#*x%-11u%-#*x%-12u%u\n", 13884734Sab196087 field, EC_WORD(elf_head_p->e_phentsize), 13894734Sab196087 EC_WORD(elf_head_p->e_phnum), 13904734Sab196087 field, EC_WORD(elf_head_p->e_shentsize), 13914734Sab196087 EC_WORD(elf_head_p->e_shnum), 13924734Sab196087 EC_WORD(elf_head_p->e_shstrndx)); 13930Sstevel@tonic-gate } else { 13940Sstevel@tonic-gate (void) printf("%-#*x%-11u%-#*x%-12uXINDEX\n", 13954734Sab196087 field, EC_WORD(elf_head_p->e_phentsize), 13964734Sab196087 EC_WORD(elf_head_p->e_phnum), 13974734Sab196087 field, EC_WORD(elf_head_p->e_shentsize), 13984734Sab196087 EC_WORD(elf_head_p->e_shnum)); 13990Sstevel@tonic-gate } 14000Sstevel@tonic-gate if ((elf_head_p->e_shnum == 0) && (elf_head_p->e_shoff > 0)) { 14010Sstevel@tonic-gate Elf_Scn *scn; 14020Sstevel@tonic-gate GElf_Shdr shdr0; 14030Sstevel@tonic-gate int field; 14040Sstevel@tonic-gate 14050Sstevel@tonic-gate if (gelf_getclass(elf_file) == ELFCLASS64) 14061618Srie field = 21; 14070Sstevel@tonic-gate else 14081618Srie field = 13; 14090Sstevel@tonic-gate if (!p_flag) { 14100Sstevel@tonic-gate (void) printf("\n **** SECTION HEADER[0] " 14110Sstevel@tonic-gate "{Elf Extensions} ****\n"); 14120Sstevel@tonic-gate (void) printf( 14130Sstevel@tonic-gate "[No]\tType\tFlags\t%-*s %-*s%-*s%sName\n", 14140Sstevel@tonic-gate field, "Addr", field, "Offset", field, 14150Sstevel@tonic-gate "Size(shnum)", 14160Sstevel@tonic-gate /* compatibility: tab for elf32 */ 14171618Srie (field == 13) ? "\t" : " "); 14180Sstevel@tonic-gate (void) printf("\tLn(strndx) Info\t%-*s Entsize\n", 14190Sstevel@tonic-gate field, "Adralgn"); 14200Sstevel@tonic-gate } 14210Sstevel@tonic-gate if ((scn = elf_getscn(elf_file, 0)) == NULL) { 14220Sstevel@tonic-gate (void) fprintf(stderr, 14234734Sab196087 "%s: %s: elf_getscn failed: %s\n", 14244734Sab196087 prog_name, filename, elf_errmsg(-1)); 14250Sstevel@tonic-gate return (NULL); 14260Sstevel@tonic-gate } 14270Sstevel@tonic-gate if (gelf_getshdr(scn, &shdr0) == 0) { 14280Sstevel@tonic-gate (void) fprintf(stderr, 14294734Sab196087 "%s: %s: gelf_getshdr: %s\n", 14304734Sab196087 prog_name, filename, elf_errmsg(-1)); 14310Sstevel@tonic-gate return (NULL); 14320Sstevel@tonic-gate } 14330Sstevel@tonic-gate (void) printf("[0]\t%u\t%llu\t", EC_WORD(shdr0.sh_type), 14344734Sab196087 EC_XWORD(shdr0.sh_flags)); 14350Sstevel@tonic-gate 14362352Sab196087 (void) printf("%-#*llx %-#*llx%-*llu%s%-*u\n", 14374734Sab196087 field, EC_ADDR(shdr0.sh_addr), 14384734Sab196087 field, EC_OFF(shdr0.sh_offset), 14394734Sab196087 field, EC_XWORD(shdr0.sh_size), 14404734Sab196087 /* compatibility: tab for elf32 */ 14414734Sab196087 ((field == 13) ? "\t" : " "), 14424734Sab196087 field, EC_WORD(shdr0.sh_name)); 14430Sstevel@tonic-gate 14440Sstevel@tonic-gate (void) printf("\t%u\t%u\t%-#*llx %-#*llx\n", 14454734Sab196087 EC_WORD(shdr0.sh_link), 14464734Sab196087 EC_WORD(shdr0.sh_info), 14474734Sab196087 field, EC_XWORD(shdr0.sh_addralign), 14484734Sab196087 field, EC_XWORD(shdr0.sh_entsize)); 14490Sstevel@tonic-gate } 14500Sstevel@tonic-gate (void) printf("\n"); 14510Sstevel@tonic-gate 14520Sstevel@tonic-gate return (elf_head_p); 14530Sstevel@tonic-gate } 14540Sstevel@tonic-gate 14550Sstevel@tonic-gate /* 14560Sstevel@tonic-gate * Print section contents. Input is an ELF file descriptor, 14570Sstevel@tonic-gate * the ELF header, the SCNTAB structure, 14580Sstevel@tonic-gate * the number of symbols, and the filename. 14590Sstevel@tonic-gate * The number of sections, 14600Sstevel@tonic-gate * and the offset into the SCNTAB structure will be 14610Sstevel@tonic-gate * set in dump_section if d_flag or n_flag are set. 14620Sstevel@tonic-gate * If v_flag is set, sections which can be interpreted will 14630Sstevel@tonic-gate * be interpreted, otherwise raw data will be output in hexidecimal. 14640Sstevel@tonic-gate */ 14650Sstevel@tonic-gate static void 14660Sstevel@tonic-gate print_section(Elf *elf_file, 14670Sstevel@tonic-gate GElf_Ehdr *p_ehdr, SCNTAB *p, int num_scns, char *filename) 14680Sstevel@tonic-gate { 14690Sstevel@tonic-gate unsigned char *p_sec; 14700Sstevel@tonic-gate int i; 14710Sstevel@tonic-gate size_t size; 14720Sstevel@tonic-gate 14730Sstevel@tonic-gate for (i = 0; i < num_scns; i++, p++) { 14740Sstevel@tonic-gate GElf_Shdr shdr; 14750Sstevel@tonic-gate 14760Sstevel@tonic-gate size = 0; 14770Sstevel@tonic-gate if (s_flag && !v_flag) 14780Sstevel@tonic-gate p_sec = (unsigned char *)get_rawscn(p->p_sd, &size); 14790Sstevel@tonic-gate else 14800Sstevel@tonic-gate p_sec = (unsigned char *)get_scndata(p->p_sd, &size); 14810Sstevel@tonic-gate 14820Sstevel@tonic-gate if ((gelf_getshdr(p->p_sd, &shdr) != NULL) && 14830Sstevel@tonic-gate (shdr.sh_type == SHT_NOBITS)) { 14840Sstevel@tonic-gate continue; 14850Sstevel@tonic-gate } 14860Sstevel@tonic-gate if (s_flag && !v_flag) { 14870Sstevel@tonic-gate (void) printf("\n%s:\n", p->scn_name); 14880Sstevel@tonic-gate print_rawdata(p_sec, size); 14890Sstevel@tonic-gate continue; 14900Sstevel@tonic-gate } 14910Sstevel@tonic-gate if (shdr.sh_type == SHT_SYMTAB) { 14920Sstevel@tonic-gate dump_symbol_table(elf_file, p, filename); 14930Sstevel@tonic-gate continue; 14940Sstevel@tonic-gate } 14950Sstevel@tonic-gate if (shdr.sh_type == SHT_DYNSYM) { 14960Sstevel@tonic-gate dump_symbol_table(elf_file, p, filename); 14970Sstevel@tonic-gate continue; 14980Sstevel@tonic-gate } 14990Sstevel@tonic-gate if (shdr.sh_type == SHT_STRTAB) { 15000Sstevel@tonic-gate dump_string_table(p, 1); 15010Sstevel@tonic-gate continue; 15020Sstevel@tonic-gate } 15030Sstevel@tonic-gate if (shdr.sh_type == SHT_RELA) { 15040Sstevel@tonic-gate dump_reloc_table(elf_file, p_ehdr, p, 1, filename); 15050Sstevel@tonic-gate continue; 15060Sstevel@tonic-gate } 15070Sstevel@tonic-gate if (shdr.sh_type == SHT_REL) { 15080Sstevel@tonic-gate dump_reloc_table(elf_file, p_ehdr, p, 1, filename); 15090Sstevel@tonic-gate continue; 15100Sstevel@tonic-gate } 15110Sstevel@tonic-gate if (shdr.sh_type == SHT_DYNAMIC) { 15120Sstevel@tonic-gate dump_dynamic(elf_file, p, 1, filename); 15130Sstevel@tonic-gate continue; 15140Sstevel@tonic-gate } 15150Sstevel@tonic-gate 15160Sstevel@tonic-gate (void) printf("\n%s:\n", p->scn_name); 15170Sstevel@tonic-gate print_rawdata(p_sec, size); 15180Sstevel@tonic-gate } 15190Sstevel@tonic-gate (void) printf("\n"); 15200Sstevel@tonic-gate } 15210Sstevel@tonic-gate 15220Sstevel@tonic-gate /* 15230Sstevel@tonic-gate * Print section contents. This function does not print the contents 15240Sstevel@tonic-gate * of the sections but sets up the parameters and then calls 15250Sstevel@tonic-gate * print_section to print the contents. Calling another function to print 15260Sstevel@tonic-gate * the contents allows both -d and -n to work correctly 15270Sstevel@tonic-gate * simultaneously. Input is an ELF file descriptor, the ELF header, 15280Sstevel@tonic-gate * the SCNTAB structure, the number of sections, and the filename. 15290Sstevel@tonic-gate * Set the range of sections if d_flag, and set section name if 15300Sstevel@tonic-gate * n_flag. 15310Sstevel@tonic-gate */ 15320Sstevel@tonic-gate static void 15330Sstevel@tonic-gate dump_section(Elf *elf_file, 15340Sstevel@tonic-gate GElf_Ehdr *p_ehdr, SCNTAB *s, int num_scns, char *filename) 15350Sstevel@tonic-gate { 15360Sstevel@tonic-gate SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */ 15370Sstevel@tonic-gate int i; 15380Sstevel@tonic-gate int found_it = 0; /* for use with -n section_name */ 15390Sstevel@tonic-gate 15400Sstevel@tonic-gate if (n_flag) { 15410Sstevel@tonic-gate n_range = s; 15420Sstevel@tonic-gate 15430Sstevel@tonic-gate for (i = 0; i < num_scns; i++, n_range++) { 15440Sstevel@tonic-gate if ((strcmp(name, n_range->scn_name)) != 0) 15450Sstevel@tonic-gate continue; 15460Sstevel@tonic-gate else { 15470Sstevel@tonic-gate found_it = 1; 15480Sstevel@tonic-gate print_section(elf_file, p_ehdr, 15494734Sab196087 n_range, 1, filename); 15500Sstevel@tonic-gate } 15510Sstevel@tonic-gate } 15520Sstevel@tonic-gate 15530Sstevel@tonic-gate if (!found_it) { 15540Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: %s not found\n", 15554734Sab196087 prog_name, filename, name); 15560Sstevel@tonic-gate } 15570Sstevel@tonic-gate } /* end n_flag */ 15580Sstevel@tonic-gate 15590Sstevel@tonic-gate if (d_flag) { 15600Sstevel@tonic-gate d_range = s; 15610Sstevel@tonic-gate d_num = check_range(d_low, d_hi, num_scns, filename); 15620Sstevel@tonic-gate if (d_num < 0) 15630Sstevel@tonic-gate return; 15640Sstevel@tonic-gate d_range += d_low - 1; 15650Sstevel@tonic-gate 15660Sstevel@tonic-gate print_section(elf_file, p_ehdr, d_range, d_num, filename); 15670Sstevel@tonic-gate } /* end d_flag */ 15680Sstevel@tonic-gate 15690Sstevel@tonic-gate if (!n_flag && !d_flag) 15700Sstevel@tonic-gate print_section(elf_file, p_ehdr, s, num_scns, filename); 15710Sstevel@tonic-gate } 15720Sstevel@tonic-gate 15730Sstevel@tonic-gate /* 15740Sstevel@tonic-gate * Print the section header table. This function does not print the contents 15750Sstevel@tonic-gate * of the section headers but sets up the parameters and then calls 15760Sstevel@tonic-gate * print_shdr to print the contents. Calling another function to print 15770Sstevel@tonic-gate * the contents allows both -d and -n to work correctly 15780Sstevel@tonic-gate * simultaneously. Input is the SCNTAB structure, 15790Sstevel@tonic-gate * the number of sections from the ELF header, and the filename. 15800Sstevel@tonic-gate * Set the range of section headers to print if d_flag, and set 15810Sstevel@tonic-gate * name of section header to print if n_flag. 15820Sstevel@tonic-gate */ 15830Sstevel@tonic-gate static void 15840Sstevel@tonic-gate dump_shdr(Elf *elf_file, SCNTAB *s, int num_scns, char *filename) 15850Sstevel@tonic-gate { 15860Sstevel@tonic-gate 15870Sstevel@tonic-gate SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */ 15880Sstevel@tonic-gate int field; 15890Sstevel@tonic-gate int i; 15900Sstevel@tonic-gate int found_it = 0; /* for use with -n section_name */ 15910Sstevel@tonic-gate 15920Sstevel@tonic-gate if (gelf_getclass(elf_file) == ELFCLASS64) 15931618Srie field = 21; 15940Sstevel@tonic-gate else 15951618Srie field = 13; 15960Sstevel@tonic-gate 15970Sstevel@tonic-gate if (!p_flag) { 15980Sstevel@tonic-gate (void) printf("\n **** SECTION HEADER TABLE ****\n"); 15990Sstevel@tonic-gate (void) printf("[No]\tType\tFlags\t%-*s %-*s %-*s%sName\n", 16000Sstevel@tonic-gate field, "Addr", field, "Offset", field, "Size", 16010Sstevel@tonic-gate /* compatibility: tab for elf32 */ 16021618Srie (field == 13) ? "\t" : " "); 16030Sstevel@tonic-gate (void) printf("\tLink\tInfo\t%-*s Entsize\n\n", 16040Sstevel@tonic-gate field, "Adralgn"); 16050Sstevel@tonic-gate } 16060Sstevel@tonic-gate 16070Sstevel@tonic-gate if (n_flag) { 16080Sstevel@tonic-gate n_range = s; 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate for (i = 1; i <= num_scns; i++, n_range++) { 16110Sstevel@tonic-gate if ((strcmp(name, n_range->scn_name)) != 0) 16120Sstevel@tonic-gate continue; 16130Sstevel@tonic-gate else { 16140Sstevel@tonic-gate found_it = 1; 16150Sstevel@tonic-gate print_shdr(elf_file, n_range, 1, i); 16160Sstevel@tonic-gate } 16170Sstevel@tonic-gate } 16180Sstevel@tonic-gate 16190Sstevel@tonic-gate if (!found_it) { 16200Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: %s not found\n", 16214734Sab196087 prog_name, filename, name); 16220Sstevel@tonic-gate } 16230Sstevel@tonic-gate } /* end n_flag */ 16240Sstevel@tonic-gate 16250Sstevel@tonic-gate if (d_flag) { 16260Sstevel@tonic-gate d_range = s; 16270Sstevel@tonic-gate d_num = check_range(d_low, d_hi, num_scns, filename); 16280Sstevel@tonic-gate if (d_num < 0) 16290Sstevel@tonic-gate return; 16300Sstevel@tonic-gate d_range += d_low - 1; 16310Sstevel@tonic-gate 16320Sstevel@tonic-gate print_shdr(elf_file, d_range, d_num, d_low); 16330Sstevel@tonic-gate } /* end d_flag */ 16340Sstevel@tonic-gate 16350Sstevel@tonic-gate if (!n_flag && !d_flag) 16360Sstevel@tonic-gate print_shdr(elf_file, s, num_scns, 1); 16370Sstevel@tonic-gate } 16380Sstevel@tonic-gate 16390Sstevel@tonic-gate /* 16400Sstevel@tonic-gate * Process all of the command line options (except 16410Sstevel@tonic-gate * for -a, -g, -f, and -o). All of the options processed 16420Sstevel@tonic-gate * by this function require the presence of the section 16430Sstevel@tonic-gate * header table and will not be processed if it is not present. 16440Sstevel@tonic-gate * Set up a buffer containing section name, section header, 16450Sstevel@tonic-gate * and section descriptor for each section in the file. This 16460Sstevel@tonic-gate * structure is used to avoid duplicate calls to libelf functions. 16470Sstevel@tonic-gate * Structure members for the symbol table, the debugging information, 16480Sstevel@tonic-gate * and the line number information are global. All of the 16490Sstevel@tonic-gate * rest are local. 16500Sstevel@tonic-gate */ 16510Sstevel@tonic-gate static void 16520Sstevel@tonic-gate dump_section_table(Elf *elf_file, GElf_Ehdr *elf_head_p, char *filename) 16530Sstevel@tonic-gate { 16540Sstevel@tonic-gate 16550Sstevel@tonic-gate static SCNTAB *buffer, *p_scns; 16560Sstevel@tonic-gate Elf_Scn *scn = 0; 16570Sstevel@tonic-gate char *s_name = NULL; 16580Sstevel@tonic-gate int found = 0; 16590Sstevel@tonic-gate unsigned int num_scns; 16600Sstevel@tonic-gate size_t shstrndx; 16610Sstevel@tonic-gate size_t shnum; 16620Sstevel@tonic-gate 16630Sstevel@tonic-gate 16649900SAli.Bahrami@Sun.COM if (elf_getshdrnum(elf_file, &shnum) == -1) { 16650Sstevel@tonic-gate (void) fprintf(stderr, 16669900SAli.Bahrami@Sun.COM "%s: %s: elf_getshdrnum failed: %s\n", 16674734Sab196087 prog_name, filename, elf_errmsg(-1)); 16680Sstevel@tonic-gate return; 16690Sstevel@tonic-gate } 16709900SAli.Bahrami@Sun.COM if (elf_getshdrstrndx(elf_file, &shstrndx) == -1) { 16710Sstevel@tonic-gate (void) fprintf(stderr, 16729900SAli.Bahrami@Sun.COM "%s: %s: elf_getshdrstrndx failed: %s\n", 16734734Sab196087 prog_name, filename, elf_errmsg(-1)); 16740Sstevel@tonic-gate return; 16750Sstevel@tonic-gate } 16760Sstevel@tonic-gate 16770Sstevel@tonic-gate if ((buffer = calloc(shnum, sizeof (SCNTAB))) == NULL) { 16780Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: cannot calloc space\n", 16794734Sab196087 prog_name, filename); 16800Sstevel@tonic-gate return; 16810Sstevel@tonic-gate } 16820Sstevel@tonic-gate /* LINTED */ 16830Sstevel@tonic-gate num_scns = (int)shnum - 1; 16840Sstevel@tonic-gate 16850Sstevel@tonic-gate p_symtab = (SCNTAB *)0; 16860Sstevel@tonic-gate p_dynsym = (SCNTAB *)0; 16870Sstevel@tonic-gate p_scns = buffer; 16880Sstevel@tonic-gate p_head_scns = buffer; 16890Sstevel@tonic-gate 16900Sstevel@tonic-gate while ((scn = elf_nextscn(elf_file, scn)) != 0) { 16910Sstevel@tonic-gate if ((gelf_getshdr(scn, &buffer->p_shdr)) == 0) { 16920Sstevel@tonic-gate (void) fprintf(stderr, 16934734Sab196087 "%s: %s: %s\n", prog_name, filename, 16944734Sab196087 elf_errmsg(-1)); 16950Sstevel@tonic-gate return; 16960Sstevel@tonic-gate } 16974734Sab196087 s_name = (char *) 16984734Sab196087 elf_strptr(elf_file, shstrndx, buffer->p_shdr.sh_name); 16990Sstevel@tonic-gate buffer->scn_name = s_name ? s_name : (char *)UNKNOWN; 17000Sstevel@tonic-gate buffer->p_sd = scn; 17010Sstevel@tonic-gate 17020Sstevel@tonic-gate if (buffer->p_shdr.sh_type == SHT_SYMTAB) { 17030Sstevel@tonic-gate found += 1; 17040Sstevel@tonic-gate p_symtab = buffer; 17050Sstevel@tonic-gate } 17060Sstevel@tonic-gate if (buffer->p_shdr.sh_type == SHT_DYNSYM) 17070Sstevel@tonic-gate p_dynsym = buffer; 17080Sstevel@tonic-gate buffer++; 17090Sstevel@tonic-gate } 17100Sstevel@tonic-gate 17110Sstevel@tonic-gate /* 17120Sstevel@tonic-gate * These functions depend upon the presence of the section header table 17130Sstevel@tonic-gate * and will not be invoked in its absence 17140Sstevel@tonic-gate */ 17150Sstevel@tonic-gate if (h_flag) { 17160Sstevel@tonic-gate dump_shdr(elf_file, p_scns, num_scns, filename); 17170Sstevel@tonic-gate } 17180Sstevel@tonic-gate if (p_symtab && (t_flag || T_flag)) { 17190Sstevel@tonic-gate dump_symbol_table(elf_file, p_symtab, filename); 17200Sstevel@tonic-gate } 17210Sstevel@tonic-gate if (c_flag) { 17220Sstevel@tonic-gate dump_string_table(p_scns, num_scns); 17230Sstevel@tonic-gate } 17240Sstevel@tonic-gate if (r_flag) { 17250Sstevel@tonic-gate dump_reloc_table(elf_file, elf_head_p, 17264734Sab196087 p_scns, num_scns, filename); 17270Sstevel@tonic-gate } 17280Sstevel@tonic-gate if (L_flag) { 17290Sstevel@tonic-gate dump_dynamic(elf_file, p_scns, num_scns, filename); 17300Sstevel@tonic-gate } 17310Sstevel@tonic-gate if (s_flag) { 17320Sstevel@tonic-gate dump_section(elf_file, elf_head_p, p_scns, 17334734Sab196087 num_scns, filename); 17340Sstevel@tonic-gate } 17350Sstevel@tonic-gate } 17360Sstevel@tonic-gate 17370Sstevel@tonic-gate /* 17380Sstevel@tonic-gate * Load the archive string table(s) (for extended-length strings) 17390Sstevel@tonic-gate * into an in-core table/list 17400Sstevel@tonic-gate */ 17410Sstevel@tonic-gate static struct stab_list_s * 17420Sstevel@tonic-gate load_arstring_table(struct stab_list_s *STabList, 17430Sstevel@tonic-gate int fd, Elf *elf_file, Elf_Arhdr *p_ar, char *filename) 17440Sstevel@tonic-gate { 17450Sstevel@tonic-gate off_t here; 17460Sstevel@tonic-gate struct stab_list_s *STL_entry, *STL_next; 17470Sstevel@tonic-gate 17480Sstevel@tonic-gate if (p_ar) { 17490Sstevel@tonic-gate STL_entry = malloc(sizeof (struct stab_list_s)); 17500Sstevel@tonic-gate STL_entry->next = 0; 17510Sstevel@tonic-gate STL_entry->strings = 0; 17520Sstevel@tonic-gate STL_entry->size = 0; 17530Sstevel@tonic-gate 17540Sstevel@tonic-gate if (!STabList) 17550Sstevel@tonic-gate STabList = STL_entry; 17560Sstevel@tonic-gate else { 17570Sstevel@tonic-gate STL_next = STabList; 17580Sstevel@tonic-gate while (STL_next->next != (void *)0) 17590Sstevel@tonic-gate STL_next = STL_next->next; 17600Sstevel@tonic-gate STL_next->next = STL_entry; 17610Sstevel@tonic-gate } 17620Sstevel@tonic-gate 17630Sstevel@tonic-gate STL_entry->size = p_ar->ar_size; 17640Sstevel@tonic-gate STL_entry->strings = malloc(p_ar->ar_size); 17650Sstevel@tonic-gate here = elf_getbase(elf_file); 17660Sstevel@tonic-gate if ((lseek(fd, here, 0)) != here) { 17670Sstevel@tonic-gate (void) fprintf(stderr, 17684734Sab196087 "%s: %s: could not lseek\n", prog_name, filename); 17690Sstevel@tonic-gate } 17700Sstevel@tonic-gate 17710Sstevel@tonic-gate if ((read(fd, STL_entry->strings, p_ar->ar_size)) == -1) { 17720Sstevel@tonic-gate (void) fprintf(stderr, 17734734Sab196087 "%s: %s: could not read\n", prog_name, filename); 17740Sstevel@tonic-gate } 17750Sstevel@tonic-gate } 17760Sstevel@tonic-gate return (STabList); 17770Sstevel@tonic-gate } 17780Sstevel@tonic-gate 17790Sstevel@tonic-gate /* 17800Sstevel@tonic-gate * Print the archive header for each member of an archive. 17810Sstevel@tonic-gate * Also call ar_sym_read to print the symbols in the 17820Sstevel@tonic-gate * archive symbol table if g_flag. Input is a file descriptor, 17830Sstevel@tonic-gate * an ELF file descriptor, and the filename. Putting the call 17840Sstevel@tonic-gate * to dump the archive symbol table in this function is more 17850Sstevel@tonic-gate * efficient since it is necessary to examine the archive member 17860Sstevel@tonic-gate * name in the archive header to determine which member is the 17870Sstevel@tonic-gate * symbol table. 17880Sstevel@tonic-gate */ 17890Sstevel@tonic-gate static void 17900Sstevel@tonic-gate dump_ar_hdr(int fd, Elf *elf_file, char *filename) 17910Sstevel@tonic-gate { 17920Sstevel@tonic-gate extern int v_flag, g_flag, a_flag, p_flag; 17930Sstevel@tonic-gate Elf_Arhdr *p_ar; 17940Sstevel@tonic-gate Elf *arf; 17950Sstevel@tonic-gate Elf_Cmd cmd; 17960Sstevel@tonic-gate int title = 0; 17970Sstevel@tonic-gate int err = 0; 17980Sstevel@tonic-gate 17990Sstevel@tonic-gate char buf[DATESIZE]; 18000Sstevel@tonic-gate 18010Sstevel@tonic-gate cmd = ELF_C_READ; 18020Sstevel@tonic-gate while ((arf = elf_begin(fd, cmd, elf_file)) != 0) { 18030Sstevel@tonic-gate p_ar = elf_getarhdr(arf); 18040Sstevel@tonic-gate if (p_ar == NULL) { 18050Sstevel@tonic-gate (void) fprintf(stderr, 18064734Sab196087 "%s: %s: %s\n", prog_name, filename, 18074734Sab196087 elf_errmsg(-1)); 18080Sstevel@tonic-gate continue; 18090Sstevel@tonic-gate } 1810*12792SAli.Bahrami@Oracle.COM if ((strcmp(p_ar->ar_name, "/") == 0) || 1811*12792SAli.Bahrami@Oracle.COM (strcmp(p_ar->ar_name, "/SYM64/") == 0)) { 18120Sstevel@tonic-gate if (g_flag) 18130Sstevel@tonic-gate ar_sym_read(elf_file, filename); 18140Sstevel@tonic-gate } else if (strcmp(p_ar->ar_name, "//") == 0) { 18150Sstevel@tonic-gate StringTableList = load_arstring_table( 18164734Sab196087 StringTableList, fd, arf, p_ar, filename); 18170Sstevel@tonic-gate cmd = elf_next(arf); 18180Sstevel@tonic-gate (void) elf_end(arf); 18190Sstevel@tonic-gate continue; 18200Sstevel@tonic-gate } else { 18210Sstevel@tonic-gate if (a_flag) { 18220Sstevel@tonic-gate (void) printf("%s[%s]:\n", filename, 18234734Sab196087 p_ar->ar_name); 18240Sstevel@tonic-gate if (!p_flag && title == 0) { 18250Sstevel@tonic-gate if (!v_flag) 18260Sstevel@tonic-gate (void) printf( 18270Sstevel@tonic-gate "\n\n\t\t\t***ARCHIVE HEADER***" 18280Sstevel@tonic-gate "\n Date Uid Gid Mode Size Member Name\n\n"); 18290Sstevel@tonic-gate else 18300Sstevel@tonic-gate (void) printf( 18310Sstevel@tonic-gate "\n\n\t\t\t***ARCHIVE HEADER***" 18320Sstevel@tonic-gate "\n Date Uid Gid Mode Size Member Name\n\n"); 18330Sstevel@tonic-gate title = 1; 18340Sstevel@tonic-gate } 18350Sstevel@tonic-gate if (!v_flag) { 18360Sstevel@tonic-gate (void) printf( 18370Sstevel@tonic-gate "\t0x%.8lx %6d %6d 0%.6ho 0x%.8lx %-s\n\n", 18384734Sab196087 p_ar->ar_date, (int)p_ar->ar_uid, 18394734Sab196087 (int)p_ar->ar_gid, 18404734Sab196087 (int)p_ar->ar_mode, 18414734Sab196087 p_ar->ar_size, p_ar->ar_name); 18420Sstevel@tonic-gate } else { 18430Sstevel@tonic-gate if ((strftime(buf, DATESIZE, 18440Sstevel@tonic-gate "%b %d %H:%M:%S %Y", 18450Sstevel@tonic-gate localtime( 18460Sstevel@tonic-gate &(p_ar->ar_date)))) == 0) { 18470Sstevel@tonic-gate (void) fprintf(stderr, 18480Sstevel@tonic-gate "%s: %s: don't have enough space to store the date\n", prog_name, filename); 18490Sstevel@tonic-gate exit(1); 18500Sstevel@tonic-gate } 18510Sstevel@tonic-gate (void) printf( 18524734Sab196087 "\t%s %6d %6d 0%.6ho 0x%.8lx %-s\n\n", 18534734Sab196087 buf, (int)p_ar->ar_uid, 18544734Sab196087 (int)p_ar->ar_gid, 18554734Sab196087 (int)p_ar->ar_mode, 18564734Sab196087 p_ar->ar_size, p_ar->ar_name); 18570Sstevel@tonic-gate } 18580Sstevel@tonic-gate } 18590Sstevel@tonic-gate } 18600Sstevel@tonic-gate cmd = elf_next(arf); 18610Sstevel@tonic-gate (void) elf_end(arf); 18620Sstevel@tonic-gate } /* end while */ 18630Sstevel@tonic-gate 18640Sstevel@tonic-gate err = elf_errno(); 18650Sstevel@tonic-gate if (err != 0) { 18660Sstevel@tonic-gate (void) fprintf(stderr, 18674734Sab196087 "%s: %s: %s\n", prog_name, filename, elf_errmsg(err)); 18680Sstevel@tonic-gate } 18690Sstevel@tonic-gate } 18700Sstevel@tonic-gate 18710Sstevel@tonic-gate /* 18720Sstevel@tonic-gate * Process member files of an archive. This function provides 18730Sstevel@tonic-gate * a loop through an archive equivalent the processing of 18740Sstevel@tonic-gate * each_file for individual object files. 18750Sstevel@tonic-gate */ 18760Sstevel@tonic-gate static void 18770Sstevel@tonic-gate dump_ar_files(int fd, Elf *elf_file, char *filename) 18780Sstevel@tonic-gate { 18790Sstevel@tonic-gate Elf_Arhdr *p_ar; 18800Sstevel@tonic-gate Elf *arf; 18810Sstevel@tonic-gate Elf_Cmd cmd; 18820Sstevel@tonic-gate Elf_Kind file_type; 18830Sstevel@tonic-gate GElf_Ehdr elf_head; 18840Sstevel@tonic-gate char *fullname; 18850Sstevel@tonic-gate 18860Sstevel@tonic-gate cmd = ELF_C_READ; 18870Sstevel@tonic-gate while ((arf = elf_begin(fd, cmd, elf_file)) != 0) { 18881618Srie size_t len; 18891618Srie 18900Sstevel@tonic-gate p_ar = elf_getarhdr(arf); 18910Sstevel@tonic-gate if (p_ar == NULL) { 18924734Sab196087 (void) fprintf(stderr, "%s: %s: %s\n", 18934734Sab196087 prog_name, filename, elf_errmsg(-1)); 18940Sstevel@tonic-gate return; 18950Sstevel@tonic-gate } 1896*12792SAli.Bahrami@Oracle.COM if (p_ar->ar_name[0] == '/') { 18970Sstevel@tonic-gate cmd = elf_next(arf); 18980Sstevel@tonic-gate (void) elf_end(arf); 18990Sstevel@tonic-gate continue; 19000Sstevel@tonic-gate } 19010Sstevel@tonic-gate 19021618Srie len = strlen(filename) + strlen(p_ar->ar_name) + 3; 19031618Srie if ((fullname = malloc(len)) == NULL) 19041618Srie return; 19051618Srie (void) snprintf(fullname, len, "%s[%s]", filename, 19061618Srie p_ar->ar_name); 19070Sstevel@tonic-gate (void) printf("\n%s:\n", fullname); 19080Sstevel@tonic-gate file_type = elf_kind(arf); 19090Sstevel@tonic-gate if (file_type == ELF_K_ELF) { 19100Sstevel@tonic-gate if (dump_elf_header(arf, fullname, &elf_head) == NULL) 19110Sstevel@tonic-gate return; 19120Sstevel@tonic-gate if (o_flag) 19130Sstevel@tonic-gate dump_exec_header(arf, 19144734Sab196087 (unsigned)elf_head.e_phnum, fullname); 19150Sstevel@tonic-gate if (x_flag) 19160Sstevel@tonic-gate dump_section_table(arf, &elf_head, fullname); 19170Sstevel@tonic-gate } else { 19184734Sab196087 (void) fprintf(stderr, "%s: %s: invalid file type\n", 19194734Sab196087 prog_name, fullname); 19200Sstevel@tonic-gate cmd = elf_next(arf); 19210Sstevel@tonic-gate (void) elf_end(arf); 19220Sstevel@tonic-gate continue; 19230Sstevel@tonic-gate } 19240Sstevel@tonic-gate 19250Sstevel@tonic-gate cmd = elf_next(arf); 19260Sstevel@tonic-gate (void) elf_end(arf); 19270Sstevel@tonic-gate } /* end while */ 19280Sstevel@tonic-gate } 19290Sstevel@tonic-gate 19300Sstevel@tonic-gate /* 19310Sstevel@tonic-gate * Takes a filename as input. Test first for a valid version 19320Sstevel@tonic-gate * of libelf.a and exit on error. Process each valid file 19330Sstevel@tonic-gate * or archive given as input on the command line. Check 19340Sstevel@tonic-gate * for file type. If it is an archive, process the archive- 19350Sstevel@tonic-gate * specific options first, then files within the archive. 19360Sstevel@tonic-gate * If it is an ELF object file, process it; otherwise 19370Sstevel@tonic-gate * warn that it is an invalid file type. 19380Sstevel@tonic-gate * All options except the archive-specific and program 19390Sstevel@tonic-gate * execution header are processed in the function, dump_section_table. 19400Sstevel@tonic-gate */ 19410Sstevel@tonic-gate static void 19420Sstevel@tonic-gate each_file(char *filename) 19430Sstevel@tonic-gate { 19440Sstevel@tonic-gate Elf *elf_file; 19450Sstevel@tonic-gate GElf_Ehdr elf_head; 19460Sstevel@tonic-gate int fd; 19470Sstevel@tonic-gate Elf_Kind file_type; 19480Sstevel@tonic-gate 19490Sstevel@tonic-gate struct stat buf; 19500Sstevel@tonic-gate 19510Sstevel@tonic-gate Elf_Cmd cmd; 19520Sstevel@tonic-gate errno = 0; 19530Sstevel@tonic-gate 19540Sstevel@tonic-gate if (stat(filename, &buf) == -1) { 19551618Srie int err = errno; 19561618Srie (void) fprintf(stderr, "%s: %s: %s", prog_name, filename, 19571618Srie strerror(err)); 19580Sstevel@tonic-gate return; 19590Sstevel@tonic-gate } 19600Sstevel@tonic-gate 19610Sstevel@tonic-gate if ((fd = open((filename), O_RDONLY)) == -1) { 19621618Srie (void) fprintf(stderr, "%s: %s: cannot read\n", prog_name, 19631618Srie filename); 19640Sstevel@tonic-gate return; 19650Sstevel@tonic-gate } 19660Sstevel@tonic-gate cmd = ELF_C_READ; 19670Sstevel@tonic-gate if ((elf_file = elf_begin(fd, cmd, (Elf *)0)) == NULL) { 19681618Srie (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename, 19691618Srie elf_errmsg(-1)); 19700Sstevel@tonic-gate return; 19710Sstevel@tonic-gate } 19720Sstevel@tonic-gate 19730Sstevel@tonic-gate file_type = elf_kind(elf_file); 19740Sstevel@tonic-gate if (file_type == ELF_K_AR) { 19750Sstevel@tonic-gate if (a_flag || g_flag) { 19760Sstevel@tonic-gate dump_ar_hdr(fd, elf_file, filename); 19770Sstevel@tonic-gate elf_file = elf_begin(fd, cmd, (Elf *)0); 19780Sstevel@tonic-gate } 19790Sstevel@tonic-gate if (z_flag) 19800Sstevel@tonic-gate dump_ar_files(fd, elf_file, filename); 19810Sstevel@tonic-gate } else { 19820Sstevel@tonic-gate if (file_type == ELF_K_ELF) { 19830Sstevel@tonic-gate (void) printf("\n%s:\n", filename); 19841618Srie if (dump_elf_header(elf_file, filename, &elf_head)) { 19851618Srie if (o_flag) 19861618Srie dump_exec_header(elf_file, 19871618Srie (unsigned)elf_head.e_phnum, 19881618Srie filename); 19891618Srie if (x_flag) 19901618Srie dump_section_table(elf_file, 19911618Srie &elf_head, filename); 19920Sstevel@tonic-gate } 19930Sstevel@tonic-gate } else { 19940Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: invalid file type\n", 19951618Srie prog_name, filename); 19960Sstevel@tonic-gate } 19970Sstevel@tonic-gate } 19980Sstevel@tonic-gate (void) elf_end(elf_file); 19990Sstevel@tonic-gate (void) close(fd); 20000Sstevel@tonic-gate } 20010Sstevel@tonic-gate 20020Sstevel@tonic-gate /* 20030Sstevel@tonic-gate * Sets up flags for command line options given and then 20040Sstevel@tonic-gate * calls each_file() to process each file. 20050Sstevel@tonic-gate */ 20060Sstevel@tonic-gate int 20070Sstevel@tonic-gate main(int argc, char *argv[], char *envp[]) 20080Sstevel@tonic-gate { 20090Sstevel@tonic-gate char *optstr = OPTSTR; /* option string used by getopt() */ 20100Sstevel@tonic-gate int optchar; 20110Sstevel@tonic-gate 20120Sstevel@tonic-gate /* 20130Sstevel@tonic-gate * Check for a binary that better fits this architecture. 20140Sstevel@tonic-gate */ 20152647Srie (void) conv_check_native(argv, envp); 20160Sstevel@tonic-gate 20170Sstevel@tonic-gate prog_name = argv[0]; 20180Sstevel@tonic-gate 20190Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 20200Sstevel@tonic-gate while ((optchar = getopt(argc, argv, optstr)) != -1) { 20210Sstevel@tonic-gate switch (optchar) { 20220Sstevel@tonic-gate case 'a': 20230Sstevel@tonic-gate a_flag = 1; 20240Sstevel@tonic-gate x_flag = 1; 20250Sstevel@tonic-gate break; 20260Sstevel@tonic-gate case 'g': 20270Sstevel@tonic-gate g_flag = 1; 20280Sstevel@tonic-gate x_flag = 1; 20290Sstevel@tonic-gate break; 20300Sstevel@tonic-gate case 'v': 20310Sstevel@tonic-gate v_flag = 1; 20320Sstevel@tonic-gate break; 20330Sstevel@tonic-gate case 'p': 20340Sstevel@tonic-gate p_flag = 1; 20350Sstevel@tonic-gate break; 20360Sstevel@tonic-gate case 'f': 20370Sstevel@tonic-gate f_flag = 1; 20380Sstevel@tonic-gate z_flag = 1; 20390Sstevel@tonic-gate break; 20400Sstevel@tonic-gate case 'o': 20410Sstevel@tonic-gate o_flag = 1; 20420Sstevel@tonic-gate z_flag = 1; 20430Sstevel@tonic-gate break; 20440Sstevel@tonic-gate case 'h': 20450Sstevel@tonic-gate h_flag = 1; 20460Sstevel@tonic-gate x_flag = 1; 20470Sstevel@tonic-gate z_flag = 1; 20480Sstevel@tonic-gate break; 20490Sstevel@tonic-gate case 's': 20500Sstevel@tonic-gate s_flag = 1; 20510Sstevel@tonic-gate x_flag = 1; 20520Sstevel@tonic-gate z_flag = 1; 20530Sstevel@tonic-gate break; 20540Sstevel@tonic-gate case 'd': 20550Sstevel@tonic-gate d_flag = 1; 20560Sstevel@tonic-gate x_flag = 1; 20570Sstevel@tonic-gate z_flag = 1; 20580Sstevel@tonic-gate set_range(optarg, &d_low, &d_hi); 20590Sstevel@tonic-gate break; 20600Sstevel@tonic-gate case 'n': 20610Sstevel@tonic-gate n_flag++; 20620Sstevel@tonic-gate x_flag = 1; 20630Sstevel@tonic-gate z_flag = 1; 20640Sstevel@tonic-gate name = optarg; 20650Sstevel@tonic-gate break; 20660Sstevel@tonic-gate case 'r': 20670Sstevel@tonic-gate r_flag = 1; 20680Sstevel@tonic-gate x_flag = 1; 20690Sstevel@tonic-gate z_flag = 1; 20700Sstevel@tonic-gate break; 20710Sstevel@tonic-gate case 't': 20720Sstevel@tonic-gate t_flag = 1; 20730Sstevel@tonic-gate x_flag = 1; 20740Sstevel@tonic-gate z_flag = 1; 20750Sstevel@tonic-gate break; 20760Sstevel@tonic-gate case 'C': 20770Sstevel@tonic-gate C_flag = 1; 20780Sstevel@tonic-gate t_flag = 1; 20790Sstevel@tonic-gate x_flag = 1; 20800Sstevel@tonic-gate z_flag = 1; 20810Sstevel@tonic-gate break; 20820Sstevel@tonic-gate case 'T': 20830Sstevel@tonic-gate T_flag = 1; 20840Sstevel@tonic-gate x_flag = 1; 20850Sstevel@tonic-gate z_flag = 1; 20860Sstevel@tonic-gate set_range(optarg, &T_low, &T_hi); 20870Sstevel@tonic-gate break; 20880Sstevel@tonic-gate case 'c': 20890Sstevel@tonic-gate c_flag = 1; 20900Sstevel@tonic-gate x_flag = 1; 20910Sstevel@tonic-gate z_flag = 1; 20920Sstevel@tonic-gate break; 20930Sstevel@tonic-gate case 'L': 20940Sstevel@tonic-gate L_flag = 1; 20950Sstevel@tonic-gate x_flag = 1; 20960Sstevel@tonic-gate z_flag = 1; 20970Sstevel@tonic-gate break; 20980Sstevel@tonic-gate case 'V': 20990Sstevel@tonic-gate V_flag = 1; 21000Sstevel@tonic-gate (void) fprintf(stderr, "dump: %s %s\n", 21010Sstevel@tonic-gate (const char *)SGU_PKG, 21020Sstevel@tonic-gate (const char *)SGU_REL); 21030Sstevel@tonic-gate break; 21040Sstevel@tonic-gate case '?': 21050Sstevel@tonic-gate errflag += 1; 21060Sstevel@tonic-gate break; 21070Sstevel@tonic-gate default: 21080Sstevel@tonic-gate break; 21090Sstevel@tonic-gate } 21100Sstevel@tonic-gate } 21110Sstevel@tonic-gate 21120Sstevel@tonic-gate if (errflag || (optind >= argc) || (!z_flag && !x_flag)) { 21130Sstevel@tonic-gate if (!(V_flag && (argc == 2))) { 21140Sstevel@tonic-gate usage(); 21150Sstevel@tonic-gate exit(269); 21160Sstevel@tonic-gate } 21170Sstevel@tonic-gate } 21180Sstevel@tonic-gate 21191618Srie if (elf_version(EV_CURRENT) == EV_NONE) { 21201618Srie (void) fprintf(stderr, "%s: libelf is out of date\n", 21211618Srie prog_name); 21221618Srie exit(101); 21231618Srie } 21241618Srie 21250Sstevel@tonic-gate while (optind < argc) { 21260Sstevel@tonic-gate each_file(argv[optind]); 21270Sstevel@tonic-gate optind++; 21280Sstevel@tonic-gate } 21290Sstevel@tonic-gate return (0); 21300Sstevel@tonic-gate } 2131