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 51618Srie * Common Development and Distribution License (the "License"). 61618Srie * 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 /* 233466Srie * Copyright 2007 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 */ 311618Srie #include <machdep.h> 321618Srie #include <sys/elf_386.h> 331618Srie #include <sys/elf_amd64.h> 341618Srie #include <sys/elf_SPARC.h> 351618Srie #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> 421618Srie #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 * 481618Srie 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; 52*3492Sab196087 const char *strs; 53*3492Sab196087 Word strn; 540Sstevel@tonic-gate 553466Srie if (strsec->c_data == NULL) 563466Srie return (NULL); 573466Srie 58*3492Sab196087 strs = (char *)strsec->c_data->d_buf; 59*3492Sab196087 strn = strsec->c_data->d_size; 600Sstevel@tonic-gate 610Sstevel@tonic-gate /* 621618Srie * Only print a diagnostic regarding an empty string table once per 630Sstevel@tonic-gate * input section being processed. 640Sstevel@tonic-gate */ 650Sstevel@tonic-gate if (osec != refsec) { 660Sstevel@tonic-gate osec = refsec; 670Sstevel@tonic-gate nostr = 0; 680Sstevel@tonic-gate } 690Sstevel@tonic-gate 700Sstevel@tonic-gate /* 710Sstevel@tonic-gate * Is the string table offset within range of the available strings? 720Sstevel@tonic-gate */ 730Sstevel@tonic-gate if (name >= strn) { 740Sstevel@tonic-gate /* 750Sstevel@tonic-gate * Do we have a empty string table? 760Sstevel@tonic-gate */ 770Sstevel@tonic-gate if (strs == 0) { 780Sstevel@tonic-gate if (nostr == 0) { 790Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 800Sstevel@tonic-gate file, strsec->c_name); 810Sstevel@tonic-gate nostr++; 820Sstevel@tonic-gate } 830Sstevel@tonic-gate } else { 840Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSTOFF), 851618Srie file, refsec->c_name, EC_WORD(ndx), strsec->c_name, 861618Srie EC_WORD(name), EC_WORD(strn - 1)); 870Sstevel@tonic-gate } 880Sstevel@tonic-gate 890Sstevel@tonic-gate /* 900Sstevel@tonic-gate * Return the empty string so that the calling function can 910Sstevel@tonic-gate * continue it's output diagnostics. 920Sstevel@tonic-gate */ 930Sstevel@tonic-gate return (MSG_INTL(MSG_STR_UNKNOWN)); 940Sstevel@tonic-gate } 950Sstevel@tonic-gate return (strs + name); 960Sstevel@tonic-gate } 970Sstevel@tonic-gate 980Sstevel@tonic-gate /* 991618Srie * Relocations can reference section symbols and standard symbols. If the 1001618Srie * former, establish the section name. 1011618Srie */ 1021618Srie static const char * 1031618Srie relsymname(Cache *cache, Cache *csec, Cache *strsec, Word symndx, Word symnum, 1041618Srie Word relndx, Sym *syms, char *secstr, size_t secsz, const char *file, 1051618Srie uint_t flags) 1061618Srie { 1071618Srie Sym *sym; 1081618Srie 1091618Srie if (symndx >= symnum) { 1101618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_RELBADSYMNDX), 1111618Srie file, EC_WORD(symndx), EC_WORD(relndx)); 1121618Srie return (MSG_INTL(MSG_STR_UNKNOWN)); 1131618Srie } 1141618Srie 1151618Srie sym = (Sym *)(syms + symndx); 1161618Srie 1171618Srie /* 1181618Srie * If the symbol represents a section offset construct an appropriate 1191618Srie * string. 1201618Srie */ 1211618Srie if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) && (sym->st_name == 0)) { 1221618Srie if (flags & FLG_LONGNAME) 1231618Srie (void) snprintf(secstr, secsz, 1241618Srie MSG_INTL(MSG_STR_L_SECTION), 1251618Srie cache[sym->st_shndx].c_name); 1261618Srie else 1271618Srie (void) snprintf(secstr, secsz, 1281618Srie MSG_INTL(MSG_STR_SECTION), 1291618Srie cache[sym->st_shndx].c_name); 1301618Srie return ((const char *)secstr); 1311618Srie } 1321618Srie 1331618Srie return (string(csec, symndx, strsec, file, sym->st_name)); 1341618Srie } 1351618Srie 1361618Srie /* 1371618Srie * Focal point for establishing a string table section. Data such as the 1381618Srie * dynamic information simply points to a string table. Data such as 1391618Srie * relocations, reference a symbol table, which in turn is associated with a 1401618Srie * string table. 1410Sstevel@tonic-gate */ 1420Sstevel@tonic-gate static int 1431618Srie stringtbl(Cache *cache, int symtab, Word ndx, Word shnum, const char *file, 1441618Srie Word *symnum, Cache **symsec, Cache **strsec) 1451618Srie { 1461618Srie Shdr *shdr = cache[ndx].c_shdr; 1471618Srie 1481618Srie if (symtab) { 1491618Srie /* 1501618Srie * Validate the symbol table section. 1511618Srie */ 1521618Srie if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1531618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1541618Srie file, cache[ndx].c_name, EC_WORD(shdr->sh_link)); 1551618Srie return (0); 1561618Srie } 1573466Srie if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1583466Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1593466Srie file, cache[ndx].c_name); 1603466Srie return (0); 1613466Srie } 1621618Srie 1631618Srie /* 1641618Srie * Obtain, and verify the symbol table data. 1651618Srie */ 1663466Srie if ((cache[ndx].c_data == NULL) || 1673466Srie (cache[ndx].c_data->d_buf == NULL)) { 1681618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1691618Srie file, cache[ndx].c_name); 1701618Srie return (0); 1711618Srie } 1721618Srie 1731618Srie /* 1741618Srie * Establish the string table index. 1751618Srie */ 1761618Srie ndx = shdr->sh_link; 1771618Srie shdr = cache[ndx].c_shdr; 1781618Srie 1791618Srie /* 1801618Srie * Return symbol table information. 1811618Srie */ 1821618Srie if (symnum) 1831618Srie *symnum = (shdr->sh_size / shdr->sh_entsize); 1841618Srie if (symsec) 1851618Srie *symsec = &cache[ndx]; 1861618Srie } 1871618Srie 1881618Srie /* 1891618Srie * Validate the associated string table section. 1901618Srie */ 1911618Srie if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1921618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1931618Srie file, cache[ndx].c_name, EC_WORD(shdr->sh_link)); 1941618Srie return (0); 1951618Srie } 1961618Srie 1971618Srie if (strsec) 1981618Srie *strsec = &cache[shdr->sh_link]; 1991618Srie 2001618Srie return (1); 2011618Srie } 2021618Srie 2031618Srie /* 2041618Srie * Lookup a symbol and set Sym accordingly. 2051618Srie */ 2061618Srie static int 2071618Srie symlookup(const char *name, Cache *cache, Word shnum, Sym **sym, 2080Sstevel@tonic-gate Cache *symtab, const char *file) 2090Sstevel@tonic-gate { 2101618Srie Shdr *shdr; 2111618Srie Word symn, cnt; 2121618Srie Sym *syms; 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate if (symtab == 0) 2150Sstevel@tonic-gate return (0); 2160Sstevel@tonic-gate 2171618Srie shdr = symtab->c_shdr; 2181618Srie 2190Sstevel@tonic-gate /* 2200Sstevel@tonic-gate * Determine the symbol data and number. 2210Sstevel@tonic-gate */ 2220Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 2230Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2240Sstevel@tonic-gate file, symtab->c_name); 2250Sstevel@tonic-gate return (0); 2260Sstevel@tonic-gate } 2273466Srie if (symtab->c_data == NULL) 2283466Srie return (0); 2293466Srie 2300Sstevel@tonic-gate /* LINTED */ 2311618Srie symn = (Word)(shdr->sh_size / shdr->sh_entsize); 2321618Srie syms = (Sym *)symtab->c_data->d_buf; 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate /* 2350Sstevel@tonic-gate * Get the associated string table section. 2360Sstevel@tonic-gate */ 2370Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 2380Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2391618Srie file, symtab->c_name, EC_WORD(shdr->sh_link)); 2400Sstevel@tonic-gate return (0); 2410Sstevel@tonic-gate } 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate /* 2440Sstevel@tonic-gate * Loop through the symbol table to find a match. 2450Sstevel@tonic-gate */ 2461618Srie for (cnt = 0; cnt < symn; syms++, cnt++) { 2471618Srie const char *symname; 2480Sstevel@tonic-gate 2491618Srie symname = string(symtab, cnt, &cache[shdr->sh_link], file, 2501618Srie syms->st_name); 2510Sstevel@tonic-gate 2521618Srie if (symname && (strcmp(name, symname) == 0)) { 2531618Srie *sym = syms; 2540Sstevel@tonic-gate return (1); 2550Sstevel@tonic-gate } 2560Sstevel@tonic-gate } 2570Sstevel@tonic-gate return (0); 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate /* 2610Sstevel@tonic-gate * Print section headers. 2620Sstevel@tonic-gate */ 2630Sstevel@tonic-gate static void 2641618Srie sections(const char *file, Cache *cache, Word shnum, Ehdr *ehdr, 2651618Srie const char *name) 2660Sstevel@tonic-gate { 2671618Srie size_t seccnt; 2680Sstevel@tonic-gate 2691618Srie for (seccnt = 1; seccnt < shnum; seccnt++) { 2701618Srie Cache *_cache = &cache[seccnt]; 2711618Srie Shdr *shdr = _cache->c_shdr; 2721618Srie const char *secname = _cache->c_name; 2730Sstevel@tonic-gate 2741618Srie if (name && strcmp(name, secname)) 2750Sstevel@tonic-gate continue; 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate /* 2780Sstevel@tonic-gate * Although numerous section header entries can be zero, it's 2790Sstevel@tonic-gate * usually a sign of trouble if the name or type are zero. 2800Sstevel@tonic-gate */ 2810Sstevel@tonic-gate if (shdr->sh_type == 0) { 2820Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE), 2831618Srie file, secname, EC_WORD(shdr->sh_type)); 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate if (shdr->sh_name == 0) { 2860Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHNAME), 2871618Srie file, secname, EC_XWORD(shdr->sh_name)); 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate /* 2900Sstevel@tonic-gate * Use the empty string, rather than the fabricated 2910Sstevel@tonic-gate * name for the section output. 2920Sstevel@tonic-gate */ 2931618Srie secname = MSG_ORIG(MSG_STR_EMPTY); 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate 2961324Srie /* 2971324Srie * Identify any sections that are suspicious. A .got section 2981324Srie * shouldn't exist in a relocatable object. 2991324Srie */ 3001324Srie if (ehdr->e_type == ET_REL) { 3011618Srie if (strncmp(secname, MSG_ORIG(MSG_ELF_GOT), 3021324Srie MSG_ELF_GOT_SIZE) == 0) { 3031324Srie (void) fprintf(stderr, 3041618Srie MSG_INTL(MSG_GOT_UNEXPECTED), file, 3051618Srie secname); 3061324Srie } 3071324Srie } 3081324Srie 3091618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 3101618Srie dbg_print(0, MSG_INTL(MSG_ELF_SHDR), EC_WORD(seccnt), secname); 3111618Srie Elf_shdr(0, ehdr->e_machine, shdr); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate 3151618Srie /* 3161618Srie * A couple of instances of unwind data are printed as tables of 8 data items 3171618Srie * expressed as 0x?? integers. 3181618Srie */ 3191618Srie #define UNWINDTBLSZ 10 + (8 * 5) + 1 3201618Srie 3211618Srie static void 3221618Srie unwindtbl(uint64_t *ndx, uint_t len, uchar_t *data, uint64_t doff, 3231618Srie const char *msg, const char *pre, size_t plen) 3241618Srie { 3251618Srie char buffer[UNWINDTBLSZ]; 3261618Srie uint_t boff = plen, cnt = 0; 3271618Srie 3281618Srie dbg_print(0, msg); 3291618Srie (void) strncpy(buffer, pre, UNWINDTBLSZ); 3301618Srie 3311618Srie while (*ndx < (len + 4)) { 3321618Srie if (cnt == 8) { 3331618Srie dbg_print(0, buffer); 3341618Srie boff = plen; 3351618Srie cnt = 0; 3361618Srie } 3371618Srie (void) snprintf(&buffer[boff], UNWINDTBLSZ - boff, 3381618Srie MSG_ORIG(MSG_UNW_TBLENTRY), data[doff + (*ndx)++]); 3391618Srie boff += 5; 3401618Srie cnt++; 3411618Srie } 3421618Srie if (cnt) 3431618Srie dbg_print(0, buffer); 3441618Srie } 3451618Srie 3461618Srie /* 3471618Srie * Obtain a specified Phdr entry. 3481618Srie */ 3491618Srie static Phdr * 3501618Srie getphdr(Word phnum, Word type, const char *file, Elf *elf) 3511618Srie { 3521618Srie Word cnt; 3531618Srie Phdr *phdr; 3541618Srie 3551618Srie if ((phdr = elf_getphdr(elf)) == NULL) { 3561618Srie failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 3571618Srie return (0); 3581618Srie } 3591618Srie 3601618Srie for (cnt = 0; cnt < phnum; phdr++, cnt++) { 3611618Srie if (phdr->p_type == type) 3621618Srie return (phdr); 3631618Srie } 3641618Srie return (0); 3651618Srie } 3661618Srie 3670Sstevel@tonic-gate static void 3681618Srie unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *name, 3691618Srie const char *file, Elf *elf) 3700Sstevel@tonic-gate { 3711618Srie Word cnt; 3721618Srie Phdr *uphdr = 0; 3731618Srie 3740Sstevel@tonic-gate /* 3751618Srie * For the moment - UNWIND is only relevant for a AMD64 object. 3760Sstevel@tonic-gate */ 3770Sstevel@tonic-gate if (ehdr->e_machine != EM_AMD64) 3781618Srie return; 3790Sstevel@tonic-gate 3801618Srie if (phnum) 3811618Srie uphdr = getphdr(phnum, PT_SUNW_UNWIND, file, elf); 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 3841618Srie Cache *_cache = &cache[cnt]; 3851618Srie Shdr *shdr = _cache->c_shdr; 3861618Srie uchar_t *data; 3870Sstevel@tonic-gate size_t datasize; 3881618Srie uint64_t off, ndx, frame_ptr, fde_cnt, tabndx; 3891618Srie uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc; 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate /* 3921618Srie * AMD64 - this is a strmcp() just to find the gcc produced 3931618Srie * sections. Soon gcc should be setting the section type - and 3941618Srie * we'll not need this strcmp(). 3950Sstevel@tonic-gate */ 3960Sstevel@tonic-gate if ((shdr->sh_type != SHT_AMD64_UNWIND) && 3970Sstevel@tonic-gate (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM), 3980Sstevel@tonic-gate MSG_SCN_FRM_SIZE) != 0) && 3990Sstevel@tonic-gate (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 4000Sstevel@tonic-gate MSG_SCN_FRMHDR_SIZE) != 0)) 4010Sstevel@tonic-gate continue; 4020Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 4030Sstevel@tonic-gate continue; 4040Sstevel@tonic-gate 4053466Srie if (_cache->c_data == NULL) 4063466Srie continue; 4073466Srie 4081618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 4091618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name); 4100Sstevel@tonic-gate 4111618Srie data = (uchar_t *)(_cache->c_data->d_buf); 4120Sstevel@tonic-gate datasize = _cache->c_data->d_size; 4130Sstevel@tonic-gate off = 0; 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate /* 4160Sstevel@tonic-gate * Is this a .eh_frame_hdr 4170Sstevel@tonic-gate */ 4181618Srie if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) || 4190Sstevel@tonic-gate (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 4201618Srie MSG_SCN_FRMHDR_SIZE) == 0)) { 4211618Srie 4221618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR)); 4231618Srie ndx = 0; 4240Sstevel@tonic-gate 4251618Srie vers = data[ndx++]; 4261618Srie frame_ptr_enc = data[ndx++]; 4271618Srie fde_cnt_enc = data[ndx++]; 4281618Srie table_enc = data[ndx++]; 4290Sstevel@tonic-gate 4301618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers); 4310Sstevel@tonic-gate 4321618Srie frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc, 4331618Srie ehdr->e_ident, shdr->sh_addr + ndx); 4340Sstevel@tonic-gate 4351618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC), 4361618Srie conv_dwarf_ehe(frame_ptr_enc), EC_XWORD(frame_ptr)); 4371618Srie 4381618Srie fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc, 4391618Srie ehdr->e_ident, shdr->sh_addr + ndx); 4400Sstevel@tonic-gate 4411618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC), 4421618Srie conv_dwarf_ehe(fde_cnt_enc), EC_XWORD(fde_cnt)); 4431618Srie dbg_print(0, MSG_ORIG(MSG_UNW_TABENC), 4441618Srie conv_dwarf_ehe(table_enc)); 4451618Srie dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1)); 4461618Srie dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2)); 4470Sstevel@tonic-gate 4481618Srie for (tabndx = 0; tabndx < fde_cnt; tabndx++) { 4491618Srie dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT), 4501618Srie EC_XWORD(dwarf_ehe_extract(data, &ndx, 4511618Srie table_enc, ehdr->e_ident, shdr->sh_addr)), 4521618Srie EC_XWORD(dwarf_ehe_extract(data, &ndx, 4531618Srie table_enc, ehdr->e_ident, shdr->sh_addr))); 4541618Srie } 4551618Srie continue; 4560Sstevel@tonic-gate } 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate /* 4590Sstevel@tonic-gate * Walk the Eh_frame's 4600Sstevel@tonic-gate */ 4610Sstevel@tonic-gate while (off < datasize) { 4620Sstevel@tonic-gate uint_t cieid, cielength, cieversion, 4630Sstevel@tonic-gate cieretaddr; 4641618Srie int cieRflag, cieLflag, ciePflag, cieZflag; 4651618Srie uint_t cieaugndx, length, id; 4660Sstevel@tonic-gate uint64_t ciecalign, ciedalign; 4670Sstevel@tonic-gate char *cieaugstr; 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate ndx = 0; 4700Sstevel@tonic-gate /* 4710Sstevel@tonic-gate * extract length in lsb format 4720Sstevel@tonic-gate */ 4730Sstevel@tonic-gate length = LSB32EXTRACT(data + off + ndx); 4740Sstevel@tonic-gate ndx += 4; 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate /* 4770Sstevel@tonic-gate * extract CIE id in lsb format 4780Sstevel@tonic-gate */ 4790Sstevel@tonic-gate id = LSB32EXTRACT(data + off + ndx); 4800Sstevel@tonic-gate ndx += 4; 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate /* 4831618Srie * A CIE record has a id of '0', otherwise this is a 4841618Srie * FDE entry and the 'id' is the CIE pointer. 4850Sstevel@tonic-gate */ 4860Sstevel@tonic-gate if (id == 0) { 4870Sstevel@tonic-gate uint64_t persVal; 4881618Srie 4890Sstevel@tonic-gate cielength = length; 4900Sstevel@tonic-gate cieid = id; 4911618Srie cieLflag = ciePflag = cieRflag = cieZflag = 0; 4920Sstevel@tonic-gate 4931618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIE), 4941618Srie EC_XWORD(shdr->sh_addr + off)); 4951618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH), 4961618Srie cielength, cieid); 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate cieversion = data[off + ndx]; 4990Sstevel@tonic-gate ndx += 1; 5000Sstevel@tonic-gate cieaugstr = (char *)(&data[off + ndx]); 5010Sstevel@tonic-gate ndx += strlen(cieaugstr) + 1; 5021618Srie 5031618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS), 5041618Srie cieversion, cieaugstr); 5051618Srie 5060Sstevel@tonic-gate ciecalign = uleb_extract(&data[off], &ndx); 5070Sstevel@tonic-gate ciedalign = sleb_extract(&data[off], &ndx); 5080Sstevel@tonic-gate cieretaddr = data[off + ndx]; 5090Sstevel@tonic-gate ndx += 1; 5101618Srie 5111618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN), 5121618Srie EC_XWORD(ciecalign), EC_XWORD(ciedalign), 5131618Srie cieretaddr); 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate if (cieaugstr[0]) 5161618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIEAUXVAL)); 5171618Srie 5180Sstevel@tonic-gate for (cieaugndx = 0; cieaugstr[cieaugndx]; 5190Sstevel@tonic-gate cieaugndx++) { 5200Sstevel@tonic-gate uint_t val; 5211618Srie 5220Sstevel@tonic-gate switch (cieaugstr[cieaugndx]) { 5230Sstevel@tonic-gate case 'z': 5240Sstevel@tonic-gate val = uleb_extract(&data[off], 5250Sstevel@tonic-gate &ndx); 5261618Srie dbg_print(0, 5270Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXSIZE), 5280Sstevel@tonic-gate val); 5290Sstevel@tonic-gate cieZflag = 1; 5300Sstevel@tonic-gate break; 5310Sstevel@tonic-gate case 'P': 5320Sstevel@tonic-gate ciePflag = data[off + ndx]; 5330Sstevel@tonic-gate ndx += 1; 5340Sstevel@tonic-gate 5350Sstevel@tonic-gate persVal = dwarf_ehe_extract( 5360Sstevel@tonic-gate &data[off], 5370Sstevel@tonic-gate &ndx, ciePflag, ehdr->e_ident, 5380Sstevel@tonic-gate shdr->sh_addr + off + ndx); 5391618Srie dbg_print(0, 5400Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXPERS), 5410Sstevel@tonic-gate ciePflag, 5421618Srie conv_dwarf_ehe(ciePflag), 5430Sstevel@tonic-gate EC_XWORD(persVal)); 5440Sstevel@tonic-gate break; 5450Sstevel@tonic-gate case 'R': 5460Sstevel@tonic-gate val = data[off + ndx]; 5470Sstevel@tonic-gate ndx += 1; 5481618Srie dbg_print(0, 5490Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXCENC), 5501618Srie val, conv_dwarf_ehe(val)); 5510Sstevel@tonic-gate cieRflag = val; 5520Sstevel@tonic-gate break; 5530Sstevel@tonic-gate case 'L': 5540Sstevel@tonic-gate val = data[off + ndx]; 5550Sstevel@tonic-gate ndx += 1; 5561618Srie dbg_print(0, 5570Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXLSDA), 5581618Srie val, conv_dwarf_ehe(val)); 5590Sstevel@tonic-gate cieLflag = val; 5600Sstevel@tonic-gate break; 5610Sstevel@tonic-gate default: 5621618Srie dbg_print(0, 5630Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXUNEC), 5640Sstevel@tonic-gate cieaugstr[cieaugndx]); 5650Sstevel@tonic-gate break; 5660Sstevel@tonic-gate } 5670Sstevel@tonic-gate } 5681618Srie if ((cielength + 4) > ndx) 5691618Srie unwindtbl(&ndx, cielength, data, off, 5701618Srie MSG_ORIG(MSG_UNW_CIECFI), 5711618Srie MSG_ORIG(MSG_UNW_CIEPRE), 5721618Srie MSG_UNW_CIEPRE_SIZE); 5730Sstevel@tonic-gate off += cielength + 4; 5741618Srie 5750Sstevel@tonic-gate } else { 5760Sstevel@tonic-gate uint_t fdelength = length; 5770Sstevel@tonic-gate int fdecieptr = id; 5780Sstevel@tonic-gate uint64_t fdeinitloc, fdeaddrrange; 5790Sstevel@tonic-gate 5801618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FDE), 5811618Srie EC_XWORD(shdr->sh_addr + off)); 5821618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH), 5830Sstevel@tonic-gate fdelength, fdecieptr); 5841618Srie 5850Sstevel@tonic-gate fdeinitloc = dwarf_ehe_extract(&data[off], 5860Sstevel@tonic-gate &ndx, cieRflag, ehdr->e_ident, 5870Sstevel@tonic-gate shdr->sh_addr + off + ndx); 5880Sstevel@tonic-gate fdeaddrrange = dwarf_ehe_extract(&data[off], 5890Sstevel@tonic-gate &ndx, (cieRflag & ~DW_EH_PE_pcrel), 5900Sstevel@tonic-gate ehdr->e_ident, 5910Sstevel@tonic-gate shdr->sh_addr + off + ndx); 5921618Srie 5931618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC), 5941618Srie EC_XWORD(fdeinitloc), 5951618Srie EC_XWORD(fdeaddrrange)); 5961618Srie 5970Sstevel@tonic-gate if (cieaugstr[0]) 5981618Srie dbg_print(0, 5991618Srie MSG_ORIG(MSG_UNW_FDEAUXVAL)); 6000Sstevel@tonic-gate if (cieZflag) { 6010Sstevel@tonic-gate uint64_t val; 6020Sstevel@tonic-gate val = uleb_extract(&data[off], &ndx); 6031618Srie dbg_print(0, 6041618Srie MSG_ORIG(MSG_UNW_FDEAUXSIZE), 6051618Srie EC_XWORD(val)); 6060Sstevel@tonic-gate if (val & cieLflag) { 6070Sstevel@tonic-gate fdeinitloc = dwarf_ehe_extract( 6080Sstevel@tonic-gate &data[off], &ndx, cieLflag, 6090Sstevel@tonic-gate ehdr->e_ident, 6100Sstevel@tonic-gate shdr->sh_addr + off + ndx); 6111618Srie dbg_print(0, 6120Sstevel@tonic-gate MSG_ORIG(MSG_UNW_FDEAUXLSDA), 6131618Srie EC_XWORD(val)); 6140Sstevel@tonic-gate } 6150Sstevel@tonic-gate } 6161618Srie if ((fdelength + 4) > ndx) 6171618Srie unwindtbl(&ndx, fdelength, data, off, 6181618Srie MSG_ORIG(MSG_UNW_FDECFI), 6191618Srie MSG_ORIG(MSG_UNW_FDEPRE), 6201618Srie MSG_UNW_FDEPRE_SIZE); 6210Sstevel@tonic-gate off += fdelength + 4; 6220Sstevel@tonic-gate } 6230Sstevel@tonic-gate } 6240Sstevel@tonic-gate } 6250Sstevel@tonic-gate } 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate /* 6280Sstevel@tonic-gate * Print the hardware/software capabilities. For executables and shared objects 6290Sstevel@tonic-gate * this should be accompanied with a program header. 6300Sstevel@tonic-gate */ 6310Sstevel@tonic-gate static void 6321618Srie cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, 6331618Srie Elf *elf) 6340Sstevel@tonic-gate { 6351618Srie Word cnt; 6363466Srie Shdr *cshdr = 0; 6373466Srie Cache *ccache; 6381618Srie Off cphdr_off = 0; 6391618Srie Xword cphdr_sz; 6400Sstevel@tonic-gate 6410Sstevel@tonic-gate /* 6420Sstevel@tonic-gate * Determine if a hardware/software capabilities header exists. 6430Sstevel@tonic-gate */ 6441618Srie if (phnum) { 6451618Srie Phdr *phdr; 6460Sstevel@tonic-gate 6471618Srie if ((phdr = elf_getphdr(elf)) == NULL) { 6480Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 6490Sstevel@tonic-gate return; 6500Sstevel@tonic-gate } 6510Sstevel@tonic-gate 6521618Srie for (cnt = 0; cnt < phnum; phdr++, cnt++) { 6531618Srie if (phdr->p_type == PT_SUNWCAP) { 6541618Srie cphdr_off = phdr->p_offset; 6551618Srie cphdr_sz = phdr->p_filesz; 6561618Srie break; 6571618Srie } 6580Sstevel@tonic-gate } 6590Sstevel@tonic-gate } 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate /* 6620Sstevel@tonic-gate * Determine if a hardware/software capabilities section exists. 6630Sstevel@tonic-gate */ 6640Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 6651618Srie Cache *_cache = &cache[cnt]; 6661618Srie Shdr *shdr = _cache->c_shdr; 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate if (shdr->sh_type != SHT_SUNW_cap) 6690Sstevel@tonic-gate continue; 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate if (cphdr_off && ((cphdr_off < shdr->sh_offset) || 6720Sstevel@tonic-gate (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size))) 6730Sstevel@tonic-gate continue; 6740Sstevel@tonic-gate 6753466Srie if (_cache->c_data == NULL) 6763466Srie continue; 6773466Srie 6780Sstevel@tonic-gate ccache = _cache; 6790Sstevel@tonic-gate cshdr = shdr; 6800Sstevel@tonic-gate break; 6810Sstevel@tonic-gate } 6820Sstevel@tonic-gate 6830Sstevel@tonic-gate if ((cshdr == 0) && (cphdr_off == 0)) 6840Sstevel@tonic-gate return; 6850Sstevel@tonic-gate 6863466Srie if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) { 6873466Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 6883466Srie file, ccache->c_name); 6893466Srie return; 6903466Srie } 6913466Srie 6920Sstevel@tonic-gate /* 6930Sstevel@tonic-gate * Print the hardware/software capabilities section. 6940Sstevel@tonic-gate */ 6950Sstevel@tonic-gate if (cshdr) { 6961618Srie Word ndx, capn; 697*3492Sab196087 Cap *cap = (Cap *)ccache->c_data->d_buf; 6980Sstevel@tonic-gate 6991618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 7001618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name); 7010Sstevel@tonic-gate 7021618Srie Elf_cap_title(0); 7031618Srie 7041618Srie capn = (Word)(cshdr->sh_size / cshdr->sh_entsize); 7050Sstevel@tonic-gate 7061618Srie for (ndx = 0; ndx < capn; cap++, ndx++) { 7071618Srie if (cap->c_tag != CA_SUNW_NULL) 7081618Srie Elf_cap_entry(0, cap, ndx, ehdr->e_machine); 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate } else 7110Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file); 7120Sstevel@tonic-gate 7130Sstevel@tonic-gate /* 7140Sstevel@tonic-gate * If this object is an executable or shared object, then the 7150Sstevel@tonic-gate * hardware/software capabilities section should have an accompanying 7160Sstevel@tonic-gate * program header. 7170Sstevel@tonic-gate */ 7180Sstevel@tonic-gate if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) { 7190Sstevel@tonic-gate if (cphdr_off == 0) 7200Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2), 7210Sstevel@tonic-gate file, ccache->c_name); 7220Sstevel@tonic-gate else if ((cphdr_off != cshdr->sh_offset) || 7230Sstevel@tonic-gate (cphdr_sz != cshdr->sh_size)) 7240Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3), 7250Sstevel@tonic-gate file, ccache->c_name); 7260Sstevel@tonic-gate } 7270Sstevel@tonic-gate } 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate /* 7300Sstevel@tonic-gate * Print the interpretor. 7310Sstevel@tonic-gate */ 7320Sstevel@tonic-gate static void 7331618Srie interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf) 7340Sstevel@tonic-gate { 7351618Srie Word cnt; 7361618Srie Shdr *ishdr = 0; 7371618Srie Cache *icache; 7381618Srie Off iphdr_off = 0; 7391618Srie Xword iphdr_fsz; 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate /* 7420Sstevel@tonic-gate * Determine if an interp header exists. 7430Sstevel@tonic-gate */ 7441618Srie if (phnum) { 7451618Srie Phdr *phdr; 7460Sstevel@tonic-gate 7471618Srie if ((phdr = getphdr(phnum, PT_INTERP, file, elf)) != 0) { 7481618Srie iphdr_off = phdr->p_offset; 7491618Srie iphdr_fsz = phdr->p_filesz; 7500Sstevel@tonic-gate } 7510Sstevel@tonic-gate } 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate if (iphdr_off == 0) 7540Sstevel@tonic-gate return; 7550Sstevel@tonic-gate 7560Sstevel@tonic-gate /* 7570Sstevel@tonic-gate * Determine if an interp section exists. 7580Sstevel@tonic-gate */ 7590Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 7601618Srie Cache *_cache = &cache[cnt]; 7611618Srie Shdr *shdr = _cache->c_shdr; 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate /* 7640Sstevel@tonic-gate * Scan sections to find a section which contains the PT_INTERP 7650Sstevel@tonic-gate * string. The target section can't be in a NOBITS section. 7660Sstevel@tonic-gate */ 7670Sstevel@tonic-gate if ((shdr->sh_type == SHT_NOBITS) || 7680Sstevel@tonic-gate (iphdr_off < shdr->sh_offset) || 7691618Srie (iphdr_off + iphdr_fsz) > (shdr->sh_offset + shdr->sh_size)) 7700Sstevel@tonic-gate continue; 7710Sstevel@tonic-gate 7720Sstevel@tonic-gate icache = _cache; 7730Sstevel@tonic-gate ishdr = shdr; 7740Sstevel@tonic-gate break; 7750Sstevel@tonic-gate } 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate /* 7780Sstevel@tonic-gate * Print the interpreter string based on the offset defined in the 7790Sstevel@tonic-gate * program header, as this is the offset used by the kernel. 7800Sstevel@tonic-gate */ 7813466Srie if (ishdr && icache->c_data) { 7821618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 7831618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name); 7841618Srie dbg_print(0, MSG_ORIG(MSG_FMT_INDENT), 7850Sstevel@tonic-gate (char *)icache->c_data->d_buf + 7860Sstevel@tonic-gate (iphdr_off - ishdr->sh_offset)); 7870Sstevel@tonic-gate } else 7880Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file); 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate /* 7910Sstevel@tonic-gate * If there are any inconsistences between the program header and 7920Sstevel@tonic-gate * section information, flag them. 7930Sstevel@tonic-gate */ 7940Sstevel@tonic-gate if (ishdr && ((iphdr_off != ishdr->sh_offset) || 7951618Srie (iphdr_fsz != ishdr->sh_size))) { 7960Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file, 7970Sstevel@tonic-gate icache->c_name); 7980Sstevel@tonic-gate } 7990Sstevel@tonic-gate } 8000Sstevel@tonic-gate 8010Sstevel@tonic-gate /* 8020Sstevel@tonic-gate * Print the syminfo section. 8030Sstevel@tonic-gate */ 8040Sstevel@tonic-gate static void 8051618Srie syminfo(Cache *cache, Word shnum, const char *file) 8060Sstevel@tonic-gate { 8071618Srie Shdr *infoshdr; 8081618Srie Syminfo *info; 8091618Srie Sym *syms; 8101618Srie Dyn *dyns; 8111618Srie Word infonum, cnt, ndx, symnum; 8121618Srie Cache *infocache = 0, *symsec, *strsec; 8130Sstevel@tonic-gate 8140Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 8151618Srie if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) { 8161618Srie infocache = &cache[cnt]; 8170Sstevel@tonic-gate break; 8180Sstevel@tonic-gate } 8190Sstevel@tonic-gate } 8201618Srie if (infocache == 0) 8210Sstevel@tonic-gate return; 8220Sstevel@tonic-gate 8231618Srie infoshdr = infocache->c_shdr; 8241618Srie if ((infoshdr->sh_entsize == 0) || (infoshdr->sh_size == 0)) { 8250Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 8261618Srie file, infocache->c_name); 8270Sstevel@tonic-gate return; 8280Sstevel@tonic-gate } 8293466Srie if (infocache->c_data == NULL) 8303466Srie return; 8313466Srie 8321618Srie infonum = (Word)(infoshdr->sh_size / infoshdr->sh_entsize); 8331618Srie info = (Syminfo *)infocache->c_data->d_buf; 8340Sstevel@tonic-gate 8350Sstevel@tonic-gate /* 8360Sstevel@tonic-gate * Get the data buffer of the associated dynamic section. 8370Sstevel@tonic-gate */ 8381618Srie if ((infoshdr->sh_info == 0) || (infoshdr->sh_info >= shnum)) { 8390Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 8401618Srie file, infocache->c_name, EC_WORD(infoshdr->sh_info)); 8410Sstevel@tonic-gate return; 8420Sstevel@tonic-gate } 8433466Srie if (cache[infoshdr->sh_info].c_data == NULL) 8443466Srie return; 8453466Srie 8461618Srie dyns = cache[infoshdr->sh_info].c_data->d_buf; 8471618Srie if (dyns == 0) { 8480Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 8491618Srie file, cache[infoshdr->sh_info].c_name); 8500Sstevel@tonic-gate return; 8510Sstevel@tonic-gate } 8520Sstevel@tonic-gate 8530Sstevel@tonic-gate /* 8541618Srie * Get the data buffer for the associated symbol table and string table. 8550Sstevel@tonic-gate */ 8561618Srie if (stringtbl(cache, 1, cnt, shnum, file, 8571618Srie &symnum, &symsec, &strsec) == 0) 8580Sstevel@tonic-gate return; 8590Sstevel@tonic-gate 8601618Srie syms = symsec->c_data->d_buf; 8610Sstevel@tonic-gate 8621618Srie /* 8631618Srie * Loop through the syminfo entries. 8641618Srie */ 8651618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 8661618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMINFO), infocache->c_name); 8671618Srie Elf_syminfo_title(0); 8680Sstevel@tonic-gate 8691618Srie for (ndx = 1, info++; ndx < infonum; ndx++, info++) { 8701618Srie Sym *sym; 8711618Srie const char *needed = 0, *name; 8721618Srie 8731618Srie if ((info->si_flags == 0) && (info->si_boundto == 0)) 8740Sstevel@tonic-gate continue; 8750Sstevel@tonic-gate 8761618Srie sym = &syms[ndx]; 8771618Srie name = string(infocache, ndx, strsec, file, sym->st_name); 8780Sstevel@tonic-gate 8791618Srie if (info->si_boundto < SYMINFO_BT_LOWRESERVE) { 8801618Srie Dyn *dyn = &dyns[info->si_boundto]; 8811618Srie 8821618Srie needed = string(infocache, info->si_boundto, 8831618Srie strsec, file, dyn->d_un.d_val); 8840Sstevel@tonic-gate } 8851618Srie Elf_syminfo_entry(0, ndx, info, name, needed); 8860Sstevel@tonic-gate } 8870Sstevel@tonic-gate } 8880Sstevel@tonic-gate 8890Sstevel@tonic-gate /* 8900Sstevel@tonic-gate * Print version definition section entries. 8910Sstevel@tonic-gate */ 8920Sstevel@tonic-gate static void 8931618Srie version_def(Verdef *vdf, Word shnum, Cache *vcache, Cache *scache, 8940Sstevel@tonic-gate const char *file) 8950Sstevel@tonic-gate { 8961618Srie Word cnt; 8971618Srie char index[MAXNDXSIZE]; 8980Sstevel@tonic-gate 8991618Srie Elf_ver_def_title(0); 9000Sstevel@tonic-gate 9010Sstevel@tonic-gate for (cnt = 1; cnt <= shnum; cnt++, 9021618Srie vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) { 9030Sstevel@tonic-gate const char *name, *dep; 9041618Srie Half vcnt = vdf->vd_cnt - 1; 9051618Srie Half ndx = vdf->vd_ndx; 9061618Srie Verdaux *vdap = (Verdaux *)((uintptr_t)vdf + 9071618Srie vdf->vd_aux); 9080Sstevel@tonic-gate 9090Sstevel@tonic-gate /* 9100Sstevel@tonic-gate * Obtain the name and first dependency (if any). 9110Sstevel@tonic-gate */ 9120Sstevel@tonic-gate name = string(vcache, cnt, scache, file, vdap->vda_name); 9131618Srie vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 9140Sstevel@tonic-gate if (vcnt) 9150Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, vdap->vda_name); 9160Sstevel@tonic-gate else 9170Sstevel@tonic-gate dep = MSG_ORIG(MSG_STR_EMPTY); 9180Sstevel@tonic-gate 9190Sstevel@tonic-gate (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX), 9200Sstevel@tonic-gate EC_XWORD(ndx)); 9211618Srie Elf_ver_line_1(0, index, name, dep, 9221618Srie conv_ver_flags(vdf->vd_flags)); 9230Sstevel@tonic-gate 9240Sstevel@tonic-gate /* 9250Sstevel@tonic-gate * Print any additional dependencies. 9260Sstevel@tonic-gate */ 9270Sstevel@tonic-gate if (vcnt) { 9281618Srie vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 9290Sstevel@tonic-gate for (vcnt--; vcnt; vcnt--, 9301618Srie vdap = (Verdaux *)((uintptr_t)vdap + 9310Sstevel@tonic-gate vdap->vda_next)) { 9320Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, 9330Sstevel@tonic-gate vdap->vda_name); 9341618Srie Elf_ver_line_2(0, MSG_ORIG(MSG_STR_EMPTY), dep); 9350Sstevel@tonic-gate } 9360Sstevel@tonic-gate } 9370Sstevel@tonic-gate } 9380Sstevel@tonic-gate } 9390Sstevel@tonic-gate 9400Sstevel@tonic-gate /* 9410Sstevel@tonic-gate * Print a version needed section entries. 9420Sstevel@tonic-gate */ 9430Sstevel@tonic-gate static void 9441618Srie version_need(Verneed *vnd, Word shnum, Cache *vcache, Cache *scache, 9450Sstevel@tonic-gate const char *file) 9460Sstevel@tonic-gate { 9471618Srie Word cnt; 9480Sstevel@tonic-gate 9491618Srie Elf_ver_need_title(0); 9500Sstevel@tonic-gate 9510Sstevel@tonic-gate for (cnt = 1; cnt <= shnum; cnt++, 9521618Srie vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 9530Sstevel@tonic-gate const char *name, *dep; 9541618Srie Half vcnt = vnd->vn_cnt; 9551618Srie Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + 9561618Srie vnd->vn_aux); 9570Sstevel@tonic-gate 9580Sstevel@tonic-gate /* 9590Sstevel@tonic-gate * Obtain the name of the needed file and the version name 9600Sstevel@tonic-gate * within it that we're dependent on. Note that the count 9610Sstevel@tonic-gate * should be at least one, otherwise this is a pretty bogus 9620Sstevel@tonic-gate * entry. 9630Sstevel@tonic-gate */ 9640Sstevel@tonic-gate name = string(vcache, cnt, scache, file, vnd->vn_file); 9650Sstevel@tonic-gate if (vcnt) 9660Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, vnap->vna_name); 9670Sstevel@tonic-gate else 9680Sstevel@tonic-gate dep = MSG_INTL(MSG_STR_NULL); 9690Sstevel@tonic-gate 9701618Srie Elf_ver_line_1(0, MSG_ORIG(MSG_STR_EMPTY), name, dep, 9711618Srie conv_ver_flags(vnap->vna_flags)); 9720Sstevel@tonic-gate 9730Sstevel@tonic-gate /* 9740Sstevel@tonic-gate * Print any additional version dependencies. 9750Sstevel@tonic-gate */ 9760Sstevel@tonic-gate if (vcnt) { 9771618Srie vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next); 9780Sstevel@tonic-gate for (vcnt--; vcnt; vcnt--, 9791618Srie vnap = (Vernaux *)((uintptr_t)vnap + 9800Sstevel@tonic-gate vnap->vna_next)) { 9810Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, 9820Sstevel@tonic-gate vnap->vna_name); 9831618Srie Elf_ver_line_3(0, MSG_ORIG(MSG_STR_EMPTY), dep, 9841618Srie conv_ver_flags(vnap->vna_flags)); 9850Sstevel@tonic-gate } 9860Sstevel@tonic-gate } 9870Sstevel@tonic-gate } 9880Sstevel@tonic-gate } 9890Sstevel@tonic-gate 9900Sstevel@tonic-gate /* 9911618Srie * Search for any version sections - the Versym output is possibly used by the 9921618Srie * symbols() printing. If VERSYM is specified - then display the version 9931618Srie * information. 9940Sstevel@tonic-gate */ 9950Sstevel@tonic-gate static Cache * 9961618Srie versions(Cache *cache, Word shnum, const char *file, uint_t flags) 9970Sstevel@tonic-gate { 9980Sstevel@tonic-gate GElf_Word cnt; 9990Sstevel@tonic-gate Cache *versymcache = 0; 10000Sstevel@tonic-gate 10010Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 10021618Srie void *ver; 10030Sstevel@tonic-gate uint_t num; 10041618Srie Cache *_cache = &cache[cnt]; 10051618Srie Shdr *shdr = _cache->c_shdr; 10061618Srie const char *secname = _cache->c_name; 10070Sstevel@tonic-gate 10080Sstevel@tonic-gate /* 10090Sstevel@tonic-gate * If this is the version symbol table simply record its 10100Sstevel@tonic-gate * data address for possible use in later symbol processing. 10110Sstevel@tonic-gate */ 10120Sstevel@tonic-gate if (shdr->sh_type == SHT_SUNW_versym) { 10130Sstevel@tonic-gate versymcache = _cache; 10140Sstevel@tonic-gate continue; 10150Sstevel@tonic-gate } 10160Sstevel@tonic-gate 10170Sstevel@tonic-gate if ((flags & FLG_VERSIONS) == 0) 10180Sstevel@tonic-gate continue; 10190Sstevel@tonic-gate 10200Sstevel@tonic-gate if ((shdr->sh_type != SHT_SUNW_verdef) && 10210Sstevel@tonic-gate (shdr->sh_type != SHT_SUNW_verneed)) 10220Sstevel@tonic-gate continue; 10230Sstevel@tonic-gate 10240Sstevel@tonic-gate /* 10250Sstevel@tonic-gate * Determine the version section data and number. 10260Sstevel@tonic-gate */ 10273466Srie if ((_cache->c_data == NULL) || 10283466Srie ((ver = (void *)_cache->c_data->d_buf) == NULL)) { 10290Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 10301618Srie file, secname); 10310Sstevel@tonic-gate continue; 10320Sstevel@tonic-gate } 10330Sstevel@tonic-gate if ((num = shdr->sh_info) == 0) { 10340Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 10351618Srie file, secname, EC_WORD(shdr->sh_info)); 10360Sstevel@tonic-gate continue; 10370Sstevel@tonic-gate } 10380Sstevel@tonic-gate 10390Sstevel@tonic-gate /* 10400Sstevel@tonic-gate * Get the data buffer for the associated string table. 10410Sstevel@tonic-gate */ 10420Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 10430Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 10441618Srie file, secname, EC_WORD(shdr->sh_link)); 10450Sstevel@tonic-gate continue; 10460Sstevel@tonic-gate } 10470Sstevel@tonic-gate 10481618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 10490Sstevel@tonic-gate if (shdr->sh_type == SHT_SUNW_verdef) { 10501618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERDEF), secname); 10511618Srie version_def((Verdef *)ver, num, _cache, 10520Sstevel@tonic-gate &cache[shdr->sh_link], file); 10530Sstevel@tonic-gate } else if (shdr->sh_type == SHT_SUNW_verneed) { 10541618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERNEED), secname); 10551618Srie version_need((Verneed *)ver, num, _cache, 10560Sstevel@tonic-gate &cache[shdr->sh_link], file); 10570Sstevel@tonic-gate } 10580Sstevel@tonic-gate } 10590Sstevel@tonic-gate return (versymcache); 10600Sstevel@tonic-gate } 10610Sstevel@tonic-gate 10620Sstevel@tonic-gate /* 1063*3492Sab196087 * SYMTBL_STATE is used to maintain information about a single symbol 1064*3492Sab196087 * table section, for use by the routines that display symbol information. 1065*3492Sab196087 */ 1066*3492Sab196087 typedef struct { 1067*3492Sab196087 const char *file; /* Name of file */ 1068*3492Sab196087 Ehdr *ehdr; /* ELF header for file */ 1069*3492Sab196087 Cache *cache; /* Cache of all section headers */ 1070*3492Sab196087 Word shnum; /* # of sections in cache */ 1071*3492Sab196087 Cache *seccache; /* Cache of symbol table section hdr */ 1072*3492Sab196087 Word secndx; /* Index of symbol table section hdr */ 1073*3492Sab196087 const char *secname; /* Name of section */ 1074*3492Sab196087 uint_t flags; /* Command line option flags */ 1075*3492Sab196087 struct { /* Extended section index data */ 1076*3492Sab196087 int checked; /* TRUE if already checked for shxndx */ 1077*3492Sab196087 Word *data; /* NULL, or extended section index */ 1078*3492Sab196087 /* used for symbol table entries */ 1079*3492Sab196087 uint_t n; /* # items in shxndx.data */ 1080*3492Sab196087 } shxndx; 1081*3492Sab196087 Versym *versym; /* NULL, or versym array for symtbl */ 1082*3492Sab196087 Sym *sym; /* Array of symbols */ 1083*3492Sab196087 Word symn; /* # of symbols */ 1084*3492Sab196087 } SYMTBL_STATE; 1085*3492Sab196087 1086*3492Sab196087 /* 1087*3492Sab196087 * Initialize a symbol table state structure 1088*3492Sab196087 * 1089*3492Sab196087 * entry: 1090*3492Sab196087 * state - State structure to be initialized 1091*3492Sab196087 * cache - Cache of all section headers 1092*3492Sab196087 * shnum - # of sections in cache 1093*3492Sab196087 * secndx - Index of symbol table section 1094*3492Sab196087 * ehdr - ELF header for file 1095*3492Sab196087 * versymcache - NULL, or cache of versym section 1096*3492Sab196087 * file - Name of file 1097*3492Sab196087 * flags - Command line option flags 10981618Srie */ 10991618Srie static int 1100*3492Sab196087 init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx, 1101*3492Sab196087 Ehdr *ehdr, Cache *versymcache, const char *file, uint_t flags) 1102*3492Sab196087 { 1103*3492Sab196087 Shdr *shdr; 1104*3492Sab196087 1105*3492Sab196087 state->file = file; 1106*3492Sab196087 state->ehdr = ehdr; 1107*3492Sab196087 state->cache = cache; 1108*3492Sab196087 state->shnum = shnum; 1109*3492Sab196087 state->seccache = &cache[secndx]; 1110*3492Sab196087 state->secndx = secndx; 1111*3492Sab196087 state->secname = state->seccache->c_name; 1112*3492Sab196087 state->flags = flags; 1113*3492Sab196087 state->shxndx.checked = 0; 1114*3492Sab196087 state->shxndx.data = NULL; 1115*3492Sab196087 state->shxndx.n = 0; 1116*3492Sab196087 1117*3492Sab196087 shdr = state->seccache->c_shdr; 1118*3492Sab196087 1119*3492Sab196087 /* 1120*3492Sab196087 * Check the symbol data and per-item size. 1121*3492Sab196087 */ 1122*3492Sab196087 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1123*3492Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1124*3492Sab196087 file, state->secname); 1125*3492Sab196087 return (0); 1126*3492Sab196087 } 1127*3492Sab196087 if (state->seccache->c_data == NULL) 1128*3492Sab196087 return (0); 1129*3492Sab196087 1130*3492Sab196087 /* LINTED */ 1131*3492Sab196087 state->symn = (Word)(shdr->sh_size / shdr->sh_entsize); 1132*3492Sab196087 state->sym = (Sym *)state->seccache->c_data->d_buf; 1133*3492Sab196087 1134*3492Sab196087 /* 1135*3492Sab196087 * Check associated string table section. 1136*3492Sab196087 */ 1137*3492Sab196087 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1138*3492Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1139*3492Sab196087 file, state->secname, EC_WORD(shdr->sh_link)); 1140*3492Sab196087 return (0); 1141*3492Sab196087 } 1142*3492Sab196087 1143*3492Sab196087 /* 1144*3492Sab196087 * Determine if there is a associated Versym section 1145*3492Sab196087 * with this Symbol Table. 1146*3492Sab196087 */ 1147*3492Sab196087 if (versymcache && (versymcache->c_shdr->sh_link == state->secndx) && 1148*3492Sab196087 versymcache->c_data) 1149*3492Sab196087 state->versym = versymcache->c_data->d_buf; 1150*3492Sab196087 else 1151*3492Sab196087 state->versym = NULL; 1152*3492Sab196087 1153*3492Sab196087 1154*3492Sab196087 return (1); 1155*3492Sab196087 } 1156*3492Sab196087 1157*3492Sab196087 /* 1158*3492Sab196087 * Determine the extended section index used for symbol tables entries. 1159*3492Sab196087 */ 1160*3492Sab196087 static void 1161*3492Sab196087 symbols_getxindex(SYMTBL_STATE * state) 11621618Srie { 11631618Srie uint_t symn; 11641618Srie Word symcnt; 11651618Srie 1166*3492Sab196087 state->shxndx.checked = 1; /* Note that we've been called */ 1167*3492Sab196087 for (symcnt = 1; symcnt < state->shnum; symcnt++) { 1168*3492Sab196087 Cache *_cache = &state->cache[symcnt]; 11691618Srie Shdr *shdr = _cache->c_shdr; 11701618Srie 11711618Srie if ((shdr->sh_type != SHT_SYMTAB_SHNDX) || 1172*3492Sab196087 (shdr->sh_link != state->secndx)) 11731618Srie continue; 11741618Srie 11751618Srie if ((shdr->sh_entsize) && 11761618Srie /* LINTED */ 11771618Srie ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0)) 11781618Srie continue; 11791618Srie 11803466Srie if (_cache->c_data == NULL) 11813466Srie continue; 11823466Srie 1183*3492Sab196087 state->shxndx.data = _cache->c_data->d_buf; 1184*3492Sab196087 state->shxndx.n = symn; 1185*3492Sab196087 return; 11861618Srie } 11871618Srie } 11881618Srie 11891618Srie /* 1190*3492Sab196087 * Produce a line of output for the given symbol 1191*3492Sab196087 * 1192*3492Sab196087 * entry: 1193*3492Sab196087 * symndx - Index of symbol within the table 1194*3492Sab196087 * symndx_disp - Index to display. This may not be the same 1195*3492Sab196087 * as symndx if the display is relative to the logical 1196*3492Sab196087 * combination of the SUNW_ldynsym/dynsym tables. 1197*3492Sab196087 * sym - Symbol to display 1198*3492Sab196087 * state - Symbol table state 11990Sstevel@tonic-gate */ 1200*3492Sab196087 static void 1201*3492Sab196087 output_symbol(SYMTBL_STATE *state, Word symndx, Word disp_symndx, Sym *sym) 12020Sstevel@tonic-gate { 12033118Sab196087 /* 12043118Sab196087 * Symbol types for which we check that the specified 12053118Sab196087 * address/size land inside the target section. 12063118Sab196087 */ 1207*3492Sab196087 static const int addr_symtype[STT_NUM] = { 12083118Sab196087 0, /* STT_NOTYPE */ 12093118Sab196087 1, /* STT_OBJECT */ 12103118Sab196087 1, /* STT_FUNC */ 12113118Sab196087 0, /* STT_SECTION */ 12123118Sab196087 0, /* STT_FILE */ 12133118Sab196087 1, /* STT_COMMON */ 12143118Sab196087 0, /* STT_TLS */ 12153118Sab196087 }; 12163118Sab196087 #if STT_NUM != (STT_TLS + 1) 1217*3492Sab196087 #error "STT_NUM has grown. Update addr_symtype[]" 12183118Sab196087 #endif 12193118Sab196087 1220*3492Sab196087 char index[MAXNDXSIZE], *sec; 1221*3492Sab196087 const char *symname; 1222*3492Sab196087 int verndx; 1223*3492Sab196087 uchar_t type; 1224*3492Sab196087 Shdr *tshdr; 1225*3492Sab196087 Word shndx; 1226*3492Sab196087 1227*3492Sab196087 /* Ensure symbol index is in range */ 1228*3492Sab196087 if (symndx >= state->symn) { 1229*3492Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORTNDX), 1230*3492Sab196087 state->file, state->secname, EC_WORD(symndx)); 1231*3492Sab196087 return; 1232*3492Sab196087 } 1233*3492Sab196087 1234*3492Sab196087 /* 1235*3492Sab196087 * If we are using extended symbol indexes, find the 1236*3492Sab196087 * corresponding SHN_SYMTAB_SHNDX table. 1237*3492Sab196087 */ 1238*3492Sab196087 if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0)) 1239*3492Sab196087 symbols_getxindex(state); 1240*3492Sab196087 1241*3492Sab196087 /* LINTED */ 1242*3492Sab196087 symname = string(state->seccache, symndx, 1243*3492Sab196087 &state->cache[state->seccache->c_shdr->sh_link], state->file, 1244*3492Sab196087 sym->st_name); 1245*3492Sab196087 1246*3492Sab196087 tshdr = 0; 1247*3492Sab196087 sec = NULL; 1248*3492Sab196087 1249*3492Sab196087 if ((state->ehdr->e_type == ET_CORE)) 1250*3492Sab196087 sec = (char *)MSG_INTL(MSG_STR_UNKNOWN); 1251*3492Sab196087 else if ((sym->st_shndx < SHN_LORESERVE) && 1252*3492Sab196087 (sym->st_shndx < state->shnum)) { 1253*3492Sab196087 shndx = sym->st_shndx; 1254*3492Sab196087 tshdr = state->cache[shndx].c_shdr; 1255*3492Sab196087 sec = state->cache[shndx].c_name; 1256*3492Sab196087 } else if (sym->st_shndx == SHN_XINDEX) { 1257*3492Sab196087 if (state->shxndx.data) { 1258*3492Sab196087 Word _shxndx; 1259*3492Sab196087 1260*3492Sab196087 if (symndx > state->shxndx.n) { 1261*3492Sab196087 (void) fprintf(stderr, 1262*3492Sab196087 MSG_INTL(MSG_ERR_BADSYMXINDEX1), 1263*3492Sab196087 state->file, state->secname, EC_WORD(symndx)); 1264*3492Sab196087 } else if ((_shxndx = 1265*3492Sab196087 state->shxndx.data[symndx]) > state->shnum) { 1266*3492Sab196087 (void) fprintf(stderr, 1267*3492Sab196087 MSG_INTL(MSG_ERR_BADSYMXINDEX2), 1268*3492Sab196087 state->file, state->secname, EC_WORD(symndx), 1269*3492Sab196087 EC_WORD(_shxndx)); 1270*3492Sab196087 } else { 1271*3492Sab196087 shndx = _shxndx; 1272*3492Sab196087 tshdr = state->cache[shndx].c_shdr; 1273*3492Sab196087 sec = state->cache[shndx].c_name; 1274*3492Sab196087 } 1275*3492Sab196087 } else { 1276*3492Sab196087 (void) fprintf(stderr, 1277*3492Sab196087 MSG_INTL(MSG_ERR_BADSYMXINDEX3), 1278*3492Sab196087 state->file, state->secname, EC_WORD(symndx)); 1279*3492Sab196087 } 1280*3492Sab196087 } else if ((sym->st_shndx < SHN_LORESERVE) && 1281*3492Sab196087 (sym->st_shndx >= state->shnum)) { 1282*3492Sab196087 (void) fprintf(stderr, 1283*3492Sab196087 MSG_INTL(MSG_ERR_BADSYM5), state->file, 1284*3492Sab196087 state->secname, demangle(symname, state->flags), 1285*3492Sab196087 sym->st_shndx); 1286*3492Sab196087 } 12870Sstevel@tonic-gate 1288*3492Sab196087 /* 1289*3492Sab196087 * If versioning is available display the 1290*3492Sab196087 * version index. 1291*3492Sab196087 */ 1292*3492Sab196087 if (state->versym) 1293*3492Sab196087 verndx = (int)state->versym[symndx]; 1294*3492Sab196087 else 1295*3492Sab196087 verndx = 0; 1296*3492Sab196087 1297*3492Sab196087 /* 1298*3492Sab196087 * Error checking for TLS. 1299*3492Sab196087 */ 1300*3492Sab196087 type = ELF_ST_TYPE(sym->st_info); 1301*3492Sab196087 if (type == STT_TLS) { 1302*3492Sab196087 if (tshdr && 1303*3492Sab196087 (sym->st_shndx != SHN_UNDEF) && 1304*3492Sab196087 ((tshdr->sh_flags & SHF_TLS) == 0)) { 1305*3492Sab196087 (void) fprintf(stderr, 1306*3492Sab196087 MSG_INTL(MSG_ERR_BADSYM3), state->file, 1307*3492Sab196087 state->secname, demangle(symname, state->flags)); 1308*3492Sab196087 } 1309*3492Sab196087 } else if ((type != STT_SECTION) && sym->st_size && 1310*3492Sab196087 tshdr && (tshdr->sh_flags & SHF_TLS)) { 1311*3492Sab196087 (void) fprintf(stderr, 1312*3492Sab196087 MSG_INTL(MSG_ERR_BADSYM4), state->file, 1313*3492Sab196087 state->secname, demangle(symname, state->flags)); 1314*3492Sab196087 } 1315*3492Sab196087 1316*3492Sab196087 /* 1317*3492Sab196087 * If a symbol with non-zero size has a type that 1318*3492Sab196087 * specifies an address, then make sure the location 1319*3492Sab196087 * it references is actually contained within the 1320*3492Sab196087 * section. UNDEF symbols don't count in this case, 1321*3492Sab196087 * so we ignore them. 1322*3492Sab196087 * 1323*3492Sab196087 * The meaning of the st_value field in a symbol 1324*3492Sab196087 * depends on the type of object. For a relocatable 1325*3492Sab196087 * object, it is the offset within the section. 1326*3492Sab196087 * For sharable objects, it is the offset relative to 1327*3492Sab196087 * the base of the object, and for other types, it is 1328*3492Sab196087 * the virtual address. To get an offset within the 1329*3492Sab196087 * section for non-ET_REL files, we subtract the 1330*3492Sab196087 * base address of the section. 1331*3492Sab196087 */ 1332*3492Sab196087 if (addr_symtype[type] && (sym->st_size > 0) && 1333*3492Sab196087 (sym->st_shndx != SHN_UNDEF) && ((sym->st_shndx < SHN_LORESERVE) || 1334*3492Sab196087 (sym->st_shndx == SHN_XINDEX)) && (tshdr != NULL)) { 1335*3492Sab196087 Word v = sym->st_value; 1336*3492Sab196087 if (state->ehdr->e_type != ET_REL) 1337*3492Sab196087 v -= tshdr->sh_addr; 1338*3492Sab196087 if (((v + sym->st_size) > tshdr->sh_size)) { 1339*3492Sab196087 (void) fprintf(stderr, 1340*3492Sab196087 MSG_INTL(MSG_ERR_BADSYM6), state->file, 1341*3492Sab196087 state->secname, demangle(symname, state->flags), 1342*3492Sab196087 EC_WORD(shndx), EC_XWORD(tshdr->sh_size), 1343*3492Sab196087 EC_XWORD(sym->st_value), EC_XWORD(sym->st_size)); 1344*3492Sab196087 } 1345*3492Sab196087 } 1346*3492Sab196087 1347*3492Sab196087 (void) snprintf(index, MAXNDXSIZE, 1348*3492Sab196087 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(disp_symndx)); 1349*3492Sab196087 Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index, 1350*3492Sab196087 state->ehdr->e_machine, sym, verndx, sec, symname); 1351*3492Sab196087 } 1352*3492Sab196087 1353*3492Sab196087 /* 1354*3492Sab196087 * Search for and process any symbol tables. 1355*3492Sab196087 */ 1356*3492Sab196087 void 1357*3492Sab196087 symbols(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, 1358*3492Sab196087 Cache *versymcache, const char *file, uint_t flags) 1359*3492Sab196087 { 1360*3492Sab196087 SYMTBL_STATE state; 1361*3492Sab196087 Cache *_cache; 1362*3492Sab196087 Word secndx; 1363*3492Sab196087 1364*3492Sab196087 for (secndx = 1; secndx < shnum; secndx++) { 1365*3492Sab196087 Word symcnt; 1366*3492Sab196087 Shdr *shdr; 1367*3492Sab196087 1368*3492Sab196087 _cache = &cache[secndx]; 1369*3492Sab196087 shdr = _cache->c_shdr; 13700Sstevel@tonic-gate 13710Sstevel@tonic-gate if ((shdr->sh_type != SHT_SYMTAB) && 13722766Sab196087 (shdr->sh_type != SHT_DYNSYM) && 13732766Sab196087 (shdr->sh_type != SHT_SUNW_LDYNSYM)) 13740Sstevel@tonic-gate continue; 1375*3492Sab196087 if (name && strcmp(name, _cache->c_name)) 13763466Srie continue; 13773466Srie 1378*3492Sab196087 if (!init_symtbl_state(&state, cache, shnum, secndx, ehdr, 1379*3492Sab196087 versymcache, file, flags)) 13800Sstevel@tonic-gate continue; 13810Sstevel@tonic-gate /* 13820Sstevel@tonic-gate * Loop through the symbol tables entries. 13830Sstevel@tonic-gate */ 13841618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1385*3492Sab196087 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), state.secname); 13861618Srie Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 13870Sstevel@tonic-gate 1388*3492Sab196087 for (symcnt = 0; symcnt < state.symn; symcnt++) 1389*3492Sab196087 output_symbol(&state, symcnt, symcnt, 1390*3492Sab196087 state.sym + symcnt); 1391*3492Sab196087 } 1392*3492Sab196087 } 13930Sstevel@tonic-gate 1394*3492Sab196087 /* 1395*3492Sab196087 * Search for and process any SHT_SUNW_symsort or SHT_SUNW_tlssort sections. 1396*3492Sab196087 * These sections are always associated with the .SUNW_ldynsym./.dynsym pair. 1397*3492Sab196087 */ 1398*3492Sab196087 static void 1399*3492Sab196087 sunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, 1400*3492Sab196087 Cache *versymcache, const char *file, uint_t flags) 1401*3492Sab196087 { 1402*3492Sab196087 SYMTBL_STATE ldynsym_state, dynsym_state; 1403*3492Sab196087 Cache *sortcache, *symcache; 1404*3492Sab196087 Shdr *sortshdr, *symshdr; 1405*3492Sab196087 Word sortsecndx, symsecndx; 1406*3492Sab196087 Word ldynsym_cnt; 1407*3492Sab196087 Word *ndx; 1408*3492Sab196087 Word ndxn; 1409*3492Sab196087 int output_cnt = 0; 14100Sstevel@tonic-gate 1411*3492Sab196087 for (sortsecndx = 1; sortsecndx < shnum; sortsecndx++) { 14120Sstevel@tonic-gate 1413*3492Sab196087 sortcache = &cache[sortsecndx]; 1414*3492Sab196087 sortshdr = sortcache->c_shdr; 14150Sstevel@tonic-gate 1416*3492Sab196087 if ((sortshdr->sh_type != SHT_SUNW_symsort) && 1417*3492Sab196087 (sortshdr->sh_type != SHT_SUNW_tlssort)) 1418*3492Sab196087 continue; 1419*3492Sab196087 if (name && strcmp(name, sortcache->c_name)) 1420*3492Sab196087 continue; 14210Sstevel@tonic-gate 1422*3492Sab196087 /* 1423*3492Sab196087 * If the section references a SUNW_ldynsym, then we 1424*3492Sab196087 * expect to see the associated .dynsym immediately 1425*3492Sab196087 * following. If it references a .dynsym, there is no 1426*3492Sab196087 * SUNW_ldynsym. If it is any other type, then we don't 1427*3492Sab196087 * know what to do with it. 1428*3492Sab196087 */ 1429*3492Sab196087 if ((sortshdr->sh_link == 0) || (sortshdr->sh_link >= shnum)) { 1430*3492Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1431*3492Sab196087 file, sortcache->c_name, 1432*3492Sab196087 EC_WORD(sortshdr->sh_link)); 1433*3492Sab196087 continue; 1434*3492Sab196087 } 1435*3492Sab196087 symcache = &cache[sortshdr->sh_link]; 1436*3492Sab196087 symshdr = symcache->c_shdr; 1437*3492Sab196087 symsecndx = sortshdr->sh_link; 1438*3492Sab196087 ldynsym_cnt = 0; 1439*3492Sab196087 switch (symshdr->sh_type) { 1440*3492Sab196087 case SHT_SUNW_LDYNSYM: 1441*3492Sab196087 if (!init_symtbl_state(&ldynsym_state, cache, shnum, 1442*3492Sab196087 symsecndx, ehdr, versymcache, file, flags)) 1443*3492Sab196087 continue; 1444*3492Sab196087 ldynsym_cnt = ldynsym_state.symn; 14450Sstevel@tonic-gate /* 1446*3492Sab196087 * We know that the dynsym follows immediately 1447*3492Sab196087 * after the SUNW_ldynsym, and so, should be at 1448*3492Sab196087 * (sortshdr->sh_link + 1). However, elfdump is a 1449*3492Sab196087 * diagnostic tool, so we do the full paranoid 1450*3492Sab196087 * search instead. 14510Sstevel@tonic-gate */ 1452*3492Sab196087 for (symsecndx = 1; symsecndx < shnum; symsecndx++) { 1453*3492Sab196087 symcache = &cache[symsecndx]; 1454*3492Sab196087 symshdr = symcache->c_shdr; 1455*3492Sab196087 if (symshdr->sh_type == SHT_DYNSYM) 1456*3492Sab196087 break; 1457*3492Sab196087 } 1458*3492Sab196087 if (symsecndx >= shnum) { /* Dynsym not found! */ 14590Sstevel@tonic-gate (void) fprintf(stderr, 1460*3492Sab196087 MSG_INTL(MSG_ERR_NODYNSYM), 1461*3492Sab196087 file, sortcache->c_name); 1462*3492Sab196087 continue; 14630Sstevel@tonic-gate } 1464*3492Sab196087 /* Fallthrough to process associated dynsym */ 1465*3492Sab196087 /*FALLTHROUGH*/ 1466*3492Sab196087 case SHT_DYNSYM: 1467*3492Sab196087 if (!init_symtbl_state(&dynsym_state, cache, shnum, 1468*3492Sab196087 symsecndx, ehdr, versymcache, file, flags)) 1469*3492Sab196087 continue; 1470*3492Sab196087 break; 1471*3492Sab196087 default: 1472*3492Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADNDXSEC), 1473*3492Sab196087 file, sortcache->c_name, conv_sec_type( 1474*3492Sab196087 ehdr->e_machine, symshdr->sh_type, 0)); 1475*3492Sab196087 continue; 1476*3492Sab196087 } 14770Sstevel@tonic-gate 1478*3492Sab196087 /* 1479*3492Sab196087 * Output header 1480*3492Sab196087 */ 1481*3492Sab196087 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1482*3492Sab196087 if (ldynsym_cnt > 0) { 1483*3492Sab196087 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT2), 1484*3492Sab196087 sortcache->c_name, ldynsym_state.secname, 1485*3492Sab196087 dynsym_state.secname); 14860Sstevel@tonic-gate /* 1487*3492Sab196087 * The data for .SUNW_ldynsym and dynsym sections 1488*3492Sab196087 * is supposed to be adjacent with SUNW_ldynsym coming 1489*3492Sab196087 * first. Check, and issue a warning if it isn't so. 14900Sstevel@tonic-gate */ 1491*3492Sab196087 if ((ldynsym_state.sym + ldynsym_state.symn) 1492*3492Sab196087 != dynsym_state.sym) 1493*3492Sab196087 (void) fprintf(stderr, 1494*3492Sab196087 MSG_INTL(MSG_ERR_LDYNNOTADJ), file, 1495*3492Sab196087 ldynsym_state.secname, 1496*3492Sab196087 dynsym_state.secname); 1497*3492Sab196087 } else { 1498*3492Sab196087 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT1), 1499*3492Sab196087 sortcache->c_name, dynsym_state.secname); 1500*3492Sab196087 } 1501*3492Sab196087 Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 1502*3492Sab196087 1503*3492Sab196087 /* If not first one, insert a line of whitespace */ 1504*3492Sab196087 if (output_cnt++ > 0) 1505*3492Sab196087 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 15063118Sab196087 1507*3492Sab196087 /* 1508*3492Sab196087 * SUNW_dynsymsort and SUNW_dyntlssort are arrays of 1509*3492Sab196087 * symbol indices. Iterate over the array entries, 1510*3492Sab196087 * dispaying the referenced symbols. 1511*3492Sab196087 */ 1512*3492Sab196087 ndxn = sortshdr->sh_size / sortshdr->sh_entsize; 1513*3492Sab196087 ndx = (Word *)sortcache->c_data->d_buf; 1514*3492Sab196087 for (; ndxn-- > 0; ndx++) { 1515*3492Sab196087 if (*ndx >= ldynsym_cnt) { 1516*3492Sab196087 Word sec_ndx = *ndx - ldynsym_cnt; 1517*3492Sab196087 1518*3492Sab196087 output_symbol(&dynsym_state, sec_ndx, 1519*3492Sab196087 *ndx, dynsym_state.sym + sec_ndx); 1520*3492Sab196087 } else { 1521*3492Sab196087 output_symbol(&ldynsym_state, *ndx, 1522*3492Sab196087 *ndx, ldynsym_state.sym + *ndx); 15230Sstevel@tonic-gate } 15240Sstevel@tonic-gate } 15250Sstevel@tonic-gate } 15260Sstevel@tonic-gate } 15270Sstevel@tonic-gate 15280Sstevel@tonic-gate /* 15290Sstevel@tonic-gate * Search for and process any relocation sections. 15300Sstevel@tonic-gate */ 15310Sstevel@tonic-gate static void 15321618Srie reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, const char *file, 15331618Srie uint_t flags) 15340Sstevel@tonic-gate { 15351618Srie Word cnt; 15360Sstevel@tonic-gate 15370Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 15381618Srie Word type, symnum; 15391618Srie Xword relndx, relnum, relsize; 15401618Srie void *rels; 15411618Srie Sym *syms; 15421618Srie Cache *symsec, *strsec; 15430Sstevel@tonic-gate Cache *_cache = &cache[cnt]; 15441618Srie Shdr *shdr = _cache->c_shdr; 15451618Srie char *relname = _cache->c_name; 15460Sstevel@tonic-gate 15470Sstevel@tonic-gate if (((type = shdr->sh_type) != SHT_RELA) && 15480Sstevel@tonic-gate (type != SHT_REL)) 15490Sstevel@tonic-gate continue; 15501618Srie if (name && strcmp(name, relname)) 15510Sstevel@tonic-gate continue; 15520Sstevel@tonic-gate 15530Sstevel@tonic-gate /* 15541618Srie * Decide entry size. 15550Sstevel@tonic-gate */ 15561618Srie if (((relsize = shdr->sh_entsize) == 0) || 15571618Srie (relsize > shdr->sh_size)) { 15580Sstevel@tonic-gate if (type == SHT_RELA) 15591618Srie relsize = sizeof (Rela); 15600Sstevel@tonic-gate else 15611618Srie relsize = sizeof (Rel); 15620Sstevel@tonic-gate } 15630Sstevel@tonic-gate 15640Sstevel@tonic-gate /* 15650Sstevel@tonic-gate * Determine the number of relocations available. 15660Sstevel@tonic-gate */ 15670Sstevel@tonic-gate if (shdr->sh_size == 0) { 15680Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 15691618Srie file, relname); 15700Sstevel@tonic-gate continue; 15710Sstevel@tonic-gate } 15723466Srie if (_cache->c_data == NULL) 15733466Srie continue; 15743466Srie 15751618Srie rels = _cache->c_data->d_buf; 15761618Srie relnum = shdr->sh_size / relsize; 15770Sstevel@tonic-gate 15780Sstevel@tonic-gate /* 15791618Srie * Get the data buffer for the associated symbol table and 15801618Srie * string table. 15810Sstevel@tonic-gate */ 15821618Srie if (stringtbl(cache, 1, cnt, shnum, file, 15831618Srie &symnum, &symsec, &strsec) == 0) 15840Sstevel@tonic-gate continue; 15851618Srie 15861618Srie syms = symsec->c_data->d_buf; 15870Sstevel@tonic-gate 15880Sstevel@tonic-gate /* 15890Sstevel@tonic-gate * Loop through the relocation entries. 15900Sstevel@tonic-gate */ 15911618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 15921618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name); 15931618Srie Elf_reloc_title(0, ELF_DBG_ELFDUMP, type); 15940Sstevel@tonic-gate 15951618Srie for (relndx = 0; relndx < relnum; relndx++, 15961618Srie rels = (void *)((char *)rels + relsize)) { 15970Sstevel@tonic-gate char section[BUFSIZ]; 15981618Srie const char *symname; 15991618Srie Word symndx, reltype; 16001618Srie Rela *rela; 16011618Srie Rel *rel; 16020Sstevel@tonic-gate 16030Sstevel@tonic-gate /* 16041618Srie * Unravel the relocation and determine the symbol with 16051618Srie * which this relocation is associated. 16060Sstevel@tonic-gate */ 16070Sstevel@tonic-gate if (type == SHT_RELA) { 16081618Srie rela = (Rela *)rels; 16091618Srie symndx = ELF_R_SYM(rela->r_info); 16101618Srie reltype = ELF_R_TYPE(rela->r_info); 16110Sstevel@tonic-gate } else { 16121618Srie rel = (Rel *)rels; 16131618Srie symndx = ELF_R_SYM(rel->r_info); 16141618Srie reltype = ELF_R_TYPE(rel->r_info); 16150Sstevel@tonic-gate } 16161618Srie 16171618Srie symname = relsymname(cache, _cache, strsec, symndx, 16181618Srie symnum, relndx, syms, section, BUFSIZ, file, 16191618Srie flags); 16201618Srie 16211618Srie /* 16221618Srie * A zero symbol index is only valid for a few 16231618Srie * relocations. 16241618Srie */ 16251618Srie if (symndx == 0) { 16261618Srie Half mach = ehdr->e_machine; 16271618Srie int badrel = 0; 16280Sstevel@tonic-gate 16291618Srie if ((mach == EM_SPARC) || 16301618Srie (mach == EM_SPARC32PLUS) || 16311618Srie (mach == EM_SPARCV9)) { 16321618Srie if ((reltype != R_SPARC_NONE) && 16331618Srie (reltype != R_SPARC_REGISTER) && 16341618Srie (reltype != R_SPARC_RELATIVE)) 16351618Srie badrel++; 16361618Srie } else if (mach == EM_386) { 16371618Srie if ((reltype != R_386_NONE) && 16381618Srie (reltype != R_386_RELATIVE)) 16391618Srie badrel++; 16401618Srie } else if (mach == EM_AMD64) { 16411618Srie if ((reltype != R_AMD64_NONE) && 16421618Srie (reltype != R_AMD64_RELATIVE)) 16431618Srie badrel++; 16441618Srie } 16451618Srie 16461618Srie if (badrel) { 16471618Srie (void) fprintf(stderr, 16481618Srie MSG_INTL(MSG_ERR_BADREL1), file, 16491976Sab196087 conv_reloc_type(mach, reltype, 0)); 16500Sstevel@tonic-gate } 16510Sstevel@tonic-gate } 16520Sstevel@tonic-gate 16531618Srie Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP, 16541618Srie MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type, 16551618Srie rels, relname, symname, 0); 16560Sstevel@tonic-gate } 16570Sstevel@tonic-gate } 16580Sstevel@tonic-gate } 16590Sstevel@tonic-gate 16600Sstevel@tonic-gate /* 16610Sstevel@tonic-gate * Search for and process a .dynamic section. 16620Sstevel@tonic-gate */ 16630Sstevel@tonic-gate static void 16641618Srie dynamic(Cache *cache, Word shnum, Ehdr *ehdr, const char *file) 16650Sstevel@tonic-gate { 16661618Srie Word cnt; 16670Sstevel@tonic-gate 16680Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 16691618Srie Dyn *dyn; 16701618Srie ulong_t numdyn; 16711618Srie int ndx; 16721618Srie Cache *_cache = &cache[cnt], *strsec; 16731618Srie Shdr *shdr = _cache->c_shdr; 16740Sstevel@tonic-gate 16750Sstevel@tonic-gate if (shdr->sh_type != SHT_DYNAMIC) 16760Sstevel@tonic-gate continue; 16770Sstevel@tonic-gate 16780Sstevel@tonic-gate /* 16791618Srie * Verify the associated string table section. 16800Sstevel@tonic-gate */ 16811618Srie if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0) 16820Sstevel@tonic-gate continue; 16831618Srie 16843466Srie if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 16853466Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 16863466Srie file, _cache->c_name); 16873466Srie continue; 16883466Srie } 16893466Srie if (_cache->c_data == NULL) 16903466Srie continue; 16913466Srie 16920Sstevel@tonic-gate numdyn = shdr->sh_size / shdr->sh_entsize; 16931618Srie dyn = (Dyn *)_cache->c_data->d_buf; 16940Sstevel@tonic-gate 16951618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 16961618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name); 16970Sstevel@tonic-gate 16981618Srie Elf_dyn_title(0); 16990Sstevel@tonic-gate 17001618Srie for (ndx = 0; ndx < numdyn; dyn++, ndx++) { 17011618Srie const char *name; 17020Sstevel@tonic-gate 17030Sstevel@tonic-gate /* 17040Sstevel@tonic-gate * Print the information numerically, and if possible 17050Sstevel@tonic-gate * as a string. 17060Sstevel@tonic-gate */ 17071618Srie if ((dyn->d_tag == DT_NEEDED) || 17081618Srie (dyn->d_tag == DT_SONAME) || 17091618Srie (dyn->d_tag == DT_FILTER) || 17101618Srie (dyn->d_tag == DT_AUXILIARY) || 17111618Srie (dyn->d_tag == DT_CONFIG) || 17121618Srie (dyn->d_tag == DT_RPATH) || 17131618Srie (dyn->d_tag == DT_RUNPATH) || 17141618Srie (dyn->d_tag == DT_USED) || 17151618Srie (dyn->d_tag == DT_DEPAUDIT) || 17161618Srie (dyn->d_tag == DT_AUDIT) || 17171618Srie (dyn->d_tag == DT_SUNW_AUXILIARY) || 17181618Srie (dyn->d_tag == DT_SUNW_FILTER)) 17191618Srie name = string(_cache, ndx, strsec, 17201618Srie file, dyn->d_un.d_ptr); 17211618Srie else if (dyn->d_tag == DT_FLAGS) 17222352Sab196087 name = conv_dyn_flag(dyn->d_un.d_val, 0); 17231618Srie else if (dyn->d_tag == DT_FLAGS_1) 17241618Srie name = conv_dyn_flag1(dyn->d_un.d_val); 17251618Srie else if (dyn->d_tag == DT_POSFLAG_1) 17262352Sab196087 name = conv_dyn_posflag1(dyn->d_un.d_val, 0); 17271618Srie else if (dyn->d_tag == DT_FEATURE_1) 17282352Sab196087 name = conv_dyn_feature1(dyn->d_un.d_val, 0); 17291618Srie else if (dyn->d_tag == DT_DEPRECATED_SPARC_REGISTER) 17301618Srie name = MSG_INTL(MSG_STR_DEPRECATED); 17310Sstevel@tonic-gate else 17321618Srie name = MSG_ORIG(MSG_STR_EMPTY); 17330Sstevel@tonic-gate 17341618Srie Elf_dyn_entry(0, dyn, ndx, name, ehdr->e_machine); 17350Sstevel@tonic-gate } 17360Sstevel@tonic-gate } 17370Sstevel@tonic-gate } 17380Sstevel@tonic-gate 17390Sstevel@tonic-gate /* 17400Sstevel@tonic-gate * Search for and process a MOVE section. 17410Sstevel@tonic-gate */ 17420Sstevel@tonic-gate static void 17431618Srie move(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags) 17440Sstevel@tonic-gate { 17451618Srie Word cnt; 17461618Srie const char *fmt = 0; 17470Sstevel@tonic-gate 17480Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 17491618Srie Word movenum, symnum, ndx; 17501618Srie Sym *syms; 17511618Srie Cache *_cache = &cache[cnt]; 17521618Srie Shdr *shdr = _cache->c_shdr; 17531618Srie Cache *symsec, *strsec; 17541618Srie Move *move; 17550Sstevel@tonic-gate 17560Sstevel@tonic-gate if (shdr->sh_type != SHT_SUNW_move) 17570Sstevel@tonic-gate continue; 17580Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 17590Sstevel@tonic-gate continue; 17600Sstevel@tonic-gate 17610Sstevel@tonic-gate /* 17620Sstevel@tonic-gate * Determine the move data and number. 17630Sstevel@tonic-gate */ 17640Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 17650Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 17660Sstevel@tonic-gate file, _cache->c_name); 17670Sstevel@tonic-gate continue; 17680Sstevel@tonic-gate } 17693466Srie if (_cache->c_data == NULL) 17703466Srie continue; 17713466Srie 17721618Srie move = (Move *)_cache->c_data->d_buf; 17731618Srie movenum = shdr->sh_size / shdr->sh_entsize; 17740Sstevel@tonic-gate 17750Sstevel@tonic-gate /* 17761618Srie * Get the data buffer for the associated symbol table and 17771618Srie * string table. 17780Sstevel@tonic-gate */ 17791618Srie if (stringtbl(cache, 1, cnt, shnum, file, 17801618Srie &symnum, &symsec, &strsec) == 0) 17811618Srie return; 17821618Srie 17831618Srie syms = (Sym *)symsec->c_data->d_buf; 17840Sstevel@tonic-gate 17851618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 17861618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name); 17871618Srie dbg_print(0, MSG_INTL(MSG_MOVE_TITLE)); 17880Sstevel@tonic-gate 17891618Srie if (fmt == 0) 17901618Srie fmt = MSG_INTL(MSG_MOVE_ENTRY); 17910Sstevel@tonic-gate 17921618Srie for (ndx = 0; ndx < movenum; move++, ndx++) { 17931618Srie const char *symname; 17941618Srie char index[MAXNDXSIZE], section[BUFSIZ]; 17951618Srie Word symndx, shndx; 17961618Srie Sym *sym; 17970Sstevel@tonic-gate 17980Sstevel@tonic-gate /* 17990Sstevel@tonic-gate * Check for null entries 18000Sstevel@tonic-gate */ 18011618Srie if ((move->m_info == 0) && (move->m_value == 0) && 18021618Srie (move->m_poffset == 0) && (move->m_repeat == 0) && 18031618Srie (move->m_stride == 0)) { 18041618Srie dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY), 18051618Srie EC_XWORD(move->m_poffset), 0, 0, 0, 18061618Srie EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY)); 18070Sstevel@tonic-gate continue; 18080Sstevel@tonic-gate } 18091618Srie if (((symndx = ELF_M_SYM(move->m_info)) == 0) || 18101618Srie (symndx >= symnum)) { 18110Sstevel@tonic-gate (void) fprintf(stderr, 18120Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADMINFO), file, 18131618Srie _cache->c_name, EC_XWORD(move->m_info)); 18141618Srie 18151618Srie (void) snprintf(index, MAXNDXSIZE, 18161618Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 18171618Srie dbg_print(0, fmt, index, 18181618Srie EC_XWORD(move->m_poffset), 18191618Srie ELF_M_SIZE(move->m_info), move->m_repeat, 18201618Srie move->m_stride, move->m_value, 18210Sstevel@tonic-gate MSG_INTL(MSG_STR_UNKNOWN)); 18220Sstevel@tonic-gate continue; 18230Sstevel@tonic-gate } 18240Sstevel@tonic-gate 18251618Srie symname = relsymname(cache, _cache, strsec, 18261618Srie symndx, symnum, ndx, syms, section, BUFSIZ, file, 18271618Srie flags); 18281618Srie sym = (Sym *)(syms + symndx); 18290Sstevel@tonic-gate 18300Sstevel@tonic-gate /* 18310Sstevel@tonic-gate * Additional sanity check. 18320Sstevel@tonic-gate */ 18331618Srie shndx = sym->st_shndx; 18340Sstevel@tonic-gate if (!((shndx == SHN_COMMON) || 18350Sstevel@tonic-gate (((shndx >= 1) && (shndx <= shnum)) && 18361618Srie (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) { 18370Sstevel@tonic-gate (void) fprintf(stderr, 18381618Srie MSG_INTL(MSG_ERR_BADSYM2), file, 18391618Srie _cache->c_name, demangle(symname, flags)); 18400Sstevel@tonic-gate } 18410Sstevel@tonic-gate 18421618Srie (void) snprintf(index, MAXNDXSIZE, 18431618Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 18441618Srie dbg_print(0, fmt, index, EC_XWORD(move->m_poffset), 18451618Srie ELF_M_SIZE(move->m_info), move->m_repeat, 18461618Srie move->m_stride, move->m_value, 18471618Srie demangle(symname, flags)); 18480Sstevel@tonic-gate } 18490Sstevel@tonic-gate } 18500Sstevel@tonic-gate } 18510Sstevel@tonic-gate 18520Sstevel@tonic-gate /* 18530Sstevel@tonic-gate * Traverse a note section analyzing each note information block. 18540Sstevel@tonic-gate * The data buffers size is used to validate references before they are made, 18550Sstevel@tonic-gate * and is decremented as each element is processed. 18560Sstevel@tonic-gate */ 18570Sstevel@tonic-gate void 18581618Srie note_entry(Cache *cache, Word *data, size_t size, const char *file) 18590Sstevel@tonic-gate { 18601618Srie size_t bsize = size; 18611618Srie 18620Sstevel@tonic-gate /* 18630Sstevel@tonic-gate * Print out a single `note' information block. 18640Sstevel@tonic-gate */ 18650Sstevel@tonic-gate while (size > 0) { 18661618Srie size_t namesz, descsz, type, pad, noteoff; 18670Sstevel@tonic-gate 18680Sstevel@tonic-gate noteoff = bsize - size; 18690Sstevel@tonic-gate /* 18700Sstevel@tonic-gate * Make sure we can at least reference the 3 initial entries 18710Sstevel@tonic-gate * (4-byte words) of the note information block. 18720Sstevel@tonic-gate */ 18731618Srie if (size >= (sizeof (Word) * 3)) 18741618Srie size -= (sizeof (Word) * 3); 18750Sstevel@tonic-gate else { 18761618Srie (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ), 18771618Srie file, cache->c_name, EC_WORD(noteoff)); 18780Sstevel@tonic-gate return; 18790Sstevel@tonic-gate } 18800Sstevel@tonic-gate 18810Sstevel@tonic-gate /* 18820Sstevel@tonic-gate * Make sure any specified name string can be referenced. 18830Sstevel@tonic-gate */ 18840Sstevel@tonic-gate if ((namesz = *data++) != 0) { 18850Sstevel@tonic-gate if (size >= namesz) 18860Sstevel@tonic-gate size -= namesz; 18870Sstevel@tonic-gate else { 18880Sstevel@tonic-gate (void) fprintf(stderr, 18891618Srie MSG_INTL(MSG_NOTE_BADNMSZ), file, 18901618Srie cache->c_name, EC_WORD(noteoff), 18911618Srie EC_WORD(namesz)); 18920Sstevel@tonic-gate return; 18930Sstevel@tonic-gate } 18940Sstevel@tonic-gate } 18951618Srie 18960Sstevel@tonic-gate /* 18970Sstevel@tonic-gate * Make sure any specified descriptor can be referenced. 18980Sstevel@tonic-gate */ 18990Sstevel@tonic-gate if ((descsz = *data++) != 0) { 19000Sstevel@tonic-gate /* 19010Sstevel@tonic-gate * If namesz isn't a 4-byte multiple, account for any 19020Sstevel@tonic-gate * padding that must exist before the descriptor. 19030Sstevel@tonic-gate */ 19041618Srie if ((pad = (namesz & (sizeof (Word) - 1))) != 0) { 19051618Srie pad = sizeof (Word) - pad; 19060Sstevel@tonic-gate size -= pad; 19070Sstevel@tonic-gate } 19080Sstevel@tonic-gate if (size >= descsz) 19090Sstevel@tonic-gate size -= descsz; 19100Sstevel@tonic-gate else { 19110Sstevel@tonic-gate (void) fprintf(stderr, 19121618Srie MSG_INTL(MSG_NOTE_BADDESZ), file, 19131618Srie cache->c_name, EC_WORD(noteoff), 19141618Srie EC_WORD(namesz)); 19150Sstevel@tonic-gate return; 19160Sstevel@tonic-gate } 19170Sstevel@tonic-gate } 19180Sstevel@tonic-gate 19190Sstevel@tonic-gate type = *data++; 19200Sstevel@tonic-gate 19211618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 19221618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE), EC_WORD(type)); 19230Sstevel@tonic-gate 19241618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_NAMESZ), EC_WORD(namesz)); 19250Sstevel@tonic-gate if (namesz) { 19260Sstevel@tonic-gate char *name = (char *)data; 19270Sstevel@tonic-gate 19280Sstevel@tonic-gate /* 19290Sstevel@tonic-gate * Since the name string may have 'null' bytes 19300Sstevel@tonic-gate * in it (ia32 .string) - we just write the 19310Sstevel@tonic-gate * whole stream in a single fwrite. 19320Sstevel@tonic-gate */ 19330Sstevel@tonic-gate (void) fwrite(name, namesz, 1, stdout); 19340Sstevel@tonic-gate name = name + ((namesz + (sizeof (Word) - 1)) & 19350Sstevel@tonic-gate ~(sizeof (Word) - 1)); 19360Sstevel@tonic-gate /* LINTED */ 19370Sstevel@tonic-gate data = (Word *)name; 19381618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 19390Sstevel@tonic-gate } 19400Sstevel@tonic-gate 19410Sstevel@tonic-gate /* 19420Sstevel@tonic-gate * If multiple information blocks exist within a .note section 19430Sstevel@tonic-gate * account for any padding that must exist before the next 19440Sstevel@tonic-gate * information block. 19450Sstevel@tonic-gate */ 19461618Srie if ((pad = (descsz & (sizeof (Word) - 1))) != 0) { 19471618Srie pad = sizeof (Word) - pad; 19480Sstevel@tonic-gate if (size > pad) 19490Sstevel@tonic-gate size -= pad; 19500Sstevel@tonic-gate } 19510Sstevel@tonic-gate 19521618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_DESCSZ), EC_WORD(descsz)); 19530Sstevel@tonic-gate if (descsz) { 19540Sstevel@tonic-gate int ndx, byte, word; 19551618Srie char string[58], *str = string; 19560Sstevel@tonic-gate uchar_t *desc = (uchar_t *)data; 19570Sstevel@tonic-gate 19580Sstevel@tonic-gate /* 19590Sstevel@tonic-gate * Dump descriptor bytes. 19600Sstevel@tonic-gate */ 19610Sstevel@tonic-gate for (ndx = byte = word = 0; descsz; descsz--, desc++) { 19620Sstevel@tonic-gate int tok = *desc; 19630Sstevel@tonic-gate 19640Sstevel@tonic-gate (void) snprintf(str, 58, MSG_ORIG(MSG_NOTE_TOK), 19650Sstevel@tonic-gate tok); 19660Sstevel@tonic-gate str += 3; 19670Sstevel@tonic-gate 19680Sstevel@tonic-gate if (++byte == 4) { 19690Sstevel@tonic-gate *str++ = ' ', *str++ = ' '; 19700Sstevel@tonic-gate word++; 19710Sstevel@tonic-gate byte = 0; 19720Sstevel@tonic-gate } 19730Sstevel@tonic-gate if (word == 4) { 19740Sstevel@tonic-gate *str = '\0'; 19751618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_DESC), 19760Sstevel@tonic-gate ndx, string); 19770Sstevel@tonic-gate word = 0; 19780Sstevel@tonic-gate ndx += 16; 19790Sstevel@tonic-gate str = string; 19800Sstevel@tonic-gate } 19810Sstevel@tonic-gate } 19820Sstevel@tonic-gate if (byte || word) { 19830Sstevel@tonic-gate *str = '\0'; 19841618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_DESC), 19851618Srie ndx, string); 19860Sstevel@tonic-gate } 19870Sstevel@tonic-gate 19880Sstevel@tonic-gate desc += pad; 19890Sstevel@tonic-gate /* LINTED */ 19900Sstevel@tonic-gate data = (Word *)desc; 19910Sstevel@tonic-gate } 19920Sstevel@tonic-gate } 19930Sstevel@tonic-gate } 19940Sstevel@tonic-gate 19950Sstevel@tonic-gate /* 19960Sstevel@tonic-gate * Search for and process a .note section. 19970Sstevel@tonic-gate */ 19980Sstevel@tonic-gate static void 19991618Srie note(Cache *cache, Word shnum, const char *name, const char *file) 20000Sstevel@tonic-gate { 20011618Srie Word cnt; 20020Sstevel@tonic-gate 20030Sstevel@tonic-gate /* 20040Sstevel@tonic-gate * Otherwise look for any .note sections. 20050Sstevel@tonic-gate */ 20060Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 20071618Srie Cache *_cache = &cache[cnt]; 20081618Srie Shdr *shdr = _cache->c_shdr; 20090Sstevel@tonic-gate 20100Sstevel@tonic-gate if (shdr->sh_type != SHT_NOTE) 20110Sstevel@tonic-gate continue; 20120Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 20130Sstevel@tonic-gate continue; 20140Sstevel@tonic-gate 20150Sstevel@tonic-gate /* 20160Sstevel@tonic-gate * As these sections are often hand rolled, make sure they're 20170Sstevel@tonic-gate * properly aligned before proceeding. 20180Sstevel@tonic-gate */ 20190Sstevel@tonic-gate if (shdr->sh_offset & (sizeof (Word) - 1)) { 20200Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN), 20210Sstevel@tonic-gate file, _cache->c_name); 20220Sstevel@tonic-gate continue; 20230Sstevel@tonic-gate } 20243466Srie if (_cache->c_data == NULL) 20253466Srie continue; 20260Sstevel@tonic-gate 20271618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 20281618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name); 20290Sstevel@tonic-gate note_entry(_cache, (Word *)_cache->c_data->d_buf, 20300Sstevel@tonic-gate /* LINTED */ 20310Sstevel@tonic-gate (Word)_cache->c_data->d_size, file); 20320Sstevel@tonic-gate } 20330Sstevel@tonic-gate } 20340Sstevel@tonic-gate 20351618Srie /* 20361618Srie * Determine an individual hash entry. This may be the initial hash entry, 20371618Srie * or an associated chain entry. 20381618Srie */ 20391618Srie static void 20401618Srie hash_entry(Cache *refsec, Cache *strsec, const char *hsecname, Word hashndx, 20411618Srie Word symndx, Word symn, Sym *syms, const char *file, ulong_t bkts, 20421618Srie uint_t flags, int chain) 20431618Srie { 20441618Srie Sym *sym; 20451618Srie const char *symname, *str; 20461618Srie char _bucket[MAXNDXSIZE], _symndx[MAXNDXSIZE]; 20471618Srie ulong_t nbkt, nhash; 20481618Srie 20491618Srie if (symndx > symn) { 20501618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_HSBADSYMNDX), file, 20511618Srie EC_WORD(symndx), EC_WORD(hashndx)); 20521618Srie symname = MSG_INTL(MSG_STR_UNKNOWN); 20531618Srie } else { 20541618Srie sym = (Sym *)(syms + symndx); 20551618Srie symname = string(refsec, symndx, strsec, file, sym->st_name); 20561618Srie } 20571618Srie 20581618Srie if (chain == 0) { 20591618Srie (void) snprintf(_bucket, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 20601618Srie hashndx); 20611618Srie str = (const char *)_bucket; 20621618Srie } else 20631618Srie str = MSG_ORIG(MSG_STR_EMPTY); 20641618Srie 20651618Srie (void) snprintf(_symndx, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX2), 20661618Srie EC_WORD(symndx)); 20671618Srie dbg_print(0, MSG_ORIG(MSG_FMT_HASH_INFO), str, _symndx, 20681618Srie demangle(symname, flags)); 20691618Srie 20701618Srie /* 20711618Srie * Determine if this string is in the correct bucket. 20721618Srie */ 20731618Srie nhash = elf_hash(symname); 20741618Srie nbkt = nhash % bkts; 20751618Srie 20761618Srie if (nbkt != hashndx) { 20771618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADHASH), file, 20781618Srie hsecname, symname, EC_WORD(hashndx), nbkt); 20791618Srie } 20801618Srie } 20810Sstevel@tonic-gate 20820Sstevel@tonic-gate #define MAXCOUNT 500 20830Sstevel@tonic-gate 20840Sstevel@tonic-gate static void 20851618Srie hash(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags) 20860Sstevel@tonic-gate { 20870Sstevel@tonic-gate static int count[MAXCOUNT]; 20881618Srie Word cnt; 20890Sstevel@tonic-gate ulong_t ndx, bkts; 20900Sstevel@tonic-gate char number[MAXNDXSIZE]; 20910Sstevel@tonic-gate 20920Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 20930Sstevel@tonic-gate uint_t *hash, *chain; 20940Sstevel@tonic-gate Cache *_cache = &cache[cnt]; 20951618Srie Shdr *sshdr, *hshdr = _cache->c_shdr; 20961618Srie char *ssecname, *hsecname = _cache->c_name; 20971618Srie Sym *syms; 20981618Srie Word symn; 20990Sstevel@tonic-gate 21001618Srie if (hshdr->sh_type != SHT_HASH) 21010Sstevel@tonic-gate continue; 21021618Srie if (name && strcmp(name, hsecname)) 21030Sstevel@tonic-gate continue; 21040Sstevel@tonic-gate 21050Sstevel@tonic-gate /* 21060Sstevel@tonic-gate * Determine the hash table data and size. 21070Sstevel@tonic-gate */ 21081618Srie if ((hshdr->sh_entsize == 0) || (hshdr->sh_size == 0)) { 21090Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 21101618Srie file, hsecname); 21110Sstevel@tonic-gate continue; 21120Sstevel@tonic-gate } 21133466Srie if (_cache->c_data == NULL) 21143466Srie continue; 21153466Srie 21160Sstevel@tonic-gate hash = (uint_t *)_cache->c_data->d_buf; 21170Sstevel@tonic-gate bkts = *hash; 21180Sstevel@tonic-gate chain = hash + 2 + bkts; 21190Sstevel@tonic-gate hash += 2; 21200Sstevel@tonic-gate 21210Sstevel@tonic-gate /* 21220Sstevel@tonic-gate * Get the data buffer for the associated symbol table. 21230Sstevel@tonic-gate */ 21241618Srie if ((hshdr->sh_link == 0) || (hshdr->sh_link >= shnum)) { 21250Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 21261618Srie file, hsecname, EC_WORD(hshdr->sh_link)); 21270Sstevel@tonic-gate continue; 21280Sstevel@tonic-gate } 21291618Srie 21301618Srie _cache = &cache[hshdr->sh_link]; 21311618Srie ssecname = _cache->c_name; 21321618Srie 21333466Srie if (_cache->c_data == NULL) 21343466Srie continue; 21353466Srie 21363466Srie if ((syms = (Sym *)_cache->c_data->d_buf) == NULL) { 21370Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 21381618Srie file, ssecname); 21390Sstevel@tonic-gate continue; 21400Sstevel@tonic-gate } 21410Sstevel@tonic-gate 21421618Srie sshdr = _cache->c_shdr; 21431618Srie /* LINTED */ 21441618Srie symn = (Word)(sshdr->sh_size / sshdr->sh_entsize); 21451618Srie 21460Sstevel@tonic-gate /* 21470Sstevel@tonic-gate * Get the associated string table section. 21480Sstevel@tonic-gate */ 21491618Srie if ((sshdr->sh_link == 0) || (sshdr->sh_link >= shnum)) { 21500Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 21511618Srie file, ssecname, EC_WORD(sshdr->sh_link)); 21520Sstevel@tonic-gate continue; 21530Sstevel@tonic-gate } 21540Sstevel@tonic-gate 21551618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 21561618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_HASH), hsecname); 21571618Srie dbg_print(0, MSG_INTL(MSG_ELF_HASH_INFO)); 21580Sstevel@tonic-gate 21590Sstevel@tonic-gate /* 21600Sstevel@tonic-gate * Loop through the hash buckets, printing the appropriate 21610Sstevel@tonic-gate * symbols. 21620Sstevel@tonic-gate */ 21630Sstevel@tonic-gate for (ndx = 0; ndx < bkts; ndx++, hash++) { 21641618Srie Word _ndx, _cnt; 21650Sstevel@tonic-gate 21660Sstevel@tonic-gate if (*hash == 0) { 21670Sstevel@tonic-gate count[0]++; 21680Sstevel@tonic-gate continue; 21690Sstevel@tonic-gate } 21700Sstevel@tonic-gate 21711618Srie hash_entry(_cache, &cache[sshdr->sh_link], hsecname, 21721618Srie ndx, *hash, symn, syms, file, bkts, flags, 0); 21730Sstevel@tonic-gate 21740Sstevel@tonic-gate /* 21750Sstevel@tonic-gate * Determine if any other symbols are chained to this 21760Sstevel@tonic-gate * bucket. 21770Sstevel@tonic-gate */ 21780Sstevel@tonic-gate _ndx = chain[*hash]; 21790Sstevel@tonic-gate _cnt = 1; 21800Sstevel@tonic-gate while (_ndx) { 21811618Srie hash_entry(_cache, &cache[sshdr->sh_link], 21821618Srie hsecname, ndx, _ndx, symn, syms, file, 21831618Srie bkts, flags, 1); 21840Sstevel@tonic-gate _ndx = chain[_ndx]; 21850Sstevel@tonic-gate _cnt++; 21860Sstevel@tonic-gate } 21870Sstevel@tonic-gate 21880Sstevel@tonic-gate if (_cnt >= MAXCOUNT) { 21890Sstevel@tonic-gate (void) fprintf(stderr, 21901324Srie MSG_INTL(MSG_HASH_OVERFLW), file, 21911618Srie _cache->c_name, EC_WORD(ndx), 21921618Srie EC_WORD(_cnt)); 21930Sstevel@tonic-gate } else 21940Sstevel@tonic-gate count[_cnt]++; 21950Sstevel@tonic-gate } 21960Sstevel@tonic-gate break; 21970Sstevel@tonic-gate } 21980Sstevel@tonic-gate 21990Sstevel@tonic-gate /* 22000Sstevel@tonic-gate * Print out the count information. 22010Sstevel@tonic-gate */ 22020Sstevel@tonic-gate bkts = cnt = 0; 22031618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 22041618Srie 22050Sstevel@tonic-gate for (ndx = 0; ndx < MAXCOUNT; ndx++) { 22061618Srie Word _cnt; 22070Sstevel@tonic-gate 22080Sstevel@tonic-gate if ((_cnt = count[ndx]) == 0) 22090Sstevel@tonic-gate continue; 22100Sstevel@tonic-gate 22111618Srie (void) snprintf(number, MAXNDXSIZE, 22121618Srie MSG_ORIG(MSG_FMT_INTEGER), _cnt); 22131618Srie dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS1), number, 22141618Srie EC_WORD(ndx)); 22150Sstevel@tonic-gate bkts += _cnt; 22161618Srie cnt += (Word)(ndx * _cnt); 22170Sstevel@tonic-gate } 22180Sstevel@tonic-gate if (cnt) { 22190Sstevel@tonic-gate (void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 22201618Srie bkts); 22211618Srie dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS2), number, 22221618Srie EC_WORD(cnt)); 22230Sstevel@tonic-gate } 22240Sstevel@tonic-gate } 22250Sstevel@tonic-gate 22260Sstevel@tonic-gate static void 22271618Srie group(Cache *cache, Word shnum, const char *name, const char *file, 22281618Srie uint_t flags) 22290Sstevel@tonic-gate { 22301618Srie Word scnt; 22310Sstevel@tonic-gate 22321618Srie for (scnt = 1; scnt < shnum; scnt++) { 22331618Srie Cache *_cache = &cache[scnt]; 22341618Srie Shdr *shdr = _cache->c_shdr; 22351618Srie Word *grpdata, gcnt, grpcnt, symnum, unknown; 22361618Srie Cache *symsec, *strsec; 22371618Srie Sym *syms, *sym; 22381618Srie char flgstrbuf[MSG_GRP_COMDAT_SIZE + 10]; 22390Sstevel@tonic-gate 22400Sstevel@tonic-gate if (shdr->sh_type != SHT_GROUP) 22410Sstevel@tonic-gate continue; 22420Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 22430Sstevel@tonic-gate continue; 22443466Srie if ((_cache->c_data == NULL) || 22453466Srie ((grpdata = (Word *)_cache->c_data->d_buf) == NULL)) 22460Sstevel@tonic-gate continue; 22471618Srie grpcnt = shdr->sh_size / sizeof (Word); 22481618Srie 22491618Srie /* 22501618Srie * Get the data buffer for the associated symbol table and 22511618Srie * string table. 22521618Srie */ 22531618Srie if (stringtbl(cache, 1, scnt, shnum, file, 22541618Srie &symnum, &symsec, &strsec) == 0) 22551618Srie return; 22561618Srie 22571618Srie syms = symsec->c_data->d_buf; 22581618Srie 22591618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 22601618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_GRP), _cache->c_name); 22611618Srie dbg_print(0, MSG_INTL(MSG_GRP_TITLE)); 22621618Srie 22631618Srie /* 22641618Srie * The first element of the group defines the group. The 22651618Srie * associated symbol is defined by the sh_link field. 22661618Srie */ 22671618Srie if ((shdr->sh_info == SHN_UNDEF) || (shdr->sh_info > symnum)) { 22681618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 22691618Srie file, _cache->c_name, EC_WORD(shdr->sh_info)); 22701618Srie return; 22710Sstevel@tonic-gate } 22720Sstevel@tonic-gate 22731618Srie (void) strcpy(flgstrbuf, MSG_ORIG(MSG_STR_OSQBRKT)); 22741618Srie if (grpdata[0] & GRP_COMDAT) { 22751618Srie (void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_COMDAT)); 22760Sstevel@tonic-gate } 22771618Srie if ((unknown = (grpdata[0] & ~GRP_COMDAT)) != 0) { 22781618Srie size_t len = strlen(flgstrbuf); 22791618Srie 22801618Srie (void) snprintf(&flgstrbuf[len], 22811618Srie (MSG_GRP_COMDAT_SIZE + 10 - len), 22821618Srie MSG_ORIG(MSG_GRP_UNKNOWN), unknown); 22830Sstevel@tonic-gate } 22841618Srie (void) strcat(flgstrbuf, MSG_ORIG(MSG_STR_CSQBRKT)); 22851618Srie sym = (Sym *)(syms + shdr->sh_info); 22860Sstevel@tonic-gate 22871618Srie dbg_print(0, MSG_INTL(MSG_GRP_SIGNATURE), flgstrbuf, 22881618Srie demangle(string(_cache, 0, strsec, file, sym->st_name), 22891618Srie flags)); 22901618Srie 22911618Srie for (gcnt = 1; gcnt < grpcnt; gcnt++) { 22920Sstevel@tonic-gate char index[MAXNDXSIZE]; 22931618Srie const char *name; 22940Sstevel@tonic-gate 22950Sstevel@tonic-gate (void) snprintf(index, MAXNDXSIZE, 22961618Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(gcnt)); 22971618Srie 22981618Srie if (grpdata[gcnt] >= shnum) 22991618Srie name = MSG_INTL(MSG_GRP_INVALSCN); 23001618Srie else 23011618Srie name = cache[grpdata[gcnt]].c_name; 23021618Srie 23031618Srie (void) printf(MSG_ORIG(MSG_GRP_ENTRY), index, name, 23041618Srie EC_XWORD(grpdata[gcnt])); 23050Sstevel@tonic-gate } 23060Sstevel@tonic-gate } 23070Sstevel@tonic-gate } 23080Sstevel@tonic-gate 23090Sstevel@tonic-gate static void 23101618Srie got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, uint_t flags) 23110Sstevel@tonic-gate { 23120Sstevel@tonic-gate Cache *gotcache = 0, *symtab = 0, *_cache; 23131618Srie Addr gotbgn, gotend; 23141618Srie Shdr *gotshdr; 23151618Srie Word cnt, gotents, gotndx; 23160Sstevel@tonic-gate size_t gentsize; 23170Sstevel@tonic-gate Got_info *gottable; 23180Sstevel@tonic-gate char *gotdata; 23191618Srie Sym *gotsym; 23201618Srie Xword gotsymaddr; 23210Sstevel@tonic-gate 23220Sstevel@tonic-gate /* 23231324Srie * First, find the got. 23240Sstevel@tonic-gate */ 23250Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 23260Sstevel@tonic-gate _cache = &cache[cnt]; 23271324Srie if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT), 23281324Srie MSG_ELF_GOT_SIZE) == 0) { 23290Sstevel@tonic-gate gotcache = _cache; 23300Sstevel@tonic-gate break; 23310Sstevel@tonic-gate } 23320Sstevel@tonic-gate } 23331618Srie if (gotcache == 0) 23340Sstevel@tonic-gate return; 23351324Srie 23361324Srie /* 23371324Srie * A got section within a relocatable object is suspicious. 23381324Srie */ 23391324Srie if (ehdr->e_type == ET_REL) { 23401324Srie (void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file, 23411324Srie _cache->c_name); 23421324Srie } 23431324Srie 23441618Srie gotshdr = gotcache->c_shdr; 23450Sstevel@tonic-gate if (gotshdr->sh_size == 0) { 23460Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 23470Sstevel@tonic-gate file, gotcache->c_name); 23480Sstevel@tonic-gate return; 23490Sstevel@tonic-gate } 23501618Srie 23511618Srie gotbgn = gotshdr->sh_addr; 23520Sstevel@tonic-gate gotend = gotbgn + gotshdr->sh_size; 23530Sstevel@tonic-gate 23540Sstevel@tonic-gate /* 23551618Srie * Some architectures don't properly set the sh_entsize for the GOT 23561618Srie * table. If it's not set, default to a size of a pointer. 23570Sstevel@tonic-gate */ 23581618Srie if ((gentsize = gotshdr->sh_entsize) == 0) 23591618Srie gentsize = sizeof (Xword); 23601618Srie 23613466Srie if (gotcache->c_data == NULL) 23623466Srie return; 23633466Srie 23640Sstevel@tonic-gate /* LINTED */ 23651618Srie gotents = (Word)(gotshdr->sh_size / gentsize); 23660Sstevel@tonic-gate gotdata = gotcache->c_data->d_buf; 23670Sstevel@tonic-gate 23680Sstevel@tonic-gate if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) { 23690Sstevel@tonic-gate int err = errno; 23701618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), file, 23711618Srie strerror(err)); 23720Sstevel@tonic-gate return; 23730Sstevel@tonic-gate } 23740Sstevel@tonic-gate 23750Sstevel@tonic-gate /* 23760Sstevel@tonic-gate * Now we scan through all the sections looking for any relocations 23770Sstevel@tonic-gate * that may be against the GOT. Since these may not be isolated to a 23780Sstevel@tonic-gate * .rel[a].got section we check them all. 23790Sstevel@tonic-gate * While scanning sections save the symbol table entry (a symtab 23800Sstevel@tonic-gate * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_. 23810Sstevel@tonic-gate */ 23820Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 23831618Srie Word type, symnum; 23841618Srie Xword relndx, relnum, relsize; 23851618Srie void *rels; 23861618Srie Sym *syms; 23871618Srie Cache *symsec, *strsec; 23881618Srie Cache *_cache = &cache[cnt]; 23891618Srie Shdr *shdr; 23900Sstevel@tonic-gate 23911618Srie shdr = _cache->c_shdr; 23921618Srie type = shdr->sh_type; 23930Sstevel@tonic-gate 23941618Srie if ((symtab == 0) && (type == SHT_DYNSYM)) { 23950Sstevel@tonic-gate symtab = _cache; 23960Sstevel@tonic-gate continue; 23970Sstevel@tonic-gate } 23981618Srie if (type == SHT_SYMTAB) { 23990Sstevel@tonic-gate symtab = _cache; 24000Sstevel@tonic-gate continue; 24010Sstevel@tonic-gate } 24021618Srie if ((type != SHT_RELA) && (type != SHT_REL)) 24030Sstevel@tonic-gate continue; 24040Sstevel@tonic-gate 24050Sstevel@tonic-gate /* 24061618Srie * Decide entry size. 24070Sstevel@tonic-gate */ 24081618Srie if (((relsize = shdr->sh_entsize) == 0) || 24091618Srie (relsize > shdr->sh_size)) { 24101618Srie if (type == SHT_RELA) 24111618Srie relsize = sizeof (Rela); 24121618Srie else 24131618Srie relsize = sizeof (Rel); 24140Sstevel@tonic-gate } 24150Sstevel@tonic-gate 24160Sstevel@tonic-gate /* 24171618Srie * Determine the number of relocations available. 24180Sstevel@tonic-gate */ 24191618Srie if (shdr->sh_size == 0) { 24201618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 24211618Srie file, _cache->c_name); 24220Sstevel@tonic-gate continue; 24230Sstevel@tonic-gate } 24243466Srie if (_cache->c_data == NULL) 24253466Srie continue; 24263466Srie 24271618Srie rels = _cache->c_data->d_buf; 24281618Srie relnum = shdr->sh_size / relsize; 24290Sstevel@tonic-gate 24301618Srie /* 24311618Srie * Get the data buffer for the associated symbol table and 24321618Srie * string table. 24331618Srie */ 24341618Srie if (stringtbl(cache, 1, cnt, shnum, file, 24351618Srie &symnum, &symsec, &strsec) == 0) 24361618Srie continue; 24371618Srie 24381618Srie syms = symsec->c_data->d_buf; 24391618Srie 24401618Srie /* 24411618Srie * Loop through the relocation entries. 24421618Srie */ 24431618Srie for (relndx = 0; relndx < relnum; relndx++, 24441618Srie rels = (void *)((char *)rels + relsize)) { 24451618Srie char section[BUFSIZ]; 24461618Srie Addr offset; 24470Sstevel@tonic-gate Got_info *gip; 24481618Srie Word symndx, reltype; 24491618Srie Rela *rela; 24501618Srie Rel *rel; 24510Sstevel@tonic-gate 24521618Srie /* 24531618Srie * Unravel the relocation. 24541618Srie */ 24551618Srie if (type == SHT_RELA) { 24561618Srie rela = (Rela *)rels; 24571618Srie symndx = ELF_R_SYM(rela->r_info); 24581618Srie reltype = ELF_R_TYPE(rela->r_info); 24591618Srie offset = rela->r_offset; 24600Sstevel@tonic-gate } else { 24611618Srie rel = (Rel *)rels; 24621618Srie symndx = ELF_R_SYM(rel->r_info); 24631618Srie reltype = ELF_R_TYPE(rel->r_info); 24641618Srie offset = rel->r_offset; 24650Sstevel@tonic-gate } 24660Sstevel@tonic-gate 24670Sstevel@tonic-gate /* 24680Sstevel@tonic-gate * Only pay attention to relocations against the GOT. 24690Sstevel@tonic-gate */ 24700Sstevel@tonic-gate if ((offset < gotbgn) || (offset > gotend)) 24710Sstevel@tonic-gate continue; 24720Sstevel@tonic-gate 24730Sstevel@tonic-gate /* LINTED */ 24741618Srie gotndx = (Word)((offset - gotbgn) / 24750Sstevel@tonic-gate gotshdr->sh_entsize); 24760Sstevel@tonic-gate gip = &gottable[gotndx]; 24771618Srie 24781618Srie if (gip->g_reltype != 0) { 24790Sstevel@tonic-gate (void) fprintf(stderr, 24800Sstevel@tonic-gate MSG_INTL(MSG_GOT_MULTIPLE), file, 24811618Srie EC_WORD(gotndx), EC_ADDR(offset)); 24820Sstevel@tonic-gate continue; 24830Sstevel@tonic-gate } 24840Sstevel@tonic-gate 24851618Srie if (symndx) 24861618Srie gip->g_symname = relsymname(cache, _cache, 24871618Srie strsec, symndx, symnum, relndx, syms, 24881618Srie section, BUFSIZ, file, flags); 24891618Srie gip->g_reltype = reltype; 24901618Srie gip->g_rel = rels; 24910Sstevel@tonic-gate } 24920Sstevel@tonic-gate } 24930Sstevel@tonic-gate 24941618Srie if (symlookup(MSG_ORIG(MSG_GOT_SYM), cache, shnum, &gotsym, symtab, 24951618Srie file)) 24961618Srie gotsymaddr = gotsym->st_value; 24970Sstevel@tonic-gate else 24981618Srie gotsymaddr = gotbgn; 24990Sstevel@tonic-gate 25001618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 25011618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name); 25021618Srie Elf_got_title(0); 25030Sstevel@tonic-gate 25040Sstevel@tonic-gate for (gotndx = 0; gotndx < gotents; gotndx++) { 25050Sstevel@tonic-gate Got_info *gip; 25060Sstevel@tonic-gate Sword gindex; 25071618Srie Addr gaddr; 25081618Srie Xword gotentry; 25090Sstevel@tonic-gate 25100Sstevel@tonic-gate gip = &gottable[gotndx]; 25110Sstevel@tonic-gate 25120Sstevel@tonic-gate gaddr = gotbgn + (gotndx * gentsize); 25131618Srie gindex = (Sword)(gaddr - gotsymaddr) / (Sword)gentsize; 25140Sstevel@tonic-gate 25151618Srie if (gentsize == sizeof (Word)) 25160Sstevel@tonic-gate /* LINTED */ 25171618Srie gotentry = (Xword)(*((Word *)(gotdata) + gotndx)); 25180Sstevel@tonic-gate else 25190Sstevel@tonic-gate /* LINTED */ 25201618Srie gotentry = *((Xword *)(gotdata) + gotndx); 25210Sstevel@tonic-gate 25221618Srie Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine, 25231618Srie gip->g_reltype, gip->g_rel, gip->g_symname); 25240Sstevel@tonic-gate } 25250Sstevel@tonic-gate free(gottable); 25260Sstevel@tonic-gate } 25270Sstevel@tonic-gate 25280Sstevel@tonic-gate void 25290Sstevel@tonic-gate checksum(Elf *elf) 25300Sstevel@tonic-gate { 25311618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 25321618Srie dbg_print(0, MSG_INTL(MSG_STR_CHECKSUM), elf_checksum(elf)); 25330Sstevel@tonic-gate } 25340Sstevel@tonic-gate 25351618Srie void 25361618Srie regular(const char *file, Elf *elf, uint_t flags, char *Nname, int wfd) 25370Sstevel@tonic-gate { 25380Sstevel@tonic-gate Elf_Scn *scn; 25391618Srie Ehdr *ehdr; 25400Sstevel@tonic-gate Elf_Data *data; 25411618Srie size_t cnt, shstrndx, shnum, phnum; 25421618Srie Shdr *nameshdr, *shdr; 25430Sstevel@tonic-gate char *names = 0; 25440Sstevel@tonic-gate Cache *cache, *_cache; 25451618Srie Cache *versymcache = 0; 25460Sstevel@tonic-gate 25471618Srie if ((ehdr = elf_getehdr(elf)) == NULL) { 25480Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETEHDR)); 25490Sstevel@tonic-gate return; 25500Sstevel@tonic-gate } 25510Sstevel@tonic-gate 25521618Srie if (elf_getshnum(elf, &shnum) == 0) { 25530Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHNUM)); 25540Sstevel@tonic-gate return; 25550Sstevel@tonic-gate } 25560Sstevel@tonic-gate 2557942Sahl if (elf_getshstrndx(elf, &shstrndx) == 0) { 25580Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX)); 25590Sstevel@tonic-gate return; 25600Sstevel@tonic-gate } 2561942Sahl 25621618Srie if (elf_getphnum(elf, &phnum) == 0) { 2563942Sahl failure(file, MSG_ORIG(MSG_ELF_GETPHNUM)); 2564942Sahl return; 2565942Sahl } 2566942Sahl 25670Sstevel@tonic-gate if ((scn = elf_getscn(elf, 0)) != NULL) { 25681618Srie if ((shdr = elf_getshdr(scn)) == NULL) { 25690Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 25700Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0); 25710Sstevel@tonic-gate return; 25720Sstevel@tonic-gate } 25730Sstevel@tonic-gate } else 25741618Srie shdr = 0; 25750Sstevel@tonic-gate 25760Sstevel@tonic-gate /* 25770Sstevel@tonic-gate * Print the elf header. 25780Sstevel@tonic-gate */ 25790Sstevel@tonic-gate if (flags & FLG_EHDR) 25801618Srie Elf_ehdr(0, ehdr, shdr); 25810Sstevel@tonic-gate 25820Sstevel@tonic-gate /* 25830Sstevel@tonic-gate * Print the program headers. 25840Sstevel@tonic-gate */ 25851618Srie if ((flags & FLG_PHDR) && (phnum != 0)) { 25861618Srie Phdr *phdr; 25870Sstevel@tonic-gate 25881618Srie if ((phdr = elf_getphdr(elf)) == NULL) { 25891618Srie failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 25901618Srie return; 25911618Srie } 25920Sstevel@tonic-gate 25931618Srie for (cnt = 0; cnt < phnum; phdr++, cnt++) { 25941618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 25951618Srie dbg_print(0, MSG_INTL(MSG_ELF_PHDR), EC_WORD(cnt)); 25961618Srie Elf_phdr(0, ehdr->e_machine, phdr); 25970Sstevel@tonic-gate } 25980Sstevel@tonic-gate } 25990Sstevel@tonic-gate 26000Sstevel@tonic-gate 26010Sstevel@tonic-gate /* 2602942Sahl * Return now if there are no section, if there's just one section to 2603942Sahl * act as an extension of the ELF header, or if on section information 2604942Sahl * was requested. 26050Sstevel@tonic-gate */ 2606942Sahl if ((shnum <= 1) || (flags && (flags & ~(FLG_EHDR | FLG_PHDR)) == 0)) { 26071618Srie if ((ehdr->e_type == ET_CORE) && (flags & FLG_NOTE)) 26080Sstevel@tonic-gate note(0, shnum, 0, file); 26090Sstevel@tonic-gate return; 26100Sstevel@tonic-gate } 26110Sstevel@tonic-gate 26121618Srie 26130Sstevel@tonic-gate /* 26140Sstevel@tonic-gate * Obtain the .shstrtab data buffer to provide the required section 26150Sstevel@tonic-gate * name strings. 26160Sstevel@tonic-gate */ 26170Sstevel@tonic-gate if ((scn = elf_getscn(elf, shstrndx)) == NULL) { 26180Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSCN)); 26190Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR), 26200Sstevel@tonic-gate EC_XWORD(shstrndx)); 26211618Srie 26220Sstevel@tonic-gate } else if ((data = elf_getdata(scn, NULL)) == NULL) { 26230Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 26240Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA), 26250Sstevel@tonic-gate EC_XWORD(shstrndx)); 26261618Srie 26271618Srie } else if ((nameshdr = elf_getshdr(scn)) == NULL) { 26280Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 26290Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 26300Sstevel@tonic-gate /* LINTED */ 26310Sstevel@tonic-gate (int)elf_ndxscn(scn)); 26321618Srie 26331618Srie } else if ((names = data->d_buf) == 0) 26340Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file); 26350Sstevel@tonic-gate 26360Sstevel@tonic-gate /* 26370Sstevel@tonic-gate * Fill in the cache descriptor with information for each section. 26380Sstevel@tonic-gate */ 26390Sstevel@tonic-gate if ((cache = malloc(shnum * sizeof (Cache))) == 0) { 26400Sstevel@tonic-gate int err = errno; 26410Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 26420Sstevel@tonic-gate file, strerror(err)); 26430Sstevel@tonic-gate return; 26440Sstevel@tonic-gate } 26450Sstevel@tonic-gate 26461618Srie *cache = cache_init; 26470Sstevel@tonic-gate _cache = cache; 26480Sstevel@tonic-gate _cache++; 26490Sstevel@tonic-gate 26500Sstevel@tonic-gate for (cnt = 1, scn = NULL; scn = elf_nextscn(elf, scn); 26510Sstevel@tonic-gate cnt++, _cache++) { 26521618Srie if ((_cache->c_shdr = elf_getshdr(scn)) == NULL) { 26530Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 26540Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 26550Sstevel@tonic-gate /* LINTED */ 26560Sstevel@tonic-gate (int)elf_ndxscn(scn)); 26570Sstevel@tonic-gate } 26580Sstevel@tonic-gate 26591618Srie if (names && _cache->c_shdr->sh_name && 26600Sstevel@tonic-gate /* LINTED */ 26611618Srie (nameshdr->sh_size > _cache->c_shdr->sh_name)) 26621618Srie _cache->c_name = names + _cache->c_shdr->sh_name; 26630Sstevel@tonic-gate else { 26640Sstevel@tonic-gate /* 26650Sstevel@tonic-gate * If there exists no shstrtab data, or a section header 26660Sstevel@tonic-gate * has no name (an invalid index of 0), then compose a 26670Sstevel@tonic-gate * name for each section. 26680Sstevel@tonic-gate */ 26690Sstevel@tonic-gate char scnndxnm[100]; 26700Sstevel@tonic-gate 26710Sstevel@tonic-gate (void) snprintf(scnndxnm, 100, MSG_INTL(MSG_FMT_SCNNDX), 26720Sstevel@tonic-gate cnt); 26730Sstevel@tonic-gate 26740Sstevel@tonic-gate /* 26750Sstevel@tonic-gate * Although we have a valid shstrtab section inform the 26760Sstevel@tonic-gate * user if this section name index exceeds the shstrtab 26770Sstevel@tonic-gate * data. 26780Sstevel@tonic-gate */ 26790Sstevel@tonic-gate if (names && 26800Sstevel@tonic-gate /* LINTED */ 26811618Srie (nameshdr->sh_size <= _cache->c_shdr->sh_name)) { 26820Sstevel@tonic-gate (void) fprintf(stderr, 26830Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSHNAME), file, 26840Sstevel@tonic-gate _cache->c_name, 26851618Srie EC_XWORD(_cache->c_shdr->sh_name)); 26860Sstevel@tonic-gate } 26870Sstevel@tonic-gate 26880Sstevel@tonic-gate if ((_cache->c_name = 26890Sstevel@tonic-gate malloc(strlen(scnndxnm) + 1)) == 0) { 26900Sstevel@tonic-gate int err = errno; 26910Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 26920Sstevel@tonic-gate file, strerror(err)); 26930Sstevel@tonic-gate return; 26940Sstevel@tonic-gate } 26950Sstevel@tonic-gate (void) strcpy(_cache->c_name, scnndxnm); 26960Sstevel@tonic-gate } 26970Sstevel@tonic-gate 26980Sstevel@tonic-gate if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) { 26990Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 27000Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA), 27010Sstevel@tonic-gate /* LINTED */ 27020Sstevel@tonic-gate (int)elf_ndxscn(scn)); 27030Sstevel@tonic-gate } 27040Sstevel@tonic-gate 27050Sstevel@tonic-gate /* 27060Sstevel@tonic-gate * Do we wish to write the section out? 27070Sstevel@tonic-gate */ 27083466Srie if (wfd && Nname && (strcmp(Nname, _cache->c_name) == 0) && 27093466Srie _cache->c_data) { 27100Sstevel@tonic-gate (void) write(wfd, _cache->c_data->d_buf, 27110Sstevel@tonic-gate _cache->c_data->d_size); 27120Sstevel@tonic-gate } 27130Sstevel@tonic-gate } 27140Sstevel@tonic-gate 27150Sstevel@tonic-gate if (flags & FLG_SHDR) 27161618Srie sections(file, cache, shnum, ehdr, Nname); 27170Sstevel@tonic-gate 27180Sstevel@tonic-gate if (flags & FLG_INTERP) 27191618Srie interp(file, cache, shnum, phnum, elf); 27200Sstevel@tonic-gate 27210Sstevel@tonic-gate versymcache = versions(cache, shnum, file, flags); 27220Sstevel@tonic-gate 27230Sstevel@tonic-gate if (flags & FLG_SYMBOLS) 27241618Srie symbols(cache, shnum, ehdr, Nname, versymcache, file, flags); 27250Sstevel@tonic-gate 2726*3492Sab196087 if (flags & FLG_SORT) 2727*3492Sab196087 sunw_sort(cache, shnum, ehdr, Nname, versymcache, file, flags); 2728*3492Sab196087 27290Sstevel@tonic-gate if (flags & FLG_HASH) 27300Sstevel@tonic-gate hash(cache, shnum, Nname, file, flags); 27310Sstevel@tonic-gate 27320Sstevel@tonic-gate if (flags & FLG_GOT) 27331618Srie got(cache, shnum, ehdr, file, flags); 27340Sstevel@tonic-gate 27350Sstevel@tonic-gate if (flags & FLG_GROUP) 27360Sstevel@tonic-gate group(cache, shnum, Nname, file, flags); 27370Sstevel@tonic-gate 27380Sstevel@tonic-gate if (flags & FLG_SYMINFO) 27390Sstevel@tonic-gate syminfo(cache, shnum, file); 27400Sstevel@tonic-gate 27410Sstevel@tonic-gate if (flags & FLG_RELOC) 27421618Srie reloc(cache, shnum, ehdr, Nname, file, flags); 27430Sstevel@tonic-gate 27440Sstevel@tonic-gate if (flags & FLG_DYNAMIC) 27451618Srie dynamic(cache, shnum, ehdr, file); 27460Sstevel@tonic-gate 27470Sstevel@tonic-gate if (flags & FLG_NOTE) 27480Sstevel@tonic-gate note(cache, shnum, Nname, file); 27490Sstevel@tonic-gate 27500Sstevel@tonic-gate if (flags & FLG_MOVE) 27510Sstevel@tonic-gate move(cache, shnum, Nname, file, flags); 27520Sstevel@tonic-gate 27530Sstevel@tonic-gate if (flags & FLG_CHECKSUM) 27540Sstevel@tonic-gate checksum(elf); 27550Sstevel@tonic-gate 27560Sstevel@tonic-gate if (flags & FLG_CAP) 27571618Srie cap(file, cache, shnum, phnum, ehdr, elf); 27580Sstevel@tonic-gate 27590Sstevel@tonic-gate if (flags & FLG_UNWIND) 27601618Srie unwind(cache, shnum, phnum, ehdr, Nname, file, elf); 27610Sstevel@tonic-gate 27620Sstevel@tonic-gate free(cache); 27630Sstevel@tonic-gate } 2764