17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 215aefb655Srie 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T 247c478bd9Sstevel@tonic-gate * Copyright (c) 1989 AT&T 257c478bd9Sstevel@tonic-gate * All Rights Reserved 267c478bd9Sstevel@tonic-gate * 271e67f0f0SAli Bahrami * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <unistd.h> 337c478bd9Sstevel@tonic-gate #include <ctype.h> 347c478bd9Sstevel@tonic-gate #include <locale.h> 357c478bd9Sstevel@tonic-gate #include <libelf.h> 367c478bd9Sstevel@tonic-gate #include <sys/elf_SPARC.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /* exit return codes */ 407c478bd9Sstevel@tonic-gate #define NOARGS 1 417c478bd9Sstevel@tonic-gate #define BADELF 2 427c478bd9Sstevel@tonic-gate #define NOALLOC 3 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate #include <fcntl.h> 457c478bd9Sstevel@tonic-gate #include <sys/stat.h> 467c478bd9Sstevel@tonic-gate #include <errno.h> 477c478bd9Sstevel@tonic-gate #include <string.h> 487c478bd9Sstevel@tonic-gate #include <dlfcn.h> 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #include "sgs.h" 517c478bd9Sstevel@tonic-gate #include "conv.h" 527c478bd9Sstevel@tonic-gate #include "gelf.h" 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate typedef struct { /* structure to translate symbol table data */ 557c478bd9Sstevel@tonic-gate int indx; 567c478bd9Sstevel@tonic-gate char *name; 577c478bd9Sstevel@tonic-gate GElf_Addr value; 587c478bd9Sstevel@tonic-gate GElf_Xword size; 597c478bd9Sstevel@tonic-gate int type; 607c478bd9Sstevel@tonic-gate int bind; 617c478bd9Sstevel@tonic-gate unsigned char other; 627c478bd9Sstevel@tonic-gate unsigned int shndx; 637c478bd9Sstevel@tonic-gate unsigned int flags; /* flags relevant to entry */ 647c478bd9Sstevel@tonic-gate } SYM; 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate #define FLG_SYM_SPECSEC 0x00000001 /* reserved scn index */ 677c478bd9Sstevel@tonic-gate /* (SHN_ABS, SHN_COMMON, ...) */ 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate #define UNDEFINED "U" 707c478bd9Sstevel@tonic-gate #define BSS_GLOB "B" 717c478bd9Sstevel@tonic-gate #define BSS_WEAK "B*" 727c478bd9Sstevel@tonic-gate #define BSS_LOCL "b" 737c478bd9Sstevel@tonic-gate #define BSS_SECN ".bss" 747c478bd9Sstevel@tonic-gate #define REG_GLOB "R" 757c478bd9Sstevel@tonic-gate #define REG_WEAK "R*" 767c478bd9Sstevel@tonic-gate #define REG_LOCL "r" 777c478bd9Sstevel@tonic-gate 787a5d89c4Sab196087 #define OPTSTR ":APDoxhvnursplLCVefgRTt:" /* option string for getopt() */ 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate #define DATESIZE 60 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate #define TYPE 7 837c478bd9Sstevel@tonic-gate #define BIND 3 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate #define DEF_MAX_SYM_SIZE 256 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate static char *key[TYPE][BIND]; 887c478bd9Sstevel@tonic-gate 89bdcb2466Sab196087 /* 90bdcb2466Sab196087 * Format type used for printing value and size items. 91bdcb2466Sab196087 * The non-negative values here are used as array indices into 92bdcb2466Sab196087 * several arrays found below. Renumbering, or adding items, 93bdcb2466Sab196087 * will require changes to those arrays as well. 94bdcb2466Sab196087 */ 95bdcb2466Sab196087 typedef enum { 96bdcb2466Sab196087 FMT_T_NONE = -1, /* No format type yet assigned */ 97bdcb2466Sab196087 98bdcb2466Sab196087 /* The following are used as array indices */ 99bdcb2466Sab196087 FMT_T_DEC = 0, 100bdcb2466Sab196087 FMT_T_HEX = 1, 101bdcb2466Sab196087 FMT_T_OCT = 2 102bdcb2466Sab196087 } FMT_T; 103bdcb2466Sab196087 104bdcb2466Sab196087 /* 105bdcb2466Sab196087 * Determine whether a proposed format type is compatible with the current 106bdcb2466Sab196087 * setting. We allow setting the format as long as it hasn't already 107bdcb2466Sab196087 * been done, or if the new setting is the same as the current one. 108bdcb2466Sab196087 */ 109bdcb2466Sab196087 #define COMPAT_FMT_FLAG(new_fmt_flag) \ 110bdcb2466Sab196087 (fmt_flag == FMT_T_NONE) || (fmt_flag == new_fmt_flag) 111bdcb2466Sab196087 112bdcb2466Sab196087 static FMT_T fmt_flag = FMT_T_NONE; /* format style to use for value/size */ 113bdcb2466Sab196087 1147c478bd9Sstevel@tonic-gate static int /* flags: ?_flag corresponds to ? option */ 1157c478bd9Sstevel@tonic-gate h_flag = 0, /* suppress printing of headings */ 1167c478bd9Sstevel@tonic-gate v_flag = 0, /* sort external symbols by value */ 1177c478bd9Sstevel@tonic-gate n_flag = 0, /* sort external symbols by name */ 1187c478bd9Sstevel@tonic-gate u_flag = 0, /* print only undefined symbols */ 1197c478bd9Sstevel@tonic-gate r_flag = 0, /* prepend object file or archive name */ 1207c478bd9Sstevel@tonic-gate /* to each symbol name */ 1217c478bd9Sstevel@tonic-gate R_flag = 0, /* if "-R" issued then prepend archive name, */ 1227c478bd9Sstevel@tonic-gate /* object file name to each symbol */ 1237c478bd9Sstevel@tonic-gate s_flag = 0, /* print section name instead of section index */ 1247c478bd9Sstevel@tonic-gate p_flag = 0, /* produce terse output */ 1257c478bd9Sstevel@tonic-gate P_flag = 0, /* Portable format output */ 1267c478bd9Sstevel@tonic-gate l_flag = 0, /* produce long listing of output */ 1277a5d89c4Sab196087 L_flag = 0, /* print SUNW_LDYNSYM instead of SYMTAB */ 1287c478bd9Sstevel@tonic-gate D_flag = 0, /* print DYNSYM instead of SYMTAB */ 1297c478bd9Sstevel@tonic-gate C_flag = 0, /* print decoded C++ names */ 130bdcb2466Sab196087 A_flag = 0, /* File name */ 1317c478bd9Sstevel@tonic-gate e_flag = 0, /* -e flag */ 1327c478bd9Sstevel@tonic-gate g_flag = 0, /* -g flag */ 1337c478bd9Sstevel@tonic-gate V_flag = 0; /* print version information */ 1347c478bd9Sstevel@tonic-gate static char A_header[DEF_MAX_SYM_SIZE+1] = {0}; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate static char *prog_name; 1377c478bd9Sstevel@tonic-gate static char *archive_name = (char *)0; 1387c478bd9Sstevel@tonic-gate static int errflag = 0; 1397c478bd9Sstevel@tonic-gate static void usage(); 1407c478bd9Sstevel@tonic-gate static void each_file(char *); 1417c478bd9Sstevel@tonic-gate static void process(Elf *, char *); 1427c478bd9Sstevel@tonic-gate static Elf_Scn * get_scnfd(Elf *, int, int); 143ba4e3c84Sab196087 static void get_symtab(Elf *, char *); 1447c478bd9Sstevel@tonic-gate static SYM * readsyms(Elf_Data *, GElf_Sxword, Elf *, unsigned int, 1457c478bd9Sstevel@tonic-gate unsigned int); 1467c478bd9Sstevel@tonic-gate static int compare(SYM *, SYM *); 1477c478bd9Sstevel@tonic-gate static char *lookup(int, int); 1487c478bd9Sstevel@tonic-gate static int is_bss_section(unsigned int, Elf *, unsigned int); 1497c478bd9Sstevel@tonic-gate static void print_ar_files(int, Elf *, char *); 150ba4e3c84Sab196087 static void print_symtab(Elf *, unsigned int, Elf_Scn *, GElf_Shdr *, char *); 1517c478bd9Sstevel@tonic-gate static void parsename(char *); 1527c478bd9Sstevel@tonic-gate static void parse_fn_and_print(const char *, char *); 1537c478bd9Sstevel@tonic-gate static char d_buf[512]; 1547c478bd9Sstevel@tonic-gate static char p_buf[512]; 155af79d7d9SAli Bahrami static int exotic(const char *s); 1567c478bd9Sstevel@tonic-gate static void set_A_header(char *); 157b9bd317cSab196087 static char *FormatName(char *, const char *); 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Parses the command line options and then 1637c478bd9Sstevel@tonic-gate * calls each_file() to process each file. 1647c478bd9Sstevel@tonic-gate */ 1657c478bd9Sstevel@tonic-gate int 1667c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char *envp[]) 1677c478bd9Sstevel@tonic-gate { 1687c478bd9Sstevel@tonic-gate char *optstr = OPTSTR; /* option string used by getopt() */ 1697c478bd9Sstevel@tonic-gate int optchar; 170bdcb2466Sab196087 FMT_T new_fmt_flag; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate #ifndef XPG4 1737c478bd9Sstevel@tonic-gate /* 1747c478bd9Sstevel@tonic-gate * Check for a binary that better fits this architecture. 1757c478bd9Sstevel@tonic-gate */ 1767010c12aSrie (void) conv_check_native(argv, envp); 1777c478bd9Sstevel@tonic-gate #endif 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* table of keyletters for use with -p and -P options */ 1807c478bd9Sstevel@tonic-gate key[STT_NOTYPE][STB_LOCAL] = "n"; 1817c478bd9Sstevel@tonic-gate key[STT_NOTYPE][STB_GLOBAL] = "N"; 1827c478bd9Sstevel@tonic-gate key[STT_NOTYPE][STB_WEAK] = "N*"; 1837c478bd9Sstevel@tonic-gate key[STT_OBJECT][STB_LOCAL] = "d"; 1847c478bd9Sstevel@tonic-gate key[STT_OBJECT][STB_GLOBAL] = "D"; 1857c478bd9Sstevel@tonic-gate key[STT_OBJECT][STB_WEAK] = "D*"; 1867c478bd9Sstevel@tonic-gate key[STT_FUNC][STB_LOCAL] = "t"; 1877c478bd9Sstevel@tonic-gate key[STT_FUNC][STB_GLOBAL] = "T"; 1887c478bd9Sstevel@tonic-gate key[STT_FUNC][STB_WEAK] = "T*"; 1897c478bd9Sstevel@tonic-gate key[STT_SECTION][STB_LOCAL] = "s"; 1907c478bd9Sstevel@tonic-gate key[STT_SECTION][STB_GLOBAL] = "S"; 1917c478bd9Sstevel@tonic-gate key[STT_SECTION][STB_WEAK] = "S*"; 1927c478bd9Sstevel@tonic-gate key[STT_FILE][STB_LOCAL] = "f"; 1937c478bd9Sstevel@tonic-gate key[STT_FILE][STB_GLOBAL] = "F"; 1947c478bd9Sstevel@tonic-gate key[STT_FILE][STB_WEAK] = "F*"; 1957c478bd9Sstevel@tonic-gate key[STT_COMMON][STB_LOCAL] = "c"; 1967c478bd9Sstevel@tonic-gate key[STT_COMMON][STB_GLOBAL] = "C"; 1977c478bd9Sstevel@tonic-gate key[STT_COMMON][STB_WEAK] = "C*"; 1987c478bd9Sstevel@tonic-gate key[STT_TLS][STB_LOCAL] = "l"; 1997c478bd9Sstevel@tonic-gate key[STT_TLS][STB_GLOBAL] = "L"; 2007c478bd9Sstevel@tonic-gate key[STT_TLS][STB_WEAK] = "L*"; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate prog_name = argv[0]; 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2057c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 2067c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 2077c478bd9Sstevel@tonic-gate #endif 2087c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate while ((optchar = getopt(argc, argv, optstr)) != -1) { 2117c478bd9Sstevel@tonic-gate switch (optchar) { 212bdcb2466Sab196087 case 'o': if (COMPAT_FMT_FLAG(FMT_T_OCT)) 213bdcb2466Sab196087 fmt_flag = FMT_T_OCT; 2147c478bd9Sstevel@tonic-gate else 2157c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 216bdcb2466Sab196087 "%s: -x or -t set, -o ignored\n"), 2177c478bd9Sstevel@tonic-gate prog_name); 2187c478bd9Sstevel@tonic-gate break; 219bdcb2466Sab196087 case 'x': if (COMPAT_FMT_FLAG(FMT_T_HEX)) 220bdcb2466Sab196087 fmt_flag = FMT_T_HEX; 2217c478bd9Sstevel@tonic-gate else 2227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 223bdcb2466Sab196087 "%s: -o or -t set, -x ignored\n"), 2247c478bd9Sstevel@tonic-gate prog_name); 2257c478bd9Sstevel@tonic-gate break; 2267c478bd9Sstevel@tonic-gate case 'h': h_flag = 1; 2277c478bd9Sstevel@tonic-gate break; 2287c478bd9Sstevel@tonic-gate case 'v': if (!n_flag) 2297c478bd9Sstevel@tonic-gate v_flag = 1; 2307c478bd9Sstevel@tonic-gate else 2317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2327c478bd9Sstevel@tonic-gate "%s: -n set, -v ignored\n"), 2337c478bd9Sstevel@tonic-gate prog_name); 2347c478bd9Sstevel@tonic-gate break; 2357c478bd9Sstevel@tonic-gate case 'n': if (!v_flag) 2367c478bd9Sstevel@tonic-gate n_flag = 1; 2377c478bd9Sstevel@tonic-gate else 2387c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2397c478bd9Sstevel@tonic-gate "%s: -v set, -n ignored\n"), 2407c478bd9Sstevel@tonic-gate prog_name); 2417c478bd9Sstevel@tonic-gate break; 2427c478bd9Sstevel@tonic-gate case 'u': if (!e_flag && !g_flag) 2437c478bd9Sstevel@tonic-gate u_flag = 1; 2447c478bd9Sstevel@tonic-gate else 2457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2467c478bd9Sstevel@tonic-gate "%s: -e or -g set, -u ignored\n"), 2477c478bd9Sstevel@tonic-gate prog_name); 2487c478bd9Sstevel@tonic-gate break; 2497c478bd9Sstevel@tonic-gate case 'e': if (!u_flag && !g_flag) 2507c478bd9Sstevel@tonic-gate e_flag = 1; 2517c478bd9Sstevel@tonic-gate else 2527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2537c478bd9Sstevel@tonic-gate "%s: -u or -g set, -e ignored\n"), 2547c478bd9Sstevel@tonic-gate prog_name); 2557c478bd9Sstevel@tonic-gate break; 2567c478bd9Sstevel@tonic-gate case 'g': if (!u_flag && !e_flag) 2577c478bd9Sstevel@tonic-gate g_flag = 1; 2587c478bd9Sstevel@tonic-gate else 2597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2607c478bd9Sstevel@tonic-gate "%s: -u or -e set, -g ignored\n"), 2617c478bd9Sstevel@tonic-gate prog_name); 2627c478bd9Sstevel@tonic-gate break; 2637c478bd9Sstevel@tonic-gate case 'r': if (R_flag) { 2647c478bd9Sstevel@tonic-gate R_flag = 0; 2657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2667c478bd9Sstevel@tonic-gate "%s: -r set, -R ignored\n"), 2677c478bd9Sstevel@tonic-gate prog_name); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate r_flag = 1; 2707c478bd9Sstevel@tonic-gate break; 2717c478bd9Sstevel@tonic-gate case 's': s_flag = 1; 2727c478bd9Sstevel@tonic-gate break; 2737c478bd9Sstevel@tonic-gate case 'p': if (P_flag == 1) { 2747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2757c478bd9Sstevel@tonic-gate "nm: -P set. -p ignored\n")); 2767c478bd9Sstevel@tonic-gate } else 2777c478bd9Sstevel@tonic-gate p_flag = 1; 2787c478bd9Sstevel@tonic-gate break; 2797c478bd9Sstevel@tonic-gate case 'P': if (p_flag == 1) { 2807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2817c478bd9Sstevel@tonic-gate "nm: -p set. -P ignored\n")); 2827c478bd9Sstevel@tonic-gate } else 2837c478bd9Sstevel@tonic-gate P_flag = 1; 2847c478bd9Sstevel@tonic-gate break; 2857c478bd9Sstevel@tonic-gate case 'l': l_flag = 1; 2867c478bd9Sstevel@tonic-gate break; 2877a5d89c4Sab196087 case 'L': if (D_flag == 1) { 2887a5d89c4Sab196087 (void) fprintf(stderr, gettext( 2897a5d89c4Sab196087 "nm: -D set. -L ignored\n")); 2907a5d89c4Sab196087 } else 2917a5d89c4Sab196087 L_flag = 1; 2927a5d89c4Sab196087 break; 2937a5d89c4Sab196087 case 'D': if (L_flag == 1) { 2947a5d89c4Sab196087 (void) fprintf(stderr, gettext( 2957a5d89c4Sab196087 "nm: -L set. -D ignored\n")); 2967a5d89c4Sab196087 } else 2977a5d89c4Sab196087 D_flag = 1; 2987c478bd9Sstevel@tonic-gate break; 2997c478bd9Sstevel@tonic-gate case 'C': 3007c478bd9Sstevel@tonic-gate C_flag = 1; 3017c478bd9Sstevel@tonic-gate break; 3027c478bd9Sstevel@tonic-gate case 'A': A_flag = 1; 3037c478bd9Sstevel@tonic-gate break; 3047c478bd9Sstevel@tonic-gate case 'V': V_flag = 1; 305b9bd317cSab196087 (void) fprintf(stderr, "nm: %s %s\n", 3067c478bd9Sstevel@tonic-gate (const char *)SGU_PKG, 3077c478bd9Sstevel@tonic-gate (const char *)SGU_REL); 3087c478bd9Sstevel@tonic-gate break; 3097c478bd9Sstevel@tonic-gate case 'f': /* -f is a noop, see man page */ 3107c478bd9Sstevel@tonic-gate break; 3117c478bd9Sstevel@tonic-gate case 'R': if (!r_flag) 3127c478bd9Sstevel@tonic-gate R_flag = 1; 3137c478bd9Sstevel@tonic-gate else 3147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3157c478bd9Sstevel@tonic-gate "%s: -r set, -R ignored\n"), 3167c478bd9Sstevel@tonic-gate prog_name); 3177c478bd9Sstevel@tonic-gate break; 3187c478bd9Sstevel@tonic-gate case 'T': 3197c478bd9Sstevel@tonic-gate break; 320bdcb2466Sab196087 case 't': if (strcmp(optarg, "o") == 0) { 321bdcb2466Sab196087 new_fmt_flag = FMT_T_OCT; 3227c478bd9Sstevel@tonic-gate } else if (strcmp(optarg, "d") == 0) { 323bdcb2466Sab196087 new_fmt_flag = FMT_T_DEC; 3247c478bd9Sstevel@tonic-gate } else if (strcmp(optarg, "x") == 0) { 325bdcb2466Sab196087 new_fmt_flag = FMT_T_HEX; 3267c478bd9Sstevel@tonic-gate } else { 327bdcb2466Sab196087 new_fmt_flag = FMT_T_NONE; 328bdcb2466Sab196087 } 329bdcb2466Sab196087 if (new_fmt_flag == FMT_T_NONE) { 3301e67f0f0SAli Bahrami errflag += 1; 3317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3321e67f0f0SAli Bahrami "nm: -t requires radix value (d, o, x): %s\n"), optarg); 333bdcb2466Sab196087 } else if (COMPAT_FMT_FLAG(new_fmt_flag)) { 334bdcb2466Sab196087 fmt_flag = new_fmt_flag; 335bdcb2466Sab196087 } else { 336bdcb2466Sab196087 (void) fprintf(stderr, gettext( 337bdcb2466Sab196087 "nm: -t or -o or -x set. -t ignored.\n")); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate break; 3407c478bd9Sstevel@tonic-gate case ':': errflag += 1; 3417c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 342b9bd317cSab196087 "nm: %c requires operand\n"), optopt); 3437c478bd9Sstevel@tonic-gate break; 3447c478bd9Sstevel@tonic-gate case '?': errflag += 1; 3457c478bd9Sstevel@tonic-gate break; 3467c478bd9Sstevel@tonic-gate default: break; 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (errflag || (optind >= argc)) { 3517c478bd9Sstevel@tonic-gate if (!(V_flag && (argc == 2))) { 3527c478bd9Sstevel@tonic-gate usage(); 3537c478bd9Sstevel@tonic-gate exit(NOARGS); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 357bdcb2466Sab196087 /* 358bdcb2466Sab196087 * If no explicit format style was specified, set the default 359bdcb2466Sab196087 * here. In general, the default is for value and size items 360bdcb2466Sab196087 * to be displayed in decimal format. The exception is that 361bdcb2466Sab196087 * the default for -P is hexidecimal. 362bdcb2466Sab196087 */ 363bdcb2466Sab196087 if (fmt_flag == FMT_T_NONE) 364bdcb2466Sab196087 fmt_flag = P_flag ? FMT_T_HEX : FMT_T_DEC; 365bdcb2466Sab196087 366bdcb2466Sab196087 3677c478bd9Sstevel@tonic-gate while (optind < argc) { 3687c478bd9Sstevel@tonic-gate each_file(argv[optind]); 3697c478bd9Sstevel@tonic-gate optind++; 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate return (errflag); 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate /* 3757c478bd9Sstevel@tonic-gate * Print out a usage message in short form when program is invoked 3767c478bd9Sstevel@tonic-gate * with insufficient or no arguments, and in long form when given 3777c478bd9Sstevel@tonic-gate * either a ? or an invalid option. 3787c478bd9Sstevel@tonic-gate */ 3797c478bd9Sstevel@tonic-gate static void 3807c478bd9Sstevel@tonic-gate usage() 3817c478bd9Sstevel@tonic-gate { 3827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3835bd55801SAli Bahrami "Usage: nm [-ACDhLlnPpRrsTVv] [-efox] [-g | -u] [-t d|o|x] file ...\n")); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate /* 3877c478bd9Sstevel@tonic-gate * Takes a filename as input. Test first for a valid version 3887c478bd9Sstevel@tonic-gate * of libelf.a and exit on error. Process each valid file 3897c478bd9Sstevel@tonic-gate * or archive given as input on the command line. Check 3907c478bd9Sstevel@tonic-gate * for file type. If it is an archive, call print_ar_files 3917c478bd9Sstevel@tonic-gate * to process each member of the archive in the same manner 3927c478bd9Sstevel@tonic-gate * as object files on the command line. The same tests for 3937c478bd9Sstevel@tonic-gate * valid object file type apply to regular archive members. 3947c478bd9Sstevel@tonic-gate * If it is an ELF object file, process it; otherwise 3957c478bd9Sstevel@tonic-gate * warn that it is an invalid file type and return from 3967c478bd9Sstevel@tonic-gate * processing the file. 3977c478bd9Sstevel@tonic-gate */ 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate static void 4007c478bd9Sstevel@tonic-gate each_file(char *filename) 4017c478bd9Sstevel@tonic-gate { 4027c478bd9Sstevel@tonic-gate Elf *elf_file; 4037c478bd9Sstevel@tonic-gate int fd; 4047c478bd9Sstevel@tonic-gate Elf_Kind file_type; 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate struct stat64 buf; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate Elf_Cmd cmd; 4097c478bd9Sstevel@tonic-gate errno = 0; 4107c478bd9Sstevel@tonic-gate if (stat64(filename, &buf) == -1) { 411b9bd317cSab196087 (void) fprintf(stderr, "%s: ", prog_name); 4127c478bd9Sstevel@tonic-gate perror(filename); 4137c478bd9Sstevel@tonic-gate errflag++; 4147c478bd9Sstevel@tonic-gate return; 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate if (elf_version(EV_CURRENT) == EV_NONE) { 4177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4181e67f0f0SAli Bahrami "%s: %s: libelf is out of date\n"), 4197c478bd9Sstevel@tonic-gate prog_name, filename); 4207c478bd9Sstevel@tonic-gate exit(BADELF); 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if ((fd = open((filename), O_RDONLY)) == -1) { 424b9bd317cSab196087 (void) fprintf(stderr, gettext("%s: %s: cannot read file\n"), 4257c478bd9Sstevel@tonic-gate prog_name, filename); 4267c478bd9Sstevel@tonic-gate errflag++; 4277c478bd9Sstevel@tonic-gate return; 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate cmd = ELF_C_READ; 4307c478bd9Sstevel@tonic-gate if ((elf_file = elf_begin(fd, cmd, (Elf *) 0)) == NULL) { 4317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4327c478bd9Sstevel@tonic-gate "%s: %s: %s\n", prog_name, filename, elf_errmsg(-1)); 4337c478bd9Sstevel@tonic-gate errflag++; 4347c478bd9Sstevel@tonic-gate (void) close(fd); 4357c478bd9Sstevel@tonic-gate return; 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate file_type = elf_kind(elf_file); 4387c478bd9Sstevel@tonic-gate if (file_type == ELF_K_AR) { 4397c478bd9Sstevel@tonic-gate print_ar_files(fd, elf_file, filename); 4407c478bd9Sstevel@tonic-gate } else { 4417c478bd9Sstevel@tonic-gate if (file_type == ELF_K_ELF) { 4427c478bd9Sstevel@tonic-gate #ifndef XPG4 4437c478bd9Sstevel@tonic-gate if (u_flag && !h_flag) { 4447c478bd9Sstevel@tonic-gate /* 4457c478bd9Sstevel@tonic-gate * u_flag is specified. 4467c478bd9Sstevel@tonic-gate */ 4477c478bd9Sstevel@tonic-gate if (p_flag) 448b9bd317cSab196087 (void) printf("\n\n%s:\n\n", filename); 4497c478bd9Sstevel@tonic-gate else 4507c478bd9Sstevel@tonic-gate (void) printf(gettext( 4517c478bd9Sstevel@tonic-gate "\n\nUndefined symbols from %s:\n\n"), 4527c478bd9Sstevel@tonic-gate filename); 4537c478bd9Sstevel@tonic-gate } else if (!h_flag & !P_flag) 4547c478bd9Sstevel@tonic-gate #else 4557c478bd9Sstevel@tonic-gate if (!h_flag & !P_flag) 4567c478bd9Sstevel@tonic-gate #endif 4577c478bd9Sstevel@tonic-gate { 4587c478bd9Sstevel@tonic-gate if (p_flag) 459b9bd317cSab196087 (void) printf("\n\n%s:\n", filename); 4607c478bd9Sstevel@tonic-gate else { 4617c478bd9Sstevel@tonic-gate if (A_flag != 0) 462b9bd317cSab196087 (void) printf("\n\n%s%s:\n", 463b9bd317cSab196087 A_header, filename); 4647c478bd9Sstevel@tonic-gate else 465b9bd317cSab196087 (void) printf("\n\n%s:\n", 4667c478bd9Sstevel@tonic-gate filename); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate archive_name = (char *)0; 4707c478bd9Sstevel@tonic-gate process(elf_file, filename); 4717c478bd9Sstevel@tonic-gate } else { 4727c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4737c478bd9Sstevel@tonic-gate "%s: %s: invalid file type\n"), 4747c478bd9Sstevel@tonic-gate prog_name, filename); 4757c478bd9Sstevel@tonic-gate errflag++; 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate (void) elf_end(elf_file); 4797c478bd9Sstevel@tonic-gate (void) close(fd); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* 4837c478bd9Sstevel@tonic-gate * Get the ELF header and, if it exists, call get_symtab() 4847c478bd9Sstevel@tonic-gate * to begin processing of the file; otherwise, return from 4857c478bd9Sstevel@tonic-gate * processing the file with a warning. 4867c478bd9Sstevel@tonic-gate */ 4877c478bd9Sstevel@tonic-gate static void 4887c478bd9Sstevel@tonic-gate process(Elf *elf_file, char *filename) 4897c478bd9Sstevel@tonic-gate { 4907c478bd9Sstevel@tonic-gate GElf_Ehdr ehdr; 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate if (gelf_getehdr(elf_file, &ehdr) == NULL) { 4937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4947c478bd9Sstevel@tonic-gate "%s: %s: %s\n", prog_name, filename, elf_errmsg(-1)); 4957c478bd9Sstevel@tonic-gate return; 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate set_A_header(filename); 499ba4e3c84Sab196087 get_symtab(elf_file, filename); 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate /* 5037c478bd9Sstevel@tonic-gate * Get section descriptor for the associated string table 5047c478bd9Sstevel@tonic-gate * and verify that the type of the section pointed to is 5057c478bd9Sstevel@tonic-gate * indeed of type STRTAB. Returns a valid section descriptor 5067c478bd9Sstevel@tonic-gate * or NULL on error. 5077c478bd9Sstevel@tonic-gate */ 5087c478bd9Sstevel@tonic-gate static Elf_Scn * 5097c478bd9Sstevel@tonic-gate get_scnfd(Elf * e_file, int shstrtab, int SCN_TYPE) 5107c478bd9Sstevel@tonic-gate { 5117c478bd9Sstevel@tonic-gate Elf_Scn *fd_scn; 5127c478bd9Sstevel@tonic-gate GElf_Shdr shdr; 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate if ((fd_scn = elf_getscn(e_file, shstrtab)) == NULL) { 5157c478bd9Sstevel@tonic-gate return (NULL); 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate (void) gelf_getshdr(fd_scn, &shdr); 5197c478bd9Sstevel@tonic-gate if (shdr.sh_type != SCN_TYPE) { 5207c478bd9Sstevel@tonic-gate return (NULL); 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate return (fd_scn); 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate /* 5277c478bd9Sstevel@tonic-gate * Print the symbol table. This function does not print the contents 5287c478bd9Sstevel@tonic-gate * of the symbol table but sets up the parameters and then calls 5297c478bd9Sstevel@tonic-gate * print_symtab to print the symbols. This function does not assume 5307c478bd9Sstevel@tonic-gate * that there is only one section of type SYMTAB. Input is an opened 5317c478bd9Sstevel@tonic-gate * ELF file, a pointer to the ELF header, and the filename. 5327c478bd9Sstevel@tonic-gate */ 5337c478bd9Sstevel@tonic-gate static void 534ba4e3c84Sab196087 get_symtab(Elf *elf_file, char *filename) 5357c478bd9Sstevel@tonic-gate { 5367c478bd9Sstevel@tonic-gate Elf_Scn *scn, *scnfd; 5377c478bd9Sstevel@tonic-gate Elf_Data *data; 5387c478bd9Sstevel@tonic-gate GElf_Word symtabtype; 5397c478bd9Sstevel@tonic-gate size_t shstrndx; 5407c478bd9Sstevel@tonic-gate 54162b628a6SAli Bahrami if (elf_getshdrstrndx(elf_file, &shstrndx) == -1) { 5427c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 5431e67f0f0SAli Bahrami "%s: %s: cannot get e_shstrndx\n"), 5447c478bd9Sstevel@tonic-gate prog_name, filename); 5457c478bd9Sstevel@tonic-gate return; 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate /* get section header string table */ 5497c478bd9Sstevel@tonic-gate scnfd = get_scnfd(elf_file, shstrndx, SHT_STRTAB); 5507c478bd9Sstevel@tonic-gate if (scnfd == NULL) { 5517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 5521e67f0f0SAli Bahrami "%s: %s: cannot get string table\n"), 5537c478bd9Sstevel@tonic-gate prog_name, filename); 5547c478bd9Sstevel@tonic-gate return; 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate data = elf_getdata(scnfd, NULL); 5587c478bd9Sstevel@tonic-gate if (data->d_size == 0) { 5597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 5607c478bd9Sstevel@tonic-gate "%s: %s: no data in string table\n"), 5617c478bd9Sstevel@tonic-gate prog_name, filename); 5627c478bd9Sstevel@tonic-gate return; 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate if (D_flag) 5667c478bd9Sstevel@tonic-gate symtabtype = SHT_DYNSYM; 5677a5d89c4Sab196087 else if (L_flag) 5687a5d89c4Sab196087 symtabtype = SHT_SUNW_LDYNSYM; 5697c478bd9Sstevel@tonic-gate else 5707c478bd9Sstevel@tonic-gate symtabtype = SHT_SYMTAB; 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate scn = 0; 5737c478bd9Sstevel@tonic-gate while ((scn = elf_nextscn(elf_file, scn)) != 0) { 5747c478bd9Sstevel@tonic-gate GElf_Shdr shdr; 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate if (gelf_getshdr(scn, &shdr) == NULL) { 577b9bd317cSab196087 (void) fprintf(stderr, "%s: %s: %s:\n", 578b9bd317cSab196087 prog_name, filename, elf_errmsg(-1)); 5797c478bd9Sstevel@tonic-gate return; 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate if (shdr.sh_type == symtabtype) { 583ba4e3c84Sab196087 print_symtab(elf_file, shstrndx, scn, 5847c478bd9Sstevel@tonic-gate &shdr, filename); 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate } /* end while */ 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate /* 5907c478bd9Sstevel@tonic-gate * Process member files of an archive. This function provides 5917c478bd9Sstevel@tonic-gate * a loop through an archive equivalent the processing of 5927c478bd9Sstevel@tonic-gate * each_file for individual object files. 5937c478bd9Sstevel@tonic-gate */ 5947c478bd9Sstevel@tonic-gate static void 5957c478bd9Sstevel@tonic-gate print_ar_files(int fd, Elf * elf_file, char *filename) 5967c478bd9Sstevel@tonic-gate { 5977c478bd9Sstevel@tonic-gate Elf_Arhdr *p_ar; 5987c478bd9Sstevel@tonic-gate Elf *arf; 5997c478bd9Sstevel@tonic-gate Elf_Cmd cmd; 6007c478bd9Sstevel@tonic-gate Elf_Kind file_type; 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate cmd = ELF_C_READ; 6047c478bd9Sstevel@tonic-gate archive_name = filename; 6057c478bd9Sstevel@tonic-gate while ((arf = elf_begin(fd, cmd, elf_file)) != 0) { 6067c478bd9Sstevel@tonic-gate p_ar = elf_getarhdr(arf); 6077c478bd9Sstevel@tonic-gate if (p_ar == NULL) { 608b9bd317cSab196087 (void) fprintf(stderr, "%s: %s: %s\n", 609b9bd317cSab196087 prog_name, filename, elf_errmsg(-1)); 6107c478bd9Sstevel@tonic-gate return; 6117c478bd9Sstevel@tonic-gate } 612*ba7866cdSAli Bahrami if (p_ar->ar_name[0] == '/') { 6137c478bd9Sstevel@tonic-gate cmd = elf_next(arf); 6147c478bd9Sstevel@tonic-gate (void) elf_end(arf); 6157c478bd9Sstevel@tonic-gate continue; 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate if (!h_flag & !P_flag) { 6197c478bd9Sstevel@tonic-gate if (p_flag) 6207c478bd9Sstevel@tonic-gate (void) printf("\n\n%s[%s]:\n", 6217c478bd9Sstevel@tonic-gate filename, p_ar->ar_name); 6227c478bd9Sstevel@tonic-gate else { 6237c478bd9Sstevel@tonic-gate if (A_flag != 0) 624b9bd317cSab196087 (void) printf("\n\n%s%s[%s]:\n", 625b9bd317cSab196087 A_header, filename, p_ar->ar_name); 6267c478bd9Sstevel@tonic-gate else 627b9bd317cSab196087 (void) printf("\n\n%s[%s]:\n", 6287c478bd9Sstevel@tonic-gate filename, p_ar->ar_name); 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate file_type = elf_kind(arf); 6327c478bd9Sstevel@tonic-gate if (file_type == ELF_K_ELF) { 6337c478bd9Sstevel@tonic-gate process(arf, p_ar->ar_name); 6347c478bd9Sstevel@tonic-gate } else { 6357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6367c478bd9Sstevel@tonic-gate "%s: %s: invalid file type\n"), 6377c478bd9Sstevel@tonic-gate prog_name, p_ar->ar_name); 6387c478bd9Sstevel@tonic-gate cmd = elf_next(arf); 6397c478bd9Sstevel@tonic-gate (void) elf_end(arf); 6407c478bd9Sstevel@tonic-gate errflag++; 6417c478bd9Sstevel@tonic-gate continue; 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate cmd = elf_next(arf); 6457c478bd9Sstevel@tonic-gate (void) elf_end(arf); 6467c478bd9Sstevel@tonic-gate } /* end while */ 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 649d67944fbSScott Rotondo static void print_header(int); 650d67944fbSScott Rotondo #ifndef XPG4 651d67944fbSScott Rotondo static void print_with_uflag(SYM *, char *); 652d67944fbSScott Rotondo #endif 653d67944fbSScott Rotondo static void print_with_pflag(int, Elf *, unsigned int, SYM *, char *); 654d67944fbSScott Rotondo static void print_with_Pflag(int, Elf *, unsigned int, SYM *); 655d67944fbSScott Rotondo static void print_with_otherflags(int, Elf *, unsigned int, 656d67944fbSScott Rotondo SYM *, char *); 6577c478bd9Sstevel@tonic-gate /* 6587c478bd9Sstevel@tonic-gate * Print the symbol table according to the flags that were 6597c478bd9Sstevel@tonic-gate * set, if any. Input is an opened ELF file, the section name, 6607c478bd9Sstevel@tonic-gate * the section header, the section descriptor, and the filename. 6617c478bd9Sstevel@tonic-gate * First get the symbol table with a call to elf_getdata. 6627c478bd9Sstevel@tonic-gate * Then translate the symbol table data in memory by calling 6637c478bd9Sstevel@tonic-gate * readsyms(). This avoids duplication of function calls 6647c478bd9Sstevel@tonic-gate * and improves sorting efficiency. qsort is used when sorting 6657c478bd9Sstevel@tonic-gate * is requested. 6667c478bd9Sstevel@tonic-gate */ 6677c478bd9Sstevel@tonic-gate static void 668ba4e3c84Sab196087 print_symtab(Elf *elf_file, unsigned int shstrndx, 6697c478bd9Sstevel@tonic-gate Elf_Scn *p_sd, GElf_Shdr *shdr, char *filename) 6707c478bd9Sstevel@tonic-gate { 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate Elf_Data * sd; 6737c478bd9Sstevel@tonic-gate SYM *sym_data; 6747c478bd9Sstevel@tonic-gate SYM *s; 6757c478bd9Sstevel@tonic-gate GElf_Sxword count = 0; 676bdcb2466Sab196087 const int ndigits_arr[] = { 677bdcb2466Sab196087 10, /* FMT_T_DEC */ 678bdcb2466Sab196087 8, /* FMT_T_HEX */ 679bdcb2466Sab196087 11, /* FMT_T_OCT */ 680bdcb2466Sab196087 }; 681ba4e3c84Sab196087 int ndigits; 682ba4e3c84Sab196087 683ba4e3c84Sab196087 /* 684ba4e3c84Sab196087 * Determine # of digits to use for each numeric value. 685ba4e3c84Sab196087 */ 686bdcb2466Sab196087 ndigits = ndigits_arr[fmt_flag]; 687ba4e3c84Sab196087 if (gelf_getclass(elf_file) == ELFCLASS64) 688ba4e3c84Sab196087 ndigits *= 2; 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate /* 6917c478bd9Sstevel@tonic-gate * print header 6927c478bd9Sstevel@tonic-gate */ 693ba4e3c84Sab196087 print_header(ndigits); 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate /* 6967c478bd9Sstevel@tonic-gate * get symbol table data 6977c478bd9Sstevel@tonic-gate */ 6987c478bd9Sstevel@tonic-gate if (((sd = elf_getdata(p_sd, NULL)) == NULL) || (sd->d_size == 0)) { 6991e67f0f0SAli Bahrami (void) fprintf(stderr, 7001e67f0f0SAli Bahrami gettext("%s: %s: no symbol table data\n"), 7017c478bd9Sstevel@tonic-gate prog_name, filename); 7027c478bd9Sstevel@tonic-gate return; 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate count = shdr->sh_size / shdr->sh_entsize; 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate /* 7077c478bd9Sstevel@tonic-gate * translate symbol table data 7087c478bd9Sstevel@tonic-gate */ 7097c478bd9Sstevel@tonic-gate sym_data = readsyms(sd, count, elf_file, shdr->sh_link, 7107c478bd9Sstevel@tonic-gate (unsigned int)elf_ndxscn(p_sd)); 7117c478bd9Sstevel@tonic-gate if (sym_data == NULL) { 7127c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7137c478bd9Sstevel@tonic-gate "%s: %s: problem reading symbol data\n"), 7147c478bd9Sstevel@tonic-gate prog_name, filename); 7157c478bd9Sstevel@tonic-gate return; 7167c478bd9Sstevel@tonic-gate } 717b9bd317cSab196087 qsort((char *)sym_data, count-1, sizeof (SYM), 7187c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *))compare); 7197c478bd9Sstevel@tonic-gate s = sym_data; 7207c478bd9Sstevel@tonic-gate while (count > 1) { 7217c478bd9Sstevel@tonic-gate #ifndef XPG4 7227c478bd9Sstevel@tonic-gate if (u_flag) { 7237c478bd9Sstevel@tonic-gate /* 7247c478bd9Sstevel@tonic-gate * U_flag specified 7257c478bd9Sstevel@tonic-gate */ 7267c478bd9Sstevel@tonic-gate print_with_uflag(sym_data, filename); 7277c478bd9Sstevel@tonic-gate } else if (p_flag) 7287c478bd9Sstevel@tonic-gate #else 7297c478bd9Sstevel@tonic-gate if (p_flag) 7307c478bd9Sstevel@tonic-gate #endif 731ba4e3c84Sab196087 print_with_pflag(ndigits, elf_file, shstrndx, 7327c478bd9Sstevel@tonic-gate sym_data, filename); 733ba4e3c84Sab196087 else if (P_flag) 734ba4e3c84Sab196087 print_with_Pflag(ndigits, elf_file, shstrndx, 735ba4e3c84Sab196087 sym_data); 736ba4e3c84Sab196087 else 737ba4e3c84Sab196087 print_with_otherflags(ndigits, elf_file, 738ba4e3c84Sab196087 shstrndx, sym_data, filename); 7397c478bd9Sstevel@tonic-gate sym_data++; 7407c478bd9Sstevel@tonic-gate count--; 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate free(s); /* allocated in readsym() */ 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate /* 7477c478bd9Sstevel@tonic-gate * Return appropriate keyletter(s) for -p option. 7487c478bd9Sstevel@tonic-gate * Returns an index into the key[][] table or NULL if 7497c478bd9Sstevel@tonic-gate * the value of the keyletter is unknown. 7507c478bd9Sstevel@tonic-gate */ 7517c478bd9Sstevel@tonic-gate static char * 7527c478bd9Sstevel@tonic-gate lookup(int a, int b) 7537c478bd9Sstevel@tonic-gate { 7547c478bd9Sstevel@tonic-gate return (((a < TYPE) && (b < BIND)) ? key[a][b] : NULL); 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate /* 7587c478bd9Sstevel@tonic-gate * Return TRUE(1) if the given section is ".bss" for "-p" option. 7597c478bd9Sstevel@tonic-gate * Return FALSE(0) if not ".bss" section. 7607c478bd9Sstevel@tonic-gate */ 7617c478bd9Sstevel@tonic-gate static int 7627c478bd9Sstevel@tonic-gate is_bss_section(unsigned int shndx, Elf * elf_file, unsigned int shstrndx) 7637c478bd9Sstevel@tonic-gate { 7647c478bd9Sstevel@tonic-gate Elf_Scn *scn = elf_getscn(elf_file, shndx); 7657c478bd9Sstevel@tonic-gate char *sym_name; 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate if (scn != NULL) { 7687c478bd9Sstevel@tonic-gate GElf_Shdr shdr; 7697c478bd9Sstevel@tonic-gate (void) gelf_getshdr(scn, &shdr); 770b9bd317cSab196087 sym_name = elf_strptr(elf_file, shstrndx, shdr.sh_name); 7717c478bd9Sstevel@tonic-gate if (strcmp(BSS_SECN, sym_name) == 0) 7727c478bd9Sstevel@tonic-gate return (1); 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate return (0); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate /* 7787c478bd9Sstevel@tonic-gate * Translate symbol table data particularly for sorting. 7797c478bd9Sstevel@tonic-gate * Input is the symbol table data structure, number of symbols, 7807c478bd9Sstevel@tonic-gate * opened ELF file, and the string table link offset. 7817c478bd9Sstevel@tonic-gate */ 7827c478bd9Sstevel@tonic-gate static SYM * 7837c478bd9Sstevel@tonic-gate readsyms(Elf_Data * data, GElf_Sxword num, Elf *elf, 7847c478bd9Sstevel@tonic-gate unsigned int link, unsigned int symscnndx) 7857c478bd9Sstevel@tonic-gate { 7867c478bd9Sstevel@tonic-gate SYM *s, *buf; 7877c478bd9Sstevel@tonic-gate GElf_Sym sym; 7887c478bd9Sstevel@tonic-gate Elf32_Word *symshndx = 0; 7897c478bd9Sstevel@tonic-gate unsigned int nosymshndx = 0; 7907c478bd9Sstevel@tonic-gate int i; 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if ((buf = calloc(num, sizeof (SYM))) == NULL) { 7931e67f0f0SAli Bahrami (void) fprintf(stderr, gettext("%s: cannot allocate memory\n"), 7941e67f0f0SAli Bahrami prog_name); 7957c478bd9Sstevel@tonic-gate return (NULL); 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate s = buf; /* save pointer to head of array */ 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate for (i = 1; i < num; i++, buf++) { 8017c478bd9Sstevel@tonic-gate (void) gelf_getsym(data, i, &sym); 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate buf->indx = i; 8047c478bd9Sstevel@tonic-gate /* allow to work on machines where NULL-derefs dump core */ 8057c478bd9Sstevel@tonic-gate if (sym.st_name == 0) 8067c478bd9Sstevel@tonic-gate buf->name = ""; 8077c478bd9Sstevel@tonic-gate else if (C_flag) { 808b9bd317cSab196087 const char *dn; 809b9bd317cSab196087 char *name = (char *)elf_strptr(elf, link, sym.st_name); 810b9bd317cSab196087 dn = conv_demangle_name(name); 8117c478bd9Sstevel@tonic-gate if (strcmp(dn, name) == 0) { /* Not demangled */ 8127c478bd9Sstevel@tonic-gate if (exotic(name)) { 8137c478bd9Sstevel@tonic-gate name = FormatName(name, d_buf); 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate } else { /* name demangled */ 8167c478bd9Sstevel@tonic-gate name = FormatName(name, dn); 8177c478bd9Sstevel@tonic-gate } 8187c478bd9Sstevel@tonic-gate buf->name = name; 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate else 821b9bd317cSab196087 buf->name = (char *)elf_strptr(elf, link, sym.st_name); 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate buf->value = sym.st_value; 8247c478bd9Sstevel@tonic-gate buf->size = sym.st_size; 8257c478bd9Sstevel@tonic-gate buf->type = GELF_ST_TYPE(sym.st_info); 8267c478bd9Sstevel@tonic-gate buf->bind = GELF_ST_BIND(sym.st_info); 8277c478bd9Sstevel@tonic-gate buf->other = sym.st_other; 8287c478bd9Sstevel@tonic-gate if ((sym.st_shndx == SHN_XINDEX) && 8297c478bd9Sstevel@tonic-gate (symshndx == 0) && (nosymshndx == 0)) { 8307c478bd9Sstevel@tonic-gate Elf_Scn *_scn; 8317c478bd9Sstevel@tonic-gate GElf_Shdr _shdr; 8327c478bd9Sstevel@tonic-gate _scn = 0; 8337c478bd9Sstevel@tonic-gate while ((_scn = elf_nextscn(elf, _scn)) != 0) { 8347c478bd9Sstevel@tonic-gate if (gelf_getshdr(_scn, &_shdr) == 0) 8357c478bd9Sstevel@tonic-gate break; 8367c478bd9Sstevel@tonic-gate if ((_shdr.sh_type == SHT_SYMTAB_SHNDX) && 8377c478bd9Sstevel@tonic-gate (_shdr.sh_link == symscnndx)) { 8387c478bd9Sstevel@tonic-gate Elf_Data *_data; 8397c478bd9Sstevel@tonic-gate if ((_data = elf_getdata(_scn, 8407c478bd9Sstevel@tonic-gate 0)) != 0) { 8417c478bd9Sstevel@tonic-gate symshndx = 8427c478bd9Sstevel@tonic-gate (Elf32_Word *)_data->d_buf; 8437c478bd9Sstevel@tonic-gate break; 8447c478bd9Sstevel@tonic-gate } 8457c478bd9Sstevel@tonic-gate } 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate nosymshndx = 1; 8487c478bd9Sstevel@tonic-gate } 8497c478bd9Sstevel@tonic-gate if ((symshndx) && (sym.st_shndx == SHN_XINDEX)) { 8507c478bd9Sstevel@tonic-gate buf->shndx = symshndx[i]; 8517c478bd9Sstevel@tonic-gate } else { 8527c478bd9Sstevel@tonic-gate buf->shndx = sym.st_shndx; 8537c478bd9Sstevel@tonic-gate if (sym.st_shndx >= SHN_LORESERVE) 8547c478bd9Sstevel@tonic-gate buf->flags |= FLG_SYM_SPECSEC; 8557c478bd9Sstevel@tonic-gate } 8567c478bd9Sstevel@tonic-gate } /* end for loop */ 8577c478bd9Sstevel@tonic-gate return (s); 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate /* 8617c478bd9Sstevel@tonic-gate * compare either by name or by value for sorting. 8627c478bd9Sstevel@tonic-gate * This is the comparison function called by qsort to 8637c478bd9Sstevel@tonic-gate * sort the symbols either by name or value when requested. 8647c478bd9Sstevel@tonic-gate */ 8657c478bd9Sstevel@tonic-gate static int 8667c478bd9Sstevel@tonic-gate compare(SYM *a, SYM *b) 8677c478bd9Sstevel@tonic-gate { 8687c478bd9Sstevel@tonic-gate if (v_flag) { 8697c478bd9Sstevel@tonic-gate if (a->value > b->value) 8707c478bd9Sstevel@tonic-gate return (1); 8717c478bd9Sstevel@tonic-gate else 8727c478bd9Sstevel@tonic-gate return ((a->value == b->value) -1); 8737c478bd9Sstevel@tonic-gate } else 8747c478bd9Sstevel@tonic-gate return ((int)strcoll(a->name, b->name)); 8757c478bd9Sstevel@tonic-gate } 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate /* 8787c478bd9Sstevel@tonic-gate * Set up a header line for -A option. 8797c478bd9Sstevel@tonic-gate */ 8807c478bd9Sstevel@tonic-gate static void 8817c478bd9Sstevel@tonic-gate set_A_header(char *fname) 8827c478bd9Sstevel@tonic-gate { 8837c478bd9Sstevel@tonic-gate if (A_flag == 0) 8847c478bd9Sstevel@tonic-gate return; 8857c478bd9Sstevel@tonic-gate 886ba4e3c84Sab196087 if (archive_name == (char *)0) { 887ba4e3c84Sab196087 (void) snprintf(A_header, sizeof (A_header), "%s: ", fname); 888ba4e3c84Sab196087 } else { 889ba4e3c84Sab196087 (void) snprintf(A_header, sizeof (A_header), "%s[%s]: ", 890ba4e3c84Sab196087 archive_name, fname); 891ba4e3c84Sab196087 } 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate /* 8957c478bd9Sstevel@tonic-gate * output functions 8967c478bd9Sstevel@tonic-gate * The following functions are called from 8977c478bd9Sstevel@tonic-gate * print_symtab(). 8987c478bd9Sstevel@tonic-gate */ 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate /* 9017c478bd9Sstevel@tonic-gate * Print header line if needed. 902ba4e3c84Sab196087 * 903ba4e3c84Sab196087 * entry: 904ba4e3c84Sab196087 * ndigits - # of digits to be used to format an integer 905ba4e3c84Sab196087 * value, not counting any '0x' (hex) or '0' (octal) prefix. 9067c478bd9Sstevel@tonic-gate */ 907ba4e3c84Sab196087 static void 908ba4e3c84Sab196087 print_header(int ndigits) 909ba4e3c84Sab196087 { 910ba4e3c84Sab196087 const char *fmt; 911ba4e3c84Sab196087 const char *section_title; 912bdcb2466Sab196087 const int pad[] = { /* Extra prefix characters for format */ 913bdcb2466Sab196087 1, /* FMT_T_DEC: '|' */ 914bdcb2466Sab196087 3, /* FMT_T_HEX: '|0x' */ 915bdcb2466Sab196087 2, /* FMT_T_OCT: '|0' */ 916bdcb2466Sab196087 }; 917ba4e3c84Sab196087 if ( 918ba4e3c84Sab196087 #ifndef XPG4 919ba4e3c84Sab196087 !u_flag && 920ba4e3c84Sab196087 #endif 921ba4e3c84Sab196087 !h_flag && !p_flag && !P_flag) { 9227c478bd9Sstevel@tonic-gate (void) printf("\n"); 923ba4e3c84Sab196087 if (!s_flag) { 924ba4e3c84Sab196087 fmt = "%-9s%-*s%-*s%-6s%-6s%-6s%-8s%s\n\n"; 925ba4e3c84Sab196087 section_title = "Shndx"; 926ba4e3c84Sab196087 } else { 927ba4e3c84Sab196087 fmt = "%-9s%-*s%-*s%-6s%-6s%-6s%-15s%s\n\n"; 928ba4e3c84Sab196087 section_title = "Shname"; 929ba4e3c84Sab196087 } 9307c478bd9Sstevel@tonic-gate if (A_flag != 0) 9317c478bd9Sstevel@tonic-gate (void) printf("%s", A_header); 932bdcb2466Sab196087 ndigits += pad[fmt_flag]; 933bdcb2466Sab196087 (void) printf(fmt, "[Index]", ndigits, " Value", 934bdcb2466Sab196087 ndigits, " Size", "Type", "Bind", 935ba4e3c84Sab196087 "Other", section_title, "Name"); 9367c478bd9Sstevel@tonic-gate } 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate /* 9407c478bd9Sstevel@tonic-gate * If the symbol can be printed, then return 1. 9417c478bd9Sstevel@tonic-gate * If the symbol can not be printed, then return 0. 9427c478bd9Sstevel@tonic-gate */ 9437c478bd9Sstevel@tonic-gate static int 9447c478bd9Sstevel@tonic-gate is_sym_print(SYM *sym_data) 9457c478bd9Sstevel@tonic-gate { 9467c478bd9Sstevel@tonic-gate /* 9477c478bd9Sstevel@tonic-gate * If -u flag is specified, 9487c478bd9Sstevel@tonic-gate * the symbol has to be undefined. 9497c478bd9Sstevel@tonic-gate */ 9507c478bd9Sstevel@tonic-gate if (u_flag != 0) { 9517c478bd9Sstevel@tonic-gate if ((sym_data->shndx == SHN_UNDEF) && 9527c478bd9Sstevel@tonic-gate (strlen(sym_data->name) != 0)) 9537c478bd9Sstevel@tonic-gate return (1); 9547c478bd9Sstevel@tonic-gate else 9557c478bd9Sstevel@tonic-gate return (0); 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate /* 9597c478bd9Sstevel@tonic-gate * If -e flag is specified, 9607c478bd9Sstevel@tonic-gate * the symbol has to be global or static. 9617c478bd9Sstevel@tonic-gate */ 9627c478bd9Sstevel@tonic-gate if (e_flag != 0) { 9637c478bd9Sstevel@tonic-gate switch (sym_data->type) { 9647c478bd9Sstevel@tonic-gate case STT_NOTYPE: 9657c478bd9Sstevel@tonic-gate case STT_OBJECT: 9667c478bd9Sstevel@tonic-gate case STT_FUNC: 9677c478bd9Sstevel@tonic-gate case STT_COMMON: 9687c478bd9Sstevel@tonic-gate case STT_TLS: 9697c478bd9Sstevel@tonic-gate switch (sym_data->bind) { 9707c478bd9Sstevel@tonic-gate case STB_LOCAL: 9717c478bd9Sstevel@tonic-gate case STB_GLOBAL: 9727c478bd9Sstevel@tonic-gate case STB_WEAK: 9737c478bd9Sstevel@tonic-gate return (1); 9747c478bd9Sstevel@tonic-gate default: 9757c478bd9Sstevel@tonic-gate return (0); 9767c478bd9Sstevel@tonic-gate } 9777c478bd9Sstevel@tonic-gate default: 9787c478bd9Sstevel@tonic-gate return (0); 9797c478bd9Sstevel@tonic-gate } 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate /* 9837c478bd9Sstevel@tonic-gate * If -g is specified, 9847c478bd9Sstevel@tonic-gate * the symbol has to be global. 9857c478bd9Sstevel@tonic-gate */ 9867c478bd9Sstevel@tonic-gate if (g_flag != 0) { 9877c478bd9Sstevel@tonic-gate switch (sym_data->type) { 9887c478bd9Sstevel@tonic-gate case STT_NOTYPE: 9897c478bd9Sstevel@tonic-gate case STT_OBJECT: 9907c478bd9Sstevel@tonic-gate case STT_FUNC: 9917c478bd9Sstevel@tonic-gate case STT_COMMON: 9927c478bd9Sstevel@tonic-gate case STT_TLS: 9937c478bd9Sstevel@tonic-gate switch (sym_data->bind) { 9947c478bd9Sstevel@tonic-gate case STB_GLOBAL: 9957c478bd9Sstevel@tonic-gate case STB_WEAK: 9967c478bd9Sstevel@tonic-gate return (1); 9977c478bd9Sstevel@tonic-gate default: 9987c478bd9Sstevel@tonic-gate return (0); 9997c478bd9Sstevel@tonic-gate } 10007c478bd9Sstevel@tonic-gate default: 10017c478bd9Sstevel@tonic-gate return (0); 10027c478bd9Sstevel@tonic-gate } 10037c478bd9Sstevel@tonic-gate } 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate /* 10067c478bd9Sstevel@tonic-gate * If it comes here, any symbol can be printed. 10077c478bd9Sstevel@tonic-gate * (So basically, -f is no-op.) 10087c478bd9Sstevel@tonic-gate */ 10097c478bd9Sstevel@tonic-gate return (1); 10107c478bd9Sstevel@tonic-gate } 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate #ifndef XPG4 10137c478bd9Sstevel@tonic-gate /* 10147c478bd9Sstevel@tonic-gate * -u flag specified 10157c478bd9Sstevel@tonic-gate */ 10167c478bd9Sstevel@tonic-gate static void 10177c478bd9Sstevel@tonic-gate print_with_uflag( 10187c478bd9Sstevel@tonic-gate SYM *sym_data, 10197c478bd9Sstevel@tonic-gate char *filename 10207c478bd9Sstevel@tonic-gate ) 10217c478bd9Sstevel@tonic-gate { 1022b9bd317cSab196087 if ((sym_data->shndx == SHN_UNDEF) && (strlen(sym_data->name))) { 10237c478bd9Sstevel@tonic-gate if (!r_flag) { 10247c478bd9Sstevel@tonic-gate if (R_flag) { 10257c478bd9Sstevel@tonic-gate if (archive_name != (char *)0) 1026b9bd317cSab196087 (void) printf(" %s:%s:%s\n", 1027b9bd317cSab196087 archive_name, filename, 10287c478bd9Sstevel@tonic-gate sym_data->name); 10297c478bd9Sstevel@tonic-gate else 10307c478bd9Sstevel@tonic-gate (void) printf(" %s:%s\n", 1031b9bd317cSab196087 filename, sym_data->name); 1032b9bd317cSab196087 } 1033b9bd317cSab196087 else 1034b9bd317cSab196087 (void) printf(" %s\n", sym_data->name); 1035b9bd317cSab196087 } 1036b9bd317cSab196087 else 1037b9bd317cSab196087 (void) printf(" %s:%s\n", filename, sym_data->name); 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate } 10407c478bd9Sstevel@tonic-gate #endif 10411e67f0f0SAli Bahrami 10427c478bd9Sstevel@tonic-gate /* 10431e67f0f0SAli Bahrami * Print a symbol type representation suitable for the -p or -P formats. 10447c478bd9Sstevel@tonic-gate */ 10457c478bd9Sstevel@tonic-gate static void 10461e67f0f0SAli Bahrami print_brief_sym_type(Elf *elf_file, unsigned int shstrndx, SYM *sym_data) 10477c478bd9Sstevel@tonic-gate { 10481e67f0f0SAli Bahrami const char *sym_key = NULL; 10497c478bd9Sstevel@tonic-gate 1050b9bd317cSab196087 if ((sym_data->shndx == SHN_UNDEF) && (strlen(sym_data->name))) 10517c478bd9Sstevel@tonic-gate sym_key = UNDEFINED; 10527c478bd9Sstevel@tonic-gate else if (sym_data->type == STT_SPARC_REGISTER) { 10537c478bd9Sstevel@tonic-gate switch (sym_data->bind) { 10547c478bd9Sstevel@tonic-gate case STB_LOCAL : sym_key = REG_LOCL; 10557c478bd9Sstevel@tonic-gate break; 10567c478bd9Sstevel@tonic-gate case STB_GLOBAL : sym_key = REG_GLOB; 10577c478bd9Sstevel@tonic-gate break; 10587c478bd9Sstevel@tonic-gate case STB_WEAK : sym_key = REG_WEAK; 10597c478bd9Sstevel@tonic-gate break; 10607c478bd9Sstevel@tonic-gate default : sym_key = REG_GLOB; 10617c478bd9Sstevel@tonic-gate break; 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate } else if (((sym_data->flags & FLG_SYM_SPECSEC) == 0) && 10647c478bd9Sstevel@tonic-gate is_bss_section((int)sym_data->shndx, elf_file, shstrndx)) { 10657c478bd9Sstevel@tonic-gate switch (sym_data->bind) { 10667c478bd9Sstevel@tonic-gate case STB_LOCAL : sym_key = BSS_LOCL; 10677c478bd9Sstevel@tonic-gate break; 10687c478bd9Sstevel@tonic-gate case STB_GLOBAL : sym_key = BSS_GLOB; 10697c478bd9Sstevel@tonic-gate break; 10707c478bd9Sstevel@tonic-gate case STB_WEAK : sym_key = BSS_WEAK; 10717c478bd9Sstevel@tonic-gate break; 10727c478bd9Sstevel@tonic-gate default : sym_key = BSS_GLOB; 10737c478bd9Sstevel@tonic-gate break; 10747c478bd9Sstevel@tonic-gate } 10757c478bd9Sstevel@tonic-gate 10761e67f0f0SAli Bahrami } else { 1077b9bd317cSab196087 sym_key = lookup(sym_data->type, sym_data->bind); 10781e67f0f0SAli Bahrami } 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate if (sym_key != NULL) { 10817c478bd9Sstevel@tonic-gate if (!l_flag) 10827c478bd9Sstevel@tonic-gate (void) printf("%c ", sym_key[0]); 10837c478bd9Sstevel@tonic-gate else 10847c478bd9Sstevel@tonic-gate (void) printf("%-3s", sym_key); 10857c478bd9Sstevel@tonic-gate } else { 10867c478bd9Sstevel@tonic-gate if (!l_flag) 10877c478bd9Sstevel@tonic-gate (void) printf("%-2d", sym_data->type); 10887c478bd9Sstevel@tonic-gate else 10897c478bd9Sstevel@tonic-gate (void) printf("%-3d", sym_data->type); 10907c478bd9Sstevel@tonic-gate } 10911e67f0f0SAli Bahrami } 10921e67f0f0SAli Bahrami 10931e67f0f0SAli Bahrami /* 10941e67f0f0SAli Bahrami * -p flag specified 10951e67f0f0SAli Bahrami */ 10961e67f0f0SAli Bahrami static void 10971e67f0f0SAli Bahrami print_with_pflag( 10981e67f0f0SAli Bahrami int ndigits, 10991e67f0f0SAli Bahrami Elf *elf_file, 11001e67f0f0SAli Bahrami unsigned int shstrndx, 11011e67f0f0SAli Bahrami SYM *sym_data, 11021e67f0f0SAli Bahrami char *filename 11031e67f0f0SAli Bahrami ) 11041e67f0f0SAli Bahrami { 11051e67f0f0SAli Bahrami const char * const fmt[] = { 11061e67f0f0SAli Bahrami "%.*llu ", /* FMT_T_DEC */ 11071e67f0f0SAli Bahrami "0x%.*llx ", /* FMT_T_HEX */ 11081e67f0f0SAli Bahrami "0%.*llo " /* FMT_T_OCT */ 11091e67f0f0SAli Bahrami }; 11101e67f0f0SAli Bahrami 11111e67f0f0SAli Bahrami if (is_sym_print(sym_data) != 1) 11121e67f0f0SAli Bahrami return; 11131e67f0f0SAli Bahrami /* 11141e67f0f0SAli Bahrami * -A header 11151e67f0f0SAli Bahrami */ 11161e67f0f0SAli Bahrami if (A_flag != 0) 11171e67f0f0SAli Bahrami (void) printf("%s", A_header); 11181e67f0f0SAli Bahrami 11191e67f0f0SAli Bahrami /* 11201e67f0f0SAli Bahrami * Symbol Value. 11211e67f0f0SAli Bahrami * (hex/octal/decimal) 11221e67f0f0SAli Bahrami */ 11231e67f0f0SAli Bahrami (void) printf(fmt[fmt_flag], ndigits, EC_ADDR(sym_data->value)); 11241e67f0f0SAli Bahrami 11251e67f0f0SAli Bahrami 11261e67f0f0SAli Bahrami /* 11271e67f0f0SAli Bahrami * Symbol Type. 11281e67f0f0SAli Bahrami */ 11291e67f0f0SAli Bahrami print_brief_sym_type(elf_file, shstrndx, sym_data); 11301e67f0f0SAli Bahrami 11317c478bd9Sstevel@tonic-gate if (!r_flag) { 11327c478bd9Sstevel@tonic-gate if (R_flag) { 11337c478bd9Sstevel@tonic-gate if (archive_name != (char *)0) 1134b9bd317cSab196087 (void) printf("%s:%s:%s\n", archive_name, 1135b9bd317cSab196087 filename, sym_data->name); 11367c478bd9Sstevel@tonic-gate else 1137b9bd317cSab196087 (void) printf("%s:%s\n", filename, 11387c478bd9Sstevel@tonic-gate sym_data->name); 11397c478bd9Sstevel@tonic-gate } 11407c478bd9Sstevel@tonic-gate else 11417c478bd9Sstevel@tonic-gate (void) printf("%s\n", sym_data->name); 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate else 1144b9bd317cSab196087 (void) printf("%s:%s\n", filename, sym_data->name); 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate /* 11487c478bd9Sstevel@tonic-gate * -P flag specified 11497c478bd9Sstevel@tonic-gate */ 11507c478bd9Sstevel@tonic-gate static void 11517c478bd9Sstevel@tonic-gate print_with_Pflag( 1152ba4e3c84Sab196087 int ndigits, 11537c478bd9Sstevel@tonic-gate Elf *elf_file, 11547c478bd9Sstevel@tonic-gate unsigned int shstrndx, 11557c478bd9Sstevel@tonic-gate SYM *sym_data 11567c478bd9Sstevel@tonic-gate ) 11577c478bd9Sstevel@tonic-gate { 11587c478bd9Sstevel@tonic-gate #define SYM_LEN 10 11597c478bd9Sstevel@tonic-gate char sym_name[SYM_LEN+1]; 11607c478bd9Sstevel@tonic-gate size_t len; 1161bdcb2466Sab196087 const char * const fmt[] = { 1162bdcb2466Sab196087 "%*llu %*llu \n", /* FMT_T_DEC */ 1163bdcb2466Sab196087 "%*llx %*llx \n", /* FMT_T_HEX */ 1164bdcb2466Sab196087 "%*llo %*llo \n" /* FMT_T_OCT */ 1165bdcb2466Sab196087 }; 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate if (is_sym_print(sym_data) != 1) 11687c478bd9Sstevel@tonic-gate return; 11697c478bd9Sstevel@tonic-gate /* 11707c478bd9Sstevel@tonic-gate * -A header 11717c478bd9Sstevel@tonic-gate */ 11727c478bd9Sstevel@tonic-gate if (A_flag != 0) 11737c478bd9Sstevel@tonic-gate (void) printf("%s", A_header); 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate /* 11767c478bd9Sstevel@tonic-gate * Symbol name 11777c478bd9Sstevel@tonic-gate */ 11787c478bd9Sstevel@tonic-gate len = strlen(sym_data->name); 11797c478bd9Sstevel@tonic-gate if (len >= SYM_LEN) 11807c478bd9Sstevel@tonic-gate (void) printf("%s ", sym_data->name); 11817c478bd9Sstevel@tonic-gate else { 11827c478bd9Sstevel@tonic-gate (void) sprintf(sym_name, "%-10s", sym_data->name); 11837c478bd9Sstevel@tonic-gate (void) printf("%s ", sym_name); 11847c478bd9Sstevel@tonic-gate } 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate /* 11877c478bd9Sstevel@tonic-gate * Symbol Type. 11887c478bd9Sstevel@tonic-gate */ 11891e67f0f0SAli Bahrami print_brief_sym_type(elf_file, shstrndx, sym_data); 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate /* 11927c478bd9Sstevel@tonic-gate * Symbol Value & size 11937c478bd9Sstevel@tonic-gate * (hex/octal/decimal) 11947c478bd9Sstevel@tonic-gate */ 1195bdcb2466Sab196087 (void) printf(fmt[fmt_flag], ndigits, EC_ADDR(sym_data->value), 1196ba4e3c84Sab196087 ndigits, EC_XWORD(sym_data->size)); 11977c478bd9Sstevel@tonic-gate } 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate /* 12007c478bd9Sstevel@tonic-gate * other flags specified 12017c478bd9Sstevel@tonic-gate */ 12027c478bd9Sstevel@tonic-gate static void 12037c478bd9Sstevel@tonic-gate print_with_otherflags( 1204ba4e3c84Sab196087 int ndigits, 12057c478bd9Sstevel@tonic-gate Elf *elf_file, 12067c478bd9Sstevel@tonic-gate unsigned int shstrndx, 12077c478bd9Sstevel@tonic-gate SYM *sym_data, 12087c478bd9Sstevel@tonic-gate char *filename 12097c478bd9Sstevel@tonic-gate ) 12107c478bd9Sstevel@tonic-gate { 1211bdcb2466Sab196087 const char * const fmt_value_size[] = { 1212bdcb2466Sab196087 "%*llu|%*lld|", /* FMT_T_DEC */ 1213bdcb2466Sab196087 "0x%.*llx|0x%.*llx|", /* FMT_T_HEX */ 1214bdcb2466Sab196087 "0%.*llo|0%.*llo|" /* FMT_T_OCT */ 1215bdcb2466Sab196087 }; 1216bdcb2466Sab196087 const char * const fmt_int[] = { 1217bdcb2466Sab196087 "%-5d", /* FMT_T_DEC */ 1218bdcb2466Sab196087 "%#-5x", /* FMT_T_HEX */ 1219bdcb2466Sab196087 "%#-5o" /* FMT_T_OCT */ 1220bdcb2466Sab196087 }; 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate if (is_sym_print(sym_data) != 1) 12237c478bd9Sstevel@tonic-gate return; 12247c478bd9Sstevel@tonic-gate (void) printf("%s", A_header); 12257c478bd9Sstevel@tonic-gate (void) printf("[%d]\t|", sym_data->indx); 1226bdcb2466Sab196087 (void) printf(fmt_value_size[fmt_flag], ndigits, 1227bdcb2466Sab196087 EC_ADDR(sym_data->value), ndigits, EC_XWORD(sym_data->size)); 12287c478bd9Sstevel@tonic-gate 12297c478bd9Sstevel@tonic-gate switch (sym_data->type) { 12307c478bd9Sstevel@tonic-gate case STT_NOTYPE:(void) printf("%-5s", "NOTY"); break; 12317c478bd9Sstevel@tonic-gate case STT_OBJECT:(void) printf("%-5s", "OBJT"); break; 12327c478bd9Sstevel@tonic-gate case STT_FUNC: (void) printf("%-5s", "FUNC"); break; 12337c478bd9Sstevel@tonic-gate case STT_SECTION:(void) printf("%-5s", "SECT"); break; 12347c478bd9Sstevel@tonic-gate case STT_FILE: (void) printf("%-5s", "FILE"); break; 12357c478bd9Sstevel@tonic-gate case STT_COMMON: (void) printf("%-5s", "COMM"); break; 12367c478bd9Sstevel@tonic-gate case STT_TLS: (void) printf("%-5s", "TLS "); break; 12377c478bd9Sstevel@tonic-gate case STT_SPARC_REGISTER: (void) printf("%-5s", "REGI"); break; 12387c478bd9Sstevel@tonic-gate default: 1239bdcb2466Sab196087 (void) printf(fmt_int[fmt_flag], sym_data->type); 12407c478bd9Sstevel@tonic-gate } 12417c478bd9Sstevel@tonic-gate (void) printf("|"); 12427c478bd9Sstevel@tonic-gate switch (sym_data->bind) { 12437c478bd9Sstevel@tonic-gate case STB_LOCAL: (void) printf("%-5s", "LOCL"); break; 12447c478bd9Sstevel@tonic-gate case STB_GLOBAL:(void) printf("%-5s", "GLOB"); break; 12457c478bd9Sstevel@tonic-gate case STB_WEAK: (void) printf("%-5s", "WEAK"); break; 12467c478bd9Sstevel@tonic-gate default: 12477c478bd9Sstevel@tonic-gate (void) printf("%-5d", sym_data->bind); 1248bdcb2466Sab196087 (void) printf(fmt_int[fmt_flag], sym_data->bind); 12497c478bd9Sstevel@tonic-gate } 12507c478bd9Sstevel@tonic-gate (void) printf("|"); 1251bdcb2466Sab196087 (void) printf(fmt_int[fmt_flag], sym_data->other); 12527c478bd9Sstevel@tonic-gate (void) printf("|"); 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate if (sym_data->shndx == SHN_UNDEF) { 12557c478bd9Sstevel@tonic-gate if (!s_flag) 1256b9bd317cSab196087 (void) printf("%-7s", "UNDEF"); 12577c478bd9Sstevel@tonic-gate else 1258b9bd317cSab196087 (void) printf("%-14s", "UNDEF"); 12597c478bd9Sstevel@tonic-gate } else if (sym_data->shndx == SHN_SUNW_IGNORE) { 12607c478bd9Sstevel@tonic-gate if (!s_flag) 1261b9bd317cSab196087 (void) printf("%-7s", "IGNORE"); 12627c478bd9Sstevel@tonic-gate else 1263b9bd317cSab196087 (void) printf("%-14s", "IGNORE"); 12647c478bd9Sstevel@tonic-gate } else if ((sym_data->flags & FLG_SYM_SPECSEC) && 12657c478bd9Sstevel@tonic-gate (sym_data->shndx == SHN_ABS)) { 12667c478bd9Sstevel@tonic-gate if (!s_flag) 1267b9bd317cSab196087 (void) printf("%-7s", "ABS"); 12687c478bd9Sstevel@tonic-gate else 1269b9bd317cSab196087 (void) printf("%-14s", "ABS"); 12707c478bd9Sstevel@tonic-gate } else if ((sym_data->flags & FLG_SYM_SPECSEC) && 12717c478bd9Sstevel@tonic-gate (sym_data->shndx == SHN_COMMON)) { 12727c478bd9Sstevel@tonic-gate if (!s_flag) 1273b9bd317cSab196087 (void) printf("%-7s", "COMMON"); 12747c478bd9Sstevel@tonic-gate else 1275b9bd317cSab196087 (void) printf("%-14s", "COMMON"); 12767c478bd9Sstevel@tonic-gate } else { 1277bdcb2466Sab196087 if (s_flag) { 1278bdcb2466Sab196087 Elf_Scn *scn = elf_getscn(elf_file, sym_data->shndx); 12797c478bd9Sstevel@tonic-gate GElf_Shdr shdr; 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate if ((gelf_getshdr(scn, &shdr) != 0) && 12827c478bd9Sstevel@tonic-gate (shdr.sh_name != 0)) { 12837c478bd9Sstevel@tonic-gate (void) printf("%-14s", 12847c478bd9Sstevel@tonic-gate (char *)elf_strptr(elf_file, 12857c478bd9Sstevel@tonic-gate shstrndx, shdr.sh_name)); 1286bdcb2466Sab196087 } else { 1287bdcb2466Sab196087 (void) printf("%-14d", sym_data->shndx); 12887c478bd9Sstevel@tonic-gate } 1289bdcb2466Sab196087 } else { 1290bdcb2466Sab196087 (void) printf("%-7d", sym_data->shndx); 1291bdcb2466Sab196087 } 12927c478bd9Sstevel@tonic-gate } 12937c478bd9Sstevel@tonic-gate (void) printf("|"); 12947c478bd9Sstevel@tonic-gate if (!r_flag) { 12957c478bd9Sstevel@tonic-gate if (R_flag) { 12967c478bd9Sstevel@tonic-gate if (archive_name != (char *)0) 1297b9bd317cSab196087 (void) printf("%s:%s:%s\n", archive_name, 1298b9bd317cSab196087 filename, sym_data->name); 12997c478bd9Sstevel@tonic-gate else 1300b9bd317cSab196087 (void) printf("%s:%s\n", filename, 13017c478bd9Sstevel@tonic-gate sym_data->name); 13027c478bd9Sstevel@tonic-gate } 13037c478bd9Sstevel@tonic-gate else 13047c478bd9Sstevel@tonic-gate (void) printf("%s\n", sym_data->name); 13057c478bd9Sstevel@tonic-gate } 13067c478bd9Sstevel@tonic-gate else 1307b9bd317cSab196087 (void) printf("%s:%s\n", filename, sym_data->name); 13087c478bd9Sstevel@tonic-gate } 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate /* 13117c478bd9Sstevel@tonic-gate * C++ name demangling supporting routines 13127c478bd9Sstevel@tonic-gate */ 13137c478bd9Sstevel@tonic-gate static const char *ctor_str = "static constructor function for %s"; 13147c478bd9Sstevel@tonic-gate static const char *dtor_str = "static destructor function for %s"; 13157c478bd9Sstevel@tonic-gate static const char *ptbl_str = "pointer to the virtual table vector for %s"; 13167c478bd9Sstevel@tonic-gate static const char *vtbl_str = "virtual table for %s"; 13177c478bd9Sstevel@tonic-gate 13187c478bd9Sstevel@tonic-gate /* 13197c478bd9Sstevel@tonic-gate * alloc memory and create name in necessary format. 13207c478bd9Sstevel@tonic-gate * Return name string 13217c478bd9Sstevel@tonic-gate */ 13227c478bd9Sstevel@tonic-gate static char * 1323b9bd317cSab196087 FormatName(char *OldName, const char *NewName) 13247c478bd9Sstevel@tonic-gate { 13257c478bd9Sstevel@tonic-gate char *s = p_flag ? 13267c478bd9Sstevel@tonic-gate "%s\n [%s]" : 13277c478bd9Sstevel@tonic-gate "%s\n\t\t\t\t\t\t [%s]"; 13287c478bd9Sstevel@tonic-gate size_t length = strlen(s)+strlen(NewName)+strlen(OldName)-3; 13297c478bd9Sstevel@tonic-gate char *hold = OldName; 13307c478bd9Sstevel@tonic-gate OldName = malloc(length); 1331ba4e3c84Sab196087 /*LINTED*/ 1332ba4e3c84Sab196087 (void) snprintf(OldName, length, s, NewName, hold); 13337c478bd9Sstevel@tonic-gate return (OldName); 13347c478bd9Sstevel@tonic-gate } 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate /* 13387c478bd9Sstevel@tonic-gate * Return 1 when s is an exotic name, 0 otherwise. s remains unchanged, 13397c478bd9Sstevel@tonic-gate * the exotic name, if exists, is saved in d_buf. 13407c478bd9Sstevel@tonic-gate */ 13417c478bd9Sstevel@tonic-gate static int 1342af79d7d9SAli Bahrami exotic(const char *in_str) 13437c478bd9Sstevel@tonic-gate { 1344af79d7d9SAli Bahrami static char *buff = 0; 1345af79d7d9SAli Bahrami static size_t buf_size; 1346af79d7d9SAli Bahrami 1347af79d7d9SAli Bahrami size_t sym_len = strlen(in_str) + 1; 13487c478bd9Sstevel@tonic-gate int tag = 0; 1349af79d7d9SAli Bahrami char *s; 1350af79d7d9SAli Bahrami 1351af79d7d9SAli Bahrami /* 1352af79d7d9SAli Bahrami * We will need to modify the symbol (in_str) as we are analyzing it, 1353af79d7d9SAli Bahrami * so copy it into a buffer so that we can play around with it. 1354af79d7d9SAli Bahrami */ 1355af79d7d9SAli Bahrami if (buff == NULL) { 1356af79d7d9SAli Bahrami buff = malloc(DEF_MAX_SYM_SIZE); 1357af79d7d9SAli Bahrami buf_size = DEF_MAX_SYM_SIZE; 1358af79d7d9SAli Bahrami } 1359af79d7d9SAli Bahrami 1360af79d7d9SAli Bahrami if (sym_len > buf_size) { 1361af79d7d9SAli Bahrami if (buff) 1362af79d7d9SAli Bahrami free(buff); 1363af79d7d9SAli Bahrami buff = malloc(sym_len); 1364af79d7d9SAli Bahrami buf_size = sym_len; 1365af79d7d9SAli Bahrami } 1366af79d7d9SAli Bahrami 1367af79d7d9SAli Bahrami if (buff == NULL) { 1368af79d7d9SAli Bahrami (void) fprintf(stderr, gettext( 13691e67f0f0SAli Bahrami "%s: cannot allocate memory\n"), prog_name); 1370af79d7d9SAli Bahrami exit(NOALLOC); 1371af79d7d9SAli Bahrami } 1372af79d7d9SAli Bahrami s = strcpy(buff, in_str); 1373af79d7d9SAli Bahrami 1374af79d7d9SAli Bahrami 13757c478bd9Sstevel@tonic-gate if (strncmp(s, "__sti__", 7) == 0) { 13767c478bd9Sstevel@tonic-gate s += 7; tag = 1; 13777c478bd9Sstevel@tonic-gate parse_fn_and_print(ctor_str, s); 13787c478bd9Sstevel@tonic-gate } else if (strncmp(s, "__std__", 7) == 0) { 13797c478bd9Sstevel@tonic-gate s += 7; tag = 1; 13807c478bd9Sstevel@tonic-gate parse_fn_and_print(dtor_str, s); 13817c478bd9Sstevel@tonic-gate } else if (strncmp(s, "__vtbl__", 8) == 0) { 13827c478bd9Sstevel@tonic-gate s += 8; tag = 1; 13837c478bd9Sstevel@tonic-gate parsename(s); 13847c478bd9Sstevel@tonic-gate (void) sprintf(d_buf, vtbl_str, p_buf); 13857c478bd9Sstevel@tonic-gate } else if (strncmp(s, "__ptbl_vec__", 12) == 0) { 13867c478bd9Sstevel@tonic-gate s += 12; tag = 1; 13877c478bd9Sstevel@tonic-gate parse_fn_and_print(ptbl_str, s); 13887c478bd9Sstevel@tonic-gate } 13897c478bd9Sstevel@tonic-gate return (tag); 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate void 13937c478bd9Sstevel@tonic-gate parsename(char *s) 13947c478bd9Sstevel@tonic-gate { 13957c478bd9Sstevel@tonic-gate register int len; 13967c478bd9Sstevel@tonic-gate char c, *orig = s; 13977c478bd9Sstevel@tonic-gate *p_buf = '\0'; 13987c478bd9Sstevel@tonic-gate (void) strcat(p_buf, "class "); 13997c478bd9Sstevel@tonic-gate while (isdigit(*s)) s++; 14007c478bd9Sstevel@tonic-gate c = *s; 14017c478bd9Sstevel@tonic-gate *s = '\0'; 14027c478bd9Sstevel@tonic-gate len = atoi(orig); 14037c478bd9Sstevel@tonic-gate *s = c; 14047c478bd9Sstevel@tonic-gate if (*(s+len) == '\0') { /* only one class name */ 14057c478bd9Sstevel@tonic-gate (void) strcat(p_buf, s); 14067c478bd9Sstevel@tonic-gate return; 14077c478bd9Sstevel@tonic-gate } else 14087c478bd9Sstevel@tonic-gate { /* two classname %drootname__%dchildname */ 14097c478bd9Sstevel@tonic-gate char *root, *child, *child_len_p; 14107c478bd9Sstevel@tonic-gate int child_len; 14117c478bd9Sstevel@tonic-gate root = s; 14127c478bd9Sstevel@tonic-gate child = s + len + 2; 14137c478bd9Sstevel@tonic-gate child_len_p = child; 14147c478bd9Sstevel@tonic-gate if (!isdigit(*child)) { 14157c478bd9Sstevel@tonic-gate /* ptbl file name */ 14167c478bd9Sstevel@tonic-gate /* %drootname__%filename */ 14177c478bd9Sstevel@tonic-gate /* kludge for getting rid of '_' in file name */ 14187c478bd9Sstevel@tonic-gate char *p; 14197c478bd9Sstevel@tonic-gate c = *(root + len); 14207c478bd9Sstevel@tonic-gate *(root + len) = '\0'; 14217c478bd9Sstevel@tonic-gate (void) strcat(p_buf, root); 14227c478bd9Sstevel@tonic-gate *(root + len) = c; 14237c478bd9Sstevel@tonic-gate (void) strcat(p_buf, " in "); 1424b9bd317cSab196087 for (p = child; *p != '_'; ++p) 1425b9bd317cSab196087 ; 14267c478bd9Sstevel@tonic-gate c = *p; 14277c478bd9Sstevel@tonic-gate *p = '.'; 14287c478bd9Sstevel@tonic-gate (void) strcat(p_buf, child); 14297c478bd9Sstevel@tonic-gate *p = c; 14307c478bd9Sstevel@tonic-gate return; 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate while (isdigit(*child)) 14347c478bd9Sstevel@tonic-gate child++; 14357c478bd9Sstevel@tonic-gate c = *child; 14367c478bd9Sstevel@tonic-gate *child = '\0'; 14377c478bd9Sstevel@tonic-gate child_len = atoi(child_len_p); 14387c478bd9Sstevel@tonic-gate *child = c; 14397c478bd9Sstevel@tonic-gate if (*(child + child_len) == '\0') { 14407c478bd9Sstevel@tonic-gate (void) strcat(p_buf, child); 14417c478bd9Sstevel@tonic-gate (void) strcat(p_buf, " derived from "); 14427c478bd9Sstevel@tonic-gate c = *(root + len); 14437c478bd9Sstevel@tonic-gate *(root + len) = '\0'; 14447c478bd9Sstevel@tonic-gate (void) strcat(p_buf, root); 14457c478bd9Sstevel@tonic-gate *(root + len) = c; 14467c478bd9Sstevel@tonic-gate return; 14477c478bd9Sstevel@tonic-gate } else { 14487c478bd9Sstevel@tonic-gate /* %drootname__%dchildname__filename */ 14497c478bd9Sstevel@tonic-gate /* kludge for getting rid of '_' in file name */ 14507c478bd9Sstevel@tonic-gate char *p; 14517c478bd9Sstevel@tonic-gate c = *(child + child_len); 14527c478bd9Sstevel@tonic-gate *(child + child_len) = '\0'; 14537c478bd9Sstevel@tonic-gate (void) strcat(p_buf, child); 14547c478bd9Sstevel@tonic-gate *(child+child_len) = c; 14557c478bd9Sstevel@tonic-gate (void) strcat(p_buf, " derived from "); 14567c478bd9Sstevel@tonic-gate c = *(root + len); 14577c478bd9Sstevel@tonic-gate *(root + len) = '\0'; 14587c478bd9Sstevel@tonic-gate (void) strcat(p_buf, root); 14597c478bd9Sstevel@tonic-gate *(root + len) = c; 14607c478bd9Sstevel@tonic-gate (void) strcat(p_buf, " in "); 1461b9bd317cSab196087 for (p = child + child_len + 2; *p != '_'; ++p) 1462b9bd317cSab196087 ; 14637c478bd9Sstevel@tonic-gate c = *p; 14647c478bd9Sstevel@tonic-gate *p = '.'; 14657c478bd9Sstevel@tonic-gate (void) strcat(p_buf, child + child_len + 2); 14667c478bd9Sstevel@tonic-gate *p = c; 14677c478bd9Sstevel@tonic-gate return; 14687c478bd9Sstevel@tonic-gate } 14697c478bd9Sstevel@tonic-gate } 14707c478bd9Sstevel@tonic-gate } 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate void 14737c478bd9Sstevel@tonic-gate parse_fn_and_print(const char *str, char *s) 14747c478bd9Sstevel@tonic-gate { 14757c478bd9Sstevel@tonic-gate char c, *p1, *p2; 14767c478bd9Sstevel@tonic-gate int yes = 1; 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate if ((p1 = p2 = strstr(s, "_c_")) == NULL) 14797c478bd9Sstevel@tonic-gate if ((p1 = p2 = strstr(s, "_C_")) == NULL) 14807c478bd9Sstevel@tonic-gate if ((p1 = p2 = strstr(s, "_cc_")) == NULL) 14817c478bd9Sstevel@tonic-gate if ((p1 = p2 = strstr(s, "_cxx_")) == NULL) 1482b9bd317cSab196087 if ((p1 = p2 = strstr(s, "_h_")) == 1483b9bd317cSab196087 NULL) 14847c478bd9Sstevel@tonic-gate yes = 0; 14857c478bd9Sstevel@tonic-gate else 14867c478bd9Sstevel@tonic-gate p2 += 2; 14877c478bd9Sstevel@tonic-gate else 14887c478bd9Sstevel@tonic-gate p2 += 4; 14897c478bd9Sstevel@tonic-gate else 14907c478bd9Sstevel@tonic-gate p2 += 3; 14917c478bd9Sstevel@tonic-gate else 14927c478bd9Sstevel@tonic-gate p2 += 2; 14937c478bd9Sstevel@tonic-gate else 14947c478bd9Sstevel@tonic-gate p2 += 2; 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate if (yes) { 14977c478bd9Sstevel@tonic-gate *p1 = '.'; 14987c478bd9Sstevel@tonic-gate c = *p2; 14997c478bd9Sstevel@tonic-gate *p2 = '\0'; 15007c478bd9Sstevel@tonic-gate } 15017c478bd9Sstevel@tonic-gate 1502b9bd317cSab196087 for (s = p1; *s != '_'; --s) 1503b9bd317cSab196087 ; 15047c478bd9Sstevel@tonic-gate ++s; 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate (void) sprintf(d_buf, str, s); 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate if (yes) { 15097c478bd9Sstevel@tonic-gate *p1 = '_'; 15107c478bd9Sstevel@tonic-gate *p2 = c; 15117c478bd9Sstevel@tonic-gate } 15127c478bd9Sstevel@tonic-gate } 1513