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