4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1988 AT&T
24 * Copyright (c) 1989 AT&T
27 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
36 #include <sys/elf_SPARC.h>
39 /* exit return codes */
54 typedef struct { /* structure to translate symbol table data */
63 unsigned int flags
; /* flags relevant to entry */
66 #define FLG_SYM_SPECSEC 0x00000001 /* reserved scn index */
67 /* (SHN_ABS, SHN_COMMON, ...) */
73 #define BSS_SECN ".bss"
78 #define OPTSTR ":APDoxhvnursplLCVefgRTt:" /* option string for getopt() */
85 #define DEF_MAX_SYM_SIZE 256
87 static char *key
[TYPE
][BIND
];
90 * Format type used for printing value and size items.
91 * The non-negative values here are used as array indices into
92 * several arrays found below. Renumbering, or adding items,
93 * will require changes to those arrays as well.
96 FMT_T_NONE
= -1, /* No format type yet assigned */
98 /* The following are used as array indices */
105 * Determine whether a proposed format type is compatible with the current
106 * setting. We allow setting the format as long as it hasn't already
107 * been done, or if the new setting is the same as the current one.
109 #define COMPAT_FMT_FLAG(new_fmt_flag) \
110 (fmt_flag == FMT_T_NONE) || (fmt_flag == new_fmt_flag)
112 static FMT_T fmt_flag
= FMT_T_NONE
; /* format style to use for value/size */
114 static int /* flags: ?_flag corresponds to ? option */
115 h_flag
= 0, /* suppress printing of headings */
116 v_flag
= 0, /* sort external symbols by value */
117 n_flag
= 0, /* sort external symbols by name */
118 u_flag
= 0, /* print only undefined symbols */
119 r_flag
= 0, /* prepend object file or archive name */
120 /* to each symbol name */
121 R_flag
= 0, /* if "-R" issued then prepend archive name, */
122 /* object file name to each symbol */
123 s_flag
= 0, /* print section name instead of section index */
124 p_flag
= 0, /* produce terse output */
125 P_flag
= 0, /* Portable format output */
126 l_flag
= 0, /* produce long listing of output */
127 L_flag
= 0, /* print SUNW_LDYNSYM instead of SYMTAB */
128 D_flag
= 0, /* print DYNSYM instead of SYMTAB */
129 C_flag
= 0, /* print decoded C++ names */
130 A_flag
= 0, /* File name */
131 e_flag
= 0, /* -e flag */
132 g_flag
= 0, /* -g flag */
133 V_flag
= 0; /* print version information */
134 static char A_header
[DEF_MAX_SYM_SIZE
+1] = {0};
136 static char *prog_name
;
137 static char *archive_name
= (char *)0;
138 static int errflag
= 0;
140 static void each_file(char *);
141 static void process(Elf
*, char *);
142 static Elf_Scn
* get_scnfd(Elf
*, int, int);
143 static void get_symtab(Elf
*, char *);
144 static SYM
* readsyms(Elf_Data
*, GElf_Sxword
, Elf
*, unsigned int,
146 static int compare(SYM
*, SYM
*);
147 static char *lookup(int, int);
148 static int is_bss_section(unsigned int, Elf
*, unsigned int);
149 static void print_ar_files(int, Elf
*, char *);
150 static void print_symtab(Elf
*, unsigned int, Elf_Scn
*, GElf_Shdr
*, char *);
151 static void parsename(char *);
152 static void parse_fn_and_print(const char *, char *);
153 static char d_buf
[512];
154 static char p_buf
[512];
155 static int exotic(const char *s
);
156 static void set_A_header(char *);
157 static char *FormatName(char *, const char *);
162 * Parses the command line options and then
163 * calls each_file() to process each file.
166 main(int argc
, char *argv
[], char *envp
[])
168 char *optstr
= OPTSTR
; /* option string used by getopt() */
174 * Check for a binary that better fits this architecture.
176 (void) conv_check_native(argv
, envp
);
179 /* table of keyletters for use with -p and -P options */
180 key
[STT_NOTYPE
][STB_LOCAL
] = "n";
181 key
[STT_NOTYPE
][STB_GLOBAL
] = "N";
182 key
[STT_NOTYPE
][STB_WEAK
] = "N*";
183 key
[STT_OBJECT
][STB_LOCAL
] = "d";
184 key
[STT_OBJECT
][STB_GLOBAL
] = "D";
185 key
[STT_OBJECT
][STB_WEAK
] = "D*";
186 key
[STT_FUNC
][STB_LOCAL
] = "t";
187 key
[STT_FUNC
][STB_GLOBAL
] = "T";
188 key
[STT_FUNC
][STB_WEAK
] = "T*";
189 key
[STT_SECTION
][STB_LOCAL
] = "s";
190 key
[STT_SECTION
][STB_GLOBAL
] = "S";
191 key
[STT_SECTION
][STB_WEAK
] = "S*";
192 key
[STT_FILE
][STB_LOCAL
] = "f";
193 key
[STT_FILE
][STB_GLOBAL
] = "F";
194 key
[STT_FILE
][STB_WEAK
] = "F*";
195 key
[STT_COMMON
][STB_LOCAL
] = "c";
196 key
[STT_COMMON
][STB_GLOBAL
] = "C";
197 key
[STT_COMMON
][STB_WEAK
] = "C*";
198 key
[STT_TLS
][STB_LOCAL
] = "l";
199 key
[STT_TLS
][STB_GLOBAL
] = "L";
200 key
[STT_TLS
][STB_WEAK
] = "L*";
204 (void) setlocale(LC_ALL
, "");
205 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
206 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
208 (void) textdomain(TEXT_DOMAIN
);
210 while ((optchar
= getopt(argc
, argv
, optstr
)) != -1) {
212 case 'o': if (COMPAT_FMT_FLAG(FMT_T_OCT
))
213 fmt_flag
= FMT_T_OCT
;
215 (void) fprintf(stderr
, gettext(
216 "%s: -x or -t set, -o ignored\n"),
219 case 'x': if (COMPAT_FMT_FLAG(FMT_T_HEX
))
220 fmt_flag
= FMT_T_HEX
;
222 (void) fprintf(stderr
, gettext(
223 "%s: -o or -t set, -x ignored\n"),
226 case 'h': h_flag
= 1;
228 case 'v': if (!n_flag
)
231 (void) fprintf(stderr
, gettext(
232 "%s: -n set, -v ignored\n"),
235 case 'n': if (!v_flag
)
238 (void) fprintf(stderr
, gettext(
239 "%s: -v set, -n ignored\n"),
242 case 'u': if (!e_flag
&& !g_flag
)
245 (void) fprintf(stderr
, gettext(
246 "%s: -e or -g set, -u ignored\n"),
249 case 'e': if (!u_flag
&& !g_flag
)
252 (void) fprintf(stderr
, gettext(
253 "%s: -u or -g set, -e ignored\n"),
256 case 'g': if (!u_flag
&& !e_flag
)
259 (void) fprintf(stderr
, gettext(
260 "%s: -u or -e set, -g ignored\n"),
263 case 'r': if (R_flag
) {
265 (void) fprintf(stderr
, gettext(
266 "%s: -r set, -R ignored\n"),
271 case 's': s_flag
= 1;
273 case 'p': if (P_flag
== 1) {
274 (void) fprintf(stderr
, gettext(
275 "nm: -P set. -p ignored\n"));
279 case 'P': if (p_flag
== 1) {
280 (void) fprintf(stderr
, gettext(
281 "nm: -p set. -P ignored\n"));
285 case 'l': l_flag
= 1;
287 case 'L': if (D_flag
== 1) {
288 (void) fprintf(stderr
, gettext(
289 "nm: -D set. -L ignored\n"));
293 case 'D': if (L_flag
== 1) {
294 (void) fprintf(stderr
, gettext(
295 "nm: -L set. -D ignored\n"));
302 case 'A': A_flag
= 1;
304 case 'V': V_flag
= 1;
305 (void) fprintf(stderr
, "nm: %s %s\n",
306 (const char *)SGU_PKG
,
307 (const char *)SGU_REL
);
309 case 'f': /* -f is a noop, see man page */
311 case 'R': if (!r_flag
)
314 (void) fprintf(stderr
, gettext(
315 "%s: -r set, -R ignored\n"),
320 case 't': if (strcmp(optarg
, "o") == 0) {
321 new_fmt_flag
= FMT_T_OCT
;
322 } else if (strcmp(optarg
, "d") == 0) {
323 new_fmt_flag
= FMT_T_DEC
;
324 } else if (strcmp(optarg
, "x") == 0) {
325 new_fmt_flag
= FMT_T_HEX
;
327 new_fmt_flag
= FMT_T_NONE
;
329 if (new_fmt_flag
== FMT_T_NONE
) {
331 (void) fprintf(stderr
, gettext(
332 "nm: -t requires radix value (d, o, x): %s\n"), optarg
);
333 } else if (COMPAT_FMT_FLAG(new_fmt_flag
)) {
334 fmt_flag
= new_fmt_flag
;
336 (void) fprintf(stderr
, gettext(
337 "nm: -t or -o or -x set. -t ignored.\n"));
340 case ':': errflag
+= 1;
341 (void) fprintf(stderr
, gettext(
342 "nm: %c requires operand\n"), optopt
);
344 case '?': errflag
+= 1;
350 if (errflag
|| (optind
>= argc
)) {
351 if (!(V_flag
&& (argc
== 2))) {
358 * If no explicit format style was specified, set the default
359 * here. In general, the default is for value and size items
360 * to be displayed in decimal format. The exception is that
361 * the default for -P is hexidecimal.
363 if (fmt_flag
== FMT_T_NONE
)
364 fmt_flag
= P_flag
? FMT_T_HEX
: FMT_T_DEC
;
367 while (optind
< argc
) {
368 each_file(argv
[optind
]);
375 * Print out a usage message in short form when program is invoked
376 * with insufficient or no arguments, and in long form when given
377 * either a ? or an invalid option.
382 (void) fprintf(stderr
, gettext(
383 "Usage: nm [-ACDhLlnPpRrsTVv] [-efox] [-g | -u] [-t d|o|x] file ...\n"));
387 * Takes a filename as input. Test first for a valid version
388 * of libelf.a and exit on error. Process each valid file
389 * or archive given as input on the command line. Check
390 * for file type. If it is an archive, call print_ar_files
391 * to process each member of the archive in the same manner
392 * as object files on the command line. The same tests for
393 * valid object file type apply to regular archive members.
394 * If it is an ELF object file, process it; otherwise
395 * warn that it is an invalid file type and return from
396 * processing the file.
400 each_file(char *filename
)
410 if (stat64(filename
, &buf
) == -1) {
411 (void) fprintf(stderr
, "%s: ", prog_name
);
416 if (elf_version(EV_CURRENT
) == EV_NONE
) {
417 (void) fprintf(stderr
, gettext(
418 "%s: %s: libelf is out of date\n"),
419 prog_name
, filename
);
423 if ((fd
= open((filename
), O_RDONLY
)) == -1) {
424 (void) fprintf(stderr
, gettext("%s: %s: cannot read file\n"),
425 prog_name
, filename
);
430 if ((elf_file
= elf_begin(fd
, cmd
, (Elf
*) 0)) == NULL
) {
431 (void) fprintf(stderr
,
432 "%s: %s: %s\n", prog_name
, filename
, elf_errmsg(-1));
437 file_type
= elf_kind(elf_file
);
438 if (file_type
== ELF_K_AR
) {
439 print_ar_files(fd
, elf_file
, filename
);
441 if (file_type
== ELF_K_ELF
) {
443 if (u_flag
&& !h_flag
) {
445 * u_flag is specified.
448 (void) printf("\n\n%s:\n\n", filename
);
450 (void) printf(gettext(
451 "\n\nUndefined symbols from %s:\n\n"),
453 } else if (!h_flag
& !P_flag
)
455 if (!h_flag
& !P_flag
)
459 (void) printf("\n\n%s:\n", filename
);
462 (void) printf("\n\n%s%s:\n",
465 (void) printf("\n\n%s:\n",
469 archive_name
= (char *)0;
470 process(elf_file
, filename
);
472 (void) fprintf(stderr
, gettext(
473 "%s: %s: invalid file type\n"),
474 prog_name
, filename
);
478 (void) elf_end(elf_file
);
483 * Get the ELF header and, if it exists, call get_symtab()
484 * to begin processing of the file; otherwise, return from
485 * processing the file with a warning.
488 process(Elf
*elf_file
, char *filename
)
492 if (gelf_getehdr(elf_file
, &ehdr
) == NULL
) {
493 (void) fprintf(stderr
,
494 "%s: %s: %s\n", prog_name
, filename
, elf_errmsg(-1));
498 set_A_header(filename
);
499 get_symtab(elf_file
, filename
);
503 * Get section descriptor for the associated string table
504 * and verify that the type of the section pointed to is
505 * indeed of type STRTAB. Returns a valid section descriptor
509 get_scnfd(Elf
* e_file
, int shstrtab
, int SCN_TYPE
)
514 if ((fd_scn
= elf_getscn(e_file
, shstrtab
)) == NULL
) {
518 (void) gelf_getshdr(fd_scn
, &shdr
);
519 if (shdr
.sh_type
!= SCN_TYPE
) {
527 * Print the symbol table. This function does not print the contents
528 * of the symbol table but sets up the parameters and then calls
529 * print_symtab to print the symbols. This function does not assume
530 * that there is only one section of type SYMTAB. Input is an opened
531 * ELF file, a pointer to the ELF header, and the filename.
534 get_symtab(Elf
*elf_file
, char *filename
)
536 Elf_Scn
*scn
, *scnfd
;
538 GElf_Word symtabtype
;
541 if (elf_getshdrstrndx(elf_file
, &shstrndx
) == -1) {
542 (void) fprintf(stderr
, gettext(
543 "%s: %s: cannot get e_shstrndx\n"),
544 prog_name
, filename
);
548 /* get section header string table */
549 scnfd
= get_scnfd(elf_file
, shstrndx
, SHT_STRTAB
);
551 (void) fprintf(stderr
, gettext(
552 "%s: %s: cannot get string table\n"),
553 prog_name
, filename
);
557 data
= elf_getdata(scnfd
, NULL
);
558 if (data
->d_size
== 0) {
559 (void) fprintf(stderr
, gettext(
560 "%s: %s: no data in string table\n"),
561 prog_name
, filename
);
566 symtabtype
= SHT_DYNSYM
;
568 symtabtype
= SHT_SUNW_LDYNSYM
;
570 symtabtype
= SHT_SYMTAB
;
573 while ((scn
= elf_nextscn(elf_file
, scn
)) != 0) {
576 if (gelf_getshdr(scn
, &shdr
) == NULL
) {
577 (void) fprintf(stderr
, "%s: %s: %s:\n",
578 prog_name
, filename
, elf_errmsg(-1));
582 if (shdr
.sh_type
== symtabtype
) {
583 print_symtab(elf_file
, shstrndx
, scn
,
590 * Process member files of an archive. This function provides
591 * a loop through an archive equivalent the processing of
592 * each_file for individual object files.
595 print_ar_files(int fd
, Elf
* elf_file
, char *filename
)
604 archive_name
= filename
;
605 while ((arf
= elf_begin(fd
, cmd
, elf_file
)) != 0) {
606 p_ar
= elf_getarhdr(arf
);
608 (void) fprintf(stderr
, "%s: %s: %s\n",
609 prog_name
, filename
, elf_errmsg(-1));
612 if (p_ar
->ar_name
[0] == '/') {
618 if (!h_flag
& !P_flag
) {
620 (void) printf("\n\n%s[%s]:\n",
621 filename
, p_ar
->ar_name
);
624 (void) printf("\n\n%s%s[%s]:\n",
625 A_header
, filename
, p_ar
->ar_name
);
627 (void) printf("\n\n%s[%s]:\n",
628 filename
, p_ar
->ar_name
);
631 file_type
= elf_kind(arf
);
632 if (file_type
== ELF_K_ELF
) {
633 process(arf
, p_ar
->ar_name
);
635 (void) fprintf(stderr
, gettext(
636 "%s: %s: invalid file type\n"),
637 prog_name
, p_ar
->ar_name
);
649 static void print_header(int);
651 static void print_with_uflag(SYM
*, char *);
653 static void print_with_pflag(int, Elf
*, unsigned int, SYM
*, char *);
654 static void print_with_Pflag(int, Elf
*, unsigned int, SYM
*);
655 static void print_with_otherflags(int, Elf
*, unsigned int,
658 * Print the symbol table according to the flags that were
659 * set, if any. Input is an opened ELF file, the section name,
660 * the section header, the section descriptor, and the filename.
661 * First get the symbol table with a call to elf_getdata.
662 * Then translate the symbol table data in memory by calling
663 * readsyms(). This avoids duplication of function calls
664 * and improves sorting efficiency. qsort is used when sorting
668 print_symtab(Elf
*elf_file
, unsigned int shstrndx
,
669 Elf_Scn
*p_sd
, GElf_Shdr
*shdr
, char *filename
)
675 GElf_Sxword count
= 0;
676 const int ndigits_arr
[] = {
684 * Determine # of digits to use for each numeric value.
686 ndigits
= ndigits_arr
[fmt_flag
];
687 if (gelf_getclass(elf_file
) == ELFCLASS64
)
693 print_header(ndigits
);
696 * get symbol table data
698 if (((sd
= elf_getdata(p_sd
, NULL
)) == NULL
) || (sd
->d_size
== 0)) {
699 (void) fprintf(stderr
,
700 gettext("%s: %s: no symbol table data\n"),
701 prog_name
, filename
);
704 count
= shdr
->sh_size
/ shdr
->sh_entsize
;
707 * translate symbol table data
709 sym_data
= readsyms(sd
, count
, elf_file
, shdr
->sh_link
,
710 (unsigned int)elf_ndxscn(p_sd
));
711 if (sym_data
== NULL
) {
712 (void) fprintf(stderr
, gettext(
713 "%s: %s: problem reading symbol data\n"),
714 prog_name
, filename
);
717 qsort((char *)sym_data
, count
-1, sizeof (SYM
),
718 (int (*)(const void *, const void *))compare
);
726 print_with_uflag(sym_data
, filename
);
731 print_with_pflag(ndigits
, elf_file
, shstrndx
,
734 print_with_Pflag(ndigits
, elf_file
, shstrndx
,
737 print_with_otherflags(ndigits
, elf_file
,
738 shstrndx
, sym_data
, filename
);
743 free(s
); /* allocated in readsym() */
747 * Return appropriate keyletter(s) for -p option.
748 * Returns an index into the key[][] table or NULL if
749 * the value of the keyletter is unknown.
754 return (((a
< TYPE
) && (b
< BIND
)) ? key
[a
][b
] : NULL
);
758 * Return TRUE(1) if the given section is ".bss" for "-p" option.
759 * Return FALSE(0) if not ".bss" section.
762 is_bss_section(unsigned int shndx
, Elf
* elf_file
, unsigned int shstrndx
)
764 Elf_Scn
*scn
= elf_getscn(elf_file
, shndx
);
769 (void) gelf_getshdr(scn
, &shdr
);
770 sym_name
= elf_strptr(elf_file
, shstrndx
, shdr
.sh_name
);
771 if (strcmp(BSS_SECN
, sym_name
) == 0)
778 * Translate symbol table data particularly for sorting.
779 * Input is the symbol table data structure, number of symbols,
780 * opened ELF file, and the string table link offset.
783 readsyms(Elf_Data
* data
, GElf_Sxword num
, Elf
*elf
,
784 unsigned int link
, unsigned int symscnndx
)
788 Elf32_Word
*symshndx
= 0;
789 unsigned int nosymshndx
= 0;
792 if ((buf
= calloc(num
, sizeof (SYM
))) == NULL
) {
793 (void) fprintf(stderr
, gettext("%s: cannot allocate memory\n"),
798 s
= buf
; /* save pointer to head of array */
800 for (i
= 1; i
< num
; i
++, buf
++) {
801 (void) gelf_getsym(data
, i
, &sym
);
804 /* allow to work on machines where NULL-derefs dump core */
805 if (sym
.st_name
== 0)
809 char *name
= (char *)elf_strptr(elf
, link
, sym
.st_name
);
810 dn
= conv_demangle_name(name
);
811 if (strcmp(dn
, name
) == 0) { /* Not demangled */
813 name
= FormatName(name
, d_buf
);
815 } else { /* name demangled */
816 name
= FormatName(name
, dn
);
821 buf
->name
= (char *)elf_strptr(elf
, link
, sym
.st_name
);
823 buf
->value
= sym
.st_value
;
824 buf
->size
= sym
.st_size
;
825 buf
->type
= GELF_ST_TYPE(sym
.st_info
);
826 buf
->bind
= GELF_ST_BIND(sym
.st_info
);
827 buf
->other
= sym
.st_other
;
828 if ((sym
.st_shndx
== SHN_XINDEX
) &&
829 (symshndx
== 0) && (nosymshndx
== 0)) {
833 while ((_scn
= elf_nextscn(elf
, _scn
)) != 0) {
834 if (gelf_getshdr(_scn
, &_shdr
) == 0)
836 if ((_shdr
.sh_type
== SHT_SYMTAB_SHNDX
) &&
837 (_shdr
.sh_link
== symscnndx
)) {
839 if ((_data
= elf_getdata(_scn
,
842 (Elf32_Word
*)_data
->d_buf
;
849 if ((symshndx
) && (sym
.st_shndx
== SHN_XINDEX
)) {
850 buf
->shndx
= symshndx
[i
];
852 buf
->shndx
= sym
.st_shndx
;
853 if (sym
.st_shndx
>= SHN_LORESERVE
)
854 buf
->flags
|= FLG_SYM_SPECSEC
;
861 * compare either by name or by value for sorting.
862 * This is the comparison function called by qsort to
863 * sort the symbols either by name or value when requested.
866 compare(SYM
*a
, SYM
*b
)
869 if (a
->value
> b
->value
)
872 return ((a
->value
== b
->value
) -1);
874 return ((int)strcoll(a
->name
, b
->name
));
878 * Set up a header line for -A option.
881 set_A_header(char *fname
)
886 if (archive_name
== (char *)0) {
887 (void) snprintf(A_header
, sizeof (A_header
), "%s: ", fname
);
889 (void) snprintf(A_header
, sizeof (A_header
), "%s[%s]: ",
890 archive_name
, fname
);
896 * The following functions are called from
901 * Print header line if needed.
904 * ndigits - # of digits to be used to format an integer
905 * value, not counting any '0x' (hex) or '0' (octal) prefix.
908 print_header(int ndigits
)
911 const char *section_title
;
912 const int pad
[] = { /* Extra prefix characters for format */
913 1, /* FMT_T_DEC: '|' */
914 3, /* FMT_T_HEX: '|0x' */
915 2, /* FMT_T_OCT: '|0' */
921 !h_flag
&& !p_flag
&& !P_flag
) {
924 fmt
= "%-9s%-*s%-*s%-6s%-6s%-6s%-8s%s\n\n";
925 section_title
= "Shndx";
927 fmt
= "%-9s%-*s%-*s%-6s%-6s%-6s%-15s%s\n\n";
928 section_title
= "Shname";
931 (void) printf("%s", A_header
);
932 ndigits
+= pad
[fmt_flag
];
933 (void) printf(fmt
, "[Index]", ndigits
, " Value",
934 ndigits
, " Size", "Type", "Bind",
935 "Other", section_title
, "Name");
940 * If the symbol can be printed, then return 1.
941 * If the symbol can not be printed, then return 0.
944 is_sym_print(SYM
*sym_data
)
947 * If -u flag is specified,
948 * the symbol has to be undefined.
951 if ((sym_data
->shndx
== SHN_UNDEF
) &&
952 (strlen(sym_data
->name
) != 0))
959 * If -e flag is specified,
960 * the symbol has to be global or static.
963 switch (sym_data
->type
) {
969 switch (sym_data
->bind
) {
983 * If -g is specified,
984 * the symbol has to be global.
987 switch (sym_data
->type
) {
993 switch (sym_data
->bind
) {
1006 * If it comes here, any symbol can be printed.
1007 * (So basically, -f is no-op.)
1022 if ((sym_data
->shndx
== SHN_UNDEF
) && (strlen(sym_data
->name
))) {
1025 if (archive_name
!= (char *)0)
1026 (void) printf(" %s:%s:%s\n",
1027 archive_name
, filename
,
1030 (void) printf(" %s:%s\n",
1031 filename
, sym_data
->name
);
1034 (void) printf(" %s\n", sym_data
->name
);
1037 (void) printf(" %s:%s\n", filename
, sym_data
->name
);
1043 * Print a symbol type representation suitable for the -p or -P formats.
1046 print_brief_sym_type(Elf
*elf_file
, unsigned int shstrndx
, SYM
*sym_data
)
1048 const char *sym_key
= NULL
;
1050 if ((sym_data
->shndx
== SHN_UNDEF
) && (strlen(sym_data
->name
)))
1051 sym_key
= UNDEFINED
;
1052 else if (sym_data
->type
== STT_SPARC_REGISTER
) {
1053 switch (sym_data
->bind
) {
1054 case STB_LOCAL
: sym_key
= REG_LOCL
;
1056 case STB_GLOBAL
: sym_key
= REG_GLOB
;
1058 case STB_WEAK
: sym_key
= REG_WEAK
;
1060 default : sym_key
= REG_GLOB
;
1063 } else if (((sym_data
->flags
& FLG_SYM_SPECSEC
) == 0) &&
1064 is_bss_section((int)sym_data
->shndx
, elf_file
, shstrndx
)) {
1065 switch (sym_data
->bind
) {
1066 case STB_LOCAL
: sym_key
= BSS_LOCL
;
1068 case STB_GLOBAL
: sym_key
= BSS_GLOB
;
1070 case STB_WEAK
: sym_key
= BSS_WEAK
;
1072 default : sym_key
= BSS_GLOB
;
1077 sym_key
= lookup(sym_data
->type
, sym_data
->bind
);
1080 if (sym_key
!= NULL
) {
1082 (void) printf("%c ", sym_key
[0]);
1084 (void) printf("%-3s", sym_key
);
1087 (void) printf("%-2d", sym_data
->type
);
1089 (void) printf("%-3d", sym_data
->type
);
1100 unsigned int shstrndx
,
1105 const char * const fmt
[] = {
1106 "%.*llu ", /* FMT_T_DEC */
1107 "0x%.*llx ", /* FMT_T_HEX */
1108 "0%.*llo " /* FMT_T_OCT */
1111 if (is_sym_print(sym_data
) != 1)
1117 (void) printf("%s", A_header
);
1121 * (hex/octal/decimal)
1123 (void) printf(fmt
[fmt_flag
], ndigits
, EC_ADDR(sym_data
->value
));
1129 print_brief_sym_type(elf_file
, shstrndx
, sym_data
);
1133 if (archive_name
!= (char *)0)
1134 (void) printf("%s:%s:%s\n", archive_name
,
1135 filename
, sym_data
->name
);
1137 (void) printf("%s:%s\n", filename
,
1141 (void) printf("%s\n", sym_data
->name
);
1144 (void) printf("%s:%s\n", filename
, sym_data
->name
);
1154 unsigned int shstrndx
,
1159 char sym_name
[SYM_LEN
+1];
1161 const char * const fmt
[] = {
1162 "%*llu %*llu \n", /* FMT_T_DEC */
1163 "%*llx %*llx \n", /* FMT_T_HEX */
1164 "%*llo %*llo \n" /* FMT_T_OCT */
1167 if (is_sym_print(sym_data
) != 1)
1173 (void) printf("%s", A_header
);
1178 len
= strlen(sym_data
->name
);
1180 (void) printf("%s ", sym_data
->name
);
1182 (void) sprintf(sym_name
, "%-10s", sym_data
->name
);
1183 (void) printf("%s ", sym_name
);
1189 print_brief_sym_type(elf_file
, shstrndx
, sym_data
);
1192 * Symbol Value & size
1193 * (hex/octal/decimal)
1195 (void) printf(fmt
[fmt_flag
], ndigits
, EC_ADDR(sym_data
->value
),
1196 ndigits
, EC_XWORD(sym_data
->size
));
1200 * other flags specified
1203 print_with_otherflags(
1206 unsigned int shstrndx
,
1211 const char * const fmt_value_size
[] = {
1212 "%*llu|%*lld|", /* FMT_T_DEC */
1213 "0x%.*llx|0x%.*llx|", /* FMT_T_HEX */
1214 "0%.*llo|0%.*llo|" /* FMT_T_OCT */
1216 const char * const fmt_int
[] = {
1217 "%-5d", /* FMT_T_DEC */
1218 "%#-5x", /* FMT_T_HEX */
1219 "%#-5o" /* FMT_T_OCT */
1222 if (is_sym_print(sym_data
) != 1)
1224 (void) printf("%s", A_header
);
1225 (void) printf("[%d]\t|", sym_data
->indx
);
1226 (void) printf(fmt_value_size
[fmt_flag
], ndigits
,
1227 EC_ADDR(sym_data
->value
), ndigits
, EC_XWORD(sym_data
->size
));
1229 switch (sym_data
->type
) {
1230 case STT_NOTYPE
:(void) printf("%-5s", "NOTY"); break;
1231 case STT_OBJECT
:(void) printf("%-5s", "OBJT"); break;
1232 case STT_FUNC
: (void) printf("%-5s", "FUNC"); break;
1233 case STT_SECTION
:(void) printf("%-5s", "SECT"); break;
1234 case STT_FILE
: (void) printf("%-5s", "FILE"); break;
1235 case STT_COMMON
: (void) printf("%-5s", "COMM"); break;
1236 case STT_TLS
: (void) printf("%-5s", "TLS "); break;
1237 case STT_SPARC_REGISTER
: (void) printf("%-5s", "REGI"); break;
1239 (void) printf(fmt_int
[fmt_flag
], sym_data
->type
);
1242 switch (sym_data
->bind
) {
1243 case STB_LOCAL
: (void) printf("%-5s", "LOCL"); break;
1244 case STB_GLOBAL
:(void) printf("%-5s", "GLOB"); break;
1245 case STB_WEAK
: (void) printf("%-5s", "WEAK"); break;
1247 (void) printf("%-5d", sym_data
->bind
);
1248 (void) printf(fmt_int
[fmt_flag
], sym_data
->bind
);
1251 (void) printf(fmt_int
[fmt_flag
], sym_data
->other
);
1254 if (sym_data
->shndx
== SHN_UNDEF
) {
1256 (void) printf("%-7s", "UNDEF");
1258 (void) printf("%-14s", "UNDEF");
1259 } else if (sym_data
->shndx
== SHN_SUNW_IGNORE
) {
1261 (void) printf("%-7s", "IGNORE");
1263 (void) printf("%-14s", "IGNORE");
1264 } else if ((sym_data
->flags
& FLG_SYM_SPECSEC
) &&
1265 (sym_data
->shndx
== SHN_ABS
)) {
1267 (void) printf("%-7s", "ABS");
1269 (void) printf("%-14s", "ABS");
1270 } else if ((sym_data
->flags
& FLG_SYM_SPECSEC
) &&
1271 (sym_data
->shndx
== SHN_COMMON
)) {
1273 (void) printf("%-7s", "COMMON");
1275 (void) printf("%-14s", "COMMON");
1278 Elf_Scn
*scn
= elf_getscn(elf_file
, sym_data
->shndx
);
1281 if ((gelf_getshdr(scn
, &shdr
) != 0) &&
1282 (shdr
.sh_name
!= 0)) {
1283 (void) printf("%-14s",
1284 (char *)elf_strptr(elf_file
,
1285 shstrndx
, shdr
.sh_name
));
1287 (void) printf("%-14d", sym_data
->shndx
);
1290 (void) printf("%-7d", sym_data
->shndx
);
1296 if (archive_name
!= (char *)0)
1297 (void) printf("%s:%s:%s\n", archive_name
,
1298 filename
, sym_data
->name
);
1300 (void) printf("%s:%s\n", filename
,
1304 (void) printf("%s\n", sym_data
->name
);
1307 (void) printf("%s:%s\n", filename
, sym_data
->name
);
1311 * C++ name demangling supporting routines
1313 static const char *ctor_str
= "static constructor function for %s";
1314 static const char *dtor_str
= "static destructor function for %s";
1315 static const char *ptbl_str
= "pointer to the virtual table vector for %s";
1316 static const char *vtbl_str
= "virtual table for %s";
1319 * alloc memory and create name in necessary format.
1320 * Return name string
1323 FormatName(char *OldName
, const char *NewName
)
1327 "%s\n\t\t\t\t\t\t [%s]";
1328 size_t length
= strlen(s
)+strlen(NewName
)+strlen(OldName
)-3;
1329 char *hold
= OldName
;
1330 OldName
= malloc(length
);
1332 (void) snprintf(OldName
, length
, s
, NewName
, hold
);
1338 * Return 1 when s is an exotic name, 0 otherwise. s remains unchanged,
1339 * the exotic name, if exists, is saved in d_buf.
1342 exotic(const char *in_str
)
1344 static char *buff
= 0;
1345 static size_t buf_size
;
1347 size_t sym_len
= strlen(in_str
) + 1;
1352 * We will need to modify the symbol (in_str) as we are analyzing it,
1353 * so copy it into a buffer so that we can play around with it.
1356 buff
= malloc(DEF_MAX_SYM_SIZE
);
1357 buf_size
= DEF_MAX_SYM_SIZE
;
1360 if (sym_len
> buf_size
) {
1363 buff
= malloc(sym_len
);
1368 (void) fprintf(stderr
, gettext(
1369 "%s: cannot allocate memory\n"), prog_name
);
1372 s
= strcpy(buff
, in_str
);
1375 if (strncmp(s
, "__sti__", 7) == 0) {
1377 parse_fn_and_print(ctor_str
, s
);
1378 } else if (strncmp(s
, "__std__", 7) == 0) {
1380 parse_fn_and_print(dtor_str
, s
);
1381 } else if (strncmp(s
, "__vtbl__", 8) == 0) {
1384 (void) sprintf(d_buf
, vtbl_str
, p_buf
);
1385 } else if (strncmp(s
, "__ptbl_vec__", 12) == 0) {
1387 parse_fn_and_print(ptbl_str
, s
);
1398 (void) strcat(p_buf
, "class ");
1399 while (isdigit(*s
)) s
++;
1404 if (*(s
+len
) == '\0') { /* only one class name */
1405 (void) strcat(p_buf
, s
);
1408 { /* two classname %drootname__%dchildname */
1409 char *root
, *child
, *child_len_p
;
1412 child
= s
+ len
+ 2;
1413 child_len_p
= child
;
1414 if (!isdigit(*child
)) {
1415 /* ptbl file name */
1416 /* %drootname__%filename */
1417 /* kludge for getting rid of '_' in file name */
1420 *(root
+ len
) = '\0';
1421 (void) strcat(p_buf
, root
);
1423 (void) strcat(p_buf
, " in ");
1424 for (p
= child
; *p
!= '_'; ++p
)
1428 (void) strcat(p_buf
, child
);
1433 while (isdigit(*child
))
1437 child_len
= atoi(child_len_p
);
1439 if (*(child
+ child_len
) == '\0') {
1440 (void) strcat(p_buf
, child
);
1441 (void) strcat(p_buf
, " derived from ");
1443 *(root
+ len
) = '\0';
1444 (void) strcat(p_buf
, root
);
1448 /* %drootname__%dchildname__filename */
1449 /* kludge for getting rid of '_' in file name */
1451 c
= *(child
+ child_len
);
1452 *(child
+ child_len
) = '\0';
1453 (void) strcat(p_buf
, child
);
1454 *(child
+child_len
) = c
;
1455 (void) strcat(p_buf
, " derived from ");
1457 *(root
+ len
) = '\0';
1458 (void) strcat(p_buf
, root
);
1460 (void) strcat(p_buf
, " in ");
1461 for (p
= child
+ child_len
+ 2; *p
!= '_'; ++p
)
1465 (void) strcat(p_buf
, child
+ child_len
+ 2);
1473 parse_fn_and_print(const char *str
, char *s
)
1478 if ((p1
= p2
= strstr(s
, "_c_")) == NULL
)
1479 if ((p1
= p2
= strstr(s
, "_C_")) == NULL
)
1480 if ((p1
= p2
= strstr(s
, "_cc_")) == NULL
)
1481 if ((p1
= p2
= strstr(s
, "_cxx_")) == NULL
)
1482 if ((p1
= p2
= strstr(s
, "_h_")) ==
1502 for (s
= p1
; *s
!= '_'; --s
)
1506 (void) sprintf(d_buf
, str
, s
);