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