1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1618 rie * Common Development and Distribution License (the "License"). 6 1618 rie * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 1324 rie 22 0 stevel /* 23 8747 Ali * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 0 stevel */ 26 0 stevel 27 0 stevel /* 28 0 stevel * Dump an elf file. 29 0 stevel */ 30 9406 Ali #include <stddef.h> 31 1618 rie #include <sys/elf_386.h> 32 1618 rie #include <sys/elf_amd64.h> 33 1618 rie #include <sys/elf_SPARC.h> 34 6206 ab196087 #include <_libelf.h> 35 1618 rie #include <dwarf.h> 36 5549 rie #include <stdio.h> 37 0 stevel #include <unistd.h> 38 0 stevel #include <errno.h> 39 0 stevel #include <strings.h> 40 0 stevel #include <debug.h> 41 0 stevel #include <conv.h> 42 0 stevel #include <msg.h> 43 1618 rie #include <_elfdump.h> 44 3875 ab196087 45 3875 ab196087 46 3875 ab196087 /* 47 3875 ab196087 * VERSYM_STATE is used to maintain information about the VERSYM section 48 3875 ab196087 * in the object being analyzed. It is filled in by versions(), and used 49 3875 ab196087 * by init_symtbl_state() when displaying symbol information. 50 3875 ab196087 * 51 7682 Ali * There are three forms of symbol versioning known to us: 52 7682 Ali * 53 7682 Ali * 1) The original form, introduced with Solaris 2.5, in which 54 7682 Ali * the Versym contains indexes to Verdef records, and the 55 7682 Ali * Versym values for UNDEF symbols resolved by other objects 56 7682 Ali * are all set to 0. 57 7682 Ali * 2) The GNU form, which is backward compatible with the original 58 7682 Ali * Solaris form, but which adds several extensions: 59 7682 Ali * - The Versym also contains indexes to Verneed records, recording 60 7682 Ali * which object/version contributed the external symbol at 61 7682 Ali * link time. These indexes start with the next value following 62 7682 Ali * the final Verdef index. The index is written to the previously 63 7682 Ali * reserved vna_other field of the ELF Vernaux structure. 64 7682 Ali * - The top bit of the Versym value is no longer part of the index, 65 7682 Ali * but is used as a "hidden bit" to prevent binding to the symbol. 66 7682 Ali * - Multiple implementations of a given symbol, contained in varying 67 7682 Ali * versions are allowed, using special assembler pseudo ops, 68 7682 Ali * and encoded in the symbol name using '@' characters. 69 7682 Ali * 3) Modified Solaris form, in which we adopt the first GNU extension 70 7682 Ali * (Versym indexes to Verneed records), but not the others. 71 7682 Ali * 72 7682 Ali * elfdump can handle any of these cases. The presence of a DT_VERSYM 73 7682 Ali * dynamic element indicates a full GNU object. An object that lacks 74 7682 Ali * a DT_VERSYM entry, but which has non-zero vna_other fields in the Vernaux 75 7682 Ali * structures is a modified Solaris object. An object that has neither of 76 7682 Ali * these uses the original form. 77 7682 Ali * 78 4716 ab196087 * max_verndx contains the largest version index that can appear 79 4716 ab196087 * in a Versym entry. This can never be less than 1: In the case where 80 4716 ab196087 * there is no verdef/verneed sections, the [0] index is reserved 81 7682 Ali * for local symbols, and the [1] index for globals. If the original 82 7682 Ali * Solaris versioning rules are in effect and there is a verdef section, 83 7682 Ali * then max_verndex is the number of defined versions. If one of the 84 7682 Ali * other versioning forms is in effect, then: 85 7682 Ali * 1) If there is no verneed section, it is the same as for 86 7682 Ali * original Solaris versioning. 87 7682 Ali * 2) If there is a verneed section, the vna_other field of the 88 4716 ab196087 * Vernaux structs contain versions, and max_verndx is the 89 4716 ab196087 * largest such index. 90 4716 ab196087 * 91 7682 Ali * If gnu_full is True, the object uses the full GNU form of versioning. 92 7682 Ali * The value of the gnu_full field is based on the presence of 93 4716 ab196087 * a DT_VERSYM entry in the dynamic section: GNU ld produces these, and 94 4716 ab196087 * Solaris ld does not. 95 7682 Ali * 96 7682 Ali * The gnu_needed field is True if the Versym contains indexes to 97 7682 Ali * Verneed records, as indicated by non-zero vna_other fields in the Verneed 98 7682 Ali * section. If gnu_full is True, then gnu_needed will always be true. 99 7682 Ali * However, gnu_needed can be true without gnu_full. This is the modified 100 7682 Ali * Solaris form. 101 3875 ab196087 */ 102 3875 ab196087 typedef struct { 103 3875 ab196087 Cache *cache; /* Pointer to cache entry for VERSYM */ 104 3875 ab196087 Versym *data; /* Pointer to versym array */ 105 7682 Ali int gnu_full; /* True if object uses GNU versioning rules */ 106 7682 Ali int gnu_needed; /* True if object uses VERSYM indexes for */ 107 7682 Ali /* VERNEED (subset of gnu_full) */ 108 4716 ab196087 int max_verndx; /* largest versym index value */ 109 3875 ab196087 } VERSYM_STATE; 110 3875 ab196087 111 3875 ab196087 /* 112 3875 ab196087 * SYMTBL_STATE is used to maintain information about a single symbol 113 3875 ab196087 * table section, for use by the routines that display symbol information. 114 3875 ab196087 */ 115 3875 ab196087 typedef struct { 116 3875 ab196087 const char *file; /* Name of file */ 117 3875 ab196087 Ehdr *ehdr; /* ELF header for file */ 118 3875 ab196087 Cache *cache; /* Cache of all section headers */ 119 9273 Ali uchar_t osabi; /* OSABI to use */ 120 3875 ab196087 Word shnum; /* # of sections in cache */ 121 3875 ab196087 Cache *seccache; /* Cache of symbol table section hdr */ 122 3875 ab196087 Word secndx; /* Index of symbol table section hdr */ 123 3875 ab196087 const char *secname; /* Name of section */ 124 3875 ab196087 uint_t flags; /* Command line option flags */ 125 3875 ab196087 struct { /* Extended section index data */ 126 3875 ab196087 int checked; /* TRUE if already checked for shxndx */ 127 3875 ab196087 Word *data; /* NULL, or extended section index */ 128 3875 ab196087 /* used for symbol table entries */ 129 3875 ab196087 uint_t n; /* # items in shxndx.data */ 130 3875 ab196087 } shxndx; 131 3875 ab196087 VERSYM_STATE *versym; /* NULL, or associated VERSYM section */ 132 3875 ab196087 Sym *sym; /* Array of symbols */ 133 3875 ab196087 Word symn; /* # of symbols */ 134 3875 ab196087 } SYMTBL_STATE; 135 3875 ab196087 136 9406 Ali /* 137 9406 Ali * A variable of this type is used to track information related to 138 9406 Ali * .eh_frame and .eh_frame_hdr sections across calls to unwind_eh_frame(). 139 9406 Ali */ 140 9406 Ali typedef struct { 141 9406 Ali Word frame_cnt; /* # .eh_frame sections seen */ 142 9406 Ali Word frame_ndx; /* Section index of 1st .eh_frame */ 143 9406 Ali Word hdr_cnt; /* # .eh_frame_hdr sections seen */ 144 9406 Ali Word hdr_ndx; /* Section index of 1st .eh_frame_hdr */ 145 9406 Ali uint64_t frame_ptr; /* Value of FramePtr field from first */ 146 9406 Ali /* .eh_frame_hdr section */ 147 9406 Ali uint64_t frame_base; /* Data addr of 1st .eh_frame */ 148 9406 Ali } gnu_eh_state_t; 149 9406 Ali 150 9406 Ali /* 151 9406 Ali * C++ .exception_ranges entries make use of the signed ptrdiff_t 152 9406 Ali * type to record self-relative pointer values. We need a type 153 9406 Ali * for this that is matched to the ELFCLASS being processed. 154 9406 Ali */ 155 9406 Ali #if defined(_ELF64) 156 9406 Ali typedef int64_t PTRDIFF_T; 157 9406 Ali #else 158 9406 Ali typedef int32_t PTRDIFF_T; 159 9406 Ali #endif 160 9406 Ali 161 9406 Ali /* 162 9406 Ali * The Sun C++ ABI uses this struct to define each .exception_ranges 163 9406 Ali * entry. From the ABI: 164 9406 Ali * 165 9406 Ali * The field ret_addr is a self relative pointer to the start of the address 166 9406 Ali * range. The name was chosen because in the current implementation the range 167 9406 Ali * typically starts at the return address for a call site. 168 9406 Ali * 169 9406 Ali * The field length is the difference, in bytes, between the pc of the last 170 9406 Ali * instruction covered by the exception range and the first. When only a 171 9406 Ali * single call site is represented without optimization, this will equal zero. 172 9406 Ali * 173 9406 Ali * The field handler_addr is a relative pointer which stores the difference 174 9406 Ali * between the start of the exception range and the address of all code to 175 9406 Ali * catch exceptions and perform the cleanup for stack unwinding. 176 9406 Ali * 177 9406 Ali * The field type_block is a relative pointer which stores the difference 178 9406 Ali * between the start of the exception range and the address of an array used 179 9406 Ali * for storing a list of the types of exceptions which can be caught within 180 9406 Ali * the exception range. 181 9406 Ali */ 182 9406 Ali typedef struct { 183 9406 Ali PTRDIFF_T ret_addr; 184 9406 Ali Xword length; 185 9406 Ali PTRDIFF_T handler_addr; 186 9406 Ali PTRDIFF_T type_block; 187 9406 Ali Xword reserved; 188 9406 Ali } exception_range_entry; 189 0 stevel 190 0 stevel /* 191 0 stevel * Focal point for verifying symbol names. 192 0 stevel */ 193 0 stevel static const char * 194 1618 rie string(Cache *refsec, Word ndx, Cache *strsec, const char *file, Word name) 195 0 stevel { 196 4063 ab196087 /* 197 4063 ab196087 * If an error in this routine is due to a property of the string 198 4063 ab196087 * section, as opposed to a bad offset into the section (a property of 199 4063 ab196087 * the referencing section), then we will detect the same error on 200 4063 ab196087 * every call involving those sections. We use these static variables 201 4063 ab196087 * to retain the information needed to only issue each such error once. 202 4063 ab196087 */ 203 4063 ab196087 static Cache *last_refsec; /* Last referencing section seen */ 204 4063 ab196087 static int strsec_err; /* True if error issued */ 205 4063 ab196087 206 3492 ab196087 const char *strs; 207 3492 ab196087 Word strn; 208 3466 rie 209 3466 rie if (strsec->c_data == NULL) 210 3466 rie return (NULL); 211 0 stevel 212 3492 ab196087 strs = (char *)strsec->c_data->d_buf; 213 3492 ab196087 strn = strsec->c_data->d_size; 214 0 stevel 215 0 stevel /* 216 4063 ab196087 * We only print a diagnostic regarding a bad string table once per 217 4063 ab196087 * input section being processed. If the refsec has changed, reset 218 4063 ab196087 * our retained error state. 219 0 stevel */ 220 4063 ab196087 if (last_refsec != refsec) { 221 4063 ab196087 last_refsec = refsec; 222 4063 ab196087 strsec_err = 0; 223 4063 ab196087 } 224 4063 ab196087 225 4063 ab196087 /* Verify that strsec really is a string table */ 226 4063 ab196087 if (strsec->c_shdr->sh_type != SHT_STRTAB) { 227 4063 ab196087 if (!strsec_err) { 228 4063 ab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_NOTSTRTAB), 229 4063 ab196087 file, strsec->c_ndx, refsec->c_ndx); 230 4063 ab196087 strsec_err = 1; 231 4063 ab196087 } 232 4063 ab196087 return (MSG_INTL(MSG_STR_UNKNOWN)); 233 0 stevel } 234 0 stevel 235 0 stevel /* 236 0 stevel * Is the string table offset within range of the available strings? 237 0 stevel */ 238 0 stevel if (name >= strn) { 239 0 stevel /* 240 0 stevel * Do we have a empty string table? 241 0 stevel */ 242 9085 Ali if (strs == NULL) { 243 4063 ab196087 if (!strsec_err) { 244 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 245 0 stevel file, strsec->c_name); 246 4063 ab196087 strsec_err = 1; 247 0 stevel } 248 0 stevel } else { 249 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSTOFF), 250 1618 rie file, refsec->c_name, EC_WORD(ndx), strsec->c_name, 251 1618 rie EC_WORD(name), EC_WORD(strn - 1)); 252 0 stevel } 253 0 stevel 254 0 stevel /* 255 0 stevel * Return the empty string so that the calling function can 256 0 stevel * continue it's output diagnostics. 257 0 stevel */ 258 0 stevel return (MSG_INTL(MSG_STR_UNKNOWN)); 259 0 stevel } 260 0 stevel return (strs + name); 261 0 stevel } 262 0 stevel 263 0 stevel /* 264 1618 rie * Relocations can reference section symbols and standard symbols. If the 265 1618 rie * former, establish the section name. 266 1618 rie */ 267 1618 rie static const char * 268 1618 rie relsymname(Cache *cache, Cache *csec, Cache *strsec, Word symndx, Word symnum, 269 7463 Rod Word relndx, Sym *syms, char *secstr, size_t secsz, const char *file) 270 7463 Rod { 271 7463 Rod Sym *sym; 272 7463 Rod const char *name; 273 1618 rie 274 1618 rie if (symndx >= symnum) { 275 1618 rie (void) fprintf(stderr, MSG_INTL(MSG_ERR_RELBADSYMNDX), 276 1618 rie file, EC_WORD(symndx), EC_WORD(relndx)); 277 1618 rie return (MSG_INTL(MSG_STR_UNKNOWN)); 278 1618 rie } 279 1618 rie 280 1618 rie sym = (Sym *)(syms + symndx); 281 7463 Rod name = string(csec, symndx, strsec, file, sym->st_name); 282 1618 rie 283 1618 rie /* 284 1618 rie * If the symbol represents a section offset construct an appropriate 285 7463 Rod * string. Note, although section symbol table entries typically have 286 7463 Rod * a NULL name pointer, entries do exist that point into the string 287 7463 Rod * table to their own NULL strings. 288 7463 Rod */ 289 7463 Rod if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) && 290 7463 Rod ((sym->st_name == 0) || (*name == '\0'))) { 291 7463 Rod (void) snprintf(secstr, secsz, MSG_INTL(MSG_STR_SECTION), 292 7463 Rod cache[sym->st_shndx].c_name); 293 1618 rie return ((const char *)secstr); 294 1618 rie } 295 1618 rie 296 7463 Rod return (name); 297 1618 rie } 298 1618 rie 299 1618 rie /* 300 1618 rie * Focal point for establishing a string table section. Data such as the 301 1618 rie * dynamic information simply points to a string table. Data such as 302 1618 rie * relocations, reference a symbol table, which in turn is associated with a 303 1618 rie * string table. 304 0 stevel */ 305 0 stevel static int 306 1618 rie stringtbl(Cache *cache, int symtab, Word ndx, Word shnum, const char *file, 307 1618 rie Word *symnum, Cache **symsec, Cache **strsec) 308 1618 rie { 309 1618 rie Shdr *shdr = cache[ndx].c_shdr; 310 1618 rie 311 1618 rie if (symtab) { 312 1618 rie /* 313 1618 rie * Validate the symbol table section. 314 1618 rie */ 315 1618 rie if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 316 1618 rie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 317 1618 rie file, cache[ndx].c_name, EC_WORD(shdr->sh_link)); 318 1618 rie return (0); 319 1618 rie } 320 3466 rie if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 321 3466 rie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 322 3466 rie file, cache[ndx].c_name); 323 3466 rie return (0); 324 3466 rie } 325 1618 rie 326 1618 rie /* 327 1618 rie * Obtain, and verify the symbol table data. 328 1618 rie */ 329 3466 rie if ((cache[ndx].c_data == NULL) || 330 3466 rie (cache[ndx].c_data->d_buf == NULL)) { 331 1618 rie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 332 1618 rie file, cache[ndx].c_name); 333 1618 rie return (0); 334 1618 rie } 335 1618 rie 336 1618 rie /* 337 1618 rie * Establish the string table index. 338 1618 rie */ 339 1618 rie ndx = shdr->sh_link; 340 1618 rie shdr = cache[ndx].c_shdr; 341 1618 rie 342 1618 rie /* 343 1618 rie * Return symbol table information. 344 1618 rie */ 345 1618 rie if (symnum) 346 1618 rie *symnum = (shdr->sh_size / shdr->sh_entsize); 347 1618 rie if (symsec) 348 1618 rie *symsec = &cache[ndx]; 349 1618 rie } 350 1618 rie 351 1618 rie /* 352 1618 rie * Validate the associated string table section. 353 1618 rie */ 354 1618 rie if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 355 1618 rie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 356 1618 rie file, cache[ndx].c_name, EC_WORD(shdr->sh_link)); 357 1618 rie return (0); 358 1618 rie } 359 1618 rie 360 1618 rie if (strsec) 361 1618 rie *strsec = &cache[shdr->sh_link]; 362 1618 rie 363 1618 rie return (1); 364 1618 rie } 365 1618 rie 366 1618 rie /* 367 1618 rie * Lookup a symbol and set Sym accordingly. 368 1618 rie */ 369 1618 rie static int 370 1618 rie symlookup(const char *name, Cache *cache, Word shnum, Sym **sym, 371 0 stevel Cache *symtab, const char *file) 372 0 stevel { 373 1618 rie Shdr *shdr; 374 1618 rie Word symn, cnt; 375 1618 rie Sym *syms; 376 0 stevel 377 0 stevel if (symtab == 0) 378 0 stevel return (0); 379 0 stevel 380 1618 rie shdr = symtab->c_shdr; 381 1618 rie 382 0 stevel /* 383 0 stevel * Determine the symbol data and number. 384 0 stevel */ 385 0 stevel if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 386 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 387 0 stevel file, symtab->c_name); 388 0 stevel return (0); 389 0 stevel } 390 3466 rie if (symtab->c_data == NULL) 391 3466 rie return (0); 392 3466 rie 393 0 stevel /* LINTED */ 394 1618 rie symn = (Word)(shdr->sh_size / shdr->sh_entsize); 395 1618 rie syms = (Sym *)symtab->c_data->d_buf; 396 0 stevel 397 0 stevel /* 398 0 stevel * Get the associated string table section. 399 0 stevel */ 400 0 stevel if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 401 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 402 1618 rie file, symtab->c_name, EC_WORD(shdr->sh_link)); 403 0 stevel return (0); 404 0 stevel } 405 0 stevel 406 0 stevel /* 407 0 stevel * Loop through the symbol table to find a match. 408 0 stevel */ 409 1618 rie for (cnt = 0; cnt < symn; syms++, cnt++) { 410 1618 rie const char *symname; 411 0 stevel 412 1618 rie symname = string(symtab, cnt, &cache[shdr->sh_link], file, 413 1618 rie syms->st_name); 414 0 stevel 415 1618 rie if (symname && (strcmp(name, symname) == 0)) { 416 1618 rie *sym = syms; 417 0 stevel return (1); 418 0 stevel } 419 0 stevel } 420 0 stevel return (0); 421 0 stevel } 422 0 stevel 423 0 stevel /* 424 0 stevel * Print section headers. 425 0 stevel */ 426 0 stevel static void 427 9273 Ali sections(const char *file, Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi) 428 0 stevel { 429 1618 rie size_t seccnt; 430 0 stevel 431 1618 rie for (seccnt = 1; seccnt < shnum; seccnt++) { 432 1618 rie Cache *_cache = &cache[seccnt]; 433 1618 rie Shdr *shdr = _cache->c_shdr; 434 1618 rie const char *secname = _cache->c_name; 435 0 stevel 436 0 stevel /* 437 0 stevel * Although numerous section header entries can be zero, it's 438 3862 rie * usually a sign of trouble if the type is zero. 439 0 stevel */ 440 0 stevel if (shdr->sh_type == 0) { 441 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE), 442 1618 rie file, secname, EC_WORD(shdr->sh_type)); 443 0 stevel } 444 0 stevel 445 5411 ab196087 if (!match(MATCH_F_ALL, secname, seccnt, shdr->sh_type)) 446 3862 rie continue; 447 1324 rie 448 1324 rie /* 449 1324 rie * Identify any sections that are suspicious. A .got section 450 1324 rie * shouldn't exist in a relocatable object. 451 1324 rie */ 452 1324 rie if (ehdr->e_type == ET_REL) { 453 1618 rie if (strncmp(secname, MSG_ORIG(MSG_ELF_GOT), 454 1324 rie MSG_ELF_GOT_SIZE) == 0) { 455 1324 rie (void) fprintf(stderr, 456 1618 rie MSG_INTL(MSG_GOT_UNEXPECTED), file, 457 1618 rie secname); 458 1324 rie } 459 0 stevel } 460 0 stevel 461 1618 rie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 462 1618 rie dbg_print(0, MSG_INTL(MSG_ELF_SHDR), EC_WORD(seccnt), secname); 463 9273 Ali Elf_shdr(0, osabi, ehdr->e_machine, shdr); 464 0 stevel } 465 0 stevel } 466 0 stevel 467 1618 rie /* 468 1618 rie * Obtain a specified Phdr entry. 469 1618 rie */ 470 1618 rie static Phdr * 471 9085 Ali getphdr(Word phnum, Word *type_arr, Word type_cnt, const char *file, Elf *elf) 472 9085 Ali { 473 9085 Ali Word cnt, tcnt; 474 1618 rie Phdr *phdr; 475 1618 rie 476 1618 rie if ((phdr = elf_getphdr(elf)) == NULL) { 477 1618 rie failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 478 9085 Ali return (NULL); 479 1618 rie } 480 1618 rie 481 1618 rie for (cnt = 0; cnt < phnum; phdr++, cnt++) { 482 9085 Ali for (tcnt = 0; tcnt < type_cnt; tcnt++) { 483 9085 Ali if (phdr->p_type == type_arr[tcnt]) 484 9085 Ali return (phdr); 485 9085 Ali } 486 9085 Ali } 487 9085 Ali return (NULL); 488 1618 rie } 489 1618 rie 490 9406 Ali /* 491 9406 Ali * Display the contents of GNU/amd64 .eh_frame and .eh_frame_hdr 492 9406 Ali * sections. 493 9406 Ali * 494 9406 Ali * entry: 495 9406 Ali * cache - Cache of all section headers 496 9406 Ali * shndx - Index of .eh_frame or .eh_frame_hdr section to be displayed 497 9406 Ali * uphdr - NULL, or unwind program header associated with 498 9406 Ali * the .eh_frame_hdr section. 499 9406 Ali * ehdr - ELF header for file 500 9406 Ali * eh_state - Data used across calls to this routine. The 501 9406 Ali * caller should zero it before the first call, and 502 9406 Ali * pass it on every call. 503 9406 Ali * osabi - OSABI to use in displaying information 504 9406 Ali * file - Name of file 505 9406 Ali * flags - Command line option flags 506 9406 Ali */ 507 9406 Ali static void 508 9406 Ali unwind_eh_frame(Cache *cache, Word shndx, Phdr *uphdr, Ehdr *ehdr, 509 9406 Ali gnu_eh_state_t *eh_state, uchar_t osabi, const char *file, uint_t flags) 510 1618 rie { 511 9085 Ali #if defined(_ELF64) 512 9085 Ali #define MSG_UNW_BINSRTAB2 MSG_UNW_BINSRTAB2_64 513 9085 Ali #define MSG_UNW_BINSRTABENT MSG_UNW_BINSRTABENT_64 514 9085 Ali #else 515 9085 Ali #define MSG_UNW_BINSRTAB2 MSG_UNW_BINSRTAB2_32 516 9085 Ali #define MSG_UNW_BINSRTABENT MSG_UNW_BINSRTABENT_32 517 9085 Ali #endif 518 9085 Ali 519 9406 Ali Cache *_cache = &cache[shndx]; 520 9406 Ali Shdr *shdr = _cache->c_shdr; 521 9406 Ali uchar_t *data = (uchar_t *)(_cache->c_data->d_buf); 522 9406 Ali size_t datasize = _cache->c_data->d_size; 523 9406 Ali Conv_dwarf_ehe_buf_t dwarf_ehe_buf; 524 9406 Ali uint64_t ndx, frame_ptr, fde_cnt, tabndx; 525 9406 Ali uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc; 526 9406 Ali uint64_t initloc, initloc0; 527 9406 Ali 528 9406 Ali 529 9406 Ali /* 530 9406 Ali * Is this a .eh_frame_hdr? 531 9406 Ali */ 532 9406 Ali if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) || 533 9406 Ali (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR), 534 9406 Ali MSG_SCN_FRMHDR_SIZE) == 0)) { 535 9406 Ali /* 536 9406 Ali * There can only be a single .eh_frame_hdr. 537 9406 Ali * Flag duplicates. 538 9406 Ali */ 539 9406 Ali if (++eh_state->hdr_cnt > 1) 540 9406 Ali (void) fprintf(stderr, MSG_INTL(MSG_ERR_MULTEHFRMHDR), 541 9406 Ali file, EC_WORD(shndx), _cache->c_name); 542 9406 Ali 543 9406 Ali dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR)); 544 9406 Ali ndx = 0; 545 9406 Ali 546 9406 Ali vers = data[ndx++]; 547 9406 Ali frame_ptr_enc = data[ndx++]; 548 9406 Ali fde_cnt_enc = data[ndx++]; 549 9406 Ali table_enc = data[ndx++]; 550 9406 Ali 551 9406 Ali dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers); 552 9406 Ali 553 9406 Ali frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc, 554 9406 Ali ehdr->e_ident, shdr->sh_addr, ndx); 555 9406 Ali if (eh_state->hdr_cnt == 1) { 556 9406 Ali eh_state->hdr_ndx = shndx; 557 9406 Ali eh_state->frame_ptr = frame_ptr; 558 9406 Ali } 559 9406 Ali 560 9406 Ali dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC), 561 9406 Ali conv_dwarf_ehe(frame_ptr_enc, &dwarf_ehe_buf), 562 9406 Ali EC_XWORD(frame_ptr)); 563 9406 Ali 564 9406 Ali fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc, 565 9406 Ali ehdr->e_ident, shdr->sh_addr, ndx); 566 9406 Ali 567 9406 Ali dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC), 568 9406 Ali conv_dwarf_ehe(fde_cnt_enc, &dwarf_ehe_buf), 569 9406 Ali EC_XWORD(fde_cnt)); 570 9406 Ali dbg_print(0, MSG_ORIG(MSG_UNW_TABENC), 571 9406 Ali conv_dwarf_ehe(table_enc, &dwarf_ehe_buf)); 572 9406 Ali dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1)); 573 9406 Ali dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2)); 574 9406 Ali 575 9406 Ali for (tabndx = 0; tabndx < fde_cnt; tabndx++) { 576 9406 Ali initloc = dwarf_ehe_extract(data, &ndx, table_enc, 577 9406 Ali ehdr->e_ident, shdr->sh_addr, ndx); 578 9406 Ali /*LINTED:E_VAR_USED_BEFORE_SET*/ 579 9406 Ali if ((tabndx != 0) && (initloc0 > initloc)) 580 9615 Ali (void) fprintf(stderr, 581 9615 Ali MSG_INTL(MSG_ERR_BADSORT), file, 582 9615 Ali _cache->c_name, EC_WORD(tabndx)); 583 9406 Ali dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT), 584 9406 Ali EC_XWORD(initloc), 585 9406 Ali EC_XWORD(dwarf_ehe_extract(data, &ndx, 586 9406 Ali table_enc, ehdr->e_ident, shdr->sh_addr, 587 9406 Ali ndx))); 588 9406 Ali initloc0 = initloc; 589 9406 Ali } 590 9406 Ali } else { /* Display the .eh_frame section */ 591 9406 Ali eh_state->frame_cnt++; 592 9406 Ali if (eh_state->frame_cnt == 1) { 593 9406 Ali eh_state->frame_ndx = shndx; 594 9406 Ali eh_state->frame_base = shdr->sh_addr; 595 9406 Ali } else if ((eh_state->frame_cnt > 1) && 596 9406 Ali (ehdr->e_type != ET_REL)) { 597 9406 Ali Conv_inv_buf_t inv_buf; 598 9406 Ali 599 9406 Ali (void) fprintf(stderr, MSG_INTL(MSG_WARN_MULTEHFRM), 600 9406 Ali file, EC_WORD(shndx), _cache->c_name, 601 9406 Ali conv_ehdr_type(osabi, ehdr->e_type, 0, &inv_buf)); 602 9406 Ali } 603 9406 Ali dump_eh_frame(data, datasize, shdr->sh_addr, 604 9406 Ali ehdr->e_machine, ehdr->e_ident); 605 9406 Ali } 606 9406 Ali 607 9406 Ali /* 608 9406 Ali * If we've seen the .eh_frame_hdr and the first .eh_frame section, 609 9406 Ali * compare the header frame_ptr to the address of the actual frame 610 9406 Ali * section to ensure the link-editor got this right. Note, this 611 9406 Ali * diagnostic is only produced when unwind information is explicitly 612 9406 Ali * asked for, as shared objects built with an older ld(1) may reveal 613 9406 Ali * this inconsistency. Although an inconsistency, it doesn't seem to 614 9406 Ali * have any adverse effect on existing tools. 615 9406 Ali */ 616 9406 Ali if (((flags & FLG_MASK_SHOW) != FLG_MASK_SHOW) && 617 9406 Ali (eh_state->hdr_cnt > 0) && (eh_state->frame_cnt > 0) && 618 9406 Ali (eh_state->frame_ptr != eh_state->frame_base)) 619 9406 Ali (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADEHFRMPTR), 620 9406 Ali file, EC_WORD(eh_state->hdr_ndx), 621 9406 Ali cache[eh_state->hdr_ndx].c_name, 622 9406 Ali EC_XWORD(eh_state->frame_ptr), 623 9406 Ali EC_WORD(eh_state->frame_ndx), 624 9406 Ali cache[eh_state->frame_ndx].c_name, 625 9406 Ali EC_XWORD(eh_state->frame_base)); 626 9406 Ali #undef MSG_UNW_BINSRTAB2 627 9406 Ali #undef MSG_UNW_BINSRTABENT 628 9406 Ali } 629 9406 Ali 630 9406 Ali /* 631 9406 Ali * Convert a self relative pointer into an address. A self relative 632 9406 Ali * pointer adds the address where the pointer resides to the offset 633 9406 Ali * contained in the pointer. The benefit is that the value of the 634 9406 Ali * pointer does not require relocation. 635 9406 Ali * 636 9406 Ali * entry: 637 9406 Ali * base_addr - Address of the pointer. 638 9406 Ali * delta - Offset relative to base_addr giving desired address 639 9406 Ali * 640 9406 Ali * exit: 641 9406 Ali * The computed address is returned. 642 9406 Ali * 643 9406 Ali * note: 644 9406 Ali * base_addr is an unsigned value, while ret_addr is signed. This routine 645 9406 Ali * used explicit testing and casting to explicitly control type 646 9406 Ali * conversion, and ensure that we handle the maximum possible range. 647 9406 Ali */ 648 9406 Ali static Addr 649 9406 Ali srelptr(Addr base_addr, PTRDIFF_T delta) 650 9406 Ali { 651 9406 Ali if (delta < 0) 652 9406 Ali return (base_addr - (Addr) (-delta)); 653 9406 Ali 654 9406 Ali return (base_addr + (Addr) delta); 655 9406 Ali } 656 9406 Ali 657 9406 Ali /* 658 9406 Ali * Byte swap a PTRDIFF_T value. 659 9406 Ali */ 660 9406 Ali static PTRDIFF_T 661 9406 Ali swap_ptrdiff(PTRDIFF_T value) 662 9406 Ali { 663 9406 Ali PTRDIFF_T r; 664 9406 Ali uchar_t *dst = (uchar_t *)&r; 665 9406 Ali uchar_t *src = (uchar_t *)&value; 666 9406 Ali 667 9406 Ali UL_ASSIGN_BSWAP_XWORD(dst, src); 668 9406 Ali return (r); 669 9406 Ali } 670 9406 Ali 671 9406 Ali /* 672 9406 Ali * Display exception_range_entry items from the .exception_ranges section 673 9406 Ali * of a Sun C++ object. 674 9406 Ali */ 675 9406 Ali static void 676 9406 Ali unwind_exception_ranges(Cache *_cache, const char *file, int do_swap) 677 9406 Ali { 678 9406 Ali /* 679 9406 Ali * Translate a PTRDIFF_T self-relative address field of 680 9406 Ali * an exception_range_entry struct into an address. 681 9406 Ali * 682 9406 Ali * entry: 683 9406 Ali * exc_addr - Address of base of exception_range_entry struct 684 9406 Ali * cur_ent - Pointer to data in the struct to be translated 685 9406 Ali * 686 9406 Ali * _f - Field of struct to be translated 687 9406 Ali */ 688 9406 Ali #define SRELPTR(_f) \ 689 9406 Ali srelptr(exc_addr + offsetof(exception_range_entry, _f), cur_ent->_f) 690 9406 Ali 691 9406 Ali #if defined(_ELF64) 692 9406 Ali #define MSG_EXR_TITLE MSG_EXR_TITLE_64 693 9406 Ali #define MSG_EXR_ENTRY MSG_EXR_ENTRY_64 694 9406 Ali #else 695 9406 Ali #define MSG_EXR_TITLE MSG_EXR_TITLE_32 696 9406 Ali #define MSG_EXR_ENTRY MSG_EXR_ENTRY_32 697 9406 Ali #endif 698 9406 Ali 699 9406 Ali exception_range_entry scratch, *ent, *cur_ent = &scratch; 700 9406 Ali char index[MAXNDXSIZE]; 701 9406 Ali Word i, nelts; 702 9406 Ali Addr addr, addr0, offset = 0; 703 9406 Ali Addr exc_addr = _cache->c_shdr->sh_addr; 704 9406 Ali 705 9406 Ali dbg_print(0, MSG_INTL(MSG_EXR_TITLE)); 706 9406 Ali ent = (exception_range_entry *)(_cache->c_data->d_buf); 707 9406 Ali nelts = _cache->c_data->d_size / sizeof (exception_range_entry); 708 9406 Ali 709 9406 Ali for (i = 0; i < nelts; i++, ent++) { 710 9406 Ali if (do_swap) { 711 9406 Ali /* 712 9406 Ali * Copy byte swapped values into the scratch buffer. 713 9406 Ali * The reserved field is not used, so we skip it. 714 9406 Ali */ 715 9406 Ali scratch.ret_addr = swap_ptrdiff(ent->ret_addr); 716 9406 Ali scratch.length = BSWAP_XWORD(ent->length); 717 9406 Ali scratch.handler_addr = swap_ptrdiff(ent->handler_addr); 718 9406 Ali scratch.type_block = swap_ptrdiff(ent->type_block); 719 9406 Ali } else { 720 9406 Ali cur_ent = ent; 721 9406 Ali } 722 9406 Ali 723 9406 Ali /* 724 9406 Ali * The table is required to be sorted by the address 725 9406 Ali * derived from ret_addr, to allow binary searching. Ensure 726 9406 Ali * that addresses grow monotonically. 727 9406 Ali */ 728 9406 Ali addr = SRELPTR(ret_addr); 729 9406 Ali /*LINTED:E_VAR_USED_BEFORE_SET*/ 730 9406 Ali if ((i != 0) && (addr0 > addr)) 731 9615 Ali (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORT), 732 9406 Ali file, _cache->c_name, EC_WORD(i)); 733 9406 Ali 734 9406 Ali (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX), 735 9406 Ali EC_XWORD(i)); 736 9406 Ali dbg_print(0, MSG_INTL(MSG_EXR_ENTRY), index, EC_ADDR(offset), 737 9406 Ali EC_ADDR(addr), EC_ADDR(cur_ent->length), 738 9406 Ali EC_ADDR(SRELPTR(handler_addr)), 739 9406 Ali EC_ADDR(SRELPTR(type_block))); 740 9406 Ali 741 9406 Ali addr0 = addr; 742 9406 Ali exc_addr += sizeof (exception_range_entry); 743 9406 Ali offset += sizeof (exception_range_entry); 744 9406 Ali } 745 9406 Ali 746 9406 Ali #undef SRELPTR 747 9406 Ali #undef MSG_EXR_TITLE 748 9406 Ali #undef MSG_EXR_ENTRY 749 9406 Ali } 750 9406 Ali 751 9406 Ali /* 752 9406 Ali * Display information from unwind/exception sections: 753 9406 Ali * 754 9406 Ali * - GNU/amd64 .eh_frame and .eh_frame_hdr 755 9406 Ali * - Sun C++ .exception_ranges 756 9406 Ali * 757 9406 Ali */ 758 9406 Ali static void 759 9406 Ali unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, uchar_t osabi, 760 9406 Ali const char *file, Elf *elf, uint_t flags) 761 9406 Ali { 762 9085 Ali static Word phdr_types[] = { PT_SUNW_UNWIND, PT_SUNW_EH_FRAME }; 763 9085 Ali 764 9085 Ali Word cnt; 765 9085 Ali Phdr *uphdr = NULL; 766 9406 Ali gnu_eh_state_t eh_state; 767 9085 Ali 768 9085 Ali /* 769 9085 Ali * Historical background: .eh_frame and .eh_frame_hdr sections 770 9085 Ali * come from the GNU compilers (particularly C++), and are used 771 9085 Ali * under all architectures. Their format is based on DWARF. When 772 9085 Ali * the amd64 ABI was defined, these sections were adopted wholesale 773 9085 Ali * from the existing practice. 774 9085 Ali * 775 9085 Ali * When amd64 support was added to Solaris, support for these 776 9085 Ali * sections was added, using the SHT_AMD64_UNWIND section type 777 9085 Ali * to identify them. At first, we ignored them in objects for 778 9085 Ali * non-amd64 targets, but later broadened our support to include 779 9085 Ali * other architectures in order to better support gcc-generated 780 9085 Ali * objects. 781 9085 Ali * 782 9406 Ali * .exception_ranges implement the same basic concepts, but 783 9406 Ali * were invented at Sun for the Sun C++ compiler. 784 9406 Ali * 785 9085 Ali * We match these sections by name, rather than section type, 786 9085 Ali * because they can come in as either SHT_AMD64_UNWIND, or as 787 9406 Ali * SHT_PROGBITS, and because the type isn't enough to determine 788 9406 Ali * how they should be interprteted. 789 9406 Ali */ 790 9406 Ali 791 9406 Ali /* Find the program header for .eh_frame_hdr if present */ 792 1618 rie if (phnum) 793 9085 Ali uphdr = getphdr(phnum, phdr_types, 794 9085 Ali sizeof (phdr_types) / sizeof (*phdr_types), file, elf); 795 0 stevel 796 9406 Ali /* 797 9406 Ali * eh_state is used to retain data used by unwind_eh_frame() 798 9406 Ali * accross calls. 799 9406 Ali */ 800 9406 Ali bzero(&eh_state, sizeof (eh_state)); 801 9406 Ali 802 9406 Ali for (cnt = 1; cnt < shnum; cnt++) { 803 9406 Ali Cache *_cache = &cache[cnt]; 804 9406 Ali Shdr *shdr = _cache->c_shdr; 805 9406 Ali int is_exrange; 806 9406 Ali 807 9406 Ali /* 808 9406 Ali * Skip sections of the wrong type. On amd64, they 809 9406 Ali * can be SHT_AMD64_UNWIND. On all platforms, they 810 9406 Ali * can be SHT_PROGBITS (including amd64, if using 811 9406 Ali * the GNU compilers). 812 9273 Ali * 813 9273 Ali * Skip anything other than these two types. The name 814 9273 Ali * test below will thin out the SHT_PROGBITS that don't apply. 815 9273 Ali */ 816 9273 Ali if ((shdr->sh_type != SHT_PROGBITS) && 817 9273 Ali (shdr->sh_type != SHT_AMD64_UNWIND)) 818 9273 Ali continue; 819 9085 Ali 820 9085 Ali /* 821 9406 Ali * Only sections with certain well known names are of interest. 822 9406 Ali * These are: 823 9406 Ali * 824 9406 Ali * .eh_frame - amd64/GNU-compiler unwind sections 825 9406 Ali * .eh_frame_hdr - Sorted table referencing .eh_frame 826 9406 Ali * .exception_ranges - Sun C++ unwind sections 827 9406 Ali * 828 9406 Ali * We do a prefix comparison, allowing for naming conventions 829 9406 Ali * like .eh_frame.foo, hence the use of strncmp() rather than 830 9406 Ali * strcmp(). This means that we only really need to test for 831 9406 Ali * .eh_frame, as it's a prefix of .eh_frame_hdr. 832 9406 Ali */ 833 9406 Ali is_exrange = strncmp(_cache->c_name, 834 9406 Ali MSG_ORIG(MSG_SCN_EXRANGE), MSG_SCN_EXRANGE_SIZE) == 0; 835 9406 Ali if ((strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM), 836 9406 Ali MSG_SCN_FRM_SIZE) != 0) && !is_exrange) 837 0 stevel continue; 838 4168 ab196087 839 5411 ab196087 if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type)) 840 3466 rie continue; 841 3466 rie 842 3466 rie if (_cache->c_data == NULL) 843 0 stevel continue; 844 0 stevel 845 1618 rie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 846 1618 rie dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name); 847 0 stevel 848 9406 Ali if (is_exrange) 849 9406 Ali unwind_exception_ranges(_cache, file, 850 9406 Ali _elf_sys_encoding() != ehdr->e_ident[EI_DATA]); 851 9406 Ali else 852 9406 Ali unwind_eh_frame(cache, cnt, uphdr, ehdr, &eh_state, 853 9406 Ali osabi, file, flags); 854 9406 Ali } 855 0 stevel } 856 0 stevel 857 0 stevel /* 858 0 stevel * Print the hardware/software capabilities. For executables and shared objects 859 0 stevel * this should be accompanied with a program header. 860 0 stevel */ 861 0 stevel static void 862 1618 rie cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, 863 1618 rie Elf *elf) 864 0 stevel { 865 1618 rie Word cnt; 866 7833 Rod Shdr *cshdr = NULL; 867 3466 rie Cache *ccache; 868 1618 rie Off cphdr_off = 0; 869 1618 rie Xword cphdr_sz; 870 0 stevel 871 0 stevel /* 872 0 stevel * Determine if a hardware/software capabilities header exists. 873 0 stevel */ 874 1618 rie if (phnum) { 875 1618 rie Phdr *phdr; 876 0 stevel 877 1618 rie if ((phdr = elf_getphdr(elf)) == NULL) { 878 0 stevel failure(file, MSG_ORIG(MSG_ELF_GETPHDR)); 879 0 stevel return; 880 0 stevel } 881 0 stevel 882 1618 rie for (cnt = 0; cnt < phnum; phdr++, cnt++) { 883 1618 rie if (phdr->p_type == PT_SUNWCAP) { 884 1618 rie cphdr_off = phdr->p_offset; 885 1618 rie cphdr_sz = phdr->p_filesz; 886 1618 rie break; 887 1618 rie } 888 0 stevel } 889 0 stevel } 890 0 stevel 891 0 stevel /* 892 0 stevel * Determine if a hardware/software capabilities section exists. 893 0 stevel */ 894 0 stevel for (cnt = 1; cnt < shnum; cnt++) { 895 1618 rie Cache *_cache = &cache[cnt]; 896 1618 rie Shdr *shdr = _cache->c_shdr; 897 0 stevel 898 0 stevel if (shdr->sh_type != SHT_SUNW_cap) 899 0 stevel continue; 900 0 stevel 901 0 stevel if (cphdr_off && ((cphdr_off < shdr->sh_offset) || 902 0 stevel (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size))) 903 0 stevel continue; 904 0 stevel 905 3466 rie if (_cache->c_data == NULL) 906 3466 rie continue; 907 3466 rie 908 0 stevel ccache = _cache; 909 0 stevel cshdr = shdr; 910 0 stevel break; 911 0 stevel } 912 0 stevel 913 7833 Rod if ((cshdr == NULL) && (cphdr_off == 0)) 914 0 stevel return; 915 0 stevel 916 0 stevel /* 917 0 stevel * Print the hardware/software capabilities section. 918 0 stevel */ 919 0 stevel if (cshdr) { 920 1618 rie Word ndx, capn; 921 3492 ab196087 Cap *cap = (Cap *)ccache->c_data->d_buf; 922 4665 ab196087 923 4665 ab196087 if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) { 924 4665 ab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 925 4665 ab196087 file, ccache->c_name); 926 4665 ab196087 return; 927 4665 ab196087 } 928 0 stevel 929 1618 rie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 930 1618 rie dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name); 931 0 stevel 932 1618 rie Elf_cap_title(0); 933 0 stevel 934 1618 rie capn = (Word)(cshdr->sh_size / cshdr->sh_entsize); 935 0 stevel 936 1618 rie for (ndx = 0; ndx < capn; cap++, ndx++) { 937 7833 Rod if (cap->c_tag == CA_SUNW_NULL) 938 7833 Rod continue; 939 7833 Rod 940 7833 Rod Elf_cap_entry(0, cap, ndx, ehdr->e_machine); 941 7833 Rod 942 7833 Rod /* 943 7833 Rod * An SF1_SUNW_ADDR32 software capability in a 32-bit 944 7833 Rod * object is suspicious as it has no effect. 945 7833 Rod */ 946 7833 Rod if ((cap->c_tag == CA_SUNW_SF_1) && 947 7833 Rod (ehdr->e_ident[EI_CLASS] == ELFCLASS32) && 948 7833 Rod (cap->c_un.c_val & SF1_SUNW_ADDR32)) { 949 7833 Rod (void) fprintf(stderr, 950 7833 Rod MSG_INTL(MSG_WARN_INADDR32SF1), 951 7833 Rod file, ccache->c_name); 952 7833 Rod } 953 0 stevel } 954 0 stevel } else 955 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file); 956 0 stevel 957 0 stevel /* 958 0 stevel * If this object is an executable or shared object, then the 959 0 stevel * hardware/software capabilities section should have an accompanying 960 0 stevel * program header. 961 0 stevel */ 962 0 stevel if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) { 963 0 stevel if (cphdr_off == 0) 964 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2), 965 0 stevel file, ccache->c_name); 966 0 stevel else if ((cphdr_off != cshdr->sh_offset) || 967 0 stevel (cphdr_sz != cshdr->sh_size)) 968 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3), 969 0 stevel file, ccache->c_name); 970 0 stevel } 971 0 stevel } 972 0 stevel 973 0 stevel /* 974 0 stevel * Print the interpretor. 975 0 stevel */ 976 0 stevel static void 977 1618 rie interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf) 978 0 stevel { 979 9085 Ali static Word phdr_types[] = { PT_INTERP }; 980 9085 Ali 981 9085 Ali 982 1618 rie Word cnt; 983 9085 Ali Shdr *ishdr = NULL; 984 1618 rie Cache *icache; 985 1618 rie Off iphdr_off = 0; 986 1618 rie Xword iphdr_fsz; 987 0 stevel 988 0 stevel /* 989 0 stevel * Determine if an interp header exists. 990 0 stevel */ 991 1618 rie if (phnum) { 992 1618 rie Phdr *phdr; 993 0 stevel 994 9085 Ali phdr = getphdr(phnum, phdr_types, 995 9085 Ali sizeof (phdr_types) / sizeof (*phdr_types), file, elf); 996 9085 Ali if (phdr != NULL) { 997 1618 rie iphdr_off = phdr->p_offset; 998 1618 rie iphdr_fsz = phdr->p_filesz; 999 0 stevel } 1000 0 stevel } 1001 0 stevel 1002 0 stevel if (iphdr_off == 0) 1003 0 stevel return; 1004 0 stevel 1005 0 stevel /* 1006 0 stevel * Determine if an interp section exists. 1007 0 stevel */ 1008 0 stevel for (cnt = 1; cnt < shnum; cnt++) { 1009 1618 rie Cache *_cache = &cache[cnt]; 1010 1618 rie Shdr *shdr = _cache->c_shdr; 1011 0 stevel 1012 0 stevel /* 1013 0 stevel * Scan sections to find a section which contains the PT_INTERP 1014 0 stevel * string. The target section can't be in a NOBITS section. 1015 0 stevel */ 1016 0 stevel if ((shdr->sh_type == SHT_NOBITS) || 1017 0 stevel (iphdr_off < shdr->sh_offset) || 1018 1618 rie (iphdr_off + iphdr_fsz) > (shdr->sh_offset + shdr->sh_size)) 1019 0 stevel continue; 1020 0 stevel 1021 0 stevel icache = _cache; 1022 0 stevel ishdr = shdr; 1023 0 stevel break; 1024 0 stevel } 1025 0 stevel 1026 0 stevel /* 1027 0 stevel * Print the interpreter string based on the offset defined in the 1028 0 stevel * program header, as this is the offset used by the kernel. 1029 0 stevel */ 1030 3466 rie if (ishdr && icache->c_data) { 1031 1618 rie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1032 1618 rie dbg_print(0, MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name); 1033 1618 rie dbg_print(0, MSG_ORIG(MSG_FMT_INDENT), 1034 0 stevel (char *)icache->c_data->d_buf + 1035 0 stevel (iphdr_off - ishdr->sh_offset)); 1036 0 stevel } else 1037 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file); 1038 0 stevel 1039 0 stevel /* 1040 0 stevel * If there are any inconsistences between the program header and 1041 0 stevel * section information, flag them. 1042 0 stevel */ 1043 0 stevel if (ishdr && ((iphdr_off != ishdr->sh_offset) || 1044 1618 rie (iphdr_fsz != ishdr->sh_size))) { 1045 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file, 1046 0 stevel icache->c_name); 1047 0 stevel } 1048 0 stevel } 1049 0 stevel 1050 0 stevel /* 1051 0 stevel * Print the syminfo section. 1052 0 stevel */ 1053 0 stevel static void 1054 1618 rie syminfo(Cache *cache, Word shnum, const char *file) 1055 0 stevel { 1056 1618 rie Shdr *infoshdr; 1057 1618 rie Syminfo *info; 1058 1618 rie Sym *syms; 1059 1618 rie Dyn *dyns; 1060 1618 rie Word infonum, cnt, ndx, symnum; 1061 9085 Ali Cache *infocache = NULL, *symsec, *strsec; 1062 0 stevel 1063 0 stevel for (cnt = 1; cnt < shnum; cnt++) { 1064 1618 rie if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) { 1065 1618 rie infocache = &cache[cnt]; 1066 0 stevel break; 1067 0 stevel } 1068 0 stevel } 1069 9085 Ali if (infocache == NULL) 1070 0 stevel return; 1071 0 stevel 1072 1618 rie infoshdr = infocache->c_shdr; 1073 1618 rie if ((infoshdr->sh_entsize == 0) || (infoshdr->sh_size == 0)) { 1074 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1075 1618 rie file, infocache->c_name); 1076 0 stevel return; 1077 0 stevel } 1078 3466 rie if (infocache->c_data == NULL) 1079 3466 rie return; 1080 3466 rie 1081 1618 rie infonum = (Word)(infoshdr->sh_size / infoshdr->sh_entsize); 1082 1618 rie info = (Syminfo *)infocache->c_data->d_buf; 1083 0 stevel 1084 0 stevel /* 1085 0 stevel * Get the data buffer of the associated dynamic section. 1086 0 stevel */ 1087 1618 rie if ((infoshdr->sh_info == 0) || (infoshdr->sh_info >= shnum)) { 1088 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO), 1089 1618 rie file, infocache->c_name, EC_WORD(infoshdr->sh_info)); 1090 0 stevel return; 1091 0 stevel } 1092 3466 rie if (cache[infoshdr->sh_info].c_data == NULL) 1093 3466 rie return; 1094 3466 rie 1095 1618 rie dyns = cache[infoshdr->sh_info].c_data->d_buf; 1096 9085 Ali if (dyns == NULL) { 1097 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1098 1618 rie file, cache[infoshdr->sh_info].c_name); 1099 0 stevel return; 1100 0 stevel } 1101 0 stevel 1102 0 stevel /* 1103 1618 rie * Get the data buffer for the associated symbol table and string table. 1104 0 stevel */ 1105 1618 rie if (stringtbl(cache, 1, cnt, shnum, file, 1106 1618 rie &symnum, &symsec, &strsec) == 0) 1107 0 stevel return; 1108 0 stevel 1109 1618 rie syms = symsec->c_data->d_buf; 1110 1618 rie 1111 0 stevel /* 1112 1618 rie * Loop through the syminfo entries. 1113 0 stevel */ 1114 1618 rie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1115 1618 rie dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMINFO), infocache->c_name); 1116 1618 rie Elf_syminfo_title(0); 1117 0 stevel 1118 1618 rie for (ndx = 1, info++; ndx < infonum; ndx++, info++) { 1119 1618 rie Sym *sym; 1120 9085 Ali const char *needed = NULL, *name; 1121 0 stevel 1122 1618 rie if ((info->si_flags == 0) && (info->si_boundto == 0)) 1123 0 stevel continue; 1124 0 stevel 1125 1618 rie sym = &syms[ndx]; 1126 1618 rie name = string(infocache, ndx, strsec, file, sym->st_name); 1127 1618 rie 1128 1618 rie if (info->si_boundto < SYMINFO_BT_LOWRESERVE) { 1129 1618 rie Dyn *dyn = &dyns[info->si_boundto]; 1130 1618 rie 1131 1618 rie needed = string(infocache, info->si_boundto, 1132 1618 rie strsec, file, dyn->d_un.d_val); 1133 0 stevel } 1134 1618 rie Elf_syminfo_entry(0, ndx, info, name, needed); 1135 0 stevel } 1136 0 stevel } 1137 0 stevel 1138 0 stevel /* 1139 0 stevel * Print version definition section entries. 1140 0 stevel */ 1141 0 stevel static void 1142 4716 ab196087 version_def(Verdef *vdf, Word vdf_num, Cache *vcache, Cache *scache, 1143 0 stevel const char *file) 1144 0 stevel { 1145 1618 rie Word cnt; 1146 1618 rie char index[MAXNDXSIZE]; 1147 0 stevel 1148 1618 rie Elf_ver_def_title(0); 1149 0 stevel 1150 4716 ab196087 for (cnt = 1; cnt <= vdf_num; cnt++, 1151 1618 rie vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) { 1152 7682 Ali Conv_ver_flags_buf_t ver_flags_buf; 1153 7682 Ali const char *name, *dep; 1154 7682 Ali Half vcnt = vdf->vd_cnt - 1; 1155 7682 Ali Half ndx = vdf->vd_ndx; 1156 7682 Ali Verdaux *vdap = (Verdaux *)((uintptr_t)vdf + vdf->vd_aux); 1157 0 stevel 1158 0 stevel /* 1159 0 stevel * Obtain the name and first dependency (if any). 1160 0 stevel */ 1161 0 stevel name = string(vcache, cnt, scache, file, vdap->vda_name); 1162 1618 rie vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 1163 0 stevel if (vcnt) 1164 0 stevel dep = string(vcache, cnt, scache, file, vdap->vda_name); 1165 0 stevel else 1166 0 stevel dep = MSG_ORIG(MSG_STR_EMPTY); 1167 0 stevel 1168 0 stevel (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX), 1169 0 stevel EC_XWORD(ndx)); 1170 1618 rie Elf_ver_line_1(0, index, name, dep, 1171 7682 Ali conv_ver_flags(vdf->vd_flags, 0, &ver_flags_buf)); 1172 0 stevel 1173 0 stevel /* 1174 0 stevel * Print any additional dependencies. 1175 0 stevel */ 1176 0 stevel if (vcnt) { 1177 1618 rie vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 1178 0 stevel for (vcnt--; vcnt; vcnt--, 1179 1618 rie vdap = (Verdaux *)((uintptr_t)vdap + 1180 0 stevel vdap->vda_next)) { 1181 0 stevel dep = string(vcache, cnt, scache, file, 1182 0 stevel vdap->vda_name); 1183 1618 rie Elf_ver_line_2(0, MSG_ORIG(MSG_STR_EMPTY), dep); 1184 0 stevel } 1185 0 stevel } 1186 0 stevel } 1187 0 stevel } 1188 0 stevel 1189 0 stevel /* 1190 4716 ab196087 * Print version needed section entries. 1191 4716 ab196087 * 1192 4716 ab196087 * entry: 1193 4716 ab196087 * vnd - Address of verneed data 1194 4716 ab196087 * vnd_num - # of Verneed entries 1195 4716 ab196087 * vcache - Cache of verneed section being processed 1196 4716 ab196087 * scache - Cache of associated string table section 1197 4716 ab196087 * file - Name of object being processed. 1198 4716 ab196087 * versym - Information about versym section 1199 4716 ab196087 * 1200 4716 ab196087 * exit: 1201 4716 ab196087 * The versions have been printed. If GNU style versioning 1202 4716 ab196087 * is in effect, versym->max_verndx has been updated to 1203 4716 ab196087 * contain the largest version index seen. 1204 7682 Ali * 1205 7682 Ali * note: 1206 7682 Ali * The versym section of an object that follows the original 1207 7682 Ali * Solaris versioning rules only contains indexes into the verdef 1208 7682 Ali * section. Symbols defined in other objects (UNDEF) are given 1209 7682 Ali * a version of 0, indicating that they are not defined by 1210 7682 Ali * this file, and the Verneed entries do not have associated version 1211 7682 Ali * indexes. For these reasons, we do not display a version index 1212 7682 Ali * for original-style Verneed sections. 1213 7682 Ali * 1214 7682 Ali * The GNU versioning extensions alter this: Symbols defined in other 1215 7682 Ali * objects receive a version index in the range above those defined 1216 7682 Ali * by the Verdef section, and the vna_other field of the Vernaux 1217 7682 Ali * structs inside the Verneed section contain the version index for 1218 7682 Ali * that item. We therefore display the index when showing the 1219 7682 Ali * contents of a GNU style Verneed section. You should not 1220 7682 Ali * necessarily expect these indexes to appear in sorted 1221 7682 Ali * order --- it seems that the GNU ld assigns the versions as 1222 7682 Ali * symbols are encountered during linking, and then the results 1223 7682 Ali * are assembled into the Verneed section afterwards. 1224 0 stevel */ 1225 0 stevel static void 1226 4716 ab196087 version_need(Verneed *vnd, Word vnd_num, Cache *vcache, Cache *scache, 1227 4716 ab196087 const char *file, VERSYM_STATE *versym) 1228 0 stevel { 1229 4716 ab196087 Word cnt; 1230 4716 ab196087 char index[MAXNDXSIZE]; 1231 4716 ab196087 const char *index_str; 1232 0 stevel 1233 7682 Ali Elf_ver_need_title(0, versym->gnu_needed); 1234 4716 ab196087 1235 4716 ab196087 for (cnt = 1; cnt <= vnd_num; cnt++, 1236 1618 rie vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 1237 7682 Ali Conv_ver_flags_buf_t ver_flags_buf; 1238 7682 Ali const char *name, *dep; 1239 7682 Ali Half vcnt = vnd->vn_cnt; 1240 4433 ab196087 Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + vnd->vn_aux); 1241 0 stevel 1242 0 stevel /* 1243 0 stevel * Obtain the name of the needed file and the version name 1244 0 stevel * within it that we're dependent on. Note that the count 1245 0 stevel * should be at least one, otherwise this is a pretty bogus 1246 0 stevel * entry. 1247 0 stevel */ 1248 0 stevel name = string(vcache, cnt, scache, file, vnd->vn_file); 1249 0 stevel if (vcnt) 1250 0 stevel dep = string(vcache, cnt, scache, file, vnap->vna_name); 1251 0 stevel else 1252 0 stevel dep = MSG_INTL(MSG_STR_NULL); 1253 0 stevel 1254 7682 Ali if (vnap->vna_other == 0) { /* Traditional form */ 1255 7682 Ali index_str = MSG_ORIG(MSG_STR_EMPTY); 1256 7682 Ali } else { /* GNU form */ 1257 7682 Ali index_str = index; 1258 4716 ab196087 /* Format the version index value */ 1259 4716 ab196087 (void) snprintf(index, MAXNDXSIZE, 1260 4716 ab196087 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(vnap->vna_other)); 1261 4716 ab196087 if (vnap->vna_other > versym->max_verndx) 1262 4716 ab196087 versym->max_verndx = vnap->vna_other; 1263 4716 ab196087 } 1264 4716 ab196087 Elf_ver_line_1(0, index_str, name, dep, 1265 7682 Ali conv_ver_flags(vnap->vna_flags, 0, &ver_flags_buf)); 1266 0 stevel 1267 0 stevel /* 1268 0 stevel * Print any additional version dependencies. 1269 0 stevel */ 1270 0 stevel if (vcnt) { 1271 1618 rie vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next); 1272 0 stevel for (vcnt--; vcnt; vcnt--, 1273 1618 rie vnap = (Vernaux *)((uintptr_t)vnap + 1274 0 stevel vnap->vna_next)) { 1275 0 stevel dep = string(vcache, cnt, scache, file, 1276 0 stevel vnap->vna_name); 1277 7682 Ali if (vnap->vna_other > 0) { 1278 4716 ab196087 /* Format the next index value */ 1279 4716 ab196087 (void) snprintf(index, MAXNDXSIZE, 1280 4716 ab196087 MSG_ORIG(MSG_FMT_INDEX), 1281 4716 ab196087 EC_XWORD(vnap->vna_other)); 1282 7682 Ali Elf_ver_line_1(0, index, 1283 4716 ab196087 MSG_ORIG(MSG_STR_EMPTY), dep, 1284 7682 Ali conv_ver_flags(vnap->vna_flags, 1285 7682 Ali 0, &ver_flags_buf)); 1286 4716 ab196087 if (vnap->vna_other > 1287 4716 ab196087 versym->max_verndx) 1288 4716 ab196087 versym->max_verndx = 1289 4716 ab196087 vnap->vna_other; 1290 4716 ab196087 } else { 1291 4716 ab196087 Elf_ver_line_3(0, 1292 4716 ab196087 MSG_ORIG(MSG_STR_EMPTY), dep, 1293 7682 Ali conv_ver_flags(vnap->vna_flags, 1294 7682 Ali 0, &ver_flags_buf)); 1295 7682 Ali } 1296 7682 Ali } 1297 7682 Ali } 1298 7682 Ali } 1299 7682 Ali } 1300 7682 Ali 1301 7682 Ali /* 1302 7682 Ali * Examine the Verneed section for information related to GNU 1303 7682 Ali * style Versym indexing: 1304 7682 Ali * - A non-zero vna_other field indicates that Versym indexes can 1305 7682 Ali * reference Verneed records. 1306 7682 Ali * - If the object uses GNU style Versym indexing, the 1307 7682 Ali * maximum index value is needed to detect bad Versym entries. 1308 4716 ab196087 * 1309 4716 ab196087 * entry: 1310 4716 ab196087 * vnd - Address of verneed data 1311 4716 ab196087 * vnd_num - # of Verneed entries 1312 4716 ab196087 * versym - Information about versym section 1313 4716 ab196087 * 1314 4716 ab196087 * exit: 1315 7682 Ali * If a non-zero vna_other field is seen, versym->gnu_needed is set. 1316 7682 Ali * 1317 4716 ab196087 * versym->max_verndx has been updated to contain the largest 1318 4716 ab196087 * version index seen. 1319 4716 ab196087 */ 1320 4716 ab196087 static void 1321 7682 Ali update_gnu_verndx(Verneed *vnd, Word vnd_num, VERSYM_STATE *versym) 1322 4716 ab196087 { 1323 4716 ab196087 Word cnt; 1324 4716 ab196087 1325 4716 ab196087 for (cnt = 1; cnt <= vnd_num; cnt++, 1326 4716 ab196087 vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 1327 4716 ab196087 Half vcnt = vnd->vn_cnt; 1328 4716 ab196087 Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + vnd->vn_aux); 1329 4716 ab196087 1330 7682 Ali /* 1331 7682 Ali * A non-zero value of vna_other indicates that this 1332 7682 Ali * object references VERNEED items from the VERSYM 1333 7682 Ali * array. 1334 7682 Ali */ 1335 7682 Ali if (vnap->vna_other != 0) { 1336 7682 Ali versym->gnu_needed = 1; 1337 7682 Ali if (vnap->vna_other > versym->max_verndx) 1338 7682 Ali versym->max_verndx = vnap->vna_other; 1339 7682 Ali } 1340 4716 ab196087 1341 4716 ab196087 /* 1342 4716 ab196087 * Check any additional version dependencies. 1343 4716 ab196087 */ 1344 4716 ab196087 if (vcnt) { 1345 4716 ab196087 vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next); 1346 4716 ab196087 for (vcnt--; vcnt; vcnt--, 1347 4716 ab196087 vnap = (Vernaux *)((uintptr_t)vnap + 1348 4716 ab196087 vnap->vna_next)) { 1349 7682 Ali if (vnap->vna_other == 0) 1350 7682 Ali continue; 1351 7682 Ali 1352 7682 Ali versym->gnu_needed = 1; 1353 4716 ab196087 if (vnap->vna_other > versym->max_verndx) 1354 4716 ab196087 versym->max_verndx = vnap->vna_other; 1355 0 stevel } 1356 0 stevel } 1357 0 stevel } 1358 0 stevel } 1359 0 stevel 1360 0 stevel /* 1361 3875 ab196087 * Display version section information if the flags require it. 1362 3875 ab196087 * Return version information needed by other output. 1363 3875 ab196087 * 1364 3875 ab196087 * entry: 1365 3875 ab196087 * cache - Cache of all section headers 1366 3875 ab196087 * shnum - # of sections in cache 1367 3875 ab196087 * file - Name of file 1368 3875 ab196087 * flags - Command line option flags 1369 3875 ab196087 * versym - VERSYM_STATE block to be filled in. 1370 0 stevel */ 1371 3875 ab196087 static void 1372 3875 ab196087 versions(Cache *cache, Word shnum, const char *file, uint_t flags, 1373 3875 ab196087 VERSYM_STATE *versym) 1374 0 stevel { 1375 0 stevel GElf_Word cnt; 1376 4716 ab196087 Cache *verdef_cache = NULL, *verneed_cache = NULL; 1377 3875 ab196087 1378 4716 ab196087 1379 4716 ab196087 /* Gather information about the version sections */ 1380 3875 ab196087 bzero(versym, sizeof (*versym)); 1381 4716 ab196087 versym->max_verndx = 1; 1382 0 stevel for (cnt = 1; cnt < shnum; cnt++) { 1383 1618 rie Cache *_cache = &cache[cnt]; 1384 1618 rie Shdr *shdr = _cache->c_shdr; 1385 4716 ab196087 Dyn *dyn; 1386 4716 ab196087 ulong_t numdyn; 1387 0 stevel 1388 4716 ab196087 switch (shdr->sh_type) { 1389 4716 ab196087 case SHT_DYNAMIC: 1390 4716 ab196087 /* 1391 4716 ab196087 * The GNU ld puts a DT_VERSYM entry in the dynamic 1392 4716 ab196087 * section so that the runtime linker can use it to 1393 4716 ab196087 * implement their versioning rules. They allow multiple 1394 4716 ab196087 * incompatible functions with the same name to exist 1395 4716 ab196087 * in different versions. The Solaris ld does not 1396 4716 ab196087 * support this mechanism, and as such, does not 1397 4716 ab196087 * produce DT_VERSYM. We use this fact to determine 1398 4716 ab196087 * which ld produced this object, and how to interpret 1399 4716 ab196087 * the version values. 1400 4716 ab196087 */ 1401 4716 ab196087 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0) || 1402 4716 ab196087 (_cache->c_data == NULL)) 1403 4716 ab196087 continue; 1404 4716 ab196087 numdyn = shdr->sh_size / shdr->sh_entsize; 1405 4716 ab196087 dyn = (Dyn *)_cache->c_data->d_buf; 1406 4716 ab196087 for (; numdyn-- > 0; dyn++) 1407 4716 ab196087 if (dyn->d_tag == DT_VERSYM) { 1408 7682 Ali versym->gnu_full = 1409 7682 Ali versym->gnu_needed = 1; 1410 4716 ab196087 break; 1411 4716 ab196087 } 1412 4716 ab196087 break; 1413 4716 ab196087 1414 4716 ab196087 case SHT_SUNW_versym: 1415 4716 ab196087 /* Record data address for later symbol processing */ 1416 4716 ab196087 if (_cache->c_data != NULL) { 1417 4716 ab196087 versym->cache = _cache; 1418 4716 ab196087 versym->data = _cache->c_data->d_buf; 1419 4716 ab196087 continue; 1420 4716 ab196087 } 1421 4716 ab196087 break; 1422 4716 ab196087 1423 4716 ab196087 case SHT_SUNW_verdef: 1424 4716 ab196087 case SHT_SUNW_verneed: 1425 4716 ab196087 /* 1426 4716 ab196087 * Ensure the data is non-NULL and the number 1427 4716 ab196087 * of items is non-zero. Otherwise, we don't 1428 4716 ab196087 * understand the section, and will not use it. 1429 4716 ab196087 */ 1430 4716 ab196087 if ((_cache->c_data == NULL) || 1431 4716 ab196087 (_cache->c_data->d_buf == NULL)) { 1432 4716 ab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1433 4716 ab196087 file, _cache->c_name); 1434 4716 ab196087 continue; 1435 4716 ab196087 } 1436 4716 ab196087 if (shdr->sh_info == 0) { 1437 4716 ab196087 (void) fprintf(stderr, 1438 4716 ab196087 MSG_INTL(MSG_ERR_BADSHINFO), 1439 4716 ab196087 file, _cache->c_name, 1440 4716 ab196087 EC_WORD(shdr->sh_info)); 1441 4716 ab196087 continue; 1442 4716 ab196087 } 1443 4716 ab196087 1444 4716 ab196087 /* Make sure the string table index is in range */ 1445 4716 ab196087 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1446 4716 ab196087 (void) fprintf(stderr, 1447 4716 ab196087 MSG_INTL(MSG_ERR_BADSHLINK), file, 1448 4716 ab196087 _cache->c_name, EC_WORD(shdr->sh_link)); 1449 4716 ab196087 continue; 1450 4716 ab196087 } 1451 4716 ab196087 1452 4716 ab196087 /* 1453 4716 ab196087 * The section is usable. Save the cache entry. 1454 4716 ab196087 */ 1455 4716 ab196087 if (shdr->sh_type == SHT_SUNW_verdef) { 1456 4716 ab196087 verdef_cache = _cache; 1457 4716 ab196087 /* 1458 4716 ab196087 * Under Solaris rules, if there is a verdef 1459 4716 ab196087 * section, the max versym index is number 1460 4716 ab196087 * of version definitions it supplies. 1461 4716 ab196087 */ 1462 4716 ab196087 versym->max_verndx = shdr->sh_info; 1463 4716 ab196087 } else { 1464 4716 ab196087 verneed_cache = _cache; 1465 4716 ab196087 } 1466 4716 ab196087 break; 1467 4716 ab196087 } 1468 4716 ab196087 } 1469 4716 ab196087 1470 7682 Ali /* 1471 7682 Ali * If there is a Verneed section, examine it for information 1472 7682 Ali * related to GNU style versioning. 1473 7682 Ali */ 1474 7682 Ali if (verneed_cache != NULL) 1475 7682 Ali update_gnu_verndx((Verneed *)verneed_cache->c_data->d_buf, 1476 7682 Ali verneed_cache->c_shdr->sh_info, versym); 1477 3875 ab196087 1478 4716 ab196087 /* 1479 4716 ab196087 * Now that all the information is available, display the 1480 7682 Ali * Verdef and Verneed section contents, if requested. 1481 7682 Ali */ 1482 7682 Ali if ((flags & FLG_SHOW_VERSIONS) == 0) 1483 7682 Ali return; 1484 4716 ab196087 if (verdef_cache != NULL) { 1485 4716 ab196087 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1486 4716 ab196087 dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERDEF), 1487 4716 ab196087 verdef_cache->c_name); 1488 4716 ab196087 version_def((Verdef *)verdef_cache->c_data->d_buf, 1489 4716 ab196087 verdef_cache->c_shdr->sh_info, verdef_cache, 1490 4716 ab196087 &cache[verdef_cache->c_shdr->sh_link], file); 1491 4716 ab196087 } 1492 4716 ab196087 if (verneed_cache != NULL) { 1493 4716 ab196087 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1494 4716 ab196087 dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERNEED), 1495 4716 ab196087 verneed_cache->c_name); 1496 3875 ab196087 /* 1497 4716 ab196087 * If GNU versioning applies to this object, version_need() 1498 4716 ab196087 * will update versym->max_verndx, and it is not 1499 7682 Ali * necessary to call update_gnu_verndx(). 1500 3875 ab196087 */ 1501 4716 ab196087 version_need((Verneed *)verneed_cache->c_data->d_buf, 1502 4716 ab196087 verneed_cache->c_shdr->sh_info, verneed_cache, 1503 4716 ab196087 &cache[verneed_cache->c_shdr->sh_link], file, versym); 1504 0 stevel } 1505 0 stevel } 1506 3492 ab196087 1507 3492 ab196087 /* 1508 3492 ab196087 * Initialize a symbol table state structure 1509 3492 ab196087 * 1510 3492 ab196087 * entry: 1511 3492 ab196087 * state - State structure to be initialized 1512 3492 ab196087 * cache - Cache of all section headers 1513 3492 ab196087 * shnum - # of sections in cache 1514 3492 ab196087 * secndx - Index of symbol table section 1515 3492 ab196087 * ehdr - ELF header for file 1516 3875 ab196087 * versym - Information about versym section 1517 3492 ab196087 * file - Name of file 1518 3492 ab196087 * flags - Command line option flags 1519 3492 ab196087 */ 1520 3492 ab196087 static int 1521 3492 ab196087 init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx, 1522 9273 Ali Ehdr *ehdr, uchar_t osabi, VERSYM_STATE *versym, const char *file, 1523 9273 Ali uint_t flags) 1524 3492 ab196087 { 1525 3492 ab196087 Shdr *shdr; 1526 3492 ab196087 1527 3492 ab196087 state->file = file; 1528 3492 ab196087 state->ehdr = ehdr; 1529 3492 ab196087 state->cache = cache; 1530 9273 Ali state->osabi = osabi; 1531 3492 ab196087 state->shnum = shnum; 1532 3492 ab196087 state->seccache = &cache[secndx]; 1533 3492 ab196087 state->secndx = secndx; 1534 3492 ab196087 state->secname = state->seccache->c_name; 1535 3492 ab196087 state->flags = flags; 1536 3492 ab196087 state->shxndx.checked = 0; 1537 3492 ab196087 state->shxndx.data = NULL; 1538 3492 ab196087 state->shxndx.n = 0; 1539 3492 ab196087 1540 3492 ab196087 shdr = state->seccache->c_shdr; 1541 3492 ab196087 1542 3492 ab196087 /* 1543 3492 ab196087 * Check the symbol data and per-item size. 1544 3492 ab196087 */ 1545 3492 ab196087 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 1546 3492 ab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 1547 3492 ab196087 file, state->secname); 1548 3492 ab196087 return (0); 1549 3492 ab196087 } 1550 3492 ab196087 if (state->seccache->c_data == NULL) 1551 3492 ab196087 return (0); 1552 3492 ab196087 1553 3492 ab196087 /* LINTED */ 1554 3492 ab196087 state->symn = (Word)(shdr->sh_size / shdr->sh_entsize); 1555 3492 ab196087 state->sym = (Sym *)state->seccache->c_data->d_buf; 1556 3492 ab196087 1557 3492 ab196087 /* 1558 3492 ab196087 * Check associated string table section. 1559 3492 ab196087 */ 1560 3492 ab196087 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { 1561 3492 ab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1562 3492 ab196087 file, state->secname, EC_WORD(shdr->sh_link)); 1563 3492 ab196087 return (0); 1564 3492 ab196087 } 1565 3492 ab196087 1566 3492 ab196087 /* 1567 3492 ab196087 * Determine if there is a associated Versym section 1568 3492 ab196087 * with this Symbol Table. 1569 3492 ab196087 */ 1570 3875 ab196087 if (versym->cache && 1571 3875 ab196087 (versym->cache->c_shdr->sh_link == state->secndx)) 1572 3875 ab196087 state->versym = versym; 1573 3492 ab196087 else 1574 3492 ab196087 state->versym = NULL; 1575 3492 ab196087 1576 3492 ab196087 1577 3492 ab196087 return (1); 1578 3492 ab196087 } 1579 3492 ab196087 1580 3492 ab196087 /* 1581 1618 rie * Determine the extended section index used for symbol tables entries. 1582 1618 rie */ 1583 3492 ab196087 static void 1584 7463 Rod symbols_getxindex(SYMTBL_STATE *state) 1585 1618 rie { 1586 1618 rie uint_t symn; 1587 1618 rie Word symcnt; 1588 1618 rie 1589 3492 ab196087 state->shxndx.checked = 1; /* Note that we've been called */ 1590 3492 ab196087 for (symcnt = 1; symcnt < state->shnum; symcnt++) { 1591 3492 ab196087 Cache *_cache = &state->cache[symcnt]; 1592 1618 rie Shdr *shdr = _cache->c_shdr; 1593 1618 rie 1594 1618 rie if ((shdr->sh_type != SHT_SYMTAB_SHNDX) || 1595 3492 ab196087 (shdr->sh_link != state->secndx)) 1596 1618 rie continue; 1597 1618 rie 1598 1618 rie if ((shdr->sh_entsize) && 1599 1618 rie /* LINTED */ 1600 1618 rie ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0)) 1601 3466 rie continue; 1602 3466 rie 1603 3466 rie if (_cache->c_data == NULL) 1604 1618 rie continue; 1605 1618 rie 1606 3492 ab196087 state->shxndx.data = _cache->c_data->d_buf; 1607 3492 ab196087 state->shxndx.n = symn; 1608 3492 ab196087 return; 1609 1618 rie } 1610 3492 ab196087 } 1611 3492 ab196087 1612 3492 ab196087 /* 1613 3492 ab196087 * Produce a line of output for the given symbol 1614 3492 ab196087 * 1615 3492 ab196087 * entry: 1616 3875 ab196087 * state - Symbol table state 1617 3492 ab196087 * symndx - Index of symbol within the table 1618 4832 rie * info - Value of st_info (indicates local/global range) 1619 3492 ab196087 * symndx_disp - Index to display. This may not be the same 1620 3492 ab196087 * as symndx if the display is relative to the logical 1621 3492 ab196087 * combination of the SUNW_ldynsym/dynsym tables. 1622 3492 ab196087 * sym - Symbol to display 1623 3492 ab196087 */ 1624 3492 ab196087 static void 1625 4832 rie output_symbol(SYMTBL_STATE *state, Word symndx, Word info, Word disp_symndx, 1626 4832 rie Sym *sym) 1627 3492 ab196087 { 1628 3492 ab196087 /* 1629 3492 ab196087 * Symbol types for which we check that the specified 1630 3492 ab196087 * address/size land inside the target section. 1631 3492 ab196087 */ 1632 9085 Ali static const int addr_symtype[] = { 1633 3492 ab196087 0, /* STT_NOTYPE */ 1634 3492 ab196087 1, /* STT_OBJECT */ 1635 3492 ab196087 1, /* STT_FUNC */ 1636 3492 ab196087 0, /* STT_SECTION */ 1637 3492 ab196087 0, /* STT_FILE */ 1638 3492 ab196087 1, /* STT_COMMON */ 1639 3492 ab196087 0, /* STT_TLS */ 1640 9900 Ali 0, /* 7 */ 1641 9085 Ali 0, /* 8 */ 1642 9085 Ali 0, /* 9 */ 1643 9085 Ali 0, /* 10 */ 1644 9085 Ali 0, /* 11 */ 1645 9085 Ali 0, /* 12 */ 1646 9085 Ali 0, /* STT_SPARC_REGISTER */ 1647 9085 Ali 0, /* 14 */ 1648 9085 Ali 0, /* 15 */ 1649 3492 ab196087 }; 1650 9900 Ali #if STT_NUM != (STT_TLS + 1) 1651 3492 ab196087 #error "STT_NUM has grown. Update addr_symtype[]" 1652 3492 ab196087 #endif 1653 3492 ab196087 1654 4665 ab196087 char index[MAXNDXSIZE]; 1655 4665 ab196087 const char *symname, *sec; 1656 3875 ab196087 Versym verndx; 1657 4716 ab196087 int gnuver; 1658 3492 ab196087 uchar_t type; 1659 3492 ab196087 Shdr *tshdr; 1660 3492 ab196087 Word shndx; 1661 4734 ab196087 Conv_inv_buf_t inv_buf; 1662 3492 ab196087 1663 3492 ab196087 /* Ensure symbol index is in range */ 1664 3492 ab196087 if (symndx >= state->symn) { 1665 3492 ab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORTNDX), 1666 3492 ab196087 state->file, state->secname, EC_WORD(symndx)); 1667 3492 ab196087 return; 1668 3492 ab196087 } 1669 3492 ab196087 1670 3492 ab196087 /* 1671 3492 ab196087 * If we are using extended symbol indexes, find the 1672 3492 ab196087 * corresponding SHN_SYMTAB_SHNDX table. 1673 3492 ab196087 */ 1674 3492 ab196087 if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0)) 1675 3492 ab196087 symbols_getxindex(state); 1676 3492 ab196087 1677 3492 ab196087 /* LINTED */ 1678 3492 ab196087 symname = string(state->seccache, symndx, 1679 3492 ab196087 &state->cache[state->seccache->c_shdr->sh_link], state->file, 1680 3492 ab196087 sym->st_name); 1681 3492 ab196087 1682 9085 Ali tshdr = NULL; 1683 3492 ab196087 sec = NULL; 1684 3492 ab196087 1685 4665 ab196087 if (state->ehdr->e_type == ET_CORE) { 1686 3492 ab196087 sec = (char *)MSG_INTL(MSG_STR_UNKNOWN); 1687 5411 ab196087 } else if (state->flags & FLG_CTL_FAKESHDR) { 1688 4665 ab196087 /* 1689 4665 ab196087 * If we are using fake section headers derived from 1690 4665 ab196087 * the program headers, then the section indexes 1691 4665 ab196087 * in the symbols do not correspond to these headers. 1692 4665 ab196087 * The section names are not available, so all we can 1693 4665 ab196087 * do is to display them in numeric form. 1694 4665 ab196087 */ 1695 9273 Ali sec = conv_sym_shndx(state->osabi, state->ehdr->e_machine, 1696 9273 Ali sym->st_shndx, CONV_FMT_DECIMAL, &inv_buf); 1697 4665 ab196087 } else if ((sym->st_shndx < SHN_LORESERVE) && 1698 3492 ab196087 (sym->st_shndx < state->shnum)) { 1699 3492 ab196087 shndx = sym->st_shndx; 1700 3492 ab196087 tshdr = state->cache[shndx].c_shdr; 1701 3492 ab196087 sec = state->cache[shndx].c_name; 1702 3492 ab196087 } else if (sym->st_shndx == SHN_XINDEX) { 1703 3492 ab196087 if (state->shxndx.data) { 1704 3492 ab196087 Word _shxndx; 1705 3492 ab196087 1706 3492 ab196087 if (symndx > state->shxndx.n) { 1707 4433 ab196087 (void) fprintf(stderr, 1708 4433 ab196087 MSG_INTL(MSG_ERR_BADSYMXINDEX1), 1709 4433 ab196087 state->file, state->secname, 1710 4433 ab196087 EC_WORD(symndx)); 1711 3492 ab196087 } else if ((_shxndx = 1712 3492 ab196087 state->shxndx.data[symndx]) > state->shnum) { 1713 4433 ab196087 (void) fprintf(stderr, 1714 4433 ab196087 MSG_INTL(MSG_ERR_BADSYMXINDEX2), 1715 4433 ab196087 state->file, state->secname, 1716 4433 ab196087 EC_WORD(symndx), EC_WORD(_shxndx)); 1717 3492 ab196087 } else { 1718 4433 ab196087 shndx = _shxndx; 1719 4433 ab196087 tshdr = state->cache[shndx].c_shdr; 1720 4433 ab196087 sec = state->cache[shndx].c_name; 1721 3492 ab196087 } 1722 3492 ab196087 } else { 1723 3492 ab196087 (void) fprintf(stderr, 1724 3492 ab196087 MSG_INTL(MSG_ERR_BADSYMXINDEX3), 1725 3492 ab196087 state->file, state->secname, EC_WORD(symndx)); 1726 3492 ab196087 } 1727 3492 ab196087 } else if ((sym->st_shndx < SHN_LORESERVE) && 1728 3492 ab196087 (sym->st_shndx >= state->shnum)) { 1729 3492 ab196087 (void) fprintf(stderr, 1730 3492 ab196087 MSG_INTL(MSG_ERR_BADSYM5), state->file, 1731 6206 ab196087 state->secname, EC_WORD(symndx), 1732 6206 ab196087 demangle(symname, state->flags), sym->st_shndx); 1733 3492 ab196087 } 1734 3492 ab196087 1735 3492 ab196087 /* 1736 3492 ab196087 * If versioning is available display the 1737 3875 ab196087 * version index. If not, then use 0. 1738 3492 ab196087 */ 1739 3875 ab196087 if (state->versym) { 1740 4716 ab196087 Versym test_verndx; 1741 4716 ab196087 1742 4716 ab196087 verndx = test_verndx = state->versym->data[symndx]; 1743 7682 Ali gnuver = state->versym->gnu_full; 1744 3875 ab196087 1745 3875 ab196087 /* 1746 3875 ab196087 * Check to see if this is a defined symbol with a 1747 3875 ab196087 * version index that is outside the valid range for 1748 4716 ab196087 * the file. The interpretation of this depends on 1749 4716 ab196087 * the style of versioning used by the object. 1750 3875 ab196087 * 1751 4716 ab196087 * Versions >= VER_NDX_LORESERVE have special meanings, 1752 4716 ab196087 * and are exempt from this checking. 1753 4716 ab196087 * 1754 4716 ab196087 * GNU style version indexes use the top bit of the 1755 4716 ab196087 * 16-bit index value (0x8000) as the "hidden bit". 1756 4716 ab196087 * We must mask off this bit in order to compare 1757 4716 ab196087 * the version against the maximum value. 1758 3875 ab196087 */ 1759 4716 ab196087 if (gnuver) 1760 4716 ab196087 test_verndx &= ~0x8000; 1761 4716 ab196087 1762 4716 ab196087 if ((test_verndx > state->versym->max_verndx) && 1763 4716 ab196087 (verndx < VER_NDX_LORESERVE)) 1764 4716 ab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADVER), 1765 4716 ab196087 state->file, state->secname, EC_WORD(symndx), 1766 4716 ab196087 EC_HALF(test_verndx), state->versym->max_verndx); 1767 3875 ab196087 } else { 1768 3492 ab196087 verndx = 0; 1769 4716 ab196087 gnuver = 0; 1770 3875 ab196087 } 1771 3492 ab196087 1772 3492 ab196087 /* 1773 3492 ab196087 * Error checking for TLS. 1774 3492 ab196087 */ 1775 3492 ab196087 type = ELF_ST_TYPE(sym->st_info); 1776 3492 ab196087 if (type == STT_TLS) { 1777 3492 ab196087 if (tshdr && 1778 3492 ab196087 (sym->st_shndx != SHN_UNDEF) && 1779 3492 ab196087 ((tshdr->sh_flags & SHF_TLS) == 0)) { 1780 3492 ab196087 (void) fprintf(stderr, 1781 3492 ab196087 MSG_INTL(MSG_ERR_BADSYM3), state->file, 1782 6206 ab196087 state->secname, EC_WORD(symndx), 1783 6206 ab196087 demangle(symname, state->flags)); 1784 3492 ab196087 } 1785 3492 ab196087 } else if ((type != STT_SECTION) && sym->st_size && 1786 3492 ab196087 tshdr && (tshdr->sh_flags & SHF_TLS)) { 1787 3492 ab196087 (void) fprintf(stderr, 1788 3492 ab196087 MSG_INTL(MSG_ERR_BADSYM4), state->file, 1789 6206 ab196087 state->secname, EC_WORD(symndx), 1790 6206 ab196087 demangle(symname, state->flags)); 1791 3492 ab196087 } 1792 3492 ab196087 1793 3492 ab196087 /* 1794 3492 ab196087 * If a symbol with non-zero size has a type that 1795 3492 ab196087 * specifies an address, then make sure the location 1796 3492 ab196087 * it references is actually contained within the 1797 3492 ab196087 * section. UNDEF symbols don't count in this case, 1798 3492 ab196087 * so we ignore them. 1799 3492 ab196087 * 1800 3492 ab196087 * The meaning of the st_value field in a symbol 1801 3492 ab196087 * depends on the type of object. For a relocatable 1802 3492 ab196087 * object, it is the offset within the section. 1803 3492 ab196087 * For sharable objects, it is the offset relative to 1804 3492 ab196087 * the base of the object, and for other types, it is 1805 3492 ab196087 * the virtual address. To get an offset within the 1806 3492 ab196087 * section for non-ET_REL files, we subtract the 1807 3492 ab196087 * base address of the section. 1808 3492 ab196087 */ 1809 3492 ab196087 if (addr_symtype[type] && (sym->st_size > 0) && 1810 3492 ab196087 (sym->st_shndx != SHN_UNDEF) && ((sym->st_shndx < SHN_LORESERVE) || 1811 3492 ab196087 (sym->st_shndx == SHN_XINDEX)) && (tshdr != NULL)) { 1812 3492 ab196087 Word v = sym->st_value; 1813 3492 ab196087 if (state->ehdr->e_type != ET_REL) 1814 4832 rie v -= tshdr->sh_addr; 1815 3492 ab196087 if (((v + sym->st_size) > tshdr->sh_size)) { 1816 3492 ab196087 (void) fprintf(stderr, 1817 3492 ab196087 MSG_INTL(MSG_ERR_BADSYM6), state->file, 1818 6206 ab196087 state->secname, EC_WORD(symndx), 1819 6206 ab196087 demangle(symname, state->flags), 1820 3492 ab196087 EC_WORD(shndx), EC_XWORD(tshdr->sh_size), 1821 3492 ab196087 EC_XWORD(sym->st_value), EC_XWORD(sym->st_size)); 1822 4832 rie } 1823 4832 rie } 1824 4832 rie 1825 4832 rie /* 1826 4832 rie * A typical symbol table uses the sh_info field to indicate one greater 1827 4832 rie * than the symbol table index of the last local symbol, STB_LOCAL. 1828 4832 rie * Therefore, symbol indexes less than sh_info should have local 1829 4832 rie * binding. Symbol indexes greater than, or equal to sh_info, should 1830 4832 rie * have global binding. Note, we exclude UNDEF/NOTY symbols with zero 1831 4832 rie * value and size, as these symbols may be the result of an mcs(1) 1832 4832 rie * section deletion. 1833 4832 rie */ 1834 4832 rie if (info) { 1835 4832 rie uchar_t bind = ELF_ST_BIND(sym->st_info); 1836 4832 rie 1837 4832 rie if ((symndx < info) && (bind != STB_LOCAL)) { 1838 4832 rie (void) fprintf(stderr, 1839 4832 rie MSG_INTL(MSG_ERR_BADSYM7), state->file, 1840 6206 ab196087 state->secname, EC_WORD(symndx), 1841 6206 ab196087 demangle(symname, state->flags), EC_XWORD(info)); 1842 4832 rie 1843 4832 rie } else if ((symndx >= info) && (bind == STB_LOCAL) && 1844 4832 rie ((sym->st_shndx != SHN_UNDEF) || 1845 4832 rie (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) || 1846 4832 rie (sym->st_size != 0) || (sym->st_value != 0))) { 1847 4832 rie (void) fprintf(stderr, 1848 4832 rie MSG_INTL(MSG_ERR_BADSYM8), state->file, 1849 6206 ab196087 state->secname, EC_WORD(symndx), 1850 6206 ab196087 demangle(symname, state->flags), EC_XWORD(info)); 1851 3492 ab196087 } 1852 3492 ab196087 } 1853 3492 ab196087 1854 3492 ab196087 (void) snprintf(index, MAXNDXSIZE, 1855 3492 ab196087 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(disp_symndx)); 1856 9273 Ali Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index, state->osabi, 1857 4716 ab196087 state->ehdr->e_machine, sym, verndx, gnuver, sec, symname); 1858 1618 rie } 1859 1618 rie 1860 1618 rie /* 1861 0 stevel * Search for and process any symbol tables. 1862 0 stevel */ 1863 1618 rie void 1864 9273 Ali symbols(Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi, 1865 9273 Ali VERSYM_STATE *versym, const char *file, uint_t flags) 1866 0 stevel { 1867 3492 ab196087 SYMTBL_STATE state; 1868 3492 ab196087 Cache *_cache; 1869 3492 ab196087 Word secndx; 1870 3118 ab196087 1871 3492 ab196087 for (secndx = 1; secndx < shnum; secndx++) { 1872 3492 ab196087 Word symcnt; 1873 3492 ab196087 Shdr *shdr; 1874 0 stevel 1875 3492 ab196087 _cache = &cache[secndx]; 1876 3492 ab196087 shdr = _cache->c_shdr; 1877 0 stevel 1878 0 stevel if ((shdr->sh_type != SHT_SYMTAB) && 1879 2766 ab196087 (shdr->sh_type != SHT_DYNSYM) && 1880 9273 Ali ((shdr->sh_type != SHT_SUNW_LDYNSYM) || 1881 9273 Ali (osabi != ELFOSABI_SOLARIS))) 1882 0 stevel continue; 1883 5411 ab196087 if (!match(MATCH_F_ALL, _cache->c_name, secndx, shdr->sh_type)) 1884 3492 ab196087 continue; 1885 3492 ab196087 1886 3492 ab196087 if (!init_symtbl_state(&state, cache, shnum, secndx, ehdr, 1887 9273 Ali osabi, versym, file, flags)) 1888 3492 ab196087 continue; 1889 3492 ab196087 /* 1890 3492 ab196087 * Loop through the symbol tables entries. 1891 3492 ab196087 */ 1892 3492 ab196087 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1893 3492 ab196087 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), state.secname); 1894 3492 ab196087 Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 1895 3492 ab196087 1896 3492 ab196087 for (symcnt = 0; symcnt < state.symn; symcnt++) 1897 4832 rie output_symbol(&state, symcnt, shdr->sh_info, symcnt, 1898 3492 ab196087 state.sym + symcnt); 1899 3492 ab196087 } 1900 3492 ab196087 } 1901 3492 ab196087 1902 3492 ab196087 /* 1903 3492 ab196087 * Search for and process any SHT_SUNW_symsort or SHT_SUNW_tlssort sections. 1904 3492 ab196087 * These sections are always associated with the .SUNW_ldynsym./.dynsym pair. 1905 3492 ab196087 */ 1906 3492 ab196087 static void 1907 9273 Ali sunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi, 1908 9273 Ali VERSYM_STATE *versym, const char *file, uint_t flags) 1909 3492 ab196087 { 1910 3492 ab196087 SYMTBL_STATE ldynsym_state, dynsym_state; 1911 3492 ab196087 Cache *sortcache, *symcache; 1912 3492 ab196087 Shdr *sortshdr, *symshdr; 1913 3492 ab196087 Word sortsecndx, symsecndx; 1914 3492 ab196087 Word ldynsym_cnt; 1915 3492 ab196087 Word *ndx; 1916 3492 ab196087 Word ndxn; 1917 3492 ab196087 int output_cnt = 0; 1918 4734 ab196087 Conv_inv_buf_t inv_buf; 1919 3492 ab196087 1920 3492 ab196087 for (sortsecndx = 1; sortsecndx < shnum; sortsecndx++) { 1921 3492 ab196087 1922 3492 ab196087 sortcache = &cache[sortsecndx]; 1923 3492 ab196087 sortshdr = sortcache->c_shdr; 1924 3492 ab196087 1925 3492 ab196087 if ((sortshdr->sh_type != SHT_SUNW_symsort) && 1926 3492 ab196087 (sortshdr->sh_type != SHT_SUNW_tlssort)) 1927 3492 ab196087 continue; 1928 5411 ab196087 if (!match(MATCH_F_ALL, sortcache->c_name, sortsecndx, 1929 5411 ab196087 sortshdr->sh_type)) 1930 0 stevel continue; 1931 0 stevel 1932 0 stevel /* 1933 3492 ab196087 * If the section references a SUNW_ldynsym, then we 1934 3492 ab196087 * expect to see the associated .dynsym immediately 1935 3492 ab196087 * following. If it references a .dynsym, there is no 1936 3492 ab196087 * SUNW_ldynsym. If it is any other type, then we don't 1937 3492 ab196087 * know what to do with it. 1938 0 stevel */ 1939 3492 ab196087 if ((sortshdr->sh_link == 0) || (sortshdr->sh_link >= shnum)) { 1940 3492 ab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), 1941 3492 ab196087 file, sortcache->c_name, 1942 3492 ab196087 EC_WORD(sortshdr->sh_link)); 1943 0 stevel continue; 1944 0 stevel } 1945 3492 ab196087 symcache = &cache[sortshdr->sh_link]; 1946 3492 ab196087 symshdr = symcache->c_shdr; 1947 3492 ab196087 symsecndx = sortshdr->sh_link; 1948 3492 ab196087 ldynsym_cnt = 0; 1949 3492 ab196087 switch (symshdr->sh_type) { 1950 3492 ab196087 case SHT_SUNW_LDYNSYM: 1951 3492 ab196087 if (!init_symtbl_state(&ldynsym_state, cache, shnum, 1952 9273 Ali symsecndx, ehdr, osabi, versym, file, flags)) 1953 3492 ab196087 continue; 1954 3492 ab196087 ldynsym_cnt = ldynsym_state.symn; 1955 3492 ab196087 /* 1956 3492 ab196087 * We know that the dynsym follows immediately 1957 3492 ab196087 * after the SUNW_ldynsym, and so, should be at 1958 3492 ab196087 * (sortshdr->sh_link + 1). However, elfdump is a 1959 3492 ab196087 * diagnostic tool, so we do the full paranoid 1960 3492 ab196087 * search instead. 1961 3492 ab196087 */ 1962 3492 ab196087 for (symsecndx = 1; symsecndx < shnum; symsecndx++) { 1963 3492 ab196087 symcache = &cache[symsecndx]; 1964 3492 ab196087 symshdr = symcache->c_shdr; 1965 3492 ab196087 if (symshdr->sh_type == SHT_DYNSYM) 1966 3492 ab196087 break; 1967 3492 ab196087 } 1968 3492 ab196087 if (symsecndx >= shnum) { /* Dynsym not found! */ 1969 3492 ab196087 (void) fprintf(stderr, 1970 3492 ab196087 MSG_INTL(MSG_ERR_NODYNSYM), 1971 3492 ab196087 file, sortcache->c_name); 1972 3492 ab196087 continue; 1973 3492 ab196087 } 1974 3492 ab196087 /* Fallthrough to process associated dynsym */ 1975 7463 Rod /* FALLTHROUGH */ 1976 3492 ab196087 case SHT_DYNSYM: 1977 3492 ab196087 if (!init_symtbl_state(&dynsym_state, cache, shnum, 1978 9273 Ali symsecndx, ehdr, osabi, versym, file, flags)) 1979 3492 ab196087 continue; 1980 3492 ab196087 break; 1981 3492 ab196087 default: 1982 3492 ab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADNDXSEC), 1983 9273 Ali file, sortcache->c_name, 1984 9273 Ali conv_sec_type(osabi, ehdr->e_machine, 1985 9273 Ali symshdr->sh_type, 0, &inv_buf)); 1986 0 stevel continue; 1987 0 stevel } 1988 0 stevel 1989 0 stevel /* 1990 3492 ab196087 * Output header 1991 0 stevel */ 1992 3492 ab196087 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 1993 3492 ab196087 if (ldynsym_cnt > 0) { 1994 3492 ab196087 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT2), 1995 3492 ab196087 sortcache->c_name, ldynsym_state.secname, 1996 3492 ab196087 dynsym_state.secname); 1997 3492 ab196087 /* 1998 3492 ab196087 * The data for .SUNW_ldynsym and dynsym sections 1999 3492 ab196087 * is supposed to be adjacent with SUNW_ldynsym coming 2000 3492 ab196087 * first. Check, and issue a warning if it isn't so. 2001 3492 ab196087 */ 2002 4665 ab196087 if (((ldynsym_state.sym + ldynsym_state.symn) 2003 4665 ab196087 != dynsym_state.sym) && 2004 5411 ab196087 ((flags & FLG_CTL_FAKESHDR) == 0)) 2005 3492 ab196087 (void) fprintf(stderr, 2006 3492 ab196087 MSG_INTL(MSG_ERR_LDYNNOTADJ), file, 2007 3492 ab196087 ldynsym_state.secname, 2008 3492 ab196087 dynsym_state.secname); 2009 3492 ab196087 } else { 2010 3492 ab196087 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT1), 2011 3492 ab196087 sortcache->c_name, dynsym_state.secname); 2012 3492 ab196087 } 2013 3492 ab196087 Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 2014 3492 ab196087 2015 3492 ab196087 /* If not first one, insert a line of whitespace */ 2016 3492 ab196087 if (output_cnt++ > 0) 2017 3492 ab196087 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2018 0 stevel 2019 0 stevel /* 2020 3492 ab196087 * SUNW_dynsymsort and SUNW_dyntlssort are arrays of 2021 3492 ab196087 * symbol indices. Iterate over the array entries, 2022 3492 ab196087 * dispaying the referenced symbols. 2023 0 stevel */ 2024 3492 ab196087 ndxn = sortshdr->sh_size / sortshdr->sh_entsize; 2025 3492 ab196087 ndx = (Word *)sortcache->c_data->d_buf; 2026 3492 ab196087 for (; ndxn-- > 0; ndx++) { 2027 3492 ab196087 if (*ndx >= ldynsym_cnt) { 2028 3492 ab196087 Word sec_ndx = *ndx - ldynsym_cnt; 2029 0 stevel 2030 4832 rie output_symbol(&dynsym_state, sec_ndx, 0, 2031 3492 ab196087 *ndx, dynsym_state.sym + sec_ndx); 2032 3492 ab196087 } else { 2033 4832 rie output_symbol(&ldynsym_state, *ndx, 0, 2034 3492 ab196087 *ndx, ldynsym_state.sym + *ndx); 2035 0 stevel } 2036 0 stevel } 2037 0 stevel } 2038 0 stevel } 2039 0 stevel 2040 0 stevel /* 2041 0 stevel * Search for and process any relocation sections. 2042 0 stevel */ 2043 0 stevel static void 2044 7463 Rod reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *file) 2045 0 stevel { 2046 1618 rie Word cnt; 2047 0 stevel 2048 0 stevel for (cnt = 1; cnt < shnum; cnt++) { 2049 1618 rie Word type, symnum; 2050 1618 rie Xword relndx, relnum, relsize; 2051 1618 rie void *rels; 2052 1618 rie Sym *syms; 2053 1618 rie Cache *symsec, *strsec; 2054 0 stevel Cache *_cache = &cache[cnt]; 2055 1618 rie Shdr *shdr = _cache->c_shdr; 2056 1618 rie char *relname = _cache->c_name; 2057 4734 ab196087 Conv_inv_buf_t inv_buf; 2058 0 stevel 2059 0 stevel if (((type = shdr->sh_type) != SHT_RELA) && 2060 0 stevel (type != SHT_REL)) 2061 0 stevel continue; 2062 5411 ab196087 if (!match(MATCH_F_ALL, relname, cnt, type)) 2063 0 stevel continue; 2064 0 stevel 2065 0 stevel /* 2066 1618 rie * Decide entry size. 2067 0 stevel */ 2068 1618 rie if (((relsize = shdr->sh_entsize) == 0) || 2069 1618 rie (relsize > shdr->sh_size)) { 2070 0 stevel if (type == SHT_RELA) 2071 1618 rie relsize = sizeof (Rela); 2072 0 stevel else 2073 1618 rie relsize = sizeof (Rel); 2074 0 stevel } 2075 0 stevel 2076 0 stevel /* 2077 0 stevel * Determine the number of relocations available. 2078 0 stevel */ 2079 0 stevel if (shdr->sh_size == 0) { 2080 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2081 1618 rie file, relname); 2082 0 stevel continue; 2083 0 stevel } 2084 3466 rie if (_cache->c_data == NULL) 2085 3466 rie continue; 2086 3466 rie 2087 1618 rie rels = _cache->c_data->d_buf; 2088 1618 rie relnum = shdr->sh_size / relsize; 2089 0 stevel 2090 0 stevel /* 2091 1618 rie * Get the data buffer for the associated symbol table and 2092 1618 rie * string table. 2093 0 stevel */ 2094 1618 rie if (stringtbl(cache, 1, cnt, shnum, file, 2095 1618 rie &symnum, &symsec, &strsec) == 0) 2096 0 stevel continue; 2097 0 stevel 2098 1618 rie syms = symsec->c_data->d_buf; 2099 0 stevel 2100 0 stevel /* 2101 0 stevel * Loop through the relocation entries. 2102 0 stevel */ 2103 1618 rie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2104 1618 rie dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name); 2105 1618 rie Elf_reloc_title(0, ELF_DBG_ELFDUMP, type); 2106 0 stevel 2107 1618 rie for (relndx = 0; relndx < relnum; relndx++, 2108 1618 rie rels = (void *)((char *)rels + relsize)) { 2109 6206 ab196087 Half mach = ehdr->e_machine; 2110 0 stevel char section[BUFSIZ]; 2111 1618 rie const char *symname; 2112 1618 rie Word symndx, reltype; 2113 1618 rie Rela *rela; 2114 1618 rie Rel *rel; 2115 0 stevel 2116 0 stevel /* 2117 1618 rie * Unravel the relocation and determine the symbol with 2118 1618 rie * which this relocation is associated. 2119 0 stevel */ 2120 0 stevel if (type == SHT_RELA) { 2121 1618 rie rela = (Rela *)rels; 2122 1618 rie symndx = ELF_R_SYM(rela->r_info); 2123 6206 ab196087 reltype = ELF_R_TYPE(rela->r_info, mach); 2124 0 stevel } else { 2125 1618 rie rel = (Rel *)rels; 2126 1618 rie symndx = ELF_R_SYM(rel->r_info); 2127 6206 ab196087 reltype = ELF_R_TYPE(rel->r_info, mach); 2128 0 stevel } 2129 0 stevel 2130 1618 rie symname = relsymname(cache, _cache, strsec, symndx, 2131 7463 Rod symnum, relndx, syms, section, BUFSIZ, file); 2132 1618 rie 2133 1618 rie /* 2134 1618 rie * A zero symbol index is only valid for a few 2135 1618 rie * relocations. 2136 1618 rie */ 2137 1618 rie if (symndx == 0) { 2138 1618 rie int badrel = 0; 2139 1618 rie 2140 1618 rie if ((mach == EM_SPARC) || 2141 1618 rie (mach == EM_SPARC32PLUS) || 2142 1618 rie (mach == EM_SPARCV9)) { 2143 1618 rie if ((reltype != R_SPARC_NONE) && 2144 1618 rie (reltype != R_SPARC_REGISTER) && 2145 1618 rie (reltype != R_SPARC_RELATIVE)) 2146 1618 rie badrel++; 2147 1618 rie } else if (mach == EM_386) { 2148 1618 rie if ((reltype != R_386_NONE) && 2149 1618 rie (reltype != R_386_RELATIVE)) 2150 1618 rie badrel++; 2151 1618 rie } else if (mach == EM_AMD64) { 2152 1618 rie if ((reltype != R_AMD64_NONE) && 2153 1618 rie (reltype != R_AMD64_RELATIVE)) 2154 1618 rie badrel++; 2155 1618 rie } 2156 1618 rie 2157 1618 rie if (badrel) { 2158 1618 rie (void) fprintf(stderr, 2159 1618 rie MSG_INTL(MSG_ERR_BADREL1), file, 2160 4734 ab196087 conv_reloc_type(mach, reltype, 2161 4734 ab196087 0, &inv_buf)); 2162 0 stevel } 2163 0 stevel } 2164 0 stevel 2165 1618 rie Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP, 2166 1618 rie MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type, 2167 1618 rie rels, relname, symname, 0); 2168 0 stevel } 2169 0 stevel } 2170 0 stevel } 2171 0 stevel 2172 5230 ab196087 2173 5230 ab196087 /* 2174 5230 ab196087 * This value controls which test dyn_test() performs. 2175 5230 ab196087 */ 2176 5230 ab196087 typedef enum { DYN_TEST_ADDR, DYN_TEST_SIZE, DYN_TEST_ENTSIZE } dyn_test_t; 2177 5230 ab196087 2178 5230 ab196087 /* 2179 5230 ab196087 * Used by dynamic() to compare the value of a dynamic element against 2180 5230 ab196087 * the starting address of the section it references. 2181 5230 ab196087 * 2182 5230 ab196087 * entry: 2183 5230 ab196087 * test_type - Specify which dyn item is being tested. 2184 5230 ab196087 * sh_type - SHT_* type value for required section. 2185 5230 ab196087 * sec_cache - Cache entry for section, or NULL if the object lacks 2186 5230 ab196087 * a section of this type. 2187 5230 ab196087 * dyn - Dyn entry to be tested 2188 5230 ab196087 * dynsec_cnt - # of dynamic section being examined. The first 2189 5230 ab196087 * dynamic section is 1, the next is 2, and so on... 2190 5230 ab196087 * ehdr - ELF header for file 2191 5230 ab196087 * file - Name of file 2192 5230 ab196087 */ 2193 5230 ab196087 static void 2194 5230 ab196087 dyn_test(dyn_test_t test_type, Word sh_type, Cache *sec_cache, Dyn *dyn, 2195 9273 Ali Word dynsec_cnt, Ehdr *ehdr, uchar_t osabi, const char *file) 2196 5230 ab196087 { 2197 5230 ab196087 Conv_inv_buf_t buf1, buf2; 2198 5230 ab196087 2199 5230 ab196087 /* 2200 5230 ab196087 * These tests are based around the implicit assumption that 2201 5230 ab196087 * there is only one dynamic section in an object, and also only 2202 5230 ab196087 * one of the sections it references. We have therefore gathered 2203 5230 ab196087 * all of the necessary information to test this in a single pass 2204 5230 ab196087 * over the section headers, which is very efficient. We are not 2205 5230 ab196087 * aware of any case where more than one dynamic section would 2206 5230 ab196087 * be meaningful in an ELF object, so this is a reasonable solution. 2207 5230 ab196087 * 2208 5230 ab196087 * To test multiple dynamic sections correctly would be more 2209 5230 ab196087 * expensive in code and time. We would have to build a data structure 2210 5230 ab196087 * containing all the dynamic elements. Then, we would use the address 2211 5230 ab196087 * to locate the section it references and ensure the section is of 2212 5230 ab196087 * the right type and that the address in the dynamic element is 2213 5230 ab196087 * to the start of the section. Then, we could check the size and 2214 5230 ab196087 * entsize values against those same sections. This is O(n^2), and 2215 5230 ab196087 * also complicated. 2216 5230 ab196087 * 2217 5230 ab196087 * In the highly unlikely case that there is more than one dynamic 2218 5230 ab196087 * section, we only test the first one, and simply allow the values 2219 5230 ab196087 * of the subsequent one to be displayed unchallenged. 2220 5230 ab196087 */ 2221 5230 ab196087 if (dynsec_cnt != 1) 2222 5230 ab196087 return; 2223 5230 ab196087 2224 5230 ab196087 /* 2225 5230 ab196087 * A DT_ item that references a section address should always find 2226 5230 ab196087 * the section in the file. 2227 5230 ab196087 */ 2228 5230 ab196087 if (sec_cache == NULL) { 2229 6299 ab196087 const char *name; 2230 6299 ab196087 2231 6299 ab196087 /* 2232 6299 ab196087 * Supply section names instead of section types for 2233 6299 ab196087 * things that reference progbits so that the error 2234 6299 ab196087 * message will make more sense. 2235 6299 ab196087 */ 2236 6299 ab196087 switch (dyn->d_tag) { 2237 6299 ab196087 case DT_INIT: 2238 6299 ab196087 name = MSG_ORIG(MSG_ELF_INIT); 2239 6299 ab196087 break; 2240 6299 ab196087 case DT_FINI: 2241 6299 ab196087 name = MSG_ORIG(MSG_ELF_FINI); 2242 6299 ab196087 break; 2243 6299 ab196087 default: 2244 9273 Ali name = conv_sec_type(osabi, ehdr->e_machine, 2245 9273 Ali sh_type, 0, &buf1); 2246 6299 ab196087 break; 2247 6299 ab196087 } 2248 5230 ab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_DYNNOBCKSEC), file, 2249 9273 Ali name, conv_dyn_tag(dyn->d_tag, osabi, ehdr->e_machine, 2250 9273 Ali 0, &buf2)); 2251 5230 ab196087 return; 2252 5230 ab196087 } 2253 5230 ab196087 2254 5230 ab196087 2255 5230 ab196087 switch (test_type) { 2256 5230 ab196087 case DYN_TEST_ADDR: 2257 5230 ab196087 /* The section address should match the DT_ item value */ 2258 5230 ab196087 if (dyn->d_un.d_val != sec_cache->c_shdr->sh_addr) 2259 5230 ab196087 (void) fprintf(stderr, 2260 5230 ab196087 MSG_INTL(MSG_ERR_DYNBADADDR), file, 2261 9273 Ali conv_dyn_tag(dyn->d_tag, osabi, ehdr->e_machine, 2262 9273 Ali 0, &buf1), EC_ADDR(dyn->d_un.d_val), 2263 9273 Ali sec_cache->c_ndx, sec_cache->c_name, 2264 5230 ab196087 EC_ADDR(sec_cache->c_shdr->sh_addr)); 2265 5230 ab196087 break; 2266 5230 ab196087 2267 5230 ab196087 case DYN_TEST_SIZE: 2268 5230 ab196087 /* The section size should match the DT_ item value */ 2269 5230 ab196087 if (dyn->d_un.d_val != sec_cache->c_shdr->sh_size) 2270 5230 ab196087 (void) fprintf(stderr, 2271 5230 ab196087 MSG_INTL(MSG_ERR_DYNBADSIZE), file, 2272 9273 Ali conv_dyn_tag(dyn->d_tag, osabi, ehdr->e_machine, 2273 9273 Ali 0, &buf1), EC_XWORD(dyn->d_un.d_val), 2274 5230 ab196087 sec_cache->c_ndx, sec_cache->c_name, 2275 5230 ab196087 EC_XWORD(sec_cache->c_shdr->sh_size)); 2276 5230 ab196087 break; 2277 5230 ab196087 2278 5230 ab196087 case DYN_TEST_ENTSIZE: 2279 5230 ab196087 /* The sh_entsize value should match the DT_ item value */ 2280 5230 ab196087 if (dyn->d_un.d_val != sec_cache->c_shdr->sh_entsize) 2281 5230 ab196087 (void) fprintf(stderr, 2282 5230 ab196087 MSG_INTL(MSG_ERR_DYNBADENTSIZE), file, 2283 9273 Ali conv_dyn_tag(dyn->d_tag, osabi, ehdr->e_machine, 2284 9273 Ali 0, &buf1), EC_XWORD(dyn->d_un.d_val), 2285 5230 ab196087 sec_cache->c_ndx, sec_cache->c_name, 2286 5230 ab196087 EC_XWORD(sec_cache->c_shdr->sh_entsize)); 2287 5230 ab196087 break; 2288 5230 ab196087 } 2289 5230 ab196087 } 2290 5230 ab196087 2291 5230 ab196087 2292 0 stevel /* 2293 6299 ab196087 * There are some DT_ entries that have corresponding symbols 2294 6299 ab196087 * (e.g. DT_INIT and _init). It is expected that these items will 2295 6299 ab196087 * both have the same value if both are present. This routine 2296 6299 ab196087 * examines the well known symbol tables for such symbols and 2297 6299 ab196087 * issues warnings for any that don't match. 2298 6299 ab196087 * 2299 6299 ab196087 * entry: 2300 6299 ab196087 * dyn - Dyn entry to be tested 2301 6299 ab196087 * symname - Name of symbol that corresponds to dyn 2302 6299 ab196087 * symtab_cache, dynsym_cache, ldynsym_cache - Symbol tables to check 2303 6299 ab196087 * cache - Cache of all section headers 2304 6299 ab196087 * shnum - # of sections in cache 2305 6299 ab196087 * ehdr - ELF header for file 2306 6299 ab196087 * file - Name of file 2307 6299 ab196087 */ 2308 6299 ab196087 static void 2309 6299 ab196087 dyn_symtest(Dyn *dyn, const char *symname, Cache *symtab_cache, 2310 6299 ab196087 Cache *dynsym_cache, Cache *ldynsym_cache, Cache *cache, 2311 9273 Ali Word shnum, Ehdr *ehdr, uchar_t osabi, const char *file) 2312 6299 ab196087 { 2313 6299 ab196087 Conv_inv_buf_t buf; 2314 6299 ab196087 int i; 2315 6299 ab196087 Sym *sym; 2316 6299 ab196087 Cache *_cache; 2317 6299 ab196087 2318 6299 ab196087 for (i = 0; i < 3; i++) { 2319 6299 ab196087 switch (i) { 2320 6299 ab196087 case 0: 2321 6299 ab196087 _cache = symtab_cache; 2322 6299 ab196087 break; 2323 6299 ab196087 case 1: 2324 6299 ab196087 _cache = dynsym_cache; 2325 6299 ab196087 break; 2326 6299 ab196087 case 2: 2327 6299 ab196087 _cache = ldynsym_cache; 2328 6299 ab196087 break; 2329 6299 ab196087 } 2330 6299 ab196087 2331 6299 ab196087 if ((_cache != NULL) && 2332 6299 ab196087 symlookup(symname, cache, shnum, &sym, _cache, file) && 2333 6299 ab196087 (sym->st_value != dyn->d_un.d_val)) 2334 6299 ab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_DYNSYMVAL), 2335 9273 Ali file, _cache->c_name, conv_dyn_tag(dyn->d_tag, 2336 9273 Ali osabi, ehdr->e_machine, 0, &buf), 2337 6299 ab196087 symname, EC_ADDR(sym->st_value)); 2338 6299 ab196087 } 2339 6299 ab196087 } 2340 6299 ab196087 2341 6299 ab196087 2342 6299 ab196087 /* 2343 0 stevel * Search for and process a .dynamic section. 2344 0 stevel */ 2345 0 stevel static void 2346 9273 Ali dynamic(Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi, const char *file) 2347 0 stevel { 2348 5230 ab196087 struct { 2349 6299 ab196087 Cache *symtab; 2350 5230 ab196087 Cache *dynstr; 2351 5230 ab196087 Cache *dynsym; 2352 5230 ab196087 Cache *hash; 2353 5230 ab196087 Cache *fini; 2354 5230 ab196087 Cache *fini_array; 2355 5230 ab196087 Cache *init; 2356 5230 ab196087 Cache *init_array; 2357 5230 ab196087 Cache *preinit_array; 2358 5230 ab196087 Cache *rel; 2359 5230 ab196087 Cache *rela; 2360 5230 ab196087 Cache *sunw_cap; 2361 5230 ab196087 Cache *sunw_ldynsym; 2362 5230 ab196087 Cache *sunw_move; 2363 5230 ab196087 Cache *sunw_syminfo; 2364 5230 ab196087 Cache *sunw_symsort; 2365 5230 ab196087 Cache *sunw_tlssort; 2366 5230 ab196087 Cache *sunw_verdef; 2367 5230 ab196087 Cache *sunw_verneed; 2368 5230 ab196087 Cache *sunw_versym; 2369 5230 ab196087 } sec; 2370 5230 ab196087 Word dynsec_ndx; 2371 5230 ab196087 Word dynsec_num; 2372 5230 ab196087 int dynsec_cnt; 2373 1618 rie Word cnt; 2374 9273 Ali int osabi_solaris = osabi == ELFOSABI_SOLARIS; 2375 0 stevel 2376 5230 ab196087 /* 2377 5230 ab196087 * Make a pass over all the sections, gathering section information 2378 5230 ab196087 * we'll need below. 2379 5230 ab196087 */ 2380 5230 ab196087 dynsec_num = 0; 2381 5230 ab196087 bzero(&sec, sizeof (sec)); 2382 0 stevel for (cnt = 1; cnt < shnum; cnt++) { 2383 5230 ab196087 Cache *_cache = &cache[cnt]; 2384 5230 ab196087 2385 5230 ab196087 switch (_cache->c_shdr->sh_type) { 2386 5230 ab196087 case SHT_DYNAMIC: 2387 5230 ab196087 if (dynsec_num == 0) { 2388 5230 ab196087 dynsec_ndx = cnt; 2389 5230 ab196087 2390 5230 ab196087 /* Does it have a valid string table? */ 2391 5230 ab196087 (void) stringtbl(cache, 0, cnt, shnum, file, 2392 5230 ab196087 0, 0, &sec.dynstr); 2393 5230 ab196087 } 2394 5230 ab196087 dynsec_num++; 2395 5230 ab196087 break; 2396 5230 ab196087 2397 5230 ab196087 2398 5230 ab196087 case SHT_PROGBITS: 2399 5230 ab196087 /* 2400 5230 ab196087 * We want to detect the .init and .fini sections, 2401 5230 ab196087 * if present. These are SHT_PROGBITS, so all we 2402 5230 ab196087 * have to go on is the section name. Normally comparing 2403 5230 ab196087 * names is a bad idea, but there are some special 2404 5230 ab196087 * names (i.e. .init/.fini/.interp) that are very 2405 5230 ab196087 * difficult to use in any other context, and for 2406 5230 ab196087 * these symbols, we do the heuristic match. 2407 5230 ab196087 */ 2408 5230 ab196087 if (strcmp(_cache->c_name, 2409 5230 ab196087 MSG_ORIG(MSG_ELF_INIT)) == 0) { 2410 5230 ab196087 if (sec.init == NULL) 2411 5230 ab196087 sec.init = _cache; 2412 5230 ab196087 } else if (strcmp(_cache->c_name, 2413 5230 ab196087 MSG_ORIG(MSG_ELF_FINI)) == 0) { 2414 5230 ab196087 if (sec.fini == NULL) 2415 5230 ab196087 sec.fini = _cache; 2416 5230 ab196087 } 2417 5230 ab196087 break; 2418 5230 ab196087 2419 5230 ab196087 case SHT_REL: 2420 5230 ab196087 /* 2421 5230 ab196087 * We want the SHT_REL section with the lowest 2422 5230 ab196087 * offset. The linker gathers them together, 2423 5230 ab196087 * and puts the address of the first one 2424 5230 ab196087 * into the DT_REL dynamic element. 2425 5230 ab196087 */ 2426 5230 ab196087 if ((sec.rel == NULL) || 2427 5230 ab196087 (_cache->c_shdr->sh_offset < 2428 5230 ab196087 sec.rel->c_shdr->sh_offset)) 2429 5230 ab196087 sec.rel = _cache; 2430 5230 ab196087 break; 2431 5230 ab196087 2432 5230 ab196087 case SHT_RELA: 2433 5230 ab196087 /* RELA is handled just like RELA above */ 2434 5230 ab196087 if ((sec.rela == NULL) || 2435 5230 ab196087 (_cache->c_shdr->sh_offset < 2436 5230 ab196087 sec.rela->c_shdr->sh_offset)) 2437 5230 ab196087 sec.rela = _cache; 2438 5230 ab196087 break; 2439 5230 ab196087 2440 5230 ab196087 /* 2441 5230 ab196087 * The GRAB macro is used for the simple case in which 2442 5230 ab196087 * we simply grab the first section of the desired type. 2443 5230 ab196087 */ 2444 5230 ab196087 #define GRAB(_sec_type, _sec_field) \ 2445 5230 ab196087 case _sec_type: \ 2446 5230 ab196087 if (sec._sec_field == NULL) \ 2447 5230 ab196087 sec._sec_field = _cache; \ 2448 5230 ab196087 break 2449 6299 ab196087 GRAB(SHT_SYMTAB, symtab); 2450 5230 ab196087 GRAB(SHT_DYNSYM, dynsym); 2451 5230 ab196087 GRAB(SHT_FINI_ARRAY, fini_array); 2452 5230 ab196087 GRAB(SHT_HASH, hash); 2453 5230 ab196087 GRAB(SHT_INIT_ARRAY, init_array); 2454 5230 ab196087 GRAB(SHT_SUNW_move, sunw_move); 2455 5230 ab196087 GRAB(SHT_PREINIT_ARRAY, preinit_array); 2456 5230 ab196087 GRAB(SHT_SUNW_cap, sunw_cap); 2457 5230 ab196087 GRAB(SHT_SUNW_LDYNSYM, sunw_ldynsym); 2458 5230 ab196087 GRAB(SHT_SUNW_syminfo, sunw_syminfo); 2459 5230 ab196087 GRAB(SHT_SUNW_symsort, sunw_symsort); 2460 5230 ab196087 GRAB(SHT_SUNW_tlssort, sunw_tlssort); 2461 5230 ab196087 GRAB(SHT_SUNW_verdef, sunw_verdef); 2462 5230 ab196087 GRAB(SHT_SUNW_verneed, sunw_verneed); 2463 5230 ab196087 GRAB(SHT_SUNW_versym, sunw_versym); 2464 5230 ab196087 #undef GRAB 2465 5230 ab196087 } 2466 5230 ab196087 } 2467 5230 ab196087 2468 5230 ab196087 /* 2469 5230 ab196087 * If no dynamic section, return immediately. If more than one 2470 5230 ab196087 * dynamic section, then something odd is going on and an error 2471 5230 ab196087 * is in order, but then continue on and display them all. 2472 5230 ab196087 */ 2473 5230 ab196087 if (dynsec_num == 0) 2474 5230 ab196087 return; 2475 5230 ab196087 if (dynsec_num > 1) 2476 5230 ab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MULTDYN), 2477 5230 ab196087 file, EC_WORD(dynsec_num)); 2478 5230 ab196087 2479 5230 ab196087 2480 5230 ab196087 dynsec_cnt = 0; 2481 5230 ab196087 for (cnt = dynsec_ndx; (cnt < shnum) && (dynsec_cnt < dynsec_num); 2482 5230 ab196087 cnt++) { 2483 1618 rie Dyn *dyn; 2484 1618 rie ulong_t numdyn; 2485 3850 ab196087 int ndx, end_ndx; 2486 1618 rie Cache *_cache = &cache[cnt], *strsec; 2487 1618 rie Shdr *shdr = _cache->c_shdr; 2488 5230 ab196087 int dumped = 0; 2489 0 stevel 2490 0 stevel if (shdr->sh_type != SHT_DYNAMIC) 2491 0 stevel continue; 2492 5230 ab196087 dynsec_cnt++; 2493 0 stevel 2494 0 stevel /* 2495 1618 rie * Verify the associated string table section. 2496 0 stevel */ 2497 1618 rie if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0) 2498 0 stevel continue; 2499 1618 rie 2500 3466 rie if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 2501 3466 rie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2502 3466 rie file, _cache->c_name); 2503 3466 rie continue; 2504 3466 rie } 2505 3466 rie if (_cache->c_data == NULL) 2506 3466 rie continue; 2507 3466 rie 2508 0 stevel numdyn = shdr->sh_size / shdr->sh_entsize; 2509 1618 rie dyn = (Dyn *)_cache->c_data->d_buf; 2510 0 stevel 2511 5230 ab196087 /* 2512 5230 ab196087 * We expect the REL/RELA entries to reference the reloc 2513 5230 ab196087 * section with the lowest address. However, this is 2514 5230 ab196087 * not true for dumped objects. Detect if this object has 2515 5230 ab196087 * been dumped so that we can skip the reloc address test 2516 5230 ab196087 * in that case. 2517 5230 ab196087 */ 2518 5230 ab196087 for (ndx = 0; ndx < numdyn; dyn++, ndx++) { 2519 5230 ab196087 if (dyn->d_tag == DT_FLAGS_1) { 2520 5230 ab196087 dumped = (dyn->d_un.d_val & DF_1_CONFALT) != 0; 2521 5230 ab196087 break; 2522 5230 ab196087 } 2523 5230 ab196087 } 2524 5230 ab196087 dyn = (Dyn *)_cache->c_data->d_buf; 2525 5230 ab196087 2526 1618 rie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2527 1618 rie dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name); 2528 0 stevel 2529 1618 rie Elf_dyn_title(0); 2530 0 stevel 2531 1618 rie for (ndx = 0; ndx < numdyn; dyn++, ndx++) { 2532 4734 ab196087 union { 2533 6206 ab196087 Conv_inv_buf_t inv; 2534 4734 ab196087 Conv_dyn_flag_buf_t flag; 2535 4734 ab196087 Conv_dyn_flag1_buf_t flag1; 2536 4734 ab196087 Conv_dyn_posflag1_buf_t posflag1; 2537 4734 ab196087 Conv_dyn_feature1_buf_t feature1; 2538 4734 ab196087 } c_buf; 2539 5230 ab196087 const char *name = NULL; 2540 0 stevel 2541 0 stevel /* 2542 0 stevel * Print the information numerically, and if possible 2543 5230 ab196087 * as a string. If a string is available, name is 2544 5230 ab196087 * set to reference it. 2545 5230 ab196087 * 2546 5230 ab196087 * Also, take this opportunity to sanity check 2547 5230 ab196087 * the values of DT elements. In the code above, 2548 5230 ab196087 * we gathered information on sections that are 2549 5230 ab196087 * referenced by the dynamic section. Here, we 2550 5230 ab196087 * compare the attributes of those sections to 2551 5230 ab196087 * the DT_ items that reference them and report 2552 5230 ab196087 * on inconsistencies. 2553 5230 ab196087 * 2554 5230 ab196087 * Things not currently tested that could be improved 2555 5230 ab196087 * in later revisions include: 2556 5230 ab196087 * - We don't check PLT or GOT related items 2557 5230 ab196087 * - We don't handle computing the lengths of 2558 5230 ab196087 * relocation arrays. To handle this 2559 5230 ab196087 * requires examining data that spans 2560 5230 ab196087 * across sections, in a contiguous span 2561 5230 ab196087 * within a single segment. 2562 5230 ab196087 * - DT_VERDEFNUM and DT_VERNEEDNUM can't be 2563 5230 ab196087 * verified without parsing the sections. 2564 5230 ab196087 * - We don't handle DT_SUNW_SYMSZ, which would 2565 5230 ab196087 * be the sum of the lengths of .dynsym and 2566 5230 ab196087 * .SUNW_ldynsym 2567 5230 ab196087 * - DT_SUNW_STRPAD can't be verified other than 2568 5230 ab196087 * to check that it's not larger than 2569 5230 ab196087 * the string table. 2570 5230 ab196087 * - Some items come in "all or none" clusters 2571 5230 ab196087 * that give an address, element size, 2572 5230 ab196087 * and data length in bytes. We don't 2573 5230 ab196087 * verify that there are no missing items 2574 5230 ab196087 * in such groups. 2575 0 stevel */ 2576 3850 ab196087 switch (dyn->d_tag) { 2577 3850 ab196087 case DT_NULL: 2578 3850 ab196087 /* 2579 3850 ab196087 * Special case: DT_NULLs can come in groups 2580 3850 ab196087 * that we prefer to reduce to a single line. 2581 3850 ab196087 */ 2582 3850 ab196087 end_ndx = ndx; 2583 3850 ab196087 while ((end_ndx < (numdyn - 1)) && 2584 4433 ab196087 ((dyn + 1)->d_tag == DT_NULL)) { 2585 3850 ab196087 dyn++; 2586 3850 ab196087 end_ndx++; 2587 3850 ab196087 } 2588 3850 ab196087 Elf_dyn_null_entry(0, dyn, ndx, end_ndx); 2589 3850 ab196087 ndx = end_ndx; 2590 3850 ab196087 continue; 2591 3850 ab196087 2592 3850 ab196087 /* 2593 5230 ab196087 * String items all reference the dynstr. The string() 2594 5230 ab196087 * function does the necessary sanity checking. 2595 3850 ab196087 */ 2596 3850 ab196087 case DT_NEEDED: 2597 3850 ab196087 case DT_SONAME: 2598 3850 ab196087 case DT_FILTER: 2599 3850 ab196087 case DT_AUXILIARY: 2600 3850 ab196087 case DT_CONFIG: 2601 3850 ab196087 case DT_RPATH: 2602 3850 ab196087 case DT_RUNPATH: 2603 3850 ab196087 case DT_USED: 2604 3850 ab196087 case DT_DEPAUDIT: 2605 3850 ab196087 case DT_AUDIT: 2606 9273 Ali name = string(_cache, ndx, strsec, 2607 9273 Ali file, dyn->d_un.d_ptr); 2608 9273 Ali break; 2609 9273 Ali 2610 3850 ab196087 case DT_SUNW_AUXILIARY: 2611 3850 ab196087 case DT_SUNW_FILTER: 2612 9273 Ali if (osabi_solaris) 2613 9273 Ali name = string(_cache, ndx, strsec, 2614 9273 Ali file, dyn->d_un.d_ptr); 2615 3850 ab196087 break; 2616 3850 ab196087 2617 3850 ab196087 case DT_FLAGS: 2618 4734 ab196087 name = conv_dyn_flag(dyn->d_un.d_val, 2619 4734 ab196087 0, &c_buf.flag); 2620 3850 ab196087 break; 2621 3850 ab196087 case DT_FLAGS_1: 2622 5088 ab196087 name = conv_dyn_flag1(dyn->d_un.d_val, 0, 2623 4734 ab196087 &c_buf.flag1); 2624 3850 ab196087 break; 2625 3850 ab196087 case DT_POSFLAG_1: 2626 4734 ab196087 name = conv_dyn_posflag1(dyn->d_un.d_val, 0, 2627 4734 ab196087 &c_buf.posflag1); 2628 3850 ab196087 break; 2629 3850 ab196087 case DT_FEATURE_1: 2630 4734 ab196087 name = conv_dyn_feature1(dyn->d_un.d_val, 0, 2631 4734 ab196087 &c_buf.feature1); 2632 3850 ab196087 break; 2633 3850 ab196087 case DT_DEPRECATED_SPARC_REGISTER: 2634 1618 rie name = MSG_INTL(MSG_STR_DEPRECATED); 2635 6206 ab196087 break; 2636 6206 ab196087 2637 6206 ab196087 case DT_SUNW_LDMACH: 2638 9273 Ali if (!osabi_solaris) 2639 9273 Ali break; 2640 9273 Ali name = conv_ehdr_mach((Half)dyn->d_un.d_val, 2641 9273 Ali 0, &c_buf.inv); 2642 3850 ab196087 break; 2643 5230 ab196087 2644 5230 ab196087 /* 2645 5230 ab196087 * Cases below this point are strictly sanity checking, 2646 5230 ab196087 * and do not generate a name string. The TEST_ macros 2647 5230 ab196087 * are used to hide the boilerplate arguments neeeded 2648 5230 ab196087 * by dyn_test(). 2649 5230 ab196087 */ 2650 5230 ab196087 #define TEST_ADDR(_sh_type, _sec_field) \ 2651 5230 ab196087 dyn_test(DYN_TEST_ADDR, _sh_type, \ 2652 9273 Ali sec._sec_field, dyn, dynsec_cnt, ehdr, \ 2653 9273 Ali osabi, file) 2654 5230 ab196087 #define TEST_SIZE(_sh_type, _sec_field) \ 2655 5230 ab196087 dyn_test(DYN_TEST_SIZE, _sh_type, \ 2656 9273 Ali sec._sec_field, dyn, dynsec_cnt, ehdr, \ 2657 9273 Ali osabi, file) 2658 5230 ab196087 #define TEST_ENTSIZE(_sh_type, _sec_field) \ 2659 5230 ab196087 dyn_test(DYN_TEST_ENTSIZE, _sh_type, \ 2660 9273 Ali sec._sec_field, dyn, dynsec_cnt, ehdr, \ 2661 9273 Ali osabi, file) 2662 5230 ab196087 2663 5230 ab196087 case DT_FINI: 2664 6299 ab196087 dyn_symtest(dyn, MSG_ORIG(MSG_SYM_FINI), 2665 6299 ab196087 sec.symtab, sec.dynsym, sec.sunw_ldynsym, 2666 9273 Ali cache, shnum, ehdr, osabi, file); 2667 5230 ab196087 TEST_ADDR(SHT_PROGBITS, fini); 2668 3850 ab196087 break; 2669 5230 ab196087 2670 5230 ab196087 case DT_FINI_ARRAY: 2671 5230 ab196087 TEST_ADDR(SHT_FINI_ARRAY, fini_array); 2672 5230 ab196087 break; 2673 5230 ab196087 2674 5230 ab196087 case DT_FINI_ARRAYSZ: 2675 5230 ab196087 TEST_SIZE(SHT_FINI_ARRAY, fini_array); 2676 5230 ab196087 break; 2677 5230 ab196087 2678 5230 ab196087 case DT_HASH: 2679 5230 ab196087 TEST_ADDR(SHT_HASH, hash); 2680 5230 ab196087 break; 2681 5230 ab196087 2682 5230 ab196087 case DT_INIT: 2683 6299 ab196087 dyn_symtest(dyn, MSG_ORIG(MSG_SYM_INIT), 2684 6299 ab196087 sec.symtab, sec.dynsym, sec.sunw_ldynsym, 2685 9273 Ali cache, shnum, ehdr, osabi, file); 2686 5230 ab196087 TEST_ADDR(SHT_PROGBITS, init); 2687 5230 ab196087 break; 2688 5230 ab196087 2689 5230 ab196087 case DT_INIT_ARRAY: 2690 5230 ab196087 TEST_ADDR(SHT_INIT_ARRAY, init_array); 2691 5230 ab196087 break; 2692 5230 ab196087 2693 5230 ab196087 case DT_INIT_ARRAYSZ: 2694 5230 ab196087 TEST_SIZE(SHT_INIT_ARRAY, init_array); 2695 5230 ab196087 break; 2696 5230 ab196087 2697 5230 ab196087 case DT_MOVEENT: 2698 5230 ab196087 TEST_ENTSIZE(SHT_SUNW_move, sunw_move); 2699 5230 ab196087 break; 2700 5230 ab196087 2701 5230 ab196087 case DT_MOVESZ: 2702 5230 ab196087 TEST_SIZE(SHT_SUNW_move, sunw_move); 2703 5230 ab196087 break; 2704 5230 ab196087 2705 5230 ab196087 case DT_MOVETAB: 2706 5230 ab196087 TEST_ADDR(SHT_SUNW_move, sunw_move); 2707 5230 ab196087 break; 2708 5230 ab196087 2709 5230 ab196087 case DT_PREINIT_ARRAY: 2710 5230 ab196087 TEST_ADDR(SHT_PREINIT_ARRAY, preinit_array); 2711 5230 ab196087 break; 2712 5230 ab196087 2713 5230 ab196087 case DT_PREINIT_ARRAYSZ: 2714 5230 ab196087 TEST_SIZE(SHT_PREINIT_ARRAY, preinit_array); 2715 5230 ab196087 break; 2716 5230 ab196087 2717 5230 ab196087 case DT_REL: 2718 5230 ab196087 if (!dumped) 2719 5230 ab196087 TEST_ADDR(SHT_REL, rel); 2720 5230 ab196087 break; 2721 5230 ab196087 2722 5230 ab196087 case DT_RELENT: 2723 5230 ab196087 TEST_ENTSIZE(SHT_REL, rel); 2724 5230 ab196087 break; 2725 5230 ab196087 2726 5230 ab196087 case DT_RELA: 2727 5230 ab196087 if (!dumped) 2728 5230 ab196087 TEST_ADDR(SHT_RELA, rela); 2729 5230 ab196087 break; 2730 5230 ab196087 2731 5230 ab196087 case DT_RELAENT: 2732 5230 ab196087 TEST_ENTSIZE(SHT_RELA, rela); 2733 5230 ab196087 break; 2734 5230 ab196087 2735 5230 ab196087 case DT_STRTAB: 2736 5230 ab196087 TEST_ADDR(SHT_STRTAB, dynstr); 2737 5230 ab196087 break; 2738 5230 ab196087 2739 5230 ab196087 case DT_STRSZ: 2740 5230 ab196087 TEST_SIZE(SHT_STRTAB, dynstr); 2741 5230 ab196087 break; 2742 5230 ab196087 2743 5230 ab196087 case DT_SUNW_CAP: 2744 5230 ab196087 TEST_ADDR(SHT_SUNW_cap, sunw_cap); 2745 5230 ab196087 break; 2746 5230 ab196087 2747 5230 ab196087 case DT_SUNW_SYMTAB: 2748 5230 ab196087 TEST_ADDR(SHT_SUNW_LDYNSYM, sunw_ldynsym); 2749 5230 ab196087 break; 2750 5230 ab196087 2751 5230 ab196087 case DT_SYMENT: 2752 5230 ab196087 TEST_ENTSIZE(SHT_DYNSYM, dynsym); 2753 5230 ab196087 break; 2754 5230 ab196087 2755 5230 ab196087 case DT_SYMINENT: 2756 5230 ab196087 TEST_ENTSIZE(SHT_SUNW_syminfo, sunw_syminfo); 2757 5230 ab196087 break; 2758 5230 ab196087 2759 5230 ab196087 case DT_SYMINFO: 2760 5230 ab196087 TEST_ADDR(SHT_SUNW_syminfo, sunw_syminfo); 2761 5230 ab196087 break; 2762 5230 ab196087 2763 5230 ab196087 case DT_SYMINSZ: 2764 5230 ab196087 TEST_SIZE(SHT_SUNW_syminfo, sunw_syminfo); 2765 5230 ab196087 break; 2766 5230 ab196087 2767 5230 ab196087 case DT_SYMTAB: 2768 5230 ab196087 TEST_ADDR(SHT_DYNSYM, dynsym); 2769 5230 ab196087 break; 2770 5230 ab196087 2771 5230 ab196087 case DT_SUNW_SORTENT: 2772 5230 ab196087 /* 2773 5230 ab196087 * This entry is related to both the symsort and 2774 5230 ab196087 * tlssort sections. 2775 5230 ab196087 */ 2776 9273 Ali if (osabi_solaris) { 2777 5230 ab196087 int test_tls = 2778 5230 ab196087 (sec.sunw_tlssort != NULL); 2779 5230 ab196087 int test_sym = 2780 5230 ab196087 (sec.sunw_symsort != NULL) || 2781 5230 ab196087 !test_tls; 2782 5230 ab196087 if (test_sym) 2783 5230 ab196087 TEST_ENTSIZE(SHT_SUNW_symsort, 2784 5230 ab196087 sunw_symsort); 2785 5230 ab196087 if (test_tls) 2786 5230 ab196087 TEST_ENTSIZE(SHT_SUNW_tlssort, 2787 5230 ab196087 sunw_tlssort); 2788 5230 ab196087 } 2789 5230 ab196087 break; 2790 5230 ab196087 2791 5230 ab196087 2792 5230 ab196087 case DT_SUNW_SYMSORT: 2793 9273 Ali if (osabi_solaris) 2794 9273 Ali TEST_ADDR(SHT_SUNW_symsort, 2795 9273 Ali sunw_symsort); 2796 5230 ab196087 break; 2797 5230 ab196087 2798 5230 ab196087 case DT_SUNW_SYMSORTSZ: 2799 9273 Ali if (osabi_solaris) 2800 9273 Ali TEST_SIZE(SHT_SUNW_symsort, 2801 9273 Ali sunw_symsort); 2802 5230 ab196087 break; 2803 5230 ab196087 2804 5230 ab196087 case DT_SUNW_TLSSORT: 2805 9273 Ali if (osabi_solaris) 2806 9273 Ali TEST_ADDR(SHT_SUNW_tlssort, 2807 9273 Ali sunw_tlssort); 2808 5230 ab196087 break; 2809 5230 ab196087 2810 5230 ab196087 case DT_SUNW_TLSSORTSZ: 2811 9273 Ali if (osabi_solaris) 2812 9273 Ali TEST_SIZE(SHT_SUNW_tlssort, 2813 9273 Ali sunw_tlssort); 2814 5230 ab196087 break; 2815 5230 ab196087 2816 5230 ab196087 case DT_VERDEF: 2817 5230 ab196087 TEST_ADDR(SHT_SUNW_verdef, sunw_verdef); 2818 5230 ab196087 break; 2819 5230 ab196087 2820 5230 ab196087 case DT_VERNEED: 2821 5230 ab196087 TEST_ADDR(SHT_SUNW_verneed, sunw_verneed); 2822 5230 ab196087 break; 2823 5230 ab196087 2824 5230 ab196087 case DT_VERSYM: 2825 5230 ab196087 TEST_ADDR(SHT_SUNW_versym, sunw_versym); 2826 5230 ab196087 break; 2827 5230 ab196087 #undef TEST_ADDR 2828 5230 ab196087 #undef TEST_SIZE 2829 5230 ab196087 #undef TEST_ENTSIZE 2830 3850 ab196087 } 2831 0 stevel 2832 5230 ab196087 if (name == NULL) 2833 5230 ab196087 name = MSG_ORIG(MSG_STR_EMPTY); 2834 9273 Ali Elf_dyn_entry(0, dyn, ndx, name, 2835 9273 Ali osabi, ehdr->e_machine); 2836 0 stevel } 2837 0 stevel } 2838 0 stevel } 2839 0 stevel 2840 0 stevel /* 2841 0 stevel * Search for and process a MOVE section. 2842 0 stevel */ 2843 0 stevel static void 2844 4168 ab196087 move(Cache *cache, Word shnum, const char *file, uint_t flags) 2845 0 stevel { 2846 1618 rie Word cnt; 2847 9085 Ali const char *fmt = NULL; 2848 0 stevel 2849 0 stevel for (cnt = 1; cnt < shnum; cnt++) { 2850 1618 rie Word movenum, symnum, ndx; 2851 1618 rie Sym *syms; 2852 1618 rie Cache *_cache = &cache[cnt]; 2853 1618 rie Shdr *shdr = _cache->c_shdr; 2854 1618 rie Cache *symsec, *strsec; 2855 1618 rie Move *move; 2856 0 stevel 2857 0 stevel if (shdr->sh_type != SHT_SUNW_move) 2858 0 stevel continue; 2859 5411 ab196087 if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type)) 2860 0 stevel continue; 2861 0 stevel 2862 0 stevel /* 2863 0 stevel * Determine the move data and number. 2864 0 stevel */ 2865 0 stevel if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { 2866 0 stevel (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), 2867 0 stevel file, _cache->c_name); 2868 0 stevel continue; 2869 0 stevel } 2870 3466 rie if (_cache->c_data == NULL) 2871 3466 rie continue; 2872 3466 rie 2873 1618 rie move = (Move *)_cache->c_data->d_buf; 2874 1618 rie movenum = shdr->sh_size / shdr->sh_entsize; 2875 0 stevel 2876 0 stevel /* 2877 1618 rie * Get the data buffer for the associated symbol table and 2878 1618 rie * string table. 2879 0 stevel */ 2880 1618 rie if (stringtbl(cache, 1, cnt, shnum, file, 2881 1618 rie &symnum, &symsec, &strsec) == 0) 2882 1618 rie return; 2883 0 stevel 2884 1618 rie syms = (Sym *)symsec->c_data->d_buf; 2885 0 stevel 2886 1618 rie dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); 2887 1618 rie dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name); 2888 1618 rie dbg_print(0, MSG_INTL(MSG_MOVE_TITLE)); 2889 0 stevel 2890 9085 Ali if (fmt == NULL) 2891 1618 rie fmt = MSG_INTL(MSG_MOVE_ENTRY); 2892 0 stevel 2893 1618 rie for (ndx = 0; ndx < movenum; move++, ndx++) { 2894 1618 rie const char *symname; 2895 1618 rie char index[MAXNDXSIZE], section[BUFSIZ]; 2896 1618 rie Word symndx, shndx; 2897 1618 rie Sym *sym; 2898 0 stevel 2899 0 stevel /* 2900 0 stevel * Check for null entries 2901 0 stevel */ 2902 1618 rie if ((move->m_info == 0) && (move->m_value == 0) && 2903 1618 rie (move->m_poffset == 0) && (move->m_repeat == 0) && 2904 1618 rie (move->m_stride == 0)) { 2905 1618 rie dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY), 2906 1618 rie EC_XWORD(move->m_poffset), 0, 0, 0, 2907 1618 rie EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY)); 2908 0 stevel continue; 2909 0 stevel } 2910 1618 rie if (((symndx = ELF_M_SYM(move->m_info)) == 0) || 2911 1618 rie (symndx >= symnum)) { 2912 0 stevel (void) fprintf(stderr, 2913 0 stevel MSG_INTL(MSG_ERR_BADMINFO), file, 2914 1618 rie _cache->c_name, EC_XWORD(move->m_info)); 2915 1618 rie 2916 1618 rie (void) snprintf(index, MAXNDXSIZE, 2917 1618 rie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 2918 1618 rie dbg_print(0, fmt, index, 2919 1618 rie EC_XWORD(move->m_poffset), 2920 1618 rie ELF_M_SIZE(move->m_info), move->m_repeat, 2921 1618 rie move->m_stride, move->m_value, 2922 0 stevel MSG_INTL(MSG_STR_UNKNOWN)); 2923 0 stevel continue; 2924 0 stevel } 2925 0 stevel 2926 1618 rie symname = relsymname(cache, _cache, strsec, 2927 7463 Rod symndx, symnum, ndx, syms, section, BUFSIZ, file); 2928 1618 rie sym = (Sym *)(syms + symndx); 2929 0 stevel 2930 0 stevel /* 2931 0 stevel * Additional sanity check. 2932 0 stevel */ 2933 1618 rie shndx = sym->st_shndx; 2934 0 stevel if (!((shndx == SHN_COMMON) || 2935 0 stevel (((shndx >= 1) && (shndx <= shnum)) && 2936 1618 rie (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) { 2937 0 stevel (void) fprintf(stderr, 2938 1618 rie MSG_INTL(MSG_ERR_BADSYM2), file, 2939 6206 ab196087 _cache->c_name, EC_WORD(symndx), 2940 6206 ab196087 demangle(symname, flags)); 2941 0 stevel } 2942 0 stevel 2943 1618 rie (void) snprintf(index, MAXNDXSIZE, 2944 1618 rie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx)); 2945 1618 rie dbg_print(0, fmt, index, EC_XWORD(move->m_poffset), 2946 1618 rie ELF_M_SIZE(move->m_info), move->m_repeat, 2947 1618 rie move->m_stride, move->m_value, 2948 1618 rie demangle(symname, flags)); 2949 0 stevel } 2950 0 stevel } 2951 0 stevel } 2952 0 stevel 2953 0 stevel /* 2954 9273 Ali * parse_note_t is used to track the state used by parse_note_entry() 2955 9273 Ali * between calls, and also to return the results of each call. 2956 9273 Ali */ 2957 9273 Ali typedef struct { 2958 9273 Ali /* pns_ fields track progress through the data */ 2959 9273 Ali const char *pns_file; /* File name */ 2960 9273 Ali Cache *pns_cache; /* Note section cache entry */ 2961 9273 Ali size_t pns_size; /* # unprocessed data bytes */ 2962 9273 Ali Word *pns_data; /* # to next unused data byte */ 2963 9273 Ali 2964 9273 Ali /* pn_ fields return the results for a single call */ 2965 9273 Ali Word pn_namesz; /* Value of note namesz field */ 2966 9273 Ali Word pn_descsz; /* Value of note descsz field */ 2967 9273 Ali Word pn_type; /* Value of note type field */ 2968 9273 Ali const char *pn_name; /* if (namesz > 0) ptr to name bytes */ 2969 9273 Ali const char *pn_desc; /* if (descsx > 0) ptr to data bytes */ 2970 9273 Ali } parse_note_t; 2971 9273 Ali 2972 9273 Ali /* 2973 9273 Ali * Extract the various sub-parts of a note entry, and advance the 2974 9273 Ali * data pointer past it. 2975 9273 Ali * 2976 9273 Ali * entry: 2977 9273 Ali * The state pns_ fields contain current values for the Note section 2978 9273 Ali * 2979 9273 Ali * exit: 2980 9273 Ali * On success, True (1) is returned, the state pns_ fields have been 2981 9273 Ali * advanced to point at the start of the next entry, and the information 2982 9273 Ali * for the recovered note entry is found in the state pn_ fields. 2983 9273 Ali * 2984 9273 Ali * On failure, False (0) is returned. The values contained in state 2985 9273 Ali * are undefined. 2986 9273 Ali */ 2987 9273 Ali static int 2988 9273 Ali parse_note_entry(parse_note_t *state) 2989 9273 Ali { 2990 9273 Ali size_t pad, noteoff; 2991 9273 Ali 2992 9273 Ali noteoff = (Word)state->pns_cache->c_data->d_size - state->pns_size; 2993 9273 Ali /* 2994 9273 Ali * Make sure we can at least reference the 3 initial entries 2995 9273 Ali * (4-byte words) of the note information block. 2996 9273 Ali */ 2997 9273 Ali if (state->pns_size >= (sizeof (Word) * 3)) { 2998 9273 Ali state->pns_size -= (sizeof (Word) * 3); 2999 9273 Ali } else { 3000 9273 Ali (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ), 3001 9273 Ali state->pns_file, state->pns_cache->c_name, 3002 9273 Ali EC_WORD(noteoff)); 3003 9273 Ali return (0); 3004 9273 Ali } 3005 9273 Ali 3006 9273 Ali /* 3007 9273 Ali * Make sure any specified name string can be referenced. 3008 9273 Ali */ 3009 9273 Ali if ((state->pn_namesz = *state->pns_data++) != 0) { 3010 9273 Ali if (state->pns_size >= state->pn_namesz) { 3011 9273 Ali state->pns_size -= state->pn_namesz; 3012 9273 Ali } else { 3013 9273 Ali (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADNMSZ), 3014 9273 Ali state->pns_file, state->pns_cache->c_name, 3015 9273 Ali EC_WORD(noteoff), EC_WORD(state->pn_namesz)); 3016 9273 Ali return (0); 3017 9273 Ali } 3018 9273 Ali } 3019 9273 Ali 3020 9273 Ali /* 3021 9273 Ali * Make sure any specified descriptor can be referenced. 3022 9273 Ali */ 3023