1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Dump an elf file. 30 */ 31 #include <machdep.h> 32 #include <sys/elf_386.h> 33 #include <sys/elf_amd64.h> 34 #include <sys/elf_SPARC.h> 35 #include <dwarf.h> 36 #include <unistd.h> 37 #include <errno.h> 38 #include <strings.h> 39 #include <debug.h> 40 #include <conv.h> 41 #include <msg.h> 42 #include <_elfdump.h> 43 44 45 46 /* 47 * VERSYM_STATE is used to maintain information about the VERSYM section 48 * in the object being analyzed. It is filled in by versions(), and used 49 * by init_symtbl_state() when displaying symbol information. 50 * 51 * 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_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(0, secname, seccnt)) 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 Word cnt; 437 Phdr *uphdr = 0; 438 439 /* 440 * For the moment - UNWIND is only relevant for a AMD64 object. 441 */ 442 if (ehdr->e_machine != EM_AMD64) 443 return; 444 445 if (phnum) 446 uphdr = getphdr(phnum, PT_SUNW_UNWIND, file, elf); 447 448 for (cnt = 1; cnt < shnum; cnt++) { 449 Cache *_cache = &cache[cnt]; 450 Shdr *shdr = _cache->c_shdr; 451 uchar_t *data; 452 size_t datasize; 453 uint64_t off, ndx, frame_ptr, fde_cnt, tabndx; 454 uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc; 455 456 /* 457 * AMD64 - this is a strmcp() just to find the gcc produced 458 * sections. Soon gcc should be setting the section type - and 459 * we'll not need this strcmp(). 460 */ 461 if ((shdr->sh_type != SHT_AMD64_UNWIND) && 462 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM), 463 MSG_SCN_FRM_SIZE) != 0) && 464 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 465 MSG_SCN_FRMHDR_SIZE) != 0)) 466 continue; 467 468 if (!match(0, _cache->c_name, cnt)) 469 continue; 470 471 if (_cache->c_data == NULL) 472 continue; 473 474 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 475 dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name); 476 477 data = (uchar_t *)(_cache->c_data->d_buf); 478 datasize = _cache->c_data->d_size; 479 off = 0; 480 481 /* 482 * Is this a .eh_frame_hdr 483 */ 484 if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) || 485 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 486 MSG_SCN_FRMHDR_SIZE) == 0)) { 487 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), EC_XWORD(frame_ptr)); 503 504 fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc, 505 ehdr->e_ident, shdr->sh_addr + ndx); 506 507 dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC), 508 conv_dwarf_ehe(fde_cnt_enc), EC_XWORD(fde_cnt)); 509 dbg_print(0, MSG_ORIG(MSG_UNW_TABENC), 510 conv_dwarf_ehe(table_enc)); 511 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1)); 512 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2)); 513 514 for (tabndx = 0; tabndx < fde_cnt; tabndx++) { 515 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT), 516 EC_XWORD(dwarf_ehe_extract(data, &ndx, 517 table_enc, ehdr->e_ident, shdr->sh_addr)), 518 EC_XWORD(dwarf_ehe_extract(data, &ndx, 519 table_enc, ehdr->e_ident, shdr->sh_addr))); 520 } 521 continue; 522 } 523 524 /* 525 * Walk the Eh_frame's 526 */ 527 while (off < datasize) { 528 uint_t cieid, cielength, cieversion; 529 uint_t cieretaddr; 530 int cieRflag, cieLflag, ciePflag, cieZflag; 531 uint_t cieaugndx, length, id; 532 uint64_t ciecalign, ciedalign; 533 char *cieaugstr; 534 535 ndx = 0; 536 /* 537 * extract length in lsb format 538 */ 539 length = LSB32EXTRACT(data + off + ndx); 540 ndx += 4; 541 542 /* 543 * extract CIE id in lsb format 544 */ 545 id = LSB32EXTRACT(data + off + ndx); 546 ndx += 4; 547 548 /* 549 * A CIE record has a id of '0', otherwise this is a 550 * FDE entry and the 'id' is the CIE pointer. 551 */ 552 if (id == 0) { 553 uint64_t persVal; 554 555 cielength = length; 556 cieid = id; 557 cieLflag = ciePflag = cieRflag = cieZflag = 0; 558 559 dbg_print(0, MSG_ORIG(MSG_UNW_CIE), 560 EC_XWORD(shdr->sh_addr + off)); 561 dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH), 562 cielength, cieid); 563 564 cieversion = data[off + ndx]; 565 ndx += 1; 566 cieaugstr = (char *)(&data[off + ndx]); 567 ndx += strlen(cieaugstr) + 1; 568 569 dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS), 570 cieversion, cieaugstr); 571 572 ciecalign = uleb_extract(&data[off], &ndx); 573 ciedalign = sleb_extract(&data[off], &ndx); 574 cieretaddr = data[off + ndx]; 575 ndx += 1; 576 577 dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN), 578 EC_XWORD(ciecalign), EC_XWORD(ciedalign), 579 cieretaddr); 580 581 if (cieaugstr[0]) 582 dbg_print(0, 583 MSG_ORIG(MSG_UNW_CIEAXVAL)); 584 585 for (cieaugndx = 0; cieaugstr[cieaugndx]; 586 cieaugndx++) { 587 uint_t val; 588 589 switch (cieaugstr[cieaugndx]) { 590 case 'z': 591 val = uleb_extract(&data[off], 592 &ndx); 593 dbg_print(0, 594 MSG_ORIG(MSG_UNW_CIEAXSIZ), 595 val); 596 cieZflag = 1; 597 break; 598 case 'P': 599 ciePflag = data[off + ndx]; 600 ndx += 1; 601 602 persVal = dwarf_ehe_extract( 603 &data[off], &ndx, ciePflag, 604 ehdr->e_ident, 605 shdr->sh_addr + off + ndx); 606 dbg_print(0, 607 MSG_ORIG(MSG_UNW_CIEAXPERS), 608 ciePflag, 609 conv_dwarf_ehe(ciePflag), 610 EC_XWORD(persVal)); 611 break; 612 case 'R': 613 val = data[off + ndx]; 614 ndx += 1; 615 dbg_print(0, 616 MSG_ORIG(MSG_UNW_CIEAXCENC), 617 val, conv_dwarf_ehe(val)); 618 cieRflag = val; 619 break; 620 case 'L': 621 val = data[off + ndx]; 622 ndx += 1; 623 dbg_print(0, 624 MSG_ORIG(MSG_UNW_CIEAXLSDA), 625 val, conv_dwarf_ehe(val)); 626 cieLflag = val; 627 break; 628 default: 629 dbg_print(0, 630 MSG_ORIG(MSG_UNW_CIEAXUNEC), 631 cieaugstr[cieaugndx]); 632 break; 633 } 634 } 635 if ((cielength + 4) > ndx) 636 unwindtbl(&ndx, cielength, data, off, 637 MSG_ORIG(MSG_UNW_CIECFI), 638 MSG_ORIG(MSG_UNW_CIEPRE), 639 MSG_UNW_CIEPRE_SIZE); 640 off += cielength + 4; 641 642 } else { 643 uint_t fdelength = length; 644 int fdecieptr = id; 645 uint64_t fdeinitloc, fdeaddrrange; 646 647 dbg_print(0, MSG_ORIG(MSG_UNW_FDE), 648 EC_XWORD(shdr->sh_addr + off)); 649 dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH), 650 fdelength, fdecieptr); 651 652 fdeinitloc = dwarf_ehe_extract(&data[off], 653 &ndx, cieRflag, ehdr->e_ident, 654 shdr->sh_addr + off + ndx); 655 fdeaddrrange = dwarf_ehe_extract(&data[off], 656 &ndx, (cieRflag & ~DW_EH_PE_pcrel), 657 ehdr->e_ident, 658 shdr->sh_addr + off + ndx); 659 660 dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC), 661 EC_XWORD(fdeinitloc), 662 EC_XWORD(fdeaddrrange)); 663 664 if (cieaugstr[0]) 665 dbg_print(0, 666 MSG_ORIG(MSG_UNW_FDEAXVAL)); 667 if (cieZflag) { 668 uint64_t val; 669 val = uleb_extract(&data[off], &ndx); 670 dbg_print(0, 671 MSG_ORIG(MSG_UNW_FDEAXSIZE), 672 EC_XWORD(val)); 673 if (val & cieLflag) { 674 fdeinitloc = dwarf_ehe_extract( 675 &data[off], &ndx, cieLflag, 676 ehdr->e_ident, 677 shdr->sh_addr + off + ndx); 678 dbg_print(0, 679 MSG_ORIG(MSG_UNW_FDEAXLSDA), 680 EC_XWORD(val)); 681 } 682 } 683 if ((fdelength + 4) > ndx) 684 unwindtbl(&ndx, fdelength, data, off, 685 MSG_ORIG(MSG_UNW_FDECFI), 686 MSG_ORIG(MSG_UNW_FDEPRE), 687 MSG_UNW_FDEPRE_SIZE); 688 off += fdelength + 4; 689 } 690 } 691 } 692 } 693 694 /* 695 * Print the hardware/software capabilities. For executables and shared objects 696 * this should be accompanied with a program header. 697 */ 698 static void 699 cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, 700 Elf *elf) 701 { 702 Word cnt; 703 Shdr *cshdr = 0; 704 Cache *ccache; 705 Off cphdr_off = 0; 706 Xword cphdr_sz; 707 708 /* 709 * Determine if a hardware/software capabilities header exists. 710 */ 711 if (phnum) { 712 Phdr *phdr; 713 714 if ((phdr = elf_getphdr(elf)) == NULL) { 715 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 716 return; 717 } 718 719 for (cnt = 0; cnt < phnum; phdr++, cnt++) { 720 if (phdr->p_type == PT_SUNWCAP) { 721 cphdr_off = phdr->p_offset; 722 cphdr_sz = phdr->p_filesz; 723 break; 724 } 725 } 726 } 727 728 /* 729 * Determine if a hardware/software capabilities section exists. 730 */ 731 for (cnt = 1; cnt < shnum; cnt++) { 732 Cache *_cache = &cache[cnt]; 733 Shdr *shdr = _cache->c_shdr; 734 735 if (shdr->sh_type != SHT_SUNW_cap) 736 continue; 737 738 if (cphdr_off && ((cphdr_off < shdr->sh_offset) || 739 (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size))) 740 continue; 741 742 if (_cache->c_data == NULL) 743 continue; 744 745 ccache = _cache; 746 cshdr = shdr; 747 break; 748 } 749 750 if ((cshdr == 0) && (cphdr_off == 0)) 751 return; 752 753 /* 754 * Print the hardware/software capabilities section. 755 */ 756 if (cshdr) { 757 Word ndx, capn; 758 Cap *cap = (Cap *)ccache->c_data->d_buf; 759 760 if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) { 761 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 762 file, ccache->c_name); 763 return; 764 } 765 766 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 767 dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name); 768 769 Elf_cap_title(0); 770 771 capn = (Word)(cshdr->sh_size / cshdr->sh_entsize); 772 773 for (ndx = 0; ndx < capn; cap++, ndx++) { 774 if (cap->c_tag != CA_SUNW_NULL) 775 Elf_cap_entry(0, cap, ndx, ehdr->e_machine); 776 } 777 } else 778 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file); 779 780 /* 781 * If this object is an executable or shared object, then the 782 * hardware/software capabilities section should have an accompanying 783 * program header. 784 */ 785 if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) { 786 if (cphdr_off == 0) 787 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2), 788 file, ccache->c_name); 789 else if ((cphdr_off != cshdr->sh_offset) || 790 (cphdr_sz != cshdr->sh_size)) 791 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3), 792 file, ccache->c_name); 793 } 794 } 795 796 /* 797 * Print the interpretor. 798 */ 799 static void 800 interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf) 801 { 802 Word cnt; 803 Shdr *ishdr = 0; 804 Cache *icache; 805 Off iphdr_off = 0; 806 Xword iphdr_fsz; 807 808 /* 809 * Determine if an interp header exists. 810 */ 811 if (phnum) { 812 Phdr *phdr; 813 814 if ((phdr = getphdr(phnum, PT_INTERP, file, elf)) != 0) { 815 iphdr_off = phdr->p_offset; 816 iphdr_fsz = phdr->p_filesz; 817 } 818 } 819 820 if (iphdr_off == 0) 821 return; 822 823 /* 824 * Determine if an interp section exists. 825 */ 826 for (cnt = 1; cnt < shnum; cnt++) { 827 Cache *_cache = &cache[cnt]; 828 Shdr *shdr = _cache->c_shdr; 829 830 /* 831 * Scan sections to find a section which contains the PT_INTERP 832 * string. The target section can't be in a NOBITS section. 833 */ 834 if ((shdr->sh_type == SHT_NOBITS) || 835 (iphdr_off < shdr->sh_offset) || 836 (iphdr_off + iphdr_fsz) > (shdr->sh_offset + shdr->sh_size)) 837 continue; 838 839 icache = _cache; 840 ishdr = shdr; 841 break; 842 } 843 844 /* 845 * Print the interpreter string based on the offset defined in the 846 * program header, as this is the offset used by the kernel. 847 */ 848 if (ishdr && icache->c_data) { 849 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 850 dbg_print(0, MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name); 851 dbg_print(0, MSG_ORIG(MSG_FMT_INDENT), 852 (char *)icache->c_data->d_buf + 853 (iphdr_off - ishdr->sh_offset)); 854 } else 855 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file); 856 857 /* 858 * If there are any inconsistences between the program header and 859 * section information, flag them. 860 */ 861 if (ishdr && ((iphdr_off != ishdr->sh_offset) || 862 (iphdr_fsz != ishdr->sh_size))) { 863 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file, 864 icache->c_name); 865 } 866 } 867 868 /* 869 * Print the syminfo section. 870 */ 871 static void 872 syminfo(Cache *cache, Word shnum, const char *file) 873 { 874 Shdr *infoshdr; 875 Syminfo *info; 876 Sym *syms; 877 Dyn *dyns; 878 Word infonum, cnt, ndx, symnum; 879 Cache *infocache = 0, *symsec, *strsec; 880 881 for (cnt = 1; cnt < shnum; cnt++) { 882 if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) { 883 infocache = &cache[cnt]; 884 break; 885 } 886 } 887 if (infocache == 0) 888 return; 889 890 infoshdr = infocache->c_shdr; 891 if ((infoshdr->sh_entsize == 0) || (infoshdr->sh_size == 0)) { 892 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 893 file, infocache->c_name); 894 return; 895 } 896 if (infocache->c_data == NULL) 897 return; 898 899 infonum = (Word)(infoshdr->sh_size / infoshdr->sh_entsize); 900 info = (Syminfo *)infocache->c_data->d_buf; 901 902 /* 903 * Get the data buffer of the associated dynamic section. 904 */ 905 if ((infoshdr->sh_info == 0) || (infoshdr->sh_info >= shnum)) { 906 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 907 file, infocache->c_name, EC_WORD(infoshdr->sh_info)); 908 return; 909 } 910 if (cache[infoshdr->sh_info].c_data == NULL) 911 return; 912 913 dyns = cache[infoshdr->sh_info].c_data->d_buf; 914 if (dyns == 0) { 915 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 916 file, cache[infoshdr->sh_info].c_name); 917 return; 918 } 919 920 /* 921 * Get the data buffer for the associated symbol table and string table. 922 */ 923 if (stringtbl(cache, 1, cnt, shnum, file, 924 &symnum, &symsec, &strsec) == 0) 925 return; 926 927 syms = symsec->c_data->d_buf; 928 929 /* 930 * Loop through the syminfo entries. 931 */ 932 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 933 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMINFO), infocache->c_name); 934 Elf_syminfo_title(0); 935 936 for (ndx = 1, info++; ndx < infonum; ndx++, info++) { 937 Sym *sym; 938 const char *needed = 0, *name; 939 940 if ((info->si_flags == 0) && (info->si_boundto == 0)) 941 continue; 942 943 sym = &syms[ndx]; 944 name = string(infocache, ndx, strsec, file, sym->st_name); 945 946 if (info->si_boundto < SYMINFO_BT_LOWRESERVE) { 947 Dyn *dyn = &dyns[info->si_boundto]; 948 949 needed = string(infocache, info->si_boundto, 950 strsec, file, dyn->d_un.d_val); 951 } 952 Elf_syminfo_entry(0, ndx, info, name, needed); 953 } 954 } 955 956 /* 957 * Print version definition section entries. 958 */ 959 static void 960 version_def(Verdef *vdf, Word vdf_num, Cache *vcache, Cache *scache, 961 const char *file) 962 { 963 Word cnt; 964 char index[MAXNDXSIZE]; 965 966 Elf_ver_def_title(0); 967 968 for (cnt = 1; cnt <= vdf_num; cnt++, 969 vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) { 970 const char *name, *dep; 971 Half vcnt = vdf->vd_cnt - 1; 972 Half ndx = vdf->vd_ndx; 973 Verdaux *vdap = (Verdaux *)((uintptr_t)vdf + vdf->vd_aux); 974 975 /* 976 * Obtain the name and first dependency (if any). 977 */ 978 name = string(vcache, cnt, scache, file, vdap->vda_name); 979 vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 980 if (vcnt) 981 dep = string(vcache, cnt, scache, file, vdap->vda_name); 982 else 983 dep = MSG_ORIG(MSG_STR_EMPTY); 984 985 (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX), 986 EC_XWORD(ndx)); 987 Elf_ver_line_1(0, index, name, dep, 988 conv_ver_flags(vdf->vd_flags)); 989 990 /* 991 * Print any additional dependencies. 992 */ 993 if (vcnt) { 994 vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 995 for (vcnt--; vcnt; vcnt--, 996 vdap = (Verdaux *)((uintptr_t)vdap + 997 vdap->vda_next)) { 998 dep = string(vcache, cnt, scache, file, 999 vdap->vda_name); 1000 Elf_ver_line_2(0, MSG_ORIG(MSG_STR_EMPTY), dep); 1001 } 1002 } 1003 } 1004 } 1005 1006 /* 1007 * Print version needed section entries. 1008 * 1009 * entry: 1010 * vnd - Address of verneed data 1011 * vnd_num - # of Verneed entries 1012 * vcache - Cache of verneed section being processed 1013 * scache - Cache of associated string table section 1014 * file - Name of object being processed. 1015 * versym - Information about versym section 1016 * 1017 * exit: 1018 * The versions have been printed. If GNU style versioning 1019 * is in effect, versym->max_verndx has been updated to 1020 * contain the largest version index seen. 1021 */ 1022 static void 1023 version_need(Verneed *vnd, Word vnd_num, Cache *vcache, Cache *scache, 1024 const char *file, VERSYM_STATE *versym) 1025 { 1026 Word cnt; 1027 char index[MAXNDXSIZE]; 1028 const char *index_str; 1029 1030 Elf_ver_need_title(0, versym->gnu); 1031 1032 /* 1033 * The versym section in an object that follows Solaris versioning 1034 * rules contains indexes into the verdef section. Symbols defined 1035 * in other objects (UNDEF) are given a version of 0, indicating that 1036 * they are not defined by this file, and the Verneed entries do not 1037 * have associated version indexes. For these reasons, we do not 1038 * display a version index for Solaris Verneed sections. 1039 * 1040 * The GNU versioning rules are different: Symbols defined in other 1041 * objects receive a version index in the range above those defined 1042 * by the Verdef section, and the vna_other field of the Vernaux 1043 * structs inside the Verneed section contain the version index for 1044 * that item. We therefore display the index when showing the 1045 * contents of a GNU Verneed section. You should not expect these 1046 * indexes to appear in sorted order --- it seems that the GNU ld 1047 * assigns the versions as symbols are encountered during linking, 1048 * and then the results are assembled into the Verneed section 1049 * afterwards. 1050 */ 1051 if (versym->gnu) { 1052 index_str = index; 1053 } else { 1054 /* For Solaris versioning, display a NULL string */ 1055 index_str = MSG_ORIG(MSG_STR_EMPTY); 1056 } 1057 1058 for (cnt = 1; cnt <= vnd_num; cnt++, 1059 vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 1060 const char *name, *dep; 1061 Half vcnt = vnd->vn_cnt; 1062 Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + vnd->vn_aux); 1063 1064 /* 1065 * Obtain the name of the needed file and the version name 1066 * within it that we're dependent on. Note that the count 1067 * should be at least one, otherwise this is a pretty bogus 1068 * entry. 1069 */ 1070 name = string(vcache, cnt, scache, file, vnd->vn_file); 1071 if (vcnt) 1072 dep = string(vcache, cnt, scache, file, vnap->vna_name); 1073 else 1074 dep = MSG_INTL(MSG_STR_NULL); 1075 1076 if (versym->gnu) { 1077 /* Format the version index value */ 1078 (void) snprintf(index, MAXNDXSIZE, 1079 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(vnap->vna_other)); 1080 if (vnap->vna_other > versym->max_verndx) 1081 versym->max_verndx = vnap->vna_other; 1082 } 1083 Elf_ver_line_1(0, index_str, name, dep, 1084 conv_ver_flags(vnap->vna_flags)); 1085 1086 /* 1087 * Print any additional version dependencies. 1088 */ 1089 if (vcnt) { 1090 vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next); 1091 for (vcnt--; vcnt; vcnt--, 1092 vnap = (Vernaux *)((uintptr_t)vnap + 1093 vnap->vna_next)) { 1094 dep = string(vcache, cnt, scache, file, 1095 vnap->vna_name); 1096 if (versym->gnu) { 1097 /* Format the next index value */ 1098 (void) snprintf(index, MAXNDXSIZE, 1099 MSG_ORIG(MSG_FMT_INDEX), 1100 EC_XWORD(vnap->vna_other)); 1101 Elf_ver_line_1(0, index_str, 1102 MSG_ORIG(MSG_STR_EMPTY), dep, 1103 conv_ver_flags(vnap->vna_flags)); 1104 if (vnap->vna_other > 1105 versym->max_verndx) 1106 versym->max_verndx = 1107 vnap->vna_other; 1108 } else { 1109 Elf_ver_line_3(0, 1110 MSG_ORIG(MSG_STR_EMPTY), dep, 1111 conv_ver_flags(vnap->vna_flags)); 1112 } 1113 } 1114 } 1115 } 1116 } 1117 1118 /* 1119 * Compute the max_verndx value for a GNU style object with 1120 * a Verneed section. This is only needed if version_need() is not 1121 * called. 1122 * 1123 * entry: 1124 * vnd - Address of verneed data 1125 * vnd_num - # of Verneed entries 1126 * versym - Information about versym section 1127 * 1128 * exit: 1129 * versym->max_verndx has been updated to contain the largest 1130 * version index seen. 1131 */ 1132 static void 1133 update_gnu_max_verndx(Verneed *vnd, Word vnd_num, VERSYM_STATE *versym) 1134 { 1135 Word cnt; 1136 1137 for (cnt = 1; cnt <= vnd_num; cnt++, 1138 vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 1139 Half vcnt = vnd->vn_cnt; 1140 Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + vnd->vn_aux); 1141 1142 if (vnap->vna_other > versym->max_verndx) 1143 versym->max_verndx = vnap->vna_other; 1144 1145 /* 1146 * Check any additional version dependencies. 1147 */ 1148 if (vcnt) { 1149 vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next); 1150 for (vcnt--; vcnt; vcnt--, 1151 vnap = (Vernaux *)((uintptr_t)vnap + 1152 vnap->vna_next)) { 1153 if (vnap->vna_other > versym->max_verndx) 1154 versym->max_verndx = vnap->vna_other; 1155 } 1156 } 1157 } 1158 } 1159 1160 /* 1161 * Display version section information if the flags require it. 1162 * Return version information needed by other output. 1163 * 1164 * entry: 1165 * cache - Cache of all section headers 1166 * shnum - # of sections in cache 1167 * file - Name of file 1168 * flags - Command line option flags 1169 * versym - VERSYM_STATE block to be filled in. 1170 */ 1171 static void 1172 versions(Cache *cache, Word shnum, const char *file, uint_t flags, 1173 VERSYM_STATE *versym) 1174 { 1175 GElf_Word cnt; 1176 Cache *verdef_cache = NULL, *verneed_cache = NULL; 1177 1178 1179 /* Gather information about the version sections */ 1180 bzero(versym, sizeof (*versym)); 1181 versym->max_verndx = 1; 1182 for (cnt = 1; cnt < shnum; cnt++) { 1183 Cache *_cache = &cache[cnt]; 1184 Shdr *shdr = _cache->c_shdr; 1185 Dyn *dyn; 1186 ulong_t numdyn; 1187 1188 switch (shdr->sh_type) { 1189 case SHT_DYNAMIC: 1190 /* 1191 * The GNU ld puts a DT_VERSYM entry in the dynamic 1192 * section so that the runtime linker can use it to 1193 * implement their versioning rules. They allow multiple 1194 * incompatible functions with the same name to exist 1195 * in different versions. The Solaris ld does not 1196 * support this mechanism, and as such, does not 1197 * produce DT_VERSYM. We use this fact to determine 1198 * which ld produced this object, and how to interpret 1199 * the version values. 1200 */ 1201 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0) || 1202 (_cache->c_data == NULL)) 1203 continue; 1204 numdyn = shdr->sh_size / shdr->sh_entsize; 1205 dyn = (Dyn *)_cache->c_data->d_buf; 1206 for (; numdyn-- > 0; dyn++) 1207 if (dyn->d_tag == DT_VERSYM) { 1208 versym->gnu = 1; 1209 break; 1210 } 1211 break; 1212 1213 case SHT_SUNW_versym: 1214 /* Record data address for later symbol processing */ 1215 if (_cache->c_data != NULL) { 1216 versym->cache = _cache; 1217 versym->data = _cache->c_data->d_buf; 1218 continue; 1219 } 1220 break; 1221 1222 case SHT_SUNW_verdef: 1223 case SHT_SUNW_verneed: 1224 /* 1225 * Ensure the data is non-NULL and the number 1226 * of items is non-zero. Otherwise, we don't 1227 * understand the section, and will not use it. 1228 */ 1229 if ((_cache->c_data == NULL) || 1230 (_cache->c_data->d_buf == NULL)) { 1231 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1232 file, _cache->c_name); 1233 continue; 1234 } 1235 if (shdr->sh_info == 0) { 1236 (void) fprintf(stderr, 1237 MSG_INTL(MSG_ERR_BADSHINFO), 1238 file, _cache->c_name, 1239 EC_WORD(shdr->sh_info)); 1240 continue; 1241 } 1242 1243 /* Make sure the string table index is in range */ 1244 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1245 (void) fprintf(stderr, 1246 MSG_INTL(MSG_ERR_BADSHLINK), file, 1247 _cache->c_name, EC_WORD(shdr->sh_link)); 1248 continue; 1249 } 1250 1251 /* 1252 * The section is usable. Save the cache entry. 1253 */ 1254 if (shdr->sh_type == SHT_SUNW_verdef) { 1255 verdef_cache = _cache; 1256 /* 1257 * Under Solaris rules, if there is a verdef 1258 * section, the max versym index is number 1259 * of version definitions it supplies. 1260 */ 1261 versym->max_verndx = shdr->sh_info; 1262 } else { 1263 verneed_cache = _cache; 1264 } 1265 break; 1266 } 1267 } 1268 1269 if ((flags & FLG_VERSIONS) == 0) { 1270 /* 1271 * If GNU versioning applies to this object, and there 1272 * is a Verneed section, then examine it to determine 1273 * the maximum Versym version index for this file. 1274 */ 1275 if ((versym->gnu) && (verneed_cache != NULL)) 1276 update_gnu_max_verndx( 1277 (Verneed *)verneed_cache->c_data->d_buf, 1278 verneed_cache->c_shdr->sh_info, versym); 1279 return; 1280 } 1281 1282 /* 1283 * Now that all the information is available, display the 1284 * Verdef and Verneed section contents. 1285 */ 1286 if (verdef_cache != NULL) { 1287 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1288 dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERDEF), 1289 verdef_cache->c_name); 1290 version_def((Verdef *)verdef_cache->c_data->d_buf, 1291 verdef_cache->c_shdr->sh_info, verdef_cache, 1292 &cache[verdef_cache->c_shdr->sh_link], file); 1293 } 1294 if (verneed_cache != NULL) { 1295 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1296 dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERNEED), 1297 verneed_cache->c_name); 1298 /* 1299 * If GNU versioning applies to this object, version_need() 1300 * will update versym->max_verndx, and it is not 1301 * necessary to call update_gnu_max_verndx(). 1302 */ 1303 version_need((Verneed *)verneed_cache->c_data->d_buf, 1304 verneed_cache->c_shdr->sh_info, verneed_cache, 1305 &cache[verneed_cache->c_shdr->sh_link], file, versym); 1306 } 1307 } 1308 1309 /* 1310 * Initialize a symbol table state structure 1311 * 1312 * entry: 1313 * state - State structure to be initialized 1314 * cache - Cache of all section headers 1315 * shnum - # of sections in cache 1316 * secndx - Index of symbol table section 1317 * ehdr - ELF header for file 1318 * versym - Information about versym section 1319 * file - Name of file 1320 * flags - Command line option flags 1321 */ 1322 static int 1323 init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx, 1324 Ehdr *ehdr, VERSYM_STATE *versym, const char *file, uint_t flags) 1325 { 1326 Shdr *shdr; 1327 1328 state->file = file; 1329 state->ehdr = ehdr; 1330 state->cache = cache; 1331 state->shnum = shnum; 1332 state->seccache = &cache[secndx]; 1333 state->secndx = secndx; 1334 state->secname = state->seccache->c_name; 1335 state->flags = flags; 1336 state->shxndx.checked = 0; 1337 state->shxndx.data = NULL; 1338 state->shxndx.n = 0; 1339 1340 shdr = state->seccache->c_shdr; 1341 1342 /* 1343 * Check the symbol data and per-item size. 1344 */ 1345 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1346 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1347 file, state->secname); 1348 return (0); 1349 } 1350 if (state->seccache->c_data == NULL) 1351 return (0); 1352 1353 /* LINTED */ 1354 state->symn = (Word)(shdr->sh_size / shdr->sh_entsize); 1355 state->sym = (Sym *)state->seccache->c_data->d_buf; 1356 1357 /* 1358 * Check associated string table section. 1359 */ 1360 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1361 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1362 file, state->secname, EC_WORD(shdr->sh_link)); 1363 return (0); 1364 } 1365 1366 /* 1367 * Determine if there is a associated Versym section 1368 * with this Symbol Table. 1369 */ 1370 if (versym->cache && 1371 (versym->cache->c_shdr->sh_link == state->secndx)) 1372 state->versym = versym; 1373 else 1374 state->versym = NULL; 1375 1376 1377 return (1); 1378 } 1379 1380 /* 1381 * Determine the extended section index used for symbol tables entries. 1382 */ 1383 static void 1384 symbols_getxindex(SYMTBL_STATE * state) 1385 { 1386 uint_t symn; 1387 Word symcnt; 1388 1389 state->shxndx.checked = 1; /* Note that we've been called */ 1390 for (symcnt = 1; symcnt < state->shnum; symcnt++) { 1391 Cache *_cache = &state->cache[symcnt]; 1392 Shdr *shdr = _cache->c_shdr; 1393 1394 if ((shdr->sh_type != SHT_SYMTAB_SHNDX) || 1395 (shdr->sh_link != state->secndx)) 1396 continue; 1397 1398 if ((shdr->sh_entsize) && 1399 /* LINTED */ 1400 ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0)) 1401 continue; 1402 1403 if (_cache->c_data == NULL) 1404 continue; 1405 1406 state->shxndx.data = _cache->c_data->d_buf; 1407 state->shxndx.n = symn; 1408 return; 1409 } 1410 } 1411 1412 /* 1413 * Produce a line of output for the given symbol 1414 * 1415 * entry: 1416 * state - Symbol table state 1417 * symndx - Index of symbol within the table 1418 * symndx_disp - Index to display. This may not be the same 1419 * as symndx if the display is relative to the logical 1420 * combination of the SUNW_ldynsym/dynsym tables. 1421 * sym - Symbol to display 1422 */ 1423 static void 1424 output_symbol(SYMTBL_STATE *state, Word symndx, Word disp_symndx, Sym *sym) 1425 { 1426 /* 1427 * Symbol types for which we check that the specified 1428 * address/size land inside the target section. 1429 */ 1430 static const int addr_symtype[STT_NUM] = { 1431 0, /* STT_NOTYPE */ 1432 1, /* STT_OBJECT */ 1433 1, /* STT_FUNC */ 1434 0, /* STT_SECTION */ 1435 0, /* STT_FILE */ 1436 1, /* STT_COMMON */ 1437 0, /* STT_TLS */ 1438 }; 1439 #if STT_NUM != (STT_TLS + 1) 1440 #error "STT_NUM has grown. Update addr_symtype[]" 1441 #endif 1442 1443 char index[MAXNDXSIZE]; 1444 const char *symname, *sec; 1445 Versym verndx; 1446 int gnuver; 1447 uchar_t type; 1448 Shdr *tshdr; 1449 Word shndx; 1450 1451 /* Ensure symbol index is in range */ 1452 if (symndx >= state->symn) { 1453 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORTNDX), 1454 state->file, state->secname, EC_WORD(symndx)); 1455 return; 1456 } 1457 1458 /* 1459 * If we are using extended symbol indexes, find the 1460 * corresponding SHN_SYMTAB_SHNDX table. 1461 */ 1462 if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0)) 1463 symbols_getxindex(state); 1464 1465 /* LINTED */ 1466 symname = string(state->seccache, symndx, 1467 &state->cache[state->seccache->c_shdr->sh_link], state->file, 1468 sym->st_name); 1469 1470 tshdr = 0; 1471 sec = NULL; 1472 1473 if (state->ehdr->e_type == ET_CORE) { 1474 sec = (char *)MSG_INTL(MSG_STR_UNKNOWN); 1475 } else if (state->flags & FLG_FAKESHDR) { 1476 /* 1477 * If we are using fake section headers derived from 1478 * the program headers, then the section indexes 1479 * in the symbols do not correspond to these headers. 1480 * The section names are not available, so all we can 1481 * do is to display them in numeric form. 1482 */ 1483 sec = conv_sym_shndx(sym->st_shndx); 1484 } else if ((sym->st_shndx < SHN_LORESERVE) && 1485 (sym->st_shndx < state->shnum)) { 1486 shndx = sym->st_shndx; 1487 tshdr = state->cache[shndx].c_shdr; 1488 sec = state->cache[shndx].c_name; 1489 } else if (sym->st_shndx == SHN_XINDEX) { 1490 if (state->shxndx.data) { 1491 Word _shxndx; 1492 1493 if (symndx > state->shxndx.n) { 1494 (void) fprintf(stderr, 1495 MSG_INTL(MSG_ERR_BADSYMXINDEX1), 1496 state->file, state->secname, 1497 EC_WORD(symndx)); 1498 } else if ((_shxndx = 1499 state->shxndx.data[symndx]) > state->shnum) { 1500 (void) fprintf(stderr, 1501 MSG_INTL(MSG_ERR_BADSYMXINDEX2), 1502 state->file, state->secname, 1503 EC_WORD(symndx), EC_WORD(_shxndx)); 1504 } else { 1505 shndx = _shxndx; 1506 tshdr = state->cache[shndx].c_shdr; 1507 sec = state->cache[shndx].c_name; 1508 } 1509 } else { 1510 (void) fprintf(stderr, 1511 MSG_INTL(MSG_ERR_BADSYMXINDEX3), 1512 state->file, state->secname, EC_WORD(symndx)); 1513 } 1514 } else if ((sym->st_shndx < SHN_LORESERVE) && 1515 (sym->st_shndx >= state->shnum)) { 1516 (void) fprintf(stderr, 1517 MSG_INTL(MSG_ERR_BADSYM5), state->file, 1518 state->secname, demangle(symname, state->flags), 1519 sym->st_shndx); 1520 } 1521 1522 /* 1523 * If versioning is available display the 1524 * version index. If not, then use 0. 1525 */ 1526 if (state->versym) { 1527 Versym test_verndx; 1528 1529 verndx = test_verndx = state->versym->data[symndx]; 1530 gnuver = state->versym->gnu; 1531 1532 /* 1533 * Check to see if this is a defined symbol with a 1534 * version index that is outside the valid range for 1535 * the file. The interpretation of this depends on 1536 * the style of versioning used by the object. 1537 * 1538 * Versions >= VER_NDX_LORESERVE have special meanings, 1539 * and are exempt from this checking. 1540 * 1541 * GNU style version indexes use the top bit of the 1542 * 16-bit index value (0x8000) as the "hidden bit". 1543 * We must mask off this bit in order to compare 1544 * the version against the maximum value. 1545 */ 1546 if (gnuver) 1547 test_verndx &= ~0x8000; 1548 1549 if ((test_verndx > state->versym->max_verndx) && 1550 (verndx < VER_NDX_LORESERVE)) 1551 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADVER), 1552 state->file, state->secname, EC_WORD(symndx), 1553 EC_HALF(test_verndx), state->versym->max_verndx); 1554 } else { 1555 verndx = 0; 1556 gnuver = 0; 1557 } 1558 1559 /* 1560 * Error checking for TLS. 1561 */ 1562 type = ELF_ST_TYPE(sym->st_info); 1563 if (type == STT_TLS) { 1564 if (tshdr && 1565 (sym->st_shndx != SHN_UNDEF) && 1566 ((tshdr->sh_flags & SHF_TLS) == 0)) { 1567 (void) fprintf(stderr, 1568 MSG_INTL(MSG_ERR_BADSYM3), state->file, 1569 state->secname, demangle(symname, state->flags)); 1570 } 1571 } else if ((type != STT_SECTION) && sym->st_size && 1572 tshdr && (tshdr->sh_flags & SHF_TLS)) { 1573 (void) fprintf(stderr, 1574 MSG_INTL(MSG_ERR_BADSYM4), state->file, 1575 state->secname, demangle(symname, state->flags)); 1576 } 1577 1578 /* 1579 * If a symbol with non-zero size has a type that 1580 * specifies an address, then make sure the location 1581 * it references is actually contained within the 1582 * section. UNDEF symbols don't count in this case, 1583 * so we ignore them. 1584 * 1585 * The meaning of the st_value field in a symbol 1586 * depends on the type of object. For a relocatable 1587 * object, it is the offset within the section. 1588 * For sharable objects, it is the offset relative to 1589 * the base of the object, and for other types, it is 1590 * the virtual address. To get an offset within the 1591 * section for non-ET_REL files, we subtract the 1592 * base address of the section. 1593 */ 1594 if (addr_symtype[type] && (sym->st_size > 0) && 1595 (sym->st_shndx != SHN_UNDEF) && ((sym->st_shndx < SHN_LORESERVE) || 1596 (sym->st_shndx == SHN_XINDEX)) && (tshdr != NULL)) { 1597 Word v = sym->st_value; 1598 if (state->ehdr->e_type != ET_REL) 1599 v -= tshdr->sh_addr; 1600 if (((v + sym->st_size) > tshdr->sh_size)) { 1601 (void) fprintf(stderr, 1602 MSG_INTL(MSG_ERR_BADSYM6), state->file, 1603 state->secname, demangle(symname, state->flags), 1604 EC_WORD(shndx), EC_XWORD(tshdr->sh_size), 1605 EC_XWORD(sym->st_value), EC_XWORD(sym->st_size)); 1606 } 1607 } 1608 1609 (void) snprintf(index, MAXNDXSIZE, 1610 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(disp_symndx)); 1611 Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index, 1612 state->ehdr->e_machine, sym, verndx, gnuver, sec, symname); 1613 } 1614 1615 /* 1616 * Search for and process any symbol tables. 1617 */ 1618 void 1619 symbols(Cache *cache, Word shnum, Ehdr *ehdr, VERSYM_STATE *versym, 1620 const char *file, uint_t flags) 1621 { 1622 SYMTBL_STATE state; 1623 Cache *_cache; 1624 Word secndx; 1625 1626 for (secndx = 1; secndx < shnum; secndx++) { 1627 Word symcnt; 1628 Shdr *shdr; 1629 1630 _cache = &cache[secndx]; 1631 shdr = _cache->c_shdr; 1632 1633 if ((shdr->sh_type != SHT_SYMTAB) && 1634 (shdr->sh_type != SHT_DYNSYM) && 1635 (shdr->sh_type != SHT_SUNW_LDYNSYM)) 1636 continue; 1637 if (!match(0, _cache->c_name, secndx)) 1638 continue; 1639 1640 if (!init_symtbl_state(&state, cache, shnum, secndx, ehdr, 1641 versym, file, flags)) 1642 continue; 1643 /* 1644 * Loop through the symbol tables entries. 1645 */ 1646 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1647 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), state.secname); 1648 Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 1649 1650 for (symcnt = 0; symcnt < state.symn; symcnt++) 1651 output_symbol(&state, symcnt, symcnt, 1652 state.sym + symcnt); 1653 } 1654 } 1655 1656 /* 1657 * Search for and process any SHT_SUNW_symsort or SHT_SUNW_tlssort sections. 1658 * These sections are always associated with the .SUNW_ldynsym./.dynsym pair. 1659 */ 1660 static void 1661 sunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, VERSYM_STATE *versym, 1662 const char *file, uint_t flags) 1663 { 1664 SYMTBL_STATE ldynsym_state, dynsym_state; 1665 Cache *sortcache, *symcache; 1666 Shdr *sortshdr, *symshdr; 1667 Word sortsecndx, symsecndx; 1668 Word ldynsym_cnt; 1669 Word *ndx; 1670 Word ndxn; 1671 int output_cnt = 0; 1672 1673 for (sortsecndx = 1; sortsecndx < shnum; sortsecndx++) { 1674 1675 sortcache = &cache[sortsecndx]; 1676 sortshdr = sortcache->c_shdr; 1677 1678 if ((sortshdr->sh_type != SHT_SUNW_symsort) && 1679 (sortshdr->sh_type != SHT_SUNW_tlssort)) 1680 continue; 1681 if (!match(0, sortcache->c_name, sortsecndx)) 1682 continue; 1683 1684 /* 1685 * If the section references a SUNW_ldynsym, then we 1686 * expect to see the associated .dynsym immediately 1687 * following. If it references a .dynsym, there is no 1688 * SUNW_ldynsym. If it is any other type, then we don't 1689 * know what to do with it. 1690 */ 1691 if ((sortshdr->sh_link == 0) || (sortshdr->sh_link >= shnum)) { 1692 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1693 file, sortcache->c_name, 1694 EC_WORD(sortshdr->sh_link)); 1695 continue; 1696 } 1697 symcache = &cache[sortshdr->sh_link]; 1698 symshdr = symcache->c_shdr; 1699 symsecndx = sortshdr->sh_link; 1700 ldynsym_cnt = 0; 1701 switch (symshdr->sh_type) { 1702 case SHT_SUNW_LDYNSYM: 1703 if (!init_symtbl_state(&ldynsym_state, cache, shnum, 1704 symsecndx, ehdr, versym, file, flags)) 1705 continue; 1706 ldynsym_cnt = ldynsym_state.symn; 1707 /* 1708 * We know that the dynsym follows immediately 1709 * after the SUNW_ldynsym, and so, should be at 1710 * (sortshdr->sh_link + 1). However, elfdump is a 1711 * diagnostic tool, so we do the full paranoid 1712 * search instead. 1713 */ 1714 for (symsecndx = 1; symsecndx < shnum; symsecndx++) { 1715 symcache = &cache[symsecndx]; 1716 symshdr = symcache->c_shdr; 1717 if (symshdr->sh_type == SHT_DYNSYM) 1718 break; 1719 } 1720 if (symsecndx >= shnum) { /* Dynsym not found! */ 1721 (void) fprintf(stderr, 1722 MSG_INTL(MSG_ERR_NODYNSYM), 1723 file, sortcache->c_name); 1724 continue; 1725 } 1726 /* Fallthrough to process associated dynsym */ 1727 /*FALLTHROUGH*/ 1728 case SHT_DYNSYM: 1729 if (!init_symtbl_state(&dynsym_state, cache, shnum, 1730 symsecndx, ehdr, versym, file, flags)) 1731 continue; 1732 break; 1733 default: 1734 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADNDXSEC), 1735 file, sortcache->c_name, conv_sec_type( 1736 ehdr->e_machine, symshdr->sh_type, 0)); 1737 continue; 1738 } 1739 1740 /* 1741 * Output header 1742 */ 1743 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1744 if (ldynsym_cnt > 0) { 1745 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT2), 1746 sortcache->c_name, ldynsym_state.secname, 1747 dynsym_state.secname); 1748 /* 1749 * The data for .SUNW_ldynsym and dynsym sections 1750 * is supposed to be adjacent with SUNW_ldynsym coming 1751 * first. Check, and issue a warning if it isn't so. 1752 */ 1753 if (((ldynsym_state.sym + ldynsym_state.symn) 1754 != dynsym_state.sym) && 1755 ((flags & FLG_FAKESHDR) == 0)) 1756 (void) fprintf(stderr, 1757 MSG_INTL(MSG_ERR_LDYNNOTADJ), file, 1758 ldynsym_state.secname, 1759 dynsym_state.secname); 1760 } else { 1761 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT1), 1762 sortcache->c_name, dynsym_state.secname); 1763 } 1764 Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 1765 1766 /* If not first one, insert a line of whitespace */ 1767 if (output_cnt++ > 0) 1768 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1769 1770 /* 1771 * SUNW_dynsymsort and SUNW_dyntlssort are arrays of 1772 * symbol indices. Iterate over the array entries, 1773 * dispaying the referenced symbols. 1774 */ 1775 ndxn = sortshdr->sh_size / sortshdr->sh_entsize; 1776 ndx = (Word *)sortcache->c_data->d_buf; 1777 for (; ndxn-- > 0; ndx++) { 1778 if (*ndx >= ldynsym_cnt) { 1779 Word sec_ndx = *ndx - ldynsym_cnt; 1780 1781 output_symbol(&dynsym_state, sec_ndx, 1782 *ndx, dynsym_state.sym + sec_ndx); 1783 } else { 1784 output_symbol(&ldynsym_state, *ndx, 1785 *ndx, ldynsym_state.sym + *ndx); 1786 } 1787 } 1788 } 1789 } 1790 1791 /* 1792 * Search for and process any relocation sections. 1793 */ 1794 static void 1795 reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, 1796 uint_t flags) 1797 { 1798 Word cnt; 1799 1800 for (cnt = 1; cnt < shnum; cnt++) { 1801 Word type, symnum; 1802 Xword relndx, relnum, relsize; 1803 void *rels; 1804 Sym *syms; 1805 Cache *symsec, *strsec; 1806 Cache *_cache = &cache[cnt]; 1807 Shdr *shdr = _cache->c_shdr; 1808 char *relname = _cache->c_name; 1809 1810 if (((type = shdr->sh_type) != SHT_RELA) && 1811 (type != SHT_REL)) 1812 continue; 1813 if (!match(0, relname, cnt)) 1814 continue; 1815 1816 /* 1817 * Decide entry size. 1818 */ 1819 if (((relsize = shdr->sh_entsize) == 0) || 1820 (relsize > shdr->sh_size)) { 1821 if (type == SHT_RELA) 1822 relsize = sizeof (Rela); 1823 else 1824 relsize = sizeof (Rel); 1825 } 1826 1827 /* 1828 * Determine the number of relocations available. 1829 */ 1830 if (shdr->sh_size == 0) { 1831 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1832 file, relname); 1833 continue; 1834 } 1835 if (_cache->c_data == NULL) 1836 continue; 1837 1838 rels = _cache->c_data->d_buf; 1839 relnum = shdr->sh_size / relsize; 1840 1841 /* 1842 * Get the data buffer for the associated symbol table and 1843 * string table. 1844 */ 1845 if (stringtbl(cache, 1, cnt, shnum, file, 1846 &symnum, &symsec, &strsec) == 0) 1847 continue; 1848 1849 syms = symsec->c_data->d_buf; 1850 1851 /* 1852 * Loop through the relocation entries. 1853 */ 1854 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1855 dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name); 1856 Elf_reloc_title(0, ELF_DBG_ELFDUMP, type); 1857 1858 for (relndx = 0; relndx < relnum; relndx++, 1859 rels = (void *)((char *)rels + relsize)) { 1860 char section[BUFSIZ]; 1861 const char *symname; 1862 Word symndx, reltype; 1863 Rela *rela; 1864 Rel *rel; 1865 1866 /* 1867 * Unravel the relocation and determine the symbol with 1868 * which this relocation is associated. 1869 */ 1870 if (type == SHT_RELA) { 1871 rela = (Rela *)rels; 1872 symndx = ELF_R_SYM(rela->r_info); 1873 reltype = ELF_R_TYPE(rela->r_info); 1874 } else { 1875 rel = (Rel *)rels; 1876 symndx = ELF_R_SYM(rel->r_info); 1877 reltype = ELF_R_TYPE(rel->r_info); 1878 } 1879 1880 symname = relsymname(cache, _cache, strsec, symndx, 1881 symnum, relndx, syms, section, BUFSIZ, file, 1882 flags); 1883 1884 /* 1885 * A zero symbol index is only valid for a few 1886 * relocations. 1887 */ 1888 if (symndx == 0) { 1889 Half mach = ehdr->e_machine; 1890 int badrel = 0; 1891 1892 if ((mach == EM_SPARC) || 1893 (mach == EM_SPARC32PLUS) || 1894 (mach == EM_SPARCV9)) { 1895 if ((reltype != R_SPARC_NONE) && 1896 (reltype != R_SPARC_REGISTER) && 1897 (reltype != R_SPARC_RELATIVE)) 1898 badrel++; 1899 } else if (mach == EM_386) { 1900 if ((reltype != R_386_NONE) && 1901 (reltype != R_386_RELATIVE)) 1902 badrel++; 1903 } else if (mach == EM_AMD64) { 1904 if ((reltype != R_AMD64_NONE) && 1905 (reltype != R_AMD64_RELATIVE)) 1906 badrel++; 1907 } 1908 1909 if (badrel) { 1910 (void) fprintf(stderr, 1911 MSG_INTL(MSG_ERR_BADREL1), file, 1912 conv_reloc_type(mach, reltype, 0)); 1913 } 1914 } 1915 1916 Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP, 1917 MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type, 1918 rels, relname, symname, 0); 1919 } 1920 } 1921 } 1922 1923 /* 1924 * Search for and process a .dynamic section. 1925 */ 1926 static void 1927 dynamic(Cache *cache, Word shnum, Ehdr *ehdr, const char *file) 1928 { 1929 Word cnt; 1930 1931 for (cnt = 1; cnt < shnum; cnt++) { 1932 Dyn *dyn; 1933 ulong_t numdyn; 1934 int ndx, end_ndx; 1935 Cache *_cache = &cache[cnt], *strsec; 1936 Shdr *shdr = _cache->c_shdr; 1937 1938 if (shdr->sh_type != SHT_DYNAMIC) 1939 continue; 1940 1941 /* 1942 * Verify the associated string table section. 1943 */ 1944 if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0) 1945 continue; 1946 1947 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1948 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1949 file, _cache->c_name); 1950 continue; 1951 } 1952 if (_cache->c_data == NULL) 1953 continue; 1954 1955 numdyn = shdr->sh_size / shdr->sh_entsize; 1956 dyn = (Dyn *)_cache->c_data->d_buf; 1957 1958 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1959 dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name); 1960 1961 Elf_dyn_title(0); 1962 1963 for (ndx = 0; ndx < numdyn; dyn++, ndx++) { 1964 const char *name; 1965 1966 /* 1967 * Print the information numerically, and if possible 1968 * as a string. 1969 */ 1970 switch (dyn->d_tag) { 1971 case DT_NULL: 1972 /* 1973 * Special case: DT_NULLs can come in groups 1974 * that we prefer to reduce to a single line. 1975 */ 1976 end_ndx = ndx; 1977 while ((end_ndx < (numdyn - 1)) && 1978 ((dyn + 1)->d_tag == DT_NULL)) { 1979 dyn++; 1980 end_ndx++; 1981 } 1982 Elf_dyn_null_entry(0, dyn, ndx, end_ndx); 1983 ndx = end_ndx; 1984 continue; 1985 1986 /* 1987 * Print the information numerically, and if possible 1988 * as a string. 1989 */ 1990 case DT_NEEDED: 1991 case DT_SONAME: 1992 case DT_FILTER: 1993 case DT_AUXILIARY: 1994 case DT_CONFIG: 1995 case DT_RPATH: 1996 case DT_RUNPATH: 1997 case DT_USED: 1998 case DT_DEPAUDIT: 1999 case DT_AUDIT: 2000 case DT_SUNW_AUXILIARY: 2001 case DT_SUNW_FILTER: 2002 name = string(_cache, ndx, strsec, 2003 file, dyn->d_un.d_ptr); 2004 break; 2005 2006 case DT_FLAGS: 2007 name = conv_dyn_flag(dyn->d_un.d_val, 0); 2008 break; 2009 case DT_FLAGS_1: 2010 name = conv_dyn_flag1(dyn->d_un.d_val); 2011 break; 2012 case DT_POSFLAG_1: 2013 name = conv_dyn_posflag1(dyn->d_un.d_val, 0); 2014 break; 2015 case DT_FEATURE_1: 2016 name = conv_dyn_feature1(dyn->d_un.d_val, 0); 2017 break; 2018 case DT_DEPRECATED_SPARC_REGISTER: 2019 name = MSG_INTL(MSG_STR_DEPRECATED); 2020 break; 2021 default: 2022 name = MSG_ORIG(MSG_STR_EMPTY); 2023 break; 2024 } 2025 2026 Elf_dyn_entry(0, dyn, ndx, name, ehdr->e_machine); 2027 } 2028 } 2029 } 2030 2031 /* 2032 * Search for and process a MOVE section. 2033 */ 2034 static void 2035 move(Cache *cache, Word shnum, const char *file, uint_t flags) 2036 { 2037 Word cnt; 2038 const char *fmt = 0; 2039 2040 for (cnt = 1; cnt < shnum; cnt++) { 2041 Word movenum, symnum, ndx; 2042 Sym *syms; 2043 Cache *_cache = &cache[cnt]; 2044 Shdr *shdr = _cache->c_shdr; 2045 Cache *symsec, *strsec; 2046 Move *move; 2047 2048 if (shdr->sh_type != SHT_SUNW_move) 2049 continue; 2050 if (!match(0, _cache->c_name, cnt)) 2051 continue; 2052 2053 /* 2054 * Determine the move data and number. 2055 */ 2056 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 2057 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2058 file, _cache->c_name); 2059 continue; 2060 } 2061 if (_cache->c_data == NULL) 2062 continue; 2063 2064 move = (Move *)_cache->c_data->d_buf; 2065 movenum = shdr->sh_size / shdr->sh_entsize; 2066 2067 /* 2068 * Get the data buffer for the associated symbol table and 2069 * string table. 2070 */ 2071 if (stringtbl(cache, 1, cnt, shnum, file, 2072 &symnum, &symsec, &strsec) == 0) 2073 return; 2074 2075 syms = (Sym *)symsec->c_data->d_buf; 2076 2077 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2078 dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name); 2079 dbg_print(0, MSG_INTL(MSG_MOVE_TITLE)); 2080 2081 if (fmt == 0) 2082 fmt = MSG_INTL(MSG_MOVE_ENTRY); 2083 2084 for (ndx = 0; ndx < movenum; move++, ndx++) { 2085 const char *symname; 2086 char index[MAXNDXSIZE], section[BUFSIZ]; 2087 Word symndx, shndx; 2088 Sym *sym; 2089 2090 /* 2091 * Check for null entries 2092 */ 2093 if ((move->m_info == 0) && (move->m_value == 0) && 2094 (move->m_poffset == 0) && (move->m_repeat == 0) && 2095 (move->m_stride == 0)) { 2096 dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY), 2097 EC_XWORD(move->m_poffset), 0, 0, 0, 2098 EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY)); 2099 continue; 2100 } 2101 if (((symndx = ELF_M_SYM(move->m_info)) == 0) || 2102 (symndx >= symnum)) { 2103 (void) fprintf(stderr, 2104 MSG_INTL(MSG_ERR_BADMINFO), file, 2105 _cache->c_name, EC_XWORD(move->m_info)); 2106 2107 (void) snprintf(index, MAXNDXSIZE, 2108 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 2109 dbg_print(0, fmt, index, 2110 EC_XWORD(move->m_poffset), 2111 ELF_M_SIZE(move->m_info), move->m_repeat, 2112 move->m_stride, move->m_value, 2113 MSG_INTL(MSG_STR_UNKNOWN)); 2114 continue; 2115 } 2116 2117 symname = relsymname(cache, _cache, strsec, 2118 symndx, symnum, ndx, syms, section, BUFSIZ, file, 2119 flags); 2120 sym = (Sym *)(syms + symndx); 2121 2122 /* 2123 * Additional sanity check. 2124 */ 2125 shndx = sym->st_shndx; 2126 if (!((shndx == SHN_COMMON) || 2127 (((shndx >= 1) && (shndx <= shnum)) && 2128 (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) { 2129 (void) fprintf(stderr, 2130 MSG_INTL(MSG_ERR_BADSYM2), file, 2131 _cache->c_name, demangle(symname, flags)); 2132 } 2133 2134 (void) snprintf(index, MAXNDXSIZE, 2135 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 2136 dbg_print(0, fmt, index, EC_XWORD(move->m_poffset), 2137 ELF_M_SIZE(move->m_info), move->m_repeat, 2138 move->m_stride, move->m_value, 2139 demangle(symname, flags)); 2140 } 2141 } 2142 } 2143 2144 /* 2145 * Traverse a note section analyzing each note information block. 2146 * The data buffers size is used to validate references before they are made, 2147 * and is decremented as each element is processed. 2148 */ 2149 void 2150 note_entry(Cache *cache, Word *data, size_t size, const char *file) 2151 { 2152 size_t bsize = size; 2153 2154 /* 2155 * Print out a single `note' information block. 2156 */ 2157 while (size > 0) { 2158 size_t namesz, descsz, type, pad, noteoff; 2159 2160 noteoff = bsize - size; 2161 /* 2162 * Make sure we can at least reference the 3 initial entries 2163 * (4-byte words) of the note information block. 2164 */ 2165 if (size >= (sizeof (Word) * 3)) 2166 size -= (sizeof (Word) * 3); 2167 else { 2168 (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ), 2169 file, cache->c_name, EC_WORD(noteoff)); 2170 return; 2171 } 2172 2173 /* 2174 * Make sure any specified name string can be referenced. 2175 */ 2176 if ((namesz = *data++) != 0) { 2177 if (size >= namesz) 2178 size -= namesz; 2179 else { 2180 (void) fprintf(stderr, 2181 MSG_INTL(MSG_NOTE_BADNMSZ), file, 2182 cache->c_name, EC_WORD(noteoff), 2183 EC_WORD(namesz)); 2184 return; 2185 } 2186 } 2187 2188 /* 2189 * Make sure any specified descriptor can be referenced. 2190 */ 2191 if ((descsz = *data++) != 0) { 2192 /* 2193 * If namesz isn't a 4-byte multiple, account for any 2194 * padding that must exist before the descriptor. 2195 */ 2196 if ((pad = (namesz & (sizeof (Word) - 1))) != 0) { 2197 pad = sizeof (Word) - pad; 2198 size -= pad; 2199 } 2200 if (size >= descsz) 2201 size -= descsz; 2202 else { 2203 (void) fprintf(stderr, 2204 MSG_INTL(MSG_NOTE_BADDESZ), file, 2205 cache->c_name, EC_WORD(noteoff), 2206 EC_WORD(namesz)); 2207 return; 2208 } 2209 } 2210 2211 type = *data++; 2212 2213 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2214 dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE), EC_WORD(type)); 2215 2216 dbg_print(0, MSG_ORIG(MSG_NOTE_NAMESZ), EC_WORD(namesz)); 2217 if (namesz) { 2218 char *name = (char *)data; 2219 2220 /* 2221 * Since the name string may have 'null' bytes 2222 * in it (ia32 .string) - we just write the 2223 * whole stream in a single fwrite. 2224 */ 2225 (void) fwrite(name, namesz, 1, stdout); 2226 name = name + ((namesz + (sizeof (Word) - 1)) & 2227 ~(sizeof (Word) - 1)); 2228 /* LINTED */ 2229 data = (Word *)name; 2230 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2231 } 2232 2233 /* 2234 * If multiple information blocks exist within a .note section 2235 * account for any padding that must exist before the next 2236 * information block. 2237 */ 2238 if ((pad = (descsz & (sizeof (Word) - 1))) != 0) { 2239 pad = sizeof (Word) - pad; 2240 if (size > pad) 2241 size -= pad; 2242 } 2243 2244 dbg_print(0, MSG_ORIG(MSG_NOTE_DESCSZ), EC_WORD(descsz)); 2245 if (descsz) { 2246 int ndx, byte, word; 2247 char string[58], *str = string; 2248 uchar_t *desc = (uchar_t *)data; 2249 2250 /* 2251 * Dump descriptor bytes. 2252 */ 2253 for (ndx = byte = word = 0; descsz; descsz--, desc++) { 2254 int tok = *desc; 2255 2256 (void) snprintf(str, 58, MSG_ORIG(MSG_NOTE_TOK), 2257 tok); 2258 str += 3; 2259 2260 if (++byte == 4) { 2261 *str++ = ' ', *str++ = ' '; 2262 word++; 2263 byte = 0; 2264 } 2265 if (word == 4) { 2266 *str = '\0'; 2267 dbg_print(0, MSG_ORIG(MSG_NOTE_DESC), 2268 ndx, string); 2269 word = 0; 2270 ndx += 16; 2271 str = string; 2272 } 2273 } 2274 if (byte || word) { 2275 *str = '\0'; 2276 dbg_print(0, MSG_ORIG(MSG_NOTE_DESC), 2277 ndx, string); 2278 } 2279 2280 desc += pad; 2281 /* LINTED */ 2282 data = (Word *)desc; 2283 } 2284 } 2285 } 2286 2287 /* 2288 * Search for and process a .note section. 2289 */ 2290 static void 2291 note(Cache *cache, Word shnum, const char *file) 2292 { 2293 Word cnt; 2294 2295 /* 2296 * Otherwise look for any .note sections. 2297 */ 2298 for (cnt = 1; cnt < shnum; cnt++) { 2299 Cache *_cache = &cache[cnt]; 2300 Shdr *shdr = _cache->c_shdr; 2301 2302 if (shdr->sh_type != SHT_NOTE) 2303 continue; 2304 if (!match(0, _cache->c_name, cnt)) 2305 continue; 2306 2307 /* 2308 * As these sections are often hand rolled, make sure they're 2309 * properly aligned before proceeding. 2310 */ 2311 if (shdr->sh_offset & (sizeof (Word) - 1)) { 2312 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN), 2313 file, _cache->c_name); 2314 continue; 2315 } 2316 if (_cache->c_data == NULL) 2317 continue; 2318 2319 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2320 dbg_print(0, MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name); 2321 note_entry(_cache, (Word *)_cache->c_data->d_buf, 2322 /* LINTED */ 2323 (Word)_cache->c_data->d_size, file); 2324 } 2325 } 2326 2327 /* 2328 * Determine an individual hash entry. This may be the initial hash entry, 2329 * or an associated chain entry. 2330 */ 2331 static void 2332 hash_entry(Cache *refsec, Cache *strsec, const char *hsecname, Word hashndx, 2333 Word symndx, Word symn, Sym *syms, const char *file, ulong_t bkts, 2334 uint_t flags, int chain) 2335 { 2336 Sym *sym; 2337 const char *symname, *str; 2338 char _bucket[MAXNDXSIZE], _symndx[MAXNDXSIZE]; 2339 ulong_t nbkt, nhash; 2340 2341 if (symndx > symn) { 2342 (void) fprintf(stderr, MSG_INTL(MSG_ERR_HSBADSYMNDX), file, 2343 EC_WORD(symndx), EC_WORD(hashndx)); 2344 symname = MSG_INTL(MSG_STR_UNKNOWN); 2345 } else { 2346 sym = (Sym *)(syms + symndx); 2347 symname = string(refsec, symndx, strsec, file, sym->st_name); 2348 } 2349 2350 if (chain == 0) { 2351 (void) snprintf(_bucket, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 2352 hashndx); 2353 str = (const char *)_bucket; 2354 } else 2355 str = MSG_ORIG(MSG_STR_EMPTY); 2356 2357 (void) snprintf(_symndx, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX2), 2358 EC_WORD(symndx)); 2359 dbg_print(0, MSG_ORIG(MSG_FMT_HASH_INFO), str, _symndx, 2360 demangle(symname, flags)); 2361 2362 /* 2363 * Determine if this string is in the correct bucket. 2364 */ 2365 nhash = elf_hash(symname); 2366 nbkt = nhash % bkts; 2367 2368 if (nbkt != hashndx) { 2369 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADHASH), file, 2370 hsecname, symname, EC_WORD(hashndx), nbkt); 2371 } 2372 } 2373 2374 #define MAXCOUNT 500 2375 2376 static void 2377 hash(Cache *cache, Word shnum, const char *file, uint_t flags) 2378 { 2379 static int count[MAXCOUNT]; 2380 Word cnt; 2381 ulong_t ndx, bkts; 2382 char number[MAXNDXSIZE]; 2383 2384 for (cnt = 1; cnt < shnum; cnt++) { 2385 uint_t *hash, *chain; 2386 Cache *_cache = &cache[cnt]; 2387 Shdr *sshdr, *hshdr = _cache->c_shdr; 2388 char *ssecname, *hsecname = _cache->c_name; 2389 Sym *syms; 2390 Word symn; 2391 2392 if (hshdr->sh_type != SHT_HASH) 2393 continue; 2394 2395 /* 2396 * Determine the hash table data and size. 2397 */ 2398 if ((hshdr->sh_entsize == 0) || (hshdr->sh_size == 0)) { 2399 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2400 file, hsecname); 2401 continue; 2402 } 2403 if (_cache->c_data == NULL) 2404 continue; 2405 2406 hash = (uint_t *)_cache->c_data->d_buf; 2407 bkts = *hash; 2408 chain = hash + 2 + bkts; 2409 hash += 2; 2410 2411 /* 2412 * Get the data buffer for the associated symbol table. 2413 */ 2414 if ((hshdr->sh_link == 0) || (hshdr->sh_link >= shnum)) { 2415 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2416 file, hsecname, EC_WORD(hshdr->sh_link)); 2417 continue; 2418 } 2419 2420 _cache = &cache[hshdr->sh_link]; 2421 ssecname = _cache->c_name; 2422 2423 if (_cache->c_data == NULL) 2424 continue; 2425 2426 if ((syms = (Sym *)_cache->c_data->d_buf) == NULL) { 2427 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2428 file, ssecname); 2429 continue; 2430 } 2431 2432 sshdr = _cache->c_shdr; 2433 /* LINTED */ 2434 symn = (Word)(sshdr->sh_size / sshdr->sh_entsize); 2435 2436 /* 2437 * Get the associated string table section. 2438 */ 2439 if ((sshdr->sh_link == 0) || (sshdr->sh_link >= shnum)) { 2440 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2441 file, ssecname, EC_WORD(sshdr->sh_link)); 2442 continue; 2443 } 2444 2445 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2446 dbg_print(0, MSG_INTL(MSG_ELF_SCN_HASH), hsecname); 2447 dbg_print(0, MSG_INTL(MSG_ELF_HASH_INFO)); 2448 2449 /* 2450 * Loop through the hash buckets, printing the appropriate 2451 * symbols. 2452 */ 2453 for (ndx = 0; ndx < bkts; ndx++, hash++) { 2454 Word _ndx, _cnt; 2455 2456 if (*hash == 0) { 2457 count[0]++; 2458 continue; 2459 } 2460 2461 hash_entry(_cache, &cache[sshdr->sh_link], hsecname, 2462 ndx, *hash, symn, syms, file, bkts, flags, 0); 2463 2464 /* 2465 * Determine if any other symbols are chained to this 2466 * bucket. 2467 */ 2468 _ndx = chain[*hash]; 2469 _cnt = 1; 2470 while (_ndx) { 2471 hash_entry(_cache, &cache[sshdr->sh_link], 2472 hsecname, ndx, _ndx, symn, syms, file, 2473 bkts, flags, 1); 2474 _ndx = chain[_ndx]; 2475 _cnt++; 2476 } 2477 2478 if (_cnt >= MAXCOUNT) { 2479 (void) fprintf(stderr, 2480 MSG_INTL(MSG_HASH_OVERFLW), file, 2481 _cache->c_name, EC_WORD(ndx), 2482 EC_WORD(_cnt)); 2483 } else 2484 count[_cnt]++; 2485 } 2486 break; 2487 } 2488 2489 /* 2490 * Print out the count information. 2491 */ 2492 bkts = cnt = 0; 2493 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2494 2495 for (ndx = 0; ndx < MAXCOUNT; ndx++) { 2496 Word _cnt; 2497 2498 if ((_cnt = count[ndx]) == 0) 2499 continue; 2500 2501 (void) snprintf(number, MAXNDXSIZE, 2502 MSG_ORIG(MSG_FMT_INTEGER), _cnt); 2503 dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS1), number, 2504 EC_WORD(ndx)); 2505 bkts += _cnt; 2506 cnt += (Word)(ndx * _cnt); 2507 } 2508 if (cnt) { 2509 (void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 2510 bkts); 2511 dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS2), number, 2512 EC_WORD(cnt)); 2513 } 2514 } 2515 2516 static void 2517 group(Cache *cache, Word shnum, const char *file, uint_t flags) 2518 { 2519 Word scnt; 2520 2521 for (scnt = 1; scnt < shnum; scnt++) { 2522 Cache *_cache = &cache[scnt]; 2523 Shdr *shdr = _cache->c_shdr; 2524 Word *grpdata, gcnt, grpcnt, symnum, unknown; 2525 Cache *symsec, *strsec; 2526 Sym *syms, *sym; 2527 char flgstrbuf[MSG_GRP_COMDAT_SIZE + 10]; 2528 2529 if (shdr->sh_type != SHT_GROUP) 2530 continue; 2531 if (!match(0, _cache->c_name, scnt)) 2532 continue; 2533 if ((_cache->c_data == NULL) || 2534 ((grpdata = (Word *)_cache->c_data->d_buf) == NULL)) 2535 continue; 2536 grpcnt = shdr->sh_size / sizeof (Word); 2537 2538 /* 2539 * Get the data buffer for the associated symbol table and 2540 * string table. 2541 */ 2542 if (stringtbl(cache, 1, scnt, shnum, file, 2543 &symnum, &symsec, &strsec) == 0) 2544 return; 2545 2546 syms = symsec->c_data->d_buf; 2547 2548 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2549 dbg_print(0, MSG_INTL(MSG_ELF_SCN_GRP), _cache->c_name); 2550 dbg_print(0, MSG_INTL(MSG_GRP_TITLE)); 2551 2552 /* 2553 * The first element of the group defines the group. The 2554 * associated symbol is defined by the sh_link field. 2555 */ 2556 if ((shdr->sh_info == SHN_UNDEF) || (shdr->sh_info > symnum)) { 2557 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 2558 file, _cache->c_name, EC_WORD(shdr->sh_info)); 2559 return; 2560 } 2561 2562 (void) strcpy(flgstrbuf, MSG_ORIG(MSG_STR_OSQBRKT)); 2563 if (grpdata[0] & GRP_COMDAT) { 2564 (void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_COMDAT)); 2565 } 2566 if ((unknown = (grpdata[0] & ~GRP_COMDAT)) != 0) { 2567 size_t len = strlen(flgstrbuf); 2568 2569 (void) snprintf(&flgstrbuf[len], 2570 (MSG_GRP_COMDAT_SIZE + 10 - len), 2571 MSG_ORIG(MSG_GRP_UNKNOWN), unknown); 2572 } 2573 (void) strcat(flgstrbuf, MSG_ORIG(MSG_STR_CSQBRKT)); 2574 sym = (Sym *)(syms + shdr->sh_info); 2575 2576 dbg_print(0, MSG_INTL(MSG_GRP_SIGNATURE), flgstrbuf, 2577 demangle(string(_cache, 0, strsec, file, sym->st_name), 2578 flags)); 2579 2580 for (gcnt = 1; gcnt < grpcnt; gcnt++) { 2581 char index[MAXNDXSIZE]; 2582 const char *name; 2583 2584 (void) snprintf(index, MAXNDXSIZE, 2585 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(gcnt)); 2586 2587 if (grpdata[gcnt] >= shnum) 2588 name = MSG_INTL(MSG_GRP_INVALSCN); 2589 else 2590 name = cache[grpdata[gcnt]].c_name; 2591 2592 (void) printf(MSG_ORIG(MSG_GRP_ENTRY), index, name, 2593 EC_XWORD(grpdata[gcnt])); 2594 } 2595 } 2596 } 2597 2598 static void 2599 got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, uint_t flags) 2600 { 2601 Cache *gotcache = 0, *symtab = 0, *_cache; 2602 Addr gotbgn, gotend; 2603 Shdr *gotshdr; 2604 Word cnt, gotents, gotndx; 2605 size_t gentsize; 2606 Got_info *gottable; 2607 char *gotdata; 2608 Sym *gotsym; 2609 Xword gotsymaddr; 2610 2611 /* 2612 * First, find the got. 2613 */ 2614 for (cnt = 1; cnt < shnum; cnt++) { 2615 _cache = &cache[cnt]; 2616 if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT), 2617 MSG_ELF_GOT_SIZE) == 0) { 2618 gotcache = _cache; 2619 break; 2620 } 2621 } 2622 if (gotcache == 0) 2623 return; 2624 2625 /* 2626 * A got section within a relocatable object is suspicious. 2627 */ 2628 if (ehdr->e_type == ET_REL) { 2629 (void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file, 2630 _cache->c_name); 2631 } 2632 2633 gotshdr = gotcache->c_shdr; 2634 if (gotshdr->sh_size == 0) { 2635 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2636 file, gotcache->c_name); 2637 return; 2638 } 2639 2640 gotbgn = gotshdr->sh_addr; 2641 gotend = gotbgn + gotshdr->sh_size; 2642 2643 /* 2644 * Some architectures don't properly set the sh_entsize for the GOT 2645 * table. If it's not set, default to a size of a pointer. 2646 */ 2647 if ((gentsize = gotshdr->sh_entsize) == 0) 2648 gentsize = sizeof (Xword); 2649 2650 if (gotcache->c_data == NULL) 2651 return; 2652 2653 /* LINTED */ 2654 gotents = (Word)(gotshdr->sh_size / gentsize); 2655 gotdata = gotcache->c_data->d_buf; 2656 2657 if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) { 2658 int err = errno; 2659 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), file, 2660 strerror(err)); 2661 return; 2662 } 2663 2664 /* 2665 * Now we scan through all the sections looking for any relocations 2666 * that may be against the GOT. Since these may not be isolated to a 2667 * .rel[a].got section we check them all. 2668 * While scanning sections save the symbol table entry (a symtab 2669 * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_. 2670 */ 2671 for (cnt = 1; cnt < shnum; cnt++) { 2672 Word type, symnum; 2673 Xword relndx, relnum, relsize; 2674 void *rels; 2675 Sym *syms; 2676 Cache *symsec, *strsec; 2677 Cache *_cache = &cache[cnt]; 2678 Shdr *shdr; 2679 2680 shdr = _cache->c_shdr; 2681 type = shdr->sh_type; 2682 2683 if ((symtab == 0) && (type == SHT_DYNSYM)) { 2684 symtab = _cache; 2685 continue; 2686 } 2687 if (type == SHT_SYMTAB) { 2688 symtab = _cache; 2689 continue; 2690 } 2691 if ((type != SHT_RELA) && (type != SHT_REL)) 2692 continue; 2693 2694 /* 2695 * Decide entry size. 2696 */ 2697 if (((relsize = shdr->sh_entsize) == 0) || 2698 (relsize > shdr->sh_size)) { 2699 if (type == SHT_RELA) 2700 relsize = sizeof (Rela); 2701 else 2702 relsize = sizeof (Rel); 2703 } 2704 2705 /* 2706 * Determine the number of relocations available. 2707 */ 2708 if (shdr->sh_size == 0) { 2709 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2710 file, _cache->c_name); 2711 continue; 2712 } 2713 if (_cache->c_data == NULL) 2714 continue; 2715 2716 rels = _cache->c_data->d_buf; 2717 relnum = shdr->sh_size / relsize; 2718 2719 /* 2720 * Get the data buffer for the associated symbol table and 2721 * string table. 2722 */ 2723 if (stringtbl(cache, 1, cnt, shnum, file, 2724 &symnum, &symsec, &strsec) == 0) 2725 continue; 2726 2727 syms = symsec->c_data->d_buf; 2728 2729 /* 2730 * Loop through the relocation entries. 2731 */ 2732 for (relndx = 0; relndx < relnum; relndx++, 2733 rels = (void *)((char *)rels + relsize)) { 2734 char section[BUFSIZ]; 2735 Addr offset; 2736 Got_info *gip; 2737 Word symndx, reltype; 2738 Rela *rela; 2739 Rel *rel; 2740 2741 /* 2742 * Unravel the relocation. 2743 */ 2744 if (type == SHT_RELA) { 2745 rela = (Rela *)rels; 2746 symndx = ELF_R_SYM(rela->r_info); 2747 reltype = ELF_R_TYPE(rela->r_info); 2748 offset = rela->r_offset; 2749 } else { 2750 rel = (Rel *)rels; 2751 symndx = ELF_R_SYM(rel->r_info); 2752 reltype = ELF_R_TYPE(rel->r_info); 2753 offset = rel->r_offset; 2754 } 2755 2756 /* 2757 * Only pay attention to relocations against the GOT. 2758 */ 2759 if ((offset < gotbgn) || (offset >= gotend)) 2760 continue; 2761 2762 /* LINTED */ 2763 gotndx = (Word)((offset - gotbgn) / 2764 gotshdr->sh_entsize); 2765 gip = &gottable[gotndx]; 2766 2767 if (gip->g_reltype != 0) { 2768 (void) fprintf(stderr, 2769 MSG_INTL(MSG_GOT_MULTIPLE), file, 2770 EC_WORD(gotndx), EC_ADDR(offset)); 2771 continue; 2772 } 2773 2774 if (symndx) 2775 gip->g_symname = relsymname(cache, _cache, 2776 strsec, symndx, symnum, relndx, syms, 2777 section, BUFSIZ, file, flags); 2778 gip->g_reltype = reltype; 2779 gip->g_rel = rels; 2780 } 2781 } 2782 2783 if (symlookup(MSG_ORIG(MSG_GOT_SYM), cache, shnum, &gotsym, symtab, 2784 file)) 2785 gotsymaddr = gotsym->st_value; 2786 else 2787 gotsymaddr = gotbgn; 2788 2789 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2790 dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name); 2791 Elf_got_title(0); 2792 2793 for (gotndx = 0; gotndx < gotents; gotndx++) { 2794 Got_info *gip; 2795 Sword gindex; 2796 Addr gaddr; 2797 Xword gotentry; 2798 2799 gip = &gottable[gotndx]; 2800 2801 gaddr = gotbgn + (gotndx * gentsize); 2802 gindex = (Sword)(gaddr - gotsymaddr) / (Sword)gentsize; 2803 2804 if (gentsize == sizeof (Word)) 2805 /* LINTED */ 2806 gotentry = (Xword)(*((Word *)(gotdata) + gotndx)); 2807 else 2808 /* LINTED */ 2809 gotentry = *((Xword *)(gotdata) + gotndx); 2810 2811 Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine, 2812 gip->g_reltype, gip->g_rel, gip->g_symname); 2813 } 2814 free(gottable); 2815 } 2816 2817 void 2818 checksum(Elf *elf) 2819 { 2820 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2821 dbg_print(0, MSG_INTL(MSG_STR_CHECKSUM), elf_checksum(elf)); 2822 } 2823 2824 /* 2825 * This variable is used by regular() to communicate the address of 2826 * the section header cache to sort_shdr_ndx_arr(). Unfortunately, 2827 * the qsort() interface does not include a userdata argument by which 2828 * such arbitrary data can be passed, so we are stuck using global data. 2829 */ 2830 static Cache *sort_shdr_ndx_arr_cache; 2831 2832 2833 /* 2834 * Used with qsort() to sort the section indices so that they can be 2835 * used to access the section headers in order of increasing data offset. 2836 * 2837 * entry: 2838 * sort_shdr_ndx_arr_cache - Contains address of 2839 * section header cache. 2840 * v1, v2 - Point at elements of sort_shdr_bits array to be compared. 2841 * 2842 * exit: 2843 * Returns -1 (less than), 0 (equal) or 1 (greater than). 2844 */ 2845 static int 2846 sort_shdr_ndx_arr(const void *v1, const void *v2) 2847 { 2848 Cache *cache1 = sort_shdr_ndx_arr_cache + *((size_t *)v1); 2849 Cache *cache2 = sort_shdr_ndx_arr_cache + *((size_t *)v2); 2850 2851 if (cache1->c_shdr->sh_offset < cache2->c_shdr->sh_offset) 2852 return (-1); 2853 2854 if (cache1->c_shdr->sh_offset > cache2->c_shdr->sh_offset) 2855 return (1); 2856 2857 return (0); 2858 } 2859 2860 2861 static int 2862 shdr_cache(const char *file, Elf *elf, Ehdr *ehdr, size_t shstrndx, 2863 size_t shnum, Cache **cache_ret) 2864 { 2865 Elf_Scn *scn; 2866 Elf_Data *data; 2867 size_t ndx; 2868 Shdr *nameshdr; 2869 char *names = 0; 2870 Cache *cache, *_cache; 2871 size_t *shdr_ndx_arr, shdr_ndx_arr_cnt; 2872 2873 2874 /* 2875 * Obtain the .shstrtab data buffer to provide the required section 2876 * name strings. 2877 */ 2878 if (shstrndx == SHN_UNDEF) { 2879 /* 2880 * It is rare, but legal, for an object to lack a 2881 * header string table section. 2882 */ 2883 names = NULL; 2884 (void) fprintf(stderr, MSG_INTL(MSG_ERR_NOSHSTRSEC), file); 2885 } else if ((scn = elf_getscn(elf, shstrndx)) == NULL) { 2886 failure(file, MSG_ORIG(MSG_ELF_GETSCN)); 2887 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR), 2888 EC_XWORD(shstrndx)); 2889 2890 } else if ((data = elf_getdata(scn, NULL)) == NULL) { 2891 failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 2892 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA), 2893 EC_XWORD(shstrndx)); 2894 2895 } else if ((nameshdr = elf_getshdr(scn)) == NULL) { 2896 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2897 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 2898 EC_WORD(elf_ndxscn(scn))); 2899 2900 } else if ((names = data->d_buf) == 0) 2901 (void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file); 2902 2903 /* 2904 * Allocate a cache to maintain a descriptor for each section. 2905 */ 2906 if ((*cache_ret = cache = malloc(shnum * sizeof (Cache))) == NULL) { 2907 int err = errno; 2908 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2909 file, strerror(err)); 2910 return (0); 2911 } 2912 2913 *cache = cache_init; 2914 _cache = cache; 2915 _cache++; 2916 2917 /* 2918 * Allocate an array that will hold the section index for 2919 * each section that has data in the ELF file: 2920 * 2921 * - Is not a NOBITS section 2922 * - Data has non-zero length 2923 * 2924 * Note that shnum is an upper bound on the size required. It 2925 * is likely that we won't use a few of these array elements. 2926 * Allocating a modest amount of extra memory in this case means 2927 * that we can avoid an extra loop to count the number of needed 2928 * items, and can fill this array immediately in the first loop 2929 * below. 2930 */ 2931 if ((shdr_ndx_arr = malloc(shnum * sizeof (*shdr_ndx_arr))) == NULL) { 2932 int err = errno; 2933 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2934 file, strerror(err)); 2935 return (0); 2936 } 2937 shdr_ndx_arr_cnt = 0; 2938 2939 /* 2940 * Traverse the sections of the file. This gathering of data is 2941 * carried out in two passes. First, the section headers are captured 2942 * and the section header names are evaluated. A verification pass is 2943 * then carried out over the section information. Files have been 2944 * known to exhibit overlapping (and hence erroneous) section header 2945 * information. 2946 * 2947 * Finally, the data for each section is obtained. This processing is 2948 * carried out after section verification because should any section 2949 * header overlap occur, and a file needs translating (ie. xlate'ing 2950 * information from a non-native architecture file), then the process 2951 * of translation can corrupt the section header information. Of 2952 * course, if there is any section overlap, the data related to the 2953 * sections is going to be compromised. However, it is the translation 2954 * of this data that has caused problems with elfdump()'s ability to 2955 * extract the data. 2956 */ 2957 for (ndx = 1, scn = NULL; scn = elf_nextscn(elf, scn); 2958 ndx++, _cache++) { 2959 char scnndxnm[100]; 2960 2961 _cache->c_ndx = ndx; 2962 _cache->c_scn = scn; 2963 2964 if ((_cache->c_shdr = elf_getshdr(scn)) == NULL) { 2965 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2966 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 2967 EC_WORD(elf_ndxscn(scn))); 2968 } 2969 2970 /* 2971 * If this section has data in the file, include it in 2972 * the array of sections to check for address overlap. 2973 */ 2974 if ((_cache->c_shdr->sh_size != 0) && 2975 (_cache->c_shdr->sh_type != SHT_NOBITS)) 2976 shdr_ndx_arr[shdr_ndx_arr_cnt++] = ndx; 2977 2978 /* 2979 * If a shstrtab exists, assign the section name. 2980 */ 2981 if (names && _cache->c_shdr) { 2982 if (_cache->c_shdr->sh_name && 2983 /* LINTED */ 2984 (nameshdr->sh_size > _cache->c_shdr->sh_name)) { 2985 _cache->c_name = 2986 names + _cache->c_shdr->sh_name; 2987 continue; 2988 } 2989 2990 /* 2991 * Generate an error if the section name index is zero 2992 * or exceeds the shstrtab data. Fall through to 2993 * fabricate a section name. 2994 */ 2995 if ((_cache->c_shdr->sh_name == 0) || 2996 /* LINTED */ 2997 (nameshdr->sh_size <= _cache->c_shdr->sh_name)) { 2998 (void) fprintf(stderr, 2999 MSG_INTL(MSG_ERR_BADSHNAME), file, 3000 EC_WORD(ndx), 3001 EC_XWORD(_cache->c_shdr->sh_name)); 3002 } 3003 } 3004 3005 /* 3006 * If there exists no shstrtab data, or a section header has no 3007 * name (an invalid index of 0), then compose a name for the 3008 * section. 3009 */ 3010 (void) snprintf(scnndxnm, sizeof (scnndxnm), 3011 MSG_INTL(MSG_FMT_SCNNDX), ndx); 3012 3013 if ((_cache->c_name = malloc(strlen(scnndxnm) + 1)) == NULL) { 3014 int err = errno; 3015 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 3016 file, strerror(err)); 3017 return (0); 3018 } 3019 (void) strcpy(_cache->c_name, scnndxnm); 3020 } 3021 3022 /* 3023 * Having collected all the sections, validate their address range. 3024 * Cases have existed where the section information has been invalid. 3025 * This can lead to all sorts of other, hard to diagnose errors, as 3026 * each section is processed individually (ie. with elf_getdata()). 3027 * Here, we carry out some address comparisons to catch a family of 3028 * overlapping memory issues we have observed (likely, there are others 3029 * that we have yet to discover). 3030 * 3031 * Note, should any memory overlap occur, obtaining any additional 3032 * data from the file is questionable. However, it might still be 3033 * possible to inspect the ELF header, Programs headers, or individual 3034 * sections, so rather than bailing on an error condition, continue 3035 * processing to see if any data can be salvaged. 3036 */ 3037 if (shdr_ndx_arr_cnt > 1) { 3038 sort_shdr_ndx_arr_cache = cache; 3039 qsort(shdr_ndx_arr, shdr_ndx_arr_cnt, 3040 sizeof (*shdr_ndx_arr), sort_shdr_ndx_arr); 3041 } 3042 for (ndx = 0; ndx < shdr_ndx_arr_cnt; ndx++) { 3043 Cache *_cache = cache + shdr_ndx_arr[ndx]; 3044 Shdr *shdr = _cache->c_shdr; 3045 Off bgn1, bgn = shdr->sh_offset; 3046 Off end1, end = shdr->sh_offset + shdr->sh_size; 3047 size_t ndx1; 3048 3049 /* 3050 * Check the section against all following ones, reporting 3051 * any overlaps. Since we've sorted the sections by offset, 3052 * we can stop after the first comparison that fails. There 3053 * are no overlaps in a properly formed ELF file, in which 3054 * case this algorithm runs in O(n) time. This will degenerate 3055 * to O(n^2) for a completely broken file. Such a file is 3056 * (1) highly unlikely, and (2) unusable, so it is reasonable 3057 * for the analysis to take longer. 3058 */ 3059 for (ndx1 = ndx + 1; ndx1 < shdr_ndx_arr_cnt; ndx1++) { 3060 Cache *_cache1 = cache + shdr_ndx_arr[ndx1]; 3061 Shdr *shdr1 = _cache1->c_shdr; 3062 3063 bgn1 = shdr1->sh_offset; 3064 end1 = shdr1->sh_offset + shdr1->sh_size; 3065 3066 if (((bgn1 <= bgn) && (end1 > bgn)) || 3067 ((bgn1 < end) && (end1 >= end))) { 3068 (void) fprintf(stderr, 3069 MSG_INTL(MSG_ERR_SECMEMOVER), file, 3070 EC_WORD(elf_ndxscn(_cache->c_scn)), 3071 _cache->c_name, EC_OFF(bgn), EC_OFF(end), 3072 EC_WORD(elf_ndxscn(_cache1->c_scn)), 3073 _cache1->c_name, EC_OFF(bgn1), 3074 EC_OFF(end1)); 3075 } else { /* No overlap, so can stop */ 3076 break; 3077 } 3078 } 3079 3080 /* 3081 * In addition to checking for sections overlapping 3082 * each other (done above), we should also make sure 3083 * the section doesn't overlap the section header array. 3084 */ 3085 bgn1 = ehdr->e_shoff; 3086 end1 = ehdr->e_shoff + (ehdr->e_shentsize * ehdr->e_shnum); 3087 3088 if (((bgn1 <= bgn) && (end1 > bgn)) || 3089 ((bgn1 < end) && (end1 >= end))) { 3090 (void) fprintf(stderr, 3091 MSG_INTL(MSG_ERR_SHDRMEMOVER), file, EC_OFF(bgn1), 3092 EC_OFF(end1), 3093 EC_WORD(elf_ndxscn(_cache->c_scn)), 3094 _cache->c_name, EC_OFF(bgn), EC_OFF(end)); 3095 } 3096 } 3097 3098 /* 3099 * Obtain the data for each section. 3100 */ 3101 for (ndx = 1; ndx < shnum; ndx++) { 3102 Cache *_cache = &cache[ndx]; 3103 Elf_Scn *scn = _cache->c_scn; 3104 3105 if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) { 3106 failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 3107 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA), 3108 EC_WORD(elf_ndxscn(scn))); 3109 } 3110 } 3111 3112 return (1); 3113 } 3114 3115 3116 3117 void 3118 regular(const char *file, int fd, Elf *elf, uint_t flags, int wfd) 3119 { 3120 Elf_Scn *scn; 3121 Ehdr *ehdr; 3122 size_t ndx, shstrndx, shnum, phnum; 3123 Shdr *shdr; 3124 Cache *cache; 3125 VERSYM_STATE versym; 3126 3127 if ((ehdr = elf_getehdr(elf)) == NULL) { 3128 failure(file, MSG_ORIG(MSG_ELF_GETEHDR)); 3129 return; 3130 } 3131 3132 if (elf_getshnum(elf, &shnum) == 0) { 3133 failure(file, MSG_ORIG(MSG_ELF_GETSHNUM)); 3134 return; 3135 } 3136 3137 if (elf_getshstrndx(elf, &shstrndx) == 0) { 3138 failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX)); 3139 return; 3140 } 3141 3142 if (elf_getphnum(elf, &phnum) == 0) { 3143 failure(file, MSG_ORIG(MSG_ELF_GETPHNUM)); 3144 return; 3145 } 3146 /* 3147 * If the user requested section headers derived from the 3148 * program headers (-P option) and this file doesn't have 3149 * any program headers (i.e. ET_REL), then we can't do it. 3150 */ 3151 if ((phnum == 0) && (flags & FLG_FAKESHDR)) { 3152 (void) fprintf(stderr, MSG_INTL(MSG_ERR_PNEEDSPH), file); 3153 return; 3154 } 3155 3156 3157 if ((scn = elf_getscn(elf, 0)) != NULL) { 3158 if ((shdr = elf_getshdr(scn)) == NULL) { 3159 failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 3160 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0); 3161 return; 3162 } 3163 } else 3164 shdr = 0; 3165 3166 /* 3167 * Print the elf header. 3168 */ 3169 if (flags & FLG_EHDR) 3170 Elf_ehdr(0, ehdr, shdr); 3171 3172 /* 3173 * If the section headers or program headers have inadequate 3174 * alignment for the class of object, print a warning. libelf 3175 * can handle such files, but programs that use them can crash 3176 * when they dereference unaligned items. 3177 */ 3178 if (ehdr->e_phoff & (sizeof (Addr) - 1)) 3179 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADPHDRALIGN), file); 3180 if (ehdr->e_shoff & (sizeof (Addr) - 1)) 3181 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHDRALIGN), file); 3182 3183 /* 3184 * Print the program headers. 3185 */ 3186 if ((flags & FLG_PHDR) && (phnum != 0)) { 3187 Phdr *phdr; 3188 3189 if ((phdr = elf_getphdr(elf)) == NULL) { 3190 failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 3191 return; 3192 } 3193 3194 for (ndx = 0; ndx < phnum; phdr++, ndx++) { 3195 if (!match(0, conv_phdr_type(ehdr->e_machine, 3196 phdr->p_type, CONV_FMT_ALTFILE), ndx)) 3197 continue; 3198 3199 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 3200 dbg_print(0, MSG_INTL(MSG_ELF_PHDR), EC_WORD(ndx)); 3201 Elf_phdr(0, ehdr->e_machine, phdr); 3202 } 3203 } 3204 3205 /* 3206 * Decide how to proceed if there are no sections, if there's just 3207 * one section (the first section can act as an extension of the 3208 * ELF header), or if only program header information was requested. 3209 */ 3210 if ((shnum <= 1) || (flags && (flags & ~(FLG_EHDR | FLG_PHDR)) == 0)) { 3211 /* If a core file, display the note and return */ 3212 if ((ehdr->e_type == ET_CORE) && (flags & FLG_NOTE)) { 3213 note(0, shnum, file); 3214 return; 3215 } 3216 3217 /* If only program header info was requested, we're done */ 3218 if (flags && (flags & ~(FLG_EHDR | FLG_PHDR)) == 0) 3219 return; 3220 3221 /* 3222 * Section headers are missing. Resort to synthesizing 3223 * section headers from the program headers. 3224 */ 3225 if ((flags & FLG_FAKESHDR) == 0) { 3226 (void) fprintf(stderr, MSG_INTL(MSG_ERR_NOSHDR), file); 3227 flags |= FLG_FAKESHDR; 3228 } 3229 } 3230 3231 /* 3232 * Generate a cache of section headers and related information 3233 * for use by the rest of elfdump. If requested (or the file 3234 * contains no section headers), we generate a fake set of 3235 * headers from the information accessible from the program headers. 3236 * Otherwise, we use the real section headers contained in the file. 3237 */ 3238 3239 if (flags & FLG_FAKESHDR) { 3240 if (fake_shdr_cache(file, fd, elf, ehdr, &cache, &shnum) == 0) 3241 return; 3242 } else { 3243 if (shdr_cache(file, elf, ehdr, shstrndx, shnum, &cache) == 0) 3244 return; 3245 } 3246 3247 /* 3248 * If -w was specified, find and write out the section(s) data. 3249 */ 3250 if (wfd) { 3251 for (ndx = 1; ndx < shnum; ndx++) { 3252 Cache *_cache = &cache[ndx]; 3253 3254 if (match(1, _cache->c_name, ndx) && _cache->c_data) { 3255 (void) write(wfd, _cache->c_data->d_buf, 3256 _cache->c_data->d_size); 3257 } 3258 } 3259 } 3260 3261 if (flags & FLG_SHDR) 3262 sections(file, cache, shnum, ehdr); 3263 3264 if (flags & FLG_INTERP) 3265 interp(file, cache, shnum, phnum, elf); 3266 3267 versions(cache, shnum, file, flags, &versym); 3268 3269 if (flags & FLG_SYMBOLS) 3270 symbols(cache, shnum, ehdr, &versym, file, flags); 3271 3272 if (flags & FLG_SORT) 3273 sunw_sort(cache, shnum, ehdr, &versym, file, flags); 3274 3275 if (flags & FLG_HASH) 3276 hash(cache, shnum, file, flags); 3277 3278 if (flags & FLG_GOT) 3279 got(cache, shnum, ehdr, file, flags); 3280 3281 if (flags & FLG_GROUP) 3282 group(cache, shnum, file, flags); 3283 3284 if (flags & FLG_SYMINFO) 3285 syminfo(cache, shnum, file); 3286 3287 if (flags & FLG_RELOC) 3288 reloc(cache, shnum, ehdr, file, flags); 3289 3290 if (flags & FLG_DYNAMIC) 3291 dynamic(cache, shnum, ehdr, file); 3292 3293 if (flags & FLG_NOTE) 3294 note(cache, shnum, file); 3295 3296 if (flags & FLG_MOVE) 3297 move(cache, shnum, file, flags); 3298 3299 if (flags & FLG_CHECKSUM) 3300 checksum(elf); 3301 3302 if (flags & FLG_CAP) 3303 cap(file, cache, shnum, phnum, ehdr, elf); 3304 3305 if (flags & FLG_UNWIND) 3306 unwind(cache, shnum, phnum, ehdr, file, elf); 3307 3308 3309 /* Release the memory used to cache section headers */ 3310 if (flags & FLG_FAKESHDR) 3311 fake_shdr_cache_free(cache, shnum); 3312 else 3313 free(cache); 3314 } 3315