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 2008 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 <sys/elf_386.h> 32 #include <sys/elf_amd64.h> 33 #include <sys/elf_SPARC.h> 34 #include <_libelf.h> 35 #include <dwarf.h> 36 #include <stdio.h> 37 #include <unistd.h> 38 #include <errno.h> 39 #include <strings.h> 40 #include <debug.h> 41 #include <conv.h> 42 #include <msg.h> 43 #include <_elfdump.h> 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 * max_verndx contains the largest version index that can appear 52 * in a Versym entry. This can never be less than 1: In the case where 53 * there is no verdef/verneed sections, the [0] index is reserved 54 * for local symbols, and the [1] index for globals. If Solaris versioning 55 * rules are in effect and there is a verdef section, then the number 56 * of defined versions provides this number. If GNU versioning is in effect, 57 * then: 58 * - If there is no verneed section, it is the same as for 59 * Solaris versioning. 60 * - If there is a verneed section, the vna_other field of the 61 * Vernaux structs contain versions, and max_verndx is the 62 * largest such index. 63 * 64 * The value of the gnu field is based on the presence of 65 * a DT_VERSYM entry in the dynamic section: GNU ld produces these, and 66 * Solaris ld does not. 67 */ 68 typedef struct { 69 Cache *cache; /* Pointer to cache entry for VERSYM */ 70 Versym *data; /* Pointer to versym array */ 71 int gnu; /* True if object uses GNU versioning rules */ 72 int max_verndx; /* largest versym index value */ 73 } VERSYM_STATE; 74 75 /* 76 * SYMTBL_STATE is used to maintain information about a single symbol 77 * table section, for use by the routines that display symbol information. 78 */ 79 typedef struct { 80 const char *file; /* Name of file */ 81 Ehdr *ehdr; /* ELF header for file */ 82 Cache *cache; /* Cache of all section headers */ 83 Word shnum; /* # of sections in cache */ 84 Cache *seccache; /* Cache of symbol table section hdr */ 85 Word secndx; /* Index of symbol table section hdr */ 86 const char *secname; /* Name of section */ 87 uint_t flags; /* Command line option flags */ 88 struct { /* Extended section index data */ 89 int checked; /* TRUE if already checked for shxndx */ 90 Word *data; /* NULL, or extended section index */ 91 /* used for symbol table entries */ 92 uint_t n; /* # items in shxndx.data */ 93 } shxndx; 94 VERSYM_STATE *versym; /* NULL, or associated VERSYM section */ 95 Sym *sym; /* Array of symbols */ 96 Word symn; /* # of symbols */ 97 } SYMTBL_STATE; 98 99 100 101 /* 102 * Focal point for verifying symbol names. 103 */ 104 static const char * 105 string(Cache *refsec, Word ndx, Cache *strsec, const char *file, Word name) 106 { 107 /* 108 * If an error in this routine is due to a property of the string 109 * section, as opposed to a bad offset into the section (a property of 110 * the referencing section), then we will detect the same error on 111 * every call involving those sections. We use these static variables 112 * to retain the information needed to only issue each such error once. 113 */ 114 static Cache *last_refsec; /* Last referencing section seen */ 115 static int strsec_err; /* True if error issued */ 116 117 const char *strs; 118 Word strn; 119 120 if (strsec->c_data == NULL) 121 return (NULL); 122 123 strs = (char *)strsec->c_data->d_buf; 124 strn = strsec->c_data->d_size; 125 126 /* 127 * We only print a diagnostic regarding a bad string table once per 128 * input section being processed. If the refsec has changed, reset 129 * our retained error state. 130 */ 131 if (last_refsec != refsec) { 132 last_refsec = refsec; 133 strsec_err = 0; 134 } 135 136 /* Verify that strsec really is a string table */ 137 if (strsec->c_shdr->sh_type != SHT_STRTAB) { 138 if (!strsec_err) { 139 (void) fprintf(stderr, MSG_INTL(MSG_ERR_NOTSTRTAB), 140 file, strsec->c_ndx, refsec->c_ndx); 141 strsec_err = 1; 142 } 143 return (MSG_INTL(MSG_STR_UNKNOWN)); 144 } 145 146 /* 147 * Is the string table offset within range of the available strings? 148 */ 149 if (name >= strn) { 150 /* 151 * Do we have a empty string table? 152 */ 153 if (strs == 0) { 154 if (!strsec_err) { 155 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 156 file, strsec->c_name); 157 strsec_err = 1; 158 } 159 } else { 160 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSTOFF), 161 file, refsec->c_name, EC_WORD(ndx), strsec->c_name, 162 EC_WORD(name), EC_WORD(strn - 1)); 163 } 164 165 /* 166 * Return the empty string so that the calling function can 167 * continue it's output diagnostics. 168 */ 169 return (MSG_INTL(MSG_STR_UNKNOWN)); 170 } 171 return (strs + name); 172 } 173 174 /* 175 * Relocations can reference section symbols and standard symbols. If the 176 * former, establish the section name. 177 */ 178 static const char * 179 relsymname(Cache *cache, Cache *csec, Cache *strsec, Word symndx, Word symnum, 180 Word relndx, Sym *syms, char *secstr, size_t secsz, const char *file, 181 uint_t flags) 182 { 183 Sym *sym; 184 185 if (symndx >= symnum) { 186 (void) fprintf(stderr, MSG_INTL(MSG_ERR_RELBADSYMNDX), 187 file, EC_WORD(symndx), EC_WORD(relndx)); 188 return (MSG_INTL(MSG_STR_UNKNOWN)); 189 } 190 191 sym = (Sym *)(syms + symndx); 192 193 /* 194 * If the symbol represents a section offset construct an appropriate 195 * string. 196 */ 197 if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) && (sym->st_name == 0)) { 198 if (flags & FLG_CTL_LONGNAME) 199 (void) snprintf(secstr, secsz, 200 MSG_INTL(MSG_STR_L_SECTION), 201 cache[sym->st_shndx].c_name); 202 else 203 (void) snprintf(secstr, secsz, 204 MSG_INTL(MSG_STR_SECTION), 205 cache[sym->st_shndx].c_name); 206 return ((const char *)secstr); 207 } 208 209 return (string(csec, symndx, strsec, file, sym->st_name)); 210 } 211 212 /* 213 * Focal point for establishing a string table section. Data such as the 214 * dynamic information simply points to a string table. Data such as 215 * relocations, reference a symbol table, which in turn is associated with a 216 * string table. 217 */ 218 static int 219 stringtbl(Cache *cache, int symtab, Word ndx, Word shnum, const char *file, 220 Word *symnum, Cache **symsec, Cache **strsec) 221 { 222 Shdr *shdr = cache[ndx].c_shdr; 223 224 if (symtab) { 225 /* 226 * Validate the symbol table section. 227 */ 228 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 229 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 230 file, cache[ndx].c_name, EC_WORD(shdr->sh_link)); 231 return (0); 232 } 233 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 234 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 235 file, cache[ndx].c_name); 236 return (0); 237 } 238 239 /* 240 * Obtain, and verify the symbol table data. 241 */ 242 if ((cache[ndx].c_data == NULL) || 243 (cache[ndx].c_data->d_buf == NULL)) { 244 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 245 file, cache[ndx].c_name); 246 return (0); 247 } 248 249 /* 250 * Establish the string table index. 251 */ 252 ndx = shdr->sh_link; 253 shdr = cache[ndx].c_shdr; 254 255 /* 256 * Return symbol table information. 257 */ 258 if (symnum) 259 *symnum = (shdr->sh_size / shdr->sh_entsize); 260 if (symsec) 261 *symsec = &cache[ndx]; 262 } 263 264 /* 265 * Validate the associated string table section. 266 */ 267 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 268 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 269 file, cache[ndx].c_name, EC_WORD(shdr->sh_link)); 270 return (0); 271 } 272 273 if (strsec) 274 *strsec = &cache[shdr->sh_link]; 275 276 return (1); 277 } 278 279 /* 280 * Lookup a symbol and set Sym accordingly. 281 */ 282 static int 283 symlookup(const char *name, Cache *cache, Word shnum, Sym **sym, 284 Cache *symtab, const char *file) 285 { 286 Shdr *shdr; 287 Word symn, cnt; 288 Sym *syms; 289 290 if (symtab == 0) 291 return (0); 292 293 shdr = symtab->c_shdr; 294 295 /* 296 * Determine the symbol data and number. 297 */ 298 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 299 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 300 file, symtab->c_name); 301 return (0); 302 } 303 if (symtab->c_data == NULL) 304 return (0); 305 306 /* LINTED */ 307 symn = (Word)(shdr->sh_size / shdr->sh_entsize); 308 syms = (Sym *)symtab->c_data->d_buf; 309 310 /* 311 * Get the associated string table section. 312 */ 313 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 314 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 315 file, symtab->c_name, EC_WORD(shdr->sh_link)); 316 return (0); 317 } 318 319 /* 320 * Loop through the symbol table to find a match. 321 */ 322 for (cnt = 0; cnt < symn; syms++, cnt++) { 323 const char *symname; 324 325 symname = string(symtab, cnt, &cache[shdr->sh_link], file, 326 syms->st_name); 327 328 if (symname && (strcmp(name, symname) == 0)) { 329 *sym = syms; 330 return (1); 331 } 332 } 333 return (0); 334 } 335 336 /* 337 * Print section headers. 338 */ 339 static void 340 sections(const char *file, Cache *cache, Word shnum, Ehdr *ehdr) 341 { 342 size_t seccnt; 343 344 for (seccnt = 1; seccnt < shnum; seccnt++) { 345 Cache *_cache = &cache[seccnt]; 346 Shdr *shdr = _cache->c_shdr; 347 const char *secname = _cache->c_name; 348 349 /* 350 * Although numerous section header entries can be zero, it's 351 * usually a sign of trouble if the type is zero. 352 */ 353 if (shdr->sh_type == 0) { 354 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE), 355 file, secname, EC_WORD(shdr->sh_type)); 356 } 357 358 if (!match(MATCH_F_ALL, secname, seccnt, shdr->sh_type)) 359 continue; 360 361 /* 362 * Identify any sections that are suspicious. A .got section 363 * shouldn't exist in a relocatable object. 364 */ 365 if (ehdr->e_type == ET_REL) { 366 if (strncmp(secname, MSG_ORIG(MSG_ELF_GOT), 367 MSG_ELF_GOT_SIZE) == 0) { 368 (void) fprintf(stderr, 369 MSG_INTL(MSG_GOT_UNEXPECTED), file, 370 secname); 371 } 372 } 373 374 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 375 dbg_print(0, MSG_INTL(MSG_ELF_SHDR), EC_WORD(seccnt), secname); 376 Elf_shdr(0, ehdr->e_machine, shdr); 377 } 378 } 379 380 /* 381 * A couple of instances of unwind data are printed as tables of 8 data items 382 * expressed as 0x?? integers. 383 */ 384 #define UNWINDTBLSZ 10 + (8 * 5) + 1 385 386 static void 387 unwindtbl(uint64_t *ndx, uint_t len, uchar_t *data, uint64_t doff, 388 const char *msg, const char *pre, size_t plen) 389 { 390 char buffer[UNWINDTBLSZ]; 391 uint_t boff = plen, cnt = 0; 392 393 dbg_print(0, msg); 394 (void) strncpy(buffer, pre, UNWINDTBLSZ); 395 396 while (*ndx < (len + 4)) { 397 if (cnt == 8) { 398 dbg_print(0, buffer); 399 boff = plen; 400 cnt = 0; 401 } 402 (void) snprintf(&buffer[boff], UNWINDTBLSZ - boff, 403 MSG_ORIG(MSG_UNW_TBLENTRY), data[doff + (*ndx)++]); 404 boff += 5; 405 cnt++; 406 } 407 if (cnt) 408 dbg_print(0, buffer); 409 } 410 411 /* 412 * Obtain a specified Phdr entry. 413 */ 414 static Phdr * 415 getphdr(Word phnum, Word type, const char *file, Elf *elf) 416 { 417 Word cnt; 418 Phdr *phdr; 419 420 if ((phdr = elf_getphdr(elf)) == NULL) { 421 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 422 return (0); 423 } 424 425 for (cnt = 0; cnt < phnum; phdr++, cnt++) { 426 if (phdr->p_type == type) 427 return (phdr); 428 } 429 return (0); 430 } 431 432 static void 433 unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *file, 434 Elf *elf) 435 { 436 Conv_dwarf_ehe_buf_t dwarf_ehe_buf; 437 Word cnt; 438 Phdr *uphdr = 0; 439 440 /* 441 * For the moment - UNWIND is only relevant for a AMD64 object. 442 */ 443 if (ehdr->e_machine != EM_AMD64) 444 return; 445 446 if (phnum) 447 uphdr = getphdr(phnum, PT_SUNW_UNWIND, file, elf); 448 449 for (cnt = 1; cnt < shnum; cnt++) { 450 Cache *_cache = &cache[cnt]; 451 Shdr *shdr = _cache->c_shdr; 452 uchar_t *data; 453 size_t datasize; 454 uint64_t off, ndx, frame_ptr, fde_cnt, tabndx; 455 uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc; 456 457 /* 458 * AMD64 - this is a strmcp() just to find the gcc produced 459 * sections. Soon gcc should be setting the section type - and 460 * we'll not need this strcmp(). 461 */ 462 if ((shdr->sh_type != SHT_AMD64_UNWIND) && 463 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM), 464 MSG_SCN_FRM_SIZE) != 0) && 465 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 466 MSG_SCN_FRMHDR_SIZE) != 0)) 467 continue; 468 469 if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type)) 470 continue; 471 472 if (_cache->c_data == NULL) 473 continue; 474 475 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 476 dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name); 477 478 data = (uchar_t *)(_cache->c_data->d_buf); 479 datasize = _cache->c_data->d_size; 480 off = 0; 481 482 /* 483 * Is this a .eh_frame_hdr 484 */ 485 if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) || 486 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 487 MSG_SCN_FRMHDR_SIZE) == 0)) { 488 dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR)); 489 ndx = 0; 490 491 vers = data[ndx++]; 492 frame_ptr_enc = data[ndx++]; 493 fde_cnt_enc = data[ndx++]; 494 table_enc = data[ndx++]; 495 496 dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers); 497 498 frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc, 499 ehdr->e_ident, shdr->sh_addr + ndx); 500 501 dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC), 502 conv_dwarf_ehe(frame_ptr_enc, &dwarf_ehe_buf), 503 EC_XWORD(frame_ptr)); 504 505 fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc, 506 ehdr->e_ident, shdr->sh_addr + ndx); 507 508 dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC), 509 conv_dwarf_ehe(fde_cnt_enc, &dwarf_ehe_buf), 510 EC_XWORD(fde_cnt)); 511 dbg_print(0, MSG_ORIG(MSG_UNW_TABENC), 512 conv_dwarf_ehe(table_enc, &dwarf_ehe_buf)); 513 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1)); 514 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2)); 515 516 for (tabndx = 0; tabndx < fde_cnt; tabndx++) { 517 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT), 518 EC_XWORD(dwarf_ehe_extract(data, &ndx, 519 table_enc, ehdr->e_ident, shdr->sh_addr)), 520 EC_XWORD(dwarf_ehe_extract(data, &ndx, 521 table_enc, ehdr->e_ident, shdr->sh_addr))); 522 } 523 continue; 524 } 525 526 /* 527 * Walk the Eh_frame's 528 */ 529 while (off < datasize) { 530 uint_t cieid, cielength, cieversion; 531 uint_t cieretaddr; 532 int cieRflag, cieLflag, ciePflag, cieZflag; 533 uint_t cieaugndx, length, id; 534 uint64_t ciecalign, ciedalign; 535 char *cieaugstr; 536 537 ndx = 0; 538 /* 539 * Extract length in lsb format. A zero length 540 * indicates that this CIE is a terminator and that 541 * processing for this unwind information should end. 542 * However, skip this entry and keep processing, just 543 * in case there is any other information remaining in 544 * this section. Note, ld(1) will terminate the 545 * processing of the .eh_frame contents for this file 546 * after a zero length CIE, thus any information that 547 * does follow is ignored by ld(1), and is therefore 548 * questionable. 549 */ 550 if ((length = LSB32EXTRACT(data + off + ndx)) == 0) { 551 dbg_print(0, MSG_ORIG(MSG_UNW_ZEROTERM)); 552 off += 4; 553 continue; 554 } 555 ndx += 4; 556 557 /* 558 * extract CIE id in lsb format 559 */ 560 id = LSB32EXTRACT(data + off + ndx); 561 ndx += 4; 562 563 /* 564 * A CIE record has a id of '0', otherwise this is a 565 * FDE entry and the 'id' is the CIE pointer. 566 */ 567 if (id == 0) { 568 uint64_t persVal; 569 570 cielength = length; 571 cieid = id; 572 cieLflag = ciePflag = cieRflag = cieZflag = 0; 573 574 dbg_print(0, MSG_ORIG(MSG_UNW_CIE), 575 EC_XWORD(shdr->sh_addr + off)); 576 dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH), 577 cielength, cieid); 578 579 cieversion = data[off + ndx]; 580 ndx += 1; 581 cieaugstr = (char *)(&data[off + ndx]); 582 ndx += strlen(cieaugstr) + 1; 583 584 dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS), 585 cieversion, cieaugstr); 586 587 ciecalign = uleb_extract(&data[off], &ndx); 588 ciedalign = sleb_extract(&data[off], &ndx); 589 cieretaddr = data[off + ndx]; 590 ndx += 1; 591 592 dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN), 593 EC_XWORD(ciecalign), EC_XWORD(ciedalign), 594 cieretaddr); 595 596 if (cieaugstr[0]) 597 dbg_print(0, 598 MSG_ORIG(MSG_UNW_CIEAXVAL)); 599 600 for (cieaugndx = 0; cieaugstr[cieaugndx]; 601 cieaugndx++) { 602 uint_t val; 603 604 switch (cieaugstr[cieaugndx]) { 605 case 'z': 606 val = uleb_extract(&data[off], 607 &ndx); 608 dbg_print(0, 609 MSG_ORIG(MSG_UNW_CIEAXSIZ), 610 val); 611 cieZflag = 1; 612 break; 613 case 'P': 614 ciePflag = data[off + ndx]; 615 ndx += 1; 616 617 persVal = dwarf_ehe_extract( 618 &data[off], &ndx, ciePflag, 619 ehdr->e_ident, 620 shdr->sh_addr + off + ndx); 621 dbg_print(0, 622 MSG_ORIG(MSG_UNW_CIEAXPERS), 623 ciePflag, 624 conv_dwarf_ehe(ciePflag, 625 &dwarf_ehe_buf), 626 EC_XWORD(persVal)); 627 break; 628 case 'R': 629 val = data[off + ndx]; 630 ndx += 1; 631 dbg_print(0, 632 MSG_ORIG(MSG_UNW_CIEAXCENC), 633 val, conv_dwarf_ehe(val, 634 &dwarf_ehe_buf)); 635 cieRflag = val; 636 break; 637 case 'L': 638 val = data[off + ndx]; 639 ndx += 1; 640 dbg_print(0, 641 MSG_ORIG(MSG_UNW_CIEAXLSDA), 642 val, conv_dwarf_ehe(val, 643 &dwarf_ehe_buf)); 644 cieLflag = val; 645 break; 646 default: 647 dbg_print(0, 648 MSG_ORIG(MSG_UNW_CIEAXUNEC), 649 cieaugstr[cieaugndx]); 650 break; 651 } 652 } 653 if ((cielength + 4) > ndx) 654 unwindtbl(&ndx, cielength, data, off, 655 MSG_ORIG(MSG_UNW_CIECFI), 656 MSG_ORIG(MSG_UNW_CIEPRE), 657 MSG_UNW_CIEPRE_SIZE); 658 off += cielength + 4; 659 660 } else { 661 uint_t fdelength = length; 662 int fdecieptr = id; 663 uint64_t fdeinitloc, fdeaddrrange; 664 665 dbg_print(0, MSG_ORIG(MSG_UNW_FDE), 666 EC_XWORD(shdr->sh_addr + off)); 667 dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH), 668 fdelength, fdecieptr); 669 670 fdeinitloc = dwarf_ehe_extract(&data[off], 671 &ndx, cieRflag, ehdr->e_ident, 672 shdr->sh_addr + off + ndx); 673 fdeaddrrange = dwarf_ehe_extract(&data[off], 674 &ndx, (cieRflag & ~DW_EH_PE_pcrel), 675 ehdr->e_ident, 676 shdr->sh_addr + off + ndx); 677 678 dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC), 679 EC_XWORD(fdeinitloc), 680 EC_XWORD(fdeaddrrange)); 681 682 if (cieaugstr[0]) 683 dbg_print(0, 684 MSG_ORIG(MSG_UNW_FDEAXVAL)); 685 if (cieZflag) { 686 uint64_t val; 687 val = uleb_extract(&data[off], &ndx); 688 dbg_print(0, 689 MSG_ORIG(MSG_UNW_FDEAXSIZE), 690 EC_XWORD(val)); 691 if (val & cieLflag) { 692 fdeinitloc = dwarf_ehe_extract( 693 &data[off], &ndx, cieLflag, 694 ehdr->e_ident, 695 shdr->sh_addr + off + ndx); 696 dbg_print(0, 697 MSG_ORIG(MSG_UNW_FDEAXLSDA), 698 EC_XWORD(val)); 699 } 700 } 701 if ((fdelength + 4) > ndx) 702 unwindtbl(&ndx, fdelength, data, off, 703 MSG_ORIG(MSG_UNW_FDECFI), 704 MSG_ORIG(MSG_UNW_FDEPRE), 705 MSG_UNW_FDEPRE_SIZE); 706 off += fdelength + 4; 707 } 708 } 709 } 710 } 711 712 /* 713 * Print the hardware/software capabilities. For executables and shared objects 714 * this should be accompanied with a program header. 715 */ 716 static void 717 cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, 718 Elf *elf) 719 { 720 Word cnt; 721 Shdr *cshdr = 0; 722 Cache *ccache; 723 Off cphdr_off = 0; 724 Xword cphdr_sz; 725 726 /* 727 * Determine if a hardware/software capabilities header exists. 728 */ 729 if (phnum) { 730 Phdr *phdr; 731 732 if ((phdr = elf_getphdr(elf)) == NULL) { 733 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 734 return; 735 } 736 737 for (cnt = 0; cnt < phnum; phdr++, cnt++) { 738 if (phdr->p_type == PT_SUNWCAP) { 739 cphdr_off = phdr->p_offset; 740 cphdr_sz = phdr->p_filesz; 741 break; 742 } 743 } 744 } 745 746 /* 747 * Determine if a hardware/software capabilities section exists. 748 */ 749 for (cnt = 1; cnt < shnum; cnt++) { 750 Cache *_cache = &cache[cnt]; 751 Shdr *shdr = _cache->c_shdr; 752 753 if (shdr->sh_type != SHT_SUNW_cap) 754 continue; 755 756 if (cphdr_off && ((cphdr_off < shdr->sh_offset) || 757 (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size))) 758 continue; 759 760 if (_cache->c_data == NULL) 761 continue; 762 763 ccache = _cache; 764 cshdr = shdr; 765 break; 766 } 767 768 if ((cshdr == 0) && (cphdr_off == 0)) 769 return; 770 771 /* 772 * Print the hardware/software capabilities section. 773 */ 774 if (cshdr) { 775 Word ndx, capn; 776 Cap *cap = (Cap *)ccache->c_data->d_buf; 777 778 if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) { 779 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 780 file, ccache->c_name); 781 return; 782 } 783 784 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 785 dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name); 786 787 Elf_cap_title(0); 788 789 capn = (Word)(cshdr->sh_size / cshdr->sh_entsize); 790 791 for (ndx = 0; ndx < capn; cap++, ndx++) { 792 if (cap->c_tag != CA_SUNW_NULL) 793 Elf_cap_entry(0, cap, ndx, ehdr->e_machine); 794 } 795 } else 796 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file); 797 798 /* 799 * If this object is an executable or shared object, then the 800 * hardware/software capabilities section should have an accompanying 801 * program header. 802 */ 803 if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) { 804 if (cphdr_off == 0) 805 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2), 806 file, ccache->c_name); 807 else if ((cphdr_off != cshdr->sh_offset) || 808 (cphdr_sz != cshdr->sh_size)) 809 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3), 810 file, ccache->c_name); 811 } 812 } 813 814 /* 815 * Print the interpretor. 816 */ 817 static void 818 interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf) 819 { 820 Word cnt; 821 Shdr *ishdr = 0; 822 Cache *icache; 823 Off iphdr_off = 0; 824 Xword iphdr_fsz; 825 826 /* 827 * Determine if an interp header exists. 828 */ 829 if (phnum) { 830 Phdr *phdr; 831 832 if ((phdr = getphdr(phnum, PT_INTERP, file, elf)) != 0) { 833 iphdr_off = phdr->p_offset; 834 iphdr_fsz = phdr->p_filesz; 835 } 836 } 837 838 if (iphdr_off == 0) 839 return; 840 841 /* 842 * Determine if an interp section exists. 843 */ 844 for (cnt = 1; cnt < shnum; cnt++) { 845 Cache *_cache = &cache[cnt]; 846 Shdr *shdr = _cache->c_shdr; 847 848 /* 849 * Scan sections to find a section which contains the PT_INTERP 850 * string. The target section can't be in a NOBITS section. 851 */ 852 if ((shdr->sh_type == SHT_NOBITS) || 853 (iphdr_off < shdr->sh_offset) || 854 (iphdr_off + iphdr_fsz) > (shdr->sh_offset + shdr->sh_size)) 855 continue; 856 857 icache = _cache; 858 ishdr = shdr; 859 break; 860 } 861 862 /* 863 * Print the interpreter string based on the offset defined in the 864 * program header, as this is the offset used by the kernel. 865 */ 866 if (ishdr && icache->c_data) { 867 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 868 dbg_print(0, MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name); 869 dbg_print(0, MSG_ORIG(MSG_FMT_INDENT), 870 (char *)icache->c_data->d_buf + 871 (iphdr_off - ishdr->sh_offset)); 872 } else 873 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file); 874 875 /* 876 * If there are any inconsistences between the program header and 877 * section information, flag them. 878 */ 879 if (ishdr && ((iphdr_off != ishdr->sh_offset) || 880 (iphdr_fsz != ishdr->sh_size))) { 881 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file, 882 icache->c_name); 883 } 884 } 885 886 /* 887 * Print the syminfo section. 888 */ 889 static void 890 syminfo(Cache *cache, Word shnum, const char *file) 891 { 892 Shdr *infoshdr; 893 Syminfo *info; 894 Sym *syms; 895 Dyn *dyns; 896 Word infonum, cnt, ndx, symnum; 897 Cache *infocache = 0, *symsec, *strsec; 898 899 for (cnt = 1; cnt < shnum; cnt++) { 900 if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) { 901 infocache = &cache[cnt]; 902 break; 903 } 904 } 905 if (infocache == 0) 906 return; 907 908 infoshdr = infocache->c_shdr; 909 if ((infoshdr->sh_entsize == 0) || (infoshdr->sh_size == 0)) { 910 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 911 file, infocache->c_name); 912 return; 913 } 914 if (infocache->c_data == NULL) 915 return; 916 917 infonum = (Word)(infoshdr->sh_size / infoshdr->sh_entsize); 918 info = (Syminfo *)infocache->c_data->d_buf; 919 920 /* 921 * Get the data buffer of the associated dynamic section. 922 */ 923 if ((infoshdr->sh_info == 0) || (infoshdr->sh_info >= shnum)) { 924 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 925 file, infocache->c_name, EC_WORD(infoshdr->sh_info)); 926 return; 927 } 928 if (cache[infoshdr->sh_info].c_data == NULL) 929 return; 930 931 dyns = cache[infoshdr->sh_info].c_data->d_buf; 932 if (dyns == 0) { 933 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 934 file, cache[infoshdr->sh_info].c_name); 935 return; 936 } 937 938 /* 939 * Get the data buffer for the associated symbol table and string table. 940 */ 941 if (stringtbl(cache, 1, cnt, shnum, file, 942 &symnum, &symsec, &strsec) == 0) 943 return; 944 945 syms = symsec->c_data->d_buf; 946 947 /* 948 * Loop through the syminfo entries. 949 */ 950 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 951 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMINFO), infocache->c_name); 952 Elf_syminfo_title(0); 953 954 for (ndx = 1, info++; ndx < infonum; ndx++, info++) { 955 Sym *sym; 956 const char *needed = 0, *name; 957 958 if ((info->si_flags == 0) && (info->si_boundto == 0)) 959 continue; 960 961 sym = &syms[ndx]; 962 name = string(infocache, ndx, strsec, file, sym->st_name); 963 964 if (info->si_boundto < SYMINFO_BT_LOWRESERVE) { 965 Dyn *dyn = &dyns[info->si_boundto]; 966 967 needed = string(infocache, info->si_boundto, 968 strsec, file, dyn->d_un.d_val); 969 } 970 Elf_syminfo_entry(0, ndx, info, name, needed); 971 } 972 } 973 974 /* 975 * Print version definition section entries. 976 */ 977 static void 978 version_def(Verdef *vdf, Word vdf_num, Cache *vcache, Cache *scache, 979 const char *file) 980 { 981 Word cnt; 982 char index[MAXNDXSIZE]; 983 984 Elf_ver_def_title(0); 985 986 for (cnt = 1; cnt <= vdf_num; cnt++, 987 vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) { 988 const char *name, *dep; 989 Half vcnt = vdf->vd_cnt - 1; 990 Half ndx = vdf->vd_ndx; 991 Verdaux *vdap = (Verdaux *)((uintptr_t)vdf + vdf->vd_aux); 992 993 /* 994 * Obtain the name and first dependency (if any). 995 */ 996 name = string(vcache, cnt, scache, file, vdap->vda_name); 997 vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 998 if (vcnt) 999 dep = string(vcache, cnt, scache, file, vdap->vda_name); 1000 else 1001 dep = MSG_ORIG(MSG_STR_EMPTY); 1002 1003 (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX), 1004 EC_XWORD(ndx)); 1005 Elf_ver_line_1(0, index, name, dep, 1006 conv_ver_flags(vdf->vd_flags)); 1007 1008 /* 1009 * Print any additional dependencies. 1010 */ 1011 if (vcnt) { 1012 vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 1013 for (vcnt--; vcnt; vcnt--, 1014 vdap = (Verdaux *)((uintptr_t)vdap + 1015 vdap->vda_next)) { 1016 dep = string(vcache, cnt, scache, file, 1017 vdap->vda_name); 1018 Elf_ver_line_2(0, MSG_ORIG(MSG_STR_EMPTY), dep); 1019 } 1020 } 1021 } 1022 } 1023 1024 /* 1025 * Print version needed section entries. 1026 * 1027 * entry: 1028 * vnd - Address of verneed data 1029 * vnd_num - # of Verneed entries 1030 * vcache - Cache of verneed section being processed 1031 * scache - Cache of associated string table section 1032 * file - Name of object being processed. 1033 * versym - Information about versym section 1034 * 1035 * exit: 1036 * The versions have been printed. If GNU style versioning 1037 * is in effect, versym->max_verndx has been updated to 1038 * contain the largest version index seen. 1039 */ 1040 static void 1041 version_need(Verneed *vnd, Word vnd_num, Cache *vcache, Cache *scache, 1042 const char *file, VERSYM_STATE *versym) 1043 { 1044 Word cnt; 1045 char index[MAXNDXSIZE]; 1046 const char *index_str; 1047 1048 Elf_ver_need_title(0, versym->gnu); 1049 1050 /* 1051 * The versym section in an object that follows Solaris versioning 1052 * rules contains indexes into the verdef section. Symbols defined 1053 * in other objects (UNDEF) are given a version of 0, indicating that 1054 * they are not defined by this file, and the Verneed entries do not 1055 * have associated version indexes. For these reasons, we do not 1056 * display a version index for Solaris Verneed sections. 1057 * 1058 * The GNU versioning rules are different: Symbols defined in other 1059 * objects receive a version index in the range above those defined 1060 * by the Verdef section, and the vna_other field of the Vernaux 1061 * structs inside the Verneed section contain the version index for 1062 * that item. We therefore display the index when showing the 1063 * contents of a GNU Verneed section. You should not expect these 1064 * indexes to appear in sorted order --- it seems that the GNU ld 1065 * assigns the versions as symbols are encountered during linking, 1066 * and then the results are assembled into the Verneed section 1067 * afterwards. 1068 */ 1069 if (versym->gnu) { 1070 index_str = index; 1071 } else { 1072 /* For Solaris versioning, display a NULL string */ 1073 index_str = MSG_ORIG(MSG_STR_EMPTY); 1074 } 1075 1076 for (cnt = 1; cnt <= vnd_num; cnt++, 1077 vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 1078 const char *name, *dep; 1079 Half vcnt = vnd->vn_cnt; 1080 Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + vnd->vn_aux); 1081 1082 /* 1083 * Obtain the name of the needed file and the version name 1084 * within it that we're dependent on. Note that the count 1085 * should be at least one, otherwise this is a pretty bogus 1086 * entry. 1087 */ 1088 name = string(vcache, cnt, scache, file, vnd->vn_file); 1089 if (vcnt) 1090 dep = string(vcache, cnt, scache, file, vnap->vna_name); 1091 else 1092 dep = MSG_INTL(MSG_STR_NULL); 1093 1094 if (versym->gnu) { 1095 /* Format the version index value */ 1096 (void) snprintf(index, MAXNDXSIZE, 1097 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(vnap->vna_other)); 1098 if (vnap->vna_other > versym->max_verndx) 1099 versym->max_verndx = vnap->vna_other; 1100 } 1101 Elf_ver_line_1(0, index_str, name, dep, 1102 conv_ver_flags(vnap->vna_flags)); 1103 1104 /* 1105 * Print any additional version dependencies. 1106 */ 1107 if (vcnt) { 1108 vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next); 1109 for (vcnt--; vcnt; vcnt--, 1110 vnap = (Vernaux *)((uintptr_t)vnap + 1111 vnap->vna_next)) { 1112 dep = string(vcache, cnt, scache, file, 1113 vnap->vna_name); 1114 if (versym->gnu) { 1115 /* Format the next index value */ 1116 (void) snprintf(index, MAXNDXSIZE, 1117 MSG_ORIG(MSG_FMT_INDEX), 1118 EC_XWORD(vnap->vna_other)); 1119 Elf_ver_line_1(0, index_str, 1120 MSG_ORIG(MSG_STR_EMPTY), dep, 1121 conv_ver_flags(vnap->vna_flags)); 1122 if (vnap->vna_other > 1123 versym->max_verndx) 1124 versym->max_verndx = 1125 vnap->vna_other; 1126 } else { 1127 Elf_ver_line_3(0, 1128 MSG_ORIG(MSG_STR_EMPTY), dep, 1129 conv_ver_flags(vnap->vna_flags)); 1130 } 1131 } 1132 } 1133 } 1134 } 1135 1136 /* 1137 * Compute the max_verndx value for a GNU style object with 1138 * a Verneed section. This is only needed if version_need() is not 1139 * called. 1140 * 1141 * entry: 1142 * vnd - Address of verneed data 1143 * vnd_num - # of Verneed entries 1144 * versym - Information about versym section 1145 * 1146 * exit: 1147 * versym->max_verndx has been updated to contain the largest 1148 * version index seen. 1149 */ 1150 static void 1151 update_gnu_max_verndx(Verneed *vnd, Word vnd_num, VERSYM_STATE *versym) 1152 { 1153 Word cnt; 1154 1155 for (cnt = 1; cnt <= vnd_num; cnt++, 1156 vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 1157 Half vcnt = vnd->vn_cnt; 1158 Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + vnd->vn_aux); 1159 1160 if (vnap->vna_other > versym->max_verndx) 1161 versym->max_verndx = vnap->vna_other; 1162 1163 /* 1164 * Check any additional version dependencies. 1165 */ 1166 if (vcnt) { 1167 vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next); 1168 for (vcnt--; vcnt; vcnt--, 1169 vnap = (Vernaux *)((uintptr_t)vnap + 1170 vnap->vna_next)) { 1171 if (vnap->vna_other > versym->max_verndx) 1172 versym->max_verndx = vnap->vna_other; 1173 } 1174 } 1175 } 1176 } 1177 1178 /* 1179 * Display version section information if the flags require it. 1180 * Return version information needed by other output. 1181 * 1182 * entry: 1183 * cache - Cache of all section headers 1184 * shnum - # of sections in cache 1185 * file - Name of file 1186 * flags - Command line option flags 1187 * versym - VERSYM_STATE block to be filled in. 1188 */ 1189 static void 1190 versions(Cache *cache, Word shnum, const char *file, uint_t flags, 1191 VERSYM_STATE *versym) 1192 { 1193 GElf_Word cnt; 1194 Cache *verdef_cache = NULL, *verneed_cache = NULL; 1195 1196 1197 /* Gather information about the version sections */ 1198 bzero(versym, sizeof (*versym)); 1199 versym->max_verndx = 1; 1200 for (cnt = 1; cnt < shnum; cnt++) { 1201 Cache *_cache = &cache[cnt]; 1202 Shdr *shdr = _cache->c_shdr; 1203 Dyn *dyn; 1204 ulong_t numdyn; 1205 1206 switch (shdr->sh_type) { 1207 case SHT_DYNAMIC: 1208 /* 1209 * The GNU ld puts a DT_VERSYM entry in the dynamic 1210 * section so that the runtime linker can use it to 1211 * implement their versioning rules. They allow multiple 1212 * incompatible functions with the same name to exist 1213 * in different versions. The Solaris ld does not 1214 * support this mechanism, and as such, does not 1215 * produce DT_VERSYM. We use this fact to determine 1216 * which ld produced this object, and how to interpret 1217 * the version values. 1218 */ 1219 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0) || 1220 (_cache->c_data == NULL)) 1221 continue; 1222 numdyn = shdr->sh_size / shdr->sh_entsize; 1223 dyn = (Dyn *)_cache->c_data->d_buf; 1224 for (; numdyn-- > 0; dyn++) 1225 if (dyn->d_tag == DT_VERSYM) { 1226 versym->gnu = 1; 1227 break; 1228 } 1229 break; 1230 1231 case SHT_SUNW_versym: 1232 /* Record data address for later symbol processing */ 1233 if (_cache->c_data != NULL) { 1234 versym->cache = _cache; 1235 versym->data = _cache->c_data->d_buf; 1236 continue; 1237 } 1238 break; 1239 1240 case SHT_SUNW_verdef: 1241 case SHT_SUNW_verneed: 1242 /* 1243 * Ensure the data is non-NULL and the number 1244 * of items is non-zero. Otherwise, we don't 1245 * understand the section, and will not use it. 1246 */ 1247 if ((_cache->c_data == NULL) || 1248 (_cache->c_data->d_buf == NULL)) { 1249 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1250 file, _cache->c_name); 1251 continue; 1252 } 1253 if (shdr->sh_info == 0) { 1254 (void) fprintf(stderr, 1255 MSG_INTL(MSG_ERR_BADSHINFO), 1256 file, _cache->c_name, 1257 EC_WORD(shdr->sh_info)); 1258 continue; 1259 } 1260 1261 /* Make sure the string table index is in range */ 1262 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1263 (void) fprintf(stderr, 1264 MSG_INTL(MSG_ERR_BADSHLINK), file, 1265 _cache->c_name, EC_WORD(shdr->sh_link)); 1266 continue; 1267 } 1268 1269 /* 1270 * The section is usable. Save the cache entry. 1271 */ 1272 if (shdr->sh_type == SHT_SUNW_verdef) { 1273 verdef_cache = _cache; 1274 /* 1275 * Under Solaris rules, if there is a verdef 1276 * section, the max versym index is number 1277 * of version definitions it supplies. 1278 */ 1279 versym->max_verndx = shdr->sh_info; 1280 } else { 1281 verneed_cache = _cache; 1282 } 1283 break; 1284 } 1285 } 1286 1287 if ((flags & FLG_SHOW_VERSIONS) == 0) { 1288 /* 1289 * If GNU versioning applies to this object, and there 1290 * is a Verneed section, then examine it to determine 1291 * the maximum Versym version index for this file. 1292 */ 1293 if ((versym->gnu) && (verneed_cache != NULL)) 1294 update_gnu_max_verndx( 1295 (Verneed *)verneed_cache->c_data->d_buf, 1296 verneed_cache->c_shdr->sh_info, versym); 1297 return; 1298 } 1299 1300 /* 1301 * Now that all the information is available, display the 1302 * Verdef and Verneed section contents. 1303 */ 1304 if (verdef_cache != NULL) { 1305 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1306 dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERDEF), 1307 verdef_cache->c_name); 1308 version_def((Verdef *)verdef_cache->c_data->d_buf, 1309 verdef_cache->c_shdr->sh_info, verdef_cache, 1310 &cache[verdef_cache->c_shdr->sh_link], file); 1311 } 1312 if (verneed_cache != NULL) { 1313 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1314 dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERNEED), 1315 verneed_cache->c_name); 1316 /* 1317 * If GNU versioning applies to this object, version_need() 1318 * will update versym->max_verndx, and it is not 1319 * necessary to call update_gnu_max_verndx(). 1320 */ 1321 version_need((Verneed *)verneed_cache->c_data->d_buf, 1322 verneed_cache->c_shdr->sh_info, verneed_cache, 1323 &cache[verneed_cache->c_shdr->sh_link], file, versym); 1324 } 1325 } 1326 1327 /* 1328 * Initialize a symbol table state structure 1329 * 1330 * entry: 1331 * state - State structure to be initialized 1332 * cache - Cache of all section headers 1333 * shnum - # of sections in cache 1334 * secndx - Index of symbol table section 1335 * ehdr - ELF header for file 1336 * versym - Information about versym section 1337 * file - Name of file 1338 * flags - Command line option flags 1339 */ 1340 static int 1341 init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx, 1342 Ehdr *ehdr, VERSYM_STATE *versym, const char *file, uint_t flags) 1343 { 1344 Shdr *shdr; 1345 1346 state->file = file; 1347 state->ehdr = ehdr; 1348 state->cache = cache; 1349 state->shnum = shnum; 1350 state->seccache = &cache[secndx]; 1351 state->secndx = secndx; 1352 state->secname = state->seccache->c_name; 1353 state->flags = flags; 1354 state->shxndx.checked = 0; 1355 state->shxndx.data = NULL; 1356 state->shxndx.n = 0; 1357 1358 shdr = state->seccache->c_shdr; 1359 1360 /* 1361 * Check the symbol data and per-item size. 1362 */ 1363 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1364 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1365 file, state->secname); 1366 return (0); 1367 } 1368 if (state->seccache->c_data == NULL) 1369 return (0); 1370 1371 /* LINTED */ 1372 state->symn = (Word)(shdr->sh_size / shdr->sh_entsize); 1373 state->sym = (Sym *)state->seccache->c_data->d_buf; 1374 1375 /* 1376 * Check associated string table section. 1377 */ 1378 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1379 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1380 file, state->secname, EC_WORD(shdr->sh_link)); 1381 return (0); 1382 } 1383 1384 /* 1385 * Determine if there is a associated Versym section 1386 * with this Symbol Table. 1387 */ 1388 if (versym->cache && 1389 (versym->cache->c_shdr->sh_link == state->secndx)) 1390 state->versym = versym; 1391 else 1392 state->versym = NULL; 1393 1394 1395 return (1); 1396 } 1397 1398 /* 1399 * Determine the extended section index used for symbol tables entries. 1400 */ 1401 static void 1402 symbols_getxindex(SYMTBL_STATE * state) 1403 { 1404 uint_t symn; 1405 Word symcnt; 1406 1407 state->shxndx.checked = 1; /* Note that we've been called */ 1408 for (symcnt = 1; symcnt < state->shnum; symcnt++) { 1409 Cache *_cache = &state->cache[symcnt]; 1410 Shdr *shdr = _cache->c_shdr; 1411 1412 if ((shdr->sh_type != SHT_SYMTAB_SHNDX) || 1413 (shdr->sh_link != state->secndx)) 1414 continue; 1415 1416 if ((shdr->sh_entsize) && 1417 /* LINTED */ 1418 ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0)) 1419 continue; 1420 1421 if (_cache->c_data == NULL) 1422 continue; 1423 1424 state->shxndx.data = _cache->c_data->d_buf; 1425 state->shxndx.n = symn; 1426 return; 1427 } 1428 } 1429 1430 /* 1431 * Produce a line of output for the given symbol 1432 * 1433 * entry: 1434 * state - Symbol table state 1435 * symndx - Index of symbol within the table 1436 * info - Value of st_info (indicates local/global range) 1437 * symndx_disp - Index to display. This may not be the same 1438 * as symndx if the display is relative to the logical 1439 * combination of the SUNW_ldynsym/dynsym tables. 1440 * sym - Symbol to display 1441 */ 1442 static void 1443 output_symbol(SYMTBL_STATE *state, Word symndx, Word info, Word disp_symndx, 1444 Sym *sym) 1445 { 1446 /* 1447 * Symbol types for which we check that the specified 1448 * address/size land inside the target section. 1449 */ 1450 static const int addr_symtype[STT_NUM] = { 1451 0, /* STT_NOTYPE */ 1452 1, /* STT_OBJECT */ 1453 1, /* STT_FUNC */ 1454 0, /* STT_SECTION */ 1455 0, /* STT_FILE */ 1456 1, /* STT_COMMON */ 1457 0, /* STT_TLS */ 1458 }; 1459 #if STT_NUM != (STT_TLS + 1) 1460 #error "STT_NUM has grown. Update addr_symtype[]" 1461 #endif 1462 1463 char index[MAXNDXSIZE]; 1464 const char *symname, *sec; 1465 Versym verndx; 1466 int gnuver; 1467 uchar_t type; 1468 Shdr *tshdr; 1469 Word shndx; 1470 Conv_inv_buf_t inv_buf; 1471 1472 /* Ensure symbol index is in range */ 1473 if (symndx >= state->symn) { 1474 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORTNDX), 1475 state->file, state->secname, EC_WORD(symndx)); 1476 return; 1477 } 1478 1479 /* 1480 * If we are using extended symbol indexes, find the 1481 * corresponding SHN_SYMTAB_SHNDX table. 1482 */ 1483 if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0)) 1484 symbols_getxindex(state); 1485 1486 /* LINTED */ 1487 symname = string(state->seccache, symndx, 1488 &state->cache[state->seccache->c_shdr->sh_link], state->file, 1489 sym->st_name); 1490 1491 tshdr = 0; 1492 sec = NULL; 1493 1494 if (state->ehdr->e_type == ET_CORE) { 1495 sec = (char *)MSG_INTL(MSG_STR_UNKNOWN); 1496 } else if (state->flags & FLG_CTL_FAKESHDR) { 1497 /* 1498 * If we are using fake section headers derived from 1499 * the program headers, then the section indexes 1500 * in the symbols do not correspond to these headers. 1501 * The section names are not available, so all we can 1502 * do is to display them in numeric form. 1503 */ 1504 sec = conv_sym_shndx(sym->st_shndx, &inv_buf); 1505 } else if ((sym->st_shndx < SHN_LORESERVE) && 1506 (sym->st_shndx < state->shnum)) { 1507 shndx = sym->st_shndx; 1508 tshdr = state->cache[shndx].c_shdr; 1509 sec = state->cache[shndx].c_name; 1510 } else if (sym->st_shndx == SHN_XINDEX) { 1511 if (state->shxndx.data) { 1512 Word _shxndx; 1513 1514 if (symndx > state->shxndx.n) { 1515 (void) fprintf(stderr, 1516 MSG_INTL(MSG_ERR_BADSYMXINDEX1), 1517 state->file, state->secname, 1518 EC_WORD(symndx)); 1519 } else if ((_shxndx = 1520 state->shxndx.data[symndx]) > state->shnum) { 1521 (void) fprintf(stderr, 1522 MSG_INTL(MSG_ERR_BADSYMXINDEX2), 1523 state->file, state->secname, 1524 EC_WORD(symndx), EC_WORD(_shxndx)); 1525 } else { 1526 shndx = _shxndx; 1527 tshdr = state->cache[shndx].c_shdr; 1528 sec = state->cache[shndx].c_name; 1529 } 1530 } else { 1531 (void) fprintf(stderr, 1532 MSG_INTL(MSG_ERR_BADSYMXINDEX3), 1533 state->file, state->secname, EC_WORD(symndx)); 1534 } 1535 } else if ((sym->st_shndx < SHN_LORESERVE) && 1536 (sym->st_shndx >= state->shnum)) { 1537 (void) fprintf(stderr, 1538 MSG_INTL(MSG_ERR_BADSYM5), state->file, 1539 state->secname, EC_WORD(symndx), 1540 demangle(symname, state->flags), sym->st_shndx); 1541 } 1542 1543 /* 1544 * If versioning is available display the 1545 * version index. If not, then use 0. 1546 */ 1547 if (state->versym) { 1548 Versym test_verndx; 1549 1550 verndx = test_verndx = state->versym->data[symndx]; 1551 gnuver = state->versym->gnu; 1552 1553 /* 1554 * Check to see if this is a defined symbol with a 1555 * version index that is outside the valid range for 1556 * the file. The interpretation of this depends on 1557 * the style of versioning used by the object. 1558 * 1559 * Versions >= VER_NDX_LORESERVE have special meanings, 1560 * and are exempt from this checking. 1561 * 1562 * GNU style version indexes use the top bit of the 1563 * 16-bit index value (0x8000) as the "hidden bit". 1564 * We must mask off this bit in order to compare 1565 * the version against the maximum value. 1566 */ 1567 if (gnuver) 1568 test_verndx &= ~0x8000; 1569 1570 if ((test_verndx > state->versym->max_verndx) && 1571 (verndx < VER_NDX_LORESERVE)) 1572 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADVER), 1573 state->file, state->secname, EC_WORD(symndx), 1574 EC_HALF(test_verndx), state->versym->max_verndx); 1575 } else { 1576 verndx = 0; 1577 gnuver = 0; 1578 } 1579 1580 /* 1581 * Error checking for TLS. 1582 */ 1583 type = ELF_ST_TYPE(sym->st_info); 1584 if (type == STT_TLS) { 1585 if (tshdr && 1586 (sym->st_shndx != SHN_UNDEF) && 1587 ((tshdr->sh_flags & SHF_TLS) == 0)) { 1588 (void) fprintf(stderr, 1589 MSG_INTL(MSG_ERR_BADSYM3), state->file, 1590 state->secname, EC_WORD(symndx), 1591 demangle(symname, state->flags)); 1592 } 1593 } else if ((type != STT_SECTION) && sym->st_size && 1594 tshdr && (tshdr->sh_flags & SHF_TLS)) { 1595 (void) fprintf(stderr, 1596 MSG_INTL(MSG_ERR_BADSYM4), state->file, 1597 state->secname, EC_WORD(symndx), 1598 demangle(symname, state->flags)); 1599 } 1600 1601 /* 1602 * If a symbol with non-zero size has a type that 1603 * specifies an address, then make sure the location 1604 * it references is actually contained within the 1605 * section. UNDEF symbols don't count in this case, 1606 * so we ignore them. 1607 * 1608 * The meaning of the st_value field in a symbol 1609 * depends on the type of object. For a relocatable 1610 * object, it is the offset within the section. 1611 * For sharable objects, it is the offset relative to 1612 * the base of the object, and for other types, it is 1613 * the virtual address. To get an offset within the 1614 * section for non-ET_REL files, we subtract the 1615 * base address of the section. 1616 */ 1617 if (addr_symtype[type] && (sym->st_size > 0) && 1618 (sym->st_shndx != SHN_UNDEF) && ((sym->st_shndx < SHN_LORESERVE) || 1619 (sym->st_shndx == SHN_XINDEX)) && (tshdr != NULL)) { 1620 Word v = sym->st_value; 1621 if (state->ehdr->e_type != ET_REL) 1622 v -= tshdr->sh_addr; 1623 if (((v + sym->st_size) > tshdr->sh_size)) { 1624 (void) fprintf(stderr, 1625 MSG_INTL(MSG_ERR_BADSYM6), state->file, 1626 state->secname, EC_WORD(symndx), 1627 demangle(symname, state->flags), 1628 EC_WORD(shndx), EC_XWORD(tshdr->sh_size), 1629 EC_XWORD(sym->st_value), EC_XWORD(sym->st_size)); 1630 } 1631 } 1632 1633 /* 1634 * A typical symbol table uses the sh_info field to indicate one greater 1635 * than the symbol table index of the last local symbol, STB_LOCAL. 1636 * Therefore, symbol indexes less than sh_info should have local 1637 * binding. Symbol indexes greater than, or equal to sh_info, should 1638 * have global binding. Note, we exclude UNDEF/NOTY symbols with zero 1639 * value and size, as these symbols may be the result of an mcs(1) 1640 * section deletion. 1641 */ 1642 if (info) { 1643 uchar_t bind = ELF_ST_BIND(sym->st_info); 1644 1645 if ((symndx < info) && (bind != STB_LOCAL)) { 1646 (void) fprintf(stderr, 1647 MSG_INTL(MSG_ERR_BADSYM7), state->file, 1648 state->secname, EC_WORD(symndx), 1649 demangle(symname, state->flags), EC_XWORD(info)); 1650 1651 } else if ((symndx >= info) && (bind == STB_LOCAL) && 1652 ((sym->st_shndx != SHN_UNDEF) || 1653 (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) || 1654 (sym->st_size != 0) || (sym->st_value != 0))) { 1655 (void) fprintf(stderr, 1656 MSG_INTL(MSG_ERR_BADSYM8), state->file, 1657 state->secname, EC_WORD(symndx), 1658 demangle(symname, state->flags), EC_XWORD(info)); 1659 } 1660 } 1661 1662 (void) snprintf(index, MAXNDXSIZE, 1663 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(disp_symndx)); 1664 Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index, 1665 state->ehdr->e_machine, sym, verndx, gnuver, sec, symname); 1666 } 1667 1668 /* 1669 * Search for and process any symbol tables. 1670 */ 1671 void 1672 symbols(Cache *cache, Word shnum, Ehdr *ehdr, VERSYM_STATE *versym, 1673 const char *file, uint_t flags) 1674 { 1675 SYMTBL_STATE state; 1676 Cache *_cache; 1677 Word secndx; 1678 1679 for (secndx = 1; secndx < shnum; secndx++) { 1680 Word symcnt; 1681 Shdr *shdr; 1682 1683 _cache = &cache[secndx]; 1684 shdr = _cache->c_shdr; 1685 1686 if ((shdr->sh_type != SHT_SYMTAB) && 1687 (shdr->sh_type != SHT_DYNSYM) && 1688 (shdr->sh_type != SHT_SUNW_LDYNSYM)) 1689 continue; 1690 if (!match(MATCH_F_ALL, _cache->c_name, secndx, shdr->sh_type)) 1691 continue; 1692 1693 if (!init_symtbl_state(&state, cache, shnum, secndx, ehdr, 1694 versym, file, flags)) 1695 continue; 1696 /* 1697 * Loop through the symbol tables entries. 1698 */ 1699 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1700 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), state.secname); 1701 Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 1702 1703 for (symcnt = 0; symcnt < state.symn; symcnt++) 1704 output_symbol(&state, symcnt, shdr->sh_info, symcnt, 1705 state.sym + symcnt); 1706 } 1707 } 1708 1709 /* 1710 * Search for and process any SHT_SUNW_symsort or SHT_SUNW_tlssort sections. 1711 * These sections are always associated with the .SUNW_ldynsym./.dynsym pair. 1712 */ 1713 static void 1714 sunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, VERSYM_STATE *versym, 1715 const char *file, uint_t flags) 1716 { 1717 SYMTBL_STATE ldynsym_state, dynsym_state; 1718 Cache *sortcache, *symcache; 1719 Shdr *sortshdr, *symshdr; 1720 Word sortsecndx, symsecndx; 1721 Word ldynsym_cnt; 1722 Word *ndx; 1723 Word ndxn; 1724 int output_cnt = 0; 1725 Conv_inv_buf_t inv_buf; 1726 1727 for (sortsecndx = 1; sortsecndx < shnum; sortsecndx++) { 1728 1729 sortcache = &cache[sortsecndx]; 1730 sortshdr = sortcache->c_shdr; 1731 1732 if ((sortshdr->sh_type != SHT_SUNW_symsort) && 1733 (sortshdr->sh_type != SHT_SUNW_tlssort)) 1734 continue; 1735 if (!match(MATCH_F_ALL, sortcache->c_name, sortsecndx, 1736 sortshdr->sh_type)) 1737 continue; 1738 1739 /* 1740 * If the section references a SUNW_ldynsym, then we 1741 * expect to see the associated .dynsym immediately 1742 * following. If it references a .dynsym, there is no 1743 * SUNW_ldynsym. If it is any other type, then we don't 1744 * know what to do with it. 1745 */ 1746 if ((sortshdr->sh_link == 0) || (sortshdr->sh_link >= shnum)) { 1747 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1748 file, sortcache->c_name, 1749 EC_WORD(sortshdr->sh_link)); 1750 continue; 1751 } 1752 symcache = &cache[sortshdr->sh_link]; 1753 symshdr = symcache->c_shdr; 1754 symsecndx = sortshdr->sh_link; 1755 ldynsym_cnt = 0; 1756 switch (symshdr->sh_type) { 1757 case SHT_SUNW_LDYNSYM: 1758 if (!init_symtbl_state(&ldynsym_state, cache, shnum, 1759 symsecndx, ehdr, versym, file, flags)) 1760 continue; 1761 ldynsym_cnt = ldynsym_state.symn; 1762 /* 1763 * We know that the dynsym follows immediately 1764 * after the SUNW_ldynsym, and so, should be at 1765 * (sortshdr->sh_link + 1). However, elfdump is a 1766 * diagnostic tool, so we do the full paranoid 1767 * search instead. 1768 */ 1769 for (symsecndx = 1; symsecndx < shnum; symsecndx++) { 1770 symcache = &cache[symsecndx]; 1771 symshdr = symcache->c_shdr; 1772 if (symshdr->sh_type == SHT_DYNSYM) 1773 break; 1774 } 1775 if (symsecndx >= shnum) { /* Dynsym not found! */ 1776 (void) fprintf(stderr, 1777 MSG_INTL(MSG_ERR_NODYNSYM), 1778 file, sortcache->c_name); 1779 continue; 1780 } 1781 /* Fallthrough to process associated dynsym */ 1782 /*FALLTHROUGH*/ 1783 case SHT_DYNSYM: 1784 if (!init_symtbl_state(&dynsym_state, cache, shnum, 1785 symsecndx, ehdr, versym, file, flags)) 1786 continue; 1787 break; 1788 default: 1789 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADNDXSEC), 1790 file, sortcache->c_name, conv_sec_type( 1791 ehdr->e_machine, symshdr->sh_type, 0, &inv_buf)); 1792 continue; 1793 } 1794 1795 /* 1796 * Output header 1797 */ 1798 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1799 if (ldynsym_cnt > 0) { 1800 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT2), 1801 sortcache->c_name, ldynsym_state.secname, 1802 dynsym_state.secname); 1803 /* 1804 * The data for .SUNW_ldynsym and dynsym sections 1805 * is supposed to be adjacent with SUNW_ldynsym coming 1806 * first. Check, and issue a warning if it isn't so. 1807 */ 1808 if (((ldynsym_state.sym + ldynsym_state.symn) 1809 != dynsym_state.sym) && 1810 ((flags & FLG_CTL_FAKESHDR) == 0)) 1811 (void) fprintf(stderr, 1812 MSG_INTL(MSG_ERR_LDYNNOTADJ), file, 1813 ldynsym_state.secname, 1814 dynsym_state.secname); 1815 } else { 1816 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT1), 1817 sortcache->c_name, dynsym_state.secname); 1818 } 1819 Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 1820 1821 /* If not first one, insert a line of whitespace */ 1822 if (output_cnt++ > 0) 1823 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1824 1825 /* 1826 * SUNW_dynsymsort and SUNW_dyntlssort are arrays of 1827 * symbol indices. Iterate over the array entries, 1828 * dispaying the referenced symbols. 1829 */ 1830 ndxn = sortshdr->sh_size / sortshdr->sh_entsize; 1831 ndx = (Word *)sortcache->c_data->d_buf; 1832 for (; ndxn-- > 0; ndx++) { 1833 if (*ndx >= ldynsym_cnt) { 1834 Word sec_ndx = *ndx - ldynsym_cnt; 1835 1836 output_symbol(&dynsym_state, sec_ndx, 0, 1837 *ndx, dynsym_state.sym + sec_ndx); 1838 } else { 1839 output_symbol(&ldynsym_state, *ndx, 0, 1840 *ndx, ldynsym_state.sym + *ndx); 1841 } 1842 } 1843 } 1844 } 1845 1846 /* 1847 * Search for and process any relocation sections. 1848 */ 1849 static void 1850 reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, 1851 uint_t flags) 1852 { 1853 Word cnt; 1854 1855 for (cnt = 1; cnt < shnum; cnt++) { 1856 Word type, symnum; 1857 Xword relndx, relnum, relsize; 1858 void *rels; 1859 Sym *syms; 1860 Cache *symsec, *strsec; 1861 Cache *_cache = &cache[cnt]; 1862 Shdr *shdr = _cache->c_shdr; 1863 char *relname = _cache->c_name; 1864 Conv_inv_buf_t inv_buf; 1865 1866 if (((type = shdr->sh_type) != SHT_RELA) && 1867 (type != SHT_REL)) 1868 continue; 1869 if (!match(MATCH_F_ALL, relname, cnt, type)) 1870 continue; 1871 1872 /* 1873 * Decide entry size. 1874 */ 1875 if (((relsize = shdr->sh_entsize) == 0) || 1876 (relsize > shdr->sh_size)) { 1877 if (type == SHT_RELA) 1878 relsize = sizeof (Rela); 1879 else 1880 relsize = sizeof (Rel); 1881 } 1882 1883 /* 1884 * Determine the number of relocations available. 1885 */ 1886 if (shdr->sh_size == 0) { 1887 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1888 file, relname); 1889 continue; 1890 } 1891 if (_cache->c_data == NULL) 1892 continue; 1893 1894 rels = _cache->c_data->d_buf; 1895 relnum = shdr->sh_size / relsize; 1896 1897 /* 1898 * Get the data buffer for the associated symbol table and 1899 * string table. 1900 */ 1901 if (stringtbl(cache, 1, cnt, shnum, file, 1902 &symnum, &symsec, &strsec) == 0) 1903 continue; 1904 1905 syms = symsec->c_data->d_buf; 1906 1907 /* 1908 * Loop through the relocation entries. 1909 */ 1910 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1911 dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name); 1912 Elf_reloc_title(0, ELF_DBG_ELFDUMP, type); 1913 1914 for (relndx = 0; relndx < relnum; relndx++, 1915 rels = (void *)((char *)rels + relsize)) { 1916 Half mach = ehdr->e_machine; 1917 char section[BUFSIZ]; 1918 const char *symname; 1919 Word symndx, reltype; 1920 Rela *rela; 1921 Rel *rel; 1922 1923 /* 1924 * Unravel the relocation and determine the symbol with 1925 * which this relocation is associated. 1926 */ 1927 if (type == SHT_RELA) { 1928 rela = (Rela *)rels; 1929 symndx = ELF_R_SYM(rela->r_info); 1930 reltype = ELF_R_TYPE(rela->r_info, mach); 1931 } else { 1932 rel = (Rel *)rels; 1933 symndx = ELF_R_SYM(rel->r_info); 1934 reltype = ELF_R_TYPE(rel->r_info, mach); 1935 } 1936 1937 symname = relsymname(cache, _cache, strsec, symndx, 1938 symnum, relndx, syms, section, BUFSIZ, file, 1939 flags); 1940 1941 /* 1942 * A zero symbol index is only valid for a few 1943 * relocations. 1944 */ 1945 if (symndx == 0) { 1946 int badrel = 0; 1947 1948 if ((mach == EM_SPARC) || 1949 (mach == EM_SPARC32PLUS) || 1950 (mach == EM_SPARCV9)) { 1951 if ((reltype != R_SPARC_NONE) && 1952 (reltype != R_SPARC_REGISTER) && 1953 (reltype != R_SPARC_RELATIVE)) 1954 badrel++; 1955 } else if (mach == EM_386) { 1956 if ((reltype != R_386_NONE) && 1957 (reltype != R_386_RELATIVE)) 1958 badrel++; 1959 } else if (mach == EM_AMD64) { 1960 if ((reltype != R_AMD64_NONE) && 1961 (reltype != R_AMD64_RELATIVE)) 1962 badrel++; 1963 } 1964 1965 if (badrel) { 1966 (void) fprintf(stderr, 1967 MSG_INTL(MSG_ERR_BADREL1), file, 1968 conv_reloc_type(mach, reltype, 1969 0, &inv_buf)); 1970 } 1971 } 1972 1973 Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP, 1974 MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type, 1975 rels, relname, symname, 0); 1976 } 1977 } 1978 } 1979 1980 1981 /* 1982 * This value controls which test dyn_test() performs. 1983 */ 1984 typedef enum { DYN_TEST_ADDR, DYN_TEST_SIZE, DYN_TEST_ENTSIZE } dyn_test_t; 1985 1986 /* 1987 * Used by dynamic() to compare the value of a dynamic element against 1988 * the starting address of the section it references. 1989 * 1990 * entry: 1991 * test_type - Specify which dyn item is being tested. 1992 * sh_type - SHT_* type value for required section. 1993 * sec_cache - Cache entry for section, or NULL if the object lacks 1994 * a section of this type. 1995 * dyn - Dyn entry to be tested 1996 * dynsec_cnt - # of dynamic section being examined. The first 1997 * dynamic section is 1, the next is 2, and so on... 1998 * ehdr - ELF header for file 1999 * file - Name of file 2000 */ 2001 static void 2002 dyn_test(dyn_test_t test_type, Word sh_type, Cache *sec_cache, Dyn *dyn, 2003 Word dynsec_cnt, Ehdr *ehdr, const char *file) 2004 { 2005 Conv_inv_buf_t buf1, buf2; 2006 2007 /* 2008 * These tests are based around the implicit assumption that 2009 * there is only one dynamic section in an object, and also only 2010 * one of the sections it references. We have therefore gathered 2011 * all of the necessary information to test this in a single pass 2012 * over the section headers, which is very efficient. We are not 2013 * aware of any case where more than one dynamic section would 2014 * be meaningful in an ELF object, so this is a reasonable solution. 2015 * 2016 * To test multiple dynamic sections correctly would be more 2017 * expensive in code and time. We would have to build a data structure 2018 * containing all the dynamic elements. Then, we would use the address 2019 * to locate the section it references and ensure the section is of 2020 * the right type and that the address in the dynamic element is 2021 * to the start of the section. Then, we could check the size and 2022 * entsize values against those same sections. This is O(n^2), and 2023 * also complicated. 2024 * 2025 * In the highly unlikely case that there is more than one dynamic 2026 * section, we only test the first one, and simply allow the values 2027 * of the subsequent one to be displayed unchallenged. 2028 */ 2029 if (dynsec_cnt != 1) 2030 return; 2031 2032 /* 2033 * A DT_ item that references a section address should always find 2034 * the section in the file. 2035 */ 2036 if (sec_cache == NULL) { 2037 const char *name; 2038 2039 /* 2040 * Supply section names instead of section types for 2041 * things that reference progbits so that the error 2042 * message will make more sense. 2043 */ 2044 switch (dyn->d_tag) { 2045 case DT_INIT: 2046 name = MSG_ORIG(MSG_ELF_INIT); 2047 break; 2048 case DT_FINI: 2049 name = MSG_ORIG(MSG_ELF_FINI); 2050 break; 2051 default: 2052 name = conv_sec_type(ehdr->e_machine, sh_type, 2053 0, &buf1); 2054 break; 2055 } 2056 (void) fprintf(stderr, MSG_INTL(MSG_ERR_DYNNOBCKSEC), file, 2057 name, conv_dyn_tag(dyn->d_tag, ehdr->e_machine, 0, &buf2)); 2058 return; 2059 } 2060 2061 2062 switch (test_type) { 2063 case DYN_TEST_ADDR: 2064 /* The section address should match the DT_ item value */ 2065 if (dyn->d_un.d_val != sec_cache->c_shdr->sh_addr) 2066 (void) fprintf(stderr, 2067 MSG_INTL(MSG_ERR_DYNBADADDR), file, 2068 conv_dyn_tag(dyn->d_tag, ehdr->e_machine, 0, &buf1), 2069 EC_ADDR(dyn->d_un.d_val), sec_cache->c_ndx, 2070 sec_cache->c_name, 2071 EC_ADDR(sec_cache->c_shdr->sh_addr)); 2072 break; 2073 2074 case DYN_TEST_SIZE: 2075 /* The section size should match the DT_ item value */ 2076 if (dyn->d_un.d_val != sec_cache->c_shdr->sh_size) 2077 (void) fprintf(stderr, 2078 MSG_INTL(MSG_ERR_DYNBADSIZE), file, 2079 conv_dyn_tag(dyn->d_tag, ehdr->e_machine, 0, &buf1), 2080 EC_XWORD(dyn->d_un.d_val), 2081 sec_cache->c_ndx, sec_cache->c_name, 2082 EC_XWORD(sec_cache->c_shdr->sh_size)); 2083 break; 2084 2085 case DYN_TEST_ENTSIZE: 2086 /* The sh_entsize value should match the DT_ item value */ 2087 if (dyn->d_un.d_val != sec_cache->c_shdr->sh_entsize) 2088 (void) fprintf(stderr, 2089 MSG_INTL(MSG_ERR_DYNBADENTSIZE), file, 2090 conv_dyn_tag(dyn->d_tag, ehdr->e_machine, 0, &buf1), 2091 EC_XWORD(dyn->d_un.d_val), 2092 sec_cache->c_ndx, sec_cache->c_name, 2093 EC_XWORD(sec_cache->c_shdr->sh_entsize)); 2094 break; 2095 } 2096 } 2097 2098 2099 /* 2100 * There are some DT_ entries that have corresponding symbols 2101 * (e.g. DT_INIT and _init). It is expected that these items will 2102 * both have the same value if both are present. This routine 2103 * examines the well known symbol tables for such symbols and 2104 * issues warnings for any that don't match. 2105 * 2106 * entry: 2107 * dyn - Dyn entry to be tested 2108 * symname - Name of symbol that corresponds to dyn 2109 * symtab_cache, dynsym_cache, ldynsym_cache - Symbol tables to check 2110 * cache - Cache of all section headers 2111 * shnum - # of sections in cache 2112 * ehdr - ELF header for file 2113 * file - Name of file 2114 */ 2115 2116 static void 2117 dyn_symtest(Dyn *dyn, const char *symname, Cache *symtab_cache, 2118 Cache *dynsym_cache, Cache *ldynsym_cache, Cache *cache, 2119 Word shnum, Ehdr *ehdr, const char *file) 2120 { 2121 Conv_inv_buf_t buf; 2122 int i; 2123 Sym *sym; 2124 Cache *_cache; 2125 2126 for (i = 0; i < 3; i++) { 2127 switch (i) { 2128 case 0: 2129 _cache = symtab_cache; 2130 break; 2131 case 1: 2132 _cache = dynsym_cache; 2133 break; 2134 case 2: 2135 _cache = ldynsym_cache; 2136 break; 2137 } 2138 2139 if ((_cache != NULL) && 2140 symlookup(symname, cache, shnum, &sym, _cache, file) && 2141 (sym->st_value != dyn->d_un.d_val)) 2142 (void) fprintf(stderr, MSG_INTL(MSG_ERR_DYNSYMVAL), 2143 file, _cache->c_name, 2144 conv_dyn_tag(dyn->d_tag, ehdr->e_machine, 0, &buf), 2145 symname, EC_ADDR(sym->st_value)); 2146 } 2147 } 2148 2149 2150 /* 2151 * Search for and process a .dynamic section. 2152 */ 2153 static void 2154 dynamic(Cache *cache, Word shnum, Ehdr *ehdr, const char *file) 2155 { 2156 struct { 2157 Cache *symtab; 2158 Cache *dynstr; 2159 Cache *dynsym; 2160 Cache *hash; 2161 Cache *fini; 2162 Cache *fini_array; 2163 Cache *init; 2164 Cache *init_array; 2165 Cache *preinit_array; 2166 Cache *rel; 2167 Cache *rela; 2168 Cache *sunw_cap; 2169 Cache *sunw_ldynsym; 2170 Cache *sunw_move; 2171 Cache *sunw_syminfo; 2172 Cache *sunw_symsort; 2173 Cache *sunw_tlssort; 2174 Cache *sunw_verdef; 2175 Cache *sunw_verneed; 2176 Cache *sunw_versym; 2177 } sec; 2178 Word dynsec_ndx; 2179 Word dynsec_num; 2180 int dynsec_cnt; 2181 Word cnt; 2182 2183 /* 2184 * Make a pass over all the sections, gathering section information 2185 * we'll need below. 2186 */ 2187 dynsec_num = 0; 2188 bzero(&sec, sizeof (sec)); 2189 for (cnt = 1; cnt < shnum; cnt++) { 2190 Cache *_cache = &cache[cnt]; 2191 2192 switch (_cache->c_shdr->sh_type) { 2193 case SHT_DYNAMIC: 2194 if (dynsec_num == 0) { 2195 dynsec_ndx = cnt; 2196 2197 /* Does it have a valid string table? */ 2198 (void) stringtbl(cache, 0, cnt, shnum, file, 2199 0, 0, &sec.dynstr); 2200 } 2201 dynsec_num++; 2202 break; 2203 2204 2205 case SHT_PROGBITS: 2206 /* 2207 * We want to detect the .init and .fini sections, 2208 * if present. These are SHT_PROGBITS, so all we 2209 * have to go on is the section name. Normally comparing 2210 * names is a bad idea, but there are some special 2211 * names (i.e. .init/.fini/.interp) that are very 2212 * difficult to use in any other context, and for 2213 * these symbols, we do the heuristic match. 2214 */ 2215 if (strcmp(_cache->c_name, 2216 MSG_ORIG(MSG_ELF_INIT)) == 0) { 2217 if (sec.init == NULL) 2218 sec.init = _cache; 2219 } else if (strcmp(_cache->c_name, 2220 MSG_ORIG(MSG_ELF_FINI)) == 0) { 2221 if (sec.fini == NULL) 2222 sec.fini = _cache; 2223 } 2224 break; 2225 2226 case SHT_REL: 2227 /* 2228 * We want the SHT_REL section with the lowest 2229 * offset. The linker gathers them together, 2230 * and puts the address of the first one 2231 * into the DT_REL dynamic element. 2232 */ 2233 if ((sec.rel == NULL) || 2234 (_cache->c_shdr->sh_offset < 2235 sec.rel->c_shdr->sh_offset)) 2236 sec.rel = _cache; 2237 break; 2238 2239 case SHT_RELA: 2240 /* RELA is handled just like RELA above */ 2241 if ((sec.rela == NULL) || 2242 (_cache->c_shdr->sh_offset < 2243 sec.rela->c_shdr->sh_offset)) 2244 sec.rela = _cache; 2245 break; 2246 2247 /* 2248 * The GRAB macro is used for the simple case in which 2249 * we simply grab the first section of the desired type. 2250 */ 2251 #define GRAB(_sec_type, _sec_field) \ 2252 case _sec_type: \ 2253 if (sec._sec_field == NULL) \ 2254 sec._sec_field = _cache; \ 2255 break 2256 GRAB(SHT_SYMTAB, symtab); 2257 GRAB(SHT_DYNSYM, dynsym); 2258 GRAB(SHT_FINI_ARRAY, fini_array); 2259 GRAB(SHT_HASH, hash); 2260 GRAB(SHT_INIT_ARRAY, init_array); 2261 GRAB(SHT_SUNW_move, sunw_move); 2262 GRAB(SHT_PREINIT_ARRAY, preinit_array); 2263 GRAB(SHT_SUNW_cap, sunw_cap); 2264 GRAB(SHT_SUNW_LDYNSYM, sunw_ldynsym); 2265 GRAB(SHT_SUNW_syminfo, sunw_syminfo); 2266 GRAB(SHT_SUNW_symsort, sunw_symsort); 2267 GRAB(SHT_SUNW_tlssort, sunw_tlssort); 2268 GRAB(SHT_SUNW_verdef, sunw_verdef); 2269 GRAB(SHT_SUNW_verneed, sunw_verneed); 2270 GRAB(SHT_SUNW_versym, sunw_versym); 2271 #undef GRAB 2272 } 2273 } 2274 2275 /* 2276 * If no dynamic section, return immediately. If more than one 2277 * dynamic section, then something odd is going on and an error 2278 * is in order, but then continue on and display them all. 2279 */ 2280 if (dynsec_num == 0) 2281 return; 2282 if (dynsec_num > 1) 2283 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MULTDYN), 2284 file, EC_WORD(dynsec_num)); 2285 2286 2287 dynsec_cnt = 0; 2288 for (cnt = dynsec_ndx; (cnt < shnum) && (dynsec_cnt < dynsec_num); 2289 cnt++) { 2290 Dyn *dyn; 2291 ulong_t numdyn; 2292 int ndx, end_ndx; 2293 Cache *_cache = &cache[cnt], *strsec; 2294 Shdr *shdr = _cache->c_shdr; 2295 int dumped = 0; 2296 2297 if (shdr->sh_type != SHT_DYNAMIC) 2298 continue; 2299 dynsec_cnt++; 2300 2301 /* 2302 * Verify the associated string table section. 2303 */ 2304 if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0) 2305 continue; 2306 2307 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 2308 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2309 file, _cache->c_name); 2310 continue; 2311 } 2312 if (_cache->c_data == NULL) 2313 continue; 2314 2315 numdyn = shdr->sh_size / shdr->sh_entsize; 2316 dyn = (Dyn *)_cache->c_data->d_buf; 2317 2318 /* 2319 * We expect the REL/RELA entries to reference the reloc 2320 * section with the lowest address. However, this is 2321 * not true for dumped objects. Detect if this object has 2322 * been dumped so that we can skip the reloc address test 2323 * in that case. 2324 */ 2325 for (ndx = 0; ndx < numdyn; dyn++, ndx++) { 2326 if (dyn->d_tag == DT_FLAGS_1) { 2327 dumped = (dyn->d_un.d_val & DF_1_CONFALT) != 0; 2328 break; 2329 } 2330 } 2331 dyn = (Dyn *)_cache->c_data->d_buf; 2332 2333 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2334 dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name); 2335 2336 Elf_dyn_title(0); 2337 2338 for (ndx = 0; ndx < numdyn; dyn++, ndx++) { 2339 union { 2340 Conv_inv_buf_t inv; 2341 Conv_dyn_flag_buf_t flag; 2342 Conv_dyn_flag1_buf_t flag1; 2343 Conv_dyn_posflag1_buf_t posflag1; 2344 Conv_dyn_feature1_buf_t feature1; 2345 } c_buf; 2346 const char *name = NULL; 2347 2348 /* 2349 * Print the information numerically, and if possible 2350 * as a string. If a string is available, name is 2351 * set to reference it. 2352 * 2353 * Also, take this opportunity to sanity check 2354 * the values of DT elements. In the code above, 2355 * we gathered information on sections that are 2356 * referenced by the dynamic section. Here, we 2357 * compare the attributes of those sections to 2358 * the DT_ items that reference them and report 2359 * on inconsistencies. 2360 * 2361 * Things not currently tested that could be improved 2362 * in later revisions include: 2363 * - We don't check PLT or GOT related items 2364 * - We don't handle computing the lengths of 2365 * relocation arrays. To handle this 2366 * requires examining data that spans 2367 * across sections, in a contiguous span 2368 * within a single segment. 2369 * - DT_VERDEFNUM and DT_VERNEEDNUM can't be 2370 * verified without parsing the sections. 2371 * - We don't handle DT_SUNW_SYMSZ, which would 2372 * be the sum of the lengths of .dynsym and 2373 * .SUNW_ldynsym 2374 * - DT_SUNW_STRPAD can't be verified other than 2375 * to check that it's not larger than 2376 * the string table. 2377 * - Some items come in "all or none" clusters 2378 * that give an address, element size, 2379 * and data length in bytes. We don't 2380 * verify that there are no missing items 2381 * in such groups. 2382 */ 2383 switch (dyn->d_tag) { 2384 case DT_NULL: 2385 /* 2386 * Special case: DT_NULLs can come in groups 2387 * that we prefer to reduce to a single line. 2388 */ 2389 end_ndx = ndx; 2390 while ((end_ndx < (numdyn - 1)) && 2391 ((dyn + 1)->d_tag == DT_NULL)) { 2392 dyn++; 2393 end_ndx++; 2394 } 2395 Elf_dyn_null_entry(0, dyn, ndx, end_ndx); 2396 ndx = end_ndx; 2397 continue; 2398 2399 /* 2400 * String items all reference the dynstr. The string() 2401 * function does the necessary sanity checking. 2402 */ 2403 case DT_NEEDED: 2404 case DT_SONAME: 2405 case DT_FILTER: 2406 case DT_AUXILIARY: 2407 case DT_CONFIG: 2408 case DT_RPATH: 2409 case DT_RUNPATH: 2410 case DT_USED: 2411 case DT_DEPAUDIT: 2412 case DT_AUDIT: 2413 case DT_SUNW_AUXILIARY: 2414 case DT_SUNW_FILTER: 2415 name = string(_cache, ndx, strsec, 2416 file, dyn->d_un.d_ptr); 2417 break; 2418 2419 case DT_FLAGS: 2420 name = conv_dyn_flag(dyn->d_un.d_val, 2421 0, &c_buf.flag); 2422 break; 2423 case DT_FLAGS_1: 2424 name = conv_dyn_flag1(dyn->d_un.d_val, 0, 2425 &c_buf.flag1); 2426 break; 2427 case DT_POSFLAG_1: 2428 name = conv_dyn_posflag1(dyn->d_un.d_val, 0, 2429 &c_buf.posflag1); 2430 break; 2431 case DT_FEATURE_1: 2432 name = conv_dyn_feature1(dyn->d_un.d_val, 0, 2433 &c_buf.feature1); 2434 break; 2435 case DT_DEPRECATED_SPARC_REGISTER: 2436 name = MSG_INTL(MSG_STR_DEPRECATED); 2437 break; 2438 2439 case DT_SUNW_LDMACH: 2440 name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0, 2441 &c_buf.inv); 2442 break; 2443 2444 /* 2445 * Cases below this point are strictly sanity checking, 2446 * and do not generate a name string. The TEST_ macros 2447 * are used to hide the boilerplate arguments neeeded 2448 * by dyn_test(). 2449 */ 2450 #define TEST_ADDR(_sh_type, _sec_field) \ 2451 dyn_test(DYN_TEST_ADDR, _sh_type, \ 2452 sec._sec_field, dyn, dynsec_cnt, ehdr, file) 2453 #define TEST_SIZE(_sh_type, _sec_field) \ 2454 dyn_test(DYN_TEST_SIZE, _sh_type, \ 2455 sec._sec_field, dyn, dynsec_cnt, ehdr, file) 2456 #define TEST_ENTSIZE(_sh_type, _sec_field) \ 2457 dyn_test(DYN_TEST_ENTSIZE, _sh_type, \ 2458 sec._sec_field, dyn, dynsec_cnt, ehdr, file) 2459 2460 case DT_FINI: 2461 dyn_symtest(dyn, MSG_ORIG(MSG_SYM_FINI), 2462 sec.symtab, sec.dynsym, sec.sunw_ldynsym, 2463 cache, shnum, ehdr, file); 2464 TEST_ADDR(SHT_PROGBITS, fini); 2465 break; 2466 2467 case DT_FINI_ARRAY: 2468 TEST_ADDR(SHT_FINI_ARRAY, fini_array); 2469 break; 2470 2471 case DT_FINI_ARRAYSZ: 2472 TEST_SIZE(SHT_FINI_ARRAY, fini_array); 2473 break; 2474 2475 case DT_HASH: 2476 TEST_ADDR(SHT_HASH, hash); 2477 break; 2478 2479 case DT_INIT: 2480 dyn_symtest(dyn, MSG_ORIG(MSG_SYM_INIT), 2481 sec.symtab, sec.dynsym, sec.sunw_ldynsym, 2482 cache, shnum, ehdr, file); 2483 TEST_ADDR(SHT_PROGBITS, init); 2484 break; 2485 2486 case DT_INIT_ARRAY: 2487 TEST_ADDR(SHT_INIT_ARRAY, init_array); 2488 break; 2489 2490 case DT_INIT_ARRAYSZ: 2491 TEST_SIZE(SHT_INIT_ARRAY, init_array); 2492 break; 2493 2494 case DT_MOVEENT: 2495 TEST_ENTSIZE(SHT_SUNW_move, sunw_move); 2496 break; 2497 2498 case DT_MOVESZ: 2499 TEST_SIZE(SHT_SUNW_move, sunw_move); 2500 break; 2501 2502 case DT_MOVETAB: 2503 TEST_ADDR(SHT_SUNW_move, sunw_move); 2504 break; 2505 2506 case DT_PREINIT_ARRAY: 2507 TEST_ADDR(SHT_PREINIT_ARRAY, preinit_array); 2508 break; 2509 2510 case DT_PREINIT_ARRAYSZ: 2511 TEST_SIZE(SHT_PREINIT_ARRAY, preinit_array); 2512 break; 2513 2514 case DT_REL: 2515 if (!dumped) 2516 TEST_ADDR(SHT_REL, rel); 2517 break; 2518 2519 case DT_RELENT: 2520 TEST_ENTSIZE(SHT_REL, rel); 2521 break; 2522 2523 case DT_RELA: 2524 if (!dumped) 2525 TEST_ADDR(SHT_RELA, rela); 2526 break; 2527 2528 case DT_RELAENT: 2529 TEST_ENTSIZE(SHT_RELA, rela); 2530 break; 2531 2532 case DT_STRTAB: 2533 TEST_ADDR(SHT_STRTAB, dynstr); 2534 break; 2535 2536 case DT_STRSZ: 2537 TEST_SIZE(SHT_STRTAB, dynstr); 2538 break; 2539 2540 case DT_SUNW_CAP: 2541 TEST_ADDR(SHT_SUNW_cap, sunw_cap); 2542 break; 2543 2544 case DT_SUNW_SYMTAB: 2545 TEST_ADDR(SHT_SUNW_LDYNSYM, sunw_ldynsym); 2546 break; 2547 2548 case DT_SYMENT: 2549 TEST_ENTSIZE(SHT_DYNSYM, dynsym); 2550 break; 2551 2552 case DT_SYMINENT: 2553 TEST_ENTSIZE(SHT_SUNW_syminfo, sunw_syminfo); 2554 break; 2555 2556 case DT_SYMINFO: 2557 TEST_ADDR(SHT_SUNW_syminfo, sunw_syminfo); 2558 break; 2559 2560 case DT_SYMINSZ: 2561 TEST_SIZE(SHT_SUNW_syminfo, sunw_syminfo); 2562 break; 2563 2564 case DT_SYMTAB: 2565 TEST_ADDR(SHT_DYNSYM, dynsym); 2566 break; 2567 2568 case DT_SUNW_SORTENT: 2569 /* 2570 * This entry is related to both the symsort and 2571 * tlssort sections. 2572 */ 2573 { 2574 int test_tls = 2575 (sec.sunw_tlssort != NULL); 2576 int test_sym = 2577 (sec.sunw_symsort != NULL) || 2578 !test_tls; 2579 if (test_sym) 2580 TEST_ENTSIZE(SHT_SUNW_symsort, 2581 sunw_symsort); 2582 if (test_tls) 2583 TEST_ENTSIZE(SHT_SUNW_tlssort, 2584 sunw_tlssort); 2585 } 2586 break; 2587 2588 2589 case DT_SUNW_SYMSORT: 2590 TEST_ADDR(SHT_SUNW_symsort, sunw_symsort); 2591 break; 2592 2593 case DT_SUNW_SYMSORTSZ: 2594 TEST_SIZE(SHT_SUNW_symsort, sunw_symsort); 2595 break; 2596 2597 case DT_SUNW_TLSSORT: 2598 TEST_ADDR(SHT_SUNW_tlssort, sunw_tlssort); 2599 break; 2600 2601 case DT_SUNW_TLSSORTSZ: 2602 TEST_SIZE(SHT_SUNW_tlssort, sunw_tlssort); 2603 break; 2604 2605 case DT_VERDEF: 2606 TEST_ADDR(SHT_SUNW_verdef, sunw_verdef); 2607 break; 2608 2609 case DT_VERNEED: 2610 TEST_ADDR(SHT_SUNW_verneed, sunw_verneed); 2611 break; 2612 2613 case DT_VERSYM: 2614 TEST_ADDR(SHT_SUNW_versym, sunw_versym); 2615 break; 2616 #undef TEST_ADDR 2617 #undef TEST_SIZE 2618 #undef TEST_ENTSIZE 2619 } 2620 2621 if (name == NULL) 2622 name = MSG_ORIG(MSG_STR_EMPTY); 2623 Elf_dyn_entry(0, dyn, ndx, name, ehdr->e_machine); 2624 } 2625 } 2626 } 2627 2628 /* 2629 * Search for and process a MOVE section. 2630 */ 2631 static void 2632 move(Cache *cache, Word shnum, const char *file, uint_t flags) 2633 { 2634 Word cnt; 2635 const char *fmt = 0; 2636 2637 for (cnt = 1; cnt < shnum; cnt++) { 2638 Word movenum, symnum, ndx; 2639 Sym *syms; 2640 Cache *_cache = &cache[cnt]; 2641 Shdr *shdr = _cache->c_shdr; 2642 Cache *symsec, *strsec; 2643 Move *move; 2644 2645 if (shdr->sh_type != SHT_SUNW_move) 2646 continue; 2647 if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type)) 2648 continue; 2649 2650 /* 2651 * Determine the move data and number. 2652 */ 2653 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 2654 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2655 file, _cache->c_name); 2656 continue; 2657 } 2658 if (_cache->c_data == NULL) 2659 continue; 2660 2661 move = (Move *)_cache->c_data->d_buf; 2662 movenum = shdr->sh_size / shdr->sh_entsize; 2663 2664 /* 2665 * Get the data buffer for the associated symbol table and 2666 * string table. 2667 */ 2668 if (stringtbl(cache, 1, cnt, shnum, file, 2669 &symnum, &symsec, &strsec) == 0) 2670 return; 2671 2672 syms = (Sym *)symsec->c_data->d_buf; 2673 2674 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2675 dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name); 2676 dbg_print(0, MSG_INTL(MSG_MOVE_TITLE)); 2677 2678 if (fmt == 0) 2679 fmt = MSG_INTL(MSG_MOVE_ENTRY); 2680 2681 for (ndx = 0; ndx < movenum; move++, ndx++) { 2682 const char *symname; 2683 char index[MAXNDXSIZE], section[BUFSIZ]; 2684 Word symndx, shndx; 2685 Sym *sym; 2686 2687 /* 2688 * Check for null entries 2689 */ 2690 if ((move->m_info == 0) && (move->m_value == 0) && 2691 (move->m_poffset == 0) && (move->m_repeat == 0) && 2692 (move->m_stride == 0)) { 2693 dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY), 2694 EC_XWORD(move->m_poffset), 0, 0, 0, 2695 EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY)); 2696 continue; 2697 } 2698 if (((symndx = ELF_M_SYM(move->m_info)) == 0) || 2699 (symndx >= symnum)) { 2700 (void) fprintf(stderr, 2701 MSG_INTL(MSG_ERR_BADMINFO), file, 2702 _cache->c_name, EC_XWORD(move->m_info)); 2703 2704 (void) snprintf(index, MAXNDXSIZE, 2705 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 2706 dbg_print(0, fmt, index, 2707 EC_XWORD(move->m_poffset), 2708 ELF_M_SIZE(move->m_info), move->m_repeat, 2709 move->m_stride, move->m_value, 2710 MSG_INTL(MSG_STR_UNKNOWN)); 2711 continue; 2712 } 2713 2714 symname = relsymname(cache, _cache, strsec, 2715 symndx, symnum, ndx, syms, section, BUFSIZ, file, 2716 flags); 2717 sym = (Sym *)(syms + symndx); 2718 2719 /* 2720 * Additional sanity check. 2721 */ 2722 shndx = sym->st_shndx; 2723 if (!((shndx == SHN_COMMON) || 2724 (((shndx >= 1) && (shndx <= shnum)) && 2725 (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) { 2726 (void) fprintf(stderr, 2727 MSG_INTL(MSG_ERR_BADSYM2), file, 2728 _cache->c_name, EC_WORD(symndx), 2729 demangle(symname, flags)); 2730 } 2731 2732 (void) snprintf(index, MAXNDXSIZE, 2733 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 2734 dbg_print(0, fmt, index, EC_XWORD(move->m_poffset), 2735 ELF_M_SIZE(move->m_info), move->m_repeat, 2736 move->m_stride, move->m_value, 2737 demangle(symname, flags)); 2738 } 2739 } 2740 } 2741 2742 /* 2743 * Traverse a note section analyzing each note information block. 2744 * The data buffers size is used to validate references before they are made, 2745 * and is decremented as each element is processed. 2746 */ 2747 void 2748 note_entry(Cache *cache, Word *data, size_t size, const char *file) 2749 { 2750 size_t bsize = size; 2751 2752 /* 2753 * Print out a single `note' information block. 2754 */ 2755 while (size > 0) { 2756 size_t namesz, descsz, type, pad, noteoff; 2757 2758 noteoff = bsize - size; 2759 /* 2760 * Make sure we can at least reference the 3 initial entries 2761 * (4-byte words) of the note information block. 2762 */ 2763 if (size >= (sizeof (Word) * 3)) 2764 size -= (sizeof (Word) * 3); 2765 else { 2766 (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ), 2767 file, cache->c_name, EC_WORD(noteoff)); 2768 return; 2769 } 2770 2771 /* 2772 * Make sure any specified name string can be referenced. 2773 */ 2774 if ((namesz = *data++) != 0) { 2775 if (size >= namesz) 2776 size -= namesz; 2777 else { 2778 (void) fprintf(stderr, 2779 MSG_INTL(MSG_NOTE_BADNMSZ), file, 2780 cache->c_name, EC_WORD(noteoff), 2781 EC_WORD(namesz)); 2782 return; 2783 } 2784 } 2785 2786 /* 2787 * Make sure any specified descriptor can be referenced. 2788 */ 2789 if ((descsz = *data++) != 0) { 2790 /* 2791 * If namesz isn't a 4-byte multiple, account for any 2792 * padding that must exist before the descriptor. 2793 */ 2794 if ((pad = (namesz & (sizeof (Word) - 1))) != 0) { 2795 pad = sizeof (Word) - pad; 2796 size -= pad; 2797 } 2798 if (size >= descsz) 2799 size -= descsz; 2800 else { 2801 (void) fprintf(stderr, 2802 MSG_INTL(MSG_NOTE_BADDESZ), file, 2803 cache->c_name, EC_WORD(noteoff), 2804 EC_WORD(namesz)); 2805 return; 2806 } 2807 } 2808 2809 type = *data++; 2810 2811 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2812 dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE), EC_WORD(type)); 2813 2814 dbg_print(0, MSG_ORIG(MSG_NOTE_NAMESZ), EC_WORD(namesz)); 2815 if (namesz) { 2816 char *name = (char *)data; 2817 2818 /* 2819 * Since the name string may have 'null' bytes 2820 * in it (ia32 .string) - we just write the 2821 * whole stream in a single fwrite. 2822 */ 2823 (void) fwrite(name, namesz, 1, stdout); 2824 name = name + ((namesz + (sizeof (Word) - 1)) & 2825 ~(sizeof (Word) - 1)); 2826 /* LINTED */ 2827 data = (Word *)name; 2828 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2829 } 2830 2831 /* 2832 * If multiple information blocks exist within a .note section 2833 * account for any padding that must exist before the next 2834 * information block. 2835 */ 2836 if ((pad = (descsz & (sizeof (Word) - 1))) != 0) { 2837 pad = sizeof (Word) - pad; 2838 if (size > pad) 2839 size -= pad; 2840 } 2841 2842 dbg_print(0, MSG_ORIG(MSG_NOTE_DESCSZ), EC_WORD(descsz)); 2843 if (descsz) { 2844 int ndx, byte, word; 2845 char string[58], *str = string; 2846 uchar_t *desc = (uchar_t *)data; 2847 2848 /* 2849 * Dump descriptor bytes. 2850 */ 2851 for (ndx = byte = word = 0; descsz; descsz--, desc++) { 2852 int tok = *desc; 2853 2854 (void) snprintf(str, 58, MSG_ORIG(MSG_NOTE_TOK), 2855 tok); 2856 str += 3; 2857 2858 if (++byte == 4) { 2859 *str++ = ' ', *str++ = ' '; 2860 word++; 2861 byte = 0; 2862 } 2863 if (word == 4) { 2864 *str = '\0'; 2865 dbg_print(0, MSG_ORIG(MSG_NOTE_DESC), 2866 ndx, string); 2867 word = 0; 2868 ndx += 16; 2869 str = string; 2870 } 2871 } 2872 if (byte || word) { 2873 *str = '\0'; 2874 dbg_print(0, MSG_ORIG(MSG_NOTE_DESC), 2875 ndx, string); 2876 } 2877 2878 desc += pad; 2879 /* LINTED */ 2880 data = (Word *)desc; 2881 } 2882 } 2883 } 2884 2885 /* 2886 * Search for and process a .note section. 2887 */ 2888 static void 2889 note(Cache *cache, Word shnum, const char *file) 2890 { 2891 Word cnt; 2892 2893 /* 2894 * Otherwise look for any .note sections. 2895 */ 2896 for (cnt = 1; cnt < shnum; cnt++) { 2897 Cache *_cache = &cache[cnt]; 2898 Shdr *shdr = _cache->c_shdr; 2899 2900 if (shdr->sh_type != SHT_NOTE) 2901 continue; 2902 if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type)) 2903 continue; 2904 2905 /* 2906 * As these sections are often hand rolled, make sure they're 2907 * properly aligned before proceeding, and issue an error 2908 * as necessary. 2909 * 2910 * Note that we will continue on to display the note even 2911 * if it has bad alignment. We can do this safely, because 2912 * libelf knows the alignment required for SHT_NOTE, and 2913 * takes steps to deliver a properly aligned buffer to us 2914 * even if the actual file is misaligned. 2915 */ 2916 if (shdr->sh_offset & (sizeof (Word) - 1)) 2917 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN), 2918 file, _cache->c_name); 2919 2920 if (_cache->c_data == NULL) 2921 continue; 2922 2923 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2924 dbg_print(0, MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name); 2925 note_entry(_cache, (Word *)_cache->c_data->d_buf, 2926 /* LINTED */ 2927 (Word)_cache->c_data->d_size, file); 2928 } 2929 } 2930 2931 /* 2932 * Determine an individual hash entry. This may be the initial hash entry, 2933 * or an associated chain entry. 2934 */ 2935 static void 2936 hash_entry(Cache *refsec, Cache *strsec, const char *hsecname, Word hashndx, 2937 Word symndx, Word symn, Sym *syms, const char *file, ulong_t bkts, 2938 uint_t flags, int chain) 2939 { 2940 Sym *sym; 2941 const char *symname, *str; 2942 char _bucket[MAXNDXSIZE], _symndx[MAXNDXSIZE]; 2943 ulong_t nbkt, nhash; 2944 2945 if (symndx > symn) { 2946 (void) fprintf(stderr, MSG_INTL(MSG_ERR_HSBADSYMNDX), file, 2947 EC_WORD(symndx), EC_WORD(hashndx)); 2948 symname = MSG_INTL(MSG_STR_UNKNOWN); 2949 } else { 2950 sym = (Sym *)(syms + symndx); 2951 symname = string(refsec, symndx, strsec, file, sym->st_name); 2952 } 2953 2954 if (chain == 0) { 2955 (void) snprintf(_bucket, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 2956 hashndx); 2957 str = (const char *)_bucket; 2958 } else 2959 str = MSG_ORIG(MSG_STR_EMPTY); 2960 2961 (void) snprintf(_symndx, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX2), 2962 EC_WORD(symndx)); 2963 dbg_print(0, MSG_ORIG(MSG_FMT_HASH_INFO), str, _symndx, 2964 demangle(symname, flags)); 2965 2966 /* 2967 * Determine if this string is in the correct bucket. 2968 */ 2969 nhash = elf_hash(symname); 2970 nbkt = nhash % bkts; 2971 2972 if (nbkt != hashndx) { 2973 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADHASH), file, 2974 hsecname, symname, EC_WORD(hashndx), nbkt); 2975 } 2976 } 2977 2978 #define MAXCOUNT 500 2979 2980 static void 2981 hash(Cache *cache, Word shnum, const char *file, uint_t flags) 2982 { 2983 static int count[MAXCOUNT]; 2984 Word cnt; 2985 ulong_t ndx, bkts; 2986 char number[MAXNDXSIZE]; 2987 2988 for (cnt = 1; cnt < shnum; cnt++) { 2989 uint_t *hash, *chain; 2990 Cache *_cache = &cache[cnt]; 2991 Shdr *sshdr, *hshdr = _cache->c_shdr; 2992 char *ssecname, *hsecname = _cache->c_name; 2993 Sym *syms; 2994 Word symn; 2995 2996 if (hshdr->sh_type != SHT_HASH) 2997 continue; 2998 2999 /* 3000 * Determine the hash table data and size. 3001 */ 3002 if ((hshdr->sh_entsize == 0) || (hshdr->sh_size == 0)) { 3003 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 3004 file, hsecname); 3005 continue; 3006 } 3007 if (_cache->c_data == NULL) 3008 continue; 3009 3010 hash = (uint_t *)_cache->c_data->d_buf; 3011 bkts = *hash; 3012 chain = hash + 2 + bkts; 3013 hash += 2; 3014 3015 /* 3016 * Get the data buffer for the associated symbol table. 3017 */ 3018 if ((hshdr->sh_link == 0) || (hshdr->sh_link >= shnum)) { 3019 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 3020 file, hsecname, EC_WORD(hshdr->sh_link)); 3021 continue; 3022 } 3023 3024 _cache = &cache[hshdr->sh_link]; 3025 ssecname = _cache->c_name; 3026 3027 if (_cache->c_data == NULL) 3028 continue; 3029 3030 if ((syms = (Sym *)_cache->c_data->d_buf) == NULL) { 3031 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 3032 file, ssecname); 3033 continue; 3034 } 3035 3036 sshdr = _cache->c_shdr; 3037 /* LINTED */ 3038 symn = (Word)(sshdr->sh_size / sshdr->sh_entsize); 3039 3040 /* 3041 * Get the associated string table section. 3042 */ 3043 if ((sshdr->sh_link == 0) || (sshdr->sh_link >= shnum)) { 3044 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 3045 file, ssecname, EC_WORD(sshdr->sh_link)); 3046 continue; 3047 } 3048 3049 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 3050 dbg_print(0, MSG_INTL(MSG_ELF_SCN_HASH), hsecname); 3051 dbg_print(0, MSG_INTL(MSG_ELF_HASH_INFO)); 3052 3053 /* 3054 * Loop through the hash buckets, printing the appropriate 3055 * symbols. 3056 */ 3057 for (ndx = 0; ndx < bkts; ndx++, hash++) { 3058 Word _ndx, _cnt; 3059 3060 if (*hash == 0) { 3061 count[0]++; 3062 continue; 3063 } 3064 3065 hash_entry(_cache, &cache[sshdr->sh_link], hsecname, 3066 ndx, *hash, symn, syms, file, bkts, flags, 0); 3067 3068 /* 3069 * Determine if any other symbols are chained to this 3070 * bucket. 3071 */ 3072 _ndx = chain[*hash]; 3073 _cnt = 1; 3074 while (_ndx) { 3075 hash_entry(_cache, &cache[sshdr->sh_link], 3076 hsecname, ndx, _ndx, symn, syms, file, 3077 bkts, flags, 1); 3078 _ndx = chain[_ndx]; 3079 _cnt++; 3080 } 3081 3082 if (_cnt >= MAXCOUNT) { 3083 (void) fprintf(stderr, 3084 MSG_INTL(MSG_HASH_OVERFLW), file, 3085 _cache->c_name, EC_WORD(ndx), 3086 EC_WORD(_cnt)); 3087 } else 3088 count[_cnt]++; 3089 } 3090 break; 3091 } 3092 3093 /* 3094 * Print out the count information. 3095 */ 3096 bkts = cnt = 0; 3097 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 3098 3099 for (ndx = 0; ndx < MAXCOUNT; ndx++) { 3100 Word _cnt; 3101 3102 if ((_cnt = count[ndx]) == 0) 3103 continue; 3104 3105 (void) snprintf(number, MAXNDXSIZE, 3106 MSG_ORIG(MSG_FMT_INTEGER), _cnt); 3107 dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS1), number, 3108 EC_WORD(ndx)); 3109 bkts += _cnt; 3110 cnt += (Word)(ndx * _cnt); 3111 } 3112 if (cnt) { 3113 (void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 3114 bkts); 3115 dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS2), number, 3116 EC_WORD(cnt)); 3117 } 3118 } 3119 3120 static void 3121 group(Cache *cache, Word shnum, const char *file, uint_t flags) 3122 { 3123 Word scnt; 3124 3125 for (scnt = 1; scnt < shnum; scnt++) { 3126 Cache *_cache = &cache[scnt]; 3127 Shdr *shdr = _cache->c_shdr; 3128 Word *grpdata, gcnt, grpcnt, symnum, unknown; 3129 Cache *symsec, *strsec; 3130 Sym *syms, *sym; 3131 char flgstrbuf[MSG_GRP_COMDAT_SIZE + 10]; 3132 3133 if (shdr->sh_type != SHT_GROUP) 3134 continue; 3135 if (!match(MATCH_F_ALL, _cache->c_name, scnt, shdr->sh_type)) 3136 continue; 3137 if ((_cache->c_data == NULL) || 3138 ((grpdata = (Word *)_cache->c_data->d_buf) == NULL)) 3139 continue; 3140 grpcnt = shdr->sh_size / sizeof (Word); 3141 3142 /* 3143 * Get the data buffer for the associated symbol table and 3144 * string table. 3145 */ 3146 if (stringtbl(cache, 1, scnt, shnum, file, 3147 &symnum, &symsec, &strsec) == 0) 3148 return; 3149 3150 syms = symsec->c_data->d_buf; 3151 3152 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 3153 dbg_print(0, MSG_INTL(MSG_ELF_SCN_GRP), _cache->c_name); 3154 dbg_print(0, MSG_INTL(MSG_GRP_TITLE)); 3155 3156 /* 3157 * The first element of the group defines the group. The 3158 * associated symbol is defined by the sh_link field. 3159 */ 3160 if ((shdr->sh_info == SHN_UNDEF) || (shdr->sh_info > symnum)) { 3161 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 3162 file, _cache->c_name, EC_WORD(shdr->sh_info)); 3163 return; 3164 } 3165 3166 (void) strcpy(flgstrbuf, MSG_ORIG(MSG_STR_OSQBRKT)); 3167 if (grpdata[0] & GRP_COMDAT) { 3168 (void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_COMDAT)); 3169 } 3170 if ((unknown = (grpdata[0] & ~GRP_COMDAT)) != 0) { 3171 size_t len = strlen(flgstrbuf); 3172 3173 (void) snprintf(&flgstrbuf[len], 3174 (MSG_GRP_COMDAT_SIZE + 10 - len), 3175 MSG_ORIG(MSG_GRP_UNKNOWN), unknown); 3176 } 3177 (void) strcat(flgstrbuf, MSG_ORIG(MSG_STR_CSQBRKT)); 3178 sym = (Sym *)(syms + shdr->sh_info); 3179 3180 dbg_print(0, MSG_INTL(MSG_GRP_SIGNATURE), flgstrbuf, 3181 demangle(string(_cache, 0, strsec, file, sym->st_name), 3182 flags)); 3183 3184 for (gcnt = 1; gcnt < grpcnt; gcnt++) { 3185 char index[MAXNDXSIZE]; 3186 const char *name; 3187 3188 (void) snprintf(index, MAXNDXSIZE, 3189 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(gcnt)); 3190 3191 if (grpdata[gcnt] >= shnum) 3192 name = MSG_INTL(MSG_GRP_INVALSCN); 3193 else 3194 name = cache[grpdata[gcnt]].c_name; 3195 3196 (void) printf(MSG_ORIG(MSG_GRP_ENTRY), index, name, 3197 EC_XWORD(grpdata[gcnt])); 3198 } 3199 } 3200 } 3201 3202 static void 3203 got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, uint_t flags) 3204 { 3205 Cache *gotcache = NULL, *symtab = NULL; 3206 Addr gotbgn, gotend; 3207 Shdr *gotshdr; 3208 Word cnt, gotents, gotndx; 3209 size_t gentsize; 3210 Got_info *gottable; 3211 char *gotdata; 3212 Sym *gotsym; 3213 Xword gotsymaddr; 3214 uint_t sys_encoding; 3215 3216 /* 3217 * First, find the got. 3218 */ 3219 for (cnt = 1; cnt < shnum; cnt++) { 3220 if (strncmp(cache[cnt].c_name, MSG_ORIG(MSG_ELF_GOT), 3221 MSG_ELF_GOT_SIZE) == 0) { 3222 gotcache = &cache[cnt]; 3223 break; 3224 } 3225 } 3226 if (gotcache == NULL) 3227 return; 3228 3229 /* 3230 * A got section within a relocatable object is suspicious. 3231 */ 3232 if (ehdr->e_type == ET_REL) { 3233 (void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file, 3234 gotcache->c_name); 3235 } 3236 3237 gotshdr = gotcache->c_shdr; 3238 if (gotshdr->sh_size == 0) { 3239 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 3240 file, gotcache->c_name); 3241 return; 3242 } 3243 3244 gotbgn = gotshdr->sh_addr; 3245 gotend = gotbgn + gotshdr->sh_size; 3246 3247 /* 3248 * Some architectures don't properly set the sh_entsize for the GOT 3249 * table. If it's not set, default to a size of a pointer. 3250 */ 3251 if ((gentsize = gotshdr->sh_entsize) == 0) 3252 gentsize = sizeof (Xword); 3253 3254 if (gotcache->c_data == NULL) 3255 return; 3256 3257 /* LINTED */ 3258 gotents = (Word)(gotshdr->sh_size / gentsize); 3259 gotdata = gotcache->c_data->d_buf; 3260 3261 if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) { 3262 int err = errno; 3263 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), file, 3264 strerror(err)); 3265 return; 3266 } 3267 3268 /* 3269 * Now we scan through all the sections looking for any relocations 3270 * that may be against the GOT. Since these may not be isolated to a 3271 * .rel[a].got section we check them all. 3272 * While scanning sections save the symbol table entry (a symtab 3273 * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_. 3274 */ 3275 for (cnt = 1; cnt < shnum; cnt++) { 3276 Word type, symnum; 3277 Xword relndx, relnum, relsize; 3278 void *rels; 3279 Sym *syms; 3280 Cache *symsec, *strsec; 3281 Cache *_cache = &cache[cnt]; 3282 Shdr *shdr; 3283 3284 shdr = _cache->c_shdr; 3285 type = shdr->sh_type; 3286 3287 if ((symtab == 0) && (type == SHT_DYNSYM)) { 3288 symtab = _cache; 3289 continue; 3290 } 3291 if (type == SHT_SYMTAB) { 3292 symtab = _cache; 3293 continue; 3294 } 3295 if ((type != SHT_RELA) && (type != SHT_REL)) 3296 continue; 3297 3298 /* 3299 * Decide entry size. 3300 */ 3301 if (((relsize = shdr->sh_entsize) == 0) || 3302 (relsize > shdr->sh_size)) { 3303 if (type == SHT_RELA) 3304 relsize = sizeof (Rela); 3305 else 3306 relsize = sizeof (Rel); 3307 } 3308 3309 /* 3310 * Determine the number of relocations available. 3311 */ 3312 if (shdr->sh_size == 0) { 3313 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 3314 file, _cache->c_name); 3315 continue; 3316 } 3317 if (_cache->c_data == NULL) 3318 continue; 3319 3320 rels = _cache->c_data->d_buf; 3321 relnum = shdr->sh_size / relsize; 3322 3323 /* 3324 * Get the data buffer for the associated symbol table and 3325 * string table. 3326 */ 3327 if (stringtbl(cache, 1, cnt, shnum, file, 3328 &symnum, &symsec, &strsec) == 0) 3329 continue; 3330 3331 syms = symsec->c_data->d_buf; 3332 3333 /* 3334 * Loop through the relocation entries. 3335 */ 3336 for (relndx = 0; relndx < relnum; relndx++, 3337 rels = (void *)((char *)rels + relsize)) { 3338 char section[BUFSIZ]; 3339 Addr offset; 3340 Got_info *gip; 3341 Word symndx, reltype; 3342 Rela *rela; 3343 Rel *rel; 3344 3345 /* 3346 * Unravel the relocation. 3347 */ 3348 if (type == SHT_RELA) { 3349 rela = (Rela *)rels; 3350 symndx = ELF_R_SYM(rela->r_info); 3351 reltype = ELF_R_TYPE(rela->r_info, 3352 ehdr->e_machine); 3353 offset = rela->r_offset; 3354 } else { 3355 rel = (Rel *)rels; 3356 symndx = ELF_R_SYM(rel->r_info); 3357 reltype = ELF_R_TYPE(rel->r_info, 3358 ehdr->e_machine); 3359 offset = rel->r_offset; 3360 } 3361 3362 /* 3363 * Only pay attention to relocations against the GOT. 3364 */ 3365 if ((offset < gotbgn) || (offset >= gotend)) 3366 continue; 3367 3368 /* LINTED */ 3369 gotndx = (Word)((offset - gotbgn) / 3370 gotshdr->sh_entsize); 3371 gip = &gottable[gotndx]; 3372 3373 if (gip->g_reltype != 0) { 3374 (void) fprintf(stderr, 3375 MSG_INTL(MSG_GOT_MULTIPLE), file, 3376 EC_WORD(gotndx), EC_ADDR(offset)); 3377 continue; 3378 } 3379 3380 if (symndx) 3381 gip->g_symname = relsymname(cache, _cache, 3382 strsec, symndx, symnum, relndx, syms, 3383 section, BUFSIZ, file, flags); 3384 gip->g_reltype = reltype; 3385 gip->g_rel = rels; 3386 } 3387 } 3388 3389 if (symlookup(MSG_ORIG(MSG_SYM_GOT), cache, shnum, &gotsym, symtab, 3390 file)) 3391 gotsymaddr = gotsym->st_value; 3392 else 3393 gotsymaddr = gotbgn; 3394 3395 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 3396 dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name); 3397 Elf_got_title(0); 3398 3399 sys_encoding = _elf_sys_encoding(); 3400 for (gotndx = 0; gotndx < gotents; gotndx++) { 3401 Got_info *gip; 3402 Sword gindex; 3403 Addr gaddr; 3404 Xword gotentry; 3405 3406 gip = &gottable[gotndx]; 3407 3408 gaddr = gotbgn + (gotndx * gentsize); 3409 gindex = (Sword)(gaddr - gotsymaddr) / (Sword)gentsize; 3410 3411 if (gentsize == sizeof (Word)) 3412 /* LINTED */ 3413 gotentry = (Xword)(*((Word *)(gotdata) + gotndx)); 3414 else 3415 /* LINTED */ 3416 gotentry = *((Xword *)(gotdata) + gotndx); 3417 3418 Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine, 3419 ehdr->e_ident[EI_DATA], sys_encoding, 3420 gip->g_reltype, gip->g_rel, gip->g_symname); 3421 } 3422 free(gottable); 3423 } 3424 3425 void 3426 checksum(Elf *elf) 3427 { 3428 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 3429 dbg_print(0, MSG_INTL(MSG_STR_CHECKSUM), elf_checksum(elf)); 3430 } 3431 3432 /* 3433 * This variable is used by regular() to communicate the address of 3434 * the section header cache to sort_shdr_ndx_arr(). Unfortunately, 3435 * the qsort() interface does not include a userdata argument by which 3436 * such arbitrary data can be passed, so we are stuck using global data. 3437 */ 3438 static Cache *sort_shdr_ndx_arr_cache; 3439 3440 3441 /* 3442 * Used with qsort() to sort the section indices so that they can be 3443 * used to access the section headers in order of increasing data offset. 3444 * 3445 * entry: 3446 * sort_shdr_ndx_arr_cache - Contains address of 3447 * section header cache. 3448 * v1, v2 - Point at elements of sort_shdr_bits array to be compared. 3449 * 3450 * exit: 3451 * Returns -1 (less than), 0 (equal) or 1 (greater than). 3452 */ 3453 static int 3454 sort_shdr_ndx_arr(const void *v1, const void *v2) 3455 { 3456 Cache *cache1 = sort_shdr_ndx_arr_cache + *((size_t *)v1); 3457 Cache *cache2 = sort_shdr_ndx_arr_cache + *((size_t *)v2); 3458 3459 if (cache1->c_shdr->sh_offset < cache2->c_shdr->sh_offset) 3460 return (-1); 3461 3462 if (cache1->c_shdr->sh_offset > cache2->c_shdr->sh_offset) 3463 return (1); 3464 3465 return (0); 3466 } 3467 3468 3469 static int 3470 shdr_cache(const char *file, Elf *elf, Ehdr *ehdr, size_t shstrndx, 3471 size_t shnum, Cache **cache_ret) 3472 { 3473 Elf_Scn *scn; 3474 Elf_Data *data; 3475 size_t ndx; 3476 Shdr *nameshdr; 3477 char *names = 0; 3478 Cache *cache, *_cache; 3479 size_t *shdr_ndx_arr, shdr_ndx_arr_cnt; 3480 3481 3482 /* 3483 * Obtain the .shstrtab data buffer to provide the required section 3484 * name strings. 3485 */ 3486 if (shstrndx == SHN_UNDEF) { 3487 /* 3488 * It is rare, but legal, for an object to lack a 3489 * header string table section. 3490 */ 3491 names = NULL; 3492 (void) fprintf(stderr, MSG_INTL(MSG_ERR_NOSHSTRSEC), file); 3493 } else if ((scn = elf_getscn(elf, shstrndx)) == NULL) { 3494 failure(file, MSG_ORIG(MSG_ELF_GETSCN)); 3495 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR), 3496 EC_XWORD(shstrndx)); 3497 3498 } else if ((data = elf_getdata(scn, NULL)) == NULL) { 3499 failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 3500 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA), 3501 EC_XWORD(shstrndx)); 3502 3503 } else if ((nameshdr = elf_getshdr(scn)) == NULL) { 3504 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 3505 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 3506 EC_WORD(elf_ndxscn(scn))); 3507 3508 } else if ((names = data->d_buf) == 0) 3509 (void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file); 3510 3511 /* 3512 * Allocate a cache to maintain a descriptor for each section. 3513 */ 3514 if ((*cache_ret = cache = malloc(shnum * sizeof (Cache))) == NULL) { 3515 int err = errno; 3516 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 3517 file, strerror(err)); 3518 return (0); 3519 } 3520 3521 *cache = cache_init; 3522 _cache = cache; 3523 _cache++; 3524 3525 /* 3526 * Allocate an array that will hold the section index for 3527 * each section that has data in the ELF file: 3528 * 3529 * - Is not a NOBITS section 3530 * - Data has non-zero length 3531 * 3532 * Note that shnum is an upper bound on the size required. It 3533 * is likely that we won't use a few of these array elements. 3534 * Allocating a modest amount of extra memory in this case means 3535 * that we can avoid an extra loop to count the number of needed 3536 * items, and can fill this array immediately in the first loop 3537 * below. 3538 */ 3539 if ((shdr_ndx_arr = malloc(shnum * sizeof (*shdr_ndx_arr))) == NULL) { 3540 int err = errno; 3541 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 3542 file, strerror(err)); 3543 return (0); 3544 } 3545 shdr_ndx_arr_cnt = 0; 3546 3547 /* 3548 * Traverse the sections of the file. This gathering of data is 3549 * carried out in two passes. First, the section headers are captured 3550 * and the section header names are evaluated. A verification pass is 3551 * then carried out over the section information. Files have been 3552 * known to exhibit overlapping (and hence erroneous) section header 3553 * information. 3554 * 3555 * Finally, the data for each section is obtained. This processing is 3556 * carried out after section verification because should any section 3557 * header overlap occur, and a file needs translating (ie. xlate'ing 3558 * information from a non-native architecture file), then the process 3559 * of translation can corrupt the section header information. Of 3560 * course, if there is any section overlap, the data related to the 3561 * sections is going to be compromised. However, it is the translation 3562 * of this data that has caused problems with elfdump()'s ability to 3563 * extract the data. 3564 */ 3565 for (ndx = 1, scn = NULL; scn = elf_nextscn(elf, scn); 3566 ndx++, _cache++) { 3567 char scnndxnm[100]; 3568 3569 _cache->c_ndx = ndx; 3570 _cache->c_scn = scn; 3571 3572 if ((_cache->c_shdr = elf_getshdr(scn)) == NULL) { 3573 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 3574 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 3575 EC_WORD(elf_ndxscn(scn))); 3576 } 3577 3578 /* 3579 * If this section has data in the file, include it in 3580 * the array of sections to check for address overlap. 3581 */ 3582 if ((_cache->c_shdr->sh_size != 0) && 3583 (_cache->c_shdr->sh_type != SHT_NOBITS)) 3584 shdr_ndx_arr[shdr_ndx_arr_cnt++] = ndx; 3585 3586 /* 3587 * If a shstrtab exists, assign the section name. 3588 */ 3589 if (names && _cache->c_shdr) { 3590 if (_cache->c_shdr->sh_name && 3591 /* LINTED */ 3592 (nameshdr->sh_size > _cache->c_shdr->sh_name)) { 3593 _cache->c_name = 3594 names + _cache->c_shdr->sh_name; 3595 continue; 3596 } 3597 3598 /* 3599 * Generate an error if the section name index is zero 3600 * or exceeds the shstrtab data. Fall through to 3601 * fabricate a section name. 3602 */ 3603 if ((_cache->c_shdr->sh_name == 0) || 3604 /* LINTED */ 3605 (nameshdr->sh_size <= _cache->c_shdr->sh_name)) { 3606 (void) fprintf(stderr, 3607 MSG_INTL(MSG_ERR_BADSHNAME), file, 3608 EC_WORD(ndx), 3609 EC_XWORD(_cache->c_shdr->sh_name)); 3610 } 3611 } 3612 3613 /* 3614 * If there exists no shstrtab data, or a section header has no 3615 * name (an invalid index of 0), then compose a name for the 3616 * section. 3617 */ 3618 (void) snprintf(scnndxnm, sizeof (scnndxnm), 3619 MSG_INTL(MSG_FMT_SCNNDX), ndx); 3620 3621 if ((_cache->c_name = malloc(strlen(scnndxnm) + 1)) == NULL) { 3622 int err = errno; 3623 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 3624 file, strerror(err)); 3625 return (0); 3626 } 3627 (void) strcpy(_cache->c_name, scnndxnm); 3628 } 3629 3630 /* 3631 * Having collected all the sections, validate their address range. 3632 * Cases have existed where the section information has been invalid. 3633 * This can lead to all sorts of other, hard to diagnose errors, as 3634 * each section is processed individually (ie. with elf_getdata()). 3635 * Here, we carry out some address comparisons to catch a family of 3636 * overlapping memory issues we have observed (likely, there are others 3637 * that we have yet to discover). 3638 * 3639 * Note, should any memory overlap occur, obtaining any additional 3640 * data from the file is questionable. However, it might still be 3641 * possible to inspect the ELF header, Programs headers, or individual 3642 * sections, so rather than bailing on an error condition, continue 3643 * processing to see if any data can be salvaged. 3644 */ 3645 if (shdr_ndx_arr_cnt > 1) { 3646 sort_shdr_ndx_arr_cache = cache; 3647 qsort(shdr_ndx_arr, shdr_ndx_arr_cnt, 3648 sizeof (*shdr_ndx_arr), sort_shdr_ndx_arr); 3649 } 3650 for (ndx = 0; ndx < shdr_ndx_arr_cnt; ndx++) { 3651 Cache *_cache = cache + shdr_ndx_arr[ndx]; 3652 Shdr *shdr = _cache->c_shdr; 3653 Off bgn1, bgn = shdr->sh_offset; 3654 Off end1, end = shdr->sh_offset + shdr->sh_size; 3655 size_t ndx1; 3656 3657 /* 3658 * Check the section against all following ones, reporting 3659 * any overlaps. Since we've sorted the sections by offset, 3660 * we can stop after the first comparison that fails. There 3661 * are no overlaps in a properly formed ELF file, in which 3662 * case this algorithm runs in O(n) time. This will degenerate 3663 * to O(n^2) for a completely broken file. Such a file is 3664 * (1) highly unlikely, and (2) unusable, so it is reasonable 3665 * for the analysis to take longer. 3666 */ 3667 for (ndx1 = ndx + 1; ndx1 < shdr_ndx_arr_cnt; ndx1++) { 3668 Cache *_cache1 = cache + shdr_ndx_arr[ndx1]; 3669 Shdr *shdr1 = _cache1->c_shdr; 3670 3671 bgn1 = shdr1->sh_offset; 3672 end1 = shdr1->sh_offset + shdr1->sh_size; 3673 3674 if (((bgn1 <= bgn) && (end1 > bgn)) || 3675 ((bgn1 < end) && (end1 >= end))) { 3676 (void) fprintf(stderr, 3677 MSG_INTL(MSG_ERR_SECMEMOVER), file, 3678 EC_WORD(elf_ndxscn(_cache->c_scn)), 3679 _cache->c_name, EC_OFF(bgn), EC_OFF(end), 3680 EC_WORD(elf_ndxscn(_cache1->c_scn)), 3681 _cache1->c_name, EC_OFF(bgn1), 3682 EC_OFF(end1)); 3683 } else { /* No overlap, so can stop */ 3684 break; 3685 } 3686 } 3687 3688 /* 3689 * In addition to checking for sections overlapping 3690 * each other (done above), we should also make sure 3691 * the section doesn't overlap the section header array. 3692 */ 3693 bgn1 = ehdr->e_shoff; 3694 end1 = ehdr->e_shoff + (ehdr->e_shentsize * ehdr->e_shnum); 3695 3696 if (((bgn1 <= bgn) && (end1 > bgn)) || 3697 ((bgn1 < end) && (end1 >= end))) { 3698 (void) fprintf(stderr, 3699 MSG_INTL(MSG_ERR_SHDRMEMOVER), file, EC_OFF(bgn1), 3700 EC_OFF(end1), 3701 EC_WORD(elf_ndxscn(_cache->c_scn)), 3702 _cache->c_name, EC_OFF(bgn), EC_OFF(end)); 3703 } 3704 } 3705 3706 /* 3707 * Obtain the data for each section. 3708 */ 3709 for (ndx = 1; ndx < shnum; ndx++) { 3710 Cache *_cache = &cache[ndx]; 3711 Elf_Scn *scn = _cache->c_scn; 3712 3713 if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) { 3714 failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 3715 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA), 3716 EC_WORD(elf_ndxscn(scn))); 3717 } 3718 } 3719 3720 return (1); 3721 } 3722 3723 3724 3725 int 3726 regular(const char *file, int fd, Elf *elf, uint_t flags, 3727 const char *wname, int wfd) 3728 { 3729 Elf_Scn *scn; 3730 Ehdr *ehdr; 3731 size_t ndx, shstrndx, shnum, phnum; 3732 Shdr *shdr; 3733 Cache *cache; 3734 VERSYM_STATE versym; 3735 int ret = 0; 3736 int addr_align; 3737 3738 if ((ehdr = elf_getehdr(elf)) == NULL) { 3739 failure(file, MSG_ORIG(MSG_ELF_GETEHDR)); 3740 return (ret); 3741 } 3742 3743 if (elf_getshnum(elf, &shnum) == 0) { 3744 failure(file, MSG_ORIG(MSG_ELF_GETSHNUM)); 3745 return (ret); 3746 } 3747 3748 if (elf_getshstrndx(elf, &shstrndx) == 0) { 3749 failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX)); 3750 return (ret); 3751 } 3752 3753 if (elf_getphnum(elf, &phnum) == 0) { 3754 failure(file, MSG_ORIG(MSG_ELF_GETPHNUM)); 3755 return (ret); 3756 } 3757 /* 3758 * If the user requested section headers derived from the 3759 * program headers (-P option) and this file doesn't have 3760 * any program headers (i.e. ET_REL), then we can't do it. 3761 */ 3762 if ((phnum == 0) && (flags & FLG_CTL_FAKESHDR)) { 3763 (void) fprintf(stderr, MSG_INTL(MSG_ERR_PNEEDSPH), file); 3764 return (ret); 3765 } 3766 3767 3768 if ((scn = elf_getscn(elf, 0)) != NULL) { 3769 if ((shdr = elf_getshdr(scn)) == NULL) { 3770 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 3771 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0); 3772 return (ret); 3773 } 3774 } else 3775 shdr = 0; 3776 3777 /* 3778 * Print the elf header. 3779 */ 3780 if (flags & FLG_SHOW_EHDR) 3781 Elf_ehdr(0, ehdr, shdr); 3782 3783 /* 3784 * If the section headers or program headers have inadequate 3785 * alignment for the class of object, print a warning. libelf 3786 * can handle such files, but programs that use them can crash 3787 * when they dereference unaligned items. 3788 * 3789 * Note that the AMD64 ABI, although it is a 64-bit architecture, 3790 * allows access to data types smaller than 128-bits to be on 3791 * word alignment. 3792 */ 3793 if (ehdr->e_machine == EM_AMD64) 3794 addr_align = sizeof (Word); 3795 else 3796 addr_align = sizeof (Addr); 3797 3798 if (ehdr->e_phoff & (addr_align - 1)) 3799 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADPHDRALIGN), file); 3800 if (ehdr->e_shoff & (addr_align - 1)) 3801 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHDRALIGN), file); 3802 3803 /* 3804 * Print the program headers. 3805 */ 3806 if ((flags & FLG_SHOW_PHDR) && (phnum != 0)) { 3807 Phdr *phdr; 3808 3809 if ((phdr = elf_getphdr(elf)) == NULL) { 3810 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 3811 return (ret); 3812 } 3813 3814 for (ndx = 0; ndx < phnum; phdr++, ndx++) { 3815 if (!match(MATCH_F_PHDR| MATCH_F_NDX | MATCH_F_TYPE, 3816 NULL, ndx, phdr->p_type)) 3817 continue; 3818 3819 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 3820 dbg_print(0, MSG_INTL(MSG_ELF_PHDR), EC_WORD(ndx)); 3821 Elf_phdr(0, ehdr->e_machine, phdr); 3822 } 3823 } 3824 3825 /* 3826 * If we have flag bits set that explicitly require a show or calc 3827 * operation, but none of them require the section headers, then 3828 * we are done and can return now. 3829 */ 3830 if (((flags & (FLG_MASK_SHOW | FLG_MASK_CALC)) != 0) && 3831 ((flags & (FLG_MASK_SHOW_SHDR | FLG_MASK_CALC_SHDR)) == 0)) 3832 return (ret); 3833 3834 /* 3835 * If there are no section headers, then resort to synthesizing 3836 * section headers from the program headers. This is normally 3837 * only done by explicit request, but in this case there's no 3838 * reason not to go ahead, since the alternative is simply to quit. 3839 */ 3840 if ((shnum <= 1) && ((flags & FLG_CTL_FAKESHDR) == 0)) { 3841 (void) fprintf(stderr, MSG_INTL(MSG_ERR_NOSHDR), file); 3842 flags |= FLG_CTL_FAKESHDR; 3843 } 3844 3845 /* 3846 * Generate a cache of section headers and related information 3847 * for use by the rest of elfdump. If requested (or the file 3848 * contains no section headers), we generate a fake set of 3849 * headers from the information accessible from the program headers. 3850 * Otherwise, we use the real section headers contained in the file. 3851 */ 3852 3853 if (flags & FLG_CTL_FAKESHDR) { 3854 if (fake_shdr_cache(file, fd, elf, ehdr, &cache, &shnum) == 0) 3855 return (ret); 3856 } else { 3857 if (shdr_cache(file, elf, ehdr, shstrndx, shnum, &cache) == 0) 3858 return (ret); 3859 } 3860 3861 /* 3862 * Everything from this point on requires section headers. 3863 * If we have no section headers, there is no reason to continue. 3864 */ 3865 if (shnum <= 1) 3866 goto done; 3867 3868 /* 3869 * If -w was specified, find and write out the section(s) data. 3870 */ 3871 if (wfd) { 3872 for (ndx = 1; ndx < shnum; ndx++) { 3873 Cache *_cache = &cache[ndx]; 3874 3875 if (match(MATCH_F_STRICT | MATCH_F_ALL, _cache->c_name, 3876 ndx, _cache->c_shdr->sh_type) && 3877 _cache->c_data && _cache->c_data->d_buf) { 3878 if (write(wfd, _cache->c_data->d_buf, 3879 _cache->c_data->d_size) != 3880 _cache->c_data->d_size) { 3881 int err = errno; 3882 (void) fprintf(stderr, 3883 MSG_INTL(MSG_ERR_WRITE), wname, 3884 strerror(err)); 3885 /* 3886 * Return an exit status of 1, because 3887 * the failure is not related to the 3888 * ELF file, but by system resources. 3889 */ 3890 ret = 1; 3891 goto done; 3892 } 3893 } 3894 } 3895 } 3896 3897 /* 3898 * If we have no flag bits set that explicitly require a show or calc 3899 * operation, but match options (-I, -N, -T) were used, then run 3900 * through the section headers and see if we can't deduce show flags 3901 * from the match options given. 3902 * 3903 * We don't do this if -w was specified, because (-I, -N, -T) used 3904 * with -w in lieu of some other option is supposed to be quiet. 3905 */ 3906 if ((wfd == 0) && (flags & FLG_CTL_MATCH) && 3907 ((flags & (FLG_MASK_SHOW | FLG_MASK_CALC)) == 0)) { 3908 for (ndx = 1; ndx < shnum; ndx++) { 3909 Cache *_cache = &cache[ndx]; 3910 3911 if (!match(MATCH_F_STRICT | MATCH_F_ALL, _cache->c_name, 3912 ndx, _cache->c_shdr->sh_type)) 3913 continue; 3914 3915 switch (_cache->c_shdr->sh_type) { 3916 case SHT_PROGBITS: 3917 /* 3918 * Heuristic time: It is usually bad form 3919 * to assume that specific section names 3920 * have a given meaning. However, the 3921 * ELF ABI does specify a few such names. Try 3922 * to match them: 3923 */ 3924 if (strcmp(_cache->c_name, 3925 MSG_ORIG(MSG_ELF_INTERP)) == 0) 3926 flags |= FLG_SHOW_INTERP; 3927 else if (strcmp(_cache->c_name, 3928 MSG_ORIG(MSG_ELF_GOT)) == 0) 3929 flags |= FLG_SHOW_GOT; 3930 break; 3931 3932 case SHT_SYMTAB: 3933 case SHT_DYNSYM: 3934 case SHT_SUNW_LDYNSYM: 3935 case SHT_SUNW_versym: 3936 case SHT_SYMTAB_SHNDX: 3937 flags |= FLG_SHOW_SYMBOLS; 3938 break; 3939 3940 case SHT_RELA: 3941 case SHT_REL: 3942 flags |= FLG_SHOW_RELOC; 3943 break; 3944 3945 case SHT_HASH: 3946 flags |= FLG_SHOW_HASH; 3947 break; 3948 3949 case SHT_DYNAMIC: 3950 flags |= FLG_SHOW_DYNAMIC; 3951 break; 3952 3953 case SHT_NOTE: 3954 flags |= FLG_SHOW_NOTE; 3955 break; 3956 3957 case SHT_GROUP: 3958 flags |= FLG_SHOW_GROUP; 3959 break; 3960 3961 case SHT_SUNW_symsort: 3962 case SHT_SUNW_tlssort: 3963 flags |= FLG_SHOW_SORT; 3964 break; 3965 3966 case SHT_SUNW_cap: 3967 flags |= FLG_SHOW_CAP; 3968 break; 3969 3970 case SHT_SUNW_move: 3971 flags |= FLG_SHOW_MOVE; 3972 break; 3973 3974 case SHT_SUNW_syminfo: 3975 flags |= FLG_SHOW_SYMINFO; 3976 break; 3977 3978 case SHT_SUNW_verdef: 3979 case SHT_SUNW_verneed: 3980 flags |= FLG_SHOW_VERSIONS; 3981 break; 3982 3983 case SHT_AMD64_UNWIND: 3984 flags |= FLG_SHOW_UNWIND; 3985 break; 3986 } 3987 } 3988 } 3989 3990 3991 if (flags & FLG_SHOW_SHDR) 3992 sections(file, cache, shnum, ehdr); 3993 3994 if (flags & FLG_SHOW_INTERP) 3995 interp(file, cache, shnum, phnum, elf); 3996 3997 versions(cache, shnum, file, flags, &versym); 3998 3999 if (flags & FLG_SHOW_SYMBOLS) 4000 symbols(cache, shnum, ehdr, &versym, file, flags); 4001 4002 if (flags & FLG_SHOW_SORT) 4003 sunw_sort(cache, shnum, ehdr, &versym, file, flags); 4004 4005 if (flags & FLG_SHOW_HASH) 4006 hash(cache, shnum, file, flags); 4007 4008 if (flags & FLG_SHOW_GOT) 4009 got(cache, shnum, ehdr, file, flags); 4010 4011 if (flags & FLG_SHOW_GROUP) 4012 group(cache, shnum, file, flags); 4013 4014 if (flags & FLG_SHOW_SYMINFO) 4015 syminfo(cache, shnum, file); 4016 4017 if (flags & FLG_SHOW_RELOC) 4018 reloc(cache, shnum, ehdr, file, flags); 4019 4020 if (flags & FLG_SHOW_DYNAMIC) 4021 dynamic(cache, shnum, ehdr, file); 4022 4023 if (flags & FLG_SHOW_NOTE) 4024 note(cache, shnum, file); 4025 4026 if (flags & FLG_SHOW_MOVE) 4027 move(cache, shnum, file, flags); 4028 4029 if (flags & FLG_CALC_CHECKSUM) 4030 checksum(elf); 4031 4032 if (flags & FLG_SHOW_CAP) 4033 cap(file, cache, shnum, phnum, ehdr, elf); 4034 4035 if (flags & FLG_SHOW_UNWIND) 4036 unwind(cache, shnum, phnum, ehdr, file, elf); 4037 4038 4039 /* Release the memory used to cache section headers */ 4040 done: 4041 if (flags & FLG_CTL_FAKESHDR) 4042 fake_shdr_cache_free(cache, shnum); 4043 else 4044 free(cache); 4045 4046 return (ret); 4047 } 4048