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