1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gate /* 29*0Sstevel@tonic-gate * Dump an elf file. 30*0Sstevel@tonic-gate */ 31*0Sstevel@tonic-gate #include <sys/param.h> 32*0Sstevel@tonic-gate #include <fcntl.h> 33*0Sstevel@tonic-gate #include <stdio.h> 34*0Sstevel@tonic-gate #include <libelf.h> 35*0Sstevel@tonic-gate #include <gelf.h> 36*0Sstevel@tonic-gate #include <link.h> 37*0Sstevel@tonic-gate #include <stdarg.h> 38*0Sstevel@tonic-gate #include <unistd.h> 39*0Sstevel@tonic-gate #include <libgen.h> 40*0Sstevel@tonic-gate #include <libintl.h> 41*0Sstevel@tonic-gate #include <locale.h> 42*0Sstevel@tonic-gate #include <errno.h> 43*0Sstevel@tonic-gate #include <strings.h> 44*0Sstevel@tonic-gate #include <sys/elf_SPARC.h> 45*0Sstevel@tonic-gate #include <sys/elf_386.h> 46*0Sstevel@tonic-gate #include <sys/elf_amd64.h> 47*0Sstevel@tonic-gate #include <debug.h> 48*0Sstevel@tonic-gate #include <_debug.h> 49*0Sstevel@tonic-gate #include <conv.h> 50*0Sstevel@tonic-gate #include <msg.h> 51*0Sstevel@tonic-gate #include <dwarf.h> 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate #define FLG_DYNAMIC 0x00000001 54*0Sstevel@tonic-gate #define FLG_EHDR 0x00000002 55*0Sstevel@tonic-gate #define FLG_INTERP 0x00000004 56*0Sstevel@tonic-gate #define FLG_SHDR 0x00000008 57*0Sstevel@tonic-gate #define FLG_NOTE 0x00000010 58*0Sstevel@tonic-gate #define FLG_PHDR 0x00000020 59*0Sstevel@tonic-gate #define FLG_RELOC 0x00000040 60*0Sstevel@tonic-gate #define FLG_SYMBOLS 0x00000080 61*0Sstevel@tonic-gate #define FLG_VERSIONS 0x00000100 62*0Sstevel@tonic-gate #define FLG_HASH 0x00000200 63*0Sstevel@tonic-gate #define FLG_GOT 0x00000400 64*0Sstevel@tonic-gate #define FLG_SYMINFO 0x00000800 65*0Sstevel@tonic-gate #define FLG_MOVE 0x00001000 66*0Sstevel@tonic-gate #define FLG_GROUP 0x00002000 67*0Sstevel@tonic-gate #define FLG_CAP 0x00004000 68*0Sstevel@tonic-gate #define FLG_UNWIND 0x00008000 69*0Sstevel@tonic-gate #define FLG_LONGNAME 0x00100000 /* not done by default */ 70*0Sstevel@tonic-gate #define FLG_CHECKSUM 0x00200000 /* not done by default */ 71*0Sstevel@tonic-gate #define FLG_DEMANGLE 0x00400000 /* not done by default */ 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate #define FLG_EVERYTHING 0x000fffff 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate #define IAM_SPARC(X) \ 76*0Sstevel@tonic-gate ((X == EM_SPARC) || (X == EM_SPARC32PLUS) || (X == EM_SPARCV9)) 77*0Sstevel@tonic-gate #define IAM_INTEL(X) \ 78*0Sstevel@tonic-gate (X == EM_386) 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate #define MAXNDXSIZE 10 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate typedef struct cache { 83*0Sstevel@tonic-gate GElf_Shdr c_shdr; 84*0Sstevel@tonic-gate Elf_Data *c_data; 85*0Sstevel@tonic-gate char *c_name; 86*0Sstevel@tonic-gate } Cache; 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate typedef struct got_info { 89*0Sstevel@tonic-gate GElf_Word g_rshtype; /* it will never happen, but */ 90*0Sstevel@tonic-gate /* support mixed relocations */ 91*0Sstevel@tonic-gate GElf_Rela g_rela; 92*0Sstevel@tonic-gate const char *g_symname; 93*0Sstevel@tonic-gate } Got_info; 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate static const Cache _cache_init = {{0}, NULL, NULL}; 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate const char * 98*0Sstevel@tonic-gate _elfdump_msg(Msg mid) 99*0Sstevel@tonic-gate { 100*0Sstevel@tonic-gate return (gettext(MSG_ORIG(mid))); 101*0Sstevel@tonic-gate } 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate /* 104*0Sstevel@tonic-gate * Determine whether a symbol name should be demangled. 105*0Sstevel@tonic-gate */ 106*0Sstevel@tonic-gate static const char * 107*0Sstevel@tonic-gate demangle(const char *name, uint32_t flags) 108*0Sstevel@tonic-gate { 109*0Sstevel@tonic-gate if (flags & FLG_DEMANGLE) 110*0Sstevel@tonic-gate return (Gelf_sym_dem(name)); 111*0Sstevel@tonic-gate else 112*0Sstevel@tonic-gate return ((char *)name); 113*0Sstevel@tonic-gate } 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate /* 117*0Sstevel@tonic-gate * Define our own printing routine. All Elf routines referenced call upon 118*0Sstevel@tonic-gate * this routine to carry out the actual printing. 119*0Sstevel@tonic-gate */ 120*0Sstevel@tonic-gate /*PRINTFLIKE1*/ 121*0Sstevel@tonic-gate void 122*0Sstevel@tonic-gate dbg_print(const char *format, ...) 123*0Sstevel@tonic-gate { 124*0Sstevel@tonic-gate va_list ap; 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate va_start(ap, format); 127*0Sstevel@tonic-gate (void) vprintf(format, ap); 128*0Sstevel@tonic-gate (void) printf(MSG_ORIG(MSG_STR_NL)); 129*0Sstevel@tonic-gate va_end(ap); 130*0Sstevel@tonic-gate } 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate /* 133*0Sstevel@tonic-gate * Just like dbg_print - except that it does not insert 134*0Sstevel@tonic-gate * a newline at the end. Can be used for printing tables 135*0Sstevel@tonic-gate * and such. 136*0Sstevel@tonic-gate */ 137*0Sstevel@tonic-gate /*PRINTFLIKE1*/ 138*0Sstevel@tonic-gate void 139*0Sstevel@tonic-gate dbg_printf(const char *format, ...) 140*0Sstevel@tonic-gate { 141*0Sstevel@tonic-gate va_list ap; 142*0Sstevel@tonic-gate va_start(ap, format); 143*0Sstevel@tonic-gate (void) vprintf(format, ap); 144*0Sstevel@tonic-gate va_end(ap); 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate /* 150*0Sstevel@tonic-gate * Define our own standard error routine. 151*0Sstevel@tonic-gate */ 152*0Sstevel@tonic-gate static void 153*0Sstevel@tonic-gate failure(const char *file, const char *func) 154*0Sstevel@tonic-gate { 155*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_FAILURE), 156*0Sstevel@tonic-gate file, func, elf_errmsg(elf_errno())); 157*0Sstevel@tonic-gate (void) fflush(stderr); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate /* 162*0Sstevel@tonic-gate * Focal point for verifying symbol names. 163*0Sstevel@tonic-gate */ 164*0Sstevel@tonic-gate static const char * 165*0Sstevel@tonic-gate string(Cache *refsec, GElf_Word ndx, Cache *strsec, const char *file, 166*0Sstevel@tonic-gate ulong_t name) 167*0Sstevel@tonic-gate { 168*0Sstevel@tonic-gate static Cache *osec = 0; 169*0Sstevel@tonic-gate static int nostr; 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate const char *strs = (char *)strsec->c_data->d_buf; 172*0Sstevel@tonic-gate ulong_t strn = strsec->c_data->d_size; 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate /* 175*0Sstevel@tonic-gate * Only print a diagnoistic regarding an empty string table once per 176*0Sstevel@tonic-gate * input section being processed. 177*0Sstevel@tonic-gate */ 178*0Sstevel@tonic-gate if (osec != refsec) { 179*0Sstevel@tonic-gate osec = refsec; 180*0Sstevel@tonic-gate nostr = 0; 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate /* 184*0Sstevel@tonic-gate * Is the string table offset within range of the available strings? 185*0Sstevel@tonic-gate */ 186*0Sstevel@tonic-gate if (name >= strn) { 187*0Sstevel@tonic-gate /* 188*0Sstevel@tonic-gate * Do we have a empty string table? 189*0Sstevel@tonic-gate */ 190*0Sstevel@tonic-gate if (strs == 0) { 191*0Sstevel@tonic-gate if (nostr == 0) { 192*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 193*0Sstevel@tonic-gate file, strsec->c_name); 194*0Sstevel@tonic-gate (void) fflush(stderr); 195*0Sstevel@tonic-gate nostr++; 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate } else { 198*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSTOFF), 199*0Sstevel@tonic-gate file, refsec->c_name, ndx, strsec->c_name, 200*0Sstevel@tonic-gate EC_XWORD(name), EC_XWORD(strn - 1)); 201*0Sstevel@tonic-gate (void) fflush(stderr); 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate /* 205*0Sstevel@tonic-gate * Return the empty string so that the calling function can 206*0Sstevel@tonic-gate * continue it's output diagnostics. 207*0Sstevel@tonic-gate */ 208*0Sstevel@tonic-gate return (MSG_INTL(MSG_STR_UNKNOWN)); 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate return (strs + name); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate /* 214*0Sstevel@tonic-gate * Lookup a symbol and set Sym accordingly. 215*0Sstevel@tonic-gate * 216*0Sstevel@tonic-gate * Returns: 217*0Sstevel@tonic-gate * 1 - symbol found 218*0Sstevel@tonic-gate * 0 - symbol not found 219*0Sstevel@tonic-gate */ 220*0Sstevel@tonic-gate static int 221*0Sstevel@tonic-gate symlookup(const char *name, Cache *cache, GElf_Word shnum, GElf_Sym *sym, 222*0Sstevel@tonic-gate Cache *symtab, const char *file) 223*0Sstevel@tonic-gate { 224*0Sstevel@tonic-gate GElf_Shdr * shdr; 225*0Sstevel@tonic-gate GElf_Word symn, cnt; 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate if (symtab == 0) 228*0Sstevel@tonic-gate return (0); 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate shdr = &symtab->c_shdr; 231*0Sstevel@tonic-gate /* 232*0Sstevel@tonic-gate * Determine the symbol data and number. 233*0Sstevel@tonic-gate */ 234*0Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 235*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 236*0Sstevel@tonic-gate file, symtab->c_name); 237*0Sstevel@tonic-gate (void) fflush(stderr); 238*0Sstevel@tonic-gate return (0); 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate /* LINTED */ 241*0Sstevel@tonic-gate symn = (GElf_Word)(shdr->sh_size / shdr->sh_entsize); 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate /* 244*0Sstevel@tonic-gate * Get the associated string table section. 245*0Sstevel@tonic-gate */ 246*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 247*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 248*0Sstevel@tonic-gate file, symtab->c_name, EC_XWORD(shdr->sh_link)); 249*0Sstevel@tonic-gate (void) fflush(stderr); 250*0Sstevel@tonic-gate return (0); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate /* 254*0Sstevel@tonic-gate * Loop through the symbol table to find a match. 255*0Sstevel@tonic-gate */ 256*0Sstevel@tonic-gate for (cnt = 0; cnt < symn; cnt++) { 257*0Sstevel@tonic-gate GElf_Sym tsym; 258*0Sstevel@tonic-gate const char *sname; 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate if (gelf_getsym(symtab->c_data, cnt, &tsym) == NULL) { 261*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSYM), 262*0Sstevel@tonic-gate file, symtab->c_name, elf_errmsg(0)); 263*0Sstevel@tonic-gate (void) fflush(stderr); 264*0Sstevel@tonic-gate return (0); 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate sname = string(symtab, cnt, &cache[shdr->sh_link], file, 268*0Sstevel@tonic-gate tsym.st_name); 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate if (strcmp(name, sname) == 0) { 271*0Sstevel@tonic-gate *sym = tsym; 272*0Sstevel@tonic-gate return (1); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate } 275*0Sstevel@tonic-gate return (0); 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate /* 279*0Sstevel@tonic-gate * The full usage message 280*0Sstevel@tonic-gate */ 281*0Sstevel@tonic-gate static void 282*0Sstevel@tonic-gate detail_usage() 283*0Sstevel@tonic-gate { 284*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL1)); 285*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL2)); 286*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL3)); 287*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL4)); 288*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL5)); 289*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL6)); 290*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL7)); 291*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL8)); 292*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9)); 293*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9_1)); 294*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL10)); 295*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL11)); 296*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL12)); 297*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL13)); 298*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL14)); 299*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL15)); 300*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL16)); 301*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL17)); 302*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL18)); 303*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL19)); 304*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL20)); 305*0Sstevel@tonic-gate (void) fflush(stderr); 306*0Sstevel@tonic-gate } 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate /* 309*0Sstevel@tonic-gate * Print section headers. 310*0Sstevel@tonic-gate */ 311*0Sstevel@tonic-gate static void 312*0Sstevel@tonic-gate sections(const char *file, Cache *cache, GElf_Word shnum, GElf_Ehdr *ehdr, 313*0Sstevel@tonic-gate const char *name) 314*0Sstevel@tonic-gate { 315*0Sstevel@tonic-gate GElf_Word cnt; 316*0Sstevel@tonic-gate Cache * _cache; 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 319*0Sstevel@tonic-gate GElf_Shdr *shdr; 320*0Sstevel@tonic-gate const char *sname; 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate _cache = &cache[cnt]; 323*0Sstevel@tonic-gate sname = _cache->c_name; 324*0Sstevel@tonic-gate if (name && strcmp(name, sname)) 325*0Sstevel@tonic-gate continue; 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate /* 328*0Sstevel@tonic-gate * Although numerous section header entries can be zero, it's 329*0Sstevel@tonic-gate * usually a sign of trouble if the name or type are zero. 330*0Sstevel@tonic-gate */ 331*0Sstevel@tonic-gate shdr = &_cache->c_shdr; 332*0Sstevel@tonic-gate if (shdr->sh_type == 0) { 333*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE), 334*0Sstevel@tonic-gate file, sname, EC_XWORD(shdr->sh_type)); 335*0Sstevel@tonic-gate (void) fflush(stderr); 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate if (shdr->sh_name == 0) { 338*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHNAME), 339*0Sstevel@tonic-gate file, sname, EC_XWORD(shdr->sh_name)); 340*0Sstevel@tonic-gate (void) fflush(stderr); 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate /* 343*0Sstevel@tonic-gate * Use the empty string, rather than the fabricated 344*0Sstevel@tonic-gate * name for the section output. 345*0Sstevel@tonic-gate */ 346*0Sstevel@tonic-gate sname = MSG_ORIG(MSG_STR_EMPTY); 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 350*0Sstevel@tonic-gate /* LINTED */ 351*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SHDR), (uint_t)cnt, sname); 352*0Sstevel@tonic-gate Gelf_shdr_entry(ehdr->e_machine, shdr); 353*0Sstevel@tonic-gate } 354*0Sstevel@tonic-gate } 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate static void 357*0Sstevel@tonic-gate unwind(Cache *cache, GElf_Word shnum, GElf_Ehdr *ehdr, const char *name, 358*0Sstevel@tonic-gate const char *file, Elf *elf) 359*0Sstevel@tonic-gate { 360*0Sstevel@tonic-gate GElf_Word cnt; 361*0Sstevel@tonic-gate GElf_Phdr unwind_phdr; 362*0Sstevel@tonic-gate /* 363*0Sstevel@tonic-gate * For the moment - UNWIND is only relevant for 364*0Sstevel@tonic-gate * a AMD64 object 365*0Sstevel@tonic-gate */ 366*0Sstevel@tonic-gate if (ehdr->e_machine != EM_AMD64) 367*0Sstevel@tonic-gate return; 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate unwind_phdr.p_type = PT_NULL; 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate for (cnt = 0; cnt < ehdr->e_phnum; cnt++) { 372*0Sstevel@tonic-gate GElf_Phdr phdr; 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate if (gelf_getphdr(elf, cnt, &phdr) == NULL) { 375*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 376*0Sstevel@tonic-gate return; 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate if (phdr.p_type == PT_SUNW_UNWIND) { 380*0Sstevel@tonic-gate unwind_phdr = phdr; 381*0Sstevel@tonic-gate break; 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate } 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 387*0Sstevel@tonic-gate Cache *_cache; 388*0Sstevel@tonic-gate GElf_Shdr *shdr; 389*0Sstevel@tonic-gate unsigned char *data; 390*0Sstevel@tonic-gate size_t datasize; 391*0Sstevel@tonic-gate uint64_t off, ndx; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate _cache = &cache[cnt]; 395*0Sstevel@tonic-gate shdr = &_cache->c_shdr; 396*0Sstevel@tonic-gate /* 397*0Sstevel@tonic-gate * XX64 - this is a strmcp() just to find the gcc 398*0Sstevel@tonic-gate * produced sections. Soon gcc should be 399*0Sstevel@tonic-gate * settng the section type - and we'll not need 400*0Sstevel@tonic-gate * this strcmp(). 401*0Sstevel@tonic-gate */ 402*0Sstevel@tonic-gate if ((shdr->sh_type != SHT_AMD64_UNWIND) && 403*0Sstevel@tonic-gate (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM), 404*0Sstevel@tonic-gate MSG_SCN_FRM_SIZE) != 0) && 405*0Sstevel@tonic-gate (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 406*0Sstevel@tonic-gate MSG_SCN_FRMHDR_SIZE) != 0)) 407*0Sstevel@tonic-gate continue; 408*0Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 409*0Sstevel@tonic-gate continue; 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 412*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name); 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate data = (unsigned char *)(_cache->c_data->d_buf); 415*0Sstevel@tonic-gate datasize = _cache->c_data->d_size; 416*0Sstevel@tonic-gate off = 0; 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate /* 419*0Sstevel@tonic-gate * Is this a .eh_frame_hdr 420*0Sstevel@tonic-gate */ 421*0Sstevel@tonic-gate if (((unwind_phdr.p_type == PT_SUNW_UNWIND) && 422*0Sstevel@tonic-gate (shdr->sh_addr == unwind_phdr.p_vaddr)) || 423*0Sstevel@tonic-gate (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 424*0Sstevel@tonic-gate MSG_SCN_FRMHDR_SIZE) == 0)) { 425*0Sstevel@tonic-gate uint_t vers; 426*0Sstevel@tonic-gate uint_t frame_ptr_enc; 427*0Sstevel@tonic-gate uint64_t frame_ptr; 428*0Sstevel@tonic-gate uint_t fde_cnt_enc; 429*0Sstevel@tonic-gate uint64_t fde_cnt; 430*0Sstevel@tonic-gate uint_t table_enc; 431*0Sstevel@tonic-gate uint64_t tabndx; 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_FRMHDR)); 434*0Sstevel@tonic-gate ndx = 0; 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate vers = data[ndx++]; 437*0Sstevel@tonic-gate frame_ptr_enc = data[ndx++]; 438*0Sstevel@tonic-gate fde_cnt_enc = data[ndx++]; 439*0Sstevel@tonic-gate table_enc = data[ndx++]; 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_FRMVERS), vers); 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate frame_ptr = dwarf_ehe_extract(data, 444*0Sstevel@tonic-gate &ndx, frame_ptr_enc, ehdr->e_ident, 445*0Sstevel@tonic-gate shdr->sh_addr + ndx); 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_FRPTRENC), 448*0Sstevel@tonic-gate conv_dwarf_ehe_str(frame_ptr_enc), 449*0Sstevel@tonic-gate frame_ptr); 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate fde_cnt = dwarf_ehe_extract(data, 452*0Sstevel@tonic-gate &ndx, fde_cnt_enc, ehdr->e_ident, 453*0Sstevel@tonic-gate shdr->sh_addr + ndx); 454*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_FDCNENC), 455*0Sstevel@tonic-gate conv_dwarf_ehe_str(fde_cnt_enc), 456*0Sstevel@tonic-gate fde_cnt); 457*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_TABENC), 458*0Sstevel@tonic-gate conv_dwarf_ehe_str(table_enc)); 459*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_BINSRTAB1)); 460*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_BINSRTAB2)); 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate for (tabndx = 0; tabndx < fde_cnt; tabndx++) { 463*0Sstevel@tonic-gate uint64_t init_loc; 464*0Sstevel@tonic-gate uint64_t fde_loc; 465*0Sstevel@tonic-gate init_loc = dwarf_ehe_extract(data, 466*0Sstevel@tonic-gate &ndx, table_enc, ehdr->e_ident, 467*0Sstevel@tonic-gate shdr->sh_addr); 468*0Sstevel@tonic-gate fde_loc = dwarf_ehe_extract(data, 469*0Sstevel@tonic-gate &ndx, table_enc, ehdr->e_ident, 470*0Sstevel@tonic-gate shdr->sh_addr); 471*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_BINSRTABENT), 472*0Sstevel@tonic-gate init_loc, fde_loc); 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate continue; 475*0Sstevel@tonic-gate } 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate /* 478*0Sstevel@tonic-gate * Walk the Eh_frame's 479*0Sstevel@tonic-gate */ 480*0Sstevel@tonic-gate while (off < datasize) { 481*0Sstevel@tonic-gate uint_t cieid, cielength, cieversion, 482*0Sstevel@tonic-gate cieretaddr; 483*0Sstevel@tonic-gate int cieRflag, cieLflag, 484*0Sstevel@tonic-gate ciePflag, cieZflag; 485*0Sstevel@tonic-gate uint_t length, id; 486*0Sstevel@tonic-gate uint64_t ciecalign, ciedalign; 487*0Sstevel@tonic-gate char *cieaugstr; 488*0Sstevel@tonic-gate uint_t cieaugndx; 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate ndx = 0; 491*0Sstevel@tonic-gate /* 492*0Sstevel@tonic-gate * extract length in lsb format 493*0Sstevel@tonic-gate */ 494*0Sstevel@tonic-gate length = LSB32EXTRACT(data + off + ndx); 495*0Sstevel@tonic-gate ndx += 4; 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate /* 498*0Sstevel@tonic-gate * extract CIE id in lsb format 499*0Sstevel@tonic-gate */ 500*0Sstevel@tonic-gate id = LSB32EXTRACT(data + off + ndx); 501*0Sstevel@tonic-gate ndx += 4; 502*0Sstevel@tonic-gate 503*0Sstevel@tonic-gate /* 504*0Sstevel@tonic-gate * A CIE record has a id of '0', otherwise 505*0Sstevel@tonic-gate * this is a FDE entry and the 'id' is the 506*0Sstevel@tonic-gate * CIE pointer. 507*0Sstevel@tonic-gate */ 508*0Sstevel@tonic-gate if (id == 0) { 509*0Sstevel@tonic-gate uint64_t persVal; 510*0Sstevel@tonic-gate cielength = length; 511*0Sstevel@tonic-gate cieid = id; 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate cieLflag = 0; 514*0Sstevel@tonic-gate ciePflag = 0; 515*0Sstevel@tonic-gate cieRflag = 0; 516*0Sstevel@tonic-gate cieZflag = 0; 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_CIE), 519*0Sstevel@tonic-gate shdr->sh_addr + off); 520*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_CIELNGTH), 521*0Sstevel@tonic-gate cielength, cieid); 522*0Sstevel@tonic-gate cieversion = data[off + ndx]; 523*0Sstevel@tonic-gate ndx += 1; 524*0Sstevel@tonic-gate cieaugstr = (char *)(&data[off + ndx]); 525*0Sstevel@tonic-gate ndx += strlen(cieaugstr) + 1; 526*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_CIEVERS), 527*0Sstevel@tonic-gate cieversion, cieaugstr); 528*0Sstevel@tonic-gate ciecalign = uleb_extract(&data[off], &ndx); 529*0Sstevel@tonic-gate ciedalign = sleb_extract(&data[off], &ndx); 530*0Sstevel@tonic-gate cieretaddr = data[off + ndx]; 531*0Sstevel@tonic-gate ndx += 1; 532*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_CIECALGN), 533*0Sstevel@tonic-gate ciecalign, ciedalign, cieretaddr); 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate if (cieaugstr[0]) 536*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_CIEAUXVAL)); 537*0Sstevel@tonic-gate for (cieaugndx = 0; cieaugstr[cieaugndx]; 538*0Sstevel@tonic-gate cieaugndx++) { 539*0Sstevel@tonic-gate uint_t val; 540*0Sstevel@tonic-gate switch (cieaugstr[cieaugndx]) { 541*0Sstevel@tonic-gate case 'z': 542*0Sstevel@tonic-gate val = uleb_extract(&data[off], 543*0Sstevel@tonic-gate &ndx); 544*0Sstevel@tonic-gate dbg_print( 545*0Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXSIZE), 546*0Sstevel@tonic-gate val); 547*0Sstevel@tonic-gate cieZflag = 1; 548*0Sstevel@tonic-gate break; 549*0Sstevel@tonic-gate case 'P': 550*0Sstevel@tonic-gate ciePflag = data[off + ndx]; 551*0Sstevel@tonic-gate ndx += 1; 552*0Sstevel@tonic-gate 553*0Sstevel@tonic-gate persVal = dwarf_ehe_extract( 554*0Sstevel@tonic-gate &data[off], 555*0Sstevel@tonic-gate &ndx, ciePflag, ehdr->e_ident, 556*0Sstevel@tonic-gate shdr->sh_addr + off + ndx); 557*0Sstevel@tonic-gate dbg_print( 558*0Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXPERS), 559*0Sstevel@tonic-gate ciePflag, 560*0Sstevel@tonic-gate conv_dwarf_ehe_str(ciePflag), 561*0Sstevel@tonic-gate EC_XWORD(persVal)); 562*0Sstevel@tonic-gate break; 563*0Sstevel@tonic-gate case 'R': 564*0Sstevel@tonic-gate val = data[off + ndx]; 565*0Sstevel@tonic-gate ndx += 1; 566*0Sstevel@tonic-gate dbg_print( 567*0Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXCENC), 568*0Sstevel@tonic-gate val, conv_dwarf_ehe_str(val)); 569*0Sstevel@tonic-gate cieRflag = val; 570*0Sstevel@tonic-gate break; 571*0Sstevel@tonic-gate case 'L': 572*0Sstevel@tonic-gate val = data[off + ndx]; 573*0Sstevel@tonic-gate ndx += 1; 574*0Sstevel@tonic-gate dbg_print( 575*0Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXLSDA), 576*0Sstevel@tonic-gate val, conv_dwarf_ehe_str(val)); 577*0Sstevel@tonic-gate cieLflag = val; 578*0Sstevel@tonic-gate break; 579*0Sstevel@tonic-gate default: 580*0Sstevel@tonic-gate dbg_print( 581*0Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIEAUXUNEC), 582*0Sstevel@tonic-gate cieaugstr[cieaugndx]); 583*0Sstevel@tonic-gate break; 584*0Sstevel@tonic-gate } 585*0Sstevel@tonic-gate } 586*0Sstevel@tonic-gate if ((cielength + 4) > ndx) { 587*0Sstevel@tonic-gate uint_t cnt; 588*0Sstevel@tonic-gate dbg_printf(MSG_ORIG(MSG_UNW_CIECFI)); 589*0Sstevel@tonic-gate cnt = 0; 590*0Sstevel@tonic-gate while (ndx < (cielength + 4)) { 591*0Sstevel@tonic-gate if ((cnt++ % 8) == 0) { 592*0Sstevel@tonic-gate dbg_printf( 593*0Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIECFI1)); 594*0Sstevel@tonic-gate } 595*0Sstevel@tonic-gate dbg_printf( 596*0Sstevel@tonic-gate MSG_ORIG(MSG_UNW_CIECFI2), 597*0Sstevel@tonic-gate data[off + ndx++]); 598*0Sstevel@tonic-gate } 599*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 600*0Sstevel@tonic-gate } 601*0Sstevel@tonic-gate off += cielength + 4; 602*0Sstevel@tonic-gate } else { 603*0Sstevel@tonic-gate uint_t fdelength = length; 604*0Sstevel@tonic-gate int fdecieptr = id; 605*0Sstevel@tonic-gate uint64_t fdeinitloc, fdeaddrrange; 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_FDE), 608*0Sstevel@tonic-gate shdr->sh_addr + off); 609*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_FDELNGTH), 610*0Sstevel@tonic-gate fdelength, fdecieptr); 611*0Sstevel@tonic-gate fdeinitloc = dwarf_ehe_extract(&data[off], 612*0Sstevel@tonic-gate &ndx, cieRflag, ehdr->e_ident, 613*0Sstevel@tonic-gate shdr->sh_addr + off + ndx); 614*0Sstevel@tonic-gate fdeaddrrange = dwarf_ehe_extract(&data[off], 615*0Sstevel@tonic-gate &ndx, (cieRflag & ~DW_EH_PE_pcrel), 616*0Sstevel@tonic-gate ehdr->e_ident, 617*0Sstevel@tonic-gate shdr->sh_addr + off + ndx); 618*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_FDEINITLOC), 619*0Sstevel@tonic-gate fdeinitloc, fdeaddrrange); 620*0Sstevel@tonic-gate if (cieaugstr[0]) 621*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_UNW_FDEAUXVAL)); 622*0Sstevel@tonic-gate if (cieZflag) { 623*0Sstevel@tonic-gate uint64_t val; 624*0Sstevel@tonic-gate val = uleb_extract(&data[off], &ndx); 625*0Sstevel@tonic-gate dbg_print( 626*0Sstevel@tonic-gate MSG_ORIG(MSG_UNW_FDEAUXSIZE), val); 627*0Sstevel@tonic-gate if (val & cieLflag) { 628*0Sstevel@tonic-gate fdeinitloc = dwarf_ehe_extract( 629*0Sstevel@tonic-gate &data[off], &ndx, cieLflag, 630*0Sstevel@tonic-gate ehdr->e_ident, 631*0Sstevel@tonic-gate shdr->sh_addr + off + ndx); 632*0Sstevel@tonic-gate dbg_print( 633*0Sstevel@tonic-gate MSG_ORIG(MSG_UNW_FDEAUXLSDA), 634*0Sstevel@tonic-gate val); 635*0Sstevel@tonic-gate } 636*0Sstevel@tonic-gate } 637*0Sstevel@tonic-gate if ((fdelength + 4) > ndx) { 638*0Sstevel@tonic-gate uint_t cnt; 639*0Sstevel@tonic-gate dbg_printf(MSG_ORIG(MSG_UNW_FDECFI)); 640*0Sstevel@tonic-gate cnt = 0; 641*0Sstevel@tonic-gate while (ndx < (fdelength + 4)) { 642*0Sstevel@tonic-gate if ((cnt++ % 8) == 0) { 643*0Sstevel@tonic-gate dbg_printf( 644*0Sstevel@tonic-gate MSG_ORIG(MSG_UNW_FDECFI1)); 645*0Sstevel@tonic-gate } 646*0Sstevel@tonic-gate dbg_printf( 647*0Sstevel@tonic-gate MSG_ORIG(MSG_UNW_FDECFI2), 648*0Sstevel@tonic-gate data[off + ndx++]); 649*0Sstevel@tonic-gate } 650*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 651*0Sstevel@tonic-gate } 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate off += fdelength + 4; 654*0Sstevel@tonic-gate } 655*0Sstevel@tonic-gate } 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate } 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate /* 660*0Sstevel@tonic-gate * Print the hardware/software capabilities. For executables and shared objects 661*0Sstevel@tonic-gate * this should be accompanied with a program header. 662*0Sstevel@tonic-gate */ 663*0Sstevel@tonic-gate static void 664*0Sstevel@tonic-gate cap(const char *file, Cache *cache, GElf_Word shnum, GElf_Ehdr *ehdr, 665*0Sstevel@tonic-gate Elf *elf) 666*0Sstevel@tonic-gate { 667*0Sstevel@tonic-gate GElf_Word cnt; 668*0Sstevel@tonic-gate GElf_Shdr * cshdr = 0; 669*0Sstevel@tonic-gate Cache * ccache; 670*0Sstevel@tonic-gate Elf64_Off cphdr_off = 0; 671*0Sstevel@tonic-gate Elf64_Xword cphdr_sz; 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate /* 674*0Sstevel@tonic-gate * Determine if a hardware/software capabilities header exists. 675*0Sstevel@tonic-gate */ 676*0Sstevel@tonic-gate for (cnt = 0; cnt < ehdr->e_phnum; cnt++) { 677*0Sstevel@tonic-gate GElf_Phdr phdr; 678*0Sstevel@tonic-gate 679*0Sstevel@tonic-gate if (gelf_getphdr(elf, cnt, &phdr) == NULL) { 680*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 681*0Sstevel@tonic-gate return; 682*0Sstevel@tonic-gate } 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate if (phdr.p_type == PT_SUNWCAP) { 685*0Sstevel@tonic-gate cphdr_off = phdr.p_offset; 686*0Sstevel@tonic-gate cphdr_sz = phdr.p_filesz; 687*0Sstevel@tonic-gate break; 688*0Sstevel@tonic-gate } 689*0Sstevel@tonic-gate } 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gate /* 692*0Sstevel@tonic-gate * Determine if a hardware/software capabilities section exists. 693*0Sstevel@tonic-gate */ 694*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 695*0Sstevel@tonic-gate Cache * _cache; 696*0Sstevel@tonic-gate GElf_Shdr *shdr; 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gate _cache = &cache[cnt]; 699*0Sstevel@tonic-gate shdr = &_cache->c_shdr; 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate if (shdr->sh_type != SHT_SUNW_cap) 702*0Sstevel@tonic-gate continue; 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate if (cphdr_off && ((cphdr_off < shdr->sh_offset) || 705*0Sstevel@tonic-gate (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size))) 706*0Sstevel@tonic-gate continue; 707*0Sstevel@tonic-gate 708*0Sstevel@tonic-gate ccache = _cache; 709*0Sstevel@tonic-gate cshdr = shdr; 710*0Sstevel@tonic-gate break; 711*0Sstevel@tonic-gate } 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate if ((cshdr == 0) && (cphdr_off == 0)) 714*0Sstevel@tonic-gate return; 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate /* 717*0Sstevel@tonic-gate * Print the hardware/software capabilities section. 718*0Sstevel@tonic-gate */ 719*0Sstevel@tonic-gate if (cshdr) { 720*0Sstevel@tonic-gate GElf_Word ndx, capn; 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 723*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name); 724*0Sstevel@tonic-gate 725*0Sstevel@tonic-gate Gelf_cap_title(); 726*0Sstevel@tonic-gate 727*0Sstevel@tonic-gate /* LINTED */ 728*0Sstevel@tonic-gate capn = (GElf_Word)(cshdr->sh_size / cshdr->sh_entsize); 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate /* LINTED */ 731*0Sstevel@tonic-gate for (ndx = 0; ndx < capn; ndx++) { 732*0Sstevel@tonic-gate GElf_Cap cap; 733*0Sstevel@tonic-gate 734*0Sstevel@tonic-gate if (gelf_getcap(ccache->c_data, ndx, &cap) == NULL) { 735*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADCAP), 736*0Sstevel@tonic-gate file, ccache->c_name, elf_errmsg(0)); 737*0Sstevel@tonic-gate (void) fflush(stderr); 738*0Sstevel@tonic-gate return; 739*0Sstevel@tonic-gate } 740*0Sstevel@tonic-gate if (cap.c_tag != CA_SUNW_NULL) 741*0Sstevel@tonic-gate Gelf_cap_print(&cap, ndx, ehdr->e_machine); 742*0Sstevel@tonic-gate } 743*0Sstevel@tonic-gate } else 744*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file); 745*0Sstevel@tonic-gate 746*0Sstevel@tonic-gate /* 747*0Sstevel@tonic-gate * If this object is an executable or shared object, then the 748*0Sstevel@tonic-gate * hardware/software capabilities section should have an accompanying 749*0Sstevel@tonic-gate * program header. 750*0Sstevel@tonic-gate */ 751*0Sstevel@tonic-gate if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) { 752*0Sstevel@tonic-gate if (cphdr_off == 0) 753*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2), 754*0Sstevel@tonic-gate file, ccache->c_name); 755*0Sstevel@tonic-gate else if ((cphdr_off != cshdr->sh_offset) || 756*0Sstevel@tonic-gate (cphdr_sz != cshdr->sh_size)) 757*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3), 758*0Sstevel@tonic-gate file, ccache->c_name); 759*0Sstevel@tonic-gate } 760*0Sstevel@tonic-gate } 761*0Sstevel@tonic-gate 762*0Sstevel@tonic-gate /* 763*0Sstevel@tonic-gate * Print the interpretor. 764*0Sstevel@tonic-gate */ 765*0Sstevel@tonic-gate static void 766*0Sstevel@tonic-gate interp(const char *file, Cache *cache, GElf_Word shnum, GElf_Ehdr *ehdr, 767*0Sstevel@tonic-gate Elf *elf) 768*0Sstevel@tonic-gate { 769*0Sstevel@tonic-gate GElf_Word cnt; 770*0Sstevel@tonic-gate GElf_Shdr * ishdr = 0; 771*0Sstevel@tonic-gate Cache * icache; 772*0Sstevel@tonic-gate Elf64_Off iphdr_off = 0; 773*0Sstevel@tonic-gate Elf64_Xword iphdr_sz; 774*0Sstevel@tonic-gate 775*0Sstevel@tonic-gate /* 776*0Sstevel@tonic-gate * Determine if an interp header exists. 777*0Sstevel@tonic-gate */ 778*0Sstevel@tonic-gate for (cnt = 0; cnt < ehdr->e_phnum; cnt++) { 779*0Sstevel@tonic-gate GElf_Phdr phdr; 780*0Sstevel@tonic-gate 781*0Sstevel@tonic-gate if (gelf_getphdr(elf, cnt, &phdr) == NULL) { 782*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 783*0Sstevel@tonic-gate return; 784*0Sstevel@tonic-gate } 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate if (phdr.p_type == PT_INTERP) { 787*0Sstevel@tonic-gate iphdr_off = phdr.p_offset; 788*0Sstevel@tonic-gate iphdr_sz = phdr.p_filesz; 789*0Sstevel@tonic-gate break; 790*0Sstevel@tonic-gate } 791*0Sstevel@tonic-gate } 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate if (iphdr_off == 0) 794*0Sstevel@tonic-gate return; 795*0Sstevel@tonic-gate 796*0Sstevel@tonic-gate /* 797*0Sstevel@tonic-gate * Determine if an interp section exists. 798*0Sstevel@tonic-gate */ 799*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 800*0Sstevel@tonic-gate Cache * _cache; 801*0Sstevel@tonic-gate GElf_Shdr *shdr; 802*0Sstevel@tonic-gate 803*0Sstevel@tonic-gate _cache = &cache[cnt]; 804*0Sstevel@tonic-gate shdr = &_cache->c_shdr; 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate /* 807*0Sstevel@tonic-gate * Scan sections to find a section which contains the PT_INTERP 808*0Sstevel@tonic-gate * string. The target section can't be in a NOBITS section. 809*0Sstevel@tonic-gate */ 810*0Sstevel@tonic-gate if ((shdr->sh_type == SHT_NOBITS) || 811*0Sstevel@tonic-gate (iphdr_off < shdr->sh_offset) || 812*0Sstevel@tonic-gate (iphdr_off + iphdr_sz) > (shdr->sh_offset + shdr->sh_size)) 813*0Sstevel@tonic-gate continue; 814*0Sstevel@tonic-gate 815*0Sstevel@tonic-gate icache = _cache; 816*0Sstevel@tonic-gate ishdr = shdr; 817*0Sstevel@tonic-gate break; 818*0Sstevel@tonic-gate } 819*0Sstevel@tonic-gate 820*0Sstevel@tonic-gate /* 821*0Sstevel@tonic-gate * Print the interpreter string based on the offset defined in the 822*0Sstevel@tonic-gate * program header, as this is the offset used by the kernel. 823*0Sstevel@tonic-gate */ 824*0Sstevel@tonic-gate if (ishdr) { 825*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 826*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name); 827*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_FMT_INDENT), 828*0Sstevel@tonic-gate (char *)icache->c_data->d_buf + 829*0Sstevel@tonic-gate (iphdr_off - ishdr->sh_offset)); 830*0Sstevel@tonic-gate } else 831*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file); 832*0Sstevel@tonic-gate 833*0Sstevel@tonic-gate /* 834*0Sstevel@tonic-gate * If there are any inconsistences between the program header and 835*0Sstevel@tonic-gate * section information, flag them. 836*0Sstevel@tonic-gate */ 837*0Sstevel@tonic-gate if (ishdr && ((iphdr_off != ishdr->sh_offset) || 838*0Sstevel@tonic-gate (iphdr_sz != ishdr->sh_size))) { 839*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file, 840*0Sstevel@tonic-gate icache->c_name); 841*0Sstevel@tonic-gate (void) fflush(stderr); 842*0Sstevel@tonic-gate } 843*0Sstevel@tonic-gate } 844*0Sstevel@tonic-gate 845*0Sstevel@tonic-gate /* 846*0Sstevel@tonic-gate * Print the syminfo section. 847*0Sstevel@tonic-gate */ 848*0Sstevel@tonic-gate static void 849*0Sstevel@tonic-gate syminfo(Cache *cache, GElf_Word shnum, const char *file) 850*0Sstevel@tonic-gate { 851*0Sstevel@tonic-gate GElf_Shdr *shdr; 852*0Sstevel@tonic-gate Elf_Data *dsyms, *ddyn; 853*0Sstevel@tonic-gate GElf_Word symn, cnt, ndx; 854*0Sstevel@tonic-gate Cache *syminfo = 0; 855*0Sstevel@tonic-gate char *sname; 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 858*0Sstevel@tonic-gate if (cache[cnt].c_shdr.sh_type == SHT_SUNW_syminfo) { 859*0Sstevel@tonic-gate syminfo = &cache[cnt]; 860*0Sstevel@tonic-gate break; 861*0Sstevel@tonic-gate } 862*0Sstevel@tonic-gate } 863*0Sstevel@tonic-gate if (syminfo == 0) 864*0Sstevel@tonic-gate return; 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate shdr = &syminfo->c_shdr; 867*0Sstevel@tonic-gate /* 868*0Sstevel@tonic-gate * Determine the symbol info data and number. 869*0Sstevel@tonic-gate */ 870*0Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 871*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 872*0Sstevel@tonic-gate file, syminfo->c_name); 873*0Sstevel@tonic-gate (void) fflush(stderr); 874*0Sstevel@tonic-gate return; 875*0Sstevel@tonic-gate } 876*0Sstevel@tonic-gate /* LINTED */ 877*0Sstevel@tonic-gate symn = (GElf_Word)(shdr->sh_size / shdr->sh_entsize); 878*0Sstevel@tonic-gate 879*0Sstevel@tonic-gate /* 880*0Sstevel@tonic-gate * Get the data buffer of the associated dynamic section. 881*0Sstevel@tonic-gate */ 882*0Sstevel@tonic-gate if ((shdr->sh_info == 0) || (shdr->sh_info >= shnum)) { 883*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 884*0Sstevel@tonic-gate file, syminfo->c_name, EC_XWORD(shdr->sh_info)); 885*0Sstevel@tonic-gate (void) fflush(stderr); 886*0Sstevel@tonic-gate return; 887*0Sstevel@tonic-gate } 888*0Sstevel@tonic-gate ddyn = cache[shdr->sh_info].c_data; 889*0Sstevel@tonic-gate if (ddyn->d_buf == 0) { 890*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 891*0Sstevel@tonic-gate file, cache[shdr->sh_info].c_name); 892*0Sstevel@tonic-gate (void) fflush(stderr); 893*0Sstevel@tonic-gate return; 894*0Sstevel@tonic-gate } 895*0Sstevel@tonic-gate 896*0Sstevel@tonic-gate /* 897*0Sstevel@tonic-gate * Get the data buffer of the associated symbol table. 898*0Sstevel@tonic-gate */ 899*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 900*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 901*0Sstevel@tonic-gate file, syminfo->c_name, EC_XWORD(shdr->sh_link)); 902*0Sstevel@tonic-gate (void) fflush(stderr); 903*0Sstevel@tonic-gate return; 904*0Sstevel@tonic-gate } 905*0Sstevel@tonic-gate dsyms = cache[shdr->sh_link].c_data; 906*0Sstevel@tonic-gate if (dsyms->d_buf == 0) { 907*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 908*0Sstevel@tonic-gate file, cache[shdr->sh_link].c_name); 909*0Sstevel@tonic-gate (void) fflush(stderr); 910*0Sstevel@tonic-gate return; 911*0Sstevel@tonic-gate } 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate sname = cache[shdr->sh_link].c_name; 914*0Sstevel@tonic-gate shdr = &cache[shdr->sh_link].c_shdr; 915*0Sstevel@tonic-gate /* 916*0Sstevel@tonic-gate * Get the associated string table section. 917*0Sstevel@tonic-gate */ 918*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 919*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 920*0Sstevel@tonic-gate file, sname, EC_XWORD(shdr->sh_link)); 921*0Sstevel@tonic-gate (void) fflush(stderr); 922*0Sstevel@tonic-gate return; 923*0Sstevel@tonic-gate } 924*0Sstevel@tonic-gate 925*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 926*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SCN_SYMINFO), syminfo->c_name); 927*0Sstevel@tonic-gate Gelf_syminfo_title(); 928*0Sstevel@tonic-gate 929*0Sstevel@tonic-gate for (ndx = 1; ndx < symn; ndx++) { 930*0Sstevel@tonic-gate GElf_Syminfo gsip; 931*0Sstevel@tonic-gate GElf_Sym gsym; 932*0Sstevel@tonic-gate GElf_Dyn gdyn; 933*0Sstevel@tonic-gate const char *needed, *sname; 934*0Sstevel@tonic-gate 935*0Sstevel@tonic-gate if (gelf_getsyminfo(syminfo->c_data, ndx, &gsip) == 0) { 936*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_SIBADCOUNT), 937*0Sstevel@tonic-gate file, syminfo->c_name, ndx); 938*0Sstevel@tonic-gate (void) fflush(stderr); 939*0Sstevel@tonic-gate return; 940*0Sstevel@tonic-gate } 941*0Sstevel@tonic-gate if ((gsip.si_flags == 0) && (gsip.si_boundto == 0)) 942*0Sstevel@tonic-gate continue; 943*0Sstevel@tonic-gate 944*0Sstevel@tonic-gate if (gelf_getsym(dsyms, ndx, &gsym) == 0) { 945*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSYM), 946*0Sstevel@tonic-gate file, syminfo->c_name, elf_errmsg(0)); 947*0Sstevel@tonic-gate (void) fflush(stderr); 948*0Sstevel@tonic-gate return; 949*0Sstevel@tonic-gate } 950*0Sstevel@tonic-gate 951*0Sstevel@tonic-gate sname = string(syminfo, cnt, &cache[shdr->sh_link], file, 952*0Sstevel@tonic-gate gsym.st_name); 953*0Sstevel@tonic-gate needed = 0; 954*0Sstevel@tonic-gate 955*0Sstevel@tonic-gate if (gsip.si_boundto < SYMINFO_BT_LOWRESERVE) { 956*0Sstevel@tonic-gate if (gelf_getdyn(ddyn, gsip.si_boundto, &gdyn) == 0) { 957*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADDYN), 958*0Sstevel@tonic-gate file, syminfo->c_name, gsip.si_boundto); 959*0Sstevel@tonic-gate (void) fflush(stderr); 960*0Sstevel@tonic-gate return; 961*0Sstevel@tonic-gate } 962*0Sstevel@tonic-gate needed = string(syminfo, gsip.si_boundto, 963*0Sstevel@tonic-gate &cache[shdr->sh_link], file, gdyn.d_un.d_val); 964*0Sstevel@tonic-gate } 965*0Sstevel@tonic-gate 966*0Sstevel@tonic-gate Gelf_syminfo_entry(ndx, &gsip, sname, needed); 967*0Sstevel@tonic-gate } 968*0Sstevel@tonic-gate } 969*0Sstevel@tonic-gate 970*0Sstevel@tonic-gate /* 971*0Sstevel@tonic-gate * Print version definition section entries. 972*0Sstevel@tonic-gate */ 973*0Sstevel@tonic-gate static void 974*0Sstevel@tonic-gate version_def(GElf_Verdef *vdf, GElf_Word shnum, Cache *vcache, Cache *scache, 975*0Sstevel@tonic-gate const char *file) 976*0Sstevel@tonic-gate { 977*0Sstevel@tonic-gate GElf_Word cnt; 978*0Sstevel@tonic-gate char index[MAXNDXSIZE]; 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate Gelf_ver_def_title(); 981*0Sstevel@tonic-gate 982*0Sstevel@tonic-gate for (cnt = 1; cnt <= shnum; cnt++, 983*0Sstevel@tonic-gate vdf = (GElf_Verdef *)((uintptr_t)vdf + vdf->vd_next)) { 984*0Sstevel@tonic-gate 985*0Sstevel@tonic-gate GElf_Half vcnt = vdf->vd_cnt - 1; 986*0Sstevel@tonic-gate GElf_Half ndx = vdf->vd_ndx; 987*0Sstevel@tonic-gate GElf_Verdaux *vdap = (GElf_Verdaux *) 988*0Sstevel@tonic-gate ((uintptr_t)vdf + vdf->vd_aux); 989*0Sstevel@tonic-gate const char *name, *dep; 990*0Sstevel@tonic-gate 991*0Sstevel@tonic-gate /* 992*0Sstevel@tonic-gate * Obtain the name and first dependency (if any). 993*0Sstevel@tonic-gate */ 994*0Sstevel@tonic-gate name = string(vcache, cnt, scache, file, vdap->vda_name); 995*0Sstevel@tonic-gate vdap = (GElf_Verdaux *)((uintptr_t)vdap + vdap->vda_next); 996*0Sstevel@tonic-gate if (vcnt) 997*0Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, vdap->vda_name); 998*0Sstevel@tonic-gate else 999*0Sstevel@tonic-gate dep = MSG_ORIG(MSG_STR_EMPTY); 1000*0Sstevel@tonic-gate 1001*0Sstevel@tonic-gate (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX), 1002*0Sstevel@tonic-gate EC_XWORD(ndx)); 1003*0Sstevel@tonic-gate Gelf_ver_line_1(index, name, dep, 1004*0Sstevel@tonic-gate conv_verflg_str(vdf->vd_flags)); 1005*0Sstevel@tonic-gate 1006*0Sstevel@tonic-gate /* 1007*0Sstevel@tonic-gate * Print any additional dependencies. 1008*0Sstevel@tonic-gate */ 1009*0Sstevel@tonic-gate if (vcnt) { 1010*0Sstevel@tonic-gate vdap = (GElf_Verdaux *)((uintptr_t)vdap + 1011*0Sstevel@tonic-gate vdap->vda_next); 1012*0Sstevel@tonic-gate for (vcnt--; vcnt; vcnt--, 1013*0Sstevel@tonic-gate vdap = (GElf_Verdaux *)((uintptr_t)vdap + 1014*0Sstevel@tonic-gate vdap->vda_next)) { 1015*0Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, 1016*0Sstevel@tonic-gate vdap->vda_name); 1017*0Sstevel@tonic-gate Gelf_ver_line_2(MSG_ORIG(MSG_STR_EMPTY), dep); 1018*0Sstevel@tonic-gate } 1019*0Sstevel@tonic-gate } 1020*0Sstevel@tonic-gate } 1021*0Sstevel@tonic-gate } 1022*0Sstevel@tonic-gate 1023*0Sstevel@tonic-gate /* 1024*0Sstevel@tonic-gate * Print a version needed section entries. 1025*0Sstevel@tonic-gate */ 1026*0Sstevel@tonic-gate static void 1027*0Sstevel@tonic-gate version_need(GElf_Verneed *vnd, GElf_Word shnum, Cache *vcache, Cache *scache, 1028*0Sstevel@tonic-gate const char *file) 1029*0Sstevel@tonic-gate { 1030*0Sstevel@tonic-gate GElf_Word cnt; 1031*0Sstevel@tonic-gate 1032*0Sstevel@tonic-gate Gelf_ver_need_title(); 1033*0Sstevel@tonic-gate 1034*0Sstevel@tonic-gate for (cnt = 1; cnt <= shnum; cnt++, 1035*0Sstevel@tonic-gate vnd = (GElf_Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 1036*0Sstevel@tonic-gate 1037*0Sstevel@tonic-gate GElf_Half vcnt = vnd->vn_cnt; 1038*0Sstevel@tonic-gate GElf_Vernaux *vnap = (GElf_Vernaux *)((uintptr_t)vnd + 1039*0Sstevel@tonic-gate vnd->vn_aux); 1040*0Sstevel@tonic-gate const char *name, *dep; 1041*0Sstevel@tonic-gate 1042*0Sstevel@tonic-gate /* 1043*0Sstevel@tonic-gate * Obtain the name of the needed file and the version name 1044*0Sstevel@tonic-gate * within it that we're dependent on. Note that the count 1045*0Sstevel@tonic-gate * should be at least one, otherwise this is a pretty bogus 1046*0Sstevel@tonic-gate * entry. 1047*0Sstevel@tonic-gate */ 1048*0Sstevel@tonic-gate name = string(vcache, cnt, scache, file, vnd->vn_file); 1049*0Sstevel@tonic-gate if (vcnt) 1050*0Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, vnap->vna_name); 1051*0Sstevel@tonic-gate else 1052*0Sstevel@tonic-gate dep = MSG_INTL(MSG_STR_NULL); 1053*0Sstevel@tonic-gate 1054*0Sstevel@tonic-gate Gelf_ver_line_1(MSG_ORIG(MSG_STR_EMPTY), name, dep, 1055*0Sstevel@tonic-gate conv_verflg_str(vnap->vna_flags)); 1056*0Sstevel@tonic-gate 1057*0Sstevel@tonic-gate /* 1058*0Sstevel@tonic-gate * Print any additional version dependencies. 1059*0Sstevel@tonic-gate */ 1060*0Sstevel@tonic-gate if (vcnt) { 1061*0Sstevel@tonic-gate vnap = (GElf_Vernaux *)((uintptr_t)vnap + 1062*0Sstevel@tonic-gate vnap->vna_next); 1063*0Sstevel@tonic-gate for (vcnt--; vcnt; vcnt--, 1064*0Sstevel@tonic-gate vnap = (GElf_Vernaux *)((uintptr_t)vnap + 1065*0Sstevel@tonic-gate vnap->vna_next)) { 1066*0Sstevel@tonic-gate dep = string(vcache, cnt, scache, file, 1067*0Sstevel@tonic-gate vnap->vna_name); 1068*0Sstevel@tonic-gate Gelf_ver_line_3(MSG_ORIG(MSG_STR_EMPTY), dep, 1069*0Sstevel@tonic-gate conv_verflg_str(vnap->vna_flags)); 1070*0Sstevel@tonic-gate } 1071*0Sstevel@tonic-gate } 1072*0Sstevel@tonic-gate } 1073*0Sstevel@tonic-gate } 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate /* 1076*0Sstevel@tonic-gate * Search for any verion sections - the Versym output is possibly 1077*0Sstevel@tonic-gate * used by the symbols() printing. If VERSYM is specified - then 1078*0Sstevel@tonic-gate * display the version information. 1079*0Sstevel@tonic-gate */ 1080*0Sstevel@tonic-gate static Cache * 1081*0Sstevel@tonic-gate versions(Cache *cache, GElf_Word shnum, const char *file, uint32_t flags) 1082*0Sstevel@tonic-gate { 1083*0Sstevel@tonic-gate GElf_Word cnt; 1084*0Sstevel@tonic-gate Cache *versymcache = 0; 1085*0Sstevel@tonic-gate 1086*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 1087*0Sstevel@tonic-gate void * ver; 1088*0Sstevel@tonic-gate uint_t num; 1089*0Sstevel@tonic-gate Cache * _cache = &cache[cnt]; 1090*0Sstevel@tonic-gate GElf_Shdr * shdr = &_cache->c_shdr; 1091*0Sstevel@tonic-gate 1092*0Sstevel@tonic-gate /* 1093*0Sstevel@tonic-gate * If this is the version symbol table simply record its 1094*0Sstevel@tonic-gate * data address for possible use in later symbol processing. 1095*0Sstevel@tonic-gate */ 1096*0Sstevel@tonic-gate if (shdr->sh_type == SHT_SUNW_versym) { 1097*0Sstevel@tonic-gate versymcache = _cache; 1098*0Sstevel@tonic-gate continue; 1099*0Sstevel@tonic-gate } 1100*0Sstevel@tonic-gate 1101*0Sstevel@tonic-gate if ((flags & FLG_VERSIONS) == 0) 1102*0Sstevel@tonic-gate continue; 1103*0Sstevel@tonic-gate 1104*0Sstevel@tonic-gate if ((shdr->sh_type != SHT_SUNW_verdef) && 1105*0Sstevel@tonic-gate (shdr->sh_type != SHT_SUNW_verneed)) 1106*0Sstevel@tonic-gate continue; 1107*0Sstevel@tonic-gate 1108*0Sstevel@tonic-gate /* 1109*0Sstevel@tonic-gate * Determine the version section data and number. 1110*0Sstevel@tonic-gate */ 1111*0Sstevel@tonic-gate if ((ver = (void *)_cache->c_data->d_buf) == 0) { 1112*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1113*0Sstevel@tonic-gate file, _cache->c_name); 1114*0Sstevel@tonic-gate (void) fflush(stderr); 1115*0Sstevel@tonic-gate continue; 1116*0Sstevel@tonic-gate } 1117*0Sstevel@tonic-gate if ((num = shdr->sh_info) == 0) { 1118*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 1119*0Sstevel@tonic-gate file, _cache->c_name, EC_XWORD(shdr->sh_info)); 1120*0Sstevel@tonic-gate (void) fflush(stderr); 1121*0Sstevel@tonic-gate continue; 1122*0Sstevel@tonic-gate } 1123*0Sstevel@tonic-gate 1124*0Sstevel@tonic-gate /* 1125*0Sstevel@tonic-gate * Get the data buffer for the associated string table. 1126*0Sstevel@tonic-gate */ 1127*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1128*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1129*0Sstevel@tonic-gate file, _cache->c_name, EC_XWORD(shdr->sh_link)); 1130*0Sstevel@tonic-gate (void) fflush(stderr); 1131*0Sstevel@tonic-gate continue; 1132*0Sstevel@tonic-gate } 1133*0Sstevel@tonic-gate 1134*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1135*0Sstevel@tonic-gate if (shdr->sh_type == SHT_SUNW_verdef) { 1136*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SCN_VERDEF), 1137*0Sstevel@tonic-gate _cache->c_name); 1138*0Sstevel@tonic-gate version_def((GElf_Verdef *)ver, num, _cache, 1139*0Sstevel@tonic-gate &cache[shdr->sh_link], file); 1140*0Sstevel@tonic-gate } else if (shdr->sh_type == SHT_SUNW_verneed) { 1141*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SCN_VERNEED), 1142*0Sstevel@tonic-gate _cache->c_name); 1143*0Sstevel@tonic-gate version_need((GElf_Verneed *)ver, num, _cache, 1144*0Sstevel@tonic-gate &cache[shdr->sh_link], file); 1145*0Sstevel@tonic-gate } 1146*0Sstevel@tonic-gate } 1147*0Sstevel@tonic-gate return (versymcache); 1148*0Sstevel@tonic-gate } 1149*0Sstevel@tonic-gate 1150*0Sstevel@tonic-gate /* 1151*0Sstevel@tonic-gate * Search for and process any symbol tables. 1152*0Sstevel@tonic-gate */ 1153*0Sstevel@tonic-gate static void 1154*0Sstevel@tonic-gate symbols(Cache *cache, GElf_Word shnum, GElf_Ehdr *ehdr, const char *name, 1155*0Sstevel@tonic-gate Cache *versymcache, const char *file) 1156*0Sstevel@tonic-gate { 1157*0Sstevel@tonic-gate GElf_Word cnt; 1158*0Sstevel@tonic-gate char is_core = (ehdr->e_type == ET_CORE); 1159*0Sstevel@tonic-gate 1160*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 1161*0Sstevel@tonic-gate GElf_Sym sym; 1162*0Sstevel@tonic-gate GElf_Word symn, _cnt; 1163*0Sstevel@tonic-gate GElf_Versym *versym; 1164*0Sstevel@tonic-gate Cache *_cache = &cache[cnt]; 1165*0Sstevel@tonic-gate GElf_Shdr *shdr = &_cache->c_shdr; 1166*0Sstevel@tonic-gate Word *symshndx; 1167*0Sstevel@tonic-gate uint_t nosymshndx; 1168*0Sstevel@tonic-gate uint_t nosyminshndx; 1169*0Sstevel@tonic-gate 1170*0Sstevel@tonic-gate if ((shdr->sh_type != SHT_SYMTAB) && 1171*0Sstevel@tonic-gate (shdr->sh_type != SHT_DYNSYM)) 1172*0Sstevel@tonic-gate continue; 1173*0Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 1174*0Sstevel@tonic-gate continue; 1175*0Sstevel@tonic-gate 1176*0Sstevel@tonic-gate /* 1177*0Sstevel@tonic-gate * Determine the symbol data and number. 1178*0Sstevel@tonic-gate */ 1179*0Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1180*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1181*0Sstevel@tonic-gate file, _cache->c_name); 1182*0Sstevel@tonic-gate (void) fflush(stderr); 1183*0Sstevel@tonic-gate continue; 1184*0Sstevel@tonic-gate } 1185*0Sstevel@tonic-gate /* LINTED */ 1186*0Sstevel@tonic-gate symn = (GElf_Word)(shdr->sh_size / shdr->sh_entsize); 1187*0Sstevel@tonic-gate 1188*0Sstevel@tonic-gate /* 1189*0Sstevel@tonic-gate * Get the associated string table section. 1190*0Sstevel@tonic-gate */ 1191*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1192*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1193*0Sstevel@tonic-gate file, _cache->c_name, EC_XWORD(shdr->sh_link)); 1194*0Sstevel@tonic-gate (void) fflush(stderr); 1195*0Sstevel@tonic-gate continue; 1196*0Sstevel@tonic-gate } 1197*0Sstevel@tonic-gate 1198*0Sstevel@tonic-gate /* 1199*0Sstevel@tonic-gate * Determine if there is a associated Versym section 1200*0Sstevel@tonic-gate * with this Symbol Table. 1201*0Sstevel@tonic-gate */ 1202*0Sstevel@tonic-gate if (versymcache && (versymcache->c_shdr.sh_link == cnt)) 1203*0Sstevel@tonic-gate versym = versymcache->c_data->d_buf; 1204*0Sstevel@tonic-gate else 1205*0Sstevel@tonic-gate versym = 0; 1206*0Sstevel@tonic-gate 1207*0Sstevel@tonic-gate /* 1208*0Sstevel@tonic-gate * Loop through the symbol tables entries. 1209*0Sstevel@tonic-gate */ 1210*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1211*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SCN_SYMTAB), _cache->c_name); 1212*0Sstevel@tonic-gate Gelf_sym_table_title(ehdr, MSG_INTL(MSG_STR_INDEX), 1213*0Sstevel@tonic-gate MSG_INTL(MSG_STR_NAME)); 1214*0Sstevel@tonic-gate 1215*0Sstevel@tonic-gate symshndx = 0; 1216*0Sstevel@tonic-gate nosymshndx = 0; 1217*0Sstevel@tonic-gate nosyminshndx = 0; 1218*0Sstevel@tonic-gate for (_cnt = 0; _cnt < symn; _cnt++) { 1219*0Sstevel@tonic-gate char index[MAXNDXSIZE]; 1220*0Sstevel@tonic-gate char *sec; 1221*0Sstevel@tonic-gate const char *sname; 1222*0Sstevel@tonic-gate int verndx; 1223*0Sstevel@tonic-gate uchar_t type; 1224*0Sstevel@tonic-gate GElf_Shdr *tshdr; 1225*0Sstevel@tonic-gate Word shndx; 1226*0Sstevel@tonic-gate 1227*0Sstevel@tonic-gate if (gelf_getsym(_cache->c_data, _cnt, &sym) == NULL) { 1228*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSYM), 1229*0Sstevel@tonic-gate file, _cache->c_name, elf_errmsg(0)); 1230*0Sstevel@tonic-gate (void) fflush(stderr); 1231*0Sstevel@tonic-gate break; 1232*0Sstevel@tonic-gate } 1233*0Sstevel@tonic-gate 1234*0Sstevel@tonic-gate /* 1235*0Sstevel@tonic-gate * If we are using extended symbol indexes, find the 1236*0Sstevel@tonic-gate * corresponding SHN_SYMTAB_SHNDX table. 1237*0Sstevel@tonic-gate */ 1238*0Sstevel@tonic-gate if ((sym.st_shndx == SHN_XINDEX) && 1239*0Sstevel@tonic-gate (symshndx == 0) && (nosymshndx == 0)) { 1240*0Sstevel@tonic-gate Word __cnt; 1241*0Sstevel@tonic-gate 1242*0Sstevel@tonic-gate for (__cnt = 1; __cnt < shnum; __cnt++) { 1243*0Sstevel@tonic-gate Cache *_cache = &cache[__cnt]; 1244*0Sstevel@tonic-gate GElf_Shdr *shdr = &_cache->c_shdr; 1245*0Sstevel@tonic-gate 1246*0Sstevel@tonic-gate if ((shdr->sh_type != 1247*0Sstevel@tonic-gate SHT_SYMTAB_SHNDX) || 1248*0Sstevel@tonic-gate (shdr->sh_link != cnt)) 1249*0Sstevel@tonic-gate continue; 1250*0Sstevel@tonic-gate if (shdr->sh_entsize) 1251*0Sstevel@tonic-gate /* LINTED */ 1252*0Sstevel@tonic-gate nosyminshndx = (uint_t) 1253*0Sstevel@tonic-gate shdr->sh_size/shdr->sh_entsize; 1254*0Sstevel@tonic-gate if (nosyminshndx == 0) 1255*0Sstevel@tonic-gate continue; 1256*0Sstevel@tonic-gate symshndx = _cache->c_data->d_buf; 1257*0Sstevel@tonic-gate break; 1258*0Sstevel@tonic-gate } 1259*0Sstevel@tonic-gate if (symshndx == 0) 1260*0Sstevel@tonic-gate nosymshndx = 1; 1261*0Sstevel@tonic-gate } 1262*0Sstevel@tonic-gate 1263*0Sstevel@tonic-gate /* LINTED */ 1264*0Sstevel@tonic-gate sname = string(_cache, _cnt, &cache[shdr->sh_link], 1265*0Sstevel@tonic-gate file, sym.st_name); 1266*0Sstevel@tonic-gate 1267*0Sstevel@tonic-gate tshdr = 0; 1268*0Sstevel@tonic-gate sec = NULL; 1269*0Sstevel@tonic-gate 1270*0Sstevel@tonic-gate if (is_core) 1271*0Sstevel@tonic-gate sec = (char *)MSG_INTL(MSG_STR_UNKNOWN); 1272*0Sstevel@tonic-gate else if ((sym.st_shndx < SHN_LORESERVE) && 1273*0Sstevel@tonic-gate (sym.st_shndx < shnum)) { 1274*0Sstevel@tonic-gate shndx = sym.st_shndx; 1275*0Sstevel@tonic-gate tshdr = &(cache[shndx].c_shdr); 1276*0Sstevel@tonic-gate sec = cache[shndx].c_name; 1277*0Sstevel@tonic-gate } else if (sym.st_shndx == SHN_XINDEX) { 1278*0Sstevel@tonic-gate if (symshndx) { 1279*0Sstevel@tonic-gate Word _symshndx; 1280*0Sstevel@tonic-gate 1281*0Sstevel@tonic-gate if (_cnt > nosyminshndx) { 1282*0Sstevel@tonic-gate (void) fprintf(stderr, 1283*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYMXINDEX1), 1284*0Sstevel@tonic-gate file, _cache->c_name, 1285*0Sstevel@tonic-gate EC_WORD(_cnt)); 1286*0Sstevel@tonic-gate (void) fflush(stderr); 1287*0Sstevel@tonic-gate } else if ((_symshndx = 1288*0Sstevel@tonic-gate symshndx[_cnt]) > shnum) { 1289*0Sstevel@tonic-gate (void) fprintf(stderr, 1290*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYMXINDEX2), 1291*0Sstevel@tonic-gate file, _cache->c_name, 1292*0Sstevel@tonic-gate EC_WORD(_cnt), 1293*0Sstevel@tonic-gate EC_WORD(_symshndx)); 1294*0Sstevel@tonic-gate (void) fflush(stderr); 1295*0Sstevel@tonic-gate } else { 1296*0Sstevel@tonic-gate shndx = _symshndx; 1297*0Sstevel@tonic-gate tshdr = &(cache[shndx].c_shdr); 1298*0Sstevel@tonic-gate sec = cache[shndx].c_name; 1299*0Sstevel@tonic-gate } 1300*0Sstevel@tonic-gate } else { 1301*0Sstevel@tonic-gate (void) fprintf(stderr, 1302*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYMXINDEX3), 1303*0Sstevel@tonic-gate file, _cache->c_name, 1304*0Sstevel@tonic-gate EC_WORD(_cnt)); 1305*0Sstevel@tonic-gate (void) fflush(stderr); 1306*0Sstevel@tonic-gate } 1307*0Sstevel@tonic-gate } else if ((sym.st_shndx < SHN_LORESERVE) && 1308*0Sstevel@tonic-gate (sym.st_shndx >= shnum)) { 1309*0Sstevel@tonic-gate (void) fprintf(stderr, 1310*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYM5), 1311*0Sstevel@tonic-gate file, _cache->c_name, 1312*0Sstevel@tonic-gate sname, sym.st_shndx); 1313*0Sstevel@tonic-gate (void) fflush(stderr); 1314*0Sstevel@tonic-gate } 1315*0Sstevel@tonic-gate 1316*0Sstevel@tonic-gate /* 1317*0Sstevel@tonic-gate * If versioning is available display the 1318*0Sstevel@tonic-gate * version index. 1319*0Sstevel@tonic-gate */ 1320*0Sstevel@tonic-gate if (versym) 1321*0Sstevel@tonic-gate verndx = (int)versym[_cnt]; 1322*0Sstevel@tonic-gate else 1323*0Sstevel@tonic-gate verndx = 0; 1324*0Sstevel@tonic-gate 1325*0Sstevel@tonic-gate /* 1326*0Sstevel@tonic-gate * Error checking for TLS. 1327*0Sstevel@tonic-gate */ 1328*0Sstevel@tonic-gate type = ELF_ST_TYPE(sym.st_info); 1329*0Sstevel@tonic-gate if (type == STT_TLS) { 1330*0Sstevel@tonic-gate if (tshdr && 1331*0Sstevel@tonic-gate (sym.st_shndx != SHN_UNDEF) && 1332*0Sstevel@tonic-gate ((tshdr->sh_flags & SHF_TLS) == 0)) { 1333*0Sstevel@tonic-gate (void) fprintf(stderr, 1334*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYM3), file, 1335*0Sstevel@tonic-gate _cache->c_name, sname); 1336*0Sstevel@tonic-gate (void) fflush(stderr); 1337*0Sstevel@tonic-gate } 1338*0Sstevel@tonic-gate } else if ((type != STT_SECTION) && sym.st_size && 1339*0Sstevel@tonic-gate tshdr && (tshdr->sh_flags & SHF_TLS)) { 1340*0Sstevel@tonic-gate (void) fprintf(stderr, 1341*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYM4), file, 1342*0Sstevel@tonic-gate _cache->c_name, sname); 1343*0Sstevel@tonic-gate (void) fflush(stderr); 1344*0Sstevel@tonic-gate } 1345*0Sstevel@tonic-gate 1346*0Sstevel@tonic-gate /* 1347*0Sstevel@tonic-gate * If a symbol has size, then make sure the section it 1348*0Sstevel@tonic-gate * references is appropriate. Note, UNDEF symbols that 1349*0Sstevel@tonic-gate * have a size, have been known to exist - ignore them. 1350*0Sstevel@tonic-gate */ 1351*0Sstevel@tonic-gate if (sym.st_size && shndx && tshdr && 1352*0Sstevel@tonic-gate (tshdr->sh_size < sym.st_size)) { 1353*0Sstevel@tonic-gate (void) fprintf(stderr, 1354*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYM6), file, 1355*0Sstevel@tonic-gate _cache->c_name, sname, EC_WORD(shndx), 1356*0Sstevel@tonic-gate EC_XWORD(tshdr->sh_size), 1357*0Sstevel@tonic-gate EC_XWORD(sym.st_size)); 1358*0Sstevel@tonic-gate (void) fflush(stderr); 1359*0Sstevel@tonic-gate } 1360*0Sstevel@tonic-gate 1361*0Sstevel@tonic-gate (void) snprintf(index, MAXNDXSIZE, 1362*0Sstevel@tonic-gate MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(_cnt)); 1363*0Sstevel@tonic-gate 1364*0Sstevel@tonic-gate Gelf_sym_table_entry(index, ehdr, &sym, verndx, sec, 1365*0Sstevel@tonic-gate sname); 1366*0Sstevel@tonic-gate } 1367*0Sstevel@tonic-gate } 1368*0Sstevel@tonic-gate } 1369*0Sstevel@tonic-gate 1370*0Sstevel@tonic-gate /* 1371*0Sstevel@tonic-gate * Search for and process any relocation sections. 1372*0Sstevel@tonic-gate */ 1373*0Sstevel@tonic-gate static void 1374*0Sstevel@tonic-gate reloc(Cache *cache, GElf_Word shnum, GElf_Ehdr *ehdr, const char *name, 1375*0Sstevel@tonic-gate const char *file, uint32_t flags) 1376*0Sstevel@tonic-gate { 1377*0Sstevel@tonic-gate GElf_Word cnt; 1378*0Sstevel@tonic-gate 1379*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 1380*0Sstevel@tonic-gate Word type; 1381*0Sstevel@tonic-gate ulong_t numrels, entsize; 1382*0Sstevel@tonic-gate int ndx; 1383*0Sstevel@tonic-gate Elf_Data *dsyms; 1384*0Sstevel@tonic-gate Cache *_cache = &cache[cnt]; 1385*0Sstevel@tonic-gate GElf_Shdr *shdr = &_cache->c_shdr; 1386*0Sstevel@tonic-gate char *sname; 1387*0Sstevel@tonic-gate 1388*0Sstevel@tonic-gate if (((type = shdr->sh_type) != SHT_RELA) && 1389*0Sstevel@tonic-gate (type != SHT_REL)) 1390*0Sstevel@tonic-gate continue; 1391*0Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 1392*0Sstevel@tonic-gate continue; 1393*0Sstevel@tonic-gate 1394*0Sstevel@tonic-gate /* 1395*0Sstevel@tonic-gate * Decide entry size 1396*0Sstevel@tonic-gate */ 1397*0Sstevel@tonic-gate if (((entsize = shdr->sh_entsize) == 0) || 1398*0Sstevel@tonic-gate (entsize > shdr->sh_size)) { 1399*0Sstevel@tonic-gate if (type == SHT_RELA) 1400*0Sstevel@tonic-gate entsize = sizeof (GElf_Rela); 1401*0Sstevel@tonic-gate else 1402*0Sstevel@tonic-gate entsize = sizeof (GElf_Rel); 1403*0Sstevel@tonic-gate } 1404*0Sstevel@tonic-gate 1405*0Sstevel@tonic-gate /* 1406*0Sstevel@tonic-gate * Determine the number of relocations available. 1407*0Sstevel@tonic-gate */ 1408*0Sstevel@tonic-gate if (shdr->sh_size == 0) { 1409*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1410*0Sstevel@tonic-gate file, _cache->c_name); 1411*0Sstevel@tonic-gate (void) fflush(stderr); 1412*0Sstevel@tonic-gate continue; 1413*0Sstevel@tonic-gate } 1414*0Sstevel@tonic-gate numrels = shdr->sh_size / entsize; 1415*0Sstevel@tonic-gate 1416*0Sstevel@tonic-gate /* 1417*0Sstevel@tonic-gate * Get the data buffer for the associated symbol table. Note 1418*0Sstevel@tonic-gate * that we've been known to create static binaries containing 1419*0Sstevel@tonic-gate * relocations against weak symbols, if these get stripped the 1420*0Sstevel@tonic-gate * relocation records can't make symbolic references. 1421*0Sstevel@tonic-gate */ 1422*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1423*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1424*0Sstevel@tonic-gate file, _cache->c_name, EC_XWORD(shdr->sh_link)); 1425*0Sstevel@tonic-gate (void) fflush(stderr); 1426*0Sstevel@tonic-gate continue; 1427*0Sstevel@tonic-gate } 1428*0Sstevel@tonic-gate dsyms = cache[shdr->sh_link].c_data; 1429*0Sstevel@tonic-gate if (dsyms->d_buf == 0) { 1430*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1431*0Sstevel@tonic-gate file, cache[shdr->sh_link].c_name); 1432*0Sstevel@tonic-gate (void) fflush(stderr); 1433*0Sstevel@tonic-gate continue; 1434*0Sstevel@tonic-gate } 1435*0Sstevel@tonic-gate 1436*0Sstevel@tonic-gate sname = cache[shdr->sh_link].c_name; 1437*0Sstevel@tonic-gate shdr = &cache[shdr->sh_link].c_shdr; 1438*0Sstevel@tonic-gate /* 1439*0Sstevel@tonic-gate * Get the associated string table section. 1440*0Sstevel@tonic-gate */ 1441*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1442*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1443*0Sstevel@tonic-gate file, sname, EC_XWORD(shdr->sh_link)); 1444*0Sstevel@tonic-gate (void) fflush(stderr); 1445*0Sstevel@tonic-gate continue; 1446*0Sstevel@tonic-gate } 1447*0Sstevel@tonic-gate 1448*0Sstevel@tonic-gate /* 1449*0Sstevel@tonic-gate * Loop through the relocation entries. 1450*0Sstevel@tonic-gate */ 1451*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1452*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name); 1453*0Sstevel@tonic-gate if (type == SHT_RELA) { 1454*0Sstevel@tonic-gate if (flags & FLG_LONGNAME) 1455*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_L_RELOC_RELA)); 1456*0Sstevel@tonic-gate else 1457*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_RELOC_RELA)); 1458*0Sstevel@tonic-gate } else { 1459*0Sstevel@tonic-gate if (flags & FLG_LONGNAME) 1460*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_L_RELOC_REL)); 1461*0Sstevel@tonic-gate else 1462*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_RELOC_REL)); 1463*0Sstevel@tonic-gate } 1464*0Sstevel@tonic-gate 1465*0Sstevel@tonic-gate /* LINTED */ 1466*0Sstevel@tonic-gate for (ndx = 0; ndx < numrels; ndx++) { 1467*0Sstevel@tonic-gate char section[BUFSIZ]; 1468*0Sstevel@tonic-gate const char *_name; 1469*0Sstevel@tonic-gate GElf_Word sndx; 1470*0Sstevel@tonic-gate ulong_t r_type; 1471*0Sstevel@tonic-gate GElf_Sym _sym; 1472*0Sstevel@tonic-gate GElf_Rela rela; 1473*0Sstevel@tonic-gate 1474*0Sstevel@tonic-gate /* 1475*0Sstevel@tonic-gate * Determine the symbol with which this relocation is 1476*0Sstevel@tonic-gate * associated. If the symbol represents a section 1477*0Sstevel@tonic-gate * offset construct an appropriate string. 1478*0Sstevel@tonic-gate */ 1479*0Sstevel@tonic-gate if (type == SHT_RELA) { 1480*0Sstevel@tonic-gate (void) gelf_getrela(_cache->c_data, ndx, 1481*0Sstevel@tonic-gate &rela); 1482*0Sstevel@tonic-gate } else { 1483*0Sstevel@tonic-gate (void) gelf_getrel(_cache->c_data, ndx, 1484*0Sstevel@tonic-gate (GElf_Rel*)&rela); 1485*0Sstevel@tonic-gate } 1486*0Sstevel@tonic-gate /* LINTED */ 1487*0Sstevel@tonic-gate sndx = (GElf_Word)GELF_R_SYM(rela.r_info); 1488*0Sstevel@tonic-gate r_type = GELF_R_TYPE(rela.r_info); 1489*0Sstevel@tonic-gate 1490*0Sstevel@tonic-gate /* LINTED */ 1491*0Sstevel@tonic-gate if (gelf_getsym(dsyms, (int)sndx, &_sym) == NULL) { 1492*0Sstevel@tonic-gate (void) fprintf(stderr, 1493*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_RELBADSYMNDX), 1494*0Sstevel@tonic-gate file, elf_errmsg(0)); 1495*0Sstevel@tonic-gate (void) fflush(stderr); 1496*0Sstevel@tonic-gate _name = MSG_INTL(MSG_STR_UNKNOWN); 1497*0Sstevel@tonic-gate } else { 1498*0Sstevel@tonic-gate if ((GELF_ST_TYPE(_sym.st_info) == 1499*0Sstevel@tonic-gate STT_SECTION) && (_sym.st_name == 0)) { 1500*0Sstevel@tonic-gate if (flags & FLG_LONGNAME) 1501*0Sstevel@tonic-gate (void) snprintf(section, BUFSIZ, 1502*0Sstevel@tonic-gate MSG_INTL(MSG_STR_L_SECTION), 1503*0Sstevel@tonic-gate cache[_sym.st_shndx].c_name); 1504*0Sstevel@tonic-gate else 1505*0Sstevel@tonic-gate (void) snprintf(section, BUFSIZ, 1506*0Sstevel@tonic-gate MSG_INTL(MSG_STR_SECTION), 1507*0Sstevel@tonic-gate cache[_sym.st_shndx].c_name); 1508*0Sstevel@tonic-gate _name = (const char *)section; 1509*0Sstevel@tonic-gate } else { 1510*0Sstevel@tonic-gate /* LINTED */ 1511*0Sstevel@tonic-gate _name = string(_cache, 1512*0Sstevel@tonic-gate sndx, &cache[shdr->sh_link], 1513*0Sstevel@tonic-gate file, _sym.st_name); 1514*0Sstevel@tonic-gate } 1515*0Sstevel@tonic-gate } 1516*0Sstevel@tonic-gate 1517*0Sstevel@tonic-gate if ((sndx == 0) && ((IAM_SPARC(ehdr->e_machine) && 1518*0Sstevel@tonic-gate ((r_type != R_SPARC_NONE) && 1519*0Sstevel@tonic-gate (r_type != R_SPARC_REGISTER) && 1520*0Sstevel@tonic-gate (r_type != R_SPARC_RELATIVE))) || 1521*0Sstevel@tonic-gate ((IAM_INTEL(ehdr->e_machine) && 1522*0Sstevel@tonic-gate ((r_type != R_386_NONE) && 1523*0Sstevel@tonic-gate (r_type != R_386_RELATIVE)))))) { 1524*0Sstevel@tonic-gate (void) fprintf(stderr, 1525*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADREL1), file, 1526*0Sstevel@tonic-gate conv_reloc_type_str(ehdr->e_machine, 1527*0Sstevel@tonic-gate /* LINTED */ 1528*0Sstevel@tonic-gate (uint_t)r_type)); 1529*0Sstevel@tonic-gate (void) fflush(stderr); 1530*0Sstevel@tonic-gate } 1531*0Sstevel@tonic-gate 1532*0Sstevel@tonic-gate Gelf_reloc_entry(MSG_ORIG(MSG_STR_EMPTY), 1533*0Sstevel@tonic-gate ehdr->e_machine, type, (void *)&rela, 1534*0Sstevel@tonic-gate _cache->c_name, _name); 1535*0Sstevel@tonic-gate } 1536*0Sstevel@tonic-gate } 1537*0Sstevel@tonic-gate } 1538*0Sstevel@tonic-gate 1539*0Sstevel@tonic-gate /* 1540*0Sstevel@tonic-gate * Search for and process a .dynamic section. 1541*0Sstevel@tonic-gate */ 1542*0Sstevel@tonic-gate static void 1543*0Sstevel@tonic-gate dynamic(Cache *cache, GElf_Word shnum, GElf_Ehdr *ehdr, const char *file) 1544*0Sstevel@tonic-gate { 1545*0Sstevel@tonic-gate GElf_Word cnt; 1546*0Sstevel@tonic-gate 1547*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 1548*0Sstevel@tonic-gate GElf_Dyn dyn; 1549*0Sstevel@tonic-gate ulong_t numdyn; 1550*0Sstevel@tonic-gate int ndx; 1551*0Sstevel@tonic-gate Cache * _cache = &cache[cnt]; 1552*0Sstevel@tonic-gate GElf_Shdr * shdr = &_cache->c_shdr; 1553*0Sstevel@tonic-gate 1554*0Sstevel@tonic-gate if (shdr->sh_type != SHT_DYNAMIC) 1555*0Sstevel@tonic-gate continue; 1556*0Sstevel@tonic-gate 1557*0Sstevel@tonic-gate /* 1558*0Sstevel@tonic-gate * Get the associated string table section. 1559*0Sstevel@tonic-gate */ 1560*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1561*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1562*0Sstevel@tonic-gate file, _cache->c_name, EC_XWORD(shdr->sh_link)); 1563*0Sstevel@tonic-gate (void) fflush(stderr); 1564*0Sstevel@tonic-gate continue; 1565*0Sstevel@tonic-gate } 1566*0Sstevel@tonic-gate numdyn = shdr->sh_size / shdr->sh_entsize; 1567*0Sstevel@tonic-gate 1568*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1569*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name); 1570*0Sstevel@tonic-gate 1571*0Sstevel@tonic-gate Gelf_dyn_title(); 1572*0Sstevel@tonic-gate 1573*0Sstevel@tonic-gate /* LINTED */ 1574*0Sstevel@tonic-gate for (ndx = 0; ndx < numdyn; ++ndx) { 1575*0Sstevel@tonic-gate const char *name; 1576*0Sstevel@tonic-gate 1577*0Sstevel@tonic-gate (void) gelf_getdyn(_cache->c_data, ndx, &dyn); 1578*0Sstevel@tonic-gate if (dyn.d_tag == DT_NULL) 1579*0Sstevel@tonic-gate break; 1580*0Sstevel@tonic-gate 1581*0Sstevel@tonic-gate /* 1582*0Sstevel@tonic-gate * Print the information numerically, and if possible 1583*0Sstevel@tonic-gate * as a string. 1584*0Sstevel@tonic-gate */ 1585*0Sstevel@tonic-gate if ((dyn.d_tag == DT_NEEDED) || 1586*0Sstevel@tonic-gate (dyn.d_tag == DT_SONAME) || 1587*0Sstevel@tonic-gate (dyn.d_tag == DT_FILTER) || 1588*0Sstevel@tonic-gate (dyn.d_tag == DT_AUXILIARY) || 1589*0Sstevel@tonic-gate (dyn.d_tag == DT_CONFIG) || 1590*0Sstevel@tonic-gate (dyn.d_tag == DT_RPATH) || 1591*0Sstevel@tonic-gate (dyn.d_tag == DT_RUNPATH) || 1592*0Sstevel@tonic-gate (dyn.d_tag == DT_USED) || 1593*0Sstevel@tonic-gate (dyn.d_tag == DT_DEPAUDIT) || 1594*0Sstevel@tonic-gate (dyn.d_tag == DT_AUDIT) || 1595*0Sstevel@tonic-gate (dyn.d_tag == DT_SUNW_AUXILIARY) || 1596*0Sstevel@tonic-gate (dyn.d_tag == DT_SUNW_FILTER)) 1597*0Sstevel@tonic-gate name = string(_cache, ndx, 1598*0Sstevel@tonic-gate &cache[shdr->sh_link], file, 1599*0Sstevel@tonic-gate dyn.d_un.d_ptr); 1600*0Sstevel@tonic-gate else if (dyn.d_tag == DT_FLAGS) 1601*0Sstevel@tonic-gate /* LINTED */ 1602*0Sstevel@tonic-gate name = conv_dynflag_str((Word)dyn.d_un.d_val); 1603*0Sstevel@tonic-gate else if (dyn.d_tag == DT_FLAGS_1) 1604*0Sstevel@tonic-gate /* LINTED */ 1605*0Sstevel@tonic-gate name = conv_dynflag_1_str((Word)dyn.d_un.d_val); 1606*0Sstevel@tonic-gate else if (dyn.d_tag == DT_POSFLAG_1) 1607*0Sstevel@tonic-gate /* LINTED */ 1608*0Sstevel@tonic-gate name = conv_dynposflag_1_str((Word)dyn.d_un.d_val); 1609*0Sstevel@tonic-gate else if (dyn.d_tag == DT_FEATURE_1) 1610*0Sstevel@tonic-gate /* LINTED */ 1611*0Sstevel@tonic-gate name = conv_dynfeature_1_str((Word)dyn.d_un.d_val); 1612*0Sstevel@tonic-gate else if (dyn.d_tag == DT_DEPRECATED_SPARC_REGISTER) 1613*0Sstevel@tonic-gate name = MSG_INTL(MSG_STR_DEPRECATED); 1614*0Sstevel@tonic-gate else 1615*0Sstevel@tonic-gate name = MSG_ORIG(MSG_STR_EMPTY); 1616*0Sstevel@tonic-gate 1617*0Sstevel@tonic-gate Gelf_dyn_print(&dyn, ndx, name, ehdr->e_machine); 1618*0Sstevel@tonic-gate } 1619*0Sstevel@tonic-gate } 1620*0Sstevel@tonic-gate } 1621*0Sstevel@tonic-gate 1622*0Sstevel@tonic-gate /* 1623*0Sstevel@tonic-gate * Search for and process a MOVE section. 1624*0Sstevel@tonic-gate */ 1625*0Sstevel@tonic-gate static void 1626*0Sstevel@tonic-gate move(Cache *cache, GElf_Word shnum, const char *name, const char *file, 1627*0Sstevel@tonic-gate uint32_t flags) 1628*0Sstevel@tonic-gate { 1629*0Sstevel@tonic-gate GElf_Word cnt; 1630*0Sstevel@tonic-gate 1631*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 1632*0Sstevel@tonic-gate ulong_t num, symn; 1633*0Sstevel@tonic-gate int ndx; 1634*0Sstevel@tonic-gate Elf_Data *dsyms; 1635*0Sstevel@tonic-gate const char *fmt; 1636*0Sstevel@tonic-gate Cache *_cache = &cache[cnt]; 1637*0Sstevel@tonic-gate GElf_Shdr *shdr = &_cache->c_shdr; 1638*0Sstevel@tonic-gate char *sname; 1639*0Sstevel@tonic-gate 1640*0Sstevel@tonic-gate if (shdr->sh_type != SHT_SUNW_move) 1641*0Sstevel@tonic-gate continue; 1642*0Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 1643*0Sstevel@tonic-gate continue; 1644*0Sstevel@tonic-gate 1645*0Sstevel@tonic-gate /* 1646*0Sstevel@tonic-gate * Determine the move data and number. 1647*0Sstevel@tonic-gate */ 1648*0Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1649*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1650*0Sstevel@tonic-gate file, _cache->c_name); 1651*0Sstevel@tonic-gate (void) fflush(stderr); 1652*0Sstevel@tonic-gate continue; 1653*0Sstevel@tonic-gate } 1654*0Sstevel@tonic-gate num = shdr->sh_size / shdr->sh_entsize; 1655*0Sstevel@tonic-gate 1656*0Sstevel@tonic-gate /* 1657*0Sstevel@tonic-gate * Get the data buffer for the associated symbol table. 1658*0Sstevel@tonic-gate */ 1659*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1660*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1661*0Sstevel@tonic-gate file, _cache->c_name, EC_XWORD(shdr->sh_link)); 1662*0Sstevel@tonic-gate (void) fflush(stderr); 1663*0Sstevel@tonic-gate continue; 1664*0Sstevel@tonic-gate } 1665*0Sstevel@tonic-gate dsyms = cache[shdr->sh_link].c_data; 1666*0Sstevel@tonic-gate if (dsyms->d_buf == 0) { 1667*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1668*0Sstevel@tonic-gate file, cache[shdr->sh_link].c_name); 1669*0Sstevel@tonic-gate (void) fflush(stderr); 1670*0Sstevel@tonic-gate continue; 1671*0Sstevel@tonic-gate } 1672*0Sstevel@tonic-gate 1673*0Sstevel@tonic-gate sname = cache[shdr->sh_link].c_name; 1674*0Sstevel@tonic-gate shdr = &cache[shdr->sh_link].c_shdr; 1675*0Sstevel@tonic-gate 1676*0Sstevel@tonic-gate /* 1677*0Sstevel@tonic-gate * Get the associated string table section. 1678*0Sstevel@tonic-gate */ 1679*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1680*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1681*0Sstevel@tonic-gate file, sname, EC_XWORD(shdr->sh_link)); 1682*0Sstevel@tonic-gate (void) fflush(stderr); 1683*0Sstevel@tonic-gate continue; 1684*0Sstevel@tonic-gate } 1685*0Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1686*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1687*0Sstevel@tonic-gate file, sname); 1688*0Sstevel@tonic-gate (void) fflush(stderr); 1689*0Sstevel@tonic-gate continue; 1690*0Sstevel@tonic-gate } 1691*0Sstevel@tonic-gate symn = shdr->sh_size / shdr->sh_entsize; 1692*0Sstevel@tonic-gate 1693*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1694*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_MV_TITLE), _cache->c_name); 1695*0Sstevel@tonic-gate 1696*0Sstevel@tonic-gate fmt = MSG_INTL(MSG_MV_ENTRY); 1697*0Sstevel@tonic-gate 1698*0Sstevel@tonic-gate /* LINTED */ 1699*0Sstevel@tonic-gate for (ndx = 0; ndx < num; ndx++) { 1700*0Sstevel@tonic-gate GElf_Move move; 1701*0Sstevel@tonic-gate const char *name; 1702*0Sstevel@tonic-gate GElf_Sym sym; 1703*0Sstevel@tonic-gate char sct[BUFSIZ]; 1704*0Sstevel@tonic-gate Word shndx; 1705*0Sstevel@tonic-gate 1706*0Sstevel@tonic-gate if (gelf_getmove(_cache->c_data, ndx, &move) == NULL) { 1707*0Sstevel@tonic-gate (void) fprintf(stderr, 1708*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADMOVE), 1709*0Sstevel@tonic-gate file, _cache->c_name, elf_errmsg(0)); 1710*0Sstevel@tonic-gate (void) fflush(stderr); 1711*0Sstevel@tonic-gate break; 1712*0Sstevel@tonic-gate } 1713*0Sstevel@tonic-gate 1714*0Sstevel@tonic-gate /* 1715*0Sstevel@tonic-gate * Check for null entries 1716*0Sstevel@tonic-gate */ 1717*0Sstevel@tonic-gate if ((move.m_info == 0) && (move.m_value == 0) && 1718*0Sstevel@tonic-gate (move.m_poffset == 0) && (move.m_repeat == 0) && 1719*0Sstevel@tonic-gate (move.m_stride == 0)) { 1720*0Sstevel@tonic-gate dbg_print(fmt, EC_XWORD(move.m_poffset), 1721*0Sstevel@tonic-gate EC_XWORD(0), 0, 0, 0, EC_LWORD(0), 1722*0Sstevel@tonic-gate MSG_ORIG(MSG_STR_EMPTY)); 1723*0Sstevel@tonic-gate continue; 1724*0Sstevel@tonic-gate } 1725*0Sstevel@tonic-gate if ((GELF_M_SYM(move.m_info) == 0) || 1726*0Sstevel@tonic-gate (GELF_M_SYM(move.m_info) >= symn)) { 1727*0Sstevel@tonic-gate (void) fprintf(stderr, 1728*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADMINFO), file, 1729*0Sstevel@tonic-gate _cache->c_name, EC_XWORD(move.m_info)); 1730*0Sstevel@tonic-gate (void) fflush(stderr); 1731*0Sstevel@tonic-gate dbg_print(fmt, EC_XWORD(move.m_poffset), 1732*0Sstevel@tonic-gate EC_XWORD(GELF_M_SYM(move.m_info)), 1733*0Sstevel@tonic-gate /* LINTED */ 1734*0Sstevel@tonic-gate GELF_M_SIZE(move.m_info), move.m_repeat, 1735*0Sstevel@tonic-gate move.m_stride, EC_LWORD(move.m_value), 1736*0Sstevel@tonic-gate MSG_INTL(MSG_STR_UNKNOWN)); 1737*0Sstevel@tonic-gate continue; 1738*0Sstevel@tonic-gate } 1739*0Sstevel@tonic-gate 1740*0Sstevel@tonic-gate if (gelf_getsym(dsyms, 1741*0Sstevel@tonic-gate /* LINTED */ 1742*0Sstevel@tonic-gate (int)GELF_M_SYM(move.m_info), &sym) == NULL) { 1743*0Sstevel@tonic-gate (void) fprintf(stderr, 1744*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_MVBADSYMNDX), 1745*0Sstevel@tonic-gate file, elf_errmsg(0)); 1746*0Sstevel@tonic-gate (void) fflush(stderr); 1747*0Sstevel@tonic-gate name = MSG_INTL(MSG_STR_UNKNOWN); 1748*0Sstevel@tonic-gate } else { 1749*0Sstevel@tonic-gate if ((GELF_ST_TYPE(sym.st_info) == 1750*0Sstevel@tonic-gate STT_SECTION) && (sym.st_name == 0)) { 1751*0Sstevel@tonic-gate if (flags & FLG_LONGNAME) 1752*0Sstevel@tonic-gate (void) snprintf(sct, BUFSIZ, 1753*0Sstevel@tonic-gate MSG_INTL(MSG_STR_L_SECTION), 1754*0Sstevel@tonic-gate cache[sym.st_shndx].c_name); 1755*0Sstevel@tonic-gate else 1756*0Sstevel@tonic-gate (void) snprintf(sct, BUFSIZ, 1757*0Sstevel@tonic-gate MSG_INTL(MSG_STR_SECTION), 1758*0Sstevel@tonic-gate cache[sym.st_shndx].c_name); 1759*0Sstevel@tonic-gate name = (const char *)sct; 1760*0Sstevel@tonic-gate } else { 1761*0Sstevel@tonic-gate name = demangle(string(_cache, 1762*0Sstevel@tonic-gate /* LINTED */ 1763*0Sstevel@tonic-gate (GElf_Word)GELF_M_SYM(move.m_info), 1764*0Sstevel@tonic-gate &cache[shdr->sh_link], file, 1765*0Sstevel@tonic-gate sym.st_name), flags); 1766*0Sstevel@tonic-gate } 1767*0Sstevel@tonic-gate } 1768*0Sstevel@tonic-gate 1769*0Sstevel@tonic-gate /* 1770*0Sstevel@tonic-gate * Additional sanity check. 1771*0Sstevel@tonic-gate */ 1772*0Sstevel@tonic-gate shndx = sym.st_shndx; 1773*0Sstevel@tonic-gate if (!((shndx == SHN_COMMON) || 1774*0Sstevel@tonic-gate (((shndx >= 1) && (shndx <= shnum)) && 1775*0Sstevel@tonic-gate (cache[shndx].c_shdr).sh_type == SHT_NOBITS))) { 1776*0Sstevel@tonic-gate (void) fprintf(stderr, 1777*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSYM2), file, 1778*0Sstevel@tonic-gate _cache->c_name, name); 1779*0Sstevel@tonic-gate (void) fflush(stderr); 1780*0Sstevel@tonic-gate } 1781*0Sstevel@tonic-gate 1782*0Sstevel@tonic-gate dbg_print(fmt, EC_XWORD(move.m_poffset), 1783*0Sstevel@tonic-gate EC_XWORD(GELF_M_SYM(move.m_info)), 1784*0Sstevel@tonic-gate /* LINTED */ 1785*0Sstevel@tonic-gate GELF_M_SIZE(move.m_info), move.m_repeat, 1786*0Sstevel@tonic-gate move.m_stride, EC_LWORD(move.m_value), name); 1787*0Sstevel@tonic-gate } 1788*0Sstevel@tonic-gate } 1789*0Sstevel@tonic-gate } 1790*0Sstevel@tonic-gate 1791*0Sstevel@tonic-gate /* 1792*0Sstevel@tonic-gate * Traverse a note section analyzing each note information block. 1793*0Sstevel@tonic-gate * The data buffers size is used to validate references before they are made, 1794*0Sstevel@tonic-gate * and is decremented as each element is processed. 1795*0Sstevel@tonic-gate */ 1796*0Sstevel@tonic-gate void 1797*0Sstevel@tonic-gate note_entry(Cache *cache, Word *data, Word size, const char *file) 1798*0Sstevel@tonic-gate { 1799*0Sstevel@tonic-gate Word bsize = size; 1800*0Sstevel@tonic-gate /* 1801*0Sstevel@tonic-gate * Print out a single `note' information block. 1802*0Sstevel@tonic-gate */ 1803*0Sstevel@tonic-gate while (size > 0) { 1804*0Sstevel@tonic-gate Word namesz, descsz, type, pad, noteoff; 1805*0Sstevel@tonic-gate 1806*0Sstevel@tonic-gate 1807*0Sstevel@tonic-gate noteoff = bsize - size; 1808*0Sstevel@tonic-gate /* 1809*0Sstevel@tonic-gate * Make sure we can at least reference the 3 initial entries 1810*0Sstevel@tonic-gate * (4-byte words) of the note information block. 1811*0Sstevel@tonic-gate */ 1812*0Sstevel@tonic-gate if (size >= (Word)(sizeof (Word) * 3)) 1813*0Sstevel@tonic-gate size -= (Word)(sizeof (Word) * 3); 1814*0Sstevel@tonic-gate else { 1815*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASIZE), 1816*0Sstevel@tonic-gate file, cache->c_name, EC_WORD(noteoff)); 1817*0Sstevel@tonic-gate (void) fflush(stderr); 1818*0Sstevel@tonic-gate return; 1819*0Sstevel@tonic-gate } 1820*0Sstevel@tonic-gate 1821*0Sstevel@tonic-gate /* 1822*0Sstevel@tonic-gate * Make sure any specified name string can be referenced. 1823*0Sstevel@tonic-gate */ 1824*0Sstevel@tonic-gate if ((namesz = *data++) != 0) { 1825*0Sstevel@tonic-gate if (size >= namesz) 1826*0Sstevel@tonic-gate size -= namesz; 1827*0Sstevel@tonic-gate else { 1828*0Sstevel@tonic-gate (void) fprintf(stderr, 1829*0Sstevel@tonic-gate MSG_INTL(MSG_NOTE_BADNMSIZE), 1830*0Sstevel@tonic-gate file, cache->c_name, EC_WORD(noteoff), 1831*0Sstevel@tonic-gate EC_WORD(namesz)); 1832*0Sstevel@tonic-gate (void) fflush(stderr); 1833*0Sstevel@tonic-gate return; 1834*0Sstevel@tonic-gate } 1835*0Sstevel@tonic-gate } 1836*0Sstevel@tonic-gate /* 1837*0Sstevel@tonic-gate * Make sure any specified descriptor can be referenced. 1838*0Sstevel@tonic-gate */ 1839*0Sstevel@tonic-gate if ((descsz = *data++) != 0) { 1840*0Sstevel@tonic-gate /* 1841*0Sstevel@tonic-gate * If namesz isn't a 4-byte multiple, account for any 1842*0Sstevel@tonic-gate * padding that must exist before the descriptor. 1843*0Sstevel@tonic-gate */ 1844*0Sstevel@tonic-gate if ((pad = (namesz & (Word)(sizeof (Word) - 1))) != 0) { 1845*0Sstevel@tonic-gate pad = (Word)sizeof (Word) - pad; 1846*0Sstevel@tonic-gate size -= pad; 1847*0Sstevel@tonic-gate } 1848*0Sstevel@tonic-gate if (size >= descsz) 1849*0Sstevel@tonic-gate size -= descsz; 1850*0Sstevel@tonic-gate else { 1851*0Sstevel@tonic-gate (void) fprintf(stderr, 1852*0Sstevel@tonic-gate MSG_INTL(MSG_NOTE_BADDESIZE), 1853*0Sstevel@tonic-gate file, cache->c_name, EC_WORD(noteoff), 1854*0Sstevel@tonic-gate EC_WORD(namesz)); 1855*0Sstevel@tonic-gate (void) fflush(stderr); 1856*0Sstevel@tonic-gate return; 1857*0Sstevel@tonic-gate } 1858*0Sstevel@tonic-gate } 1859*0Sstevel@tonic-gate 1860*0Sstevel@tonic-gate type = *data++; 1861*0Sstevel@tonic-gate 1862*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1863*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_NOTE_TYPE), EC_WORD(type)); 1864*0Sstevel@tonic-gate 1865*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_NOTE_NAMESZ), EC_WORD(namesz)); 1866*0Sstevel@tonic-gate if (namesz) { 1867*0Sstevel@tonic-gate char *name = (char *)data; 1868*0Sstevel@tonic-gate 1869*0Sstevel@tonic-gate /* 1870*0Sstevel@tonic-gate * Since the name string may have 'null' bytes 1871*0Sstevel@tonic-gate * in it (ia32 .string) - we just write the 1872*0Sstevel@tonic-gate * whole stream in a single fwrite. 1873*0Sstevel@tonic-gate */ 1874*0Sstevel@tonic-gate (void) fwrite(name, namesz, 1, stdout); 1875*0Sstevel@tonic-gate name = name + ((namesz + (sizeof (Word) - 1)) & 1876*0Sstevel@tonic-gate ~(sizeof (Word) - 1)); 1877*0Sstevel@tonic-gate /* LINTED */ 1878*0Sstevel@tonic-gate data = (Word *)name; 1879*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1880*0Sstevel@tonic-gate } 1881*0Sstevel@tonic-gate 1882*0Sstevel@tonic-gate /* 1883*0Sstevel@tonic-gate * If multiple information blocks exist within a .note section 1884*0Sstevel@tonic-gate * account for any padding that must exist before the next 1885*0Sstevel@tonic-gate * information block. 1886*0Sstevel@tonic-gate */ 1887*0Sstevel@tonic-gate if ((pad = (descsz & (Word)(sizeof (Word) - 1))) != 0) { 1888*0Sstevel@tonic-gate pad = (Word)sizeof (Word) - pad; 1889*0Sstevel@tonic-gate if (size > pad) 1890*0Sstevel@tonic-gate size -= pad; 1891*0Sstevel@tonic-gate } 1892*0Sstevel@tonic-gate 1893*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_NOTE_DESCSZ), EC_WORD(descsz)); 1894*0Sstevel@tonic-gate if (descsz) { 1895*0Sstevel@tonic-gate int ndx, byte, word; 1896*0Sstevel@tonic-gate char string[58], * str = string; 1897*0Sstevel@tonic-gate uchar_t *desc = (uchar_t *)data; 1898*0Sstevel@tonic-gate 1899*0Sstevel@tonic-gate /* 1900*0Sstevel@tonic-gate * Dump descriptor bytes. 1901*0Sstevel@tonic-gate */ 1902*0Sstevel@tonic-gate for (ndx = byte = word = 0; descsz; descsz--, desc++) { 1903*0Sstevel@tonic-gate int tok = *desc; 1904*0Sstevel@tonic-gate 1905*0Sstevel@tonic-gate (void) snprintf(str, 58, MSG_ORIG(MSG_NOTE_TOK), 1906*0Sstevel@tonic-gate tok); 1907*0Sstevel@tonic-gate str += 3; 1908*0Sstevel@tonic-gate 1909*0Sstevel@tonic-gate if (++byte == 4) { 1910*0Sstevel@tonic-gate *str++ = ' ', *str++ = ' '; 1911*0Sstevel@tonic-gate word++; 1912*0Sstevel@tonic-gate byte = 0; 1913*0Sstevel@tonic-gate } 1914*0Sstevel@tonic-gate if (word == 4) { 1915*0Sstevel@tonic-gate *str = '\0'; 1916*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_NOTE_DESC), 1917*0Sstevel@tonic-gate ndx, string); 1918*0Sstevel@tonic-gate word = 0; 1919*0Sstevel@tonic-gate ndx += 16; 1920*0Sstevel@tonic-gate str = string; 1921*0Sstevel@tonic-gate } 1922*0Sstevel@tonic-gate } 1923*0Sstevel@tonic-gate if (byte || word) { 1924*0Sstevel@tonic-gate *str = '\0'; 1925*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_NOTE_DESC), ndx, string); 1926*0Sstevel@tonic-gate } 1927*0Sstevel@tonic-gate 1928*0Sstevel@tonic-gate desc += pad; 1929*0Sstevel@tonic-gate /* LINTED */ 1930*0Sstevel@tonic-gate data = (Word *)desc; 1931*0Sstevel@tonic-gate } 1932*0Sstevel@tonic-gate } 1933*0Sstevel@tonic-gate } 1934*0Sstevel@tonic-gate 1935*0Sstevel@tonic-gate /* 1936*0Sstevel@tonic-gate * Search for and process a .note section. 1937*0Sstevel@tonic-gate */ 1938*0Sstevel@tonic-gate static void 1939*0Sstevel@tonic-gate note(Cache *cache, GElf_Word shnum, const char *name, const char *file) 1940*0Sstevel@tonic-gate { 1941*0Sstevel@tonic-gate GElf_Word cnt; 1942*0Sstevel@tonic-gate 1943*0Sstevel@tonic-gate /* 1944*0Sstevel@tonic-gate * Otherwise look for any .note sections. 1945*0Sstevel@tonic-gate */ 1946*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 1947*0Sstevel@tonic-gate Cache * _cache = &cache[cnt]; 1948*0Sstevel@tonic-gate GElf_Shdr * shdr = &_cache->c_shdr; 1949*0Sstevel@tonic-gate 1950*0Sstevel@tonic-gate if (shdr->sh_type != SHT_NOTE) 1951*0Sstevel@tonic-gate continue; 1952*0Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 1953*0Sstevel@tonic-gate continue; 1954*0Sstevel@tonic-gate 1955*0Sstevel@tonic-gate /* 1956*0Sstevel@tonic-gate * As these sections are often hand rolled, make sure they're 1957*0Sstevel@tonic-gate * properly aligned before proceeding. 1958*0Sstevel@tonic-gate */ 1959*0Sstevel@tonic-gate if (shdr->sh_offset & (sizeof (Word) - 1)) { 1960*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN), 1961*0Sstevel@tonic-gate file, _cache->c_name); 1962*0Sstevel@tonic-gate (void) fflush(stderr); 1963*0Sstevel@tonic-gate continue; 1964*0Sstevel@tonic-gate } 1965*0Sstevel@tonic-gate 1966*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 1967*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name); 1968*0Sstevel@tonic-gate note_entry(_cache, (Word *)_cache->c_data->d_buf, 1969*0Sstevel@tonic-gate /* LINTED */ 1970*0Sstevel@tonic-gate (Word)_cache->c_data->d_size, file); 1971*0Sstevel@tonic-gate } 1972*0Sstevel@tonic-gate } 1973*0Sstevel@tonic-gate 1974*0Sstevel@tonic-gate 1975*0Sstevel@tonic-gate #define MAXCOUNT 500 1976*0Sstevel@tonic-gate 1977*0Sstevel@tonic-gate static void 1978*0Sstevel@tonic-gate hash(Cache *cache, GElf_Word shnum, const char *name, const char *file, 1979*0Sstevel@tonic-gate uint32_t flags) 1980*0Sstevel@tonic-gate { 1981*0Sstevel@tonic-gate static int count[MAXCOUNT]; 1982*0Sstevel@tonic-gate GElf_Word cnt; 1983*0Sstevel@tonic-gate ulong_t ndx, bkts; 1984*0Sstevel@tonic-gate char number[MAXNDXSIZE]; 1985*0Sstevel@tonic-gate 1986*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 1987*0Sstevel@tonic-gate uint_t *hash, *chain; 1988*0Sstevel@tonic-gate Elf_Data *dsyms; 1989*0Sstevel@tonic-gate Cache *_cache = &cache[cnt]; 1990*0Sstevel@tonic-gate GElf_Shdr *shdr = &_cache->c_shdr; 1991*0Sstevel@tonic-gate char *sname; 1992*0Sstevel@tonic-gate 1993*0Sstevel@tonic-gate if (shdr->sh_type != SHT_HASH) 1994*0Sstevel@tonic-gate continue; 1995*0Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 1996*0Sstevel@tonic-gate continue; 1997*0Sstevel@tonic-gate 1998*0Sstevel@tonic-gate /* 1999*0Sstevel@tonic-gate * Determine the hash table data and size. 2000*0Sstevel@tonic-gate */ 2001*0Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 2002*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2003*0Sstevel@tonic-gate file, _cache->c_name); 2004*0Sstevel@tonic-gate (void) fflush(stderr); 2005*0Sstevel@tonic-gate continue; 2006*0Sstevel@tonic-gate } 2007*0Sstevel@tonic-gate hash = (uint_t *)_cache->c_data->d_buf; 2008*0Sstevel@tonic-gate bkts = *hash; 2009*0Sstevel@tonic-gate chain = hash + 2 + bkts; 2010*0Sstevel@tonic-gate hash += 2; 2011*0Sstevel@tonic-gate 2012*0Sstevel@tonic-gate /* 2013*0Sstevel@tonic-gate * Get the data buffer for the associated symbol table. 2014*0Sstevel@tonic-gate */ 2015*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 2016*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2017*0Sstevel@tonic-gate file, _cache->c_name, EC_XWORD(shdr->sh_link)); 2018*0Sstevel@tonic-gate (void) fflush(stderr); 2019*0Sstevel@tonic-gate continue; 2020*0Sstevel@tonic-gate } 2021*0Sstevel@tonic-gate dsyms = cache[shdr->sh_link].c_data; 2022*0Sstevel@tonic-gate if (dsyms->d_buf == 0) { 2023*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2024*0Sstevel@tonic-gate file, cache[shdr->sh_link].c_name); 2025*0Sstevel@tonic-gate (void) fflush(stderr); 2026*0Sstevel@tonic-gate continue; 2027*0Sstevel@tonic-gate } 2028*0Sstevel@tonic-gate 2029*0Sstevel@tonic-gate sname = cache[shdr->sh_link].c_name; 2030*0Sstevel@tonic-gate shdr = &cache[shdr->sh_link].c_shdr; 2031*0Sstevel@tonic-gate /* 2032*0Sstevel@tonic-gate * Get the associated string table section. 2033*0Sstevel@tonic-gate */ 2034*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 2035*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2036*0Sstevel@tonic-gate file, sname, EC_XWORD(shdr->sh_link)); 2037*0Sstevel@tonic-gate (void) fflush(stderr); 2038*0Sstevel@tonic-gate continue; 2039*0Sstevel@tonic-gate } 2040*0Sstevel@tonic-gate 2041*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 2042*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SCN_HASH), _cache->c_name); 2043*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_HASH_INFO)); 2044*0Sstevel@tonic-gate 2045*0Sstevel@tonic-gate /* 2046*0Sstevel@tonic-gate * Loop through the hash buckets, printing the appropriate 2047*0Sstevel@tonic-gate * symbols. 2048*0Sstevel@tonic-gate */ 2049*0Sstevel@tonic-gate for (ndx = 0; ndx < bkts; ndx++, hash++) { 2050*0Sstevel@tonic-gate GElf_Sym _sym; 2051*0Sstevel@tonic-gate const char *_str; 2052*0Sstevel@tonic-gate GElf_Word _ndx, _cnt; 2053*0Sstevel@tonic-gate char _number[MAXNDXSIZE]; 2054*0Sstevel@tonic-gate ulong_t nbkt, nhash; 2055*0Sstevel@tonic-gate 2056*0Sstevel@tonic-gate if (*hash == 0) { 2057*0Sstevel@tonic-gate count[0]++; 2058*0Sstevel@tonic-gate continue; 2059*0Sstevel@tonic-gate } 2060*0Sstevel@tonic-gate 2061*0Sstevel@tonic-gate /* LINTED */ 2062*0Sstevel@tonic-gate if (gelf_getsym(dsyms, (int)*hash, &_sym) == NULL) { 2063*0Sstevel@tonic-gate (void) fprintf(stderr, 2064*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_HSBADSYMNDX), 2065*0Sstevel@tonic-gate file, elf_errmsg(0)); 2066*0Sstevel@tonic-gate (void) fflush(stderr); 2067*0Sstevel@tonic-gate _str = MSG_INTL(MSG_STR_UNKNOWN); 2068*0Sstevel@tonic-gate } else { 2069*0Sstevel@tonic-gate _str = string(_cache, (GElf_Word)*hash, 2070*0Sstevel@tonic-gate &cache[shdr->sh_link], file, 2071*0Sstevel@tonic-gate _sym.st_name); 2072*0Sstevel@tonic-gate } 2073*0Sstevel@tonic-gate 2074*0Sstevel@tonic-gate (void) snprintf(number, MAXNDXSIZE, 2075*0Sstevel@tonic-gate /* LINTED */ 2076*0Sstevel@tonic-gate MSG_ORIG(MSG_FMT_INTEGER), (int)ndx); 2077*0Sstevel@tonic-gate (void) snprintf(_number, MAXNDXSIZE, 2078*0Sstevel@tonic-gate MSG_ORIG(MSG_FMT_INDEX2), EC_XWORD(*hash)); 2079*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_FMT_HASH_INFO), number, _number, 2080*0Sstevel@tonic-gate demangle(_str, flags)); 2081*0Sstevel@tonic-gate 2082*0Sstevel@tonic-gate /* 2083*0Sstevel@tonic-gate * Determine if this string is in the correct bucket. 2084*0Sstevel@tonic-gate */ 2085*0Sstevel@tonic-gate nhash = elf_hash(_str); 2086*0Sstevel@tonic-gate nbkt = nhash % bkts; 2087*0Sstevel@tonic-gate if (nbkt != ndx) { 2088*0Sstevel@tonic-gate (void) fprintf(stderr, 2089*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADHASH), file, 2090*0Sstevel@tonic-gate /* LINTED */ 2091*0Sstevel@tonic-gate _cache->c_name, _str, (int)ndx, (int)nbkt); 2092*0Sstevel@tonic-gate (void) fflush(stderr); 2093*0Sstevel@tonic-gate } 2094*0Sstevel@tonic-gate 2095*0Sstevel@tonic-gate /* 2096*0Sstevel@tonic-gate * Determine if any other symbols are chained to this 2097*0Sstevel@tonic-gate * bucket. 2098*0Sstevel@tonic-gate */ 2099*0Sstevel@tonic-gate _ndx = chain[*hash]; 2100*0Sstevel@tonic-gate _cnt = 1; 2101*0Sstevel@tonic-gate while (_ndx) { 2102*0Sstevel@tonic-gate /* LINTED */ 2103*0Sstevel@tonic-gate if (gelf_getsym(dsyms, (int)_ndx, 2104*0Sstevel@tonic-gate &_sym) == NULL) { 2105*0Sstevel@tonic-gate (void) fprintf(stderr, 2106*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_HSBADSYMNDX), 2107*0Sstevel@tonic-gate file, elf_errmsg(0)); 2108*0Sstevel@tonic-gate (void) fflush(stderr); 2109*0Sstevel@tonic-gate _str = MSG_INTL(MSG_STR_UNKNOWN); 2110*0Sstevel@tonic-gate } else 2111*0Sstevel@tonic-gate _str = string(_cache, _ndx, 2112*0Sstevel@tonic-gate &cache[shdr->sh_link], file, 2113*0Sstevel@tonic-gate _sym.st_name); 2114*0Sstevel@tonic-gate 2115*0Sstevel@tonic-gate (void) snprintf(_number, MAXNDXSIZE, 2116*0Sstevel@tonic-gate MSG_ORIG(MSG_FMT_INDEX2), EC_XWORD(_ndx)); 2117*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_FMT_HASH_INFO), 2118*0Sstevel@tonic-gate MSG_ORIG(MSG_STR_EMPTY), _number, 2119*0Sstevel@tonic-gate demangle(_str, flags)); 2120*0Sstevel@tonic-gate _ndx = chain[_ndx]; 2121*0Sstevel@tonic-gate _cnt++; 2122*0Sstevel@tonic-gate 2123*0Sstevel@tonic-gate /* 2124*0Sstevel@tonic-gate * Determine if this string is in the correct 2125*0Sstevel@tonic-gate * bucket. 2126*0Sstevel@tonic-gate */ 2127*0Sstevel@tonic-gate nhash = elf_hash(_str); 2128*0Sstevel@tonic-gate nbkt = nhash % bkts; 2129*0Sstevel@tonic-gate if (nbkt != ndx) { 2130*0Sstevel@tonic-gate (void) fprintf(stderr, 2131*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADHASH), file, 2132*0Sstevel@tonic-gate _cache->c_name, _str, 2133*0Sstevel@tonic-gate /* LINTED */ 2134*0Sstevel@tonic-gate (int)ndx, (int)nbkt); 2135*0Sstevel@tonic-gate (void) fflush(stderr); 2136*0Sstevel@tonic-gate } 2137*0Sstevel@tonic-gate } 2138*0Sstevel@tonic-gate 2139*0Sstevel@tonic-gate if (_cnt >= MAXCOUNT) { 2140*0Sstevel@tonic-gate (void) fprintf(stderr, 2141*0Sstevel@tonic-gate MSG_INTL(MSG_HASH_OVERFLW), 2142*0Sstevel@tonic-gate /* LINTED */ 2143*0Sstevel@tonic-gate (int)ndx, _cnt); 2144*0Sstevel@tonic-gate (void) fflush(stderr); 2145*0Sstevel@tonic-gate } else 2146*0Sstevel@tonic-gate count[_cnt]++; 2147*0Sstevel@tonic-gate } 2148*0Sstevel@tonic-gate break; 2149*0Sstevel@tonic-gate } 2150*0Sstevel@tonic-gate 2151*0Sstevel@tonic-gate /* 2152*0Sstevel@tonic-gate * Print out the count information. 2153*0Sstevel@tonic-gate */ 2154*0Sstevel@tonic-gate bkts = cnt = 0; 2155*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 2156*0Sstevel@tonic-gate for (ndx = 0; ndx < MAXCOUNT; ndx++) { 2157*0Sstevel@tonic-gate GElf_Word _cnt; 2158*0Sstevel@tonic-gate 2159*0Sstevel@tonic-gate if ((_cnt = count[ndx]) == 0) 2160*0Sstevel@tonic-gate continue; 2161*0Sstevel@tonic-gate 2162*0Sstevel@tonic-gate (void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 2163*0Sstevel@tonic-gate /* LINTED */ 2164*0Sstevel@tonic-gate (int)_cnt); 2165*0Sstevel@tonic-gate /* LINTED */ 2166*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_HASH_BKTS1), number, (int)ndx); 2167*0Sstevel@tonic-gate bkts += _cnt; 2168*0Sstevel@tonic-gate /* LINTED */ 2169*0Sstevel@tonic-gate cnt += (GElf_Word)(ndx * _cnt); 2170*0Sstevel@tonic-gate } 2171*0Sstevel@tonic-gate if (cnt) { 2172*0Sstevel@tonic-gate (void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER), 2173*0Sstevel@tonic-gate /* LINTED */ 2174*0Sstevel@tonic-gate (int)bkts); 2175*0Sstevel@tonic-gate /* LINTED */ 2176*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_HASH_BKTS2), number, (int)cnt); 2177*0Sstevel@tonic-gate } 2178*0Sstevel@tonic-gate } 2179*0Sstevel@tonic-gate 2180*0Sstevel@tonic-gate 2181*0Sstevel@tonic-gate static void 2182*0Sstevel@tonic-gate group(Cache *cache, GElf_Word shnum, const char *name, const char *file, 2183*0Sstevel@tonic-gate uint32_t flags) 2184*0Sstevel@tonic-gate { 2185*0Sstevel@tonic-gate GElf_Word cnt; 2186*0Sstevel@tonic-gate 2187*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 2188*0Sstevel@tonic-gate Cache *_cache = &cache[cnt]; 2189*0Sstevel@tonic-gate GElf_Shdr *shdr = &_cache->c_shdr; 2190*0Sstevel@tonic-gate Elf_Data *dsyms; 2191*0Sstevel@tonic-gate GElf_Shdr *symshdr; 2192*0Sstevel@tonic-gate GElf_Sym sym; 2193*0Sstevel@tonic-gate const char *symname; 2194*0Sstevel@tonic-gate char flgstrbuf[MSG_GRP_COMDAT_SIZE + 10]; 2195*0Sstevel@tonic-gate Word *grpdata; 2196*0Sstevel@tonic-gate size_t _cnt; 2197*0Sstevel@tonic-gate size_t grpcnt; 2198*0Sstevel@tonic-gate 2199*0Sstevel@tonic-gate 2200*0Sstevel@tonic-gate if (shdr->sh_type != SHT_GROUP) 2201*0Sstevel@tonic-gate continue; 2202*0Sstevel@tonic-gate if (name && strcmp(name, _cache->c_name)) 2203*0Sstevel@tonic-gate continue; 2204*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_GRP_LINE1), _cache->c_name); 2205*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 2206*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2207*0Sstevel@tonic-gate file, _cache->c_name, EC_XWORD(shdr->sh_link)); 2208*0Sstevel@tonic-gate (void) fflush(stderr); 2209*0Sstevel@tonic-gate continue; 2210*0Sstevel@tonic-gate } 2211*0Sstevel@tonic-gate 2212*0Sstevel@tonic-gate if (shdr->sh_entsize != sizeof (Word)) { 2213*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GRP_BADENTSZ), 2214*0Sstevel@tonic-gate file, _cache->c_name, 2215*0Sstevel@tonic-gate EC_XWORD(shdr->sh_entsize)); 2216*0Sstevel@tonic-gate (void) fflush(stderr); 2217*0Sstevel@tonic-gate } 2218*0Sstevel@tonic-gate symshdr = &(cache[shdr->sh_link].c_shdr); 2219*0Sstevel@tonic-gate if ((symshdr->sh_type != SHT_SYMTAB) && 2220*0Sstevel@tonic-gate (symshdr->sh_type != SHT_DYNSYM)) { 2221*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GRP_NOTSYMTAB), 2222*0Sstevel@tonic-gate file, _cache->c_name, EC_XWORD(shdr->sh_link)); 2223*0Sstevel@tonic-gate (void) fflush(stderr); 2224*0Sstevel@tonic-gate continue; 2225*0Sstevel@tonic-gate } 2226*0Sstevel@tonic-gate dsyms = cache[shdr->sh_link].c_data; 2227*0Sstevel@tonic-gate if ((shdr->sh_info == SHN_UNDEF) || ((ulong_t)shdr->sh_info > 2228*0Sstevel@tonic-gate (symshdr->sh_size / symshdr->sh_entsize))) { 2229*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GRP_BADSYMNDX), 2230*0Sstevel@tonic-gate file, _cache->c_name, EC_XWORD(shdr->sh_info)); 2231*0Sstevel@tonic-gate (void) fflush(stderr); 2232*0Sstevel@tonic-gate continue; 2233*0Sstevel@tonic-gate } 2234*0Sstevel@tonic-gate flgstrbuf[0] = '['; 2235*0Sstevel@tonic-gate flgstrbuf[1] = '\0'; 2236*0Sstevel@tonic-gate if ((shdr->sh_size != 0) && 2237*0Sstevel@tonic-gate (_cache->c_data) && 2238*0Sstevel@tonic-gate ((grpdata = (Word *)_cache->c_data->d_buf) != 0)) { 2239*0Sstevel@tonic-gate if (grpdata[0] & GRP_COMDAT) { 2240*0Sstevel@tonic-gate (void) strcat(flgstrbuf, 2241*0Sstevel@tonic-gate MSG_ORIG(MSG_GRP_COMDAT)); 2242*0Sstevel@tonic-gate } 2243*0Sstevel@tonic-gate if ((grpdata[0] & ~GRP_COMDAT) != 0) { 2244*0Sstevel@tonic-gate (void) snprintf(flgstrbuf + strlen(flgstrbuf), 2245*0Sstevel@tonic-gate (MSG_GRP_COMDAT_SIZE + 10), 2246*0Sstevel@tonic-gate MSG_ORIG(MSG_GRP_FMT1), 2247*0Sstevel@tonic-gate (uint_t)(grpdata[0] & ~GRP_COMDAT)); 2248*0Sstevel@tonic-gate } 2249*0Sstevel@tonic-gate } 2250*0Sstevel@tonic-gate (void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_CLOSBRKT)); 2251*0Sstevel@tonic-gate 2252*0Sstevel@tonic-gate if (gelf_getsym(dsyms, shdr->sh_info, &sym) == NULL) { 2253*0Sstevel@tonic-gate (void) fprintf(stderr, 2254*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_GRBADSYMNDX), 2255*0Sstevel@tonic-gate file, elf_errmsg(0)); 2256*0Sstevel@tonic-gate (void) fflush(stderr); 2257*0Sstevel@tonic-gate } 2258*0Sstevel@tonic-gate symname = demangle(string(_cache, shdr->sh_link, 2259*0Sstevel@tonic-gate &cache[symshdr->sh_link], file, sym.st_name), 2260*0Sstevel@tonic-gate flags); 2261*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_GRP_LINE2)); 2262*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_GRP_LINE3), 2263*0Sstevel@tonic-gate flgstrbuf, symname); 2264*0Sstevel@tonic-gate for (_cnt = 1, grpcnt = (shdr->sh_size / sizeof (Word)); 2265*0Sstevel@tonic-gate _cnt < grpcnt; _cnt++) { 2266*0Sstevel@tonic-gate char index[MAXNDXSIZE]; 2267*0Sstevel@tonic-gate const char *sname; 2268*0Sstevel@tonic-gate 2269*0Sstevel@tonic-gate (void) snprintf(index, MAXNDXSIZE, 2270*0Sstevel@tonic-gate MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(_cnt)); 2271*0Sstevel@tonic-gate if (grpdata[_cnt] >= shnum) { 2272*0Sstevel@tonic-gate sname = MSG_INTL(MSG_GRP_INVALSCN); 2273*0Sstevel@tonic-gate } else { 2274*0Sstevel@tonic-gate sname = cache[grpdata[_cnt]].c_name; 2275*0Sstevel@tonic-gate } 2276*0Sstevel@tonic-gate (void) printf(MSG_ORIG(MSG_GRP_FMT2), index, sname, 2277*0Sstevel@tonic-gate (uint_t)grpdata[_cnt]); 2278*0Sstevel@tonic-gate } 2279*0Sstevel@tonic-gate } 2280*0Sstevel@tonic-gate } 2281*0Sstevel@tonic-gate 2282*0Sstevel@tonic-gate 2283*0Sstevel@tonic-gate static void 2284*0Sstevel@tonic-gate got(Cache *cache, GElf_Word shnum, GElf_Ehdr *ehdr, const char *file) 2285*0Sstevel@tonic-gate { 2286*0Sstevel@tonic-gate Cache *gotcache = 0, *symtab = 0, *_cache; 2287*0Sstevel@tonic-gate GElf_Addr gotbgn, gotend; 2288*0Sstevel@tonic-gate GElf_Shdr *gotshdr; 2289*0Sstevel@tonic-gate GElf_Word cnt, gotents, gotndx; 2290*0Sstevel@tonic-gate size_t gentsize; 2291*0Sstevel@tonic-gate Got_info *gottable; 2292*0Sstevel@tonic-gate char *gotdata; 2293*0Sstevel@tonic-gate GElf_Sym gsym; 2294*0Sstevel@tonic-gate GElf_Xword gsymaddr; 2295*0Sstevel@tonic-gate 2296*0Sstevel@tonic-gate /* 2297*0Sstevel@tonic-gate * First we find the got 2298*0Sstevel@tonic-gate */ 2299*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 2300*0Sstevel@tonic-gate _cache = &cache[cnt]; 2301*0Sstevel@tonic-gate if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT), 4) == 0) { 2302*0Sstevel@tonic-gate gotcache = _cache; 2303*0Sstevel@tonic-gate break; 2304*0Sstevel@tonic-gate } 2305*0Sstevel@tonic-gate } 2306*0Sstevel@tonic-gate if (!gotcache) 2307*0Sstevel@tonic-gate return; 2308*0Sstevel@tonic-gate gotshdr = &gotcache->c_shdr; 2309*0Sstevel@tonic-gate gotbgn = gotshdr->sh_addr; 2310*0Sstevel@tonic-gate 2311*0Sstevel@tonic-gate if (gotshdr->sh_size == 0) { 2312*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2313*0Sstevel@tonic-gate file, gotcache->c_name); 2314*0Sstevel@tonic-gate (void) fflush(stderr); 2315*0Sstevel@tonic-gate return; 2316*0Sstevel@tonic-gate } 2317*0Sstevel@tonic-gate gotend = gotbgn + gotshdr->sh_size; 2318*0Sstevel@tonic-gate 2319*0Sstevel@tonic-gate /* 2320*0Sstevel@tonic-gate * Some architectures don't properly set the sh_entsize 2321*0Sstevel@tonic-gate * for the GOT table. If it's not set we will default 2322*0Sstevel@tonic-gate * to a size of a pointer. 2323*0Sstevel@tonic-gate */ 2324*0Sstevel@tonic-gate if ((gentsize = gotshdr->sh_entsize) == 0) { 2325*0Sstevel@tonic-gate if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) 2326*0Sstevel@tonic-gate gentsize = sizeof (GElf_Xword); 2327*0Sstevel@tonic-gate else 2328*0Sstevel@tonic-gate gentsize = sizeof (GElf_Word); 2329*0Sstevel@tonic-gate } 2330*0Sstevel@tonic-gate /* LINTED */ 2331*0Sstevel@tonic-gate gotents = (GElf_Word)(gotshdr->sh_size / gentsize); 2332*0Sstevel@tonic-gate gotdata = gotcache->c_data->d_buf; 2333*0Sstevel@tonic-gate 2334*0Sstevel@tonic-gate if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) { 2335*0Sstevel@tonic-gate int err = errno; 2336*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2337*0Sstevel@tonic-gate file, strerror(err)); 2338*0Sstevel@tonic-gate (void) fflush(stderr); 2339*0Sstevel@tonic-gate return; 2340*0Sstevel@tonic-gate } 2341*0Sstevel@tonic-gate 2342*0Sstevel@tonic-gate /* 2343*0Sstevel@tonic-gate * Now we scan through all the sections looking for any relocations 2344*0Sstevel@tonic-gate * that may be against the GOT. Since these may not be isolated to a 2345*0Sstevel@tonic-gate * .rel[a].got section we check them all. 2346*0Sstevel@tonic-gate * While scanning sections save the symbol table entry (a symtab 2347*0Sstevel@tonic-gate * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_. 2348*0Sstevel@tonic-gate */ 2349*0Sstevel@tonic-gate for (cnt = 1; cnt < shnum; cnt++) { 2350*0Sstevel@tonic-gate GElf_Shdr *shdr; 2351*0Sstevel@tonic-gate GElf_Word rtype; 2352*0Sstevel@tonic-gate Elf_Data *dsyms, *reldata; 2353*0Sstevel@tonic-gate GElf_Rela rela; 2354*0Sstevel@tonic-gate ulong_t rcount; 2355*0Sstevel@tonic-gate int ndx; 2356*0Sstevel@tonic-gate char *sname; 2357*0Sstevel@tonic-gate 2358*0Sstevel@tonic-gate _cache = &cache[cnt]; 2359*0Sstevel@tonic-gate shdr = &_cache->c_shdr; 2360*0Sstevel@tonic-gate 2361*0Sstevel@tonic-gate if ((symtab == 0) && (shdr->sh_type == SHT_DYNSYM)) { 2362*0Sstevel@tonic-gate symtab = _cache; 2363*0Sstevel@tonic-gate continue; 2364*0Sstevel@tonic-gate } 2365*0Sstevel@tonic-gate if (shdr->sh_type == SHT_SYMTAB) { 2366*0Sstevel@tonic-gate symtab = _cache; 2367*0Sstevel@tonic-gate continue; 2368*0Sstevel@tonic-gate } 2369*0Sstevel@tonic-gate 2370*0Sstevel@tonic-gate rtype = shdr->sh_type; 2371*0Sstevel@tonic-gate if ((rtype != SHT_RELA) && (rtype != SHT_REL)) 2372*0Sstevel@tonic-gate continue; 2373*0Sstevel@tonic-gate 2374*0Sstevel@tonic-gate /* 2375*0Sstevel@tonic-gate * Determine the relocation data and number. 2376*0Sstevel@tonic-gate */ 2377*0Sstevel@tonic-gate if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 2378*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2379*0Sstevel@tonic-gate file, _cache->c_name); 2380*0Sstevel@tonic-gate (void) fflush(stderr); 2381*0Sstevel@tonic-gate continue; 2382*0Sstevel@tonic-gate } 2383*0Sstevel@tonic-gate rcount = shdr->sh_size / shdr->sh_entsize; 2384*0Sstevel@tonic-gate 2385*0Sstevel@tonic-gate reldata = _cache->c_data; 2386*0Sstevel@tonic-gate 2387*0Sstevel@tonic-gate /* 2388*0Sstevel@tonic-gate * Get the data buffer for the associated symbol table. 2389*0Sstevel@tonic-gate */ 2390*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 2391*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2392*0Sstevel@tonic-gate file, _cache->c_name, EC_XWORD(shdr->sh_link)); 2393*0Sstevel@tonic-gate (void) fflush(stderr); 2394*0Sstevel@tonic-gate continue; 2395*0Sstevel@tonic-gate } 2396*0Sstevel@tonic-gate dsyms = cache[shdr->sh_link].c_data; 2397*0Sstevel@tonic-gate if (dsyms->d_buf == 0) { 2398*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2399*0Sstevel@tonic-gate file, cache[shdr->sh_link].c_name); 2400*0Sstevel@tonic-gate (void) fflush(stderr); 2401*0Sstevel@tonic-gate continue; 2402*0Sstevel@tonic-gate } 2403*0Sstevel@tonic-gate 2404*0Sstevel@tonic-gate sname = cache[shdr->sh_link].c_name; 2405*0Sstevel@tonic-gate shdr = &cache[shdr->sh_link].c_shdr; 2406*0Sstevel@tonic-gate /* 2407*0Sstevel@tonic-gate * Get the associated string table section. 2408*0Sstevel@tonic-gate */ 2409*0Sstevel@tonic-gate if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 2410*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 2411*0Sstevel@tonic-gate file, sname, EC_XWORD(shdr->sh_link)); 2412*0Sstevel@tonic-gate (void) fflush(stderr); 2413*0Sstevel@tonic-gate continue; 2414*0Sstevel@tonic-gate } 2415*0Sstevel@tonic-gate 2416*0Sstevel@tonic-gate /* LINTED */ 2417*0Sstevel@tonic-gate for (ndx = 0; ndx < rcount; ++ndx) { 2418*0Sstevel@tonic-gate GElf_Sym _sym; 2419*0Sstevel@tonic-gate GElf_Word sndx; 2420*0Sstevel@tonic-gate GElf_Addr offset; 2421*0Sstevel@tonic-gate Got_info *gip; 2422*0Sstevel@tonic-gate void *relret; 2423*0Sstevel@tonic-gate 2424*0Sstevel@tonic-gate if (rtype == SHT_RELA) { 2425*0Sstevel@tonic-gate relret = (void *)gelf_getrela(reldata, ndx, 2426*0Sstevel@tonic-gate &rela); 2427*0Sstevel@tonic-gate } else { 2428*0Sstevel@tonic-gate relret = (void *)gelf_getrel(reldata, ndx, 2429*0Sstevel@tonic-gate (GElf_Rel *)&rela); 2430*0Sstevel@tonic-gate } 2431*0Sstevel@tonic-gate if (relret == NULL) { 2432*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADREL), 2433*0Sstevel@tonic-gate file, _cache->c_name, elf_errmsg(0)); 2434*0Sstevel@tonic-gate (void) fflush(stderr); 2435*0Sstevel@tonic-gate break; 2436*0Sstevel@tonic-gate } 2437*0Sstevel@tonic-gate 2438*0Sstevel@tonic-gate offset = rela.r_offset; 2439*0Sstevel@tonic-gate /* LINTED */ 2440*0Sstevel@tonic-gate sndx = (GElf_Word)GELF_R_SYM(rela.r_info); 2441*0Sstevel@tonic-gate 2442*0Sstevel@tonic-gate /* 2443*0Sstevel@tonic-gate * Only pay attention to relocations against the GOT. 2444*0Sstevel@tonic-gate */ 2445*0Sstevel@tonic-gate if ((offset < gotbgn) || (offset > gotend)) 2446*0Sstevel@tonic-gate continue; 2447*0Sstevel@tonic-gate 2448*0Sstevel@tonic-gate /* LINTED */ 2449*0Sstevel@tonic-gate gotndx = (GElf_Word)((offset - gotbgn) / 2450*0Sstevel@tonic-gate gotshdr->sh_entsize); 2451*0Sstevel@tonic-gate gip = &gottable[gotndx]; 2452*0Sstevel@tonic-gate if (gip->g_rshtype != 0) { 2453*0Sstevel@tonic-gate (void) fprintf(stderr, 2454*0Sstevel@tonic-gate MSG_INTL(MSG_GOT_MULTIPLE), file, 2455*0Sstevel@tonic-gate /* LINTED */ 2456*0Sstevel@tonic-gate EC_WORD(gotndx), EC_XWORD(offset)); 2457*0Sstevel@tonic-gate (void) fflush(stderr); 2458*0Sstevel@tonic-gate continue; 2459*0Sstevel@tonic-gate } 2460*0Sstevel@tonic-gate 2461*0Sstevel@tonic-gate /* LINTED */ 2462*0Sstevel@tonic-gate if (gelf_getsym(dsyms, sndx, &_sym) == NULL) { 2463*0Sstevel@tonic-gate (void) fprintf(stderr, 2464*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_RELBADSYMNDX), 2465*0Sstevel@tonic-gate file, elf_errmsg(0)); 2466*0Sstevel@tonic-gate (void) fflush(stderr); 2467*0Sstevel@tonic-gate gip->g_symname = MSG_INTL(MSG_STR_UNKNOWN); 2468*0Sstevel@tonic-gate } else { 2469*0Sstevel@tonic-gate gip->g_symname = string(_cache, sndx, 2470*0Sstevel@tonic-gate &cache[shdr->sh_link], file, _sym.st_name); 2471*0Sstevel@tonic-gate } 2472*0Sstevel@tonic-gate gip->g_rshtype = rtype; 2473*0Sstevel@tonic-gate gip->g_rela = rela; 2474*0Sstevel@tonic-gate } 2475*0Sstevel@tonic-gate } 2476*0Sstevel@tonic-gate 2477*0Sstevel@tonic-gate if (symlookup(MSG_ORIG(MSG_GOT_SYM), cache, shnum, &gsym, symtab, file)) 2478*0Sstevel@tonic-gate gsymaddr = gsym.st_value; 2479*0Sstevel@tonic-gate else 2480*0Sstevel@tonic-gate gsymaddr = gotbgn; 2481*0Sstevel@tonic-gate 2482*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 2483*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name, gotents); 2484*0Sstevel@tonic-gate Gelf_got_title(ehdr->e_ident[EI_CLASS]); 2485*0Sstevel@tonic-gate 2486*0Sstevel@tonic-gate for (gotndx = 0; gotndx < gotents; gotndx++) { 2487*0Sstevel@tonic-gate Got_info *gip; 2488*0Sstevel@tonic-gate Sword gindex; 2489*0Sstevel@tonic-gate GElf_Addr gaddr; 2490*0Sstevel@tonic-gate GElf_Xword gotentry; 2491*0Sstevel@tonic-gate 2492*0Sstevel@tonic-gate gip = &gottable[gotndx]; 2493*0Sstevel@tonic-gate 2494*0Sstevel@tonic-gate gaddr = gotbgn + (gotndx * gentsize); 2495*0Sstevel@tonic-gate /* LINTED */ 2496*0Sstevel@tonic-gate gindex = (Sword)((gaddr - gsymaddr) / gentsize); 2497*0Sstevel@tonic-gate 2498*0Sstevel@tonic-gate if (gentsize == sizeof (GElf_Word)) 2499*0Sstevel@tonic-gate /* LINTED */ 2500*0Sstevel@tonic-gate gotentry = (GElf_Xword)(*((GElf_Word *)(gotdata) + 2501*0Sstevel@tonic-gate gotndx)); 2502*0Sstevel@tonic-gate else 2503*0Sstevel@tonic-gate /* LINTED */ 2504*0Sstevel@tonic-gate gotentry = *((GElf_Xword *)(gotdata) + gotndx); 2505*0Sstevel@tonic-gate 2506*0Sstevel@tonic-gate Gelf_got_entry(ehdr, gindex, gaddr, gotentry, gip->g_rshtype, 2507*0Sstevel@tonic-gate &gip->g_rela, gip->g_symname); 2508*0Sstevel@tonic-gate } 2509*0Sstevel@tonic-gate 2510*0Sstevel@tonic-gate free(gottable); 2511*0Sstevel@tonic-gate } 2512*0Sstevel@tonic-gate 2513*0Sstevel@tonic-gate void 2514*0Sstevel@tonic-gate checksum(Elf *elf) 2515*0Sstevel@tonic-gate { 2516*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 2517*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_STR_CHECKSUM), gelf_checksum(elf)); 2518*0Sstevel@tonic-gate } 2519*0Sstevel@tonic-gate 2520*0Sstevel@tonic-gate static void 2521*0Sstevel@tonic-gate regular(const char *file, Elf *elf, uint32_t flags, char *Nname, int wfd) 2522*0Sstevel@tonic-gate { 2523*0Sstevel@tonic-gate Elf_Scn *scn; 2524*0Sstevel@tonic-gate GElf_Ehdr ehdr; 2525*0Sstevel@tonic-gate Elf_Data *data; 2526*0Sstevel@tonic-gate uint_t cnt; 2527*0Sstevel@tonic-gate GElf_Word shnum; 2528*0Sstevel@tonic-gate size_t shstrndx, _shnum; 2529*0Sstevel@tonic-gate GElf_Shdr nameshdr; 2530*0Sstevel@tonic-gate GElf_Shdr shdr0; 2531*0Sstevel@tonic-gate GElf_Shdr *_shdr0; 2532*0Sstevel@tonic-gate char *names = 0; 2533*0Sstevel@tonic-gate Cache *cache, *_cache; 2534*0Sstevel@tonic-gate Cache *versymcache; 2535*0Sstevel@tonic-gate 2536*0Sstevel@tonic-gate if (gelf_getehdr(elf, &ehdr) == NULL) { 2537*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETEHDR)); 2538*0Sstevel@tonic-gate return; 2539*0Sstevel@tonic-gate } 2540*0Sstevel@tonic-gate 2541*0Sstevel@tonic-gate if (elf_getshnum(elf, &_shnum) == NULL) { 2542*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHNUM)); 2543*0Sstevel@tonic-gate return; 2544*0Sstevel@tonic-gate } 2545*0Sstevel@tonic-gate /* LINTED */ 2546*0Sstevel@tonic-gate shnum = (GElf_Word)_shnum; 2547*0Sstevel@tonic-gate 2548*0Sstevel@tonic-gate if (elf_getshstrndx(elf, &shstrndx) == NULL) { 2549*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHSTRNDX)); 2550*0Sstevel@tonic-gate return; 2551*0Sstevel@tonic-gate } 2552*0Sstevel@tonic-gate if ((scn = elf_getscn(elf, 0)) != NULL) { 2553*0Sstevel@tonic-gate if ((_shdr0 = gelf_getshdr(scn, &shdr0)) == NULL) { 2554*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2555*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0); 2556*0Sstevel@tonic-gate (void) fflush(stderr); 2557*0Sstevel@tonic-gate return; 2558*0Sstevel@tonic-gate } 2559*0Sstevel@tonic-gate } else 2560*0Sstevel@tonic-gate _shdr0 = 0; 2561*0Sstevel@tonic-gate 2562*0Sstevel@tonic-gate /* 2563*0Sstevel@tonic-gate * Print the elf header. 2564*0Sstevel@tonic-gate */ 2565*0Sstevel@tonic-gate if (flags & FLG_EHDR) 2566*0Sstevel@tonic-gate Gelf_elf_header(&ehdr, _shdr0); 2567*0Sstevel@tonic-gate 2568*0Sstevel@tonic-gate /* 2569*0Sstevel@tonic-gate * Print the program headers. 2570*0Sstevel@tonic-gate */ 2571*0Sstevel@tonic-gate if ((flags & FLG_PHDR) && ehdr.e_phnum) { 2572*0Sstevel@tonic-gate GElf_Phdr phdr; 2573*0Sstevel@tonic-gate 2574*0Sstevel@tonic-gate for (cnt = 0; cnt < ehdr.e_phnum; cnt++) { 2575*0Sstevel@tonic-gate if (gelf_getphdr(elf, cnt, &phdr) == NULL) { 2576*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 2577*0Sstevel@tonic-gate return; 2578*0Sstevel@tonic-gate } 2579*0Sstevel@tonic-gate 2580*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 2581*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ELF_PHDR), cnt); 2582*0Sstevel@tonic-gate Gelf_phdr_entry(ehdr.e_machine, &phdr); 2583*0Sstevel@tonic-gate } 2584*0Sstevel@tonic-gate } 2585*0Sstevel@tonic-gate 2586*0Sstevel@tonic-gate 2587*0Sstevel@tonic-gate /* 2588*0Sstevel@tonic-gate * If there are no sections (core files), or if we don't want 2589*0Sstevel@tonic-gate * any section information we might as well return now. 2590*0Sstevel@tonic-gate */ 2591*0Sstevel@tonic-gate if ((shnum == 0) || (flags && (flags & ~(FLG_EHDR | FLG_PHDR)) == 0)) { 2592*0Sstevel@tonic-gate if ((ehdr.e_type == ET_CORE) && (flags & FLG_NOTE)) 2593*0Sstevel@tonic-gate note(0, shnum, 0, file); 2594*0Sstevel@tonic-gate return; 2595*0Sstevel@tonic-gate } 2596*0Sstevel@tonic-gate 2597*0Sstevel@tonic-gate 2598*0Sstevel@tonic-gate /* 2599*0Sstevel@tonic-gate * Obtain the .shstrtab data buffer to provide the required section 2600*0Sstevel@tonic-gate * name strings. 2601*0Sstevel@tonic-gate */ 2602*0Sstevel@tonic-gate if ((scn = elf_getscn(elf, shstrndx)) == NULL) { 2603*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSCN)); 2604*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR), 2605*0Sstevel@tonic-gate EC_XWORD(shstrndx)); 2606*0Sstevel@tonic-gate (void) fflush(stderr); 2607*0Sstevel@tonic-gate } else if ((data = elf_getdata(scn, NULL)) == NULL) { 2608*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 2609*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA), 2610*0Sstevel@tonic-gate EC_XWORD(shstrndx)); 2611*0Sstevel@tonic-gate (void) fflush(stderr); 2612*0Sstevel@tonic-gate } else if (gelf_getshdr(scn, &nameshdr) == NULL) { 2613*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2614*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 2615*0Sstevel@tonic-gate /* LINTED */ 2616*0Sstevel@tonic-gate (int)elf_ndxscn(scn)); 2617*0Sstevel@tonic-gate (void) fflush(stderr); 2618*0Sstevel@tonic-gate } else if ((names = data->d_buf) == 0) { 2619*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file); 2620*0Sstevel@tonic-gate (void) fflush(stderr); 2621*0Sstevel@tonic-gate } 2622*0Sstevel@tonic-gate 2623*0Sstevel@tonic-gate /* 2624*0Sstevel@tonic-gate * Fill in the cache descriptor with information for each section. 2625*0Sstevel@tonic-gate */ 2626*0Sstevel@tonic-gate if ((cache = malloc(shnum * sizeof (Cache))) == 0) { 2627*0Sstevel@tonic-gate int err = errno; 2628*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2629*0Sstevel@tonic-gate file, strerror(err)); 2630*0Sstevel@tonic-gate (void) fflush(stderr); 2631*0Sstevel@tonic-gate return; 2632*0Sstevel@tonic-gate } 2633*0Sstevel@tonic-gate 2634*0Sstevel@tonic-gate *cache = _cache_init; 2635*0Sstevel@tonic-gate _cache = cache; 2636*0Sstevel@tonic-gate _cache++; 2637*0Sstevel@tonic-gate 2638*0Sstevel@tonic-gate for (cnt = 1, scn = NULL; scn = elf_nextscn(elf, scn); 2639*0Sstevel@tonic-gate cnt++, _cache++) { 2640*0Sstevel@tonic-gate if (gelf_getshdr(scn, &_cache->c_shdr) == NULL) { 2641*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETSHDR)); 2642*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 2643*0Sstevel@tonic-gate /* LINTED */ 2644*0Sstevel@tonic-gate (int)elf_ndxscn(scn)); 2645*0Sstevel@tonic-gate (void) fflush(stderr); 2646*0Sstevel@tonic-gate } 2647*0Sstevel@tonic-gate 2648*0Sstevel@tonic-gate if (names && _cache->c_shdr.sh_name && 2649*0Sstevel@tonic-gate /* LINTED */ 2650*0Sstevel@tonic-gate (nameshdr.sh_size > _cache->c_shdr.sh_name)) 2651*0Sstevel@tonic-gate _cache->c_name = names + _cache->c_shdr.sh_name; 2652*0Sstevel@tonic-gate else { 2653*0Sstevel@tonic-gate /* 2654*0Sstevel@tonic-gate * If there exists no shstrtab data, or a section header 2655*0Sstevel@tonic-gate * has no name (an invalid index of 0), then compose a 2656*0Sstevel@tonic-gate * name for each section. 2657*0Sstevel@tonic-gate */ 2658*0Sstevel@tonic-gate char scnndxnm[100]; 2659*0Sstevel@tonic-gate 2660*0Sstevel@tonic-gate (void) snprintf(scnndxnm, 100, MSG_INTL(MSG_FMT_SCNNDX), 2661*0Sstevel@tonic-gate cnt); 2662*0Sstevel@tonic-gate 2663*0Sstevel@tonic-gate /* 2664*0Sstevel@tonic-gate * Although we have a valid shstrtab section inform the 2665*0Sstevel@tonic-gate * user if this section name index exceeds the shstrtab 2666*0Sstevel@tonic-gate * data. 2667*0Sstevel@tonic-gate */ 2668*0Sstevel@tonic-gate if (names && 2669*0Sstevel@tonic-gate /* LINTED */ 2670*0Sstevel@tonic-gate (nameshdr.sh_size <= _cache->c_shdr.sh_name)) { 2671*0Sstevel@tonic-gate (void) fprintf(stderr, 2672*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADSHNAME), file, 2673*0Sstevel@tonic-gate _cache->c_name, 2674*0Sstevel@tonic-gate EC_XWORD(_cache->c_shdr.sh_name)); 2675*0Sstevel@tonic-gate (void) fflush(stderr); 2676*0Sstevel@tonic-gate } 2677*0Sstevel@tonic-gate 2678*0Sstevel@tonic-gate if ((_cache->c_name = 2679*0Sstevel@tonic-gate malloc(strlen(scnndxnm) + 1)) == 0) { 2680*0Sstevel@tonic-gate int err = errno; 2681*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), 2682*0Sstevel@tonic-gate file, strerror(err)); 2683*0Sstevel@tonic-gate (void) fflush(stderr); 2684*0Sstevel@tonic-gate return; 2685*0Sstevel@tonic-gate } 2686*0Sstevel@tonic-gate (void) strcpy(_cache->c_name, scnndxnm); 2687*0Sstevel@tonic-gate } 2688*0Sstevel@tonic-gate 2689*0Sstevel@tonic-gate if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) { 2690*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETDATA)); 2691*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA), 2692*0Sstevel@tonic-gate /* LINTED */ 2693*0Sstevel@tonic-gate (int)elf_ndxscn(scn)); 2694*0Sstevel@tonic-gate (void) fflush(stderr); 2695*0Sstevel@tonic-gate } 2696*0Sstevel@tonic-gate 2697*0Sstevel@tonic-gate /* 2698*0Sstevel@tonic-gate * Do we wish to write the section out? 2699*0Sstevel@tonic-gate */ 2700*0Sstevel@tonic-gate if (wfd && Nname && (strcmp(Nname, _cache->c_name) == 0)) { 2701*0Sstevel@tonic-gate (void) write(wfd, _cache->c_data->d_buf, 2702*0Sstevel@tonic-gate _cache->c_data->d_size); 2703*0Sstevel@tonic-gate } 2704*0Sstevel@tonic-gate } 2705*0Sstevel@tonic-gate 2706*0Sstevel@tonic-gate if (flags & FLG_SHDR) 2707*0Sstevel@tonic-gate sections(file, cache, shnum, &ehdr, Nname); 2708*0Sstevel@tonic-gate 2709*0Sstevel@tonic-gate if (flags & FLG_INTERP) 2710*0Sstevel@tonic-gate interp(file, cache, shnum, &ehdr, elf); 2711*0Sstevel@tonic-gate 2712*0Sstevel@tonic-gate versymcache = versions(cache, shnum, file, flags); 2713*0Sstevel@tonic-gate 2714*0Sstevel@tonic-gate if (flags & FLG_SYMBOLS) 2715*0Sstevel@tonic-gate symbols(cache, shnum, &ehdr, Nname, versymcache, file); 2716*0Sstevel@tonic-gate 2717*0Sstevel@tonic-gate if (flags & FLG_HASH) 2718*0Sstevel@tonic-gate hash(cache, shnum, Nname, file, flags); 2719*0Sstevel@tonic-gate 2720*0Sstevel@tonic-gate if (flags & FLG_GOT) 2721*0Sstevel@tonic-gate got(cache, shnum, &ehdr, file); 2722*0Sstevel@tonic-gate 2723*0Sstevel@tonic-gate if (flags & FLG_GROUP) 2724*0Sstevel@tonic-gate group(cache, shnum, Nname, file, flags); 2725*0Sstevel@tonic-gate 2726*0Sstevel@tonic-gate if (flags & FLG_SYMINFO) 2727*0Sstevel@tonic-gate syminfo(cache, shnum, file); 2728*0Sstevel@tonic-gate 2729*0Sstevel@tonic-gate if (flags & FLG_RELOC) 2730*0Sstevel@tonic-gate reloc(cache, shnum, &ehdr, Nname, file, flags); 2731*0Sstevel@tonic-gate 2732*0Sstevel@tonic-gate if (flags & FLG_DYNAMIC) 2733*0Sstevel@tonic-gate dynamic(cache, shnum, &ehdr, file); 2734*0Sstevel@tonic-gate 2735*0Sstevel@tonic-gate if (flags & FLG_NOTE) 2736*0Sstevel@tonic-gate note(cache, shnum, Nname, file); 2737*0Sstevel@tonic-gate 2738*0Sstevel@tonic-gate if (flags & FLG_MOVE) 2739*0Sstevel@tonic-gate move(cache, shnum, Nname, file, flags); 2740*0Sstevel@tonic-gate 2741*0Sstevel@tonic-gate if (flags & FLG_CHECKSUM) 2742*0Sstevel@tonic-gate checksum(elf); 2743*0Sstevel@tonic-gate 2744*0Sstevel@tonic-gate if (flags & FLG_CAP) 2745*0Sstevel@tonic-gate cap(file, cache, shnum, &ehdr, elf); 2746*0Sstevel@tonic-gate 2747*0Sstevel@tonic-gate if (flags & FLG_UNWIND) 2748*0Sstevel@tonic-gate unwind(cache, shnum, &ehdr, Nname, file, elf); 2749*0Sstevel@tonic-gate 2750*0Sstevel@tonic-gate free(cache); 2751*0Sstevel@tonic-gate } 2752*0Sstevel@tonic-gate 2753*0Sstevel@tonic-gate static void 2754*0Sstevel@tonic-gate archive(const char *file, int fd, Elf *elf, uint32_t flags, char *Nname, 2755*0Sstevel@tonic-gate int wfd) 2756*0Sstevel@tonic-gate { 2757*0Sstevel@tonic-gate Elf_Cmd cmd = ELF_C_READ; 2758*0Sstevel@tonic-gate Elf_Arhdr *arhdr; 2759*0Sstevel@tonic-gate Elf *_elf = 0; 2760*0Sstevel@tonic-gate size_t ptr; 2761*0Sstevel@tonic-gate Elf_Arsym *arsym = 0; 2762*0Sstevel@tonic-gate 2763*0Sstevel@tonic-gate /* 2764*0Sstevel@tonic-gate * Determine if the archive sysmbol table itself is required. 2765*0Sstevel@tonic-gate */ 2766*0Sstevel@tonic-gate if ((flags & FLG_SYMBOLS) && ((Nname == NULL) || 2767*0Sstevel@tonic-gate (strcmp(Nname, MSG_ORIG(MSG_ELF_ARSYM)) == 0))) { 2768*0Sstevel@tonic-gate /* 2769*0Sstevel@tonic-gate * Get the archive symbol table. 2770*0Sstevel@tonic-gate */ 2771*0Sstevel@tonic-gate if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) { 2772*0Sstevel@tonic-gate /* 2773*0Sstevel@tonic-gate * The arsym could be 0 even though there was no error. 2774*0Sstevel@tonic-gate * Print the error message only when there was 2775*0Sstevel@tonic-gate * real error from elf_getarsym(). 2776*0Sstevel@tonic-gate */ 2777*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETARSYM)); 2778*0Sstevel@tonic-gate return; 2779*0Sstevel@tonic-gate } 2780*0Sstevel@tonic-gate } 2781*0Sstevel@tonic-gate 2782*0Sstevel@tonic-gate /* 2783*0Sstevel@tonic-gate * Print the archive symbol table only when the archive symbol 2784*0Sstevel@tonic-gate * table exists and it was requested to print. 2785*0Sstevel@tonic-gate */ 2786*0Sstevel@tonic-gate if (arsym) { 2787*0Sstevel@tonic-gate size_t cnt; 2788*0Sstevel@tonic-gate char index[MAXNDXSIZE]; 2789*0Sstevel@tonic-gate size_t offset = 0, _offset = 0; 2790*0Sstevel@tonic-gate 2791*0Sstevel@tonic-gate /* 2792*0Sstevel@tonic-gate * Print out all the symbol entries. 2793*0Sstevel@tonic-gate */ 2794*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ARCHIVE_SYMTAB)); 2795*0Sstevel@tonic-gate dbg_print(MSG_INTL(MSG_ARCHIVE_FIELDS)); 2796*0Sstevel@tonic-gate 2797*0Sstevel@tonic-gate for (cnt = 0; cnt < ptr; cnt++, arsym++) { 2798*0Sstevel@tonic-gate /* 2799*0Sstevel@tonic-gate * For each object obtain an elf descriptor so that we 2800*0Sstevel@tonic-gate * can establish the members name. Note, we have had 2801*0Sstevel@tonic-gate * archives where the archive header has not been 2802*0Sstevel@tonic-gate * obtainable so be lenient with errors. 2803*0Sstevel@tonic-gate */ 2804*0Sstevel@tonic-gate if ((offset == 0) || ((arsym->as_off != 0) && 2805*0Sstevel@tonic-gate (arsym->as_off != _offset))) { 2806*0Sstevel@tonic-gate 2807*0Sstevel@tonic-gate if (_elf) 2808*0Sstevel@tonic-gate (void) elf_end(_elf); 2809*0Sstevel@tonic-gate 2810*0Sstevel@tonic-gate if (elf_rand(elf, arsym->as_off) != 2811*0Sstevel@tonic-gate arsym->as_off) { 2812*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_RAND)); 2813*0Sstevel@tonic-gate arhdr = 0; 2814*0Sstevel@tonic-gate } else if ((_elf = elf_begin(fd, 2815*0Sstevel@tonic-gate ELF_C_READ, elf)) == 0) { 2816*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 2817*0Sstevel@tonic-gate arhdr = 0; 2818*0Sstevel@tonic-gate } else if ((arhdr = elf_getarhdr(_elf)) == 0) { 2819*0Sstevel@tonic-gate failure(file, 2820*0Sstevel@tonic-gate MSG_ORIG(MSG_ELF_GETARHDR)); 2821*0Sstevel@tonic-gate arhdr = 0; 2822*0Sstevel@tonic-gate } 2823*0Sstevel@tonic-gate 2824*0Sstevel@tonic-gate _offset = arsym->as_off; 2825*0Sstevel@tonic-gate if (offset == 0) 2826*0Sstevel@tonic-gate offset = _offset; 2827*0Sstevel@tonic-gate } 2828*0Sstevel@tonic-gate 2829*0Sstevel@tonic-gate (void) snprintf(index, MAXNDXSIZE, 2830*0Sstevel@tonic-gate MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt)); 2831*0Sstevel@tonic-gate if (arsym->as_off) 2832*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_FMT_ARSYM1), index, 2833*0Sstevel@tonic-gate /* LINTED */ 2834*0Sstevel@tonic-gate (int)arsym->as_off, arhdr ? arhdr->ar_name : 2835*0Sstevel@tonic-gate MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ? 2836*0Sstevel@tonic-gate demangle(arsym->as_name, flags) : 2837*0Sstevel@tonic-gate MSG_INTL(MSG_STR_NULL))); 2838*0Sstevel@tonic-gate else 2839*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_FMT_ARSYM2), index, 2840*0Sstevel@tonic-gate /* LINTED */ 2841*0Sstevel@tonic-gate (int)arsym->as_off); 2842*0Sstevel@tonic-gate } 2843*0Sstevel@tonic-gate 2844*0Sstevel@tonic-gate if (_elf) 2845*0Sstevel@tonic-gate (void) elf_end(_elf); 2846*0Sstevel@tonic-gate 2847*0Sstevel@tonic-gate /* 2848*0Sstevel@tonic-gate * If we only need the archive symbol table return. 2849*0Sstevel@tonic-gate */ 2850*0Sstevel@tonic-gate if ((flags & FLG_SYMBOLS) && Nname && 2851*0Sstevel@tonic-gate (strcmp(Nname, MSG_ORIG(MSG_ELF_ARSYM)) == 0)) 2852*0Sstevel@tonic-gate return; 2853*0Sstevel@tonic-gate 2854*0Sstevel@tonic-gate /* 2855*0Sstevel@tonic-gate * Reset elf descriptor in preparation for processing each 2856*0Sstevel@tonic-gate * member. 2857*0Sstevel@tonic-gate */ 2858*0Sstevel@tonic-gate if (offset) 2859*0Sstevel@tonic-gate (void) elf_rand(elf, offset); 2860*0Sstevel@tonic-gate } 2861*0Sstevel@tonic-gate 2862*0Sstevel@tonic-gate /* 2863*0Sstevel@tonic-gate * Process each object within the archive. 2864*0Sstevel@tonic-gate */ 2865*0Sstevel@tonic-gate while ((_elf = elf_begin(fd, cmd, elf)) != NULL) { 2866*0Sstevel@tonic-gate char name[MAXPATHLEN]; 2867*0Sstevel@tonic-gate 2868*0Sstevel@tonic-gate if ((arhdr = elf_getarhdr(_elf)) == NULL) { 2869*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_GETARHDR)); 2870*0Sstevel@tonic-gate return; 2871*0Sstevel@tonic-gate } 2872*0Sstevel@tonic-gate if (*arhdr->ar_name != '/') { 2873*0Sstevel@tonic-gate (void) snprintf(name, MAXPATHLEN, 2874*0Sstevel@tonic-gate MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name); 2875*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_FMT_NLSTR), name); 2876*0Sstevel@tonic-gate 2877*0Sstevel@tonic-gate switch (elf_kind(_elf)) { 2878*0Sstevel@tonic-gate case ELF_K_AR: 2879*0Sstevel@tonic-gate archive(name, fd, _elf, flags, Nname, wfd); 2880*0Sstevel@tonic-gate break; 2881*0Sstevel@tonic-gate case ELF_K_ELF: 2882*0Sstevel@tonic-gate regular(name, _elf, flags, Nname, wfd); 2883*0Sstevel@tonic-gate break; 2884*0Sstevel@tonic-gate default: 2885*0Sstevel@tonic-gate (void) fprintf(stderr, 2886*0Sstevel@tonic-gate MSG_INTL(MSG_ERR_BADFILE), name); 2887*0Sstevel@tonic-gate (void) fflush(stderr); 2888*0Sstevel@tonic-gate break; 2889*0Sstevel@tonic-gate } 2890*0Sstevel@tonic-gate } 2891*0Sstevel@tonic-gate 2892*0Sstevel@tonic-gate cmd = elf_next(_elf); 2893*0Sstevel@tonic-gate (void) elf_end(_elf); 2894*0Sstevel@tonic-gate } 2895*0Sstevel@tonic-gate } 2896*0Sstevel@tonic-gate 2897*0Sstevel@tonic-gate int 2898*0Sstevel@tonic-gate main(int argc, char **argv, char **envp) 2899*0Sstevel@tonic-gate { 2900*0Sstevel@tonic-gate Elf *elf; 2901*0Sstevel@tonic-gate int var, fd, wfd = 0; 2902*0Sstevel@tonic-gate char *Nname = NULL, *wname = 0; 2903*0Sstevel@tonic-gate uint32_t flags = 0, dbg_flags = 0; 2904*0Sstevel@tonic-gate 2905*0Sstevel@tonic-gate /* 2906*0Sstevel@tonic-gate * If we're on a 64-bit kernel, try to exec a full 64-bit version of 2907*0Sstevel@tonic-gate * the binary. If successful, conv_check_native() won't return. 2908*0Sstevel@tonic-gate */ 2909*0Sstevel@tonic-gate conv_check_native(argv, envp); 2910*0Sstevel@tonic-gate 2911*0Sstevel@tonic-gate /* 2912*0Sstevel@tonic-gate * Establish locale. 2913*0Sstevel@tonic-gate */ 2914*0Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 2915*0Sstevel@tonic-gate (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 2916*0Sstevel@tonic-gate 2917*0Sstevel@tonic-gate (void) setvbuf(stdout, NULL, _IOLBF, 0); 2918*0Sstevel@tonic-gate (void) setvbuf(stderr, NULL, _IOLBF, 0); 2919*0Sstevel@tonic-gate 2920*0Sstevel@tonic-gate opterr = 0; 2921*0Sstevel@tonic-gate while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) { 2922*0Sstevel@tonic-gate switch (var) { 2923*0Sstevel@tonic-gate case 'C': 2924*0Sstevel@tonic-gate flags |= FLG_DEMANGLE; 2925*0Sstevel@tonic-gate break; 2926*0Sstevel@tonic-gate case 'c': 2927*0Sstevel@tonic-gate flags |= FLG_SHDR; 2928*0Sstevel@tonic-gate break; 2929*0Sstevel@tonic-gate case 'd': 2930*0Sstevel@tonic-gate flags |= FLG_DYNAMIC; 2931*0Sstevel@tonic-gate break; 2932*0Sstevel@tonic-gate case 'e': 2933*0Sstevel@tonic-gate flags |= FLG_EHDR; 2934*0Sstevel@tonic-gate break; 2935*0Sstevel@tonic-gate case 'G': 2936*0Sstevel@tonic-gate flags |= FLG_GOT; 2937*0Sstevel@tonic-gate break; 2938*0Sstevel@tonic-gate case 'g': 2939*0Sstevel@tonic-gate flags |= FLG_GROUP; 2940*0Sstevel@tonic-gate break; 2941*0Sstevel@tonic-gate case 'H': 2942*0Sstevel@tonic-gate flags |= FLG_CAP; 2943*0Sstevel@tonic-gate break; 2944*0Sstevel@tonic-gate case 'h': 2945*0Sstevel@tonic-gate flags |= FLG_HASH; 2946*0Sstevel@tonic-gate break; 2947*0Sstevel@tonic-gate case 'i': 2948*0Sstevel@tonic-gate flags |= FLG_INTERP; 2949*0Sstevel@tonic-gate break; 2950*0Sstevel@tonic-gate case 'k': 2951*0Sstevel@tonic-gate flags |= FLG_CHECKSUM; 2952*0Sstevel@tonic-gate break; 2953*0Sstevel@tonic-gate case 'l': 2954*0Sstevel@tonic-gate flags |= FLG_LONGNAME; 2955*0Sstevel@tonic-gate break; 2956*0Sstevel@tonic-gate case 'm': 2957*0Sstevel@tonic-gate flags |= FLG_MOVE; 2958*0Sstevel@tonic-gate break; 2959*0Sstevel@tonic-gate case 'N': 2960*0Sstevel@tonic-gate Nname = optarg; 2961*0Sstevel@tonic-gate break; 2962*0Sstevel@tonic-gate case 'n': 2963*0Sstevel@tonic-gate flags |= FLG_NOTE; 2964*0Sstevel@tonic-gate break; 2965*0Sstevel@tonic-gate case 'p': 2966*0Sstevel@tonic-gate flags |= FLG_PHDR; 2967*0Sstevel@tonic-gate break; 2968*0Sstevel@tonic-gate case 'r': 2969*0Sstevel@tonic-gate flags |= FLG_RELOC; 2970*0Sstevel@tonic-gate break; 2971*0Sstevel@tonic-gate case 's': 2972*0Sstevel@tonic-gate flags |= FLG_SYMBOLS; 2973*0Sstevel@tonic-gate break; 2974*0Sstevel@tonic-gate case 'u': 2975*0Sstevel@tonic-gate flags |= FLG_UNWIND; 2976*0Sstevel@tonic-gate break; 2977*0Sstevel@tonic-gate case 'v': 2978*0Sstevel@tonic-gate flags |= FLG_VERSIONS; 2979*0Sstevel@tonic-gate break; 2980*0Sstevel@tonic-gate case 'w': 2981*0Sstevel@tonic-gate wname = optarg; 2982*0Sstevel@tonic-gate break; 2983*0Sstevel@tonic-gate case 'y': 2984*0Sstevel@tonic-gate flags |= FLG_SYMINFO; 2985*0Sstevel@tonic-gate break; 2986*0Sstevel@tonic-gate case '?': 2987*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 2988*0Sstevel@tonic-gate basename(argv[0])); 2989*0Sstevel@tonic-gate detail_usage(); 2990*0Sstevel@tonic-gate return (1); 2991*0Sstevel@tonic-gate default: 2992*0Sstevel@tonic-gate break; 2993*0Sstevel@tonic-gate } 2994*0Sstevel@tonic-gate } 2995*0Sstevel@tonic-gate 2996*0Sstevel@tonic-gate /* 2997*0Sstevel@tonic-gate * Validate any arguments. 2998*0Sstevel@tonic-gate */ 2999*0Sstevel@tonic-gate if (flags == 0) { 3000*0Sstevel@tonic-gate if (!wname && !Nname) { 3001*0Sstevel@tonic-gate flags = FLG_EVERYTHING; 3002*0Sstevel@tonic-gate } else if (!wname || !Nname) { 3003*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 3004*0Sstevel@tonic-gate basename(argv[0])); 3005*0Sstevel@tonic-gate return (1); 3006*0Sstevel@tonic-gate } 3007*0Sstevel@tonic-gate } 3008*0Sstevel@tonic-gate 3009*0Sstevel@tonic-gate if ((var = argc - optind) == 0) { 3010*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 3011*0Sstevel@tonic-gate basename(argv[0])); 3012*0Sstevel@tonic-gate return (1); 3013*0Sstevel@tonic-gate } 3014*0Sstevel@tonic-gate 3015*0Sstevel@tonic-gate /* 3016*0Sstevel@tonic-gate * If the -C option is used by itself, report an error since the option 3017*0Sstevel@tonic-gate * has no use without other symbol name generating options. 3018*0Sstevel@tonic-gate * 3019*0Sstevel@tonic-gate * If the -l option is used by itself, report an error. 3020*0Sstevel@tonic-gate */ 3021*0Sstevel@tonic-gate if ((flags == FLG_DEMANGLE) || (flags == FLG_LONGNAME) || 3022*0Sstevel@tonic-gate (flags == (FLG_DEMANGLE | FLG_LONGNAME))) { 3023*0Sstevel@tonic-gate if (flags & FLG_DEMANGLE) 3024*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DEMANGLE)); 3025*0Sstevel@tonic-gate if (flags & FLG_LONGNAME) 3026*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USAGE_LONGNAME)); 3027*0Sstevel@tonic-gate return (1); 3028*0Sstevel@tonic-gate } 3029*0Sstevel@tonic-gate 3030*0Sstevel@tonic-gate /* 3031*0Sstevel@tonic-gate * If the -l/-C option is specified, set up the liblddbg.so. 3032*0Sstevel@tonic-gate */ 3033*0Sstevel@tonic-gate if (flags & FLG_LONGNAME) 3034*0Sstevel@tonic-gate dbg_flags = DBG_LONG; 3035*0Sstevel@tonic-gate if (flags & FLG_DEMANGLE) 3036*0Sstevel@tonic-gate dbg_flags |= DBG_DEMANGLE; 3037*0Sstevel@tonic-gate if (dbg_flags) 3038*0Sstevel@tonic-gate Dbg_set(dbg_flags); 3039*0Sstevel@tonic-gate 3040*0Sstevel@tonic-gate /* 3041*0Sstevel@tonic-gate * If the -w option has indicated an output file open it. It's 3042*0Sstevel@tonic-gate * arguable whether this option has much use when multiple files are 3043*0Sstevel@tonic-gate * being processed. 3044*0Sstevel@tonic-gate */ 3045*0Sstevel@tonic-gate if (wname) { 3046*0Sstevel@tonic-gate if ((wfd = open(wname, (O_RDWR | O_CREAT | O_TRUNC), 3047*0Sstevel@tonic-gate 0666)) < 0) { 3048*0Sstevel@tonic-gate int err = errno; 3049*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 3050*0Sstevel@tonic-gate wname, strerror(err)); 3051*0Sstevel@tonic-gate (void) fflush(stderr); 3052*0Sstevel@tonic-gate wfd = 0; 3053*0Sstevel@tonic-gate } 3054*0Sstevel@tonic-gate } 3055*0Sstevel@tonic-gate 3056*0Sstevel@tonic-gate /* 3057*0Sstevel@tonic-gate * Open the input file and initialize the elf interface. 3058*0Sstevel@tonic-gate */ 3059*0Sstevel@tonic-gate for (; optind < argc; optind++) { 3060*0Sstevel@tonic-gate const char *file = argv[optind]; 3061*0Sstevel@tonic-gate 3062*0Sstevel@tonic-gate if ((fd = open(argv[optind], O_RDONLY)) == -1) { 3063*0Sstevel@tonic-gate int err = errno; 3064*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), 3065*0Sstevel@tonic-gate file, strerror(err)); 3066*0Sstevel@tonic-gate (void) fflush(stderr); 3067*0Sstevel@tonic-gate continue; 3068*0Sstevel@tonic-gate } 3069*0Sstevel@tonic-gate (void) elf_version(EV_CURRENT); 3070*0Sstevel@tonic-gate if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 3071*0Sstevel@tonic-gate failure(file, MSG_ORIG(MSG_ELF_BEGIN)); 3072*0Sstevel@tonic-gate (void) close(fd); 3073*0Sstevel@tonic-gate continue; 3074*0Sstevel@tonic-gate } 3075*0Sstevel@tonic-gate 3076*0Sstevel@tonic-gate if (var > 1) 3077*0Sstevel@tonic-gate dbg_print(MSG_ORIG(MSG_FMT_NLSTRNL), file); 3078*0Sstevel@tonic-gate 3079*0Sstevel@tonic-gate switch (elf_kind(elf)) { 3080*0Sstevel@tonic-gate case ELF_K_AR: 3081*0Sstevel@tonic-gate archive(file, fd, elf, flags, Nname, wfd); 3082*0Sstevel@tonic-gate break; 3083*0Sstevel@tonic-gate case ELF_K_ELF: 3084*0Sstevel@tonic-gate regular(file, elf, flags, Nname, wfd); 3085*0Sstevel@tonic-gate break; 3086*0Sstevel@tonic-gate default: 3087*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADFILE), file); 3088*0Sstevel@tonic-gate (void) fflush(stderr); 3089*0Sstevel@tonic-gate break; 3090*0Sstevel@tonic-gate } 3091*0Sstevel@tonic-gate 3092*0Sstevel@tonic-gate (void) close(fd); 3093*0Sstevel@tonic-gate (void) elf_end(elf); 3094*0Sstevel@tonic-gate } 3095*0Sstevel@tonic-gate 3096*0Sstevel@tonic-gate if (wfd) 3097*0Sstevel@tonic-gate (void) close(wfd); 3098*0Sstevel@tonic-gate return (0); 3099*0Sstevel@tonic-gate } 3100