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