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; 523492Sab196087 const char *strs; 533492Sab196087 Word strn; 540Sstevel@tonic-gate 553466Srie if (strsec->c_data == NULL) 563466Srie return (NULL); 573466Srie 583492Sab196087 strs = (char *)strsec->c_data->d_buf; 593492Sab196087 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 2740Sstevel@tonic-gate /* 2750Sstevel@tonic-gate * Although numerous section header entries can be zero, it's 276*3862Srie * usually a sign of trouble if the type is zero. 2770Sstevel@tonic-gate */ 2780Sstevel@tonic-gate if (shdr->sh_type == 0) { 2790Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE), 2801618Srie file, secname, EC_WORD(shdr->sh_type)); 2810Sstevel@tonic-gate } 282*3862Srie 283*3862Srie if (name && strcmp(name, secname)) 284*3862Srie continue; 2850Sstevel@tonic-gate 2861324Srie /* 2871324Srie * Identify any sections that are suspicious. A .got section 2881324Srie * shouldn't exist in a relocatable object. 2891324Srie */ 2901324Srie if (ehdr->e_type == ET_REL) { 2911618Srie if (strncmp(secname, MSG_ORIG(MSG_ELF_GOT), 2921324Srie MSG_ELF_GOT_SIZE) == 0) { 2931324Srie (void) fprintf(stderr, 2941618Srie MSG_INTL(MSG_GOT_UNEXPECTED), file, 2951618Srie secname); 2961324Srie } 2971324Srie } 2981324Srie 2991618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 3001618Srie dbg_print(0, MSG_INTL(MSG_ELF_SHDR), EC_WORD(seccnt), secname); 3011618Srie Elf_shdr(0, ehdr->e_machine, shdr); 3020Sstevel@tonic-gate } 3030Sstevel@tonic-gate } 3040Sstevel@tonic-gate 3051618Srie /* 3061618Srie * A couple of instances of unwind data are printed as tables of 8 data items 3071618Srie * expressed as 0x?? integers. 3081618Srie */ 3091618Srie #define UNWINDTBLSZ 10 + (8 * 5) + 1 3101618Srie 3111618Srie static void 3121618Srie unwindtbl(uint64_t *ndx, uint_t len, uchar_t *data, uint64_t doff, 3131618Srie const char *msg, const char *pre, size_t plen) 3141618Srie { 3151618Srie char buffer[UNWINDTBLSZ]; 3161618Srie uint_t boff = plen, cnt = 0; 3171618Srie 3181618Srie dbg_print(0, msg); 3191618Srie (void) strncpy(buffer, pre, UNWINDTBLSZ); 3201618Srie 3211618Srie while (*ndx < (len + 4)) { 3221618Srie if (cnt == 8) { 3231618Srie dbg_print(0, buffer); 3241618Srie boff = plen; 3251618Srie cnt = 0; 3261618Srie } 3271618Srie (void) snprintf(&buffer[boff], UNWINDTBLSZ - boff, 3281618Srie MSG_ORIG(MSG_UNW_TBLENTRY), data[doff + (*ndx)++]); 3291618Srie boff += 5; 3301618Srie cnt++; 3311618Srie } 3321618Srie if (cnt) 3331618Srie dbg_print(0, buffer); 3341618Srie } 3351618Srie 3361618Srie /* 3371618Srie * Obtain a specified Phdr entry. 3381618Srie */ 3391618Srie static Phdr * 3401618Srie getphdr(Word phnum, Word type, const char *file, Elf *elf) 3411618Srie { 3421618Srie Word cnt; 3431618Srie Phdr *phdr; 3441618Srie 3451618Srie if ((phdr = elf_getphdr(elf)) == NULL) { 3461618Srie failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 3471618Srie return (0); 3481618Srie } 3491618Srie 3501618Srie for (cnt = 0; cnt < phnum; phdr++, cnt++) { 3511618Srie if (phdr->p_type == type) 3521618Srie return (phdr); 3531618Srie } 3541618Srie return (0); 3551618Srie } 3561618Srie 3570Sstevel@tonic-gate static void 3581618Srie unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, const char *name, 3591618Srie const char *file, Elf *elf) 3600Sstevel@tonic-gate { 3611618Srie Word cnt; 3621618Srie Phdr *uphdr = 0; 3631618Srie 3640Sstevel@tonic-gate /* 3651618Srie * For the moment - UNWIND is only relevant for a AMD64 object. 3660Sstevel@tonic-gate */ 3670Sstevel@tonic-gate if (ehdr->e_machine != EM_AMD64) 3681618Srie return; 3690Sstevel@tonic-gate 3701618Srie if (phnum) 3711618Srie uphdr = getphdr(phnum, PT_SUNW_UNWIND, file, elf); 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 3741618Srie Cache *_cache = &cache[cnt]; 3751618Srie Shdr *shdr = _cache->c_shdr; 3761618Srie uchar_t *data; 3770Sstevel@tonic-gate size_t datasize; 3781618Srie uint64_t off, ndx, frame_ptr, fde_cnt, tabndx; 3791618Srie uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc; 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate /* 3821618Srie * AMD64 - this is a strmcp() just to find the gcc produced 3831618Srie * sections. Soon gcc should be setting the section type - and 3841618Srie * we'll not need this strcmp(). 3850Sstevel@tonic-gate */ 3860Sstevel@tonic-gate if ((shdr->sh_type != SHT_AMD64_UNWIND) && 3870Sstevel@tonic-gate (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM), 3880Sstevel@tonic-gate MSG_SCN_FRM_SIZE) != 0) && 3890Sstevel@tonic-gate (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 3900Sstevel@tonic-gate MSG_SCN_FRMHDR_SIZE) != 0)) 3910Sstevel@tonic-gate continue; 3920Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 3930Sstevel@tonic-gate continue; 3940Sstevel@tonic-gate 3953466Srie if (_cache->c_data == NULL) 3963466Srie continue; 3973466Srie 3981618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 3991618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name); 4000Sstevel@tonic-gate 4011618Srie data = (uchar_t *)(_cache->c_data->d_buf); 4020Sstevel@tonic-gate datasize = _cache->c_data->d_size; 4030Sstevel@tonic-gate off = 0; 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate /* 4060Sstevel@tonic-gate * Is this a .eh_frame_hdr 4070Sstevel@tonic-gate */ 4081618Srie if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) || 4090Sstevel@tonic-gate (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 4101618Srie MSG_SCN_FRMHDR_SIZE) == 0)) { 4111618Srie 4121618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR)); 4131618Srie ndx = 0; 4140Sstevel@tonic-gate 4151618Srie vers = data[ndx++]; 4161618Srie frame_ptr_enc = data[ndx++]; 4171618Srie fde_cnt_enc = data[ndx++]; 4181618Srie table_enc = data[ndx++]; 4190Sstevel@tonic-gate 4201618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers); 4210Sstevel@tonic-gate 4221618Srie frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc, 4231618Srie ehdr->e_ident, shdr->sh_addr + ndx); 4240Sstevel@tonic-gate 4251618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC), 4261618Srie conv_dwarf_ehe(frame_ptr_enc), EC_XWORD(frame_ptr)); 4271618Srie 4281618Srie fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc, 4291618Srie ehdr->e_ident, shdr->sh_addr + ndx); 4300Sstevel@tonic-gate 4311618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC), 4321618Srie conv_dwarf_ehe(fde_cnt_enc), EC_XWORD(fde_cnt)); 4331618Srie dbg_print(0, MSG_ORIG(MSG_UNW_TABENC), 4341618Srie conv_dwarf_ehe(table_enc)); 4351618Srie dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1)); 4361618Srie dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2)); 4370Sstevel@tonic-gate 4381618Srie for (tabndx = 0; tabndx < fde_cnt; tabndx++) { 4391618Srie dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT), 4401618Srie EC_XWORD(dwarf_ehe_extract(data, &ndx, 4411618Srie table_enc, ehdr->e_ident, shdr->sh_addr)), 4421618Srie EC_XWORD(dwarf_ehe_extract(data, &ndx, 4431618Srie table_enc, ehdr->e_ident, shdr->sh_addr))); 4441618Srie } 4451618Srie continue; 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate /* 4490Sstevel@tonic-gate * Walk the Eh_frame's 4500Sstevel@tonic-gate */ 4510Sstevel@tonic-gate while (off < datasize) { 4520Sstevel@tonic-gate uint_t cieid, cielength, cieversion, 4530Sstevel@tonic-gate cieretaddr; 4541618Srie int cieRflag, cieLflag, ciePflag, cieZflag; 4551618Srie uint_t cieaugndx, length, id; 4560Sstevel@tonic-gate uint64_t ciecalign, ciedalign; 4570Sstevel@tonic-gate char *cieaugstr; 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate ndx = 0; 4600Sstevel@tonic-gate /* 4610Sstevel@tonic-gate * extract length in lsb format 4620Sstevel@tonic-gate */ 4630Sstevel@tonic-gate length = LSB32EXTRACT(data + off + ndx); 4640Sstevel@tonic-gate ndx += 4; 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate /* 4670Sstevel@tonic-gate * extract CIE id in lsb format 4680Sstevel@tonic-gate */ 4690Sstevel@tonic-gate id = LSB32EXTRACT(data + off + ndx); 4700Sstevel@tonic-gate ndx += 4; 4710Sstevel@tonic-gate 4720Sstevel@tonic-gate /* 4731618Srie * A CIE record has a id of '0', otherwise this is a 4741618Srie * FDE entry and the 'id' is the CIE pointer. 4750Sstevel@tonic-gate */ 4760Sstevel@tonic-gate if (id == 0) { 4770Sstevel@tonic-gate uint64_t persVal; 4781618Srie 4790Sstevel@tonic-gate cielength = length; 4800Sstevel@tonic-gate cieid = id; 4811618Srie cieLflag = ciePflag = cieRflag = cieZflag = 0; 4820Sstevel@tonic-gate 4831618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIE), 4841618Srie EC_XWORD(shdr->sh_addr + off)); 4851618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH), 4861618Srie cielength, cieid); 4870Sstevel@tonic-gate 4880Sstevel@tonic-gate cieversion = data[off + ndx]; 4890Sstevel@tonic-gate ndx += 1; 4900Sstevel@tonic-gate cieaugstr = (char *)(&data[off + ndx]); 4910Sstevel@tonic-gate ndx += strlen(cieaugstr) + 1; 4921618Srie 4931618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS), 4941618Srie cieversion, cieaugstr); 4951618Srie 4960Sstevel@tonic-gate ciecalign = uleb_extract(&data[off], &ndx); 4970Sstevel@tonic-gate ciedalign = sleb_extract(&data[off], &ndx); 4980Sstevel@tonic-gate cieretaddr = data[off + ndx]; 4990Sstevel@tonic-gate ndx += 1; 5001618Srie 5011618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN), 5021618Srie EC_XWORD(ciecalign), EC_XWORD(ciedalign), 5031618Srie cieretaddr); 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate if (cieaugstr[0]) 5061618Srie dbg_print(0, MSG_ORIG(MSG_UNW_CIEAUXVAL)); 5071618Srie 5080Sstevel@tonic-gate for (cieaugndx = 0; cieaugstr[cieaugndx]; 5090Sstevel@tonic-gate cieaugndx++) { 5100Sstevel@tonic-gate uint_t val; 5111618Srie 5120Sstevel@tonic-gate switch (cieaugstr[cieaugndx]) { 5130Sstevel@tonic-gate case 'z': 5140Sstevel@tonic-gate val = uleb_extract(&data[off], 5150Sstevel@tonic-gate &ndx); 5161618Srie dbg_print(0, 5170Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXSIZE), 5180Sstevel@tonic-gate val); 5190Sstevel@tonic-gate cieZflag = 1; 5200Sstevel@tonic-gate break; 5210Sstevel@tonic-gate case 'P': 5220Sstevel@tonic-gate ciePflag = data[off + ndx]; 5230Sstevel@tonic-gate ndx += 1; 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate persVal = dwarf_ehe_extract( 5260Sstevel@tonic-gate &data[off], 5270Sstevel@tonic-gate &ndx, ciePflag, ehdr->e_ident, 5280Sstevel@tonic-gate shdr->sh_addr + off + ndx); 5291618Srie dbg_print(0, 5300Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXPERS), 5310Sstevel@tonic-gate ciePflag, 5321618Srie conv_dwarf_ehe(ciePflag), 5330Sstevel@tonic-gate EC_XWORD(persVal)); 5340Sstevel@tonic-gate break; 5350Sstevel@tonic-gate case 'R': 5360Sstevel@tonic-gate val = data[off + ndx]; 5370Sstevel@tonic-gate ndx += 1; 5381618Srie dbg_print(0, 5390Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXCENC), 5401618Srie val, conv_dwarf_ehe(val)); 5410Sstevel@tonic-gate cieRflag = val; 5420Sstevel@tonic-gate break; 5430Sstevel@tonic-gate case 'L': 5440Sstevel@tonic-gate val = data[off + ndx]; 5450Sstevel@tonic-gate ndx += 1; 5461618Srie dbg_print(0, 5470Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXLSDA), 5481618Srie val, conv_dwarf_ehe(val)); 5490Sstevel@tonic-gate cieLflag = val; 5500Sstevel@tonic-gate break; 5510Sstevel@tonic-gate default: 5521618Srie dbg_print(0, 5530Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXUNEC), 5540Sstevel@tonic-gate cieaugstr[cieaugndx]); 5550Sstevel@tonic-gate break; 5560Sstevel@tonic-gate } 5570Sstevel@tonic-gate } 5581618Srie if ((cielength + 4) > ndx) 5591618Srie unwindtbl(&ndx, cielength, data, off, 5601618Srie MSG_ORIG(MSG_UNW_CIECFI), 5611618Srie MSG_ORIG(MSG_UNW_CIEPRE), 5621618Srie MSG_UNW_CIEPRE_SIZE); 5630Sstevel@tonic-gate off += cielength + 4; 5641618Srie 5650Sstevel@tonic-gate } else { 5660Sstevel@tonic-gate uint_t fdelength = length; 5670Sstevel@tonic-gate int fdecieptr = id; 5680Sstevel@tonic-gate uint64_t fdeinitloc, fdeaddrrange; 5690Sstevel@tonic-gate 5701618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FDE), 5711618Srie EC_XWORD(shdr->sh_addr + off)); 5721618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH), 5730Sstevel@tonic-gate fdelength, fdecieptr); 5741618Srie 5750Sstevel@tonic-gate fdeinitloc = dwarf_ehe_extract(&data[off], 5760Sstevel@tonic-gate &ndx, cieRflag, ehdr->e_ident, 5770Sstevel@tonic-gate shdr->sh_addr + off + ndx); 5780Sstevel@tonic-gate fdeaddrrange = dwarf_ehe_extract(&data[off], 5790Sstevel@tonic-gate &ndx, (cieRflag & ~DW_EH_PE_pcrel), 5800Sstevel@tonic-gate ehdr->e_ident, 5810Sstevel@tonic-gate shdr->sh_addr + off + ndx); 5821618Srie 5831618Srie dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC), 5841618Srie EC_XWORD(fdeinitloc), 5851618Srie EC_XWORD(fdeaddrrange)); 5861618Srie 5870Sstevel@tonic-gate if (cieaugstr[0]) 5881618Srie dbg_print(0, 5891618Srie MSG_ORIG(MSG_UNW_FDEAUXVAL)); 5900Sstevel@tonic-gate if (cieZflag) { 5910Sstevel@tonic-gate uint64_t val; 5920Sstevel@tonic-gate val = uleb_extract(&data[off], &ndx); 5931618Srie dbg_print(0, 5941618Srie MSG_ORIG(MSG_UNW_FDEAUXSIZE), 5951618Srie EC_XWORD(val)); 5960Sstevel@tonic-gate if (val & cieLflag) { 5970Sstevel@tonic-gate fdeinitloc = dwarf_ehe_extract( 5980Sstevel@tonic-gate &data[off], &ndx, cieLflag, 5990Sstevel@tonic-gate ehdr->e_ident, 6000Sstevel@tonic-gate shdr->sh_addr + off + ndx); 6011618Srie dbg_print(0, 6020Sstevel@tonic-gate MSG_ORIG(MSG_UNW_FDEAUXLSDA), 6031618Srie EC_XWORD(val)); 6040Sstevel@tonic-gate } 6050Sstevel@tonic-gate } 6061618Srie if ((fdelength + 4) > ndx) 6071618Srie unwindtbl(&ndx, fdelength, data, off, 6081618Srie MSG_ORIG(MSG_UNW_FDECFI), 6091618Srie MSG_ORIG(MSG_UNW_FDEPRE), 6101618Srie MSG_UNW_FDEPRE_SIZE); 6110Sstevel@tonic-gate off += fdelength + 4; 6120Sstevel@tonic-gate } 6130Sstevel@tonic-gate } 6140Sstevel@tonic-gate } 6150Sstevel@tonic-gate } 6160Sstevel@tonic-gate 6170Sstevel@tonic-gate /* 6180Sstevel@tonic-gate * Print the hardware/software capabilities. For executables and shared objects 6190Sstevel@tonic-gate * this should be accompanied with a program header. 6200Sstevel@tonic-gate */ 6210Sstevel@tonic-gate static void 6221618Srie cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, 6231618Srie Elf *elf) 6240Sstevel@tonic-gate { 6251618Srie Word cnt; 6263466Srie Shdr *cshdr = 0; 6273466Srie Cache *ccache; 6281618Srie Off cphdr_off = 0; 6291618Srie Xword cphdr_sz; 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate /* 6320Sstevel@tonic-gate * Determine if a hardware/software capabilities header exists. 6330Sstevel@tonic-gate */ 6341618Srie if (phnum) { 6351618Srie Phdr *phdr; 6360Sstevel@tonic-gate 6371618Srie if ((phdr = elf_getphdr(elf)) == NULL) { 6380Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 6390Sstevel@tonic-gate return; 6400Sstevel@tonic-gate } 6410Sstevel@tonic-gate 6421618Srie for (cnt = 0; cnt < phnum; phdr++, cnt++) { 6431618Srie if (phdr->p_type == PT_SUNWCAP) { 6441618Srie cphdr_off = phdr->p_offset; 6451618Srie cphdr_sz = phdr->p_filesz; 6461618Srie break; 6471618Srie } 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate } 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate /* 6520Sstevel@tonic-gate * Determine if a hardware/software capabilities section exists. 6530Sstevel@tonic-gate */ 6540Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 6551618Srie Cache *_cache = &cache[cnt]; 6561618Srie Shdr *shdr = _cache->c_shdr; 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate if (shdr->sh_type != SHT_SUNW_cap) 6590Sstevel@tonic-gate continue; 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate if (cphdr_off && ((cphdr_off < shdr->sh_offset) || 6620Sstevel@tonic-gate (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size))) 6630Sstevel@tonic-gate continue; 6640Sstevel@tonic-gate 6653466Srie if (_cache->c_data == NULL) 6663466Srie continue; 6673466Srie 6680Sstevel@tonic-gate ccache = _cache; 6690Sstevel@tonic-gate cshdr = shdr; 6700Sstevel@tonic-gate break; 6710Sstevel@tonic-gate } 6720Sstevel@tonic-gate 6730Sstevel@tonic-gate if ((cshdr == 0) && (cphdr_off == 0)) 6740Sstevel@tonic-gate return; 6750Sstevel@tonic-gate 6763466Srie if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) { 6773466Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 6783466Srie file, ccache->c_name); 6793466Srie return; 6803466Srie } 6813466Srie 6820Sstevel@tonic-gate /* 6830Sstevel@tonic-gate * Print the hardware/software capabilities section. 6840Sstevel@tonic-gate */ 6850Sstevel@tonic-gate if (cshdr) { 6861618Srie Word ndx, capn; 6873492Sab196087 Cap *cap = (Cap *)ccache->c_data->d_buf; 6880Sstevel@tonic-gate 6891618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 6901618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name); 6910Sstevel@tonic-gate 6921618Srie Elf_cap_title(0); 6931618Srie 6941618Srie capn = (Word)(cshdr->sh_size / cshdr->sh_entsize); 6950Sstevel@tonic-gate 6961618Srie for (ndx = 0; ndx < capn; cap++, ndx++) { 6971618Srie if (cap->c_tag != CA_SUNW_NULL) 6981618Srie Elf_cap_entry(0, cap, ndx, ehdr->e_machine); 6990Sstevel@tonic-gate } 7000Sstevel@tonic-gate } else 7010Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file); 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate /* 7040Sstevel@tonic-gate * If this object is an executable or shared object, then the 7050Sstevel@tonic-gate * hardware/software capabilities section should have an accompanying 7060Sstevel@tonic-gate * program header. 7070Sstevel@tonic-gate */ 7080Sstevel@tonic-gate if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) { 7090Sstevel@tonic-gate if (cphdr_off == 0) 7100Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2), 7110Sstevel@tonic-gate file, ccache->c_name); 7120Sstevel@tonic-gate else if ((cphdr_off != cshdr->sh_offset) || 7130Sstevel@tonic-gate (cphdr_sz != cshdr->sh_size)) 7140Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3), 7150Sstevel@tonic-gate file, ccache->c_name); 7160Sstevel@tonic-gate } 7170Sstevel@tonic-gate } 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate /* 7200Sstevel@tonic-gate * Print the interpretor. 7210Sstevel@tonic-gate */ 7220Sstevel@tonic-gate static void 7231618Srie interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf) 7240Sstevel@tonic-gate { 7251618Srie Word cnt; 7261618Srie Shdr *ishdr = 0; 7271618Srie Cache *icache; 7281618Srie Off iphdr_off = 0; 7291618Srie Xword iphdr_fsz; 7300Sstevel@tonic-gate 7310Sstevel@tonic-gate /* 7320Sstevel@tonic-gate * Determine if an interp header exists. 7330Sstevel@tonic-gate */ 7341618Srie if (phnum) { 7351618Srie Phdr *phdr; 7360Sstevel@tonic-gate 7371618Srie if ((phdr = getphdr(phnum, PT_INTERP, file, elf)) != 0) { 7381618Srie iphdr_off = phdr->p_offset; 7391618Srie iphdr_fsz = phdr->p_filesz; 7400Sstevel@tonic-gate } 7410Sstevel@tonic-gate } 7420Sstevel@tonic-gate 7430Sstevel@tonic-gate if (iphdr_off == 0) 7440Sstevel@tonic-gate return; 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate /* 7470Sstevel@tonic-gate * Determine if an interp section exists. 7480Sstevel@tonic-gate */ 7490Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 7501618Srie Cache *_cache = &cache[cnt]; 7511618Srie Shdr *shdr = _cache->c_shdr; 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate /* 7540Sstevel@tonic-gate * Scan sections to find a section which contains the PT_INTERP 7550Sstevel@tonic-gate * string. The target section can't be in a NOBITS section. 7560Sstevel@tonic-gate */ 7570Sstevel@tonic-gate if ((shdr->sh_type == SHT_NOBITS) || 7580Sstevel@tonic-gate (iphdr_off < shdr->sh_offset) || 7591618Srie (iphdr_off + iphdr_fsz) > (shdr->sh_offset + shdr->sh_size)) 7600Sstevel@tonic-gate continue; 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate icache = _cache; 7630Sstevel@tonic-gate ishdr = shdr; 7640Sstevel@tonic-gate break; 7650Sstevel@tonic-gate } 7660Sstevel@tonic-gate 7670Sstevel@tonic-gate /* 7680Sstevel@tonic-gate * Print the interpreter string based on the offset defined in the 7690Sstevel@tonic-gate * program header, as this is the offset used by the kernel. 7700Sstevel@tonic-gate */ 7713466Srie if (ishdr && icache->c_data) { 7721618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 7731618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name); 7741618Srie dbg_print(0, MSG_ORIG(MSG_FMT_INDENT), 7750Sstevel@tonic-gate (char *)icache->c_data->d_buf + 7760Sstevel@tonic-gate (iphdr_off - ishdr->sh_offset)); 7770Sstevel@tonic-gate } else 7780Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file); 7790Sstevel@tonic-gate 7800Sstevel@tonic-gate /* 7810Sstevel@tonic-gate * If there are any inconsistences between the program header and 7820Sstevel@tonic-gate * section information, flag them. 7830Sstevel@tonic-gate */ 7840Sstevel@tonic-gate if (ishdr && ((iphdr_off != ishdr->sh_offset) || 7851618Srie (iphdr_fsz != ishdr->sh_size))) { 7860Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file, 7870Sstevel@tonic-gate icache->c_name); 7880Sstevel@tonic-gate } 7890Sstevel@tonic-gate } 7900Sstevel@tonic-gate 7910Sstevel@tonic-gate /* 7920Sstevel@tonic-gate * Print the syminfo section. 7930Sstevel@tonic-gate */ 7940Sstevel@tonic-gate static void 7951618Srie syminfo(Cache *cache, Word shnum, const char *file) 7960Sstevel@tonic-gate { 7971618Srie Shdr *infoshdr; 7981618Srie Syminfo *info; 7991618Srie Sym *syms; 8001618Srie Dyn *dyns; 8011618Srie Word infonum, cnt, ndx, symnum; 8021618Srie Cache *infocache = 0, *symsec, *strsec; 8030Sstevel@tonic-gate 8040Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 8051618Srie if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) { 8061618Srie infocache = &cache[cnt]; 8070Sstevel@tonic-gate break; 8080Sstevel@tonic-gate } 8090Sstevel@tonic-gate } 8101618Srie if (infocache == 0) 8110Sstevel@tonic-gate return; 8120Sstevel@tonic-gate 8131618Srie infoshdr = infocache->c_shdr; 8141618Srie if ((infoshdr->sh_entsize == 0) || (infoshdr->sh_size == 0)) { 8150Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 8161618Srie file, infocache->c_name); 8170Sstevel@tonic-gate return; 8180Sstevel@tonic-gate } 8193466Srie if (infocache->c_data == NULL) 8203466Srie return; 8213466Srie 8221618Srie infonum = (Word)(infoshdr->sh_size / infoshdr->sh_entsize); 8231618Srie info = (Syminfo *)infocache->c_data->d_buf; 8240Sstevel@tonic-gate 8250Sstevel@tonic-gate /* 8260Sstevel@tonic-gate * Get the data buffer of the associated dynamic section. 8270Sstevel@tonic-gate */ 8281618Srie if ((infoshdr->sh_info == 0) || (infoshdr->sh_info >= shnum)) { 8290Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 8301618Srie file, infocache->c_name, EC_WORD(infoshdr->sh_info)); 8310Sstevel@tonic-gate return; 8320Sstevel@tonic-gate } 8333466Srie if (cache[infoshdr->sh_info].c_data == NULL) 8343466Srie return; 8353466Srie 8361618Srie dyns = cache[infoshdr->sh_info].c_data->d_buf; 8371618Srie if (dyns == 0) { 8380Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 8391618Srie file, cache[infoshdr->sh_info].c_name); 8400Sstevel@tonic-gate return; 8410Sstevel@tonic-gate } 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate /* 8441618Srie * Get the data buffer for the associated symbol table and string table. 8450Sstevel@tonic-gate */ 8461618Srie if (stringtbl(cache, 1, cnt, shnum, file, 8471618Srie &symnum, &symsec, &strsec) == 0) 8480Sstevel@tonic-gate return; 8490Sstevel@tonic-gate 8501618Srie syms = symsec->c_data->d_buf; 8510Sstevel@tonic-gate 8521618Srie /* 8531618Srie * Loop through the syminfo entries. 8541618Srie */ 8551618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 8561618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMINFO), infocache->c_name); 8571618Srie Elf_syminfo_title(0); 8580Sstevel@tonic-gate 8591618Srie for (ndx = 1, info++; ndx < infonum; ndx++, info++) { 8601618Srie Sym *sym; 8611618Srie const char *needed = 0, *name; 8621618Srie 8631618Srie if ((info->si_flags == 0) && (info->si_boundto == 0)) 8640Sstevel@tonic-gate continue; 8650Sstevel@tonic-gate 8661618Srie sym = &syms[ndx]; 8671618Srie name = string(infocache, ndx, strsec, file, sym->st_name); 8680Sstevel@tonic-gate 8691618Srie if (info->si_boundto < SYMINFO_BT_LOWRESERVE) { 8701618Srie Dyn *dyn = &dyns[info->si_boundto]; 8711618Srie 8721618Srie needed = string(infocache, info->si_boundto, 8731618Srie strsec, file, dyn->d_un.d_val); 8740Sstevel@tonic-gate } 8751618Srie Elf_syminfo_entry(0, ndx, info, name, needed); 8760Sstevel@tonic-gate } 8770Sstevel@tonic-gate } 8780Sstevel@tonic-gate 8790Sstevel@tonic-gate /* 8800Sstevel@tonic-gate * Print version definition section entries. 8810Sstevel@tonic-gate */ 8820Sstevel@tonic-gate static void 8831618Srie version_def(Verdef *vdf, Word shnum, Cache *vcache, Cache *scache, 8840Sstevel@tonic-gate const char *file) 8850Sstevel@tonic-gate { 8861618Srie Word cnt; 8871618Srie char index[MAXNDXSIZE]; 8880Sstevel@tonic-gate 8891618Srie Elf_ver_def_title(0); 8900Sstevel@tonic-gate 8910Sstevel@tonic-gate for (cnt = 1; cnt <= shnum; cnt++, 8921618Srie vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) { 8930Sstevel@tonic-gate const char *name, *dep; 8941618Srie Half vcnt = vdf->vd_cnt - 1; 8951618Srie Half ndx = vdf->vd_ndx; 8961618Srie Verdaux *vdap = (Verdaux *)((uintptr_t)vdf + 8971618Srie vdf->vd_aux); 8980Sstevel@tonic-gate 8990Sstevel@tonic-gate /* 9000Sstevel@tonic-gate * Obtain the name and first dependency (if any). 9010Sstevel@tonic-gate */ 9020Sstevel@tonic-gate name = string(vcache, cnt, scache, file, vdap->vda_name); 9031618Srie vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 9040Sstevel@tonic-gate if (vcnt) 9050Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, vdap->vda_name); 9060Sstevel@tonic-gate else 9070Sstevel@tonic-gate dep = MSG_ORIG(MSG_STR_EMPTY); 9080Sstevel@tonic-gate 9090Sstevel@tonic-gate (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX), 9100Sstevel@tonic-gate EC_XWORD(ndx)); 9111618Srie Elf_ver_line_1(0, index, name, dep, 9121618Srie conv_ver_flags(vdf->vd_flags)); 9130Sstevel@tonic-gate 9140Sstevel@tonic-gate /* 9150Sstevel@tonic-gate * Print any additional dependencies. 9160Sstevel@tonic-gate */ 9170Sstevel@tonic-gate if (vcnt) { 9181618Srie vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 9190Sstevel@tonic-gate for (vcnt--; vcnt; vcnt--, 9201618Srie vdap = (Verdaux *)((uintptr_t)vdap + 9210Sstevel@tonic-gate vdap->vda_next)) { 9220Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, 9230Sstevel@tonic-gate vdap->vda_name); 9241618Srie Elf_ver_line_2(0, MSG_ORIG(MSG_STR_EMPTY), dep); 9250Sstevel@tonic-gate } 9260Sstevel@tonic-gate } 9270Sstevel@tonic-gate } 9280Sstevel@tonic-gate } 9290Sstevel@tonic-gate 9300Sstevel@tonic-gate /* 9310Sstevel@tonic-gate * Print a version needed section entries. 9320Sstevel@tonic-gate */ 9330Sstevel@tonic-gate static void 9341618Srie version_need(Verneed *vnd, Word shnum, Cache *vcache, Cache *scache, 9350Sstevel@tonic-gate const char *file) 9360Sstevel@tonic-gate { 9371618Srie Word cnt; 9380Sstevel@tonic-gate 9391618Srie Elf_ver_need_title(0); 9400Sstevel@tonic-gate 9410Sstevel@tonic-gate for (cnt = 1; cnt <= shnum; cnt++, 9421618Srie vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 9430Sstevel@tonic-gate const char *name, *dep; 9441618Srie Half vcnt = vnd->vn_cnt; 9451618Srie Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + 9461618Srie vnd->vn_aux); 9470Sstevel@tonic-gate 9480Sstevel@tonic-gate /* 9490Sstevel@tonic-gate * Obtain the name of the needed file and the version name 9500Sstevel@tonic-gate * within it that we're dependent on. Note that the count 9510Sstevel@tonic-gate * should be at least one, otherwise this is a pretty bogus 9520Sstevel@tonic-gate * entry. 9530Sstevel@tonic-gate */ 9540Sstevel@tonic-gate name = string(vcache, cnt, scache, file, vnd->vn_file); 9550Sstevel@tonic-gate if (vcnt) 9560Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, vnap->vna_name); 9570Sstevel@tonic-gate else 9580Sstevel@tonic-gate dep = MSG_INTL(MSG_STR_NULL); 9590Sstevel@tonic-gate 9601618Srie Elf_ver_line_1(0, MSG_ORIG(MSG_STR_EMPTY), name, dep, 9611618Srie conv_ver_flags(vnap->vna_flags)); 9620Sstevel@tonic-gate 9630Sstevel@tonic-gate /* 9640Sstevel@tonic-gate * Print any additional version dependencies. 9650Sstevel@tonic-gate */ 9660Sstevel@tonic-gate if (vcnt) { 9671618Srie vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next); 9680Sstevel@tonic-gate for (vcnt--; vcnt; vcnt--, 9691618Srie vnap = (Vernaux *)((uintptr_t)vnap + 9700Sstevel@tonic-gate vnap->vna_next)) { 9710Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, 9720Sstevel@tonic-gate vnap->vna_name); 9731618Srie Elf_ver_line_3(0, MSG_ORIG(MSG_STR_EMPTY), dep, 9741618Srie conv_ver_flags(vnap->vna_flags)); 9750Sstevel@tonic-gate } 9760Sstevel@tonic-gate } 9770Sstevel@tonic-gate } 9780Sstevel@tonic-gate } 9790Sstevel@tonic-gate 9800Sstevel@tonic-gate /* 9811618Srie * Search for any version sections - the Versym output is possibly used by the 9821618Srie * symbols() printing. If VERSYM is specified - then display the version 9831618Srie * information. 9840Sstevel@tonic-gate */ 9850Sstevel@tonic-gate static Cache * 9861618Srie versions(Cache *cache, Word shnum, const char *file, uint_t flags) 9870Sstevel@tonic-gate { 9880Sstevel@tonic-gate GElf_Word cnt; 9890Sstevel@tonic-gate Cache *versymcache = 0; 9900Sstevel@tonic-gate 9910Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 9921618Srie void *ver; 9930Sstevel@tonic-gate uint_t num; 9941618Srie Cache *_cache = &cache[cnt]; 9951618Srie Shdr *shdr = _cache->c_shdr; 9961618Srie const char *secname = _cache->c_name; 9970Sstevel@tonic-gate 9980Sstevel@tonic-gate /* 9990Sstevel@tonic-gate * If this is the version symbol table simply record its 10000Sstevel@tonic-gate * data address for possible use in later symbol processing. 10010Sstevel@tonic-gate */ 10020Sstevel@tonic-gate if (shdr->sh_type == SHT_SUNW_versym) { 10030Sstevel@tonic-gate versymcache = _cache; 10040Sstevel@tonic-gate continue; 10050Sstevel@tonic-gate } 10060Sstevel@tonic-gate 10070Sstevel@tonic-gate if ((flags & FLG_VERSIONS) == 0) 10080Sstevel@tonic-gate continue; 10090Sstevel@tonic-gate 10100Sstevel@tonic-gate if ((shdr->sh_type != SHT_SUNW_verdef) && 10110Sstevel@tonic-gate (shdr->sh_type != SHT_SUNW_verneed)) 10120Sstevel@tonic-gate continue; 10130Sstevel@tonic-gate 10140Sstevel@tonic-gate /* 10150Sstevel@tonic-gate * Determine the version section data and number. 10160Sstevel@tonic-gate */ 10173466Srie if ((_cache->c_data == NULL) || 10183466Srie ((ver = (void *)_cache->c_data->d_buf) == NULL)) { 10190Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 10201618Srie file, secname); 10210Sstevel@tonic-gate continue; 10220Sstevel@tonic-gate } 10230Sstevel@tonic-gate if ((num = shdr->sh_info) == 0) { 10240Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 10251618Srie file, secname, EC_WORD(shdr->sh_info)); 10260Sstevel@tonic-gate continue; 10270Sstevel@tonic-gate } 10280Sstevel@tonic-gate 10290Sstevel@tonic-gate /* 10300Sstevel@tonic-gate * Get the data buffer for the associated string table. 10310Sstevel@tonic-gate */ 10320Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 10330Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 10341618Srie file, secname, EC_WORD(shdr->sh_link)); 10350Sstevel@tonic-gate continue; 10360Sstevel@tonic-gate } 10370Sstevel@tonic-gate 10381618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 10390Sstevel@tonic-gate if (shdr->sh_type == SHT_SUNW_verdef) { 10401618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERDEF), secname); 10411618Srie version_def((Verdef *)ver, num, _cache, 10420Sstevel@tonic-gate &cache[shdr->sh_link], file); 10430Sstevel@tonic-gate } else if (shdr->sh_type == SHT_SUNW_verneed) { 10441618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERNEED), secname); 10451618Srie version_need((Verneed *)ver, num, _cache, 10460Sstevel@tonic-gate &cache[shdr->sh_link], file); 10470Sstevel@tonic-gate } 10480Sstevel@tonic-gate } 10490Sstevel@tonic-gate return (versymcache); 10500Sstevel@tonic-gate } 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate /* 10533492Sab196087 * SYMTBL_STATE is used to maintain information about a single symbol 10543492Sab196087 * table section, for use by the routines that display symbol information. 10553492Sab196087 */ 10563492Sab196087 typedef struct { 10573492Sab196087 const char *file; /* Name of file */ 10583492Sab196087 Ehdr *ehdr; /* ELF header for file */ 10593492Sab196087 Cache *cache; /* Cache of all section headers */ 10603492Sab196087 Word shnum; /* # of sections in cache */ 10613492Sab196087 Cache *seccache; /* Cache of symbol table section hdr */ 10623492Sab196087 Word secndx; /* Index of symbol table section hdr */ 10633492Sab196087 const char *secname; /* Name of section */ 10643492Sab196087 uint_t flags; /* Command line option flags */ 10653492Sab196087 struct { /* Extended section index data */ 10663492Sab196087 int checked; /* TRUE if already checked for shxndx */ 10673492Sab196087 Word *data; /* NULL, or extended section index */ 10683492Sab196087 /* used for symbol table entries */ 10693492Sab196087 uint_t n; /* # items in shxndx.data */ 10703492Sab196087 } shxndx; 10713492Sab196087 Versym *versym; /* NULL, or versym array for symtbl */ 10723492Sab196087 Sym *sym; /* Array of symbols */ 10733492Sab196087 Word symn; /* # of symbols */ 10743492Sab196087 } SYMTBL_STATE; 10753492Sab196087 10763492Sab196087 /* 10773492Sab196087 * Initialize a symbol table state structure 10783492Sab196087 * 10793492Sab196087 * entry: 10803492Sab196087 * state - State structure to be initialized 10813492Sab196087 * cache - Cache of all section headers 10823492Sab196087 * shnum - # of sections in cache 10833492Sab196087 * secndx - Index of symbol table section 10843492Sab196087 * ehdr - ELF header for file 10853492Sab196087 * versymcache - NULL, or cache of versym section 10863492Sab196087 * file - Name of file 10873492Sab196087 * flags - Command line option flags 10881618Srie */ 10891618Srie static int 10903492Sab196087 init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx, 10913492Sab196087 Ehdr *ehdr, Cache *versymcache, const char *file, uint_t flags) 10923492Sab196087 { 10933492Sab196087 Shdr *shdr; 10943492Sab196087 10953492Sab196087 state->file = file; 10963492Sab196087 state->ehdr = ehdr; 10973492Sab196087 state->cache = cache; 10983492Sab196087 state->shnum = shnum; 10993492Sab196087 state->seccache = &cache[secndx]; 11003492Sab196087 state->secndx = secndx; 11013492Sab196087 state->secname = state->seccache->c_name; 11023492Sab196087 state->flags = flags; 11033492Sab196087 state->shxndx.checked = 0; 11043492Sab196087 state->shxndx.data = NULL; 11053492Sab196087 state->shxndx.n = 0; 11063492Sab196087 11073492Sab196087 shdr = state->seccache->c_shdr; 11083492Sab196087 11093492Sab196087 /* 11103492Sab196087 * Check the symbol data and per-item size. 11113492Sab196087 */ 11123492Sab196087 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 11133492Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 11143492Sab196087 file, state->secname); 11153492Sab196087 return (0); 11163492Sab196087 } 11173492Sab196087 if (state->seccache->c_data == NULL) 11183492Sab196087 return (0); 11193492Sab196087 11203492Sab196087 /* LINTED */ 11213492Sab196087 state->symn = (Word)(shdr->sh_size / shdr->sh_entsize); 11223492Sab196087 state->sym = (Sym *)state->seccache->c_data->d_buf; 11233492Sab196087 11243492Sab196087 /* 11253492Sab196087 * Check associated string table section. 11263492Sab196087 */ 11273492Sab196087 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 11283492Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 11293492Sab196087 file, state->secname, EC_WORD(shdr->sh_link)); 11303492Sab196087 return (0); 11313492Sab196087 } 11323492Sab196087 11333492Sab196087 /* 11343492Sab196087 * Determine if there is a associated Versym section 11353492Sab196087 * with this Symbol Table. 11363492Sab196087 */ 11373492Sab196087 if (versymcache && (versymcache->c_shdr->sh_link == state->secndx) && 11383492Sab196087 versymcache->c_data) 11393492Sab196087 state->versym = versymcache->c_data->d_buf; 11403492Sab196087 else 11413492Sab196087 state->versym = NULL; 11423492Sab196087 11433492Sab196087 11443492Sab196087 return (1); 11453492Sab196087 } 11463492Sab196087 11473492Sab196087 /* 11483492Sab196087 * Determine the extended section index used for symbol tables entries. 11493492Sab196087 */ 11503492Sab196087 static void 11513492Sab196087 symbols_getxindex(SYMTBL_STATE * state) 11521618Srie { 11531618Srie uint_t symn; 11541618Srie Word symcnt; 11551618Srie 11563492Sab196087 state->shxndx.checked = 1; /* Note that we've been called */ 11573492Sab196087 for (symcnt = 1; symcnt < state->shnum; symcnt++) { 11583492Sab196087 Cache *_cache = &state->cache[symcnt]; 11591618Srie Shdr *shdr = _cache->c_shdr; 11601618Srie 11611618Srie if ((shdr->sh_type != SHT_SYMTAB_SHNDX) || 11623492Sab196087 (shdr->sh_link != state->secndx)) 11631618Srie continue; 11641618Srie 11651618Srie if ((shdr->sh_entsize) && 11661618Srie /* LINTED */ 11671618Srie ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0)) 11681618Srie continue; 11691618Srie 11703466Srie if (_cache->c_data == NULL) 11713466Srie continue; 11723466Srie 11733492Sab196087 state->shxndx.data = _cache->c_data->d_buf; 11743492Sab196087 state->shxndx.n = symn; 11753492Sab196087 return; 11761618Srie } 11771618Srie } 11781618Srie 11791618Srie /* 11803492Sab196087 * Produce a line of output for the given symbol 11813492Sab196087 * 11823492Sab196087 * entry: 11833492Sab196087 * symndx - Index of symbol within the table 11843492Sab196087 * symndx_disp - Index to display. This may not be the same 11853492Sab196087 * as symndx if the display is relative to the logical 11863492Sab196087 * combination of the SUNW_ldynsym/dynsym tables. 11873492Sab196087 * sym - Symbol to display 11883492Sab196087 * state - Symbol table state 11890Sstevel@tonic-gate */ 11903492Sab196087 static void 11913492Sab196087 output_symbol(SYMTBL_STATE *state, Word symndx, Word disp_symndx, Sym *sym) 11920Sstevel@tonic-gate { 11933118Sab196087 /* 11943118Sab196087 * Symbol types for which we check that the specified 11953118Sab196087 * address/size land inside the target section. 11963118Sab196087 */ 11973492Sab196087 static const int addr_symtype[STT_NUM] = { 11983118Sab196087 0, /* STT_NOTYPE */ 11993118Sab196087 1, /* STT_OBJECT */ 12003118Sab196087 1, /* STT_FUNC */ 12013118Sab196087 0, /* STT_SECTION */ 12023118Sab196087 0, /* STT_FILE */ 12033118Sab196087 1, /* STT_COMMON */ 12043118Sab196087 0, /* STT_TLS */ 12053118Sab196087 }; 12063118Sab196087 #if STT_NUM != (STT_TLS + 1) 12073492Sab196087 #error "STT_NUM has grown. Update addr_symtype[]" 12083118Sab196087 #endif 12093118Sab196087 12103492Sab196087 char index[MAXNDXSIZE], *sec; 12113492Sab196087 const char *symname; 12123492Sab196087 int verndx; 12133492Sab196087 uchar_t type; 12143492Sab196087 Shdr *tshdr; 12153492Sab196087 Word shndx; 12163492Sab196087 12173492Sab196087 /* Ensure symbol index is in range */ 12183492Sab196087 if (symndx >= state->symn) { 12193492Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORTNDX), 12203492Sab196087 state->file, state->secname, EC_WORD(symndx)); 12213492Sab196087 return; 12223492Sab196087 } 12233492Sab196087 12243492Sab196087 /* 12253492Sab196087 * If we are using extended symbol indexes, find the 12263492Sab196087 * corresponding SHN_SYMTAB_SHNDX table. 12273492Sab196087 */ 12283492Sab196087 if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0)) 12293492Sab196087 symbols_getxindex(state); 12303492Sab196087 12313492Sab196087 /* LINTED */ 12323492Sab196087 symname = string(state->seccache, symndx, 12333492Sab196087 &state->cache[state->seccache->c_shdr->sh_link], state->file, 12343492Sab196087 sym->st_name); 12353492Sab196087 12363492Sab196087 tshdr = 0; 12373492Sab196087 sec = NULL; 12383492Sab196087 12393492Sab196087 if ((state->ehdr->e_type == ET_CORE)) 12403492Sab196087 sec = (char *)MSG_INTL(MSG_STR_UNKNOWN); 12413492Sab196087 else if ((sym->st_shndx < SHN_LORESERVE) && 12423492Sab196087 (sym->st_shndx < state->shnum)) { 12433492Sab196087 shndx = sym->st_shndx; 12443492Sab196087 tshdr = state->cache[shndx].c_shdr; 12453492Sab196087 sec = state->cache[shndx].c_name; 12463492Sab196087 } else if (sym->st_shndx == SHN_XINDEX) { 12473492Sab196087 if (state->shxndx.data) { 12483492Sab196087 Word _shxndx; 12493492Sab196087 12503492Sab196087 if (symndx > state->shxndx.n) { 12513492Sab196087 (void) fprintf(stderr, 12523492Sab196087 MSG_INTL(MSG_ERR_BADSYMXINDEX1), 12533492Sab196087 state->file, state->secname, EC_WORD(symndx)); 12543492Sab196087 } else if ((_shxndx = 12553492Sab196087 state->shxndx.data[symndx]) > state->shnum) { 12563492Sab196087 (void) fprintf(stderr, 12573492Sab196087 MSG_INTL(MSG_ERR_BADSYMXINDEX2), 12583492Sab196087 state->file, state->secname, EC_WORD(symndx), 12593492Sab196087 EC_WORD(_shxndx)); 12603492Sab196087 } else { 12613492Sab196087 shndx = _shxndx; 12623492Sab196087 tshdr = state->cache[shndx].c_shdr; 12633492Sab196087 sec = state->cache[shndx].c_name; 12643492Sab196087 } 12653492Sab196087 } else { 12663492Sab196087 (void) fprintf(stderr, 12673492Sab196087 MSG_INTL(MSG_ERR_BADSYMXINDEX3), 12683492Sab196087 state->file, state->secname, EC_WORD(symndx)); 12693492Sab196087 } 12703492Sab196087 } else if ((sym->st_shndx < SHN_LORESERVE) && 12713492Sab196087 (sym->st_shndx >= state->shnum)) { 12723492Sab196087 (void) fprintf(stderr, 12733492Sab196087 MSG_INTL(MSG_ERR_BADSYM5), state->file, 12743492Sab196087 state->secname, demangle(symname, state->flags), 12753492Sab196087 sym->st_shndx); 12763492Sab196087 } 12770Sstevel@tonic-gate 12783492Sab196087 /* 12793492Sab196087 * If versioning is available display the 12803492Sab196087 * version index. 12813492Sab196087 */ 12823492Sab196087 if (state->versym) 12833492Sab196087 verndx = (int)state->versym[symndx]; 12843492Sab196087 else 12853492Sab196087 verndx = 0; 12863492Sab196087 12873492Sab196087 /* 12883492Sab196087 * Error checking for TLS. 12893492Sab196087 */ 12903492Sab196087 type = ELF_ST_TYPE(sym->st_info); 12913492Sab196087 if (type == STT_TLS) { 12923492Sab196087 if (tshdr && 12933492Sab196087 (sym->st_shndx != SHN_UNDEF) && 12943492Sab196087 ((tshdr->sh_flags & SHF_TLS) == 0)) { 12953492Sab196087 (void) fprintf(stderr, 12963492Sab196087 MSG_INTL(MSG_ERR_BADSYM3), state->file, 12973492Sab196087 state->secname, demangle(symname, state->flags)); 12983492Sab196087 } 12993492Sab196087 } else if ((type != STT_SECTION) && sym->st_size && 13003492Sab196087 tshdr && (tshdr->sh_flags & SHF_TLS)) { 13013492Sab196087 (void) fprintf(stderr, 13023492Sab196087 MSG_INTL(MSG_ERR_BADSYM4), state->file, 13033492Sab196087 state->secname, demangle(symname, state->flags)); 13043492Sab196087 } 13053492Sab196087 13063492Sab196087 /* 13073492Sab196087 * If a symbol with non-zero size has a type that 13083492Sab196087 * specifies an address, then make sure the location 13093492Sab196087 * it references is actually contained within the 13103492Sab196087 * section. UNDEF symbols don't count in this case, 13113492Sab196087 * so we ignore them. 13123492Sab196087 * 13133492Sab196087 * The meaning of the st_value field in a symbol 13143492Sab196087 * depends on the type of object. For a relocatable 13153492Sab196087 * object, it is the offset within the section. 13163492Sab196087 * For sharable objects, it is the offset relative to 13173492Sab196087 * the base of the object, and for other types, it is 13183492Sab196087 * the virtual address. To get an offset within the 13193492Sab196087 * section for non-ET_REL files, we subtract the 13203492Sab196087 * base address of the section. 13213492Sab196087 */ 13223492Sab196087 if (addr_symtype[type] && (sym->st_size > 0) && 13233492Sab196087 (sym->st_shndx != SHN_UNDEF) && ((sym->st_shndx < SHN_LORESERVE) || 13243492Sab196087 (sym->st_shndx == SHN_XINDEX)) && (tshdr != NULL)) { 13253492Sab196087 Word v = sym->st_value; 13263492Sab196087 if (state->ehdr->e_type != ET_REL) 13273492Sab196087 v -= tshdr->sh_addr; 13283492Sab196087 if (((v + sym->st_size) > tshdr->sh_size)) { 13293492Sab196087 (void) fprintf(stderr, 13303492Sab196087 MSG_INTL(MSG_ERR_BADSYM6), state->file, 13313492Sab196087 state->secname, demangle(symname, state->flags), 13323492Sab196087 EC_WORD(shndx), EC_XWORD(tshdr->sh_size), 13333492Sab196087 EC_XWORD(sym->st_value), EC_XWORD(sym->st_size)); 13343492Sab196087 } 13353492Sab196087 } 13363492Sab196087 13373492Sab196087 (void) snprintf(index, MAXNDXSIZE, 13383492Sab196087 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(disp_symndx)); 13393492Sab196087 Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index, 13403492Sab196087 state->ehdr->e_machine, sym, verndx, sec, symname); 13413492Sab196087 } 13423492Sab196087 13433492Sab196087 /* 13443492Sab196087 * Search for and process any symbol tables. 13453492Sab196087 */ 13463492Sab196087 void 13473492Sab196087 symbols(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, 13483492Sab196087 Cache *versymcache, const char *file, uint_t flags) 13493492Sab196087 { 13503492Sab196087 SYMTBL_STATE state; 13513492Sab196087 Cache *_cache; 13523492Sab196087 Word secndx; 13533492Sab196087 13543492Sab196087 for (secndx = 1; secndx < shnum; secndx++) { 13553492Sab196087 Word symcnt; 13563492Sab196087 Shdr *shdr; 13573492Sab196087 13583492Sab196087 _cache = &cache[secndx]; 13593492Sab196087 shdr = _cache->c_shdr; 13600Sstevel@tonic-gate 13610Sstevel@tonic-gate if ((shdr->sh_type != SHT_SYMTAB) && 13622766Sab196087 (shdr->sh_type != SHT_DYNSYM) && 13632766Sab196087 (shdr->sh_type != SHT_SUNW_LDYNSYM)) 13640Sstevel@tonic-gate continue; 13653492Sab196087 if (name && strcmp(name, _cache->c_name)) 13663466Srie continue; 13673466Srie 13683492Sab196087 if (!init_symtbl_state(&state, cache, shnum, secndx, ehdr, 13693492Sab196087 versymcache, file, flags)) 13700Sstevel@tonic-gate continue; 13710Sstevel@tonic-gate /* 13720Sstevel@tonic-gate * Loop through the symbol tables entries. 13730Sstevel@tonic-gate */ 13741618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 13753492Sab196087 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), state.secname); 13761618Srie Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 13770Sstevel@tonic-gate 13783492Sab196087 for (symcnt = 0; symcnt < state.symn; symcnt++) 13793492Sab196087 output_symbol(&state, symcnt, symcnt, 13803492Sab196087 state.sym + symcnt); 13813492Sab196087 } 13823492Sab196087 } 13830Sstevel@tonic-gate 13843492Sab196087 /* 13853492Sab196087 * Search for and process any SHT_SUNW_symsort or SHT_SUNW_tlssort sections. 13863492Sab196087 * These sections are always associated with the .SUNW_ldynsym./.dynsym pair. 13873492Sab196087 */ 13883492Sab196087 static void 13893492Sab196087 sunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, 13903492Sab196087 Cache *versymcache, const char *file, uint_t flags) 13913492Sab196087 { 13923492Sab196087 SYMTBL_STATE ldynsym_state, dynsym_state; 13933492Sab196087 Cache *sortcache, *symcache; 13943492Sab196087 Shdr *sortshdr, *symshdr; 13953492Sab196087 Word sortsecndx, symsecndx; 13963492Sab196087 Word ldynsym_cnt; 13973492Sab196087 Word *ndx; 13983492Sab196087 Word ndxn; 13993492Sab196087 int output_cnt = 0; 14000Sstevel@tonic-gate 14013492Sab196087 for (sortsecndx = 1; sortsecndx < shnum; sortsecndx++) { 14020Sstevel@tonic-gate 14033492Sab196087 sortcache = &cache[sortsecndx]; 14043492Sab196087 sortshdr = sortcache->c_shdr; 14050Sstevel@tonic-gate 14063492Sab196087 if ((sortshdr->sh_type != SHT_SUNW_symsort) && 14073492Sab196087 (sortshdr->sh_type != SHT_SUNW_tlssort)) 14083492Sab196087 continue; 14093492Sab196087 if (name && strcmp(name, sortcache->c_name)) 14103492Sab196087 continue; 14110Sstevel@tonic-gate 14123492Sab196087 /* 14133492Sab196087 * If the section references a SUNW_ldynsym, then we 14143492Sab196087 * expect to see the associated .dynsym immediately 14153492Sab196087 * following. If it references a .dynsym, there is no 14163492Sab196087 * SUNW_ldynsym. If it is any other type, then we don't 14173492Sab196087 * know what to do with it. 14183492Sab196087 */ 14193492Sab196087 if ((sortshdr->sh_link == 0) || (sortshdr->sh_link >= shnum)) { 14203492Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 14213492Sab196087 file, sortcache->c_name, 14223492Sab196087 EC_WORD(sortshdr->sh_link)); 14233492Sab196087 continue; 14243492Sab196087 } 14253492Sab196087 symcache = &cache[sortshdr->sh_link]; 14263492Sab196087 symshdr = symcache->c_shdr; 14273492Sab196087 symsecndx = sortshdr->sh_link; 14283492Sab196087 ldynsym_cnt = 0; 14293492Sab196087 switch (symshdr->sh_type) { 14303492Sab196087 case SHT_SUNW_LDYNSYM: 14313492Sab196087 if (!init_symtbl_state(&ldynsym_state, cache, shnum, 14323492Sab196087 symsecndx, ehdr, versymcache, file, flags)) 14333492Sab196087 continue; 14343492Sab196087 ldynsym_cnt = ldynsym_state.symn; 14350Sstevel@tonic-gate /* 14363492Sab196087 * We know that the dynsym follows immediately 14373492Sab196087 * after the SUNW_ldynsym, and so, should be at 14383492Sab196087 * (sortshdr->sh_link + 1). However, elfdump is a 14393492Sab196087 * diagnostic tool, so we do the full paranoid 14403492Sab196087 * search instead. 14410Sstevel@tonic-gate */ 14423492Sab196087 for (symsecndx = 1; symsecndx < shnum; symsecndx++) { 14433492Sab196087 symcache = &cache[symsecndx]; 14443492Sab196087 symshdr = symcache->c_shdr; 14453492Sab196087 if (symshdr->sh_type == SHT_DYNSYM) 14463492Sab196087 break; 14473492Sab196087 } 14483492Sab196087 if (symsecndx >= shnum) { /* Dynsym not found! */ 14490Sstevel@tonic-gate (void) fprintf(stderr, 14503492Sab196087 MSG_INTL(MSG_ERR_NODYNSYM), 14513492Sab196087 file, sortcache->c_name); 14523492Sab196087 continue; 14530Sstevel@tonic-gate } 14543492Sab196087 /* Fallthrough to process associated dynsym */ 14553492Sab196087 /*FALLTHROUGH*/ 14563492Sab196087 case SHT_DYNSYM: 14573492Sab196087 if (!init_symtbl_state(&dynsym_state, cache, shnum, 14583492Sab196087 symsecndx, ehdr, versymcache, file, flags)) 14593492Sab196087 continue; 14603492Sab196087 break; 14613492Sab196087 default: 14623492Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADNDXSEC), 14633492Sab196087 file, sortcache->c_name, conv_sec_type( 14643492Sab196087 ehdr->e_machine, symshdr->sh_type, 0)); 14653492Sab196087 continue; 14663492Sab196087 } 14670Sstevel@tonic-gate 14683492Sab196087 /* 14693492Sab196087 * Output header 14703492Sab196087 */ 14713492Sab196087 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 14723492Sab196087 if (ldynsym_cnt > 0) { 14733492Sab196087 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT2), 14743492Sab196087 sortcache->c_name, ldynsym_state.secname, 14753492Sab196087 dynsym_state.secname); 14760Sstevel@tonic-gate /* 14773492Sab196087 * The data for .SUNW_ldynsym and dynsym sections 14783492Sab196087 * is supposed to be adjacent with SUNW_ldynsym coming 14793492Sab196087 * first. Check, and issue a warning if it isn't so. 14800Sstevel@tonic-gate */ 14813492Sab196087 if ((ldynsym_state.sym + ldynsym_state.symn) 14823492Sab196087 != dynsym_state.sym) 14833492Sab196087 (void) fprintf(stderr, 14843492Sab196087 MSG_INTL(MSG_ERR_LDYNNOTADJ), file, 14853492Sab196087 ldynsym_state.secname, 14863492Sab196087 dynsym_state.secname); 14873492Sab196087 } else { 14883492Sab196087 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT1), 14893492Sab196087 sortcache->c_name, dynsym_state.secname); 14903492Sab196087 } 14913492Sab196087 Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 14923492Sab196087 14933492Sab196087 /* If not first one, insert a line of whitespace */ 14943492Sab196087 if (output_cnt++ > 0) 14953492Sab196087 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 14963118Sab196087 14973492Sab196087 /* 14983492Sab196087 * SUNW_dynsymsort and SUNW_dyntlssort are arrays of 14993492Sab196087 * symbol indices. Iterate over the array entries, 15003492Sab196087 * dispaying the referenced symbols. 15013492Sab196087 */ 15023492Sab196087 ndxn = sortshdr->sh_size / sortshdr->sh_entsize; 15033492Sab196087 ndx = (Word *)sortcache->c_data->d_buf; 15043492Sab196087 for (; ndxn-- > 0; ndx++) { 15053492Sab196087 if (*ndx >= ldynsym_cnt) { 15063492Sab196087 Word sec_ndx = *ndx - ldynsym_cnt; 15073492Sab196087 15083492Sab196087 output_symbol(&dynsym_state, sec_ndx, 15093492Sab196087 *ndx, dynsym_state.sym + sec_ndx); 15103492Sab196087 } else { 15113492Sab196087 output_symbol(&ldynsym_state, *ndx, 15123492Sab196087 *ndx, ldynsym_state.sym + *ndx); 15130Sstevel@tonic-gate } 15140Sstevel@tonic-gate } 15150Sstevel@tonic-gate } 15160Sstevel@tonic-gate } 15170Sstevel@tonic-gate 15180Sstevel@tonic-gate /* 15190Sstevel@tonic-gate * Search for and process any relocation sections. 15200Sstevel@tonic-gate */ 15210Sstevel@tonic-gate static void 15221618Srie reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, const char *file, 15231618Srie uint_t flags) 15240Sstevel@tonic-gate { 15251618Srie Word cnt; 15260Sstevel@tonic-gate 15270Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 15281618Srie Word type, symnum; 15291618Srie Xword relndx, relnum, relsize; 15301618Srie void *rels; 15311618Srie Sym *syms; 15321618Srie Cache *symsec, *strsec; 15330Sstevel@tonic-gate Cache *_cache = &cache[cnt]; 15341618Srie Shdr *shdr = _cache->c_shdr; 15351618Srie char *relname = _cache->c_name; 15360Sstevel@tonic-gate 15370Sstevel@tonic-gate if (((type = shdr->sh_type) != SHT_RELA) && 15380Sstevel@tonic-gate (type != SHT_REL)) 15390Sstevel@tonic-gate continue; 15401618Srie if (name && strcmp(name, relname)) 15410Sstevel@tonic-gate continue; 15420Sstevel@tonic-gate 15430Sstevel@tonic-gate /* 15441618Srie * Decide entry size. 15450Sstevel@tonic-gate */ 15461618Srie if (((relsize = shdr->sh_entsize) == 0) || 15471618Srie (relsize > shdr->sh_size)) { 15480Sstevel@tonic-gate if (type == SHT_RELA) 15491618Srie relsize = sizeof (Rela); 15500Sstevel@tonic-gate else 15511618Srie relsize = sizeof (Rel); 15520Sstevel@tonic-gate } 15530Sstevel@tonic-gate 15540Sstevel@tonic-gate /* 15550Sstevel@tonic-gate * Determine the number of relocations available. 15560Sstevel@tonic-gate */ 15570Sstevel@tonic-gate if (shdr->sh_size == 0) { 15580Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 15591618Srie file, relname); 15600Sstevel@tonic-gate continue; 15610Sstevel@tonic-gate } 15623466Srie if (_cache->c_data == NULL) 15633466Srie continue; 15643466Srie 15651618Srie rels = _cache->c_data->d_buf; 15661618Srie relnum = shdr->sh_size / relsize; 15670Sstevel@tonic-gate 15680Sstevel@tonic-gate /* 15691618Srie * Get the data buffer for the associated symbol table and 15701618Srie * string table. 15710Sstevel@tonic-gate */ 15721618Srie if (stringtbl(cache, 1, cnt, shnum, file, 15731618Srie &symnum, &symsec, &strsec) == 0) 15740Sstevel@tonic-gate continue; 15751618Srie 15761618Srie syms = symsec->c_data->d_buf; 15770Sstevel@tonic-gate 15780Sstevel@tonic-gate /* 15790Sstevel@tonic-gate * Loop through the relocation entries. 15800Sstevel@tonic-gate */ 15811618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 15821618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name); 15831618Srie Elf_reloc_title(0, ELF_DBG_ELFDUMP, type); 15840Sstevel@tonic-gate 15851618Srie for (relndx = 0; relndx < relnum; relndx++, 15861618Srie rels = (void *)((char *)rels + relsize)) { 15870Sstevel@tonic-gate char section[BUFSIZ]; 15881618Srie const char *symname; 15891618Srie Word symndx, reltype; 15901618Srie Rela *rela; 15911618Srie Rel *rel; 15920Sstevel@tonic-gate 15930Sstevel@tonic-gate /* 15941618Srie * Unravel the relocation and determine the symbol with 15951618Srie * which this relocation is associated. 15960Sstevel@tonic-gate */ 15970Sstevel@tonic-gate if (type == SHT_RELA) { 15981618Srie rela = (Rela *)rels; 15991618Srie symndx = ELF_R_SYM(rela->r_info); 16001618Srie reltype = ELF_R_TYPE(rela->r_info); 16010Sstevel@tonic-gate } else { 16021618Srie rel = (Rel *)rels; 16031618Srie symndx = ELF_R_SYM(rel->r_info); 16041618Srie reltype = ELF_R_TYPE(rel->r_info); 16050Sstevel@tonic-gate } 16061618Srie 16071618Srie symname = relsymname(cache, _cache, strsec, symndx, 16081618Srie symnum, relndx, syms, section, BUFSIZ, file, 16091618Srie flags); 16101618Srie 16111618Srie /* 16121618Srie * A zero symbol index is only valid for a few 16131618Srie * relocations. 16141618Srie */ 16151618Srie if (symndx == 0) { 16161618Srie Half mach = ehdr->e_machine; 16171618Srie int badrel = 0; 16180Sstevel@tonic-gate 16191618Srie if ((mach == EM_SPARC) || 16201618Srie (mach == EM_SPARC32PLUS) || 16211618Srie (mach == EM_SPARCV9)) { 16221618Srie if ((reltype != R_SPARC_NONE) && 16231618Srie (reltype != R_SPARC_REGISTER) && 16241618Srie (reltype != R_SPARC_RELATIVE)) 16251618Srie badrel++; 16261618Srie } else if (mach == EM_386) { 16271618Srie if ((reltype != R_386_NONE) && 16281618Srie (reltype != R_386_RELATIVE)) 16291618Srie badrel++; 16301618Srie } else if (mach == EM_AMD64) { 16311618Srie if ((reltype != R_AMD64_NONE) && 16321618Srie (reltype != R_AMD64_RELATIVE)) 16331618Srie badrel++; 16341618Srie } 16351618Srie 16361618Srie if (badrel) { 16371618Srie (void) fprintf(stderr, 16381618Srie MSG_INTL(MSG_ERR_BADREL1), file, 16391976Sab196087 conv_reloc_type(mach, reltype, 0)); 16400Sstevel@tonic-gate } 16410Sstevel@tonic-gate } 16420Sstevel@tonic-gate 16431618Srie Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP, 16441618Srie MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type, 16451618Srie rels, relname, symname, 0); 16460Sstevel@tonic-gate } 16470Sstevel@tonic-gate } 16480Sstevel@tonic-gate } 16490Sstevel@tonic-gate 16500Sstevel@tonic-gate /* 16510Sstevel@tonic-gate * Search for and process a .dynamic section. 16520Sstevel@tonic-gate */ 16530Sstevel@tonic-gate static void 16541618Srie dynamic(Cache *cache, Word shnum, Ehdr *ehdr, const char *file) 16550Sstevel@tonic-gate { 16561618Srie Word cnt; 16570Sstevel@tonic-gate 16580Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 16591618Srie Dyn *dyn; 16601618Srie ulong_t numdyn; 16613850Sab196087 int ndx, end_ndx; 16621618Srie Cache *_cache = &cache[cnt], *strsec; 16631618Srie Shdr *shdr = _cache->c_shdr; 16640Sstevel@tonic-gate 16650Sstevel@tonic-gate if (shdr->sh_type != SHT_DYNAMIC) 16660Sstevel@tonic-gate continue; 16670Sstevel@tonic-gate 16680Sstevel@tonic-gate /* 16691618Srie * Verify the associated string table section. 16700Sstevel@tonic-gate */ 16711618Srie if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0) 16720Sstevel@tonic-gate continue; 16731618Srie 16743466Srie if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 16753466Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 16763466Srie file, _cache->c_name); 16773466Srie continue; 16783466Srie } 16793466Srie if (_cache->c_data == NULL) 16803466Srie continue; 16813466Srie 16820Sstevel@tonic-gate numdyn = shdr->sh_size / shdr->sh_entsize; 16831618Srie dyn = (Dyn *)_cache->c_data->d_buf; 16840Sstevel@tonic-gate 16851618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 16861618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name); 16870Sstevel@tonic-gate 16881618Srie Elf_dyn_title(0); 16890Sstevel@tonic-gate 16901618Srie for (ndx = 0; ndx < numdyn; dyn++, ndx++) { 16911618Srie const char *name; 16920Sstevel@tonic-gate 16930Sstevel@tonic-gate /* 16940Sstevel@tonic-gate * Print the information numerically, and if possible 16950Sstevel@tonic-gate * as a string. 16960Sstevel@tonic-gate */ 16973850Sab196087 switch (dyn->d_tag) { 16983850Sab196087 case DT_NULL: 16993850Sab196087 /* 17003850Sab196087 * Special case: DT_NULLs can come in groups 17013850Sab196087 * that we prefer to reduce to a single line. 17023850Sab196087 */ 17033850Sab196087 end_ndx = ndx; 17043850Sab196087 while ((end_ndx < (numdyn - 1)) && 17053850Sab196087 ((dyn + 1)->d_tag == DT_NULL)) { 17063850Sab196087 dyn++; 17073850Sab196087 end_ndx++; 17083850Sab196087 } 17093850Sab196087 Elf_dyn_null_entry(0, dyn, ndx, end_ndx); 17103850Sab196087 ndx = end_ndx; 17113850Sab196087 continue; 17123850Sab196087 17133850Sab196087 /* 17143850Sab196087 * Print the information numerically, and if possible 17153850Sab196087 * as a string. 17163850Sab196087 */ 17173850Sab196087 case DT_NEEDED: 17183850Sab196087 case DT_SONAME: 17193850Sab196087 case DT_FILTER: 17203850Sab196087 case DT_AUXILIARY: 17213850Sab196087 case DT_CONFIG: 17223850Sab196087 case DT_RPATH: 17233850Sab196087 case DT_RUNPATH: 17243850Sab196087 case DT_USED: 17253850Sab196087 case DT_DEPAUDIT: 17263850Sab196087 case DT_AUDIT: 17273850Sab196087 case DT_SUNW_AUXILIARY: 17283850Sab196087 case DT_SUNW_FILTER: 17291618Srie name = string(_cache, ndx, strsec, 17301618Srie file, dyn->d_un.d_ptr); 17313850Sab196087 break; 17323850Sab196087 17333850Sab196087 case DT_FLAGS: 17342352Sab196087 name = conv_dyn_flag(dyn->d_un.d_val, 0); 17353850Sab196087 break; 17363850Sab196087 case DT_FLAGS_1: 17371618Srie name = conv_dyn_flag1(dyn->d_un.d_val); 17383850Sab196087 break; 17393850Sab196087 case DT_POSFLAG_1: 17402352Sab196087 name = conv_dyn_posflag1(dyn->d_un.d_val, 0); 17413850Sab196087 break; 17423850Sab196087 case DT_FEATURE_1: 17432352Sab196087 name = conv_dyn_feature1(dyn->d_un.d_val, 0); 17443850Sab196087 break; 17453850Sab196087 case DT_DEPRECATED_SPARC_REGISTER: 17461618Srie name = MSG_INTL(MSG_STR_DEPRECATED); 17473850Sab196087 break; 17483850Sab196087 default: 17491618Srie name = MSG_ORIG(MSG_STR_EMPTY); 17503850Sab196087 break; 17513850Sab196087 } 17520Sstevel@tonic-gate 17531618Srie Elf_dyn_entry(0, dyn, ndx, name, ehdr->e_machine); 17540Sstevel@tonic-gate } 17550Sstevel@tonic-gate } 17560Sstevel@tonic-gate } 17570Sstevel@tonic-gate 17580Sstevel@tonic-gate /* 17590Sstevel@tonic-gate * Search for and process a MOVE section. 17600Sstevel@tonic-gate */ 17610Sstevel@tonic-gate static void 17621618Srie move(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags) 17630Sstevel@tonic-gate { 17641618Srie Word cnt; 17651618Srie const char *fmt = 0; 17660Sstevel@tonic-gate 17670Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 17681618Srie Word movenum, symnum, ndx; 17691618Srie Sym *syms; 17701618Srie Cache *_cache = &cache[cnt]; 17711618Srie Shdr *shdr = _cache->c_shdr; 17721618Srie Cache *symsec, *strsec; 17731618Srie Move *move; 17740Sstevel@tonic-gate 17750Sstevel@tonic-gate if (shdr->sh_type != SHT_SUNW_move) 17760Sstevel@tonic-gate continue; 17770Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 17780Sstevel@tonic-gate continue; 17790Sstevel@tonic-gate 17800Sstevel@tonic-gate /* 17810Sstevel@tonic-gate * Determine the move data and number. 17820Sstevel@tonic-gate */ 17830Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 17840Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 17850Sstevel@tonic-gate file, _cache->c_name); 17860Sstevel@tonic-gate continue; 17870Sstevel@tonic-gate } 17883466Srie if (_cache->c_data == NULL) 17893466Srie continue; 17903466Srie 17911618Srie move = (Move *)_cache->c_data->d_buf; 17921618Srie movenum = shdr->sh_size / shdr->sh_entsize; 17930Sstevel@tonic-gate 17940Sstevel@tonic-gate /* 17951618Srie * Get the data buffer for the associated symbol table and 17961618Srie * string table. 17970Sstevel@tonic-gate */ 17981618Srie if (stringtbl(cache, 1, cnt, shnum, file, 17991618Srie &symnum, &symsec, &strsec) == 0) 18001618Srie return; 18011618Srie 18021618Srie syms = (Sym *)symsec->c_data->d_buf; 18030Sstevel@tonic-gate 18041618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 18051618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name); 18061618Srie dbg_print(0, MSG_INTL(MSG_MOVE_TITLE)); 18070Sstevel@tonic-gate 18081618Srie if (fmt == 0) 18091618Srie fmt = MSG_INTL(MSG_MOVE_ENTRY); 18100Sstevel@tonic-gate 18111618Srie for (ndx = 0; ndx < movenum; move++, ndx++) { 18121618Srie const char *symname; 18131618Srie char index[MAXNDXSIZE], section[BUFSIZ]; 18141618Srie Word symndx, shndx; 18151618Srie Sym *sym; 18160Sstevel@tonic-gate 18170Sstevel@tonic-gate /* 18180Sstevel@tonic-gate * Check for null entries 18190Sstevel@tonic-gate */ 18201618Srie if ((move->m_info == 0) && (move->m_value == 0) && 18211618Srie (move->m_poffset == 0) && (move->m_repeat == 0) && 18221618Srie (move->m_stride == 0)) { 18231618Srie dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY), 18241618Srie EC_XWORD(move->m_poffset), 0, 0, 0, 18251618Srie EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY)); 18260Sstevel@tonic-gate continue; 18270Sstevel@tonic-gate } 18281618Srie if (((symndx = ELF_M_SYM(move->m_info)) == 0) || 18291618Srie (symndx >= symnum)) { 18300Sstevel@tonic-gate (void) fprintf(stderr, 18310Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADMINFO), file, 18321618Srie _cache->c_name, EC_XWORD(move->m_info)); 18331618Srie 18341618Srie (void) snprintf(index, MAXNDXSIZE, 18351618Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 18361618Srie dbg_print(0, fmt, index, 18371618Srie EC_XWORD(move->m_poffset), 18381618Srie ELF_M_SIZE(move->m_info), move->m_repeat, 18391618Srie move->m_stride, move->m_value, 18400Sstevel@tonic-gate MSG_INTL(MSG_STR_UNKNOWN)); 18410Sstevel@tonic-gate continue; 18420Sstevel@tonic-gate } 18430Sstevel@tonic-gate 18441618Srie symname = relsymname(cache, _cache, strsec, 18451618Srie symndx, symnum, ndx, syms, section, BUFSIZ, file, 18461618Srie flags); 18471618Srie sym = (Sym *)(syms + symndx); 18480Sstevel@tonic-gate 18490Sstevel@tonic-gate /* 18500Sstevel@tonic-gate * Additional sanity check. 18510Sstevel@tonic-gate */ 18521618Srie shndx = sym->st_shndx; 18530Sstevel@tonic-gate if (!((shndx == SHN_COMMON) || 18540Sstevel@tonic-gate (((shndx >= 1) && (shndx <= shnum)) && 18551618Srie (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) { 18560Sstevel@tonic-gate (void) fprintf(stderr, 18571618Srie MSG_INTL(MSG_ERR_BADSYM2), file, 18581618Srie _cache->c_name, demangle(symname, flags)); 18590Sstevel@tonic-gate } 18600Sstevel@tonic-gate 18611618Srie (void) snprintf(index, MAXNDXSIZE, 18621618Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 18631618Srie dbg_print(0, fmt, index, EC_XWORD(move->m_poffset), 18641618Srie ELF_M_SIZE(move->m_info), move->m_repeat, 18651618Srie move->m_stride, move->m_value, 18661618Srie demangle(symname, flags)); 18670Sstevel@tonic-gate } 18680Sstevel@tonic-gate } 18690Sstevel@tonic-gate } 18700Sstevel@tonic-gate 18710Sstevel@tonic-gate /* 18720Sstevel@tonic-gate * Traverse a note section analyzing each note information block. 18730Sstevel@tonic-gate * The data buffers size is used to validate references before they are made, 18740Sstevel@tonic-gate * and is decremented as each element is processed. 18750Sstevel@tonic-gate */ 18760Sstevel@tonic-gate void 18771618Srie note_entry(Cache *cache, Word *data, size_t size, const char *file) 18780Sstevel@tonic-gate { 18791618Srie size_t bsize = size; 18801618Srie 18810Sstevel@tonic-gate /* 18820Sstevel@tonic-gate * Print out a single `note' information block. 18830Sstevel@tonic-gate */ 18840Sstevel@tonic-gate while (size > 0) { 18851618Srie size_t namesz, descsz, type, pad, noteoff; 18860Sstevel@tonic-gate 18870Sstevel@tonic-gate noteoff = bsize - size; 18880Sstevel@tonic-gate /* 18890Sstevel@tonic-gate * Make sure we can at least reference the 3 initial entries 18900Sstevel@tonic-gate * (4-byte words) of the note information block. 18910Sstevel@tonic-gate */ 18921618Srie if (size >= (sizeof (Word) * 3)) 18931618Srie size -= (sizeof (Word) * 3); 18940Sstevel@tonic-gate else { 18951618Srie (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ), 18961618Srie file, cache->c_name, EC_WORD(noteoff)); 18970Sstevel@tonic-gate return; 18980Sstevel@tonic-gate } 18990Sstevel@tonic-gate 19000Sstevel@tonic-gate /* 19010Sstevel@tonic-gate * Make sure any specified name string can be referenced. 19020Sstevel@tonic-gate */ 19030Sstevel@tonic-gate if ((namesz = *data++) != 0) { 19040Sstevel@tonic-gate if (size >= namesz) 19050Sstevel@tonic-gate size -= namesz; 19060Sstevel@tonic-gate else { 19070Sstevel@tonic-gate (void) fprintf(stderr, 19081618Srie MSG_INTL(MSG_NOTE_BADNMSZ), file, 19091618Srie cache->c_name, EC_WORD(noteoff), 19101618Srie EC_WORD(namesz)); 19110Sstevel@tonic-gate return; 19120Sstevel@tonic-gate } 19130Sstevel@tonic-gate } 19141618Srie 19150Sstevel@tonic-gate /* 19160Sstevel@tonic-gate * Make sure any specified descriptor can be referenced. 19170Sstevel@tonic-gate */ 19180Sstevel@tonic-gate if ((descsz = *data++) != 0) { 19190Sstevel@tonic-gate /* 19200Sstevel@tonic-gate * If namesz isn't a 4-byte multiple, account for any 19210Sstevel@tonic-gate * padding that must exist before the descriptor. 19220Sstevel@tonic-gate */ 19231618Srie if ((pad = (namesz & (sizeof (Word) - 1))) != 0) { 19241618Srie pad = sizeof (Word) - pad; 19250Sstevel@tonic-gate size -= pad; 19260Sstevel@tonic-gate } 19270Sstevel@tonic-gate if (size >= descsz) 19280Sstevel@tonic-gate size -= descsz; 19290Sstevel@tonic-gate else { 19300Sstevel@tonic-gate (void) fprintf(stderr, 19311618Srie MSG_INTL(MSG_NOTE_BADDESZ), file, 19321618Srie cache->c_name, EC_WORD(noteoff), 19331618Srie EC_WORD(namesz)); 19340Sstevel@tonic-gate return; 19350Sstevel@tonic-gate } 19360Sstevel@tonic-gate } 19370Sstevel@tonic-gate 19380Sstevel@tonic-gate type = *data++; 19390Sstevel@tonic-gate 19401618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 19411618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE), EC_WORD(type)); 19420Sstevel@tonic-gate 19431618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_NAMESZ), EC_WORD(namesz)); 19440Sstevel@tonic-gate if (namesz) { 19450Sstevel@tonic-gate char *name = (char *)data; 19460Sstevel@tonic-gate 19470Sstevel@tonic-gate /* 19480Sstevel@tonic-gate * Since the name string may have 'null' bytes 19490Sstevel@tonic-gate * in it (ia32 .string) - we just write the 19500Sstevel@tonic-gate * whole stream in a single fwrite. 19510Sstevel@tonic-gate */ 19520Sstevel@tonic-gate (void) fwrite(name, namesz, 1, stdout); 19530Sstevel@tonic-gate name = name + ((namesz + (sizeof (Word) - 1)) & 19540Sstevel@tonic-gate ~(sizeof (Word) - 1)); 19550Sstevel@tonic-gate /* LINTED */ 19560Sstevel@tonic-gate data = (Word *)name; 19571618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 19580Sstevel@tonic-gate } 19590Sstevel@tonic-gate 19600Sstevel@tonic-gate /* 19610Sstevel@tonic-gate * If multiple information blocks exist within a .note section 19620Sstevel@tonic-gate * account for any padding that must exist before the next 19630Sstevel@tonic-gate * information block. 19640Sstevel@tonic-gate */ 19651618Srie if ((pad = (descsz & (sizeof (Word) - 1))) != 0) { 19661618Srie pad = sizeof (Word) - pad; 19670Sstevel@tonic-gate if (size > pad) 19680Sstevel@tonic-gate size -= pad; 19690Sstevel@tonic-gate } 19700Sstevel@tonic-gate 19711618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_DESCSZ), EC_WORD(descsz)); 19720Sstevel@tonic-gate if (descsz) { 19730Sstevel@tonic-gate int ndx, byte, word; 19741618Srie char string[58], *str = string; 19750Sstevel@tonic-gate uchar_t *desc = (uchar_t *)data; 19760Sstevel@tonic-gate 19770Sstevel@tonic-gate /* 19780Sstevel@tonic-gate * Dump descriptor bytes. 19790Sstevel@tonic-gate */ 19800Sstevel@tonic-gate for (ndx = byte = word = 0; descsz; descsz--, desc++) { 19810Sstevel@tonic-gate int tok = *desc; 19820Sstevel@tonic-gate 19830Sstevel@tonic-gate (void) snprintf(str, 58, MSG_ORIG(MSG_NOTE_TOK), 19840Sstevel@tonic-gate tok); 19850Sstevel@tonic-gate str += 3; 19860Sstevel@tonic-gate 19870Sstevel@tonic-gate if (++byte == 4) { 19880Sstevel@tonic-gate *str++ = ' ', *str++ = ' '; 19890Sstevel@tonic-gate word++; 19900Sstevel@tonic-gate byte = 0; 19910Sstevel@tonic-gate } 19920Sstevel@tonic-gate if (word == 4) { 19930Sstevel@tonic-gate *str = '\0'; 19941618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_DESC), 19950Sstevel@tonic-gate ndx, string); 19960Sstevel@tonic-gate word = 0; 19970Sstevel@tonic-gate ndx += 16; 19980Sstevel@tonic-gate str = string; 19990Sstevel@tonic-gate } 20000Sstevel@tonic-gate } 20010Sstevel@tonic-gate if (byte || word) { 20020Sstevel@tonic-gate *str = '\0'; 20031618Srie dbg_print(0, MSG_ORIG(MSG_NOTE_DESC), 20041618Srie ndx, string); 20050Sstevel@tonic-gate } 20060Sstevel@tonic-gate 20070Sstevel@tonic-gate desc += pad; 20080Sstevel@tonic-gate /* LINTED */ 20090Sstevel@tonic-gate data = (Word *)desc; 20100Sstevel@tonic-gate } 20110Sstevel@tonic-gate } 20120Sstevel@tonic-gate } 20130Sstevel@tonic-gate 20140Sstevel@tonic-gate /* 20150Sstevel@tonic-gate * Search for and process a .note section. 20160Sstevel@tonic-gate */ 20170Sstevel@tonic-gate static void 20181618Srie note(Cache *cache, Word shnum, const char *name, const char *file) 20190Sstevel@tonic-gate { 20201618Srie Word cnt; 20210Sstevel@tonic-gate 20220Sstevel@tonic-gate /* 20230Sstevel@tonic-gate * Otherwise look for any .note sections. 20240Sstevel@tonic-gate */ 20250Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 20261618Srie Cache *_cache = &cache[cnt]; 20271618Srie Shdr *shdr = _cache->c_shdr; 20280Sstevel@tonic-gate 20290Sstevel@tonic-gate if (shdr->sh_type != SHT_NOTE) 20300Sstevel@tonic-gate continue; 20310Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 20320Sstevel@tonic-gate continue; 20330Sstevel@tonic-gate 20340Sstevel@tonic-gate /* 20350Sstevel@tonic-gate * As these sections are often hand rolled, make sure they're 20360Sstevel@tonic-gate * properly aligned before proceeding. 20370Sstevel@tonic-gate */ 20380Sstevel@tonic-gate if (shdr->sh_offset & (sizeof (Word) - 1)) { 20390Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN), 20400Sstevel@tonic-gate file, _cache->c_name); 20410Sstevel@tonic-gate continue; 20420Sstevel@tonic-gate } 20433466Srie if (_cache->c_data == NULL) 20443466Srie continue; 20450Sstevel@tonic-gate 20461618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 20471618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name); 20480Sstevel@tonic-gate note_entry(_cache, (Word *)_cache->c_data->d_buf, 20490Sstevel@tonic-gate /* LINTED */ 20500Sstevel@tonic-gate (Word)_cache->c_data->d_size, file); 20510Sstevel@tonic-gate } 20520Sstevel@tonic-gate } 20530Sstevel@tonic-gate 20541618Srie /* 20551618Srie * Determine an individual hash entry. This may be the initial hash entry, 20561618Srie * or an associated chain entry. 20571618Srie */ 20581618Srie static void 20591618Srie hash_entry(Cache *refsec, Cache *strsec, const char *hsecname, Word hashndx, 20601618Srie Word symndx, Word symn, Sym *syms, const char *file, ulong_t bkts, 20611618Srie uint_t flags, int chain) 20621618Srie { 20631618Srie Sym *sym; 20641618Srie const char *symname, *str; 20651618Srie char _bucket[MAXNDXSIZE], _symndx[MAXNDXSIZE]; 20661618Srie ulong_t nbkt, nhash; 20671618Srie 20681618Srie if (symndx > symn) { 20691618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_HSBADSYMNDX), file, 20701618Srie EC_WORD(symndx), EC_WORD(hashndx)); 20711618Srie symname = MSG_INTL(MSG_STR_UNKNOWN); 20721618Srie } else { 20731618Srie sym = (Sym *)(syms + symndx); 20741618Srie symname = string(refsec, symndx, strsec, file, sym->st_name); 20751618Srie } 20761618Srie 20771618Srie if (chain == 0) { 20781618Srie (void) snprintf(_bucket, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 20791618Srie hashndx); 20801618Srie str = (const char *)_bucket; 20811618Srie } else 20821618Srie str = MSG_ORIG(MSG_STR_EMPTY); 20831618Srie 20841618Srie (void) snprintf(_symndx, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX2), 20851618Srie EC_WORD(symndx)); 20861618Srie dbg_print(0, MSG_ORIG(MSG_FMT_HASH_INFO), str, _symndx, 20871618Srie demangle(symname, flags)); 20881618Srie 20891618Srie /* 20901618Srie * Determine if this string is in the correct bucket. 20911618Srie */ 20921618Srie nhash = elf_hash(symname); 20931618Srie nbkt = nhash % bkts; 20941618Srie 20951618Srie if (nbkt != hashndx) { 20961618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADHASH), file, 20971618Srie hsecname, symname, EC_WORD(hashndx), nbkt); 20981618Srie } 20991618Srie } 21000Sstevel@tonic-gate 21010Sstevel@tonic-gate #define MAXCOUNT 500 21020Sstevel@tonic-gate 21030Sstevel@tonic-gate static void 21041618Srie hash(Cache *cache, Word shnum, const char *name, const char *file, uint_t flags) 21050Sstevel@tonic-gate { 21060Sstevel@tonic-gate static int count[MAXCOUNT]; 21071618Srie Word cnt; 21080Sstevel@tonic-gate ulong_t ndx, bkts; 21090Sstevel@tonic-gate char number[MAXNDXSIZE]; 21100Sstevel@tonic-gate 21110Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 21120Sstevel@tonic-gate uint_t *hash, *chain; 21130Sstevel@tonic-gate Cache *_cache = &cache[cnt]; 21141618Srie Shdr *sshdr, *hshdr = _cache->c_shdr; 21151618Srie char *ssecname, *hsecname = _cache->c_name; 21161618Srie Sym *syms; 21171618Srie Word symn; 21180Sstevel@tonic-gate 21191618Srie if (hshdr->sh_type != SHT_HASH) 21200Sstevel@tonic-gate continue; 21211618Srie if (name && strcmp(name, hsecname)) 21220Sstevel@tonic-gate continue; 21230Sstevel@tonic-gate 21240Sstevel@tonic-gate /* 21250Sstevel@tonic-gate * Determine the hash table data and size. 21260Sstevel@tonic-gate */ 21271618Srie if ((hshdr->sh_entsize == 0) || (hshdr->sh_size == 0)) { 21280Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 21291618Srie file, hsecname); 21300Sstevel@tonic-gate continue; 21310Sstevel@tonic-gate } 21323466Srie if (_cache->c_data == NULL) 21333466Srie continue; 21343466Srie 21350Sstevel@tonic-gate hash = (uint_t *)_cache->c_data->d_buf; 21360Sstevel@tonic-gate bkts = *hash; 21370Sstevel@tonic-gate chain = hash + 2 + bkts; 21380Sstevel@tonic-gate hash += 2; 21390Sstevel@tonic-gate 21400Sstevel@tonic-gate /* 21410Sstevel@tonic-gate * Get the data buffer for the associated symbol table. 21420Sstevel@tonic-gate */ 21431618Srie if ((hshdr->sh_link == 0) || (hshdr->sh_link >= shnum)) { 21440Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 21451618Srie file, hsecname, EC_WORD(hshdr->sh_link)); 21460Sstevel@tonic-gate continue; 21470Sstevel@tonic-gate } 21481618Srie 21491618Srie _cache = &cache[hshdr->sh_link]; 21501618Srie ssecname = _cache->c_name; 21511618Srie 21523466Srie if (_cache->c_data == NULL) 21533466Srie continue; 21543466Srie 21553466Srie if ((syms = (Sym *)_cache->c_data->d_buf) == NULL) { 21560Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 21571618Srie file, ssecname); 21580Sstevel@tonic-gate continue; 21590Sstevel@tonic-gate } 21600Sstevel@tonic-gate 21611618Srie sshdr = _cache->c_shdr; 21621618Srie /* LINTED */ 21631618Srie symn = (Word)(sshdr->sh_size / sshdr->sh_entsize); 21641618Srie 21650Sstevel@tonic-gate /* 21660Sstevel@tonic-gate * Get the associated string table section. 21670Sstevel@tonic-gate */ 21681618Srie if ((sshdr->sh_link == 0) || (sshdr->sh_link >= shnum)) { 21690Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 21701618Srie file, ssecname, EC_WORD(sshdr->sh_link)); 21710Sstevel@tonic-gate continue; 21720Sstevel@tonic-gate } 21730Sstevel@tonic-gate 21741618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 21751618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_HASH), hsecname); 21761618Srie dbg_print(0, MSG_INTL(MSG_ELF_HASH_INFO)); 21770Sstevel@tonic-gate 21780Sstevel@tonic-gate /* 21790Sstevel@tonic-gate * Loop through the hash buckets, printing the appropriate 21800Sstevel@tonic-gate * symbols. 21810Sstevel@tonic-gate */ 21820Sstevel@tonic-gate for (ndx = 0; ndx < bkts; ndx++, hash++) { 21831618Srie Word _ndx, _cnt; 21840Sstevel@tonic-gate 21850Sstevel@tonic-gate if (*hash == 0) { 21860Sstevel@tonic-gate count[0]++; 21870Sstevel@tonic-gate continue; 21880Sstevel@tonic-gate } 21890Sstevel@tonic-gate 21901618Srie hash_entry(_cache, &cache[sshdr->sh_link], hsecname, 21911618Srie ndx, *hash, symn, syms, file, bkts, flags, 0); 21920Sstevel@tonic-gate 21930Sstevel@tonic-gate /* 21940Sstevel@tonic-gate * Determine if any other symbols are chained to this 21950Sstevel@tonic-gate * bucket. 21960Sstevel@tonic-gate */ 21970Sstevel@tonic-gate _ndx = chain[*hash]; 21980Sstevel@tonic-gate _cnt = 1; 21990Sstevel@tonic-gate while (_ndx) { 22001618Srie hash_entry(_cache, &cache[sshdr->sh_link], 22011618Srie hsecname, ndx, _ndx, symn, syms, file, 22021618Srie bkts, flags, 1); 22030Sstevel@tonic-gate _ndx = chain[_ndx]; 22040Sstevel@tonic-gate _cnt++; 22050Sstevel@tonic-gate } 22060Sstevel@tonic-gate 22070Sstevel@tonic-gate if (_cnt >= MAXCOUNT) { 22080Sstevel@tonic-gate (void) fprintf(stderr, 22091324Srie MSG_INTL(MSG_HASH_OVERFLW), file, 22101618Srie _cache->c_name, EC_WORD(ndx), 22111618Srie EC_WORD(_cnt)); 22120Sstevel@tonic-gate } else 22130Sstevel@tonic-gate count[_cnt]++; 22140Sstevel@tonic-gate } 22150Sstevel@tonic-gate break; 22160Sstevel@tonic-gate } 22170Sstevel@tonic-gate 22180Sstevel@tonic-gate /* 22190Sstevel@tonic-gate * Print out the count information. 22200Sstevel@tonic-gate */ 22210Sstevel@tonic-gate bkts = cnt = 0; 22221618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 22231618Srie 22240Sstevel@tonic-gate for (ndx = 0; ndx < MAXCOUNT; ndx++) { 22251618Srie Word _cnt; 22260Sstevel@tonic-gate 22270Sstevel@tonic-gate if ((_cnt = count[ndx]) == 0) 22280Sstevel@tonic-gate continue; 22290Sstevel@tonic-gate 22301618Srie (void) snprintf(number, MAXNDXSIZE, 22311618Srie MSG_ORIG(MSG_FMT_INTEGER), _cnt); 22321618Srie dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS1), number, 22331618Srie EC_WORD(ndx)); 22340Sstevel@tonic-gate bkts += _cnt; 22351618Srie cnt += (Word)(ndx * _cnt); 22360Sstevel@tonic-gate } 22370Sstevel@tonic-gate if (cnt) { 22380Sstevel@tonic-gate (void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 22391618Srie bkts); 22401618Srie dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS2), number, 22411618Srie EC_WORD(cnt)); 22420Sstevel@tonic-gate } 22430Sstevel@tonic-gate } 22440Sstevel@tonic-gate 22450Sstevel@tonic-gate static void 22461618Srie group(Cache *cache, Word shnum, const char *name, const char *file, 22471618Srie uint_t flags) 22480Sstevel@tonic-gate { 22491618Srie Word scnt; 22500Sstevel@tonic-gate 22511618Srie for (scnt = 1; scnt < shnum; scnt++) { 22521618Srie Cache *_cache = &cache[scnt]; 22531618Srie Shdr *shdr = _cache->c_shdr; 22541618Srie Word *grpdata, gcnt, grpcnt, symnum, unknown; 22551618Srie Cache *symsec, *strsec; 22561618Srie Sym *syms, *sym; 22571618Srie char flgstrbuf[MSG_GRP_COMDAT_SIZE + 10]; 22580Sstevel@tonic-gate 22590Sstevel@tonic-gate if (shdr->sh_type != SHT_GROUP) 22600Sstevel@tonic-gate continue; 22610Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 22620Sstevel@tonic-gate continue; 22633466Srie if ((_cache->c_data == NULL) || 22643466Srie ((grpdata = (Word *)_cache->c_data->d_buf) == NULL)) 22650Sstevel@tonic-gate continue; 22661618Srie grpcnt = shdr->sh_size / sizeof (Word); 22671618Srie 22681618Srie /* 22691618Srie * Get the data buffer for the associated symbol table and 22701618Srie * string table. 22711618Srie */ 22721618Srie if (stringtbl(cache, 1, scnt, shnum, file, 22731618Srie &symnum, &symsec, &strsec) == 0) 22741618Srie return; 22751618Srie 22761618Srie syms = symsec->c_data->d_buf; 22771618Srie 22781618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 22791618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_GRP), _cache->c_name); 22801618Srie dbg_print(0, MSG_INTL(MSG_GRP_TITLE)); 22811618Srie 22821618Srie /* 22831618Srie * The first element of the group defines the group. The 22841618Srie * associated symbol is defined by the sh_link field. 22851618Srie */ 22861618Srie if ((shdr->sh_info == SHN_UNDEF) || (shdr->sh_info > symnum)) { 22871618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 22881618Srie file, _cache->c_name, EC_WORD(shdr->sh_info)); 22891618Srie return; 22900Sstevel@tonic-gate } 22910Sstevel@tonic-gate 22921618Srie (void) strcpy(flgstrbuf, MSG_ORIG(MSG_STR_OSQBRKT)); 22931618Srie if (grpdata[0] & GRP_COMDAT) { 22941618Srie (void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_COMDAT)); 22950Sstevel@tonic-gate } 22961618Srie if ((unknown = (grpdata[0] & ~GRP_COMDAT)) != 0) { 22971618Srie size_t len = strlen(flgstrbuf); 22981618Srie 22991618Srie (void) snprintf(&flgstrbuf[len], 23001618Srie (MSG_GRP_COMDAT_SIZE + 10 - len), 23011618Srie MSG_ORIG(MSG_GRP_UNKNOWN), unknown); 23020Sstevel@tonic-gate } 23031618Srie (void) strcat(flgstrbuf, MSG_ORIG(MSG_STR_CSQBRKT)); 23041618Srie sym = (Sym *)(syms + shdr->sh_info); 23050Sstevel@tonic-gate 23061618Srie dbg_print(0, MSG_INTL(MSG_GRP_SIGNATURE), flgstrbuf, 23071618Srie demangle(string(_cache, 0, strsec, file, sym->st_name), 23081618Srie flags)); 23091618Srie 23101618Srie for (gcnt = 1; gcnt < grpcnt; gcnt++) { 23110Sstevel@tonic-gate char index[MAXNDXSIZE]; 23121618Srie const char *name; 23130Sstevel@tonic-gate 23140Sstevel@tonic-gate (void) snprintf(index, MAXNDXSIZE, 23151618Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(gcnt)); 23161618Srie 23171618Srie if (grpdata[gcnt] >= shnum) 23181618Srie name = MSG_INTL(MSG_GRP_INVALSCN); 23191618Srie else 23201618Srie name = cache[grpdata[gcnt]].c_name; 23211618Srie 23221618Srie (void) printf(MSG_ORIG(MSG_GRP_ENTRY), index, name, 23231618Srie EC_XWORD(grpdata[gcnt])); 23240Sstevel@tonic-gate } 23250Sstevel@tonic-gate } 23260Sstevel@tonic-gate } 23270Sstevel@tonic-gate 23280Sstevel@tonic-gate static void 23291618Srie got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, uint_t flags) 23300Sstevel@tonic-gate { 23310Sstevel@tonic-gate Cache *gotcache = 0, *symtab = 0, *_cache; 23321618Srie Addr gotbgn, gotend; 23331618Srie Shdr *gotshdr; 23341618Srie Word cnt, gotents, gotndx; 23350Sstevel@tonic-gate size_t gentsize; 23360Sstevel@tonic-gate Got_info *gottable; 23370Sstevel@tonic-gate char *gotdata; 23381618Srie Sym *gotsym; 23391618Srie Xword gotsymaddr; 23400Sstevel@tonic-gate 23410Sstevel@tonic-gate /* 23421324Srie * First, find the got. 23430Sstevel@tonic-gate */ 23440Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 23450Sstevel@tonic-gate _cache = &cache[cnt]; 23461324Srie if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT), 23471324Srie MSG_ELF_GOT_SIZE) == 0) { 23480Sstevel@tonic-gate gotcache = _cache; 23490Sstevel@tonic-gate break; 23500Sstevel@tonic-gate } 23510Sstevel@tonic-gate } 23521618Srie if (gotcache == 0) 23530Sstevel@tonic-gate return; 23541324Srie 23551324Srie /* 23561324Srie * A got section within a relocatable object is suspicious. 23571324Srie */ 23581324Srie if (ehdr->e_type == ET_REL) { 23591324Srie (void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file, 23601324Srie _cache->c_name); 23611324Srie } 23621324Srie 23631618Srie gotshdr = gotcache->c_shdr; 23640Sstevel@tonic-gate if (gotshdr->sh_size == 0) { 23650Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 23660Sstevel@tonic-gate file, gotcache->c_name); 23670Sstevel@tonic-gate return; 23680Sstevel@tonic-gate } 23691618Srie 23701618Srie gotbgn = gotshdr->sh_addr; 23710Sstevel@tonic-gate gotend = gotbgn + gotshdr->sh_size; 23720Sstevel@tonic-gate 23730Sstevel@tonic-gate /* 23741618Srie * Some architectures don't properly set the sh_entsize for the GOT 23751618Srie * table. If it's not set, default to a size of a pointer. 23760Sstevel@tonic-gate */ 23771618Srie if ((gentsize = gotshdr->sh_entsize) == 0) 23781618Srie gentsize = sizeof (Xword); 23791618Srie 23803466Srie if (gotcache->c_data == NULL) 23813466Srie return; 23823466Srie 23830Sstevel@tonic-gate /* LINTED */ 23841618Srie gotents = (Word)(gotshdr->sh_size / gentsize); 23850Sstevel@tonic-gate gotdata = gotcache->c_data->d_buf; 23860Sstevel@tonic-gate 23870Sstevel@tonic-gate if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) { 23880Sstevel@tonic-gate int err = errno; 23891618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), file, 23901618Srie strerror(err)); 23910Sstevel@tonic-gate return; 23920Sstevel@tonic-gate } 23930Sstevel@tonic-gate 23940Sstevel@tonic-gate /* 23950Sstevel@tonic-gate * Now we scan through all the sections looking for any relocations 23960Sstevel@tonic-gate * that may be against the GOT. Since these may not be isolated to a 23970Sstevel@tonic-gate * .rel[a].got section we check them all. 23980Sstevel@tonic-gate * While scanning sections save the symbol table entry (a symtab 23990Sstevel@tonic-gate * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_. 24000Sstevel@tonic-gate */ 24010Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 24021618Srie Word type, symnum; 24031618Srie Xword relndx, relnum, relsize; 24041618Srie void *rels; 24051618Srie Sym *syms; 24061618Srie Cache *symsec, *strsec; 24071618Srie Cache *_cache = &cache[cnt]; 24081618Srie Shdr *shdr; 24090Sstevel@tonic-gate 24101618Srie shdr = _cache->c_shdr; 24111618Srie type = shdr->sh_type; 24120Sstevel@tonic-gate 24131618Srie if ((symtab == 0) && (type == SHT_DYNSYM)) { 24140Sstevel@tonic-gate symtab = _cache; 24150Sstevel@tonic-gate continue; 24160Sstevel@tonic-gate } 24171618Srie if (type == SHT_SYMTAB) { 24180Sstevel@tonic-gate symtab = _cache; 24190Sstevel@tonic-gate continue; 24200Sstevel@tonic-gate } 24211618Srie if ((type != SHT_RELA) && (type != SHT_REL)) 24220Sstevel@tonic-gate continue; 24230Sstevel@tonic-gate 24240Sstevel@tonic-gate /* 24251618Srie * Decide entry size. 24260Sstevel@tonic-gate */ 24271618Srie if (((relsize = shdr->sh_entsize) == 0) || 24281618Srie (relsize > shdr->sh_size)) { 24291618Srie if (type == SHT_RELA) 24301618Srie relsize = sizeof (Rela); 24311618Srie else 24321618Srie relsize = sizeof (Rel); 24330Sstevel@tonic-gate } 24340Sstevel@tonic-gate 24350Sstevel@tonic-gate /* 24361618Srie * Determine the number of relocations available. 24370Sstevel@tonic-gate */ 24381618Srie if (shdr->sh_size == 0) { 24391618Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 24401618Srie file, _cache->c_name); 24410Sstevel@tonic-gate continue; 24420Sstevel@tonic-gate } 24433466Srie if (_cache->c_data == NULL) 24443466Srie continue; 24453466Srie 24461618Srie rels = _cache->c_data->d_buf; 24471618Srie relnum = shdr->sh_size / relsize; 24480Sstevel@tonic-gate 24491618Srie /* 24501618Srie * Get the data buffer for the associated symbol table and 24511618Srie * string table. 24521618Srie */ 24531618Srie if (stringtbl(cache, 1, cnt, shnum, file, 24541618Srie &symnum, &symsec, &strsec) == 0) 24551618Srie continue; 24561618Srie 24571618Srie syms = symsec->c_data->d_buf; 24581618Srie 24591618Srie /* 24601618Srie * Loop through the relocation entries. 24611618Srie */ 24621618Srie for (relndx = 0; relndx < relnum; relndx++, 24631618Srie rels = (void *)((char *)rels + relsize)) { 24641618Srie char section[BUFSIZ]; 24651618Srie Addr offset; 24660Sstevel@tonic-gate Got_info *gip; 24671618Srie Word symndx, reltype; 24681618Srie Rela *rela; 24691618Srie Rel *rel; 24700Sstevel@tonic-gate 24711618Srie /* 24721618Srie * Unravel the relocation. 24731618Srie */ 24741618Srie if (type == SHT_RELA) { 24751618Srie rela = (Rela *)rels; 24761618Srie symndx = ELF_R_SYM(rela->r_info); 24771618Srie reltype = ELF_R_TYPE(rela->r_info); 24781618Srie offset = rela->r_offset; 24790Sstevel@tonic-gate } else { 24801618Srie rel = (Rel *)rels; 24811618Srie symndx = ELF_R_SYM(rel->r_info); 24821618Srie reltype = ELF_R_TYPE(rel->r_info); 24831618Srie offset = rel->r_offset; 24840Sstevel@tonic-gate } 24850Sstevel@tonic-gate 24860Sstevel@tonic-gate /* 24870Sstevel@tonic-gate * Only pay attention to relocations against the GOT. 24880Sstevel@tonic-gate */ 24890Sstevel@tonic-gate if ((offset < gotbgn) || (offset > gotend)) 24900Sstevel@tonic-gate continue; 24910Sstevel@tonic-gate 24920Sstevel@tonic-gate /* LINTED */ 24931618Srie gotndx = (Word)((offset - gotbgn) / 24940Sstevel@tonic-gate gotshdr->sh_entsize); 24950Sstevel@tonic-gate gip = &gottable[gotndx]; 24961618Srie 24971618Srie if (gip->g_reltype != 0) { 24980Sstevel@tonic-gate (void) fprintf(stderr, 24990Sstevel@tonic-gate MSG_INTL(MSG_GOT_MULTIPLE), file, 25001618Srie EC_WORD(gotndx), EC_ADDR(offset)); 25010Sstevel@tonic-gate continue; 25020Sstevel@tonic-gate } 25030Sstevel@tonic-gate 25041618Srie if (symndx) 25051618Srie gip->g_symname = relsymname(cache, _cache, 25061618Srie strsec, symndx, symnum, relndx, syms, 25071618Srie section, BUFSIZ, file, flags); 25081618Srie gip->g_reltype = reltype; 25091618Srie gip->g_rel = rels; 25100Sstevel@tonic-gate } 25110Sstevel@tonic-gate } 25120Sstevel@tonic-gate 25131618Srie if (symlookup(MSG_ORIG(MSG_GOT_SYM), cache, shnum, &gotsym, symtab, 25141618Srie file)) 25151618Srie gotsymaddr = gotsym->st_value; 25160Sstevel@tonic-gate else 25171618Srie gotsymaddr = gotbgn; 25180Sstevel@tonic-gate 25191618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 25201618Srie dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name); 25211618Srie Elf_got_title(0); 25220Sstevel@tonic-gate 25230Sstevel@tonic-gate for (gotndx = 0; gotndx < gotents; gotndx++) { 25240Sstevel@tonic-gate Got_info *gip; 25250Sstevel@tonic-gate Sword gindex; 25261618Srie Addr gaddr; 25271618Srie Xword gotentry; 25280Sstevel@tonic-gate 25290Sstevel@tonic-gate gip = &gottable[gotndx]; 25300Sstevel@tonic-gate 25310Sstevel@tonic-gate gaddr = gotbgn + (gotndx * gentsize); 25321618Srie gindex = (Sword)(gaddr - gotsymaddr) / (Sword)gentsize; 25330Sstevel@tonic-gate 25341618Srie if (gentsize == sizeof (Word)) 25350Sstevel@tonic-gate /* LINTED */ 25361618Srie gotentry = (Xword)(*((Word *)(gotdata) + gotndx)); 25370Sstevel@tonic-gate else 25380Sstevel@tonic-gate /* LINTED */ 25391618Srie gotentry = *((Xword *)(gotdata) + gotndx); 25400Sstevel@tonic-gate 25411618Srie Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine, 25421618Srie gip->g_reltype, gip->g_rel, gip->g_symname); 25430Sstevel@tonic-gate } 25440Sstevel@tonic-gate free(gottable); 25450Sstevel@tonic-gate } 25460Sstevel@tonic-gate 25470Sstevel@tonic-gate void 25480Sstevel@tonic-gate checksum(Elf *elf) 25490Sstevel@tonic-gate { 25501618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 25511618Srie dbg_print(0, MSG_INTL(MSG_STR_CHECKSUM), elf_checksum(elf)); 25520Sstevel@tonic-gate } 25530Sstevel@tonic-gate 25541618Srie void 25551618Srie regular(const char *file, Elf *elf, uint_t flags, char *Nname, int wfd) 25560Sstevel@tonic-gate { 2557*3862Srie /* 2558*3862Srie * Program header names that we can test for. 2559*3862Srie */ 2560*3862Srie static const char *pnames[PT_NUM] = { 2561*3862Srie MSG_ORIG(MSG_PT_NULL), MSG_ORIG(MSG_PT_LOAD), 2562*3862Srie MSG_ORIG(MSG_PT_DYNAMIC), MSG_ORIG(MSG_PT_INTERP), 2563*3862Srie MSG_ORIG(MSG_PT_NOTE), MSG_ORIG(MSG_PT_SHLIB), 2564*3862Srie MSG_ORIG(MSG_PT_PHDR), MSG_ORIG(MSG_PT_TLS) 2565*3862Srie }; 2566*3862Srie #if PT_NUM != (PT_TLS + 1) 2567*3862Srie #error "P_NUM has grown. Update addr_symtype[]" 2568*3862Srie #endif 2569*3862Srie 25700Sstevel@tonic-gate Elf_Scn *scn; 25711618Srie Ehdr *ehdr; 25720Sstevel@tonic-gate Elf_Data *data; 25731618Srie size_t cnt, shstrndx, shnum, phnum; 25741618Srie Shdr *nameshdr, *shdr; 25750Sstevel@tonic-gate char *names = 0; 25760Sstevel@tonic-gate Cache *cache, *_cache; 25771618Srie Cache *versymcache = 0; 25780Sstevel@tonic-gate 25791618Srie if ((ehdr = elf_getehdr(elf)) == NULL) { 25800Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETEHDR)); 25810Sstevel@tonic-gate return; 25820Sstevel@tonic-gate } 25830Sstevel@tonic-gate 25841618Srie if (elf_getshnum(elf, &shnum) == 0) { 25850Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHNUM)); 25860Sstevel@tonic-gate return; 25870Sstevel@tonic-gate } 25880Sstevel@tonic-gate 2589942Sahl if (elf_getshstrndx(elf, &shstrndx) == 0) { 25900Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX)); 25910Sstevel@tonic-gate return; 25920Sstevel@tonic-gate } 2593942Sahl 25941618Srie if (elf_getphnum(elf, &phnum) == 0) { 2595942Sahl failure(file, MSG_ORIG(MSG_ELF_GETPHNUM)); 2596942Sahl return; 2597942Sahl } 2598942Sahl 25990Sstevel@tonic-gate if ((scn = elf_getscn(elf, 0)) != NULL) { 26001618Srie if ((shdr = elf_getshdr(scn)) == NULL) { 26010Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 26020Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0); 26030Sstevel@tonic-gate return; 26040Sstevel@tonic-gate } 26050Sstevel@tonic-gate } else 26061618Srie shdr = 0; 26070Sstevel@tonic-gate 26080Sstevel@tonic-gate /* 26090Sstevel@tonic-gate * Print the elf header. 26100Sstevel@tonic-gate */ 26110Sstevel@tonic-gate if (flags & FLG_EHDR) 26121618Srie Elf_ehdr(0, ehdr, shdr); 26130Sstevel@tonic-gate 26140Sstevel@tonic-gate /* 26150Sstevel@tonic-gate * Print the program headers. 26160Sstevel@tonic-gate */ 26171618Srie if ((flags & FLG_PHDR) && (phnum != 0)) { 26181618Srie Phdr *phdr; 26190Sstevel@tonic-gate 26201618Srie if ((phdr = elf_getphdr(elf)) == NULL) { 26211618Srie failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 26221618Srie return; 26231618Srie } 26240Sstevel@tonic-gate 26251618Srie for (cnt = 0; cnt < phnum; phdr++, cnt++) { 2626*3862Srie 2627*3862Srie if (Nname && ((phdr->p_type >= PT_NUM) || 2628*3862Srie (strcmp(Nname, pnames[phdr->p_type]) != 0))) 2629*3862Srie continue; 2630*3862Srie 26311618Srie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 26321618Srie dbg_print(0, MSG_INTL(MSG_ELF_PHDR), EC_WORD(cnt)); 26331618Srie Elf_phdr(0, ehdr->e_machine, phdr); 26340Sstevel@tonic-gate } 26350Sstevel@tonic-gate } 26360Sstevel@tonic-gate 26370Sstevel@tonic-gate /* 2638942Sahl * Return now if there are no section, if there's just one section to 2639942Sahl * act as an extension of the ELF header, or if on section information 2640942Sahl * was requested. 26410Sstevel@tonic-gate */ 2642942Sahl if ((shnum <= 1) || (flags && (flags & ~(FLG_EHDR | FLG_PHDR)) == 0)) { 26431618Srie if ((ehdr->e_type == ET_CORE) && (flags & FLG_NOTE)) 26440Sstevel@tonic-gate note(0, shnum, 0, file); 26450Sstevel@tonic-gate return; 26460Sstevel@tonic-gate } 26470Sstevel@tonic-gate 26480Sstevel@tonic-gate /* 26490Sstevel@tonic-gate * Obtain the .shstrtab data buffer to provide the required section 26500Sstevel@tonic-gate * name strings. 26510Sstevel@tonic-gate */ 26520Sstevel@tonic-gate if ((scn = elf_getscn(elf, shstrndx)) == NULL) { 26530Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSCN)); 26540Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR), 26550Sstevel@tonic-gate EC_XWORD(shstrndx)); 26561618Srie 26570Sstevel@tonic-gate } else if ((data = elf_getdata(scn, NULL)) == NULL) { 26580Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 26590Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA), 26600Sstevel@tonic-gate EC_XWORD(shstrndx)); 26611618Srie 26621618Srie } else if ((nameshdr = elf_getshdr(scn)) == NULL) { 26630Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 26640Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 2665*3862Srie EC_WORD(elf_ndxscn(scn))); 26661618Srie 26671618Srie } else if ((names = data->d_buf) == 0) 26680Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file); 26690Sstevel@tonic-gate 26700Sstevel@tonic-gate /* 2671*3862Srie * Allocate a cache to maintain a descriptor for each section. 26720Sstevel@tonic-gate */ 26730Sstevel@tonic-gate if ((cache = malloc(shnum * sizeof (Cache))) == 0) { 26740Sstevel@tonic-gate int err = errno; 26750Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 26760Sstevel@tonic-gate file, strerror(err)); 26770Sstevel@tonic-gate return; 26780Sstevel@tonic-gate } 26790Sstevel@tonic-gate 26801618Srie *cache = cache_init; 26810Sstevel@tonic-gate _cache = cache; 26820Sstevel@tonic-gate _cache++; 26830Sstevel@tonic-gate 2684*3862Srie /* 2685*3862Srie * Traverse the sections of the file. This gathering of data is 2686*3862Srie * carried out in two passes. First, the section headers are captured 2687*3862Srie * and the section header names are evaluated. A verification pass is 2688*3862Srie * then carried out over the section information. Files have been 2689*3862Srie * known to exhibit overlapping (and hence erroneous) section header 2690*3862Srie * information. 2691*3862Srie * 2692*3862Srie * Finally, the data for each section is obtained. This processing is 2693*3862Srie * carried out after section verification because should any section 2694*3862Srie * header overlap occur, and a file needs translating (ie. xlate'ing 2695*3862Srie * information from a non-native architecture file), then the process 2696*3862Srie * of translation can corrupt the section header information. Of 2697*3862Srie * course, if there is any section overlap, the data related to the 2698*3862Srie * sections is going to be compromised. However, it is the translation 2699*3862Srie * of this data that has caused problems with elfdump()'s ability to 2700*3862Srie * extract the data. 2701*3862Srie */ 27020Sstevel@tonic-gate for (cnt = 1, scn = NULL; scn = elf_nextscn(elf, scn); 27030Sstevel@tonic-gate cnt++, _cache++) { 2704*3862Srie char scnndxnm[100]; 2705*3862Srie 2706*3862Srie _cache->c_scn = scn; 2707*3862Srie 27081618Srie if ((_cache->c_shdr = elf_getshdr(scn)) == NULL) { 27090Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 27100Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 2711*3862Srie EC_WORD(elf_ndxscn(scn))); 27120Sstevel@tonic-gate } 27130Sstevel@tonic-gate 2714*3862Srie /* 2715*3862Srie * If a shstrtab exists, assign the section name. 2716*3862Srie */ 2717*3862Srie if (names && _cache->c_shdr) { 2718*3862Srie if (_cache->c_shdr->sh_name && 2719*3862Srie /* LINTED */ 2720*3862Srie (nameshdr->sh_size > _cache->c_shdr->sh_name)) { 2721*3862Srie _cache->c_name = 2722*3862Srie names + _cache->c_shdr->sh_name; 2723*3862Srie continue; 2724*3862Srie } 27250Sstevel@tonic-gate 27260Sstevel@tonic-gate /* 2727*3862Srie * Generate an error if the section name index is zero 2728*3862Srie * or exceeds the shstrtab data. Fall through to 2729*3862Srie * fabricate a section name. 27300Sstevel@tonic-gate */ 2731*3862Srie if ((_cache->c_shdr->sh_name == 0) || 27320Sstevel@tonic-gate /* LINTED */ 27331618Srie (nameshdr->sh_size <= _cache->c_shdr->sh_name)) { 27340Sstevel@tonic-gate (void) fprintf(stderr, 27350Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSHNAME), file, 2736*3862Srie EC_WORD(cnt), 27371618Srie EC_XWORD(_cache->c_shdr->sh_name)); 27380Sstevel@tonic-gate } 2739*3862Srie } 2740*3862Srie 2741*3862Srie /* 2742*3862Srie * If there exists no shstrtab data, or a section header has no 2743*3862Srie * name (an invalid index of 0), then compose a name for the 2744*3862Srie * section. 2745*3862Srie */ 2746*3862Srie (void) snprintf(scnndxnm, sizeof (scnndxnm), 2747*3862Srie MSG_INTL(MSG_FMT_SCNNDX), cnt); 2748*3862Srie 2749*3862Srie if ((_cache->c_name = malloc(strlen(scnndxnm) + 1)) == 0) { 2750*3862Srie int err = errno; 2751*3862Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2752*3862Srie file, strerror(err)); 2753*3862Srie return; 2754*3862Srie } 2755*3862Srie (void) strcpy(_cache->c_name, scnndxnm); 2756*3862Srie } 2757*3862Srie 2758*3862Srie /* 2759*3862Srie * Having collected all the sections, validate their address range. 2760*3862Srie * Cases have existed where the section information has been invalid. 2761*3862Srie * This can lead to all sorts of other, hard to diagnose errors, as 2762*3862Srie * each section is processed individually (ie. with elf_getdata()). 2763*3862Srie * Here, we carry out some address comparisons to catch a family of 2764*3862Srie * overlapping memory issues we have observed (likely, there are others 2765*3862Srie * that we have yet to discover). 2766*3862Srie * 2767*3862Srie * Note, should any memory overlap occur, obtaining any additional 2768*3862Srie * data from the file is questionable. However, it might still be 2769*3862Srie * possible to inspect the ELF header, Programs headers, or individual 2770*3862Srie * sections, so rather than bailing on an error condition, continue 2771*3862Srie * processing to see if any data can be salvaged. 2772*3862Srie */ 2773*3862Srie for (cnt = 1; cnt < shnum; cnt++) { 2774*3862Srie Cache *_cache = &cache[cnt]; 2775*3862Srie Shdr *shdr = _cache->c_shdr; 2776*3862Srie Off bgn1, bgn = shdr->sh_offset; 2777*3862Srie Off end1, end = shdr->sh_offset + shdr->sh_size; 2778*3862Srie int cnt1; 2779*3862Srie 2780*3862Srie if ((shdr->sh_size == 0) || (shdr->sh_type == SHT_NOBITS)) 2781*3862Srie continue; 2782*3862Srie 2783*3862Srie for (cnt1 = 1; cnt1 < shnum; cnt1++) { 2784*3862Srie Cache *_cache1 = &cache[cnt1]; 2785*3862Srie Shdr *shdr1 = _cache1->c_shdr; 2786*3862Srie 2787*3862Srie bgn1 = shdr1->sh_offset; 2788*3862Srie end1 = shdr1->sh_offset + shdr1->sh_size; 2789*3862Srie 2790*3862Srie if ((cnt1 == cnt) || (shdr->sh_size == 0) || 2791*3862Srie (shdr1->sh_type == SHT_NOBITS)) 2792*3862Srie continue; 2793*3862Srie 2794*3862Srie if (((bgn1 <= bgn) && (end1 > bgn)) || 2795*3862Srie ((bgn1 < end) && (end1 >= end))) { 2796*3862Srie (void) fprintf(stderr, 2797*3862Srie MSG_INTL(MSG_ERR_SECMEMOVER), file, 2798*3862Srie EC_WORD(elf_ndxscn(_cache1->c_scn)), 2799*3862Srie _cache1->c_name, EC_OFF(bgn1), EC_OFF(end1), 2800*3862Srie EC_WORD(elf_ndxscn(_cache->c_scn)), 2801*3862Srie _cache->c_name, EC_OFF(bgn), EC_OFF(end)); 28020Sstevel@tonic-gate } 28030Sstevel@tonic-gate } 28040Sstevel@tonic-gate 2805*3862Srie /* 2806*3862Srie * And finally, make sure this section doesn't overlap the 2807*3862Srie * section header itself. 2808*3862Srie */ 2809*3862Srie bgn1 = ehdr->e_shoff; 2810*3862Srie end1 = ehdr->e_shoff + (ehdr->e_shentsize * ehdr->e_shnum); 2811*3862Srie 2812*3862Srie if (((bgn1 <= bgn) && (end1 > bgn)) || 2813*3862Srie ((bgn1 < end) && (end1 >= end))) { 2814*3862Srie (void) fprintf(stderr, 2815*3862Srie MSG_INTL(MSG_ERR_SHDRMEMOVER), file, EC_OFF(bgn1), 2816*3862Srie EC_OFF(end1), 2817*3862Srie EC_WORD(elf_ndxscn(_cache->c_scn)), 2818*3862Srie _cache->c_name, EC_OFF(bgn), EC_OFF(end)); 2819*3862Srie } 2820*3862Srie } 2821*3862Srie 2822*3862Srie /* 2823*3862Srie * Finally, obtain the data for each section. 2824*3862Srie */ 2825*3862Srie for (cnt = 1; cnt < shnum; cnt++) { 2826*3862Srie Cache *_cache = &cache[cnt]; 2827*3862Srie Elf_Scn *scn = _cache->c_scn; 2828*3862Srie 28290Sstevel@tonic-gate if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) { 28300Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 28310Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA), 2832*3862Srie EC_WORD(elf_ndxscn(scn))); 28330Sstevel@tonic-gate } 28340Sstevel@tonic-gate 28350Sstevel@tonic-gate /* 28360Sstevel@tonic-gate * Do we wish to write the section out? 28370Sstevel@tonic-gate */ 28383466Srie if (wfd && Nname && (strcmp(Nname, _cache->c_name) == 0) && 28393466Srie _cache->c_data) { 28400Sstevel@tonic-gate (void) write(wfd, _cache->c_data->d_buf, 28410Sstevel@tonic-gate _cache->c_data->d_size); 28420Sstevel@tonic-gate } 28430Sstevel@tonic-gate } 28440Sstevel@tonic-gate 28450Sstevel@tonic-gate if (flags & FLG_SHDR) 28461618Srie sections(file, cache, shnum, ehdr, Nname); 28470Sstevel@tonic-gate 28480Sstevel@tonic-gate if (flags & FLG_INTERP) 28491618Srie interp(file, cache, shnum, phnum, elf); 28500Sstevel@tonic-gate 28510Sstevel@tonic-gate versymcache = versions(cache, shnum, file, flags); 28520Sstevel@tonic-gate 28530Sstevel@tonic-gate if (flags & FLG_SYMBOLS) 28541618Srie symbols(cache, shnum, ehdr, Nname, versymcache, file, flags); 28550Sstevel@tonic-gate 28563492Sab196087 if (flags & FLG_SORT) 28573492Sab196087 sunw_sort(cache, shnum, ehdr, Nname, versymcache, file, flags); 28583492Sab196087 28590Sstevel@tonic-gate if (flags & FLG_HASH) 28600Sstevel@tonic-gate hash(cache, shnum, Nname, file, flags); 28610Sstevel@tonic-gate 28620Sstevel@tonic-gate if (flags & FLG_GOT) 28631618Srie got(cache, shnum, ehdr, file, flags); 28640Sstevel@tonic-gate 28650Sstevel@tonic-gate if (flags & FLG_GROUP) 28660Sstevel@tonic-gate group(cache, shnum, Nname, file, flags); 28670Sstevel@tonic-gate 28680Sstevel@tonic-gate if (flags & FLG_SYMINFO) 28690Sstevel@tonic-gate syminfo(cache, shnum, file); 28700Sstevel@tonic-gate 28710Sstevel@tonic-gate if (flags & FLG_RELOC) 28721618Srie reloc(cache, shnum, ehdr, Nname, file, flags); 28730Sstevel@tonic-gate 28740Sstevel@tonic-gate if (flags & FLG_DYNAMIC) 28751618Srie dynamic(cache, shnum, ehdr, file); 28760Sstevel@tonic-gate 28770Sstevel@tonic-gate if (flags & FLG_NOTE) 28780Sstevel@tonic-gate note(cache, shnum, Nname, file); 28790Sstevel@tonic-gate 28800Sstevel@tonic-gate if (flags & FLG_MOVE) 28810Sstevel@tonic-gate move(cache, shnum, Nname, file, flags); 28820Sstevel@tonic-gate 28830Sstevel@tonic-gate if (flags & FLG_CHECKSUM) 28840Sstevel@tonic-gate checksum(elf); 28850Sstevel@tonic-gate 28860Sstevel@tonic-gate if (flags & FLG_CAP) 28871618Srie cap(file, cache, shnum, phnum, ehdr, elf); 28880Sstevel@tonic-gate 28890Sstevel@tonic-gate if (flags & FLG_UNWIND) 28901618Srie unwind(cache, shnum, phnum, ehdr, Nname, file, elf); 28910Sstevel@tonic-gate 28920Sstevel@tonic-gate free(cache); 28930Sstevel@tonic-gate } 2894