1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <locale.h> 35 #include <unistd.h> 36 #include <libelf.h> 37 #include <link.h> 38 #include <sys/elf_M32.h> 39 #include <sys/elf_386.h> 40 #include <sys/elf_SPARC.h> 41 #include <sys/elf_amd64.h> 42 #include <sys/machelf.h> 43 #include <fcntl.h> 44 #include <sys/stat.h> 45 #include <errno.h> 46 #include <string.h> 47 #include "sgs.h" 48 #include "conv.h" 49 #include "dump.h" 50 51 52 #define OPTSTR "agcd:fhn:oprstvCLT:V?" /* option string for getopt() */ 53 54 const char *UNKNOWN = "<unknown>"; 55 56 static SCNTAB *p_symtab, *p_head_scns, *p_dynsym; 57 58 static int 59 x_flag = 0, /* option requires section header table */ 60 z_flag = 0, /* process files within an archive */ 61 rn_flag = 0; /* dump named relocation information */ 62 63 static int 64 /* flags: ?_flag corresponds to ? option */ 65 a_flag = 0, /* dump archive header of each member of archive */ 66 g_flag = 0, /* dump archive symbol table */ 67 c_flag = 0, /* dump the string table */ 68 d_flag = 0, /* dump range of sections */ 69 f_flag = 0, /* dump each file header */ 70 h_flag = 0, /* dump section headers */ 71 n_flag = 0, /* dump named section */ 72 o_flag = 0, /* dump each program execution header */ 73 r_flag = 0, /* dump relocation information */ 74 s_flag = 0, /* dump section contents */ 75 t_flag = 0, /* dump symbol table entries */ 76 C_flag = 0, /* dump decoded C++ symbol names */ 77 L_flag = 0, /* dump dynamic linking information */ 78 T_flag = 0, /* dump symbol table range */ 79 V_flag = 0; /* dump version information */ 80 81 int p_flag = 0, /* suppress printing of headings */ 82 v_flag = 0; /* print information in verbose form */ 83 84 static int 85 d_low = 0, /* range for use with -d */ 86 d_hi = 0, 87 d_num = 0; 88 89 static int 90 T_low = 0, /* range for use with -T */ 91 T_hi = 0, 92 T_num = 0; 93 94 static char *name = NULL; /* for use with -n option */ 95 char *prog_name; 96 static int errflag = 0; 97 98 static struct stab_list_s { 99 struct stab_list_s *next; 100 char *strings; 101 size_t size; 102 } *StringTableList = (void *)0; 103 104 extern void ar_sym_read(); 105 extern void dump_exec_header(); 106 107 108 /* 109 * Get the section descriptor and set the size of the 110 * data returned. Data is byte-order converted. 111 */ 112 void * 113 get_scndata(Elf_Scn *fd_scn, size_t *size) 114 { 115 Elf_Data *p_data; 116 117 p_data = 0; 118 if ((p_data = elf_getdata(fd_scn, p_data)) == 0 || 119 p_data->d_size == 0) { 120 return (NULL); 121 } 122 *size = p_data->d_size; 123 return (p_data->d_buf); 124 } 125 126 /* 127 * Get the section descriptor and set the size of the 128 * data returned. Data is raw (i.e., not byte-order converted). 129 */ 130 static void * 131 get_rawscn(Elf_Scn *fd_scn, size_t *size) 132 { 133 Elf_Data *p_data; 134 135 p_data = 0; 136 if ((p_data = elf_rawdata(fd_scn, p_data)) == 0 || 137 p_data->d_size == 0) { 138 return (NULL); 139 } 140 141 *size = p_data->d_size; 142 return (p_data->d_buf); 143 } 144 145 /* 146 * Print out a usage message in short form when program is invoked 147 * with insufficient or no arguments, and in long form when given 148 * either a ? or an invalid option. 149 */ 150 static void 151 usage() 152 { 153 (void) fprintf(stderr, 154 "Usage: %s [-%s] file(s) ...\n", prog_name, OPTSTR); 155 if (errflag) { 156 (void) fprintf(stderr, 157 "\t\t[-a dump archive header of each member of archive]\n\ 158 [-g dump archive global symbol table]\n\ 159 [-c dump the string table]\n\ 160 [-d dump range of sections]\n\ 161 [-f dump each file header]\n\ 162 [-h dump section headers]\n\ 163 [-n dump named section]\n\ 164 [-o dump each program execution header]\n\ 165 [-p suppress printing of headings]\n\ 166 [-r dump relocation information]\n\ 167 [-s dump section contents]\n\ 168 [-t dump symbol table entries]\n\ 169 [-v print information in verbose form]\n\ 170 [-C dump decoded C++ symbol names]\n\ 171 [-L dump the .dynamic structure]\n\ 172 [-T dump symbol table range]\n\ 173 [-V dump version information]\n"); 174 } 175 } 176 177 /* 178 * Set a range. Input is a character string, a lower 179 * bound and an upper bound. This function converts 180 * a character string into its correct integer values, 181 * setting the first value as the lower bound, and 182 * the second value as the upper bound. If more values 183 * are given they are ignored with a warning. 184 */ 185 static void 186 set_range(char *s, int *low, int *high) 187 { 188 char *w; 189 char *lasts; 190 191 while ((w = strtok_r(s, ",", &lasts)) != NULL) { 192 if (!(*low)) 193 /* LINTED */ 194 *low = (int)atol(w); 195 else 196 if (!(*high)) 197 /* LINTED */ 198 *high = (int)atol(w); 199 else { 200 (void) fprintf(stderr, 201 "%s: too many arguments - %s ignored\n", 202 prog_name, w); 203 return; 204 } 205 s = NULL; 206 } /* end while */ 207 } 208 209 210 /* 211 * Print static shared library information. 212 */ 213 static void 214 print_static(SCNTAB *l_scns, char *filename) 215 { 216 size_t section_size; 217 unsigned char *strtab; 218 unsigned char *path, buf[1024]; 219 unsigned long *temp; 220 unsigned long total, topath; 221 222 (void) printf("\n **** STATIC SHARED LIBRARY INFORMATION ****\n"); 223 (void) printf("\n%s:\n", filename); 224 (void) printf("\t"); 225 section_size = 0; 226 if ((strtab = (unsigned char *) 227 get_scndata(l_scns->p_sd, §ion_size)) == NULL) { 228 return; 229 } 230 231 while (section_size != 0) { 232 /* LINTED */ 233 temp = (unsigned long *)strtab; 234 total = temp[0]; 235 topath = temp[1]; 236 path = strtab + (topath*sizeof (long)); 237 (void) strncpy((char *)buf, (char *)path, 238 (total - topath)*sizeof (long)); 239 (void) fprintf(stdout, "%s\n", buf); 240 strtab += total*sizeof (long); 241 section_size -= (total*sizeof (long)); 242 } 243 } 244 245 /* 246 * Print raw data in hexidecimal. Input is the section data to 247 * be printed out and the size of the data. Output is relative 248 * to a table lookup in dumpmap.h. 249 */ 250 static void 251 print_rawdata(unsigned char *p_sec, size_t size) 252 { 253 size_t j; 254 size_t count; 255 256 count = 1; 257 258 (void) printf("\t"); 259 for (j = size/sizeof (short); j != 0; --j, ++count) { 260 (void) printf("%.2x %.2x ", p_sec[0], p_sec[1]); 261 p_sec += 2; 262 if (count == 12) { 263 (void) printf("\n\t"); 264 count = 0; 265 } 266 } 267 268 /* 269 * take care of last byte if odd byte section 270 */ 271 if ((size & 0x1L) == 1L) 272 (void) printf("%.2x", *p_sec); 273 (void) printf("\n"); 274 } 275 276 277 278 /* 279 * Print relocation data of type SHT_RELA 280 * If d_flag, print data corresponding only to 281 * the section or range of sections specified. 282 * If n_flag, print data corresponding only to 283 * the named section. 284 */ 285 static void 286 print_rela(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data, 287 GElf_Ehdr * p_ehdr, size_t reloc_size, size_t sym_size, char *filename, 288 SCNTAB *reloc_symtab) 289 { 290 GElf_Rela rela; 291 GElf_Sym sym; 292 size_t no_entries; 293 size_t rel_entsize; 294 size_t no_syms; 295 int type, symid; 296 static int n_title = 0; 297 int ndx = 0; 298 char *sym_name; 299 int adj = 0; 300 301 if (gelf_getclass(elf_file) == ELFCLASS64) 302 adj = 8; 303 304 rel_entsize = p_scns->p_shdr.sh_entsize; 305 if ((rel_entsize == 0) || 306 (rel_entsize > p_scns->p_shdr.sh_size)) { 307 rel_entsize = gelf_fsize(elf_file, ELF_T_RELA, 1, 308 EV_CURRENT); 309 } 310 no_entries = reloc_size / rel_entsize; 311 312 no_syms = sym_size / gelf_fsize(elf_file, ELF_T_SYM, 1, EV_CURRENT); 313 while (no_entries--) { 314 (void) gelf_getrela(rdata, ndx, &rela); 315 /* LINTED */ 316 type = (int)GELF_R_TYPE(rela.r_info); 317 /* LINTED */ 318 symid = (int)GELF_R_SYM(rela.r_info); 319 /* LINTED */ 320 if ((symid > (no_syms - 1)) || (symid < 0)) { 321 (void) fprintf(stderr, "%s: %s: invalid symbol table " 322 "offset - %d - in %s\n", prog_name, filename, 323 symid, p_scns->scn_name); 324 ndx++; 325 continue; 326 } 327 (void) gelf_getsym(sym_data, symid, &sym); 328 sym_name = (char *)elf_strptr(elf_file, 329 reloc_symtab->p_shdr.sh_link, sym.st_name); 330 if (sym_name == NULL) 331 sym_name = (char *)UNKNOWN; 332 if (r_flag && rn_flag) { 333 if (strcmp(name, p_scns->scn_name) != 0) { 334 ndx++; 335 continue; 336 } 337 if (!n_title) { 338 (void) printf("\n%s:\n", p_scns->scn_name); 339 (void) printf("%-*s%-*s%-*s%s\n\n", 340 12 + adj, "Offset", 22, "Symndx", 341 16, "Type", "Addend"); 342 n_title = 1; 343 } 344 } 345 if (d_flag) { 346 if (!d_hi) 347 d_hi = d_low; 348 if ((symid < d_low) || (symid > d_hi)) { 349 ndx++; 350 continue; 351 } 352 } 353 354 (void) printf("%-#*llx", 12 + adj, EC_XWORD(rela.r_offset)); 355 if (!v_flag) { 356 (void) printf("%-22d%-18d", symid, type); 357 } else { 358 if (strlen(sym_name)) { 359 size_t len = strlen(sym_name) + 1; 360 char tmpstr[10]; 361 if (len > 22) { 362 (void) sprintf(tmpstr, "%%-%ds", 363 /* LINTED */ 364 (int)len); 365 (void) printf(tmpstr, sym_name); 366 } else 367 (void) printf("%-22s", sym_name); 368 } else 369 (void) printf("%-22d", symid); 370 print_reloc_type(p_ehdr->e_machine, type); 371 } 372 (void) printf("%lld\n", EC_SXWORD(rela.r_addend)); 373 ndx++; 374 } 375 } 376 377 /* 378 * Print relocation data of type SHT_REL. 379 * If d_flag, print data corresponding only to 380 * the section or range of sections specified. 381 * If n_flag, print data corresponding only to 382 * the named section. 383 */ 384 static void 385 print_rel(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data, 386 GElf_Ehdr *p_ehdr, size_t reloc_size, size_t sym_size, char *filename, 387 SCNTAB *reloc_symtab) 388 { 389 GElf_Rel rel; 390 GElf_Sym sym; 391 size_t no_entries; 392 size_t rel_entsize; 393 int type, symid; 394 size_t no_syms; 395 static int n_title = 0; 396 int ndx = 0; 397 char *sym_name; 398 int adj = 0; 399 400 if (gelf_getclass(elf_file) == ELFCLASS64) 401 adj = 8; 402 403 rel_entsize = p_scns->p_shdr.sh_entsize; 404 if ((rel_entsize == 0) || 405 (rel_entsize > p_scns->p_shdr.sh_size)) { 406 rel_entsize = gelf_fsize(elf_file, ELF_T_REL, 1, 407 EV_CURRENT); 408 } 409 no_entries = reloc_size / rel_entsize; 410 411 no_syms = sym_size / gelf_fsize(elf_file, ELF_T_SYM, 1, EV_CURRENT); 412 while (no_entries--) { 413 (void) gelf_getrel(rdata, ndx, &rel); 414 /* LINTED */ 415 type = (int)GELF_R_TYPE(rel.r_info); 416 /* LINTED */ 417 symid = (int)GELF_R_SYM(rel.r_info); 418 /* LINTED */ 419 if ((symid > (no_syms - 1)) || (symid < 0)) { 420 (void) fprintf(stderr, "%s: %s: invalid symbol table " 421 "offset - %d - in %s\n", prog_name, filename, 422 symid, p_scns->scn_name); 423 ndx++; 424 continue; 425 } 426 (void) gelf_getsym(sym_data, symid, &sym); 427 sym_name = (char *)elf_strptr(elf_file, 428 reloc_symtab->p_shdr.sh_link, sym.st_name); 429 if (sym_name == NULL) 430 sym_name = (char *)UNKNOWN; 431 if (r_flag && rn_flag) { 432 if (strcmp(name, p_scns->scn_name) != 0) { 433 ndx++; 434 continue; 435 } 436 if (!n_title) { 437 (void) printf("\n%s:\n", p_scns->scn_name); 438 (void) printf("%-*s%-*s%s\n\n", 439 12 + adj, "Offset", 20, "Symndx", "Type"); 440 n_title = 1; 441 } 442 } 443 if (d_flag) { 444 if (!d_hi) 445 d_hi = d_low; 446 if ((symid < d_low) || (symid > d_hi)) { 447 ndx++; 448 continue; 449 } 450 } 451 452 (void) printf("%-#*llx", 12 + adj, EC_ADDR(rel.r_offset)); 453 if (!v_flag) { 454 (void) printf("%-20d%-18d", symid, type); 455 } else { 456 if (strlen(sym_name)) 457 (void) printf("%-20s", sym_name); 458 else 459 (void) printf("%-20d", sym.st_name); 460 461 print_reloc_type(p_ehdr->e_machine, type); 462 } 463 (void) printf("\n"); 464 ndx++; 465 } 466 } 467 468 /* demangle C++ names */ 469 static char * 470 demangled_name(char *s) 471 { 472 static char *buf = NULL; 473 char *dn; 474 size_t len; 475 476 dn = sgs_demangle(s); 477 478 /* 479 * If not demangled, just return the symbol name 480 */ 481 if (strcmp(s, dn) == 0) 482 return (s); 483 484 /* 485 * Demangled. Format it 486 */ 487 if (buf != NULL) 488 free(buf); 489 490 len = strlen(dn) + strlen(s) + 4; 491 if ((buf = malloc(len)) == NULL) 492 return (s); 493 494 (void) snprintf(buf, len, "%s\t[%s]", dn, s); 495 return (buf); 496 } 497 498 /* 499 * Print the symbol table. Input is an ELF file descriptor, a 500 * pointer to the symbol table SCNTAB structure, 501 * the number of symbols, a range of symbols to print, 502 * an index which is the number of the 503 * section in the file, and the filename. The number of sections, 504 * the range, and the index are set in 505 * dump_symbol_table, depending on whether -n or -T were set. 506 */ 507 static void 508 print_symtab(Elf *elf_file, SCNTAB *p_symtab, Elf_Data *sym_data, 509 long range, int index) 510 { 511 GElf_Sym sym; 512 int adj = 0; /* field adjustment for elf64 */ 513 Elf32_Word *symshndx = 0; 514 unsigned int nosymshndx = 0; 515 516 if (gelf_getclass(elf_file) == ELFCLASS64) 517 adj = 8; 518 519 while (range > 0) { 520 char *sym_name = (char *)0; 521 int type, bind; 522 int specsec; 523 unsigned int shndx; 524 525 (void) gelf_getsym(sym_data, index, &sym); 526 type = (int)GELF_ST_TYPE(sym.st_info); 527 bind = (int)GELF_ST_BIND(sym.st_info); 528 529 if ((sym.st_shndx == SHN_XINDEX) && 530 (symshndx == 0) && (nosymshndx == 0)) { 531 Elf_Scn *_scn; 532 GElf_Shdr _shdr; 533 size_t symscnndx; 534 535 symscnndx = elf_ndxscn(p_symtab->p_sd); 536 _scn = 0; 537 while ((_scn = elf_nextscn(elf_file, _scn)) != 0) { 538 if (gelf_getshdr(_scn, &_shdr) == 0) 539 break; 540 if ((_shdr.sh_type == SHT_SYMTAB_SHNDX) && 541 /* LINTED */ 542 (_shdr.sh_link == (GElf_Word)symscnndx)) { 543 Elf_Data *_data; 544 545 if ((_data = elf_getdata(_scn, 0)) == 0) 546 continue; 547 548 symshndx = (Elf32_Word *)_data->d_buf; 549 nosymshndx = 0; 550 break; 551 } 552 } 553 nosymshndx = 1; 554 } 555 556 if ((symshndx) && (sym.st_shndx == SHN_XINDEX)) { 557 shndx = symshndx[index]; 558 specsec = 0; 559 } else { 560 shndx = sym.st_shndx; 561 if ((sym.st_shndx == SHN_UNDEF) || 562 (sym.st_shndx >= SHN_LORESERVE)) 563 specsec = 1; 564 else 565 specsec = 0; 566 } 567 568 569 (void) printf("[%d]\t ", index++); 570 571 if (v_flag && (type == STT_SPARC_REGISTER)) { 572 /* 573 * The strings "REG_G1" through "REG_G7" are intended 574 * to be consistent with output from elfdump(1). 575 */ 576 switch (sym.st_value) { 577 case STO_SPARC_REGISTER_G1: 578 (void) printf("%-*s", 12 + adj, "REG_G1"); 579 break; 580 case STO_SPARC_REGISTER_G2: 581 (void) printf("%-*s", 12 + adj, "REG_G2"); 582 break; 583 case STO_SPARC_REGISTER_G3: 584 (void) printf("%-*s", 12 + adj, "REG_G3"); 585 break; 586 case STO_SPARC_REGISTER_G4: 587 (void) printf("%-*s", 12 + adj, "REG_G4"); 588 break; 589 case STO_SPARC_REGISTER_G5: 590 (void) printf("%-*s", 12 + adj, "REG_G5"); 591 break; 592 case STO_SPARC_REGISTER_G6: 593 (void) printf("%-*s", 12 + adj, "REG_G6"); 594 break; 595 case STO_SPARC_REGISTER_G7: 596 (void) printf("%-*s", 12 + adj, "REG_G7"); 597 break; 598 default: 599 (void) printf("0x%-*llx", 10 + adj, 600 EC_ADDR(sym.st_value)); 601 } 602 } else 603 (void) printf("0x%-*llx", 10 + adj, 604 EC_ADDR(sym.st_value)); 605 606 (void) printf("%-*lld", 9 + adj, EC_XWORD(sym.st_size)); 607 608 if (!v_flag) { 609 (void) printf("%d\t\t%d\t%d\t%#x\t", 610 type, bind, (int)sym.st_other, (int)shndx); 611 } else { 612 switch (type) { 613 case STT_NOTYPE: 614 (void) printf("%s\t", "NOTY"); 615 break; 616 case STT_OBJECT: 617 (void) printf("%s\t", "OBJT"); 618 break; 619 case STT_FUNC: 620 (void) printf("%s\t", "FUNC"); 621 break; 622 case STT_SECTION: 623 (void) printf("%s\t", "SECT"); 624 break; 625 case STT_FILE: 626 (void) printf("%s\t", "FILE"); 627 break; 628 case STT_SPARC_REGISTER: 629 (void) printf("%s\t", "REGI"); 630 break; 631 case STT_COMMON: 632 (void) printf("%s\t", "COMM"); 633 break; 634 case STT_TLS: 635 (void) printf("%s\t", "TLS "); 636 break; 637 default: 638 (void) printf("%d\t", type); 639 } 640 switch (bind) { 641 case STB_LOCAL: 642 (void) printf("LOCL"); 643 break; 644 case STB_GLOBAL: 645 (void) printf("GLOB"); 646 break; 647 case STB_WEAK: 648 (void) printf("WEAK"); 649 break; 650 default: 651 (void) printf("%d", bind); 652 } 653 (void) printf("\t %d\t", EC_WORD(sym.st_other)); 654 655 if (specsec) { 656 switch (shndx) { 657 case SHN_UNDEF: 658 (void) printf("UNDEF"); 659 break; 660 case SHN_ABS: 661 (void) printf("ABS"); 662 break; 663 case SHN_COMMON: 664 (void) printf("COMMON"); 665 break; 666 case SHN_XINDEX: 667 (void) printf("XINDEX"); 668 break; 669 default: 670 (void) printf("%d", EC_WORD(shndx)); 671 } 672 } else 673 (void) printf("%d", EC_WORD(shndx)); 674 (void) printf("\t"); 675 } 676 677 /* support machines where NULL-deref causes core dump */ 678 if (sym.st_name == 0) 679 sym_name = (char *)UNKNOWN; 680 else 681 if (C_flag) 682 sym_name = demangled_name( 683 (char *)elf_strptr(elf_file, 684 p_symtab->p_shdr.sh_link, 685 sym.st_name)); 686 else 687 sym_name = (char *)elf_strptr(elf_file, 688 p_symtab->p_shdr.sh_link, 689 sym.st_name); 690 if (sym_name == NULL) 691 sym_name = (char *)UNKNOWN; 692 (void) printf("%s\n", sym_name); 693 694 range--; 695 } /* end while */ 696 } 697 698 /* 699 * Print the section header table. Input is the SCNTAB structure, 700 * the number of sections, an index which is the number of the 701 * section in the file, and the filename. The values of the SCNTAB 702 * structure, the number of sections, and the index are set in 703 * dump_shdr depending on whether the -n or -d modifiers were set. 704 */ 705 static void 706 print_shdr(Elf *elf_file, SCNTAB *s, int num_scns, int index) 707 { 708 SCNTAB *p; 709 int num; 710 int field; 711 712 if (gelf_getclass(elf_file) == ELFCLASS64) 713 field = 21; 714 else 715 field = 13; 716 717 p = s; 718 719 for (num = 0; num < num_scns; num++, p++) { 720 (void) printf("[%d]\t", index++); 721 if (!v_flag) { 722 (void) printf("%u\t%llu\t", 723 EC_WORD(p->p_shdr.sh_type), 724 EC_XWORD(p->p_shdr.sh_flags)); 725 } else { 726 switch (p->p_shdr.sh_type) { 727 case SHT_NULL: 728 (void) printf("NULL"); 729 break; 730 case SHT_PROGBITS: 731 (void) printf("PBIT"); 732 break; 733 case SHT_SYMTAB: 734 (void) printf("SYMT"); 735 break; 736 case SHT_STRTAB: 737 (void) printf("STRT"); 738 break; 739 case SHT_RELA: 740 (void) printf("RELA"); 741 break; 742 case SHT_HASH: 743 (void) printf("HASH"); 744 break; 745 case SHT_DYNAMIC: 746 (void) printf("DYNM"); 747 break; 748 case SHT_NOTE: 749 (void) printf("NOTE"); 750 break; 751 case SHT_NOBITS: 752 (void) printf("NOBI"); 753 break; 754 case SHT_REL: 755 (void) printf("REL "); 756 break; 757 case SHT_DYNSYM: 758 (void) printf("DYNS"); 759 break; 760 case ((GElf_Word) SHT_LOUSER): 761 (void) printf("LUSR"); 762 break; 763 case ((GElf_Word) SHT_HIUSER): 764 (void) printf("HUSR"); 765 break; 766 case SHT_SHLIB: 767 (void) printf("SHLB"); 768 break; 769 case SHT_SUNW_SIGNATURE: 770 (void) printf("SIGN"); 771 break; 772 case SHT_SUNW_ANNOTATE: 773 (void) printf("ANOT"); 774 break; 775 case SHT_SUNW_DEBUGSTR: 776 (void) printf("DBGS"); 777 break; 778 case SHT_SUNW_DEBUG: 779 (void) printf("DBG "); 780 break; 781 case SHT_SUNW_move: 782 (void) printf("MOVE"); 783 break; 784 case SHT_SUNW_verdef: 785 (void) printf("VERD"); 786 break; 787 case SHT_SUNW_verneed: 788 (void) printf("VERN"); 789 break; 790 case SHT_SUNW_versym: 791 (void) printf("VERS"); 792 break; 793 case SHT_SUNW_syminfo: 794 (void) printf("SYMI"); 795 break; 796 case SHT_SUNW_COMDAT: 797 (void) printf("COMD"); 798 break; 799 case SHT_AMD64_UNWIND: 800 (void) printf("UNWD"); 801 break; 802 case SHT_SPARC_GOTDATA: 803 (void) printf("GOTD"); 804 break; 805 default: 806 (void) printf("%u", EC_WORD(p->p_shdr.sh_type)); 807 break; 808 } 809 (void) printf(" "); 810 811 if (p->p_shdr.sh_flags & SHF_WRITE) 812 (void) printf("W"); 813 else 814 (void) printf("-"); 815 if (p->p_shdr.sh_flags & SHF_ALLOC) 816 (void) printf("A"); 817 else 818 (void) printf("-"); 819 if (p->p_shdr.sh_flags & SHF_EXECINSTR) 820 (void) printf("I"); 821 else 822 (void) printf("-"); 823 824 if (p->p_shdr.sh_flags & SHF_ORDERED) 825 (void) printf("O"); 826 if (p->p_shdr.sh_flags & SHF_EXCLUDE) 827 (void) printf("E"); 828 829 (void) printf("\t"); 830 831 } 832 (void) printf("%-#*llx%-#*llx%-#*llx%s%s\n", 833 field, EC_ADDR(p->p_shdr.sh_addr), 834 field, EC_OFF(p->p_shdr.sh_offset), 835 field, EC_XWORD(p->p_shdr.sh_size), 836 /* compatibility: tab for elf32 */ 837 (field == 13) ? "\t" : " ", p->scn_name); 838 839 (void) printf("\t%u\t%u\t%-#*llx%-#*llx\n\n", 840 EC_WORD(p->p_shdr.sh_link), 841 EC_WORD(p->p_shdr.sh_info), 842 field, EC_XWORD(p->p_shdr.sh_addralign), 843 field, EC_XWORD(p->p_shdr.sh_entsize)); 844 } 845 } 846 847 /* 848 * Check that a range of numbers is valid. Input is 849 * a lower bound, an upper bound, a boundary condition, 850 * and the filename. Negative numbers and numbers greater 851 * than the bound are invalid. low must be smaller than hi. 852 * The returned integer is the number of items in the 853 * range if it is valid and -1 otherwise. 854 */ 855 static int 856 check_range(int low, int hi, size_t bound, char *filename) 857 { 858 if (((size_t)low > bound) || (low <= 0)) { 859 (void) fprintf(stderr, 860 "%s: %s: number out of range, %d\n", 861 prog_name, filename, low); 862 return (-1); 863 } 864 if (((size_t)hi > bound) || (hi < 0)) { 865 (void) fprintf(stderr, 866 "%s: %s: number out of range, %d\n", 867 prog_name, filename, hi); 868 return (-1); 869 } 870 871 if (hi && (low > hi)) { 872 (void) fprintf(stderr, 873 "%s: %s: invalid range, %d,%d\n", 874 prog_name, filename, low, hi); 875 return (-1); 876 } 877 if (hi) 878 return (hi - low + 1); 879 else 880 return (1); 881 } 882 883 /* 884 * Print relocation information. Since this information is 885 * machine dependent, new sections must be added for each machine 886 * that is supported. Input is an ELF file descriptor, the ELF header, 887 * the SCNTAB structure, the number of sections, and a filename. 888 * Set up necessary information to print relocation information 889 * and call the appropriate print function depending on the 890 * type of relocation information. If the symbol table is 891 * absent, no relocation data is processed. Input is an 892 * ELF file descriptor, the ELF header, the SCNTAB structure, 893 * and the filename. Set range of d_flag and name if n_flag. 894 */ 895 static void 896 dump_reloc_table(Elf *elf_file, GElf_Ehdr *p_ehdr, 897 SCNTAB *p_scns, int num_scns, char *filename) 898 { 899 Elf_Data *rel_data; 900 Elf_Data *sym_data; 901 size_t sym_size; 902 size_t reloc_size; 903 SCNTAB *reloc_symtab; 904 SCNTAB *head_scns; 905 int r_title = 0; 906 int adj = 0; 907 size_t shnum; 908 909 if (gelf_getclass(elf_file) == ELFCLASS64) 910 adj = 8; 911 912 if ((!p_flag) && (!r_title)) { 913 (void) printf("\n **** RELOCATION INFORMATION ****\n"); 914 r_title = 1; 915 } 916 917 while (num_scns-- > 0) { 918 if ((p_scns->p_shdr.sh_type != SHT_RELA) && 919 (p_scns->p_shdr.sh_type != SHT_REL)) { 920 p_scns++; 921 continue; 922 } 923 924 head_scns = p_head_scns; 925 926 if (elf_getshnum(elf_file, &shnum) == 0) { 927 (void) fprintf(stderr, 928 "%s: %s: elf_getshnum failed: %s\n", 929 prog_name, filename, elf_errmsg(-1)); 930 return; 931 } 932 933 if ((p_scns->p_shdr.sh_link == 0) || 934 /* LINTED */ 935 (p_scns->p_shdr.sh_link >= (GElf_Word)shnum)) { 936 (void) fprintf(stderr, "%s: %s: invalid sh_link field: " 937 "section #: %d sh_link: %d\n", 938 /* LINTED */ 939 prog_name, filename, (int)elf_ndxscn(p_scns->p_sd), 940 (int)p_scns->p_shdr.sh_link); 941 return; 942 } 943 head_scns += (p_scns->p_shdr.sh_link -1); 944 945 if (head_scns->p_shdr.sh_type == SHT_SYMTAB) { 946 reloc_symtab = p_symtab; 947 } else if (head_scns->p_shdr.sh_type == SHT_DYNSYM) { 948 reloc_symtab = p_dynsym; 949 } else { 950 (void) fprintf(stderr, 951 "%s: %s: could not get symbol table\n", prog_name, filename); 952 return; 953 } 954 955 sym_data = NULL; 956 sym_size = 0; 957 reloc_size = 0; 958 959 if ((sym_data = elf_getdata(reloc_symtab->p_sd, NULL)) == NULL) { 960 (void) fprintf(stderr, 961 "%s: %s: no symbol table data\n", prog_name, filename); 962 return; 963 } 964 sym_size = sym_data->d_size; 965 966 if (p_scns == NULL) { 967 (void) fprintf(stderr, 968 "%s: %s: no section table data\n", prog_name, filename); 969 return; 970 } 971 972 if (p_scns->p_shdr.sh_type == SHT_RELA) { 973 if (!n_flag && r_flag) 974 (void) printf("\n%s:\n", p_scns->scn_name); 975 if (!p_flag && (!n_flag && r_flag)) 976 (void) printf("%-*s%-*s%-*s%s\n\n", 977 12 + adj, "Offset", 22, "Symndx", 978 18, "Type", "Addend"); 979 if ((rel_data = elf_getdata(p_scns->p_sd, NULL)) == NULL) { 980 (void) fprintf(stderr, 981 "%s: %s: no relocation information\n", prog_name, filename); 982 return; 983 } 984 reloc_size = rel_data->d_size; 985 986 if (n_flag) { 987 rn_flag = 1; 988 print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr, 989 reloc_size, sym_size, filename, reloc_symtab); 990 } 991 if (d_flag) { 992 rn_flag = 0; 993 print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr, 994 reloc_size, sym_size, filename, reloc_symtab); 995 } 996 if (!n_flag && !d_flag) 997 print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr, 998 reloc_size, sym_size, filename, reloc_symtab); 999 } else { 1000 if (p_scns->p_shdr.sh_type == SHT_REL) { 1001 if (!n_flag && r_flag) 1002 (void) printf("\n%s:\n", p_scns->scn_name); 1003 if (!p_flag && (!n_flag && r_flag)) { 1004 (void) printf("%-*s%-*s%s\n\n", 1005 12 + adj, "Offset", 20, "Symndx", "Type"); 1006 } 1007 if ((rel_data = elf_getdata(p_scns->p_sd, NULL)) 1008 == NULL) { 1009 (void) fprintf(stderr, 1010 "%s: %s: no relocation information\n", prog_name, filename); 1011 return; 1012 } 1013 reloc_size = rel_data->d_size; 1014 if (n_flag) { 1015 rn_flag = 1; 1016 print_rel(elf_file, p_scns, rel_data, sym_data, 1017 p_ehdr, reloc_size, sym_size, 1018 filename, reloc_symtab); 1019 } 1020 if (d_flag) { 1021 rn_flag = 0; 1022 print_rel(elf_file, p_scns, rel_data, sym_data, 1023 p_ehdr, reloc_size, sym_size, 1024 filename, reloc_symtab); 1025 } 1026 if (!n_flag && !d_flag) 1027 print_rel(elf_file, p_scns, rel_data, sym_data, 1028 p_ehdr, reloc_size, sym_size, 1029 filename, reloc_symtab); 1030 } 1031 } 1032 p_scns++; 1033 } 1034 } 1035 1036 /* 1037 * Print out the string tables. Input is an opened ELF file, 1038 * the SCNTAB structure, the number of sections, and the filename. 1039 * Since there can be more than one string table, all sections are 1040 * examined and any with the correct type are printed out. 1041 */ 1042 static void 1043 dump_string_table(SCNTAB *s, int num_scns) 1044 { 1045 size_t section_size; 1046 unsigned char *strtab; 1047 int beg_of_string; 1048 int counter = 0; 1049 int str_off; 1050 int i; 1051 1052 if (!p_flag) { 1053 (void) printf("\n **** STRING TABLE INFORMATION ****\n"); 1054 } 1055 1056 for (i = 0; i < num_scns; i++, s++) { 1057 if (s->p_shdr.sh_type != SHT_STRTAB) 1058 continue; 1059 1060 str_off = 0; 1061 1062 if (!p_flag) { 1063 (void) printf("\n%s:\n", s->scn_name); 1064 (void) printf(" <offset> \tName\n"); 1065 } 1066 section_size = 0; 1067 if ((strtab = (unsigned char *) 1068 get_scndata(s->p_sd, §ion_size)) == NULL) { 1069 continue; 1070 } 1071 1072 if (section_size != 0) { 1073 (void) printf(" <%d> \t", str_off); 1074 beg_of_string = 0; 1075 while (section_size--) { 1076 unsigned char c = *strtab++; 1077 1078 if (beg_of_string) { 1079 (void) printf(" <%d> \t", str_off); 1080 counter++; 1081 beg_of_string = 0; 1082 } 1083 str_off++; 1084 switch (c) { 1085 case '\0': 1086 (void) printf("\n"); 1087 beg_of_string = 1; 1088 break; 1089 default: 1090 (void) putchar(c); 1091 } 1092 } 1093 } 1094 } 1095 (void) printf("\n"); 1096 } 1097 1098 /* 1099 * Print the symbol table. This function does not print the contents 1100 * of the symbol table but sets up the parameters and then calls 1101 * print_symtab to print the symbols. Calling another function to print 1102 * the symbols allows both -T and -n to work correctly 1103 * simultaneously. Input is an opened ELF file, a pointer to the 1104 * symbol table SCNTAB structure, and the filename. 1105 * Set the range of symbols to print if T_flag, and set 1106 * name of symbol to print if n_flag. 1107 */ 1108 static void 1109 dump_symbol_table(Elf *elf_file, SCNTAB *p_symtab, char *filename) 1110 { 1111 Elf_Data *sym_data; 1112 GElf_Sym T_range, n_range; /* for use with -T and -n */ 1113 size_t count = 0; 1114 size_t sym_size; 1115 int index = 1; 1116 int found_it = 0; 1117 int i; 1118 int adj = 0; /* field adjustment for elf64 */ 1119 1120 if (gelf_getclass(elf_file) == ELFCLASS64) 1121 adj = 8; 1122 1123 if (p_symtab == NULL) { 1124 (void) fprintf(stderr, 1125 "%s: %s: could not get symbol table\n", prog_name, filename); 1126 return; 1127 } 1128 1129 /* get symbol table data */ 1130 sym_data = NULL; 1131 sym_size = 0; 1132 if ((sym_data = 1133 elf_getdata(p_symtab->p_sd, NULL)) == NULL) { 1134 (void) printf("\n%s:\n", p_symtab->scn_name); 1135 (void) printf("No symbol table data\n"); 1136 return; 1137 } 1138 sym_size = sym_data->d_size; 1139 1140 count = sym_size / p_symtab->p_shdr.sh_entsize; 1141 1142 if (n_flag && t_flag && !T_flag) { 1143 /* LINTED */ 1144 for (i = 1; i < count; i++) { 1145 (void) gelf_getsym(sym_data, i, &n_range); 1146 if (strcmp(name, (char *) 1147 elf_strptr(elf_file, 1148 p_symtab->p_shdr.sh_link, 1149 n_range.st_name)) != 0) { 1150 continue; 1151 } else { 1152 found_it = 1; 1153 if (!p_flag) { 1154 (void) printf( 1155 "\n ***** SYMBOL TABLE INFORMATION *****\n"); 1156 (void) printf( 1157 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName", 1158 12 + adj, "Value", 9 + adj, "Size"); 1159 } 1160 (void) printf("\n%s:\n", p_symtab->scn_name); 1161 print_symtab(elf_file, p_symtab, sym_data, 1162 1, i); 1163 } 1164 } /* end for */ 1165 if (!found_it) { 1166 (void) fprintf(stderr, "%s: %s: %s not found\n", 1167 prog_name, filename, name); 1168 } 1169 } else if (T_flag) { 1170 T_num = check_range(T_low, T_hi, count, filename); 1171 if (T_num < 0) 1172 return; 1173 1174 (void) gelf_getsym(sym_data, T_low-1, &T_range); 1175 index = T_low; 1176 1177 if (!p_flag) { 1178 (void) printf( 1179 "\n ***** SYMBOL TABLE INFORMATION *****\n"); 1180 (void) printf( 1181 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName", 1182 12 + adj, "Value", 9 + adj, "Size"); 1183 } 1184 (void) printf("\n%s:\n", p_symtab->scn_name); 1185 print_symtab(elf_file, p_symtab, sym_data, T_num, index); 1186 } else { 1187 if (!p_flag) { 1188 (void) printf( 1189 "\n ***** SYMBOL TABLE INFORMATION *****\n"); 1190 (void) printf( 1191 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName", 1192 12 + adj, "Value", 9 + adj, "Size"); 1193 } 1194 (void) printf("\n%s:\n", p_symtab->scn_name); 1195 print_symtab(elf_file, p_symtab, sym_data, count-1, 1); 1196 } 1197 } 1198 1199 1200 /* 1201 * The items in a dynamic section are displayed using a small set 1202 * of standard output styles. To reduce code size and promote 1203 * consistency, the following family of functions, all named 1204 * with the prefix "pdynitem_", are used by dump_dynamic(). 1205 * 1206 * entry: 1207 * name - Name of element 1208 * p_dyn - Pointer to struct describing element 1209 * elf_file, link - Used to look up a string from the string table 1210 * in the ELF file. 1211 * bitdesc - Pointer to NULL terminated array of PDYNITEM_BITDESC 1212 * structs describing the allowed bit values. 1213 */ 1214 #define Fmttag "%-15.15s " 1215 #define Fmtptr "%#llx" 1216 1217 void 1218 pdynitem_addr(const char *name, GElf_Dyn *p_dyn) 1219 { 1220 (void) printf(Fmttag, name); 1221 (void) printf(Fmtptr, EC_ADDR(p_dyn->d_un.d_ptr)); 1222 } 1223 1224 void 1225 pdynitem_val(const char *name, GElf_Dyn *p_dyn) 1226 { 1227 (void) printf(Fmttag, name); 1228 (void) printf(Fmtptr, EC_XWORD(p_dyn->d_un.d_val)); 1229 } 1230 1231 void 1232 pdynitem_depval(const char *name, GElf_Dyn *p_dyn) 1233 { 1234 (void) printf(Fmttag, name); 1235 (void) printf(Fmtptr " (deprecated value)", 1236 EC_XWORD(p_dyn->d_un.d_val)); 1237 } 1238 1239 void 1240 pdynitem_ign(const char *name) 1241 { 1242 (void) printf(Fmttag "(ignored)", name); 1243 } 1244 1245 void 1246 pdynitem_str(const char *name, GElf_Dyn *p_dyn, Elf *elf_file, GElf_Word link) 1247 { 1248 char *str; 1249 1250 (void) printf(Fmttag, name); 1251 if (v_flag) { /* Look up the string */ 1252 str = (char *)elf_strptr(elf_file, link, p_dyn->d_un.d_ptr); 1253 if (!(str && *str)) 1254 str = (char *)UNKNOWN; 1255 (void) printf("%s", str); 1256 } else { /* Show the address */ 1257 (void) printf(Fmtptr, EC_ADDR(p_dyn->d_un.d_ptr)); 1258 } 1259 } 1260 1261 /* 1262 * Arrays of this type are used for the values argument to 1263 * pdynitem_bitmask(). It maps a bit value to a human readable 1264 * name string. The final element of such an array must always 1265 * be NULL. 1266 */ 1267 typedef struct { 1268 int bit; /* Bit Value */ 1269 const char *name; /* Name corresponding to bit */ 1270 } PDYNITEM_BITDESC; 1271 1272 void 1273 pdynitem_bitmask(const char *name, GElf_Dyn *p_dyn, PDYNITEM_BITDESC *bitdesc) 1274 { 1275 char buf[512]; 1276 1277 (void) printf(Fmttag, name); 1278 if (v_flag) { 1279 buf[0] = '\0'; 1280 for (; bitdesc->bit; bitdesc++) { 1281 if (p_dyn->d_un.d_val & bitdesc->bit) 1282 (void) strlcat(buf, bitdesc->name, 1283 sizeof (buf)); 1284 } 1285 if (buf[0]) { 1286 (void) printf("%s", buf); 1287 return; 1288 } 1289 } 1290 1291 /* We don't have a string, or one is not requested. Show address */ 1292 (void) printf(Fmtptr, EC_ADDR(p_dyn->d_un.d_ptr)); 1293 1294 } 1295 1296 #undef Fmttag 1297 #undef Fmtptr 1298 1299 /* 1300 * Print dynamic linking information. Input is an ELF 1301 * file descriptor, the SCNTAB structure, the number of 1302 * sections, and the filename. 1303 */ 1304 static void 1305 dump_dynamic(Elf *elf_file, SCNTAB *p_scns, int num_scns, char *filename) 1306 { 1307 /* 1308 * Map dynamic bit fields to readable strings. These tables 1309 * must be kept in sync with the definitions in <link.h>. 1310 * 1311 * The string displayed is always the same as the name used 1312 * for the constant, with the prefix removed. The BITDESC macro 1313 * generate both PDYNITEM_BITDESC fields from the base name. 1314 */ 1315 #define BITDESC(prefix, item) { prefix ## item, #item " " } 1316 1317 static PDYNITEM_BITDESC dyn_dt_flags[] = { /* DT_FLAGS */ 1318 BITDESC(DF_, ORIGIN), 1319 BITDESC(DF_, SYMBOLIC), 1320 BITDESC(DF_, TEXTREL), 1321 BITDESC(DF_, BIND_NOW), 1322 BITDESC(DF_, STATIC_TLS), 1323 { 0 } 1324 }; 1325 1326 static PDYNITEM_BITDESC dyn_dt_flags_1[] = { /* DT_FLAGS_1 */ 1327 BITDESC(DF_1_, NOW), 1328 BITDESC(DF_1_, GLOBAL), 1329 BITDESC(DF_1_, GROUP), 1330 BITDESC(DF_1_, NODELETE), 1331 BITDESC(DF_1_, LOADFLTR), 1332 BITDESC(DF_1_, INITFIRST), 1333 BITDESC(DF_1_, NOOPEN), 1334 BITDESC(DF_1_, ORIGIN), 1335 BITDESC(DF_1_, DIRECT), 1336 BITDESC(DF_1_, TRANS), 1337 BITDESC(DF_1_, INTERPOSE), 1338 BITDESC(DF_1_, NODEFLIB), 1339 BITDESC(DF_1_, NODUMP), 1340 BITDESC(DF_1_, CONFALT), 1341 BITDESC(DF_1_, ENDFILTEE), 1342 BITDESC(DF_1_, DISPRELDNE), 1343 BITDESC(DF_1_, DISPRELPND), 1344 BITDESC(DF_1_, NODIRECT), 1345 BITDESC(DF_1_, IGNMULDEF), 1346 BITDESC(DF_1_, NOKSYMS), 1347 BITDESC(DF_1_, NOHDR), 1348 BITDESC(DF_1_, NORELOC), 1349 { 0 } 1350 }; 1351 1352 static PDYNITEM_BITDESC dyn_dt_feature_1[] = { /* DT_FEATURE_1 */ 1353 BITDESC(DTF_1_, PARINIT), 1354 BITDESC(DTF_1_, CONFEXP), 1355 { 0 } 1356 }; 1357 1358 static PDYNITEM_BITDESC dyn_dt_posflag_1[] = { /* DT_POSFLAG_1 */ 1359 BITDESC(DF_P1_, LAZYLOAD), 1360 BITDESC(DF_P1_, GROUPPERM), 1361 { 0 } 1362 }; 1363 1364 #undef BITDESC 1365 1366 Elf_Data *dyn_data; 1367 GElf_Dyn p_dyn; 1368 GElf_Phdr p_phdr; 1369 GElf_Ehdr p_ehdr; 1370 int index = 1; 1371 int lib_scns = num_scns; 1372 SCNTAB *l_scns = p_scns; 1373 int header_num = 0; 1374 1375 if (!p_flag) 1376 (void) printf("\n **** DYNAMIC SECTION INFORMATION ****\n"); 1377 1378 for (; num_scns > 0; num_scns--, p_scns++) { 1379 GElf_Word link; 1380 int ii; 1381 1382 1383 if (p_scns->p_shdr.sh_type != SHT_DYNAMIC) 1384 continue; 1385 1386 if (!p_flag) { 1387 (void) printf("%s:\n", p_scns->scn_name); 1388 (void) printf("[INDEX]\tTag Value\n"); 1389 } 1390 1391 if ((dyn_data = elf_getdata(p_scns->p_sd, NULL)) == 0) { 1392 (void) fprintf(stderr, "%s: %s: no data in " 1393 "%s section\n", prog_name, filename, 1394 p_scns->scn_name); 1395 return; 1396 } 1397 1398 link = p_scns->p_shdr.sh_link; 1399 ii = 0; 1400 1401 (void) gelf_getdyn(dyn_data, ii++, &p_dyn); 1402 while (p_dyn.d_tag != DT_NULL) { 1403 (void) printf("[%d]\t", index++); 1404 1405 /* 1406 * It would be nice to use a table driven loop 1407 * here, but the address space is too sparse 1408 * and irregular. A switch is simple and robust. 1409 */ 1410 switch (p_dyn.d_tag) { 1411 /* 1412 * Start of generic flags. 1413 */ 1414 case (DT_NEEDED): 1415 pdynitem_str("NEEDED", &p_dyn, elf_file, link); 1416 break; 1417 case (DT_PLTRELSZ): 1418 pdynitem_val("PLTSZ", &p_dyn); 1419 break; 1420 case (DT_PLTGOT): 1421 pdynitem_addr("PLTGOT", &p_dyn); 1422 break; 1423 case (DT_HASH): 1424 pdynitem_addr("HASH", &p_dyn); 1425 break; 1426 case (DT_STRTAB): 1427 pdynitem_addr("STRTAB", &p_dyn); 1428 break; 1429 case (DT_SYMTAB): 1430 pdynitem_addr("SYMTAB", &p_dyn); 1431 break; 1432 case (DT_RELA): 1433 pdynitem_addr("RELA", &p_dyn); 1434 break; 1435 case (DT_RELASZ): 1436 pdynitem_val("RELASZ", &p_dyn); 1437 break; 1438 case (DT_RELAENT): 1439 pdynitem_val("RELAENT", &p_dyn); 1440 break; 1441 case (DT_STRSZ): 1442 pdynitem_val("STRSZ", &p_dyn); 1443 break; 1444 case (DT_SYMENT): 1445 pdynitem_val("SYMENT", &p_dyn); 1446 break; 1447 case (DT_INIT): 1448 pdynitem_addr("INIT", &p_dyn); 1449 break; 1450 case (DT_FINI): 1451 pdynitem_addr("FINI", &p_dyn); 1452 break; 1453 case (DT_SONAME): 1454 pdynitem_str("SONAME", &p_dyn, elf_file, link); 1455 break; 1456 case (DT_RPATH): 1457 pdynitem_str("RPATH", &p_dyn, elf_file, link); 1458 break; 1459 case (DT_SYMBOLIC): 1460 pdynitem_ign("SYMB"); 1461 break; 1462 case (DT_REL): 1463 pdynitem_addr("REL", &p_dyn); 1464 break; 1465 case (DT_RELSZ): 1466 pdynitem_val("RELSZ", &p_dyn); 1467 break; 1468 case (DT_RELENT): 1469 pdynitem_val("RELENT", &p_dyn); 1470 break; 1471 case (DT_PLTREL): 1472 pdynitem_val("PLTREL", &p_dyn); 1473 break; 1474 case (DT_DEBUG): 1475 pdynitem_addr("DEBUG", &p_dyn); 1476 break; 1477 case (DT_TEXTREL): 1478 pdynitem_addr("TEXTREL", &p_dyn); 1479 break; 1480 case (DT_JMPREL): 1481 pdynitem_addr("JMPREL", &p_dyn); 1482 break; 1483 case (DT_BIND_NOW): 1484 pdynitem_val("BIND_NOW", &p_dyn); 1485 break; 1486 case (DT_INIT_ARRAY): 1487 pdynitem_addr("INIT_ARRAY", &p_dyn); 1488 break; 1489 case (DT_FINI_ARRAY): 1490 pdynitem_addr("FINI_ARRAY", &p_dyn); 1491 break; 1492 case (DT_INIT_ARRAYSZ): 1493 pdynitem_addr("INIT_ARRAYSZ", &p_dyn); 1494 break; 1495 case (DT_FINI_ARRAYSZ): 1496 pdynitem_addr("FINI_ARRAYSZ", &p_dyn); 1497 break; 1498 case (DT_RUNPATH): 1499 pdynitem_str("RUNPATH", &p_dyn, 1500 elf_file, link); 1501 break; 1502 case (DT_FLAGS): 1503 pdynitem_bitmask("FLAGS", &p_dyn, 1504 dyn_dt_flags); 1505 break; 1506 1507 case (DT_PREINIT_ARRAY): 1508 pdynitem_addr("PRINIT_ARRAY", &p_dyn); 1509 break; 1510 case (DT_PREINIT_ARRAYSZ): 1511 pdynitem_addr("PRINIT_ARRAYSZ", &p_dyn); 1512 break; 1513 /* 1514 * DT_LOOS - DT_HIOS range. 1515 */ 1516 case (DT_SUNW_AUXILIARY): 1517 pdynitem_str("SUNW_AUXILIARY", &p_dyn, 1518 elf_file, link); 1519 break; 1520 case (DT_SUNW_RTLDINF): 1521 pdynitem_addr("SUNW_RTLDINF", &p_dyn); 1522 break; 1523 case (DT_SUNW_FILTER): 1524 pdynitem_str("SUNW_FILTER", &p_dyn, 1525 elf_file, link); 1526 break; 1527 case (DT_SUNW_CAP): 1528 pdynitem_addr("SUNW_CAP", &p_dyn); 1529 break; 1530 1531 /* 1532 * SUNW: DT_VALRNGLO - DT_VALRNGHI range. 1533 */ 1534 case (DT_CHECKSUM): 1535 pdynitem_val("CHECKSUM", &p_dyn); 1536 break; 1537 case (DT_PLTPADSZ): 1538 pdynitem_val("PLTPADSZ", &p_dyn); 1539 break; 1540 case (DT_MOVEENT): 1541 pdynitem_val("MOVEENT", &p_dyn); 1542 break; 1543 case (DT_MOVESZ): 1544 pdynitem_val("MOVESZ", &p_dyn); 1545 break; 1546 case (DT_FEATURE_1): 1547 pdynitem_bitmask("FEATURE_1", &p_dyn, 1548 dyn_dt_feature_1); 1549 break; 1550 case (DT_POSFLAG_1): 1551 pdynitem_bitmask("POSFLAG_1", &p_dyn, 1552 dyn_dt_posflag_1); 1553 break; 1554 case (DT_SYMINSZ): 1555 pdynitem_val("SYMINSZ", &p_dyn); 1556 break; 1557 case (DT_SYMINENT): 1558 pdynitem_val("SYMINENT", &p_dyn); 1559 break; 1560 1561 /* 1562 * SUNW: DT_ADDRRNGLO - DT_ADDRRNGHI range. 1563 */ 1564 case (DT_CONFIG): 1565 pdynitem_str("CONFIG", &p_dyn, elf_file, link); 1566 break; 1567 case (DT_DEPAUDIT): 1568 pdynitem_str("DEPAUDIT", &p_dyn, 1569 elf_file, link); 1570 break; 1571 case (DT_AUDIT): 1572 pdynitem_str("AUDIT", &p_dyn, elf_file, link); 1573 break; 1574 case (DT_PLTPAD): 1575 pdynitem_addr("PLTPAD", &p_dyn); 1576 break; 1577 case (DT_MOVETAB): 1578 pdynitem_addr("MOVETAB", &p_dyn); 1579 break; 1580 case (DT_SYMINFO): 1581 pdynitem_addr("SYMINFO", &p_dyn); 1582 break; 1583 1584 /* 1585 * SUNW: generic range. 1586 */ 1587 case (DT_RELACOUNT): 1588 pdynitem_addr("RELACOUNT", &p_dyn); 1589 break; 1590 case (DT_RELCOUNT): 1591 pdynitem_addr("RELCOUNT", &p_dyn); 1592 break; 1593 case (DT_FLAGS_1): 1594 pdynitem_bitmask("FLAGS_1", &p_dyn, 1595 dyn_dt_flags_1); 1596 break; 1597 case (DT_VERSYM): 1598 pdynitem_addr("VERSYM", &p_dyn); 1599 break; 1600 case (DT_VERDEF): 1601 pdynitem_addr("VERDEF", &p_dyn); 1602 break; 1603 case (DT_VERDEFNUM): 1604 pdynitem_addr("VERDEFNUM", &p_dyn); 1605 break; 1606 case (DT_VERNEED): 1607 pdynitem_addr("VERNEED", &p_dyn); 1608 break; 1609 case (DT_VERNEEDNUM): 1610 pdynitem_val("VERNEEDNUM", &p_dyn); 1611 break; 1612 case (DT_AUXILIARY): 1613 pdynitem_str("AUXILIARY", &p_dyn, 1614 elf_file, link); 1615 break; 1616 case (DT_USED): 1617 pdynitem_str("USED", &p_dyn, elf_file, link); 1618 break; 1619 case (DT_FILTER): 1620 pdynitem_str("FILTER", &p_dyn, elf_file, link); 1621 break; 1622 1623 /* 1624 * SUNW: machine specific range. 1625 */ 1626 case (DT_SPARC_REGISTER): 1627 pdynitem_val("REGISTER", &p_dyn); 1628 break; 1629 case (DT_DEPRECATED_SPARC_REGISTER): 1630 pdynitem_depval("REGISTER", &p_dyn); 1631 break; 1632 default: 1633 (void) printf("%lld", EC_XWORD(p_dyn.d_tag)); 1634 break; 1635 } 1636 (void) printf("\n"); 1637 (void) gelf_getdyn(dyn_data, ii++, &p_dyn); 1638 } 1639 } 1640 1641 /* 1642 * Check for existence of static shared library information. 1643 */ 1644 (void) gelf_getehdr(elf_file, &p_ehdr); 1645 while (header_num < p_ehdr.e_phnum) { 1646 (void) gelf_getphdr(elf_file, header_num, &p_phdr); 1647 if (p_phdr.p_type == PT_SHLIB) { 1648 while (--lib_scns > 0) { 1649 if (strcmp(l_scns->scn_name, ".lib") == 0) { 1650 print_static(l_scns, filename); 1651 } 1652 l_scns++; 1653 } 1654 } 1655 header_num++; 1656 } 1657 } 1658 1659 /* 1660 * Print the ELF header. Input is an ELF file descriptor 1661 * and the filename. If f_flag is set, the ELF header is 1662 * printed to stdout, otherwise the function returns after 1663 * setting the pointer to the ELF header. Any values which 1664 * are not known are printed in decimal. Fields must be updated 1665 * as new values are added. 1666 */ 1667 static GElf_Ehdr * 1668 dump_elf_header(Elf *elf_file, char *filename, GElf_Ehdr * elf_head_p) 1669 { 1670 int class, data; 1671 int field; 1672 1673 if (gelf_getehdr(elf_file, elf_head_p) == NULL) { 1674 (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename, 1675 elf_errmsg(-1)); 1676 return (NULL); 1677 } 1678 1679 class = (int)elf_head_p->e_ident[4]; 1680 1681 if (class == ELFCLASS64) 1682 field = 21; 1683 else 1684 field = 13; 1685 1686 if (!f_flag) 1687 return (elf_head_p); 1688 1689 if (!p_flag) { 1690 (void) printf("\n **** ELF HEADER ****\n"); 1691 (void) printf("%-*s%-11s%-*sMachine Version\n", 1692 field, "Class", "Data", field, "Type"); 1693 (void) printf("%-*s%-11s%-*sFlags Ehsize\n", 1694 field, "Entry", "Phoff", field, "Shoff"); 1695 (void) printf("%-*s%-11s%-*sShnum Shstrndx\n\n", 1696 field, "Phentsize", "Phnum", field, "Shentsz"); 1697 } 1698 1699 if (!v_flag) { 1700 (void) printf("%-*d%-11d%-*d%-12d%d\n", 1701 field, elf_head_p->e_ident[4], 1702 elf_head_p->e_ident[5], 1703 field, (int)elf_head_p->e_type, 1704 (int)elf_head_p->e_machine, 1705 elf_head_p->e_version); 1706 } else { 1707 data = elf_head_p->e_ident[5]; 1708 1709 switch (class) { 1710 case ELFCLASSNONE: 1711 (void) printf("%-*s", field, "None"); 1712 break; 1713 case ELFCLASS32: 1714 (void) printf("%-*s", field, "32-bit"); 1715 break; 1716 case ELFCLASS64: 1717 (void) printf("%-*s", field, "64-bit"); 1718 break; 1719 default: 1720 (void) printf("%-*d", field, class); 1721 break; 1722 } 1723 switch (data) { 1724 case ELFDATANONE: 1725 (void) printf("%-11s", "None "); 1726 break; 1727 case ELFDATA2LSB: 1728 (void) printf("%-11s", "2LSB "); 1729 break; 1730 case ELFDATA2MSB: 1731 (void) printf("%-11s", "2MSB "); 1732 break; 1733 default: 1734 (void) printf("%-11d", data); 1735 break; 1736 } 1737 1738 switch (elf_head_p->e_type) { 1739 case ET_NONE: 1740 (void) printf("%-*s", field, "None"); 1741 break; 1742 case ET_REL: 1743 (void) printf("%-*s", field, "Reloc"); 1744 break; 1745 case ET_EXEC: 1746 (void) printf("%-*s", field, "Exec"); 1747 break; 1748 case ET_DYN: 1749 (void) printf("%-*s", field, "Dyn"); 1750 break; 1751 case ET_CORE: 1752 (void) printf("%-*s", field, "Core"); 1753 break; 1754 default: 1755 (void) printf("%-*d", field, 1756 EC_WORD(elf_head_p->e_type)); 1757 break; 1758 } 1759 switch (elf_head_p->e_machine) { 1760 case EM_NONE: 1761 (void) printf("%-12s", "No mach"); 1762 break; 1763 case EM_M32: 1764 (void) printf("%-12s", "WE32100"); 1765 break; 1766 case EM_SPARC: 1767 (void) printf("%-12s", "SPARC"); 1768 break; 1769 case EM_SPARCV9: 1770 (void) printf("%-12s", "SPARCV9"); 1771 break; 1772 case EM_386: 1773 (void) printf("%-12s", "80386"); 1774 break; 1775 case EM_68K: 1776 (void) printf("%-12s", "68000"); 1777 break; 1778 case EM_88K: 1779 (void) printf("%-12s", "88000"); 1780 break; 1781 case EM_486: 1782 (void) printf("%-12s", "80486"); 1783 break; 1784 case EM_860: 1785 (void) printf("%-12s", "i860"); 1786 break; 1787 case EM_MIPS: 1788 (void) printf("%-12s", "RS3000_BE"); 1789 break; 1790 case EM_MIPS_RS3_LE: 1791 (void) printf("%-12s", "RS3000_LE"); 1792 break; 1793 case EM_RS6000: 1794 (void) printf("%-12s", "RS6000"); 1795 break; 1796 case EM_PA_RISC: 1797 (void) printf("%-12s", "PA_RISC"); 1798 break; 1799 case EM_nCUBE: 1800 (void) printf("%-12s", "nCUBE"); 1801 break; 1802 case EM_VPP500: 1803 (void) printf("%-12s", "VPP500"); 1804 break; 1805 case EM_SPARC32PLUS: 1806 (void) printf("%-12s", "SPARC32PLUS"); 1807 break; 1808 case EM_PPC: 1809 (void) printf("%-12s", "PowerPC"); 1810 break; 1811 case EM_IA_64: 1812 (void) printf("%-12s", "IA64"); 1813 break; 1814 default: 1815 (void) printf("%-12d", EC_WORD(elf_head_p->e_machine)); 1816 } 1817 switch (elf_head_p->e_version) { 1818 case EV_NONE: 1819 (void) printf("Invalid\n"); 1820 break; 1821 case EV_CURRENT: 1822 (void) printf("Current\n"); 1823 break; 1824 default: 1825 (void) printf("%d\n", elf_head_p->e_version); 1826 } 1827 } 1828 (void) printf("%-#*llx%-#11llx%-#*llx%-#12x%#x\n", 1829 field, EC_ADDR(elf_head_p->e_entry), 1830 EC_OFF(elf_head_p->e_phoff), 1831 field, EC_OFF(elf_head_p->e_shoff), 1832 EC_WORD(elf_head_p->e_flags), 1833 EC_WORD(elf_head_p->e_ehsize)); 1834 if (!v_flag || (elf_head_p->e_shstrndx != SHN_XINDEX)) { 1835 (void) printf("%-#*x%-11u%-#*x%-12u%u\n", 1836 field, EC_WORD(elf_head_p->e_phentsize), 1837 EC_WORD(elf_head_p->e_phnum), 1838 field, EC_WORD(elf_head_p->e_shentsize), 1839 EC_WORD(elf_head_p->e_shnum), 1840 EC_WORD(elf_head_p->e_shstrndx)); 1841 } else { 1842 (void) printf("%-#*x%-11u%-#*x%-12uXINDEX\n", 1843 field, EC_WORD(elf_head_p->e_phentsize), 1844 EC_WORD(elf_head_p->e_phnum), 1845 field, EC_WORD(elf_head_p->e_shentsize), 1846 EC_WORD(elf_head_p->e_shnum)); 1847 } 1848 if ((elf_head_p->e_shnum == 0) && (elf_head_p->e_shoff > 0)) { 1849 Elf_Scn *scn; 1850 GElf_Shdr shdr0; 1851 int field; 1852 1853 if (gelf_getclass(elf_file) == ELFCLASS64) 1854 field = 21; 1855 else 1856 field = 13; 1857 if (!p_flag) { 1858 (void) printf("\n **** SECTION HEADER[0] " 1859 "{Elf Extensions} ****\n"); 1860 (void) printf( 1861 "[No]\tType\tFlags\t%-*s %-*s%-*s%sName\n", 1862 field, "Addr", field, "Offset", field, 1863 "Size(shnum)", 1864 /* compatibility: tab for elf32 */ 1865 (field == 13) ? "\t" : " "); 1866 (void) printf("\tLn(strndx) Info\t%-*s Entsize\n", 1867 field, "Adralgn"); 1868 } 1869 if ((scn = elf_getscn(elf_file, 0)) == NULL) { 1870 (void) fprintf(stderr, 1871 "%s: %s: elf_getscn failed: %s\n", 1872 prog_name, filename, elf_errmsg(-1)); 1873 return (NULL); 1874 } 1875 if (gelf_getshdr(scn, &shdr0) == 0) { 1876 (void) fprintf(stderr, 1877 "%s: %s: gelf_getshdr: %s\n", 1878 prog_name, filename, elf_errmsg(-1)); 1879 return (NULL); 1880 } 1881 (void) printf("[0]\t%u\t%llu\t", EC_WORD(shdr0.sh_type), 1882 EC_XWORD(shdr0.sh_flags)); 1883 1884 /* 1885 * LINTED - field and EC_XWORD cause -#*llu complaints that 1886 * even this comment can't shutup. 1887 */ 1888 (void) printf("%-#*llx %-#*llx%-#*llu%s%-#*u\n", 1889 field, EC_ADDR(shdr0.sh_addr), 1890 field, EC_OFF(shdr0.sh_offset), 1891 field, EC_XWORD(shdr0.sh_size), 1892 /* compatibility: tab for elf32 */ 1893 ((field == 13) ? "\t" : " "), 1894 field, EC_WORD(shdr0.sh_name)); 1895 1896 (void) printf("\t%u\t%u\t%-#*llx %-#*llx\n", 1897 EC_WORD(shdr0.sh_link), 1898 EC_WORD(shdr0.sh_info), 1899 field, EC_XWORD(shdr0.sh_addralign), 1900 field, EC_XWORD(shdr0.sh_entsize)); 1901 } 1902 (void) printf("\n"); 1903 1904 return (elf_head_p); 1905 } 1906 1907 /* 1908 * Print section contents. Input is an ELF file descriptor, 1909 * the ELF header, the SCNTAB structure, 1910 * the number of symbols, and the filename. 1911 * The number of sections, 1912 * and the offset into the SCNTAB structure will be 1913 * set in dump_section if d_flag or n_flag are set. 1914 * If v_flag is set, sections which can be interpreted will 1915 * be interpreted, otherwise raw data will be output in hexidecimal. 1916 */ 1917 static void 1918 print_section(Elf *elf_file, 1919 GElf_Ehdr *p_ehdr, SCNTAB *p, int num_scns, char *filename) 1920 { 1921 unsigned char *p_sec; 1922 int i; 1923 size_t size; 1924 1925 for (i = 0; i < num_scns; i++, p++) { 1926 GElf_Shdr shdr; 1927 1928 size = 0; 1929 if (s_flag && !v_flag) 1930 p_sec = (unsigned char *)get_rawscn(p->p_sd, &size); 1931 else 1932 p_sec = (unsigned char *)get_scndata(p->p_sd, &size); 1933 1934 if ((gelf_getshdr(p->p_sd, &shdr) != NULL) && 1935 (shdr.sh_type == SHT_NOBITS)) { 1936 continue; 1937 } 1938 if (s_flag && !v_flag) { 1939 (void) printf("\n%s:\n", p->scn_name); 1940 print_rawdata(p_sec, size); 1941 continue; 1942 } 1943 if (shdr.sh_type == SHT_SYMTAB) { 1944 dump_symbol_table(elf_file, p, filename); 1945 continue; 1946 } 1947 if (shdr.sh_type == SHT_DYNSYM) { 1948 dump_symbol_table(elf_file, p, filename); 1949 continue; 1950 } 1951 if (shdr.sh_type == SHT_STRTAB) { 1952 dump_string_table(p, 1); 1953 continue; 1954 } 1955 if (shdr.sh_type == SHT_RELA) { 1956 dump_reloc_table(elf_file, p_ehdr, p, 1, filename); 1957 continue; 1958 } 1959 if (shdr.sh_type == SHT_REL) { 1960 dump_reloc_table(elf_file, p_ehdr, p, 1, filename); 1961 continue; 1962 } 1963 if (shdr.sh_type == SHT_DYNAMIC) { 1964 dump_dynamic(elf_file, p, 1, filename); 1965 continue; 1966 } 1967 1968 (void) printf("\n%s:\n", p->scn_name); 1969 print_rawdata(p_sec, size); 1970 } 1971 (void) printf("\n"); 1972 } 1973 1974 /* 1975 * Print section contents. This function does not print the contents 1976 * of the sections but sets up the parameters and then calls 1977 * print_section to print the contents. Calling another function to print 1978 * the contents allows both -d and -n to work correctly 1979 * simultaneously. Input is an ELF file descriptor, the ELF header, 1980 * the SCNTAB structure, the number of sections, and the filename. 1981 * Set the range of sections if d_flag, and set section name if 1982 * n_flag. 1983 */ 1984 static void 1985 dump_section(Elf *elf_file, 1986 GElf_Ehdr *p_ehdr, SCNTAB *s, int num_scns, char *filename) 1987 { 1988 SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */ 1989 int i; 1990 int found_it = 0; /* for use with -n section_name */ 1991 1992 if (n_flag) { 1993 n_range = s; 1994 1995 for (i = 0; i < num_scns; i++, n_range++) { 1996 if ((strcmp(name, n_range->scn_name)) != 0) 1997 continue; 1998 else { 1999 found_it = 1; 2000 print_section(elf_file, p_ehdr, 2001 n_range, 1, filename); 2002 } 2003 } 2004 2005 if (!found_it) { 2006 (void) fprintf(stderr, "%s: %s: %s not found\n", 2007 prog_name, filename, name); 2008 } 2009 } /* end n_flag */ 2010 2011 if (d_flag) { 2012 d_range = s; 2013 d_num = check_range(d_low, d_hi, num_scns, filename); 2014 if (d_num < 0) 2015 return; 2016 d_range += d_low - 1; 2017 2018 print_section(elf_file, p_ehdr, d_range, d_num, filename); 2019 } /* end d_flag */ 2020 2021 if (!n_flag && !d_flag) 2022 print_section(elf_file, p_ehdr, s, num_scns, filename); 2023 } 2024 2025 /* 2026 * Print the section header table. This function does not print the contents 2027 * of the section headers but sets up the parameters and then calls 2028 * print_shdr to print the contents. Calling another function to print 2029 * the contents allows both -d and -n to work correctly 2030 * simultaneously. Input is the SCNTAB structure, 2031 * the number of sections from the ELF header, and the filename. 2032 * Set the range of section headers to print if d_flag, and set 2033 * name of section header to print if n_flag. 2034 */ 2035 static void 2036 dump_shdr(Elf *elf_file, SCNTAB *s, int num_scns, char *filename) 2037 { 2038 2039 SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */ 2040 int field; 2041 int i; 2042 int found_it = 0; /* for use with -n section_name */ 2043 2044 if (gelf_getclass(elf_file) == ELFCLASS64) 2045 field = 21; 2046 else 2047 field = 13; 2048 2049 if (!p_flag) { 2050 (void) printf("\n **** SECTION HEADER TABLE ****\n"); 2051 (void) printf("[No]\tType\tFlags\t%-*s %-*s %-*s%sName\n", 2052 field, "Addr", field, "Offset", field, "Size", 2053 /* compatibility: tab for elf32 */ 2054 (field == 13) ? "\t" : " "); 2055 (void) printf("\tLink\tInfo\t%-*s Entsize\n\n", 2056 field, "Adralgn"); 2057 } 2058 2059 if (n_flag) { 2060 n_range = s; 2061 2062 for (i = 1; i <= num_scns; i++, n_range++) { 2063 if ((strcmp(name, n_range->scn_name)) != 0) 2064 continue; 2065 else { 2066 found_it = 1; 2067 print_shdr(elf_file, n_range, 1, i); 2068 } 2069 } 2070 2071 if (!found_it) { 2072 (void) fprintf(stderr, "%s: %s: %s not found\n", 2073 prog_name, filename, name); 2074 } 2075 } /* end n_flag */ 2076 2077 if (d_flag) { 2078 d_range = s; 2079 d_num = check_range(d_low, d_hi, num_scns, filename); 2080 if (d_num < 0) 2081 return; 2082 d_range += d_low - 1; 2083 2084 print_shdr(elf_file, d_range, d_num, d_low); 2085 } /* end d_flag */ 2086 2087 if (!n_flag && !d_flag) 2088 print_shdr(elf_file, s, num_scns, 1); 2089 } 2090 2091 /* 2092 * Process all of the command line options (except 2093 * for -a, -g, -f, and -o). All of the options processed 2094 * by this function require the presence of the section 2095 * header table and will not be processed if it is not present. 2096 * Set up a buffer containing section name, section header, 2097 * and section descriptor for each section in the file. This 2098 * structure is used to avoid duplicate calls to libelf functions. 2099 * Structure members for the symbol table, the debugging information, 2100 * and the line number information are global. All of the 2101 * rest are local. 2102 */ 2103 static void 2104 dump_section_table(Elf *elf_file, GElf_Ehdr *elf_head_p, char *filename) 2105 { 2106 2107 static SCNTAB *buffer, *p_scns; 2108 Elf_Scn *scn = 0; 2109 char *s_name = NULL; 2110 int found = 0; 2111 unsigned int num_scns; 2112 size_t shstrndx; 2113 size_t shnum; 2114 2115 2116 if (elf_getshnum(elf_file, &shnum) == 0) { 2117 (void) fprintf(stderr, 2118 "%s: %s: elf_getshnum failed: %s\n", 2119 prog_name, filename, elf_errmsg(-1)); 2120 return; 2121 } 2122 if (elf_getshstrndx(elf_file, &shstrndx) == 0) { 2123 (void) fprintf(stderr, 2124 "%s: %s: elf_getshstrndx failed: %s\n", 2125 prog_name, filename, elf_errmsg(-1)); 2126 return; 2127 } 2128 2129 if ((buffer = calloc(shnum, sizeof (SCNTAB))) == NULL) { 2130 (void) fprintf(stderr, "%s: %s: cannot calloc space\n", 2131 prog_name, filename); 2132 return; 2133 } 2134 /* LINTED */ 2135 num_scns = (int)shnum - 1; 2136 2137 p_symtab = (SCNTAB *)0; 2138 p_dynsym = (SCNTAB *)0; 2139 p_scns = buffer; 2140 p_head_scns = buffer; 2141 2142 while ((scn = elf_nextscn(elf_file, scn)) != 0) { 2143 if ((gelf_getshdr(scn, &buffer->p_shdr)) == 0) { 2144 (void) fprintf(stderr, 2145 "%s: %s: %s\n", prog_name, filename, elf_errmsg(-1)); 2146 return; 2147 } 2148 s_name = (char *)elf_strptr(elf_file, 2149 shstrndx, buffer->p_shdr.sh_name); 2150 buffer->scn_name = s_name ? s_name : (char *)UNKNOWN; 2151 buffer->p_sd = scn; 2152 2153 if (buffer->p_shdr.sh_type == SHT_SYMTAB) { 2154 found += 1; 2155 p_symtab = buffer; 2156 } 2157 if (buffer->p_shdr.sh_type == SHT_DYNSYM) 2158 p_dynsym = buffer; 2159 buffer++; 2160 } 2161 2162 /* 2163 * These functions depend upon the presence of the section header table 2164 * and will not be invoked in its absence 2165 */ 2166 if (h_flag) { 2167 dump_shdr(elf_file, p_scns, num_scns, filename); 2168 } 2169 if (p_symtab && (t_flag || T_flag)) { 2170 dump_symbol_table(elf_file, p_symtab, filename); 2171 } 2172 if (c_flag) { 2173 dump_string_table(p_scns, num_scns); 2174 } 2175 if (r_flag) { 2176 dump_reloc_table(elf_file, elf_head_p, 2177 p_scns, num_scns, filename); 2178 } 2179 if (L_flag) { 2180 dump_dynamic(elf_file, p_scns, num_scns, filename); 2181 } 2182 if (s_flag) { 2183 dump_section(elf_file, elf_head_p, p_scns, 2184 num_scns, filename); 2185 } 2186 } 2187 2188 /* 2189 * Load the archive string table(s) (for extended-length strings) 2190 * into an in-core table/list 2191 */ 2192 static struct stab_list_s * 2193 load_arstring_table(struct stab_list_s *STabList, 2194 int fd, Elf *elf_file, Elf_Arhdr *p_ar, char *filename) 2195 { 2196 off_t here; 2197 struct stab_list_s *STL_entry, *STL_next; 2198 2199 if (p_ar) { 2200 STL_entry = malloc(sizeof (struct stab_list_s)); 2201 STL_entry->next = 0; 2202 STL_entry->strings = 0; 2203 STL_entry->size = 0; 2204 2205 if (!STabList) 2206 STabList = STL_entry; 2207 else { 2208 STL_next = STabList; 2209 while (STL_next->next != (void *)0) 2210 STL_next = STL_next->next; 2211 STL_next->next = STL_entry; 2212 } 2213 2214 STL_entry->size = p_ar->ar_size; 2215 STL_entry->strings = malloc(p_ar->ar_size); 2216 here = elf_getbase(elf_file); 2217 if ((lseek(fd, here, 0)) != here) { 2218 (void) fprintf(stderr, 2219 "%s: %s: could not lseek\n", prog_name, filename); 2220 } 2221 2222 if ((read(fd, STL_entry->strings, p_ar->ar_size)) == -1) { 2223 (void) fprintf(stderr, 2224 "%s: %s: could not read\n", prog_name, filename); 2225 } 2226 } 2227 return (STabList); 2228 } 2229 2230 /* 2231 * Print the archive header for each member of an archive. 2232 * Also call ar_sym_read to print the symbols in the 2233 * archive symbol table if g_flag. Input is a file descriptor, 2234 * an ELF file descriptor, and the filename. Putting the call 2235 * to dump the archive symbol table in this function is more 2236 * efficient since it is necessary to examine the archive member 2237 * name in the archive header to determine which member is the 2238 * symbol table. 2239 */ 2240 static void 2241 dump_ar_hdr(int fd, Elf *elf_file, char *filename) 2242 { 2243 extern int v_flag, g_flag, a_flag, p_flag; 2244 Elf_Arhdr *p_ar; 2245 Elf *arf; 2246 Elf_Cmd cmd; 2247 int title = 0; 2248 int err = 0; 2249 2250 char buf[DATESIZE]; 2251 2252 cmd = ELF_C_READ; 2253 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) { 2254 p_ar = elf_getarhdr(arf); 2255 if (p_ar == NULL) { 2256 (void) fprintf(stderr, 2257 "%s: %s: %s\n", prog_name, filename, elf_errmsg(-1)); 2258 continue; 2259 } 2260 if (strcmp(p_ar->ar_name, "/") == 0) { 2261 if (g_flag) 2262 ar_sym_read(elf_file, filename); 2263 } else if (strcmp(p_ar->ar_name, "//") == 0) { 2264 StringTableList = load_arstring_table( 2265 StringTableList, fd, arf, p_ar, 2266 filename); 2267 cmd = elf_next(arf); 2268 (void) elf_end(arf); 2269 continue; 2270 } else { 2271 if (a_flag) { 2272 (void) printf("%s[%s]:\n", filename, 2273 p_ar->ar_name); 2274 if (!p_flag && title == 0) { 2275 if (!v_flag) 2276 (void) printf( 2277 "\n\n\t\t\t***ARCHIVE HEADER***" 2278 "\n Date Uid Gid Mode Size Member Name\n\n"); 2279 else 2280 (void) printf( 2281 "\n\n\t\t\t***ARCHIVE HEADER***" 2282 "\n Date Uid Gid Mode Size Member Name\n\n"); 2283 title = 1; 2284 } 2285 if (!v_flag) { 2286 (void) printf( 2287 "\t0x%.8lx %6d %6d 0%.6ho 0x%.8lx %-s\n\n", 2288 p_ar->ar_date, 2289 (int)p_ar->ar_uid, 2290 (int)p_ar->ar_gid, 2291 (int)p_ar->ar_mode, 2292 p_ar->ar_size, 2293 p_ar->ar_name); 2294 } else { 2295 if ((strftime(buf, DATESIZE, 2296 "%b %d %H:%M:%S %Y", 2297 localtime( 2298 &(p_ar->ar_date)))) == 0) { 2299 (void) fprintf(stderr, 2300 "%s: %s: don't have enough space to store the date\n", prog_name, filename); 2301 exit(1); 2302 } 2303 (void) printf( 2304 "\t%s %6d %6d 0%.6ho 0x%.8lx %-s\n\n", 2305 buf, 2306 (int)p_ar->ar_uid, 2307 (int)p_ar->ar_gid, 2308 (int)p_ar->ar_mode, 2309 p_ar->ar_size, 2310 p_ar->ar_name); 2311 } 2312 } 2313 } 2314 cmd = elf_next(arf); 2315 (void) elf_end(arf); 2316 } /* end while */ 2317 2318 err = elf_errno(); 2319 if (err != 0) { 2320 (void) fprintf(stderr, 2321 "%s: %s: %s\n", prog_name, filename, elf_errmsg(err)); 2322 } 2323 } 2324 2325 /* 2326 * Process member files of an archive. This function provides 2327 * a loop through an archive equivalent the processing of 2328 * each_file for individual object files. 2329 */ 2330 static void 2331 dump_ar_files(int fd, Elf *elf_file, char *filename) 2332 { 2333 Elf_Arhdr *p_ar; 2334 Elf *arf; 2335 Elf_Cmd cmd; 2336 Elf_Kind file_type; 2337 GElf_Ehdr elf_head; 2338 char *fullname; 2339 2340 cmd = ELF_C_READ; 2341 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) { 2342 size_t len; 2343 2344 p_ar = elf_getarhdr(arf); 2345 if (p_ar == NULL) { 2346 (void) fprintf(stderr, 2347 "%s: %s: %s\n", 2348 prog_name, filename, elf_errmsg(-1)); 2349 return; 2350 } 2351 if ((strcmp(p_ar->ar_name, "/") == 0) || 2352 (strcmp(p_ar->ar_name, "//") == 0)) { 2353 cmd = elf_next(arf); 2354 (void) elf_end(arf); 2355 continue; 2356 } 2357 2358 len = strlen(filename) + strlen(p_ar->ar_name) + 3; 2359 if ((fullname = malloc(len)) == NULL) 2360 return; 2361 (void) snprintf(fullname, len, "%s[%s]", filename, 2362 p_ar->ar_name); 2363 (void) printf("\n%s:\n", fullname); 2364 file_type = elf_kind(arf); 2365 if (file_type == ELF_K_ELF) { 2366 if (dump_elf_header(arf, fullname, &elf_head) == NULL) 2367 return; 2368 if (o_flag) 2369 dump_exec_header(arf, 2370 (unsigned)elf_head.e_phnum, fullname); 2371 if (x_flag) 2372 dump_section_table(arf, &elf_head, fullname); 2373 } else { 2374 (void) fprintf(stderr, 2375 "%s: %s: invalid file type\n", 2376 prog_name, fullname); 2377 cmd = elf_next(arf); 2378 (void) elf_end(arf); 2379 continue; 2380 } 2381 2382 cmd = elf_next(arf); 2383 (void) elf_end(arf); 2384 } /* end while */ 2385 } 2386 2387 /* 2388 * Takes a filename as input. Test first for a valid version 2389 * of libelf.a and exit on error. Process each valid file 2390 * or archive given as input on the command line. Check 2391 * for file type. If it is an archive, process the archive- 2392 * specific options first, then files within the archive. 2393 * If it is an ELF object file, process it; otherwise 2394 * warn that it is an invalid file type. 2395 * All options except the archive-specific and program 2396 * execution header are processed in the function, dump_section_table. 2397 */ 2398 static void 2399 each_file(char *filename) 2400 { 2401 Elf *elf_file; 2402 GElf_Ehdr elf_head; 2403 int fd; 2404 Elf_Kind file_type; 2405 2406 struct stat buf; 2407 2408 Elf_Cmd cmd; 2409 errno = 0; 2410 2411 if (stat(filename, &buf) == -1) { 2412 int err = errno; 2413 (void) fprintf(stderr, "%s: %s: %s", prog_name, filename, 2414 strerror(err)); 2415 return; 2416 } 2417 2418 if ((fd = open((filename), O_RDONLY)) == -1) { 2419 (void) fprintf(stderr, "%s: %s: cannot read\n", prog_name, 2420 filename); 2421 return; 2422 } 2423 cmd = ELF_C_READ; 2424 if ((elf_file = elf_begin(fd, cmd, (Elf *)0)) == NULL) { 2425 (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename, 2426 elf_errmsg(-1)); 2427 return; 2428 } 2429 2430 file_type = elf_kind(elf_file); 2431 if (file_type == ELF_K_AR) { 2432 if (a_flag || g_flag) { 2433 dump_ar_hdr(fd, elf_file, filename); 2434 elf_file = elf_begin(fd, cmd, (Elf *)0); 2435 } 2436 if (z_flag) 2437 dump_ar_files(fd, elf_file, filename); 2438 } else { 2439 if (file_type == ELF_K_ELF) { 2440 (void) printf("\n%s:\n", filename); 2441 if (dump_elf_header(elf_file, filename, &elf_head)) { 2442 if (o_flag) 2443 dump_exec_header(elf_file, 2444 (unsigned)elf_head.e_phnum, 2445 filename); 2446 if (x_flag) 2447 dump_section_table(elf_file, 2448 &elf_head, filename); 2449 } 2450 } else { 2451 (void) fprintf(stderr, "%s: %s: invalid file type\n", 2452 prog_name, filename); 2453 } 2454 } 2455 (void) elf_end(elf_file); 2456 (void) close(fd); 2457 } 2458 2459 /* 2460 * Sets up flags for command line options given and then 2461 * calls each_file() to process each file. 2462 */ 2463 int 2464 main(int argc, char *argv[], char *envp[]) 2465 { 2466 char *optstr = OPTSTR; /* option string used by getopt() */ 2467 int optchar; 2468 2469 /* 2470 * Check for a binary that better fits this architecture. 2471 */ 2472 conv_check_native(argv, envp); 2473 2474 prog_name = argv[0]; 2475 2476 (void) setlocale(LC_ALL, ""); 2477 while ((optchar = getopt(argc, argv, optstr)) != -1) { 2478 switch (optchar) { 2479 case 'a': 2480 a_flag = 1; 2481 x_flag = 1; 2482 break; 2483 case 'g': 2484 g_flag = 1; 2485 x_flag = 1; 2486 break; 2487 case 'v': 2488 v_flag = 1; 2489 break; 2490 case 'p': 2491 p_flag = 1; 2492 break; 2493 case 'f': 2494 f_flag = 1; 2495 z_flag = 1; 2496 break; 2497 case 'o': 2498 o_flag = 1; 2499 z_flag = 1; 2500 break; 2501 case 'h': 2502 h_flag = 1; 2503 x_flag = 1; 2504 z_flag = 1; 2505 break; 2506 case 's': 2507 s_flag = 1; 2508 x_flag = 1; 2509 z_flag = 1; 2510 break; 2511 case 'd': 2512 d_flag = 1; 2513 x_flag = 1; 2514 z_flag = 1; 2515 set_range(optarg, &d_low, &d_hi); 2516 break; 2517 case 'n': 2518 n_flag++; 2519 x_flag = 1; 2520 z_flag = 1; 2521 name = optarg; 2522 break; 2523 case 'r': 2524 r_flag = 1; 2525 x_flag = 1; 2526 z_flag = 1; 2527 break; 2528 case 't': 2529 t_flag = 1; 2530 x_flag = 1; 2531 z_flag = 1; 2532 break; 2533 case 'C': 2534 C_flag = 1; 2535 t_flag = 1; 2536 x_flag = 1; 2537 z_flag = 1; 2538 break; 2539 case 'T': 2540 T_flag = 1; 2541 x_flag = 1; 2542 z_flag = 1; 2543 set_range(optarg, &T_low, &T_hi); 2544 break; 2545 case 'c': 2546 c_flag = 1; 2547 x_flag = 1; 2548 z_flag = 1; 2549 break; 2550 case 'L': 2551 L_flag = 1; 2552 x_flag = 1; 2553 z_flag = 1; 2554 break; 2555 case 'V': 2556 V_flag = 1; 2557 (void) fprintf(stderr, "dump: %s %s\n", 2558 (const char *)SGU_PKG, 2559 (const char *)SGU_REL); 2560 break; 2561 case '?': 2562 errflag += 1; 2563 break; 2564 default: 2565 break; 2566 } 2567 } 2568 2569 if (errflag || (optind >= argc) || (!z_flag && !x_flag)) { 2570 if (!(V_flag && (argc == 2))) { 2571 usage(); 2572 exit(269); 2573 } 2574 } 2575 2576 if (elf_version(EV_CURRENT) == EV_NONE) { 2577 (void) fprintf(stderr, "%s: libelf is out of date\n", 2578 prog_name); 2579 exit(101); 2580 } 2581 2582 while (optind < argc) { 2583 each_file(argv[optind]); 2584 optind++; 2585 } 2586 return (0); 2587 } 2588