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 /* 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Dump an elf file. 31 */ 32 #include <sys/param.h> 33 #include <fcntl.h> 34 #include <stdio.h> 35 #include <libelf.h> 36 #include <gelf.h> 37 #include <link.h> 38 #include <stdarg.h> 39 #include <unistd.h> 40 #include <libgen.h> 41 #include <libintl.h> 42 #include <locale.h> 43 #include <errno.h> 44 #include <strings.h> 45 #include <sys/elf_SPARC.h> 46 #include <sys/elf_386.h> 47 #include <sys/elf_amd64.h> 48 #include <debug.h> 49 #include <_debug.h> 50 #include <conv.h> 51 #include <msg.h> 52 #include <dwarf.h> 53 54 #define FLG_DYNAMIC 0x00000001 55 #define FLG_EHDR 0x00000002 56 #define FLG_INTERP 0x00000004 57 #define FLG_SHDR 0x00000008 58 #define FLG_NOTE 0x00000010 59 #define FLG_PHDR 0x00000020 60 #define FLG_RELOC 0x00000040 61 #define FLG_SYMBOLS 0x00000080 62 #define FLG_VERSIONS 0x00000100 63 #define FLG_HASH 0x00000200 64 #define FLG_GOT 0x00000400 65 #define FLG_SYMINFO 0x00000800 66 #define FLG_MOVE 0x00001000 67 #define FLG_GROUP 0x00002000 68 #define FLG_CAP 0x00004000 69 #define FLG_UNWIND 0x00008000 70 #define FLG_LONGNAME 0x00100000 /* not done by default */ 71 #define FLG_CHECKSUM 0x00200000 /* not done by default */ 72 #define FLG_DEMANGLE 0x00400000 /* not done by default */ 73 74 #define FLG_EVERYTHING 0x000fffff 75 76 #define IAM_SPARC(X) \ 77 ((X == EM_SPARC) || (X == EM_SPARC32PLUS) || (X == EM_SPARCV9)) 78 #define IAM_INTEL(X) \ 79 (X == EM_386) 80 81 #define MAXNDXSIZE 10 82 83 typedef struct cache { 84 GElf_Shdr c_shdr; 85 Elf_Data *c_data; 86 char *c_name; 87 } Cache; 88 89 typedef struct got_info { 90 GElf_Word g_rshtype; /* it will never happen, but */ 91 /* support mixed relocations */ 92 GElf_Rela g_rela; 93 const char *g_symname; 94 } Got_info; 95 96 static const Cache _cache_init = {{0}, NULL, NULL}; 97 98 const char * 99 _elfdump_msg(Msg mid) 100 { 101 return (gettext(MSG_ORIG(mid))); 102 } 103 104 /* 105 * Determine whether a symbol name should be demangled. 106 */ 107 static const char * 108 demangle(const char *name, uint32_t flags) 109 { 110 if (flags & FLG_DEMANGLE) 111 return (Gelf_sym_dem(name)); 112 else 113 return ((char *)name); 114 } 115 116 117 /* 118 * Define our own printing routine. All Elf routines referenced call upon 119 * this routine to carry out the actual printing. 120 */ 121 /*PRINTFLIKE1*/ 122 void 123 dbg_print(const char *format, ...) 124 { 125 va_list ap; 126 127 va_start(ap, format); 128 (void) vprintf(format, ap); 129 (void) printf(MSG_ORIG(MSG_STR_NL)); 130 va_end(ap); 131 } 132 133 /* 134 * Just like dbg_print - except that it does not insert 135 * a newline at the end. Can be used for printing tables 136 * and such. 137 */ 138 /*PRINTFLIKE1*/ 139 void 140 dbg_printf(const char *format, ...) 141 { 142 va_list ap; 143 va_start(ap, format); 144 (void) vprintf(format, ap); 145 va_end(ap); 146 } 147 148 149 150 /* 151 * Define our own standard error routine. 152 */ 153 static void 154 failure(const char *file, const char *func) 155 { 156 (void) fprintf(stderr, MSG_INTL(MSG_ERR_FAILURE), 157 file, func, elf_errmsg(elf_errno())); 158 (void) fflush(stderr); 159 } 160 161 162 /* 163 * Focal point for verifying symbol names. 164 */ 165 static const char * 166 string(Cache *refsec, GElf_Word ndx, Cache *strsec, const char *file, 167 ulong_t name) 168 { 169 static Cache *osec = 0; 170 static int nostr; 171 172 const char *strs = (char *)strsec->c_data->d_buf; 173 ulong_t strn = strsec->c_data->d_size; 174 175 /* 176 * Only print a diagnoistic regarding an empty string table once per 177 * input section being processed. 178 */ 179 if (osec != refsec) { 180 osec = refsec; 181 nostr = 0; 182 } 183 184 /* 185 * Is the string table offset within range of the available strings? 186 */ 187 if (name >= strn) { 188 /* 189 * Do we have a empty string table? 190 */ 191 if (strs == 0) { 192 if (nostr == 0) { 193 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 194 file, strsec->c_name); 195 (void) fflush(stderr); 196 nostr++; 197 } 198 } else { 199 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSTOFF), 200 file, refsec->c_name, ndx, strsec->c_name, 201 EC_XWORD(name), EC_XWORD(strn - 1)); 202 (void) fflush(stderr); 203 } 204 205 /* 206 * Return the empty string so that the calling function can 207 * continue it's output diagnostics. 208 */ 209 return (MSG_INTL(MSG_STR_UNKNOWN)); 210 } 211 return (strs + name); 212 } 213 214 /* 215 * Lookup a symbol and set Sym accordingly. 216 * 217 * Returns: 218 * 1 - symbol found 219 * 0 - symbol not found 220 */ 221 static int 222 symlookup(const char *name, Cache *cache, GElf_Word shnum, GElf_Sym *sym, 223 Cache *symtab, const char *file) 224 { 225 GElf_Shdr * shdr; 226 GElf_Word symn, cnt; 227 228 if (symtab == 0) 229 return (0); 230 231 shdr = &symtab->c_shdr; 232 /* 233 * Determine the symbol data and number. 234 */ 235 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 236 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 237 file, symtab->c_name); 238 (void) fflush(stderr); 239 return (0); 240 } 241 /* LINTED */ 242 symn = (GElf_Word)(shdr->sh_size / shdr->sh_entsize); 243 244 /* 245 * Get the associated string table section. 246 */ 247 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 248 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 249 file, symtab->c_name, EC_XWORD(shdr->sh_link)); 250 (void) fflush(stderr); 251 return (0); 252 } 253 254 /* 255 * Loop through the symbol table to find a match. 256 */ 257 for (cnt = 0; cnt < symn; cnt++) { 258 GElf_Sym tsym; 259 const char *sname; 260 261 if (gelf_getsym(symtab->c_data, cnt, &tsym) == NULL) { 262 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSYM), 263 file, symtab->c_name, elf_errmsg(0)); 264 (void) fflush(stderr); 265 return (0); 266 } 267 268 sname = string(symtab, cnt, &cache[shdr->sh_link], file, 269 tsym.st_name); 270 271 if (strcmp(name, sname) == 0) { 272 *sym = tsym; 273 return (1); 274 } 275 } 276 return (0); 277 } 278 279 /* 280 * The full usage message 281 */ 282 static void 283 detail_usage() 284 { 285 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL1)); 286 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL2)); 287 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL3)); 288 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL4)); 289 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL5)); 290 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL6)); 291 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL7)); 292 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL8)); 293 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9)); 294 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9_1)); 295 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL10)); 296 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL11)); 297 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL12)); 298 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL13)); 299 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL14)); 300 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL15)); 301 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL16)); 302 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL17)); 303 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL18)); 304 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL19)); 305 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL20)); 306 (void) fflush(stderr); 307 } 308 309 /* 310 * Print section headers. 311 */ 312 static void 313 sections(const char *file, Cache *cache, GElf_Word shnum, GElf_Word phnum, 314 GElf_Ehdr *ehdr, const char *name) 315 { 316 GElf_Word cnt; 317 Cache * _cache; 318 319 for (cnt = 1; cnt < shnum; cnt++) { 320 GElf_Shdr *shdr; 321 const char *sname; 322 323 _cache = &cache[cnt]; 324 sname = _cache->c_name; 325 if (name && strcmp(name, sname)) 326 continue; 327 328 /* 329 * Although numerous section header entries can be zero, it's 330 * usually a sign of trouble if the name or type are zero. 331 */ 332 shdr = &_cache->c_shdr; 333 if (shdr->sh_type == 0) { 334 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE), 335 file, sname, EC_XWORD(shdr->sh_type)); 336 (void) fflush(stderr); 337 } 338 if (shdr->sh_name == 0) { 339 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHNAME), 340 file, sname, EC_XWORD(shdr->sh_name)); 341 (void) fflush(stderr); 342 343 /* 344 * Use the empty string, rather than the fabricated 345 * name for the section output. 346 */ 347 sname = MSG_ORIG(MSG_STR_EMPTY); 348 } 349 350 /* 351 * Identify any sections that are suspicious. A .got section 352 * shouldn't exist in a relocatable object. 353 */ 354 if (ehdr->e_type == ET_REL) { 355 if (strncmp(sname, MSG_ORIG(MSG_ELF_GOT), 356 MSG_ELF_GOT_SIZE) == 0) { 357 (void) fprintf(stderr, 358 MSG_INTL(MSG_GOT_UNEXPECTED), file, sname); 359 (void) fflush(stderr); 360 } 361 } 362 363 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 364 /* LINTED */ 365 dbg_print(MSG_INTL(MSG_ELF_SHDR), (uint_t)cnt, sname); 366 Gelf_shdr_entry(ehdr->e_machine, shdr); 367 } 368 } 369 370 static void 371 unwind(Cache *cache, GElf_Word shnum, GElf_Word phnum, GElf_Ehdr *ehdr, 372 const char *name, const char *file, Elf *elf) 373 { 374 GElf_Word cnt; 375 GElf_Phdr unwind_phdr; 376 /* 377 * For the moment - UNWIND is only relevant for 378 * a AMD64 object 379 */ 380 if (ehdr->e_machine != EM_AMD64) 381 return; 382 383 unwind_phdr.p_type = PT_NULL; 384 385 for (cnt = 0; cnt < phnum; cnt++) { 386 GElf_Phdr phdr; 387 388 if (gelf_getphdr(elf, cnt, &phdr) == NULL) { 389 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 390 return; 391 } 392 393 if (phdr.p_type == PT_SUNW_UNWIND) { 394 unwind_phdr = phdr; 395 break; 396 } 397 } 398 399 400 for (cnt = 1; cnt < shnum; cnt++) { 401 Cache *_cache; 402 GElf_Shdr *shdr; 403 unsigned char *data; 404 size_t datasize; 405 uint64_t off, ndx; 406 407 408 _cache = &cache[cnt]; 409 shdr = &_cache->c_shdr; 410 /* 411 * XX64 - this is a strmcp() just to find the gcc 412 * produced sections. Soon gcc should be 413 * settng the section type - and we'll not need 414 * this strcmp(). 415 */ 416 if ((shdr->sh_type != SHT_AMD64_UNWIND) && 417 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM), 418 MSG_SCN_FRM_SIZE) != 0) && 419 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 420 MSG_SCN_FRMHDR_SIZE) != 0)) 421 continue; 422 if (name && strcmp(name, _cache->c_name)) 423 continue; 424 425 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 426 dbg_print(MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name); 427 428 data = (unsigned char *)(_cache->c_data->d_buf); 429 datasize = _cache->c_data->d_size; 430 off = 0; 431 432 /* 433 * Is this a .eh_frame_hdr 434 */ 435 if (((unwind_phdr.p_type == PT_SUNW_UNWIND) && 436 (shdr->sh_addr == unwind_phdr.p_vaddr)) || 437 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 438 MSG_SCN_FRMHDR_SIZE) == 0)) { 439 uint_t vers; 440 uint_t frame_ptr_enc; 441 uint64_t frame_ptr; 442 uint_t fde_cnt_enc; 443 uint64_t fde_cnt; 444 uint_t table_enc; 445 uint64_t tabndx; 446 447 dbg_print(MSG_ORIG(MSG_UNW_FRMHDR)); 448 ndx = 0; 449 450 vers = data[ndx++]; 451 frame_ptr_enc = data[ndx++]; 452 fde_cnt_enc = data[ndx++]; 453 table_enc = data[ndx++]; 454 455 dbg_print(MSG_ORIG(MSG_UNW_FRMVERS), vers); 456 457 frame_ptr = dwarf_ehe_extract(data, 458 &ndx, frame_ptr_enc, ehdr->e_ident, 459 shdr->sh_addr + ndx); 460 461 dbg_print(MSG_ORIG(MSG_UNW_FRPTRENC), 462 conv_dwarf_ehe_str(frame_ptr_enc), 463 frame_ptr); 464 465 fde_cnt = dwarf_ehe_extract(data, 466 &ndx, fde_cnt_enc, ehdr->e_ident, 467 shdr->sh_addr + ndx); 468 dbg_print(MSG_ORIG(MSG_UNW_FDCNENC), 469 conv_dwarf_ehe_str(fde_cnt_enc), 470 fde_cnt); 471 dbg_print(MSG_ORIG(MSG_UNW_TABENC), 472 conv_dwarf_ehe_str(table_enc)); 473 dbg_print(MSG_ORIG(MSG_UNW_BINSRTAB1)); 474 dbg_print(MSG_ORIG(MSG_UNW_BINSRTAB2)); 475 476 for (tabndx = 0; tabndx < fde_cnt; tabndx++) { 477 uint64_t init_loc; 478 uint64_t fde_loc; 479 init_loc = dwarf_ehe_extract(data, 480 &ndx, table_enc, ehdr->e_ident, 481 shdr->sh_addr); 482 fde_loc = dwarf_ehe_extract(data, 483 &ndx, table_enc, ehdr->e_ident, 484 shdr->sh_addr); 485 dbg_print(MSG_ORIG(MSG_UNW_BINSRTABENT), 486 init_loc, fde_loc); 487 } 488 continue; 489 } 490 491 /* 492 * Walk the Eh_frame's 493 */ 494 while (off < datasize) { 495 uint_t cieid, cielength, cieversion, 496 cieretaddr; 497 int cieRflag, cieLflag, 498 ciePflag, cieZflag; 499 uint_t length, id; 500 uint64_t ciecalign, ciedalign; 501 char *cieaugstr; 502 uint_t cieaugndx; 503 504 ndx = 0; 505 /* 506 * extract length in lsb format 507 */ 508 length = LSB32EXTRACT(data + off + ndx); 509 ndx += 4; 510 511 /* 512 * extract CIE id in lsb format 513 */ 514 id = LSB32EXTRACT(data + off + ndx); 515 ndx += 4; 516 517 /* 518 * A CIE record has a id of '0', otherwise 519 * this is a FDE entry and the 'id' is the 520 * CIE pointer. 521 */ 522 if (id == 0) { 523 uint64_t persVal; 524 cielength = length; 525 cieid = id; 526 527 cieLflag = 0; 528 ciePflag = 0; 529 cieRflag = 0; 530 cieZflag = 0; 531 532 dbg_print(MSG_ORIG(MSG_UNW_CIE), 533 shdr->sh_addr + off); 534 dbg_print(MSG_ORIG(MSG_UNW_CIELNGTH), 535 cielength, cieid); 536 cieversion = data[off + ndx]; 537 ndx += 1; 538 cieaugstr = (char *)(&data[off + ndx]); 539 ndx += strlen(cieaugstr) + 1; 540 dbg_print(MSG_ORIG(MSG_UNW_CIEVERS), 541 cieversion, cieaugstr); 542 ciecalign = uleb_extract(&data[off], &ndx); 543 ciedalign = sleb_extract(&data[off], &ndx); 544 cieretaddr = data[off + ndx]; 545 ndx += 1; 546 dbg_print(MSG_ORIG(MSG_UNW_CIECALGN), 547 ciecalign, ciedalign, cieretaddr); 548 549 if (cieaugstr[0]) 550 dbg_print(MSG_ORIG(MSG_UNW_CIEAUXVAL)); 551 for (cieaugndx = 0; cieaugstr[cieaugndx]; 552 cieaugndx++) { 553 uint_t val; 554 switch (cieaugstr[cieaugndx]) { 555 case 'z': 556 val = uleb_extract(&data[off], 557 &ndx); 558 dbg_print( 559 MSG_ORIG(MSG_UNW_CIEAUXSIZE), 560 val); 561 cieZflag = 1; 562 break; 563 case 'P': 564 ciePflag = data[off + ndx]; 565 ndx += 1; 566 567 persVal = dwarf_ehe_extract( 568 &data[off], 569 &ndx, ciePflag, ehdr->e_ident, 570 shdr->sh_addr + off + ndx); 571 dbg_print( 572 MSG_ORIG(MSG_UNW_CIEAUXPERS), 573 ciePflag, 574 conv_dwarf_ehe_str(ciePflag), 575 EC_XWORD(persVal)); 576 break; 577 case 'R': 578 val = data[off + ndx]; 579 ndx += 1; 580 dbg_print( 581 MSG_ORIG(MSG_UNW_CIEAUXCENC), 582 val, conv_dwarf_ehe_str(val)); 583 cieRflag = val; 584 break; 585 case 'L': 586 val = data[off + ndx]; 587 ndx += 1; 588 dbg_print( 589 MSG_ORIG(MSG_UNW_CIEAUXLSDA), 590 val, conv_dwarf_ehe_str(val)); 591 cieLflag = val; 592 break; 593 default: 594 dbg_print( 595 MSG_ORIG(MSG_UNW_CIEAUXUNEC), 596 cieaugstr[cieaugndx]); 597 break; 598 } 599 } 600 if ((cielength + 4) > ndx) { 601 uint_t cnt; 602 dbg_printf(MSG_ORIG(MSG_UNW_CIECFI)); 603 cnt = 0; 604 while (ndx < (cielength + 4)) { 605 if ((cnt++ % 8) == 0) { 606 dbg_printf( 607 MSG_ORIG(MSG_UNW_CIECFI1)); 608 } 609 dbg_printf( 610 MSG_ORIG(MSG_UNW_CIECFI2), 611 data[off + ndx++]); 612 } 613 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 614 } 615 off += cielength + 4; 616 } else { 617 uint_t fdelength = length; 618 int fdecieptr = id; 619 uint64_t fdeinitloc, fdeaddrrange; 620 621 dbg_print(MSG_ORIG(MSG_UNW_FDE), 622 shdr->sh_addr + off); 623 dbg_print(MSG_ORIG(MSG_UNW_FDELNGTH), 624 fdelength, fdecieptr); 625 fdeinitloc = dwarf_ehe_extract(&data[off], 626 &ndx, cieRflag, ehdr->e_ident, 627 shdr->sh_addr + off + ndx); 628 fdeaddrrange = dwarf_ehe_extract(&data[off], 629 &ndx, (cieRflag & ~DW_EH_PE_pcrel), 630 ehdr->e_ident, 631 shdr->sh_addr + off + ndx); 632 dbg_print(MSG_ORIG(MSG_UNW_FDEINITLOC), 633 fdeinitloc, fdeaddrrange); 634 if (cieaugstr[0]) 635 dbg_print(MSG_ORIG(MSG_UNW_FDEAUXVAL)); 636 if (cieZflag) { 637 uint64_t val; 638 val = uleb_extract(&data[off], &ndx); 639 dbg_print( 640 MSG_ORIG(MSG_UNW_FDEAUXSIZE), val); 641 if (val & cieLflag) { 642 fdeinitloc = dwarf_ehe_extract( 643 &data[off], &ndx, cieLflag, 644 ehdr->e_ident, 645 shdr->sh_addr + off + ndx); 646 dbg_print( 647 MSG_ORIG(MSG_UNW_FDEAUXLSDA), 648 val); 649 } 650 } 651 if ((fdelength + 4) > ndx) { 652 uint_t cnt; 653 dbg_printf(MSG_ORIG(MSG_UNW_FDECFI)); 654 cnt = 0; 655 while (ndx < (fdelength + 4)) { 656 if ((cnt++ % 8) == 0) { 657 dbg_printf( 658 MSG_ORIG(MSG_UNW_FDECFI1)); 659 } 660 dbg_printf( 661 MSG_ORIG(MSG_UNW_FDECFI2), 662 data[off + ndx++]); 663 } 664 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 665 } 666 667 off += fdelength + 4; 668 } 669 } 670 } 671 } 672 673 /* 674 * Print the hardware/software capabilities. For executables and shared objects 675 * this should be accompanied with a program header. 676 */ 677 static void 678 cap(const char *file, Cache *cache, GElf_Word shnum, GElf_Word phnum, 679 GElf_Ehdr *ehdr, Elf *elf) 680 { 681 GElf_Word cnt; 682 GElf_Shdr * cshdr = 0; 683 Cache * ccache; 684 Elf64_Off cphdr_off = 0; 685 Elf64_Xword cphdr_sz; 686 687 /* 688 * Determine if a hardware/software capabilities header exists. 689 */ 690 for (cnt = 0; cnt < phnum; cnt++) { 691 GElf_Phdr phdr; 692 693 if (gelf_getphdr(elf, cnt, &phdr) == NULL) { 694 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 695 return; 696 } 697 698 if (phdr.p_type == PT_SUNWCAP) { 699 cphdr_off = phdr.p_offset; 700 cphdr_sz = phdr.p_filesz; 701 break; 702 } 703 } 704 705 /* 706 * Determine if a hardware/software capabilities section exists. 707 */ 708 for (cnt = 1; cnt < shnum; cnt++) { 709 Cache * _cache; 710 GElf_Shdr *shdr; 711 712 _cache = &cache[cnt]; 713 shdr = &_cache->c_shdr; 714 715 if (shdr->sh_type != SHT_SUNW_cap) 716 continue; 717 718 if (cphdr_off && ((cphdr_off < shdr->sh_offset) || 719 (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size))) 720 continue; 721 722 ccache = _cache; 723 cshdr = shdr; 724 break; 725 } 726 727 if ((cshdr == 0) && (cphdr_off == 0)) 728 return; 729 730 /* 731 * Print the hardware/software capabilities section. 732 */ 733 if (cshdr) { 734 GElf_Word ndx, capn; 735 736 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 737 dbg_print(MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name); 738 739 Gelf_cap_title(); 740 741 /* LINTED */ 742 capn = (GElf_Word)(cshdr->sh_size / cshdr->sh_entsize); 743 744 /* LINTED */ 745 for (ndx = 0; ndx < capn; ndx++) { 746 GElf_Cap cap; 747 748 if (gelf_getcap(ccache->c_data, ndx, &cap) == NULL) { 749 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADCAP), 750 file, ccache->c_name, elf_errmsg(0)); 751 (void) fflush(stderr); 752 return; 753 } 754 if (cap.c_tag != CA_SUNW_NULL) 755 Gelf_cap_print(&cap, ndx, ehdr->e_machine); 756 } 757 } else 758 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file); 759 760 /* 761 * If this object is an executable or shared object, then the 762 * hardware/software capabilities section should have an accompanying 763 * program header. 764 */ 765 if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) { 766 if (cphdr_off == 0) 767 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2), 768 file, ccache->c_name); 769 else if ((cphdr_off != cshdr->sh_offset) || 770 (cphdr_sz != cshdr->sh_size)) 771 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3), 772 file, ccache->c_name); 773 } 774 } 775 776 /* 777 * Print the interpretor. 778 */ 779 static void 780 interp(const char *file, Cache *cache, GElf_Word shnum, GElf_Word phnum, 781 GElf_Ehdr *ehdr, Elf *elf) 782 { 783 GElf_Word cnt; 784 GElf_Shdr * ishdr = 0; 785 Cache * icache; 786 Elf64_Off iphdr_off = 0; 787 Elf64_Xword iphdr_sz; 788 789 /* 790 * Determine if an interp header exists. 791 */ 792 for (cnt = 0; cnt < phnum; cnt++) { 793 GElf_Phdr phdr; 794 795 if (gelf_getphdr(elf, cnt, &phdr) == NULL) { 796 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 797 return; 798 } 799 800 if (phdr.p_type == PT_INTERP) { 801 iphdr_off = phdr.p_offset; 802 iphdr_sz = phdr.p_filesz; 803 break; 804 } 805 } 806 807 if (iphdr_off == 0) 808 return; 809 810 /* 811 * Determine if an interp section exists. 812 */ 813 for (cnt = 1; cnt < shnum; cnt++) { 814 Cache * _cache; 815 GElf_Shdr *shdr; 816 817 _cache = &cache[cnt]; 818 shdr = &_cache->c_shdr; 819 820 /* 821 * Scan sections to find a section which contains the PT_INTERP 822 * string. The target section can't be in a NOBITS section. 823 */ 824 if ((shdr->sh_type == SHT_NOBITS) || 825 (iphdr_off < shdr->sh_offset) || 826 (iphdr_off + iphdr_sz) > (shdr->sh_offset + shdr->sh_size)) 827 continue; 828 829 icache = _cache; 830 ishdr = shdr; 831 break; 832 } 833 834 /* 835 * Print the interpreter string based on the offset defined in the 836 * program header, as this is the offset used by the kernel. 837 */ 838 if (ishdr) { 839 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 840 dbg_print(MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name); 841 dbg_print(MSG_ORIG(MSG_FMT_INDENT), 842 (char *)icache->c_data->d_buf + 843 (iphdr_off - ishdr->sh_offset)); 844 } else 845 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file); 846 847 /* 848 * If there are any inconsistences between the program header and 849 * section information, flag them. 850 */ 851 if (ishdr && ((iphdr_off != ishdr->sh_offset) || 852 (iphdr_sz != ishdr->sh_size))) { 853 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file, 854 icache->c_name); 855 (void) fflush(stderr); 856 } 857 } 858 859 /* 860 * Print the syminfo section. 861 */ 862 static void 863 syminfo(Cache *cache, GElf_Word shnum, const char *file) 864 { 865 GElf_Shdr *shdr; 866 Elf_Data *dsyms, *ddyn; 867 GElf_Word symn, cnt, ndx; 868 Cache *syminfo = 0; 869 char *sname; 870 871 for (cnt = 1; cnt < shnum; cnt++) { 872 if (cache[cnt].c_shdr.sh_type == SHT_SUNW_syminfo) { 873 syminfo = &cache[cnt]; 874 break; 875 } 876 } 877 if (syminfo == 0) 878 return; 879 880 shdr = &syminfo->c_shdr; 881 /* 882 * Determine the symbol info data and number. 883 */ 884 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 885 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 886 file, syminfo->c_name); 887 (void) fflush(stderr); 888 return; 889 } 890 /* LINTED */ 891 symn = (GElf_Word)(shdr->sh_size / shdr->sh_entsize); 892 893 /* 894 * Get the data buffer of the associated dynamic section. 895 */ 896 if ((shdr->sh_info == 0) || (shdr->sh_info >= shnum)) { 897 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 898 file, syminfo->c_name, EC_XWORD(shdr->sh_info)); 899 (void) fflush(stderr); 900 return; 901 } 902 ddyn = cache[shdr->sh_info].c_data; 903 if (ddyn->d_buf == 0) { 904 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 905 file, cache[shdr->sh_info].c_name); 906 (void) fflush(stderr); 907 return; 908 } 909 910 /* 911 * Get the data buffer of the associated symbol table. 912 */ 913 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 914 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 915 file, syminfo->c_name, EC_XWORD(shdr->sh_link)); 916 (void) fflush(stderr); 917 return; 918 } 919 dsyms = cache[shdr->sh_link].c_data; 920 if (dsyms->d_buf == 0) { 921 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 922 file, cache[shdr->sh_link].c_name); 923 (void) fflush(stderr); 924 return; 925 } 926 927 sname = cache[shdr->sh_link].c_name; 928 shdr = &cache[shdr->sh_link].c_shdr; 929 /* 930 * Get the associated string table section. 931 */ 932 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 933 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 934 file, sname, EC_XWORD(shdr->sh_link)); 935 (void) fflush(stderr); 936 return; 937 } 938 939 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 940 dbg_print(MSG_INTL(MSG_ELF_SCN_SYMINFO), syminfo->c_name); 941 Gelf_syminfo_title(); 942 943 for (ndx = 1; ndx < symn; ndx++) { 944 GElf_Syminfo gsip; 945 GElf_Sym gsym; 946 GElf_Dyn gdyn; 947 const char *needed, *sname; 948 949 if (gelf_getsyminfo(syminfo->c_data, ndx, &gsip) == 0) { 950 (void) fprintf(stderr, MSG_INTL(MSG_ERR_SIBADCOUNT), 951 file, syminfo->c_name, ndx); 952 (void) fflush(stderr); 953 return; 954 } 955 if ((gsip.si_flags == 0) && (gsip.si_boundto == 0)) 956 continue; 957 958 if (gelf_getsym(dsyms, ndx, &gsym) == 0) { 959 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSYM), 960 file, syminfo->c_name, elf_errmsg(0)); 961 (void) fflush(stderr); 962 return; 963 } 964 965 sname = string(syminfo, cnt, &cache[shdr->sh_link], file, 966 gsym.st_name); 967 needed = 0; 968 969 if (gsip.si_boundto < SYMINFO_BT_LOWRESERVE) { 970 if (gelf_getdyn(ddyn, gsip.si_boundto, &gdyn) == 0) { 971 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADDYN), 972 file, syminfo->c_name, gsip.si_boundto); 973 (void) fflush(stderr); 974 return; 975 } 976 needed = string(syminfo, gsip.si_boundto, 977 &cache[shdr->sh_link], file, gdyn.d_un.d_val); 978 } 979 980 Gelf_syminfo_entry(ndx, &gsip, sname, needed); 981 } 982 } 983 984 /* 985 * Print version definition section entries. 986 */ 987 static void 988 version_def(GElf_Verdef *vdf, GElf_Word shnum, Cache *vcache, Cache *scache, 989 const char *file) 990 { 991 GElf_Word cnt; 992 char index[MAXNDXSIZE]; 993 994 Gelf_ver_def_title(); 995 996 for (cnt = 1; cnt <= shnum; cnt++, 997 vdf = (GElf_Verdef *)((uintptr_t)vdf + vdf->vd_next)) { 998 999 GElf_Half vcnt = vdf->vd_cnt - 1; 1000 GElf_Half ndx = vdf->vd_ndx; 1001 GElf_Verdaux *vdap = (GElf_Verdaux *) 1002 ((uintptr_t)vdf + vdf->vd_aux); 1003 const char *name, *dep; 1004 1005 /* 1006 * Obtain the name and first dependency (if any). 1007 */ 1008 name = string(vcache, cnt, scache, file, vdap->vda_name); 1009 vdap = (GElf_Verdaux *)((uintptr_t)vdap + vdap->vda_next); 1010 if (vcnt) 1011 dep = string(vcache, cnt, scache, file, vdap->vda_name); 1012 else 1013 dep = MSG_ORIG(MSG_STR_EMPTY); 1014 1015 (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX), 1016 EC_XWORD(ndx)); 1017 Gelf_ver_line_1(index, name, dep, 1018 conv_verflg_str(vdf->vd_flags)); 1019 1020 /* 1021 * Print any additional dependencies. 1022 */ 1023 if (vcnt) { 1024 vdap = (GElf_Verdaux *)((uintptr_t)vdap + 1025 vdap->vda_next); 1026 for (vcnt--; vcnt; vcnt--, 1027 vdap = (GElf_Verdaux *)((uintptr_t)vdap + 1028 vdap->vda_next)) { 1029 dep = string(vcache, cnt, scache, file, 1030 vdap->vda_name); 1031 Gelf_ver_line_2(MSG_ORIG(MSG_STR_EMPTY), dep); 1032 } 1033 } 1034 } 1035 } 1036 1037 /* 1038 * Print a version needed section entries. 1039 */ 1040 static void 1041 version_need(GElf_Verneed *vnd, GElf_Word shnum, Cache *vcache, Cache *scache, 1042 const char *file) 1043 { 1044 GElf_Word cnt; 1045 1046 Gelf_ver_need_title(); 1047 1048 for (cnt = 1; cnt <= shnum; cnt++, 1049 vnd = (GElf_Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 1050 1051 GElf_Half vcnt = vnd->vn_cnt; 1052 GElf_Vernaux *vnap = (GElf_Vernaux *)((uintptr_t)vnd + 1053 vnd->vn_aux); 1054 const char *name, *dep; 1055 1056 /* 1057 * Obtain the name of the needed file and the version name 1058 * within it that we're dependent on. Note that the count 1059 * should be at least one, otherwise this is a pretty bogus 1060 * entry. 1061 */ 1062 name = string(vcache, cnt, scache, file, vnd->vn_file); 1063 if (vcnt) 1064 dep = string(vcache, cnt, scache, file, vnap->vna_name); 1065 else 1066 dep = MSG_INTL(MSG_STR_NULL); 1067 1068 Gelf_ver_line_1(MSG_ORIG(MSG_STR_EMPTY), name, dep, 1069 conv_verflg_str(vnap->vna_flags)); 1070 1071 /* 1072 * Print any additional version dependencies. 1073 */ 1074 if (vcnt) { 1075 vnap = (GElf_Vernaux *)((uintptr_t)vnap + 1076 vnap->vna_next); 1077 for (vcnt--; vcnt; vcnt--, 1078 vnap = (GElf_Vernaux *)((uintptr_t)vnap + 1079 vnap->vna_next)) { 1080 dep = string(vcache, cnt, scache, file, 1081 vnap->vna_name); 1082 Gelf_ver_line_3(MSG_ORIG(MSG_STR_EMPTY), dep, 1083 conv_verflg_str(vnap->vna_flags)); 1084 } 1085 } 1086 } 1087 } 1088 1089 /* 1090 * Search for any verion sections - the Versym output is possibly 1091 * used by the symbols() printing. If VERSYM is specified - then 1092 * display the version information. 1093 */ 1094 static Cache * 1095 versions(Cache *cache, GElf_Word shnum, const char *file, uint32_t flags) 1096 { 1097 GElf_Word cnt; 1098 Cache *versymcache = 0; 1099 1100 for (cnt = 1; cnt < shnum; cnt++) { 1101 void * ver; 1102 uint_t num; 1103 Cache * _cache = &cache[cnt]; 1104 GElf_Shdr * shdr = &_cache->c_shdr; 1105 1106 /* 1107 * If this is the version symbol table simply record its 1108 * data address for possible use in later symbol processing. 1109 */ 1110 if (shdr->sh_type == SHT_SUNW_versym) { 1111 versymcache = _cache; 1112 continue; 1113 } 1114 1115 if ((flags & FLG_VERSIONS) == 0) 1116 continue; 1117 1118 if ((shdr->sh_type != SHT_SUNW_verdef) && 1119 (shdr->sh_type != SHT_SUNW_verneed)) 1120 continue; 1121 1122 /* 1123 * Determine the version section data and number. 1124 */ 1125 if ((ver = (void *)_cache->c_data->d_buf) == 0) { 1126 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1127 file, _cache->c_name); 1128 (void) fflush(stderr); 1129 continue; 1130 } 1131 if ((num = shdr->sh_info) == 0) { 1132 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 1133 file, _cache->c_name, EC_XWORD(shdr->sh_info)); 1134 (void) fflush(stderr); 1135 continue; 1136 } 1137 1138 /* 1139 * Get the data buffer for the associated string table. 1140 */ 1141 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1142 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1143 file, _cache->c_name, EC_XWORD(shdr->sh_link)); 1144 (void) fflush(stderr); 1145 continue; 1146 } 1147 1148 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1149 if (shdr->sh_type == SHT_SUNW_verdef) { 1150 dbg_print(MSG_INTL(MSG_ELF_SCN_VERDEF), 1151 _cache->c_name); 1152 version_def((GElf_Verdef *)ver, num, _cache, 1153 &cache[shdr->sh_link], file); 1154 } else if (shdr->sh_type == SHT_SUNW_verneed) { 1155 dbg_print(MSG_INTL(MSG_ELF_SCN_VERNEED), 1156 _cache->c_name); 1157 version_need((GElf_Verneed *)ver, num, _cache, 1158 &cache[shdr->sh_link], file); 1159 } 1160 } 1161 return (versymcache); 1162 } 1163 1164 /* 1165 * Search for and process any symbol tables. 1166 */ 1167 static void 1168 symbols(Cache *cache, GElf_Word shnum, GElf_Word phnum, GElf_Ehdr *ehdr, 1169 const char *name, Cache *versymcache, const char *file) 1170 { 1171 GElf_Word cnt; 1172 char is_core = (ehdr->e_type == ET_CORE); 1173 1174 for (cnt = 1; cnt < shnum; cnt++) { 1175 GElf_Sym sym; 1176 GElf_Word symn, _cnt; 1177 GElf_Versym *versym; 1178 Cache *_cache = &cache[cnt]; 1179 GElf_Shdr *shdr = &_cache->c_shdr; 1180 Word *symshndx; 1181 uint_t nosymshndx; 1182 uint_t nosyminshndx; 1183 1184 if ((shdr->sh_type != SHT_SYMTAB) && 1185 (shdr->sh_type != SHT_DYNSYM)) 1186 continue; 1187 if (name && strcmp(name, _cache->c_name)) 1188 continue; 1189 1190 /* 1191 * Determine the symbol data and number. 1192 */ 1193 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1194 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1195 file, _cache->c_name); 1196 (void) fflush(stderr); 1197 continue; 1198 } 1199 /* LINTED */ 1200 symn = (GElf_Word)(shdr->sh_size / shdr->sh_entsize); 1201 1202 /* 1203 * Get the associated string table section. 1204 */ 1205 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1206 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1207 file, _cache->c_name, EC_XWORD(shdr->sh_link)); 1208 (void) fflush(stderr); 1209 continue; 1210 } 1211 1212 /* 1213 * Determine if there is a associated Versym section 1214 * with this Symbol Table. 1215 */ 1216 if (versymcache && (versymcache->c_shdr.sh_link == cnt)) 1217 versym = versymcache->c_data->d_buf; 1218 else 1219 versym = 0; 1220 1221 /* 1222 * Loop through the symbol tables entries. 1223 */ 1224 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1225 dbg_print(MSG_INTL(MSG_ELF_SCN_SYMTAB), _cache->c_name); 1226 Gelf_sym_table_title(ehdr, MSG_INTL(MSG_STR_INDEX), 1227 MSG_INTL(MSG_STR_NAME)); 1228 1229 symshndx = 0; 1230 nosymshndx = 0; 1231 nosyminshndx = 0; 1232 for (_cnt = 0; _cnt < symn; _cnt++) { 1233 char index[MAXNDXSIZE]; 1234 char *sec; 1235 const char *sname; 1236 int verndx; 1237 uchar_t type; 1238 GElf_Shdr *tshdr; 1239 Word shndx; 1240 1241 if (gelf_getsym(_cache->c_data, _cnt, &sym) == NULL) { 1242 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSYM), 1243 file, _cache->c_name, elf_errmsg(0)); 1244 (void) fflush(stderr); 1245 break; 1246 } 1247 1248 /* 1249 * If we are using extended symbol indexes, find the 1250 * corresponding SHN_SYMTAB_SHNDX table. 1251 */ 1252 if ((sym.st_shndx == SHN_XINDEX) && 1253 (symshndx == 0) && (nosymshndx == 0)) { 1254 Word __cnt; 1255 1256 for (__cnt = 1; __cnt < shnum; __cnt++) { 1257 Cache *_cache = &cache[__cnt]; 1258 GElf_Shdr *shdr = &_cache->c_shdr; 1259 1260 if ((shdr->sh_type != 1261 SHT_SYMTAB_SHNDX) || 1262 (shdr->sh_link != cnt)) 1263 continue; 1264 if (shdr->sh_entsize) 1265 /* LINTED */ 1266 nosyminshndx = (uint_t) 1267 shdr->sh_size/shdr->sh_entsize; 1268 if (nosyminshndx == 0) 1269 continue; 1270 symshndx = _cache->c_data->d_buf; 1271 break; 1272 } 1273 if (symshndx == 0) 1274 nosymshndx = 1; 1275 } 1276 1277 /* LINTED */ 1278 sname = string(_cache, _cnt, &cache[shdr->sh_link], 1279 file, sym.st_name); 1280 1281 tshdr = 0; 1282 sec = NULL; 1283 1284 if (is_core) 1285 sec = (char *)MSG_INTL(MSG_STR_UNKNOWN); 1286 else if ((sym.st_shndx < SHN_LORESERVE) && 1287 (sym.st_shndx < shnum)) { 1288 shndx = sym.st_shndx; 1289 tshdr = &(cache[shndx].c_shdr); 1290 sec = cache[shndx].c_name; 1291 } else if (sym.st_shndx == SHN_XINDEX) { 1292 if (symshndx) { 1293 Word _symshndx; 1294 1295 if (_cnt > nosyminshndx) { 1296 (void) fprintf(stderr, 1297 MSG_INTL(MSG_ERR_BADSYMXINDEX1), 1298 file, _cache->c_name, 1299 EC_WORD(_cnt)); 1300 (void) fflush(stderr); 1301 } else if ((_symshndx = 1302 symshndx[_cnt]) > shnum) { 1303 (void) fprintf(stderr, 1304 MSG_INTL(MSG_ERR_BADSYMXINDEX2), 1305 file, _cache->c_name, 1306 EC_WORD(_cnt), 1307 EC_WORD(_symshndx)); 1308 (void) fflush(stderr); 1309 } else { 1310 shndx = _symshndx; 1311 tshdr = &(cache[shndx].c_shdr); 1312 sec = cache[shndx].c_name; 1313 } 1314 } else { 1315 (void) fprintf(stderr, 1316 MSG_INTL(MSG_ERR_BADSYMXINDEX3), 1317 file, _cache->c_name, 1318 EC_WORD(_cnt)); 1319 (void) fflush(stderr); 1320 } 1321 } else if ((sym.st_shndx < SHN_LORESERVE) && 1322 (sym.st_shndx >= shnum)) { 1323 (void) fprintf(stderr, 1324 MSG_INTL(MSG_ERR_BADSYM5), 1325 file, _cache->c_name, 1326 sname, sym.st_shndx); 1327 (void) fflush(stderr); 1328 } 1329 1330 /* 1331 * If versioning is available display the 1332 * version index. 1333 */ 1334 if (versym) 1335 verndx = (int)versym[_cnt]; 1336 else 1337 verndx = 0; 1338 1339 /* 1340 * Error checking for TLS. 1341 */ 1342 type = ELF_ST_TYPE(sym.st_info); 1343 if (type == STT_TLS) { 1344 if (tshdr && 1345 (sym.st_shndx != SHN_UNDEF) && 1346 ((tshdr->sh_flags & SHF_TLS) == 0)) { 1347 (void) fprintf(stderr, 1348 MSG_INTL(MSG_ERR_BADSYM3), file, 1349 _cache->c_name, sname); 1350 (void) fflush(stderr); 1351 } 1352 } else if ((type != STT_SECTION) && sym.st_size && 1353 tshdr && (tshdr->sh_flags & SHF_TLS)) { 1354 (void) fprintf(stderr, 1355 MSG_INTL(MSG_ERR_BADSYM4), file, 1356 _cache->c_name, sname); 1357 (void) fflush(stderr); 1358 } 1359 1360 /* 1361 * If a symbol has size, then make sure the section it 1362 * references is appropriate. Note, UNDEF symbols that 1363 * have a size, have been known to exist - ignore them. 1364 */ 1365 if (sym.st_size && shndx && tshdr && 1366 (tshdr->sh_size < sym.st_size)) { 1367 (void) fprintf(stderr, 1368 MSG_INTL(MSG_ERR_BADSYM6), file, 1369 _cache->c_name, sname, EC_WORD(shndx), 1370 EC_XWORD(tshdr->sh_size), 1371 EC_XWORD(sym.st_size)); 1372 (void) fflush(stderr); 1373 } 1374 1375 (void) snprintf(index, MAXNDXSIZE, 1376 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(_cnt)); 1377 1378 Gelf_sym_table_entry(index, ehdr, &sym, verndx, sec, 1379 sname); 1380 } 1381 } 1382 } 1383 1384 /* 1385 * Search for and process any relocation sections. 1386 */ 1387 static void 1388 reloc(Cache *cache, GElf_Word shnum, GElf_Word phnum, GElf_Ehdr *ehdr, 1389 const char *name, const char *file, uint32_t flags) 1390 { 1391 GElf_Word cnt; 1392 1393 for (cnt = 1; cnt < shnum; cnt++) { 1394 Word type; 1395 ulong_t numrels, entsize; 1396 int ndx; 1397 Elf_Data *dsyms; 1398 Cache *_cache = &cache[cnt]; 1399 GElf_Shdr *shdr = &_cache->c_shdr; 1400 char *sname; 1401 1402 if (((type = shdr->sh_type) != SHT_RELA) && 1403 (type != SHT_REL)) 1404 continue; 1405 if (name && strcmp(name, _cache->c_name)) 1406 continue; 1407 1408 /* 1409 * Decide entry size 1410 */ 1411 if (((entsize = shdr->sh_entsize) == 0) || 1412 (entsize > shdr->sh_size)) { 1413 if (type == SHT_RELA) 1414 entsize = sizeof (GElf_Rela); 1415 else 1416 entsize = sizeof (GElf_Rel); 1417 } 1418 1419 /* 1420 * Determine the number of relocations available. 1421 */ 1422 if (shdr->sh_size == 0) { 1423 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1424 file, _cache->c_name); 1425 (void) fflush(stderr); 1426 continue; 1427 } 1428 numrels = shdr->sh_size / entsize; 1429 1430 /* 1431 * Get the data buffer for the associated symbol table. Note 1432 * that we've been known to create static binaries containing 1433 * relocations against weak symbols, if these get stripped the 1434 * relocation records can't make symbolic references. 1435 */ 1436 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1437 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1438 file, _cache->c_name, EC_XWORD(shdr->sh_link)); 1439 (void) fflush(stderr); 1440 continue; 1441 } 1442 dsyms = cache[shdr->sh_link].c_data; 1443 if (dsyms->d_buf == 0) { 1444 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1445 file, cache[shdr->sh_link].c_name); 1446 (void) fflush(stderr); 1447 continue; 1448 } 1449 1450 sname = cache[shdr->sh_link].c_name; 1451 shdr = &cache[shdr->sh_link].c_shdr; 1452 /* 1453 * Get the associated string table section. 1454 */ 1455 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1456 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1457 file, sname, EC_XWORD(shdr->sh_link)); 1458 (void) fflush(stderr); 1459 continue; 1460 } 1461 1462 /* 1463 * Loop through the relocation entries. 1464 */ 1465 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1466 dbg_print(MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name); 1467 if (type == SHT_RELA) { 1468 if (flags & FLG_LONGNAME) 1469 dbg_print(MSG_INTL(MSG_ELF_L_RELOC_RELA)); 1470 else 1471 dbg_print(MSG_INTL(MSG_ELF_RELOC_RELA)); 1472 } else { 1473 if (flags & FLG_LONGNAME) 1474 dbg_print(MSG_INTL(MSG_ELF_L_RELOC_REL)); 1475 else 1476 dbg_print(MSG_INTL(MSG_ELF_RELOC_REL)); 1477 } 1478 1479 /* LINTED */ 1480 for (ndx = 0; ndx < numrels; ndx++) { 1481 char section[BUFSIZ]; 1482 const char *_name; 1483 GElf_Word sndx; 1484 ulong_t r_type; 1485 GElf_Sym _sym; 1486 GElf_Rela rela; 1487 1488 /* 1489 * Determine the symbol with which this relocation is 1490 * associated. If the symbol represents a section 1491 * offset construct an appropriate string. 1492 */ 1493 if (type == SHT_RELA) { 1494 (void) gelf_getrela(_cache->c_data, ndx, 1495 &rela); 1496 } else { 1497 (void) gelf_getrel(_cache->c_data, ndx, 1498 (GElf_Rel*)&rela); 1499 } 1500 /* LINTED */ 1501 sndx = (GElf_Word)GELF_R_SYM(rela.r_info); 1502 r_type = GELF_R_TYPE(rela.r_info); 1503 1504 /* LINTED */ 1505 if (gelf_getsym(dsyms, (int)sndx, &_sym) == NULL) { 1506 (void) fprintf(stderr, 1507 MSG_INTL(MSG_ERR_RELBADSYMNDX), 1508 file, elf_errmsg(0)); 1509 (void) fflush(stderr); 1510 _name = MSG_INTL(MSG_STR_UNKNOWN); 1511 } else { 1512 if ((GELF_ST_TYPE(_sym.st_info) == 1513 STT_SECTION) && (_sym.st_name == 0)) { 1514 if (flags & FLG_LONGNAME) 1515 (void) snprintf(section, BUFSIZ, 1516 MSG_INTL(MSG_STR_L_SECTION), 1517 cache[_sym.st_shndx].c_name); 1518 else 1519 (void) snprintf(section, BUFSIZ, 1520 MSG_INTL(MSG_STR_SECTION), 1521 cache[_sym.st_shndx].c_name); 1522 _name = (const char *)section; 1523 } else { 1524 /* LINTED */ 1525 _name = string(_cache, 1526 sndx, &cache[shdr->sh_link], 1527 file, _sym.st_name); 1528 } 1529 } 1530 1531 if ((sndx == 0) && ((IAM_SPARC(ehdr->e_machine) && 1532 ((r_type != R_SPARC_NONE) && 1533 (r_type != R_SPARC_REGISTER) && 1534 (r_type != R_SPARC_RELATIVE))) || 1535 ((IAM_INTEL(ehdr->e_machine) && 1536 ((r_type != R_386_NONE) && 1537 (r_type != R_386_RELATIVE)))))) { 1538 (void) fprintf(stderr, 1539 MSG_INTL(MSG_ERR_BADREL1), file, 1540 conv_reloc_type_str(ehdr->e_machine, 1541 /* LINTED */ 1542 (uint_t)r_type)); 1543 (void) fflush(stderr); 1544 } 1545 1546 Gelf_reloc_entry(MSG_ORIG(MSG_STR_EMPTY), 1547 ehdr->e_machine, type, (void *)&rela, 1548 _cache->c_name, _name); 1549 } 1550 } 1551 } 1552 1553 /* 1554 * Search for and process a .dynamic section. 1555 */ 1556 static void 1557 dynamic(Cache *cache, GElf_Word shnum, GElf_Ehdr *ehdr, const char *file) 1558 { 1559 GElf_Word cnt; 1560 1561 for (cnt = 1; cnt < shnum; cnt++) { 1562 GElf_Dyn dyn; 1563 ulong_t numdyn; 1564 int ndx; 1565 Cache * _cache = &cache[cnt]; 1566 GElf_Shdr * shdr = &_cache->c_shdr; 1567 1568 if (shdr->sh_type != SHT_DYNAMIC) 1569 continue; 1570 1571 /* 1572 * Get the associated string table section. 1573 */ 1574 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1575 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1576 file, _cache->c_name, EC_XWORD(shdr->sh_link)); 1577 (void) fflush(stderr); 1578 continue; 1579 } 1580 numdyn = shdr->sh_size / shdr->sh_entsize; 1581 1582 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1583 dbg_print(MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name); 1584 1585 Gelf_dyn_title(); 1586 1587 /* LINTED */ 1588 for (ndx = 0; ndx < numdyn; ++ndx) { 1589 const char *name; 1590 1591 (void) gelf_getdyn(_cache->c_data, ndx, &dyn); 1592 if (dyn.d_tag == DT_NULL) 1593 break; 1594 1595 /* 1596 * Print the information numerically, and if possible 1597 * as a string. 1598 */ 1599 if ((dyn.d_tag == DT_NEEDED) || 1600 (dyn.d_tag == DT_SONAME) || 1601 (dyn.d_tag == DT_FILTER) || 1602 (dyn.d_tag == DT_AUXILIARY) || 1603 (dyn.d_tag == DT_CONFIG) || 1604 (dyn.d_tag == DT_RPATH) || 1605 (dyn.d_tag == DT_RUNPATH) || 1606 (dyn.d_tag == DT_USED) || 1607 (dyn.d_tag == DT_DEPAUDIT) || 1608 (dyn.d_tag == DT_AUDIT) || 1609 (dyn.d_tag == DT_SUNW_AUXILIARY) || 1610 (dyn.d_tag == DT_SUNW_FILTER)) 1611 name = string(_cache, ndx, 1612 &cache[shdr->sh_link], file, 1613 dyn.d_un.d_ptr); 1614 else if (dyn.d_tag == DT_FLAGS) 1615 /* LINTED */ 1616 name = conv_dynflag_str((Word)dyn.d_un.d_val); 1617 else if (dyn.d_tag == DT_FLAGS_1) 1618 /* LINTED */ 1619 name = conv_dynflag_1_str((Word)dyn.d_un.d_val); 1620 else if (dyn.d_tag == DT_POSFLAG_1) 1621 /* LINTED */ 1622 name = conv_dynposflag_1_str((Word)dyn.d_un.d_val); 1623 else if (dyn.d_tag == DT_FEATURE_1) 1624 /* LINTED */ 1625 name = conv_dynfeature_1_str((Word)dyn.d_un.d_val); 1626 else if (dyn.d_tag == DT_DEPRECATED_SPARC_REGISTER) 1627 name = MSG_INTL(MSG_STR_DEPRECATED); 1628 else 1629 name = MSG_ORIG(MSG_STR_EMPTY); 1630 1631 Gelf_dyn_print(&dyn, ndx, name, ehdr->e_machine); 1632 } 1633 } 1634 } 1635 1636 /* 1637 * Search for and process a MOVE section. 1638 */ 1639 static void 1640 move(Cache *cache, GElf_Word shnum, const char *name, const char *file, 1641 uint32_t flags) 1642 { 1643 GElf_Word cnt; 1644 1645 for (cnt = 1; cnt < shnum; cnt++) { 1646 ulong_t num, symn; 1647 int ndx; 1648 Elf_Data *dsyms; 1649 const char *fmt; 1650 Cache *_cache = &cache[cnt]; 1651 GElf_Shdr *shdr = &_cache->c_shdr; 1652 char *sname; 1653 1654 if (shdr->sh_type != SHT_SUNW_move) 1655 continue; 1656 if (name && strcmp(name, _cache->c_name)) 1657 continue; 1658 1659 /* 1660 * Determine the move data and number. 1661 */ 1662 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1663 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1664 file, _cache->c_name); 1665 (void) fflush(stderr); 1666 continue; 1667 } 1668 num = shdr->sh_size / shdr->sh_entsize; 1669 1670 /* 1671 * Get the data buffer for the associated symbol table. 1672 */ 1673 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1674 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1675 file, _cache->c_name, EC_XWORD(shdr->sh_link)); 1676 (void) fflush(stderr); 1677 continue; 1678 } 1679 dsyms = cache[shdr->sh_link].c_data; 1680 if (dsyms->d_buf == 0) { 1681 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1682 file, cache[shdr->sh_link].c_name); 1683 (void) fflush(stderr); 1684 continue; 1685 } 1686 1687 sname = cache[shdr->sh_link].c_name; 1688 shdr = &cache[shdr->sh_link].c_shdr; 1689 1690 /* 1691 * Get the associated string table section. 1692 */ 1693 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1694 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1695 file, sname, EC_XWORD(shdr->sh_link)); 1696 (void) fflush(stderr); 1697 continue; 1698 } 1699 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1700 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1701 file, sname); 1702 (void) fflush(stderr); 1703 continue; 1704 } 1705 symn = shdr->sh_size / shdr->sh_entsize; 1706 1707 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1708 dbg_print(MSG_INTL(MSG_MV_TITLE), _cache->c_name); 1709 1710 fmt = MSG_INTL(MSG_MV_ENTRY); 1711 1712 /* LINTED */ 1713 for (ndx = 0; ndx < num; ndx++) { 1714 GElf_Move move; 1715 const char *name; 1716 GElf_Sym sym; 1717 char sct[BUFSIZ]; 1718 Word shndx; 1719 1720 if (gelf_getmove(_cache->c_data, ndx, &move) == NULL) { 1721 (void) fprintf(stderr, 1722 MSG_INTL(MSG_ERR_BADMOVE), 1723 file, _cache->c_name, elf_errmsg(0)); 1724 (void) fflush(stderr); 1725 break; 1726 } 1727 1728 /* 1729 * Check for null entries 1730 */ 1731 if ((move.m_info == 0) && (move.m_value == 0) && 1732 (move.m_poffset == 0) && (move.m_repeat == 0) && 1733 (move.m_stride == 0)) { 1734 dbg_print(fmt, EC_XWORD(move.m_poffset), 1735 EC_XWORD(0), 0, 0, 0, EC_LWORD(0), 1736 MSG_ORIG(MSG_STR_EMPTY)); 1737 continue; 1738 } 1739 if ((GELF_M_SYM(move.m_info) == 0) || 1740 (GELF_M_SYM(move.m_info) >= symn)) { 1741 (void) fprintf(stderr, 1742 MSG_INTL(MSG_ERR_BADMINFO), file, 1743 _cache->c_name, EC_XWORD(move.m_info)); 1744 (void) fflush(stderr); 1745 dbg_print(fmt, EC_XWORD(move.m_poffset), 1746 EC_XWORD(GELF_M_SYM(move.m_info)), 1747 /* LINTED */ 1748 GELF_M_SIZE(move.m_info), move.m_repeat, 1749 move.m_stride, EC_LWORD(move.m_value), 1750 MSG_INTL(MSG_STR_UNKNOWN)); 1751 continue; 1752 } 1753 1754 if (gelf_getsym(dsyms, 1755 /* LINTED */ 1756 (int)GELF_M_SYM(move.m_info), &sym) == NULL) { 1757 (void) fprintf(stderr, 1758 MSG_INTL(MSG_ERR_MVBADSYMNDX), 1759 file, elf_errmsg(0)); 1760 (void) fflush(stderr); 1761 name = MSG_INTL(MSG_STR_UNKNOWN); 1762 } else { 1763 if ((GELF_ST_TYPE(sym.st_info) == 1764 STT_SECTION) && (sym.st_name == 0)) { 1765 if (flags & FLG_LONGNAME) 1766 (void) snprintf(sct, BUFSIZ, 1767 MSG_INTL(MSG_STR_L_SECTION), 1768 cache[sym.st_shndx].c_name); 1769 else 1770 (void) snprintf(sct, BUFSIZ, 1771 MSG_INTL(MSG_STR_SECTION), 1772 cache[sym.st_shndx].c_name); 1773 name = (const char *)sct; 1774 } else { 1775 name = demangle(string(_cache, 1776 /* LINTED */ 1777 (GElf_Word)GELF_M_SYM(move.m_info), 1778 &cache[shdr->sh_link], file, 1779 sym.st_name), flags); 1780 } 1781 } 1782 1783 /* 1784 * Additional sanity check. 1785 */ 1786 shndx = sym.st_shndx; 1787 if (!((shndx == SHN_COMMON) || 1788 (((shndx >= 1) && (shndx <= shnum)) && 1789 (cache[shndx].c_shdr).sh_type == SHT_NOBITS))) { 1790 (void) fprintf(stderr, 1791 MSG_INTL(MSG_ERR_BADSYM2), file, 1792 _cache->c_name, name); 1793 (void) fflush(stderr); 1794 } 1795 1796 dbg_print(fmt, EC_XWORD(move.m_poffset), 1797 EC_XWORD(GELF_M_SYM(move.m_info)), 1798 /* LINTED */ 1799 GELF_M_SIZE(move.m_info), move.m_repeat, 1800 move.m_stride, EC_LWORD(move.m_value), name); 1801 } 1802 } 1803 } 1804 1805 /* 1806 * Traverse a note section analyzing each note information block. 1807 * The data buffers size is used to validate references before they are made, 1808 * and is decremented as each element is processed. 1809 */ 1810 void 1811 note_entry(Cache *cache, Word *data, Word size, const char *file) 1812 { 1813 Word bsize = size; 1814 /* 1815 * Print out a single `note' information block. 1816 */ 1817 while (size > 0) { 1818 Word namesz, descsz, type, pad, noteoff; 1819 1820 1821 noteoff = bsize - size; 1822 /* 1823 * Make sure we can at least reference the 3 initial entries 1824 * (4-byte words) of the note information block. 1825 */ 1826 if (size >= (Word)(sizeof (Word) * 3)) 1827 size -= (Word)(sizeof (Word) * 3); 1828 else { 1829 (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASIZE), 1830 file, cache->c_name, EC_WORD(noteoff)); 1831 (void) fflush(stderr); 1832 return; 1833 } 1834 1835 /* 1836 * Make sure any specified name string can be referenced. 1837 */ 1838 if ((namesz = *data++) != 0) { 1839 if (size >= namesz) 1840 size -= namesz; 1841 else { 1842 (void) fprintf(stderr, 1843 MSG_INTL(MSG_NOTE_BADNMSIZE), 1844 file, cache->c_name, EC_WORD(noteoff), 1845 EC_WORD(namesz)); 1846 (void) fflush(stderr); 1847 return; 1848 } 1849 } 1850 /* 1851 * Make sure any specified descriptor can be referenced. 1852 */ 1853 if ((descsz = *data++) != 0) { 1854 /* 1855 * If namesz isn't a 4-byte multiple, account for any 1856 * padding that must exist before the descriptor. 1857 */ 1858 if ((pad = (namesz & (Word)(sizeof (Word) - 1))) != 0) { 1859 pad = (Word)sizeof (Word) - pad; 1860 size -= pad; 1861 } 1862 if (size >= descsz) 1863 size -= descsz; 1864 else { 1865 (void) fprintf(stderr, 1866 MSG_INTL(MSG_NOTE_BADDESIZE), 1867 file, cache->c_name, EC_WORD(noteoff), 1868 EC_WORD(namesz)); 1869 (void) fflush(stderr); 1870 return; 1871 } 1872 } 1873 1874 type = *data++; 1875 1876 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1877 dbg_print(MSG_ORIG(MSG_NOTE_TYPE), EC_WORD(type)); 1878 1879 dbg_print(MSG_ORIG(MSG_NOTE_NAMESZ), EC_WORD(namesz)); 1880 if (namesz) { 1881 char *name = (char *)data; 1882 1883 /* 1884 * Since the name string may have 'null' bytes 1885 * in it (ia32 .string) - we just write the 1886 * whole stream in a single fwrite. 1887 */ 1888 (void) fwrite(name, namesz, 1, stdout); 1889 name = name + ((namesz + (sizeof (Word) - 1)) & 1890 ~(sizeof (Word) - 1)); 1891 /* LINTED */ 1892 data = (Word *)name; 1893 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1894 } 1895 1896 /* 1897 * If multiple information blocks exist within a .note section 1898 * account for any padding that must exist before the next 1899 * information block. 1900 */ 1901 if ((pad = (descsz & (Word)(sizeof (Word) - 1))) != 0) { 1902 pad = (Word)sizeof (Word) - pad; 1903 if (size > pad) 1904 size -= pad; 1905 } 1906 1907 dbg_print(MSG_ORIG(MSG_NOTE_DESCSZ), EC_WORD(descsz)); 1908 if (descsz) { 1909 int ndx, byte, word; 1910 char string[58], * str = string; 1911 uchar_t *desc = (uchar_t *)data; 1912 1913 /* 1914 * Dump descriptor bytes. 1915 */ 1916 for (ndx = byte = word = 0; descsz; descsz--, desc++) { 1917 int tok = *desc; 1918 1919 (void) snprintf(str, 58, MSG_ORIG(MSG_NOTE_TOK), 1920 tok); 1921 str += 3; 1922 1923 if (++byte == 4) { 1924 *str++ = ' ', *str++ = ' '; 1925 word++; 1926 byte = 0; 1927 } 1928 if (word == 4) { 1929 *str = '\0'; 1930 dbg_print(MSG_ORIG(MSG_NOTE_DESC), 1931 ndx, string); 1932 word = 0; 1933 ndx += 16; 1934 str = string; 1935 } 1936 } 1937 if (byte || word) { 1938 *str = '\0'; 1939 dbg_print(MSG_ORIG(MSG_NOTE_DESC), ndx, string); 1940 } 1941 1942 desc += pad; 1943 /* LINTED */ 1944 data = (Word *)desc; 1945 } 1946 } 1947 } 1948 1949 /* 1950 * Search for and process a .note section. 1951 */ 1952 static void 1953 note(Cache *cache, GElf_Word shnum, const char *name, const char *file) 1954 { 1955 GElf_Word cnt; 1956 1957 /* 1958 * Otherwise look for any .note sections. 1959 */ 1960 for (cnt = 1; cnt < shnum; cnt++) { 1961 Cache * _cache = &cache[cnt]; 1962 GElf_Shdr * shdr = &_cache->c_shdr; 1963 1964 if (shdr->sh_type != SHT_NOTE) 1965 continue; 1966 if (name && strcmp(name, _cache->c_name)) 1967 continue; 1968 1969 /* 1970 * As these sections are often hand rolled, make sure they're 1971 * properly aligned before proceeding. 1972 */ 1973 if (shdr->sh_offset & (sizeof (Word) - 1)) { 1974 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN), 1975 file, _cache->c_name); 1976 (void) fflush(stderr); 1977 continue; 1978 } 1979 1980 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1981 dbg_print(MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name); 1982 note_entry(_cache, (Word *)_cache->c_data->d_buf, 1983 /* LINTED */ 1984 (Word)_cache->c_data->d_size, file); 1985 } 1986 } 1987 1988 1989 #define MAXCOUNT 500 1990 1991 static void 1992 hash(Cache *cache, GElf_Word shnum, const char *name, const char *file, 1993 uint32_t flags) 1994 { 1995 static int count[MAXCOUNT]; 1996 GElf_Word cnt; 1997 ulong_t ndx, bkts; 1998 char number[MAXNDXSIZE]; 1999 2000 for (cnt = 1; cnt < shnum; cnt++) { 2001 uint_t *hash, *chain; 2002 Elf_Data *dsyms; 2003 Cache *_cache = &cache[cnt]; 2004 GElf_Shdr *shdr = &_cache->c_shdr; 2005 char *sname; 2006 2007 if (shdr->sh_type != SHT_HASH) 2008 continue; 2009 if (name && strcmp(name, _cache->c_name)) 2010 continue; 2011 2012 /* 2013 * Determine the hash table data and size. 2014 */ 2015 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 2016 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2017 file, _cache->c_name); 2018 (void) fflush(stderr); 2019 continue; 2020 } 2021 hash = (uint_t *)_cache->c_data->d_buf; 2022 bkts = *hash; 2023 chain = hash + 2 + bkts; 2024 hash += 2; 2025 2026 /* 2027 * Get the data buffer for the associated symbol table. 2028 */ 2029 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 2030 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2031 file, _cache->c_name, EC_XWORD(shdr->sh_link)); 2032 (void) fflush(stderr); 2033 continue; 2034 } 2035 dsyms = cache[shdr->sh_link].c_data; 2036 if (dsyms->d_buf == 0) { 2037 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2038 file, cache[shdr->sh_link].c_name); 2039 (void) fflush(stderr); 2040 continue; 2041 } 2042 2043 sname = cache[shdr->sh_link].c_name; 2044 shdr = &cache[shdr->sh_link].c_shdr; 2045 /* 2046 * Get the associated string table section. 2047 */ 2048 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 2049 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2050 file, sname, EC_XWORD(shdr->sh_link)); 2051 (void) fflush(stderr); 2052 continue; 2053 } 2054 2055 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 2056 dbg_print(MSG_INTL(MSG_ELF_SCN_HASH), _cache->c_name); 2057 dbg_print(MSG_INTL(MSG_ELF_HASH_INFO)); 2058 2059 /* 2060 * Loop through the hash buckets, printing the appropriate 2061 * symbols. 2062 */ 2063 for (ndx = 0; ndx < bkts; ndx++, hash++) { 2064 GElf_Sym _sym; 2065 const char *_str; 2066 GElf_Word _ndx, _cnt; 2067 char _number[MAXNDXSIZE]; 2068 ulong_t nbkt, nhash; 2069 2070 if (*hash == 0) { 2071 count[0]++; 2072 continue; 2073 } 2074 2075 /* LINTED */ 2076 if (gelf_getsym(dsyms, (int)*hash, &_sym) == NULL) { 2077 (void) fprintf(stderr, 2078 MSG_INTL(MSG_ERR_HSBADSYMNDX), 2079 file, elf_errmsg(0)); 2080 (void) fflush(stderr); 2081 _str = MSG_INTL(MSG_STR_UNKNOWN); 2082 } else { 2083 _str = string(_cache, (GElf_Word)*hash, 2084 &cache[shdr->sh_link], file, 2085 _sym.st_name); 2086 } 2087 2088 (void) snprintf(number, MAXNDXSIZE, 2089 /* LINTED */ 2090 MSG_ORIG(MSG_FMT_INTEGER), (int)ndx); 2091 (void) snprintf(_number, MAXNDXSIZE, 2092 MSG_ORIG(MSG_FMT_INDEX2), EC_XWORD(*hash)); 2093 dbg_print(MSG_ORIG(MSG_FMT_HASH_INFO), number, _number, 2094 demangle(_str, flags)); 2095 2096 /* 2097 * Determine if this string is in the correct bucket. 2098 */ 2099 nhash = elf_hash(_str); 2100 nbkt = nhash % bkts; 2101 if (nbkt != ndx) { 2102 (void) fprintf(stderr, 2103 MSG_INTL(MSG_ERR_BADHASH), file, 2104 /* LINTED */ 2105 _cache->c_name, _str, (int)ndx, (int)nbkt); 2106 (void) fflush(stderr); 2107 } 2108 2109 /* 2110 * Determine if any other symbols are chained to this 2111 * bucket. 2112 */ 2113 _ndx = chain[*hash]; 2114 _cnt = 1; 2115 while (_ndx) { 2116 /* LINTED */ 2117 if (gelf_getsym(dsyms, (int)_ndx, 2118 &_sym) == NULL) { 2119 (void) fprintf(stderr, 2120 MSG_INTL(MSG_ERR_HSBADSYMNDX), 2121 file, elf_errmsg(0)); 2122 (void) fflush(stderr); 2123 _str = MSG_INTL(MSG_STR_UNKNOWN); 2124 } else 2125 _str = string(_cache, _ndx, 2126 &cache[shdr->sh_link], file, 2127 _sym.st_name); 2128 2129 (void) snprintf(_number, MAXNDXSIZE, 2130 MSG_ORIG(MSG_FMT_INDEX2), EC_XWORD(_ndx)); 2131 dbg_print(MSG_ORIG(MSG_FMT_HASH_INFO), 2132 MSG_ORIG(MSG_STR_EMPTY), _number, 2133 demangle(_str, flags)); 2134 _ndx = chain[_ndx]; 2135 _cnt++; 2136 2137 /* 2138 * Determine if this string is in the correct 2139 * bucket. 2140 */ 2141 nhash = elf_hash(_str); 2142 nbkt = nhash % bkts; 2143 if (nbkt != ndx) { 2144 (void) fprintf(stderr, 2145 MSG_INTL(MSG_ERR_BADHASH), file, 2146 _cache->c_name, _str, 2147 /* LINTED */ 2148 (int)ndx, (int)nbkt); 2149 (void) fflush(stderr); 2150 } 2151 } 2152 2153 if (_cnt >= MAXCOUNT) { 2154 (void) fprintf(stderr, 2155 MSG_INTL(MSG_HASH_OVERFLW), file, 2156 _cache->c_name, 2157 /* LINTED */ 2158 (int)ndx, _cnt); 2159 (void) fflush(stderr); 2160 } else 2161 count[_cnt]++; 2162 } 2163 break; 2164 } 2165 2166 /* 2167 * Print out the count information. 2168 */ 2169 bkts = cnt = 0; 2170 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 2171 for (ndx = 0; ndx < MAXCOUNT; ndx++) { 2172 GElf_Word _cnt; 2173 2174 if ((_cnt = count[ndx]) == 0) 2175 continue; 2176 2177 (void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 2178 /* LINTED */ 2179 (int)_cnt); 2180 /* LINTED */ 2181 dbg_print(MSG_INTL(MSG_ELF_HASH_BKTS1), number, (int)ndx); 2182 bkts += _cnt; 2183 /* LINTED */ 2184 cnt += (GElf_Word)(ndx * _cnt); 2185 } 2186 if (cnt) { 2187 (void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 2188 /* LINTED */ 2189 (int)bkts); 2190 /* LINTED */ 2191 dbg_print(MSG_INTL(MSG_ELF_HASH_BKTS2), number, (int)cnt); 2192 } 2193 } 2194 2195 2196 static void 2197 group(Cache *cache, GElf_Word shnum, const char *name, const char *file, 2198 uint32_t flags) 2199 { 2200 GElf_Word cnt; 2201 2202 for (cnt = 1; cnt < shnum; cnt++) { 2203 Cache *_cache = &cache[cnt]; 2204 GElf_Shdr *shdr = &_cache->c_shdr; 2205 Elf_Data *dsyms; 2206 GElf_Shdr *symshdr; 2207 GElf_Sym sym; 2208 const char *symname; 2209 char flgstrbuf[MSG_GRP_COMDAT_SIZE + 10]; 2210 Word *grpdata; 2211 size_t _cnt; 2212 size_t grpcnt; 2213 2214 2215 if (shdr->sh_type != SHT_GROUP) 2216 continue; 2217 if (name && strcmp(name, _cache->c_name)) 2218 continue; 2219 dbg_print(MSG_INTL(MSG_GRP_LINE1), _cache->c_name); 2220 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 2221 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2222 file, _cache->c_name, EC_XWORD(shdr->sh_link)); 2223 (void) fflush(stderr); 2224 continue; 2225 } 2226 2227 if (shdr->sh_entsize != sizeof (Word)) { 2228 (void) fprintf(stderr, MSG_INTL(MSG_GRP_BADENTSZ), 2229 file, _cache->c_name, 2230 EC_XWORD(shdr->sh_entsize)); 2231 (void) fflush(stderr); 2232 } 2233 symshdr = &(cache[shdr->sh_link].c_shdr); 2234 if ((symshdr->sh_type != SHT_SYMTAB) && 2235 (symshdr->sh_type != SHT_DYNSYM)) { 2236 (void) fprintf(stderr, MSG_INTL(MSG_GRP_NOTSYMTAB), 2237 file, _cache->c_name, EC_XWORD(shdr->sh_link)); 2238 (void) fflush(stderr); 2239 continue; 2240 } 2241 dsyms = cache[shdr->sh_link].c_data; 2242 if ((shdr->sh_info == SHN_UNDEF) || ((ulong_t)shdr->sh_info > 2243 (symshdr->sh_size / symshdr->sh_entsize))) { 2244 (void) fprintf(stderr, MSG_INTL(MSG_GRP_BADSYMNDX), 2245 file, _cache->c_name, EC_XWORD(shdr->sh_info)); 2246 (void) fflush(stderr); 2247 continue; 2248 } 2249 flgstrbuf[0] = '['; 2250 flgstrbuf[1] = '\0'; 2251 if ((shdr->sh_size != 0) && 2252 (_cache->c_data) && 2253 ((grpdata = (Word *)_cache->c_data->d_buf) != 0)) { 2254 if (grpdata[0] & GRP_COMDAT) { 2255 (void) strcat(flgstrbuf, 2256 MSG_ORIG(MSG_GRP_COMDAT)); 2257 } 2258 if ((grpdata[0] & ~GRP_COMDAT) != 0) { 2259 (void) snprintf(flgstrbuf + strlen(flgstrbuf), 2260 (MSG_GRP_COMDAT_SIZE + 10), 2261 MSG_ORIG(MSG_GRP_FMT1), 2262 (uint_t)(grpdata[0] & ~GRP_COMDAT)); 2263 } 2264 } 2265 (void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_CLOSBRKT)); 2266 2267 if (gelf_getsym(dsyms, shdr->sh_info, &sym) == NULL) { 2268 (void) fprintf(stderr, 2269 MSG_INTL(MSG_ERR_GRBADSYMNDX), 2270 file, elf_errmsg(0)); 2271 (void) fflush(stderr); 2272 } 2273 symname = demangle(string(_cache, shdr->sh_link, 2274 &cache[symshdr->sh_link], file, sym.st_name), 2275 flags); 2276 dbg_print(MSG_INTL(MSG_GRP_LINE2)); 2277 dbg_print(MSG_INTL(MSG_GRP_LINE3), 2278 flgstrbuf, symname); 2279 for (_cnt = 1, grpcnt = (shdr->sh_size / sizeof (Word)); 2280 _cnt < grpcnt; _cnt++) { 2281 char index[MAXNDXSIZE]; 2282 const char *sname; 2283 2284 (void) snprintf(index, MAXNDXSIZE, 2285 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(_cnt)); 2286 if (grpdata[_cnt] >= shnum) { 2287 sname = MSG_INTL(MSG_GRP_INVALSCN); 2288 } else { 2289 sname = cache[grpdata[_cnt]].c_name; 2290 } 2291 (void) printf(MSG_ORIG(MSG_GRP_FMT2), index, sname, 2292 (uint_t)grpdata[_cnt]); 2293 } 2294 } 2295 } 2296 2297 2298 static void 2299 got(Cache *cache, GElf_Word shnum, GElf_Word phnum, GElf_Ehdr *ehdr, 2300 const char *file) 2301 { 2302 Cache *gotcache = 0, *symtab = 0, *_cache; 2303 GElf_Addr gotbgn, gotend; 2304 GElf_Shdr *gotshdr; 2305 GElf_Word cnt, gotents, gotndx; 2306 size_t gentsize; 2307 Got_info *gottable; 2308 char *gotdata; 2309 GElf_Sym gsym; 2310 GElf_Xword gsymaddr; 2311 2312 /* 2313 * First, find the got. 2314 */ 2315 for (cnt = 1; cnt < shnum; cnt++) { 2316 _cache = &cache[cnt]; 2317 if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT), 2318 MSG_ELF_GOT_SIZE) == 0) { 2319 gotcache = _cache; 2320 break; 2321 } 2322 } 2323 if (!gotcache) 2324 return; 2325 2326 /* 2327 * A got section within a relocatable object is suspicious. 2328 */ 2329 if (ehdr->e_type == ET_REL) { 2330 (void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file, 2331 _cache->c_name); 2332 (void) fflush(stderr); 2333 } 2334 2335 gotshdr = &gotcache->c_shdr; 2336 gotbgn = gotshdr->sh_addr; 2337 2338 if (gotshdr->sh_size == 0) { 2339 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2340 file, gotcache->c_name); 2341 (void) fflush(stderr); 2342 return; 2343 } 2344 gotend = gotbgn + gotshdr->sh_size; 2345 2346 /* 2347 * Some architectures don't properly set the sh_entsize 2348 * for the GOT table. If it's not set we will default 2349 * to a size of a pointer. 2350 */ 2351 if ((gentsize = gotshdr->sh_entsize) == 0) { 2352 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) 2353 gentsize = sizeof (GElf_Xword); 2354 else 2355 gentsize = sizeof (GElf_Word); 2356 } 2357 /* LINTED */ 2358 gotents = (GElf_Word)(gotshdr->sh_size / gentsize); 2359 gotdata = gotcache->c_data->d_buf; 2360 2361 if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) { 2362 int err = errno; 2363 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2364 file, strerror(err)); 2365 (void) fflush(stderr); 2366 return; 2367 } 2368 2369 /* 2370 * Now we scan through all the sections looking for any relocations 2371 * that may be against the GOT. Since these may not be isolated to a 2372 * .rel[a].got section we check them all. 2373 * While scanning sections save the symbol table entry (a symtab 2374 * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_. 2375 */ 2376 for (cnt = 1; cnt < shnum; cnt++) { 2377 GElf_Shdr *shdr; 2378 GElf_Word rtype; 2379 Elf_Data *dsyms, *reldata; 2380 GElf_Rela rela; 2381 ulong_t rcount; 2382 int ndx; 2383 char *sname; 2384 2385 _cache = &cache[cnt]; 2386 shdr = &_cache->c_shdr; 2387 2388 if ((symtab == 0) && (shdr->sh_type == SHT_DYNSYM)) { 2389 symtab = _cache; 2390 continue; 2391 } 2392 if (shdr->sh_type == SHT_SYMTAB) { 2393 symtab = _cache; 2394 continue; 2395 } 2396 2397 rtype = shdr->sh_type; 2398 if ((rtype != SHT_RELA) && (rtype != SHT_REL)) 2399 continue; 2400 2401 /* 2402 * Determine the relocation data and number. 2403 */ 2404 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 2405 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2406 file, _cache->c_name); 2407 (void) fflush(stderr); 2408 continue; 2409 } 2410 rcount = shdr->sh_size / shdr->sh_entsize; 2411 2412 reldata = _cache->c_data; 2413 2414 /* 2415 * Get the data buffer for the associated symbol table. 2416 */ 2417 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 2418 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2419 file, _cache->c_name, EC_XWORD(shdr->sh_link)); 2420 (void) fflush(stderr); 2421 continue; 2422 } 2423 dsyms = cache[shdr->sh_link].c_data; 2424 if (dsyms->d_buf == 0) { 2425 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2426 file, cache[shdr->sh_link].c_name); 2427 (void) fflush(stderr); 2428 continue; 2429 } 2430 2431 sname = cache[shdr->sh_link].c_name; 2432 shdr = &cache[shdr->sh_link].c_shdr; 2433 /* 2434 * Get the associated string table section. 2435 */ 2436 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 2437 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2438 file, sname, EC_XWORD(shdr->sh_link)); 2439 (void) fflush(stderr); 2440 continue; 2441 } 2442 2443 /* LINTED */ 2444 for (ndx = 0; ndx < rcount; ++ndx) { 2445 GElf_Sym _sym; 2446 GElf_Word sndx; 2447 GElf_Addr offset; 2448 Got_info *gip; 2449 void *relret; 2450 2451 if (rtype == SHT_RELA) { 2452 relret = (void *)gelf_getrela(reldata, ndx, 2453 &rela); 2454 } else { 2455 relret = (void *)gelf_getrel(reldata, ndx, 2456 (GElf_Rel *)&rela); 2457 } 2458 if (relret == NULL) { 2459 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADREL), 2460 file, _cache->c_name, elf_errmsg(0)); 2461 (void) fflush(stderr); 2462 break; 2463 } 2464 2465 offset = rela.r_offset; 2466 /* LINTED */ 2467 sndx = (GElf_Word)GELF_R_SYM(rela.r_info); 2468 2469 /* 2470 * Only pay attention to relocations against the GOT. 2471 */ 2472 if ((offset < gotbgn) || (offset > gotend)) 2473 continue; 2474 2475 /* LINTED */ 2476 gotndx = (GElf_Word)((offset - gotbgn) / 2477 gotshdr->sh_entsize); 2478 gip = &gottable[gotndx]; 2479 if (gip->g_rshtype != 0) { 2480 (void) fprintf(stderr, 2481 MSG_INTL(MSG_GOT_MULTIPLE), file, 2482 /* LINTED */ 2483 EC_WORD(gotndx), EC_XWORD(offset)); 2484 (void) fflush(stderr); 2485 continue; 2486 } 2487 2488 /* LINTED */ 2489 if (gelf_getsym(dsyms, sndx, &_sym) == NULL) { 2490 (void) fprintf(stderr, 2491 MSG_INTL(MSG_ERR_RELBADSYMNDX), 2492 file, elf_errmsg(0)); 2493 (void) fflush(stderr); 2494 gip->g_symname = MSG_INTL(MSG_STR_UNKNOWN); 2495 } else { 2496 gip->g_symname = string(_cache, sndx, 2497 &cache[shdr->sh_link], file, _sym.st_name); 2498 } 2499 gip->g_rshtype = rtype; 2500 gip->g_rela = rela; 2501 } 2502 } 2503 2504 if (symlookup(MSG_ORIG(MSG_GOT_SYM), cache, shnum, &gsym, symtab, file)) 2505 gsymaddr = gsym.st_value; 2506 else 2507 gsymaddr = gotbgn; 2508 2509 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 2510 dbg_print(MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name, gotents); 2511 Gelf_got_title(ehdr->e_ident[EI_CLASS]); 2512 2513 for (gotndx = 0; gotndx < gotents; gotndx++) { 2514 Got_info *gip; 2515 Sword gindex; 2516 GElf_Addr gaddr; 2517 GElf_Xword gotentry; 2518 2519 gip = &gottable[gotndx]; 2520 2521 gaddr = gotbgn + (gotndx * gentsize); 2522 /* LINTED */ 2523 gindex = (Sword)((gaddr - gsymaddr) / gentsize); 2524 2525 if (gentsize == sizeof (GElf_Word)) 2526 /* LINTED */ 2527 gotentry = (GElf_Xword)(*((GElf_Word *)(gotdata) + 2528 gotndx)); 2529 else 2530 /* LINTED */ 2531 gotentry = *((GElf_Xword *)(gotdata) + gotndx); 2532 2533 Gelf_got_entry(ehdr, gindex, gaddr, gotentry, gip->g_rshtype, 2534 &gip->g_rela, gip->g_symname); 2535 } 2536 2537 free(gottable); 2538 } 2539 2540 void 2541 checksum(Elf *elf) 2542 { 2543 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 2544 dbg_print(MSG_INTL(MSG_STR_CHECKSUM), gelf_checksum(elf)); 2545 } 2546 2547 static void 2548 regular(const char *file, Elf *elf, uint32_t flags, char *Nname, int wfd) 2549 { 2550 Elf_Scn *scn; 2551 GElf_Ehdr ehdr; 2552 Elf_Data *data; 2553 uint_t cnt; 2554 GElf_Word shnum, phnum; 2555 size_t shstrndx, _shnum, _phnum; 2556 GElf_Shdr nameshdr; 2557 GElf_Shdr shdr0; 2558 GElf_Shdr *_shdr0; 2559 char *names = 0; 2560 Cache *cache, *_cache; 2561 Cache *versymcache; 2562 2563 if (gelf_getehdr(elf, &ehdr) == NULL) { 2564 failure(file, MSG_ORIG(MSG_ELF_GETEHDR)); 2565 return; 2566 } 2567 2568 if (elf_getshnum(elf, &_shnum) == 0) { 2569 failure(file, MSG_ORIG(MSG_ELF_GETSHNUM)); 2570 return; 2571 } 2572 /* LINTED */ 2573 shnum = (GElf_Word)_shnum; 2574 2575 if (elf_getshstrndx(elf, &shstrndx) == 0) { 2576 failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX)); 2577 return; 2578 } 2579 2580 if (elf_getphnum(elf, &_phnum) == 0) { 2581 failure(file, MSG_ORIG(MSG_ELF_GETPHNUM)); 2582 return; 2583 } 2584 /* LINTED */ 2585 phnum = (GElf_Word)_phnum; 2586 2587 if ((scn = elf_getscn(elf, 0)) != NULL) { 2588 if ((_shdr0 = gelf_getshdr(scn, &shdr0)) == NULL) { 2589 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2590 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0); 2591 (void) fflush(stderr); 2592 return; 2593 } 2594 } else 2595 _shdr0 = 0; 2596 2597 /* 2598 * Print the elf header. 2599 */ 2600 if (flags & FLG_EHDR) 2601 Gelf_elf_header(&ehdr, _shdr0); 2602 2603 /* 2604 * Print the program headers. 2605 */ 2606 if ((flags & FLG_PHDR) && phnum != 0) { 2607 GElf_Phdr phdr; 2608 2609 for (cnt = 0; cnt < phnum; cnt++) { 2610 if (gelf_getphdr(elf, cnt, &phdr) == NULL) { 2611 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 2612 return; 2613 } 2614 2615 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 2616 dbg_print(MSG_INTL(MSG_ELF_PHDR), cnt); 2617 Gelf_phdr_entry(ehdr.e_machine, &phdr); 2618 } 2619 } 2620 2621 2622 /* 2623 * Return now if there are no section, if there's just one section to 2624 * act as an extension of the ELF header, or if on section information 2625 * was requested. 2626 */ 2627 if ((shnum <= 1) || (flags && (flags & ~(FLG_EHDR | FLG_PHDR)) == 0)) { 2628 if ((ehdr.e_type == ET_CORE) && (flags & FLG_NOTE)) 2629 note(0, shnum, 0, file); 2630 return; 2631 } 2632 2633 /* 2634 * Obtain the .shstrtab data buffer to provide the required section 2635 * name strings. 2636 */ 2637 if ((scn = elf_getscn(elf, shstrndx)) == NULL) { 2638 failure(file, MSG_ORIG(MSG_ELF_GETSCN)); 2639 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR), 2640 EC_XWORD(shstrndx)); 2641 (void) fflush(stderr); 2642 } else if ((data = elf_getdata(scn, NULL)) == NULL) { 2643 failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 2644 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA), 2645 EC_XWORD(shstrndx)); 2646 (void) fflush(stderr); 2647 } else if (gelf_getshdr(scn, &nameshdr) == NULL) { 2648 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2649 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 2650 /* LINTED */ 2651 (int)elf_ndxscn(scn)); 2652 (void) fflush(stderr); 2653 } else if ((names = data->d_buf) == 0) { 2654 (void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file); 2655 (void) fflush(stderr); 2656 } 2657 2658 /* 2659 * Fill in the cache descriptor with information for each section. 2660 */ 2661 if ((cache = malloc(shnum * sizeof (Cache))) == 0) { 2662 int err = errno; 2663 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2664 file, strerror(err)); 2665 (void) fflush(stderr); 2666 return; 2667 } 2668 2669 *cache = _cache_init; 2670 _cache = cache; 2671 _cache++; 2672 2673 for (cnt = 1, scn = NULL; scn = elf_nextscn(elf, scn); 2674 cnt++, _cache++) { 2675 if (gelf_getshdr(scn, &_cache->c_shdr) == NULL) { 2676 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2677 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 2678 /* LINTED */ 2679 (int)elf_ndxscn(scn)); 2680 (void) fflush(stderr); 2681 } 2682 2683 if (names && _cache->c_shdr.sh_name && 2684 /* LINTED */ 2685 (nameshdr.sh_size > _cache->c_shdr.sh_name)) 2686 _cache->c_name = names + _cache->c_shdr.sh_name; 2687 else { 2688 /* 2689 * If there exists no shstrtab data, or a section header 2690 * has no name (an invalid index of 0), then compose a 2691 * name for each section. 2692 */ 2693 char scnndxnm[100]; 2694 2695 (void) snprintf(scnndxnm, 100, MSG_INTL(MSG_FMT_SCNNDX), 2696 cnt); 2697 2698 /* 2699 * Although we have a valid shstrtab section inform the 2700 * user if this section name index exceeds the shstrtab 2701 * data. 2702 */ 2703 if (names && 2704 /* LINTED */ 2705 (nameshdr.sh_size <= _cache->c_shdr.sh_name)) { 2706 (void) fprintf(stderr, 2707 MSG_INTL(MSG_ERR_BADSHNAME), file, 2708 _cache->c_name, 2709 EC_XWORD(_cache->c_shdr.sh_name)); 2710 (void) fflush(stderr); 2711 } 2712 2713 if ((_cache->c_name = 2714 malloc(strlen(scnndxnm) + 1)) == 0) { 2715 int err = errno; 2716 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2717 file, strerror(err)); 2718 (void) fflush(stderr); 2719 return; 2720 } 2721 (void) strcpy(_cache->c_name, scnndxnm); 2722 } 2723 2724 if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) { 2725 failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 2726 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA), 2727 /* LINTED */ 2728 (int)elf_ndxscn(scn)); 2729 (void) fflush(stderr); 2730 } 2731 2732 /* 2733 * Do we wish to write the section out? 2734 */ 2735 if (wfd && Nname && (strcmp(Nname, _cache->c_name) == 0)) { 2736 (void) write(wfd, _cache->c_data->d_buf, 2737 _cache->c_data->d_size); 2738 } 2739 } 2740 2741 if (flags & FLG_SHDR) 2742 sections(file, cache, shnum, phnum, &ehdr, Nname); 2743 2744 if (flags & FLG_INTERP) 2745 interp(file, cache, shnum, phnum, &ehdr, elf); 2746 2747 versymcache = versions(cache, shnum, file, flags); 2748 2749 if (flags & FLG_SYMBOLS) 2750 symbols(cache, shnum, phnum, &ehdr, Nname, versymcache, file); 2751 2752 if (flags & FLG_HASH) 2753 hash(cache, shnum, Nname, file, flags); 2754 2755 if (flags & FLG_GOT) 2756 got(cache, shnum, phnum, &ehdr, file); 2757 2758 if (flags & FLG_GROUP) 2759 group(cache, shnum, Nname, file, flags); 2760 2761 if (flags & FLG_SYMINFO) 2762 syminfo(cache, shnum, file); 2763 2764 if (flags & FLG_RELOC) 2765 reloc(cache, shnum, phnum, &ehdr, Nname, file, flags); 2766 2767 if (flags & FLG_DYNAMIC) 2768 dynamic(cache, shnum, &ehdr, file); 2769 2770 if (flags & FLG_NOTE) 2771 note(cache, shnum, Nname, file); 2772 2773 if (flags & FLG_MOVE) 2774 move(cache, shnum, Nname, file, flags); 2775 2776 if (flags & FLG_CHECKSUM) 2777 checksum(elf); 2778 2779 if (flags & FLG_CAP) 2780 cap(file, cache, shnum, phnum, &ehdr, elf); 2781 2782 if (flags & FLG_UNWIND) 2783 unwind(cache, shnum, phnum, &ehdr, Nname, file, elf); 2784 2785 free(cache); 2786 } 2787 2788 static void 2789 archive(const char *file, int fd, Elf *elf, uint32_t flags, char *Nname, 2790 int wfd) 2791 { 2792 Elf_Cmd cmd = ELF_C_READ; 2793 Elf_Arhdr *arhdr; 2794 Elf *_elf = 0; 2795 size_t ptr; 2796 Elf_Arsym *arsym = 0; 2797 2798 /* 2799 * Determine if the archive sysmbol table itself is required. 2800 */ 2801 if ((flags & FLG_SYMBOLS) && ((Nname == NULL) || 2802 (strcmp(Nname, MSG_ORIG(MSG_ELF_ARSYM)) == 0))) { 2803 /* 2804 * Get the archive symbol table. 2805 */ 2806 if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) { 2807 /* 2808 * The arsym could be 0 even though there was no error. 2809 * Print the error message only when there was 2810 * real error from elf_getarsym(). 2811 */ 2812 failure(file, MSG_ORIG(MSG_ELF_GETARSYM)); 2813 return; 2814 } 2815 } 2816 2817 /* 2818 * Print the archive symbol table only when the archive symbol 2819 * table exists and it was requested to print. 2820 */ 2821 if (arsym) { 2822 size_t cnt; 2823 char index[MAXNDXSIZE]; 2824 size_t offset = 0, _offset = 0; 2825 2826 /* 2827 * Print out all the symbol entries. 2828 */ 2829 dbg_print(MSG_INTL(MSG_ARCHIVE_SYMTAB)); 2830 dbg_print(MSG_INTL(MSG_ARCHIVE_FIELDS)); 2831 2832 for (cnt = 0; cnt < ptr; cnt++, arsym++) { 2833 /* 2834 * For each object obtain an elf descriptor so that we 2835 * can establish the members name. Note, we have had 2836 * archives where the archive header has not been 2837 * obtainable so be lenient with errors. 2838 */ 2839 if ((offset == 0) || ((arsym->as_off != 0) && 2840 (arsym->as_off != _offset))) { 2841 2842 if (_elf) 2843 (void) elf_end(_elf); 2844 2845 if (elf_rand(elf, arsym->as_off) != 2846 arsym->as_off) { 2847 failure(file, MSG_ORIG(MSG_ELF_RAND)); 2848 arhdr = 0; 2849 } else if ((_elf = elf_begin(fd, 2850 ELF_C_READ, elf)) == 0) { 2851 failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 2852 arhdr = 0; 2853 } else if ((arhdr = elf_getarhdr(_elf)) == 0) { 2854 failure(file, 2855 MSG_ORIG(MSG_ELF_GETARHDR)); 2856 arhdr = 0; 2857 } 2858 2859 _offset = arsym->as_off; 2860 if (offset == 0) 2861 offset = _offset; 2862 } 2863 2864 (void) snprintf(index, MAXNDXSIZE, 2865 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt)); 2866 if (arsym->as_off) 2867 dbg_print(MSG_ORIG(MSG_FMT_ARSYM1), index, 2868 /* LINTED */ 2869 (int)arsym->as_off, arhdr ? arhdr->ar_name : 2870 MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ? 2871 demangle(arsym->as_name, flags) : 2872 MSG_INTL(MSG_STR_NULL))); 2873 else 2874 dbg_print(MSG_ORIG(MSG_FMT_ARSYM2), index, 2875 /* LINTED */ 2876 (int)arsym->as_off); 2877 } 2878 2879 if (_elf) 2880 (void) elf_end(_elf); 2881 2882 /* 2883 * If we only need the archive symbol table return. 2884 */ 2885 if ((flags & FLG_SYMBOLS) && Nname && 2886 (strcmp(Nname, MSG_ORIG(MSG_ELF_ARSYM)) == 0)) 2887 return; 2888 2889 /* 2890 * Reset elf descriptor in preparation for processing each 2891 * member. 2892 */ 2893 if (offset) 2894 (void) elf_rand(elf, offset); 2895 } 2896 2897 /* 2898 * Process each object within the archive. 2899 */ 2900 while ((_elf = elf_begin(fd, cmd, elf)) != NULL) { 2901 char name[MAXPATHLEN]; 2902 2903 if ((arhdr = elf_getarhdr(_elf)) == NULL) { 2904 failure(file, MSG_ORIG(MSG_ELF_GETARHDR)); 2905 return; 2906 } 2907 if (*arhdr->ar_name != '/') { 2908 (void) snprintf(name, MAXPATHLEN, 2909 MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name); 2910 dbg_print(MSG_ORIG(MSG_FMT_NLSTR), name); 2911 2912 switch (elf_kind(_elf)) { 2913 case ELF_K_AR: 2914 archive(name, fd, _elf, flags, Nname, wfd); 2915 break; 2916 case ELF_K_ELF: 2917 regular(name, _elf, flags, Nname, wfd); 2918 break; 2919 default: 2920 (void) fprintf(stderr, 2921 MSG_INTL(MSG_ERR_BADFILE), name); 2922 (void) fflush(stderr); 2923 break; 2924 } 2925 } 2926 2927 cmd = elf_next(_elf); 2928 (void) elf_end(_elf); 2929 } 2930 } 2931 2932 int 2933 main(int argc, char **argv, char **envp) 2934 { 2935 Elf *elf; 2936 int var, fd, wfd = 0; 2937 char *Nname = NULL, *wname = 0; 2938 uint32_t flags = 0, dbg_flags = 0; 2939 2940 /* 2941 * If we're on a 64-bit kernel, try to exec a full 64-bit version of 2942 * the binary. If successful, conv_check_native() won't return. 2943 */ 2944 conv_check_native(argv, envp); 2945 2946 /* 2947 * Establish locale. 2948 */ 2949 (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 2950 (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 2951 2952 (void) setvbuf(stdout, NULL, _IOLBF, 0); 2953 (void) setvbuf(stderr, NULL, _IOLBF, 0); 2954 2955 opterr = 0; 2956 while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) { 2957 switch (var) { 2958 case 'C': 2959 flags |= FLG_DEMANGLE; 2960 break; 2961 case 'c': 2962 flags |= FLG_SHDR; 2963 break; 2964 case 'd': 2965 flags |= FLG_DYNAMIC; 2966 break; 2967 case 'e': 2968 flags |= FLG_EHDR; 2969 break; 2970 case 'G': 2971 flags |= FLG_GOT; 2972 break; 2973 case 'g': 2974 flags |= FLG_GROUP; 2975 break; 2976 case 'H': 2977 flags |= FLG_CAP; 2978 break; 2979 case 'h': 2980 flags |= FLG_HASH; 2981 break; 2982 case 'i': 2983 flags |= FLG_INTERP; 2984 break; 2985 case 'k': 2986 flags |= FLG_CHECKSUM; 2987 break; 2988 case 'l': 2989 flags |= FLG_LONGNAME; 2990 break; 2991 case 'm': 2992 flags |= FLG_MOVE; 2993 break; 2994 case 'N': 2995 Nname = optarg; 2996 break; 2997 case 'n': 2998 flags |= FLG_NOTE; 2999 break; 3000 case 'p': 3001 flags |= FLG_PHDR; 3002 break; 3003 case 'r': 3004 flags |= FLG_RELOC; 3005 break; 3006 case 's': 3007 flags |= FLG_SYMBOLS; 3008 break; 3009 case 'u': 3010 flags |= FLG_UNWIND; 3011 break; 3012 case 'v': 3013 flags |= FLG_VERSIONS; 3014 break; 3015 case 'w': 3016 wname = optarg; 3017 break; 3018 case 'y': 3019 flags |= FLG_SYMINFO; 3020 break; 3021 case '?': 3022 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 3023 basename(argv[0])); 3024 detail_usage(); 3025 return (1); 3026 default: 3027 break; 3028 } 3029 } 3030 3031 /* 3032 * Validate any arguments. 3033 */ 3034 if (flags == 0) { 3035 if (!wname && !Nname) { 3036 flags = FLG_EVERYTHING; 3037 } else if (!wname || !Nname) { 3038 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 3039 basename(argv[0])); 3040 return (1); 3041 } 3042 } 3043 3044 if ((var = argc - optind) == 0) { 3045 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 3046 basename(argv[0])); 3047 return (1); 3048 } 3049 3050 /* 3051 * If the -C option is used by itself, report an error since the option 3052 * has no use without other symbol name generating options. 3053 * 3054 * If the -l option is used by itself, report an error. 3055 */ 3056 if ((flags == FLG_DEMANGLE) || (flags == FLG_LONGNAME) || 3057 (flags == (FLG_DEMANGLE | FLG_LONGNAME))) { 3058 if (flags & FLG_DEMANGLE) 3059 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DEMANGLE)); 3060 if (flags & FLG_LONGNAME) 3061 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_LONGNAME)); 3062 return (1); 3063 } 3064 3065 /* 3066 * If the -l/-C option is specified, set up the liblddbg.so. 3067 */ 3068 if (flags & FLG_LONGNAME) 3069 dbg_flags = DBG_LONG; 3070 if (flags & FLG_DEMANGLE) 3071 dbg_flags |= DBG_DEMANGLE; 3072 if (dbg_flags) 3073 Dbg_set(dbg_flags); 3074 3075 /* 3076 * If the -w option has indicated an output file open it. It's 3077 * arguable whether this option has much use when multiple files are 3078 * being processed. 3079 */ 3080 if (wname) { 3081 if ((wfd = open(wname, (O_RDWR | O_CREAT | O_TRUNC), 3082 0666)) < 0) { 3083 int err = errno; 3084 (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 3085 wname, strerror(err)); 3086 (void) fflush(stderr); 3087 wfd = 0; 3088 } 3089 } 3090 3091 /* 3092 * Open the input file and initialize the elf interface. 3093 */ 3094 for (; optind < argc; optind++) { 3095 const char *file = argv[optind]; 3096 3097 if ((fd = open(argv[optind], O_RDONLY)) == -1) { 3098 int err = errno; 3099 (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 3100 file, strerror(err)); 3101 (void) fflush(stderr); 3102 continue; 3103 } 3104 (void) elf_version(EV_CURRENT); 3105 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 3106 failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 3107 (void) close(fd); 3108 continue; 3109 } 3110 3111 if (var > 1) 3112 dbg_print(MSG_ORIG(MSG_FMT_NLSTRNL), file); 3113 3114 switch (elf_kind(elf)) { 3115 case ELF_K_AR: 3116 archive(file, fd, elf, flags, Nname, wfd); 3117 break; 3118 case ELF_K_ELF: 3119 regular(file, elf, flags, Nname, wfd); 3120 break; 3121 default: 3122 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADFILE), file); 3123 (void) fflush(stderr); 3124 break; 3125 } 3126 3127 (void) close(fd); 3128 (void) elf_end(elf); 3129 } 3130 3131 if (wfd) 3132 (void) close(wfd); 3133 return (0); 3134 } 3135