Print this page
libconv
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/nm/common/nm.c
+++ new/usr/src/cmd/sgs/nm/common/nm.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1988 AT&T
24 24 * Copyright (c) 1989 AT&T
25 25 * All Rights Reserved
26 26 *
27 27 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
28 + * Copyright 2018 Jason King
28 29 */
29 30
30 31 #include <stdio.h>
31 32 #include <stdlib.h>
32 33 #include <unistd.h>
33 34 #include <ctype.h>
34 35 #include <locale.h>
35 36 #include <libelf.h>
36 37 #include <sys/elf_SPARC.h>
37 38
38 39
39 40 /* exit return codes */
40 41 #define NOARGS 1
41 42 #define BADELF 2
42 43 #define NOALLOC 3
43 44
44 45 #include <fcntl.h>
45 46 #include <sys/stat.h>
46 47 #include <errno.h>
47 48 #include <string.h>
48 49 #include <dlfcn.h>
49 50
50 51 #include "sgs.h"
51 52 #include "conv.h"
52 53 #include "gelf.h"
53 54
54 55 typedef struct { /* structure to translate symbol table data */
55 56 int indx;
56 57 char *name;
57 58 GElf_Addr value;
58 59 GElf_Xword size;
59 60 int type;
60 61 int bind;
61 62 unsigned char other;
62 63 unsigned int shndx;
63 64 unsigned int flags; /* flags relevant to entry */
64 65 } SYM;
65 66
66 67 #define FLG_SYM_SPECSEC 0x00000001 /* reserved scn index */
67 68 /* (SHN_ABS, SHN_COMMON, ...) */
68 69
69 70 #define UNDEFINED "U"
70 71 #define BSS_GLOB "B"
71 72 #define BSS_WEAK "B*"
72 73 #define BSS_LOCL "b"
73 74 #define BSS_SECN ".bss"
74 75 #define REG_GLOB "R"
75 76 #define REG_WEAK "R*"
76 77 #define REG_LOCL "r"
77 78
78 79 #define OPTSTR ":APDoxhvnursplLCVefgRTt:" /* option string for getopt() */
79 80
80 81 #define DATESIZE 60
81 82
82 83 #define TYPE 7
83 84 #define BIND 3
84 85
85 86 #define DEF_MAX_SYM_SIZE 256
86 87
87 88 static char *key[TYPE][BIND];
88 89
89 90 /*
90 91 * Format type used for printing value and size items.
91 92 * The non-negative values here are used as array indices into
92 93 * several arrays found below. Renumbering, or adding items,
93 94 * will require changes to those arrays as well.
94 95 */
95 96 typedef enum {
96 97 FMT_T_NONE = -1, /* No format type yet assigned */
97 98
98 99 /* The following are used as array indices */
99 100 FMT_T_DEC = 0,
100 101 FMT_T_HEX = 1,
101 102 FMT_T_OCT = 2
102 103 } FMT_T;
103 104
104 105 /*
105 106 * Determine whether a proposed format type is compatible with the current
106 107 * setting. We allow setting the format as long as it hasn't already
107 108 * been done, or if the new setting is the same as the current one.
108 109 */
109 110 #define COMPAT_FMT_FLAG(new_fmt_flag) \
110 111 (fmt_flag == FMT_T_NONE) || (fmt_flag == new_fmt_flag)
111 112
112 113 static FMT_T fmt_flag = FMT_T_NONE; /* format style to use for value/size */
113 114
114 115 static int /* flags: ?_flag corresponds to ? option */
115 116 h_flag = 0, /* suppress printing of headings */
116 117 v_flag = 0, /* sort external symbols by value */
117 118 n_flag = 0, /* sort external symbols by name */
118 119 u_flag = 0, /* print only undefined symbols */
119 120 r_flag = 0, /* prepend object file or archive name */
120 121 /* to each symbol name */
121 122 R_flag = 0, /* if "-R" issued then prepend archive name, */
122 123 /* object file name to each symbol */
123 124 s_flag = 0, /* print section name instead of section index */
124 125 p_flag = 0, /* produce terse output */
125 126 P_flag = 0, /* Portable format output */
126 127 l_flag = 0, /* produce long listing of output */
127 128 L_flag = 0, /* print SUNW_LDYNSYM instead of SYMTAB */
128 129 D_flag = 0, /* print DYNSYM instead of SYMTAB */
129 130 C_flag = 0, /* print decoded C++ names */
130 131 A_flag = 0, /* File name */
131 132 e_flag = 0, /* -e flag */
132 133 g_flag = 0, /* -g flag */
133 134 V_flag = 0; /* print version information */
134 135 static char A_header[DEF_MAX_SYM_SIZE+1] = {0};
135 136
136 137 static char *prog_name;
137 138 static char *archive_name = (char *)0;
138 139 static int errflag = 0;
139 140 static void usage();
140 141 static void each_file(char *);
141 142 static void process(Elf *, char *);
142 143 static Elf_Scn * get_scnfd(Elf *, int, int);
143 144 static void get_symtab(Elf *, char *);
144 145 static SYM * readsyms(Elf_Data *, GElf_Sxword, Elf *, unsigned int,
145 146 unsigned int);
146 147 static int compare(SYM *, SYM *);
147 148 static char *lookup(int, int);
148 149 static int is_bss_section(unsigned int, Elf *, unsigned int);
149 150 static void print_ar_files(int, Elf *, char *);
150 151 static void print_symtab(Elf *, unsigned int, Elf_Scn *, GElf_Shdr *, char *);
151 152 static void parsename(char *);
152 153 static void parse_fn_and_print(const char *, char *);
153 154 static char d_buf[512];
154 155 static char p_buf[512];
155 156 static int exotic(const char *s);
156 157 static void set_A_header(char *);
157 158 static char *FormatName(char *, const char *);
158 159
159 160
160 161
161 162 /*
162 163 * Parses the command line options and then
163 164 * calls each_file() to process each file.
164 165 */
165 166 int
166 167 main(int argc, char *argv[], char *envp[])
167 168 {
168 169 char *optstr = OPTSTR; /* option string used by getopt() */
169 170 int optchar;
170 171 FMT_T new_fmt_flag;
171 172
172 173 #ifndef XPG4
173 174 /*
174 175 * Check for a binary that better fits this architecture.
175 176 */
176 177 (void) conv_check_native(argv, envp);
177 178 #endif
178 179
179 180 /* table of keyletters for use with -p and -P options */
180 181 key[STT_NOTYPE][STB_LOCAL] = "n";
181 182 key[STT_NOTYPE][STB_GLOBAL] = "N";
182 183 key[STT_NOTYPE][STB_WEAK] = "N*";
183 184 key[STT_OBJECT][STB_LOCAL] = "d";
184 185 key[STT_OBJECT][STB_GLOBAL] = "D";
185 186 key[STT_OBJECT][STB_WEAK] = "D*";
186 187 key[STT_FUNC][STB_LOCAL] = "t";
187 188 key[STT_FUNC][STB_GLOBAL] = "T";
188 189 key[STT_FUNC][STB_WEAK] = "T*";
189 190 key[STT_SECTION][STB_LOCAL] = "s";
190 191 key[STT_SECTION][STB_GLOBAL] = "S";
191 192 key[STT_SECTION][STB_WEAK] = "S*";
192 193 key[STT_FILE][STB_LOCAL] = "f";
193 194 key[STT_FILE][STB_GLOBAL] = "F";
194 195 key[STT_FILE][STB_WEAK] = "F*";
195 196 key[STT_COMMON][STB_LOCAL] = "c";
196 197 key[STT_COMMON][STB_GLOBAL] = "C";
197 198 key[STT_COMMON][STB_WEAK] = "C*";
198 199 key[STT_TLS][STB_LOCAL] = "l";
199 200 key[STT_TLS][STB_GLOBAL] = "L";
200 201 key[STT_TLS][STB_WEAK] = "L*";
201 202
202 203 prog_name = argv[0];
203 204
204 205 (void) setlocale(LC_ALL, "");
205 206 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
206 207 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
207 208 #endif
208 209 (void) textdomain(TEXT_DOMAIN);
209 210
210 211 while ((optchar = getopt(argc, argv, optstr)) != -1) {
211 212 switch (optchar) {
212 213 case 'o': if (COMPAT_FMT_FLAG(FMT_T_OCT))
213 214 fmt_flag = FMT_T_OCT;
214 215 else
215 216 (void) fprintf(stderr, gettext(
216 217 "%s: -x or -t set, -o ignored\n"),
217 218 prog_name);
218 219 break;
219 220 case 'x': if (COMPAT_FMT_FLAG(FMT_T_HEX))
220 221 fmt_flag = FMT_T_HEX;
221 222 else
222 223 (void) fprintf(stderr, gettext(
223 224 "%s: -o or -t set, -x ignored\n"),
224 225 prog_name);
225 226 break;
226 227 case 'h': h_flag = 1;
227 228 break;
228 229 case 'v': if (!n_flag)
229 230 v_flag = 1;
230 231 else
231 232 (void) fprintf(stderr, gettext(
232 233 "%s: -n set, -v ignored\n"),
233 234 prog_name);
234 235 break;
235 236 case 'n': if (!v_flag)
236 237 n_flag = 1;
237 238 else
238 239 (void) fprintf(stderr, gettext(
239 240 "%s: -v set, -n ignored\n"),
240 241 prog_name);
241 242 break;
242 243 case 'u': if (!e_flag && !g_flag)
243 244 u_flag = 1;
244 245 else
245 246 (void) fprintf(stderr, gettext(
246 247 "%s: -e or -g set, -u ignored\n"),
247 248 prog_name);
248 249 break;
249 250 case 'e': if (!u_flag && !g_flag)
250 251 e_flag = 1;
251 252 else
252 253 (void) fprintf(stderr, gettext(
253 254 "%s: -u or -g set, -e ignored\n"),
254 255 prog_name);
255 256 break;
256 257 case 'g': if (!u_flag && !e_flag)
257 258 g_flag = 1;
258 259 else
259 260 (void) fprintf(stderr, gettext(
260 261 "%s: -u or -e set, -g ignored\n"),
261 262 prog_name);
262 263 break;
263 264 case 'r': if (R_flag) {
264 265 R_flag = 0;
265 266 (void) fprintf(stderr, gettext(
266 267 "%s: -r set, -R ignored\n"),
267 268 prog_name);
268 269 }
269 270 r_flag = 1;
270 271 break;
271 272 case 's': s_flag = 1;
272 273 break;
273 274 case 'p': if (P_flag == 1) {
274 275 (void) fprintf(stderr, gettext(
275 276 "nm: -P set. -p ignored\n"));
276 277 } else
277 278 p_flag = 1;
278 279 break;
279 280 case 'P': if (p_flag == 1) {
280 281 (void) fprintf(stderr, gettext(
281 282 "nm: -p set. -P ignored\n"));
282 283 } else
283 284 P_flag = 1;
284 285 break;
285 286 case 'l': l_flag = 1;
286 287 break;
287 288 case 'L': if (D_flag == 1) {
288 289 (void) fprintf(stderr, gettext(
289 290 "nm: -D set. -L ignored\n"));
290 291 } else
291 292 L_flag = 1;
292 293 break;
293 294 case 'D': if (L_flag == 1) {
294 295 (void) fprintf(stderr, gettext(
295 296 "nm: -L set. -D ignored\n"));
296 297 } else
297 298 D_flag = 1;
298 299 break;
299 300 case 'C':
300 301 C_flag = 1;
301 302 break;
302 303 case 'A': A_flag = 1;
303 304 break;
304 305 case 'V': V_flag = 1;
305 306 (void) fprintf(stderr, "nm: %s %s\n",
306 307 (const char *)SGU_PKG,
307 308 (const char *)SGU_REL);
308 309 break;
309 310 case 'f': /* -f is a noop, see man page */
310 311 break;
311 312 case 'R': if (!r_flag)
312 313 R_flag = 1;
313 314 else
314 315 (void) fprintf(stderr, gettext(
315 316 "%s: -r set, -R ignored\n"),
316 317 prog_name);
317 318 break;
318 319 case 'T':
319 320 break;
320 321 case 't': if (strcmp(optarg, "o") == 0) {
321 322 new_fmt_flag = FMT_T_OCT;
322 323 } else if (strcmp(optarg, "d") == 0) {
323 324 new_fmt_flag = FMT_T_DEC;
324 325 } else if (strcmp(optarg, "x") == 0) {
325 326 new_fmt_flag = FMT_T_HEX;
326 327 } else {
327 328 new_fmt_flag = FMT_T_NONE;
328 329 }
329 330 if (new_fmt_flag == FMT_T_NONE) {
330 331 errflag += 1;
331 332 (void) fprintf(stderr, gettext(
332 333 "nm: -t requires radix value (d, o, x): %s\n"), optarg);
333 334 } else if (COMPAT_FMT_FLAG(new_fmt_flag)) {
334 335 fmt_flag = new_fmt_flag;
335 336 } else {
336 337 (void) fprintf(stderr, gettext(
337 338 "nm: -t or -o or -x set. -t ignored.\n"));
338 339 }
339 340 break;
340 341 case ':': errflag += 1;
341 342 (void) fprintf(stderr, gettext(
342 343 "nm: %c requires operand\n"), optopt);
343 344 break;
344 345 case '?': errflag += 1;
345 346 break;
346 347 default: break;
347 348 }
348 349 }
349 350
350 351 if (errflag || (optind >= argc)) {
351 352 if (!(V_flag && (argc == 2))) {
352 353 usage();
353 354 exit(NOARGS);
354 355 }
355 356 }
356 357
357 358 /*
358 359 * If no explicit format style was specified, set the default
359 360 * here. In general, the default is for value and size items
360 361 * to be displayed in decimal format. The exception is that
361 362 * the default for -P is hexidecimal.
362 363 */
363 364 if (fmt_flag == FMT_T_NONE)
364 365 fmt_flag = P_flag ? FMT_T_HEX : FMT_T_DEC;
365 366
366 367
367 368 while (optind < argc) {
368 369 each_file(argv[optind]);
369 370 optind++;
370 371 }
371 372 return (errflag);
372 373 }
373 374
374 375 /*
375 376 * Print out a usage message in short form when program is invoked
376 377 * with insufficient or no arguments, and in long form when given
377 378 * either a ? or an invalid option.
378 379 */
379 380 static void
380 381 usage()
381 382 {
382 383 (void) fprintf(stderr, gettext(
383 384 "Usage: nm [-ACDhLlnPpRrsTVv] [-efox] [-g | -u] [-t d|o|x] file ...\n"));
384 385 }
385 386
386 387 /*
387 388 * Takes a filename as input. Test first for a valid version
388 389 * of libelf.a and exit on error. Process each valid file
389 390 * or archive given as input on the command line. Check
390 391 * for file type. If it is an archive, call print_ar_files
391 392 * to process each member of the archive in the same manner
392 393 * as object files on the command line. The same tests for
393 394 * valid object file type apply to regular archive members.
394 395 * If it is an ELF object file, process it; otherwise
395 396 * warn that it is an invalid file type and return from
396 397 * processing the file.
397 398 */
398 399
399 400 static void
400 401 each_file(char *filename)
401 402 {
402 403 Elf *elf_file;
403 404 int fd;
404 405 Elf_Kind file_type;
405 406
406 407 struct stat64 buf;
407 408
408 409 Elf_Cmd cmd;
409 410 errno = 0;
410 411 if (stat64(filename, &buf) == -1) {
411 412 (void) fprintf(stderr, "%s: ", prog_name);
412 413 perror(filename);
413 414 errflag++;
414 415 return;
415 416 }
416 417 if (elf_version(EV_CURRENT) == EV_NONE) {
417 418 (void) fprintf(stderr, gettext(
418 419 "%s: %s: libelf is out of date\n"),
419 420 prog_name, filename);
420 421 exit(BADELF);
421 422 }
422 423
423 424 if ((fd = open((filename), O_RDONLY)) == -1) {
424 425 (void) fprintf(stderr, gettext("%s: %s: cannot read file\n"),
425 426 prog_name, filename);
426 427 errflag++;
427 428 return;
428 429 }
429 430 cmd = ELF_C_READ;
430 431 if ((elf_file = elf_begin(fd, cmd, (Elf *) 0)) == NULL) {
431 432 (void) fprintf(stderr,
432 433 "%s: %s: %s\n", prog_name, filename, elf_errmsg(-1));
433 434 errflag++;
434 435 (void) close(fd);
435 436 return;
436 437 }
437 438 file_type = elf_kind(elf_file);
438 439 if (file_type == ELF_K_AR) {
439 440 print_ar_files(fd, elf_file, filename);
440 441 } else {
441 442 if (file_type == ELF_K_ELF) {
442 443 #ifndef XPG4
443 444 if (u_flag && !h_flag) {
444 445 /*
445 446 * u_flag is specified.
446 447 */
447 448 if (p_flag)
448 449 (void) printf("\n\n%s:\n\n", filename);
449 450 else
450 451 (void) printf(gettext(
451 452 "\n\nUndefined symbols from %s:\n\n"),
452 453 filename);
453 454 } else if (!h_flag & !P_flag)
454 455 #else
455 456 if (!h_flag & !P_flag)
456 457 #endif
457 458 {
458 459 if (p_flag)
459 460 (void) printf("\n\n%s:\n", filename);
460 461 else {
461 462 if (A_flag != 0)
462 463 (void) printf("\n\n%s%s:\n",
463 464 A_header, filename);
464 465 else
465 466 (void) printf("\n\n%s:\n",
466 467 filename);
467 468 }
468 469 }
469 470 archive_name = (char *)0;
470 471 process(elf_file, filename);
471 472 } else {
472 473 (void) fprintf(stderr, gettext(
473 474 "%s: %s: invalid file type\n"),
474 475 prog_name, filename);
475 476 errflag++;
476 477 }
477 478 }
478 479 (void) elf_end(elf_file);
479 480 (void) close(fd);
480 481 }
481 482
482 483 /*
483 484 * Get the ELF header and, if it exists, call get_symtab()
484 485 * to begin processing of the file; otherwise, return from
485 486 * processing the file with a warning.
486 487 */
487 488 static void
488 489 process(Elf *elf_file, char *filename)
489 490 {
490 491 GElf_Ehdr ehdr;
491 492
492 493 if (gelf_getehdr(elf_file, &ehdr) == NULL) {
493 494 (void) fprintf(stderr,
494 495 "%s: %s: %s\n", prog_name, filename, elf_errmsg(-1));
495 496 return;
496 497 }
497 498
498 499 set_A_header(filename);
499 500 get_symtab(elf_file, filename);
500 501 }
501 502
502 503 /*
503 504 * Get section descriptor for the associated string table
504 505 * and verify that the type of the section pointed to is
505 506 * indeed of type STRTAB. Returns a valid section descriptor
506 507 * or NULL on error.
507 508 */
508 509 static Elf_Scn *
509 510 get_scnfd(Elf * e_file, int shstrtab, int SCN_TYPE)
510 511 {
511 512 Elf_Scn *fd_scn;
512 513 GElf_Shdr shdr;
513 514
514 515 if ((fd_scn = elf_getscn(e_file, shstrtab)) == NULL) {
515 516 return (NULL);
516 517 }
517 518
518 519 (void) gelf_getshdr(fd_scn, &shdr);
519 520 if (shdr.sh_type != SCN_TYPE) {
520 521 return (NULL);
521 522 }
522 523 return (fd_scn);
523 524 }
524 525
525 526
526 527 /*
527 528 * Print the symbol table. This function does not print the contents
528 529 * of the symbol table but sets up the parameters and then calls
529 530 * print_symtab to print the symbols. This function does not assume
530 531 * that there is only one section of type SYMTAB. Input is an opened
531 532 * ELF file, a pointer to the ELF header, and the filename.
532 533 */
533 534 static void
534 535 get_symtab(Elf *elf_file, char *filename)
535 536 {
536 537 Elf_Scn *scn, *scnfd;
537 538 Elf_Data *data;
538 539 GElf_Word symtabtype;
539 540 size_t shstrndx;
540 541
541 542 if (elf_getshdrstrndx(elf_file, &shstrndx) == -1) {
542 543 (void) fprintf(stderr, gettext(
543 544 "%s: %s: cannot get e_shstrndx\n"),
544 545 prog_name, filename);
545 546 return;
546 547 }
547 548
548 549 /* get section header string table */
549 550 scnfd = get_scnfd(elf_file, shstrndx, SHT_STRTAB);
550 551 if (scnfd == NULL) {
551 552 (void) fprintf(stderr, gettext(
552 553 "%s: %s: cannot get string table\n"),
553 554 prog_name, filename);
554 555 return;
555 556 }
556 557
557 558 data = elf_getdata(scnfd, NULL);
558 559 if (data->d_size == 0) {
559 560 (void) fprintf(stderr, gettext(
560 561 "%s: %s: no data in string table\n"),
561 562 prog_name, filename);
562 563 return;
563 564 }
564 565
565 566 if (D_flag)
566 567 symtabtype = SHT_DYNSYM;
567 568 else if (L_flag)
568 569 symtabtype = SHT_SUNW_LDYNSYM;
569 570 else
570 571 symtabtype = SHT_SYMTAB;
571 572
572 573 scn = 0;
573 574 while ((scn = elf_nextscn(elf_file, scn)) != 0) {
574 575 GElf_Shdr shdr;
575 576
576 577 if (gelf_getshdr(scn, &shdr) == NULL) {
577 578 (void) fprintf(stderr, "%s: %s: %s:\n",
578 579 prog_name, filename, elf_errmsg(-1));
579 580 return;
580 581 }
581 582
582 583 if (shdr.sh_type == symtabtype) {
583 584 print_symtab(elf_file, shstrndx, scn,
584 585 &shdr, filename);
585 586 }
586 587 } /* end while */
587 588 }
588 589
589 590 /*
590 591 * Process member files of an archive. This function provides
591 592 * a loop through an archive equivalent the processing of
592 593 * each_file for individual object files.
593 594 */
594 595 static void
595 596 print_ar_files(int fd, Elf * elf_file, char *filename)
596 597 {
597 598 Elf_Arhdr *p_ar;
598 599 Elf *arf;
599 600 Elf_Cmd cmd;
600 601 Elf_Kind file_type;
601 602
602 603
603 604 cmd = ELF_C_READ;
604 605 archive_name = filename;
605 606 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
606 607 p_ar = elf_getarhdr(arf);
607 608 if (p_ar == NULL) {
608 609 (void) fprintf(stderr, "%s: %s: %s\n",
609 610 prog_name, filename, elf_errmsg(-1));
610 611 return;
611 612 }
612 613 if (p_ar->ar_name[0] == '/') {
613 614 cmd = elf_next(arf);
614 615 (void) elf_end(arf);
615 616 continue;
616 617 }
617 618
618 619 if (!h_flag & !P_flag) {
619 620 if (p_flag)
620 621 (void) printf("\n\n%s[%s]:\n",
621 622 filename, p_ar->ar_name);
622 623 else {
623 624 if (A_flag != 0)
624 625 (void) printf("\n\n%s%s[%s]:\n",
625 626 A_header, filename, p_ar->ar_name);
626 627 else
627 628 (void) printf("\n\n%s[%s]:\n",
628 629 filename, p_ar->ar_name);
629 630 }
630 631 }
631 632 file_type = elf_kind(arf);
632 633 if (file_type == ELF_K_ELF) {
633 634 process(arf, p_ar->ar_name);
634 635 } else {
635 636 (void) fprintf(stderr, gettext(
636 637 "%s: %s: invalid file type\n"),
637 638 prog_name, p_ar->ar_name);
638 639 cmd = elf_next(arf);
639 640 (void) elf_end(arf);
640 641 errflag++;
641 642 continue;
642 643 }
643 644
644 645 cmd = elf_next(arf);
645 646 (void) elf_end(arf);
646 647 } /* end while */
647 648 }
648 649
649 650 static void print_header(int);
650 651 #ifndef XPG4
651 652 static void print_with_uflag(SYM *, char *);
652 653 #endif
653 654 static void print_with_pflag(int, Elf *, unsigned int, SYM *, char *);
654 655 static void print_with_Pflag(int, Elf *, unsigned int, SYM *);
655 656 static void print_with_otherflags(int, Elf *, unsigned int,
656 657 SYM *, char *);
657 658 /*
658 659 * Print the symbol table according to the flags that were
659 660 * set, if any. Input is an opened ELF file, the section name,
660 661 * the section header, the section descriptor, and the filename.
661 662 * First get the symbol table with a call to elf_getdata.
662 663 * Then translate the symbol table data in memory by calling
663 664 * readsyms(). This avoids duplication of function calls
664 665 * and improves sorting efficiency. qsort is used when sorting
665 666 * is requested.
666 667 */
667 668 static void
668 669 print_symtab(Elf *elf_file, unsigned int shstrndx,
669 670 Elf_Scn *p_sd, GElf_Shdr *shdr, char *filename)
670 671 {
671 672
672 673 Elf_Data * sd;
673 674 SYM *sym_data;
674 675 SYM *s;
675 676 GElf_Sxword count = 0;
676 677 const int ndigits_arr[] = {
677 678 10, /* FMT_T_DEC */
678 679 8, /* FMT_T_HEX */
679 680 11, /* FMT_T_OCT */
680 681 };
681 682 int ndigits;
682 683
683 684 /*
684 685 * Determine # of digits to use for each numeric value.
685 686 */
686 687 ndigits = ndigits_arr[fmt_flag];
687 688 if (gelf_getclass(elf_file) == ELFCLASS64)
688 689 ndigits *= 2;
689 690
690 691 /*
691 692 * print header
692 693 */
693 694 print_header(ndigits);
694 695
695 696 /*
696 697 * get symbol table data
697 698 */
698 699 if (((sd = elf_getdata(p_sd, NULL)) == NULL) || (sd->d_size == 0)) {
699 700 (void) fprintf(stderr,
700 701 gettext("%s: %s: no symbol table data\n"),
701 702 prog_name, filename);
702 703 return;
703 704 }
704 705 count = shdr->sh_size / shdr->sh_entsize;
705 706
706 707 /*
707 708 * translate symbol table data
708 709 */
709 710 sym_data = readsyms(sd, count, elf_file, shdr->sh_link,
710 711 (unsigned int)elf_ndxscn(p_sd));
711 712 if (sym_data == NULL) {
712 713 (void) fprintf(stderr, gettext(
713 714 "%s: %s: problem reading symbol data\n"),
714 715 prog_name, filename);
715 716 return;
716 717 }
717 718 qsort((char *)sym_data, count-1, sizeof (SYM),
718 719 (int (*)(const void *, const void *))compare);
719 720 s = sym_data;
720 721 while (count > 1) {
721 722 #ifndef XPG4
722 723 if (u_flag) {
723 724 /*
724 725 * U_flag specified
725 726 */
726 727 print_with_uflag(sym_data, filename);
727 728 } else if (p_flag)
728 729 #else
729 730 if (p_flag)
730 731 #endif
731 732 print_with_pflag(ndigits, elf_file, shstrndx,
732 733 sym_data, filename);
733 734 else if (P_flag)
734 735 print_with_Pflag(ndigits, elf_file, shstrndx,
735 736 sym_data);
736 737 else
737 738 print_with_otherflags(ndigits, elf_file,
738 739 shstrndx, sym_data, filename);
739 740 sym_data++;
740 741 count--;
741 742 }
742 743
743 744 free(s); /* allocated in readsym() */
744 745 }
745 746
746 747 /*
747 748 * Return appropriate keyletter(s) for -p option.
748 749 * Returns an index into the key[][] table or NULL if
749 750 * the value of the keyletter is unknown.
750 751 */
751 752 static char *
752 753 lookup(int a, int b)
753 754 {
754 755 return (((a < TYPE) && (b < BIND)) ? key[a][b] : NULL);
755 756 }
756 757
757 758 /*
758 759 * Return TRUE(1) if the given section is ".bss" for "-p" option.
759 760 * Return FALSE(0) if not ".bss" section.
760 761 */
761 762 static int
762 763 is_bss_section(unsigned int shndx, Elf * elf_file, unsigned int shstrndx)
763 764 {
764 765 Elf_Scn *scn = elf_getscn(elf_file, shndx);
765 766 char *sym_name;
766 767
767 768 if (scn != NULL) {
768 769 GElf_Shdr shdr;
769 770 (void) gelf_getshdr(scn, &shdr);
770 771 sym_name = elf_strptr(elf_file, shstrndx, shdr.sh_name);
771 772 if (strcmp(BSS_SECN, sym_name) == 0)
772 773 return (1);
773 774 }
774 775 return (0);
775 776 }
776 777
777 778 /*
778 779 * Translate symbol table data particularly for sorting.
779 780 * Input is the symbol table data structure, number of symbols,
780 781 * opened ELF file, and the string table link offset.
781 782 */
782 783 static SYM *
783 784 readsyms(Elf_Data * data, GElf_Sxword num, Elf *elf,
784 785 unsigned int link, unsigned int symscnndx)
785 786 {
786 787 SYM *s, *buf;
787 788 GElf_Sym sym;
788 789 Elf32_Word *symshndx = 0;
789 790 unsigned int nosymshndx = 0;
790 791 int i;
791 792
792 793 if ((buf = calloc(num, sizeof (SYM))) == NULL) {
793 794 (void) fprintf(stderr, gettext("%s: cannot allocate memory\n"),
794 795 prog_name);
795 796 return (NULL);
796 797 }
797 798
↓ open down ↓ |
760 lines elided |
↑ open up ↑ |
798 799 s = buf; /* save pointer to head of array */
799 800
800 801 for (i = 1; i < num; i++, buf++) {
801 802 (void) gelf_getsym(data, i, &sym);
802 803
803 804 buf->indx = i;
804 805 /* allow to work on machines where NULL-derefs dump core */
805 806 if (sym.st_name == 0)
806 807 buf->name = "";
807 808 else if (C_flag) {
808 - const char *dn;
809 + const char *dn = NULL;
809 810 char *name = (char *)elf_strptr(elf, link, sym.st_name);
811 +
810 812 dn = conv_demangle_name(name);
811 - if (strcmp(dn, name) == 0) { /* Not demangled */
812 - if (exotic(name)) {
813 - name = FormatName(name, d_buf);
814 - }
815 - } else { /* name demangled */
813 + if (dn != name) {
816 814 name = FormatName(name, dn);
815 + free((void *)dn);
816 + } else if (exotic(name)) {
817 + name = FormatName(name, d_buf);
817 818 }
818 819 buf->name = name;
819 820 }
820 821 else
821 822 buf->name = (char *)elf_strptr(elf, link, sym.st_name);
822 823
823 824 buf->value = sym.st_value;
824 825 buf->size = sym.st_size;
825 826 buf->type = GELF_ST_TYPE(sym.st_info);
826 827 buf->bind = GELF_ST_BIND(sym.st_info);
827 828 buf->other = sym.st_other;
828 829 if ((sym.st_shndx == SHN_XINDEX) &&
829 830 (symshndx == 0) && (nosymshndx == 0)) {
830 831 Elf_Scn *_scn;
831 832 GElf_Shdr _shdr;
832 833 _scn = 0;
833 834 while ((_scn = elf_nextscn(elf, _scn)) != 0) {
834 835 if (gelf_getshdr(_scn, &_shdr) == 0)
835 836 break;
836 837 if ((_shdr.sh_type == SHT_SYMTAB_SHNDX) &&
837 838 (_shdr.sh_link == symscnndx)) {
838 839 Elf_Data *_data;
839 840 if ((_data = elf_getdata(_scn,
840 841 0)) != 0) {
841 842 symshndx =
842 843 (Elf32_Word *)_data->d_buf;
843 844 break;
844 845 }
845 846 }
846 847 }
847 848 nosymshndx = 1;
848 849 }
849 850 if ((symshndx) && (sym.st_shndx == SHN_XINDEX)) {
850 851 buf->shndx = symshndx[i];
851 852 } else {
852 853 buf->shndx = sym.st_shndx;
853 854 if (sym.st_shndx >= SHN_LORESERVE)
854 855 buf->flags |= FLG_SYM_SPECSEC;
855 856 }
856 857 } /* end for loop */
857 858 return (s);
858 859 }
859 860
860 861 /*
861 862 * compare either by name or by value for sorting.
862 863 * This is the comparison function called by qsort to
863 864 * sort the symbols either by name or value when requested.
864 865 */
865 866 static int
866 867 compare(SYM *a, SYM *b)
867 868 {
868 869 if (v_flag) {
869 870 if (a->value > b->value)
870 871 return (1);
871 872 else
872 873 return ((a->value == b->value) -1);
873 874 } else
874 875 return ((int)strcoll(a->name, b->name));
875 876 }
876 877
877 878 /*
878 879 * Set up a header line for -A option.
879 880 */
880 881 static void
881 882 set_A_header(char *fname)
882 883 {
883 884 if (A_flag == 0)
884 885 return;
885 886
886 887 if (archive_name == (char *)0) {
887 888 (void) snprintf(A_header, sizeof (A_header), "%s: ", fname);
888 889 } else {
889 890 (void) snprintf(A_header, sizeof (A_header), "%s[%s]: ",
890 891 archive_name, fname);
891 892 }
892 893 }
893 894
894 895 /*
895 896 * output functions
896 897 * The following functions are called from
897 898 * print_symtab().
898 899 */
899 900
900 901 /*
901 902 * Print header line if needed.
902 903 *
903 904 * entry:
904 905 * ndigits - # of digits to be used to format an integer
905 906 * value, not counting any '0x' (hex) or '0' (octal) prefix.
906 907 */
907 908 static void
908 909 print_header(int ndigits)
909 910 {
910 911 const char *fmt;
911 912 const char *section_title;
912 913 const int pad[] = { /* Extra prefix characters for format */
913 914 1, /* FMT_T_DEC: '|' */
914 915 3, /* FMT_T_HEX: '|0x' */
915 916 2, /* FMT_T_OCT: '|0' */
916 917 };
917 918 if (
918 919 #ifndef XPG4
919 920 !u_flag &&
920 921 #endif
921 922 !h_flag && !p_flag && !P_flag) {
922 923 (void) printf("\n");
923 924 if (!s_flag) {
924 925 fmt = "%-9s%-*s%-*s%-6s%-6s%-6s%-8s%s\n\n";
925 926 section_title = "Shndx";
926 927 } else {
927 928 fmt = "%-9s%-*s%-*s%-6s%-6s%-6s%-15s%s\n\n";
928 929 section_title = "Shname";
929 930 }
930 931 if (A_flag != 0)
931 932 (void) printf("%s", A_header);
932 933 ndigits += pad[fmt_flag];
933 934 (void) printf(fmt, "[Index]", ndigits, " Value",
934 935 ndigits, " Size", "Type", "Bind",
935 936 "Other", section_title, "Name");
936 937 }
937 938 }
938 939
939 940 /*
940 941 * If the symbol can be printed, then return 1.
941 942 * If the symbol can not be printed, then return 0.
942 943 */
943 944 static int
944 945 is_sym_print(SYM *sym_data)
945 946 {
946 947 /*
947 948 * If -u flag is specified,
948 949 * the symbol has to be undefined.
949 950 */
950 951 if (u_flag != 0) {
951 952 if ((sym_data->shndx == SHN_UNDEF) &&
952 953 (strlen(sym_data->name) != 0))
953 954 return (1);
954 955 else
955 956 return (0);
956 957 }
957 958
958 959 /*
959 960 * If -e flag is specified,
960 961 * the symbol has to be global or static.
961 962 */
962 963 if (e_flag != 0) {
963 964 switch (sym_data->type) {
964 965 case STT_NOTYPE:
965 966 case STT_OBJECT:
966 967 case STT_FUNC:
967 968 case STT_COMMON:
968 969 case STT_TLS:
969 970 switch (sym_data->bind) {
970 971 case STB_LOCAL:
971 972 case STB_GLOBAL:
972 973 case STB_WEAK:
973 974 return (1);
974 975 default:
975 976 return (0);
976 977 }
977 978 default:
978 979 return (0);
979 980 }
980 981 }
981 982
982 983 /*
983 984 * If -g is specified,
984 985 * the symbol has to be global.
985 986 */
986 987 if (g_flag != 0) {
987 988 switch (sym_data->type) {
988 989 case STT_NOTYPE:
989 990 case STT_OBJECT:
990 991 case STT_FUNC:
991 992 case STT_COMMON:
992 993 case STT_TLS:
993 994 switch (sym_data->bind) {
994 995 case STB_GLOBAL:
995 996 case STB_WEAK:
996 997 return (1);
997 998 default:
998 999 return (0);
999 1000 }
1000 1001 default:
1001 1002 return (0);
1002 1003 }
1003 1004 }
1004 1005
1005 1006 /*
1006 1007 * If it comes here, any symbol can be printed.
1007 1008 * (So basically, -f is no-op.)
1008 1009 */
1009 1010 return (1);
1010 1011 }
1011 1012
1012 1013 #ifndef XPG4
1013 1014 /*
1014 1015 * -u flag specified
1015 1016 */
1016 1017 static void
1017 1018 print_with_uflag(
1018 1019 SYM *sym_data,
1019 1020 char *filename
1020 1021 )
1021 1022 {
1022 1023 if ((sym_data->shndx == SHN_UNDEF) && (strlen(sym_data->name))) {
1023 1024 if (!r_flag) {
1024 1025 if (R_flag) {
1025 1026 if (archive_name != (char *)0)
1026 1027 (void) printf(" %s:%s:%s\n",
1027 1028 archive_name, filename,
1028 1029 sym_data->name);
1029 1030 else
1030 1031 (void) printf(" %s:%s\n",
1031 1032 filename, sym_data->name);
1032 1033 }
1033 1034 else
1034 1035 (void) printf(" %s\n", sym_data->name);
1035 1036 }
1036 1037 else
1037 1038 (void) printf(" %s:%s\n", filename, sym_data->name);
1038 1039 }
1039 1040 }
1040 1041 #endif
1041 1042
1042 1043 /*
1043 1044 * Print a symbol type representation suitable for the -p or -P formats.
1044 1045 */
1045 1046 static void
1046 1047 print_brief_sym_type(Elf *elf_file, unsigned int shstrndx, SYM *sym_data)
1047 1048 {
1048 1049 const char *sym_key = NULL;
1049 1050
1050 1051 if ((sym_data->shndx == SHN_UNDEF) && (strlen(sym_data->name)))
1051 1052 sym_key = UNDEFINED;
1052 1053 else if (sym_data->type == STT_SPARC_REGISTER) {
1053 1054 switch (sym_data->bind) {
1054 1055 case STB_LOCAL : sym_key = REG_LOCL;
1055 1056 break;
1056 1057 case STB_GLOBAL : sym_key = REG_GLOB;
1057 1058 break;
1058 1059 case STB_WEAK : sym_key = REG_WEAK;
1059 1060 break;
1060 1061 default : sym_key = REG_GLOB;
1061 1062 break;
1062 1063 }
1063 1064 } else if (((sym_data->flags & FLG_SYM_SPECSEC) == 0) &&
1064 1065 is_bss_section((int)sym_data->shndx, elf_file, shstrndx)) {
1065 1066 switch (sym_data->bind) {
1066 1067 case STB_LOCAL : sym_key = BSS_LOCL;
1067 1068 break;
1068 1069 case STB_GLOBAL : sym_key = BSS_GLOB;
1069 1070 break;
1070 1071 case STB_WEAK : sym_key = BSS_WEAK;
1071 1072 break;
1072 1073 default : sym_key = BSS_GLOB;
1073 1074 break;
1074 1075 }
1075 1076
1076 1077 } else {
1077 1078 sym_key = lookup(sym_data->type, sym_data->bind);
1078 1079 }
1079 1080
1080 1081 if (sym_key != NULL) {
1081 1082 if (!l_flag)
1082 1083 (void) printf("%c ", sym_key[0]);
1083 1084 else
1084 1085 (void) printf("%-3s", sym_key);
1085 1086 } else {
1086 1087 if (!l_flag)
1087 1088 (void) printf("%-2d", sym_data->type);
1088 1089 else
1089 1090 (void) printf("%-3d", sym_data->type);
1090 1091 }
1091 1092 }
1092 1093
1093 1094 /*
1094 1095 * -p flag specified
1095 1096 */
1096 1097 static void
1097 1098 print_with_pflag(
1098 1099 int ndigits,
1099 1100 Elf *elf_file,
1100 1101 unsigned int shstrndx,
1101 1102 SYM *sym_data,
1102 1103 char *filename
1103 1104 )
1104 1105 {
1105 1106 const char * const fmt[] = {
1106 1107 "%.*llu ", /* FMT_T_DEC */
1107 1108 "0x%.*llx ", /* FMT_T_HEX */
1108 1109 "0%.*llo " /* FMT_T_OCT */
1109 1110 };
1110 1111
1111 1112 if (is_sym_print(sym_data) != 1)
1112 1113 return;
1113 1114 /*
1114 1115 * -A header
1115 1116 */
1116 1117 if (A_flag != 0)
1117 1118 (void) printf("%s", A_header);
1118 1119
1119 1120 /*
1120 1121 * Symbol Value.
1121 1122 * (hex/octal/decimal)
1122 1123 */
1123 1124 (void) printf(fmt[fmt_flag], ndigits, EC_ADDR(sym_data->value));
1124 1125
1125 1126
1126 1127 /*
1127 1128 * Symbol Type.
1128 1129 */
1129 1130 print_brief_sym_type(elf_file, shstrndx, sym_data);
1130 1131
1131 1132 if (!r_flag) {
1132 1133 if (R_flag) {
1133 1134 if (archive_name != (char *)0)
1134 1135 (void) printf("%s:%s:%s\n", archive_name,
1135 1136 filename, sym_data->name);
1136 1137 else
1137 1138 (void) printf("%s:%s\n", filename,
1138 1139 sym_data->name);
1139 1140 }
1140 1141 else
1141 1142 (void) printf("%s\n", sym_data->name);
1142 1143 }
1143 1144 else
1144 1145 (void) printf("%s:%s\n", filename, sym_data->name);
1145 1146 }
1146 1147
1147 1148 /*
1148 1149 * -P flag specified
1149 1150 */
1150 1151 static void
1151 1152 print_with_Pflag(
1152 1153 int ndigits,
1153 1154 Elf *elf_file,
1154 1155 unsigned int shstrndx,
1155 1156 SYM *sym_data
1156 1157 )
1157 1158 {
1158 1159 #define SYM_LEN 10
1159 1160 char sym_name[SYM_LEN+1];
1160 1161 size_t len;
1161 1162 const char * const fmt[] = {
1162 1163 "%*llu %*llu \n", /* FMT_T_DEC */
1163 1164 "%*llx %*llx \n", /* FMT_T_HEX */
1164 1165 "%*llo %*llo \n" /* FMT_T_OCT */
1165 1166 };
1166 1167
1167 1168 if (is_sym_print(sym_data) != 1)
1168 1169 return;
1169 1170 /*
1170 1171 * -A header
1171 1172 */
1172 1173 if (A_flag != 0)
1173 1174 (void) printf("%s", A_header);
1174 1175
1175 1176 /*
1176 1177 * Symbol name
1177 1178 */
1178 1179 len = strlen(sym_data->name);
1179 1180 if (len >= SYM_LEN)
1180 1181 (void) printf("%s ", sym_data->name);
1181 1182 else {
1182 1183 (void) sprintf(sym_name, "%-10s", sym_data->name);
1183 1184 (void) printf("%s ", sym_name);
1184 1185 }
1185 1186
1186 1187 /*
1187 1188 * Symbol Type.
1188 1189 */
1189 1190 print_brief_sym_type(elf_file, shstrndx, sym_data);
1190 1191
1191 1192 /*
1192 1193 * Symbol Value & size
1193 1194 * (hex/octal/decimal)
1194 1195 */
1195 1196 (void) printf(fmt[fmt_flag], ndigits, EC_ADDR(sym_data->value),
1196 1197 ndigits, EC_XWORD(sym_data->size));
1197 1198 }
1198 1199
1199 1200 /*
1200 1201 * other flags specified
1201 1202 */
1202 1203 static void
1203 1204 print_with_otherflags(
1204 1205 int ndigits,
1205 1206 Elf *elf_file,
1206 1207 unsigned int shstrndx,
1207 1208 SYM *sym_data,
1208 1209 char *filename
1209 1210 )
1210 1211 {
1211 1212 const char * const fmt_value_size[] = {
1212 1213 "%*llu|%*lld|", /* FMT_T_DEC */
1213 1214 "0x%.*llx|0x%.*llx|", /* FMT_T_HEX */
1214 1215 "0%.*llo|0%.*llo|" /* FMT_T_OCT */
1215 1216 };
1216 1217 const char * const fmt_int[] = {
1217 1218 "%-5d", /* FMT_T_DEC */
1218 1219 "%#-5x", /* FMT_T_HEX */
1219 1220 "%#-5o" /* FMT_T_OCT */
1220 1221 };
1221 1222
1222 1223 if (is_sym_print(sym_data) != 1)
1223 1224 return;
1224 1225 (void) printf("%s", A_header);
1225 1226 (void) printf("[%d]\t|", sym_data->indx);
1226 1227 (void) printf(fmt_value_size[fmt_flag], ndigits,
1227 1228 EC_ADDR(sym_data->value), ndigits, EC_XWORD(sym_data->size));
1228 1229
1229 1230 switch (sym_data->type) {
1230 1231 case STT_NOTYPE:(void) printf("%-5s", "NOTY"); break;
1231 1232 case STT_OBJECT:(void) printf("%-5s", "OBJT"); break;
1232 1233 case STT_FUNC: (void) printf("%-5s", "FUNC"); break;
1233 1234 case STT_SECTION:(void) printf("%-5s", "SECT"); break;
1234 1235 case STT_FILE: (void) printf("%-5s", "FILE"); break;
1235 1236 case STT_COMMON: (void) printf("%-5s", "COMM"); break;
1236 1237 case STT_TLS: (void) printf("%-5s", "TLS "); break;
1237 1238 case STT_SPARC_REGISTER: (void) printf("%-5s", "REGI"); break;
1238 1239 default:
1239 1240 (void) printf(fmt_int[fmt_flag], sym_data->type);
1240 1241 }
1241 1242 (void) printf("|");
1242 1243 switch (sym_data->bind) {
1243 1244 case STB_LOCAL: (void) printf("%-5s", "LOCL"); break;
1244 1245 case STB_GLOBAL:(void) printf("%-5s", "GLOB"); break;
1245 1246 case STB_WEAK: (void) printf("%-5s", "WEAK"); break;
1246 1247 default:
1247 1248 (void) printf("%-5d", sym_data->bind);
1248 1249 (void) printf(fmt_int[fmt_flag], sym_data->bind);
1249 1250 }
1250 1251 (void) printf("|");
1251 1252 (void) printf(fmt_int[fmt_flag], sym_data->other);
1252 1253 (void) printf("|");
1253 1254
1254 1255 if (sym_data->shndx == SHN_UNDEF) {
1255 1256 if (!s_flag)
1256 1257 (void) printf("%-7s", "UNDEF");
1257 1258 else
1258 1259 (void) printf("%-14s", "UNDEF");
1259 1260 } else if (sym_data->shndx == SHN_SUNW_IGNORE) {
1260 1261 if (!s_flag)
1261 1262 (void) printf("%-7s", "IGNORE");
1262 1263 else
1263 1264 (void) printf("%-14s", "IGNORE");
1264 1265 } else if ((sym_data->flags & FLG_SYM_SPECSEC) &&
1265 1266 (sym_data->shndx == SHN_ABS)) {
1266 1267 if (!s_flag)
1267 1268 (void) printf("%-7s", "ABS");
1268 1269 else
1269 1270 (void) printf("%-14s", "ABS");
1270 1271 } else if ((sym_data->flags & FLG_SYM_SPECSEC) &&
1271 1272 (sym_data->shndx == SHN_COMMON)) {
1272 1273 if (!s_flag)
1273 1274 (void) printf("%-7s", "COMMON");
1274 1275 else
1275 1276 (void) printf("%-14s", "COMMON");
1276 1277 } else {
1277 1278 if (s_flag) {
1278 1279 Elf_Scn *scn = elf_getscn(elf_file, sym_data->shndx);
1279 1280 GElf_Shdr shdr;
1280 1281
1281 1282 if ((gelf_getshdr(scn, &shdr) != 0) &&
1282 1283 (shdr.sh_name != 0)) {
1283 1284 (void) printf("%-14s",
1284 1285 (char *)elf_strptr(elf_file,
1285 1286 shstrndx, shdr.sh_name));
1286 1287 } else {
1287 1288 (void) printf("%-14d", sym_data->shndx);
1288 1289 }
1289 1290 } else {
1290 1291 (void) printf("%-7d", sym_data->shndx);
1291 1292 }
1292 1293 }
1293 1294 (void) printf("|");
1294 1295 if (!r_flag) {
1295 1296 if (R_flag) {
1296 1297 if (archive_name != (char *)0)
1297 1298 (void) printf("%s:%s:%s\n", archive_name,
1298 1299 filename, sym_data->name);
1299 1300 else
1300 1301 (void) printf("%s:%s\n", filename,
1301 1302 sym_data->name);
1302 1303 }
1303 1304 else
1304 1305 (void) printf("%s\n", sym_data->name);
1305 1306 }
1306 1307 else
1307 1308 (void) printf("%s:%s\n", filename, sym_data->name);
1308 1309 }
1309 1310
1310 1311 /*
1311 1312 * C++ name demangling supporting routines
1312 1313 */
1313 1314 static const char *ctor_str = "static constructor function for %s";
1314 1315 static const char *dtor_str = "static destructor function for %s";
1315 1316 static const char *ptbl_str = "pointer to the virtual table vector for %s";
1316 1317 static const char *vtbl_str = "virtual table for %s";
1317 1318
1318 1319 /*
1319 1320 * alloc memory and create name in necessary format.
1320 1321 * Return name string
1321 1322 */
1322 1323 static char *
1323 1324 FormatName(char *OldName, const char *NewName)
1324 1325 {
1325 1326 char *s = p_flag ?
1326 1327 "%s\n [%s]" :
1327 1328 "%s\n\t\t\t\t\t\t [%s]";
1328 1329 size_t length = strlen(s)+strlen(NewName)+strlen(OldName)-3;
1329 1330 char *hold = OldName;
1330 1331 OldName = malloc(length);
1331 1332 /*LINTED*/
1332 1333 (void) snprintf(OldName, length, s, NewName, hold);
1333 1334 return (OldName);
1334 1335 }
1335 1336
1336 1337
1337 1338 /*
1338 1339 * Return 1 when s is an exotic name, 0 otherwise. s remains unchanged,
1339 1340 * the exotic name, if exists, is saved in d_buf.
1340 1341 */
1341 1342 static int
1342 1343 exotic(const char *in_str)
1343 1344 {
1344 1345 static char *buff = 0;
1345 1346 static size_t buf_size;
1346 1347
1347 1348 size_t sym_len = strlen(in_str) + 1;
1348 1349 int tag = 0;
1349 1350 char *s;
1350 1351
1351 1352 /*
1352 1353 * We will need to modify the symbol (in_str) as we are analyzing it,
1353 1354 * so copy it into a buffer so that we can play around with it.
1354 1355 */
1355 1356 if (buff == NULL) {
1356 1357 buff = malloc(DEF_MAX_SYM_SIZE);
1357 1358 buf_size = DEF_MAX_SYM_SIZE;
1358 1359 }
1359 1360
1360 1361 if (sym_len > buf_size) {
1361 1362 if (buff)
1362 1363 free(buff);
1363 1364 buff = malloc(sym_len);
1364 1365 buf_size = sym_len;
1365 1366 }
1366 1367
1367 1368 if (buff == NULL) {
1368 1369 (void) fprintf(stderr, gettext(
1369 1370 "%s: cannot allocate memory\n"), prog_name);
1370 1371 exit(NOALLOC);
1371 1372 }
1372 1373 s = strcpy(buff, in_str);
1373 1374
1374 1375
1375 1376 if (strncmp(s, "__sti__", 7) == 0) {
1376 1377 s += 7; tag = 1;
1377 1378 parse_fn_and_print(ctor_str, s);
1378 1379 } else if (strncmp(s, "__std__", 7) == 0) {
1379 1380 s += 7; tag = 1;
1380 1381 parse_fn_and_print(dtor_str, s);
1381 1382 } else if (strncmp(s, "__vtbl__", 8) == 0) {
1382 1383 s += 8; tag = 1;
1383 1384 parsename(s);
1384 1385 (void) sprintf(d_buf, vtbl_str, p_buf);
1385 1386 } else if (strncmp(s, "__ptbl_vec__", 12) == 0) {
1386 1387 s += 12; tag = 1;
1387 1388 parse_fn_and_print(ptbl_str, s);
1388 1389 }
1389 1390 return (tag);
1390 1391 }
1391 1392
1392 1393 void
1393 1394 parsename(char *s)
1394 1395 {
1395 1396 register int len;
1396 1397 char c, *orig = s;
1397 1398 *p_buf = '\0';
1398 1399 (void) strcat(p_buf, "class ");
1399 1400 while (isdigit(*s)) s++;
1400 1401 c = *s;
1401 1402 *s = '\0';
1402 1403 len = atoi(orig);
1403 1404 *s = c;
1404 1405 if (*(s+len) == '\0') { /* only one class name */
1405 1406 (void) strcat(p_buf, s);
1406 1407 return;
1407 1408 } else
1408 1409 { /* two classname %drootname__%dchildname */
1409 1410 char *root, *child, *child_len_p;
1410 1411 int child_len;
1411 1412 root = s;
1412 1413 child = s + len + 2;
1413 1414 child_len_p = child;
1414 1415 if (!isdigit(*child)) {
1415 1416 /* ptbl file name */
1416 1417 /* %drootname__%filename */
1417 1418 /* kludge for getting rid of '_' in file name */
1418 1419 char *p;
1419 1420 c = *(root + len);
1420 1421 *(root + len) = '\0';
1421 1422 (void) strcat(p_buf, root);
1422 1423 *(root + len) = c;
1423 1424 (void) strcat(p_buf, " in ");
1424 1425 for (p = child; *p != '_'; ++p)
1425 1426 ;
1426 1427 c = *p;
1427 1428 *p = '.';
1428 1429 (void) strcat(p_buf, child);
1429 1430 *p = c;
1430 1431 return;
1431 1432 }
1432 1433
1433 1434 while (isdigit(*child))
1434 1435 child++;
1435 1436 c = *child;
1436 1437 *child = '\0';
1437 1438 child_len = atoi(child_len_p);
1438 1439 *child = c;
1439 1440 if (*(child + child_len) == '\0') {
1440 1441 (void) strcat(p_buf, child);
1441 1442 (void) strcat(p_buf, " derived from ");
1442 1443 c = *(root + len);
1443 1444 *(root + len) = '\0';
1444 1445 (void) strcat(p_buf, root);
1445 1446 *(root + len) = c;
1446 1447 return;
1447 1448 } else {
1448 1449 /* %drootname__%dchildname__filename */
1449 1450 /* kludge for getting rid of '_' in file name */
1450 1451 char *p;
1451 1452 c = *(child + child_len);
1452 1453 *(child + child_len) = '\0';
1453 1454 (void) strcat(p_buf, child);
1454 1455 *(child+child_len) = c;
1455 1456 (void) strcat(p_buf, " derived from ");
1456 1457 c = *(root + len);
1457 1458 *(root + len) = '\0';
1458 1459 (void) strcat(p_buf, root);
1459 1460 *(root + len) = c;
1460 1461 (void) strcat(p_buf, " in ");
1461 1462 for (p = child + child_len + 2; *p != '_'; ++p)
1462 1463 ;
1463 1464 c = *p;
1464 1465 *p = '.';
1465 1466 (void) strcat(p_buf, child + child_len + 2);
1466 1467 *p = c;
1467 1468 return;
1468 1469 }
1469 1470 }
1470 1471 }
1471 1472
1472 1473 void
1473 1474 parse_fn_and_print(const char *str, char *s)
1474 1475 {
1475 1476 char c, *p1, *p2;
1476 1477 int yes = 1;
1477 1478
1478 1479 if ((p1 = p2 = strstr(s, "_c_")) == NULL)
1479 1480 if ((p1 = p2 = strstr(s, "_C_")) == NULL)
1480 1481 if ((p1 = p2 = strstr(s, "_cc_")) == NULL)
1481 1482 if ((p1 = p2 = strstr(s, "_cxx_")) == NULL)
1482 1483 if ((p1 = p2 = strstr(s, "_h_")) ==
1483 1484 NULL)
1484 1485 yes = 0;
1485 1486 else
1486 1487 p2 += 2;
1487 1488 else
1488 1489 p2 += 4;
1489 1490 else
1490 1491 p2 += 3;
1491 1492 else
1492 1493 p2 += 2;
1493 1494 else
1494 1495 p2 += 2;
1495 1496
1496 1497 if (yes) {
1497 1498 *p1 = '.';
1498 1499 c = *p2;
1499 1500 *p2 = '\0';
1500 1501 }
1501 1502
1502 1503 for (s = p1; *s != '_'; --s)
1503 1504 ;
1504 1505 ++s;
1505 1506
1506 1507 (void) sprintf(d_buf, str, s);
1507 1508
1508 1509 if (yes) {
1509 1510 *p1 = '_';
1510 1511 *p2 = c;
1511 1512 }
1512 1513 }
↓ open down ↓ |
686 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX