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