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