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 (shdr->sh_type != SHT_SUNW_LDYNSYM)) 1082 continue; 1083 if (name && strcmp(name, secname)) 1084 continue; 1085 1086 /* 1087 * Determine the symbol data and number. 1088 */ 1089 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1090 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1091 file, secname); 1092 continue; 1093 } 1094 /* LINTED */ 1095 symn = (Word)(shdr->sh_size / shdr->sh_entsize); 1096 sym = (Sym *)_cache->c_data->d_buf; 1097 1098 /* 1099 * Get the associated string table section. 1100 */ 1101 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1102 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1103 file, secname, EC_WORD(shdr->sh_link)); 1104 continue; 1105 } 1106 1107 /* 1108 * Determine if there is a associated Versym section 1109 * with this Symbol Table. 1110 */ 1111 if (versymcache && (versymcache->c_shdr->sh_link == seccnt)) 1112 versym = versymcache->c_data->d_buf; 1113 else 1114 versym = 0; 1115 1116 /* 1117 * Loop through the symbol tables entries. 1118 */ 1119 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1120 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), secname); 1121 Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 1122 1123 shxndx = 0; 1124 noshxndx = 0; 1125 symnshxndx = 0; 1126 for (symcnt = 0; symcnt < symn; sym++, symcnt++) { 1127 char index[MAXNDXSIZE], *sec; 1128 const char *symname; 1129 int verndx; 1130 uchar_t type; 1131 Shdr *tshdr; 1132 Word shndx; 1133 1134 /* 1135 * If we are using extended symbol indexes, find the 1136 * corresponding SHN_SYMTAB_SHNDX table. 1137 */ 1138 if ((sym->st_shndx == SHN_XINDEX) && 1139 (shxndx == 0) && (noshxndx == 0)) 1140 noshxndx = symbols_getxindex(cache, shnum, 1141 seccnt, &shxndx, &symnshxndx); 1142 1143 /* LINTED */ 1144 symname = string(_cache, symcnt, &cache[shdr->sh_link], 1145 file, sym->st_name); 1146 1147 tshdr = 0; 1148 sec = NULL; 1149 1150 if (is_core) 1151 sec = (char *)MSG_INTL(MSG_STR_UNKNOWN); 1152 else if ((sym->st_shndx < SHN_LORESERVE) && 1153 (sym->st_shndx < shnum)) { 1154 shndx = sym->st_shndx; 1155 tshdr = cache[shndx].c_shdr; 1156 sec = cache[shndx].c_name; 1157 } else if (sym->st_shndx == SHN_XINDEX) { 1158 if (shxndx) { 1159 Word _shxndx; 1160 1161 if (symcnt > symnshxndx) { 1162 (void) fprintf(stderr, 1163 MSG_INTL(MSG_ERR_BADSYMXINDEX1), 1164 file, secname, EC_WORD(symcnt)); 1165 } else if ((_shxndx = 1166 shxndx[symcnt]) > shnum) { 1167 (void) fprintf(stderr, 1168 MSG_INTL(MSG_ERR_BADSYMXINDEX2), 1169 file, secname, EC_WORD(symcnt), 1170 EC_WORD(_shxndx)); 1171 } else { 1172 shndx = _shxndx; 1173 tshdr = cache[shndx].c_shdr; 1174 sec = cache[shndx].c_name; 1175 } 1176 } else { 1177 (void) fprintf(stderr, 1178 MSG_INTL(MSG_ERR_BADSYMXINDEX3), 1179 file, secname, EC_WORD(symcnt)); 1180 } 1181 } else if ((sym->st_shndx < SHN_LORESERVE) && 1182 (sym->st_shndx >= shnum)) { 1183 (void) fprintf(stderr, 1184 MSG_INTL(MSG_ERR_BADSYM5), file, 1185 secname, demangle(symname, flags), 1186 sym->st_shndx); 1187 } 1188 1189 /* 1190 * If versioning is available display the 1191 * version index. 1192 */ 1193 if (versym) 1194 verndx = (int)versym[symcnt]; 1195 else 1196 verndx = 0; 1197 1198 /* 1199 * Error checking for TLS. 1200 */ 1201 type = ELF_ST_TYPE(sym->st_info); 1202 if (type == STT_TLS) { 1203 if (tshdr && 1204 (sym->st_shndx != SHN_UNDEF) && 1205 ((tshdr->sh_flags & SHF_TLS) == 0)) { 1206 (void) fprintf(stderr, 1207 MSG_INTL(MSG_ERR_BADSYM3), file, 1208 secname, demangle(symname, flags)); 1209 } 1210 } else if ((type != STT_SECTION) && sym->st_size && 1211 tshdr && (tshdr->sh_flags & SHF_TLS)) { 1212 (void) fprintf(stderr, 1213 MSG_INTL(MSG_ERR_BADSYM4), file, 1214 secname, demangle(symname, flags)); 1215 } 1216 1217 /* 1218 * If a symbol has size, then make sure the section it 1219 * references is appropriate. Note, UNDEF symbols that 1220 * have a size, have been known to exist - ignore them. 1221 */ 1222 if (sym->st_size && shndx && tshdr && 1223 (tshdr->sh_size < sym->st_size)) { 1224 (void) fprintf(stderr, 1225 MSG_INTL(MSG_ERR_BADSYM6), file, 1226 secname, demangle(symname, flags), 1227 EC_WORD(shndx), EC_XWORD(tshdr->sh_size), 1228 EC_XWORD(sym->st_size)); 1229 } 1230 1231 (void) snprintf(index, MAXNDXSIZE, 1232 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symcnt)); 1233 Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index, 1234 ehdr->e_machine, sym, verndx, sec, symname); 1235 } 1236 } 1237 } 1238 1239 /* 1240 * Search for and process any relocation sections. 1241 */ 1242 static void 1243 reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, const char *file, 1244 uint_t flags) 1245 { 1246 Word cnt; 1247 1248 for (cnt = 1; cnt < shnum; cnt++) { 1249 Word type, symnum; 1250 Xword relndx, relnum, relsize; 1251 void *rels; 1252 Sym *syms; 1253 Cache *symsec, *strsec; 1254 Cache *_cache = &cache[cnt]; 1255 Shdr *shdr = _cache->c_shdr; 1256 char *relname = _cache->c_name; 1257 1258 if (((type = shdr->sh_type) != SHT_RELA) && 1259 (type != SHT_REL)) 1260 continue; 1261 if (name && strcmp(name, relname)) 1262 continue; 1263 1264 /* 1265 * Decide entry size. 1266 */ 1267 if (((relsize = shdr->sh_entsize) == 0) || 1268 (relsize > shdr->sh_size)) { 1269 if (type == SHT_RELA) 1270 relsize = sizeof (Rela); 1271 else 1272 relsize = sizeof (Rel); 1273 } 1274 1275 /* 1276 * Determine the number of relocations available. 1277 */ 1278 if (shdr->sh_size == 0) { 1279 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1280 file, relname); 1281 continue; 1282 } 1283 rels = _cache->c_data->d_buf; 1284 relnum = shdr->sh_size / relsize; 1285 1286 /* 1287 * Get the data buffer for the associated symbol table and 1288 * string table. 1289 */ 1290 if (stringtbl(cache, 1, cnt, shnum, file, 1291 &symnum, &symsec, &strsec) == 0) 1292 continue; 1293 1294 syms = symsec->c_data->d_buf; 1295 1296 /* 1297 * Loop through the relocation entries. 1298 */ 1299 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1300 dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name); 1301 Elf_reloc_title(0, ELF_DBG_ELFDUMP, type); 1302 1303 for (relndx = 0; relndx < relnum; relndx++, 1304 rels = (void *)((char *)rels + relsize)) { 1305 char section[BUFSIZ]; 1306 const char *symname; 1307 Word symndx, reltype; 1308 Rela *rela; 1309 Rel *rel; 1310 1311 /* 1312 * Unravel the relocation and determine the symbol with 1313 * which this relocation is associated. 1314 */ 1315 if (type == SHT_RELA) { 1316 rela = (Rela *)rels; 1317 symndx = ELF_R_SYM(rela->r_info); 1318 reltype = ELF_R_TYPE(rela->r_info); 1319 } else { 1320 rel = (Rel *)rels; 1321 symndx = ELF_R_SYM(rel->r_info); 1322 reltype = ELF_R_TYPE(rel->r_info); 1323 } 1324 1325 symname = relsymname(cache, _cache, strsec, symndx, 1326 symnum, relndx, syms, section, BUFSIZ, file, 1327 flags); 1328 1329 /* 1330 * A zero symbol index is only valid for a few 1331 * relocations. 1332 */ 1333 if (symndx == 0) { 1334 Half mach = ehdr->e_machine; 1335 int badrel = 0; 1336 1337 if ((mach == EM_SPARC) || 1338 (mach == EM_SPARC32PLUS) || 1339 (mach == EM_SPARCV9)) { 1340 if ((reltype != R_SPARC_NONE) && 1341 (reltype != R_SPARC_REGISTER) && 1342 (reltype != R_SPARC_RELATIVE)) 1343 badrel++; 1344 } else if (mach == EM_386) { 1345 if ((reltype != R_386_NONE) && 1346 (reltype != R_386_RELATIVE)) 1347 badrel++; 1348 } else if (mach == EM_AMD64) { 1349 if ((reltype != R_AMD64_NONE) && 1350 (reltype != R_AMD64_RELATIVE)) 1351 badrel++; 1352 } 1353 1354 if (badrel) { 1355 (void) fprintf(stderr, 1356 MSG_INTL(MSG_ERR_BADREL1), file, 1357 conv_reloc_type(mach, reltype, 0)); 1358 } 1359 } 1360 1361 Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP, 1362 MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type, 1363 rels, relname, symname, 0); 1364 } 1365 } 1366 } 1367 1368 /* 1369 * Search for and process a .dynamic section. 1370 */ 1371 static void 1372 dynamic(Cache *cache, Word shnum, Ehdr *ehdr, const char *file) 1373 { 1374 Word cnt; 1375 1376 for (cnt = 1; cnt < shnum; cnt++) { 1377 Dyn *dyn; 1378 ulong_t numdyn; 1379 int ndx; 1380 Cache *_cache = &cache[cnt], *strsec; 1381 Shdr *shdr = _cache->c_shdr; 1382 1383 if (shdr->sh_type != SHT_DYNAMIC) 1384 continue; 1385 1386 /* 1387 * Verify the associated string table section. 1388 */ 1389 if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0) 1390 continue; 1391 1392 numdyn = shdr->sh_size / shdr->sh_entsize; 1393 dyn = (Dyn *)_cache->c_data->d_buf; 1394 1395 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1396 dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name); 1397 1398 Elf_dyn_title(0); 1399 1400 for (ndx = 0; ndx < numdyn; dyn++, ndx++) { 1401 const char *name; 1402 1403 /* 1404 * Print the information numerically, and if possible 1405 * as a string. 1406 */ 1407 if ((dyn->d_tag == DT_NEEDED) || 1408 (dyn->d_tag == DT_SONAME) || 1409 (dyn->d_tag == DT_FILTER) || 1410 (dyn->d_tag == DT_AUXILIARY) || 1411 (dyn->d_tag == DT_CONFIG) || 1412 (dyn->d_tag == DT_RPATH) || 1413 (dyn->d_tag == DT_RUNPATH) || 1414 (dyn->d_tag == DT_USED) || 1415 (dyn->d_tag == DT_DEPAUDIT) || 1416 (dyn->d_tag == DT_AUDIT) || 1417 (dyn->d_tag == DT_SUNW_AUXILIARY) || 1418 (dyn->d_tag == DT_SUNW_FILTER)) 1419 name = string(_cache, ndx, strsec, 1420 file, dyn->d_un.d_ptr); 1421 else if (dyn->d_tag == DT_FLAGS) 1422 name = conv_dyn_flag(dyn->d_un.d_val, 0); 1423 else if (dyn->d_tag == DT_FLAGS_1) 1424 name = conv_dyn_flag1(dyn->d_un.d_val); 1425 else if (dyn->d_tag == DT_POSFLAG_1) 1426 name = conv_dyn_posflag1(dyn->d_un.d_val, 0); 1427 else if (dyn->d_tag == DT_FEATURE_1) 1428 name = conv_dyn_feature1(dyn->d_un.d_val, 0); 1429 else if (dyn->d_tag == DT_DEPRECATED_SPARC_REGISTER) 1430 name = MSG_INTL(MSG_STR_DEPRECATED); 1431 else 1432 name = MSG_ORIG(MSG_STR_EMPTY); 1433 1434 Elf_dyn_entry(0, dyn, ndx, name, ehdr->e_machine); 1435 } 1436 } 1437 } 1438 1439 /* 1440 * Search for and process a MOVE section. 1441 */ 1442 static void 1443 move(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags) 1444 { 1445 Word cnt; 1446 const char *fmt = 0; 1447 1448 for (cnt = 1; cnt < shnum; cnt++) { 1449 Word movenum, symnum, ndx; 1450 Sym *syms; 1451 Cache *_cache = &cache[cnt]; 1452 Shdr *shdr = _cache->c_shdr; 1453 Cache *symsec, *strsec; 1454 Move *move; 1455 1456 if (shdr->sh_type != SHT_SUNW_move) 1457 continue; 1458 if (name && strcmp(name, _cache->c_name)) 1459 continue; 1460 1461 /* 1462 * Determine the move data and number. 1463 */ 1464 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1465 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1466 file, _cache->c_name); 1467 continue; 1468 } 1469 move = (Move *)_cache->c_data->d_buf; 1470 movenum = shdr->sh_size / shdr->sh_entsize; 1471 1472 /* 1473 * Get the data buffer for the associated symbol table and 1474 * string table. 1475 */ 1476 if (stringtbl(cache, 1, cnt, shnum, file, 1477 &symnum, &symsec, &strsec) == 0) 1478 return; 1479 1480 syms = (Sym *)symsec->c_data->d_buf; 1481 1482 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1483 dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name); 1484 dbg_print(0, MSG_INTL(MSG_MOVE_TITLE)); 1485 1486 if (fmt == 0) 1487 fmt = MSG_INTL(MSG_MOVE_ENTRY); 1488 1489 for (ndx = 0; ndx < movenum; move++, ndx++) { 1490 const char *symname; 1491 char index[MAXNDXSIZE], section[BUFSIZ]; 1492 Word symndx, shndx; 1493 Sym *sym; 1494 1495 /* 1496 * Check for null entries 1497 */ 1498 if ((move->m_info == 0) && (move->m_value == 0) && 1499 (move->m_poffset == 0) && (move->m_repeat == 0) && 1500 (move->m_stride == 0)) { 1501 dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY), 1502 EC_XWORD(move->m_poffset), 0, 0, 0, 1503 EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY)); 1504 continue; 1505 } 1506 if (((symndx = ELF_M_SYM(move->m_info)) == 0) || 1507 (symndx >= symnum)) { 1508 (void) fprintf(stderr, 1509 MSG_INTL(MSG_ERR_BADMINFO), file, 1510 _cache->c_name, EC_XWORD(move->m_info)); 1511 1512 (void) snprintf(index, MAXNDXSIZE, 1513 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 1514 dbg_print(0, fmt, index, 1515 EC_XWORD(move->m_poffset), 1516 ELF_M_SIZE(move->m_info), move->m_repeat, 1517 move->m_stride, move->m_value, 1518 MSG_INTL(MSG_STR_UNKNOWN)); 1519 continue; 1520 } 1521 1522 symname = relsymname(cache, _cache, strsec, 1523 symndx, symnum, ndx, syms, section, BUFSIZ, file, 1524 flags); 1525 sym = (Sym *)(syms + symndx); 1526 1527 /* 1528 * Additional sanity check. 1529 */ 1530 shndx = sym->st_shndx; 1531 if (!((shndx == SHN_COMMON) || 1532 (((shndx >= 1) && (shndx <= shnum)) && 1533 (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) { 1534 (void) fprintf(stderr, 1535 MSG_INTL(MSG_ERR_BADSYM2), file, 1536 _cache->c_name, demangle(symname, flags)); 1537 } 1538 1539 (void) snprintf(index, MAXNDXSIZE, 1540 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 1541 dbg_print(0, fmt, index, EC_XWORD(move->m_poffset), 1542 ELF_M_SIZE(move->m_info), move->m_repeat, 1543 move->m_stride, move->m_value, 1544 demangle(symname, flags)); 1545 } 1546 } 1547 } 1548 1549 /* 1550 * Traverse a note section analyzing each note information block. 1551 * The data buffers size is used to validate references before they are made, 1552 * and is decremented as each element is processed. 1553 */ 1554 void 1555 note_entry(Cache *cache, Word *data, size_t size, const char *file) 1556 { 1557 size_t bsize = size; 1558 1559 /* 1560 * Print out a single `note' information block. 1561 */ 1562 while (size > 0) { 1563 size_t namesz, descsz, type, pad, noteoff; 1564 1565 noteoff = bsize - size; 1566 /* 1567 * Make sure we can at least reference the 3 initial entries 1568 * (4-byte words) of the note information block. 1569 */ 1570 if (size >= (sizeof (Word) * 3)) 1571 size -= (sizeof (Word) * 3); 1572 else { 1573 (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ), 1574 file, cache->c_name, EC_WORD(noteoff)); 1575 return; 1576 } 1577 1578 /* 1579 * Make sure any specified name string can be referenced. 1580 */ 1581 if ((namesz = *data++) != 0) { 1582 if (size >= namesz) 1583 size -= namesz; 1584 else { 1585 (void) fprintf(stderr, 1586 MSG_INTL(MSG_NOTE_BADNMSZ), file, 1587 cache->c_name, EC_WORD(noteoff), 1588 EC_WORD(namesz)); 1589 return; 1590 } 1591 } 1592 1593 /* 1594 * Make sure any specified descriptor can be referenced. 1595 */ 1596 if ((descsz = *data++) != 0) { 1597 /* 1598 * If namesz isn't a 4-byte multiple, account for any 1599 * padding that must exist before the descriptor. 1600 */ 1601 if ((pad = (namesz & (sizeof (Word) - 1))) != 0) { 1602 pad = sizeof (Word) - pad; 1603 size -= pad; 1604 } 1605 if (size >= descsz) 1606 size -= descsz; 1607 else { 1608 (void) fprintf(stderr, 1609 MSG_INTL(MSG_NOTE_BADDESZ), file, 1610 cache->c_name, EC_WORD(noteoff), 1611 EC_WORD(namesz)); 1612 return; 1613 } 1614 } 1615 1616 type = *data++; 1617 1618 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1619 dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE), EC_WORD(type)); 1620 1621 dbg_print(0, MSG_ORIG(MSG_NOTE_NAMESZ), EC_WORD(namesz)); 1622 if (namesz) { 1623 char *name = (char *)data; 1624 1625 /* 1626 * Since the name string may have 'null' bytes 1627 * in it (ia32 .string) - we just write the 1628 * whole stream in a single fwrite. 1629 */ 1630 (void) fwrite(name, namesz, 1, stdout); 1631 name = name + ((namesz + (sizeof (Word) - 1)) & 1632 ~(sizeof (Word) - 1)); 1633 /* LINTED */ 1634 data = (Word *)name; 1635 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1636 } 1637 1638 /* 1639 * If multiple information blocks exist within a .note section 1640 * account for any padding that must exist before the next 1641 * information block. 1642 */ 1643 if ((pad = (descsz & (sizeof (Word) - 1))) != 0) { 1644 pad = sizeof (Word) - pad; 1645 if (size > pad) 1646 size -= pad; 1647 } 1648 1649 dbg_print(0, MSG_ORIG(MSG_NOTE_DESCSZ), EC_WORD(descsz)); 1650 if (descsz) { 1651 int ndx, byte, word; 1652 char string[58], *str = string; 1653 uchar_t *desc = (uchar_t *)data; 1654 1655 /* 1656 * Dump descriptor bytes. 1657 */ 1658 for (ndx = byte = word = 0; descsz; descsz--, desc++) { 1659 int tok = *desc; 1660 1661 (void) snprintf(str, 58, MSG_ORIG(MSG_NOTE_TOK), 1662 tok); 1663 str += 3; 1664 1665 if (++byte == 4) { 1666 *str++ = ' ', *str++ = ' '; 1667 word++; 1668 byte = 0; 1669 } 1670 if (word == 4) { 1671 *str = '\0'; 1672 dbg_print(0, MSG_ORIG(MSG_NOTE_DESC), 1673 ndx, string); 1674 word = 0; 1675 ndx += 16; 1676 str = string; 1677 } 1678 } 1679 if (byte || word) { 1680 *str = '\0'; 1681 dbg_print(0, MSG_ORIG(MSG_NOTE_DESC), 1682 ndx, string); 1683 } 1684 1685 desc += pad; 1686 /* LINTED */ 1687 data = (Word *)desc; 1688 } 1689 } 1690 } 1691 1692 /* 1693 * Search for and process a .note section. 1694 */ 1695 static void 1696 note(Cache *cache, Word shnum, const char *name, const char *file) 1697 { 1698 Word cnt; 1699 1700 /* 1701 * Otherwise look for any .note sections. 1702 */ 1703 for (cnt = 1; cnt < shnum; cnt++) { 1704 Cache *_cache = &cache[cnt]; 1705 Shdr *shdr = _cache->c_shdr; 1706 1707 if (shdr->sh_type != SHT_NOTE) 1708 continue; 1709 if (name && strcmp(name, _cache->c_name)) 1710 continue; 1711 1712 /* 1713 * As these sections are often hand rolled, make sure they're 1714 * properly aligned before proceeding. 1715 */ 1716 if (shdr->sh_offset & (sizeof (Word) - 1)) { 1717 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN), 1718 file, _cache->c_name); 1719 continue; 1720 } 1721 1722 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1723 dbg_print(0, MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name); 1724 note_entry(_cache, (Word *)_cache->c_data->d_buf, 1725 /* LINTED */ 1726 (Word)_cache->c_data->d_size, file); 1727 } 1728 } 1729 1730 /* 1731 * Determine an individual hash entry. This may be the initial hash entry, 1732 * or an associated chain entry. 1733 */ 1734 static void 1735 hash_entry(Cache *refsec, Cache *strsec, const char *hsecname, Word hashndx, 1736 Word symndx, Word symn, Sym *syms, const char *file, ulong_t bkts, 1737 uint_t flags, int chain) 1738 { 1739 Sym *sym; 1740 const char *symname, *str; 1741 char _bucket[MAXNDXSIZE], _symndx[MAXNDXSIZE]; 1742 ulong_t nbkt, nhash; 1743 1744 if (symndx > symn) { 1745 (void) fprintf(stderr, MSG_INTL(MSG_ERR_HSBADSYMNDX), file, 1746 EC_WORD(symndx), EC_WORD(hashndx)); 1747 symname = MSG_INTL(MSG_STR_UNKNOWN); 1748 } else { 1749 sym = (Sym *)(syms + symndx); 1750 symname = string(refsec, symndx, strsec, file, sym->st_name); 1751 } 1752 1753 if (chain == 0) { 1754 (void) snprintf(_bucket, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 1755 hashndx); 1756 str = (const char *)_bucket; 1757 } else 1758 str = MSG_ORIG(MSG_STR_EMPTY); 1759 1760 (void) snprintf(_symndx, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX2), 1761 EC_WORD(symndx)); 1762 dbg_print(0, MSG_ORIG(MSG_FMT_HASH_INFO), str, _symndx, 1763 demangle(symname, flags)); 1764 1765 /* 1766 * Determine if this string is in the correct bucket. 1767 */ 1768 nhash = elf_hash(symname); 1769 nbkt = nhash % bkts; 1770 1771 if (nbkt != hashndx) { 1772 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADHASH), file, 1773 hsecname, symname, EC_WORD(hashndx), nbkt); 1774 } 1775 } 1776 1777 #define MAXCOUNT 500 1778 1779 static void 1780 hash(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags) 1781 { 1782 static int count[MAXCOUNT]; 1783 Word cnt; 1784 ulong_t ndx, bkts; 1785 char number[MAXNDXSIZE]; 1786 1787 for (cnt = 1; cnt < shnum; cnt++) { 1788 uint_t *hash, *chain; 1789 Cache *_cache = &cache[cnt]; 1790 Shdr *sshdr, *hshdr = _cache->c_shdr; 1791 char *ssecname, *hsecname = _cache->c_name; 1792 Sym *syms; 1793 Word symn; 1794 1795 if (hshdr->sh_type != SHT_HASH) 1796 continue; 1797 if (name && strcmp(name, hsecname)) 1798 continue; 1799 1800 /* 1801 * Determine the hash table data and size. 1802 */ 1803 if ((hshdr->sh_entsize == 0) || (hshdr->sh_size == 0)) { 1804 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1805 file, hsecname); 1806 continue; 1807 } 1808 hash = (uint_t *)_cache->c_data->d_buf; 1809 bkts = *hash; 1810 chain = hash + 2 + bkts; 1811 hash += 2; 1812 1813 /* 1814 * Get the data buffer for the associated symbol table. 1815 */ 1816 if ((hshdr->sh_link == 0) || (hshdr->sh_link >= shnum)) { 1817 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1818 file, hsecname, EC_WORD(hshdr->sh_link)); 1819 continue; 1820 } 1821 1822 _cache = &cache[hshdr->sh_link]; 1823 ssecname = _cache->c_name; 1824 1825 if ((syms = (Sym *)_cache->c_data->d_buf) == 0) { 1826 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1827 file, ssecname); 1828 continue; 1829 } 1830 1831 sshdr = _cache->c_shdr; 1832 /* LINTED */ 1833 symn = (Word)(sshdr->sh_size / sshdr->sh_entsize); 1834 1835 /* 1836 * Get the associated string table section. 1837 */ 1838 if ((sshdr->sh_link == 0) || (sshdr->sh_link >= shnum)) { 1839 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1840 file, ssecname, EC_WORD(sshdr->sh_link)); 1841 continue; 1842 } 1843 1844 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1845 dbg_print(0, MSG_INTL(MSG_ELF_SCN_HASH), hsecname); 1846 dbg_print(0, MSG_INTL(MSG_ELF_HASH_INFO)); 1847 1848 /* 1849 * Loop through the hash buckets, printing the appropriate 1850 * symbols. 1851 */ 1852 for (ndx = 0; ndx < bkts; ndx++, hash++) { 1853 Word _ndx, _cnt; 1854 1855 if (*hash == 0) { 1856 count[0]++; 1857 continue; 1858 } 1859 1860 hash_entry(_cache, &cache[sshdr->sh_link], hsecname, 1861 ndx, *hash, symn, syms, file, bkts, flags, 0); 1862 1863 /* 1864 * Determine if any other symbols are chained to this 1865 * bucket. 1866 */ 1867 _ndx = chain[*hash]; 1868 _cnt = 1; 1869 while (_ndx) { 1870 hash_entry(_cache, &cache[sshdr->sh_link], 1871 hsecname, ndx, _ndx, symn, syms, file, 1872 bkts, flags, 1); 1873 _ndx = chain[_ndx]; 1874 _cnt++; 1875 } 1876 1877 if (_cnt >= MAXCOUNT) { 1878 (void) fprintf(stderr, 1879 MSG_INTL(MSG_HASH_OVERFLW), file, 1880 _cache->c_name, EC_WORD(ndx), 1881 EC_WORD(_cnt)); 1882 } else 1883 count[_cnt]++; 1884 } 1885 break; 1886 } 1887 1888 /* 1889 * Print out the count information. 1890 */ 1891 bkts = cnt = 0; 1892 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1893 1894 for (ndx = 0; ndx < MAXCOUNT; ndx++) { 1895 Word _cnt; 1896 1897 if ((_cnt = count[ndx]) == 0) 1898 continue; 1899 1900 (void) snprintf(number, MAXNDXSIZE, 1901 MSG_ORIG(MSG_FMT_INTEGER), _cnt); 1902 dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS1), number, 1903 EC_WORD(ndx)); 1904 bkts += _cnt; 1905 cnt += (Word)(ndx * _cnt); 1906 } 1907 if (cnt) { 1908 (void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 1909 bkts); 1910 dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS2), number, 1911 EC_WORD(cnt)); 1912 } 1913 } 1914 1915 static void 1916 group(Cache *cache, Word shnum, const char *name, const char *file, 1917 uint_t flags) 1918 { 1919 Word scnt; 1920 1921 for (scnt = 1; scnt < shnum; scnt++) { 1922 Cache *_cache = &cache[scnt]; 1923 Shdr *shdr = _cache->c_shdr; 1924 Word *grpdata, gcnt, grpcnt, symnum, unknown; 1925 Cache *symsec, *strsec; 1926 Sym *syms, *sym; 1927 char flgstrbuf[MSG_GRP_COMDAT_SIZE + 10]; 1928 1929 if (shdr->sh_type != SHT_GROUP) 1930 continue; 1931 if (name && strcmp(name, _cache->c_name)) 1932 continue; 1933 if ((_cache->c_data == 0) || 1934 ((grpdata = (Word *)_cache->c_data->d_buf) == 0)) 1935 continue; 1936 grpcnt = shdr->sh_size / sizeof (Word); 1937 1938 /* 1939 * Get the data buffer for the associated symbol table and 1940 * string table. 1941 */ 1942 if (stringtbl(cache, 1, scnt, shnum, file, 1943 &symnum, &symsec, &strsec) == 0) 1944 return; 1945 1946 syms = symsec->c_data->d_buf; 1947 1948 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1949 dbg_print(0, MSG_INTL(MSG_ELF_SCN_GRP), _cache->c_name); 1950 dbg_print(0, MSG_INTL(MSG_GRP_TITLE)); 1951 1952 /* 1953 * The first element of the group defines the group. The 1954 * associated symbol is defined by the sh_link field. 1955 */ 1956 if ((shdr->sh_info == SHN_UNDEF) || (shdr->sh_info > symnum)) { 1957 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 1958 file, _cache->c_name, EC_WORD(shdr->sh_info)); 1959 return; 1960 } 1961 1962 (void) strcpy(flgstrbuf, MSG_ORIG(MSG_STR_OSQBRKT)); 1963 if (grpdata[0] & GRP_COMDAT) { 1964 (void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_COMDAT)); 1965 } 1966 if ((unknown = (grpdata[0] & ~GRP_COMDAT)) != 0) { 1967 size_t len = strlen(flgstrbuf); 1968 1969 (void) snprintf(&flgstrbuf[len], 1970 (MSG_GRP_COMDAT_SIZE + 10 - len), 1971 MSG_ORIG(MSG_GRP_UNKNOWN), unknown); 1972 } 1973 (void) strcat(flgstrbuf, MSG_ORIG(MSG_STR_CSQBRKT)); 1974 sym = (Sym *)(syms + shdr->sh_info); 1975 1976 dbg_print(0, MSG_INTL(MSG_GRP_SIGNATURE), flgstrbuf, 1977 demangle(string(_cache, 0, strsec, file, sym->st_name), 1978 flags)); 1979 1980 for (gcnt = 1; gcnt < grpcnt; gcnt++) { 1981 char index[MAXNDXSIZE]; 1982 const char *name; 1983 1984 (void) snprintf(index, MAXNDXSIZE, 1985 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(gcnt)); 1986 1987 if (grpdata[gcnt] >= shnum) 1988 name = MSG_INTL(MSG_GRP_INVALSCN); 1989 else 1990 name = cache[grpdata[gcnt]].c_name; 1991 1992 (void) printf(MSG_ORIG(MSG_GRP_ENTRY), index, name, 1993 EC_XWORD(grpdata[gcnt])); 1994 } 1995 } 1996 } 1997 1998 static void 1999 got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, uint_t flags) 2000 { 2001 Cache *gotcache = 0, *symtab = 0, *_cache; 2002 Addr gotbgn, gotend; 2003 Shdr *gotshdr; 2004 Word cnt, gotents, gotndx; 2005 size_t gentsize; 2006 Got_info *gottable; 2007 char *gotdata; 2008 Sym *gotsym; 2009 Xword gotsymaddr; 2010 2011 /* 2012 * First, find the got. 2013 */ 2014 for (cnt = 1; cnt < shnum; cnt++) { 2015 _cache = &cache[cnt]; 2016 if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT), 2017 MSG_ELF_GOT_SIZE) == 0) { 2018 gotcache = _cache; 2019 break; 2020 } 2021 } 2022 if (gotcache == 0) 2023 return; 2024 2025 /* 2026 * A got section within a relocatable object is suspicious. 2027 */ 2028 if (ehdr->e_type == ET_REL) { 2029 (void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file, 2030 _cache->c_name); 2031 } 2032 2033 gotshdr = gotcache->c_shdr; 2034 if (gotshdr->sh_size == 0) { 2035 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2036 file, gotcache->c_name); 2037 return; 2038 } 2039 2040 gotbgn = gotshdr->sh_addr; 2041 gotend = gotbgn + gotshdr->sh_size; 2042 2043 /* 2044 * Some architectures don't properly set the sh_entsize for the GOT 2045 * table. If it's not set, default to a size of a pointer. 2046 */ 2047 if ((gentsize = gotshdr->sh_entsize) == 0) 2048 gentsize = sizeof (Xword); 2049 2050 /* LINTED */ 2051 gotents = (Word)(gotshdr->sh_size / gentsize); 2052 gotdata = gotcache->c_data->d_buf; 2053 2054 if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) { 2055 int err = errno; 2056 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), file, 2057 strerror(err)); 2058 return; 2059 } 2060 2061 /* 2062 * Now we scan through all the sections looking for any relocations 2063 * that may be against the GOT. Since these may not be isolated to a 2064 * .rel[a].got section we check them all. 2065 * While scanning sections save the symbol table entry (a symtab 2066 * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_. 2067 */ 2068 for (cnt = 1; cnt < shnum; cnt++) { 2069 Word type, symnum; 2070 Xword relndx, relnum, relsize; 2071 void *rels; 2072 Sym *syms; 2073 Cache *symsec, *strsec; 2074 Cache *_cache = &cache[cnt]; 2075 Shdr *shdr; 2076 2077 shdr = _cache->c_shdr; 2078 type = shdr->sh_type; 2079 2080 if ((symtab == 0) && (type == SHT_DYNSYM)) { 2081 symtab = _cache; 2082 continue; 2083 } 2084 if (type == SHT_SYMTAB) { 2085 symtab = _cache; 2086 continue; 2087 } 2088 if ((type != SHT_RELA) && (type != SHT_REL)) 2089 continue; 2090 2091 /* 2092 * Decide entry size. 2093 */ 2094 if (((relsize = shdr->sh_entsize) == 0) || 2095 (relsize > shdr->sh_size)) { 2096 if (type == SHT_RELA) 2097 relsize = sizeof (Rela); 2098 else 2099 relsize = sizeof (Rel); 2100 } 2101 2102 /* 2103 * Determine the number of relocations available. 2104 */ 2105 if (shdr->sh_size == 0) { 2106 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2107 file, _cache->c_name); 2108 continue; 2109 } 2110 rels = _cache->c_data->d_buf; 2111 relnum = shdr->sh_size / relsize; 2112 2113 /* 2114 * Get the data buffer for the associated symbol table and 2115 * string table. 2116 */ 2117 if (stringtbl(cache, 1, cnt, shnum, file, 2118 &symnum, &symsec, &strsec) == 0) 2119 continue; 2120 2121 syms = symsec->c_data->d_buf; 2122 2123 /* 2124 * Loop through the relocation entries. 2125 */ 2126 for (relndx = 0; relndx < relnum; relndx++, 2127 rels = (void *)((char *)rels + relsize)) { 2128 char section[BUFSIZ]; 2129 Addr offset; 2130 Got_info *gip; 2131 Word symndx, reltype; 2132 Rela *rela; 2133 Rel *rel; 2134 2135 /* 2136 * Unravel the relocation. 2137 */ 2138 if (type == SHT_RELA) { 2139 rela = (Rela *)rels; 2140 symndx = ELF_R_SYM(rela->r_info); 2141 reltype = ELF_R_TYPE(rela->r_info); 2142 offset = rela->r_offset; 2143 } else { 2144 rel = (Rel *)rels; 2145 symndx = ELF_R_SYM(rel->r_info); 2146 reltype = ELF_R_TYPE(rel->r_info); 2147 offset = rel->r_offset; 2148 } 2149 2150 /* 2151 * Only pay attention to relocations against the GOT. 2152 */ 2153 if ((offset < gotbgn) || (offset > gotend)) 2154 continue; 2155 2156 /* LINTED */ 2157 gotndx = (Word)((offset - gotbgn) / 2158 gotshdr->sh_entsize); 2159 gip = &gottable[gotndx]; 2160 2161 if (gip->g_reltype != 0) { 2162 (void) fprintf(stderr, 2163 MSG_INTL(MSG_GOT_MULTIPLE), file, 2164 EC_WORD(gotndx), EC_ADDR(offset)); 2165 continue; 2166 } 2167 2168 if (symndx) 2169 gip->g_symname = relsymname(cache, _cache, 2170 strsec, symndx, symnum, relndx, syms, 2171 section, BUFSIZ, file, flags); 2172 gip->g_reltype = reltype; 2173 gip->g_rel = rels; 2174 } 2175 } 2176 2177 if (symlookup(MSG_ORIG(MSG_GOT_SYM), cache, shnum, &gotsym, symtab, 2178 file)) 2179 gotsymaddr = gotsym->st_value; 2180 else 2181 gotsymaddr = gotbgn; 2182 2183 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2184 dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name); 2185 Elf_got_title(0); 2186 2187 for (gotndx = 0; gotndx < gotents; gotndx++) { 2188 Got_info *gip; 2189 Sword gindex; 2190 Addr gaddr; 2191 Xword gotentry; 2192 2193 gip = &gottable[gotndx]; 2194 2195 gaddr = gotbgn + (gotndx * gentsize); 2196 gindex = (Sword)(gaddr - gotsymaddr) / (Sword)gentsize; 2197 2198 if (gentsize == sizeof (Word)) 2199 /* LINTED */ 2200 gotentry = (Xword)(*((Word *)(gotdata) + gotndx)); 2201 else 2202 /* LINTED */ 2203 gotentry = *((Xword *)(gotdata) + gotndx); 2204 2205 Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine, 2206 gip->g_reltype, gip->g_rel, gip->g_symname); 2207 } 2208 free(gottable); 2209 } 2210 2211 void 2212 checksum(Elf *elf) 2213 { 2214 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2215 dbg_print(0, MSG_INTL(MSG_STR_CHECKSUM), elf_checksum(elf)); 2216 } 2217 2218 void 2219 regular(const char *file, Elf *elf, uint_t flags, char *Nname, int wfd) 2220 { 2221 Elf_Scn *scn; 2222 Ehdr *ehdr; 2223 Elf_Data *data; 2224 size_t cnt, shstrndx, shnum, phnum; 2225 Shdr *nameshdr, *shdr; 2226 char *names = 0; 2227 Cache *cache, *_cache; 2228 Cache *versymcache = 0; 2229 2230 if ((ehdr = elf_getehdr(elf)) == NULL) { 2231 failure(file, MSG_ORIG(MSG_ELF_GETEHDR)); 2232 return; 2233 } 2234 2235 if (elf_getshnum(elf, &shnum) == 0) { 2236 failure(file, MSG_ORIG(MSG_ELF_GETSHNUM)); 2237 return; 2238 } 2239 2240 if (elf_getshstrndx(elf, &shstrndx) == 0) { 2241 failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX)); 2242 return; 2243 } 2244 2245 if (elf_getphnum(elf, &phnum) == 0) { 2246 failure(file, MSG_ORIG(MSG_ELF_GETPHNUM)); 2247 return; 2248 } 2249 2250 if ((scn = elf_getscn(elf, 0)) != NULL) { 2251 if ((shdr = elf_getshdr(scn)) == NULL) { 2252 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2253 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0); 2254 return; 2255 } 2256 } else 2257 shdr = 0; 2258 2259 /* 2260 * Print the elf header. 2261 */ 2262 if (flags & FLG_EHDR) 2263 Elf_ehdr(0, ehdr, shdr); 2264 2265 /* 2266 * Print the program headers. 2267 */ 2268 if ((flags & FLG_PHDR) && (phnum != 0)) { 2269 Phdr *phdr; 2270 2271 if ((phdr = elf_getphdr(elf)) == NULL) { 2272 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 2273 return; 2274 } 2275 2276 for (cnt = 0; cnt < phnum; phdr++, cnt++) { 2277 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2278 dbg_print(0, MSG_INTL(MSG_ELF_PHDR), EC_WORD(cnt)); 2279 Elf_phdr(0, ehdr->e_machine, phdr); 2280 } 2281 } 2282 2283 2284 /* 2285 * Return now if there are no section, if there's just one section to 2286 * act as an extension of the ELF header, or if on section information 2287 * was requested. 2288 */ 2289 if ((shnum <= 1) || (flags && (flags & ~(FLG_EHDR | FLG_PHDR)) == 0)) { 2290 if ((ehdr->e_type == ET_CORE) && (flags & FLG_NOTE)) 2291 note(0, shnum, 0, file); 2292 return; 2293 } 2294 2295 2296 /* 2297 * Obtain the .shstrtab data buffer to provide the required section 2298 * name strings. 2299 */ 2300 if ((scn = elf_getscn(elf, shstrndx)) == NULL) { 2301 failure(file, MSG_ORIG(MSG_ELF_GETSCN)); 2302 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR), 2303 EC_XWORD(shstrndx)); 2304 2305 } else if ((data = elf_getdata(scn, NULL)) == NULL) { 2306 failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 2307 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA), 2308 EC_XWORD(shstrndx)); 2309 2310 } else if ((nameshdr = elf_getshdr(scn)) == NULL) { 2311 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2312 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 2313 /* LINTED */ 2314 (int)elf_ndxscn(scn)); 2315 2316 } else if ((names = data->d_buf) == 0) 2317 (void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file); 2318 2319 /* 2320 * Fill in the cache descriptor with information for each section. 2321 */ 2322 if ((cache = malloc(shnum * sizeof (Cache))) == 0) { 2323 int err = errno; 2324 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2325 file, strerror(err)); 2326 return; 2327 } 2328 2329 *cache = cache_init; 2330 _cache = cache; 2331 _cache++; 2332 2333 for (cnt = 1, scn = NULL; scn = elf_nextscn(elf, scn); 2334 cnt++, _cache++) { 2335 if ((_cache->c_shdr = elf_getshdr(scn)) == NULL) { 2336 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2337 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 2338 /* LINTED */ 2339 (int)elf_ndxscn(scn)); 2340 } 2341 2342 if (names && _cache->c_shdr->sh_name && 2343 /* LINTED */ 2344 (nameshdr->sh_size > _cache->c_shdr->sh_name)) 2345 _cache->c_name = names + _cache->c_shdr->sh_name; 2346 else { 2347 /* 2348 * If there exists no shstrtab data, or a section header 2349 * has no name (an invalid index of 0), then compose a 2350 * name for each section. 2351 */ 2352 char scnndxnm[100]; 2353 2354 (void) snprintf(scnndxnm, 100, MSG_INTL(MSG_FMT_SCNNDX), 2355 cnt); 2356 2357 /* 2358 * Although we have a valid shstrtab section inform the 2359 * user if this section name index exceeds the shstrtab 2360 * data. 2361 */ 2362 if (names && 2363 /* LINTED */ 2364 (nameshdr->sh_size <= _cache->c_shdr->sh_name)) { 2365 (void) fprintf(stderr, 2366 MSG_INTL(MSG_ERR_BADSHNAME), file, 2367 _cache->c_name, 2368 EC_XWORD(_cache->c_shdr->sh_name)); 2369 } 2370 2371 if ((_cache->c_name = 2372 malloc(strlen(scnndxnm) + 1)) == 0) { 2373 int err = errno; 2374 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2375 file, strerror(err)); 2376 return; 2377 } 2378 (void) strcpy(_cache->c_name, scnndxnm); 2379 } 2380 2381 if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) { 2382 failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 2383 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA), 2384 /* LINTED */ 2385 (int)elf_ndxscn(scn)); 2386 } 2387 2388 /* 2389 * Do we wish to write the section out? 2390 */ 2391 if (wfd && Nname && (strcmp(Nname, _cache->c_name) == 0)) { 2392 (void) write(wfd, _cache->c_data->d_buf, 2393 _cache->c_data->d_size); 2394 } 2395 } 2396 2397 if (flags & FLG_SHDR) 2398 sections(file, cache, shnum, ehdr, Nname); 2399 2400 if (flags & FLG_INTERP) 2401 interp(file, cache, shnum, phnum, elf); 2402 2403 versymcache = versions(cache, shnum, file, flags); 2404 2405 if (flags & FLG_SYMBOLS) 2406 symbols(cache, shnum, ehdr, Nname, versymcache, file, flags); 2407 2408 if (flags & FLG_HASH) 2409 hash(cache, shnum, Nname, file, flags); 2410 2411 if (flags & FLG_GOT) 2412 got(cache, shnum, ehdr, file, flags); 2413 2414 if (flags & FLG_GROUP) 2415 group(cache, shnum, Nname, file, flags); 2416 2417 if (flags & FLG_SYMINFO) 2418 syminfo(cache, shnum, file); 2419 2420 if (flags & FLG_RELOC) 2421 reloc(cache, shnum, ehdr, Nname, file, flags); 2422 2423 if (flags & FLG_DYNAMIC) 2424 dynamic(cache, shnum, ehdr, file); 2425 2426 if (flags & FLG_NOTE) 2427 note(cache, shnum, Nname, file); 2428 2429 if (flags & FLG_MOVE) 2430 move(cache, shnum, Nname, file, flags); 2431 2432 if (flags & FLG_CHECKSUM) 2433 checksum(elf); 2434 2435 if (flags & FLG_CAP) 2436 cap(file, cache, shnum, phnum, ehdr, elf); 2437 2438 if (flags & FLG_UNWIND) 2439 unwind(cache, shnum, phnum, ehdr, Nname, file, elf); 2440 2441 free(cache); 2442 } 2443