10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1618Srie * Common Development and Distribution License (the "License"). 6*1618Srie * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211324Srie 220Sstevel@tonic-gate /* 231324Srie * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * Dump an elf file. 300Sstevel@tonic-gate */ 31*1618Srie #include <machdep.h> 32*1618Srie #include <sys/elf_386.h> 33*1618Srie #include <sys/elf_amd64.h> 34*1618Srie #include <sys/elf_SPARC.h> 35*1618Srie #include <dwarf.h> 360Sstevel@tonic-gate #include <unistd.h> 370Sstevel@tonic-gate #include <errno.h> 380Sstevel@tonic-gate #include <strings.h> 390Sstevel@tonic-gate #include <debug.h> 400Sstevel@tonic-gate #include <conv.h> 410Sstevel@tonic-gate #include <msg.h> 42*1618Srie #include <_elfdump.h> 430Sstevel@tonic-gate 440Sstevel@tonic-gate /* 450Sstevel@tonic-gate * Focal point for verifying symbol names. 460Sstevel@tonic-gate */ 470Sstevel@tonic-gate static const char * 48*1618Srie string(Cache *refsec, Word ndx, Cache *strsec, const char *file, Word name) 490Sstevel@tonic-gate { 500Sstevel@tonic-gate static Cache *osec = 0; 510Sstevel@tonic-gate static int nostr; 520Sstevel@tonic-gate 530Sstevel@tonic-gate const char *strs = (char *)strsec->c_data->d_buf; 54*1618Srie Word strn = strsec->c_data->d_size; 550Sstevel@tonic-gate 560Sstevel@tonic-gate /* 57*1618Srie * Only print a diagnostic regarding an empty string table once per 580Sstevel@tonic-gate * input section being processed. 590Sstevel@tonic-gate */ 600Sstevel@tonic-gate if (osec != refsec) { 610Sstevel@tonic-gate osec = refsec; 620Sstevel@tonic-gate nostr = 0; 630Sstevel@tonic-gate } 640Sstevel@tonic-gate 650Sstevel@tonic-gate /* 660Sstevel@tonic-gate * Is the string table offset within range of the available strings? 670Sstevel@tonic-gate */ 680Sstevel@tonic-gate if (name >= strn) { 690Sstevel@tonic-gate /* 700Sstevel@tonic-gate * Do we have a empty string table? 710Sstevel@tonic-gate */ 720Sstevel@tonic-gate if (strs == 0) { 730Sstevel@tonic-gate if (nostr == 0) { 740Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 750Sstevel@tonic-gate file, strsec->c_name); 760Sstevel@tonic-gate nostr++; 770Sstevel@tonic-gate } 780Sstevel@tonic-gate } else { 790Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSTOFF), 80*1618Srie file, refsec->c_name, EC_WORD(ndx), strsec->c_name, 81*1618Srie EC_WORD(name), EC_WORD(strn - 1)); 820Sstevel@tonic-gate } 830Sstevel@tonic-gate 840Sstevel@tonic-gate /* 850Sstevel@tonic-gate * Return the empty string so that the calling function can 860Sstevel@tonic-gate * continue it's output diagnostics. 870Sstevel@tonic-gate */ 880Sstevel@tonic-gate return (MSG_INTL(MSG_STR_UNKNOWN)); 890Sstevel@tonic-gate } 900Sstevel@tonic-gate return (strs + name); 910Sstevel@tonic-gate } 920Sstevel@tonic-gate 930Sstevel@tonic-gate /* 94*1618Srie * Relocations can reference section symbols and standard symbols. If the 95*1618Srie * former, establish the section name. 96*1618Srie */ 97*1618Srie static const char * 98*1618Srie relsymname(Cache *cache, Cache *csec, Cache *strsec, Word symndx, Word symnum, 99*1618Srie Word relndx, Sym *syms, char *secstr, size_t secsz, const char *file, 100*1618Srie uint_t flags) 101*1618Srie { 102*1618Srie Sym *sym; 103*1618Srie 104*1618Srie if (symndx >= symnum) { 105*1618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_RELBADSYMNDX), 106*1618Srie file, EC_WORD(symndx), EC_WORD(relndx)); 107*1618Srie return (MSG_INTL(MSG_STR_UNKNOWN)); 108*1618Srie } 109*1618Srie 110*1618Srie sym = (Sym *)(syms + symndx); 111*1618Srie 112*1618Srie /* 113*1618Srie * If the symbol represents a section offset construct an appropriate 114*1618Srie * string. 115*1618Srie */ 116*1618Srie if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) && (sym->st_name == 0)) { 117*1618Srie if (flags & FLG_LONGNAME) 118*1618Srie (void) snprintf(secstr, secsz, 119*1618Srie MSG_INTL(MSG_STR_L_SECTION), 120*1618Srie cache[sym->st_shndx].c_name); 121*1618Srie else 122*1618Srie (void) snprintf(secstr, secsz, 123*1618Srie MSG_INTL(MSG_STR_SECTION), 124*1618Srie cache[sym->st_shndx].c_name); 125*1618Srie return ((const char *)secstr); 126*1618Srie } 127*1618Srie 128*1618Srie return (string(csec, symndx, strsec, file, sym->st_name)); 129*1618Srie } 130*1618Srie 131*1618Srie /* 132*1618Srie * Focal point for establishing a string table section. Data such as the 133*1618Srie * dynamic information simply points to a string table. Data such as 134*1618Srie * relocations, reference a symbol table, which in turn is associated with a 135*1618Srie * string table. 1360Sstevel@tonic-gate */ 1370Sstevel@tonic-gate static int 138*1618Srie stringtbl(Cache *cache, int symtab, Word ndx, Word shnum, const char *file, 139*1618Srie Word *symnum, Cache **symsec, Cache **strsec) 140*1618Srie { 141*1618Srie Shdr *shdr = cache[ndx].c_shdr; 142*1618Srie 143*1618Srie if (symtab) { 144*1618Srie /* 145*1618Srie * Validate the symbol table section. 146*1618Srie */ 147*1618Srie if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 148*1618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 149*1618Srie file, cache[ndx].c_name, EC_WORD(shdr->sh_link)); 150*1618Srie return (0); 151*1618Srie } 152*1618Srie 153*1618Srie /* 154*1618Srie * Obtain, and verify the symbol table data. 155*1618Srie */ 156*1618Srie if (cache[ndx].c_data->d_buf == 0) { 157*1618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 158*1618Srie file, cache[ndx].c_name); 159*1618Srie return (0); 160*1618Srie } 161*1618Srie 162*1618Srie /* 163*1618Srie * Establish the string table index. 164*1618Srie */ 165*1618Srie ndx = shdr->sh_link; 166*1618Srie shdr = cache[ndx].c_shdr; 167*1618Srie 168*1618Srie /* 169*1618Srie * Return symbol table information. 170*1618Srie */ 171*1618Srie if (symnum) 172*1618Srie *symnum = (shdr->sh_size / shdr->sh_entsize); 173*1618Srie if (symsec) 174*1618Srie *symsec = &cache[ndx]; 175*1618Srie } 176*1618Srie 177*1618Srie /* 178*1618Srie * Validate the associated string table section. 179*1618Srie */ 180*1618Srie if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 181*1618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 182*1618Srie file, cache[ndx].c_name, EC_WORD(shdr->sh_link)); 183*1618Srie return (0); 184*1618Srie } 185*1618Srie 186*1618Srie if (strsec) 187*1618Srie *strsec = &cache[shdr->sh_link]; 188*1618Srie 189*1618Srie return (1); 190*1618Srie } 191*1618Srie 192*1618Srie /* 193*1618Srie * Lookup a symbol and set Sym accordingly. 194*1618Srie */ 195*1618Srie static int 196*1618Srie symlookup(const char *name, Cache *cache, Word shnum, Sym **sym, 1970Sstevel@tonic-gate Cache *symtab, const char *file) 1980Sstevel@tonic-gate { 199*1618Srie Shdr *shdr; 200*1618Srie Word symn, cnt; 201*1618Srie Sym *syms; 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate if (symtab == 0) 2040Sstevel@tonic-gate return (0); 2050Sstevel@tonic-gate 206*1618Srie shdr = symtab->c_shdr; 207*1618Srie 2080Sstevel@tonic-gate /* 2090Sstevel@tonic-gate * Determine the symbol data and number. 2100Sstevel@tonic-gate */ 2110Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 2120Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2130Sstevel@tonic-gate file, symtab->c_name); 2140Sstevel@tonic-gate return (0); 2150Sstevel@tonic-gate } 2160Sstevel@tonic-gate /* LINTED */ 217*1618Srie symn = (Word)(shdr->sh_size / shdr->sh_entsize); 218*1618Srie syms = (Sym *)symtab->c_data->d_buf; 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate /* 2210Sstevel@tonic-gate * Get the associated string table section. 2220Sstevel@tonic-gate */ 2230Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 2240Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 225*1618Srie file, symtab->c_name, EC_WORD(shdr->sh_link)); 2260Sstevel@tonic-gate return (0); 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate /* 2300Sstevel@tonic-gate * Loop through the symbol table to find a match. 2310Sstevel@tonic-gate */ 232*1618Srie for (cnt = 0; cnt < symn; syms++, cnt++) { 233*1618Srie const char *symname; 2340Sstevel@tonic-gate 235*1618Srie symname = string(symtab, cnt, &cache[shdr->sh_link], file, 236*1618Srie syms->st_name); 2370Sstevel@tonic-gate 238*1618Srie if (symname && (strcmp(name, symname) == 0)) { 239*1618Srie *sym = syms; 2400Sstevel@tonic-gate return (1); 2410Sstevel@tonic-gate } 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate return (0); 2440Sstevel@tonic-gate } 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate /* 2470Sstevel@tonic-gate * Print section headers. 2480Sstevel@tonic-gate */ 2490Sstevel@tonic-gate static void 250*1618Srie sections(const char *file, Cache *cache, Word shnum, Ehdr *ehdr, 251*1618Srie const char *name) 2520Sstevel@tonic-gate { 253*1618Srie size_t seccnt; 2540Sstevel@tonic-gate 255*1618Srie for (seccnt = 1; seccnt < shnum; seccnt++) { 256*1618Srie Cache *_cache = &cache[seccnt]; 257*1618Srie Shdr *shdr = _cache->c_shdr; 258*1618Srie const char *secname = _cache->c_name; 2590Sstevel@tonic-gate 260*1618Srie if (name && strcmp(name, secname)) 2610Sstevel@tonic-gate continue; 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate /* 2640Sstevel@tonic-gate * Although numerous section header entries can be zero, it's 2650Sstevel@tonic-gate * usually a sign of trouble if the name or type are zero. 2660Sstevel@tonic-gate */ 2670Sstevel@tonic-gate if (shdr->sh_type == 0) { 2680Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE), 269*1618Srie file, secname, EC_WORD(shdr->sh_type)); 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate if (shdr->sh_name == 0) { 2720Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHNAME), 273*1618Srie file, secname, EC_XWORD(shdr->sh_name)); 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate /* 2760Sstevel@tonic-gate * Use the empty string, rather than the fabricated 2770Sstevel@tonic-gate * name for the section output. 2780Sstevel@tonic-gate */ 279*1618Srie secname = MSG_ORIG(MSG_STR_EMPTY); 2800Sstevel@tonic-gate } 2810Sstevel@tonic-gate 2821324Srie /* 2831324Srie * Identify any sections that are suspicious. A .got section 2841324Srie * shouldn't exist in a relocatable object. 2851324Srie */ 2861324Srie if (ehdr->e_type == ET_REL) { 287*1618Srie if (strncmp(secname, MSG_ORIG(MSG_ELF_GOT), 2881324Srie MSG_ELF_GOT_SIZE) == 0) { 2891324Srie (void) fprintf(stderr, 290*1618Srie MSG_INTL(MSG_GOT_UNEXPECTED), file, 291*1618Srie secname); 2921324Srie } 2931324Srie } 2941324Srie 295*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 296*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SHDR), EC_WORD(seccnt), secname); 297*1618Srie Elf_shdr(0, ehdr->e_machine, shdr); 2980Sstevel@tonic-gate } 2990Sstevel@tonic-gate } 3000Sstevel@tonic-gate 301*1618Srie /* 302*1618Srie * A couple of instances of unwind data are printed as tables of 8 data items 303*1618Srie * expressed as 0x?? integers. 304*1618Srie */ 305*1618Srie #define UNWINDTBLSZ 10 + (8 * 5) + 1 306*1618Srie 307*1618Srie static void 308*1618Srie unwindtbl(uint64_t *ndx, uint_t len, uchar_t *data, uint64_t doff, 309*1618Srie const char *msg, const char *pre, size_t plen) 310*1618Srie { 311*1618Srie char buffer[UNWINDTBLSZ]; 312*1618Srie uint_t boff = plen, cnt = 0; 313*1618Srie 314*1618Srie dbg_print(0, msg); 315*1618Srie (void) strncpy(buffer, pre, UNWINDTBLSZ); 316*1618Srie 317*1618Srie while (*ndx < (len + 4)) { 318*1618Srie if (cnt == 8) { 319*1618Srie dbg_print(0, buffer); 320*1618Srie boff = plen; 321*1618Srie cnt = 0; 322*1618Srie } 323*1618Srie (void) snprintf(&buffer[boff], UNWINDTBLSZ - boff, 324*1618Srie MSG_ORIG(MSG_UNW_TBLENTRY), data[doff + (*ndx)++]); 325*1618Srie boff += 5; 326*1618Srie cnt++; 327*1618Srie } 328*1618Srie if (cnt) 329*1618Srie dbg_print(0, buffer); 330*1618Srie } 331*1618Srie 332*1618Srie /* 333*1618Srie * Obtain a specified Phdr entry. 334*1618Srie */ 335*1618Srie static Phdr * 336*1618Srie getphdr(Word phnum, Word type, const char *file, Elf *elf) 337*1618Srie { 338*1618Srie Word cnt; 339*1618Srie Phdr *phdr; 340*1618Srie 341*1618Srie if ((phdr = elf_getphdr(elf)) == NULL) { 342*1618Srie failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 343*1618Srie return (0); 344*1618Srie } 345*1618Srie 346*1618Srie for (cnt = 0; cnt < phnum; phdr++, cnt++) { 347*1618Srie if (phdr->p_type == type) 348*1618Srie return (phdr); 349*1618Srie } 350*1618Srie return (0); 351*1618Srie } 352*1618Srie 3530Sstevel@tonic-gate static void 354*1618Srie unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *name, 355*1618Srie const char *file, Elf *elf) 3560Sstevel@tonic-gate { 357*1618Srie Word cnt; 358*1618Srie Phdr *uphdr = 0; 359*1618Srie 3600Sstevel@tonic-gate /* 361*1618Srie * For the moment - UNWIND is only relevant for a AMD64 object. 3620Sstevel@tonic-gate */ 3630Sstevel@tonic-gate if (ehdr->e_machine != EM_AMD64) 364*1618Srie return; 3650Sstevel@tonic-gate 366*1618Srie if (phnum) 367*1618Srie uphdr = getphdr(phnum, PT_SUNW_UNWIND, file, elf); 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 370*1618Srie Cache *_cache = &cache[cnt]; 371*1618Srie Shdr *shdr = _cache->c_shdr; 372*1618Srie uchar_t *data; 3730Sstevel@tonic-gate size_t datasize; 374*1618Srie uint64_t off, ndx, frame_ptr, fde_cnt, tabndx; 375*1618Srie uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc; 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate /* 378*1618Srie * AMD64 - this is a strmcp() just to find the gcc produced 379*1618Srie * sections. Soon gcc should be setting the section type - and 380*1618Srie * we'll not need this strcmp(). 3810Sstevel@tonic-gate */ 3820Sstevel@tonic-gate if ((shdr->sh_type != SHT_AMD64_UNWIND) && 3830Sstevel@tonic-gate (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM), 3840Sstevel@tonic-gate MSG_SCN_FRM_SIZE) != 0) && 3850Sstevel@tonic-gate (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 3860Sstevel@tonic-gate MSG_SCN_FRMHDR_SIZE) != 0)) 3870Sstevel@tonic-gate continue; 3880Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 3890Sstevel@tonic-gate continue; 3900Sstevel@tonic-gate 391*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 392*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name); 3930Sstevel@tonic-gate 394*1618Srie data = (uchar_t *)(_cache->c_data->d_buf); 3950Sstevel@tonic-gate datasize = _cache->c_data->d_size; 3960Sstevel@tonic-gate off = 0; 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate /* 3990Sstevel@tonic-gate * Is this a .eh_frame_hdr 4000Sstevel@tonic-gate */ 401*1618Srie if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) || 4020Sstevel@tonic-gate (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 403*1618Srie MSG_SCN_FRMHDR_SIZE) == 0)) { 404*1618Srie 405*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR)); 406*1618Srie ndx = 0; 4070Sstevel@tonic-gate 408*1618Srie vers = data[ndx++]; 409*1618Srie frame_ptr_enc = data[ndx++]; 410*1618Srie fde_cnt_enc = data[ndx++]; 411*1618Srie table_enc = data[ndx++]; 4120Sstevel@tonic-gate 413*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers); 4140Sstevel@tonic-gate 415*1618Srie frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc, 416*1618Srie ehdr->e_ident, shdr->sh_addr + ndx); 4170Sstevel@tonic-gate 418*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC), 419*1618Srie conv_dwarf_ehe(frame_ptr_enc), EC_XWORD(frame_ptr)); 420*1618Srie 421*1618Srie fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc, 422*1618Srie ehdr->e_ident, shdr->sh_addr + ndx); 4230Sstevel@tonic-gate 424*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC), 425*1618Srie conv_dwarf_ehe(fde_cnt_enc), EC_XWORD(fde_cnt)); 426*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_TABENC), 427*1618Srie conv_dwarf_ehe(table_enc)); 428*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1)); 429*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2)); 4300Sstevel@tonic-gate 431*1618Srie for (tabndx = 0; tabndx < fde_cnt; tabndx++) { 432*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT), 433*1618Srie EC_XWORD(dwarf_ehe_extract(data, &ndx, 434*1618Srie table_enc, ehdr->e_ident, shdr->sh_addr)), 435*1618Srie EC_XWORD(dwarf_ehe_extract(data, &ndx, 436*1618Srie table_enc, ehdr->e_ident, shdr->sh_addr))); 437*1618Srie } 438*1618Srie continue; 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate /* 4420Sstevel@tonic-gate * Walk the Eh_frame's 4430Sstevel@tonic-gate */ 4440Sstevel@tonic-gate while (off < datasize) { 4450Sstevel@tonic-gate uint_t cieid, cielength, cieversion, 4460Sstevel@tonic-gate cieretaddr; 447*1618Srie int cieRflag, cieLflag, ciePflag, cieZflag; 448*1618Srie uint_t cieaugndx, length, id; 4490Sstevel@tonic-gate uint64_t ciecalign, ciedalign; 4500Sstevel@tonic-gate char *cieaugstr; 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate ndx = 0; 4530Sstevel@tonic-gate /* 4540Sstevel@tonic-gate * extract length in lsb format 4550Sstevel@tonic-gate */ 4560Sstevel@tonic-gate length = LSB32EXTRACT(data + off + ndx); 4570Sstevel@tonic-gate ndx += 4; 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate /* 4600Sstevel@tonic-gate * extract CIE id in lsb format 4610Sstevel@tonic-gate */ 4620Sstevel@tonic-gate id = LSB32EXTRACT(data + off + ndx); 4630Sstevel@tonic-gate ndx += 4; 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate /* 466*1618Srie * A CIE record has a id of '0', otherwise this is a 467*1618Srie * FDE entry and the 'id' is the CIE pointer. 4680Sstevel@tonic-gate */ 4690Sstevel@tonic-gate if (id == 0) { 4700Sstevel@tonic-gate uint64_t persVal; 471*1618Srie 4720Sstevel@tonic-gate cielength = length; 4730Sstevel@tonic-gate cieid = id; 474*1618Srie cieLflag = ciePflag = cieRflag = cieZflag = 0; 4750Sstevel@tonic-gate 476*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIE), 477*1618Srie EC_XWORD(shdr->sh_addr + off)); 478*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH), 479*1618Srie cielength, cieid); 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate cieversion = data[off + ndx]; 4820Sstevel@tonic-gate ndx += 1; 4830Sstevel@tonic-gate cieaugstr = (char *)(&data[off + ndx]); 4840Sstevel@tonic-gate ndx += strlen(cieaugstr) + 1; 485*1618Srie 486*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS), 487*1618Srie cieversion, cieaugstr); 488*1618Srie 4890Sstevel@tonic-gate ciecalign = uleb_extract(&data[off], &ndx); 4900Sstevel@tonic-gate ciedalign = sleb_extract(&data[off], &ndx); 4910Sstevel@tonic-gate cieretaddr = data[off + ndx]; 4920Sstevel@tonic-gate ndx += 1; 493*1618Srie 494*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN), 495*1618Srie EC_XWORD(ciecalign), EC_XWORD(ciedalign), 496*1618Srie cieretaddr); 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate if (cieaugstr[0]) 499*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIEAUXVAL)); 500*1618Srie 5010Sstevel@tonic-gate for (cieaugndx = 0; cieaugstr[cieaugndx]; 5020Sstevel@tonic-gate cieaugndx++) { 5030Sstevel@tonic-gate uint_t val; 504*1618Srie 5050Sstevel@tonic-gate switch (cieaugstr[cieaugndx]) { 5060Sstevel@tonic-gate case 'z': 5070Sstevel@tonic-gate val = uleb_extract(&data[off], 5080Sstevel@tonic-gate &ndx); 509*1618Srie dbg_print(0, 5100Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXSIZE), 5110Sstevel@tonic-gate val); 5120Sstevel@tonic-gate cieZflag = 1; 5130Sstevel@tonic-gate break; 5140Sstevel@tonic-gate case 'P': 5150Sstevel@tonic-gate ciePflag = data[off + ndx]; 5160Sstevel@tonic-gate ndx += 1; 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate persVal = dwarf_ehe_extract( 5190Sstevel@tonic-gate &data[off], 5200Sstevel@tonic-gate &ndx, ciePflag, ehdr->e_ident, 5210Sstevel@tonic-gate shdr->sh_addr + off + ndx); 522*1618Srie dbg_print(0, 5230Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXPERS), 5240Sstevel@tonic-gate ciePflag, 525*1618Srie conv_dwarf_ehe(ciePflag), 5260Sstevel@tonic-gate EC_XWORD(persVal)); 5270Sstevel@tonic-gate break; 5280Sstevel@tonic-gate case 'R': 5290Sstevel@tonic-gate val = data[off + ndx]; 5300Sstevel@tonic-gate ndx += 1; 531*1618Srie dbg_print(0, 5320Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXCENC), 533*1618Srie val, conv_dwarf_ehe(val)); 5340Sstevel@tonic-gate cieRflag = val; 5350Sstevel@tonic-gate break; 5360Sstevel@tonic-gate case 'L': 5370Sstevel@tonic-gate val = data[off + ndx]; 5380Sstevel@tonic-gate ndx += 1; 539*1618Srie dbg_print(0, 5400Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXLSDA), 541*1618Srie val, conv_dwarf_ehe(val)); 5420Sstevel@tonic-gate cieLflag = val; 5430Sstevel@tonic-gate break; 5440Sstevel@tonic-gate default: 545*1618Srie dbg_print(0, 5460Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXUNEC), 5470Sstevel@tonic-gate cieaugstr[cieaugndx]); 5480Sstevel@tonic-gate break; 5490Sstevel@tonic-gate } 5500Sstevel@tonic-gate } 551*1618Srie if ((cielength + 4) > ndx) 552*1618Srie unwindtbl(&ndx, cielength, data, off, 553*1618Srie MSG_ORIG(MSG_UNW_CIECFI), 554*1618Srie MSG_ORIG(MSG_UNW_CIEPRE), 555*1618Srie MSG_UNW_CIEPRE_SIZE); 5560Sstevel@tonic-gate off += cielength + 4; 557*1618Srie 5580Sstevel@tonic-gate } else { 5590Sstevel@tonic-gate uint_t fdelength = length; 5600Sstevel@tonic-gate int fdecieptr = id; 5610Sstevel@tonic-gate uint64_t fdeinitloc, fdeaddrrange; 5620Sstevel@tonic-gate 563*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FDE), 564*1618Srie EC_XWORD(shdr->sh_addr + off)); 565*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH), 5660Sstevel@tonic-gate fdelength, fdecieptr); 567*1618Srie 5680Sstevel@tonic-gate fdeinitloc = dwarf_ehe_extract(&data[off], 5690Sstevel@tonic-gate &ndx, cieRflag, ehdr->e_ident, 5700Sstevel@tonic-gate shdr->sh_addr + off + ndx); 5710Sstevel@tonic-gate fdeaddrrange = dwarf_ehe_extract(&data[off], 5720Sstevel@tonic-gate &ndx, (cieRflag & ~DW_EH_PE_pcrel), 5730Sstevel@tonic-gate ehdr->e_ident, 5740Sstevel@tonic-gate shdr->sh_addr + off + ndx); 575*1618Srie 576*1618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC), 577*1618Srie EC_XWORD(fdeinitloc), 578*1618Srie EC_XWORD(fdeaddrrange)); 579*1618Srie 5800Sstevel@tonic-gate if (cieaugstr[0]) 581*1618Srie dbg_print(0, 582*1618Srie MSG_ORIG(MSG_UNW_FDEAUXVAL)); 5830Sstevel@tonic-gate if (cieZflag) { 5840Sstevel@tonic-gate uint64_t val; 5850Sstevel@tonic-gate val = uleb_extract(&data[off], &ndx); 586*1618Srie dbg_print(0, 587*1618Srie MSG_ORIG(MSG_UNW_FDEAUXSIZE), 588*1618Srie EC_XWORD(val)); 5890Sstevel@tonic-gate if (val & cieLflag) { 5900Sstevel@tonic-gate fdeinitloc = dwarf_ehe_extract( 5910Sstevel@tonic-gate &data[off], &ndx, cieLflag, 5920Sstevel@tonic-gate ehdr->e_ident, 5930Sstevel@tonic-gate shdr->sh_addr + off + ndx); 594*1618Srie dbg_print(0, 5950Sstevel@tonic-gate MSG_ORIG(MSG_UNW_FDEAUXLSDA), 596*1618Srie EC_XWORD(val)); 5970Sstevel@tonic-gate } 5980Sstevel@tonic-gate } 599*1618Srie if ((fdelength + 4) > ndx) 600*1618Srie unwindtbl(&ndx, fdelength, data, off, 601*1618Srie MSG_ORIG(MSG_UNW_FDECFI), 602*1618Srie MSG_ORIG(MSG_UNW_FDEPRE), 603*1618Srie MSG_UNW_FDEPRE_SIZE); 6040Sstevel@tonic-gate off += fdelength + 4; 6050Sstevel@tonic-gate } 6060Sstevel@tonic-gate } 6070Sstevel@tonic-gate } 6080Sstevel@tonic-gate } 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate /* 6110Sstevel@tonic-gate * Print the hardware/software capabilities. For executables and shared objects 6120Sstevel@tonic-gate * this should be accompanied with a program header. 6130Sstevel@tonic-gate */ 6140Sstevel@tonic-gate static void 615*1618Srie cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, 616*1618Srie Elf *elf) 6170Sstevel@tonic-gate { 618*1618Srie Word cnt; 619*1618Srie Shdr * cshdr = 0; 6200Sstevel@tonic-gate Cache * ccache; 621*1618Srie Off cphdr_off = 0; 622*1618Srie Xword cphdr_sz; 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate /* 6250Sstevel@tonic-gate * Determine if a hardware/software capabilities header exists. 6260Sstevel@tonic-gate */ 627*1618Srie if (phnum) { 628*1618Srie Phdr *phdr; 6290Sstevel@tonic-gate 630*1618Srie if ((phdr = elf_getphdr(elf)) == NULL) { 6310Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 6320Sstevel@tonic-gate return; 6330Sstevel@tonic-gate } 6340Sstevel@tonic-gate 635*1618Srie for (cnt = 0; cnt < phnum; phdr++, cnt++) { 636*1618Srie if (phdr->p_type == PT_SUNWCAP) { 637*1618Srie cphdr_off = phdr->p_offset; 638*1618Srie cphdr_sz = phdr->p_filesz; 639*1618Srie break; 640*1618Srie } 6410Sstevel@tonic-gate } 6420Sstevel@tonic-gate } 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate /* 6450Sstevel@tonic-gate * Determine if a hardware/software capabilities section exists. 6460Sstevel@tonic-gate */ 6470Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 648*1618Srie Cache *_cache = &cache[cnt]; 649*1618Srie Shdr *shdr = _cache->c_shdr; 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate if (shdr->sh_type != SHT_SUNW_cap) 6520Sstevel@tonic-gate continue; 6530Sstevel@tonic-gate 6540Sstevel@tonic-gate if (cphdr_off && ((cphdr_off < shdr->sh_offset) || 6550Sstevel@tonic-gate (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size))) 6560Sstevel@tonic-gate continue; 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate ccache = _cache; 6590Sstevel@tonic-gate cshdr = shdr; 6600Sstevel@tonic-gate break; 6610Sstevel@tonic-gate } 6620Sstevel@tonic-gate 6630Sstevel@tonic-gate if ((cshdr == 0) && (cphdr_off == 0)) 6640Sstevel@tonic-gate return; 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate /* 6670Sstevel@tonic-gate * Print the hardware/software capabilities section. 6680Sstevel@tonic-gate */ 6690Sstevel@tonic-gate if (cshdr) { 670*1618Srie Word ndx, capn; 671*1618Srie Cap *cap = (Cap *)ccache->c_data->d_buf; 6720Sstevel@tonic-gate 673*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 674*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name); 6750Sstevel@tonic-gate 676*1618Srie Elf_cap_title(0); 677*1618Srie 678*1618Srie capn = (Word)(cshdr->sh_size / cshdr->sh_entsize); 6790Sstevel@tonic-gate 680*1618Srie for (ndx = 0; ndx < capn; cap++, ndx++) { 681*1618Srie if (cap->c_tag != CA_SUNW_NULL) 682*1618Srie Elf_cap_entry(0, cap, ndx, ehdr->e_machine); 6830Sstevel@tonic-gate } 6840Sstevel@tonic-gate } else 6850Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file); 6860Sstevel@tonic-gate 6870Sstevel@tonic-gate /* 6880Sstevel@tonic-gate * If this object is an executable or shared object, then the 6890Sstevel@tonic-gate * hardware/software capabilities section should have an accompanying 6900Sstevel@tonic-gate * program header. 6910Sstevel@tonic-gate */ 6920Sstevel@tonic-gate if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) { 6930Sstevel@tonic-gate if (cphdr_off == 0) 6940Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2), 6950Sstevel@tonic-gate file, ccache->c_name); 6960Sstevel@tonic-gate else if ((cphdr_off != cshdr->sh_offset) || 6970Sstevel@tonic-gate (cphdr_sz != cshdr->sh_size)) 6980Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3), 6990Sstevel@tonic-gate file, ccache->c_name); 7000Sstevel@tonic-gate } 7010Sstevel@tonic-gate } 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate /* 7040Sstevel@tonic-gate * Print the interpretor. 7050Sstevel@tonic-gate */ 7060Sstevel@tonic-gate static void 707*1618Srie interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf) 7080Sstevel@tonic-gate { 709*1618Srie Word cnt; 710*1618Srie Shdr *ishdr = 0; 711*1618Srie Cache *icache; 712*1618Srie Off iphdr_off = 0; 713*1618Srie Xword iphdr_fsz; 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate /* 7160Sstevel@tonic-gate * Determine if an interp header exists. 7170Sstevel@tonic-gate */ 718*1618Srie if (phnum) { 719*1618Srie Phdr *phdr; 7200Sstevel@tonic-gate 721*1618Srie if ((phdr = getphdr(phnum, PT_INTERP, file, elf)) != 0) { 722*1618Srie iphdr_off = phdr->p_offset; 723*1618Srie iphdr_fsz = phdr->p_filesz; 7240Sstevel@tonic-gate } 7250Sstevel@tonic-gate } 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate if (iphdr_off == 0) 7280Sstevel@tonic-gate return; 7290Sstevel@tonic-gate 7300Sstevel@tonic-gate /* 7310Sstevel@tonic-gate * Determine if an interp section exists. 7320Sstevel@tonic-gate */ 7330Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 734*1618Srie Cache *_cache = &cache[cnt]; 735*1618Srie Shdr *shdr = _cache->c_shdr; 7360Sstevel@tonic-gate 7370Sstevel@tonic-gate /* 7380Sstevel@tonic-gate * Scan sections to find a section which contains the PT_INTERP 7390Sstevel@tonic-gate * string. The target section can't be in a NOBITS section. 7400Sstevel@tonic-gate */ 7410Sstevel@tonic-gate if ((shdr->sh_type == SHT_NOBITS) || 7420Sstevel@tonic-gate (iphdr_off < shdr->sh_offset) || 743*1618Srie (iphdr_off + iphdr_fsz) > (shdr->sh_offset + shdr->sh_size)) 7440Sstevel@tonic-gate continue; 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate icache = _cache; 7470Sstevel@tonic-gate ishdr = shdr; 7480Sstevel@tonic-gate break; 7490Sstevel@tonic-gate } 7500Sstevel@tonic-gate 7510Sstevel@tonic-gate /* 7520Sstevel@tonic-gate * Print the interpreter string based on the offset defined in the 7530Sstevel@tonic-gate * program header, as this is the offset used by the kernel. 7540Sstevel@tonic-gate */ 7550Sstevel@tonic-gate if (ishdr) { 756*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 757*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name); 758*1618Srie dbg_print(0, MSG_ORIG(MSG_FMT_INDENT), 7590Sstevel@tonic-gate (char *)icache->c_data->d_buf + 7600Sstevel@tonic-gate (iphdr_off - ishdr->sh_offset)); 7610Sstevel@tonic-gate } else 7620Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file); 7630Sstevel@tonic-gate 7640Sstevel@tonic-gate /* 7650Sstevel@tonic-gate * If there are any inconsistences between the program header and 7660Sstevel@tonic-gate * section information, flag them. 7670Sstevel@tonic-gate */ 7680Sstevel@tonic-gate if (ishdr && ((iphdr_off != ishdr->sh_offset) || 769*1618Srie (iphdr_fsz != ishdr->sh_size))) { 7700Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file, 7710Sstevel@tonic-gate icache->c_name); 7720Sstevel@tonic-gate } 7730Sstevel@tonic-gate } 7740Sstevel@tonic-gate 7750Sstevel@tonic-gate /* 7760Sstevel@tonic-gate * Print the syminfo section. 7770Sstevel@tonic-gate */ 7780Sstevel@tonic-gate static void 779*1618Srie syminfo(Cache *cache, Word shnum, const char *file) 7800Sstevel@tonic-gate { 781*1618Srie Shdr *infoshdr; 782*1618Srie Syminfo *info; 783*1618Srie Sym *syms; 784*1618Srie Dyn *dyns; 785*1618Srie Word infonum, cnt, ndx, symnum; 786*1618Srie Cache *infocache = 0, *symsec, *strsec; 7870Sstevel@tonic-gate 7880Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 789*1618Srie if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) { 790*1618Srie infocache = &cache[cnt]; 7910Sstevel@tonic-gate break; 7920Sstevel@tonic-gate } 7930Sstevel@tonic-gate } 794*1618Srie if (infocache == 0) 7950Sstevel@tonic-gate return; 7960Sstevel@tonic-gate 797*1618Srie infoshdr = infocache->c_shdr; 798*1618Srie if ((infoshdr->sh_entsize == 0) || (infoshdr->sh_size == 0)) { 7990Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 800*1618Srie file, infocache->c_name); 8010Sstevel@tonic-gate return; 8020Sstevel@tonic-gate } 803*1618Srie infonum = (Word)(infoshdr->sh_size / infoshdr->sh_entsize); 804*1618Srie info = (Syminfo *)infocache->c_data->d_buf; 8050Sstevel@tonic-gate 8060Sstevel@tonic-gate /* 8070Sstevel@tonic-gate * Get the data buffer of the associated dynamic section. 8080Sstevel@tonic-gate */ 809*1618Srie if ((infoshdr->sh_info == 0) || (infoshdr->sh_info >= shnum)) { 8100Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 811*1618Srie file, infocache->c_name, EC_WORD(infoshdr->sh_info)); 8120Sstevel@tonic-gate return; 8130Sstevel@tonic-gate } 814*1618Srie dyns = cache[infoshdr->sh_info].c_data->d_buf; 815*1618Srie if (dyns == 0) { 8160Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 817*1618Srie file, cache[infoshdr->sh_info].c_name); 8180Sstevel@tonic-gate return; 8190Sstevel@tonic-gate } 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate /* 822*1618Srie * Get the data buffer for the associated symbol table and string table. 8230Sstevel@tonic-gate */ 824*1618Srie if (stringtbl(cache, 1, cnt, shnum, file, 825*1618Srie &symnum, &symsec, &strsec) == 0) 8260Sstevel@tonic-gate return; 8270Sstevel@tonic-gate 828*1618Srie syms = symsec->c_data->d_buf; 8290Sstevel@tonic-gate 830*1618Srie /* 831*1618Srie * Loop through the syminfo entries. 832*1618Srie */ 833*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 834*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMINFO), infocache->c_name); 835*1618Srie Elf_syminfo_title(0); 8360Sstevel@tonic-gate 837*1618Srie for (ndx = 1, info++; ndx < infonum; ndx++, info++) { 838*1618Srie Sym *sym; 839*1618Srie const char *needed = 0, *name; 840*1618Srie 841*1618Srie if ((info->si_flags == 0) && (info->si_boundto == 0)) 8420Sstevel@tonic-gate continue; 8430Sstevel@tonic-gate 844*1618Srie sym = &syms[ndx]; 845*1618Srie name = string(infocache, ndx, strsec, file, sym->st_name); 8460Sstevel@tonic-gate 847*1618Srie if (info->si_boundto < SYMINFO_BT_LOWRESERVE) { 848*1618Srie Dyn *dyn = &dyns[info->si_boundto]; 849*1618Srie 850*1618Srie needed = string(infocache, info->si_boundto, 851*1618Srie strsec, file, dyn->d_un.d_val); 8520Sstevel@tonic-gate } 853*1618Srie Elf_syminfo_entry(0, ndx, info, name, needed); 8540Sstevel@tonic-gate } 8550Sstevel@tonic-gate } 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate /* 8580Sstevel@tonic-gate * Print version definition section entries. 8590Sstevel@tonic-gate */ 8600Sstevel@tonic-gate static void 861*1618Srie version_def(Verdef *vdf, Word shnum, Cache *vcache, Cache *scache, 8620Sstevel@tonic-gate const char *file) 8630Sstevel@tonic-gate { 864*1618Srie Word cnt; 865*1618Srie char index[MAXNDXSIZE]; 8660Sstevel@tonic-gate 867*1618Srie Elf_ver_def_title(0); 8680Sstevel@tonic-gate 8690Sstevel@tonic-gate for (cnt = 1; cnt <= shnum; cnt++, 870*1618Srie vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) { 8710Sstevel@tonic-gate const char *name, *dep; 872*1618Srie Half vcnt = vdf->vd_cnt - 1; 873*1618Srie Half ndx = vdf->vd_ndx; 874*1618Srie Verdaux *vdap = (Verdaux *)((uintptr_t)vdf + 875*1618Srie vdf->vd_aux); 8760Sstevel@tonic-gate 8770Sstevel@tonic-gate /* 8780Sstevel@tonic-gate * Obtain the name and first dependency (if any). 8790Sstevel@tonic-gate */ 8800Sstevel@tonic-gate name = string(vcache, cnt, scache, file, vdap->vda_name); 881*1618Srie vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 8820Sstevel@tonic-gate if (vcnt) 8830Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, vdap->vda_name); 8840Sstevel@tonic-gate else 8850Sstevel@tonic-gate dep = MSG_ORIG(MSG_STR_EMPTY); 8860Sstevel@tonic-gate 8870Sstevel@tonic-gate (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX), 8880Sstevel@tonic-gate EC_XWORD(ndx)); 889*1618Srie Elf_ver_line_1(0, index, name, dep, 890*1618Srie conv_ver_flags(vdf->vd_flags)); 8910Sstevel@tonic-gate 8920Sstevel@tonic-gate /* 8930Sstevel@tonic-gate * Print any additional dependencies. 8940Sstevel@tonic-gate */ 8950Sstevel@tonic-gate if (vcnt) { 896*1618Srie vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 8970Sstevel@tonic-gate for (vcnt--; vcnt; vcnt--, 898*1618Srie vdap = (Verdaux *)((uintptr_t)vdap + 8990Sstevel@tonic-gate vdap->vda_next)) { 9000Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, 9010Sstevel@tonic-gate vdap->vda_name); 902*1618Srie Elf_ver_line_2(0, MSG_ORIG(MSG_STR_EMPTY), dep); 9030Sstevel@tonic-gate } 9040Sstevel@tonic-gate } 9050Sstevel@tonic-gate } 9060Sstevel@tonic-gate } 9070Sstevel@tonic-gate 9080Sstevel@tonic-gate /* 9090Sstevel@tonic-gate * Print a version needed section entries. 9100Sstevel@tonic-gate */ 9110Sstevel@tonic-gate static void 912*1618Srie version_need(Verneed *vnd, Word shnum, Cache *vcache, Cache *scache, 9130Sstevel@tonic-gate const char *file) 9140Sstevel@tonic-gate { 915*1618Srie Word cnt; 9160Sstevel@tonic-gate 917*1618Srie Elf_ver_need_title(0); 9180Sstevel@tonic-gate 9190Sstevel@tonic-gate for (cnt = 1; cnt <= shnum; cnt++, 920*1618Srie vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 9210Sstevel@tonic-gate const char *name, *dep; 922*1618Srie Half vcnt = vnd->vn_cnt; 923*1618Srie Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + 924*1618Srie vnd->vn_aux); 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate /* 9270Sstevel@tonic-gate * Obtain the name of the needed file and the version name 9280Sstevel@tonic-gate * within it that we're dependent on. Note that the count 9290Sstevel@tonic-gate * should be at least one, otherwise this is a pretty bogus 9300Sstevel@tonic-gate * entry. 9310Sstevel@tonic-gate */ 9320Sstevel@tonic-gate name = string(vcache, cnt, scache, file, vnd->vn_file); 9330Sstevel@tonic-gate if (vcnt) 9340Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, vnap->vna_name); 9350Sstevel@tonic-gate else 9360Sstevel@tonic-gate dep = MSG_INTL(MSG_STR_NULL); 9370Sstevel@tonic-gate 938*1618Srie Elf_ver_line_1(0, MSG_ORIG(MSG_STR_EMPTY), name, dep, 939*1618Srie conv_ver_flags(vnap->vna_flags)); 9400Sstevel@tonic-gate 9410Sstevel@tonic-gate /* 9420Sstevel@tonic-gate * Print any additional version dependencies. 9430Sstevel@tonic-gate */ 9440Sstevel@tonic-gate if (vcnt) { 945*1618Srie vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next); 9460Sstevel@tonic-gate for (vcnt--; vcnt; vcnt--, 947*1618Srie vnap = (Vernaux *)((uintptr_t)vnap + 9480Sstevel@tonic-gate vnap->vna_next)) { 9490Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, 9500Sstevel@tonic-gate vnap->vna_name); 951*1618Srie Elf_ver_line_3(0, MSG_ORIG(MSG_STR_EMPTY), dep, 952*1618Srie conv_ver_flags(vnap->vna_flags)); 9530Sstevel@tonic-gate } 9540Sstevel@tonic-gate } 9550Sstevel@tonic-gate } 9560Sstevel@tonic-gate } 9570Sstevel@tonic-gate 9580Sstevel@tonic-gate /* 959*1618Srie * Search for any version sections - the Versym output is possibly used by the 960*1618Srie * symbols() printing. If VERSYM is specified - then display the version 961*1618Srie * information. 9620Sstevel@tonic-gate */ 9630Sstevel@tonic-gate static Cache * 964*1618Srie versions(Cache *cache, Word shnum, const char *file, uint_t flags) 9650Sstevel@tonic-gate { 9660Sstevel@tonic-gate GElf_Word cnt; 9670Sstevel@tonic-gate Cache *versymcache = 0; 9680Sstevel@tonic-gate 9690Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 970*1618Srie void *ver; 9710Sstevel@tonic-gate uint_t num; 972*1618Srie Cache *_cache = &cache[cnt]; 973*1618Srie Shdr *shdr = _cache->c_shdr; 974*1618Srie const char *secname = _cache->c_name; 9750Sstevel@tonic-gate 9760Sstevel@tonic-gate /* 9770Sstevel@tonic-gate * If this is the version symbol table simply record its 9780Sstevel@tonic-gate * data address for possible use in later symbol processing. 9790Sstevel@tonic-gate */ 9800Sstevel@tonic-gate if (shdr->sh_type == SHT_SUNW_versym) { 9810Sstevel@tonic-gate versymcache = _cache; 9820Sstevel@tonic-gate continue; 9830Sstevel@tonic-gate } 9840Sstevel@tonic-gate 9850Sstevel@tonic-gate if ((flags & FLG_VERSIONS) == 0) 9860Sstevel@tonic-gate continue; 9870Sstevel@tonic-gate 9880Sstevel@tonic-gate if ((shdr->sh_type != SHT_SUNW_verdef) && 9890Sstevel@tonic-gate (shdr->sh_type != SHT_SUNW_verneed)) 9900Sstevel@tonic-gate continue; 9910Sstevel@tonic-gate 9920Sstevel@tonic-gate /* 9930Sstevel@tonic-gate * Determine the version section data and number. 9940Sstevel@tonic-gate */ 9950Sstevel@tonic-gate if ((ver = (void *)_cache->c_data->d_buf) == 0) { 9960Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 997*1618Srie file, secname); 9980Sstevel@tonic-gate continue; 9990Sstevel@tonic-gate } 10000Sstevel@tonic-gate if ((num = shdr->sh_info) == 0) { 10010Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 1002*1618Srie file, secname, EC_WORD(shdr->sh_info)); 10030Sstevel@tonic-gate continue; 10040Sstevel@tonic-gate } 10050Sstevel@tonic-gate 10060Sstevel@tonic-gate /* 10070Sstevel@tonic-gate * Get the data buffer for the associated string table. 10080Sstevel@tonic-gate */ 10090Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 10100Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1011*1618Srie file, secname, EC_WORD(shdr->sh_link)); 10120Sstevel@tonic-gate continue; 10130Sstevel@tonic-gate } 10140Sstevel@tonic-gate 1015*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 10160Sstevel@tonic-gate if (shdr->sh_type == SHT_SUNW_verdef) { 1017*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERDEF), secname); 1018*1618Srie version_def((Verdef *)ver, num, _cache, 10190Sstevel@tonic-gate &cache[shdr->sh_link], file); 10200Sstevel@tonic-gate } else if (shdr->sh_type == SHT_SUNW_verneed) { 1021*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERNEED), secname); 1022*1618Srie version_need((Verneed *)ver, num, _cache, 10230Sstevel@tonic-gate &cache[shdr->sh_link], file); 10240Sstevel@tonic-gate } 10250Sstevel@tonic-gate } 10260Sstevel@tonic-gate return (versymcache); 10270Sstevel@tonic-gate } 10280Sstevel@tonic-gate 10290Sstevel@tonic-gate /* 1030*1618Srie * Determine the extended section index used for symbol tables entries. 1031*1618Srie */ 1032*1618Srie static int 1033*1618Srie symbols_getxindex(Cache *cache, Word shnum, Word seccnt, Word **shxndx, 1034*1618Srie uint_t *symnshxndx) 1035*1618Srie { 1036*1618Srie uint_t symn; 1037*1618Srie Word symcnt; 1038*1618Srie 1039*1618Srie for (symcnt = 1; symcnt < shnum; symcnt++) { 1040*1618Srie Cache *_cache = &cache[symcnt]; 1041*1618Srie Shdr *shdr = _cache->c_shdr; 1042*1618Srie 1043*1618Srie if ((shdr->sh_type != SHT_SYMTAB_SHNDX) || 1044*1618Srie (shdr->sh_link != seccnt)) 1045*1618Srie continue; 1046*1618Srie 1047*1618Srie if ((shdr->sh_entsize) && 1048*1618Srie /* LINTED */ 1049*1618Srie ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0)) 1050*1618Srie continue; 1051*1618Srie 1052*1618Srie *shxndx = _cache->c_data->d_buf; 1053*1618Srie *symnshxndx = symn; 1054*1618Srie return (0); 1055*1618Srie } 1056*1618Srie return (1); 1057*1618Srie } 1058*1618Srie 1059*1618Srie /* 10600Sstevel@tonic-gate * Search for and process any symbol tables. 10610Sstevel@tonic-gate */ 1062*1618Srie void 1063*1618Srie symbols(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, 1064*1618Srie Cache *versymcache, const char *file, uint_t flags) 10650Sstevel@tonic-gate { 1066*1618Srie Word seccnt; 1067*1618Srie char is_core = (ehdr->e_type == ET_CORE); 10680Sstevel@tonic-gate 1069*1618Srie for (seccnt = 1; seccnt < shnum; seccnt++) { 1070*1618Srie Word symn, symcnt, *shxndx; 1071*1618Srie Versym *versym; 1072*1618Srie Cache *_cache = &cache[seccnt]; 1073*1618Srie Shdr *shdr = _cache->c_shdr; 1074*1618Srie const char *secname = _cache->c_name; 1075*1618Srie Sym *sym; 1076*1618Srie int noshxndx; 1077*1618Srie uint_t symnshxndx; 10780Sstevel@tonic-gate 10790Sstevel@tonic-gate if ((shdr->sh_type != SHT_SYMTAB) && 10800Sstevel@tonic-gate (shdr->sh_type != SHT_DYNSYM)) 10810Sstevel@tonic-gate continue; 1082*1618Srie if (name && strcmp(name, secname)) 10830Sstevel@tonic-gate continue; 10840Sstevel@tonic-gate 10850Sstevel@tonic-gate /* 10860Sstevel@tonic-gate * Determine the symbol data and number. 10870Sstevel@tonic-gate */ 10880Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 10890Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1090*1618Srie file, secname); 10910Sstevel@tonic-gate continue; 10920Sstevel@tonic-gate } 10930Sstevel@tonic-gate /* LINTED */ 1094*1618Srie symn = (Word)(shdr->sh_size / shdr->sh_entsize); 1095*1618Srie sym = (Sym *)_cache->c_data->d_buf; 10960Sstevel@tonic-gate 10970Sstevel@tonic-gate /* 10980Sstevel@tonic-gate * Get the associated string table section. 10990Sstevel@tonic-gate */ 11000Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 11010Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1102*1618Srie file, secname, EC_WORD(shdr->sh_link)); 11030Sstevel@tonic-gate continue; 11040Sstevel@tonic-gate } 11050Sstevel@tonic-gate 11060Sstevel@tonic-gate /* 11070Sstevel@tonic-gate * Determine if there is a associated Versym section 11080Sstevel@tonic-gate * with this Symbol Table. 11090Sstevel@tonic-gate */ 1110*1618Srie if (versymcache && (versymcache->c_shdr->sh_link == seccnt)) 11110Sstevel@tonic-gate versym = versymcache->c_data->d_buf; 11120Sstevel@tonic-gate else 11130Sstevel@tonic-gate versym = 0; 11140Sstevel@tonic-gate 11150Sstevel@tonic-gate /* 11160Sstevel@tonic-gate * Loop through the symbol tables entries. 11170Sstevel@tonic-gate */ 1118*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1119*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), secname); 1120*1618Srie Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 11210Sstevel@tonic-gate 1122*1618Srie shxndx = 0; 1123*1618Srie noshxndx = 0; 1124*1618Srie symnshxndx = 0; 1125*1618Srie for (symcnt = 0; symcnt < symn; sym++, symcnt++) { 1126*1618Srie char index[MAXNDXSIZE], *sec; 1127*1618Srie const char *symname; 11280Sstevel@tonic-gate int verndx; 11290Sstevel@tonic-gate uchar_t type; 1130*1618Srie Shdr *tshdr; 11310Sstevel@tonic-gate Word shndx; 11320Sstevel@tonic-gate 11330Sstevel@tonic-gate /* 11340Sstevel@tonic-gate * If we are using extended symbol indexes, find the 11350Sstevel@tonic-gate * corresponding SHN_SYMTAB_SHNDX table. 11360Sstevel@tonic-gate */ 1137*1618Srie if ((sym->st_shndx == SHN_XINDEX) && 1138*1618Srie (shxndx == 0) && (noshxndx == 0)) 1139*1618Srie noshxndx = symbols_getxindex(cache, shnum, 1140*1618Srie seccnt, &shxndx, &symnshxndx); 11410Sstevel@tonic-gate 11420Sstevel@tonic-gate /* LINTED */ 1143*1618Srie symname = string(_cache, symcnt, &cache[shdr->sh_link], 1144*1618Srie file, sym->st_name); 11450Sstevel@tonic-gate 11460Sstevel@tonic-gate tshdr = 0; 11470Sstevel@tonic-gate sec = NULL; 11480Sstevel@tonic-gate 11490Sstevel@tonic-gate if (is_core) 11500Sstevel@tonic-gate sec = (char *)MSG_INTL(MSG_STR_UNKNOWN); 1151*1618Srie else if ((sym->st_shndx < SHN_LORESERVE) && 1152*1618Srie (sym->st_shndx < shnum)) { 1153*1618Srie shndx = sym->st_shndx; 1154*1618Srie tshdr = cache[shndx].c_shdr; 11550Sstevel@tonic-gate sec = cache[shndx].c_name; 1156*1618Srie } else if (sym->st_shndx == SHN_XINDEX) { 1157*1618Srie if (shxndx) { 1158*1618Srie Word _shxndx; 11590Sstevel@tonic-gate 1160*1618Srie if (symcnt > symnshxndx) { 11610Sstevel@tonic-gate (void) fprintf(stderr, 11620Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYMXINDEX1), 1163*1618Srie file, secname, EC_WORD(symcnt)); 1164*1618Srie } else if ((_shxndx = 1165*1618Srie shxndx[symcnt]) > shnum) { 11660Sstevel@tonic-gate (void) fprintf(stderr, 11670Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYMXINDEX2), 1168*1618Srie file, secname, EC_WORD(symcnt), 1169*1618Srie EC_WORD(_shxndx)); 11700Sstevel@tonic-gate } else { 1171*1618Srie shndx = _shxndx; 1172*1618Srie tshdr = cache[shndx].c_shdr; 11730Sstevel@tonic-gate sec = cache[shndx].c_name; 11740Sstevel@tonic-gate } 11750Sstevel@tonic-gate } else { 11760Sstevel@tonic-gate (void) fprintf(stderr, 1177*1618Srie MSG_INTL(MSG_ERR_BADSYMXINDEX3), 1178*1618Srie file, secname, EC_WORD(symcnt)); 11790Sstevel@tonic-gate } 1180*1618Srie } else if ((sym->st_shndx < SHN_LORESERVE) && 1181*1618Srie (sym->st_shndx >= shnum)) { 11820Sstevel@tonic-gate (void) fprintf(stderr, 1183*1618Srie MSG_INTL(MSG_ERR_BADSYM5), file, 1184*1618Srie secname, demangle(symname, flags), 1185*1618Srie sym->st_shndx); 11860Sstevel@tonic-gate } 11870Sstevel@tonic-gate 11880Sstevel@tonic-gate /* 11890Sstevel@tonic-gate * If versioning is available display the 11900Sstevel@tonic-gate * version index. 11910Sstevel@tonic-gate */ 11920Sstevel@tonic-gate if (versym) 1193*1618Srie verndx = (int)versym[symcnt]; 11940Sstevel@tonic-gate else 11950Sstevel@tonic-gate verndx = 0; 11960Sstevel@tonic-gate 11970Sstevel@tonic-gate /* 11980Sstevel@tonic-gate * Error checking for TLS. 11990Sstevel@tonic-gate */ 1200*1618Srie type = ELF_ST_TYPE(sym->st_info); 12010Sstevel@tonic-gate if (type == STT_TLS) { 12020Sstevel@tonic-gate if (tshdr && 1203*1618Srie (sym->st_shndx != SHN_UNDEF) && 12040Sstevel@tonic-gate ((tshdr->sh_flags & SHF_TLS) == 0)) { 12050Sstevel@tonic-gate (void) fprintf(stderr, 12060Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYM3), file, 1207*1618Srie secname, demangle(symname, flags)); 12080Sstevel@tonic-gate } 1209*1618Srie } else if ((type != STT_SECTION) && sym->st_size && 12100Sstevel@tonic-gate tshdr && (tshdr->sh_flags & SHF_TLS)) { 12110Sstevel@tonic-gate (void) fprintf(stderr, 12120Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYM4), file, 1213*1618Srie secname, demangle(symname, flags)); 12140Sstevel@tonic-gate } 12150Sstevel@tonic-gate 12160Sstevel@tonic-gate /* 12170Sstevel@tonic-gate * If a symbol has size, then make sure the section it 12180Sstevel@tonic-gate * references is appropriate. Note, UNDEF symbols that 12190Sstevel@tonic-gate * have a size, have been known to exist - ignore them. 12200Sstevel@tonic-gate */ 1221*1618Srie if (sym->st_size && shndx && tshdr && 1222*1618Srie (tshdr->sh_size < sym->st_size)) { 12230Sstevel@tonic-gate (void) fprintf(stderr, 12240Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYM6), file, 1225*1618Srie secname, demangle(symname, flags), 1226*1618Srie EC_WORD(shndx), EC_XWORD(tshdr->sh_size), 1227*1618Srie EC_XWORD(sym->st_size)); 12280Sstevel@tonic-gate } 12290Sstevel@tonic-gate 12300Sstevel@tonic-gate (void) snprintf(index, MAXNDXSIZE, 1231*1618Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symcnt)); 1232*1618Srie Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index, 1233*1618Srie ehdr->e_machine, sym, verndx, sec, symname); 12340Sstevel@tonic-gate } 12350Sstevel@tonic-gate } 12360Sstevel@tonic-gate } 12370Sstevel@tonic-gate 12380Sstevel@tonic-gate /* 12390Sstevel@tonic-gate * Search for and process any relocation sections. 12400Sstevel@tonic-gate */ 12410Sstevel@tonic-gate static void 1242*1618Srie reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, const char *file, 1243*1618Srie uint_t flags) 12440Sstevel@tonic-gate { 1245*1618Srie Word cnt; 12460Sstevel@tonic-gate 12470Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 1248*1618Srie Word type, symnum; 1249*1618Srie Xword relndx, relnum, relsize; 1250*1618Srie void *rels; 1251*1618Srie Sym *syms; 1252*1618Srie Cache *symsec, *strsec; 12530Sstevel@tonic-gate Cache *_cache = &cache[cnt]; 1254*1618Srie Shdr *shdr = _cache->c_shdr; 1255*1618Srie char *relname = _cache->c_name; 12560Sstevel@tonic-gate 12570Sstevel@tonic-gate if (((type = shdr->sh_type) != SHT_RELA) && 12580Sstevel@tonic-gate (type != SHT_REL)) 12590Sstevel@tonic-gate continue; 1260*1618Srie if (name && strcmp(name, relname)) 12610Sstevel@tonic-gate continue; 12620Sstevel@tonic-gate 12630Sstevel@tonic-gate /* 1264*1618Srie * Decide entry size. 12650Sstevel@tonic-gate */ 1266*1618Srie if (((relsize = shdr->sh_entsize) == 0) || 1267*1618Srie (relsize > shdr->sh_size)) { 12680Sstevel@tonic-gate if (type == SHT_RELA) 1269*1618Srie relsize = sizeof (Rela); 12700Sstevel@tonic-gate else 1271*1618Srie relsize = sizeof (Rel); 12720Sstevel@tonic-gate } 12730Sstevel@tonic-gate 12740Sstevel@tonic-gate /* 12750Sstevel@tonic-gate * Determine the number of relocations available. 12760Sstevel@tonic-gate */ 12770Sstevel@tonic-gate if (shdr->sh_size == 0) { 12780Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1279*1618Srie file, relname); 12800Sstevel@tonic-gate continue; 12810Sstevel@tonic-gate } 1282*1618Srie rels = _cache->c_data->d_buf; 1283*1618Srie relnum = shdr->sh_size / relsize; 12840Sstevel@tonic-gate 12850Sstevel@tonic-gate /* 1286*1618Srie * Get the data buffer for the associated symbol table and 1287*1618Srie * string table. 12880Sstevel@tonic-gate */ 1289*1618Srie if (stringtbl(cache, 1, cnt, shnum, file, 1290*1618Srie &symnum, &symsec, &strsec) == 0) 12910Sstevel@tonic-gate continue; 1292*1618Srie 1293*1618Srie syms = symsec->c_data->d_buf; 12940Sstevel@tonic-gate 12950Sstevel@tonic-gate /* 12960Sstevel@tonic-gate * Loop through the relocation entries. 12970Sstevel@tonic-gate */ 1298*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1299*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name); 1300*1618Srie Elf_reloc_title(0, ELF_DBG_ELFDUMP, type); 13010Sstevel@tonic-gate 1302*1618Srie for (relndx = 0; relndx < relnum; relndx++, 1303*1618Srie rels = (void *)((char *)rels + relsize)) { 13040Sstevel@tonic-gate char section[BUFSIZ]; 1305*1618Srie const char *symname; 1306*1618Srie Word symndx, reltype; 1307*1618Srie Rela *rela; 1308*1618Srie Rel *rel; 13090Sstevel@tonic-gate 13100Sstevel@tonic-gate /* 1311*1618Srie * Unravel the relocation and determine the symbol with 1312*1618Srie * which this relocation is associated. 13130Sstevel@tonic-gate */ 13140Sstevel@tonic-gate if (type == SHT_RELA) { 1315*1618Srie rela = (Rela *)rels; 1316*1618Srie symndx = ELF_R_SYM(rela->r_info); 1317*1618Srie reltype = ELF_R_TYPE(rela->r_info); 13180Sstevel@tonic-gate } else { 1319*1618Srie rel = (Rel *)rels; 1320*1618Srie symndx = ELF_R_SYM(rel->r_info); 1321*1618Srie reltype = ELF_R_TYPE(rel->r_info); 13220Sstevel@tonic-gate } 1323*1618Srie 1324*1618Srie symname = relsymname(cache, _cache, strsec, symndx, 1325*1618Srie symnum, relndx, syms, section, BUFSIZ, file, 1326*1618Srie flags); 1327*1618Srie 1328*1618Srie /* 1329*1618Srie * A zero symbol index is only valid for a few 1330*1618Srie * relocations. 1331*1618Srie */ 1332*1618Srie if (symndx == 0) { 1333*1618Srie Half mach = ehdr->e_machine; 1334*1618Srie int badrel = 0; 13350Sstevel@tonic-gate 1336*1618Srie if ((mach == EM_SPARC) || 1337*1618Srie (mach == EM_SPARC32PLUS) || 1338*1618Srie (mach == EM_SPARCV9)) { 1339*1618Srie if ((reltype != R_SPARC_NONE) && 1340*1618Srie (reltype != R_SPARC_REGISTER) && 1341*1618Srie (reltype != R_SPARC_RELATIVE)) 1342*1618Srie badrel++; 1343*1618Srie } else if (mach == EM_386) { 1344*1618Srie if ((reltype != R_386_NONE) && 1345*1618Srie (reltype != R_386_RELATIVE)) 1346*1618Srie badrel++; 1347*1618Srie } else if (mach == EM_AMD64) { 1348*1618Srie if ((reltype != R_AMD64_NONE) && 1349*1618Srie (reltype != R_AMD64_RELATIVE)) 1350*1618Srie badrel++; 1351*1618Srie } 1352*1618Srie 1353*1618Srie if (badrel) { 1354*1618Srie (void) fprintf(stderr, 1355*1618Srie MSG_INTL(MSG_ERR_BADREL1), file, 1356*1618Srie conv_reloc_type(mach, reltype)); 13570Sstevel@tonic-gate } 13580Sstevel@tonic-gate } 13590Sstevel@tonic-gate 1360*1618Srie Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP, 1361*1618Srie MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type, 1362*1618Srie rels, relname, symname, 0); 13630Sstevel@tonic-gate } 13640Sstevel@tonic-gate } 13650Sstevel@tonic-gate } 13660Sstevel@tonic-gate 13670Sstevel@tonic-gate /* 13680Sstevel@tonic-gate * Search for and process a .dynamic section. 13690Sstevel@tonic-gate */ 13700Sstevel@tonic-gate static void 1371*1618Srie dynamic(Cache *cache, Word shnum, Ehdr *ehdr, const char *file) 13720Sstevel@tonic-gate { 1373*1618Srie Word cnt; 13740Sstevel@tonic-gate 13750Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 1376*1618Srie Dyn *dyn; 1377*1618Srie ulong_t numdyn; 1378*1618Srie int ndx; 1379*1618Srie Cache *_cache = &cache[cnt], *strsec; 1380*1618Srie Shdr *shdr = _cache->c_shdr; 13810Sstevel@tonic-gate 13820Sstevel@tonic-gate if (shdr->sh_type != SHT_DYNAMIC) 13830Sstevel@tonic-gate continue; 13840Sstevel@tonic-gate 13850Sstevel@tonic-gate /* 1386*1618Srie * Verify the associated string table section. 13870Sstevel@tonic-gate */ 1388*1618Srie if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0) 13890Sstevel@tonic-gate continue; 1390*1618Srie 13910Sstevel@tonic-gate numdyn = shdr->sh_size / shdr->sh_entsize; 1392*1618Srie dyn = (Dyn *)_cache->c_data->d_buf; 13930Sstevel@tonic-gate 1394*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1395*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name); 13960Sstevel@tonic-gate 1397*1618Srie Elf_dyn_title(0); 13980Sstevel@tonic-gate 1399*1618Srie for (ndx = 0; ndx < numdyn; dyn++, ndx++) { 1400*1618Srie const char *name; 14010Sstevel@tonic-gate 14020Sstevel@tonic-gate /* 14030Sstevel@tonic-gate * Print the information numerically, and if possible 14040Sstevel@tonic-gate * as a string. 14050Sstevel@tonic-gate */ 1406*1618Srie if ((dyn->d_tag == DT_NEEDED) || 1407*1618Srie (dyn->d_tag == DT_SONAME) || 1408*1618Srie (dyn->d_tag == DT_FILTER) || 1409*1618Srie (dyn->d_tag == DT_AUXILIARY) || 1410*1618Srie (dyn->d_tag == DT_CONFIG) || 1411*1618Srie (dyn->d_tag == DT_RPATH) || 1412*1618Srie (dyn->d_tag == DT_RUNPATH) || 1413*1618Srie (dyn->d_tag == DT_USED) || 1414*1618Srie (dyn->d_tag == DT_DEPAUDIT) || 1415*1618Srie (dyn->d_tag == DT_AUDIT) || 1416*1618Srie (dyn->d_tag == DT_SUNW_AUXILIARY) || 1417*1618Srie (dyn->d_tag == DT_SUNW_FILTER)) 1418*1618Srie name = string(_cache, ndx, strsec, 1419*1618Srie file, dyn->d_un.d_ptr); 1420*1618Srie else if (dyn->d_tag == DT_FLAGS) 1421*1618Srie name = conv_dyn_flag(dyn->d_un.d_val); 1422*1618Srie else if (dyn->d_tag == DT_FLAGS_1) 1423*1618Srie name = conv_dyn_flag1(dyn->d_un.d_val); 1424*1618Srie else if (dyn->d_tag == DT_POSFLAG_1) 1425*1618Srie name = conv_dyn_posflag1(dyn->d_un.d_val); 1426*1618Srie else if (dyn->d_tag == DT_FEATURE_1) 1427*1618Srie name = conv_dyn_feature1(dyn->d_un.d_val); 1428*1618Srie else if (dyn->d_tag == DT_DEPRECATED_SPARC_REGISTER) 1429*1618Srie name = MSG_INTL(MSG_STR_DEPRECATED); 14300Sstevel@tonic-gate else 1431*1618Srie name = MSG_ORIG(MSG_STR_EMPTY); 14320Sstevel@tonic-gate 1433*1618Srie Elf_dyn_entry(0, dyn, ndx, name, ehdr->e_machine); 14340Sstevel@tonic-gate } 14350Sstevel@tonic-gate } 14360Sstevel@tonic-gate } 14370Sstevel@tonic-gate 14380Sstevel@tonic-gate /* 14390Sstevel@tonic-gate * Search for and process a MOVE section. 14400Sstevel@tonic-gate */ 14410Sstevel@tonic-gate static void 1442*1618Srie move(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags) 14430Sstevel@tonic-gate { 1444*1618Srie Word cnt; 1445*1618Srie const char *fmt = 0; 14460Sstevel@tonic-gate 14470Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 1448*1618Srie Word movenum, symnum, ndx; 1449*1618Srie Sym *syms; 1450*1618Srie Cache *_cache = &cache[cnt]; 1451*1618Srie Shdr *shdr = _cache->c_shdr; 1452*1618Srie Cache *symsec, *strsec; 1453*1618Srie Move *move; 14540Sstevel@tonic-gate 14550Sstevel@tonic-gate if (shdr->sh_type != SHT_SUNW_move) 14560Sstevel@tonic-gate continue; 14570Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 14580Sstevel@tonic-gate continue; 14590Sstevel@tonic-gate 14600Sstevel@tonic-gate /* 14610Sstevel@tonic-gate * Determine the move data and number. 14620Sstevel@tonic-gate */ 14630Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 14640Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 14650Sstevel@tonic-gate file, _cache->c_name); 14660Sstevel@tonic-gate continue; 14670Sstevel@tonic-gate } 1468*1618Srie move = (Move *)_cache->c_data->d_buf; 1469*1618Srie movenum = shdr->sh_size / shdr->sh_entsize; 14700Sstevel@tonic-gate 14710Sstevel@tonic-gate /* 1472*1618Srie * Get the data buffer for the associated symbol table and 1473*1618Srie * string table. 14740Sstevel@tonic-gate */ 1475*1618Srie if (stringtbl(cache, 1, cnt, shnum, file, 1476*1618Srie &symnum, &symsec, &strsec) == 0) 1477*1618Srie return; 1478*1618Srie 1479*1618Srie syms = (Sym *)symsec->c_data->d_buf; 14800Sstevel@tonic-gate 1481*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1482*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name); 1483*1618Srie dbg_print(0, MSG_INTL(MSG_MOVE_TITLE)); 14840Sstevel@tonic-gate 1485*1618Srie if (fmt == 0) 1486*1618Srie fmt = MSG_INTL(MSG_MOVE_ENTRY); 14870Sstevel@tonic-gate 1488*1618Srie for (ndx = 0; ndx < movenum; move++, ndx++) { 1489*1618Srie const char *symname; 1490*1618Srie char index[MAXNDXSIZE], section[BUFSIZ]; 1491*1618Srie Word symndx, shndx; 1492*1618Srie Sym *sym; 14930Sstevel@tonic-gate 14940Sstevel@tonic-gate /* 14950Sstevel@tonic-gate * Check for null entries 14960Sstevel@tonic-gate */ 1497*1618Srie if ((move->m_info == 0) && (move->m_value == 0) && 1498*1618Srie (move->m_poffset == 0) && (move->m_repeat == 0) && 1499*1618Srie (move->m_stride == 0)) { 1500*1618Srie dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY), 1501*1618Srie EC_XWORD(move->m_poffset), 0, 0, 0, 1502*1618Srie EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY)); 15030Sstevel@tonic-gate continue; 15040Sstevel@tonic-gate } 1505*1618Srie if (((symndx = ELF_M_SYM(move->m_info)) == 0) || 1506*1618Srie (symndx >= symnum)) { 15070Sstevel@tonic-gate (void) fprintf(stderr, 15080Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADMINFO), file, 1509*1618Srie _cache->c_name, EC_XWORD(move->m_info)); 1510*1618Srie 1511*1618Srie (void) snprintf(index, MAXNDXSIZE, 1512*1618Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 1513*1618Srie dbg_print(0, fmt, index, 1514*1618Srie EC_XWORD(move->m_poffset), 1515*1618Srie ELF_M_SIZE(move->m_info), move->m_repeat, 1516*1618Srie move->m_stride, move->m_value, 15170Sstevel@tonic-gate MSG_INTL(MSG_STR_UNKNOWN)); 15180Sstevel@tonic-gate continue; 15190Sstevel@tonic-gate } 15200Sstevel@tonic-gate 1521*1618Srie symname = relsymname(cache, _cache, strsec, 1522*1618Srie symndx, symnum, ndx, syms, section, BUFSIZ, file, 1523*1618Srie flags); 1524*1618Srie sym = (Sym *)(syms + symndx); 15250Sstevel@tonic-gate 15260Sstevel@tonic-gate /* 15270Sstevel@tonic-gate * Additional sanity check. 15280Sstevel@tonic-gate */ 1529*1618Srie shndx = sym->st_shndx; 15300Sstevel@tonic-gate if (!((shndx == SHN_COMMON) || 15310Sstevel@tonic-gate (((shndx >= 1) && (shndx <= shnum)) && 1532*1618Srie (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) { 15330Sstevel@tonic-gate (void) fprintf(stderr, 1534*1618Srie MSG_INTL(MSG_ERR_BADSYM2), file, 1535*1618Srie _cache->c_name, demangle(symname, flags)); 15360Sstevel@tonic-gate } 15370Sstevel@tonic-gate 1538*1618Srie (void) snprintf(index, MAXNDXSIZE, 1539*1618Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 1540*1618Srie dbg_print(0, fmt, index, EC_XWORD(move->m_poffset), 1541*1618Srie ELF_M_SIZE(move->m_info), move->m_repeat, 1542*1618Srie move->m_stride, move->m_value, 1543*1618Srie demangle(symname, flags)); 15440Sstevel@tonic-gate } 15450Sstevel@tonic-gate } 15460Sstevel@tonic-gate } 15470Sstevel@tonic-gate 15480Sstevel@tonic-gate /* 15490Sstevel@tonic-gate * Traverse a note section analyzing each note information block. 15500Sstevel@tonic-gate * The data buffers size is used to validate references before they are made, 15510Sstevel@tonic-gate * and is decremented as each element is processed. 15520Sstevel@tonic-gate */ 15530Sstevel@tonic-gate void 1554*1618Srie note_entry(Cache *cache, Word *data, size_t size, const char *file) 15550Sstevel@tonic-gate { 1556*1618Srie size_t bsize = size; 1557*1618Srie 15580Sstevel@tonic-gate /* 15590Sstevel@tonic-gate * Print out a single `note' information block. 15600Sstevel@tonic-gate */ 15610Sstevel@tonic-gate while (size > 0) { 1562*1618Srie size_t namesz, descsz, type, pad, noteoff; 15630Sstevel@tonic-gate 15640Sstevel@tonic-gate noteoff = bsize - size; 15650Sstevel@tonic-gate /* 15660Sstevel@tonic-gate * Make sure we can at least reference the 3 initial entries 15670Sstevel@tonic-gate * (4-byte words) of the note information block. 15680Sstevel@tonic-gate */ 1569*1618Srie if (size >= (sizeof (Word) * 3)) 1570*1618Srie size -= (sizeof (Word) * 3); 15710Sstevel@tonic-gate else { 1572*1618Srie (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ), 1573*1618Srie file, cache->c_name, EC_WORD(noteoff)); 15740Sstevel@tonic-gate return; 15750Sstevel@tonic-gate } 15760Sstevel@tonic-gate 15770Sstevel@tonic-gate /* 15780Sstevel@tonic-gate * Make sure any specified name string can be referenced. 15790Sstevel@tonic-gate */ 15800Sstevel@tonic-gate if ((namesz = *data++) != 0) { 15810Sstevel@tonic-gate if (size >= namesz) 15820Sstevel@tonic-gate size -= namesz; 15830Sstevel@tonic-gate else { 15840Sstevel@tonic-gate (void) fprintf(stderr, 1585*1618Srie MSG_INTL(MSG_NOTE_BADNMSZ), file, 1586*1618Srie cache->c_name, EC_WORD(noteoff), 1587*1618Srie EC_WORD(namesz)); 15880Sstevel@tonic-gate return; 15890Sstevel@tonic-gate } 15900Sstevel@tonic-gate } 1591*1618Srie 15920Sstevel@tonic-gate /* 15930Sstevel@tonic-gate * Make sure any specified descriptor can be referenced. 15940Sstevel@tonic-gate */ 15950Sstevel@tonic-gate if ((descsz = *data++) != 0) { 15960Sstevel@tonic-gate /* 15970Sstevel@tonic-gate * If namesz isn't a 4-byte multiple, account for any 15980Sstevel@tonic-gate * padding that must exist before the descriptor. 15990Sstevel@tonic-gate */ 1600*1618Srie if ((pad = (namesz & (sizeof (Word) - 1))) != 0) { 1601*1618Srie pad = sizeof (Word) - pad; 16020Sstevel@tonic-gate size -= pad; 16030Sstevel@tonic-gate } 16040Sstevel@tonic-gate if (size >= descsz) 16050Sstevel@tonic-gate size -= descsz; 16060Sstevel@tonic-gate else { 16070Sstevel@tonic-gate (void) fprintf(stderr, 1608*1618Srie MSG_INTL(MSG_NOTE_BADDESZ), file, 1609*1618Srie cache->c_name, EC_WORD(noteoff), 1610*1618Srie EC_WORD(namesz)); 16110Sstevel@tonic-gate return; 16120Sstevel@tonic-gate } 16130Sstevel@tonic-gate } 16140Sstevel@tonic-gate 16150Sstevel@tonic-gate type = *data++; 16160Sstevel@tonic-gate 1617*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1618*1618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE), EC_WORD(type)); 16190Sstevel@tonic-gate 1620*1618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_NAMESZ), EC_WORD(namesz)); 16210Sstevel@tonic-gate if (namesz) { 16220Sstevel@tonic-gate char *name = (char *)data; 16230Sstevel@tonic-gate 16240Sstevel@tonic-gate /* 16250Sstevel@tonic-gate * Since the name string may have 'null' bytes 16260Sstevel@tonic-gate * in it (ia32 .string) - we just write the 16270Sstevel@tonic-gate * whole stream in a single fwrite. 16280Sstevel@tonic-gate */ 16290Sstevel@tonic-gate (void) fwrite(name, namesz, 1, stdout); 16300Sstevel@tonic-gate name = name + ((namesz + (sizeof (Word) - 1)) & 16310Sstevel@tonic-gate ~(sizeof (Word) - 1)); 16320Sstevel@tonic-gate /* LINTED */ 16330Sstevel@tonic-gate data = (Word *)name; 1634*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 16350Sstevel@tonic-gate } 16360Sstevel@tonic-gate 16370Sstevel@tonic-gate /* 16380Sstevel@tonic-gate * If multiple information blocks exist within a .note section 16390Sstevel@tonic-gate * account for any padding that must exist before the next 16400Sstevel@tonic-gate * information block. 16410Sstevel@tonic-gate */ 1642*1618Srie if ((pad = (descsz & (sizeof (Word) - 1))) != 0) { 1643*1618Srie pad = sizeof (Word) - pad; 16440Sstevel@tonic-gate if (size > pad) 16450Sstevel@tonic-gate size -= pad; 16460Sstevel@tonic-gate } 16470Sstevel@tonic-gate 1648*1618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_DESCSZ), EC_WORD(descsz)); 16490Sstevel@tonic-gate if (descsz) { 16500Sstevel@tonic-gate int ndx, byte, word; 1651*1618Srie char string[58], *str = string; 16520Sstevel@tonic-gate uchar_t *desc = (uchar_t *)data; 16530Sstevel@tonic-gate 16540Sstevel@tonic-gate /* 16550Sstevel@tonic-gate * Dump descriptor bytes. 16560Sstevel@tonic-gate */ 16570Sstevel@tonic-gate for (ndx = byte = word = 0; descsz; descsz--, desc++) { 16580Sstevel@tonic-gate int tok = *desc; 16590Sstevel@tonic-gate 16600Sstevel@tonic-gate (void) snprintf(str, 58, MSG_ORIG(MSG_NOTE_TOK), 16610Sstevel@tonic-gate tok); 16620Sstevel@tonic-gate str += 3; 16630Sstevel@tonic-gate 16640Sstevel@tonic-gate if (++byte == 4) { 16650Sstevel@tonic-gate *str++ = ' ', *str++ = ' '; 16660Sstevel@tonic-gate word++; 16670Sstevel@tonic-gate byte = 0; 16680Sstevel@tonic-gate } 16690Sstevel@tonic-gate if (word == 4) { 16700Sstevel@tonic-gate *str = '\0'; 1671*1618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_DESC), 16720Sstevel@tonic-gate ndx, string); 16730Sstevel@tonic-gate word = 0; 16740Sstevel@tonic-gate ndx += 16; 16750Sstevel@tonic-gate str = string; 16760Sstevel@tonic-gate } 16770Sstevel@tonic-gate } 16780Sstevel@tonic-gate if (byte || word) { 16790Sstevel@tonic-gate *str = '\0'; 1680*1618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_DESC), 1681*1618Srie ndx, string); 16820Sstevel@tonic-gate } 16830Sstevel@tonic-gate 16840Sstevel@tonic-gate desc += pad; 16850Sstevel@tonic-gate /* LINTED */ 16860Sstevel@tonic-gate data = (Word *)desc; 16870Sstevel@tonic-gate } 16880Sstevel@tonic-gate } 16890Sstevel@tonic-gate } 16900Sstevel@tonic-gate 16910Sstevel@tonic-gate /* 16920Sstevel@tonic-gate * Search for and process a .note section. 16930Sstevel@tonic-gate */ 16940Sstevel@tonic-gate static void 1695*1618Srie note(Cache *cache, Word shnum, const char *name, const char *file) 16960Sstevel@tonic-gate { 1697*1618Srie Word cnt; 16980Sstevel@tonic-gate 16990Sstevel@tonic-gate /* 17000Sstevel@tonic-gate * Otherwise look for any .note sections. 17010Sstevel@tonic-gate */ 17020Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 1703*1618Srie Cache *_cache = &cache[cnt]; 1704*1618Srie Shdr *shdr = _cache->c_shdr; 17050Sstevel@tonic-gate 17060Sstevel@tonic-gate if (shdr->sh_type != SHT_NOTE) 17070Sstevel@tonic-gate continue; 17080Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 17090Sstevel@tonic-gate continue; 17100Sstevel@tonic-gate 17110Sstevel@tonic-gate /* 17120Sstevel@tonic-gate * As these sections are often hand rolled, make sure they're 17130Sstevel@tonic-gate * properly aligned before proceeding. 17140Sstevel@tonic-gate */ 17150Sstevel@tonic-gate if (shdr->sh_offset & (sizeof (Word) - 1)) { 17160Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN), 17170Sstevel@tonic-gate file, _cache->c_name); 17180Sstevel@tonic-gate continue; 17190Sstevel@tonic-gate } 17200Sstevel@tonic-gate 1721*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1722*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name); 17230Sstevel@tonic-gate note_entry(_cache, (Word *)_cache->c_data->d_buf, 17240Sstevel@tonic-gate /* LINTED */ 17250Sstevel@tonic-gate (Word)_cache->c_data->d_size, file); 17260Sstevel@tonic-gate } 17270Sstevel@tonic-gate } 17280Sstevel@tonic-gate 1729*1618Srie /* 1730*1618Srie * Determine an individual hash entry. This may be the initial hash entry, 1731*1618Srie * or an associated chain entry. 1732*1618Srie */ 1733*1618Srie static void 1734*1618Srie hash_entry(Cache *refsec, Cache *strsec, const char *hsecname, Word hashndx, 1735*1618Srie Word symndx, Word symn, Sym *syms, const char *file, ulong_t bkts, 1736*1618Srie uint_t flags, int chain) 1737*1618Srie { 1738*1618Srie Sym *sym; 1739*1618Srie const char *symname, *str; 1740*1618Srie char _bucket[MAXNDXSIZE], _symndx[MAXNDXSIZE]; 1741*1618Srie ulong_t nbkt, nhash; 1742*1618Srie 1743*1618Srie if (symndx > symn) { 1744*1618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_HSBADSYMNDX), file, 1745*1618Srie EC_WORD(symndx), EC_WORD(hashndx)); 1746*1618Srie symname = MSG_INTL(MSG_STR_UNKNOWN); 1747*1618Srie } else { 1748*1618Srie sym = (Sym *)(syms + symndx); 1749*1618Srie symname = string(refsec, symndx, strsec, file, sym->st_name); 1750*1618Srie } 1751*1618Srie 1752*1618Srie if (chain == 0) { 1753*1618Srie (void) snprintf(_bucket, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 1754*1618Srie hashndx); 1755*1618Srie str = (const char *)_bucket; 1756*1618Srie } else 1757*1618Srie str = MSG_ORIG(MSG_STR_EMPTY); 1758*1618Srie 1759*1618Srie (void) snprintf(_symndx, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX2), 1760*1618Srie EC_WORD(symndx)); 1761*1618Srie dbg_print(0, MSG_ORIG(MSG_FMT_HASH_INFO), str, _symndx, 1762*1618Srie demangle(symname, flags)); 1763*1618Srie 1764*1618Srie /* 1765*1618Srie * Determine if this string is in the correct bucket. 1766*1618Srie */ 1767*1618Srie nhash = elf_hash(symname); 1768*1618Srie nbkt = nhash % bkts; 1769*1618Srie 1770*1618Srie if (nbkt != hashndx) { 1771*1618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADHASH), file, 1772*1618Srie hsecname, symname, EC_WORD(hashndx), nbkt); 1773*1618Srie } 1774*1618Srie } 17750Sstevel@tonic-gate 17760Sstevel@tonic-gate #define MAXCOUNT 500 17770Sstevel@tonic-gate 17780Sstevel@tonic-gate static void 1779*1618Srie hash(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags) 17800Sstevel@tonic-gate { 17810Sstevel@tonic-gate static int count[MAXCOUNT]; 1782*1618Srie Word cnt; 17830Sstevel@tonic-gate ulong_t ndx, bkts; 17840Sstevel@tonic-gate char number[MAXNDXSIZE]; 17850Sstevel@tonic-gate 17860Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 17870Sstevel@tonic-gate uint_t *hash, *chain; 17880Sstevel@tonic-gate Cache *_cache = &cache[cnt]; 1789*1618Srie Shdr *sshdr, *hshdr = _cache->c_shdr; 1790*1618Srie char *ssecname, *hsecname = _cache->c_name; 1791*1618Srie Sym *syms; 1792*1618Srie Word symn; 17930Sstevel@tonic-gate 1794*1618Srie if (hshdr->sh_type != SHT_HASH) 17950Sstevel@tonic-gate continue; 1796*1618Srie if (name && strcmp(name, hsecname)) 17970Sstevel@tonic-gate continue; 17980Sstevel@tonic-gate 17990Sstevel@tonic-gate /* 18000Sstevel@tonic-gate * Determine the hash table data and size. 18010Sstevel@tonic-gate */ 1802*1618Srie if ((hshdr->sh_entsize == 0) || (hshdr->sh_size == 0)) { 18030Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1804*1618Srie file, hsecname); 18050Sstevel@tonic-gate continue; 18060Sstevel@tonic-gate } 18070Sstevel@tonic-gate hash = (uint_t *)_cache->c_data->d_buf; 18080Sstevel@tonic-gate bkts = *hash; 18090Sstevel@tonic-gate chain = hash + 2 + bkts; 18100Sstevel@tonic-gate hash += 2; 18110Sstevel@tonic-gate 18120Sstevel@tonic-gate /* 18130Sstevel@tonic-gate * Get the data buffer for the associated symbol table. 18140Sstevel@tonic-gate */ 1815*1618Srie if ((hshdr->sh_link == 0) || (hshdr->sh_link >= shnum)) { 18160Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1817*1618Srie file, hsecname, EC_WORD(hshdr->sh_link)); 18180Sstevel@tonic-gate continue; 18190Sstevel@tonic-gate } 1820*1618Srie 1821*1618Srie _cache = &cache[hshdr->sh_link]; 1822*1618Srie ssecname = _cache->c_name; 1823*1618Srie 1824*1618Srie if ((syms = (Sym *)_cache->c_data->d_buf) == 0) { 18250Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1826*1618Srie file, ssecname); 18270Sstevel@tonic-gate continue; 18280Sstevel@tonic-gate } 18290Sstevel@tonic-gate 1830*1618Srie sshdr = _cache->c_shdr; 1831*1618Srie /* LINTED */ 1832*1618Srie symn = (Word)(sshdr->sh_size / sshdr->sh_entsize); 1833*1618Srie 18340Sstevel@tonic-gate /* 18350Sstevel@tonic-gate * Get the associated string table section. 18360Sstevel@tonic-gate */ 1837*1618Srie if ((sshdr->sh_link == 0) || (sshdr->sh_link >= shnum)) { 18380Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1839*1618Srie file, ssecname, EC_WORD(sshdr->sh_link)); 18400Sstevel@tonic-gate continue; 18410Sstevel@tonic-gate } 18420Sstevel@tonic-gate 1843*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1844*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_HASH), hsecname); 1845*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_HASH_INFO)); 18460Sstevel@tonic-gate 18470Sstevel@tonic-gate /* 18480Sstevel@tonic-gate * Loop through the hash buckets, printing the appropriate 18490Sstevel@tonic-gate * symbols. 18500Sstevel@tonic-gate */ 18510Sstevel@tonic-gate for (ndx = 0; ndx < bkts; ndx++, hash++) { 1852*1618Srie Word _ndx, _cnt; 18530Sstevel@tonic-gate 18540Sstevel@tonic-gate if (*hash == 0) { 18550Sstevel@tonic-gate count[0]++; 18560Sstevel@tonic-gate continue; 18570Sstevel@tonic-gate } 18580Sstevel@tonic-gate 1859*1618Srie hash_entry(_cache, &cache[sshdr->sh_link], hsecname, 1860*1618Srie ndx, *hash, symn, syms, file, bkts, flags, 0); 18610Sstevel@tonic-gate 18620Sstevel@tonic-gate /* 18630Sstevel@tonic-gate * Determine if any other symbols are chained to this 18640Sstevel@tonic-gate * bucket. 18650Sstevel@tonic-gate */ 18660Sstevel@tonic-gate _ndx = chain[*hash]; 18670Sstevel@tonic-gate _cnt = 1; 18680Sstevel@tonic-gate while (_ndx) { 1869*1618Srie hash_entry(_cache, &cache[sshdr->sh_link], 1870*1618Srie hsecname, ndx, _ndx, symn, syms, file, 1871*1618Srie bkts, flags, 1); 18720Sstevel@tonic-gate _ndx = chain[_ndx]; 18730Sstevel@tonic-gate _cnt++; 18740Sstevel@tonic-gate } 18750Sstevel@tonic-gate 18760Sstevel@tonic-gate if (_cnt >= MAXCOUNT) { 18770Sstevel@tonic-gate (void) fprintf(stderr, 18781324Srie MSG_INTL(MSG_HASH_OVERFLW), file, 1879*1618Srie _cache->c_name, EC_WORD(ndx), 1880*1618Srie EC_WORD(_cnt)); 18810Sstevel@tonic-gate } else 18820Sstevel@tonic-gate count[_cnt]++; 18830Sstevel@tonic-gate } 18840Sstevel@tonic-gate break; 18850Sstevel@tonic-gate } 18860Sstevel@tonic-gate 18870Sstevel@tonic-gate /* 18880Sstevel@tonic-gate * Print out the count information. 18890Sstevel@tonic-gate */ 18900Sstevel@tonic-gate bkts = cnt = 0; 1891*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1892*1618Srie 18930Sstevel@tonic-gate for (ndx = 0; ndx < MAXCOUNT; ndx++) { 1894*1618Srie Word _cnt; 18950Sstevel@tonic-gate 18960Sstevel@tonic-gate if ((_cnt = count[ndx]) == 0) 18970Sstevel@tonic-gate continue; 18980Sstevel@tonic-gate 1899*1618Srie (void) snprintf(number, MAXNDXSIZE, 1900*1618Srie MSG_ORIG(MSG_FMT_INTEGER), _cnt); 1901*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS1), number, 1902*1618Srie EC_WORD(ndx)); 19030Sstevel@tonic-gate bkts += _cnt; 1904*1618Srie cnt += (Word)(ndx * _cnt); 19050Sstevel@tonic-gate } 19060Sstevel@tonic-gate if (cnt) { 19070Sstevel@tonic-gate (void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 1908*1618Srie bkts); 1909*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS2), number, 1910*1618Srie EC_WORD(cnt)); 19110Sstevel@tonic-gate } 19120Sstevel@tonic-gate } 19130Sstevel@tonic-gate 19140Sstevel@tonic-gate static void 1915*1618Srie group(Cache *cache, Word shnum, const char *name, const char *file, 1916*1618Srie uint_t flags) 19170Sstevel@tonic-gate { 1918*1618Srie Word scnt; 19190Sstevel@tonic-gate 1920*1618Srie for (scnt = 1; scnt < shnum; scnt++) { 1921*1618Srie Cache *_cache = &cache[scnt]; 1922*1618Srie Shdr *shdr = _cache->c_shdr; 1923*1618Srie Word *grpdata, gcnt, grpcnt, symnum, unknown; 1924*1618Srie Cache *symsec, *strsec; 1925*1618Srie Sym *syms, *sym; 1926*1618Srie char flgstrbuf[MSG_GRP_COMDAT_SIZE + 10]; 19270Sstevel@tonic-gate 19280Sstevel@tonic-gate if (shdr->sh_type != SHT_GROUP) 19290Sstevel@tonic-gate continue; 19300Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 19310Sstevel@tonic-gate continue; 1932*1618Srie if ((_cache->c_data == 0) || 1933*1618Srie ((grpdata = (Word *)_cache->c_data->d_buf) == 0)) 19340Sstevel@tonic-gate continue; 1935*1618Srie grpcnt = shdr->sh_size / sizeof (Word); 1936*1618Srie 1937*1618Srie /* 1938*1618Srie * Get the data buffer for the associated symbol table and 1939*1618Srie * string table. 1940*1618Srie */ 1941*1618Srie if (stringtbl(cache, 1, scnt, shnum, file, 1942*1618Srie &symnum, &symsec, &strsec) == 0) 1943*1618Srie return; 1944*1618Srie 1945*1618Srie syms = symsec->c_data->d_buf; 1946*1618Srie 1947*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1948*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_GRP), _cache->c_name); 1949*1618Srie dbg_print(0, MSG_INTL(MSG_GRP_TITLE)); 1950*1618Srie 1951*1618Srie /* 1952*1618Srie * The first element of the group defines the group. The 1953*1618Srie * associated symbol is defined by the sh_link field. 1954*1618Srie */ 1955*1618Srie if ((shdr->sh_info == SHN_UNDEF) || (shdr->sh_info > symnum)) { 1956*1618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 1957*1618Srie file, _cache->c_name, EC_WORD(shdr->sh_info)); 1958*1618Srie return; 19590Sstevel@tonic-gate } 19600Sstevel@tonic-gate 1961*1618Srie (void) strcpy(flgstrbuf, MSG_ORIG(MSG_STR_OSQBRKT)); 1962*1618Srie if (grpdata[0] & GRP_COMDAT) { 1963*1618Srie (void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_COMDAT)); 19640Sstevel@tonic-gate } 1965*1618Srie if ((unknown = (grpdata[0] & ~GRP_COMDAT)) != 0) { 1966*1618Srie size_t len = strlen(flgstrbuf); 1967*1618Srie 1968*1618Srie (void) snprintf(&flgstrbuf[len], 1969*1618Srie (MSG_GRP_COMDAT_SIZE + 10 - len), 1970*1618Srie MSG_ORIG(MSG_GRP_UNKNOWN), unknown); 19710Sstevel@tonic-gate } 1972*1618Srie (void) strcat(flgstrbuf, MSG_ORIG(MSG_STR_CSQBRKT)); 1973*1618Srie sym = (Sym *)(syms + shdr->sh_info); 19740Sstevel@tonic-gate 1975*1618Srie dbg_print(0, MSG_INTL(MSG_GRP_SIGNATURE), flgstrbuf, 1976*1618Srie demangle(string(_cache, 0, strsec, file, sym->st_name), 1977*1618Srie flags)); 1978*1618Srie 1979*1618Srie for (gcnt = 1; gcnt < grpcnt; gcnt++) { 19800Sstevel@tonic-gate char index[MAXNDXSIZE]; 1981*1618Srie const char *name; 19820Sstevel@tonic-gate 19830Sstevel@tonic-gate (void) snprintf(index, MAXNDXSIZE, 1984*1618Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(gcnt)); 1985*1618Srie 1986*1618Srie if (grpdata[gcnt] >= shnum) 1987*1618Srie name = MSG_INTL(MSG_GRP_INVALSCN); 1988*1618Srie else 1989*1618Srie name = cache[grpdata[gcnt]].c_name; 1990*1618Srie 1991*1618Srie (void) printf(MSG_ORIG(MSG_GRP_ENTRY), index, name, 1992*1618Srie EC_XWORD(grpdata[gcnt])); 19930Sstevel@tonic-gate } 19940Sstevel@tonic-gate } 19950Sstevel@tonic-gate } 19960Sstevel@tonic-gate 19970Sstevel@tonic-gate static void 1998*1618Srie got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, uint_t flags) 19990Sstevel@tonic-gate { 20000Sstevel@tonic-gate Cache *gotcache = 0, *symtab = 0, *_cache; 2001*1618Srie Addr gotbgn, gotend; 2002*1618Srie Shdr *gotshdr; 2003*1618Srie Word cnt, gotents, gotndx; 20040Sstevel@tonic-gate size_t gentsize; 20050Sstevel@tonic-gate Got_info *gottable; 20060Sstevel@tonic-gate char *gotdata; 2007*1618Srie Sym *gotsym; 2008*1618Srie Xword gotsymaddr; 20090Sstevel@tonic-gate 20100Sstevel@tonic-gate /* 20111324Srie * First, find the got. 20120Sstevel@tonic-gate */ 20130Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 20140Sstevel@tonic-gate _cache = &cache[cnt]; 20151324Srie if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT), 20161324Srie MSG_ELF_GOT_SIZE) == 0) { 20170Sstevel@tonic-gate gotcache = _cache; 20180Sstevel@tonic-gate break; 20190Sstevel@tonic-gate } 20200Sstevel@tonic-gate } 2021*1618Srie if (gotcache == 0) 20220Sstevel@tonic-gate return; 20231324Srie 20241324Srie /* 20251324Srie * A got section within a relocatable object is suspicious. 20261324Srie */ 20271324Srie if (ehdr->e_type == ET_REL) { 20281324Srie (void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file, 20291324Srie _cache->c_name); 20301324Srie } 20311324Srie 2032*1618Srie gotshdr = gotcache->c_shdr; 20330Sstevel@tonic-gate if (gotshdr->sh_size == 0) { 20340Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 20350Sstevel@tonic-gate file, gotcache->c_name); 20360Sstevel@tonic-gate return; 20370Sstevel@tonic-gate } 2038*1618Srie 2039*1618Srie gotbgn = gotshdr->sh_addr; 20400Sstevel@tonic-gate gotend = gotbgn + gotshdr->sh_size; 20410Sstevel@tonic-gate 20420Sstevel@tonic-gate /* 2043*1618Srie * Some architectures don't properly set the sh_entsize for the GOT 2044*1618Srie * table. If it's not set, default to a size of a pointer. 20450Sstevel@tonic-gate */ 2046*1618Srie if ((gentsize = gotshdr->sh_entsize) == 0) 2047*1618Srie gentsize = sizeof (Xword); 2048*1618Srie 20490Sstevel@tonic-gate /* LINTED */ 2050*1618Srie gotents = (Word)(gotshdr->sh_size / gentsize); 20510Sstevel@tonic-gate gotdata = gotcache->c_data->d_buf; 20520Sstevel@tonic-gate 20530Sstevel@tonic-gate if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) { 20540Sstevel@tonic-gate int err = errno; 2055*1618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), file, 2056*1618Srie strerror(err)); 20570Sstevel@tonic-gate return; 20580Sstevel@tonic-gate } 20590Sstevel@tonic-gate 20600Sstevel@tonic-gate /* 20610Sstevel@tonic-gate * Now we scan through all the sections looking for any relocations 20620Sstevel@tonic-gate * that may be against the GOT. Since these may not be isolated to a 20630Sstevel@tonic-gate * .rel[a].got section we check them all. 20640Sstevel@tonic-gate * While scanning sections save the symbol table entry (a symtab 20650Sstevel@tonic-gate * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_. 20660Sstevel@tonic-gate */ 20670Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 2068*1618Srie Word type, symnum; 2069*1618Srie Xword relndx, relnum, relsize; 2070*1618Srie void *rels; 2071*1618Srie Sym *syms; 2072*1618Srie Cache *symsec, *strsec; 2073*1618Srie Cache *_cache = &cache[cnt]; 2074*1618Srie Shdr *shdr; 20750Sstevel@tonic-gate 2076*1618Srie shdr = _cache->c_shdr; 2077*1618Srie type = shdr->sh_type; 20780Sstevel@tonic-gate 2079*1618Srie if ((symtab == 0) && (type == SHT_DYNSYM)) { 20800Sstevel@tonic-gate symtab = _cache; 20810Sstevel@tonic-gate continue; 20820Sstevel@tonic-gate } 2083*1618Srie if (type == SHT_SYMTAB) { 20840Sstevel@tonic-gate symtab = _cache; 20850Sstevel@tonic-gate continue; 20860Sstevel@tonic-gate } 2087*1618Srie if ((type != SHT_RELA) && (type != SHT_REL)) 20880Sstevel@tonic-gate continue; 20890Sstevel@tonic-gate 20900Sstevel@tonic-gate /* 2091*1618Srie * Decide entry size. 20920Sstevel@tonic-gate */ 2093*1618Srie if (((relsize = shdr->sh_entsize) == 0) || 2094*1618Srie (relsize > shdr->sh_size)) { 2095*1618Srie if (type == SHT_RELA) 2096*1618Srie relsize = sizeof (Rela); 2097*1618Srie else 2098*1618Srie relsize = sizeof (Rel); 20990Sstevel@tonic-gate } 21000Sstevel@tonic-gate 21010Sstevel@tonic-gate /* 2102*1618Srie * Determine the number of relocations available. 21030Sstevel@tonic-gate */ 2104*1618Srie if (shdr->sh_size == 0) { 2105*1618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2106*1618Srie file, _cache->c_name); 21070Sstevel@tonic-gate continue; 21080Sstevel@tonic-gate } 2109*1618Srie rels = _cache->c_data->d_buf; 2110*1618Srie relnum = shdr->sh_size / relsize; 21110Sstevel@tonic-gate 2112*1618Srie /* 2113*1618Srie * Get the data buffer for the associated symbol table and 2114*1618Srie * string table. 2115*1618Srie */ 2116*1618Srie if (stringtbl(cache, 1, cnt, shnum, file, 2117*1618Srie &symnum, &symsec, &strsec) == 0) 2118*1618Srie continue; 2119*1618Srie 2120*1618Srie syms = symsec->c_data->d_buf; 2121*1618Srie 2122*1618Srie /* 2123*1618Srie * Loop through the relocation entries. 2124*1618Srie */ 2125*1618Srie for (relndx = 0; relndx < relnum; relndx++, 2126*1618Srie rels = (void *)((char *)rels + relsize)) { 2127*1618Srie char section[BUFSIZ]; 2128*1618Srie Addr offset; 21290Sstevel@tonic-gate Got_info *gip; 2130*1618Srie Word symndx, reltype; 2131*1618Srie Rela *rela; 2132*1618Srie Rel *rel; 21330Sstevel@tonic-gate 2134*1618Srie /* 2135*1618Srie * Unravel the relocation. 2136*1618Srie */ 2137*1618Srie if (type == SHT_RELA) { 2138*1618Srie rela = (Rela *)rels; 2139*1618Srie symndx = ELF_R_SYM(rela->r_info); 2140*1618Srie reltype = ELF_R_TYPE(rela->r_info); 2141*1618Srie offset = rela->r_offset; 21420Sstevel@tonic-gate } else { 2143*1618Srie rel = (Rel *)rels; 2144*1618Srie symndx = ELF_R_SYM(rel->r_info); 2145*1618Srie reltype = ELF_R_TYPE(rel->r_info); 2146*1618Srie offset = rel->r_offset; 21470Sstevel@tonic-gate } 21480Sstevel@tonic-gate 21490Sstevel@tonic-gate /* 21500Sstevel@tonic-gate * Only pay attention to relocations against the GOT. 21510Sstevel@tonic-gate */ 21520Sstevel@tonic-gate if ((offset < gotbgn) || (offset > gotend)) 21530Sstevel@tonic-gate continue; 21540Sstevel@tonic-gate 21550Sstevel@tonic-gate /* LINTED */ 2156*1618Srie gotndx = (Word)((offset - gotbgn) / 21570Sstevel@tonic-gate gotshdr->sh_entsize); 21580Sstevel@tonic-gate gip = &gottable[gotndx]; 2159*1618Srie 2160*1618Srie if (gip->g_reltype != 0) { 21610Sstevel@tonic-gate (void) fprintf(stderr, 21620Sstevel@tonic-gate MSG_INTL(MSG_GOT_MULTIPLE), file, 2163*1618Srie EC_WORD(gotndx), EC_ADDR(offset)); 21640Sstevel@tonic-gate continue; 21650Sstevel@tonic-gate } 21660Sstevel@tonic-gate 2167*1618Srie if (symndx) 2168*1618Srie gip->g_symname = relsymname(cache, _cache, 2169*1618Srie strsec, symndx, symnum, relndx, syms, 2170*1618Srie section, BUFSIZ, file, flags); 2171*1618Srie gip->g_reltype = reltype; 2172*1618Srie gip->g_rel = rels; 21730Sstevel@tonic-gate } 21740Sstevel@tonic-gate } 21750Sstevel@tonic-gate 2176*1618Srie if (symlookup(MSG_ORIG(MSG_GOT_SYM), cache, shnum, &gotsym, symtab, 2177*1618Srie file)) 2178*1618Srie gotsymaddr = gotsym->st_value; 21790Sstevel@tonic-gate else 2180*1618Srie gotsymaddr = gotbgn; 21810Sstevel@tonic-gate 2182*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2183*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name); 2184*1618Srie Elf_got_title(0); 21850Sstevel@tonic-gate 21860Sstevel@tonic-gate for (gotndx = 0; gotndx < gotents; gotndx++) { 21870Sstevel@tonic-gate Got_info *gip; 21880Sstevel@tonic-gate Sword gindex; 2189*1618Srie Addr gaddr; 2190*1618Srie Xword gotentry; 21910Sstevel@tonic-gate 21920Sstevel@tonic-gate gip = &gottable[gotndx]; 21930Sstevel@tonic-gate 21940Sstevel@tonic-gate gaddr = gotbgn + (gotndx * gentsize); 2195*1618Srie gindex = (Sword)(gaddr - gotsymaddr) / (Sword)gentsize; 21960Sstevel@tonic-gate 2197*1618Srie if (gentsize == sizeof (Word)) 21980Sstevel@tonic-gate /* LINTED */ 2199*1618Srie gotentry = (Xword)(*((Word *)(gotdata) + gotndx)); 22000Sstevel@tonic-gate else 22010Sstevel@tonic-gate /* LINTED */ 2202*1618Srie gotentry = *((Xword *)(gotdata) + gotndx); 22030Sstevel@tonic-gate 2204*1618Srie Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine, 2205*1618Srie gip->g_reltype, gip->g_rel, gip->g_symname); 22060Sstevel@tonic-gate } 22070Sstevel@tonic-gate free(gottable); 22080Sstevel@tonic-gate } 22090Sstevel@tonic-gate 22100Sstevel@tonic-gate void 22110Sstevel@tonic-gate checksum(Elf *elf) 22120Sstevel@tonic-gate { 2213*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2214*1618Srie dbg_print(0, MSG_INTL(MSG_STR_CHECKSUM), elf_checksum(elf)); 22150Sstevel@tonic-gate } 22160Sstevel@tonic-gate 2217*1618Srie void 2218*1618Srie regular(const char *file, Elf *elf, uint_t flags, char *Nname, int wfd) 22190Sstevel@tonic-gate { 22200Sstevel@tonic-gate Elf_Scn *scn; 2221*1618Srie Ehdr *ehdr; 22220Sstevel@tonic-gate Elf_Data *data; 2223*1618Srie size_t cnt, shstrndx, shnum, phnum; 2224*1618Srie Shdr *nameshdr, *shdr; 22250Sstevel@tonic-gate char *names = 0; 22260Sstevel@tonic-gate Cache *cache, *_cache; 2227*1618Srie Cache *versymcache = 0; 22280Sstevel@tonic-gate 2229*1618Srie if ((ehdr = elf_getehdr(elf)) == NULL) { 22300Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETEHDR)); 22310Sstevel@tonic-gate return; 22320Sstevel@tonic-gate } 22330Sstevel@tonic-gate 2234*1618Srie if (elf_getshnum(elf, &shnum) == 0) { 22350Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHNUM)); 22360Sstevel@tonic-gate return; 22370Sstevel@tonic-gate } 22380Sstevel@tonic-gate 2239942Sahl if (elf_getshstrndx(elf, &shstrndx) == 0) { 22400Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX)); 22410Sstevel@tonic-gate return; 22420Sstevel@tonic-gate } 2243942Sahl 2244*1618Srie if (elf_getphnum(elf, &phnum) == 0) { 2245942Sahl failure(file, MSG_ORIG(MSG_ELF_GETPHNUM)); 2246942Sahl return; 2247942Sahl } 2248942Sahl 22490Sstevel@tonic-gate if ((scn = elf_getscn(elf, 0)) != NULL) { 2250*1618Srie if ((shdr = elf_getshdr(scn)) == NULL) { 22510Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 22520Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0); 22530Sstevel@tonic-gate return; 22540Sstevel@tonic-gate } 22550Sstevel@tonic-gate } else 2256*1618Srie shdr = 0; 22570Sstevel@tonic-gate 22580Sstevel@tonic-gate /* 22590Sstevel@tonic-gate * Print the elf header. 22600Sstevel@tonic-gate */ 22610Sstevel@tonic-gate if (flags & FLG_EHDR) 2262*1618Srie Elf_ehdr(0, ehdr, shdr); 22630Sstevel@tonic-gate 22640Sstevel@tonic-gate /* 22650Sstevel@tonic-gate * Print the program headers. 22660Sstevel@tonic-gate */ 2267*1618Srie if ((flags & FLG_PHDR) && (phnum != 0)) { 2268*1618Srie Phdr *phdr; 22690Sstevel@tonic-gate 2270*1618Srie if ((phdr = elf_getphdr(elf)) == NULL) { 2271*1618Srie failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 2272*1618Srie return; 2273*1618Srie } 22740Sstevel@tonic-gate 2275*1618Srie for (cnt = 0; cnt < phnum; phdr++, cnt++) { 2276*1618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2277*1618Srie dbg_print(0, MSG_INTL(MSG_ELF_PHDR), EC_WORD(cnt)); 2278*1618Srie Elf_phdr(0, ehdr->e_machine, phdr); 22790Sstevel@tonic-gate } 22800Sstevel@tonic-gate } 22810Sstevel@tonic-gate 22820Sstevel@tonic-gate 22830Sstevel@tonic-gate /* 2284942Sahl * Return now if there are no section, if there's just one section to 2285942Sahl * act as an extension of the ELF header, or if on section information 2286942Sahl * was requested. 22870Sstevel@tonic-gate */ 2288942Sahl if ((shnum <= 1) || (flags && (flags & ~(FLG_EHDR | FLG_PHDR)) == 0)) { 2289*1618Srie if ((ehdr->e_type == ET_CORE) && (flags & FLG_NOTE)) 22900Sstevel@tonic-gate note(0, shnum, 0, file); 22910Sstevel@tonic-gate return; 22920Sstevel@tonic-gate } 22930Sstevel@tonic-gate 2294*1618Srie 22950Sstevel@tonic-gate /* 22960Sstevel@tonic-gate * Obtain the .shstrtab data buffer to provide the required section 22970Sstevel@tonic-gate * name strings. 22980Sstevel@tonic-gate */ 22990Sstevel@tonic-gate if ((scn = elf_getscn(elf, shstrndx)) == NULL) { 23000Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSCN)); 23010Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR), 23020Sstevel@tonic-gate EC_XWORD(shstrndx)); 2303*1618Srie 23040Sstevel@tonic-gate } else if ((data = elf_getdata(scn, NULL)) == NULL) { 23050Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 23060Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA), 23070Sstevel@tonic-gate EC_XWORD(shstrndx)); 2308*1618Srie 2309*1618Srie } else if ((nameshdr = elf_getshdr(scn)) == NULL) { 23100Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 23110Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 23120Sstevel@tonic-gate /* LINTED */ 23130Sstevel@tonic-gate (int)elf_ndxscn(scn)); 2314*1618Srie 2315*1618Srie } else if ((names = data->d_buf) == 0) 23160Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file); 23170Sstevel@tonic-gate 23180Sstevel@tonic-gate /* 23190Sstevel@tonic-gate * Fill in the cache descriptor with information for each section. 23200Sstevel@tonic-gate */ 23210Sstevel@tonic-gate if ((cache = malloc(shnum * sizeof (Cache))) == 0) { 23220Sstevel@tonic-gate int err = errno; 23230Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 23240Sstevel@tonic-gate file, strerror(err)); 23250Sstevel@tonic-gate return; 23260Sstevel@tonic-gate } 23270Sstevel@tonic-gate 2328*1618Srie *cache = cache_init; 23290Sstevel@tonic-gate _cache = cache; 23300Sstevel@tonic-gate _cache++; 23310Sstevel@tonic-gate 23320Sstevel@tonic-gate for (cnt = 1, scn = NULL; scn = elf_nextscn(elf, scn); 23330Sstevel@tonic-gate cnt++, _cache++) { 2334*1618Srie if ((_cache->c_shdr = elf_getshdr(scn)) == NULL) { 23350Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 23360Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 23370Sstevel@tonic-gate /* LINTED */ 23380Sstevel@tonic-gate (int)elf_ndxscn(scn)); 23390Sstevel@tonic-gate } 23400Sstevel@tonic-gate 2341*1618Srie if (names && _cache->c_shdr->sh_name && 23420Sstevel@tonic-gate /* LINTED */ 2343*1618Srie (nameshdr->sh_size > _cache->c_shdr->sh_name)) 2344*1618Srie _cache->c_name = names + _cache->c_shdr->sh_name; 23450Sstevel@tonic-gate else { 23460Sstevel@tonic-gate /* 23470Sstevel@tonic-gate * If there exists no shstrtab data, or a section header 23480Sstevel@tonic-gate * has no name (an invalid index of 0), then compose a 23490Sstevel@tonic-gate * name for each section. 23500Sstevel@tonic-gate */ 23510Sstevel@tonic-gate char scnndxnm[100]; 23520Sstevel@tonic-gate 23530Sstevel@tonic-gate (void) snprintf(scnndxnm, 100, MSG_INTL(MSG_FMT_SCNNDX), 23540Sstevel@tonic-gate cnt); 23550Sstevel@tonic-gate 23560Sstevel@tonic-gate /* 23570Sstevel@tonic-gate * Although we have a valid shstrtab section inform the 23580Sstevel@tonic-gate * user if this section name index exceeds the shstrtab 23590Sstevel@tonic-gate * data. 23600Sstevel@tonic-gate */ 23610Sstevel@tonic-gate if (names && 23620Sstevel@tonic-gate /* LINTED */ 2363*1618Srie (nameshdr->sh_size <= _cache->c_shdr->sh_name)) { 23640Sstevel@tonic-gate (void) fprintf(stderr, 23650Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSHNAME), file, 23660Sstevel@tonic-gate _cache->c_name, 2367*1618Srie EC_XWORD(_cache->c_shdr->sh_name)); 23680Sstevel@tonic-gate } 23690Sstevel@tonic-gate 23700Sstevel@tonic-gate if ((_cache->c_name = 23710Sstevel@tonic-gate malloc(strlen(scnndxnm) + 1)) == 0) { 23720Sstevel@tonic-gate int err = errno; 23730Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 23740Sstevel@tonic-gate file, strerror(err)); 23750Sstevel@tonic-gate return; 23760Sstevel@tonic-gate } 23770Sstevel@tonic-gate (void) strcpy(_cache->c_name, scnndxnm); 23780Sstevel@tonic-gate } 23790Sstevel@tonic-gate 23800Sstevel@tonic-gate if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) { 23810Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 23820Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA), 23830Sstevel@tonic-gate /* LINTED */ 23840Sstevel@tonic-gate (int)elf_ndxscn(scn)); 23850Sstevel@tonic-gate } 23860Sstevel@tonic-gate 23870Sstevel@tonic-gate /* 23880Sstevel@tonic-gate * Do we wish to write the section out? 23890Sstevel@tonic-gate */ 23900Sstevel@tonic-gate if (wfd && Nname && (strcmp(Nname, _cache->c_name) == 0)) { 23910Sstevel@tonic-gate (void) write(wfd, _cache->c_data->d_buf, 23920Sstevel@tonic-gate _cache->c_data->d_size); 23930Sstevel@tonic-gate } 23940Sstevel@tonic-gate } 23950Sstevel@tonic-gate 23960Sstevel@tonic-gate if (flags & FLG_SHDR) 2397*1618Srie sections(file, cache, shnum, ehdr, Nname); 23980Sstevel@tonic-gate 23990Sstevel@tonic-gate if (flags & FLG_INTERP) 2400*1618Srie interp(file, cache, shnum, phnum, elf); 24010Sstevel@tonic-gate 24020Sstevel@tonic-gate versymcache = versions(cache, shnum, file, flags); 24030Sstevel@tonic-gate 24040Sstevel@tonic-gate if (flags & FLG_SYMBOLS) 2405*1618Srie symbols(cache, shnum, ehdr, Nname, versymcache, file, flags); 24060Sstevel@tonic-gate 24070Sstevel@tonic-gate if (flags & FLG_HASH) 24080Sstevel@tonic-gate hash(cache, shnum, Nname, file, flags); 24090Sstevel@tonic-gate 24100Sstevel@tonic-gate if (flags & FLG_GOT) 2411*1618Srie got(cache, shnum, ehdr, file, flags); 24120Sstevel@tonic-gate 24130Sstevel@tonic-gate if (flags & FLG_GROUP) 24140Sstevel@tonic-gate group(cache, shnum, Nname, file, flags); 24150Sstevel@tonic-gate 24160Sstevel@tonic-gate if (flags & FLG_SYMINFO) 24170Sstevel@tonic-gate syminfo(cache, shnum, file); 24180Sstevel@tonic-gate 24190Sstevel@tonic-gate if (flags & FLG_RELOC) 2420*1618Srie reloc(cache, shnum, ehdr, Nname, file, flags); 24210Sstevel@tonic-gate 24220Sstevel@tonic-gate if (flags & FLG_DYNAMIC) 2423*1618Srie dynamic(cache, shnum, ehdr, file); 24240Sstevel@tonic-gate 24250Sstevel@tonic-gate if (flags & FLG_NOTE) 24260Sstevel@tonic-gate note(cache, shnum, Nname, file); 24270Sstevel@tonic-gate 24280Sstevel@tonic-gate if (flags & FLG_MOVE) 24290Sstevel@tonic-gate move(cache, shnum, Nname, file, flags); 24300Sstevel@tonic-gate 24310Sstevel@tonic-gate if (flags & FLG_CHECKSUM) 24320Sstevel@tonic-gate checksum(elf); 24330Sstevel@tonic-gate 24340Sstevel@tonic-gate if (flags & FLG_CAP) 2435*1618Srie cap(file, cache, shnum, phnum, ehdr, elf); 24360Sstevel@tonic-gate 24370Sstevel@tonic-gate if (flags & FLG_UNWIND) 2438*1618Srie unwind(cache, shnum, phnum, ehdr, Nname, file, elf); 24390Sstevel@tonic-gate 24400Sstevel@tonic-gate free(cache); 24410Sstevel@tonic-gate } 2442