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