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 * Print dynamic linking information. Input is an ELF 1201 * file descriptor, the SCNTAB structure, the number of 1202 * sections, and the filename. 1203 */ 1204 static void 1205 dump_dynamic(Elf *elf_file, SCNTAB *p_scns, int num_scns, char *filename) 1206 { 1207 Elf_Data *dyn_data; 1208 GElf_Dyn p_dyn; 1209 GElf_Phdr p_phdr; 1210 GElf_Ehdr p_ehdr; 1211 char *dt_name; 1212 int index = 1; 1213 int lib_scns = num_scns; 1214 SCNTAB *l_scns = p_scns; 1215 int header_num = 0; 1216 #define Fmttag "%-15.15s " 1217 #define Fmtptr "%#llx" 1218 1219 if (!p_flag) 1220 (void) printf("\n **** DYNAMIC SECTION INFORMATION ****\n"); 1221 1222 for (; num_scns > 0; num_scns--, p_scns++) { 1223 GElf_Word link; 1224 int ii; 1225 1226 1227 if (p_scns->p_shdr.sh_type != SHT_DYNAMIC) 1228 continue; 1229 1230 if (!p_flag) { 1231 (void) printf("%s:\n", p_scns->scn_name); 1232 (void) printf("[INDEX]\tTag Value\n"); 1233 } 1234 1235 if ((dyn_data = elf_getdata(p_scns->p_sd, NULL)) == 0) { 1236 (void) fprintf(stderr, "%s: %s: no data in " 1237 "%s section\n", prog_name, filename, 1238 p_scns->scn_name); 1239 return; 1240 } 1241 1242 link = p_scns->p_shdr.sh_link; 1243 ii = 0; 1244 1245 (void) gelf_getdyn(dyn_data, ii++, &p_dyn); 1246 while (p_dyn.d_tag != DT_NULL) { 1247 char value[256]; 1248 1249 (void) printf("[%d]\t", index++); 1250 1251 switch (p_dyn.d_tag) { 1252 /* 1253 * Start of generic flags. 1254 */ 1255 case (DT_NEEDED): 1256 (void) printf(Fmttag, (const char *)"NEEDED"); 1257 if (v_flag) 1258 dt_name = (char *)elf_strptr(elf_file, 1259 link, p_dyn.d_un.d_ptr); 1260 if (dt_name == NULL) 1261 dt_name = (char *)UNKNOWN; 1262 if (v_flag && strlen(dt_name)) 1263 (void) printf("%s", dt_name); 1264 else 1265 (void) printf(Fmtptr, 1266 EC_ADDR(p_dyn.d_un.d_ptr)); 1267 break; 1268 case (DT_PLTRELSZ): 1269 (void) printf(Fmttag, (const char *)"PLTSZ"); 1270 (void) printf(Fmtptr, 1271 EC_XWORD(p_dyn.d_un.d_val)); 1272 break; 1273 case (DT_PLTGOT): 1274 (void) printf(Fmttag, (const char *)"PLTGOT"); 1275 (void) printf(Fmtptr, 1276 EC_ADDR(p_dyn.d_un.d_ptr)); 1277 break; 1278 case (DT_HASH): 1279 (void) printf(Fmttag, (const char *)"HASH"); 1280 (void) printf(Fmtptr, 1281 EC_ADDR(p_dyn.d_un.d_ptr)); 1282 break; 1283 case (DT_STRTAB): 1284 (void) printf(Fmttag, (const char *)"STRTAB"); 1285 (void) printf(Fmtptr, 1286 EC_ADDR(p_dyn.d_un.d_ptr)); 1287 break; 1288 case (DT_SYMTAB): 1289 (void) printf(Fmttag, (const char *)"SYMTAB"); 1290 (void) printf(Fmtptr, 1291 EC_ADDR(p_dyn.d_un.d_ptr)); 1292 break; 1293 case (DT_RELA): 1294 (void) printf(Fmttag, (const char *)"RELA"); 1295 (void) printf(Fmtptr, 1296 EC_ADDR(p_dyn.d_un.d_ptr)); 1297 break; 1298 case (DT_RELASZ): 1299 (void) printf(Fmttag, (const char *)"RELASZ"); 1300 (void) printf(Fmtptr, 1301 EC_XWORD(p_dyn.d_un.d_val)); 1302 break; 1303 case (DT_RELAENT): 1304 (void) printf(Fmttag, (const char *)"RELAENT"); 1305 (void) printf(Fmtptr, 1306 EC_XWORD(p_dyn.d_un.d_val)); 1307 break; 1308 case (DT_STRSZ): 1309 (void) printf(Fmttag, (const char *)"STRSZ"); 1310 (void) printf(Fmtptr, 1311 EC_XWORD(p_dyn.d_un.d_val)); 1312 break; 1313 case (DT_SYMENT): 1314 (void) printf(Fmttag, (const char *)"SYMENT"); 1315 (void) printf(Fmtptr, 1316 EC_XWORD(p_dyn.d_un.d_val)); 1317 break; 1318 case (DT_INIT): 1319 (void) printf(Fmttag, (const char *)"INIT"); 1320 (void) printf(Fmtptr, 1321 EC_ADDR(p_dyn.d_un.d_ptr)); 1322 break; 1323 case (DT_FINI): 1324 (void) printf(Fmttag, (const char *)"FINI"); 1325 (void) printf(Fmtptr, 1326 EC_ADDR(p_dyn.d_un.d_ptr)); 1327 break; 1328 case (DT_SONAME): 1329 (void) printf(Fmttag, (const char *)"SONAME"); 1330 if (v_flag) 1331 dt_name = (char *)elf_strptr(elf_file, 1332 link, p_dyn.d_un.d_ptr); 1333 if (dt_name == NULL) 1334 dt_name = (char *)UNKNOWN; 1335 if (v_flag && strlen(dt_name)) 1336 (void) printf("%s", dt_name); 1337 else 1338 (void) printf(Fmtptr, 1339 EC_ADDR(p_dyn.d_un.d_ptr)); 1340 break; 1341 case (DT_RPATH): 1342 (void) printf(Fmttag, (const char *)"RPATH"); 1343 if (v_flag) 1344 dt_name = (char *)elf_strptr(elf_file, 1345 link, p_dyn.d_un.d_ptr); 1346 if (dt_name == NULL) 1347 dt_name = (char *)UNKNOWN; 1348 if (v_flag && strlen(dt_name)) 1349 (void) printf("%s", dt_name); 1350 else 1351 (void) printf(Fmtptr, 1352 EC_ADDR(p_dyn.d_un.d_ptr)); 1353 break; 1354 case (DT_SYMBOLIC): 1355 (void) printf(Fmttag, (const char *)"SYMB"); 1356 (void) printf("%s", (const char *)"(ignored)"); 1357 break; 1358 case (DT_REL): 1359 (void) printf(Fmttag, (const char *)"REL"); 1360 (void) printf(Fmtptr, 1361 EC_ADDR(p_dyn.d_un.d_ptr)); 1362 break; 1363 case (DT_RELSZ): 1364 (void) printf(Fmttag, (const char *)"RELSZ"); 1365 (void) printf(Fmtptr, 1366 EC_XWORD(p_dyn.d_un.d_val)); 1367 break; 1368 case (DT_RELENT): 1369 (void) printf(Fmttag, (const char *)"RELENT"); 1370 (void) printf(Fmtptr, 1371 EC_XWORD(p_dyn.d_un.d_val)); 1372 break; 1373 case (DT_PLTREL): 1374 (void) printf(Fmttag, (const char *)"PLTREL"); 1375 (void) printf(Fmtptr, 1376 EC_XWORD(p_dyn.d_un.d_val)); 1377 break; 1378 case (DT_DEBUG): 1379 (void) printf(Fmttag, (const char *)"DEBUG"); 1380 (void) printf(Fmtptr, 1381 EC_ADDR(p_dyn.d_un.d_ptr)); 1382 break; 1383 case (DT_TEXTREL): 1384 (void) printf(Fmttag, (const char *)"TEXTREL"); 1385 (void) printf(Fmtptr, 1386 EC_ADDR(p_dyn.d_un.d_val)); 1387 break; 1388 case (DT_JMPREL): 1389 (void) printf(Fmttag, (const char *)"JMPREL"); 1390 (void) printf(Fmtptr, 1391 EC_ADDR(p_dyn.d_un.d_ptr)); 1392 break; 1393 case (DT_BIND_NOW): 1394 (void) printf(Fmttag, (const char *)"BIND_NOW"); 1395 (void) printf(Fmtptr, 1396 EC_ADDR(p_dyn.d_un.d_val)); 1397 break; 1398 case (DT_INIT_ARRAY): 1399 (void) printf(Fmttag, 1400 (const char *)"INIT_ARRAY"); 1401 (void) printf(Fmtptr, 1402 EC_ADDR(p_dyn.d_un.d_ptr)); 1403 break; 1404 case (DT_FINI_ARRAY): 1405 (void) printf(Fmttag, 1406 (const char *)"FINI_ARRAY"); 1407 (void) printf(Fmtptr, 1408 EC_ADDR(p_dyn.d_un.d_ptr)); 1409 break; 1410 case (DT_INIT_ARRAYSZ): 1411 (void) printf(Fmttag, 1412 (const char *)"INIT_ARRAYSZ"); 1413 (void) printf(Fmtptr, 1414 EC_ADDR(p_dyn.d_un.d_ptr)); 1415 break; 1416 case (DT_FINI_ARRAYSZ): 1417 (void) printf(Fmttag, 1418 (const char *)"FINI_ARRAYSZ"); 1419 (void) printf(Fmtptr, 1420 EC_ADDR(p_dyn.d_un.d_ptr)); 1421 break; 1422 case (DT_RUNPATH): 1423 (void) printf(Fmttag, (const char *)"RUNPATH"); 1424 if (v_flag) 1425 dt_name = (char *)elf_strptr(elf_file, 1426 link, p_dyn.d_un.d_ptr); 1427 if (dt_name == NULL) 1428 dt_name = (char *)UNKNOWN; 1429 if (v_flag && strlen(dt_name)) 1430 (void) printf("%s", dt_name); 1431 else 1432 (void) printf(Fmtptr, 1433 EC_ADDR(p_dyn.d_un.d_ptr)); 1434 break; 1435 case (DT_FLAGS): 1436 (void) printf(Fmttag, 1437 (const char *)"FLAGS"); 1438 value[0] = '\0'; 1439 if (v_flag) { 1440 if (p_dyn.d_un.d_val & DF_ORIGIN) 1441 (void) strcat(value, 1442 (const char *)"ORIGIN "); 1443 if (p_dyn.d_un.d_val & DF_SYMBOLIC) 1444 (void) strcat(value, 1445 (const char *)"SYMBOLIC "); 1446 if (p_dyn.d_un.d_val & DF_TEXTREL) 1447 (void) strcat(value, 1448 (const char *)"TEXTREL "); 1449 if (p_dyn.d_un.d_val & DF_BIND_NOW) 1450 (void) strcat(value, 1451 (const char *)"BIND_NOW "); 1452 if (p_dyn.d_un.d_val & DF_STATIC_TLS) 1453 (void) strcat(value, 1454 (const char *)"STATIC_TLS "); 1455 } 1456 if (v_flag && strlen(value)) 1457 (void) printf("%s", value); 1458 else 1459 (void) printf(Fmtptr, 1460 EC_ADDR(p_dyn.d_un.d_ptr)); 1461 break; 1462 case (DT_PREINIT_ARRAY): 1463 (void) printf(Fmttag, 1464 (const char *)"PRINIT_ARRAY"); 1465 (void) printf(Fmtptr, 1466 EC_ADDR(p_dyn.d_un.d_ptr)); 1467 break; 1468 case (DT_PREINIT_ARRAYSZ): 1469 (void) printf(Fmttag, 1470 (const char *)"PRINIT_ARRAYSZ"); 1471 (void) printf(Fmtptr, 1472 EC_ADDR(p_dyn.d_un.d_ptr)); 1473 break; 1474 /* 1475 * DT_LOOS - DT_HIOS range. 1476 */ 1477 case (DT_SUNW_AUXILIARY): 1478 (void) printf(Fmttag, 1479 (const char *)"SUNW_AUXILIARY"); 1480 if (v_flag) 1481 dt_name = (char *)elf_strptr(elf_file, 1482 link, p_dyn.d_un.d_ptr); 1483 if (dt_name == NULL) 1484 dt_name = (char *)UNKNOWN; 1485 if (v_flag && strlen(dt_name)) 1486 (void) printf("%s", dt_name); 1487 else 1488 (void) printf(Fmtptr, 1489 EC_ADDR(p_dyn.d_un.d_ptr)); 1490 break; 1491 case (DT_SUNW_RTLDINF): 1492 (void) printf(Fmttag, 1493 (const char *)"SUNW_RTLDINF"); 1494 (void) printf(Fmtptr, 1495 EC_ADDR(p_dyn.d_un.d_ptr)); 1496 break; 1497 case (DT_SUNW_FILTER): 1498 (void) printf(Fmttag, 1499 (const char *)"SUNW_FILTER"); 1500 if (v_flag) 1501 dt_name = (char *)elf_strptr(elf_file, 1502 link, p_dyn.d_un.d_ptr); 1503 if (dt_name == NULL) 1504 dt_name = (char *)UNKNOWN; 1505 if (v_flag && strlen(dt_name)) 1506 (void) printf("%s", dt_name); 1507 else 1508 (void) printf(Fmtptr, 1509 EC_ADDR(p_dyn.d_un.d_ptr)); 1510 break; 1511 case (DT_SUNW_CAP): 1512 (void) printf(Fmttag, 1513 (const char *)"SUNW_CAP"); 1514 (void) printf(Fmtptr, 1515 EC_ADDR(p_dyn.d_un.d_ptr)); 1516 break; 1517 1518 /* 1519 * SUNW: DT_VALRNGLO - DT_VALRNGHI range. 1520 */ 1521 case (DT_CHECKSUM): 1522 (void) printf(Fmttag, 1523 (const char *)"CHECKSUM"); 1524 (void) printf(Fmtptr, 1525 EC_XWORD(p_dyn.d_un.d_val)); 1526 break; 1527 case (DT_PLTPADSZ): 1528 (void) printf(Fmttag, 1529 (const char *)"PLTPADSZ"); 1530 (void) printf(Fmtptr, 1531 EC_XWORD(p_dyn.d_un.d_val)); 1532 break; 1533 case (DT_MOVEENT): 1534 (void) printf(Fmttag, 1535 (const char *)"MOVEENT"); 1536 (void) printf(Fmtptr, 1537 EC_XWORD(p_dyn.d_un.d_val)); 1538 break; 1539 case (DT_MOVESZ): 1540 (void) printf(Fmttag, 1541 (const char *)"MOVESZ"); 1542 (void) printf(Fmtptr, 1543 EC_XWORD(p_dyn.d_un.d_val)); 1544 break; 1545 case (DT_FEATURE_1): 1546 (void) printf(Fmttag, 1547 (const char *)"FEATURE_1"); 1548 value[0] = '\0'; 1549 if (v_flag) { 1550 if (p_dyn.d_un.d_val & DTF_1_PARINIT) 1551 (void) strcat(value, 1552 (const char *)"PARINIT "); 1553 if (p_dyn.d_un.d_val & DTF_1_CONFEXP) 1554 (void) strcat(value, 1555 (const char *)"CONFEXP "); 1556 } 1557 if (v_flag && strlen(value)) 1558 (void) printf("%s", value); 1559 else 1560 (void) printf(Fmtptr, 1561 EC_ADDR(p_dyn.d_un.d_ptr)); 1562 break; 1563 case (DT_POSFLAG_1): 1564 (void) printf(Fmttag, 1565 (const char *)"POSFLAG_1"); 1566 value[0] = '\0'; 1567 if (v_flag) { 1568 if (p_dyn.d_un.d_val & DF_P1_LAZYLOAD) 1569 (void) strcat(value, 1570 (const char *)"LAZYLOAD "); 1571 if (p_dyn.d_un.d_val & DF_P1_GROUPPERM) 1572 (void) strcat(value, 1573 (const char *)"GROUPPERM "); 1574 } 1575 if (v_flag && strlen(value)) 1576 (void) printf("%s", value); 1577 else 1578 (void) printf(Fmtptr, 1579 EC_ADDR(p_dyn.d_un.d_ptr)); 1580 break; 1581 case (DT_SYMINSZ): 1582 (void) printf(Fmttag, 1583 (const char *)"SYMINSZ"); 1584 (void) printf(Fmtptr, 1585 EC_XWORD(p_dyn.d_un.d_val)); 1586 break; 1587 case (DT_SYMINENT): 1588 (void) printf(Fmttag, 1589 (const char *)"SYMINENT"); 1590 (void) printf(Fmtptr, 1591 EC_XWORD(p_dyn.d_un.d_val)); 1592 break; 1593 1594 /* 1595 * SUNW: DT_ADDRRNGLO - DT_ADDRRNGHI range. 1596 */ 1597 case (DT_CONFIG): 1598 (void) printf(Fmttag, (const char *)"CONFIG"); 1599 if (v_flag) 1600 dt_name = (char *)elf_strptr(elf_file, 1601 link, p_dyn.d_un.d_ptr); 1602 if (dt_name == NULL) 1603 dt_name = (char *)UNKNOWN; 1604 if (v_flag && strlen(dt_name)) 1605 (void) printf("%s", dt_name); 1606 else 1607 (void) printf(Fmtptr, 1608 EC_ADDR(p_dyn.d_un.d_ptr)); 1609 break; 1610 case (DT_DEPAUDIT): 1611 (void) printf(Fmttag, 1612 (const char *)"DEPAUDIT"); 1613 if (v_flag) 1614 dt_name = (char *)elf_strptr(elf_file, 1615 link, p_dyn.d_un.d_ptr); 1616 if (dt_name == NULL) 1617 dt_name = (char *)UNKNOWN; 1618 if (v_flag && strlen(dt_name)) 1619 (void) printf("%s", dt_name); 1620 else 1621 (void) printf(Fmtptr, 1622 EC_ADDR(p_dyn.d_un.d_ptr)); 1623 break; 1624 case (DT_AUDIT): 1625 (void) printf(Fmttag, 1626 (const char *)"AUDIT"); 1627 if (v_flag) 1628 dt_name = (char *)elf_strptr(elf_file, 1629 link, p_dyn.d_un.d_ptr); 1630 if (dt_name == NULL) 1631 dt_name = (char *)UNKNOWN; 1632 if (v_flag && strlen(dt_name)) 1633 (void) printf("%s", dt_name); 1634 else 1635 (void) printf(Fmtptr, 1636 EC_ADDR(p_dyn.d_un.d_ptr)); 1637 break; 1638 case (DT_PLTPAD): 1639 (void) printf(Fmttag, 1640 (const char *)"PLTPAD"); 1641 (void) printf(Fmtptr, 1642 EC_ADDR(p_dyn.d_un.d_ptr)); 1643 break; 1644 case (DT_MOVETAB): 1645 (void) printf(Fmttag, 1646 (const char *)"MOVETAB"); 1647 (void) printf(Fmtptr, 1648 EC_ADDR(p_dyn.d_un.d_ptr)); 1649 break; 1650 case (DT_SYMINFO): 1651 (void) printf(Fmttag, 1652 (const char *)"SYMINFO"); 1653 (void) printf(Fmtptr, 1654 EC_ADDR(p_dyn.d_un.d_ptr)); 1655 break; 1656 1657 /* 1658 * SUNW: generic range. 1659 */ 1660 case (DT_RELACOUNT): 1661 (void) printf(Fmttag, 1662 (const char *)"RELACOUNT"); 1663 (void) printf(Fmtptr, 1664 EC_ADDR(p_dyn.d_un.d_ptr)); 1665 break; 1666 case (DT_RELCOUNT): 1667 (void) printf(Fmttag, 1668 (const char *)"RELCOUNT"); 1669 (void) printf(Fmtptr, 1670 EC_ADDR(p_dyn.d_un.d_ptr)); 1671 break; 1672 case (DT_FLAGS_1): 1673 (void) printf(Fmttag, 1674 (const char *)"FLAGS_1"); 1675 value[0] = '\0'; 1676 if (v_flag) { 1677 if (p_dyn.d_un.d_val & DF_1_NOW) 1678 (void) strcat(value, 1679 (const char *)"NOW "); 1680 if (p_dyn.d_un.d_val & DF_1_GLOBAL) 1681 (void) strcat(value, 1682 (const char *)"GLOBAL "); 1683 if (p_dyn.d_un.d_val & DF_1_GROUP) 1684 (void) strcat(value, 1685 (const char *)"GROUP "); 1686 if (p_dyn.d_un.d_val & DF_1_NODELETE) 1687 (void) strcat(value, 1688 (const char *)"NODELETE "); 1689 if (p_dyn.d_un.d_val & DF_1_LOADFLTR) 1690 (void) strcat(value, 1691 (const char *)"LOADFLTR "); 1692 if (p_dyn.d_un.d_val & DF_1_INITFIRST) 1693 (void) strcat(value, 1694 (const char *)"INITFIRST "); 1695 if (p_dyn.d_un.d_val & DF_1_NOOPEN) 1696 (void) strcat(value, 1697 (const char *)"NOOPEN "); 1698 if (p_dyn.d_un.d_val & DF_1_ORIGIN) 1699 (void) strcat(value, 1700 (const char *)"ORIGIN "); 1701 if (p_dyn.d_un.d_val & DF_1_DIRECT) 1702 (void) strcat(value, 1703 (const char *)"DIRECT "); 1704 if (p_dyn.d_un.d_val & DF_1_TRANS) 1705 (void) strcat(value, 1706 (const char *)"TRANS "); 1707 if (p_dyn.d_un.d_val & DF_1_INTERPOSE) 1708 (void) strcat(value, 1709 (const char *)"INTERPOSE "); 1710 if (p_dyn.d_un.d_val & DF_1_NODEFLIB) 1711 (void) strcat(value, 1712 (const char *)"NODEFLIB "); 1713 if (p_dyn.d_un.d_val & DF_1_NODUMP) 1714 (void) strcat(value, 1715 (const char *)"NODUMP "); 1716 if (p_dyn.d_un.d_val & DF_1_CONFALT) 1717 (void) strcat(value, 1718 (const char *)"CONFALT "); 1719 if (p_dyn.d_un.d_val & DF_1_ENDFILTEE) 1720 (void) strcat(value, 1721 (const char *)"ENDFILTEE "); 1722 if (p_dyn.d_un.d_val & DF_1_DISPRELDNE) 1723 (void) strcat(value, 1724 (const char *)"DISPRELDONE "); 1725 if (p_dyn.d_un.d_val & DF_1_DISPRELPND) 1726 (void) strcat(value, 1727 (const char *)"DISPRELPND "); 1728 if (p_dyn.d_un.d_val & DF_1_IGNMULDEF) 1729 (void) strcat(value, 1730 (const char *)"IGNMULDEF "); 1731 if (p_dyn.d_un.d_val & DF_1_NOKSYMS) 1732 (void) strcat(value, 1733 (const char *)"NOKSYMS "); 1734 if (p_dyn.d_un.d_val & DF_1_NORELOC) 1735 (void) strcat(value, 1736 (const char *)"NORELOC "); 1737 } 1738 if (v_flag && strlen(value)) 1739 (void) printf("%s", value); 1740 else 1741 (void) printf(Fmtptr, 1742 EC_ADDR(p_dyn.d_un.d_ptr)); 1743 break; 1744 case (DT_VERSYM): 1745 (void) printf(Fmttag, (const char *)"VERSYM"); 1746 (void) printf(Fmtptr, 1747 EC_ADDR(p_dyn.d_un.d_ptr)); 1748 break; 1749 case (DT_VERDEF): 1750 (void) printf(Fmttag, (const char *)"VERDEF"); 1751 (void) printf(Fmtptr, 1752 EC_ADDR(p_dyn.d_un.d_ptr)); 1753 break; 1754 case (DT_VERDEFNUM): 1755 (void) printf(Fmttag, 1756 (const char *)"VERDEFNUM"); 1757 (void) printf(Fmtptr, 1758 EC_XWORD(p_dyn.d_un.d_val)); 1759 break; 1760 case (DT_VERNEED): 1761 (void) printf(Fmttag, (const char *)"VERNEED"); 1762 (void) printf(Fmtptr, 1763 EC_ADDR(p_dyn.d_un.d_ptr)); 1764 break; 1765 case (DT_VERNEEDNUM): 1766 (void) printf(Fmttag, 1767 (const char *)"VERNEEDNUM"); 1768 (void) printf(Fmtptr, 1769 EC_XWORD(p_dyn.d_un.d_val)); 1770 break; 1771 case (DT_AUXILIARY): 1772 (void) printf(Fmttag, 1773 (const char *)"AUXILIARY"); 1774 if (v_flag) 1775 dt_name = (char *)elf_strptr(elf_file, 1776 link, p_dyn.d_un.d_ptr); 1777 if (dt_name == NULL) 1778 dt_name = (char *)UNKNOWN; 1779 if (v_flag && strlen(dt_name)) 1780 (void) printf("%s", dt_name); 1781 else 1782 (void) printf(Fmtptr, 1783 EC_ADDR(p_dyn.d_un.d_ptr)); 1784 break; 1785 case (DT_USED): 1786 (void) printf(Fmttag, (const char *)"USED"); 1787 if (v_flag) 1788 dt_name = (char *)elf_strptr(elf_file, 1789 link, p_dyn.d_un.d_ptr); 1790 if (dt_name == NULL) 1791 dt_name = (char *)UNKNOWN; 1792 if (v_flag && strlen(dt_name)) 1793 (void) printf("%s", dt_name); 1794 else 1795 (void) printf(Fmtptr, 1796 EC_ADDR(p_dyn.d_un.d_ptr)); 1797 break; 1798 case (DT_FILTER): 1799 (void) printf(Fmttag, (const char *)"FILTER"); 1800 if (v_flag) 1801 dt_name = (char *)elf_strptr(elf_file, 1802 link, p_dyn.d_un.d_ptr); 1803 if (dt_name == NULL) 1804 dt_name = (char *)UNKNOWN; 1805 if (v_flag && strlen(dt_name)) 1806 (void) printf("%s", dt_name); 1807 else 1808 (void) printf(Fmtptr, 1809 EC_ADDR(p_dyn.d_un.d_ptr)); 1810 break; 1811 1812 /* 1813 * SUNW: machine specific range. 1814 */ 1815 case (DT_SPARC_REGISTER): 1816 (void) printf(Fmttag, 1817 (const char *)"REGISTER"); 1818 (void) printf(Fmtptr, 1819 EC_XWORD(p_dyn.d_un.d_val)); 1820 break; 1821 case (DT_DEPRECATED_SPARC_REGISTER): 1822 (void) printf(Fmttag, 1823 (const char *)"REGISTER"); 1824 (void) printf("%#llx (deprecated value)", 1825 EC_XWORD(p_dyn.d_un.d_val)); 1826 break; 1827 default: 1828 (void) printf("%lld", EC_XWORD(p_dyn.d_tag)); 1829 break; 1830 } 1831 (void) printf("\n"); 1832 (void) gelf_getdyn(dyn_data, ii++, &p_dyn); 1833 } 1834 } 1835 1836 /* 1837 * Check for existence of static shared library information. 1838 */ 1839 (void) gelf_getehdr(elf_file, &p_ehdr); 1840 while (header_num < p_ehdr.e_phnum) { 1841 (void) gelf_getphdr(elf_file, header_num, &p_phdr); 1842 if (p_phdr.p_type == PT_SHLIB) { 1843 while (--lib_scns > 0) { 1844 if (strcmp(l_scns->scn_name, ".lib") == 0) { 1845 print_static(l_scns, filename); 1846 } 1847 l_scns++; 1848 } 1849 } 1850 header_num++; 1851 } 1852 } 1853 1854 /* 1855 * Print the ELF header. Input is an ELF file descriptor 1856 * and the filename. If f_flag is set, the ELF header is 1857 * printed to stdout, otherwise the function returns after 1858 * setting the pointer to the ELF header. Any values which 1859 * are not known are printed in decimal. Fields must be updated 1860 * as new values are added. 1861 */ 1862 static GElf_Ehdr * 1863 dump_elf_header(Elf *elf_file, char *filename, GElf_Ehdr * elf_head_p) 1864 { 1865 int class, data; 1866 int field; 1867 1868 if (gelf_getehdr(elf_file, elf_head_p) == NULL) { 1869 (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename, 1870 elf_errmsg(-1)); 1871 return (NULL); 1872 } 1873 1874 class = (int)elf_head_p->e_ident[4]; 1875 1876 if (class == ELFCLASS64) 1877 field = 21; 1878 else 1879 field = 13; 1880 1881 if (!f_flag) 1882 return (elf_head_p); 1883 1884 if (!p_flag) { 1885 (void) printf("\n **** ELF HEADER ****\n"); 1886 (void) printf("%-*s%-11s%-*sMachine Version\n", 1887 field, "Class", "Data", field, "Type"); 1888 (void) printf("%-*s%-11s%-*sFlags Ehsize\n", 1889 field, "Entry", "Phoff", field, "Shoff"); 1890 (void) printf("%-*s%-11s%-*sShnum Shstrndx\n\n", 1891 field, "Phentsize", "Phnum", field, "Shentsz"); 1892 } 1893 1894 if (!v_flag) { 1895 (void) printf("%-*d%-11d%-*d%-12d%d\n", 1896 field, elf_head_p->e_ident[4], 1897 elf_head_p->e_ident[5], 1898 field, (int)elf_head_p->e_type, 1899 (int)elf_head_p->e_machine, 1900 elf_head_p->e_version); 1901 } else { 1902 data = elf_head_p->e_ident[5]; 1903 1904 switch (class) { 1905 case ELFCLASSNONE: 1906 (void) printf("%-*s", field, "None"); 1907 break; 1908 case ELFCLASS32: 1909 (void) printf("%-*s", field, "32-bit"); 1910 break; 1911 case ELFCLASS64: 1912 (void) printf("%-*s", field, "64-bit"); 1913 break; 1914 default: 1915 (void) printf("%-*d", field, class); 1916 break; 1917 } 1918 switch (data) { 1919 case ELFDATANONE: 1920 (void) printf("%-11s", "None "); 1921 break; 1922 case ELFDATA2LSB: 1923 (void) printf("%-11s", "2LSB "); 1924 break; 1925 case ELFDATA2MSB: 1926 (void) printf("%-11s", "2MSB "); 1927 break; 1928 default: 1929 (void) printf("%-11d", data); 1930 break; 1931 } 1932 1933 switch (elf_head_p->e_type) { 1934 case ET_NONE: 1935 (void) printf("%-*s", field, "None"); 1936 break; 1937 case ET_REL: 1938 (void) printf("%-*s", field, "Reloc"); 1939 break; 1940 case ET_EXEC: 1941 (void) printf("%-*s", field, "Exec"); 1942 break; 1943 case ET_DYN: 1944 (void) printf("%-*s", field, "Dyn"); 1945 break; 1946 case ET_CORE: 1947 (void) printf("%-*s", field, "Core"); 1948 break; 1949 default: 1950 (void) printf("%-*d", field, 1951 EC_WORD(elf_head_p->e_type)); 1952 break; 1953 } 1954 switch (elf_head_p->e_machine) { 1955 case EM_NONE: 1956 (void) printf("%-12s", "No mach"); 1957 break; 1958 case EM_M32: 1959 (void) printf("%-12s", "WE32100"); 1960 break; 1961 case EM_SPARC: 1962 (void) printf("%-12s", "SPARC"); 1963 break; 1964 case EM_SPARCV9: 1965 (void) printf("%-12s", "SPARCV9"); 1966 break; 1967 case EM_386: 1968 (void) printf("%-12s", "80386"); 1969 break; 1970 case EM_68K: 1971 (void) printf("%-12s", "68000"); 1972 break; 1973 case EM_88K: 1974 (void) printf("%-12s", "88000"); 1975 break; 1976 case EM_486: 1977 (void) printf("%-12s", "80486"); 1978 break; 1979 case EM_860: 1980 (void) printf("%-12s", "i860"); 1981 break; 1982 case EM_MIPS: 1983 (void) printf("%-12s", "RS3000_BE"); 1984 break; 1985 case EM_MIPS_RS3_LE: 1986 (void) printf("%-12s", "RS3000_LE"); 1987 break; 1988 case EM_RS6000: 1989 (void) printf("%-12s", "RS6000"); 1990 break; 1991 case EM_PA_RISC: 1992 (void) printf("%-12s", "PA_RISC"); 1993 break; 1994 case EM_nCUBE: 1995 (void) printf("%-12s", "nCUBE"); 1996 break; 1997 case EM_VPP500: 1998 (void) printf("%-12s", "VPP500"); 1999 break; 2000 case EM_SPARC32PLUS: 2001 (void) printf("%-12s", "SPARC32PLUS"); 2002 break; 2003 case EM_PPC: 2004 (void) printf("%-12s", "PowerPC"); 2005 break; 2006 case EM_IA_64: 2007 (void) printf("%-12s", "IA64"); 2008 break; 2009 default: 2010 (void) printf("%-12d", EC_WORD(elf_head_p->e_machine)); 2011 } 2012 switch (elf_head_p->e_version) { 2013 case EV_NONE: 2014 (void) printf("Invalid\n"); 2015 break; 2016 case EV_CURRENT: 2017 (void) printf("Current\n"); 2018 break; 2019 default: 2020 (void) printf("%d\n", elf_head_p->e_version); 2021 } 2022 } 2023 (void) printf("%-#*llx%-#11llx%-#*llx%-#12x%#x\n", 2024 field, EC_ADDR(elf_head_p->e_entry), 2025 EC_OFF(elf_head_p->e_phoff), 2026 field, EC_OFF(elf_head_p->e_shoff), 2027 EC_WORD(elf_head_p->e_flags), 2028 EC_WORD(elf_head_p->e_ehsize)); 2029 if (!v_flag || (elf_head_p->e_shstrndx != SHN_XINDEX)) { 2030 (void) printf("%-#*x%-11u%-#*x%-12u%u\n", 2031 field, EC_WORD(elf_head_p->e_phentsize), 2032 EC_WORD(elf_head_p->e_phnum), 2033 field, EC_WORD(elf_head_p->e_shentsize), 2034 EC_WORD(elf_head_p->e_shnum), 2035 EC_WORD(elf_head_p->e_shstrndx)); 2036 } else { 2037 (void) printf("%-#*x%-11u%-#*x%-12uXINDEX\n", 2038 field, EC_WORD(elf_head_p->e_phentsize), 2039 EC_WORD(elf_head_p->e_phnum), 2040 field, EC_WORD(elf_head_p->e_shentsize), 2041 EC_WORD(elf_head_p->e_shnum)); 2042 } 2043 if ((elf_head_p->e_shnum == 0) && (elf_head_p->e_shoff > 0)) { 2044 Elf_Scn *scn; 2045 GElf_Shdr shdr0; 2046 int field; 2047 2048 if (gelf_getclass(elf_file) == ELFCLASS64) 2049 field = 21; 2050 else 2051 field = 13; 2052 if (!p_flag) { 2053 (void) printf("\n **** SECTION HEADER[0] " 2054 "{Elf Extensions} ****\n"); 2055 (void) printf( 2056 "[No]\tType\tFlags\t%-*s %-*s%-*s%sName\n", 2057 field, "Addr", field, "Offset", field, 2058 "Size(shnum)", 2059 /* compatibility: tab for elf32 */ 2060 (field == 13) ? "\t" : " "); 2061 (void) printf("\tLn(strndx) Info\t%-*s Entsize\n", 2062 field, "Adralgn"); 2063 } 2064 if ((scn = elf_getscn(elf_file, 0)) == NULL) { 2065 (void) fprintf(stderr, 2066 "%s: %s: elf_getscn failed: %s\n", 2067 prog_name, filename, elf_errmsg(-1)); 2068 return (NULL); 2069 } 2070 if (gelf_getshdr(scn, &shdr0) == 0) { 2071 (void) fprintf(stderr, 2072 "%s: %s: gelf_getshdr: %s\n", 2073 prog_name, filename, elf_errmsg(-1)); 2074 return (NULL); 2075 } 2076 (void) printf("[0]\t%u\t%llu\t", EC_WORD(shdr0.sh_type), 2077 EC_XWORD(shdr0.sh_flags)); 2078 2079 /* 2080 * LINTED - field and EC_XWORD cause -#*llu complaints that 2081 * even this comment can't shutup. 2082 */ 2083 (void) printf("%-#*llx %-#*llx%-#*llu%s%-#*u\n", 2084 field, EC_ADDR(shdr0.sh_addr), 2085 field, EC_OFF(shdr0.sh_offset), 2086 field, EC_XWORD(shdr0.sh_size), 2087 /* compatibility: tab for elf32 */ 2088 ((field == 13) ? "\t" : " "), 2089 field, EC_WORD(shdr0.sh_name)); 2090 2091 (void) printf("\t%u\t%u\t%-#*llx %-#*llx\n", 2092 EC_WORD(shdr0.sh_link), 2093 EC_WORD(shdr0.sh_info), 2094 field, EC_XWORD(shdr0.sh_addralign), 2095 field, EC_XWORD(shdr0.sh_entsize)); 2096 } 2097 (void) printf("\n"); 2098 2099 return (elf_head_p); 2100 } 2101 2102 /* 2103 * Print section contents. Input is an ELF file descriptor, 2104 * the ELF header, the SCNTAB structure, 2105 * the number of symbols, and the filename. 2106 * The number of sections, 2107 * and the offset into the SCNTAB structure will be 2108 * set in dump_section if d_flag or n_flag are set. 2109 * If v_flag is set, sections which can be interpreted will 2110 * be interpreted, otherwise raw data will be output in hexidecimal. 2111 */ 2112 static void 2113 print_section(Elf *elf_file, 2114 GElf_Ehdr *p_ehdr, SCNTAB *p, int num_scns, char *filename) 2115 { 2116 unsigned char *p_sec; 2117 int i; 2118 size_t size; 2119 2120 for (i = 0; i < num_scns; i++, p++) { 2121 GElf_Shdr shdr; 2122 2123 size = 0; 2124 if (s_flag && !v_flag) 2125 p_sec = (unsigned char *)get_rawscn(p->p_sd, &size); 2126 else 2127 p_sec = (unsigned char *)get_scndata(p->p_sd, &size); 2128 2129 if ((gelf_getshdr(p->p_sd, &shdr) != NULL) && 2130 (shdr.sh_type == SHT_NOBITS)) { 2131 continue; 2132 } 2133 if (s_flag && !v_flag) { 2134 (void) printf("\n%s:\n", p->scn_name); 2135 print_rawdata(p_sec, size); 2136 continue; 2137 } 2138 if (shdr.sh_type == SHT_SYMTAB) { 2139 dump_symbol_table(elf_file, p, filename); 2140 continue; 2141 } 2142 if (shdr.sh_type == SHT_DYNSYM) { 2143 dump_symbol_table(elf_file, p, filename); 2144 continue; 2145 } 2146 if (shdr.sh_type == SHT_STRTAB) { 2147 dump_string_table(p, 1); 2148 continue; 2149 } 2150 if (shdr.sh_type == SHT_RELA) { 2151 dump_reloc_table(elf_file, p_ehdr, p, 1, filename); 2152 continue; 2153 } 2154 if (shdr.sh_type == SHT_REL) { 2155 dump_reloc_table(elf_file, p_ehdr, p, 1, filename); 2156 continue; 2157 } 2158 if (shdr.sh_type == SHT_DYNAMIC) { 2159 dump_dynamic(elf_file, p, 1, filename); 2160 continue; 2161 } 2162 2163 (void) printf("\n%s:\n", p->scn_name); 2164 print_rawdata(p_sec, size); 2165 } 2166 (void) printf("\n"); 2167 } 2168 2169 /* 2170 * Print section contents. This function does not print the contents 2171 * of the sections but sets up the parameters and then calls 2172 * print_section to print the contents. Calling another function to print 2173 * the contents allows both -d and -n to work correctly 2174 * simultaneously. Input is an ELF file descriptor, the ELF header, 2175 * the SCNTAB structure, the number of sections, and the filename. 2176 * Set the range of sections if d_flag, and set section name if 2177 * n_flag. 2178 */ 2179 static void 2180 dump_section(Elf *elf_file, 2181 GElf_Ehdr *p_ehdr, SCNTAB *s, int num_scns, char *filename) 2182 { 2183 SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */ 2184 int i; 2185 int found_it = 0; /* for use with -n section_name */ 2186 2187 if (n_flag) { 2188 n_range = s; 2189 2190 for (i = 0; i < num_scns; i++, n_range++) { 2191 if ((strcmp(name, n_range->scn_name)) != 0) 2192 continue; 2193 else { 2194 found_it = 1; 2195 print_section(elf_file, p_ehdr, 2196 n_range, 1, filename); 2197 } 2198 } 2199 2200 if (!found_it) { 2201 (void) fprintf(stderr, "%s: %s: %s not found\n", 2202 prog_name, filename, name); 2203 } 2204 } /* end n_flag */ 2205 2206 if (d_flag) { 2207 d_range = s; 2208 d_num = check_range(d_low, d_hi, num_scns, filename); 2209 if (d_num < 0) 2210 return; 2211 d_range += d_low - 1; 2212 2213 print_section(elf_file, p_ehdr, d_range, d_num, filename); 2214 } /* end d_flag */ 2215 2216 if (!n_flag && !d_flag) 2217 print_section(elf_file, p_ehdr, s, num_scns, filename); 2218 } 2219 2220 /* 2221 * Print the section header table. This function does not print the contents 2222 * of the section headers but sets up the parameters and then calls 2223 * print_shdr to print the contents. Calling another function to print 2224 * the contents allows both -d and -n to work correctly 2225 * simultaneously. Input is the SCNTAB structure, 2226 * the number of sections from the ELF header, and the filename. 2227 * Set the range of section headers to print if d_flag, and set 2228 * name of section header to print if n_flag. 2229 */ 2230 static void 2231 dump_shdr(Elf *elf_file, SCNTAB *s, int num_scns, char *filename) 2232 { 2233 2234 SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */ 2235 int field; 2236 int i; 2237 int found_it = 0; /* for use with -n section_name */ 2238 2239 if (gelf_getclass(elf_file) == ELFCLASS64) 2240 field = 21; 2241 else 2242 field = 13; 2243 2244 if (!p_flag) { 2245 (void) printf("\n **** SECTION HEADER TABLE ****\n"); 2246 (void) printf("[No]\tType\tFlags\t%-*s %-*s %-*s%sName\n", 2247 field, "Addr", field, "Offset", field, "Size", 2248 /* compatibility: tab for elf32 */ 2249 (field == 13) ? "\t" : " "); 2250 (void) printf("\tLink\tInfo\t%-*s Entsize\n\n", 2251 field, "Adralgn"); 2252 } 2253 2254 if (n_flag) { 2255 n_range = s; 2256 2257 for (i = 1; i <= num_scns; i++, n_range++) { 2258 if ((strcmp(name, n_range->scn_name)) != 0) 2259 continue; 2260 else { 2261 found_it = 1; 2262 print_shdr(elf_file, n_range, 1, i); 2263 } 2264 } 2265 2266 if (!found_it) { 2267 (void) fprintf(stderr, "%s: %s: %s not found\n", 2268 prog_name, filename, name); 2269 } 2270 } /* end n_flag */ 2271 2272 if (d_flag) { 2273 d_range = s; 2274 d_num = check_range(d_low, d_hi, num_scns, filename); 2275 if (d_num < 0) 2276 return; 2277 d_range += d_low - 1; 2278 2279 print_shdr(elf_file, d_range, d_num, d_low); 2280 } /* end d_flag */ 2281 2282 if (!n_flag && !d_flag) 2283 print_shdr(elf_file, s, num_scns, 1); 2284 } 2285 2286 /* 2287 * Process all of the command line options (except 2288 * for -a, -g, -f, and -o). All of the options processed 2289 * by this function require the presence of the section 2290 * header table and will not be processed if it is not present. 2291 * Set up a buffer containing section name, section header, 2292 * and section descriptor for each section in the file. This 2293 * structure is used to avoid duplicate calls to libelf functions. 2294 * Structure members for the symbol table, the debugging information, 2295 * and the line number information are global. All of the 2296 * rest are local. 2297 */ 2298 static void 2299 dump_section_table(Elf *elf_file, GElf_Ehdr *elf_head_p, char *filename) 2300 { 2301 2302 static SCNTAB *buffer, *p_scns; 2303 Elf_Scn *scn = 0; 2304 char *s_name = NULL; 2305 int found = 0; 2306 unsigned int num_scns; 2307 size_t shstrndx; 2308 size_t shnum; 2309 2310 2311 if (elf_getshnum(elf_file, &shnum) == 0) { 2312 (void) fprintf(stderr, 2313 "%s: %s: elf_getshnum failed: %s\n", 2314 prog_name, filename, elf_errmsg(-1)); 2315 return; 2316 } 2317 if (elf_getshstrndx(elf_file, &shstrndx) == 0) { 2318 (void) fprintf(stderr, 2319 "%s: %s: elf_getshstrndx failed: %s\n", 2320 prog_name, filename, elf_errmsg(-1)); 2321 return; 2322 } 2323 2324 if ((buffer = calloc(shnum, sizeof (SCNTAB))) == NULL) { 2325 (void) fprintf(stderr, "%s: %s: cannot calloc space\n", 2326 prog_name, filename); 2327 return; 2328 } 2329 /* LINTED */ 2330 num_scns = (int)shnum - 1; 2331 2332 p_symtab = (SCNTAB *)0; 2333 p_dynsym = (SCNTAB *)0; 2334 p_scns = buffer; 2335 p_head_scns = buffer; 2336 2337 while ((scn = elf_nextscn(elf_file, scn)) != 0) { 2338 if ((gelf_getshdr(scn, &buffer->p_shdr)) == 0) { 2339 (void) fprintf(stderr, 2340 "%s: %s: %s\n", prog_name, filename, elf_errmsg(-1)); 2341 return; 2342 } 2343 s_name = (char *)elf_strptr(elf_file, 2344 shstrndx, buffer->p_shdr.sh_name); 2345 buffer->scn_name = s_name ? s_name : (char *)UNKNOWN; 2346 buffer->p_sd = scn; 2347 2348 if (buffer->p_shdr.sh_type == SHT_SYMTAB) { 2349 found += 1; 2350 p_symtab = buffer; 2351 } 2352 if (buffer->p_shdr.sh_type == SHT_DYNSYM) 2353 p_dynsym = buffer; 2354 buffer++; 2355 } 2356 2357 /* 2358 * These functions depend upon the presence of the section header table 2359 * and will not be invoked in its absence 2360 */ 2361 if (h_flag) { 2362 dump_shdr(elf_file, p_scns, num_scns, filename); 2363 } 2364 if (p_symtab && (t_flag || T_flag)) { 2365 dump_symbol_table(elf_file, p_symtab, filename); 2366 } 2367 if (c_flag) { 2368 dump_string_table(p_scns, num_scns); 2369 } 2370 if (r_flag) { 2371 dump_reloc_table(elf_file, elf_head_p, 2372 p_scns, num_scns, filename); 2373 } 2374 if (L_flag) { 2375 dump_dynamic(elf_file, p_scns, num_scns, filename); 2376 } 2377 if (s_flag) { 2378 dump_section(elf_file, elf_head_p, p_scns, 2379 num_scns, filename); 2380 } 2381 } 2382 2383 /* 2384 * Load the archive string table(s) (for extended-length strings) 2385 * into an in-core table/list 2386 */ 2387 static struct stab_list_s * 2388 load_arstring_table(struct stab_list_s *STabList, 2389 int fd, Elf *elf_file, Elf_Arhdr *p_ar, char *filename) 2390 { 2391 off_t here; 2392 struct stab_list_s *STL_entry, *STL_next; 2393 2394 if (p_ar) { 2395 STL_entry = malloc(sizeof (struct stab_list_s)); 2396 STL_entry->next = 0; 2397 STL_entry->strings = 0; 2398 STL_entry->size = 0; 2399 2400 if (!STabList) 2401 STabList = STL_entry; 2402 else { 2403 STL_next = STabList; 2404 while (STL_next->next != (void *)0) 2405 STL_next = STL_next->next; 2406 STL_next->next = STL_entry; 2407 } 2408 2409 STL_entry->size = p_ar->ar_size; 2410 STL_entry->strings = malloc(p_ar->ar_size); 2411 here = elf_getbase(elf_file); 2412 if ((lseek(fd, here, 0)) != here) { 2413 (void) fprintf(stderr, 2414 "%s: %s: could not lseek\n", prog_name, filename); 2415 } 2416 2417 if ((read(fd, STL_entry->strings, p_ar->ar_size)) == -1) { 2418 (void) fprintf(stderr, 2419 "%s: %s: could not read\n", prog_name, filename); 2420 } 2421 } 2422 return (STabList); 2423 } 2424 2425 /* 2426 * Print the archive header for each member of an archive. 2427 * Also call ar_sym_read to print the symbols in the 2428 * archive symbol table if g_flag. Input is a file descriptor, 2429 * an ELF file descriptor, and the filename. Putting the call 2430 * to dump the archive symbol table in this function is more 2431 * efficient since it is necessary to examine the archive member 2432 * name in the archive header to determine which member is the 2433 * symbol table. 2434 */ 2435 static void 2436 dump_ar_hdr(int fd, Elf *elf_file, char *filename) 2437 { 2438 extern int v_flag, g_flag, a_flag, p_flag; 2439 Elf_Arhdr *p_ar; 2440 Elf *arf; 2441 Elf_Cmd cmd; 2442 int title = 0; 2443 int err = 0; 2444 2445 char buf[DATESIZE]; 2446 2447 cmd = ELF_C_READ; 2448 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) { 2449 p_ar = elf_getarhdr(arf); 2450 if (p_ar == NULL) { 2451 (void) fprintf(stderr, 2452 "%s: %s: %s\n", prog_name, filename, elf_errmsg(-1)); 2453 continue; 2454 } 2455 if (strcmp(p_ar->ar_name, "/") == 0) { 2456 if (g_flag) 2457 ar_sym_read(elf_file, filename); 2458 } else if (strcmp(p_ar->ar_name, "//") == 0) { 2459 StringTableList = load_arstring_table( 2460 StringTableList, fd, arf, p_ar, 2461 filename); 2462 cmd = elf_next(arf); 2463 (void) elf_end(arf); 2464 continue; 2465 } else { 2466 if (a_flag) { 2467 (void) printf("%s[%s]:\n", filename, 2468 p_ar->ar_name); 2469 if (!p_flag && title == 0) { 2470 if (!v_flag) 2471 (void) printf( 2472 "\n\n\t\t\t***ARCHIVE HEADER***" 2473 "\n Date Uid Gid Mode Size Member Name\n\n"); 2474 else 2475 (void) printf( 2476 "\n\n\t\t\t***ARCHIVE HEADER***" 2477 "\n Date Uid Gid Mode Size Member Name\n\n"); 2478 title = 1; 2479 } 2480 if (!v_flag) { 2481 (void) printf( 2482 "\t0x%.8lx %6d %6d 0%.6ho 0x%.8lx %-s\n\n", 2483 p_ar->ar_date, 2484 (int)p_ar->ar_uid, 2485 (int)p_ar->ar_gid, 2486 (int)p_ar->ar_mode, 2487 p_ar->ar_size, 2488 p_ar->ar_name); 2489 } else { 2490 if ((strftime(buf, DATESIZE, 2491 "%b %d %H:%M:%S %Y", 2492 localtime( 2493 &(p_ar->ar_date)))) == 0) { 2494 (void) fprintf(stderr, 2495 "%s: %s: don't have enough space to store the date\n", prog_name, filename); 2496 exit(1); 2497 } 2498 (void) printf( 2499 "\t%s %6d %6d 0%.6ho 0x%.8lx %-s\n\n", 2500 buf, 2501 (int)p_ar->ar_uid, 2502 (int)p_ar->ar_gid, 2503 (int)p_ar->ar_mode, 2504 p_ar->ar_size, 2505 p_ar->ar_name); 2506 } 2507 } 2508 } 2509 cmd = elf_next(arf); 2510 (void) elf_end(arf); 2511 } /* end while */ 2512 2513 err = elf_errno(); 2514 if (err != 0) { 2515 (void) fprintf(stderr, 2516 "%s: %s: %s\n", prog_name, filename, elf_errmsg(err)); 2517 } 2518 } 2519 2520 /* 2521 * Process member files of an archive. This function provides 2522 * a loop through an archive equivalent the processing of 2523 * each_file for individual object files. 2524 */ 2525 static void 2526 dump_ar_files(int fd, Elf *elf_file, char *filename) 2527 { 2528 Elf_Arhdr *p_ar; 2529 Elf *arf; 2530 Elf_Cmd cmd; 2531 Elf_Kind file_type; 2532 GElf_Ehdr elf_head; 2533 char *fullname; 2534 2535 cmd = ELF_C_READ; 2536 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) { 2537 size_t len; 2538 2539 p_ar = elf_getarhdr(arf); 2540 if (p_ar == NULL) { 2541 (void) fprintf(stderr, 2542 "%s: %s: %s\n", 2543 prog_name, filename, elf_errmsg(-1)); 2544 return; 2545 } 2546 if ((strcmp(p_ar->ar_name, "/") == 0) || 2547 (strcmp(p_ar->ar_name, "//") == 0)) { 2548 cmd = elf_next(arf); 2549 (void) elf_end(arf); 2550 continue; 2551 } 2552 2553 len = strlen(filename) + strlen(p_ar->ar_name) + 3; 2554 if ((fullname = malloc(len)) == NULL) 2555 return; 2556 (void) snprintf(fullname, len, "%s[%s]", filename, 2557 p_ar->ar_name); 2558 (void) printf("\n%s:\n", fullname); 2559 file_type = elf_kind(arf); 2560 if (file_type == ELF_K_ELF) { 2561 if (dump_elf_header(arf, fullname, &elf_head) == NULL) 2562 return; 2563 if (o_flag) 2564 dump_exec_header(arf, 2565 (unsigned)elf_head.e_phnum, fullname); 2566 if (x_flag) 2567 dump_section_table(arf, &elf_head, fullname); 2568 } else { 2569 (void) fprintf(stderr, 2570 "%s: %s: invalid file type\n", 2571 prog_name, fullname); 2572 cmd = elf_next(arf); 2573 (void) elf_end(arf); 2574 continue; 2575 } 2576 2577 cmd = elf_next(arf); 2578 (void) elf_end(arf); 2579 } /* end while */ 2580 } 2581 2582 /* 2583 * Takes a filename as input. Test first for a valid version 2584 * of libelf.a and exit on error. Process each valid file 2585 * or archive given as input on the command line. Check 2586 * for file type. If it is an archive, process the archive- 2587 * specific options first, then files within the archive. 2588 * If it is an ELF object file, process it; otherwise 2589 * warn that it is an invalid file type. 2590 * All options except the archive-specific and program 2591 * execution header are processed in the function, dump_section_table. 2592 */ 2593 static void 2594 each_file(char *filename) 2595 { 2596 Elf *elf_file; 2597 GElf_Ehdr elf_head; 2598 int fd; 2599 Elf_Kind file_type; 2600 2601 struct stat buf; 2602 2603 Elf_Cmd cmd; 2604 errno = 0; 2605 2606 if (stat(filename, &buf) == -1) { 2607 int err = errno; 2608 (void) fprintf(stderr, "%s: %s: %s", prog_name, filename, 2609 strerror(err)); 2610 return; 2611 } 2612 2613 if ((fd = open((filename), O_RDONLY)) == -1) { 2614 (void) fprintf(stderr, "%s: %s: cannot read\n", prog_name, 2615 filename); 2616 return; 2617 } 2618 cmd = ELF_C_READ; 2619 if ((elf_file = elf_begin(fd, cmd, (Elf *)0)) == NULL) { 2620 (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename, 2621 elf_errmsg(-1)); 2622 return; 2623 } 2624 2625 file_type = elf_kind(elf_file); 2626 if (file_type == ELF_K_AR) { 2627 if (a_flag || g_flag) { 2628 dump_ar_hdr(fd, elf_file, filename); 2629 elf_file = elf_begin(fd, cmd, (Elf *)0); 2630 } 2631 if (z_flag) 2632 dump_ar_files(fd, elf_file, filename); 2633 } else { 2634 if (file_type == ELF_K_ELF) { 2635 (void) printf("\n%s:\n", filename); 2636 if (dump_elf_header(elf_file, filename, &elf_head)) { 2637 if (o_flag) 2638 dump_exec_header(elf_file, 2639 (unsigned)elf_head.e_phnum, 2640 filename); 2641 if (x_flag) 2642 dump_section_table(elf_file, 2643 &elf_head, filename); 2644 } 2645 } else { 2646 (void) fprintf(stderr, "%s: %s: invalid file type\n", 2647 prog_name, filename); 2648 } 2649 } 2650 (void) elf_end(elf_file); 2651 (void) close(fd); 2652 } 2653 2654 /* 2655 * Sets up flags for command line options given and then 2656 * calls each_file() to process each file. 2657 */ 2658 int 2659 main(int argc, char *argv[], char *envp[]) 2660 { 2661 char *optstr = OPTSTR; /* option string used by getopt() */ 2662 int optchar; 2663 2664 /* 2665 * Check for a binary that better fits this architecture. 2666 */ 2667 conv_check_native(argv, envp); 2668 2669 prog_name = argv[0]; 2670 2671 (void) setlocale(LC_ALL, ""); 2672 while ((optchar = getopt(argc, argv, optstr)) != -1) { 2673 switch (optchar) { 2674 case 'a': 2675 a_flag = 1; 2676 x_flag = 1; 2677 break; 2678 case 'g': 2679 g_flag = 1; 2680 x_flag = 1; 2681 break; 2682 case 'v': 2683 v_flag = 1; 2684 break; 2685 case 'p': 2686 p_flag = 1; 2687 break; 2688 case 'f': 2689 f_flag = 1; 2690 z_flag = 1; 2691 break; 2692 case 'o': 2693 o_flag = 1; 2694 z_flag = 1; 2695 break; 2696 case 'h': 2697 h_flag = 1; 2698 x_flag = 1; 2699 z_flag = 1; 2700 break; 2701 case 's': 2702 s_flag = 1; 2703 x_flag = 1; 2704 z_flag = 1; 2705 break; 2706 case 'd': 2707 d_flag = 1; 2708 x_flag = 1; 2709 z_flag = 1; 2710 set_range(optarg, &d_low, &d_hi); 2711 break; 2712 case 'n': 2713 n_flag++; 2714 x_flag = 1; 2715 z_flag = 1; 2716 name = optarg; 2717 break; 2718 case 'r': 2719 r_flag = 1; 2720 x_flag = 1; 2721 z_flag = 1; 2722 break; 2723 case 't': 2724 t_flag = 1; 2725 x_flag = 1; 2726 z_flag = 1; 2727 break; 2728 case 'C': 2729 C_flag = 1; 2730 t_flag = 1; 2731 x_flag = 1; 2732 z_flag = 1; 2733 break; 2734 case 'T': 2735 T_flag = 1; 2736 x_flag = 1; 2737 z_flag = 1; 2738 set_range(optarg, &T_low, &T_hi); 2739 break; 2740 case 'c': 2741 c_flag = 1; 2742 x_flag = 1; 2743 z_flag = 1; 2744 break; 2745 case 'L': 2746 L_flag = 1; 2747 x_flag = 1; 2748 z_flag = 1; 2749 break; 2750 case 'V': 2751 V_flag = 1; 2752 (void) fprintf(stderr, "dump: %s %s\n", 2753 (const char *)SGU_PKG, 2754 (const char *)SGU_REL); 2755 break; 2756 case '?': 2757 errflag += 1; 2758 break; 2759 default: 2760 break; 2761 } 2762 } 2763 2764 if (errflag || (optind >= argc) || (!z_flag && !x_flag)) { 2765 if (!(V_flag && (argc == 2))) { 2766 usage(); 2767 exit(269); 2768 } 2769 } 2770 2771 if (elf_version(EV_CURRENT) == EV_NONE) { 2772 (void) fprintf(stderr, "%s: libelf is out of date\n", 2773 prog_name); 2774 exit(101); 2775 } 2776 2777 while (optind < argc) { 2778 each_file(argv[optind]); 2779 optind++; 2780 } 2781 return (0); 2782 } 2783