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 { 328 size_t seccnt; 329 330 for (seccnt = 1; seccnt < shnum; seccnt++) { 331 Cache *_cache = &cache[seccnt]; 332 Shdr *shdr = _cache->c_shdr; 333 const char *secname = _cache->c_name; 334 335 /* 336 * Although numerous section header entries can be zero, it's 337 * usually a sign of trouble if the type is zero. 338 */ 339 if (shdr->sh_type == 0) { 340 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE), 341 file, secname, EC_WORD(shdr->sh_type)); 342 } 343 344 if (!match(0, secname, seccnt)) 345 continue; 346 347 /* 348 * Identify any sections that are suspicious. A .got section 349 * shouldn't exist in a relocatable object. 350 */ 351 if (ehdr->e_type == ET_REL) { 352 if (strncmp(secname, MSG_ORIG(MSG_ELF_GOT), 353 MSG_ELF_GOT_SIZE) == 0) { 354 (void) fprintf(stderr, 355 MSG_INTL(MSG_GOT_UNEXPECTED), file, 356 secname); 357 } 358 } 359 360 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 361 dbg_print(0, MSG_INTL(MSG_ELF_SHDR), EC_WORD(seccnt), secname); 362 Elf_shdr(0, ehdr->e_machine, shdr); 363 } 364 } 365 366 /* 367 * A couple of instances of unwind data are printed as tables of 8 data items 368 * expressed as 0x?? integers. 369 */ 370 #define UNWINDTBLSZ 10 + (8 * 5) + 1 371 372 static void 373 unwindtbl(uint64_t *ndx, uint_t len, uchar_t *data, uint64_t doff, 374 const char *msg, const char *pre, size_t plen) 375 { 376 char buffer[UNWINDTBLSZ]; 377 uint_t boff = plen, cnt = 0; 378 379 dbg_print(0, msg); 380 (void) strncpy(buffer, pre, UNWINDTBLSZ); 381 382 while (*ndx < (len + 4)) { 383 if (cnt == 8) { 384 dbg_print(0, buffer); 385 boff = plen; 386 cnt = 0; 387 } 388 (void) snprintf(&buffer[boff], UNWINDTBLSZ - boff, 389 MSG_ORIG(MSG_UNW_TBLENTRY), data[doff + (*ndx)++]); 390 boff += 5; 391 cnt++; 392 } 393 if (cnt) 394 dbg_print(0, buffer); 395 } 396 397 /* 398 * Obtain a specified Phdr entry. 399 */ 400 static Phdr * 401 getphdr(Word phnum, Word type, const char *file, Elf *elf) 402 { 403 Word cnt; 404 Phdr *phdr; 405 406 if ((phdr = elf_getphdr(elf)) == NULL) { 407 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 408 return (0); 409 } 410 411 for (cnt = 0; cnt < phnum; phdr++, cnt++) { 412 if (phdr->p_type == type) 413 return (phdr); 414 } 415 return (0); 416 } 417 418 static void 419 unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *file, 420 Elf *elf) 421 { 422 Word cnt; 423 Phdr *uphdr = 0; 424 425 /* 426 * For the moment - UNWIND is only relevant for a AMD64 object. 427 */ 428 if (ehdr->e_machine != EM_AMD64) 429 return; 430 431 if (phnum) 432 uphdr = getphdr(phnum, PT_SUNW_UNWIND, file, elf); 433 434 for (cnt = 1; cnt < shnum; cnt++) { 435 Cache *_cache = &cache[cnt]; 436 Shdr *shdr = _cache->c_shdr; 437 uchar_t *data; 438 size_t datasize; 439 uint64_t off, ndx, frame_ptr, fde_cnt, tabndx; 440 uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc; 441 442 /* 443 * AMD64 - this is a strmcp() just to find the gcc produced 444 * sections. Soon gcc should be setting the section type - and 445 * we'll not need this strcmp(). 446 */ 447 if ((shdr->sh_type != SHT_AMD64_UNWIND) && 448 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM), 449 MSG_SCN_FRM_SIZE) != 0) && 450 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 451 MSG_SCN_FRMHDR_SIZE) != 0)) 452 continue; 453 454 if (!match(0, _cache->c_name, cnt)) 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 uint_t 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, 569 MSG_ORIG(MSG_UNW_CIEAXVAL)); 570 571 for (cieaugndx = 0; cieaugstr[cieaugndx]; 572 cieaugndx++) { 573 uint_t val; 574 575 switch (cieaugstr[cieaugndx]) { 576 case 'z': 577 val = uleb_extract(&data[off], 578 &ndx); 579 dbg_print(0, 580 MSG_ORIG(MSG_UNW_CIEAXSIZ), 581 val); 582 cieZflag = 1; 583 break; 584 case 'P': 585 ciePflag = data[off + ndx]; 586 ndx += 1; 587 588 persVal = dwarf_ehe_extract( 589 &data[off], &ndx, ciePflag, 590 ehdr->e_ident, 591 shdr->sh_addr + off + ndx); 592 dbg_print(0, 593 MSG_ORIG(MSG_UNW_CIEAXPERS), 594 ciePflag, 595 conv_dwarf_ehe(ciePflag), 596 EC_XWORD(persVal)); 597 break; 598 case 'R': 599 val = data[off + ndx]; 600 ndx += 1; 601 dbg_print(0, 602 MSG_ORIG(MSG_UNW_CIEAXCENC), 603 val, conv_dwarf_ehe(val)); 604 cieRflag = val; 605 break; 606 case 'L': 607 val = data[off + ndx]; 608 ndx += 1; 609 dbg_print(0, 610 MSG_ORIG(MSG_UNW_CIEAXLSDA), 611 val, conv_dwarf_ehe(val)); 612 cieLflag = val; 613 break; 614 default: 615 dbg_print(0, 616 MSG_ORIG(MSG_UNW_CIEAXUNEC), 617 cieaugstr[cieaugndx]); 618 break; 619 } 620 } 621 if ((cielength + 4) > ndx) 622 unwindtbl(&ndx, cielength, data, off, 623 MSG_ORIG(MSG_UNW_CIECFI), 624 MSG_ORIG(MSG_UNW_CIEPRE), 625 MSG_UNW_CIEPRE_SIZE); 626 off += cielength + 4; 627 628 } else { 629 uint_t fdelength = length; 630 int fdecieptr = id; 631 uint64_t fdeinitloc, fdeaddrrange; 632 633 dbg_print(0, MSG_ORIG(MSG_UNW_FDE), 634 EC_XWORD(shdr->sh_addr + off)); 635 dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH), 636 fdelength, fdecieptr); 637 638 fdeinitloc = dwarf_ehe_extract(&data[off], 639 &ndx, cieRflag, ehdr->e_ident, 640 shdr->sh_addr + off + ndx); 641 fdeaddrrange = dwarf_ehe_extract(&data[off], 642 &ndx, (cieRflag & ~DW_EH_PE_pcrel), 643 ehdr->e_ident, 644 shdr->sh_addr + off + ndx); 645 646 dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC), 647 EC_XWORD(fdeinitloc), 648 EC_XWORD(fdeaddrrange)); 649 650 if (cieaugstr[0]) 651 dbg_print(0, 652 MSG_ORIG(MSG_UNW_FDEAXVAL)); 653 if (cieZflag) { 654 uint64_t val; 655 val = uleb_extract(&data[off], &ndx); 656 dbg_print(0, 657 MSG_ORIG(MSG_UNW_FDEAXSIZE), 658 EC_XWORD(val)); 659 if (val & cieLflag) { 660 fdeinitloc = dwarf_ehe_extract( 661 &data[off], &ndx, cieLflag, 662 ehdr->e_ident, 663 shdr->sh_addr + off + ndx); 664 dbg_print(0, 665 MSG_ORIG(MSG_UNW_FDEAXLSDA), 666 EC_XWORD(val)); 667 } 668 } 669 if ((fdelength + 4) > ndx) 670 unwindtbl(&ndx, fdelength, data, off, 671 MSG_ORIG(MSG_UNW_FDECFI), 672 MSG_ORIG(MSG_UNW_FDEPRE), 673 MSG_UNW_FDEPRE_SIZE); 674 off += fdelength + 4; 675 } 676 } 677 } 678 } 679 680 /* 681 * Print the hardware/software capabilities. For executables and shared objects 682 * this should be accompanied with a program header. 683 */ 684 static void 685 cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, 686 Elf *elf) 687 { 688 Word cnt; 689 Shdr *cshdr = 0; 690 Cache *ccache; 691 Off cphdr_off = 0; 692 Xword cphdr_sz; 693 694 /* 695 * Determine if a hardware/software capabilities header exists. 696 */ 697 if (phnum) { 698 Phdr *phdr; 699 700 if ((phdr = elf_getphdr(elf)) == NULL) { 701 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 702 return; 703 } 704 705 for (cnt = 0; cnt < phnum; phdr++, cnt++) { 706 if (phdr->p_type == PT_SUNWCAP) { 707 cphdr_off = phdr->p_offset; 708 cphdr_sz = phdr->p_filesz; 709 break; 710 } 711 } 712 } 713 714 /* 715 * Determine if a hardware/software capabilities section exists. 716 */ 717 for (cnt = 1; cnt < shnum; cnt++) { 718 Cache *_cache = &cache[cnt]; 719 Shdr *shdr = _cache->c_shdr; 720 721 if (shdr->sh_type != SHT_SUNW_cap) 722 continue; 723 724 if (cphdr_off && ((cphdr_off < shdr->sh_offset) || 725 (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size))) 726 continue; 727 728 if (_cache->c_data == NULL) 729 continue; 730 731 ccache = _cache; 732 cshdr = shdr; 733 break; 734 } 735 736 if ((cshdr == 0) && (cphdr_off == 0)) 737 return; 738 739 if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) { 740 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 741 file, ccache->c_name); 742 return; 743 } 744 745 /* 746 * Print the hardware/software capabilities section. 747 */ 748 if (cshdr) { 749 Word ndx, capn; 750 Cap *cap = (Cap *)ccache->c_data->d_buf; 751 752 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 753 dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name); 754 755 Elf_cap_title(0); 756 757 capn = (Word)(cshdr->sh_size / cshdr->sh_entsize); 758 759 for (ndx = 0; ndx < capn; cap++, ndx++) { 760 if (cap->c_tag != CA_SUNW_NULL) 761 Elf_cap_entry(0, cap, ndx, ehdr->e_machine); 762 } 763 } else 764 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file); 765 766 /* 767 * If this object is an executable or shared object, then the 768 * hardware/software capabilities section should have an accompanying 769 * program header. 770 */ 771 if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) { 772 if (cphdr_off == 0) 773 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2), 774 file, ccache->c_name); 775 else if ((cphdr_off != cshdr->sh_offset) || 776 (cphdr_sz != cshdr->sh_size)) 777 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3), 778 file, ccache->c_name); 779 } 780 } 781 782 /* 783 * Print the interpretor. 784 */ 785 static void 786 interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf) 787 { 788 Word cnt; 789 Shdr *ishdr = 0; 790 Cache *icache; 791 Off iphdr_off = 0; 792 Xword iphdr_fsz; 793 794 /* 795 * Determine if an interp header exists. 796 */ 797 if (phnum) { 798 Phdr *phdr; 799 800 if ((phdr = getphdr(phnum, PT_INTERP, file, elf)) != 0) { 801 iphdr_off = phdr->p_offset; 802 iphdr_fsz = phdr->p_filesz; 803 } 804 } 805 806 if (iphdr_off == 0) 807 return; 808 809 /* 810 * Determine if an interp section exists. 811 */ 812 for (cnt = 1; cnt < shnum; cnt++) { 813 Cache *_cache = &cache[cnt]; 814 Shdr *shdr = _cache->c_shdr; 815 816 /* 817 * Scan sections to find a section which contains the PT_INTERP 818 * string. The target section can't be in a NOBITS section. 819 */ 820 if ((shdr->sh_type == SHT_NOBITS) || 821 (iphdr_off < shdr->sh_offset) || 822 (iphdr_off + iphdr_fsz) > (shdr->sh_offset + shdr->sh_size)) 823 continue; 824 825 icache = _cache; 826 ishdr = shdr; 827 break; 828 } 829 830 /* 831 * Print the interpreter string based on the offset defined in the 832 * program header, as this is the offset used by the kernel. 833 */ 834 if (ishdr && icache->c_data) { 835 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 836 dbg_print(0, MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name); 837 dbg_print(0, MSG_ORIG(MSG_FMT_INDENT), 838 (char *)icache->c_data->d_buf + 839 (iphdr_off - ishdr->sh_offset)); 840 } else 841 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file); 842 843 /* 844 * If there are any inconsistences between the program header and 845 * section information, flag them. 846 */ 847 if (ishdr && ((iphdr_off != ishdr->sh_offset) || 848 (iphdr_fsz != ishdr->sh_size))) { 849 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file, 850 icache->c_name); 851 } 852 } 853 854 /* 855 * Print the syminfo section. 856 */ 857 static void 858 syminfo(Cache *cache, Word shnum, const char *file) 859 { 860 Shdr *infoshdr; 861 Syminfo *info; 862 Sym *syms; 863 Dyn *dyns; 864 Word infonum, cnt, ndx, symnum; 865 Cache *infocache = 0, *symsec, *strsec; 866 867 for (cnt = 1; cnt < shnum; cnt++) { 868 if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) { 869 infocache = &cache[cnt]; 870 break; 871 } 872 } 873 if (infocache == 0) 874 return; 875 876 infoshdr = infocache->c_shdr; 877 if ((infoshdr->sh_entsize == 0) || (infoshdr->sh_size == 0)) { 878 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 879 file, infocache->c_name); 880 return; 881 } 882 if (infocache->c_data == NULL) 883 return; 884 885 infonum = (Word)(infoshdr->sh_size / infoshdr->sh_entsize); 886 info = (Syminfo *)infocache->c_data->d_buf; 887 888 /* 889 * Get the data buffer of the associated dynamic section. 890 */ 891 if ((infoshdr->sh_info == 0) || (infoshdr->sh_info >= shnum)) { 892 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 893 file, infocache->c_name, EC_WORD(infoshdr->sh_info)); 894 return; 895 } 896 if (cache[infoshdr->sh_info].c_data == NULL) 897 return; 898 899 dyns = cache[infoshdr->sh_info].c_data->d_buf; 900 if (dyns == 0) { 901 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 902 file, cache[infoshdr->sh_info].c_name); 903 return; 904 } 905 906 /* 907 * Get the data buffer for the associated symbol table and string table. 908 */ 909 if (stringtbl(cache, 1, cnt, shnum, file, 910 &symnum, &symsec, &strsec) == 0) 911 return; 912 913 syms = symsec->c_data->d_buf; 914 915 /* 916 * Loop through the syminfo entries. 917 */ 918 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 919 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMINFO), infocache->c_name); 920 Elf_syminfo_title(0); 921 922 for (ndx = 1, info++; ndx < infonum; ndx++, info++) { 923 Sym *sym; 924 const char *needed = 0, *name; 925 926 if ((info->si_flags == 0) && (info->si_boundto == 0)) 927 continue; 928 929 sym = &syms[ndx]; 930 name = string(infocache, ndx, strsec, file, sym->st_name); 931 932 if (info->si_boundto < SYMINFO_BT_LOWRESERVE) { 933 Dyn *dyn = &dyns[info->si_boundto]; 934 935 needed = string(infocache, info->si_boundto, 936 strsec, file, dyn->d_un.d_val); 937 } 938 Elf_syminfo_entry(0, ndx, info, name, needed); 939 } 940 } 941 942 /* 943 * Print version definition section entries. 944 */ 945 static void 946 version_def(Verdef *vdf, Word shnum, Cache *vcache, Cache *scache, 947 const char *file) 948 { 949 Word cnt; 950 char index[MAXNDXSIZE]; 951 952 Elf_ver_def_title(0); 953 954 for (cnt = 1; cnt <= shnum; cnt++, 955 vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) { 956 const char *name, *dep; 957 Half vcnt = vdf->vd_cnt - 1; 958 Half ndx = vdf->vd_ndx; 959 Verdaux *vdap = (Verdaux *)((uintptr_t)vdf + 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 + vnd->vn_aux); 1008 1009 /* 1010 * Obtain the name of the needed file and the version name 1011 * within it that we're dependent on. Note that the count 1012 * should be at least one, otherwise this is a pretty bogus 1013 * entry. 1014 */ 1015 name = string(vcache, cnt, scache, file, vnd->vn_file); 1016 if (vcnt) 1017 dep = string(vcache, cnt, scache, file, vnap->vna_name); 1018 else 1019 dep = MSG_INTL(MSG_STR_NULL); 1020 1021 Elf_ver_line_1(0, MSG_ORIG(MSG_STR_EMPTY), name, dep, 1022 conv_ver_flags(vnap->vna_flags)); 1023 1024 /* 1025 * Print any additional version dependencies. 1026 */ 1027 if (vcnt) { 1028 vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next); 1029 for (vcnt--; vcnt; vcnt--, 1030 vnap = (Vernaux *)((uintptr_t)vnap + 1031 vnap->vna_next)) { 1032 dep = string(vcache, cnt, scache, file, 1033 vnap->vna_name); 1034 Elf_ver_line_3(0, MSG_ORIG(MSG_STR_EMPTY), dep, 1035 conv_ver_flags(vnap->vna_flags)); 1036 } 1037 } 1038 } 1039 } 1040 1041 /* 1042 * Display version section information if the flags require it. 1043 * Return version information needed by other output. 1044 * 1045 * entry: 1046 * cache - Cache of all section headers 1047 * shnum - # of sections in cache 1048 * file - Name of file 1049 * flags - Command line option flags 1050 * versym - VERSYM_STATE block to be filled in. 1051 */ 1052 static void 1053 versions(Cache *cache, Word shnum, const char *file, uint_t flags, 1054 VERSYM_STATE *versym) 1055 { 1056 GElf_Word cnt; 1057 const char *gnu_prefix; 1058 size_t gnu_prefix_len; 1059 1060 bzero(versym, sizeof (*versym)); 1061 gnu_prefix = MSG_ORIG(MSG_GNU_VERNAMPREFIX); 1062 gnu_prefix_len = strlen(gnu_prefix); 1063 1064 for (cnt = 1; cnt < shnum; cnt++) { 1065 void *ver; 1066 uint_t num; 1067 Cache *_cache = &cache[cnt]; 1068 Shdr *shdr = _cache->c_shdr; 1069 const char *secname = _cache->c_name; 1070 1071 /* 1072 * If the section names starts with the .gnu.version prefix, 1073 * then this object was almost certainly produced by the 1074 * GNU ld and not the native Solaris ld. 1075 */ 1076 if (strncmp(gnu_prefix, secname, gnu_prefix_len) == 0) 1077 versym->gnu = 1; 1078 1079 /* 1080 * If this is the version symbol table record its data 1081 * address for later symbol processing. 1082 */ 1083 if ((shdr->sh_type == SHT_SUNW_versym) && 1084 (_cache->c_data != NULL)) { 1085 versym->cache = _cache; 1086 versym->data = _cache->c_data->d_buf; 1087 continue; 1088 } 1089 1090 /* 1091 * If this is a version definition section, retain # of 1092 * version definitions for later symbol processing. 1093 */ 1094 if (shdr->sh_type == SHT_SUNW_verdef) 1095 versym->num_verdef = shdr->sh_info; 1096 1097 if ((flags & FLG_VERSIONS) == 0) 1098 continue; 1099 1100 if ((shdr->sh_type != SHT_SUNW_verdef) && 1101 (shdr->sh_type != SHT_SUNW_verneed)) 1102 continue; 1103 1104 /* 1105 * Determine the version section data and number. 1106 */ 1107 if ((_cache->c_data == NULL) || 1108 ((ver = (void *)_cache->c_data->d_buf) == NULL)) { 1109 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1110 file, secname); 1111 continue; 1112 } 1113 if ((num = shdr->sh_info) == 0) { 1114 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 1115 file, secname, EC_WORD(shdr->sh_info)); 1116 continue; 1117 } 1118 1119 /* 1120 * Get the data buffer for the associated string table. 1121 */ 1122 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1123 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1124 file, secname, EC_WORD(shdr->sh_link)); 1125 continue; 1126 } 1127 1128 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1129 if (shdr->sh_type == SHT_SUNW_verdef) { 1130 dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERDEF), secname); 1131 version_def((Verdef *)ver, num, _cache, 1132 &cache[shdr->sh_link], file); 1133 } else if (shdr->sh_type == SHT_SUNW_verneed) { 1134 dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERNEED), secname); 1135 version_need((Verneed *)ver, num, _cache, 1136 &cache[shdr->sh_link], file); 1137 } 1138 } 1139 } 1140 1141 /* 1142 * Initialize a symbol table state structure 1143 * 1144 * entry: 1145 * state - State structure to be initialized 1146 * cache - Cache of all section headers 1147 * shnum - # of sections in cache 1148 * secndx - Index of symbol table section 1149 * ehdr - ELF header for file 1150 * versym - Information about versym section 1151 * file - Name of file 1152 * flags - Command line option flags 1153 */ 1154 static int 1155 init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx, 1156 Ehdr *ehdr, VERSYM_STATE *versym, const char *file, uint_t flags) 1157 { 1158 Shdr *shdr; 1159 1160 state->file = file; 1161 state->ehdr = ehdr; 1162 state->cache = cache; 1163 state->shnum = shnum; 1164 state->seccache = &cache[secndx]; 1165 state->secndx = secndx; 1166 state->secname = state->seccache->c_name; 1167 state->flags = flags; 1168 state->shxndx.checked = 0; 1169 state->shxndx.data = NULL; 1170 state->shxndx.n = 0; 1171 1172 shdr = state->seccache->c_shdr; 1173 1174 /* 1175 * Check the symbol data and per-item size. 1176 */ 1177 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1178 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1179 file, state->secname); 1180 return (0); 1181 } 1182 if (state->seccache->c_data == NULL) 1183 return (0); 1184 1185 /* LINTED */ 1186 state->symn = (Word)(shdr->sh_size / shdr->sh_entsize); 1187 state->sym = (Sym *)state->seccache->c_data->d_buf; 1188 1189 /* 1190 * Check associated string table section. 1191 */ 1192 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1193 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1194 file, state->secname, EC_WORD(shdr->sh_link)); 1195 return (0); 1196 } 1197 1198 /* 1199 * Determine if there is a associated Versym section 1200 * with this Symbol Table. 1201 */ 1202 if (versym->cache && 1203 (versym->cache->c_shdr->sh_link == state->secndx)) 1204 state->versym = versym; 1205 else 1206 state->versym = NULL; 1207 1208 1209 return (1); 1210 } 1211 1212 /* 1213 * Determine the extended section index used for symbol tables entries. 1214 */ 1215 static void 1216 symbols_getxindex(SYMTBL_STATE * state) 1217 { 1218 uint_t symn; 1219 Word symcnt; 1220 1221 state->shxndx.checked = 1; /* Note that we've been called */ 1222 for (symcnt = 1; symcnt < state->shnum; symcnt++) { 1223 Cache *_cache = &state->cache[symcnt]; 1224 Shdr *shdr = _cache->c_shdr; 1225 1226 if ((shdr->sh_type != SHT_SYMTAB_SHNDX) || 1227 (shdr->sh_link != state->secndx)) 1228 continue; 1229 1230 if ((shdr->sh_entsize) && 1231 /* LINTED */ 1232 ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0)) 1233 continue; 1234 1235 if (_cache->c_data == NULL) 1236 continue; 1237 1238 state->shxndx.data = _cache->c_data->d_buf; 1239 state->shxndx.n = symn; 1240 return; 1241 } 1242 } 1243 1244 /* 1245 * Produce a line of output for the given symbol 1246 * 1247 * entry: 1248 * state - Symbol table state 1249 * symndx - Index of symbol within the table 1250 * symndx_disp - Index to display. This may not be the same 1251 * as symndx if the display is relative to the logical 1252 * combination of the SUNW_ldynsym/dynsym tables. 1253 * sym - Symbol to display 1254 */ 1255 static void 1256 output_symbol(SYMTBL_STATE *state, Word symndx, Word disp_symndx, Sym *sym) 1257 { 1258 /* 1259 * Symbol types for which we check that the specified 1260 * address/size land inside the target section. 1261 */ 1262 static const int addr_symtype[STT_NUM] = { 1263 0, /* STT_NOTYPE */ 1264 1, /* STT_OBJECT */ 1265 1, /* STT_FUNC */ 1266 0, /* STT_SECTION */ 1267 0, /* STT_FILE */ 1268 1, /* STT_COMMON */ 1269 0, /* STT_TLS */ 1270 }; 1271 #if STT_NUM != (STT_TLS + 1) 1272 #error "STT_NUM has grown. Update addr_symtype[]" 1273 #endif 1274 1275 char index[MAXNDXSIZE], *sec; 1276 const char *symname; 1277 Versym verndx; 1278 uchar_t type; 1279 Shdr *tshdr; 1280 Word shndx; 1281 1282 /* Ensure symbol index is in range */ 1283 if (symndx >= state->symn) { 1284 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORTNDX), 1285 state->file, state->secname, EC_WORD(symndx)); 1286 return; 1287 } 1288 1289 /* 1290 * If we are using extended symbol indexes, find the 1291 * corresponding SHN_SYMTAB_SHNDX table. 1292 */ 1293 if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0)) 1294 symbols_getxindex(state); 1295 1296 /* LINTED */ 1297 symname = string(state->seccache, symndx, 1298 &state->cache[state->seccache->c_shdr->sh_link], state->file, 1299 sym->st_name); 1300 1301 tshdr = 0; 1302 sec = NULL; 1303 1304 if ((state->ehdr->e_type == ET_CORE)) 1305 sec = (char *)MSG_INTL(MSG_STR_UNKNOWN); 1306 else if ((sym->st_shndx < SHN_LORESERVE) && 1307 (sym->st_shndx < state->shnum)) { 1308 shndx = sym->st_shndx; 1309 tshdr = state->cache[shndx].c_shdr; 1310 sec = state->cache[shndx].c_name; 1311 } else if (sym->st_shndx == SHN_XINDEX) { 1312 if (state->shxndx.data) { 1313 Word _shxndx; 1314 1315 if (symndx > state->shxndx.n) { 1316 (void) fprintf(stderr, 1317 MSG_INTL(MSG_ERR_BADSYMXINDEX1), 1318 state->file, state->secname, 1319 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, 1325 EC_WORD(symndx), 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_DIAG(sym->st_shndx, 1366 state->versym->num_verdef, state->versym->data, symndx)) { 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, VERSYM_STATE *versym, 1446 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 (!match(0, _cache->c_name, secndx)) 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, VERSYM_STATE *versym, 1488 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 (!match(0, sortcache->c_name, sortsecndx)) 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 *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 (!match(0, relname, cnt)) 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 *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 (!match(0, _cache->c_name, cnt)) 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 *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 (!match(0, _cache->c_name, cnt)) 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 *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 2220 /* 2221 * Determine the hash table data and size. 2222 */ 2223 if ((hshdr->sh_entsize == 0) || (hshdr->sh_size == 0)) { 2224 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2225 file, hsecname); 2226 continue; 2227 } 2228 if (_cache->c_data == NULL) 2229 continue; 2230 2231 hash = (uint_t *)_cache->c_data->d_buf; 2232 bkts = *hash; 2233 chain = hash + 2 + bkts; 2234 hash += 2; 2235 2236 /* 2237 * Get the data buffer for the associated symbol table. 2238 */ 2239 if ((hshdr->sh_link == 0) || (hshdr->sh_link >= shnum)) { 2240 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2241 file, hsecname, EC_WORD(hshdr->sh_link)); 2242 continue; 2243 } 2244 2245 _cache = &cache[hshdr->sh_link]; 2246 ssecname = _cache->c_name; 2247 2248 if (_cache->c_data == NULL) 2249 continue; 2250 2251 if ((syms = (Sym *)_cache->c_data->d_buf) == NULL) { 2252 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2253 file, ssecname); 2254 continue; 2255 } 2256 2257 sshdr = _cache->c_shdr; 2258 /* LINTED */ 2259 symn = (Word)(sshdr->sh_size / sshdr->sh_entsize); 2260 2261 /* 2262 * Get the associated string table section. 2263 */ 2264 if ((sshdr->sh_link == 0) || (sshdr->sh_link >= shnum)) { 2265 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2266 file, ssecname, EC_WORD(sshdr->sh_link)); 2267 continue; 2268 } 2269 2270 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2271 dbg_print(0, MSG_INTL(MSG_ELF_SCN_HASH), hsecname); 2272 dbg_print(0, MSG_INTL(MSG_ELF_HASH_INFO)); 2273 2274 /* 2275 * Loop through the hash buckets, printing the appropriate 2276 * symbols. 2277 */ 2278 for (ndx = 0; ndx < bkts; ndx++, hash++) { 2279 Word _ndx, _cnt; 2280 2281 if (*hash == 0) { 2282 count[0]++; 2283 continue; 2284 } 2285 2286 hash_entry(_cache, &cache[sshdr->sh_link], hsecname, 2287 ndx, *hash, symn, syms, file, bkts, flags, 0); 2288 2289 /* 2290 * Determine if any other symbols are chained to this 2291 * bucket. 2292 */ 2293 _ndx = chain[*hash]; 2294 _cnt = 1; 2295 while (_ndx) { 2296 hash_entry(_cache, &cache[sshdr->sh_link], 2297 hsecname, ndx, _ndx, symn, syms, file, 2298 bkts, flags, 1); 2299 _ndx = chain[_ndx]; 2300 _cnt++; 2301 } 2302 2303 if (_cnt >= MAXCOUNT) { 2304 (void) fprintf(stderr, 2305 MSG_INTL(MSG_HASH_OVERFLW), file, 2306 _cache->c_name, EC_WORD(ndx), 2307 EC_WORD(_cnt)); 2308 } else 2309 count[_cnt]++; 2310 } 2311 break; 2312 } 2313 2314 /* 2315 * Print out the count information. 2316 */ 2317 bkts = cnt = 0; 2318 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2319 2320 for (ndx = 0; ndx < MAXCOUNT; ndx++) { 2321 Word _cnt; 2322 2323 if ((_cnt = count[ndx]) == 0) 2324 continue; 2325 2326 (void) snprintf(number, MAXNDXSIZE, 2327 MSG_ORIG(MSG_FMT_INTEGER), _cnt); 2328 dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS1), number, 2329 EC_WORD(ndx)); 2330 bkts += _cnt; 2331 cnt += (Word)(ndx * _cnt); 2332 } 2333 if (cnt) { 2334 (void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 2335 bkts); 2336 dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS2), number, 2337 EC_WORD(cnt)); 2338 } 2339 } 2340 2341 static void 2342 group(Cache *cache, Word shnum, const char *file, uint_t flags) 2343 { 2344 Word scnt; 2345 2346 for (scnt = 1; scnt < shnum; scnt++) { 2347 Cache *_cache = &cache[scnt]; 2348 Shdr *shdr = _cache->c_shdr; 2349 Word *grpdata, gcnt, grpcnt, symnum, unknown; 2350 Cache *symsec, *strsec; 2351 Sym *syms, *sym; 2352 char flgstrbuf[MSG_GRP_COMDAT_SIZE + 10]; 2353 2354 if (shdr->sh_type != SHT_GROUP) 2355 continue; 2356 if (!match(0, _cache->c_name, scnt)) 2357 continue; 2358 if ((_cache->c_data == NULL) || 2359 ((grpdata = (Word *)_cache->c_data->d_buf) == NULL)) 2360 continue; 2361 grpcnt = shdr->sh_size / sizeof (Word); 2362 2363 /* 2364 * Get the data buffer for the associated symbol table and 2365 * string table. 2366 */ 2367 if (stringtbl(cache, 1, scnt, shnum, file, 2368 &symnum, &symsec, &strsec) == 0) 2369 return; 2370 2371 syms = symsec->c_data->d_buf; 2372 2373 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2374 dbg_print(0, MSG_INTL(MSG_ELF_SCN_GRP), _cache->c_name); 2375 dbg_print(0, MSG_INTL(MSG_GRP_TITLE)); 2376 2377 /* 2378 * The first element of the group defines the group. The 2379 * associated symbol is defined by the sh_link field. 2380 */ 2381 if ((shdr->sh_info == SHN_UNDEF) || (shdr->sh_info > symnum)) { 2382 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 2383 file, _cache->c_name, EC_WORD(shdr->sh_info)); 2384 return; 2385 } 2386 2387 (void) strcpy(flgstrbuf, MSG_ORIG(MSG_STR_OSQBRKT)); 2388 if (grpdata[0] & GRP_COMDAT) { 2389 (void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_COMDAT)); 2390 } 2391 if ((unknown = (grpdata[0] & ~GRP_COMDAT)) != 0) { 2392 size_t len = strlen(flgstrbuf); 2393 2394 (void) snprintf(&flgstrbuf[len], 2395 (MSG_GRP_COMDAT_SIZE + 10 - len), 2396 MSG_ORIG(MSG_GRP_UNKNOWN), unknown); 2397 } 2398 (void) strcat(flgstrbuf, MSG_ORIG(MSG_STR_CSQBRKT)); 2399 sym = (Sym *)(syms + shdr->sh_info); 2400 2401 dbg_print(0, MSG_INTL(MSG_GRP_SIGNATURE), flgstrbuf, 2402 demangle(string(_cache, 0, strsec, file, sym->st_name), 2403 flags)); 2404 2405 for (gcnt = 1; gcnt < grpcnt; gcnt++) { 2406 char index[MAXNDXSIZE]; 2407 const char *name; 2408 2409 (void) snprintf(index, MAXNDXSIZE, 2410 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(gcnt)); 2411 2412 if (grpdata[gcnt] >= shnum) 2413 name = MSG_INTL(MSG_GRP_INVALSCN); 2414 else 2415 name = cache[grpdata[gcnt]].c_name; 2416 2417 (void) printf(MSG_ORIG(MSG_GRP_ENTRY), index, name, 2418 EC_XWORD(grpdata[gcnt])); 2419 } 2420 } 2421 } 2422 2423 static void 2424 got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, uint_t flags) 2425 { 2426 Cache *gotcache = 0, *symtab = 0, *_cache; 2427 Addr gotbgn, gotend; 2428 Shdr *gotshdr; 2429 Word cnt, gotents, gotndx; 2430 size_t gentsize; 2431 Got_info *gottable; 2432 char *gotdata; 2433 Sym *gotsym; 2434 Xword gotsymaddr; 2435 2436 /* 2437 * First, find the got. 2438 */ 2439 for (cnt = 1; cnt < shnum; cnt++) { 2440 _cache = &cache[cnt]; 2441 if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT), 2442 MSG_ELF_GOT_SIZE) == 0) { 2443 gotcache = _cache; 2444 break; 2445 } 2446 } 2447 if (gotcache == 0) 2448 return; 2449 2450 /* 2451 * A got section within a relocatable object is suspicious. 2452 */ 2453 if (ehdr->e_type == ET_REL) { 2454 (void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file, 2455 _cache->c_name); 2456 } 2457 2458 gotshdr = gotcache->c_shdr; 2459 if (gotshdr->sh_size == 0) { 2460 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2461 file, gotcache->c_name); 2462 return; 2463 } 2464 2465 gotbgn = gotshdr->sh_addr; 2466 gotend = gotbgn + gotshdr->sh_size; 2467 2468 /* 2469 * Some architectures don't properly set the sh_entsize for the GOT 2470 * table. If it's not set, default to a size of a pointer. 2471 */ 2472 if ((gentsize = gotshdr->sh_entsize) == 0) 2473 gentsize = sizeof (Xword); 2474 2475 if (gotcache->c_data == NULL) 2476 return; 2477 2478 /* LINTED */ 2479 gotents = (Word)(gotshdr->sh_size / gentsize); 2480 gotdata = gotcache->c_data->d_buf; 2481 2482 if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) { 2483 int err = errno; 2484 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), file, 2485 strerror(err)); 2486 return; 2487 } 2488 2489 /* 2490 * Now we scan through all the sections looking for any relocations 2491 * that may be against the GOT. Since these may not be isolated to a 2492 * .rel[a].got section we check them all. 2493 * While scanning sections save the symbol table entry (a symtab 2494 * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_. 2495 */ 2496 for (cnt = 1; cnt < shnum; cnt++) { 2497 Word type, symnum; 2498 Xword relndx, relnum, relsize; 2499 void *rels; 2500 Sym *syms; 2501 Cache *symsec, *strsec; 2502 Cache *_cache = &cache[cnt]; 2503 Shdr *shdr; 2504 2505 shdr = _cache->c_shdr; 2506 type = shdr->sh_type; 2507 2508 if ((symtab == 0) && (type == SHT_DYNSYM)) { 2509 symtab = _cache; 2510 continue; 2511 } 2512 if (type == SHT_SYMTAB) { 2513 symtab = _cache; 2514 continue; 2515 } 2516 if ((type != SHT_RELA) && (type != SHT_REL)) 2517 continue; 2518 2519 /* 2520 * Decide entry size. 2521 */ 2522 if (((relsize = shdr->sh_entsize) == 0) || 2523 (relsize > shdr->sh_size)) { 2524 if (type == SHT_RELA) 2525 relsize = sizeof (Rela); 2526 else 2527 relsize = sizeof (Rel); 2528 } 2529 2530 /* 2531 * Determine the number of relocations available. 2532 */ 2533 if (shdr->sh_size == 0) { 2534 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2535 file, _cache->c_name); 2536 continue; 2537 } 2538 if (_cache->c_data == NULL) 2539 continue; 2540 2541 rels = _cache->c_data->d_buf; 2542 relnum = shdr->sh_size / relsize; 2543 2544 /* 2545 * Get the data buffer for the associated symbol table and 2546 * string table. 2547 */ 2548 if (stringtbl(cache, 1, cnt, shnum, file, 2549 &symnum, &symsec, &strsec) == 0) 2550 continue; 2551 2552 syms = symsec->c_data->d_buf; 2553 2554 /* 2555 * Loop through the relocation entries. 2556 */ 2557 for (relndx = 0; relndx < relnum; relndx++, 2558 rels = (void *)((char *)rels + relsize)) { 2559 char section[BUFSIZ]; 2560 Addr offset; 2561 Got_info *gip; 2562 Word symndx, reltype; 2563 Rela *rela; 2564 Rel *rel; 2565 2566 /* 2567 * Unravel the relocation. 2568 */ 2569 if (type == SHT_RELA) { 2570 rela = (Rela *)rels; 2571 symndx = ELF_R_SYM(rela->r_info); 2572 reltype = ELF_R_TYPE(rela->r_info); 2573 offset = rela->r_offset; 2574 } else { 2575 rel = (Rel *)rels; 2576 symndx = ELF_R_SYM(rel->r_info); 2577 reltype = ELF_R_TYPE(rel->r_info); 2578 offset = rel->r_offset; 2579 } 2580 2581 /* 2582 * Only pay attention to relocations against the GOT. 2583 */ 2584 if ((offset < gotbgn) || (offset >= gotend)) 2585 continue; 2586 2587 /* LINTED */ 2588 gotndx = (Word)((offset - gotbgn) / 2589 gotshdr->sh_entsize); 2590 gip = &gottable[gotndx]; 2591 2592 if (gip->g_reltype != 0) { 2593 (void) fprintf(stderr, 2594 MSG_INTL(MSG_GOT_MULTIPLE), file, 2595 EC_WORD(gotndx), EC_ADDR(offset)); 2596 continue; 2597 } 2598 2599 if (symndx) 2600 gip->g_symname = relsymname(cache, _cache, 2601 strsec, symndx, symnum, relndx, syms, 2602 section, BUFSIZ, file, flags); 2603 gip->g_reltype = reltype; 2604 gip->g_rel = rels; 2605 } 2606 } 2607 2608 if (symlookup(MSG_ORIG(MSG_GOT_SYM), cache, shnum, &gotsym, symtab, 2609 file)) 2610 gotsymaddr = gotsym->st_value; 2611 else 2612 gotsymaddr = gotbgn; 2613 2614 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2615 dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name); 2616 Elf_got_title(0); 2617 2618 for (gotndx = 0; gotndx < gotents; gotndx++) { 2619 Got_info *gip; 2620 Sword gindex; 2621 Addr gaddr; 2622 Xword gotentry; 2623 2624 gip = &gottable[gotndx]; 2625 2626 gaddr = gotbgn + (gotndx * gentsize); 2627 gindex = (Sword)(gaddr - gotsymaddr) / (Sword)gentsize; 2628 2629 if (gentsize == sizeof (Word)) 2630 /* LINTED */ 2631 gotentry = (Xword)(*((Word *)(gotdata) + gotndx)); 2632 else 2633 /* LINTED */ 2634 gotentry = *((Xword *)(gotdata) + gotndx); 2635 2636 Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine, 2637 gip->g_reltype, gip->g_rel, gip->g_symname); 2638 } 2639 free(gottable); 2640 } 2641 2642 void 2643 checksum(Elf *elf) 2644 { 2645 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2646 dbg_print(0, MSG_INTL(MSG_STR_CHECKSUM), elf_checksum(elf)); 2647 } 2648 2649 /* 2650 * This variable is used by regular() to communicate the address of 2651 * the section header cache to sort_shdr_ndx_arr(). Unfortunately, 2652 * the qsort() interface does not include a userdata argument by which 2653 * such arbitrary data can be passed, so we are stuck using global data. 2654 */ 2655 static Cache *sort_shdr_ndx_arr_cache; 2656 2657 2658 /* 2659 * Used with qsort() to sort the section indices so that they can be 2660 * used to access the section headers in order of increasing data offset. 2661 * 2662 * entry: 2663 * sort_shdr_ndx_arr_cache - Contains address of 2664 * section header cache. 2665 * v1, v2 - Point at elements of sort_shdr_bits array to be compared. 2666 * 2667 * exit: 2668 * Returns -1 (less than), 0 (equal) or 1 (greater than). 2669 */ 2670 static int 2671 sort_shdr_ndx_arr(const void *v1, const void *v2) 2672 { 2673 Cache *cache1 = sort_shdr_ndx_arr_cache + *((size_t *)v1); 2674 Cache *cache2 = sort_shdr_ndx_arr_cache + *((size_t *)v2); 2675 2676 if (cache1->c_shdr->sh_offset < cache2->c_shdr->sh_offset) 2677 return (-1); 2678 2679 if (cache1->c_shdr->sh_offset > cache2->c_shdr->sh_offset) 2680 return (1); 2681 2682 return (0); 2683 } 2684 2685 2686 void 2687 regular(const char *file, Elf *elf, uint_t flags, int wfd) 2688 { 2689 Elf_Scn *scn; 2690 Ehdr *ehdr; 2691 Elf_Data *data; 2692 size_t ndx, shstrndx, shnum, phnum; 2693 Shdr *nameshdr, *shdr; 2694 char *names = 0; 2695 Cache *cache, *_cache; 2696 VERSYM_STATE versym; 2697 size_t *shdr_ndx_arr, shdr_ndx_arr_cnt; 2698 2699 if ((ehdr = elf_getehdr(elf)) == NULL) { 2700 failure(file, MSG_ORIG(MSG_ELF_GETEHDR)); 2701 return; 2702 } 2703 2704 if (elf_getshnum(elf, &shnum) == 0) { 2705 failure(file, MSG_ORIG(MSG_ELF_GETSHNUM)); 2706 return; 2707 } 2708 2709 if (elf_getshstrndx(elf, &shstrndx) == 0) { 2710 failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX)); 2711 return; 2712 } 2713 2714 if (elf_getphnum(elf, &phnum) == 0) { 2715 failure(file, MSG_ORIG(MSG_ELF_GETPHNUM)); 2716 return; 2717 } 2718 2719 if ((scn = elf_getscn(elf, 0)) != NULL) { 2720 if ((shdr = elf_getshdr(scn)) == NULL) { 2721 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2722 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0); 2723 return; 2724 } 2725 } else 2726 shdr = 0; 2727 2728 /* 2729 * Print the elf header. 2730 */ 2731 if (flags & FLG_EHDR) 2732 Elf_ehdr(0, ehdr, shdr); 2733 2734 /* 2735 * If the section headers or program headers have inadequate 2736 * alignment for the class of object, print a warning. libelf 2737 * can handle such files, but programs that use them can crash 2738 * when they dereference unaligned items. 2739 */ 2740 if (ehdr->e_phoff & (sizeof (Addr) - 1)) 2741 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADPHDRALIGN), file); 2742 if (ehdr->e_shoff & (sizeof (Addr) - 1)) 2743 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHDRALIGN), file); 2744 2745 /* 2746 * Print the program headers. 2747 */ 2748 if ((flags & FLG_PHDR) && (phnum != 0)) { 2749 Phdr *phdr; 2750 2751 if ((phdr = elf_getphdr(elf)) == NULL) { 2752 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 2753 return; 2754 } 2755 2756 for (ndx = 0; ndx < phnum; phdr++, ndx++) { 2757 if (!match(0, conv_phdr_type(ehdr->e_machine, 2758 phdr->p_type, CONV_FMT_ALTFILE), ndx)) 2759 continue; 2760 2761 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2762 dbg_print(0, MSG_INTL(MSG_ELF_PHDR), EC_WORD(ndx)); 2763 Elf_phdr(0, ehdr->e_machine, phdr); 2764 } 2765 } 2766 2767 /* 2768 * Return now if there are no section, if there's just one section to 2769 * act as an extension of the ELF header, or if only program header 2770 * information was requested. 2771 */ 2772 if ((shnum <= 1) || (flags && (flags & ~(FLG_EHDR | FLG_PHDR)) == 0)) { 2773 if ((ehdr->e_type == ET_CORE) && (flags & FLG_NOTE)) 2774 note(0, shnum, file); 2775 return; 2776 } 2777 2778 /* 2779 * Obtain the .shstrtab data buffer to provide the required section 2780 * name strings. 2781 */ 2782 if (shstrndx == SHN_UNDEF) { 2783 /* 2784 * It is rare, but legal, for an object to lack a 2785 * header string table section. 2786 */ 2787 names = NULL; 2788 (void) fprintf(stderr, MSG_INTL(MSG_ERR_NOSHSTRSEC), file); 2789 } else if ((scn = elf_getscn(elf, shstrndx)) == NULL) { 2790 failure(file, MSG_ORIG(MSG_ELF_GETSCN)); 2791 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR), 2792 EC_XWORD(shstrndx)); 2793 2794 } else if ((data = elf_getdata(scn, NULL)) == NULL) { 2795 failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 2796 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA), 2797 EC_XWORD(shstrndx)); 2798 2799 } else if ((nameshdr = elf_getshdr(scn)) == NULL) { 2800 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2801 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 2802 EC_WORD(elf_ndxscn(scn))); 2803 2804 } else if ((names = data->d_buf) == 0) 2805 (void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file); 2806 2807 /* 2808 * Allocate a cache to maintain a descriptor for each section. 2809 */ 2810 if ((cache = malloc(shnum * sizeof (Cache))) == NULL) { 2811 int err = errno; 2812 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2813 file, strerror(err)); 2814 return; 2815 } 2816 2817 *cache = cache_init; 2818 _cache = cache; 2819 _cache++; 2820 2821 /* 2822 * Allocate an array that will hold the section index for 2823 * each section that has data in the ELF file: 2824 * 2825 * - Is not a NOBITS section 2826 * - Data has non-zero length 2827 * 2828 * Note that shnum is an upper bound on the size required. It 2829 * is likely that we won't use a few of these array elements. 2830 * Allocating a modest amount of extra memory in this case means 2831 * that we can avoid an extra loop to count the number of needed 2832 * items, and can fill this array immediately in the first loop 2833 * below. 2834 */ 2835 if ((shdr_ndx_arr = malloc(shnum * sizeof (*shdr_ndx_arr))) == NULL) { 2836 int err = errno; 2837 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2838 file, strerror(err)); 2839 return; 2840 } 2841 shdr_ndx_arr_cnt = 0; 2842 2843 /* 2844 * Traverse the sections of the file. This gathering of data is 2845 * carried out in two passes. First, the section headers are captured 2846 * and the section header names are evaluated. A verification pass is 2847 * then carried out over the section information. Files have been 2848 * known to exhibit overlapping (and hence erroneous) section header 2849 * information. 2850 * 2851 * Finally, the data for each section is obtained. This processing is 2852 * carried out after section verification because should any section 2853 * header overlap occur, and a file needs translating (ie. xlate'ing 2854 * information from a non-native architecture file), then the process 2855 * of translation can corrupt the section header information. Of 2856 * course, if there is any section overlap, the data related to the 2857 * sections is going to be compromised. However, it is the translation 2858 * of this data that has caused problems with elfdump()'s ability to 2859 * extract the data. 2860 */ 2861 for (ndx = 1, scn = NULL; scn = elf_nextscn(elf, scn); 2862 ndx++, _cache++) { 2863 char scnndxnm[100]; 2864 2865 _cache->c_ndx = ndx; 2866 _cache->c_scn = scn; 2867 2868 if ((_cache->c_shdr = elf_getshdr(scn)) == NULL) { 2869 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2870 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 2871 EC_WORD(elf_ndxscn(scn))); 2872 } 2873 2874 /* 2875 * If this section has data in the file, include it in 2876 * the array of sections to check for address overlap. 2877 */ 2878 if ((_cache->c_shdr->sh_size != 0) && 2879 (_cache->c_shdr->sh_type != SHT_NOBITS)) 2880 shdr_ndx_arr[shdr_ndx_arr_cnt++] = ndx; 2881 2882 /* 2883 * If a shstrtab exists, assign the section name. 2884 */ 2885 if (names && _cache->c_shdr) { 2886 if (_cache->c_shdr->sh_name && 2887 /* LINTED */ 2888 (nameshdr->sh_size > _cache->c_shdr->sh_name)) { 2889 _cache->c_name = 2890 names + _cache->c_shdr->sh_name; 2891 continue; 2892 } 2893 2894 /* 2895 * Generate an error if the section name index is zero 2896 * or exceeds the shstrtab data. Fall through to 2897 * fabricate a section name. 2898 */ 2899 if ((_cache->c_shdr->sh_name == 0) || 2900 /* LINTED */ 2901 (nameshdr->sh_size <= _cache->c_shdr->sh_name)) { 2902 (void) fprintf(stderr, 2903 MSG_INTL(MSG_ERR_BADSHNAME), file, 2904 EC_WORD(ndx), 2905 EC_XWORD(_cache->c_shdr->sh_name)); 2906 } 2907 } 2908 2909 /* 2910 * If there exists no shstrtab data, or a section header has no 2911 * name (an invalid index of 0), then compose a name for the 2912 * section. 2913 */ 2914 (void) snprintf(scnndxnm, sizeof (scnndxnm), 2915 MSG_INTL(MSG_FMT_SCNNDX), ndx); 2916 2917 if ((_cache->c_name = malloc(strlen(scnndxnm) + 1)) == NULL) { 2918 int err = errno; 2919 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2920 file, strerror(err)); 2921 return; 2922 } 2923 (void) strcpy(_cache->c_name, scnndxnm); 2924 } 2925 2926 /* 2927 * Having collected all the sections, validate their address range. 2928 * Cases have existed where the section information has been invalid. 2929 * This can lead to all sorts of other, hard to diagnose errors, as 2930 * each section is processed individually (ie. with elf_getdata()). 2931 * Here, we carry out some address comparisons to catch a family of 2932 * overlapping memory issues we have observed (likely, there are others 2933 * that we have yet to discover). 2934 * 2935 * Note, should any memory overlap occur, obtaining any additional 2936 * data from the file is questionable. However, it might still be 2937 * possible to inspect the ELF header, Programs headers, or individual 2938 * sections, so rather than bailing on an error condition, continue 2939 * processing to see if any data can be salvaged. 2940 */ 2941 if (shdr_ndx_arr_cnt > 1) { 2942 sort_shdr_ndx_arr_cache = cache; 2943 qsort(shdr_ndx_arr, shdr_ndx_arr_cnt, 2944 sizeof (*shdr_ndx_arr), sort_shdr_ndx_arr); 2945 } 2946 for (ndx = 0; ndx < shdr_ndx_arr_cnt; ndx++) { 2947 Cache *_cache = cache + shdr_ndx_arr[ndx]; 2948 Shdr *shdr = _cache->c_shdr; 2949 Off bgn1, bgn = shdr->sh_offset; 2950 Off end1, end = shdr->sh_offset + shdr->sh_size; 2951 size_t ndx1; 2952 2953 /* 2954 * Check the section against all following ones, reporting 2955 * any overlaps. Since we've sorted the sections by offset, 2956 * we can stop after the first comparison that fails. There 2957 * are no overlaps in a properly formed ELF file, in which 2958 * case this algorithm runs in O(n) time. This will degenerate 2959 * to O(n^2) for a completely broken file. Such a file is 2960 * (1) highly unlikely, and (2) unusable, so it is reasonable 2961 * for the analysis to take longer. 2962 */ 2963 for (ndx1 = ndx + 1; ndx1 < shdr_ndx_arr_cnt; ndx1++) { 2964 Cache *_cache1 = cache + shdr_ndx_arr[ndx1]; 2965 Shdr *shdr1 = _cache1->c_shdr; 2966 2967 bgn1 = shdr1->sh_offset; 2968 end1 = shdr1->sh_offset + shdr1->sh_size; 2969 2970 if (((bgn1 <= bgn) && (end1 > bgn)) || 2971 ((bgn1 < end) && (end1 >= end))) { 2972 (void) fprintf(stderr, 2973 MSG_INTL(MSG_ERR_SECMEMOVER), file, 2974 EC_WORD(elf_ndxscn(_cache->c_scn)), 2975 _cache->c_name, EC_OFF(bgn), EC_OFF(end), 2976 EC_WORD(elf_ndxscn(_cache1->c_scn)), 2977 _cache1->c_name, EC_OFF(bgn1), 2978 EC_OFF(end1)); 2979 } else { /* No overlap, so can stop */ 2980 break; 2981 } 2982 } 2983 2984 /* 2985 * In addition to checking for sections overlapping 2986 * each other (done above), we should also make sure 2987 * the section doesn't overlap the section header array. 2988 */ 2989 bgn1 = ehdr->e_shoff; 2990 end1 = ehdr->e_shoff + (ehdr->e_shentsize * ehdr->e_shnum); 2991 2992 if (((bgn1 <= bgn) && (end1 > bgn)) || 2993 ((bgn1 < end) && (end1 >= end))) { 2994 (void) fprintf(stderr, 2995 MSG_INTL(MSG_ERR_SHDRMEMOVER), file, EC_OFF(bgn1), 2996 EC_OFF(end1), 2997 EC_WORD(elf_ndxscn(_cache->c_scn)), 2998 _cache->c_name, EC_OFF(bgn), EC_OFF(end)); 2999 } 3000 } 3001 3002 /* 3003 * Obtain the data for each section. 3004 */ 3005 for (ndx = 1; ndx < shnum; ndx++) { 3006 Cache *_cache = &cache[ndx]; 3007 Elf_Scn *scn = _cache->c_scn; 3008 3009 if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) { 3010 failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 3011 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA), 3012 EC_WORD(elf_ndxscn(scn))); 3013 } 3014 3015 /* 3016 * Do we wish to write the section out? 3017 */ 3018 if (wfd && match(1, _cache->c_name, ndx) && _cache->c_data) { 3019 (void) write(wfd, _cache->c_data->d_buf, 3020 _cache->c_data->d_size); 3021 } 3022 } 3023 3024 if (flags & FLG_SHDR) 3025 sections(file, cache, shnum, ehdr); 3026 3027 if (flags & FLG_INTERP) 3028 interp(file, cache, shnum, phnum, elf); 3029 3030 versions(cache, shnum, file, flags, &versym); 3031 3032 if (flags & FLG_SYMBOLS) 3033 symbols(cache, shnum, ehdr, &versym, file, flags); 3034 3035 if (flags & FLG_SORT) 3036 sunw_sort(cache, shnum, ehdr, &versym, file, flags); 3037 3038 if (flags & FLG_HASH) 3039 hash(cache, shnum, file, flags); 3040 3041 if (flags & FLG_GOT) 3042 got(cache, shnum, ehdr, file, flags); 3043 3044 if (flags & FLG_GROUP) 3045 group(cache, shnum, file, flags); 3046 3047 if (flags & FLG_SYMINFO) 3048 syminfo(cache, shnum, file); 3049 3050 if (flags & FLG_RELOC) 3051 reloc(cache, shnum, ehdr, file, flags); 3052 3053 if (flags & FLG_DYNAMIC) 3054 dynamic(cache, shnum, ehdr, file); 3055 3056 if (flags & FLG_NOTE) 3057 note(cache, shnum, file); 3058 3059 if (flags & FLG_MOVE) 3060 move(cache, shnum, file, flags); 3061 3062 if (flags & FLG_CHECKSUM) 3063 checksum(elf); 3064 3065 if (flags & FLG_CAP) 3066 cap(file, cache, shnum, phnum, ehdr, elf); 3067 3068 if (flags & FLG_UNWIND) 3069 unwind(cache, shnum, phnum, ehdr, file, elf); 3070 3071 free(cache); 3072 } 3073