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 } 1735 if (v_flag && strlen(value)) 1736 (void) printf("%s", value); 1737 else 1738 (void) printf(Fmtptr, 1739 EC_ADDR(p_dyn.d_un.d_ptr)); 1740 break; 1741 case (DT_VERSYM): 1742 (void) printf(Fmttag, (const char *)"VERSYM"); 1743 (void) printf(Fmtptr, 1744 EC_ADDR(p_dyn.d_un.d_ptr)); 1745 break; 1746 case (DT_VERDEF): 1747 (void) printf(Fmttag, (const char *)"VERDEF"); 1748 (void) printf(Fmtptr, 1749 EC_ADDR(p_dyn.d_un.d_ptr)); 1750 break; 1751 case (DT_VERDEFNUM): 1752 (void) printf(Fmttag, 1753 (const char *)"VERDEFNUM"); 1754 (void) printf(Fmtptr, 1755 EC_XWORD(p_dyn.d_un.d_val)); 1756 break; 1757 case (DT_VERNEED): 1758 (void) printf(Fmttag, (const char *)"VERNEED"); 1759 (void) printf(Fmtptr, 1760 EC_ADDR(p_dyn.d_un.d_ptr)); 1761 break; 1762 case (DT_VERNEEDNUM): 1763 (void) printf(Fmttag, 1764 (const char *)"VERNEEDNUM"); 1765 (void) printf(Fmtptr, 1766 EC_XWORD(p_dyn.d_un.d_val)); 1767 break; 1768 case (DT_AUXILIARY): 1769 (void) printf(Fmttag, 1770 (const char *)"AUXILIARY"); 1771 if (v_flag) 1772 dt_name = (char *)elf_strptr(elf_file, 1773 link, p_dyn.d_un.d_ptr); 1774 if (dt_name == NULL) 1775 dt_name = (char *)UNKNOWN; 1776 if (v_flag && strlen(dt_name)) 1777 (void) printf("%s", dt_name); 1778 else 1779 (void) printf(Fmtptr, 1780 EC_ADDR(p_dyn.d_un.d_ptr)); 1781 break; 1782 case (DT_USED): 1783 (void) printf(Fmttag, (const char *)"USED"); 1784 if (v_flag) 1785 dt_name = (char *)elf_strptr(elf_file, 1786 link, p_dyn.d_un.d_ptr); 1787 if (dt_name == NULL) 1788 dt_name = (char *)UNKNOWN; 1789 if (v_flag && strlen(dt_name)) 1790 (void) printf("%s", dt_name); 1791 else 1792 (void) printf(Fmtptr, 1793 EC_ADDR(p_dyn.d_un.d_ptr)); 1794 break; 1795 case (DT_FILTER): 1796 (void) printf(Fmttag, (const char *)"FILTER"); 1797 if (v_flag) 1798 dt_name = (char *)elf_strptr(elf_file, 1799 link, p_dyn.d_un.d_ptr); 1800 if (dt_name == NULL) 1801 dt_name = (char *)UNKNOWN; 1802 if (v_flag && strlen(dt_name)) 1803 (void) printf("%s", dt_name); 1804 else 1805 (void) printf(Fmtptr, 1806 EC_ADDR(p_dyn.d_un.d_ptr)); 1807 break; 1808 1809 /* 1810 * SUNW: machine specific range. 1811 */ 1812 case (DT_SPARC_REGISTER): 1813 (void) printf(Fmttag, 1814 (const char *)"REGISTER"); 1815 (void) printf(Fmtptr, 1816 EC_XWORD(p_dyn.d_un.d_val)); 1817 break; 1818 case (DT_DEPRECATED_SPARC_REGISTER): 1819 (void) printf(Fmttag, 1820 (const char *)"REGISTER"); 1821 (void) printf("%#llx (deprecated value)", 1822 EC_XWORD(p_dyn.d_un.d_val)); 1823 break; 1824 default: 1825 (void) printf("%lld", EC_XWORD(p_dyn.d_tag)); 1826 break; 1827 } 1828 (void) printf("\n"); 1829 (void) gelf_getdyn(dyn_data, ii++, &p_dyn); 1830 } 1831 } 1832 1833 /* 1834 * Check for existence of static shared library information. 1835 */ 1836 (void) gelf_getehdr(elf_file, &p_ehdr); 1837 while (header_num < p_ehdr.e_phnum) { 1838 (void) gelf_getphdr(elf_file, header_num, &p_phdr); 1839 if (p_phdr.p_type == PT_SHLIB) { 1840 while (--lib_scns > 0) { 1841 if (strcmp(l_scns->scn_name, ".lib") == 0) { 1842 print_static(l_scns, filename); 1843 } 1844 l_scns++; 1845 } 1846 } 1847 header_num++; 1848 } 1849 } 1850 1851 /* 1852 * Print the ELF header. Input is an ELF file descriptor 1853 * and the filename. If f_flag is set, the ELF header is 1854 * printed to stdout, otherwise the function returns after 1855 * setting the pointer to the ELF header. Any values which 1856 * are not known are printed in decimal. Fields must be updated 1857 * as new values are added. 1858 */ 1859 static GElf_Ehdr * 1860 dump_elf_header(Elf *elf_file, char *filename, GElf_Ehdr * elf_head_p) 1861 { 1862 int class, data; 1863 int field; 1864 1865 if (gelf_getehdr(elf_file, elf_head_p) == NULL) { 1866 (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename, 1867 elf_errmsg(-1)); 1868 return (NULL); 1869 } 1870 1871 class = (int)elf_head_p->e_ident[4]; 1872 1873 if (class == ELFCLASS64) 1874 field = 21; 1875 else 1876 field = 13; 1877 1878 if (!f_flag) 1879 return (elf_head_p); 1880 1881 if (!p_flag) { 1882 (void) printf("\n **** ELF HEADER ****\n"); 1883 (void) printf("%-*s%-11s%-*sMachine Version\n", 1884 field, "Class", "Data", field, "Type"); 1885 (void) printf("%-*s%-11s%-*sFlags Ehsize\n", 1886 field, "Entry", "Phoff", field, "Shoff"); 1887 (void) printf("%-*s%-11s%-*sShnum Shstrndx\n\n", 1888 field, "Phentsize", "Phnum", field, "Shentsz"); 1889 } 1890 1891 if (!v_flag) { 1892 (void) printf("%-*d%-11d%-*d%-12d%d\n", 1893 field, elf_head_p->e_ident[4], 1894 elf_head_p->e_ident[5], 1895 field, (int)elf_head_p->e_type, 1896 (int)elf_head_p->e_machine, 1897 elf_head_p->e_version); 1898 } else { 1899 data = elf_head_p->e_ident[5]; 1900 1901 switch (class) { 1902 case ELFCLASSNONE: 1903 (void) printf("%-*s", field, "None"); 1904 break; 1905 case ELFCLASS32: 1906 (void) printf("%-*s", field, "32-bit"); 1907 break; 1908 case ELFCLASS64: 1909 (void) printf("%-*s", field, "64-bit"); 1910 break; 1911 default: 1912 (void) printf("%-*d", field, class); 1913 break; 1914 } 1915 switch (data) { 1916 case ELFDATANONE: 1917 (void) printf("%-11s", "None "); 1918 break; 1919 case ELFDATA2LSB: 1920 (void) printf("%-11s", "2LSB "); 1921 break; 1922 case ELFDATA2MSB: 1923 (void) printf("%-11s", "2MSB "); 1924 break; 1925 default: 1926 (void) printf("%-11d", data); 1927 break; 1928 } 1929 1930 switch (elf_head_p->e_type) { 1931 case ET_NONE: 1932 (void) printf("%-*s", field, "None"); 1933 break; 1934 case ET_REL: 1935 (void) printf("%-*s", field, "Reloc"); 1936 break; 1937 case ET_EXEC: 1938 (void) printf("%-*s", field, "Exec"); 1939 break; 1940 case ET_DYN: 1941 (void) printf("%-*s", field, "Dyn"); 1942 break; 1943 case ET_CORE: 1944 (void) printf("%-*s", field, "Core"); 1945 break; 1946 default: 1947 (void) printf("%-*d", field, 1948 EC_WORD(elf_head_p->e_type)); 1949 break; 1950 } 1951 switch (elf_head_p->e_machine) { 1952 case EM_NONE: 1953 (void) printf("%-12s", "No mach"); 1954 break; 1955 case EM_M32: 1956 (void) printf("%-12s", "WE32100"); 1957 break; 1958 case EM_SPARC: 1959 (void) printf("%-12s", "SPARC"); 1960 break; 1961 case EM_SPARCV9: 1962 (void) printf("%-12s", "SPARCV9"); 1963 break; 1964 case EM_386: 1965 (void) printf("%-12s", "80386"); 1966 break; 1967 case EM_68K: 1968 (void) printf("%-12s", "68000"); 1969 break; 1970 case EM_88K: 1971 (void) printf("%-12s", "88000"); 1972 break; 1973 case EM_486: 1974 (void) printf("%-12s", "80486"); 1975 break; 1976 case EM_860: 1977 (void) printf("%-12s", "i860"); 1978 break; 1979 case EM_MIPS: 1980 (void) printf("%-12s", "RS3000_BE"); 1981 break; 1982 case EM_MIPS_RS3_LE: 1983 (void) printf("%-12s", "RS3000_LE"); 1984 break; 1985 case EM_RS6000: 1986 (void) printf("%-12s", "RS6000"); 1987 break; 1988 case EM_PA_RISC: 1989 (void) printf("%-12s", "PA_RISC"); 1990 break; 1991 case EM_nCUBE: 1992 (void) printf("%-12s", "nCUBE"); 1993 break; 1994 case EM_VPP500: 1995 (void) printf("%-12s", "VPP500"); 1996 break; 1997 case EM_SPARC32PLUS: 1998 (void) printf("%-12s", "SPARC32PLUS"); 1999 break; 2000 case EM_PPC: 2001 (void) printf("%-12s", "PowerPC"); 2002 break; 2003 case EM_IA_64: 2004 (void) printf("%-12s", "IA64"); 2005 break; 2006 default: 2007 (void) printf("%-12d", EC_WORD(elf_head_p->e_machine)); 2008 } 2009 switch (elf_head_p->e_version) { 2010 case EV_NONE: 2011 (void) printf("Invalid\n"); 2012 break; 2013 case EV_CURRENT: 2014 (void) printf("Current\n"); 2015 break; 2016 default: 2017 (void) printf("%d\n", elf_head_p->e_version); 2018 } 2019 } 2020 (void) printf("%-#*llx%-#11llx%-#*llx%-#12x%#x\n", 2021 field, EC_ADDR(elf_head_p->e_entry), 2022 EC_OFF(elf_head_p->e_phoff), 2023 field, EC_OFF(elf_head_p->e_shoff), 2024 EC_WORD(elf_head_p->e_flags), 2025 EC_WORD(elf_head_p->e_ehsize)); 2026 if (!v_flag || (elf_head_p->e_shstrndx != SHN_XINDEX)) { 2027 (void) printf("%-#*x%-11u%-#*x%-12u%u\n", 2028 field, EC_WORD(elf_head_p->e_phentsize), 2029 EC_WORD(elf_head_p->e_phnum), 2030 field, EC_WORD(elf_head_p->e_shentsize), 2031 EC_WORD(elf_head_p->e_shnum), 2032 EC_WORD(elf_head_p->e_shstrndx)); 2033 } else { 2034 (void) printf("%-#*x%-11u%-#*x%-12uXINDEX\n", 2035 field, EC_WORD(elf_head_p->e_phentsize), 2036 EC_WORD(elf_head_p->e_phnum), 2037 field, EC_WORD(elf_head_p->e_shentsize), 2038 EC_WORD(elf_head_p->e_shnum)); 2039 } 2040 if ((elf_head_p->e_shnum == 0) && (elf_head_p->e_shoff > 0)) { 2041 Elf_Scn *scn; 2042 GElf_Shdr shdr0; 2043 int field; 2044 2045 if (gelf_getclass(elf_file) == ELFCLASS64) 2046 field = 21; 2047 else 2048 field = 13; 2049 if (!p_flag) { 2050 (void) printf("\n **** SECTION HEADER[0] " 2051 "{Elf Extensions} ****\n"); 2052 (void) printf( 2053 "[No]\tType\tFlags\t%-*s %-*s%-*s%sName\n", 2054 field, "Addr", field, "Offset", field, 2055 "Size(shnum)", 2056 /* compatibility: tab for elf32 */ 2057 (field == 13) ? "\t" : " "); 2058 (void) printf("\tLn(strndx) Info\t%-*s Entsize\n", 2059 field, "Adralgn"); 2060 } 2061 if ((scn = elf_getscn(elf_file, 0)) == NULL) { 2062 (void) fprintf(stderr, 2063 "%s: %s: elf_getscn failed: %s\n", 2064 prog_name, filename, elf_errmsg(-1)); 2065 return (NULL); 2066 } 2067 if (gelf_getshdr(scn, &shdr0) == 0) { 2068 (void) fprintf(stderr, 2069 "%s: %s: gelf_getshdr: %s\n", 2070 prog_name, filename, elf_errmsg(-1)); 2071 return (NULL); 2072 } 2073 (void) printf("[0]\t%u\t%llu\t", EC_WORD(shdr0.sh_type), 2074 EC_XWORD(shdr0.sh_flags)); 2075 2076 /* 2077 * LINTED - field and EC_XWORD cause -#*llu complaints that 2078 * even this comment can't shutup. 2079 */ 2080 (void) printf("%-#*llx %-#*llx%-#*llu%s%-#*u\n", 2081 field, EC_ADDR(shdr0.sh_addr), 2082 field, EC_OFF(shdr0.sh_offset), 2083 field, EC_XWORD(shdr0.sh_size), 2084 /* compatibility: tab for elf32 */ 2085 ((field == 13) ? "\t" : " "), 2086 field, EC_WORD(shdr0.sh_name)); 2087 2088 (void) printf("\t%u\t%u\t%-#*llx %-#*llx\n", 2089 EC_WORD(shdr0.sh_link), 2090 EC_WORD(shdr0.sh_info), 2091 field, EC_XWORD(shdr0.sh_addralign), 2092 field, EC_XWORD(shdr0.sh_entsize)); 2093 } 2094 (void) printf("\n"); 2095 2096 return (elf_head_p); 2097 } 2098 2099 /* 2100 * Print section contents. Input is an ELF file descriptor, 2101 * the ELF header, the SCNTAB structure, 2102 * the number of symbols, and the filename. 2103 * The number of sections, 2104 * and the offset into the SCNTAB structure will be 2105 * set in dump_section if d_flag or n_flag are set. 2106 * If v_flag is set, sections which can be interpreted will 2107 * be interpreted, otherwise raw data will be output in hexidecimal. 2108 */ 2109 static void 2110 print_section(Elf *elf_file, 2111 GElf_Ehdr *p_ehdr, SCNTAB *p, int num_scns, char *filename) 2112 { 2113 unsigned char *p_sec; 2114 int i; 2115 size_t size; 2116 2117 for (i = 0; i < num_scns; i++, p++) { 2118 GElf_Shdr shdr; 2119 2120 size = 0; 2121 if (s_flag && !v_flag) 2122 p_sec = (unsigned char *)get_rawscn(p->p_sd, &size); 2123 else 2124 p_sec = (unsigned char *)get_scndata(p->p_sd, &size); 2125 2126 if ((gelf_getshdr(p->p_sd, &shdr) != NULL) && 2127 (shdr.sh_type == SHT_NOBITS)) { 2128 continue; 2129 } 2130 if (s_flag && !v_flag) { 2131 (void) printf("\n%s:\n", p->scn_name); 2132 print_rawdata(p_sec, size); 2133 continue; 2134 } 2135 if (shdr.sh_type == SHT_SYMTAB) { 2136 dump_symbol_table(elf_file, p, filename); 2137 continue; 2138 } 2139 if (shdr.sh_type == SHT_DYNSYM) { 2140 dump_symbol_table(elf_file, p, filename); 2141 continue; 2142 } 2143 if (shdr.sh_type == SHT_STRTAB) { 2144 dump_string_table(p, 1); 2145 continue; 2146 } 2147 if (shdr.sh_type == SHT_RELA) { 2148 dump_reloc_table(elf_file, p_ehdr, p, 1, filename); 2149 continue; 2150 } 2151 if (shdr.sh_type == SHT_REL) { 2152 dump_reloc_table(elf_file, p_ehdr, p, 1, filename); 2153 continue; 2154 } 2155 if (shdr.sh_type == SHT_DYNAMIC) { 2156 dump_dynamic(elf_file, p, 1, filename); 2157 continue; 2158 } 2159 2160 (void) printf("\n%s:\n", p->scn_name); 2161 print_rawdata(p_sec, size); 2162 } 2163 (void) printf("\n"); 2164 } 2165 2166 /* 2167 * Print section contents. This function does not print the contents 2168 * of the sections but sets up the parameters and then calls 2169 * print_section to print the contents. Calling another function to print 2170 * the contents allows both -d and -n to work correctly 2171 * simultaneously. Input is an ELF file descriptor, the ELF header, 2172 * the SCNTAB structure, the number of sections, and the filename. 2173 * Set the range of sections if d_flag, and set section name if 2174 * n_flag. 2175 */ 2176 static void 2177 dump_section(Elf *elf_file, 2178 GElf_Ehdr *p_ehdr, SCNTAB *s, int num_scns, char *filename) 2179 { 2180 SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */ 2181 int i; 2182 int found_it = 0; /* for use with -n section_name */ 2183 2184 if (n_flag) { 2185 n_range = s; 2186 2187 for (i = 0; i < num_scns; i++, n_range++) { 2188 if ((strcmp(name, n_range->scn_name)) != 0) 2189 continue; 2190 else { 2191 found_it = 1; 2192 print_section(elf_file, p_ehdr, 2193 n_range, 1, filename); 2194 } 2195 } 2196 2197 if (!found_it) { 2198 (void) fprintf(stderr, "%s: %s: %s not found\n", 2199 prog_name, filename, name); 2200 } 2201 } /* end n_flag */ 2202 2203 if (d_flag) { 2204 d_range = s; 2205 d_num = check_range(d_low, d_hi, num_scns, filename); 2206 if (d_num < 0) 2207 return; 2208 d_range += d_low - 1; 2209 2210 print_section(elf_file, p_ehdr, d_range, d_num, filename); 2211 } /* end d_flag */ 2212 2213 if (!n_flag && !d_flag) 2214 print_section(elf_file, p_ehdr, s, num_scns, filename); 2215 } 2216 2217 /* 2218 * Print the section header table. This function does not print the contents 2219 * of the section headers but sets up the parameters and then calls 2220 * print_shdr to print the contents. Calling another function to print 2221 * the contents allows both -d and -n to work correctly 2222 * simultaneously. Input is the SCNTAB structure, 2223 * the number of sections from the ELF header, and the filename. 2224 * Set the range of section headers to print if d_flag, and set 2225 * name of section header to print if n_flag. 2226 */ 2227 static void 2228 dump_shdr(Elf *elf_file, SCNTAB *s, int num_scns, char *filename) 2229 { 2230 2231 SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */ 2232 int field; 2233 int i; 2234 int found_it = 0; /* for use with -n section_name */ 2235 2236 if (gelf_getclass(elf_file) == ELFCLASS64) 2237 field = 21; 2238 else 2239 field = 13; 2240 2241 if (!p_flag) { 2242 (void) printf("\n **** SECTION HEADER TABLE ****\n"); 2243 (void) printf("[No]\tType\tFlags\t%-*s %-*s %-*s%sName\n", 2244 field, "Addr", field, "Offset", field, "Size", 2245 /* compatibility: tab for elf32 */ 2246 (field == 13) ? "\t" : " "); 2247 (void) printf("\tLink\tInfo\t%-*s Entsize\n\n", 2248 field, "Adralgn"); 2249 } 2250 2251 if (n_flag) { 2252 n_range = s; 2253 2254 for (i = 1; i <= num_scns; i++, n_range++) { 2255 if ((strcmp(name, n_range->scn_name)) != 0) 2256 continue; 2257 else { 2258 found_it = 1; 2259 print_shdr(elf_file, n_range, 1, i); 2260 } 2261 } 2262 2263 if (!found_it) { 2264 (void) fprintf(stderr, "%s: %s: %s not found\n", 2265 prog_name, filename, name); 2266 } 2267 } /* end n_flag */ 2268 2269 if (d_flag) { 2270 d_range = s; 2271 d_num = check_range(d_low, d_hi, num_scns, filename); 2272 if (d_num < 0) 2273 return; 2274 d_range += d_low - 1; 2275 2276 print_shdr(elf_file, d_range, d_num, d_low); 2277 } /* end d_flag */ 2278 2279 if (!n_flag && !d_flag) 2280 print_shdr(elf_file, s, num_scns, 1); 2281 } 2282 2283 /* 2284 * Process all of the command line options (except 2285 * for -a, -g, -f, and -o). All of the options processed 2286 * by this function require the presence of the section 2287 * header table and will not be processed if it is not present. 2288 * Set up a buffer containing section name, section header, 2289 * and section descriptor for each section in the file. This 2290 * structure is used to avoid duplicate calls to libelf functions. 2291 * Structure members for the symbol table, the debugging information, 2292 * and the line number information are global. All of the 2293 * rest are local. 2294 */ 2295 static void 2296 dump_section_table(Elf *elf_file, GElf_Ehdr *elf_head_p, char *filename) 2297 { 2298 2299 static SCNTAB *buffer, *p_scns; 2300 Elf_Scn *scn = 0; 2301 char *s_name = NULL; 2302 int found = 0; 2303 unsigned int num_scns; 2304 size_t shstrndx; 2305 size_t shnum; 2306 2307 2308 if (elf_getshnum(elf_file, &shnum) == 0) { 2309 (void) fprintf(stderr, 2310 "%s: %s: elf_getshnum failed: %s\n", 2311 prog_name, filename, elf_errmsg(-1)); 2312 return; 2313 } 2314 if (elf_getshstrndx(elf_file, &shstrndx) == 0) { 2315 (void) fprintf(stderr, 2316 "%s: %s: elf_getshstrndx failed: %s\n", 2317 prog_name, filename, elf_errmsg(-1)); 2318 return; 2319 } 2320 2321 if ((buffer = calloc(shnum, sizeof (SCNTAB))) == NULL) { 2322 (void) fprintf(stderr, "%s: %s: cannot calloc space\n", 2323 prog_name, filename); 2324 return; 2325 } 2326 /* LINTED */ 2327 num_scns = (int)shnum - 1; 2328 2329 p_symtab = (SCNTAB *)0; 2330 p_dynsym = (SCNTAB *)0; 2331 p_scns = buffer; 2332 p_head_scns = buffer; 2333 2334 while ((scn = elf_nextscn(elf_file, scn)) != 0) { 2335 if ((gelf_getshdr(scn, &buffer->p_shdr)) == 0) { 2336 (void) fprintf(stderr, 2337 "%s: %s: %s\n", prog_name, filename, elf_errmsg(-1)); 2338 return; 2339 } 2340 s_name = (char *)elf_strptr(elf_file, 2341 shstrndx, buffer->p_shdr.sh_name); 2342 buffer->scn_name = s_name ? s_name : (char *)UNKNOWN; 2343 buffer->p_sd = scn; 2344 2345 if (buffer->p_shdr.sh_type == SHT_SYMTAB) { 2346 found += 1; 2347 p_symtab = buffer; 2348 } 2349 if (buffer->p_shdr.sh_type == SHT_DYNSYM) 2350 p_dynsym = buffer; 2351 buffer++; 2352 } 2353 2354 /* 2355 * These functions depend upon the presence of the section header table 2356 * and will not be invoked in its absence 2357 */ 2358 if (h_flag) { 2359 dump_shdr(elf_file, p_scns, num_scns, filename); 2360 } 2361 if (p_symtab && (t_flag || T_flag)) { 2362 dump_symbol_table(elf_file, p_symtab, filename); 2363 } 2364 if (c_flag) { 2365 dump_string_table(p_scns, num_scns); 2366 } 2367 if (r_flag) { 2368 dump_reloc_table(elf_file, elf_head_p, 2369 p_scns, num_scns, filename); 2370 } 2371 if (L_flag) { 2372 dump_dynamic(elf_file, p_scns, num_scns, filename); 2373 } 2374 if (s_flag) { 2375 dump_section(elf_file, elf_head_p, p_scns, 2376 num_scns, filename); 2377 } 2378 } 2379 2380 /* 2381 * Load the archive string table(s) (for extended-length strings) 2382 * into an in-core table/list 2383 */ 2384 static struct stab_list_s * 2385 load_arstring_table(struct stab_list_s *STabList, 2386 int fd, Elf *elf_file, Elf_Arhdr *p_ar, char *filename) 2387 { 2388 off_t here; 2389 struct stab_list_s *STL_entry, *STL_next; 2390 2391 if (p_ar) { 2392 STL_entry = malloc(sizeof (struct stab_list_s)); 2393 STL_entry->next = 0; 2394 STL_entry->strings = 0; 2395 STL_entry->size = 0; 2396 2397 if (!STabList) 2398 STabList = STL_entry; 2399 else { 2400 STL_next = STabList; 2401 while (STL_next->next != (void *)0) 2402 STL_next = STL_next->next; 2403 STL_next->next = STL_entry; 2404 } 2405 2406 STL_entry->size = p_ar->ar_size; 2407 STL_entry->strings = malloc(p_ar->ar_size); 2408 here = elf_getbase(elf_file); 2409 if ((lseek(fd, here, 0)) != here) { 2410 (void) fprintf(stderr, 2411 "%s: %s: could not lseek\n", prog_name, filename); 2412 } 2413 2414 if ((read(fd, STL_entry->strings, p_ar->ar_size)) == -1) { 2415 (void) fprintf(stderr, 2416 "%s: %s: could not read\n", prog_name, filename); 2417 } 2418 } 2419 return (STabList); 2420 } 2421 2422 /* 2423 * Print the archive header for each member of an archive. 2424 * Also call ar_sym_read to print the symbols in the 2425 * archive symbol table if g_flag. Input is a file descriptor, 2426 * an ELF file descriptor, and the filename. Putting the call 2427 * to dump the archive symbol table in this function is more 2428 * efficient since it is necessary to examine the archive member 2429 * name in the archive header to determine which member is the 2430 * symbol table. 2431 */ 2432 static void 2433 dump_ar_hdr(int fd, Elf *elf_file, char *filename) 2434 { 2435 extern int v_flag, g_flag, a_flag, p_flag; 2436 Elf_Arhdr *p_ar; 2437 Elf *arf; 2438 Elf_Cmd cmd; 2439 int title = 0; 2440 int err = 0; 2441 2442 char buf[DATESIZE]; 2443 2444 cmd = ELF_C_READ; 2445 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) { 2446 p_ar = elf_getarhdr(arf); 2447 if (p_ar == NULL) { 2448 (void) fprintf(stderr, 2449 "%s: %s: %s\n", prog_name, filename, elf_errmsg(-1)); 2450 continue; 2451 } 2452 if (strcmp(p_ar->ar_name, "/") == 0) { 2453 if (g_flag) 2454 ar_sym_read(elf_file, filename); 2455 } else if (strcmp(p_ar->ar_name, "//") == 0) { 2456 StringTableList = load_arstring_table( 2457 StringTableList, fd, arf, p_ar, 2458 filename); 2459 cmd = elf_next(arf); 2460 (void) elf_end(arf); 2461 continue; 2462 } else { 2463 if (a_flag) { 2464 (void) printf("%s[%s]:\n", filename, 2465 p_ar->ar_name); 2466 if (!p_flag && title == 0) { 2467 if (!v_flag) 2468 (void) printf( 2469 "\n\n\t\t\t***ARCHIVE HEADER***" 2470 "\n Date Uid Gid Mode Size Member Name\n\n"); 2471 else 2472 (void) printf( 2473 "\n\n\t\t\t***ARCHIVE HEADER***" 2474 "\n Date Uid Gid Mode Size Member Name\n\n"); 2475 title = 1; 2476 } 2477 if (!v_flag) { 2478 (void) printf( 2479 "\t0x%.8lx %6d %6d 0%.6ho 0x%.8lx %-s\n\n", 2480 p_ar->ar_date, 2481 (int)p_ar->ar_uid, 2482 (int)p_ar->ar_gid, 2483 (int)p_ar->ar_mode, 2484 p_ar->ar_size, 2485 p_ar->ar_name); 2486 } else { 2487 if ((strftime(buf, DATESIZE, 2488 "%b %d %H:%M:%S %Y", 2489 localtime( 2490 &(p_ar->ar_date)))) == 0) { 2491 (void) fprintf(stderr, 2492 "%s: %s: don't have enough space to store the date\n", prog_name, filename); 2493 exit(1); 2494 } 2495 (void) printf( 2496 "\t%s %6d %6d 0%.6ho 0x%.8lx %-s\n\n", 2497 buf, 2498 (int)p_ar->ar_uid, 2499 (int)p_ar->ar_gid, 2500 (int)p_ar->ar_mode, 2501 p_ar->ar_size, 2502 p_ar->ar_name); 2503 } 2504 } 2505 } 2506 cmd = elf_next(arf); 2507 (void) elf_end(arf); 2508 } /* end while */ 2509 2510 err = elf_errno(); 2511 if (err != 0) { 2512 (void) fprintf(stderr, 2513 "%s: %s: %s\n", prog_name, filename, elf_errmsg(err)); 2514 } 2515 } 2516 2517 /* 2518 * Process member files of an archive. This function provides 2519 * a loop through an archive equivalent the processing of 2520 * each_file for individual object files. 2521 */ 2522 static void 2523 dump_ar_files(int fd, Elf *elf_file, char *filename) 2524 { 2525 Elf_Arhdr *p_ar; 2526 Elf *arf; 2527 Elf_Cmd cmd; 2528 Elf_Kind file_type; 2529 GElf_Ehdr elf_head; 2530 char *fullname; 2531 2532 cmd = ELF_C_READ; 2533 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) { 2534 size_t len; 2535 2536 p_ar = elf_getarhdr(arf); 2537 if (p_ar == NULL) { 2538 (void) fprintf(stderr, 2539 "%s: %s: %s\n", 2540 prog_name, filename, elf_errmsg(-1)); 2541 return; 2542 } 2543 if ((strcmp(p_ar->ar_name, "/") == 0) || 2544 (strcmp(p_ar->ar_name, "//") == 0)) { 2545 cmd = elf_next(arf); 2546 (void) elf_end(arf); 2547 continue; 2548 } 2549 2550 len = strlen(filename) + strlen(p_ar->ar_name) + 3; 2551 if ((fullname = malloc(len)) == NULL) 2552 return; 2553 (void) snprintf(fullname, len, "%s[%s]", filename, 2554 p_ar->ar_name); 2555 (void) printf("\n%s:\n", fullname); 2556 file_type = elf_kind(arf); 2557 if (file_type == ELF_K_ELF) { 2558 if (dump_elf_header(arf, fullname, &elf_head) == NULL) 2559 return; 2560 if (o_flag) 2561 dump_exec_header(arf, 2562 (unsigned)elf_head.e_phnum, fullname); 2563 if (x_flag) 2564 dump_section_table(arf, &elf_head, fullname); 2565 } else { 2566 (void) fprintf(stderr, 2567 "%s: %s: invalid file type\n", 2568 prog_name, fullname); 2569 cmd = elf_next(arf); 2570 (void) elf_end(arf); 2571 continue; 2572 } 2573 2574 cmd = elf_next(arf); 2575 (void) elf_end(arf); 2576 } /* end while */ 2577 } 2578 2579 /* 2580 * Takes a filename as input. Test first for a valid version 2581 * of libelf.a and exit on error. Process each valid file 2582 * or archive given as input on the command line. Check 2583 * for file type. If it is an archive, process the archive- 2584 * specific options first, then files within the archive. 2585 * If it is an ELF object file, process it; otherwise 2586 * warn that it is an invalid file type. 2587 * All options except the archive-specific and program 2588 * execution header are processed in the function, dump_section_table. 2589 */ 2590 static void 2591 each_file(char *filename) 2592 { 2593 Elf *elf_file; 2594 GElf_Ehdr elf_head; 2595 int fd; 2596 Elf_Kind file_type; 2597 2598 struct stat buf; 2599 2600 Elf_Cmd cmd; 2601 errno = 0; 2602 2603 if (stat(filename, &buf) == -1) { 2604 int err = errno; 2605 (void) fprintf(stderr, "%s: %s: %s", prog_name, filename, 2606 strerror(err)); 2607 return; 2608 } 2609 2610 if ((fd = open((filename), O_RDONLY)) == -1) { 2611 (void) fprintf(stderr, "%s: %s: cannot read\n", prog_name, 2612 filename); 2613 return; 2614 } 2615 cmd = ELF_C_READ; 2616 if ((elf_file = elf_begin(fd, cmd, (Elf *)0)) == NULL) { 2617 (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename, 2618 elf_errmsg(-1)); 2619 return; 2620 } 2621 2622 file_type = elf_kind(elf_file); 2623 if (file_type == ELF_K_AR) { 2624 if (a_flag || g_flag) { 2625 dump_ar_hdr(fd, elf_file, filename); 2626 elf_file = elf_begin(fd, cmd, (Elf *)0); 2627 } 2628 if (z_flag) 2629 dump_ar_files(fd, elf_file, filename); 2630 } else { 2631 if (file_type == ELF_K_ELF) { 2632 (void) printf("\n%s:\n", filename); 2633 if (dump_elf_header(elf_file, filename, &elf_head)) { 2634 if (o_flag) 2635 dump_exec_header(elf_file, 2636 (unsigned)elf_head.e_phnum, 2637 filename); 2638 if (x_flag) 2639 dump_section_table(elf_file, 2640 &elf_head, filename); 2641 } 2642 } else { 2643 (void) fprintf(stderr, "%s: %s: invalid file type\n", 2644 prog_name, filename); 2645 } 2646 } 2647 (void) elf_end(elf_file); 2648 (void) close(fd); 2649 } 2650 2651 /* 2652 * Sets up flags for command line options given and then 2653 * calls each_file() to process each file. 2654 */ 2655 int 2656 main(int argc, char *argv[], char *envp[]) 2657 { 2658 char *optstr = OPTSTR; /* option string used by getopt() */ 2659 int optchar; 2660 2661 /* 2662 * Check for a binary that better fits this architecture. 2663 */ 2664 conv_check_native(argv, envp); 2665 2666 prog_name = argv[0]; 2667 2668 (void) setlocale(LC_ALL, ""); 2669 while ((optchar = getopt(argc, argv, optstr)) != -1) { 2670 switch (optchar) { 2671 case 'a': 2672 a_flag = 1; 2673 x_flag = 1; 2674 break; 2675 case 'g': 2676 g_flag = 1; 2677 x_flag = 1; 2678 break; 2679 case 'v': 2680 v_flag = 1; 2681 break; 2682 case 'p': 2683 p_flag = 1; 2684 break; 2685 case 'f': 2686 f_flag = 1; 2687 z_flag = 1; 2688 break; 2689 case 'o': 2690 o_flag = 1; 2691 z_flag = 1; 2692 break; 2693 case 'h': 2694 h_flag = 1; 2695 x_flag = 1; 2696 z_flag = 1; 2697 break; 2698 case 's': 2699 s_flag = 1; 2700 x_flag = 1; 2701 z_flag = 1; 2702 break; 2703 case 'd': 2704 d_flag = 1; 2705 x_flag = 1; 2706 z_flag = 1; 2707 set_range(optarg, &d_low, &d_hi); 2708 break; 2709 case 'n': 2710 n_flag++; 2711 x_flag = 1; 2712 z_flag = 1; 2713 name = optarg; 2714 break; 2715 case 'r': 2716 r_flag = 1; 2717 x_flag = 1; 2718 z_flag = 1; 2719 break; 2720 case 't': 2721 t_flag = 1; 2722 x_flag = 1; 2723 z_flag = 1; 2724 break; 2725 case 'C': 2726 C_flag = 1; 2727 t_flag = 1; 2728 x_flag = 1; 2729 z_flag = 1; 2730 break; 2731 case 'T': 2732 T_flag = 1; 2733 x_flag = 1; 2734 z_flag = 1; 2735 set_range(optarg, &T_low, &T_hi); 2736 break; 2737 case 'c': 2738 c_flag = 1; 2739 x_flag = 1; 2740 z_flag = 1; 2741 break; 2742 case 'L': 2743 L_flag = 1; 2744 x_flag = 1; 2745 z_flag = 1; 2746 break; 2747 case 'V': 2748 V_flag = 1; 2749 (void) fprintf(stderr, "dump: %s %s\n", 2750 (const char *)SGU_PKG, 2751 (const char *)SGU_REL); 2752 break; 2753 case '?': 2754 errflag += 1; 2755 break; 2756 default: 2757 break; 2758 } 2759 } 2760 2761 if (errflag || (optind >= argc) || (!z_flag && !x_flag)) { 2762 if (!(V_flag && (argc == 2))) { 2763 usage(); 2764 exit(269); 2765 } 2766 } 2767 2768 if (elf_version(EV_CURRENT) == EV_NONE) { 2769 (void) fprintf(stderr, "%s: libelf is out of date\n", 2770 prog_name); 2771 exit(101); 2772 } 2773 2774 while (optind < argc) { 2775 each_file(argv[optind]); 2776 optind++; 2777 } 2778 return (0); 2779 } 2780