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