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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Dump an elf file. 29 */ 30 #include <sys/param.h> 31 #include <fcntl.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <ctype.h> 35 #include <libelf.h> 36 #include <link.h> 37 #include <stdarg.h> 38 #include <unistd.h> 39 #include <libgen.h> 40 #include <libintl.h> 41 #include <locale.h> 42 #include <errno.h> 43 #include <strings.h> 44 #include <debug.h> 45 #include <conv.h> 46 #include <msg.h> 47 #include <_elfdump.h> 48 #include <sys/elf_SPARC.h> 49 #include <sys/elf_amd64.h> 50 51 52 const Cache cache_init = {NULL, NULL, NULL, NULL, 0}; 53 54 55 56 /* 57 * The -I, -N, and -T options are called "match options", because 58 * they allow selecting the items to be displayed based on matching 59 * their index, name, or type. 60 * 61 * The ELF information to which -I, -N, or -T are applied in 62 * the current invocation is called the "match item". 63 */ 64 typedef enum { 65 MATCH_ITEM_PT, /* Program header (PT_) */ 66 MATCH_ITEM_SHT /* Section header (SHT_) */ 67 } match_item_t; 68 69 /* match_opt_t is used to note which match option was used */ 70 typedef enum { 71 MATCH_OPT_NAME, /* Record contains a name */ 72 MATCH_OPT_NDX, /* Record contains a single index */ 73 MATCH_OPT_RANGE, /* Record contains an index range */ 74 MATCH_OPT_TYPE, /* Record contains a type (shdr or phdr) */ 75 } match_opt_t; 76 77 typedef struct _match { 78 struct _match *next; /* Pointer to next item in list */ 79 match_opt_t opt_type; 80 union { 81 const char *name; /* MATCH_OPT_NAME */ 82 struct { /* MATCH_OPT_NDX and MATCH_OPT_RANGE */ 83 int start; 84 int end; /* Only for MATCH_OPT_RANGE */ 85 } ndx; 86 uint32_t type; /* MATCH_OPT_TYPE */ 87 } value; 88 } match_rec_t; 89 90 static struct { 91 match_item_t item_type; /* Type of item being matched */ 92 match_rec_t *list; /* Records for (-I, -N, -T) options */ 93 } match_state; 94 95 96 97 const char * 98 _elfdump_msg(Msg mid) 99 { 100 return (gettext(MSG_ORIG(mid))); 101 } 102 103 /* 104 * Determine whether a symbol name should be demangled. 105 */ 106 const char * 107 demangle(const char *name, uint_t flags) 108 { 109 if (flags & FLG_CTL_DEMANGLE) 110 return (Elf_demangle_name(name)); 111 else 112 return ((char *)name); 113 } 114 115 /* 116 * Define our own standard error routine. 117 */ 118 void 119 failure(const char *file, const char *func) 120 { 121 (void) fprintf(stderr, MSG_INTL(MSG_ERR_FAILURE), 122 file, func, elf_errmsg(elf_errno())); 123 } 124 125 /* 126 * The full usage message 127 */ 128 static void 129 detail_usage() 130 { 131 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL1)); 132 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL2)); 133 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL3)); 134 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL4)); 135 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL5)); 136 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL6)); 137 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL7)); 138 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL8)); 139 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9)); 140 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL10)); 141 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL11)); 142 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL12)); 143 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL13)); 144 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL14)); 145 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL15)); 146 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL16)); 147 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL17)); 148 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL18)); 149 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL19)); 150 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL20)); 151 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL21)); 152 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL22)); 153 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL23)); 154 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL24)); 155 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL25)); 156 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL26)); 157 } 158 159 /* 160 * Output a block of raw data as hex bytes. Each row is given 161 * the index of the first byte in the row. 162 * 163 * entry: 164 * data - Pointer to first byte of data to be displayed 165 * n - # of bytes of data 166 * prefix - String to be output before each line. Useful 167 * for indenting output. 168 * bytes_per_col - # of space separated bytes to output 169 * in each column. 170 * col_per_row - # of columns to output per row 171 * 172 * exit: 173 * The formatted data has been sent to stdout. Each row of output 174 * shows (bytes_per_col * col_per_row) bytes of data. 175 */ 176 void 177 dump_hex_bytes(const void *data, size_t n, int indent, 178 int bytes_per_col, int col_per_row) 179 { 180 const uchar_t *ldata = data; 181 int bytes_per_row = bytes_per_col * col_per_row; 182 int ndx, byte, word; 183 char string[128], *str = string; 184 char index[MAXNDXSIZE]; 185 int index_width; 186 int sp_prefix = 0; 187 188 189 /* 190 * Determine the width to use for the index string. We follow 191 * 8-byte tab rules, but don't use an actual \t character so 192 * that the output can be arbitrarily shifted without odd 193 * tab effects, and so that all the columns line up no matter 194 * how many lines of output are produced. 195 */ 196 ndx = n / bytes_per_row; 197 (void) snprintf(index, sizeof (index), 198 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx)); 199 index_width = strlen(index); 200 index_width = S_ROUND(index_width, 8); 201 202 for (ndx = byte = word = 0; n > 0; n--, ldata++) { 203 while (sp_prefix-- > 0) 204 *str++ = ' '; 205 206 (void) snprintf(str, sizeof (string), 207 MSG_ORIG(MSG_HEXDUMP_TOK), (int)*ldata); 208 str += 2; 209 sp_prefix = 1; 210 211 if (++byte == bytes_per_col) { 212 sp_prefix += 2; 213 word++; 214 byte = 0; 215 } 216 if (word == col_per_row) { 217 *str = '\0'; 218 (void) snprintf(index, sizeof (index), 219 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx)); 220 dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW), 221 indent, MSG_ORIG(MSG_STR_EMPTY), 222 index_width, index, string); 223 sp_prefix = 0; 224 word = 0; 225 ndx += bytes_per_row; 226 str = string; 227 } 228 } 229 if (byte || word) { 230 *str = '\0'; /* */ 231 (void) snprintf(index, sizeof (index), 232 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx)); 233 dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW), indent, 234 MSG_ORIG(MSG_STR_EMPTY), index_width, index, string); 235 } 236 } 237 238 /* 239 * Convert the ASCII representation of an index, or index range, into 240 * binary form, and store it in rec: 241 * 242 * index: An positive or 0 valued integer 243 * range: Two indexes, separated by a ':' character, denoting 244 * a range of allowed values. If the second value is omitted, 245 * any values equal to or greater than the first will match. 246 * 247 * exit: 248 * On success, *rec is filled in with a MATCH_OPT_NDX or MATCH_OPT_RANGE 249 * value, and this function returns (1). On failure, the contents 250 * of *rec are undefined, and (0) is returned. 251 */ 252 int 253 process_index_opt(const char *str, match_rec_t *rec) 254 { 255 #define SKIP_BLANK for (; *str && isspace(*str); str++) 256 257 char *endptr; 258 259 rec->value.ndx.start = strtol(str, &endptr, 10); 260 /* Value must use some of the input, and be 0 or positive */ 261 if ((str == endptr) || (rec->value.ndx.start < 0)) 262 return (0); 263 str = endptr; 264 265 SKIP_BLANK; 266 if (*str != ':') { 267 rec->opt_type = MATCH_OPT_NDX; 268 } else { 269 str++; /* Skip the ':' */ 270 rec->opt_type = MATCH_OPT_RANGE; 271 SKIP_BLANK; 272 if (*str == '\0') { 273 rec->value.ndx.end = -1; /* Indicates "to end" */ 274 } else { 275 rec->value.ndx.end = strtol(str, &endptr, 10); 276 if ((str == endptr) || (rec->value.ndx.end < 0)) 277 return (0); 278 str = endptr; 279 SKIP_BLANK; 280 } 281 } 282 283 /* Syntax error if anything is left over */ 284 if (*str != '\0') 285 return (0); 286 287 return (1); 288 289 #undef SKIP_BLANK 290 } 291 292 /* 293 * Convert a string containing a specific type of ELF constant, or an ASCII 294 * representation of a number, to an integer. Strings starting with '0' 295 * are taken to be octal, those staring with '0x' are hex, and all 296 * others are decimal. 297 * 298 * entry: 299 * str - String to be converted 300 * ctype - Constant type 301 * v - Address of variable to receive resulting value. 302 * 303 * exit: 304 * On success, returns True (1) and *v is set to the value. 305 * On failure, returns False (0) and *v is undefined. 306 */ 307 typedef enum { 308 ATOUI_PT, 309 ATOUI_SHT, 310 ATOUI_OSABI 311 } atoui_type_t; 312 313 static int 314 atoui(const char *str, atoui_type_t type, uint32_t *v) 315 { 316 conv_strtol_uvalue_t uvalue; 317 char *endptr; 318 319 if (conv_iter_strtol_init(str, &uvalue) != 0) { 320 switch (type) { 321 case ATOUI_PT: 322 if (conv_iter_phdr_type(CONV_OSABI_ALL, CONV_FMT_ALT_CF, 323 conv_iter_strtol, &uvalue) == CONV_ITER_DONE) 324 break; 325 (void) conv_iter_phdr_type(CONV_OSABI_ALL, 326 CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue); 327 break; 328 case ATOUI_SHT: 329 if (conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL, 330 CONV_FMT_ALT_CF, conv_iter_strtol, &uvalue) == 331 CONV_ITER_DONE) 332 break; 333 (void) conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL, 334 CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue); 335 break; 336 case ATOUI_OSABI: 337 if (conv_iter_ehdr_osabi(CONV_FMT_ALT_CF, 338 conv_iter_strtol, &uvalue) == CONV_ITER_DONE) 339 break; 340 (void) conv_iter_ehdr_osabi(CONV_FMT_ALT_NF, 341 conv_iter_strtol, &uvalue); 342 break; 343 } 344 if (uvalue.csl_found) { 345 *v = uvalue.csl_value; 346 return (1); 347 } 348 } 349 350 *v = strtoull(str, &endptr, 0); 351 352 /* If the left over part contains anything but whitespace, fail */ 353 for (; *endptr; endptr++) 354 if (!isspace(*endptr)) 355 return (0); 356 return (1); 357 } 358 359 /* 360 * Called after getopt() processing is finished if there is a non-empty 361 * match list. Prepares the matching code for use. 362 * 363 * exit: 364 * Returns True (1) if no errors are encountered. Writes an 365 * error string to stderr and returns False (0) otherwise. 366 */ 367 static int 368 match_prepare(char *argv0, uint_t flags) 369 { 370 match_rec_t *list; 371 const char *str; 372 int minus_p = (flags & FLG_SHOW_PHDR) != 0; 373 atoui_type_t atoui_type; 374 375 /* 376 * Flag ambiguous attempt to use match option with both -p and 377 * and one or more section SHOW options. In this case, we 378 * can't tell what type of item we're supposed to match against. 379 */ 380 if (minus_p && (flags & FLG_MASK_SHOW_SHDR)) { 381 (void) fprintf(stderr, MSG_INTL(MSG_ERR_AMBIG_MATCH), 382 basename(argv0)); 383 return (0); 384 } 385 386 /* Set the match type, based on the presence of the -p option */ 387 if (minus_p) { 388 match_state.item_type = MATCH_ITEM_PT; 389 atoui_type = ATOUI_PT; 390 } else { 391 match_state.item_type = MATCH_ITEM_SHT; 392 atoui_type = ATOUI_SHT; 393 } 394 395 /* 396 * Scan match list and perform any necessary fixups: 397 * 398 * MATCH_OPT_NAME: If -p is specified, convert MATCH_OPT_NAME (-N) 399 * requests into MATCH_OPT_TYPE (-T). 400 * 401 * MATCH_OPT_TYPE: Now that we know item type we are matching 402 * against, we can convert the string saved in the name 403 * field during getopt() processing into an integer and 404 * write it into the type field. 405 */ 406 for (list = match_state.list; list; list = list->next) { 407 if ((list->opt_type == MATCH_OPT_NAME) && minus_p) 408 list->opt_type = MATCH_OPT_TYPE; 409 410 if (list->opt_type != MATCH_OPT_TYPE) 411 continue; 412 413 str = list->value.name; 414 if (atoui(str, atoui_type, &list->value.type) == 0) { 415 const char *fmt = minus_p ? 416 MSG_INTL(MSG_ERR_BAD_T_PT) : 417 MSG_INTL(MSG_ERR_BAD_T_SHT); 418 419 (void) fprintf(stderr, fmt, basename(argv0), str); 420 return (0); 421 } 422 } 423 424 return (1); 425 } 426 427 428 /* 429 * Returns True (1) if the item with the given name or index should 430 * be displayed, and False (0) if it should not be. 431 * 432 * entry: 433 * match_flags - Bitmask specifying matching options, as described 434 * in _elfdump.h. 435 * name - If MATCH_F_NAME flag is set, name of item under 436 * consideration. Otherwise ignored. 437 * should not be considered. 438 * ndx - If MATCH_F_NDX flag is set, index of item under consideration. 439 * type - If MATCH_F_TYPE is set, type of item under consideration. 440 * If MATCH_F_PHDR is set, this would be a program 441 * header type (PT_). Otherwise, a section header type (SHT_). 442 * 443 * exit: 444 * True will be returned if the given name/index matches those given 445 * by one of the (-I, -N -T) command line options, or if no such option 446 * was used in the command invocation and MATCH_F_STRICT is not 447 * set. 448 */ 449 int 450 match(match_flags_t match_flags, const char *name, uint_t ndx, uint_t type) 451 { 452 match_item_t item_type = (match_flags & MATCH_F_PHDR) ? 453 MATCH_ITEM_PT : MATCH_ITEM_SHT; 454 match_rec_t *list; 455 456 /* 457 * If there is no match list, then we use the MATCH_F_STRICT 458 * flag to decide what to return. In the strict case, we return 459 * False (0), in the normal case, True (1). 460 */ 461 if (match_state.list == NULL) 462 return ((match_flags & MATCH_F_STRICT) == 0); 463 464 /* 465 * If item being checked is not the current match type, 466 * then allow it. 467 */ 468 if (item_type != match_state.item_type) 469 return (1); 470 471 /* Run through the match records and check for a hit */ 472 for (list = match_state.list; list; list = list->next) { 473 switch (list->opt_type) { 474 case MATCH_OPT_NAME: 475 if (((match_flags & MATCH_F_NAME) == 0) || 476 (name == NULL)) 477 break; 478 if (strcmp(list->value.name, name) == 0) 479 return (1); 480 break; 481 case MATCH_OPT_NDX: 482 if ((match_flags & MATCH_F_NDX) && 483 (ndx == list->value.ndx.start)) 484 return (1); 485 break; 486 case MATCH_OPT_RANGE: 487 /* 488 * A range end value less than 0 means that any value 489 * above the start is acceptible. 490 */ 491 if ((match_flags & MATCH_F_NDX) && 492 (ndx >= list->value.ndx.start) && 493 ((list->value.ndx.end < 0) || 494 (ndx <= list->value.ndx.end))) 495 return (1); 496 break; 497 498 case MATCH_OPT_TYPE: 499 if ((match_flags & MATCH_F_TYPE) && 500 (type == list->value.type)) 501 return (1); 502 break; 503 } 504 } 505 506 /* Nothing matched */ 507 return (0); 508 } 509 510 /* 511 * Add an entry to match_state.list for use by match(). This routine is for 512 * use during getopt() processing. It should not be called once 513 * match_prepare() has been called. 514 * 515 * Return True (1) for success. On failure, an error is written 516 * to stderr, and False (0) is returned. 517 */ 518 static int 519 add_match_record(char *argv0, match_rec_t *data) 520 { 521 match_rec_t *rec; 522 match_rec_t *list; 523 524 if ((rec = malloc(sizeof (*rec))) == NULL) { 525 int err = errno; 526 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 527 basename(argv0), strerror(err)); 528 return (0); 529 } 530 531 *rec = *data; 532 533 /* Insert at end of match_state.list */ 534 if (match_state.list == NULL) { 535 match_state.list = rec; 536 } else { 537 for (list = match_state.list; list->next != NULL; 538 list = list->next) 539 ; 540 list->next = rec; 541 } 542 543 rec->next = NULL; 544 return (1); 545 } 546 547 static int 548 decide(const char *file, int fd, Elf *elf, uint_t flags, 549 const char *wname, int wfd, uchar_t osabi) 550 { 551 int r; 552 553 if (gelf_getclass(elf) == ELFCLASS64) 554 r = regular64(file, fd, elf, flags, wname, wfd, osabi); 555 else 556 r = regular32(file, fd, elf, flags, wname, wfd, osabi); 557 558 return (r); 559 } 560 561 static int 562 archive(const char *file, int fd, Elf *elf, uint_t flags, 563 const char *wname, int wfd, uchar_t osabi) 564 { 565 Elf_Cmd cmd = ELF_C_READ; 566 Elf_Arhdr *arhdr; 567 Elf *_elf = NULL; 568 size_t ptr; 569 Elf_Arsym *arsym = NULL; 570 571 /* 572 * Determine if the archive symbol table itself is required. 573 */ 574 if ((flags & FLG_SHOW_SYMBOLS) && 575 match(MATCH_F_NAME, MSG_ORIG(MSG_ELF_ARSYM), 0, 0)) { 576 /* 577 * Get the archive symbol table. 578 */ 579 if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) { 580 /* 581 * The arsym could be 0 even though there was no error. 582 * Print the error message only when there was 583 * real error from elf_getarsym(). 584 */ 585 failure(file, MSG_ORIG(MSG_ELF_GETARSYM)); 586 return (0); 587 } 588 } 589 590 /* 591 * Print the archive symbol table only when the archive symbol 592 * table exists and it was requested to print. 593 */ 594 if (arsym) { 595 size_t cnt; 596 char index[MAXNDXSIZE]; 597 size_t offset = 0, _offset = 0; 598 599 /* 600 * Print out all the symbol entries. 601 */ 602 dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB)); 603 dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS)); 604 605 for (cnt = 0; cnt < ptr; cnt++, arsym++) { 606 /* 607 * For each object obtain an elf descriptor so that we 608 * can establish the members name. Note, we have had 609 * archives where the archive header has not been 610 * obtainable so be lenient with errors. 611 */ 612 if ((offset == 0) || ((arsym->as_off != 0) && 613 (arsym->as_off != _offset))) { 614 615 if (_elf) 616 (void) elf_end(_elf); 617 618 if (elf_rand(elf, arsym->as_off) != 619 arsym->as_off) { 620 failure(file, MSG_ORIG(MSG_ELF_RAND)); 621 arhdr = NULL; 622 } else if ((_elf = elf_begin(fd, 623 ELF_C_READ, elf)) == 0) { 624 failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 625 arhdr = NULL; 626 } else if ((arhdr = elf_getarhdr(_elf)) == 0) { 627 failure(file, 628 MSG_ORIG(MSG_ELF_GETARHDR)); 629 arhdr = NULL; 630 } 631 632 _offset = arsym->as_off; 633 if (offset == 0) 634 offset = _offset; 635 } 636 637 (void) snprintf(index, MAXNDXSIZE, 638 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt)); 639 if (arsym->as_off) 640 dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM1), index, 641 /* LINTED */ 642 (int)arsym->as_off, arhdr ? arhdr->ar_name : 643 MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ? 644 demangle(arsym->as_name, flags) : 645 MSG_INTL(MSG_STR_NULL))); 646 else 647 dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM2), index, 648 /* LINTED */ 649 (int)arsym->as_off); 650 } 651 652 if (_elf) 653 (void) elf_end(_elf); 654 655 /* 656 * If we only need the archive symbol table return. 657 */ 658 if ((flags & FLG_SHOW_SYMBOLS) && 659 match(MATCH_F_STRICT | MATCH_F_NAME, 660 MSG_ORIG(MSG_ELF_ARSYM), -1, -1)) 661 return (0); 662 663 /* 664 * Reset elf descriptor in preparation for processing each 665 * member. 666 */ 667 if (offset) 668 (void) elf_rand(elf, offset); 669 } 670 671 /* 672 * Process each object within the archive. 673 */ 674 while ((_elf = elf_begin(fd, cmd, elf)) != NULL) { 675 char name[MAXPATHLEN]; 676 677 if ((arhdr = elf_getarhdr(_elf)) == NULL) { 678 failure(file, MSG_ORIG(MSG_ELF_GETARHDR)); 679 return (0); 680 } 681 if (*arhdr->ar_name != '/') { 682 (void) snprintf(name, MAXPATHLEN, 683 MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name); 684 dbg_print(0, MSG_ORIG(MSG_FMT_NLSTR), name); 685 686 switch (elf_kind(_elf)) { 687 case ELF_K_AR: 688 if (archive(name, fd, _elf, flags, 689 wname, wfd, osabi) == 1) 690 return (1); 691 break; 692 case ELF_K_ELF: 693 if (decide(name, fd, _elf, flags, 694 wname, wfd, osabi) == 1) 695 return (1); 696 break; 697 default: 698 (void) fprintf(stderr, 699 MSG_INTL(MSG_ERR_BADFILE), name); 700 break; 701 } 702 } 703 704 cmd = elf_next(_elf); 705 (void) elf_end(_elf); 706 } 707 708 return (0); 709 } 710 711 int 712 main(int argc, char **argv, char **envp) 713 { 714 Elf *elf; 715 int var, fd, wfd = 0; 716 char *wname = NULL; 717 uint_t flags = 0; 718 match_rec_t match_data; 719 int ret; 720 uchar_t osabi; 721 722 /* 723 * If we're on a 64-bit kernel, try to exec a full 64-bit version of 724 * the binary. If successful, conv_check_native() won't return. 725 */ 726 (void) conv_check_native(argv, envp); 727 728 /* 729 * Establish locale. 730 */ 731 (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 732 (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 733 734 (void) setvbuf(stdout, NULL, _IOLBF, 0); 735 (void) setvbuf(stderr, NULL, _IOLBF, 0); 736 737 opterr = 0; 738 while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) { 739 switch (var) { 740 case 'C': 741 flags |= FLG_CTL_DEMANGLE; 742 break; 743 case 'c': 744 flags |= FLG_SHOW_SHDR; 745 break; 746 case 'd': 747 flags |= FLG_SHOW_DYNAMIC; 748 break; 749 case 'e': 750 flags |= FLG_SHOW_EHDR; 751 break; 752 case 'G': 753 flags |= FLG_SHOW_GOT; 754 break; 755 case 'g': 756 flags |= FLG_SHOW_GROUP; 757 break; 758 case 'H': 759 flags |= FLG_SHOW_CAP; 760 break; 761 case 'h': 762 flags |= FLG_SHOW_HASH; 763 break; 764 case 'I': 765 if (!process_index_opt(optarg, &match_data)) 766 goto usage_brief; 767 if (!add_match_record(argv[0], &match_data)) 768 return (1); 769 flags |= FLG_CTL_MATCH; 770 break; 771 case 'i': 772 flags |= FLG_SHOW_INTERP; 773 break; 774 case 'k': 775 flags |= FLG_CALC_CHECKSUM; 776 break; 777 case 'l': 778 flags |= FLG_CTL_LONGNAME; 779 break; 780 case 'm': 781 flags |= FLG_SHOW_MOVE; 782 break; 783 case 'N': 784 match_data.opt_type = MATCH_OPT_NAME; 785 match_data.value.name = optarg; 786 if (!add_match_record(argv[0], &match_data)) 787 return (1); 788 flags |= FLG_CTL_MATCH; 789 break; 790 case 'n': 791 flags |= FLG_SHOW_NOTE; 792 break; 793 case 'O': 794 { 795 uint32_t val; 796 797 /* 798 * osabi is a uchar_t in the ELF header. 799 * Don't accept any value that exceeds 800 * that range. 801 */ 802 if ((atoui(optarg, ATOUI_OSABI, &val) == 0) || 803 (val > 255)) { 804 (void) fprintf(stderr, 805 MSG_INTL(MSG_ERR_BAD_T_OSABI), 806 basename(argv[0]), optarg); 807 return (1); 808 } 809 osabi = val; 810 } 811 flags |= FLG_CTL_OSABI; 812 break; 813 case 'P': 814 flags |= FLG_CTL_FAKESHDR; 815 break; 816 case 'p': 817 flags |= FLG_SHOW_PHDR; 818 break; 819 case 'r': 820 flags |= FLG_SHOW_RELOC; 821 break; 822 case 'S': 823 flags |= FLG_SHOW_SORT; 824 break; 825 case 's': 826 flags |= FLG_SHOW_SYMBOLS; 827 break; 828 case 'T': 829 /* 830 * We can't evaluate the value yet, because 831 * we need to know if -p is used or not in 832 * order to tell if we're seeing section header 833 * or program header types. So, we save the 834 * string in the name field, and then convert 835 * it to a type integer in a following pass. 836 */ 837 match_data.opt_type = MATCH_OPT_TYPE; 838 match_data.value.name = optarg; 839 if (!add_match_record(argv[0], &match_data)) 840 return (1); 841 flags |= FLG_CTL_MATCH; 842 break; 843 case 'u': 844 flags |= FLG_SHOW_UNWIND; 845 break; 846 case 'v': 847 flags |= FLG_SHOW_VERSIONS; 848 break; 849 case 'w': 850 wname = optarg; 851 break; 852 case 'y': 853 flags |= FLG_SHOW_SYMINFO; 854 break; 855 case '?': 856 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 857 basename(argv[0])); 858 detail_usage(); 859 return (1); 860 default: 861 break; 862 } 863 } 864 865 /* -p and -w are mutually exclusive. -w only works with sections */ 866 if (((flags & FLG_SHOW_PHDR) != 0) && (wname != NULL)) 867 goto usage_brief; 868 869 /* If a match argument is present, prepare the match state */ 870 if ((match_state.list != NULL) && (match_prepare(argv[0], flags) == 0)) 871 return (1); 872 873 /* 874 * Decide what to do if no options specifying something to 875 * show or do are present. 876 * 877 * If there is no -w and no match options, then we will set all 878 * the show flags, causing a full display of everything in the 879 * file that we know how to handle. 880 * 881 * Otherwise, if there is no match list, we generate a usage 882 * error and quit. 883 * 884 * In the case where there is a match list, we go ahead and call 885 * regular() anyway, leaving it to decide what to do. If -w is 886 * present, regular() will use the match list to handle it. 887 * In addition, in the absence of explicit show/calc flags, regular() 888 * will compare the section headers to the match list and use 889 * that to generate the FLG_ bits that will display the information 890 * specified by the match list. 891 */ 892 if ((flags & ~FLG_MASK_CTL) == 0) { 893 if (!wname && (match_state.list == NULL)) 894 flags |= FLG_MASK_SHOW; 895 else if (match_state.list == NULL) 896 goto usage_brief; 897 } 898 899 /* There needs to be at least 1 filename left following the options */ 900 if ((var = argc - optind) == 0) 901 goto usage_brief; 902 903 /* 904 * If the -l/-C option is specified, set up the liblddbg.so. 905 */ 906 if (flags & FLG_CTL_LONGNAME) 907 dbg_desc->d_extra |= DBG_E_LONG; 908 if (flags & FLG_CTL_DEMANGLE) 909 dbg_desc->d_extra |= DBG_E_DEMANGLE; 910 911 /* 912 * If the -w option has indicated an output file open it. It's 913 * arguable whether this option has much use when multiple files are 914 * being processed. 915 * 916 * If wname is non-NULL, we know that -p was not specified, due 917 * to the test above. 918 */ 919 if (wname) { 920 if ((wfd = open(wname, (O_RDWR | O_CREAT | O_TRUNC), 921 0666)) < 0) { 922 int err = errno; 923 (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 924 wname, strerror(err)); 925 return (1); 926 } 927 } 928 929 /* 930 * Open the input file, initialize the elf interface, and 931 * process it. 932 */ 933 ret = 0; 934 for (; (optind < argc) && (ret == 0); optind++) { 935 const char *file = argv[optind]; 936 937 if ((fd = open(argv[optind], O_RDONLY)) == -1) { 938 int err = errno; 939 (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 940 file, strerror(err)); 941 continue; 942 } 943 (void) elf_version(EV_CURRENT); 944 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 945 failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 946 (void) close(fd); 947 continue; 948 } 949 950 if (var > 1) 951 dbg_print(0, MSG_ORIG(MSG_FMT_NLSTRNL), file); 952 953 switch (elf_kind(elf)) { 954 case ELF_K_AR: 955 ret = archive(file, fd, elf, flags, wname, wfd, osabi); 956 break; 957 case ELF_K_ELF: 958 ret = decide(file, fd, elf, flags, wname, wfd, osabi); 959 break; 960 default: 961 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADFILE), file); 962 break; 963 } 964 965 (void) close(fd); 966 (void) elf_end(elf); 967 } 968 969 if (wfd) 970 (void) close(wfd); 971 return (ret); 972 973 usage_brief: 974 /* Control comes here for a simple usage message and exit */ 975 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 976 basename(argv[0])); 977 return (1); 978 979 } 980