Print this page
6375 Add native name demangling support
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/sgs/dump/common/dump.c
+++ new/usr/src/cmd/sgs/dump/common/dump.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
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
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 * All Rights Reserved
25 25 *
26 26 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
27 + * Copyright 2018, Joyent, Inc.
27 28 */
28 29
29 30 /* Get definitions for the relocation types supported. */
30 31 #define ELF_TARGET_ALL
31 32
32 33 #include <stdio.h>
33 34 #include <stdlib.h>
34 35 #include <locale.h>
35 36 #include <unistd.h>
36 37 #include <libelf.h>
37 38 #include <sys/link.h>
38 39 #include <sys/elf.h>
39 40 #include <sys/machelf.h>
40 41 #include <fcntl.h>
41 42 #include <sys/stat.h>
42 43 #include <errno.h>
43 44 #include <string.h>
44 45 #include "sgs.h"
45 46 #include "conv.h"
46 47 #include "dump.h"
47 48
48 49
49 50 #define OPTSTR "agcd:fhn:oprstvCLT:V?" /* option string for getopt() */
50 51
51 52 const char *UNKNOWN = "<unknown>";
52 53
53 54 static SCNTAB *p_symtab, *p_head_scns, *p_dynsym;
54 55
55 56 static int
56 57 x_flag = 0, /* option requires section header table */
57 58 z_flag = 0, /* process files within an archive */
58 59 rn_flag = 0; /* dump named relocation information */
59 60
60 61 static int
61 62 /* flags: ?_flag corresponds to ? option */
62 63 a_flag = 0, /* dump archive header of each member of archive */
63 64 g_flag = 0, /* dump archive symbol table */
64 65 c_flag = 0, /* dump the string table */
65 66 d_flag = 0, /* dump range of sections */
66 67 f_flag = 0, /* dump each file header */
67 68 h_flag = 0, /* dump section headers */
68 69 n_flag = 0, /* dump named section */
69 70 o_flag = 0, /* dump each program execution header */
70 71 r_flag = 0, /* dump relocation information */
71 72 s_flag = 0, /* dump section contents */
72 73 t_flag = 0, /* dump symbol table entries */
73 74 C_flag = 0, /* dump decoded C++ symbol names */
74 75 L_flag = 0, /* dump dynamic linking information */
75 76 T_flag = 0, /* dump symbol table range */
76 77 V_flag = 0; /* dump version information */
77 78
78 79 int p_flag = 0, /* suppress printing of headings */
79 80 v_flag = 0; /* print information in verbose form */
80 81
81 82 static int
82 83 d_low = 0, /* range for use with -d */
83 84 d_hi = 0,
84 85 d_num = 0;
85 86
86 87 static int
87 88 T_low = 0, /* range for use with -T */
88 89 T_hi = 0,
89 90 T_num = 0;
90 91
91 92 static char *name = NULL; /* for use with -n option */
92 93 char *prog_name;
93 94 static int errflag = 0;
94 95
95 96 static struct stab_list_s {
96 97 struct stab_list_s *next;
97 98 char *strings;
98 99 size_t size;
99 100 } *StringTableList = (void *)0;
100 101
101 102 extern void ar_sym_read();
102 103 extern void dump_exec_header();
103 104
104 105
105 106 /*
106 107 * Get the section descriptor and set the size of the
107 108 * data returned. Data is byte-order converted.
108 109 */
109 110 void *
110 111 get_scndata(Elf_Scn *fd_scn, size_t *size)
111 112 {
112 113 Elf_Data *p_data;
113 114
114 115 p_data = 0;
115 116 if ((p_data = elf_getdata(fd_scn, p_data)) == 0 ||
116 117 p_data->d_size == 0) {
117 118 return (NULL);
118 119 }
119 120 *size = p_data->d_size;
120 121 return (p_data->d_buf);
121 122 }
122 123
123 124 /*
124 125 * Get the section descriptor and set the size of the
125 126 * data returned. Data is raw (i.e., not byte-order converted).
126 127 */
127 128 static void *
128 129 get_rawscn(Elf_Scn *fd_scn, size_t *size)
129 130 {
130 131 Elf_Data *p_data;
131 132
132 133 p_data = 0;
133 134 if ((p_data = elf_rawdata(fd_scn, p_data)) == 0 ||
134 135 p_data->d_size == 0) {
135 136 return (NULL);
136 137 }
137 138
138 139 *size = p_data->d_size;
139 140 return (p_data->d_buf);
140 141 }
141 142
142 143 /*
143 144 * Print out a usage message in short form when program is invoked
144 145 * with insufficient or no arguments, and in long form when given
145 146 * either a ? or an invalid option.
146 147 */
147 148 static void
148 149 usage()
149 150 {
150 151 (void) fprintf(stderr,
151 152 "Usage: %s [-%s] file(s) ...\n", prog_name, OPTSTR);
152 153 if (errflag) {
153 154 (void) fprintf(stderr,
154 155 "\t\t[-a dump archive header of each member of archive]\n\
155 156 [-g dump archive global symbol table]\n\
156 157 [-c dump the string table]\n\
157 158 [-d dump range of sections]\n\
158 159 [-f dump each file header]\n\
159 160 [-h dump section headers]\n\
160 161 [-n dump named section]\n\
161 162 [-o dump each program execution header]\n\
162 163 [-p suppress printing of headings]\n\
163 164 [-r dump relocation information]\n\
164 165 [-s dump section contents]\n\
165 166 [-t dump symbol table entries]\n\
166 167 [-v print information in verbose form]\n\
167 168 [-C dump decoded C++ symbol names]\n\
168 169 [-L dump the .dynamic structure]\n\
169 170 [-T dump symbol table range]\n\
170 171 [-V dump version information]\n");
171 172 }
172 173 }
173 174
174 175 /*
175 176 * Set a range. Input is a character string, a lower
176 177 * bound and an upper bound. This function converts
177 178 * a character string into its correct integer values,
178 179 * setting the first value as the lower bound, and
179 180 * the second value as the upper bound. If more values
180 181 * are given they are ignored with a warning.
181 182 */
182 183 static void
183 184 set_range(char *s, int *low, int *high)
184 185 {
185 186 char *w;
186 187 char *lasts;
187 188
188 189 while ((w = strtok_r(s, ",", &lasts)) != NULL) {
189 190 if (!(*low))
190 191 /* LINTED */
191 192 *low = (int)atol(w);
192 193 else
193 194 if (!(*high))
194 195 /* LINTED */
195 196 *high = (int)atol(w);
196 197 else {
197 198 (void) fprintf(stderr,
198 199 "%s: too many arguments - %s ignored\n",
199 200 prog_name, w);
200 201 return;
201 202 }
202 203 s = NULL;
203 204 } /* end while */
204 205 }
205 206
206 207
207 208 /*
208 209 * Print static shared library information.
209 210 */
210 211 static void
211 212 print_static(SCNTAB *l_scns, char *filename)
212 213 {
213 214 size_t section_size;
214 215 unsigned char *strtab;
215 216 unsigned char *path, buf[1024];
216 217 unsigned long *temp;
217 218 unsigned long total, topath;
218 219
219 220 (void) printf("\n **** STATIC SHARED LIBRARY INFORMATION ****\n");
220 221 (void) printf("\n%s:\n", filename);
221 222 (void) printf("\t");
222 223 section_size = 0;
223 224 if ((strtab = (unsigned char *)
224 225 get_scndata(l_scns->p_sd, §ion_size)) == NULL) {
225 226 return;
226 227 }
227 228
228 229 while (section_size != 0) {
229 230 /* LINTED */
230 231 temp = (unsigned long *)strtab;
231 232 total = temp[0];
232 233 topath = temp[1];
233 234 path = strtab + (topath*sizeof (long));
234 235 (void) strncpy((char *)buf, (char *)path,
235 236 (total - topath)*sizeof (long));
236 237 (void) fprintf(stdout, "%s\n", buf);
237 238 strtab += total*sizeof (long);
238 239 section_size -= (total*sizeof (long));
239 240 }
240 241 }
241 242
242 243 /*
243 244 * Print raw data in hexidecimal. Input is the section data to
244 245 * be printed out and the size of the data. Output is relative
245 246 * to a table lookup in dumpmap.h.
246 247 */
247 248 static void
248 249 print_rawdata(unsigned char *p_sec, size_t size)
249 250 {
250 251 size_t j;
251 252 size_t count;
252 253
253 254 count = 1;
254 255
255 256 (void) printf("\t");
256 257 for (j = size/sizeof (short); j != 0; --j, ++count) {
257 258 (void) printf("%.2x %.2x ", p_sec[0], p_sec[1]);
258 259 p_sec += 2;
259 260 if (count == 12) {
260 261 (void) printf("\n\t");
261 262 count = 0;
262 263 }
263 264 }
264 265
265 266 /*
266 267 * take care of last byte if odd byte section
267 268 */
268 269 if ((size & 0x1L) == 1L)
269 270 (void) printf("%.2x", *p_sec);
270 271 (void) printf("\n");
271 272 }
272 273
273 274
274 275
275 276 /*
276 277 * Print relocation data of type SHT_RELA
277 278 * If d_flag, print data corresponding only to
278 279 * the section or range of sections specified.
279 280 * If n_flag, print data corresponding only to
280 281 * the named section.
281 282 */
282 283 static void
283 284 print_rela(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data,
284 285 GElf_Ehdr * p_ehdr, size_t reloc_size, size_t sym_size, char *filename,
285 286 SCNTAB *reloc_symtab)
286 287 {
287 288 GElf_Rela rela;
288 289 GElf_Sym sym;
289 290 size_t no_entries;
290 291 size_t rel_entsize;
291 292 size_t no_syms;
292 293 int type, symid;
293 294 static int n_title = 0;
294 295 int ndx = 0;
295 296 char *sym_name;
296 297 int adj = 0;
297 298
298 299 if (gelf_getclass(elf_file) == ELFCLASS64)
299 300 adj = 8;
300 301
301 302 rel_entsize = p_scns->p_shdr.sh_entsize;
302 303 if ((rel_entsize == 0) ||
303 304 (rel_entsize > p_scns->p_shdr.sh_size)) {
304 305 rel_entsize = gelf_fsize(elf_file, ELF_T_RELA, 1,
305 306 EV_CURRENT);
306 307 }
307 308 no_entries = reloc_size / rel_entsize;
308 309
309 310 no_syms = sym_size / gelf_fsize(elf_file, ELF_T_SYM, 1, EV_CURRENT);
310 311 while (no_entries--) {
311 312 (void) gelf_getrela(rdata, ndx, &rela);
312 313 /* LINTED */
313 314 type = (int)GELF_R_TYPE(rela.r_info);
314 315 /* LINTED */
315 316 symid = (int)GELF_R_SYM(rela.r_info);
316 317 /* LINTED */
317 318 if ((symid > (no_syms - 1)) || (symid < 0)) {
318 319 (void) fprintf(stderr, "%s: %s: invalid symbol table "
319 320 "offset - %d - in %s\n", prog_name, filename,
320 321 symid, p_scns->scn_name);
321 322 ndx++;
322 323 continue;
323 324 }
324 325 (void) gelf_getsym(sym_data, symid, &sym);
325 326 sym_name = (char *)elf_strptr(elf_file,
326 327 reloc_symtab->p_shdr.sh_link, sym.st_name);
327 328 if (sym_name == NULL)
328 329 sym_name = (char *)UNKNOWN;
329 330 if (r_flag && rn_flag) {
330 331 if (strcmp(name, p_scns->scn_name) != 0) {
331 332 ndx++;
332 333 continue;
333 334 }
334 335 if (!n_title) {
335 336 (void) printf("\n%s:\n", p_scns->scn_name);
336 337 (void) printf("%-*s%-*s%-*s%s\n\n",
337 338 12 + adj, "Offset", 22, "Symndx",
338 339 16, "Type", "Addend");
339 340 n_title = 1;
340 341 }
341 342 }
342 343 if (d_flag) {
343 344 if (!d_hi)
344 345 d_hi = d_low;
345 346 if ((symid < d_low) || (symid > d_hi)) {
346 347 ndx++;
347 348 continue;
348 349 }
349 350 }
350 351
351 352 (void) printf("%-#*llx", 12 + adj, EC_XWORD(rela.r_offset));
352 353 if (!v_flag) {
353 354 (void) printf("%-22d%-18d", symid, type);
354 355 } else {
355 356 Conv_inv_buf_t inv_buf;
356 357
357 358 if (strlen(sym_name)) {
358 359 size_t len = strlen(sym_name) + 1;
359 360 char tmpstr[10];
360 361 if (len > 22) {
361 362 (void) sprintf(tmpstr, "%%-%ds",
362 363 /* LINTED */
363 364 (int)len);
364 365 /*LINTED: E_SEC_PRINTF_VAR_FMT*/
365 366 (void) printf(tmpstr, sym_name);
366 367 } else
367 368 (void) printf("%-22s", sym_name);
368 369 } else {
369 370 (void) printf("%-22d", symid);
370 371 }
371 372 (void) printf("%-20s",
372 373 conv_reloc_type(p_ehdr->e_machine,
373 374 type, DUMP_CONVFMT, &inv_buf));
374 375 }
375 376 (void) printf("%lld\n", EC_SXWORD(rela.r_addend));
376 377 ndx++;
377 378 }
378 379 }
379 380
380 381 /*
381 382 * Print relocation data of type SHT_REL.
382 383 * If d_flag, print data corresponding only to
383 384 * the section or range of sections specified.
384 385 * If n_flag, print data corresponding only to
385 386 * the named section.
386 387 */
387 388 static void
388 389 print_rel(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data,
389 390 GElf_Ehdr *p_ehdr, size_t reloc_size, size_t sym_size, char *filename,
390 391 SCNTAB *reloc_symtab)
391 392 {
392 393 GElf_Rel rel;
393 394 GElf_Sym sym;
394 395 size_t no_entries;
395 396 size_t rel_entsize;
396 397 int type, symid;
397 398 size_t no_syms;
398 399 static int n_title = 0;
399 400 int ndx = 0;
400 401 char *sym_name;
401 402 int adj = 0;
402 403
403 404 if (gelf_getclass(elf_file) == ELFCLASS64)
404 405 adj = 8;
405 406
406 407 rel_entsize = p_scns->p_shdr.sh_entsize;
407 408 if ((rel_entsize == 0) ||
408 409 (rel_entsize > p_scns->p_shdr.sh_size)) {
409 410 rel_entsize = gelf_fsize(elf_file, ELF_T_REL, 1,
410 411 EV_CURRENT);
411 412 }
412 413 no_entries = reloc_size / rel_entsize;
413 414
414 415 no_syms = sym_size / gelf_fsize(elf_file, ELF_T_SYM, 1, EV_CURRENT);
415 416 while (no_entries--) {
416 417 (void) gelf_getrel(rdata, ndx, &rel);
417 418 /* LINTED */
418 419 type = (int)GELF_R_TYPE(rel.r_info);
419 420 /* LINTED */
420 421 symid = (int)GELF_R_SYM(rel.r_info);
421 422 /* LINTED */
422 423 if ((symid > (no_syms - 1)) || (symid < 0)) {
423 424 (void) fprintf(stderr, "%s: %s: invalid symbol table "
424 425 "offset - %d - in %s\n", prog_name, filename,
425 426 symid, p_scns->scn_name);
426 427 ndx++;
427 428 continue;
428 429 }
429 430 (void) gelf_getsym(sym_data, symid, &sym);
430 431 sym_name = (char *)elf_strptr(elf_file,
431 432 reloc_symtab->p_shdr.sh_link, sym.st_name);
432 433 if (sym_name == NULL)
433 434 sym_name = (char *)UNKNOWN;
434 435 if (r_flag && rn_flag) {
435 436 if (strcmp(name, p_scns->scn_name) != 0) {
436 437 ndx++;
437 438 continue;
438 439 }
439 440 if (!n_title) {
440 441 (void) printf("\n%s:\n", p_scns->scn_name);
441 442 (void) printf("%-*s%-*s%s\n\n",
442 443 12 + adj, "Offset", 20, "Symndx", "Type");
443 444 n_title = 1;
444 445 }
445 446 }
446 447 if (d_flag) {
447 448 if (!d_hi)
448 449 d_hi = d_low;
449 450 if ((symid < d_low) || (symid > d_hi)) {
450 451 ndx++;
451 452 continue;
452 453 }
453 454 }
454 455
455 456 (void) printf("%-#*llx", 12 + adj, EC_ADDR(rel.r_offset));
456 457 if (!v_flag) {
457 458 (void) printf("%-20d%-18d", symid, type);
458 459 } else {
459 460 Conv_inv_buf_t inv_buf;
460 461
461 462 if (strlen(sym_name))
462 463 (void) printf("%-20s", sym_name);
463 464 else {
464 465 (void) printf("%-20d", sym.st_name);
465 466 }
466 467 (void) printf("%-20s",
467 468 conv_reloc_type(p_ehdr->e_machine,
468 469 type, DUMP_CONVFMT, &inv_buf));
469 470 }
|
↓ open down ↓ |
433 lines elided |
↑ open up ↑ |
470 471 (void) printf("\n");
471 472 ndx++;
472 473 }
473 474 }
474 475
475 476 /* demangle C++ names */
476 477 static char *
477 478 demangled_name(char *s)
478 479 {
479 480 static char *buf = NULL;
480 - const char *dn;
481 + size_t buflen = 0;
482 + char *dn;
481 483 size_t len;
482 484
483 - dn = conv_demangle_name(s);
485 + dn = (char *)conv_demangle_name(s);
484 486
485 487 /*
486 488 * If not demangled, just return the symbol name
487 489 */
488 - if (strcmp(s, dn) == 0)
490 + if (dn == s)
489 491 return (s);
490 492
493 + len = strlen(dn) + strlen(s) + 4;
494 +
495 + if (buflen < len) {
496 + free(buf);
497 + if ((buf = malloc(len)) == NULL)
498 + return (s);
499 + buflen = len;
500 + }
501 +
491 502 /*
492 503 * Demangled. Format it
493 504 */
494 - if (buf != NULL)
495 - free(buf);
496 -
497 - len = strlen(dn) + strlen(s) + 4;
498 - if ((buf = malloc(len)) == NULL)
499 - return (s);
500 -
501 - (void) snprintf(buf, len, "%s\t[%s]", dn, s);
505 + (void) snprintf(buf, buflen, "%s\t[%s]", dn, s);
506 + free(dn);
502 507 return (buf);
503 508 }
504 509
505 510 /*
506 511 * Print the symbol table. Input is an ELF file descriptor, a
507 512 * pointer to the symbol table SCNTAB structure,
508 513 * the number of symbols, a range of symbols to print,
509 514 * an index which is the number of the
510 515 * section in the file, and the filename. The number of sections,
511 516 * the range, and the index are set in
512 517 * dump_symbol_table, depending on whether -n or -T were set.
513 518 */
514 519 static void
515 520 print_symtab(Elf *elf_file, SCNTAB *p_symtab, Elf_Data *sym_data,
516 521 long range, int index)
517 522 {
518 523 GElf_Sym sym;
|
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
519 524 int adj = 0; /* field adjustment for elf64 */
520 525 Elf32_Word *symshndx = 0;
521 526 unsigned int nosymshndx = 0;
522 527 Conv_inv_buf_t inv_buf;
523 528
524 529
525 530 if (gelf_getclass(elf_file) == ELFCLASS64)
526 531 adj = 8;
527 532
528 533 while (range > 0) {
529 - char *sym_name = (char *)0;
534 + char *sym_name = NULL;
530 535 int type, bind;
531 536 int specsec;
532 537 unsigned int shndx;
533 538
534 539 (void) gelf_getsym(sym_data, index, &sym);
535 540 type = (int)GELF_ST_TYPE(sym.st_info);
536 541 bind = (int)GELF_ST_BIND(sym.st_info);
537 542
538 543 if ((sym.st_shndx == SHN_XINDEX) &&
539 544 (symshndx == 0) && (nosymshndx == 0)) {
540 545 Elf_Scn *_scn;
541 546 GElf_Shdr _shdr;
542 547 size_t symscnndx;
543 548
544 549 symscnndx = elf_ndxscn(p_symtab->p_sd);
545 550 _scn = 0;
546 551 while ((_scn = elf_nextscn(elf_file, _scn)) != 0) {
547 552 if (gelf_getshdr(_scn, &_shdr) == 0)
548 553 break;
549 554 if ((_shdr.sh_type == SHT_SYMTAB_SHNDX) &&
550 555 /* LINTED */
551 556 (_shdr.sh_link == (GElf_Word)symscnndx)) {
552 557 Elf_Data *_data;
553 558
554 559 if ((_data = elf_getdata(_scn, 0)) == 0)
555 560 continue;
556 561
557 562 symshndx = (Elf32_Word *)_data->d_buf;
558 563 nosymshndx = 0;
559 564 break;
560 565 }
561 566 }
562 567 nosymshndx = 1;
563 568 }
564 569
565 570 if ((symshndx) && (sym.st_shndx == SHN_XINDEX)) {
566 571 shndx = symshndx[index];
567 572 specsec = 0;
568 573 } else {
569 574 shndx = sym.st_shndx;
570 575 if ((sym.st_shndx == SHN_UNDEF) ||
571 576 (sym.st_shndx >= SHN_LORESERVE))
572 577 specsec = 1;
573 578 else
574 579 specsec = 0;
575 580 }
576 581
577 582
578 583 (void) printf("[%d]\t ", index++);
579 584
580 585 if (v_flag && (type == STT_SPARC_REGISTER)) {
581 586 /*
582 587 * The strings "REG_G1" through "REG_G7" are intended
583 588 * to be consistent with output from elfdump(1).
584 589 */
585 590 (void) printf("%-*s", 12 + adj,
586 591 conv_sym_SPARC_value(sym.st_value,
587 592 DUMP_CONVFMT, &inv_buf));
588 593 } else {
589 594 (void) printf("0x%-*llx", 10 + adj,
590 595 EC_ADDR(sym.st_value));
591 596 }
592 597
593 598 (void) printf("%-*lld", 9 + adj, EC_XWORD(sym.st_size));
594 599
595 600 if (!v_flag) {
596 601 (void) printf("%d\t\t%d\t%d\t%#x\t",
597 602 type, bind, (int)sym.st_other, (int)shndx);
598 603 } else {
599 604 GElf_Ehdr p_ehdr;
600 605 (void) gelf_getehdr(elf_file, &p_ehdr);
601 606 (void) printf("%s\t",
602 607 conv_sym_info_type(p_ehdr.e_machine, type,
603 608 DUMP_CONVFMT, &inv_buf));
604 609 (void) printf("%s",
605 610 conv_sym_info_bind(bind, DUMP_CONVFMT, &inv_buf));
606 611 (void) printf("\t %d\t", EC_WORD(sym.st_other));
607 612
608 613 if (specsec)
609 614 (void) printf("%s",
610 615 conv_sym_shndx(p_ehdr.e_ident[EI_OSABI],
611 616 p_ehdr.e_machine, shndx,
612 617 CONV_FMT_DECIMAL, &inv_buf));
613 618 else
614 619 (void) printf("%d", EC_WORD(shndx));
615 620 (void) printf("\t");
616 621 }
617 622
618 623 /* support machines where NULL-deref causes core dump */
619 624 if (sym.st_name == 0)
620 625 sym_name = (char *)UNKNOWN;
621 626 else
622 627 if (C_flag)
623 628 sym_name = demangled_name(
624 629 (char *)elf_strptr(elf_file,
625 630 p_symtab->p_shdr.sh_link,
626 631 sym.st_name));
627 632 else
628 633 sym_name = (char *)elf_strptr(elf_file,
629 634 p_symtab->p_shdr.sh_link, sym.st_name);
630 635 if (sym_name == NULL)
631 636 sym_name = (char *)UNKNOWN;
632 637 (void) printf("%s\n", sym_name);
633 638
634 639 range--;
635 640 } /* end while */
636 641 }
637 642
638 643 /*
639 644 * Print the section header table. Input is the SCNTAB structure,
640 645 * the number of sections, an index which is the number of the
641 646 * section in the file, and the filename. The values of the SCNTAB
642 647 * structure, the number of sections, and the index are set in
643 648 * dump_shdr depending on whether the -n or -d modifiers were set.
644 649 */
645 650 static void
646 651 print_shdr(Elf *elf_file, SCNTAB *s, int num_scns, int index)
647 652 {
648 653 SCNTAB *p;
649 654 int num;
650 655 int field;
651 656 GElf_Ehdr p_ehdr;
652 657
653 658 if (gelf_getclass(elf_file) == ELFCLASS64)
654 659 field = 21;
655 660 else
656 661 field = 13;
657 662
658 663 p = s;
659 664 (void) gelf_getehdr(elf_file, &p_ehdr);
660 665
661 666 for (num = 0; num < num_scns; num++, p++) {
662 667 (void) printf("[%d]\t", index++);
663 668 if (!v_flag) {
664 669 (void) printf("%u\t%llu\t",
665 670 EC_WORD(p->p_shdr.sh_type),
666 671 EC_XWORD(p->p_shdr.sh_flags));
667 672 } else {
668 673 Conv_inv_buf_t inv_buf;
669 674
670 675 /*LINTED: E_SEC_PRINTF_VAR_FMT*/
671 676 (void) printf(conv_sec_type(
672 677 p_ehdr.e_ident[EI_OSABI], p_ehdr.e_machine,
673 678 p->p_shdr.sh_type, DUMP_CONVFMT, &inv_buf));
674 679 (void) printf(" ");
675 680
676 681 if (p->p_shdr.sh_flags & SHF_WRITE)
677 682 (void) printf("W");
678 683 else
679 684 (void) printf("-");
680 685 if (p->p_shdr.sh_flags & SHF_ALLOC)
681 686 (void) printf("A");
682 687 else
683 688 (void) printf("-");
684 689 if (p->p_shdr.sh_flags & SHF_EXECINSTR)
685 690 (void) printf("I");
686 691 else
687 692 (void) printf("-");
688 693
689 694 if (p->p_shdr.sh_flags & SHF_ORDERED)
690 695 (void) printf("O");
691 696 if (p->p_shdr.sh_flags & SHF_EXCLUDE)
692 697 (void) printf("E");
693 698
694 699 (void) printf("\t");
695 700
696 701 }
697 702 (void) printf("%-#*llx%-#*llx%-#*llx%s%s\n",
698 703 field, EC_ADDR(p->p_shdr.sh_addr),
699 704 field, EC_OFF(p->p_shdr.sh_offset),
700 705 field, EC_XWORD(p->p_shdr.sh_size),
701 706 /* compatibility: tab for elf32 */
702 707 (field == 13) ? "\t" : " ", p->scn_name);
703 708
704 709 (void) printf("\t%u\t%u\t%-#*llx%-#*llx\n\n",
705 710 EC_WORD(p->p_shdr.sh_link),
706 711 EC_WORD(p->p_shdr.sh_info),
707 712 field, EC_XWORD(p->p_shdr.sh_addralign),
708 713 field, EC_XWORD(p->p_shdr.sh_entsize));
709 714 }
710 715 }
711 716
712 717 /*
713 718 * Check that a range of numbers is valid. Input is
714 719 * a lower bound, an upper bound, a boundary condition,
715 720 * and the filename. Negative numbers and numbers greater
716 721 * than the bound are invalid. low must be smaller than hi.
717 722 * The returned integer is the number of items in the
718 723 * range if it is valid and -1 otherwise.
719 724 */
720 725 static int
721 726 check_range(int low, int hi, size_t bound, char *filename)
722 727 {
723 728 if (((size_t)low > bound) || (low <= 0)) {
724 729 (void) fprintf(stderr,
725 730 "%s: %s: number out of range, %d\n",
726 731 prog_name, filename, low);
727 732 return (-1);
728 733 }
729 734 if (((size_t)hi > bound) || (hi < 0)) {
730 735 (void) fprintf(stderr,
731 736 "%s: %s: number out of range, %d\n",
732 737 prog_name, filename, hi);
733 738 return (-1);
734 739 }
735 740
736 741 if (hi && (low > hi)) {
737 742 (void) fprintf(stderr,
738 743 "%s: %s: invalid range, %d,%d\n",
739 744 prog_name, filename, low, hi);
740 745 return (-1);
741 746 }
742 747 if (hi)
743 748 return (hi - low + 1);
744 749 else
745 750 return (1);
746 751 }
747 752
748 753 /*
749 754 * Print relocation information. Since this information is
750 755 * machine dependent, new sections must be added for each machine
751 756 * that is supported. Input is an ELF file descriptor, the ELF header,
752 757 * the SCNTAB structure, the number of sections, and a filename.
753 758 * Set up necessary information to print relocation information
754 759 * and call the appropriate print function depending on the
755 760 * type of relocation information. If the symbol table is
756 761 * absent, no relocation data is processed. Input is an
757 762 * ELF file descriptor, the ELF header, the SCNTAB structure,
758 763 * and the filename. Set range of d_flag and name if n_flag.
759 764 */
760 765 static void
761 766 dump_reloc_table(Elf *elf_file, GElf_Ehdr *p_ehdr,
762 767 SCNTAB *p_scns, int num_scns, char *filename)
763 768 {
764 769 Elf_Data *rel_data;
765 770 Elf_Data *sym_data;
766 771 size_t sym_size;
767 772 size_t reloc_size;
768 773 SCNTAB *reloc_symtab;
769 774 SCNTAB *head_scns;
770 775 int r_title = 0;
771 776 int adj = 0;
772 777 size_t shnum;
773 778
774 779 if (gelf_getclass(elf_file) == ELFCLASS64)
775 780 adj = 8;
776 781
777 782 if ((!p_flag) && (!r_title)) {
778 783 (void) printf("\n **** RELOCATION INFORMATION ****\n");
779 784 r_title = 1;
780 785 }
781 786
782 787 while (num_scns-- > 0) {
783 788 if ((p_scns->p_shdr.sh_type != SHT_RELA) &&
784 789 (p_scns->p_shdr.sh_type != SHT_REL)) {
785 790 p_scns++;
786 791 continue;
787 792 }
788 793
789 794 head_scns = p_head_scns;
790 795
791 796 if (elf_getshdrnum(elf_file, &shnum) == -1) {
792 797 (void) fprintf(stderr,
793 798 "%s: %s: elf_getshdrnum failed: %s\n",
794 799 prog_name, filename, elf_errmsg(-1));
795 800 return;
796 801 }
797 802
798 803 if ((p_scns->p_shdr.sh_link == 0) ||
799 804 /* LINTED */
800 805 (p_scns->p_shdr.sh_link >= (GElf_Word)shnum)) {
801 806 (void) fprintf(stderr, "%s: %s: invalid sh_link field: "
802 807 "section #: %d sh_link: %d\n",
803 808 /* LINTED */
804 809 prog_name, filename, (int)elf_ndxscn(p_scns->p_sd),
805 810 (int)p_scns->p_shdr.sh_link);
806 811 return;
807 812 }
808 813 head_scns += (p_scns->p_shdr.sh_link -1);
809 814
810 815 if (head_scns->p_shdr.sh_type == SHT_SYMTAB) {
811 816 reloc_symtab = p_symtab;
812 817 } else if (head_scns->p_shdr.sh_type == SHT_DYNSYM) {
813 818 reloc_symtab = p_dynsym;
814 819 } else {
815 820 (void) fprintf(stderr,
816 821 "%s: %s: could not get symbol table\n", prog_name, filename);
817 822 return;
818 823 }
819 824
820 825 sym_data = NULL;
821 826 sym_size = 0;
822 827 reloc_size = 0;
823 828
824 829 if ((sym_data = elf_getdata(reloc_symtab->p_sd, NULL)) == NULL) {
825 830 (void) fprintf(stderr,
826 831 "%s: %s: no symbol table data\n", prog_name, filename);
827 832 return;
828 833 }
829 834 sym_size = sym_data->d_size;
830 835
831 836 if (p_scns == NULL) {
832 837 (void) fprintf(stderr,
833 838 "%s: %s: no section table data\n", prog_name, filename);
834 839 return;
835 840 }
836 841
837 842 if (p_scns->p_shdr.sh_type == SHT_RELA) {
838 843 if (!n_flag && r_flag)
839 844 (void) printf("\n%s:\n", p_scns->scn_name);
840 845 if (!p_flag && (!n_flag && r_flag))
841 846 (void) printf("%-*s%-*s%-*s%s\n\n",
842 847 12 + adj, "Offset", 22, "Symndx",
843 848 18, "Type", "Addend");
844 849 if ((rel_data = elf_getdata(p_scns->p_sd, NULL)) == NULL) {
845 850 (void) fprintf(stderr,
846 851 "%s: %s: no relocation information\n", prog_name, filename);
847 852 return;
848 853 }
849 854 reloc_size = rel_data->d_size;
850 855
851 856 if (n_flag) {
852 857 rn_flag = 1;
853 858 print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr,
854 859 reloc_size, sym_size, filename, reloc_symtab);
855 860 }
856 861 if (d_flag) {
857 862 rn_flag = 0;
858 863 print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr,
859 864 reloc_size, sym_size, filename, reloc_symtab);
860 865 }
861 866 if (!n_flag && !d_flag)
862 867 print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr,
863 868 reloc_size, sym_size, filename, reloc_symtab);
864 869 } else {
865 870 if (p_scns->p_shdr.sh_type == SHT_REL) {
866 871 if (!n_flag && r_flag)
867 872 (void) printf("\n%s:\n", p_scns->scn_name);
868 873 if (!p_flag && (!n_flag && r_flag)) {
869 874 (void) printf("%-*s%-*s%s\n\n",
870 875 12 + adj, "Offset", 20, "Symndx", "Type");
871 876 }
872 877 if ((rel_data = elf_getdata(p_scns->p_sd, NULL))
873 878 == NULL) {
874 879 (void) fprintf(stderr,
875 880 "%s: %s: no relocation information\n", prog_name, filename);
876 881 return;
877 882 }
878 883 reloc_size = rel_data->d_size;
879 884 if (n_flag) {
880 885 rn_flag = 1;
881 886 print_rel(elf_file, p_scns, rel_data, sym_data,
882 887 p_ehdr, reloc_size, sym_size,
883 888 filename, reloc_symtab);
884 889 }
885 890 if (d_flag) {
886 891 rn_flag = 0;
887 892 print_rel(elf_file, p_scns, rel_data, sym_data,
888 893 p_ehdr, reloc_size, sym_size,
889 894 filename, reloc_symtab);
890 895 }
891 896 if (!n_flag && !d_flag)
892 897 print_rel(elf_file, p_scns, rel_data, sym_data,
893 898 p_ehdr, reloc_size, sym_size,
894 899 filename, reloc_symtab);
895 900 }
896 901 }
897 902 p_scns++;
898 903 }
899 904 }
900 905
901 906 /*
902 907 * Print out the string tables. Input is an opened ELF file,
903 908 * the SCNTAB structure, the number of sections, and the filename.
904 909 * Since there can be more than one string table, all sections are
905 910 * examined and any with the correct type are printed out.
906 911 */
907 912 static void
908 913 dump_string_table(SCNTAB *s, int num_scns)
909 914 {
910 915 size_t section_size;
911 916 unsigned char *strtab;
912 917 int beg_of_string;
913 918 int counter = 0;
914 919 int str_off;
915 920 int i;
916 921
917 922 if (!p_flag) {
918 923 (void) printf("\n **** STRING TABLE INFORMATION ****\n");
919 924 }
920 925
921 926 for (i = 0; i < num_scns; i++, s++) {
922 927 if (s->p_shdr.sh_type != SHT_STRTAB)
923 928 continue;
924 929
925 930 str_off = 0;
926 931
927 932 if (!p_flag) {
928 933 (void) printf("\n%s:\n", s->scn_name);
929 934 (void) printf(" <offset> \tName\n");
930 935 }
931 936 section_size = 0;
932 937 if ((strtab = (unsigned char *)
933 938 get_scndata(s->p_sd, §ion_size)) == NULL) {
934 939 continue;
935 940 }
936 941
937 942 if (section_size != 0) {
938 943 (void) printf(" <%d> \t", str_off);
939 944 beg_of_string = 0;
940 945 while (section_size--) {
941 946 unsigned char c = *strtab++;
942 947
943 948 if (beg_of_string) {
944 949 (void) printf(" <%d> \t", str_off);
945 950 counter++;
946 951 beg_of_string = 0;
947 952 }
948 953 str_off++;
949 954 switch (c) {
950 955 case '\0':
951 956 (void) printf("\n");
952 957 beg_of_string = 1;
953 958 break;
954 959 default:
955 960 (void) putchar(c);
956 961 }
957 962 }
958 963 }
959 964 }
960 965 (void) printf("\n");
961 966 }
962 967
963 968 /*
964 969 * Print the symbol table. This function does not print the contents
965 970 * of the symbol table but sets up the parameters and then calls
966 971 * print_symtab to print the symbols. Calling another function to print
967 972 * the symbols allows both -T and -n to work correctly
968 973 * simultaneously. Input is an opened ELF file, a pointer to the
969 974 * symbol table SCNTAB structure, and the filename.
970 975 * Set the range of symbols to print if T_flag, and set
971 976 * name of symbol to print if n_flag.
972 977 */
973 978 static void
974 979 dump_symbol_table(Elf *elf_file, SCNTAB *p_symtab, char *filename)
975 980 {
976 981 Elf_Data *sym_data;
977 982 GElf_Sym T_range, n_range; /* for use with -T and -n */
978 983 size_t count = 0;
979 984 size_t sym_size;
980 985 int index = 1;
981 986 int found_it = 0;
982 987 int i;
983 988 int adj = 0; /* field adjustment for elf64 */
984 989
985 990 if (gelf_getclass(elf_file) == ELFCLASS64)
986 991 adj = 8;
987 992
988 993 if (p_symtab == NULL) {
989 994 (void) fprintf(stderr,
990 995 "%s: %s: could not get symbol table\n", prog_name, filename);
991 996 return;
992 997 }
993 998
994 999 /* get symbol table data */
995 1000 sym_data = NULL;
996 1001 sym_size = 0;
997 1002 if ((sym_data =
998 1003 elf_getdata(p_symtab->p_sd, NULL)) == NULL) {
999 1004 (void) printf("\n%s:\n", p_symtab->scn_name);
1000 1005 (void) printf("No symbol table data\n");
1001 1006 return;
1002 1007 }
1003 1008 sym_size = sym_data->d_size;
1004 1009
1005 1010 count = sym_size / p_symtab->p_shdr.sh_entsize;
1006 1011
1007 1012 if (n_flag && t_flag && !T_flag) {
1008 1013 /* LINTED */
1009 1014 for (i = 1; i < count; i++) {
1010 1015 (void) gelf_getsym(sym_data, i, &n_range);
1011 1016 if (strcmp(name, (char *)
1012 1017 elf_strptr(elf_file,
1013 1018 p_symtab->p_shdr.sh_link,
1014 1019 n_range.st_name)) != 0) {
1015 1020 continue;
1016 1021 } else {
1017 1022 found_it = 1;
1018 1023 if (!p_flag) {
1019 1024 (void) printf(
1020 1025 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1021 1026 (void) printf(
1022 1027 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1023 1028 12 + adj, "Value", 9 + adj, "Size");
1024 1029 }
1025 1030 (void) printf("\n%s:\n", p_symtab->scn_name);
1026 1031 print_symtab(elf_file, p_symtab, sym_data,
1027 1032 1, i);
1028 1033 }
1029 1034 } /* end for */
1030 1035 if (!found_it) {
1031 1036 (void) fprintf(stderr, "%s: %s: %s not found\n",
1032 1037 prog_name, filename, name);
1033 1038 }
1034 1039 } else if (T_flag) {
1035 1040 T_num = check_range(T_low, T_hi, count, filename);
1036 1041 if (T_num < 0)
1037 1042 return;
1038 1043
1039 1044 (void) gelf_getsym(sym_data, T_low-1, &T_range);
1040 1045 index = T_low;
1041 1046
1042 1047 if (!p_flag) {
1043 1048 (void) printf(
1044 1049 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1045 1050 (void) printf(
1046 1051 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1047 1052 12 + adj, "Value", 9 + adj, "Size");
1048 1053 }
1049 1054 (void) printf("\n%s:\n", p_symtab->scn_name);
1050 1055 print_symtab(elf_file, p_symtab, sym_data, T_num, index);
1051 1056 } else {
1052 1057 if (!p_flag) {
1053 1058 (void) printf(
1054 1059 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1055 1060 (void) printf(
1056 1061 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1057 1062 12 + adj, "Value", 9 + adj, "Size");
1058 1063 }
1059 1064 (void) printf("\n%s:\n", p_symtab->scn_name);
1060 1065 print_symtab(elf_file, p_symtab, sym_data, count-1, 1);
1061 1066 }
1062 1067 }
1063 1068
1064 1069
1065 1070 /*
1066 1071 * Print dynamic linking information. Input is an ELF
1067 1072 * file descriptor, the SCNTAB structure, the number of
1068 1073 * sections, and the filename.
1069 1074 */
1070 1075 static void
1071 1076 dump_dynamic(Elf *elf_file, SCNTAB *p_scns, int num_scns, char *filename)
1072 1077 {
1073 1078 #define pdyn_Fmtptr "%#llx"
1074 1079
1075 1080 Elf_Data *dyn_data;
1076 1081 GElf_Dyn p_dyn;
1077 1082 GElf_Phdr p_phdr;
1078 1083 GElf_Ehdr p_ehdr;
1079 1084 int index = 1;
1080 1085 int lib_scns = num_scns;
1081 1086 SCNTAB *l_scns = p_scns;
1082 1087 int header_num = 0;
1083 1088 const char *str;
1084 1089
1085 1090 (void) gelf_getehdr(elf_file, &p_ehdr);
1086 1091
1087 1092 if (!p_flag)
1088 1093 (void) printf("\n **** DYNAMIC SECTION INFORMATION ****\n");
1089 1094
1090 1095 for (; num_scns > 0; num_scns--, p_scns++) {
1091 1096 GElf_Word link;
1092 1097 int ii;
1093 1098
1094 1099
1095 1100 if (p_scns->p_shdr.sh_type != SHT_DYNAMIC)
1096 1101 continue;
1097 1102
1098 1103 if (!p_flag) {
1099 1104 (void) printf("%s:\n", p_scns->scn_name);
1100 1105 (void) printf("[INDEX]\tTag Value\n");
1101 1106 }
1102 1107
1103 1108 if ((dyn_data = elf_getdata(p_scns->p_sd, NULL)) == 0) {
1104 1109 (void) fprintf(stderr, "%s: %s: no data in "
1105 1110 "%s section\n", prog_name, filename,
1106 1111 p_scns->scn_name);
1107 1112 return;
1108 1113 }
1109 1114
1110 1115 link = p_scns->p_shdr.sh_link;
1111 1116 ii = 0;
1112 1117
1113 1118 (void) gelf_getdyn(dyn_data, ii++, &p_dyn);
1114 1119 while (p_dyn.d_tag != DT_NULL) {
1115 1120 union {
1116 1121 Conv_inv_buf_t inv;
1117 1122 Conv_dyn_flag_buf_t dyn_flag;
1118 1123 Conv_dyn_flag1_buf_t dyn_flag1;
1119 1124 Conv_dyn_feature1_buf_t dyn_feature1;
1120 1125 Conv_dyn_posflag1_buf_t dyn_posflag1;
1121 1126 } conv_buf;
1122 1127
1123 1128 (void) printf("[%d]\t%-15.15s ", index++,
1124 1129 conv_dyn_tag(p_dyn.d_tag,
1125 1130 p_ehdr.e_ident[EI_OSABI], p_ehdr.e_machine,
1126 1131 DUMP_CONVFMT, &conv_buf.inv));
1127 1132
1128 1133 /*
1129 1134 * It would be nice to use a table driven loop
1130 1135 * here, but the address space is too sparse
1131 1136 * and irregular. A switch is simple and robust.
1132 1137 */
1133 1138 switch (p_dyn.d_tag) {
1134 1139 /*
1135 1140 * Items with an address value
1136 1141 */
1137 1142 case DT_PLTGOT:
1138 1143 case DT_HASH:
1139 1144 case DT_STRTAB:
1140 1145 case DT_RELA:
1141 1146 case DT_SYMTAB:
1142 1147 case DT_INIT:
1143 1148 case DT_FINI:
1144 1149 case DT_REL:
1145 1150 case DT_DEBUG:
1146 1151 case DT_TEXTREL:
1147 1152 case DT_JMPREL:
1148 1153 case DT_INIT_ARRAY:
1149 1154 case DT_FINI_ARRAY:
1150 1155 case DT_INIT_ARRAYSZ:
1151 1156 case DT_FINI_ARRAYSZ:
1152 1157 case DT_PREINIT_ARRAY:
1153 1158 case DT_PREINIT_ARRAYSZ:
1154 1159 case DT_SUNW_RTLDINF:
1155 1160 case DT_SUNW_CAP:
1156 1161 case DT_SUNW_CAPINFO:
1157 1162 case DT_SUNW_CAPCHAIN:
1158 1163 case DT_SUNW_SYMTAB:
1159 1164 case DT_SUNW_SYMSORT:
1160 1165 case DT_SUNW_TLSSORT:
1161 1166 case DT_PLTPAD:
1162 1167 case DT_MOVETAB:
1163 1168 case DT_SYMINFO:
1164 1169 case DT_RELACOUNT:
1165 1170 case DT_RELCOUNT:
1166 1171 case DT_VERSYM:
1167 1172 case DT_VERDEF:
1168 1173 case DT_VERDEFNUM:
1169 1174 case DT_VERNEED:
1170 1175 (void) printf(pdyn_Fmtptr,
1171 1176 EC_ADDR(p_dyn.d_un.d_ptr));
1172 1177 break;
1173 1178
1174 1179 /*
1175 1180 * Items with a string value
1176 1181 */
1177 1182 case DT_NEEDED:
1178 1183 case DT_SONAME:
1179 1184 case DT_RPATH:
1180 1185 case DT_RUNPATH:
1181 1186 case DT_SUNW_AUXILIARY:
1182 1187 case DT_SUNW_FILTER:
1183 1188 case DT_CONFIG:
1184 1189 case DT_DEPAUDIT:
1185 1190 case DT_AUDIT:
1186 1191 case DT_AUXILIARY:
1187 1192 case DT_USED:
1188 1193 case DT_FILTER:
1189 1194 if (v_flag) { /* Look up the string */
1190 1195 str = (char *)elf_strptr(elf_file, link,
1191 1196 p_dyn.d_un.d_ptr);
1192 1197 if (!(str && *str))
1193 1198 str = (char *)UNKNOWN;
1194 1199 (void) printf("%s", str);
1195 1200 } else { /* Show the address */
1196 1201 (void) printf(pdyn_Fmtptr,
1197 1202 EC_ADDR(p_dyn.d_un.d_ptr));
1198 1203 }
1199 1204 break;
1200 1205
1201 1206 /*
1202 1207 * Items with a literal value
1203 1208 */
1204 1209 case DT_PLTRELSZ:
1205 1210 case DT_RELASZ:
1206 1211 case DT_RELAENT:
1207 1212 case DT_STRSZ:
1208 1213 case DT_SYMENT:
1209 1214 case DT_RELSZ:
1210 1215 case DT_RELENT:
1211 1216 case DT_PLTREL:
1212 1217 case DT_BIND_NOW:
1213 1218 case DT_CHECKSUM:
1214 1219 case DT_PLTPADSZ:
1215 1220 case DT_MOVEENT:
1216 1221 case DT_MOVESZ:
1217 1222 case DT_SYMINSZ:
1218 1223 case DT_SYMINENT:
1219 1224 case DT_VERNEEDNUM:
1220 1225 case DT_SPARC_REGISTER:
1221 1226 case DT_SUNW_SYMSZ:
1222 1227 case DT_SUNW_SORTENT:
1223 1228 case DT_SUNW_SYMSORTSZ:
1224 1229 case DT_SUNW_TLSSORTSZ:
1225 1230 case DT_SUNW_STRPAD:
1226 1231 case DT_SUNW_CAPCHAINENT:
1227 1232 case DT_SUNW_CAPCHAINSZ:
1228 1233 case DT_SUNW_ASLR:
1229 1234 (void) printf(pdyn_Fmtptr,
1230 1235 EC_XWORD(p_dyn.d_un.d_val));
1231 1236 break;
1232 1237
1233 1238 /*
1234 1239 * Integer items that are bitmasks, or which
1235 1240 * can be otherwise formatted in symbolic form.
1236 1241 */
1237 1242 case DT_FLAGS:
1238 1243 case DT_FEATURE_1:
1239 1244 case DT_POSFLAG_1:
1240 1245 case DT_FLAGS_1:
1241 1246 case DT_SUNW_LDMACH:
1242 1247 str = NULL;
1243 1248 if (v_flag) {
1244 1249 switch (p_dyn.d_tag) {
1245 1250 case DT_FLAGS:
1246 1251 str = conv_dyn_flag(
1247 1252 p_dyn.d_un.d_val,
1248 1253 DUMP_CONVFMT,
1249 1254 &conv_buf.dyn_flag);
1250 1255 break;
1251 1256 case DT_FEATURE_1:
1252 1257 str = conv_dyn_feature1(
1253 1258 p_dyn.d_un.d_val,
1254 1259 DUMP_CONVFMT,
1255 1260 &conv_buf.dyn_feature1);
1256 1261 break;
1257 1262 case DT_POSFLAG_1:
1258 1263 str = conv_dyn_posflag1(
1259 1264 p_dyn.d_un.d_val,
1260 1265 DUMP_CONVFMT,
1261 1266 &conv_buf.dyn_posflag1);
1262 1267 break;
1263 1268 case DT_FLAGS_1:
1264 1269 str = conv_dyn_flag1(
1265 1270 p_dyn.d_un.d_val, 0,
1266 1271 &conv_buf.dyn_flag1);
1267 1272 break;
1268 1273 case DT_SUNW_LDMACH:
1269 1274 str = conv_ehdr_mach(
1270 1275 p_dyn.d_un.d_val, 0,
1271 1276 &conv_buf.inv);
1272 1277 break;
1273 1278 }
1274 1279 }
1275 1280 if (str) { /* Show as string */
1276 1281 (void) printf("%s", str);
1277 1282 } else { /* Numeric form */
1278 1283 (void) printf(pdyn_Fmtptr,
1279 1284 EC_ADDR(p_dyn.d_un.d_ptr));
1280 1285 }
1281 1286 break;
1282 1287
1283 1288 /*
1284 1289 * Depreciated items with a literal value
1285 1290 */
1286 1291 case DT_DEPRECATED_SPARC_REGISTER:
1287 1292 (void) printf(pdyn_Fmtptr
1288 1293 " (deprecated value)",
1289 1294 EC_XWORD(p_dyn.d_un.d_val));
1290 1295 break;
1291 1296
1292 1297 /* Ignored items */
1293 1298 case DT_SYMBOLIC:
1294 1299 (void) printf("(ignored)");
1295 1300 break;
1296 1301 }
1297 1302 (void) printf("\n");
1298 1303 (void) gelf_getdyn(dyn_data, ii++, &p_dyn);
1299 1304 }
1300 1305 }
1301 1306
1302 1307 /*
1303 1308 * Check for existence of static shared library information.
1304 1309 */
1305 1310 while (header_num < p_ehdr.e_phnum) {
1306 1311 (void) gelf_getphdr(elf_file, header_num, &p_phdr);
1307 1312 if (p_phdr.p_type == PT_SHLIB) {
1308 1313 while (--lib_scns > 0) {
1309 1314 if (strcmp(l_scns->scn_name, ".lib") == 0) {
1310 1315 print_static(l_scns, filename);
1311 1316 }
1312 1317 l_scns++;
1313 1318 }
1314 1319 }
1315 1320 header_num++;
1316 1321 }
1317 1322 #undef pdyn_Fmtptr
1318 1323 }
1319 1324
1320 1325 /*
1321 1326 * Print the ELF header. Input is an ELF file descriptor
1322 1327 * and the filename. If f_flag is set, the ELF header is
1323 1328 * printed to stdout, otherwise the function returns after
1324 1329 * setting the pointer to the ELF header. Any values which
1325 1330 * are not known are printed in decimal. Fields must be updated
1326 1331 * as new values are added.
1327 1332 */
1328 1333 static GElf_Ehdr *
1329 1334 dump_elf_header(Elf *elf_file, char *filename, GElf_Ehdr * elf_head_p)
1330 1335 {
1331 1336 int class;
1332 1337 int field;
1333 1338
1334 1339 if (gelf_getehdr(elf_file, elf_head_p) == NULL) {
1335 1340 (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename,
1336 1341 elf_errmsg(-1));
1337 1342 return (NULL);
1338 1343 }
1339 1344
1340 1345 class = (int)elf_head_p->e_ident[4];
1341 1346
1342 1347 if (class == ELFCLASS64)
1343 1348 field = 21;
1344 1349 else
1345 1350 field = 13;
1346 1351
1347 1352 if (!f_flag)
1348 1353 return (elf_head_p);
1349 1354
1350 1355 if (!p_flag) {
1351 1356 (void) printf("\n **** ELF HEADER ****\n");
1352 1357 (void) printf("%-*s%-11s%-*sMachine Version\n",
1353 1358 field, "Class", "Data", field, "Type");
1354 1359 (void) printf("%-*s%-11s%-*sFlags Ehsize\n",
1355 1360 field, "Entry", "Phoff", field, "Shoff");
1356 1361 (void) printf("%-*s%-11s%-*sShnum Shstrndx\n\n",
1357 1362 field, "Phentsize", "Phnum", field, "Shentsz");
1358 1363 }
1359 1364
1360 1365 if (!v_flag) {
1361 1366 (void) printf("%-*d%-11d%-*d%-12d%d\n",
1362 1367 field, elf_head_p->e_ident[4], elf_head_p->e_ident[5],
1363 1368 field, (int)elf_head_p->e_type, (int)elf_head_p->e_machine,
1364 1369 elf_head_p->e_version);
1365 1370 } else {
1366 1371 Conv_inv_buf_t inv_buf;
1367 1372
1368 1373 (void) printf("%-*s", field,
1369 1374 conv_ehdr_class(class, DUMP_CONVFMT, &inv_buf));
1370 1375 (void) printf("%-11s",
1371 1376 conv_ehdr_data(elf_head_p->e_ident[5], DUMP_CONVFMT,
1372 1377 &inv_buf));
1373 1378 (void) printf("%-*s", field,
1374 1379 conv_ehdr_type(elf_head_p->e_ident[EI_OSABI],
1375 1380 elf_head_p->e_type, DUMP_CONVFMT, &inv_buf));
1376 1381 (void) printf("%-12s",
1377 1382 conv_ehdr_mach(elf_head_p->e_machine, DUMP_CONVFMT,
1378 1383 &inv_buf));
1379 1384 (void) printf("%s\n",
1380 1385 conv_ehdr_vers(elf_head_p->e_version, DUMP_CONVFMT,
1381 1386 &inv_buf));
1382 1387 }
1383 1388 (void) printf("%-#*llx%-#11llx%-#*llx%-#12x%#x\n",
1384 1389 field, EC_ADDR(elf_head_p->e_entry), EC_OFF(elf_head_p->e_phoff),
1385 1390 field, EC_OFF(elf_head_p->e_shoff), EC_WORD(elf_head_p->e_flags),
1386 1391 EC_WORD(elf_head_p->e_ehsize));
1387 1392 if (!v_flag || (elf_head_p->e_shstrndx != SHN_XINDEX)) {
1388 1393 (void) printf("%-#*x%-11u%-#*x%-12u%u\n",
1389 1394 field, EC_WORD(elf_head_p->e_phentsize),
1390 1395 EC_WORD(elf_head_p->e_phnum),
1391 1396 field, EC_WORD(elf_head_p->e_shentsize),
1392 1397 EC_WORD(elf_head_p->e_shnum),
1393 1398 EC_WORD(elf_head_p->e_shstrndx));
1394 1399 } else {
1395 1400 (void) printf("%-#*x%-11u%-#*x%-12uXINDEX\n",
1396 1401 field, EC_WORD(elf_head_p->e_phentsize),
1397 1402 EC_WORD(elf_head_p->e_phnum),
1398 1403 field, EC_WORD(elf_head_p->e_shentsize),
1399 1404 EC_WORD(elf_head_p->e_shnum));
1400 1405 }
1401 1406 if ((elf_head_p->e_shnum == 0) && (elf_head_p->e_shoff > 0)) {
1402 1407 Elf_Scn *scn;
1403 1408 GElf_Shdr shdr0;
1404 1409 int field;
1405 1410
1406 1411 if (gelf_getclass(elf_file) == ELFCLASS64)
1407 1412 field = 21;
1408 1413 else
1409 1414 field = 13;
1410 1415 if (!p_flag) {
1411 1416 (void) printf("\n **** SECTION HEADER[0] "
1412 1417 "{Elf Extensions} ****\n");
1413 1418 (void) printf(
1414 1419 "[No]\tType\tFlags\t%-*s %-*s%-*s%sName\n",
1415 1420 field, "Addr", field, "Offset", field,
1416 1421 "Size(shnum)",
1417 1422 /* compatibility: tab for elf32 */
1418 1423 (field == 13) ? "\t" : " ");
1419 1424 (void) printf("\tLn(strndx) Info\t%-*s Entsize\n",
1420 1425 field, "Adralgn");
1421 1426 }
1422 1427 if ((scn = elf_getscn(elf_file, 0)) == NULL) {
1423 1428 (void) fprintf(stderr,
1424 1429 "%s: %s: elf_getscn failed: %s\n",
1425 1430 prog_name, filename, elf_errmsg(-1));
1426 1431 return (NULL);
1427 1432 }
1428 1433 if (gelf_getshdr(scn, &shdr0) == 0) {
1429 1434 (void) fprintf(stderr,
1430 1435 "%s: %s: gelf_getshdr: %s\n",
1431 1436 prog_name, filename, elf_errmsg(-1));
1432 1437 return (NULL);
1433 1438 }
1434 1439 (void) printf("[0]\t%u\t%llu\t", EC_WORD(shdr0.sh_type),
1435 1440 EC_XWORD(shdr0.sh_flags));
1436 1441
1437 1442 (void) printf("%-#*llx %-#*llx%-*llu%s%-*u\n",
1438 1443 field, EC_ADDR(shdr0.sh_addr),
1439 1444 field, EC_OFF(shdr0.sh_offset),
1440 1445 field, EC_XWORD(shdr0.sh_size),
1441 1446 /* compatibility: tab for elf32 */
1442 1447 ((field == 13) ? "\t" : " "),
1443 1448 field, EC_WORD(shdr0.sh_name));
1444 1449
1445 1450 (void) printf("\t%u\t%u\t%-#*llx %-#*llx\n",
1446 1451 EC_WORD(shdr0.sh_link),
1447 1452 EC_WORD(shdr0.sh_info),
1448 1453 field, EC_XWORD(shdr0.sh_addralign),
1449 1454 field, EC_XWORD(shdr0.sh_entsize));
1450 1455 }
1451 1456 (void) printf("\n");
1452 1457
1453 1458 return (elf_head_p);
1454 1459 }
1455 1460
1456 1461 /*
1457 1462 * Print section contents. Input is an ELF file descriptor,
1458 1463 * the ELF header, the SCNTAB structure,
1459 1464 * the number of symbols, and the filename.
1460 1465 * The number of sections,
1461 1466 * and the offset into the SCNTAB structure will be
1462 1467 * set in dump_section if d_flag or n_flag are set.
1463 1468 * If v_flag is set, sections which can be interpreted will
1464 1469 * be interpreted, otherwise raw data will be output in hexidecimal.
1465 1470 */
1466 1471 static void
1467 1472 print_section(Elf *elf_file,
1468 1473 GElf_Ehdr *p_ehdr, SCNTAB *p, int num_scns, char *filename)
1469 1474 {
1470 1475 unsigned char *p_sec;
1471 1476 int i;
1472 1477 size_t size;
1473 1478
1474 1479 for (i = 0; i < num_scns; i++, p++) {
1475 1480 GElf_Shdr shdr;
1476 1481
1477 1482 size = 0;
1478 1483 if (s_flag && !v_flag)
1479 1484 p_sec = (unsigned char *)get_rawscn(p->p_sd, &size);
1480 1485 else
1481 1486 p_sec = (unsigned char *)get_scndata(p->p_sd, &size);
1482 1487
1483 1488 if ((gelf_getshdr(p->p_sd, &shdr) != NULL) &&
1484 1489 (shdr.sh_type == SHT_NOBITS)) {
1485 1490 continue;
1486 1491 }
1487 1492 if (s_flag && !v_flag) {
1488 1493 (void) printf("\n%s:\n", p->scn_name);
1489 1494 print_rawdata(p_sec, size);
1490 1495 continue;
1491 1496 }
1492 1497 if (shdr.sh_type == SHT_SYMTAB) {
1493 1498 dump_symbol_table(elf_file, p, filename);
1494 1499 continue;
1495 1500 }
1496 1501 if (shdr.sh_type == SHT_DYNSYM) {
1497 1502 dump_symbol_table(elf_file, p, filename);
1498 1503 continue;
1499 1504 }
1500 1505 if (shdr.sh_type == SHT_STRTAB) {
1501 1506 dump_string_table(p, 1);
1502 1507 continue;
1503 1508 }
1504 1509 if (shdr.sh_type == SHT_RELA) {
1505 1510 dump_reloc_table(elf_file, p_ehdr, p, 1, filename);
1506 1511 continue;
1507 1512 }
1508 1513 if (shdr.sh_type == SHT_REL) {
1509 1514 dump_reloc_table(elf_file, p_ehdr, p, 1, filename);
1510 1515 continue;
1511 1516 }
1512 1517 if (shdr.sh_type == SHT_DYNAMIC) {
1513 1518 dump_dynamic(elf_file, p, 1, filename);
1514 1519 continue;
1515 1520 }
1516 1521
1517 1522 (void) printf("\n%s:\n", p->scn_name);
1518 1523 print_rawdata(p_sec, size);
1519 1524 }
1520 1525 (void) printf("\n");
1521 1526 }
1522 1527
1523 1528 /*
1524 1529 * Print section contents. This function does not print the contents
1525 1530 * of the sections but sets up the parameters and then calls
1526 1531 * print_section to print the contents. Calling another function to print
1527 1532 * the contents allows both -d and -n to work correctly
1528 1533 * simultaneously. Input is an ELF file descriptor, the ELF header,
1529 1534 * the SCNTAB structure, the number of sections, and the filename.
1530 1535 * Set the range of sections if d_flag, and set section name if
1531 1536 * n_flag.
1532 1537 */
1533 1538 static void
1534 1539 dump_section(Elf *elf_file,
1535 1540 GElf_Ehdr *p_ehdr, SCNTAB *s, int num_scns, char *filename)
1536 1541 {
1537 1542 SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */
1538 1543 int i;
1539 1544 int found_it = 0; /* for use with -n section_name */
1540 1545
1541 1546 if (n_flag) {
1542 1547 n_range = s;
1543 1548
1544 1549 for (i = 0; i < num_scns; i++, n_range++) {
1545 1550 if ((strcmp(name, n_range->scn_name)) != 0)
1546 1551 continue;
1547 1552 else {
1548 1553 found_it = 1;
1549 1554 print_section(elf_file, p_ehdr,
1550 1555 n_range, 1, filename);
1551 1556 }
1552 1557 }
1553 1558
1554 1559 if (!found_it) {
1555 1560 (void) fprintf(stderr, "%s: %s: %s not found\n",
1556 1561 prog_name, filename, name);
1557 1562 }
1558 1563 } /* end n_flag */
1559 1564
1560 1565 if (d_flag) {
1561 1566 d_range = s;
1562 1567 d_num = check_range(d_low, d_hi, num_scns, filename);
1563 1568 if (d_num < 0)
1564 1569 return;
1565 1570 d_range += d_low - 1;
1566 1571
1567 1572 print_section(elf_file, p_ehdr, d_range, d_num, filename);
1568 1573 } /* end d_flag */
1569 1574
1570 1575 if (!n_flag && !d_flag)
1571 1576 print_section(elf_file, p_ehdr, s, num_scns, filename);
1572 1577 }
1573 1578
1574 1579 /*
1575 1580 * Print the section header table. This function does not print the contents
1576 1581 * of the section headers but sets up the parameters and then calls
1577 1582 * print_shdr to print the contents. Calling another function to print
1578 1583 * the contents allows both -d and -n to work correctly
1579 1584 * simultaneously. Input is the SCNTAB structure,
1580 1585 * the number of sections from the ELF header, and the filename.
1581 1586 * Set the range of section headers to print if d_flag, and set
1582 1587 * name of section header to print if n_flag.
1583 1588 */
1584 1589 static void
1585 1590 dump_shdr(Elf *elf_file, SCNTAB *s, int num_scns, char *filename)
1586 1591 {
1587 1592
1588 1593 SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */
1589 1594 int field;
1590 1595 int i;
1591 1596 int found_it = 0; /* for use with -n section_name */
1592 1597
1593 1598 if (gelf_getclass(elf_file) == ELFCLASS64)
1594 1599 field = 21;
1595 1600 else
1596 1601 field = 13;
1597 1602
1598 1603 if (!p_flag) {
1599 1604 (void) printf("\n **** SECTION HEADER TABLE ****\n");
1600 1605 (void) printf("[No]\tType\tFlags\t%-*s %-*s %-*s%sName\n",
1601 1606 field, "Addr", field, "Offset", field, "Size",
1602 1607 /* compatibility: tab for elf32 */
1603 1608 (field == 13) ? "\t" : " ");
1604 1609 (void) printf("\tLink\tInfo\t%-*s Entsize\n\n",
1605 1610 field, "Adralgn");
1606 1611 }
1607 1612
1608 1613 if (n_flag) {
1609 1614 n_range = s;
1610 1615
1611 1616 for (i = 1; i <= num_scns; i++, n_range++) {
1612 1617 if ((strcmp(name, n_range->scn_name)) != 0)
1613 1618 continue;
1614 1619 else {
1615 1620 found_it = 1;
1616 1621 print_shdr(elf_file, n_range, 1, i);
1617 1622 }
1618 1623 }
1619 1624
1620 1625 if (!found_it) {
1621 1626 (void) fprintf(stderr, "%s: %s: %s not found\n",
1622 1627 prog_name, filename, name);
1623 1628 }
1624 1629 } /* end n_flag */
1625 1630
1626 1631 if (d_flag) {
1627 1632 d_range = s;
1628 1633 d_num = check_range(d_low, d_hi, num_scns, filename);
1629 1634 if (d_num < 0)
1630 1635 return;
1631 1636 d_range += d_low - 1;
1632 1637
1633 1638 print_shdr(elf_file, d_range, d_num, d_low);
1634 1639 } /* end d_flag */
1635 1640
1636 1641 if (!n_flag && !d_flag)
1637 1642 print_shdr(elf_file, s, num_scns, 1);
1638 1643 }
1639 1644
1640 1645 /*
1641 1646 * Process all of the command line options (except
1642 1647 * for -a, -g, -f, and -o). All of the options processed
1643 1648 * by this function require the presence of the section
1644 1649 * header table and will not be processed if it is not present.
1645 1650 * Set up a buffer containing section name, section header,
1646 1651 * and section descriptor for each section in the file. This
1647 1652 * structure is used to avoid duplicate calls to libelf functions.
1648 1653 * Structure members for the symbol table, the debugging information,
1649 1654 * and the line number information are global. All of the
1650 1655 * rest are local.
1651 1656 */
1652 1657 static void
1653 1658 dump_section_table(Elf *elf_file, GElf_Ehdr *elf_head_p, char *filename)
1654 1659 {
1655 1660
1656 1661 static SCNTAB *buffer, *p_scns;
1657 1662 Elf_Scn *scn = 0;
1658 1663 char *s_name = NULL;
1659 1664 int found = 0;
1660 1665 unsigned int num_scns;
1661 1666 size_t shstrndx;
1662 1667 size_t shnum;
1663 1668
1664 1669
1665 1670 if (elf_getshdrnum(elf_file, &shnum) == -1) {
1666 1671 (void) fprintf(stderr,
1667 1672 "%s: %s: elf_getshdrnum failed: %s\n",
1668 1673 prog_name, filename, elf_errmsg(-1));
1669 1674 return;
1670 1675 }
1671 1676 if (elf_getshdrstrndx(elf_file, &shstrndx) == -1) {
1672 1677 (void) fprintf(stderr,
1673 1678 "%s: %s: elf_getshdrstrndx failed: %s\n",
1674 1679 prog_name, filename, elf_errmsg(-1));
1675 1680 return;
1676 1681 }
1677 1682
1678 1683 if ((buffer = calloc(shnum, sizeof (SCNTAB))) == NULL) {
1679 1684 (void) fprintf(stderr, "%s: %s: cannot calloc space\n",
1680 1685 prog_name, filename);
1681 1686 return;
1682 1687 }
1683 1688 /* LINTED */
1684 1689 num_scns = (int)shnum - 1;
1685 1690
1686 1691 p_symtab = (SCNTAB *)0;
1687 1692 p_dynsym = (SCNTAB *)0;
1688 1693 p_scns = buffer;
1689 1694 p_head_scns = buffer;
1690 1695
1691 1696 while ((scn = elf_nextscn(elf_file, scn)) != 0) {
1692 1697 if ((gelf_getshdr(scn, &buffer->p_shdr)) == 0) {
1693 1698 (void) fprintf(stderr,
1694 1699 "%s: %s: %s\n", prog_name, filename,
1695 1700 elf_errmsg(-1));
1696 1701 return;
1697 1702 }
1698 1703 s_name = (char *)
1699 1704 elf_strptr(elf_file, shstrndx, buffer->p_shdr.sh_name);
1700 1705 buffer->scn_name = s_name ? s_name : (char *)UNKNOWN;
1701 1706 buffer->p_sd = scn;
1702 1707
1703 1708 if (buffer->p_shdr.sh_type == SHT_SYMTAB) {
1704 1709 found += 1;
1705 1710 p_symtab = buffer;
1706 1711 }
1707 1712 if (buffer->p_shdr.sh_type == SHT_DYNSYM)
1708 1713 p_dynsym = buffer;
1709 1714 buffer++;
1710 1715 }
1711 1716
1712 1717 /*
1713 1718 * These functions depend upon the presence of the section header table
1714 1719 * and will not be invoked in its absence
1715 1720 */
1716 1721 if (h_flag) {
1717 1722 dump_shdr(elf_file, p_scns, num_scns, filename);
1718 1723 }
1719 1724 if (p_symtab && (t_flag || T_flag)) {
1720 1725 dump_symbol_table(elf_file, p_symtab, filename);
1721 1726 }
1722 1727 if (c_flag) {
1723 1728 dump_string_table(p_scns, num_scns);
1724 1729 }
1725 1730 if (r_flag) {
1726 1731 dump_reloc_table(elf_file, elf_head_p,
1727 1732 p_scns, num_scns, filename);
1728 1733 }
1729 1734 if (L_flag) {
1730 1735 dump_dynamic(elf_file, p_scns, num_scns, filename);
1731 1736 }
1732 1737 if (s_flag) {
1733 1738 dump_section(elf_file, elf_head_p, p_scns,
1734 1739 num_scns, filename);
1735 1740 }
1736 1741 }
1737 1742
1738 1743 /*
1739 1744 * Load the archive string table(s) (for extended-length strings)
1740 1745 * into an in-core table/list
1741 1746 */
1742 1747 static struct stab_list_s *
1743 1748 load_arstring_table(struct stab_list_s *STabList,
1744 1749 int fd, Elf *elf_file, Elf_Arhdr *p_ar, char *filename)
1745 1750 {
1746 1751 off_t here;
1747 1752 struct stab_list_s *STL_entry, *STL_next;
1748 1753
1749 1754 if (p_ar) {
1750 1755 STL_entry = malloc(sizeof (struct stab_list_s));
1751 1756 STL_entry->next = 0;
1752 1757 STL_entry->strings = 0;
1753 1758 STL_entry->size = 0;
1754 1759
1755 1760 if (!STabList)
1756 1761 STabList = STL_entry;
1757 1762 else {
1758 1763 STL_next = STabList;
1759 1764 while (STL_next->next != (void *)0)
1760 1765 STL_next = STL_next->next;
1761 1766 STL_next->next = STL_entry;
1762 1767 }
1763 1768
1764 1769 STL_entry->size = p_ar->ar_size;
1765 1770 STL_entry->strings = malloc(p_ar->ar_size);
1766 1771 here = elf_getbase(elf_file);
1767 1772 if ((lseek(fd, here, 0)) != here) {
1768 1773 (void) fprintf(stderr,
1769 1774 "%s: %s: could not lseek\n", prog_name, filename);
1770 1775 }
1771 1776
1772 1777 if ((read(fd, STL_entry->strings, p_ar->ar_size)) == -1) {
1773 1778 (void) fprintf(stderr,
1774 1779 "%s: %s: could not read\n", prog_name, filename);
1775 1780 }
1776 1781 }
1777 1782 return (STabList);
1778 1783 }
1779 1784
1780 1785 /*
1781 1786 * Print the archive header for each member of an archive.
1782 1787 * Also call ar_sym_read to print the symbols in the
1783 1788 * archive symbol table if g_flag. Input is a file descriptor,
1784 1789 * an ELF file descriptor, and the filename. Putting the call
1785 1790 * to dump the archive symbol table in this function is more
1786 1791 * efficient since it is necessary to examine the archive member
1787 1792 * name in the archive header to determine which member is the
1788 1793 * symbol table.
1789 1794 */
1790 1795 static void
1791 1796 dump_ar_hdr(int fd, Elf *elf_file, char *filename)
1792 1797 {
1793 1798 extern int v_flag, g_flag, a_flag, p_flag;
1794 1799 Elf_Arhdr *p_ar;
1795 1800 Elf *arf;
1796 1801 Elf_Cmd cmd;
1797 1802 int title = 0;
1798 1803 int err = 0;
1799 1804
1800 1805 char buf[DATESIZE];
1801 1806
1802 1807 cmd = ELF_C_READ;
1803 1808 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
1804 1809 p_ar = elf_getarhdr(arf);
1805 1810 if (p_ar == NULL) {
1806 1811 (void) fprintf(stderr,
1807 1812 "%s: %s: %s\n", prog_name, filename,
1808 1813 elf_errmsg(-1));
1809 1814 continue;
1810 1815 }
1811 1816 if ((strcmp(p_ar->ar_name, "/") == 0) ||
1812 1817 (strcmp(p_ar->ar_name, "/SYM64/") == 0)) {
1813 1818 if (g_flag)
1814 1819 ar_sym_read(elf_file, filename);
1815 1820 } else if (strcmp(p_ar->ar_name, "//") == 0) {
1816 1821 StringTableList = load_arstring_table(
1817 1822 StringTableList, fd, arf, p_ar, filename);
1818 1823 cmd = elf_next(arf);
1819 1824 (void) elf_end(arf);
1820 1825 continue;
1821 1826 } else {
1822 1827 if (a_flag) {
1823 1828 (void) printf("%s[%s]:\n", filename,
1824 1829 p_ar->ar_name);
1825 1830 if (!p_flag && title == 0) {
1826 1831 if (!v_flag)
1827 1832 (void) printf(
1828 1833 "\n\n\t\t\t***ARCHIVE HEADER***"
1829 1834 "\n Date Uid Gid Mode Size Member Name\n\n");
1830 1835 else
1831 1836 (void) printf(
1832 1837 "\n\n\t\t\t***ARCHIVE HEADER***"
1833 1838 "\n Date Uid Gid Mode Size Member Name\n\n");
1834 1839 title = 1;
1835 1840 }
1836 1841 if (!v_flag) {
1837 1842 (void) printf(
1838 1843 "\t0x%.8lx %6d %6d 0%.6ho 0x%.8lx %-s\n\n",
1839 1844 p_ar->ar_date, (int)p_ar->ar_uid,
1840 1845 (int)p_ar->ar_gid,
1841 1846 (int)p_ar->ar_mode,
1842 1847 p_ar->ar_size, p_ar->ar_name);
1843 1848 } else {
1844 1849 if ((strftime(buf, DATESIZE,
1845 1850 "%b %d %H:%M:%S %Y",
1846 1851 localtime(
1847 1852 &(p_ar->ar_date)))) == 0) {
1848 1853 (void) fprintf(stderr,
1849 1854 "%s: %s: don't have enough space to store the date\n", prog_name, filename);
1850 1855 exit(1);
1851 1856 }
1852 1857 (void) printf(
1853 1858 "\t%s %6d %6d 0%.6ho 0x%.8lx %-s\n\n",
1854 1859 buf, (int)p_ar->ar_uid,
1855 1860 (int)p_ar->ar_gid,
1856 1861 (int)p_ar->ar_mode,
1857 1862 p_ar->ar_size, p_ar->ar_name);
1858 1863 }
1859 1864 }
1860 1865 }
1861 1866 cmd = elf_next(arf);
1862 1867 (void) elf_end(arf);
1863 1868 } /* end while */
1864 1869
1865 1870 err = elf_errno();
1866 1871 if (err != 0) {
1867 1872 (void) fprintf(stderr,
1868 1873 "%s: %s: %s\n", prog_name, filename, elf_errmsg(err));
1869 1874 }
1870 1875 }
1871 1876
1872 1877 /*
1873 1878 * Process member files of an archive. This function provides
1874 1879 * a loop through an archive equivalent the processing of
1875 1880 * each_file for individual object files.
1876 1881 */
1877 1882 static void
1878 1883 dump_ar_files(int fd, Elf *elf_file, char *filename)
1879 1884 {
1880 1885 Elf_Arhdr *p_ar;
1881 1886 Elf *arf;
1882 1887 Elf_Cmd cmd;
1883 1888 Elf_Kind file_type;
1884 1889 GElf_Ehdr elf_head;
1885 1890 char *fullname;
1886 1891
1887 1892 cmd = ELF_C_READ;
1888 1893 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
1889 1894 size_t len;
1890 1895
1891 1896 p_ar = elf_getarhdr(arf);
1892 1897 if (p_ar == NULL) {
1893 1898 (void) fprintf(stderr, "%s: %s: %s\n",
1894 1899 prog_name, filename, elf_errmsg(-1));
1895 1900 return;
1896 1901 }
1897 1902 if (p_ar->ar_name[0] == '/') {
1898 1903 cmd = elf_next(arf);
1899 1904 (void) elf_end(arf);
1900 1905 continue;
1901 1906 }
1902 1907
1903 1908 len = strlen(filename) + strlen(p_ar->ar_name) + 3;
1904 1909 if ((fullname = malloc(len)) == NULL)
1905 1910 return;
1906 1911 (void) snprintf(fullname, len, "%s[%s]", filename,
1907 1912 p_ar->ar_name);
1908 1913 (void) printf("\n%s:\n", fullname);
1909 1914 file_type = elf_kind(arf);
1910 1915 if (file_type == ELF_K_ELF) {
1911 1916 if (dump_elf_header(arf, fullname, &elf_head) == NULL)
1912 1917 return;
1913 1918 if (o_flag)
1914 1919 dump_exec_header(arf,
1915 1920 (unsigned)elf_head.e_phnum, fullname);
1916 1921 if (x_flag)
1917 1922 dump_section_table(arf, &elf_head, fullname);
1918 1923 } else {
1919 1924 (void) fprintf(stderr, "%s: %s: invalid file type\n",
1920 1925 prog_name, fullname);
1921 1926 cmd = elf_next(arf);
1922 1927 (void) elf_end(arf);
1923 1928 continue;
1924 1929 }
1925 1930
1926 1931 cmd = elf_next(arf);
1927 1932 (void) elf_end(arf);
1928 1933 } /* end while */
1929 1934 }
1930 1935
1931 1936 /*
1932 1937 * Takes a filename as input. Test first for a valid version
1933 1938 * of libelf.a and exit on error. Process each valid file
1934 1939 * or archive given as input on the command line. Check
1935 1940 * for file type. If it is an archive, process the archive-
1936 1941 * specific options first, then files within the archive.
1937 1942 * If it is an ELF object file, process it; otherwise
1938 1943 * warn that it is an invalid file type.
1939 1944 * All options except the archive-specific and program
1940 1945 * execution header are processed in the function, dump_section_table.
1941 1946 */
1942 1947 static void
1943 1948 each_file(char *filename)
1944 1949 {
1945 1950 Elf *elf_file;
1946 1951 GElf_Ehdr elf_head;
1947 1952 int fd;
1948 1953 Elf_Kind file_type;
1949 1954
1950 1955 struct stat buf;
1951 1956
1952 1957 Elf_Cmd cmd;
1953 1958 errno = 0;
1954 1959
1955 1960 if (stat(filename, &buf) == -1) {
1956 1961 int err = errno;
1957 1962 (void) fprintf(stderr, "%s: %s: %s", prog_name, filename,
1958 1963 strerror(err));
1959 1964 return;
1960 1965 }
1961 1966
1962 1967 if ((fd = open((filename), O_RDONLY)) == -1) {
1963 1968 (void) fprintf(stderr, "%s: %s: cannot read\n", prog_name,
1964 1969 filename);
1965 1970 return;
1966 1971 }
1967 1972 cmd = ELF_C_READ;
1968 1973 if ((elf_file = elf_begin(fd, cmd, (Elf *)0)) == NULL) {
1969 1974 (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename,
1970 1975 elf_errmsg(-1));
1971 1976 return;
1972 1977 }
1973 1978
1974 1979 file_type = elf_kind(elf_file);
1975 1980 if (file_type == ELF_K_AR) {
1976 1981 if (a_flag || g_flag) {
1977 1982 dump_ar_hdr(fd, elf_file, filename);
1978 1983 elf_file = elf_begin(fd, cmd, (Elf *)0);
1979 1984 }
1980 1985 if (z_flag)
1981 1986 dump_ar_files(fd, elf_file, filename);
1982 1987 } else {
1983 1988 if (file_type == ELF_K_ELF) {
1984 1989 (void) printf("\n%s:\n", filename);
1985 1990 if (dump_elf_header(elf_file, filename, &elf_head)) {
1986 1991 if (o_flag)
1987 1992 dump_exec_header(elf_file,
1988 1993 (unsigned)elf_head.e_phnum,
1989 1994 filename);
1990 1995 if (x_flag)
1991 1996 dump_section_table(elf_file,
1992 1997 &elf_head, filename);
1993 1998 }
1994 1999 } else {
1995 2000 (void) fprintf(stderr, "%s: %s: invalid file type\n",
1996 2001 prog_name, filename);
1997 2002 }
1998 2003 }
1999 2004 (void) elf_end(elf_file);
2000 2005 (void) close(fd);
2001 2006 }
2002 2007
2003 2008 /*
2004 2009 * Sets up flags for command line options given and then
2005 2010 * calls each_file() to process each file.
2006 2011 */
2007 2012 int
2008 2013 main(int argc, char *argv[], char *envp[])
2009 2014 {
2010 2015 char *optstr = OPTSTR; /* option string used by getopt() */
2011 2016 int optchar;
2012 2017
2013 2018 /*
2014 2019 * Check for a binary that better fits this architecture.
2015 2020 */
2016 2021 (void) conv_check_native(argv, envp);
2017 2022
2018 2023 prog_name = argv[0];
2019 2024
2020 2025 (void) setlocale(LC_ALL, "");
2021 2026 while ((optchar = getopt(argc, argv, optstr)) != -1) {
2022 2027 switch (optchar) {
2023 2028 case 'a':
2024 2029 a_flag = 1;
2025 2030 x_flag = 1;
2026 2031 break;
2027 2032 case 'g':
2028 2033 g_flag = 1;
2029 2034 x_flag = 1;
2030 2035 break;
2031 2036 case 'v':
2032 2037 v_flag = 1;
2033 2038 break;
2034 2039 case 'p':
2035 2040 p_flag = 1;
2036 2041 break;
2037 2042 case 'f':
2038 2043 f_flag = 1;
2039 2044 z_flag = 1;
2040 2045 break;
2041 2046 case 'o':
2042 2047 o_flag = 1;
2043 2048 z_flag = 1;
2044 2049 break;
2045 2050 case 'h':
2046 2051 h_flag = 1;
2047 2052 x_flag = 1;
2048 2053 z_flag = 1;
2049 2054 break;
2050 2055 case 's':
2051 2056 s_flag = 1;
2052 2057 x_flag = 1;
2053 2058 z_flag = 1;
2054 2059 break;
2055 2060 case 'd':
2056 2061 d_flag = 1;
2057 2062 x_flag = 1;
2058 2063 z_flag = 1;
2059 2064 set_range(optarg, &d_low, &d_hi);
2060 2065 break;
2061 2066 case 'n':
2062 2067 n_flag++;
2063 2068 x_flag = 1;
2064 2069 z_flag = 1;
2065 2070 name = optarg;
2066 2071 break;
2067 2072 case 'r':
2068 2073 r_flag = 1;
2069 2074 x_flag = 1;
2070 2075 z_flag = 1;
2071 2076 break;
2072 2077 case 't':
2073 2078 t_flag = 1;
2074 2079 x_flag = 1;
2075 2080 z_flag = 1;
2076 2081 break;
2077 2082 case 'C':
2078 2083 C_flag = 1;
2079 2084 t_flag = 1;
2080 2085 x_flag = 1;
2081 2086 z_flag = 1;
2082 2087 break;
2083 2088 case 'T':
2084 2089 T_flag = 1;
2085 2090 x_flag = 1;
2086 2091 z_flag = 1;
2087 2092 set_range(optarg, &T_low, &T_hi);
2088 2093 break;
2089 2094 case 'c':
2090 2095 c_flag = 1;
2091 2096 x_flag = 1;
2092 2097 z_flag = 1;
2093 2098 break;
2094 2099 case 'L':
2095 2100 L_flag = 1;
2096 2101 x_flag = 1;
2097 2102 z_flag = 1;
2098 2103 break;
2099 2104 case 'V':
2100 2105 V_flag = 1;
2101 2106 (void) fprintf(stderr, "dump: %s %s\n",
2102 2107 (const char *)SGU_PKG,
2103 2108 (const char *)SGU_REL);
2104 2109 break;
2105 2110 case '?':
2106 2111 errflag += 1;
2107 2112 break;
2108 2113 default:
2109 2114 break;
2110 2115 }
2111 2116 }
2112 2117
2113 2118 if (errflag || (optind >= argc) || (!z_flag && !x_flag)) {
2114 2119 if (!(V_flag && (argc == 2))) {
2115 2120 usage();
2116 2121 exit(269);
2117 2122 }
2118 2123 }
2119 2124
2120 2125 if (elf_version(EV_CURRENT) == EV_NONE) {
2121 2126 (void) fprintf(stderr, "%s: libelf is out of date\n",
2122 2127 prog_name);
2123 2128 exit(101);
2124 2129 }
2125 2130
2126 2131 while (optind < argc) {
2127 2132 each_file(argv[optind]);
2128 2133 optind++;
2129 2134 }
2130 2135 return (0);
2131 2136 }
|
↓ open down ↓ |
1592 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX