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