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