Print this page
3265 link-editor builds bogus .eh_frame_hdr on ia32
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/elfdump/common/elfdump.c
+++ new/usr/src/cmd/sgs/elfdump/common/elfdump.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Dump an elf file.
29 29 */
30 30 #include <stddef.h>
31 31 #include <sys/elf_386.h>
32 32 #include <sys/elf_amd64.h>
33 33 #include <sys/elf_SPARC.h>
34 34 #include <_libelf.h>
35 35 #include <dwarf.h>
36 36 #include <stdio.h>
37 37 #include <unistd.h>
38 38 #include <errno.h>
39 39 #include <strings.h>
40 40 #include <debug.h>
41 41 #include <conv.h>
42 42 #include <msg.h>
43 43 #include <_elfdump.h>
44 44
45 45
46 46 /*
47 47 * VERSYM_STATE is used to maintain information about the VERSYM section
48 48 * in the object being analyzed. It is filled in by versions(), and used
49 49 * by init_symtbl_state() when displaying symbol information.
50 50 *
51 51 * There are three forms of symbol versioning known to us:
52 52 *
53 53 * 1) The original form, introduced with Solaris 2.5, in which
54 54 * the Versym contains indexes to Verdef records, and the
55 55 * Versym values for UNDEF symbols resolved by other objects
56 56 * are all set to 0.
57 57 * 2) The GNU form, which is backward compatible with the original
58 58 * Solaris form, but which adds several extensions:
59 59 * - The Versym also contains indexes to Verneed records, recording
60 60 * which object/version contributed the external symbol at
61 61 * link time. These indexes start with the next value following
62 62 * the final Verdef index. The index is written to the previously
63 63 * reserved vna_other field of the ELF Vernaux structure.
64 64 * - The top bit of the Versym value is no longer part of the index,
65 65 * but is used as a "hidden bit" to prevent binding to the symbol.
66 66 * - Multiple implementations of a given symbol, contained in varying
67 67 * versions are allowed, using special assembler pseudo ops,
68 68 * and encoded in the symbol name using '@' characters.
69 69 * 3) Modified Solaris form, in which we adopt the first GNU extension
70 70 * (Versym indexes to Verneed records), but not the others.
71 71 *
72 72 * elfdump can handle any of these cases. The presence of a DT_VERSYM
73 73 * dynamic element indicates a full GNU object. An object that lacks
74 74 * a DT_VERSYM entry, but which has non-zero vna_other fields in the Vernaux
75 75 * structures is a modified Solaris object. An object that has neither of
76 76 * these uses the original form.
77 77 *
78 78 * max_verndx contains the largest version index that can appear
79 79 * in a Versym entry. This can never be less than 1: In the case where
80 80 * there is no verdef/verneed sections, the [0] index is reserved
81 81 * for local symbols, and the [1] index for globals. If the original
82 82 * Solaris versioning rules are in effect and there is a verdef section,
83 83 * then max_verndex is the number of defined versions. If one of the
84 84 * other versioning forms is in effect, then:
85 85 * 1) If there is no verneed section, it is the same as for
86 86 * original Solaris versioning.
87 87 * 2) If there is a verneed section, the vna_other field of the
88 88 * Vernaux structs contain versions, and max_verndx is the
89 89 * largest such index.
90 90 *
91 91 * If gnu_full is True, the object uses the full GNU form of versioning.
92 92 * The value of the gnu_full field is based on the presence of
93 93 * a DT_VERSYM entry in the dynamic section: GNU ld produces these, and
94 94 * Solaris ld does not.
95 95 *
96 96 * The gnu_needed field is True if the Versym contains indexes to
97 97 * Verneed records, as indicated by non-zero vna_other fields in the Verneed
98 98 * section. If gnu_full is True, then gnu_needed will always be true.
99 99 * However, gnu_needed can be true without gnu_full. This is the modified
100 100 * Solaris form.
101 101 */
102 102 typedef struct {
103 103 Cache *cache; /* Pointer to cache entry for VERSYM */
104 104 Versym *data; /* Pointer to versym array */
105 105 int gnu_full; /* True if object uses GNU versioning rules */
106 106 int gnu_needed; /* True if object uses VERSYM indexes for */
107 107 /* VERNEED (subset of gnu_full) */
108 108 int max_verndx; /* largest versym index value */
109 109 } VERSYM_STATE;
110 110
111 111 /*
112 112 * SYMTBL_STATE is used to maintain information about a single symbol
113 113 * table section, for use by the routines that display symbol information.
114 114 */
115 115 typedef struct {
116 116 const char *file; /* Name of file */
117 117 Ehdr *ehdr; /* ELF header for file */
118 118 Cache *cache; /* Cache of all section headers */
119 119 uchar_t osabi; /* OSABI to use */
120 120 Word shnum; /* # of sections in cache */
121 121 Cache *seccache; /* Cache of symbol table section hdr */
122 122 Word secndx; /* Index of symbol table section hdr */
123 123 const char *secname; /* Name of section */
124 124 uint_t flags; /* Command line option flags */
125 125 struct { /* Extended section index data */
126 126 int checked; /* TRUE if already checked for shxndx */
127 127 Word *data; /* NULL, or extended section index */
128 128 /* used for symbol table entries */
129 129 uint_t n; /* # items in shxndx.data */
130 130 } shxndx;
131 131 VERSYM_STATE *versym; /* NULL, or associated VERSYM section */
132 132 Sym *sym; /* Array of symbols */
133 133 Word symn; /* # of symbols */
134 134 } SYMTBL_STATE;
135 135
136 136 /*
137 137 * A variable of this type is used to track information related to
138 138 * .eh_frame and .eh_frame_hdr sections across calls to unwind_eh_frame().
139 139 */
140 140 typedef struct {
141 141 Word frame_cnt; /* # .eh_frame sections seen */
142 142 Word frame_ndx; /* Section index of 1st .eh_frame */
143 143 Word hdr_cnt; /* # .eh_frame_hdr sections seen */
144 144 Word hdr_ndx; /* Section index of 1st .eh_frame_hdr */
145 145 uint64_t frame_ptr; /* Value of FramePtr field from first */
146 146 /* .eh_frame_hdr section */
147 147 uint64_t frame_base; /* Data addr of 1st .eh_frame */
148 148 } gnu_eh_state_t;
149 149
150 150 /*
151 151 * C++ .exception_ranges entries make use of the signed ptrdiff_t
152 152 * type to record self-relative pointer values. We need a type
153 153 * for this that is matched to the ELFCLASS being processed.
154 154 */
155 155 #if defined(_ELF64)
156 156 typedef int64_t PTRDIFF_T;
157 157 #else
158 158 typedef int32_t PTRDIFF_T;
159 159 #endif
160 160
161 161 /*
162 162 * The Sun C++ ABI uses this struct to define each .exception_ranges
163 163 * entry. From the ABI:
164 164 *
165 165 * The field ret_addr is a self relative pointer to the start of the address
166 166 * range. The name was chosen because in the current implementation the range
167 167 * typically starts at the return address for a call site.
168 168 *
169 169 * The field length is the difference, in bytes, between the pc of the last
170 170 * instruction covered by the exception range and the first. When only a
171 171 * single call site is represented without optimization, this will equal zero.
172 172 *
173 173 * The field handler_addr is a relative pointer which stores the difference
174 174 * between the start of the exception range and the address of all code to
175 175 * catch exceptions and perform the cleanup for stack unwinding.
176 176 *
177 177 * The field type_block is a relative pointer which stores the difference
178 178 * between the start of the exception range and the address of an array used
179 179 * for storing a list of the types of exceptions which can be caught within
180 180 * the exception range.
181 181 */
182 182 typedef struct {
183 183 PTRDIFF_T ret_addr;
184 184 Xword length;
185 185 PTRDIFF_T handler_addr;
186 186 PTRDIFF_T type_block;
187 187 Xword reserved;
188 188 } exception_range_entry;
189 189
190 190 /*
191 191 * Focal point for verifying symbol names.
192 192 */
193 193 static const char *
194 194 string(Cache *refsec, Word ndx, Cache *strsec, const char *file, Word name)
195 195 {
196 196 /*
197 197 * If an error in this routine is due to a property of the string
198 198 * section, as opposed to a bad offset into the section (a property of
199 199 * the referencing section), then we will detect the same error on
200 200 * every call involving those sections. We use these static variables
201 201 * to retain the information needed to only issue each such error once.
202 202 */
203 203 static Cache *last_refsec; /* Last referencing section seen */
204 204 static int strsec_err; /* True if error issued */
205 205
206 206 const char *strs;
207 207 Word strn;
208 208
209 209 if (strsec->c_data == NULL)
210 210 return (NULL);
211 211
212 212 strs = (char *)strsec->c_data->d_buf;
213 213 strn = strsec->c_data->d_size;
214 214
215 215 /*
216 216 * We only print a diagnostic regarding a bad string table once per
217 217 * input section being processed. If the refsec has changed, reset
218 218 * our retained error state.
219 219 */
220 220 if (last_refsec != refsec) {
221 221 last_refsec = refsec;
222 222 strsec_err = 0;
223 223 }
224 224
225 225 /* Verify that strsec really is a string table */
226 226 if (strsec->c_shdr->sh_type != SHT_STRTAB) {
227 227 if (!strsec_err) {
228 228 (void) fprintf(stderr, MSG_INTL(MSG_ERR_NOTSTRTAB),
229 229 file, strsec->c_ndx, refsec->c_ndx);
230 230 strsec_err = 1;
231 231 }
232 232 return (MSG_INTL(MSG_STR_UNKNOWN));
233 233 }
234 234
235 235 /*
236 236 * Is the string table offset within range of the available strings?
237 237 */
238 238 if (name >= strn) {
239 239 /*
240 240 * Do we have a empty string table?
241 241 */
242 242 if (strs == NULL) {
243 243 if (!strsec_err) {
244 244 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
245 245 file, strsec->c_name);
246 246 strsec_err = 1;
247 247 }
248 248 } else {
249 249 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSTOFF),
250 250 file, refsec->c_name, EC_WORD(ndx), strsec->c_name,
251 251 EC_WORD(name), EC_WORD(strn - 1));
252 252 }
253 253
254 254 /*
255 255 * Return the empty string so that the calling function can
256 256 * continue it's output diagnostics.
257 257 */
258 258 return (MSG_INTL(MSG_STR_UNKNOWN));
259 259 }
260 260 return (strs + name);
261 261 }
262 262
263 263 /*
264 264 * Relocations can reference section symbols and standard symbols. If the
265 265 * former, establish the section name.
266 266 */
267 267 static const char *
268 268 relsymname(Cache *cache, Cache *csec, Cache *strsec, Word symndx, Word symnum,
269 269 Word relndx, Sym *syms, char *secstr, size_t secsz, const char *file)
270 270 {
271 271 Sym *sym;
272 272 const char *name;
273 273
274 274 if (symndx >= symnum) {
275 275 (void) fprintf(stderr, MSG_INTL(MSG_ERR_RELBADSYMNDX),
276 276 file, EC_WORD(symndx), EC_WORD(relndx));
277 277 return (MSG_INTL(MSG_STR_UNKNOWN));
278 278 }
279 279
280 280 sym = (Sym *)(syms + symndx);
281 281 name = string(csec, symndx, strsec, file, sym->st_name);
282 282
283 283 /*
284 284 * If the symbol represents a section offset construct an appropriate
285 285 * string. Note, although section symbol table entries typically have
286 286 * a NULL name pointer, entries do exist that point into the string
287 287 * table to their own NULL strings.
288 288 */
289 289 if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) &&
290 290 ((sym->st_name == 0) || (*name == '\0'))) {
291 291 (void) snprintf(secstr, secsz, MSG_INTL(MSG_STR_SECTION),
292 292 cache[sym->st_shndx].c_name);
293 293 return ((const char *)secstr);
294 294 }
295 295
296 296 return (name);
297 297 }
298 298
299 299 /*
300 300 * Focal point for establishing a string table section. Data such as the
301 301 * dynamic information simply points to a string table. Data such as
302 302 * relocations, reference a symbol table, which in turn is associated with a
303 303 * string table.
304 304 */
305 305 static int
306 306 stringtbl(Cache *cache, int symtab, Word ndx, Word shnum, const char *file,
307 307 Word *symnum, Cache **symsec, Cache **strsec)
308 308 {
309 309 Shdr *shdr = cache[ndx].c_shdr;
310 310
311 311 if (symtab) {
312 312 /*
313 313 * Validate the symbol table section.
314 314 */
315 315 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
316 316 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
317 317 file, cache[ndx].c_name, EC_WORD(shdr->sh_link));
318 318 return (0);
319 319 }
320 320 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
321 321 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
322 322 file, cache[ndx].c_name);
323 323 return (0);
324 324 }
325 325
326 326 /*
327 327 * Obtain, and verify the symbol table data.
328 328 */
329 329 if ((cache[ndx].c_data == NULL) ||
330 330 (cache[ndx].c_data->d_buf == NULL)) {
331 331 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
332 332 file, cache[ndx].c_name);
333 333 return (0);
334 334 }
335 335
336 336 /*
337 337 * Establish the string table index.
338 338 */
339 339 ndx = shdr->sh_link;
340 340 shdr = cache[ndx].c_shdr;
341 341
342 342 /*
343 343 * Return symbol table information.
344 344 */
345 345 if (symnum)
346 346 *symnum = (shdr->sh_size / shdr->sh_entsize);
347 347 if (symsec)
348 348 *symsec = &cache[ndx];
349 349 }
350 350
351 351 /*
352 352 * Validate the associated string table section.
353 353 */
354 354 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
355 355 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
356 356 file, cache[ndx].c_name, EC_WORD(shdr->sh_link));
357 357 return (0);
358 358 }
359 359
360 360 if (strsec)
361 361 *strsec = &cache[shdr->sh_link];
362 362
363 363 return (1);
364 364 }
365 365
366 366 /*
367 367 * Lookup a symbol and set Sym accordingly.
368 368 *
369 369 * entry:
370 370 * name - Name of symbol to lookup
371 371 * cache - Cache of all section headers
372 372 * shnum - # of sections in cache
373 373 * sym - Address of pointer to receive symbol
374 374 * target - NULL, or section to which the symbol must be associated.
375 375 * symtab - Symbol table to search for symbol
376 376 * file - Name of file
377 377 *
378 378 * exit:
379 379 * If the symbol is found, *sym is set to reference it, and True is
380 380 * returned. If target is non-NULL, the symbol must reference the given
381 381 * section --- otherwise the section is not checked.
382 382 *
383 383 * If no symbol is found, False is returned.
384 384 */
385 385 static int
386 386 symlookup(const char *name, Cache *cache, Word shnum, Sym **sym,
387 387 Cache *target, Cache *symtab, const char *file)
388 388 {
389 389 Shdr *shdr;
390 390 Word symn, cnt;
391 391 Sym *syms;
392 392
393 393 if (symtab == 0)
394 394 return (0);
395 395
396 396 shdr = symtab->c_shdr;
397 397
398 398 /*
399 399 * Determine the symbol data and number.
400 400 */
401 401 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
402 402 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
403 403 file, symtab->c_name);
404 404 return (0);
405 405 }
406 406 if (symtab->c_data == NULL)
407 407 return (0);
408 408
409 409 /* LINTED */
410 410 symn = (Word)(shdr->sh_size / shdr->sh_entsize);
411 411 syms = (Sym *)symtab->c_data->d_buf;
412 412
413 413 /*
414 414 * Get the associated string table section.
415 415 */
416 416 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
417 417 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
418 418 file, symtab->c_name, EC_WORD(shdr->sh_link));
419 419 return (0);
420 420 }
421 421
422 422 /*
423 423 * Loop through the symbol table to find a match.
424 424 */
425 425 *sym = NULL;
426 426 for (cnt = 0; cnt < symn; syms++, cnt++) {
427 427 const char *symname;
428 428
429 429 symname = string(symtab, cnt, &cache[shdr->sh_link], file,
430 430 syms->st_name);
431 431
432 432 if (symname && (strcmp(name, symname) == 0) &&
433 433 ((target == NULL) || (target->c_ndx == syms->st_shndx))) {
434 434 /*
435 435 * It is possible, though rare, for a local and
436 436 * global symbol of the same name to exist, each
437 437 * contributed by a different input object. If the
438 438 * symbol just found is local, remember it, but
439 439 * continue looking.
440 440 */
441 441 *sym = syms;
442 442 if (ELF_ST_BIND(syms->st_info) != STB_LOCAL)
443 443 break;
444 444 }
445 445 }
446 446
447 447 return (*sym != NULL);
448 448 }
449 449
450 450 /*
451 451 * Print section headers.
452 452 */
453 453 static void
454 454 sections(const char *file, Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi)
455 455 {
456 456 size_t seccnt;
457 457
458 458 for (seccnt = 1; seccnt < shnum; seccnt++) {
459 459 Cache *_cache = &cache[seccnt];
460 460 Shdr *shdr = _cache->c_shdr;
461 461 const char *secname = _cache->c_name;
462 462
463 463 /*
464 464 * Although numerous section header entries can be zero, it's
465 465 * usually a sign of trouble if the type is zero.
466 466 */
467 467 if (shdr->sh_type == 0) {
468 468 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHTYPE),
469 469 file, secname, EC_WORD(shdr->sh_type));
470 470 }
471 471
472 472 if (!match(MATCH_F_ALL, secname, seccnt, shdr->sh_type))
473 473 continue;
474 474
475 475 /*
476 476 * Identify any sections that are suspicious. A .got section
477 477 * shouldn't exist in a relocatable object.
478 478 */
479 479 if (ehdr->e_type == ET_REL) {
480 480 if (strncmp(secname, MSG_ORIG(MSG_ELF_GOT),
481 481 MSG_ELF_GOT_SIZE) == 0) {
482 482 (void) fprintf(stderr,
483 483 MSG_INTL(MSG_GOT_UNEXPECTED), file,
484 484 secname);
485 485 }
486 486 }
487 487
488 488 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
489 489 dbg_print(0, MSG_INTL(MSG_ELF_SHDR), EC_WORD(seccnt), secname);
490 490 Elf_shdr(0, osabi, ehdr->e_machine, shdr);
491 491 }
492 492 }
493 493
494 494 /*
495 495 * Obtain a specified Phdr entry.
496 496 */
497 497 static Phdr *
498 498 getphdr(Word phnum, Word *type_arr, Word type_cnt, const char *file, Elf *elf)
499 499 {
500 500 Word cnt, tcnt;
501 501 Phdr *phdr;
502 502
503 503 if ((phdr = elf_getphdr(elf)) == NULL) {
504 504 failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
505 505 return (NULL);
506 506 }
507 507
508 508 for (cnt = 0; cnt < phnum; phdr++, cnt++) {
509 509 for (tcnt = 0; tcnt < type_cnt; tcnt++) {
510 510 if (phdr->p_type == type_arr[tcnt])
511 511 return (phdr);
512 512 }
513 513 }
514 514 return (NULL);
515 515 }
516 516
517 517 /*
518 518 * Display the contents of GNU/amd64 .eh_frame and .eh_frame_hdr
519 519 * sections.
520 520 *
521 521 * entry:
522 522 * cache - Cache of all section headers
523 523 * shndx - Index of .eh_frame or .eh_frame_hdr section to be displayed
524 524 * uphdr - NULL, or unwind program header associated with
↓ open down ↓ |
524 lines elided |
↑ open up ↑ |
525 525 * the .eh_frame_hdr section.
526 526 * ehdr - ELF header for file
527 527 * eh_state - Data used across calls to this routine. The
528 528 * caller should zero it before the first call, and
529 529 * pass it on every call.
530 530 * osabi - OSABI to use in displaying information
531 531 * file - Name of file
532 532 * flags - Command line option flags
533 533 */
534 534 static void
535 -unwind_eh_frame(Cache *cache, Word shndx, Phdr *uphdr, Ehdr *ehdr,
535 +unwind_eh_frame(Cache *cache, Word shndx, Word shnum, Phdr *uphdr, Ehdr *ehdr,
536 536 gnu_eh_state_t *eh_state, uchar_t osabi, const char *file, uint_t flags)
537 537 {
538 538 #if defined(_ELF64)
539 539 #define MSG_UNW_BINSRTAB2 MSG_UNW_BINSRTAB2_64
540 540 #define MSG_UNW_BINSRTABENT MSG_UNW_BINSRTABENT_64
541 541 #else
542 542 #define MSG_UNW_BINSRTAB2 MSG_UNW_BINSRTAB2_32
543 543 #define MSG_UNW_BINSRTABENT MSG_UNW_BINSRTABENT_32
544 544 #endif
545 545
546 546 Cache *_cache = &cache[shndx];
547 547 Shdr *shdr = _cache->c_shdr;
548 548 uchar_t *data = (uchar_t *)(_cache->c_data->d_buf);
549 549 size_t datasize = _cache->c_data->d_size;
550 550 Conv_dwarf_ehe_buf_t dwarf_ehe_buf;
551 551 uint64_t ndx, frame_ptr, fde_cnt, tabndx;
552 552 uint_t vers, frame_ptr_enc, fde_cnt_enc, table_enc;
553 553 uint64_t initloc, initloc0;
554 + uint64_t gotaddr = 0;
555 + int cnt;
554 556
557 + for (cnt = 1; cnt < shnum; cnt++) {
558 + if (strncmp(cache[cnt].c_name, MSG_ORIG(MSG_ELF_GOT),
559 + MSG_ELF_GOT_SIZE) == 0) {
560 + gotaddr = cache[cnt].c_shdr->sh_addr;
561 + break;
562 + }
563 + }
555 564
556 565 /*
557 566 * Is this a .eh_frame_hdr?
558 567 */
559 568 if ((uphdr && (shdr->sh_addr == uphdr->p_vaddr)) ||
560 569 (strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRMHDR),
561 570 MSG_SCN_FRMHDR_SIZE) == 0)) {
562 571 /*
563 572 * There can only be a single .eh_frame_hdr.
564 573 * Flag duplicates.
565 574 */
566 575 if (++eh_state->hdr_cnt > 1)
567 576 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MULTEHFRMHDR),
568 577 file, EC_WORD(shndx), _cache->c_name);
569 578
570 579 dbg_print(0, MSG_ORIG(MSG_UNW_FRMHDR));
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
571 580 ndx = 0;
572 581
573 582 vers = data[ndx++];
574 583 frame_ptr_enc = data[ndx++];
575 584 fde_cnt_enc = data[ndx++];
576 585 table_enc = data[ndx++];
577 586
578 587 dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers);
579 588
580 589 frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc,
581 - ehdr->e_ident, shdr->sh_addr, ndx);
590 + ehdr->e_ident, B_TRUE, shdr->sh_addr, ndx, gotaddr);
582 591 if (eh_state->hdr_cnt == 1) {
583 592 eh_state->hdr_ndx = shndx;
584 593 eh_state->frame_ptr = frame_ptr;
585 594 }
586 595
587 596 dbg_print(0, MSG_ORIG(MSG_UNW_FRPTRENC),
588 597 conv_dwarf_ehe(frame_ptr_enc, &dwarf_ehe_buf),
589 598 EC_XWORD(frame_ptr));
590 599
591 600 fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc,
592 - ehdr->e_ident, shdr->sh_addr, ndx);
601 + ehdr->e_ident, B_TRUE, shdr->sh_addr, ndx, gotaddr);
593 602
594 603 dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC),
595 604 conv_dwarf_ehe(fde_cnt_enc, &dwarf_ehe_buf),
596 605 EC_XWORD(fde_cnt));
597 606 dbg_print(0, MSG_ORIG(MSG_UNW_TABENC),
598 607 conv_dwarf_ehe(table_enc, &dwarf_ehe_buf));
599 608 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB1));
600 609 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTAB2));
601 610
602 611 for (tabndx = 0; tabndx < fde_cnt; tabndx++) {
603 612 initloc = dwarf_ehe_extract(data, &ndx, table_enc,
604 - ehdr->e_ident, shdr->sh_addr, ndx);
613 + ehdr->e_ident, B_TRUE, shdr->sh_addr, ndx, gotaddr);
605 614 /*LINTED:E_VAR_USED_BEFORE_SET*/
606 615 if ((tabndx != 0) && (initloc0 > initloc))
607 616 (void) fprintf(stderr,
608 617 MSG_INTL(MSG_ERR_BADSORT), file,
609 618 _cache->c_name, EC_WORD(tabndx));
610 619 dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT),
611 620 EC_XWORD(initloc),
612 621 EC_XWORD(dwarf_ehe_extract(data, &ndx,
613 - table_enc, ehdr->e_ident, shdr->sh_addr,
614 - ndx)));
622 + table_enc, ehdr->e_ident, B_TRUE, shdr->sh_addr,
623 + ndx, gotaddr)));
615 624 initloc0 = initloc;
616 625 }
617 626 } else { /* Display the .eh_frame section */
618 627 eh_state->frame_cnt++;
619 628 if (eh_state->frame_cnt == 1) {
620 629 eh_state->frame_ndx = shndx;
621 630 eh_state->frame_base = shdr->sh_addr;
622 631 } else if ((eh_state->frame_cnt > 1) &&
623 632 (ehdr->e_type != ET_REL)) {
624 633 Conv_inv_buf_t inv_buf;
625 634
626 635 (void) fprintf(stderr, MSG_INTL(MSG_WARN_MULTEHFRM),
627 636 file, EC_WORD(shndx), _cache->c_name,
628 637 conv_ehdr_type(osabi, ehdr->e_type, 0, &inv_buf));
629 638 }
630 639 dump_eh_frame(data, datasize, shdr->sh_addr,
631 - ehdr->e_machine, ehdr->e_ident);
640 + ehdr->e_machine, ehdr->e_ident, gotaddr);
632 641 }
633 642
634 643 /*
635 644 * If we've seen the .eh_frame_hdr and the first .eh_frame section,
636 645 * compare the header frame_ptr to the address of the actual frame
637 646 * section to ensure the link-editor got this right. Note, this
638 647 * diagnostic is only produced when unwind information is explicitly
639 648 * asked for, as shared objects built with an older ld(1) may reveal
640 649 * this inconsistency. Although an inconsistency, it doesn't seem to
641 650 * have any adverse effect on existing tools.
642 651 */
643 652 if (((flags & FLG_MASK_SHOW) != FLG_MASK_SHOW) &&
644 653 (eh_state->hdr_cnt > 0) && (eh_state->frame_cnt > 0) &&
645 654 (eh_state->frame_ptr != eh_state->frame_base))
646 655 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADEHFRMPTR),
647 656 file, EC_WORD(eh_state->hdr_ndx),
648 657 cache[eh_state->hdr_ndx].c_name,
649 658 EC_XWORD(eh_state->frame_ptr),
650 659 EC_WORD(eh_state->frame_ndx),
651 660 cache[eh_state->frame_ndx].c_name,
652 661 EC_XWORD(eh_state->frame_base));
653 662 #undef MSG_UNW_BINSRTAB2
654 663 #undef MSG_UNW_BINSRTABENT
655 664 }
656 665
657 666 /*
658 667 * Convert a self relative pointer into an address. A self relative
659 668 * pointer adds the address where the pointer resides to the offset
660 669 * contained in the pointer. The benefit is that the value of the
661 670 * pointer does not require relocation.
662 671 *
663 672 * entry:
664 673 * base_addr - Address of the pointer.
665 674 * delta - Offset relative to base_addr giving desired address
666 675 *
667 676 * exit:
668 677 * The computed address is returned.
669 678 *
670 679 * note:
671 680 * base_addr is an unsigned value, while ret_addr is signed. This routine
672 681 * used explicit testing and casting to explicitly control type
673 682 * conversion, and ensure that we handle the maximum possible range.
674 683 */
675 684 static Addr
676 685 srelptr(Addr base_addr, PTRDIFF_T delta)
677 686 {
678 687 if (delta < 0)
679 688 return (base_addr - (Addr) (-delta));
680 689
681 690 return (base_addr + (Addr) delta);
682 691 }
683 692
684 693 /*
685 694 * Byte swap a PTRDIFF_T value.
686 695 */
687 696 static PTRDIFF_T
688 697 swap_ptrdiff(PTRDIFF_T value)
689 698 {
690 699 PTRDIFF_T r;
691 700 uchar_t *dst = (uchar_t *)&r;
692 701 uchar_t *src = (uchar_t *)&value;
693 702
694 703 UL_ASSIGN_BSWAP_XWORD(dst, src);
695 704 return (r);
696 705 }
697 706
698 707 /*
699 708 * Display exception_range_entry items from the .exception_ranges section
700 709 * of a Sun C++ object.
701 710 */
702 711 static void
703 712 unwind_exception_ranges(Cache *_cache, const char *file, int do_swap)
704 713 {
705 714 /*
706 715 * Translate a PTRDIFF_T self-relative address field of
707 716 * an exception_range_entry struct into an address.
708 717 *
709 718 * entry:
710 719 * exc_addr - Address of base of exception_range_entry struct
711 720 * cur_ent - Pointer to data in the struct to be translated
712 721 *
713 722 * _f - Field of struct to be translated
714 723 */
715 724 #define SRELPTR(_f) \
716 725 srelptr(exc_addr + offsetof(exception_range_entry, _f), cur_ent->_f)
717 726
718 727 #if defined(_ELF64)
719 728 #define MSG_EXR_TITLE MSG_EXR_TITLE_64
720 729 #define MSG_EXR_ENTRY MSG_EXR_ENTRY_64
721 730 #else
722 731 #define MSG_EXR_TITLE MSG_EXR_TITLE_32
723 732 #define MSG_EXR_ENTRY MSG_EXR_ENTRY_32
724 733 #endif
725 734
726 735 exception_range_entry scratch, *ent, *cur_ent = &scratch;
727 736 char index[MAXNDXSIZE];
728 737 Word i, nelts;
729 738 Addr addr, addr0, offset = 0;
730 739 Addr exc_addr = _cache->c_shdr->sh_addr;
731 740
732 741 dbg_print(0, MSG_INTL(MSG_EXR_TITLE));
733 742 ent = (exception_range_entry *)(_cache->c_data->d_buf);
734 743 nelts = _cache->c_data->d_size / sizeof (exception_range_entry);
735 744
736 745 for (i = 0; i < nelts; i++, ent++) {
737 746 if (do_swap) {
738 747 /*
739 748 * Copy byte swapped values into the scratch buffer.
740 749 * The reserved field is not used, so we skip it.
741 750 */
742 751 scratch.ret_addr = swap_ptrdiff(ent->ret_addr);
743 752 scratch.length = BSWAP_XWORD(ent->length);
744 753 scratch.handler_addr = swap_ptrdiff(ent->handler_addr);
745 754 scratch.type_block = swap_ptrdiff(ent->type_block);
746 755 } else {
747 756 cur_ent = ent;
748 757 }
749 758
750 759 /*
751 760 * The table is required to be sorted by the address
752 761 * derived from ret_addr, to allow binary searching. Ensure
753 762 * that addresses grow monotonically.
754 763 */
755 764 addr = SRELPTR(ret_addr);
756 765 /*LINTED:E_VAR_USED_BEFORE_SET*/
757 766 if ((i != 0) && (addr0 > addr))
758 767 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORT),
759 768 file, _cache->c_name, EC_WORD(i));
760 769
761 770 (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX),
762 771 EC_XWORD(i));
763 772 dbg_print(0, MSG_INTL(MSG_EXR_ENTRY), index, EC_ADDR(offset),
764 773 EC_ADDR(addr), EC_ADDR(cur_ent->length),
765 774 EC_ADDR(SRELPTR(handler_addr)),
766 775 EC_ADDR(SRELPTR(type_block)));
767 776
768 777 addr0 = addr;
769 778 exc_addr += sizeof (exception_range_entry);
770 779 offset += sizeof (exception_range_entry);
771 780 }
772 781
773 782 #undef SRELPTR
774 783 #undef MSG_EXR_TITLE
775 784 #undef MSG_EXR_ENTRY
776 785 }
777 786
778 787 /*
779 788 * Display information from unwind/exception sections:
780 789 *
781 790 * - GNU/amd64 .eh_frame and .eh_frame_hdr
782 791 * - Sun C++ .exception_ranges
783 792 *
784 793 */
785 794 static void
786 795 unwind(Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, uchar_t osabi,
787 796 const char *file, Elf *elf, uint_t flags)
788 797 {
789 798 static Word phdr_types[] = { PT_SUNW_UNWIND, PT_SUNW_EH_FRAME };
790 799
791 800 Word cnt;
792 801 Phdr *uphdr = NULL;
793 802 gnu_eh_state_t eh_state;
794 803
795 804 /*
796 805 * Historical background: .eh_frame and .eh_frame_hdr sections
797 806 * come from the GNU compilers (particularly C++), and are used
798 807 * under all architectures. Their format is based on DWARF. When
799 808 * the amd64 ABI was defined, these sections were adopted wholesale
800 809 * from the existing practice.
801 810 *
802 811 * When amd64 support was added to Solaris, support for these
803 812 * sections was added, using the SHT_AMD64_UNWIND section type
804 813 * to identify them. At first, we ignored them in objects for
805 814 * non-amd64 targets, but later broadened our support to include
806 815 * other architectures in order to better support gcc-generated
807 816 * objects.
808 817 *
809 818 * .exception_ranges implement the same basic concepts, but
810 819 * were invented at Sun for the Sun C++ compiler.
811 820 *
812 821 * We match these sections by name, rather than section type,
813 822 * because they can come in as either SHT_AMD64_UNWIND, or as
814 823 * SHT_PROGBITS, and because the type isn't enough to determine
815 824 * how they should be interpreted.
816 825 */
817 826 /* Find the program header for .eh_frame_hdr if present */
818 827 if (phnum)
819 828 uphdr = getphdr(phnum, phdr_types,
820 829 sizeof (phdr_types) / sizeof (*phdr_types), file, elf);
821 830
822 831 /*
823 832 * eh_state is used to retain data used by unwind_eh_frame()
824 833 * across calls.
825 834 */
826 835 bzero(&eh_state, sizeof (eh_state));
827 836
828 837 for (cnt = 1; cnt < shnum; cnt++) {
829 838 Cache *_cache = &cache[cnt];
830 839 Shdr *shdr = _cache->c_shdr;
831 840 int is_exrange;
832 841
833 842 /*
834 843 * Skip sections of the wrong type. On amd64, they
835 844 * can be SHT_AMD64_UNWIND. On all platforms, they
836 845 * can be SHT_PROGBITS (including amd64, if using
837 846 * the GNU compilers).
838 847 *
839 848 * Skip anything other than these two types. The name
840 849 * test below will thin out the SHT_PROGBITS that don't apply.
841 850 */
842 851 if ((shdr->sh_type != SHT_PROGBITS) &&
843 852 (shdr->sh_type != SHT_AMD64_UNWIND))
844 853 continue;
845 854
846 855 /*
847 856 * Only sections with certain well known names are of interest.
848 857 * These are:
849 858 *
850 859 * .eh_frame - amd64/GNU-compiler unwind sections
851 860 * .eh_frame_hdr - Sorted table referencing .eh_frame
852 861 * .exception_ranges - Sun C++ unwind sections
853 862 *
854 863 * We do a prefix comparison, allowing for naming conventions
855 864 * like .eh_frame.foo, hence the use of strncmp() rather than
856 865 * strcmp(). This means that we only really need to test for
857 866 * .eh_frame, as it's a prefix of .eh_frame_hdr.
858 867 */
859 868 is_exrange = strncmp(_cache->c_name,
860 869 MSG_ORIG(MSG_SCN_EXRANGE), MSG_SCN_EXRANGE_SIZE) == 0;
861 870 if ((strncmp(_cache->c_name, MSG_ORIG(MSG_SCN_FRM),
862 871 MSG_SCN_FRM_SIZE) != 0) && !is_exrange)
863 872 continue;
864 873
865 874 if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type))
866 875 continue;
867 876
↓ open down ↓ |
226 lines elided |
↑ open up ↑ |
868 877 if (_cache->c_data == NULL)
869 878 continue;
870 879
871 880 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
872 881 dbg_print(0, MSG_INTL(MSG_ELF_SCN_UNWIND), _cache->c_name);
873 882
874 883 if (is_exrange)
875 884 unwind_exception_ranges(_cache, file,
876 885 _elf_sys_encoding() != ehdr->e_ident[EI_DATA]);
877 886 else
878 - unwind_eh_frame(cache, cnt, uphdr, ehdr, &eh_state,
879 - osabi, file, flags);
887 + unwind_eh_frame(cache, cnt, shnum, uphdr, ehdr,
888 + &eh_state, osabi, file, flags);
880 889 }
881 890 }
882 891
883 892 /*
884 893 * Initialize a symbol table state structure
885 894 *
886 895 * entry:
887 896 * state - State structure to be initialized
888 897 * cache - Cache of all section headers
889 898 * shnum - # of sections in cache
890 899 * secndx - Index of symbol table section
891 900 * ehdr - ELF header for file
892 901 * versym - Information about versym section
893 902 * file - Name of file
894 903 * flags - Command line option flags
895 904 */
896 905 static int
897 906 init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx,
898 907 Ehdr *ehdr, uchar_t osabi, VERSYM_STATE *versym, const char *file,
899 908 uint_t flags)
900 909 {
901 910 Shdr *shdr;
902 911
903 912 state->file = file;
904 913 state->ehdr = ehdr;
905 914 state->cache = cache;
906 915 state->osabi = osabi;
907 916 state->shnum = shnum;
908 917 state->seccache = &cache[secndx];
909 918 state->secndx = secndx;
910 919 state->secname = state->seccache->c_name;
911 920 state->flags = flags;
912 921 state->shxndx.checked = 0;
913 922 state->shxndx.data = NULL;
914 923 state->shxndx.n = 0;
915 924
916 925 shdr = state->seccache->c_shdr;
917 926
918 927 /*
919 928 * Check the symbol data and per-item size.
920 929 */
921 930 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
922 931 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
923 932 file, state->secname);
924 933 return (0);
925 934 }
926 935 if (state->seccache->c_data == NULL)
927 936 return (0);
928 937
929 938 /* LINTED */
930 939 state->symn = (Word)(shdr->sh_size / shdr->sh_entsize);
931 940 state->sym = (Sym *)state->seccache->c_data->d_buf;
932 941
933 942 /*
934 943 * Check associated string table section.
935 944 */
936 945 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
937 946 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
938 947 file, state->secname, EC_WORD(shdr->sh_link));
939 948 return (0);
940 949 }
941 950
942 951 /*
943 952 * Determine if there is a associated Versym section
944 953 * with this Symbol Table.
945 954 */
946 955 if (versym && versym->cache &&
947 956 (versym->cache->c_shdr->sh_link == state->secndx))
948 957 state->versym = versym;
949 958 else
950 959 state->versym = NULL;
951 960
952 961
953 962 return (1);
954 963 }
955 964
956 965 /*
957 966 * Determine the extended section index used for symbol tables entries.
958 967 */
959 968 static void
960 969 symbols_getxindex(SYMTBL_STATE *state)
961 970 {
962 971 uint_t symn;
963 972 Word symcnt;
964 973
965 974 state->shxndx.checked = 1; /* Note that we've been called */
966 975 for (symcnt = 1; symcnt < state->shnum; symcnt++) {
967 976 Cache *_cache = &state->cache[symcnt];
968 977 Shdr *shdr = _cache->c_shdr;
969 978
970 979 if ((shdr->sh_type != SHT_SYMTAB_SHNDX) ||
971 980 (shdr->sh_link != state->secndx))
972 981 continue;
973 982
974 983 if ((shdr->sh_entsize) &&
975 984 /* LINTED */
976 985 ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0))
977 986 continue;
978 987
979 988 if (_cache->c_data == NULL)
980 989 continue;
981 990
982 991 state->shxndx.data = _cache->c_data->d_buf;
983 992 state->shxndx.n = symn;
984 993 return;
985 994 }
986 995 }
987 996
988 997 /*
989 998 * Produce a line of output for the given symbol
990 999 *
991 1000 * entry:
992 1001 * state - Symbol table state
993 1002 * symndx - Index of symbol within the table
994 1003 * info - Value of st_info (indicates local/global range)
995 1004 * symndx_disp - Index to display. This may not be the same
996 1005 * as symndx if the display is relative to the logical
997 1006 * combination of the SUNW_ldynsym/dynsym tables.
998 1007 * sym - Symbol to display
999 1008 */
1000 1009 static void
1001 1010 output_symbol(SYMTBL_STATE *state, Word symndx, Word info, Word disp_symndx,
1002 1011 Sym *sym)
1003 1012 {
1004 1013 /*
1005 1014 * Symbol types for which we check that the specified
1006 1015 * address/size land inside the target section.
1007 1016 */
1008 1017 static const int addr_symtype[] = {
1009 1018 0, /* STT_NOTYPE */
1010 1019 1, /* STT_OBJECT */
1011 1020 1, /* STT_FUNC */
1012 1021 0, /* STT_SECTION */
1013 1022 0, /* STT_FILE */
1014 1023 1, /* STT_COMMON */
1015 1024 0, /* STT_TLS */
1016 1025 0, /* 7 */
1017 1026 0, /* 8 */
1018 1027 0, /* 9 */
1019 1028 0, /* 10 */
1020 1029 0, /* 11 */
1021 1030 0, /* 12 */
1022 1031 0, /* STT_SPARC_REGISTER */
1023 1032 0, /* 14 */
1024 1033 0, /* 15 */
1025 1034 };
1026 1035 #if STT_NUM != (STT_TLS + 1)
1027 1036 #error "STT_NUM has grown. Update addr_symtype[]"
1028 1037 #endif
1029 1038
1030 1039 char index[MAXNDXSIZE];
1031 1040 const char *symname, *sec;
1032 1041 Versym verndx;
1033 1042 int gnuver;
1034 1043 uchar_t type;
1035 1044 Shdr *tshdr;
1036 1045 Word shndx;
1037 1046 Conv_inv_buf_t inv_buf;
1038 1047
1039 1048 /* Ensure symbol index is in range */
1040 1049 if (symndx >= state->symn) {
1041 1050 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSYMNDX),
1042 1051 state->file, state->secname, EC_WORD(symndx));
1043 1052 return;
1044 1053 }
1045 1054
1046 1055 /*
1047 1056 * If we are using extended symbol indexes, find the
1048 1057 * corresponding SHN_SYMTAB_SHNDX table.
1049 1058 */
1050 1059 if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0))
1051 1060 symbols_getxindex(state);
1052 1061
1053 1062 /* LINTED */
1054 1063 symname = string(state->seccache, symndx,
1055 1064 &state->cache[state->seccache->c_shdr->sh_link], state->file,
1056 1065 sym->st_name);
1057 1066
1058 1067 tshdr = NULL;
1059 1068 sec = NULL;
1060 1069
1061 1070 if (state->ehdr->e_type == ET_CORE) {
1062 1071 sec = (char *)MSG_INTL(MSG_STR_UNKNOWN);
1063 1072 } else if (state->flags & FLG_CTL_FAKESHDR) {
1064 1073 /*
1065 1074 * If we are using fake section headers derived from
1066 1075 * the program headers, then the section indexes
1067 1076 * in the symbols do not correspond to these headers.
1068 1077 * The section names are not available, so all we can
1069 1078 * do is to display them in numeric form.
1070 1079 */
1071 1080 sec = conv_sym_shndx(state->osabi, state->ehdr->e_machine,
1072 1081 sym->st_shndx, CONV_FMT_DECIMAL, &inv_buf);
1073 1082 } else if ((sym->st_shndx < SHN_LORESERVE) &&
1074 1083 (sym->st_shndx < state->shnum)) {
1075 1084 shndx = sym->st_shndx;
1076 1085 tshdr = state->cache[shndx].c_shdr;
1077 1086 sec = state->cache[shndx].c_name;
1078 1087 } else if (sym->st_shndx == SHN_XINDEX) {
1079 1088 if (state->shxndx.data) {
1080 1089 Word _shxndx;
1081 1090
1082 1091 if (symndx > state->shxndx.n) {
1083 1092 (void) fprintf(stderr,
1084 1093 MSG_INTL(MSG_ERR_BADSYMXINDEX1),
1085 1094 state->file, state->secname,
1086 1095 EC_WORD(symndx));
1087 1096 } else if ((_shxndx =
1088 1097 state->shxndx.data[symndx]) > state->shnum) {
1089 1098 (void) fprintf(stderr,
1090 1099 MSG_INTL(MSG_ERR_BADSYMXINDEX2),
1091 1100 state->file, state->secname,
1092 1101 EC_WORD(symndx), EC_WORD(_shxndx));
1093 1102 } else {
1094 1103 shndx = _shxndx;
1095 1104 tshdr = state->cache[shndx].c_shdr;
1096 1105 sec = state->cache[shndx].c_name;
1097 1106 }
1098 1107 } else {
1099 1108 (void) fprintf(stderr,
1100 1109 MSG_INTL(MSG_ERR_BADSYMXINDEX3),
1101 1110 state->file, state->secname, EC_WORD(symndx));
1102 1111 }
1103 1112 } else if ((sym->st_shndx < SHN_LORESERVE) &&
1104 1113 (sym->st_shndx >= state->shnum)) {
1105 1114 (void) fprintf(stderr,
1106 1115 MSG_INTL(MSG_ERR_BADSYM5), state->file,
1107 1116 state->secname, EC_WORD(symndx),
1108 1117 demangle(symname, state->flags), sym->st_shndx);
1109 1118 }
1110 1119
1111 1120 /*
1112 1121 * If versioning is available display the
1113 1122 * version index. If not, then use 0.
1114 1123 */
1115 1124 if (state->versym) {
1116 1125 Versym test_verndx;
1117 1126
1118 1127 verndx = test_verndx = state->versym->data[symndx];
1119 1128 gnuver = state->versym->gnu_full;
1120 1129
1121 1130 /*
1122 1131 * Check to see if this is a defined symbol with a
1123 1132 * version index that is outside the valid range for
1124 1133 * the file. The interpretation of this depends on
1125 1134 * the style of versioning used by the object.
1126 1135 *
1127 1136 * Versions >= VER_NDX_LORESERVE have special meanings,
1128 1137 * and are exempt from this checking.
1129 1138 *
1130 1139 * GNU style version indexes use the top bit of the
1131 1140 * 16-bit index value (0x8000) as the "hidden bit".
1132 1141 * We must mask off this bit in order to compare
1133 1142 * the version against the maximum value.
1134 1143 */
1135 1144 if (gnuver)
1136 1145 test_verndx &= ~0x8000;
1137 1146
1138 1147 if ((test_verndx > state->versym->max_verndx) &&
1139 1148 (verndx < VER_NDX_LORESERVE))
1140 1149 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADVER),
1141 1150 state->file, state->secname, EC_WORD(symndx),
1142 1151 EC_HALF(test_verndx), state->versym->max_verndx);
1143 1152 } else {
1144 1153 verndx = 0;
1145 1154 gnuver = 0;
1146 1155 }
1147 1156
1148 1157 /*
1149 1158 * Error checking for TLS.
1150 1159 */
1151 1160 type = ELF_ST_TYPE(sym->st_info);
1152 1161 if (type == STT_TLS) {
1153 1162 if (tshdr &&
1154 1163 (sym->st_shndx != SHN_UNDEF) &&
1155 1164 ((tshdr->sh_flags & SHF_TLS) == 0)) {
1156 1165 (void) fprintf(stderr,
1157 1166 MSG_INTL(MSG_ERR_BADSYM3), state->file,
1158 1167 state->secname, EC_WORD(symndx),
1159 1168 demangle(symname, state->flags));
1160 1169 }
1161 1170 } else if ((type != STT_SECTION) && sym->st_size &&
1162 1171 tshdr && (tshdr->sh_flags & SHF_TLS)) {
1163 1172 (void) fprintf(stderr,
1164 1173 MSG_INTL(MSG_ERR_BADSYM4), state->file,
1165 1174 state->secname, EC_WORD(symndx),
1166 1175 demangle(symname, state->flags));
1167 1176 }
1168 1177
1169 1178 /*
1170 1179 * If a symbol with non-zero size has a type that
1171 1180 * specifies an address, then make sure the location
1172 1181 * it references is actually contained within the
1173 1182 * section. UNDEF symbols don't count in this case,
1174 1183 * so we ignore them.
1175 1184 *
1176 1185 * The meaning of the st_value field in a symbol
1177 1186 * depends on the type of object. For a relocatable
1178 1187 * object, it is the offset within the section.
1179 1188 * For sharable objects, it is the offset relative to
1180 1189 * the base of the object, and for other types, it is
1181 1190 * the virtual address. To get an offset within the
1182 1191 * section for non-ET_REL files, we subtract the
1183 1192 * base address of the section.
1184 1193 */
1185 1194 if (addr_symtype[type] && (sym->st_size > 0) &&
1186 1195 (sym->st_shndx != SHN_UNDEF) && ((sym->st_shndx < SHN_LORESERVE) ||
1187 1196 (sym->st_shndx == SHN_XINDEX)) && (tshdr != NULL)) {
1188 1197 Word v = sym->st_value;
1189 1198 if (state->ehdr->e_type != ET_REL)
1190 1199 v -= tshdr->sh_addr;
1191 1200 if (((v + sym->st_size) > tshdr->sh_size)) {
1192 1201 (void) fprintf(stderr,
1193 1202 MSG_INTL(MSG_ERR_BADSYM6), state->file,
1194 1203 state->secname, EC_WORD(symndx),
1195 1204 demangle(symname, state->flags),
1196 1205 EC_WORD(shndx), EC_XWORD(tshdr->sh_size),
1197 1206 EC_XWORD(sym->st_value), EC_XWORD(sym->st_size));
1198 1207 }
1199 1208 }
1200 1209
1201 1210 /*
1202 1211 * A typical symbol table uses the sh_info field to indicate one greater
1203 1212 * than the symbol table index of the last local symbol, STB_LOCAL.
1204 1213 * Therefore, symbol indexes less than sh_info should have local
1205 1214 * binding. Symbol indexes greater than, or equal to sh_info, should
1206 1215 * have global binding. Note, we exclude UNDEF/NOTY symbols with zero
1207 1216 * value and size, as these symbols may be the result of an mcs(1)
1208 1217 * section deletion.
1209 1218 */
1210 1219 if (info) {
1211 1220 uchar_t bind = ELF_ST_BIND(sym->st_info);
1212 1221
1213 1222 if ((symndx < info) && (bind != STB_LOCAL)) {
1214 1223 (void) fprintf(stderr,
1215 1224 MSG_INTL(MSG_ERR_BADSYM7), state->file,
1216 1225 state->secname, EC_WORD(symndx),
1217 1226 demangle(symname, state->flags), EC_XWORD(info));
1218 1227
1219 1228 } else if ((symndx >= info) && (bind == STB_LOCAL) &&
1220 1229 ((sym->st_shndx != SHN_UNDEF) ||
1221 1230 (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) ||
1222 1231 (sym->st_size != 0) || (sym->st_value != 0))) {
1223 1232 (void) fprintf(stderr,
1224 1233 MSG_INTL(MSG_ERR_BADSYM8), state->file,
1225 1234 state->secname, EC_WORD(symndx),
1226 1235 demangle(symname, state->flags), EC_XWORD(info));
1227 1236 }
1228 1237 }
1229 1238
1230 1239 (void) snprintf(index, MAXNDXSIZE,
1231 1240 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(disp_symndx));
1232 1241 Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index, state->osabi,
1233 1242 state->ehdr->e_machine, sym, verndx, gnuver, sec, symname);
1234 1243 }
1235 1244
1236 1245 /*
1237 1246 * Process a SHT_SUNW_cap capabilities section.
1238 1247 */
1239 1248 static int
1240 1249 cap_section(const char *file, Cache *cache, Word shnum, Cache *ccache,
1241 1250 uchar_t osabi, Ehdr *ehdr, uint_t flags)
1242 1251 {
1243 1252 SYMTBL_STATE state;
1244 1253 Word cnum, capnum, nulls, symcaps;
1245 1254 int descapndx, objcap, title;
1246 1255 Cap *cap = (Cap *)ccache->c_data->d_buf;
1247 1256 Shdr *cishdr, *cshdr = ccache->c_shdr;
1248 1257 Cache *cicache, *strcache;
1249 1258 Capinfo *capinfo = NULL;
1250 1259 Word capinfonum;
1251 1260 const char *strs = NULL;
1252 1261 size_t strs_size;
1253 1262
1254 1263 if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) {
1255 1264 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1256 1265 file, ccache->c_name);
1257 1266 return (0);
1258 1267 }
1259 1268
1260 1269 /*
1261 1270 * If this capabilities section is associated with symbols, then the
1262 1271 * sh_link field points to the associated capabilities information
1263 1272 * section. The sh_link field of the capabilities information section
1264 1273 * points to the associated symbol table.
1265 1274 */
1266 1275 if (cshdr->sh_link) {
1267 1276 Cache *scache;
1268 1277 Shdr *sshdr;
1269 1278
1270 1279 /*
1271 1280 * Validate that the sh_link field points to a capabilities
1272 1281 * information section.
1273 1282 */
1274 1283 if (cshdr->sh_link >= shnum) {
1275 1284 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
1276 1285 file, ccache->c_name, EC_WORD(cshdr->sh_link));
1277 1286 return (0);
1278 1287 }
1279 1288
1280 1289 cicache = &cache[cshdr->sh_link];
1281 1290 cishdr = cicache->c_shdr;
1282 1291
1283 1292 if (cishdr->sh_type != SHT_SUNW_capinfo) {
1284 1293 (void) fprintf(stderr, MSG_INTL(MSG_ERR_INVCAP),
1285 1294 file, ccache->c_name, EC_WORD(cshdr->sh_link));
1286 1295 return (0);
1287 1296 }
1288 1297
1289 1298 capinfo = cicache->c_data->d_buf;
1290 1299 capinfonum = (Word)(cishdr->sh_size / cishdr->sh_entsize);
1291 1300
1292 1301 /*
1293 1302 * Validate that the sh_link field of the capabilities
1294 1303 * information section points to a valid symbol table.
1295 1304 */
1296 1305 if ((cishdr->sh_link == 0) || (cishdr->sh_link >= shnum)) {
1297 1306 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
1298 1307 file, cicache->c_name, EC_WORD(cishdr->sh_link));
1299 1308 return (0);
1300 1309 }
1301 1310 scache = &cache[cishdr->sh_link];
1302 1311 sshdr = scache->c_shdr;
1303 1312
1304 1313 if ((sshdr->sh_type != SHT_SYMTAB) &&
1305 1314 (sshdr->sh_type != SHT_DYNSYM)) {
1306 1315 (void) fprintf(stderr, MSG_INTL(MSG_ERR_INVCAPINFO1),
1307 1316 file, cicache->c_name, EC_WORD(cishdr->sh_link));
1308 1317 return (0);
1309 1318 }
1310 1319
1311 1320 if (!init_symtbl_state(&state, cache, shnum,
1312 1321 cishdr->sh_link, ehdr, osabi, NULL, file, flags))
1313 1322 return (0);
1314 1323 }
1315 1324
1316 1325 /*
1317 1326 * If this capabilities section contains capability string entries,
1318 1327 * then determine the associated string table. Capabilities entries
1319 1328 * that define names require that the capability section indicate
1320 1329 * which string table to use via sh_info.
1321 1330 */
1322 1331 if (cshdr->sh_info) {
1323 1332 Shdr *strshdr;
1324 1333
1325 1334 /*
1326 1335 * Validate that the sh_info field points to a string table.
1327 1336 */
1328 1337 if (cshdr->sh_info >= shnum) {
1329 1338 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
1330 1339 file, ccache->c_name, EC_WORD(cshdr->sh_info));
1331 1340 return (0);
1332 1341 }
1333 1342
1334 1343 strcache = &cache[cshdr->sh_info];
1335 1344 strshdr = strcache->c_shdr;
1336 1345
1337 1346 if (strshdr->sh_type != SHT_STRTAB) {
1338 1347 (void) fprintf(stderr, MSG_INTL(MSG_ERR_INVCAP),
1339 1348 file, ccache->c_name, EC_WORD(cshdr->sh_info));
1340 1349 return (0);
1341 1350 }
1342 1351 strs = (const char *)strcache->c_data->d_buf;
1343 1352 strs_size = strcache->c_data->d_size;
1344 1353 }
1345 1354
1346 1355 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1347 1356 dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name);
1348 1357
1349 1358 capnum = (Word)(cshdr->sh_size / cshdr->sh_entsize);
1350 1359
1351 1360 nulls = symcaps = 0;
1352 1361 objcap = title = 1;
1353 1362 descapndx = -1;
1354 1363
1355 1364 /*
1356 1365 * Traverse the capabilities section printing each capability group.
1357 1366 * The first capabilities group defines any object capabilities. Any
1358 1367 * following groups define symbol capabilities. In the case where no
1359 1368 * object capabilities exist, but symbol capabilities do, a single
1360 1369 * CA_SUNW_NULL terminator for the object capabilities exists.
1361 1370 */
1362 1371 for (cnum = 0; cnum < capnum; cap++, cnum++) {
1363 1372 if (cap->c_tag == CA_SUNW_NULL) {
1364 1373 /*
1365 1374 * A CA_SUNW_NULL tag terminates a capabilities group.
1366 1375 * If the first capabilities tag is CA_SUNW_NULL, then
1367 1376 * no object capabilities exist.
1368 1377 */
1369 1378 if ((nulls++ == 0) && (cnum == 0))
1370 1379 objcap = 0;
1371 1380 title = 1;
1372 1381 } else {
1373 1382 if (title) {
1374 1383 if (nulls == 0) {
1375 1384 /*
1376 1385 * If this capabilities group represents
1377 1386 * the object capabilities (i.e., no
1378 1387 * CA_SUNW_NULL tag has been processed
1379 1388 * yet), then display an object
1380 1389 * capabilities title.
1381 1390 */
1382 1391 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1383 1392 dbg_print(0,
1384 1393 MSG_INTL(MSG_OBJ_CAP_TITLE));
1385 1394 } else {
1386 1395 /*
1387 1396 * If this is a symbols capabilities
1388 1397 * group (i.e., a CA_SUNW_NULL tag has
1389 1398 * already be found that terminates
1390 1399 * the object capabilities group), then
1391 1400 * display a symbol capabilities title,
1392 1401 * and retain this capabilities index
1393 1402 * for later processing.
1394 1403 */
1395 1404 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1396 1405 dbg_print(0,
1397 1406 MSG_INTL(MSG_SYM_CAP_TITLE));
1398 1407 descapndx = cnum;
1399 1408 }
1400 1409 Elf_cap_title(0);
1401 1410 title = 0;
1402 1411 }
1403 1412
1404 1413 /*
1405 1414 * Print the capabilities data.
1406 1415 *
1407 1416 * Note that CA_SUNW_PLAT, CA_SUNW_MACH and CA_SUNW_ID
1408 1417 * entries require a string table, which should have
1409 1418 * already been established.
1410 1419 */
1411 1420 if ((strs == NULL) && ((cap->c_tag == CA_SUNW_PLAT) ||
1412 1421 (cap->c_tag == CA_SUNW_MACH) ||
1413 1422 (cap->c_tag == CA_SUNW_ID))) {
1414 1423 (void) fprintf(stderr,
1415 1424 MSG_INTL(MSG_WARN_INVCAP4), file,
1416 1425 EC_WORD(elf_ndxscn(ccache->c_scn)),
1417 1426 ccache->c_name, EC_WORD(cshdr->sh_info));
1418 1427 }
1419 1428 Elf_cap_entry(0, cap, cnum, strs, strs_size,
1420 1429 ehdr->e_machine);
1421 1430 }
1422 1431
1423 1432 /*
1424 1433 * If this CA_SUNW_NULL tag terminates a symbol capabilities
1425 1434 * group, determine the associated symbols.
1426 1435 */
1427 1436 if ((cap->c_tag == CA_SUNW_NULL) && (nulls > 1) &&
1428 1437 (descapndx != -1)) {
1429 1438 Capinfo *cip;
1430 1439 Word inum;
1431 1440
1432 1441 symcaps++;
1433 1442
1434 1443 /*
1435 1444 * Make sure we've discovered a SHT_SUNW_capinfo table.
1436 1445 */
1437 1446 if ((cip = capinfo) == NULL) {
1438 1447 (void) fprintf(stderr,
1439 1448 MSG_INTL(MSG_ERR_INVCAP), file,
1440 1449 ccache->c_name, EC_WORD(cshdr->sh_link));
1441 1450 return (0);
1442 1451 }
1443 1452
1444 1453 /*
1445 1454 * Determine what symbols reference this capabilities
1446 1455 * group.
1447 1456 */
1448 1457 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1449 1458 dbg_print(0, MSG_INTL(MSG_CAPINFO_ENTRIES));
1450 1459 Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
1451 1460
1452 1461 for (inum = 1, cip++; inum < capinfonum;
1453 1462 inum++, cip++) {
1454 1463 Word gndx = (Word)ELF_C_GROUP(*cip);
1455 1464
1456 1465 if (gndx && (gndx == descapndx)) {
1457 1466 output_symbol(&state, inum, 0,
1458 1467 inum, state.sym + inum);
1459 1468 }
1460 1469 }
1461 1470 descapndx = -1;
1462 1471 continue;
1463 1472 }
1464 1473
1465 1474 /*
1466 1475 * An SF1_SUNW_ADDR32 software capability tag in a 32-bit
1467 1476 * object is suspicious as it has no effect.
1468 1477 */
1469 1478 if ((cap->c_tag == CA_SUNW_SF_1) &&
1470 1479 (ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
1471 1480 (cap->c_un.c_val & SF1_SUNW_ADDR32)) {
1472 1481 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INADDR32SF1),
1473 1482 file, ccache->c_name);
1474 1483 }
1475 1484 }
1476 1485
1477 1486 /*
1478 1487 * If this is a dynamic object, with symbol capabilities, then a
1479 1488 * .SUNW_capchain section should exist. This section contains a chain
1480 1489 * of symbol indexes for each capabilities family. This is the list
1481 1490 * that is searched by ld.so.1 to determine the best capabilities
1482 1491 * candidate.
1483 1492 *
1484 1493 * Note, more than one capabilities lead symbol can point to the same
1485 1494 * family chain. For example, a weak/global pair of symbols can both
1486 1495 * represent the same family of capabilities symbols. Therefore, to
1487 1496 * display all possible families we traverse the capabilities
1488 1497 * information section looking for CAPINFO_SUNW_GLOB lead symbols.
1489 1498 * From these we determine the associated capabilities chain to inspect.
1490 1499 */
1491 1500 if (symcaps &&
1492 1501 ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) {
1493 1502 Capinfo *cip;
1494 1503 Capchain *chain;
1495 1504 Cache *chcache;
1496 1505 Shdr *chshdr;
1497 1506 Word chainnum, inum;
1498 1507
1499 1508 /*
1500 1509 * Validate that the sh_info field of the capabilities
1501 1510 * information section points to a capabilities chain section.
1502 1511 */
1503 1512 if (cishdr->sh_info >= shnum) {
1504 1513 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
1505 1514 file, cicache->c_name, EC_WORD(cishdr->sh_info));
1506 1515 return (0);
1507 1516 }
1508 1517
1509 1518 chcache = &cache[cishdr->sh_info];
1510 1519 chshdr = chcache->c_shdr;
1511 1520
1512 1521 if (chshdr->sh_type != SHT_SUNW_capchain) {
1513 1522 (void) fprintf(stderr, MSG_INTL(MSG_ERR_INVCAPINFO2),
1514 1523 file, cicache->c_name, EC_WORD(cishdr->sh_info));
1515 1524 return (0);
1516 1525 }
1517 1526
1518 1527 chainnum = (Word)(chshdr->sh_size / chshdr->sh_entsize);
1519 1528 chain = (Capchain *)chcache->c_data->d_buf;
1520 1529
1521 1530 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1522 1531 dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAPCHAIN), chcache->c_name);
1523 1532
1524 1533 /*
1525 1534 * Traverse the capabilities information section looking for
1526 1535 * CAPINFO_SUNW_GLOB lead capabilities symbols.
1527 1536 */
1528 1537 cip = capinfo;
1529 1538 for (inum = 1, cip++; inum < capinfonum; inum++, cip++) {
1530 1539 const char *name;
1531 1540 Sym *sym;
1532 1541 Word sndx, cndx;
1533 1542 Word gndx = (Word)ELF_C_GROUP(*cip);
1534 1543
1535 1544 if ((gndx == 0) || (gndx != CAPINFO_SUNW_GLOB))
1536 1545 continue;
1537 1546
1538 1547 /*
1539 1548 * Determine the symbol that is associated with this
1540 1549 * capability information entry, and use this to
1541 1550 * identify this capability family.
1542 1551 */
1543 1552 sym = (Sym *)(state.sym + inum);
1544 1553 name = string(cicache, inum, strcache, file,
1545 1554 sym->st_name);
1546 1555
1547 1556 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1548 1557 dbg_print(0, MSG_INTL(MSG_CAPCHAIN_TITLE), name);
1549 1558 dbg_print(0, MSG_INTL(MSG_CAPCHAIN_ENTRY));
1550 1559
1551 1560 cndx = (Word)ELF_C_SYM(*cip);
1552 1561
1553 1562 /*
1554 1563 * Traverse this families chain and identify each
1555 1564 * family member.
1556 1565 */
1557 1566 for (;;) {
1558 1567 char _chain[MAXNDXSIZE], _symndx[MAXNDXSIZE];
1559 1568
1560 1569 if (cndx >= chainnum) {
1561 1570 (void) fprintf(stderr,
1562 1571 MSG_INTL(MSG_ERR_INVCAPINFO3), file,
1563 1572 cicache->c_name, EC_WORD(inum),
1564 1573 EC_WORD(cndx));
1565 1574 break;
1566 1575 }
1567 1576 if ((sndx = chain[cndx]) == 0)
1568 1577 break;
1569 1578
1570 1579 /*
1571 1580 * Determine this entries symbol reference.
1572 1581 */
1573 1582 if (sndx > state.symn) {
1574 1583 (void) fprintf(stderr,
1575 1584 MSG_INTL(MSG_ERR_CHBADSYMNDX), file,
1576 1585 EC_WORD(sndx), chcache->c_name,
1577 1586 EC_WORD(cndx));
1578 1587 name = MSG_INTL(MSG_STR_UNKNOWN);
1579 1588 } else {
1580 1589 sym = (Sym *)(state.sym + sndx);
1581 1590 name = string(chcache, sndx,
1582 1591 strcache, file, sym->st_name);
1583 1592 }
1584 1593
1585 1594 /*
1586 1595 * Display the family member.
1587 1596 */
1588 1597 (void) snprintf(_chain, MAXNDXSIZE,
1589 1598 MSG_ORIG(MSG_FMT_INTEGER), cndx);
1590 1599 (void) snprintf(_symndx, MAXNDXSIZE,
1591 1600 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(sndx));
1592 1601 dbg_print(0, MSG_ORIG(MSG_FMT_CHAIN_INFO),
1593 1602 _chain, _symndx, demangle(name, flags));
1594 1603
1595 1604 cndx++;
1596 1605 }
1597 1606 }
1598 1607 }
1599 1608 return (objcap);
1600 1609 }
1601 1610
1602 1611 /*
1603 1612 * Print the capabilities.
1604 1613 *
1605 1614 * A .SUNW_cap section can contain one or more, CA_SUNW_NULL terminated,
1606 1615 * capabilities groups. The first group defines the object capabilities.
1607 1616 * This group defines the minimum capability requirements of the entire
1608 1617 * object file. If this is a dynamic object, this group should be associated
1609 1618 * with a PT_SUNWCAP program header.
1610 1619 *
1611 1620 * Additional capabilities groups define the association of individual symbols
1612 1621 * to specific capabilities.
1613 1622 */
1614 1623 static void
1615 1624 cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr,
1616 1625 uchar_t osabi, Elf *elf, uint_t flags)
1617 1626 {
1618 1627 Word cnt;
1619 1628 Shdr *cshdr = NULL;
1620 1629 Cache *ccache;
1621 1630 Off cphdr_off = 0;
1622 1631 Xword cphdr_sz;
1623 1632
1624 1633 /*
1625 1634 * Determine if a global capabilities header exists.
1626 1635 */
1627 1636 if (phnum) {
1628 1637 Phdr *phdr;
1629 1638
1630 1639 if ((phdr = elf_getphdr(elf)) == NULL) {
1631 1640 failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
1632 1641 return;
1633 1642 }
1634 1643
1635 1644 for (cnt = 0; cnt < phnum; phdr++, cnt++) {
1636 1645 if (phdr->p_type == PT_SUNWCAP) {
1637 1646 cphdr_off = phdr->p_offset;
1638 1647 cphdr_sz = phdr->p_filesz;
1639 1648 break;
1640 1649 }
1641 1650 }
1642 1651 }
1643 1652
1644 1653 /*
1645 1654 * Determine if a capabilities section exists.
1646 1655 */
1647 1656 for (cnt = 1; cnt < shnum; cnt++) {
1648 1657 Cache *_cache = &cache[cnt];
1649 1658 Shdr *shdr = _cache->c_shdr;
1650 1659
1651 1660 /*
1652 1661 * Process any capabilities information.
1653 1662 */
1654 1663 if (shdr->sh_type == SHT_SUNW_cap) {
1655 1664 if (cap_section(file, cache, shnum, _cache, osabi,
1656 1665 ehdr, flags)) {
1657 1666 /*
1658 1667 * If this section defined an object capability
1659 1668 * group, retain the section information for
1660 1669 * program header validation.
1661 1670 */
1662 1671 ccache = _cache;
1663 1672 cshdr = shdr;
1664 1673 }
1665 1674 continue;
1666 1675 }
1667 1676 }
1668 1677
1669 1678 if ((cshdr == NULL) && (cphdr_off == 0))
1670 1679 return;
1671 1680
1672 1681 if (cphdr_off && (cshdr == NULL))
1673 1682 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file);
1674 1683
1675 1684 /*
1676 1685 * If this object is an executable or shared object, and it provided
1677 1686 * an object capabilities group, then the group should have an
1678 1687 * accompanying PT_SUNWCAP program header.
1679 1688 */
1680 1689 if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) {
1681 1690 if (cphdr_off == 0) {
1682 1691 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2),
1683 1692 file, EC_WORD(elf_ndxscn(ccache->c_scn)),
1684 1693 ccache->c_name);
1685 1694 } else if ((cphdr_off != cshdr->sh_offset) ||
1686 1695 (cphdr_sz != cshdr->sh_size)) {
1687 1696 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3),
1688 1697 file, EC_WORD(elf_ndxscn(ccache->c_scn)),
1689 1698 ccache->c_name);
1690 1699 }
1691 1700 }
1692 1701 }
1693 1702
1694 1703 /*
1695 1704 * Print the interpretor.
1696 1705 */
1697 1706 static void
1698 1707 interp(const char *file, Cache *cache, Word shnum, Word phnum, Elf *elf)
1699 1708 {
1700 1709 static Word phdr_types[] = { PT_INTERP };
1701 1710
1702 1711
1703 1712 Word cnt;
1704 1713 Shdr *ishdr = NULL;
1705 1714 Cache *icache;
1706 1715 Off iphdr_off = 0;
1707 1716 Xword iphdr_fsz;
1708 1717
1709 1718 /*
1710 1719 * Determine if an interp header exists.
1711 1720 */
1712 1721 if (phnum) {
1713 1722 Phdr *phdr;
1714 1723
1715 1724 phdr = getphdr(phnum, phdr_types,
1716 1725 sizeof (phdr_types) / sizeof (*phdr_types), file, elf);
1717 1726 if (phdr != NULL) {
1718 1727 iphdr_off = phdr->p_offset;
1719 1728 iphdr_fsz = phdr->p_filesz;
1720 1729 }
1721 1730 }
1722 1731
1723 1732 if (iphdr_off == 0)
1724 1733 return;
1725 1734
1726 1735 /*
1727 1736 * Determine if an interp section exists.
1728 1737 */
1729 1738 for (cnt = 1; cnt < shnum; cnt++) {
1730 1739 Cache *_cache = &cache[cnt];
1731 1740 Shdr *shdr = _cache->c_shdr;
1732 1741
1733 1742 /*
1734 1743 * Scan sections to find a section which contains the PT_INTERP
1735 1744 * string. The target section can't be in a NOBITS section.
1736 1745 */
1737 1746 if ((shdr->sh_type == SHT_NOBITS) ||
1738 1747 (iphdr_off < shdr->sh_offset) ||
1739 1748 (iphdr_off + iphdr_fsz) > (shdr->sh_offset + shdr->sh_size))
1740 1749 continue;
1741 1750
1742 1751 icache = _cache;
1743 1752 ishdr = shdr;
1744 1753 break;
1745 1754 }
1746 1755
1747 1756 /*
1748 1757 * Print the interpreter string based on the offset defined in the
1749 1758 * program header, as this is the offset used by the kernel.
1750 1759 */
1751 1760 if (ishdr && icache->c_data) {
1752 1761 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1753 1762 dbg_print(0, MSG_INTL(MSG_ELF_SCN_INTERP), icache->c_name);
1754 1763 dbg_print(0, MSG_ORIG(MSG_FMT_INDENT),
1755 1764 (char *)icache->c_data->d_buf +
1756 1765 (iphdr_off - ishdr->sh_offset));
1757 1766 } else
1758 1767 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP1), file);
1759 1768
1760 1769 /*
1761 1770 * If there are any inconsistences between the program header and
1762 1771 * section information, flag them.
1763 1772 */
1764 1773 if (ishdr && ((iphdr_off != ishdr->sh_offset) ||
1765 1774 (iphdr_fsz != ishdr->sh_size))) {
1766 1775 (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVINTERP2), file,
1767 1776 icache->c_name);
1768 1777 }
1769 1778 }
1770 1779
1771 1780 /*
1772 1781 * Print the syminfo section.
1773 1782 */
1774 1783 static void
1775 1784 syminfo(Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi, const char *file)
1776 1785 {
1777 1786 Shdr *infoshdr;
1778 1787 Syminfo *info;
1779 1788 Sym *syms;
1780 1789 Dyn *dyns;
1781 1790 Word infonum, cnt, ndx, symnum, dynnum;
1782 1791 Cache *infocache = NULL, *dyncache = NULL, *symsec, *strsec;
1783 1792 Boolean *dynerr;
1784 1793
1785 1794 for (cnt = 1; cnt < shnum; cnt++) {
1786 1795 if (cache[cnt].c_shdr->sh_type == SHT_SUNW_syminfo) {
1787 1796 infocache = &cache[cnt];
1788 1797 break;
1789 1798 }
1790 1799 }
1791 1800 if (infocache == NULL)
1792 1801 return;
1793 1802
1794 1803 infoshdr = infocache->c_shdr;
1795 1804 if ((infoshdr->sh_entsize == 0) || (infoshdr->sh_size == 0)) {
1796 1805 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1797 1806 file, infocache->c_name);
1798 1807 return;
1799 1808 }
1800 1809 if (infocache->c_data == NULL)
1801 1810 return;
1802 1811
1803 1812 infonum = (Word)(infoshdr->sh_size / infoshdr->sh_entsize);
1804 1813 info = (Syminfo *)infocache->c_data->d_buf;
1805 1814
1806 1815 /*
1807 1816 * If there is no associated dynamic section, determine if one
1808 1817 * is needed, and if so issue a warning. If there is an
1809 1818 * associated dynamic section, validate it and get the data buffer
1810 1819 * for it.
1811 1820 */
1812 1821 dyns = NULL;
1813 1822 dynnum = 0;
1814 1823 if (infoshdr->sh_info == 0) {
1815 1824 Syminfo *_info = info + 1;
1816 1825
1817 1826 for (ndx = 1; ndx < infonum; ndx++, _info++) {
1818 1827 if ((_info->si_flags == 0) && (_info->si_boundto == 0))
1819 1828 continue;
1820 1829
1821 1830 if (_info->si_boundto < SYMINFO_BT_LOWRESERVE)
1822 1831 (void) fprintf(stderr,
1823 1832 MSG_INTL(MSG_ERR_BADSHINFO), file,
1824 1833 infocache->c_name,
1825 1834 EC_WORD(infoshdr->sh_info));
1826 1835 }
1827 1836 } else if ((infoshdr->sh_info >= shnum) ||
1828 1837 (cache[infoshdr->sh_info].c_shdr->sh_type != SHT_DYNAMIC)) {
1829 1838 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO),
1830 1839 file, infocache->c_name, EC_WORD(infoshdr->sh_info));
1831 1840 } else {
1832 1841 dyncache = &cache[infoshdr->sh_info];
1833 1842 if ((dyncache->c_data == NULL) ||
1834 1843 ((dyns = dyncache->c_data->d_buf) == NULL)) {
1835 1844 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
1836 1845 file, dyncache->c_name);
1837 1846 }
1838 1847 if (dyns != NULL) {
1839 1848 dynnum = dyncache->c_shdr->sh_size /
1840 1849 dyncache->c_shdr->sh_entsize;
1841 1850
1842 1851 /*
1843 1852 * We validate the type of dynamic elements referenced
1844 1853 * from the syminfo. This array is used report any
1845 1854 * bad dynamic entries.
1846 1855 */
1847 1856 if ((dynerr = calloc(dynnum, sizeof (*dynerr))) ==
1848 1857 NULL) {
1849 1858 int err = errno;
1850 1859 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
1851 1860 file, strerror(err));
1852 1861 return;
1853 1862 }
1854 1863 }
1855 1864 }
1856 1865
1857 1866 /*
1858 1867 * Get the data buffer for the associated symbol table and string table.
1859 1868 */
1860 1869 if (stringtbl(cache, 1, cnt, shnum, file,
1861 1870 &symnum, &symsec, &strsec) == 0)
1862 1871 return;
1863 1872
1864 1873 syms = symsec->c_data->d_buf;
1865 1874
1866 1875 /*
1867 1876 * Loop through the syminfo entries.
1868 1877 */
1869 1878 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
1870 1879 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMINFO), infocache->c_name);
1871 1880 Elf_syminfo_title(0);
1872 1881
1873 1882 for (ndx = 1, info++; ndx < infonum; ndx++, info++) {
1874 1883 Sym *sym;
1875 1884 const char *needed, *name;
1876 1885 Word expect_dt;
1877 1886 Word boundto = info->si_boundto;
1878 1887
1879 1888 if ((info->si_flags == 0) && (boundto == 0))
1880 1889 continue;
1881 1890
1882 1891 sym = &syms[ndx];
1883 1892 name = string(infocache, ndx, strsec, file, sym->st_name);
1884 1893
1885 1894 /* Is si_boundto set to one of the reserved values? */
1886 1895 if (boundto >= SYMINFO_BT_LOWRESERVE) {
1887 1896 Elf_syminfo_entry(0, ndx, info, name, NULL);
1888 1897 continue;
1889 1898 }
1890 1899
1891 1900 /*
1892 1901 * si_boundto is referencing a dynamic section. If we don't
1893 1902 * have one, an error was already issued above, so it suffices
1894 1903 * to display an empty string. If we are out of bounds, then
1895 1904 * report that and then display an empty string.
1896 1905 */
1897 1906 if ((dyns == NULL) || (boundto >= dynnum)) {
1898 1907 if (dyns != NULL)
1899 1908 (void) fprintf(stderr,
1900 1909 MSG_INTL(MSG_ERR_BADSIDYNNDX), file,
1901 1910 infocache->c_ndx, infocache->c_name,
1902 1911 EC_WORD(ndx), EC_WORD(dynnum - 1),
1903 1912 EC_WORD(boundto));
1904 1913 Elf_syminfo_entry(0, ndx, info, name,
1905 1914 MSG_ORIG(MSG_STR_EMPTY));
1906 1915 continue;
1907 1916 }
1908 1917
1909 1918 /*
1910 1919 * The si_boundto reference expects a specific dynamic element
1911 1920 * type at the given index. The dynamic element is always a
1912 1921 * string that gives an object name. The specific type depends
1913 1922 * on the si_flags present. Ensure that we've got the right
1914 1923 * type.
1915 1924 */
1916 1925 if (info->si_flags & SYMINFO_FLG_FILTER)
1917 1926 expect_dt = DT_SUNW_FILTER;
1918 1927 else if (info->si_flags & SYMINFO_FLG_AUXILIARY)
1919 1928 expect_dt = DT_SUNW_AUXILIARY;
1920 1929 else if (info->si_flags & (SYMINFO_FLG_DIRECT |
1921 1930 SYMINFO_FLG_LAZYLOAD | SYMINFO_FLG_DIRECTBIND))
1922 1931 expect_dt = DT_NEEDED;
1923 1932 else
1924 1933 expect_dt = DT_NULL; /* means we ignore the type */
1925 1934
1926 1935 if ((dyns[boundto].d_tag != expect_dt) &&
1927 1936 (expect_dt != DT_NULL)) {
1928 1937 Conv_inv_buf_t buf1, buf2;
1929 1938
1930 1939 /* Only complain about each dynamic element once */
1931 1940 if (!dynerr[boundto]) {
1932 1941 (void) fprintf(stderr,
1933 1942 MSG_INTL(MSG_ERR_BADSIDYNTAG),
1934 1943 file, infocache->c_ndx, infocache->c_name,
1935 1944 EC_WORD(ndx), dyncache->c_ndx,
1936 1945 dyncache->c_name, EC_WORD(boundto),
1937 1946 conv_dyn_tag(expect_dt, osabi,
1938 1947 ehdr->e_machine, CONV_FMT_ALT_CF, &buf1),
1939 1948 conv_dyn_tag(dyns[boundto].d_tag, osabi,
1940 1949 ehdr->e_machine, CONV_FMT_ALT_CF, &buf2));
1941 1950 dynerr[boundto] = TRUE;
1942 1951 }
1943 1952 }
1944 1953
1945 1954 /*
1946 1955 * Whether or not the DT item we're pointing at is
1947 1956 * of the right type, if it's a type we recognize as
1948 1957 * providing a string, go ahead and show it. Otherwise
1949 1958 * an empty string.
1950 1959 */
1951 1960 switch (dyns[boundto].d_tag) {
1952 1961 case DT_NEEDED:
1953 1962 case DT_SONAME:
1954 1963 case DT_RPATH:
1955 1964 case DT_RUNPATH:
1956 1965 case DT_CONFIG:
1957 1966 case DT_DEPAUDIT:
1958 1967 case DT_USED:
1959 1968 case DT_AUDIT:
1960 1969 case DT_SUNW_AUXILIARY:
1961 1970 case DT_SUNW_FILTER:
1962 1971 case DT_FILTER:
1963 1972 case DT_AUXILIARY:
1964 1973 needed = string(infocache, boundto,
1965 1974 strsec, file, dyns[boundto].d_un.d_val);
1966 1975 break;
1967 1976 default:
1968 1977 needed = MSG_ORIG(MSG_STR_EMPTY);
1969 1978 }
1970 1979 Elf_syminfo_entry(0, ndx, info, name, needed);
1971 1980 }
1972 1981 if (dyns != NULL)
1973 1982 free(dynerr);
1974 1983 }
1975 1984
1976 1985 /*
1977 1986 * Print version definition section entries.
1978 1987 */
1979 1988 static void
1980 1989 version_def(Verdef *vdf, Word vdf_num, Cache *vcache, Cache *scache,
1981 1990 const char *file)
1982 1991 {
1983 1992 Word cnt;
1984 1993 char index[MAXNDXSIZE];
1985 1994
1986 1995 Elf_ver_def_title(0);
1987 1996
1988 1997 for (cnt = 1; cnt <= vdf_num; cnt++,
1989 1998 vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) {
1990 1999 Conv_ver_flags_buf_t ver_flags_buf;
1991 2000 const char *name, *dep;
1992 2001 Half vcnt = vdf->vd_cnt - 1;
1993 2002 Half ndx = vdf->vd_ndx;
1994 2003 Verdaux *vdap = (Verdaux *)((uintptr_t)vdf + vdf->vd_aux);
1995 2004
1996 2005 /*
1997 2006 * Obtain the name and first dependency (if any).
1998 2007 */
1999 2008 name = string(vcache, cnt, scache, file, vdap->vda_name);
2000 2009 vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
2001 2010 if (vcnt)
2002 2011 dep = string(vcache, cnt, scache, file, vdap->vda_name);
2003 2012 else
2004 2013 dep = MSG_ORIG(MSG_STR_EMPTY);
2005 2014
2006 2015 (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX),
2007 2016 EC_XWORD(ndx));
2008 2017 Elf_ver_line_1(0, index, name, dep,
2009 2018 conv_ver_flags(vdf->vd_flags, 0, &ver_flags_buf));
2010 2019
2011 2020 /*
2012 2021 * Print any additional dependencies.
2013 2022 */
2014 2023 if (vcnt) {
2015 2024 vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
2016 2025 for (vcnt--; vcnt; vcnt--,
2017 2026 vdap = (Verdaux *)((uintptr_t)vdap +
2018 2027 vdap->vda_next)) {
2019 2028 dep = string(vcache, cnt, scache, file,
2020 2029 vdap->vda_name);
2021 2030 Elf_ver_line_2(0, MSG_ORIG(MSG_STR_EMPTY), dep);
2022 2031 }
2023 2032 }
2024 2033 }
2025 2034 }
2026 2035
2027 2036 /*
2028 2037 * Print version needed section entries.
2029 2038 *
2030 2039 * entry:
2031 2040 * vnd - Address of verneed data
2032 2041 * vnd_num - # of Verneed entries
2033 2042 * vcache - Cache of verneed section being processed
2034 2043 * scache - Cache of associated string table section
2035 2044 * file - Name of object being processed.
2036 2045 * versym - Information about versym section
2037 2046 *
2038 2047 * exit:
2039 2048 * The versions have been printed. If GNU style versioning
2040 2049 * is in effect, versym->max_verndx has been updated to
2041 2050 * contain the largest version index seen.
2042 2051 *
2043 2052 * note:
2044 2053 * The versym section of an object that follows the original
2045 2054 * Solaris versioning rules only contains indexes into the verdef
2046 2055 * section. Symbols defined in other objects (UNDEF) are given
2047 2056 * a version of 0, indicating that they are not defined by
2048 2057 * this file, and the Verneed entries do not have associated version
2049 2058 * indexes. For these reasons, we do not display a version index
2050 2059 * for original-style Verneed sections.
2051 2060 *
2052 2061 * The GNU versioning extensions alter this: Symbols defined in other
2053 2062 * objects receive a version index in the range above those defined
2054 2063 * by the Verdef section, and the vna_other field of the Vernaux
2055 2064 * structs inside the Verneed section contain the version index for
2056 2065 * that item. We therefore display the index when showing the
2057 2066 * contents of a GNU style Verneed section. You should not
2058 2067 * necessarily expect these indexes to appear in sorted
2059 2068 * order --- it seems that the GNU ld assigns the versions as
2060 2069 * symbols are encountered during linking, and then the results
2061 2070 * are assembled into the Verneed section afterwards.
2062 2071 */
2063 2072 static void
2064 2073 version_need(Verneed *vnd, Word vnd_num, Cache *vcache, Cache *scache,
2065 2074 const char *file, VERSYM_STATE *versym)
2066 2075 {
2067 2076 Word cnt;
2068 2077 char index[MAXNDXSIZE];
2069 2078 const char *index_str;
2070 2079
2071 2080 Elf_ver_need_title(0, versym->gnu_needed);
2072 2081
2073 2082 for (cnt = 1; cnt <= vnd_num; cnt++,
2074 2083 vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) {
2075 2084 Conv_ver_flags_buf_t ver_flags_buf;
2076 2085 const char *name, *dep;
2077 2086 Half vcnt = vnd->vn_cnt;
2078 2087 Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + vnd->vn_aux);
2079 2088
2080 2089 /*
2081 2090 * Obtain the name of the needed file and the version name
2082 2091 * within it that we're dependent on. Note that the count
2083 2092 * should be at least one, otherwise this is a pretty bogus
2084 2093 * entry.
2085 2094 */
2086 2095 name = string(vcache, cnt, scache, file, vnd->vn_file);
2087 2096 if (vcnt)
2088 2097 dep = string(vcache, cnt, scache, file, vnap->vna_name);
2089 2098 else
2090 2099 dep = MSG_INTL(MSG_STR_NULL);
2091 2100
2092 2101 if (vnap->vna_other == 0) { /* Traditional form */
2093 2102 index_str = MSG_ORIG(MSG_STR_EMPTY);
2094 2103 } else { /* GNU form */
2095 2104 index_str = index;
2096 2105 /* Format the version index value */
2097 2106 (void) snprintf(index, MAXNDXSIZE,
2098 2107 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(vnap->vna_other));
2099 2108 if (vnap->vna_other > versym->max_verndx)
2100 2109 versym->max_verndx = vnap->vna_other;
2101 2110 }
2102 2111 Elf_ver_line_1(0, index_str, name, dep,
2103 2112 conv_ver_flags(vnap->vna_flags, 0, &ver_flags_buf));
2104 2113
2105 2114 /*
2106 2115 * Print any additional version dependencies.
2107 2116 */
2108 2117 if (vcnt) {
2109 2118 vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next);
2110 2119 for (vcnt--; vcnt; vcnt--,
2111 2120 vnap = (Vernaux *)((uintptr_t)vnap +
2112 2121 vnap->vna_next)) {
2113 2122 dep = string(vcache, cnt, scache, file,
2114 2123 vnap->vna_name);
2115 2124 if (vnap->vna_other > 0) {
2116 2125 /* Format the next index value */
2117 2126 (void) snprintf(index, MAXNDXSIZE,
2118 2127 MSG_ORIG(MSG_FMT_INDEX),
2119 2128 EC_XWORD(vnap->vna_other));
2120 2129 Elf_ver_line_1(0, index,
2121 2130 MSG_ORIG(MSG_STR_EMPTY), dep,
2122 2131 conv_ver_flags(vnap->vna_flags,
2123 2132 0, &ver_flags_buf));
2124 2133 if (vnap->vna_other >
2125 2134 versym->max_verndx)
2126 2135 versym->max_verndx =
2127 2136 vnap->vna_other;
2128 2137 } else {
2129 2138 Elf_ver_line_3(0,
2130 2139 MSG_ORIG(MSG_STR_EMPTY), dep,
2131 2140 conv_ver_flags(vnap->vna_flags,
2132 2141 0, &ver_flags_buf));
2133 2142 }
2134 2143 }
2135 2144 }
2136 2145 }
2137 2146 }
2138 2147
2139 2148 /*
2140 2149 * Examine the Verneed section for information related to GNU
2141 2150 * style Versym indexing:
2142 2151 * - A non-zero vna_other field indicates that Versym indexes can
2143 2152 * reference Verneed records.
2144 2153 * - If the object uses GNU style Versym indexing, the
2145 2154 * maximum index value is needed to detect bad Versym entries.
2146 2155 *
2147 2156 * entry:
2148 2157 * vnd - Address of verneed data
2149 2158 * vnd_num - # of Verneed entries
2150 2159 * versym - Information about versym section
2151 2160 *
2152 2161 * exit:
2153 2162 * If a non-zero vna_other field is seen, versym->gnu_needed is set.
2154 2163 *
2155 2164 * versym->max_verndx has been updated to contain the largest
2156 2165 * version index seen.
2157 2166 */
2158 2167 static void
2159 2168 update_gnu_verndx(Verneed *vnd, Word vnd_num, VERSYM_STATE *versym)
2160 2169 {
2161 2170 Word cnt;
2162 2171
2163 2172 for (cnt = 1; cnt <= vnd_num; cnt++,
2164 2173 vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) {
2165 2174 Half vcnt = vnd->vn_cnt;
2166 2175 Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + vnd->vn_aux);
2167 2176
2168 2177 /*
2169 2178 * A non-zero value of vna_other indicates that this
2170 2179 * object references VERNEED items from the VERSYM
2171 2180 * array.
2172 2181 */
2173 2182 if (vnap->vna_other != 0) {
2174 2183 versym->gnu_needed = 1;
2175 2184 if (vnap->vna_other > versym->max_verndx)
2176 2185 versym->max_verndx = vnap->vna_other;
2177 2186 }
2178 2187
2179 2188 /*
2180 2189 * Check any additional version dependencies.
2181 2190 */
2182 2191 if (vcnt) {
2183 2192 vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next);
2184 2193 for (vcnt--; vcnt; vcnt--,
2185 2194 vnap = (Vernaux *)((uintptr_t)vnap +
2186 2195 vnap->vna_next)) {
2187 2196 if (vnap->vna_other == 0)
2188 2197 continue;
2189 2198
2190 2199 versym->gnu_needed = 1;
2191 2200 if (vnap->vna_other > versym->max_verndx)
2192 2201 versym->max_verndx = vnap->vna_other;
2193 2202 }
2194 2203 }
2195 2204 }
2196 2205 }
2197 2206
2198 2207 /*
2199 2208 * Display version section information if the flags require it.
2200 2209 * Return version information needed by other output.
2201 2210 *
2202 2211 * entry:
2203 2212 * cache - Cache of all section headers
2204 2213 * shnum - # of sections in cache
2205 2214 * file - Name of file
2206 2215 * flags - Command line option flags
2207 2216 * versym - VERSYM_STATE block to be filled in.
2208 2217 */
2209 2218 static void
2210 2219 versions(Cache *cache, Word shnum, const char *file, uint_t flags,
2211 2220 VERSYM_STATE *versym)
2212 2221 {
2213 2222 GElf_Word cnt;
2214 2223 Cache *verdef_cache = NULL, *verneed_cache = NULL;
2215 2224
2216 2225
2217 2226 /* Gather information about the version sections */
2218 2227 bzero(versym, sizeof (*versym));
2219 2228 versym->max_verndx = 1;
2220 2229 for (cnt = 1; cnt < shnum; cnt++) {
2221 2230 Cache *_cache = &cache[cnt];
2222 2231 Shdr *shdr = _cache->c_shdr;
2223 2232 Dyn *dyn;
2224 2233 ulong_t numdyn;
2225 2234
2226 2235 switch (shdr->sh_type) {
2227 2236 case SHT_DYNAMIC:
2228 2237 /*
2229 2238 * The GNU ld puts a DT_VERSYM entry in the dynamic
2230 2239 * section so that the runtime linker can use it to
2231 2240 * implement their versioning rules. They allow multiple
2232 2241 * incompatible functions with the same name to exist
2233 2242 * in different versions. The Solaris ld does not
2234 2243 * support this mechanism, and as such, does not
2235 2244 * produce DT_VERSYM. We use this fact to determine
2236 2245 * which ld produced this object, and how to interpret
2237 2246 * the version values.
2238 2247 */
2239 2248 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0) ||
2240 2249 (_cache->c_data == NULL))
2241 2250 continue;
2242 2251 numdyn = shdr->sh_size / shdr->sh_entsize;
2243 2252 dyn = (Dyn *)_cache->c_data->d_buf;
2244 2253 for (; numdyn-- > 0; dyn++)
2245 2254 if (dyn->d_tag == DT_VERSYM) {
2246 2255 versym->gnu_full =
2247 2256 versym->gnu_needed = 1;
2248 2257 break;
2249 2258 }
2250 2259 break;
2251 2260
2252 2261 case SHT_SUNW_versym:
2253 2262 /* Record data address for later symbol processing */
2254 2263 if (_cache->c_data != NULL) {
2255 2264 versym->cache = _cache;
2256 2265 versym->data = _cache->c_data->d_buf;
2257 2266 continue;
2258 2267 }
2259 2268 break;
2260 2269
2261 2270 case SHT_SUNW_verdef:
2262 2271 case SHT_SUNW_verneed:
2263 2272 /*
2264 2273 * Ensure the data is non-NULL and the number
2265 2274 * of items is non-zero. Otherwise, we don't
2266 2275 * understand the section, and will not use it.
2267 2276 */
2268 2277 if ((_cache->c_data == NULL) ||
2269 2278 (_cache->c_data->d_buf == NULL)) {
2270 2279 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
2271 2280 file, _cache->c_name);
2272 2281 continue;
2273 2282 }
2274 2283 if (shdr->sh_info == 0) {
2275 2284 (void) fprintf(stderr,
2276 2285 MSG_INTL(MSG_ERR_BADSHINFO),
2277 2286 file, _cache->c_name,
2278 2287 EC_WORD(shdr->sh_info));
2279 2288 continue;
2280 2289 }
2281 2290
2282 2291 /* Make sure the string table index is in range */
2283 2292 if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) {
2284 2293 (void) fprintf(stderr,
2285 2294 MSG_INTL(MSG_ERR_BADSHLINK), file,
2286 2295 _cache->c_name, EC_WORD(shdr->sh_link));
2287 2296 continue;
2288 2297 }
2289 2298
2290 2299 /*
2291 2300 * The section is usable. Save the cache entry.
2292 2301 */
2293 2302 if (shdr->sh_type == SHT_SUNW_verdef) {
2294 2303 verdef_cache = _cache;
2295 2304 /*
2296 2305 * Under Solaris rules, if there is a verdef
2297 2306 * section, the max versym index is number
2298 2307 * of version definitions it supplies.
2299 2308 */
2300 2309 versym->max_verndx = shdr->sh_info;
2301 2310 } else {
2302 2311 verneed_cache = _cache;
2303 2312 }
2304 2313 break;
2305 2314 }
2306 2315 }
2307 2316
2308 2317 /*
2309 2318 * If there is a Verneed section, examine it for information
2310 2319 * related to GNU style versioning.
2311 2320 */
2312 2321 if (verneed_cache != NULL)
2313 2322 update_gnu_verndx((Verneed *)verneed_cache->c_data->d_buf,
2314 2323 verneed_cache->c_shdr->sh_info, versym);
2315 2324
2316 2325 /*
2317 2326 * Now that all the information is available, display the
2318 2327 * Verdef and Verneed section contents, if requested.
2319 2328 */
2320 2329 if ((flags & FLG_SHOW_VERSIONS) == 0)
2321 2330 return;
2322 2331 if (verdef_cache != NULL) {
2323 2332 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2324 2333 dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERDEF),
2325 2334 verdef_cache->c_name);
2326 2335 version_def((Verdef *)verdef_cache->c_data->d_buf,
2327 2336 verdef_cache->c_shdr->sh_info, verdef_cache,
2328 2337 &cache[verdef_cache->c_shdr->sh_link], file);
2329 2338 }
2330 2339 if (verneed_cache != NULL) {
2331 2340 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2332 2341 dbg_print(0, MSG_INTL(MSG_ELF_SCN_VERNEED),
2333 2342 verneed_cache->c_name);
2334 2343 /*
2335 2344 * If GNU versioning applies to this object, version_need()
2336 2345 * will update versym->max_verndx, and it is not
2337 2346 * necessary to call update_gnu_verndx().
2338 2347 */
2339 2348 version_need((Verneed *)verneed_cache->c_data->d_buf,
2340 2349 verneed_cache->c_shdr->sh_info, verneed_cache,
2341 2350 &cache[verneed_cache->c_shdr->sh_link], file, versym);
2342 2351 }
2343 2352 }
2344 2353
2345 2354 /*
2346 2355 * Search for and process any symbol tables.
2347 2356 */
2348 2357 void
2349 2358 symbols(Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi,
2350 2359 VERSYM_STATE *versym, const char *file, uint_t flags)
2351 2360 {
2352 2361 SYMTBL_STATE state;
2353 2362 Cache *_cache;
2354 2363 Word secndx;
2355 2364
2356 2365 for (secndx = 1; secndx < shnum; secndx++) {
2357 2366 Word symcnt;
2358 2367 Shdr *shdr;
2359 2368
2360 2369 _cache = &cache[secndx];
2361 2370 shdr = _cache->c_shdr;
2362 2371
2363 2372 if ((shdr->sh_type != SHT_SYMTAB) &&
2364 2373 (shdr->sh_type != SHT_DYNSYM) &&
2365 2374 ((shdr->sh_type != SHT_SUNW_LDYNSYM) ||
2366 2375 (osabi != ELFOSABI_SOLARIS)))
2367 2376 continue;
2368 2377 if (!match(MATCH_F_ALL, _cache->c_name, secndx, shdr->sh_type))
2369 2378 continue;
2370 2379
2371 2380 if (!init_symtbl_state(&state, cache, shnum, secndx, ehdr,
2372 2381 osabi, versym, file, flags))
2373 2382 continue;
2374 2383 /*
2375 2384 * Loop through the symbol tables entries.
2376 2385 */
2377 2386 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2378 2387 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMTAB), state.secname);
2379 2388 Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
2380 2389
2381 2390 for (symcnt = 0; symcnt < state.symn; symcnt++)
2382 2391 output_symbol(&state, symcnt, shdr->sh_info, symcnt,
2383 2392 state.sym + symcnt);
2384 2393 }
2385 2394 }
2386 2395
2387 2396 /*
2388 2397 * Search for and process any SHT_SUNW_symsort or SHT_SUNW_tlssort sections.
2389 2398 * These sections are always associated with the .SUNW_ldynsym./.dynsym pair.
2390 2399 */
2391 2400 static void
2392 2401 sunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi,
2393 2402 VERSYM_STATE *versym, const char *file, uint_t flags)
2394 2403 {
2395 2404 SYMTBL_STATE ldynsym_state, dynsym_state;
2396 2405 Cache *sortcache, *symcache;
2397 2406 Shdr *sortshdr, *symshdr;
2398 2407 Word sortsecndx, symsecndx;
2399 2408 Word ldynsym_cnt;
2400 2409 Word *ndx;
2401 2410 Word ndxn;
2402 2411 int output_cnt = 0;
2403 2412 Conv_inv_buf_t inv_buf;
2404 2413
2405 2414 for (sortsecndx = 1; sortsecndx < shnum; sortsecndx++) {
2406 2415
2407 2416 sortcache = &cache[sortsecndx];
2408 2417 sortshdr = sortcache->c_shdr;
2409 2418
2410 2419 if ((sortshdr->sh_type != SHT_SUNW_symsort) &&
2411 2420 (sortshdr->sh_type != SHT_SUNW_tlssort))
2412 2421 continue;
2413 2422 if (!match(MATCH_F_ALL, sortcache->c_name, sortsecndx,
2414 2423 sortshdr->sh_type))
2415 2424 continue;
2416 2425
2417 2426 /*
2418 2427 * If the section references a SUNW_ldynsym, then we
2419 2428 * expect to see the associated .dynsym immediately
2420 2429 * following. If it references a .dynsym, there is no
2421 2430 * SUNW_ldynsym. If it is any other type, then we don't
2422 2431 * know what to do with it.
2423 2432 */
2424 2433 if ((sortshdr->sh_link == 0) || (sortshdr->sh_link >= shnum)) {
2425 2434 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
2426 2435 file, sortcache->c_name,
2427 2436 EC_WORD(sortshdr->sh_link));
2428 2437 continue;
2429 2438 }
2430 2439 symcache = &cache[sortshdr->sh_link];
2431 2440 symshdr = symcache->c_shdr;
2432 2441 symsecndx = sortshdr->sh_link;
2433 2442 ldynsym_cnt = 0;
2434 2443 switch (symshdr->sh_type) {
2435 2444 case SHT_SUNW_LDYNSYM:
2436 2445 if (!init_symtbl_state(&ldynsym_state, cache, shnum,
2437 2446 symsecndx, ehdr, osabi, versym, file, flags))
2438 2447 continue;
2439 2448 ldynsym_cnt = ldynsym_state.symn;
2440 2449 /*
2441 2450 * We know that the dynsym follows immediately
2442 2451 * after the SUNW_ldynsym, and so, should be at
2443 2452 * (sortshdr->sh_link + 1). However, elfdump is a
2444 2453 * diagnostic tool, so we do the full paranoid
2445 2454 * search instead.
2446 2455 */
2447 2456 for (symsecndx = 1; symsecndx < shnum; symsecndx++) {
2448 2457 symcache = &cache[symsecndx];
2449 2458 symshdr = symcache->c_shdr;
2450 2459 if (symshdr->sh_type == SHT_DYNSYM)
2451 2460 break;
2452 2461 }
2453 2462 if (symsecndx >= shnum) { /* Dynsym not found! */
2454 2463 (void) fprintf(stderr,
2455 2464 MSG_INTL(MSG_ERR_NODYNSYM),
2456 2465 file, sortcache->c_name);
2457 2466 continue;
2458 2467 }
2459 2468 /* Fallthrough to process associated dynsym */
2460 2469 /* FALLTHROUGH */
2461 2470 case SHT_DYNSYM:
2462 2471 if (!init_symtbl_state(&dynsym_state, cache, shnum,
2463 2472 symsecndx, ehdr, osabi, versym, file, flags))
2464 2473 continue;
2465 2474 break;
2466 2475 default:
2467 2476 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADNDXSEC),
2468 2477 file, sortcache->c_name,
2469 2478 conv_sec_type(osabi, ehdr->e_machine,
2470 2479 symshdr->sh_type, 0, &inv_buf));
2471 2480 continue;
2472 2481 }
2473 2482
2474 2483 /*
2475 2484 * Output header
2476 2485 */
2477 2486 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2478 2487 if (ldynsym_cnt > 0) {
2479 2488 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT2),
2480 2489 sortcache->c_name, ldynsym_state.secname,
2481 2490 dynsym_state.secname);
2482 2491 /*
2483 2492 * The data for .SUNW_ldynsym and dynsym sections
2484 2493 * is supposed to be adjacent with SUNW_ldynsym coming
2485 2494 * first. Check, and issue a warning if it isn't so.
2486 2495 */
2487 2496 if (((ldynsym_state.sym + ldynsym_state.symn)
2488 2497 != dynsym_state.sym) &&
2489 2498 ((flags & FLG_CTL_FAKESHDR) == 0))
2490 2499 (void) fprintf(stderr,
2491 2500 MSG_INTL(MSG_ERR_LDYNNOTADJ), file,
2492 2501 ldynsym_state.secname,
2493 2502 dynsym_state.secname);
2494 2503 } else {
2495 2504 dbg_print(0, MSG_INTL(MSG_ELF_SCN_SYMSORT1),
2496 2505 sortcache->c_name, dynsym_state.secname);
2497 2506 }
2498 2507 Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
2499 2508
2500 2509 /* If not first one, insert a line of white space */
2501 2510 if (output_cnt++ > 0)
2502 2511 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2503 2512
2504 2513 /*
2505 2514 * SUNW_dynsymsort and SUNW_dyntlssort are arrays of
2506 2515 * symbol indices. Iterate over the array entries,
2507 2516 * dispaying the referenced symbols.
2508 2517 */
2509 2518 ndxn = sortshdr->sh_size / sortshdr->sh_entsize;
2510 2519 ndx = (Word *)sortcache->c_data->d_buf;
2511 2520 for (; ndxn-- > 0; ndx++) {
2512 2521 if (*ndx >= ldynsym_cnt) {
2513 2522 Word sec_ndx = *ndx - ldynsym_cnt;
2514 2523
2515 2524 output_symbol(&dynsym_state, sec_ndx, 0,
2516 2525 *ndx, dynsym_state.sym + sec_ndx);
2517 2526 } else {
2518 2527 output_symbol(&ldynsym_state, *ndx, 0,
2519 2528 *ndx, ldynsym_state.sym + *ndx);
2520 2529 }
2521 2530 }
2522 2531 }
2523 2532 }
2524 2533
2525 2534 /*
2526 2535 * Search for and process any relocation sections.
2527 2536 */
2528 2537 static void
2529 2538 reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *file)
2530 2539 {
2531 2540 Word cnt;
2532 2541
2533 2542 for (cnt = 1; cnt < shnum; cnt++) {
2534 2543 Word type, symnum;
2535 2544 Xword relndx, relnum, relsize;
2536 2545 void *rels;
2537 2546 Sym *syms;
2538 2547 Cache *symsec, *strsec;
2539 2548 Cache *_cache = &cache[cnt];
2540 2549 Shdr *shdr = _cache->c_shdr;
2541 2550 char *relname = _cache->c_name;
2542 2551 Conv_inv_buf_t inv_buf;
2543 2552
2544 2553 if (((type = shdr->sh_type) != SHT_RELA) &&
2545 2554 (type != SHT_REL))
2546 2555 continue;
2547 2556 if (!match(MATCH_F_ALL, relname, cnt, type))
2548 2557 continue;
2549 2558
2550 2559 /*
2551 2560 * Decide entry size.
2552 2561 */
2553 2562 if (((relsize = shdr->sh_entsize) == 0) ||
2554 2563 (relsize > shdr->sh_size)) {
2555 2564 if (type == SHT_RELA)
2556 2565 relsize = sizeof (Rela);
2557 2566 else
2558 2567 relsize = sizeof (Rel);
2559 2568 }
2560 2569
2561 2570 /*
2562 2571 * Determine the number of relocations available.
2563 2572 */
2564 2573 if (shdr->sh_size == 0) {
2565 2574 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
2566 2575 file, relname);
2567 2576 continue;
2568 2577 }
2569 2578 if (_cache->c_data == NULL)
2570 2579 continue;
2571 2580
2572 2581 rels = _cache->c_data->d_buf;
2573 2582 relnum = shdr->sh_size / relsize;
2574 2583
2575 2584 /*
2576 2585 * Get the data buffer for the associated symbol table and
2577 2586 * string table.
2578 2587 */
2579 2588 if (stringtbl(cache, 1, cnt, shnum, file,
2580 2589 &symnum, &symsec, &strsec) == 0)
2581 2590 continue;
2582 2591
2583 2592 syms = symsec->c_data->d_buf;
2584 2593
2585 2594 /*
2586 2595 * Loop through the relocation entries.
2587 2596 */
2588 2597 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
2589 2598 dbg_print(0, MSG_INTL(MSG_ELF_SCN_RELOC), _cache->c_name);
2590 2599 Elf_reloc_title(0, ELF_DBG_ELFDUMP, type);
2591 2600
2592 2601 for (relndx = 0; relndx < relnum; relndx++,
2593 2602 rels = (void *)((char *)rels + relsize)) {
2594 2603 Half mach = ehdr->e_machine;
2595 2604 char section[BUFSIZ];
2596 2605 const char *symname;
2597 2606 Word symndx, reltype;
2598 2607 Rela *rela;
2599 2608 Rel *rel;
2600 2609
2601 2610 /*
2602 2611 * Unravel the relocation and determine the symbol with
2603 2612 * which this relocation is associated.
2604 2613 */
2605 2614 if (type == SHT_RELA) {
2606 2615 rela = (Rela *)rels;
2607 2616 symndx = ELF_R_SYM(rela->r_info);
2608 2617 reltype = ELF_R_TYPE(rela->r_info, mach);
2609 2618 } else {
2610 2619 rel = (Rel *)rels;
2611 2620 symndx = ELF_R_SYM(rel->r_info);
2612 2621 reltype = ELF_R_TYPE(rel->r_info, mach);
2613 2622 }
2614 2623
2615 2624 symname = relsymname(cache, _cache, strsec, symndx,
2616 2625 symnum, relndx, syms, section, BUFSIZ, file);
2617 2626
2618 2627 /*
2619 2628 * A zero symbol index is only valid for a few
2620 2629 * relocations.
2621 2630 */
2622 2631 if (symndx == 0) {
2623 2632 int badrel = 0;
2624 2633
2625 2634 if ((mach == EM_SPARC) ||
2626 2635 (mach == EM_SPARC32PLUS) ||
2627 2636 (mach == EM_SPARCV9)) {
2628 2637 if ((reltype != R_SPARC_NONE) &&
2629 2638 (reltype != R_SPARC_REGISTER) &&
2630 2639 (reltype != R_SPARC_RELATIVE))
2631 2640 badrel++;
2632 2641 } else if (mach == EM_386) {
2633 2642 if ((reltype != R_386_NONE) &&
2634 2643 (reltype != R_386_RELATIVE))
2635 2644 badrel++;
2636 2645 } else if (mach == EM_AMD64) {
2637 2646 if ((reltype != R_AMD64_NONE) &&
2638 2647 (reltype != R_AMD64_RELATIVE))
2639 2648 badrel++;
2640 2649 }
2641 2650
2642 2651 if (badrel) {
2643 2652 (void) fprintf(stderr,
2644 2653 MSG_INTL(MSG_ERR_BADREL1), file,
2645 2654 conv_reloc_type(mach, reltype,
2646 2655 0, &inv_buf));
2647 2656 }
2648 2657 }
2649 2658
2650 2659 Elf_reloc_entry_1(0, ELF_DBG_ELFDUMP,
2651 2660 MSG_ORIG(MSG_STR_EMPTY), ehdr->e_machine, type,
2652 2661 rels, relname, symname, 0);
2653 2662 }
2654 2663 }
2655 2664 }
2656 2665
2657 2666
2658 2667 /*
2659 2668 * This value controls which test dyn_test() performs.
2660 2669 */
2661 2670 typedef enum { DYN_TEST_ADDR, DYN_TEST_SIZE, DYN_TEST_ENTSIZE } dyn_test_t;
2662 2671
2663 2672 /*
2664 2673 * Used by dynamic() to compare the value of a dynamic element against
2665 2674 * the starting address of the section it references.
2666 2675 *
2667 2676 * entry:
2668 2677 * test_type - Specify which dyn item is being tested.
2669 2678 * sh_type - SHT_* type value for required section.
2670 2679 * sec_cache - Cache entry for section, or NULL if the object lacks
2671 2680 * a section of this type.
2672 2681 * dyn - Dyn entry to be tested
2673 2682 * dynsec_cnt - # of dynamic section being examined. The first
2674 2683 * dynamic section is 1, the next is 2, and so on...
2675 2684 * ehdr - ELF header for file
2676 2685 * file - Name of file
2677 2686 */
2678 2687 static void
2679 2688 dyn_test(dyn_test_t test_type, Word sh_type, Cache *sec_cache, Dyn *dyn,
2680 2689 Word dynsec_cnt, Ehdr *ehdr, uchar_t osabi, const char *file)
2681 2690 {
2682 2691 Conv_inv_buf_t buf1, buf2;
2683 2692
2684 2693 /*
2685 2694 * These tests are based around the implicit assumption that
2686 2695 * there is only one dynamic section in an object, and also only
2687 2696 * one of the sections it references. We have therefore gathered
2688 2697 * all of the necessary information to test this in a single pass
2689 2698 * over the section headers, which is very efficient. We are not
2690 2699 * aware of any case where more than one dynamic section would
2691 2700 * be meaningful in an ELF object, so this is a reasonable solution.
2692 2701 *
2693 2702 * To test multiple dynamic sections correctly would be more
2694 2703 * expensive in code and time. We would have to build a data structure
2695 2704 * containing all the dynamic elements. Then, we would use the address
2696 2705 * to locate the section it references and ensure the section is of
2697 2706 * the right type and that the address in the dynamic element is
2698 2707 * to the start of the section. Then, we could check the size and
2699 2708 * entsize values against those same sections. This is O(n^2), and
2700 2709 * also complicated.
2701 2710 *
2702 2711 * In the highly unlikely case that there is more than one dynamic
2703 2712 * section, we only test the first one, and simply allow the values
2704 2713 * of the subsequent one to be displayed unchallenged.
2705 2714 */
2706 2715 if (dynsec_cnt != 1)
2707 2716 return;
2708 2717
2709 2718 /*
2710 2719 * A DT_ item that references a section address should always find
2711 2720 * the section in the file.
2712 2721 */
2713 2722 if (sec_cache == NULL) {
2714 2723 const char *name;
2715 2724
2716 2725 /*
2717 2726 * Supply section names instead of section types for
2718 2727 * things that reference progbits so that the error
2719 2728 * message will make more sense.
2720 2729 */
2721 2730 switch (dyn->d_tag) {
2722 2731 case DT_INIT:
2723 2732 name = MSG_ORIG(MSG_ELF_INIT);
2724 2733 break;
2725 2734 case DT_FINI:
2726 2735 name = MSG_ORIG(MSG_ELF_FINI);
2727 2736 break;
2728 2737 default:
2729 2738 name = conv_sec_type(osabi, ehdr->e_machine,
2730 2739 sh_type, 0, &buf1);
2731 2740 break;
2732 2741 }
2733 2742 (void) fprintf(stderr, MSG_INTL(MSG_ERR_DYNNOBCKSEC), file,
2734 2743 name, conv_dyn_tag(dyn->d_tag, osabi, ehdr->e_machine,
2735 2744 CONV_FMT_ALT_CF, &buf2));
2736 2745 return;
2737 2746 }
2738 2747
2739 2748
2740 2749 switch (test_type) {
2741 2750 case DYN_TEST_ADDR:
2742 2751 /* The section address should match the DT_ item value */
2743 2752 if (dyn->d_un.d_val != sec_cache->c_shdr->sh_addr)
2744 2753 (void) fprintf(stderr,
2745 2754 MSG_INTL(MSG_ERR_DYNBADADDR), file,
2746 2755 conv_dyn_tag(dyn->d_tag, osabi, ehdr->e_machine,
2747 2756 CONV_FMT_ALT_CF, &buf1), EC_ADDR(dyn->d_un.d_val),
2748 2757 sec_cache->c_ndx, sec_cache->c_name,
2749 2758 EC_ADDR(sec_cache->c_shdr->sh_addr));
2750 2759 break;
2751 2760
2752 2761 case DYN_TEST_SIZE:
2753 2762 /* The section size should match the DT_ item value */
2754 2763 if (dyn->d_un.d_val != sec_cache->c_shdr->sh_size)
2755 2764 (void) fprintf(stderr,
2756 2765 MSG_INTL(MSG_ERR_DYNBADSIZE), file,
2757 2766 conv_dyn_tag(dyn->d_tag, osabi, ehdr->e_machine,
2758 2767 CONV_FMT_ALT_CF, &buf1), EC_XWORD(dyn->d_un.d_val),
2759 2768 sec_cache->c_ndx, sec_cache->c_name,
2760 2769 EC_XWORD(sec_cache->c_shdr->sh_size));
2761 2770 break;
2762 2771
2763 2772 case DYN_TEST_ENTSIZE:
2764 2773 /* The sh_entsize value should match the DT_ item value */
2765 2774 if (dyn->d_un.d_val != sec_cache->c_shdr->sh_entsize)
2766 2775 (void) fprintf(stderr,
2767 2776 MSG_INTL(MSG_ERR_DYNBADENTSIZE), file,
2768 2777 conv_dyn_tag(dyn->d_tag, osabi, ehdr->e_machine,
2769 2778 CONV_FMT_ALT_CF, &buf1), EC_XWORD(dyn->d_un.d_val),
2770 2779 sec_cache->c_ndx, sec_cache->c_name,
2771 2780 EC_XWORD(sec_cache->c_shdr->sh_entsize));
2772 2781 break;
2773 2782 }
2774 2783 }
2775 2784
2776 2785 /*
2777 2786 * There are some DT_ entries that have corresponding symbols
2778 2787 * (e.g. DT_INIT and _init). It is expected that these items will
2779 2788 * both have the same value if both are present. This routine
2780 2789 * examines the well known symbol tables for such symbols and
2781 2790 * issues warnings for any that don't match.
2782 2791 *
2783 2792 * entry:
2784 2793 * dyn - Dyn entry to be tested
2785 2794 * symname - Name of symbol that corresponds to dyn
2786 2795 * symtab_cache, dynsym_cache, ldynsym_cache - Symbol tables to check
2787 2796 * target_cache - Section the symname section is expected to be
2788 2797 * associated with.
2789 2798 * cache - Cache of all section headers
2790 2799 * shnum - # of sections in cache
2791 2800 * ehdr - ELF header for file
2792 2801 * osabi - OSABI to apply when interpreting object
2793 2802 * file - Name of file
2794 2803 */
2795 2804 static void
2796 2805 dyn_symtest(Dyn *dyn, const char *symname, Cache *symtab_cache,
2797 2806 Cache *dynsym_cache, Cache *ldynsym_cache, Cache *target_cache,
2798 2807 Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi, const char *file)
2799 2808 {
2800 2809 Conv_inv_buf_t buf;
2801 2810 int i;
2802 2811 Sym *sym;
2803 2812 Cache *_cache;
2804 2813
2805 2814 for (i = 0; i < 3; i++) {
2806 2815 switch (i) {
2807 2816 case 0:
2808 2817 _cache = symtab_cache;
2809 2818 break;
2810 2819 case 1:
2811 2820 _cache = dynsym_cache;
2812 2821 break;
2813 2822 case 2:
2814 2823 _cache = ldynsym_cache;
2815 2824 break;
2816 2825 }
2817 2826
2818 2827 if ((_cache != NULL) &&
2819 2828 symlookup(symname, cache, shnum, &sym, target_cache,
2820 2829 _cache, file) && (sym->st_value != dyn->d_un.d_val))
2821 2830 (void) fprintf(stderr, MSG_INTL(MSG_ERR_DYNSYMVAL),
2822 2831 file, _cache->c_name, conv_dyn_tag(dyn->d_tag,
2823 2832 osabi, ehdr->e_machine, CONV_FMT_ALT_CF, &buf),
2824 2833 symname, EC_ADDR(sym->st_value));
2825 2834 }
2826 2835 }
2827 2836
2828 2837 /*
2829 2838 * Search for and process a .dynamic section.
2830 2839 */
2831 2840 static void
2832 2841 dynamic(Cache *cache, Word shnum, Ehdr *ehdr, uchar_t osabi, const char *file)
2833 2842 {
2834 2843 struct {
2835 2844 Cache *symtab;
2836 2845 Cache *dynstr;
2837 2846 Cache *dynsym;
2838 2847 Cache *hash;
2839 2848 Cache *fini;
2840 2849 Cache *fini_array;
2841 2850 Cache *init;
2842 2851 Cache *init_array;
2843 2852 Cache *preinit_array;
2844 2853 Cache *rel;
2845 2854 Cache *rela;
2846 2855 Cache *sunw_cap;
2847 2856 Cache *sunw_capinfo;
2848 2857 Cache *sunw_capchain;
2849 2858 Cache *sunw_ldynsym;
2850 2859 Cache *sunw_move;
2851 2860 Cache *sunw_syminfo;
2852 2861 Cache *sunw_symsort;
2853 2862 Cache *sunw_tlssort;
2854 2863 Cache *sunw_verdef;
2855 2864 Cache *sunw_verneed;
2856 2865 Cache *sunw_versym;
2857 2866 } sec;
2858 2867 Word dynsec_ndx;
2859 2868 Word dynsec_num;
2860 2869 int dynsec_cnt;
2861 2870 Word cnt;
2862 2871 int osabi_solaris = osabi == ELFOSABI_SOLARIS;
2863 2872
2864 2873 /*
2865 2874 * Make a pass over all the sections, gathering section information
2866 2875 * we'll need below.
2867 2876 */
2868 2877 dynsec_num = 0;
2869 2878 bzero(&sec, sizeof (sec));
2870 2879 for (cnt = 1; cnt < shnum; cnt++) {
2871 2880 Cache *_cache = &cache[cnt];
2872 2881
2873 2882 switch (_cache->c_shdr->sh_type) {
2874 2883 case SHT_DYNAMIC:
2875 2884 if (dynsec_num == 0) {
2876 2885 dynsec_ndx = cnt;
2877 2886
2878 2887 /* Does it have a valid string table? */
2879 2888 (void) stringtbl(cache, 0, cnt, shnum, file,
2880 2889 0, 0, &sec.dynstr);
2881 2890 }
2882 2891 dynsec_num++;
2883 2892 break;
2884 2893
2885 2894
2886 2895 case SHT_PROGBITS:
2887 2896 /*
2888 2897 * We want to detect the .init and .fini sections,
2889 2898 * if present. These are SHT_PROGBITS, so all we
2890 2899 * have to go on is the section name. Normally comparing
2891 2900 * names is a bad idea, but there are some special
2892 2901 * names (i.e. .init/.fini/.interp) that are very
2893 2902 * difficult to use in any other context, and for
2894 2903 * these symbols, we do the heuristic match.
2895 2904 */
2896 2905 if (strcmp(_cache->c_name,
2897 2906 MSG_ORIG(MSG_ELF_INIT)) == 0) {
2898 2907 if (sec.init == NULL)
2899 2908 sec.init = _cache;
2900 2909 } else if (strcmp(_cache->c_name,
2901 2910 MSG_ORIG(MSG_ELF_FINI)) == 0) {
2902 2911 if (sec.fini == NULL)
2903 2912 sec.fini = _cache;
2904 2913 }
2905 2914 break;
2906 2915
2907 2916 case SHT_REL:
2908 2917 /*
2909 2918 * We want the SHT_REL section with the lowest
2910 2919 * offset. The linker gathers them together,
2911 2920 * and puts the address of the first one
2912 2921 * into the DT_REL dynamic element.
2913 2922 */
2914 2923 if ((sec.rel == NULL) ||
2915 2924 (_cache->c_shdr->sh_offset <
2916 2925 sec.rel->c_shdr->sh_offset))
2917 2926 sec.rel = _cache;
2918 2927 break;
2919 2928
2920 2929 case SHT_RELA:
2921 2930 /* RELA is handled just like RELA above */
2922 2931 if ((sec.rela == NULL) ||
2923 2932 (_cache->c_shdr->sh_offset <
2924 2933 sec.rela->c_shdr->sh_offset))
2925 2934 sec.rela = _cache;
2926 2935 break;
2927 2936
2928 2937 /*
2929 2938 * The GRAB macro is used for the simple case in which
2930 2939 * we simply grab the first section of the desired type.
2931 2940 */
2932 2941 #define GRAB(_sec_type, _sec_field) \
2933 2942 case _sec_type: \
2934 2943 if (sec._sec_field == NULL) \
2935 2944 sec._sec_field = _cache; \
2936 2945 break
2937 2946 GRAB(SHT_SYMTAB, symtab);
2938 2947 GRAB(SHT_DYNSYM, dynsym);
2939 2948 GRAB(SHT_FINI_ARRAY, fini_array);
2940 2949 GRAB(SHT_HASH, hash);
2941 2950 GRAB(SHT_INIT_ARRAY, init_array);
2942 2951 GRAB(SHT_SUNW_move, sunw_move);
2943 2952 GRAB(SHT_PREINIT_ARRAY, preinit_array);
2944 2953 GRAB(SHT_SUNW_cap, sunw_cap);
2945 2954 GRAB(SHT_SUNW_capinfo, sunw_capinfo);
2946 2955 GRAB(SHT_SUNW_capchain, sunw_capchain);
2947 2956 GRAB(SHT_SUNW_LDYNSYM, sunw_ldynsym);
2948 2957 GRAB(SHT_SUNW_syminfo, sunw_syminfo);
2949 2958 GRAB(SHT_SUNW_symsort, sunw_symsort);
2950 2959 GRAB(SHT_SUNW_tlssort, sunw_tlssort);
2951 2960 GRAB(SHT_SUNW_verdef, sunw_verdef);
2952 2961 GRAB(SHT_SUNW_verneed, sunw_verneed);
2953 2962 GRAB(SHT_SUNW_versym, sunw_versym);
2954 2963 #undef GRAB
2955 2964 }
2956 2965 }
2957 2966
2958 2967 /*
2959 2968 * If no dynamic section, return immediately. If more than one
2960 2969 * dynamic section, then something odd is going on and an error
2961 2970 * is in order, but then continue on and display them all.
2962 2971 */
2963 2972 if (dynsec_num == 0)
2964 2973 return;
2965 2974 if (dynsec_num > 1)
2966 2975 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MULTDYN),
2967 2976 file, EC_WORD(dynsec_num));
2968 2977
2969 2978
2970 2979 dynsec_cnt = 0;
2971 2980 for (cnt = dynsec_ndx; (cnt < shnum) && (dynsec_cnt < dynsec_num);
2972 2981 cnt++) {
2973 2982 Dyn *dyn;
2974 2983 ulong_t numdyn;
2975 2984 int ndx, end_ndx;
2976 2985 Cache *_cache = &cache[cnt], *strsec;
2977 2986 Shdr *shdr = _cache->c_shdr;
2978 2987 int dumped = 0;
2979 2988
2980 2989 if (shdr->sh_type != SHT_DYNAMIC)
2981 2990 continue;
2982 2991 dynsec_cnt++;
2983 2992
2984 2993 /*
2985 2994 * Verify the associated string table section.
2986 2995 */
2987 2996 if (stringtbl(cache, 0, cnt, shnum, file, 0, 0, &strsec) == 0)
2988 2997 continue;
2989 2998
2990 2999 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
2991 3000 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
2992 3001 file, _cache->c_name);
2993 3002 continue;
2994 3003 }
2995 3004 if (_cache->c_data == NULL)
2996 3005 continue;
2997 3006
2998 3007 numdyn = shdr->sh_size / shdr->sh_entsize;
2999 3008 dyn = (Dyn *)_cache->c_data->d_buf;
3000 3009
3001 3010 /*
3002 3011 * We expect the REL/RELA entries to reference the reloc
3003 3012 * section with the lowest address. However, this is
3004 3013 * not true for dumped objects. Detect if this object has
3005 3014 * been dumped so that we can skip the reloc address test
3006 3015 * in that case.
3007 3016 */
3008 3017 for (ndx = 0; ndx < numdyn; dyn++, ndx++) {
3009 3018 if (dyn->d_tag == DT_FLAGS_1) {
3010 3019 dumped = (dyn->d_un.d_val & DF_1_CONFALT) != 0;
3011 3020 break;
3012 3021 }
3013 3022 }
3014 3023 dyn = (Dyn *)_cache->c_data->d_buf;
3015 3024
3016 3025 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3017 3026 dbg_print(0, MSG_INTL(MSG_ELF_SCN_DYNAMIC), _cache->c_name);
3018 3027
3019 3028 Elf_dyn_title(0);
3020 3029
3021 3030 for (ndx = 0; ndx < numdyn; dyn++, ndx++) {
3022 3031 union {
3023 3032 Conv_inv_buf_t inv;
3024 3033 Conv_dyn_flag_buf_t flag;
3025 3034 Conv_dyn_flag1_buf_t flag1;
3026 3035 Conv_dyn_posflag1_buf_t posflag1;
3027 3036 Conv_dyn_feature1_buf_t feature1;
3028 3037 } c_buf;
3029 3038 const char *name = NULL;
3030 3039
3031 3040 /*
3032 3041 * Print the information numerically, and if possible
3033 3042 * as a string. If a string is available, name is
3034 3043 * set to reference it.
3035 3044 *
3036 3045 * Also, take this opportunity to sanity check
3037 3046 * the values of DT elements. In the code above,
3038 3047 * we gathered information on sections that are
3039 3048 * referenced by the dynamic section. Here, we
3040 3049 * compare the attributes of those sections to
3041 3050 * the DT_ items that reference them and report
3042 3051 * on inconsistencies.
3043 3052 *
3044 3053 * Things not currently tested that could be improved
3045 3054 * in later revisions include:
3046 3055 * - We don't check PLT or GOT related items
3047 3056 * - We don't handle computing the lengths of
3048 3057 * relocation arrays. To handle this
3049 3058 * requires examining data that spans
3050 3059 * across sections, in a contiguous span
3051 3060 * within a single segment.
3052 3061 * - DT_VERDEFNUM and DT_VERNEEDNUM can't be
3053 3062 * verified without parsing the sections.
3054 3063 * - We don't handle DT_SUNW_SYMSZ, which would
3055 3064 * be the sum of the lengths of .dynsym and
3056 3065 * .SUNW_ldynsym
3057 3066 * - DT_SUNW_STRPAD can't be verified other than
3058 3067 * to check that it's not larger than
3059 3068 * the string table.
3060 3069 * - Some items come in "all or none" clusters
3061 3070 * that give an address, element size,
3062 3071 * and data length in bytes. We don't
3063 3072 * verify that there are no missing items
3064 3073 * in such groups.
3065 3074 */
3066 3075 switch (dyn->d_tag) {
3067 3076 case DT_NULL:
3068 3077 /*
3069 3078 * Special case: DT_NULLs can come in groups
3070 3079 * that we prefer to reduce to a single line.
3071 3080 */
3072 3081 end_ndx = ndx;
3073 3082 while ((end_ndx < (numdyn - 1)) &&
3074 3083 ((dyn + 1)->d_tag == DT_NULL)) {
3075 3084 dyn++;
3076 3085 end_ndx++;
3077 3086 }
3078 3087 Elf_dyn_null_entry(0, dyn, ndx, end_ndx);
3079 3088 ndx = end_ndx;
3080 3089 continue;
3081 3090
3082 3091 /*
3083 3092 * String items all reference the dynstr. The string()
3084 3093 * function does the necessary sanity checking.
3085 3094 */
3086 3095 case DT_NEEDED:
3087 3096 case DT_SONAME:
3088 3097 case DT_FILTER:
3089 3098 case DT_AUXILIARY:
3090 3099 case DT_CONFIG:
3091 3100 case DT_RPATH:
3092 3101 case DT_RUNPATH:
3093 3102 case DT_USED:
3094 3103 case DT_DEPAUDIT:
3095 3104 case DT_AUDIT:
3096 3105 name = string(_cache, ndx, strsec,
3097 3106 file, dyn->d_un.d_ptr);
3098 3107 break;
3099 3108
3100 3109 case DT_SUNW_AUXILIARY:
3101 3110 case DT_SUNW_FILTER:
3102 3111 if (osabi_solaris)
3103 3112 name = string(_cache, ndx, strsec,
3104 3113 file, dyn->d_un.d_ptr);
3105 3114 break;
3106 3115
3107 3116 case DT_FLAGS:
3108 3117 name = conv_dyn_flag(dyn->d_un.d_val,
3109 3118 0, &c_buf.flag);
3110 3119 break;
3111 3120 case DT_FLAGS_1:
3112 3121 name = conv_dyn_flag1(dyn->d_un.d_val, 0,
3113 3122 &c_buf.flag1);
3114 3123 break;
3115 3124 case DT_POSFLAG_1:
3116 3125 name = conv_dyn_posflag1(dyn->d_un.d_val, 0,
3117 3126 &c_buf.posflag1);
3118 3127 break;
3119 3128 case DT_FEATURE_1:
3120 3129 name = conv_dyn_feature1(dyn->d_un.d_val, 0,
3121 3130 &c_buf.feature1);
3122 3131 break;
3123 3132 case DT_DEPRECATED_SPARC_REGISTER:
3124 3133 name = MSG_INTL(MSG_STR_DEPRECATED);
3125 3134 break;
3126 3135
3127 3136 case DT_SUNW_LDMACH:
3128 3137 if (!osabi_solaris)
3129 3138 break;
3130 3139 name = conv_ehdr_mach((Half)dyn->d_un.d_val,
3131 3140 0, &c_buf.inv);
3132 3141 break;
3133 3142
3134 3143 /*
3135 3144 * Cases below this point are strictly sanity checking,
3136 3145 * and do not generate a name string. The TEST_ macros
3137 3146 * are used to hide the boiler plate arguments neeeded
3138 3147 * by dyn_test().
3139 3148 */
3140 3149 #define TEST_ADDR(_sh_type, _sec_field) \
3141 3150 dyn_test(DYN_TEST_ADDR, _sh_type, \
3142 3151 sec._sec_field, dyn, dynsec_cnt, ehdr, \
3143 3152 osabi, file)
3144 3153 #define TEST_SIZE(_sh_type, _sec_field) \
3145 3154 dyn_test(DYN_TEST_SIZE, _sh_type, \
3146 3155 sec._sec_field, dyn, dynsec_cnt, ehdr, \
3147 3156 osabi, file)
3148 3157 #define TEST_ENTSIZE(_sh_type, _sec_field) \
3149 3158 dyn_test(DYN_TEST_ENTSIZE, _sh_type, \
3150 3159 sec._sec_field, dyn, dynsec_cnt, ehdr, \
3151 3160 osabi, file)
3152 3161
3153 3162 case DT_FINI:
3154 3163 dyn_symtest(dyn, MSG_ORIG(MSG_SYM_FINI),
3155 3164 sec.symtab, sec.dynsym, sec.sunw_ldynsym,
3156 3165 sec.fini, cache, shnum, ehdr, osabi, file);
3157 3166 TEST_ADDR(SHT_PROGBITS, fini);
3158 3167 break;
3159 3168
3160 3169 case DT_FINI_ARRAY:
3161 3170 TEST_ADDR(SHT_FINI_ARRAY, fini_array);
3162 3171 break;
3163 3172
3164 3173 case DT_FINI_ARRAYSZ:
3165 3174 TEST_SIZE(SHT_FINI_ARRAY, fini_array);
3166 3175 break;
3167 3176
3168 3177 case DT_HASH:
3169 3178 TEST_ADDR(SHT_HASH, hash);
3170 3179 break;
3171 3180
3172 3181 case DT_INIT:
3173 3182 dyn_symtest(dyn, MSG_ORIG(MSG_SYM_INIT),
3174 3183 sec.symtab, sec.dynsym, sec.sunw_ldynsym,
3175 3184 sec.init, cache, shnum, ehdr, osabi, file);
3176 3185 TEST_ADDR(SHT_PROGBITS, init);
3177 3186 break;
3178 3187
3179 3188 case DT_INIT_ARRAY:
3180 3189 TEST_ADDR(SHT_INIT_ARRAY, init_array);
3181 3190 break;
3182 3191
3183 3192 case DT_INIT_ARRAYSZ:
3184 3193 TEST_SIZE(SHT_INIT_ARRAY, init_array);
3185 3194 break;
3186 3195
3187 3196 case DT_MOVEENT:
3188 3197 TEST_ENTSIZE(SHT_SUNW_move, sunw_move);
3189 3198 break;
3190 3199
3191 3200 case DT_MOVESZ:
3192 3201 TEST_SIZE(SHT_SUNW_move, sunw_move);
3193 3202 break;
3194 3203
3195 3204 case DT_MOVETAB:
3196 3205 TEST_ADDR(SHT_SUNW_move, sunw_move);
3197 3206 break;
3198 3207
3199 3208 case DT_PREINIT_ARRAY:
3200 3209 TEST_ADDR(SHT_PREINIT_ARRAY, preinit_array);
3201 3210 break;
3202 3211
3203 3212 case DT_PREINIT_ARRAYSZ:
3204 3213 TEST_SIZE(SHT_PREINIT_ARRAY, preinit_array);
3205 3214 break;
3206 3215
3207 3216 case DT_REL:
3208 3217 if (!dumped)
3209 3218 TEST_ADDR(SHT_REL, rel);
3210 3219 break;
3211 3220
3212 3221 case DT_RELENT:
3213 3222 TEST_ENTSIZE(SHT_REL, rel);
3214 3223 break;
3215 3224
3216 3225 case DT_RELA:
3217 3226 if (!dumped)
3218 3227 TEST_ADDR(SHT_RELA, rela);
3219 3228 break;
3220 3229
3221 3230 case DT_RELAENT:
3222 3231 TEST_ENTSIZE(SHT_RELA, rela);
3223 3232 break;
3224 3233
3225 3234 case DT_STRTAB:
3226 3235 TEST_ADDR(SHT_STRTAB, dynstr);
3227 3236 break;
3228 3237
3229 3238 case DT_STRSZ:
3230 3239 TEST_SIZE(SHT_STRTAB, dynstr);
3231 3240 break;
3232 3241
3233 3242 case DT_SUNW_CAP:
3234 3243 if (osabi_solaris)
3235 3244 TEST_ADDR(SHT_SUNW_cap, sunw_cap);
3236 3245 break;
3237 3246
3238 3247 case DT_SUNW_CAPINFO:
3239 3248 if (osabi_solaris)
3240 3249 TEST_ADDR(SHT_SUNW_capinfo,
3241 3250 sunw_capinfo);
3242 3251 break;
3243 3252
3244 3253 case DT_SUNW_CAPCHAIN:
3245 3254 if (osabi_solaris)
3246 3255 TEST_ADDR(SHT_SUNW_capchain,
3247 3256 sunw_capchain);
3248 3257 break;
3249 3258
3250 3259 case DT_SUNW_SYMTAB:
3251 3260 TEST_ADDR(SHT_SUNW_LDYNSYM, sunw_ldynsym);
3252 3261 break;
3253 3262
3254 3263 case DT_SYMENT:
3255 3264 TEST_ENTSIZE(SHT_DYNSYM, dynsym);
3256 3265 break;
3257 3266
3258 3267 case DT_SYMINENT:
3259 3268 TEST_ENTSIZE(SHT_SUNW_syminfo, sunw_syminfo);
3260 3269 break;
3261 3270
3262 3271 case DT_SYMINFO:
3263 3272 TEST_ADDR(SHT_SUNW_syminfo, sunw_syminfo);
3264 3273 break;
3265 3274
3266 3275 case DT_SYMINSZ:
3267 3276 TEST_SIZE(SHT_SUNW_syminfo, sunw_syminfo);
3268 3277 break;
3269 3278
3270 3279 case DT_SYMTAB:
3271 3280 TEST_ADDR(SHT_DYNSYM, dynsym);
3272 3281 break;
3273 3282
3274 3283 case DT_SUNW_SORTENT:
3275 3284 /*
3276 3285 * This entry is related to both the symsort and
3277 3286 * tlssort sections.
3278 3287 */
3279 3288 if (osabi_solaris) {
3280 3289 int test_tls =
3281 3290 (sec.sunw_tlssort != NULL);
3282 3291 int test_sym =
3283 3292 (sec.sunw_symsort != NULL) ||
3284 3293 !test_tls;
3285 3294 if (test_sym)
3286 3295 TEST_ENTSIZE(SHT_SUNW_symsort,
3287 3296 sunw_symsort);
3288 3297 if (test_tls)
3289 3298 TEST_ENTSIZE(SHT_SUNW_tlssort,
3290 3299 sunw_tlssort);
3291 3300 }
3292 3301 break;
3293 3302
3294 3303
3295 3304 case DT_SUNW_SYMSORT:
3296 3305 if (osabi_solaris)
3297 3306 TEST_ADDR(SHT_SUNW_symsort,
3298 3307 sunw_symsort);
3299 3308 break;
3300 3309
3301 3310 case DT_SUNW_SYMSORTSZ:
3302 3311 if (osabi_solaris)
3303 3312 TEST_SIZE(SHT_SUNW_symsort,
3304 3313 sunw_symsort);
3305 3314 break;
3306 3315
3307 3316 case DT_SUNW_TLSSORT:
3308 3317 if (osabi_solaris)
3309 3318 TEST_ADDR(SHT_SUNW_tlssort,
3310 3319 sunw_tlssort);
3311 3320 break;
3312 3321
3313 3322 case DT_SUNW_TLSSORTSZ:
3314 3323 if (osabi_solaris)
3315 3324 TEST_SIZE(SHT_SUNW_tlssort,
3316 3325 sunw_tlssort);
3317 3326 break;
3318 3327
3319 3328 case DT_VERDEF:
3320 3329 TEST_ADDR(SHT_SUNW_verdef, sunw_verdef);
3321 3330 break;
3322 3331
3323 3332 case DT_VERNEED:
3324 3333 TEST_ADDR(SHT_SUNW_verneed, sunw_verneed);
3325 3334 break;
3326 3335
3327 3336 case DT_VERSYM:
3328 3337 TEST_ADDR(SHT_SUNW_versym, sunw_versym);
3329 3338 break;
3330 3339 #undef TEST_ADDR
3331 3340 #undef TEST_SIZE
3332 3341 #undef TEST_ENTSIZE
3333 3342 }
3334 3343
3335 3344 if (name == NULL)
3336 3345 name = MSG_ORIG(MSG_STR_EMPTY);
3337 3346 Elf_dyn_entry(0, dyn, ndx, name,
3338 3347 osabi, ehdr->e_machine);
3339 3348 }
3340 3349 }
3341 3350 }
3342 3351
3343 3352 /*
3344 3353 * Search for and process a MOVE section.
3345 3354 */
3346 3355 static void
3347 3356 move(Cache *cache, Word shnum, const char *file, uint_t flags)
3348 3357 {
3349 3358 Word cnt;
3350 3359 const char *fmt = NULL;
3351 3360
3352 3361 for (cnt = 1; cnt < shnum; cnt++) {
3353 3362 Word movenum, symnum, ndx;
3354 3363 Sym *syms;
3355 3364 Cache *_cache = &cache[cnt];
3356 3365 Shdr *shdr = _cache->c_shdr;
3357 3366 Cache *symsec, *strsec;
3358 3367 Move *move;
3359 3368
3360 3369 if (shdr->sh_type != SHT_SUNW_move)
3361 3370 continue;
3362 3371 if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type))
3363 3372 continue;
3364 3373
3365 3374 /*
3366 3375 * Determine the move data and number.
3367 3376 */
3368 3377 if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) {
3369 3378 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
3370 3379 file, _cache->c_name);
3371 3380 continue;
3372 3381 }
3373 3382 if (_cache->c_data == NULL)
3374 3383 continue;
3375 3384
3376 3385 move = (Move *)_cache->c_data->d_buf;
3377 3386 movenum = shdr->sh_size / shdr->sh_entsize;
3378 3387
3379 3388 /*
3380 3389 * Get the data buffer for the associated symbol table and
3381 3390 * string table.
3382 3391 */
3383 3392 if (stringtbl(cache, 1, cnt, shnum, file,
3384 3393 &symnum, &symsec, &strsec) == 0)
3385 3394 return;
3386 3395
3387 3396 syms = (Sym *)symsec->c_data->d_buf;
3388 3397
3389 3398 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3390 3399 dbg_print(0, MSG_INTL(MSG_ELF_SCN_MOVE), _cache->c_name);
3391 3400 dbg_print(0, MSG_INTL(MSG_MOVE_TITLE));
3392 3401
3393 3402 if (fmt == NULL)
3394 3403 fmt = MSG_INTL(MSG_MOVE_ENTRY);
3395 3404
3396 3405 for (ndx = 0; ndx < movenum; move++, ndx++) {
3397 3406 const char *symname;
3398 3407 char index[MAXNDXSIZE], section[BUFSIZ];
3399 3408 Word symndx, shndx;
3400 3409 Sym *sym;
3401 3410
3402 3411 /*
3403 3412 * Check for null entries
3404 3413 */
3405 3414 if ((move->m_info == 0) && (move->m_value == 0) &&
3406 3415 (move->m_poffset == 0) && (move->m_repeat == 0) &&
3407 3416 (move->m_stride == 0)) {
3408 3417 dbg_print(0, fmt, MSG_ORIG(MSG_STR_EMPTY),
3409 3418 EC_XWORD(move->m_poffset), 0, 0, 0,
3410 3419 EC_LWORD(0), MSG_ORIG(MSG_STR_EMPTY));
3411 3420 continue;
3412 3421 }
3413 3422 if (((symndx = ELF_M_SYM(move->m_info)) == 0) ||
3414 3423 (symndx >= symnum)) {
3415 3424 (void) fprintf(stderr,
3416 3425 MSG_INTL(MSG_ERR_BADMINFO), file,
3417 3426 _cache->c_name, EC_XWORD(move->m_info));
3418 3427
3419 3428 (void) snprintf(index, MAXNDXSIZE,
3420 3429 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx));
3421 3430 dbg_print(0, fmt, index,
3422 3431 EC_XWORD(move->m_poffset),
3423 3432 ELF_M_SIZE(move->m_info), move->m_repeat,
3424 3433 move->m_stride, move->m_value,
3425 3434 MSG_INTL(MSG_STR_UNKNOWN));
3426 3435 continue;
3427 3436 }
3428 3437
3429 3438 symname = relsymname(cache, _cache, strsec,
3430 3439 symndx, symnum, ndx, syms, section, BUFSIZ, file);
3431 3440 sym = (Sym *)(syms + symndx);
3432 3441
3433 3442 /*
3434 3443 * Additional sanity check.
3435 3444 */
3436 3445 shndx = sym->st_shndx;
3437 3446 if (!((shndx == SHN_COMMON) ||
3438 3447 (((shndx >= 1) && (shndx <= shnum)) &&
3439 3448 (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) {
3440 3449 (void) fprintf(stderr,
3441 3450 MSG_INTL(MSG_ERR_BADSYM2), file,
3442 3451 _cache->c_name, EC_WORD(symndx),
3443 3452 demangle(symname, flags));
3444 3453 }
3445 3454
3446 3455 (void) snprintf(index, MAXNDXSIZE,
3447 3456 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(symndx));
3448 3457 dbg_print(0, fmt, index, EC_XWORD(move->m_poffset),
3449 3458 ELF_M_SIZE(move->m_info), move->m_repeat,
3450 3459 move->m_stride, move->m_value,
3451 3460 demangle(symname, flags));
3452 3461 }
3453 3462 }
3454 3463 }
3455 3464
3456 3465 /*
3457 3466 * parse_note_t is used to track the state used by parse_note_entry()
3458 3467 * between calls, and also to return the results of each call.
3459 3468 */
3460 3469 typedef struct {
3461 3470 /* pns_ fields track progress through the data */
3462 3471 const char *pns_file; /* File name */
3463 3472 Cache *pns_cache; /* Note section cache entry */
3464 3473 size_t pns_size; /* # unprocessed data bytes */
3465 3474 Word *pns_data; /* # to next unused data byte */
3466 3475
3467 3476 /* pn_ fields return the results for a single call */
3468 3477 Word pn_namesz; /* Value of note namesz field */
3469 3478 Word pn_descsz; /* Value of note descsz field */
3470 3479 Word pn_type; /* Value of note type field */
3471 3480 const char *pn_name; /* if (namesz > 0) ptr to name bytes */
3472 3481 const char *pn_desc; /* if (descsx > 0) ptr to data bytes */
3473 3482 } parse_note_t;
3474 3483
3475 3484 /*
3476 3485 * Extract the various sub-parts of a note entry, and advance the
3477 3486 * data pointer past it.
3478 3487 *
3479 3488 * entry:
3480 3489 * The state pns_ fields contain current values for the Note section
3481 3490 *
3482 3491 * exit:
3483 3492 * On success, True (1) is returned, the state pns_ fields have been
3484 3493 * advanced to point at the start of the next entry, and the information
3485 3494 * for the recovered note entry is found in the state pn_ fields.
3486 3495 *
3487 3496 * On failure, False (0) is returned. The values contained in state
3488 3497 * are undefined.
3489 3498 */
3490 3499 static int
3491 3500 parse_note_entry(parse_note_t *state)
3492 3501 {
3493 3502 size_t pad, noteoff;
3494 3503
3495 3504 noteoff = (Word)state->pns_cache->c_data->d_size - state->pns_size;
3496 3505 /*
3497 3506 * Make sure we can at least reference the 3 initial entries
3498 3507 * (4-byte words) of the note information block.
3499 3508 */
3500 3509 if (state->pns_size >= (sizeof (Word) * 3)) {
3501 3510 state->pns_size -= (sizeof (Word) * 3);
3502 3511 } else {
3503 3512 (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDATASZ),
3504 3513 state->pns_file, state->pns_cache->c_name,
3505 3514 EC_WORD(noteoff));
3506 3515 return (0);
3507 3516 }
3508 3517
3509 3518 /*
3510 3519 * Make sure any specified name string can be referenced.
3511 3520 */
3512 3521 if ((state->pn_namesz = *state->pns_data++) != 0) {
3513 3522 if (state->pns_size >= state->pn_namesz) {
3514 3523 state->pns_size -= state->pn_namesz;
3515 3524 } else {
3516 3525 (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADNMSZ),
3517 3526 state->pns_file, state->pns_cache->c_name,
3518 3527 EC_WORD(noteoff), EC_WORD(state->pn_namesz));
3519 3528 return (0);
3520 3529 }
3521 3530 }
3522 3531
3523 3532 /*
3524 3533 * Make sure any specified descriptor can be referenced.
3525 3534 */
3526 3535 if ((state->pn_descsz = *state->pns_data++) != 0) {
3527 3536 /*
3528 3537 * If namesz isn't a 4-byte multiple, account for any
3529 3538 * padding that must exist before the descriptor.
3530 3539 */
3531 3540 if ((pad = (state->pn_namesz & (sizeof (Word) - 1))) != 0) {
3532 3541 pad = sizeof (Word) - pad;
3533 3542 state->pns_size -= pad;
3534 3543 }
3535 3544 if (state->pns_size >= state->pn_descsz) {
3536 3545 state->pns_size -= state->pn_descsz;
3537 3546 } else {
3538 3547 (void) fprintf(stderr, MSG_INTL(MSG_NOTE_BADDESZ),
3539 3548 state->pns_file, state->pns_cache->c_name,
3540 3549 EC_WORD(noteoff), EC_WORD(state->pn_namesz));
3541 3550 return (0);
3542 3551 }
3543 3552 }
3544 3553
3545 3554 state->pn_type = *state->pns_data++;
3546 3555
3547 3556 /* Name */
3548 3557 if (state->pn_namesz) {
3549 3558 state->pn_name = (char *)state->pns_data;
3550 3559 pad = (state->pn_namesz +
3551 3560 (sizeof (Word) - 1)) & ~(sizeof (Word) - 1);
3552 3561 /* LINTED */
3553 3562 state->pns_data = (Word *)(state->pn_name + pad);
3554 3563 }
3555 3564
3556 3565 /*
3557 3566 * If multiple information blocks exist within a .note section
3558 3567 * account for any padding that must exist before the next
3559 3568 * information block.
3560 3569 */
3561 3570 if ((pad = (state->pn_descsz & (sizeof (Word) - 1))) != 0) {
3562 3571 pad = sizeof (Word) - pad;
3563 3572 if (state->pns_size > pad)
3564 3573 state->pns_size -= pad;
3565 3574 }
3566 3575
3567 3576 /* Data */
3568 3577 if (state->pn_descsz) {
3569 3578 state->pn_desc = (const char *)state->pns_data;
3570 3579 /* LINTED */
3571 3580 state->pns_data = (Word *)(state->pn_desc +
3572 3581 state->pn_descsz + pad);
3573 3582 }
3574 3583
3575 3584 return (1);
3576 3585 }
3577 3586
3578 3587 /*
3579 3588 * Callback function for use with conv_str_to_c_literal() below.
3580 3589 */
3581 3590 /*ARGSUSED2*/
3582 3591 static void
3583 3592 c_literal_cb(const void *ptr, size_t size, void *uvalue)
3584 3593 {
3585 3594 (void) fwrite(ptr, size, 1, stdout);
3586 3595 }
3587 3596
3588 3597 /*
3589 3598 * Traverse a note section analyzing each note information block.
3590 3599 * The data buffers size is used to validate references before they are made,
3591 3600 * and is decremented as each element is processed.
3592 3601 */
3593 3602 void
3594 3603 note_entry(Cache *cache, Word *data, size_t size, Ehdr *ehdr, const char *file)
3595 3604 {
3596 3605 int cnt = 0;
3597 3606 int is_corenote;
3598 3607 int do_swap;
3599 3608 Conv_inv_buf_t inv_buf;
3600 3609 parse_note_t pnstate;
3601 3610
3602 3611 pnstate.pns_file = file;
3603 3612 pnstate.pns_cache = cache;
3604 3613 pnstate.pns_size = size;
3605 3614 pnstate.pns_data = data;
3606 3615 do_swap = _elf_sys_encoding() != ehdr->e_ident[EI_DATA];
3607 3616
3608 3617 /*
3609 3618 * Print out a single `note' information block.
3610 3619 */
3611 3620 while (pnstate.pns_size > 0) {
3612 3621
3613 3622 if (parse_note_entry(&pnstate) == 0)
3614 3623 return;
3615 3624
3616 3625 /*
3617 3626 * Is this a Solaris core note? Such notes all have
3618 3627 * the name "CORE".
3619 3628 */
3620 3629 is_corenote = (ehdr->e_type == ET_CORE) &&
3621 3630 (pnstate.pn_namesz == (MSG_STR_CORE_SIZE + 1)) &&
3622 3631 (strncmp(MSG_ORIG(MSG_STR_CORE), pnstate.pn_name,
3623 3632 MSG_STR_CORE_SIZE + 1) == 0);
3624 3633
3625 3634 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3626 3635 dbg_print(0, MSG_INTL(MSG_FMT_NOTEENTNDX), EC_WORD(cnt));
3627 3636 cnt++;
3628 3637 dbg_print(0, MSG_ORIG(MSG_NOTE_NAMESZ),
3629 3638 EC_WORD(pnstate.pn_namesz));
3630 3639 dbg_print(0, MSG_ORIG(MSG_NOTE_DESCSZ),
3631 3640 EC_WORD(pnstate.pn_descsz));
3632 3641
3633 3642 if (is_corenote)
3634 3643 dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE_STR),
3635 3644 conv_cnote_type(pnstate.pn_type, 0, &inv_buf));
3636 3645 else
3637 3646 dbg_print(0, MSG_ORIG(MSG_NOTE_TYPE),
3638 3647 EC_WORD(pnstate.pn_type));
3639 3648 if (pnstate.pn_namesz) {
3640 3649 dbg_print(0, MSG_ORIG(MSG_NOTE_NAME));
3641 3650 /*
3642 3651 * The name string can contain embedded 'null'
3643 3652 * bytes and/or unprintable characters. Also,
3644 3653 * the final NULL is documented in the ELF ABI
3645 3654 * as being included in the namesz. So, display
3646 3655 * the name using C literal string notation, and
3647 3656 * include the terminating NULL in the output.
3648 3657 * We don't show surrounding double quotes, as
3649 3658 * that implies the termination that we are showing
3650 3659 * explicitly.
3651 3660 */
3652 3661 (void) fwrite(MSG_ORIG(MSG_STR_8SP),
3653 3662 MSG_STR_8SP_SIZE, 1, stdout);
3654 3663 conv_str_to_c_literal(pnstate.pn_name,
3655 3664 pnstate.pn_namesz, c_literal_cb, NULL);
3656 3665 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3657 3666 }
3658 3667
3659 3668 if (pnstate.pn_descsz) {
3660 3669 int hexdump = 1;
3661 3670
3662 3671 /*
3663 3672 * If this is a core note, let the corenote()
3664 3673 * function handle it.
3665 3674 */
3666 3675 if (is_corenote) {
3667 3676 /* We only issue the bad arch error once */
3668 3677 static int badnote_done = 0;
3669 3678 corenote_ret_t corenote_ret;
3670 3679
3671 3680 corenote_ret = corenote(ehdr->e_machine,
3672 3681 do_swap, pnstate.pn_type, pnstate.pn_desc,
3673 3682 pnstate.pn_descsz);
3674 3683 switch (corenote_ret) {
3675 3684 case CORENOTE_R_OK:
3676 3685 hexdump = 0;
3677 3686 break;
3678 3687 case CORENOTE_R_BADDATA:
3679 3688 (void) fprintf(stderr,
3680 3689 MSG_INTL(MSG_NOTE_BADCOREDATA),
3681 3690 file);
3682 3691 break;
3683 3692 case CORENOTE_R_BADARCH:
3684 3693 if (badnote_done)
3685 3694 break;
3686 3695 (void) fprintf(stderr,
3687 3696 MSG_INTL(MSG_NOTE_BADCOREARCH),
3688 3697 file,
3689 3698 conv_ehdr_mach(ehdr->e_machine,
3690 3699 0, &inv_buf));
3691 3700 break;
3692 3701 }
3693 3702 }
3694 3703
3695 3704 /*
3696 3705 * The default thing when we don't understand
3697 3706 * the note data is to display it as hex bytes.
3698 3707 */
3699 3708 if (hexdump) {
3700 3709 dbg_print(0, MSG_ORIG(MSG_NOTE_DESC));
3701 3710 dump_hex_bytes(pnstate.pn_desc,
3702 3711 pnstate.pn_descsz, 8, 4, 4);
3703 3712 }
3704 3713 }
3705 3714 }
3706 3715 }
3707 3716
3708 3717 /*
3709 3718 * Search for and process .note sections.
3710 3719 *
3711 3720 * Returns the number of note sections seen.
3712 3721 */
3713 3722 static Word
3714 3723 note(Cache *cache, Word shnum, Ehdr *ehdr, const char *file)
3715 3724 {
3716 3725 Word cnt, note_cnt = 0;
3717 3726
3718 3727 /*
3719 3728 * Otherwise look for any .note sections.
3720 3729 */
3721 3730 for (cnt = 1; cnt < shnum; cnt++) {
3722 3731 Cache *_cache = &cache[cnt];
3723 3732 Shdr *shdr = _cache->c_shdr;
3724 3733
3725 3734 if (shdr->sh_type != SHT_NOTE)
3726 3735 continue;
3727 3736 note_cnt++;
3728 3737 if (!match(MATCH_F_ALL, _cache->c_name, cnt, shdr->sh_type))
3729 3738 continue;
3730 3739
3731 3740 /*
3732 3741 * As these sections are often hand rolled, make sure they're
3733 3742 * properly aligned before proceeding, and issue an error
3734 3743 * as necessary.
3735 3744 *
3736 3745 * Note that we will continue on to display the note even
3737 3746 * if it has bad alignment. We can do this safely, because
3738 3747 * libelf knows the alignment required for SHT_NOTE, and
3739 3748 * takes steps to deliver a properly aligned buffer to us
3740 3749 * even if the actual file is misaligned.
3741 3750 */
3742 3751 if (shdr->sh_offset & (sizeof (Word) - 1))
3743 3752 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADALIGN),
3744 3753 file, _cache->c_name);
3745 3754
3746 3755 if (_cache->c_data == NULL)
3747 3756 continue;
3748 3757
3749 3758 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3750 3759 dbg_print(0, MSG_INTL(MSG_ELF_SCN_NOTE), _cache->c_name);
3751 3760 note_entry(_cache, (Word *)_cache->c_data->d_buf,
3752 3761 /* LINTED */
3753 3762 (Word)_cache->c_data->d_size, ehdr, file);
3754 3763 }
3755 3764
3756 3765 return (note_cnt);
3757 3766 }
3758 3767
3759 3768 /*
3760 3769 * The Linux Standard Base defines a special note named .note.ABI-tag
3761 3770 * that is used to maintain Linux ABI information. Presence of this section
3762 3771 * is a strong indication that the object should be considered to be
3763 3772 * ELFOSABI_LINUX.
3764 3773 *
3765 3774 * This function returns True (1) if such a note is seen, and False (0)
3766 3775 * otherwise.
3767 3776 */
3768 3777 static int
3769 3778 has_linux_abi_note(Cache *cache, Word shnum, const char *file)
3770 3779 {
3771 3780 Word cnt;
3772 3781
3773 3782 for (cnt = 1; cnt < shnum; cnt++) {
3774 3783 parse_note_t pnstate;
3775 3784 Cache *_cache = &cache[cnt];
3776 3785 Shdr *shdr = _cache->c_shdr;
3777 3786
3778 3787 /*
3779 3788 * Section must be SHT_NOTE, must have the name
3780 3789 * .note.ABI-tag, and must have data.
3781 3790 */
3782 3791 if ((shdr->sh_type != SHT_NOTE) ||
3783 3792 (strcmp(MSG_ORIG(MSG_STR_NOTEABITAG),
3784 3793 _cache->c_name) != 0) || (_cache->c_data == NULL))
3785 3794 continue;
3786 3795
3787 3796 pnstate.pns_file = file;
3788 3797 pnstate.pns_cache = _cache;
3789 3798 pnstate.pns_size = _cache->c_data->d_size;
3790 3799 pnstate.pns_data = (Word *)_cache->c_data->d_buf;
3791 3800
3792 3801 while (pnstate.pns_size > 0) {
3793 3802 Word *w;
3794 3803
3795 3804 if (parse_note_entry(&pnstate) == 0)
3796 3805 break;
3797 3806
3798 3807 /*
3799 3808 * The type must be 1, and the name must be "GNU".
3800 3809 * The descsz must be at least 16 bytes.
3801 3810 */
3802 3811 if ((pnstate.pn_type != 1) ||
3803 3812 (pnstate.pn_namesz != (MSG_STR_GNU_SIZE + 1)) ||
3804 3813 (strncmp(MSG_ORIG(MSG_STR_GNU), pnstate.pn_name,
3805 3814 MSG_STR_CORE_SIZE + 1) != 0) ||
3806 3815 (pnstate.pn_descsz < 16))
3807 3816 continue;
3808 3817
3809 3818 /*
3810 3819 * desc contains 4 32-bit fields. Field 0 must be 0,
3811 3820 * indicating Linux. The second, third, and fourth
3812 3821 * fields represent the earliest Linux kernel
3813 3822 * version compatible with this object.
3814 3823 */
3815 3824 /*LINTED*/
3816 3825 w = (Word *) pnstate.pn_desc;
3817 3826 if (*w == 0)
3818 3827 return (1);
3819 3828 }
3820 3829 }
3821 3830
3822 3831 return (0);
3823 3832 }
3824 3833
3825 3834 /*
3826 3835 * Determine an individual hash entry. This may be the initial hash entry,
3827 3836 * or an associated chain entry.
3828 3837 */
3829 3838 static void
3830 3839 hash_entry(Cache *refsec, Cache *strsec, const char *hsecname, Word hashndx,
3831 3840 Word symndx, Word symn, Sym *syms, const char *file, ulong_t bkts,
3832 3841 uint_t flags, int chain)
3833 3842 {
3834 3843 Sym *sym;
3835 3844 const char *symname, *str;
3836 3845 char _bucket[MAXNDXSIZE], _symndx[MAXNDXSIZE];
3837 3846 ulong_t nbkt, nhash;
3838 3847
3839 3848 if (symndx > symn) {
3840 3849 (void) fprintf(stderr, MSG_INTL(MSG_ERR_HSBADSYMNDX), file,
3841 3850 EC_WORD(symndx), EC_WORD(hashndx));
3842 3851 symname = MSG_INTL(MSG_STR_UNKNOWN);
3843 3852 } else {
3844 3853 sym = (Sym *)(syms + symndx);
3845 3854 symname = string(refsec, symndx, strsec, file, sym->st_name);
3846 3855 }
3847 3856
3848 3857 if (chain == 0) {
3849 3858 (void) snprintf(_bucket, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER),
3850 3859 hashndx);
3851 3860 str = (const char *)_bucket;
3852 3861 } else
3853 3862 str = MSG_ORIG(MSG_STR_EMPTY);
3854 3863
3855 3864 (void) snprintf(_symndx, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX2),
3856 3865 EC_WORD(symndx));
3857 3866 dbg_print(0, MSG_ORIG(MSG_FMT_HASH_INFO), str, _symndx,
3858 3867 demangle(symname, flags));
3859 3868
3860 3869 /*
3861 3870 * Determine if this string is in the correct bucket.
3862 3871 */
3863 3872 nhash = elf_hash(symname);
3864 3873 nbkt = nhash % bkts;
3865 3874
3866 3875 if (nbkt != hashndx) {
3867 3876 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADHASH), file,
3868 3877 hsecname, symname, EC_WORD(hashndx), nbkt);
3869 3878 }
3870 3879 }
3871 3880
3872 3881 #define MAXCOUNT 500
3873 3882
3874 3883 static void
3875 3884 hash(Cache *cache, Word shnum, const char *file, uint_t flags)
3876 3885 {
3877 3886 static int count[MAXCOUNT];
3878 3887 Word cnt;
3879 3888 ulong_t ndx, bkts;
3880 3889 char number[MAXNDXSIZE];
3881 3890
3882 3891 for (cnt = 1; cnt < shnum; cnt++) {
3883 3892 uint_t *hash, *chain;
3884 3893 Cache *_cache = &cache[cnt];
3885 3894 Shdr *sshdr, *hshdr = _cache->c_shdr;
3886 3895 char *ssecname, *hsecname = _cache->c_name;
3887 3896 Sym *syms;
3888 3897 Word symn;
3889 3898
3890 3899 if (hshdr->sh_type != SHT_HASH)
3891 3900 continue;
3892 3901
3893 3902 /*
3894 3903 * Determine the hash table data and size.
3895 3904 */
3896 3905 if ((hshdr->sh_entsize == 0) || (hshdr->sh_size == 0)) {
3897 3906 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
3898 3907 file, hsecname);
3899 3908 continue;
3900 3909 }
3901 3910 if (_cache->c_data == NULL)
3902 3911 continue;
3903 3912
3904 3913 hash = (uint_t *)_cache->c_data->d_buf;
3905 3914 bkts = *hash;
3906 3915 chain = hash + 2 + bkts;
3907 3916 hash += 2;
3908 3917
3909 3918 /*
3910 3919 * Get the data buffer for the associated symbol table.
3911 3920 */
3912 3921 if ((hshdr->sh_link == 0) || (hshdr->sh_link >= shnum)) {
3913 3922 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
3914 3923 file, hsecname, EC_WORD(hshdr->sh_link));
3915 3924 continue;
3916 3925 }
3917 3926
3918 3927 _cache = &cache[hshdr->sh_link];
3919 3928 ssecname = _cache->c_name;
3920 3929
3921 3930 if (_cache->c_data == NULL)
3922 3931 continue;
3923 3932
3924 3933 if ((syms = (Sym *)_cache->c_data->d_buf) == NULL) {
3925 3934 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
3926 3935 file, ssecname);
3927 3936 continue;
3928 3937 }
3929 3938
3930 3939 sshdr = _cache->c_shdr;
3931 3940 /* LINTED */
3932 3941 symn = (Word)(sshdr->sh_size / sshdr->sh_entsize);
3933 3942
3934 3943 /*
3935 3944 * Get the associated string table section.
3936 3945 */
3937 3946 if ((sshdr->sh_link == 0) || (sshdr->sh_link >= shnum)) {
3938 3947 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK),
3939 3948 file, ssecname, EC_WORD(sshdr->sh_link));
3940 3949 continue;
3941 3950 }
3942 3951
3943 3952 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3944 3953 dbg_print(0, MSG_INTL(MSG_ELF_SCN_HASH), hsecname);
3945 3954 dbg_print(0, MSG_INTL(MSG_ELF_HASH_INFO));
3946 3955
3947 3956 /*
3948 3957 * Loop through the hash buckets, printing the appropriate
3949 3958 * symbols.
3950 3959 */
3951 3960 for (ndx = 0; ndx < bkts; ndx++, hash++) {
3952 3961 Word _ndx, _cnt;
3953 3962
3954 3963 if (*hash == 0) {
3955 3964 count[0]++;
3956 3965 continue;
3957 3966 }
3958 3967
3959 3968 hash_entry(_cache, &cache[sshdr->sh_link], hsecname,
3960 3969 ndx, *hash, symn, syms, file, bkts, flags, 0);
3961 3970
3962 3971 /*
3963 3972 * Determine if any other symbols are chained to this
3964 3973 * bucket.
3965 3974 */
3966 3975 _ndx = chain[*hash];
3967 3976 _cnt = 1;
3968 3977 while (_ndx) {
3969 3978 hash_entry(_cache, &cache[sshdr->sh_link],
3970 3979 hsecname, ndx, _ndx, symn, syms, file,
3971 3980 bkts, flags, 1);
3972 3981 _ndx = chain[_ndx];
3973 3982 _cnt++;
3974 3983 }
3975 3984
3976 3985 if (_cnt >= MAXCOUNT) {
3977 3986 (void) fprintf(stderr,
3978 3987 MSG_INTL(MSG_HASH_OVERFLW), file,
3979 3988 _cache->c_name, EC_WORD(ndx),
3980 3989 EC_WORD(_cnt));
3981 3990 } else
3982 3991 count[_cnt]++;
3983 3992 }
3984 3993 break;
3985 3994 }
3986 3995
3987 3996 /*
3988 3997 * Print out the count information.
3989 3998 */
3990 3999 bkts = cnt = 0;
3991 4000 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
3992 4001
3993 4002 for (ndx = 0; ndx < MAXCOUNT; ndx++) {
3994 4003 Word _cnt;
3995 4004
3996 4005 if ((_cnt = count[ndx]) == 0)
3997 4006 continue;
3998 4007
3999 4008 (void) snprintf(number, MAXNDXSIZE,
4000 4009 MSG_ORIG(MSG_FMT_INTEGER), _cnt);
4001 4010 dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS1), number,
4002 4011 EC_WORD(ndx));
4003 4012 bkts += _cnt;
4004 4013 cnt += (Word)(ndx * _cnt);
4005 4014 }
4006 4015 if (cnt) {
4007 4016 (void) snprintf(number, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INTEGER),
4008 4017 bkts);
4009 4018 dbg_print(0, MSG_INTL(MSG_ELF_HASH_BKTS2), number,
4010 4019 EC_WORD(cnt));
4011 4020 }
4012 4021 }
4013 4022
4014 4023 static void
4015 4024 group(Cache *cache, Word shnum, const char *file, uint_t flags)
4016 4025 {
4017 4026 Word scnt;
4018 4027
4019 4028 for (scnt = 1; scnt < shnum; scnt++) {
4020 4029 Cache *_cache = &cache[scnt];
4021 4030 Shdr *shdr = _cache->c_shdr;
4022 4031 Word *grpdata, gcnt, grpcnt, symnum, unknown;
4023 4032 Cache *symsec, *strsec;
4024 4033 Sym *syms, *sym;
4025 4034 char flgstrbuf[MSG_GRP_COMDAT_SIZE + 10];
4026 4035 const char *grpnam;
4027 4036
4028 4037 if (shdr->sh_type != SHT_GROUP)
4029 4038 continue;
4030 4039 if (!match(MATCH_F_ALL, _cache->c_name, scnt, shdr->sh_type))
4031 4040 continue;
4032 4041 if ((_cache->c_data == NULL) ||
4033 4042 ((grpdata = (Word *)_cache->c_data->d_buf) == NULL))
4034 4043 continue;
4035 4044 grpcnt = shdr->sh_size / sizeof (Word);
4036 4045
4037 4046 /*
4038 4047 * Get the data buffer for the associated symbol table and
4039 4048 * string table.
4040 4049 */
4041 4050 if (stringtbl(cache, 1, scnt, shnum, file,
4042 4051 &symnum, &symsec, &strsec) == 0)
4043 4052 return;
4044 4053
4045 4054 syms = symsec->c_data->d_buf;
4046 4055
4047 4056 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
4048 4057 dbg_print(0, MSG_INTL(MSG_ELF_SCN_GRP), _cache->c_name);
4049 4058 dbg_print(0, MSG_INTL(MSG_GRP_TITLE));
4050 4059
4051 4060 /*
4052 4061 * The first element of the group defines the group. The
4053 4062 * associated symbol is defined by the sh_link field.
4054 4063 */
4055 4064 if ((shdr->sh_info == SHN_UNDEF) || (shdr->sh_info > symnum)) {
4056 4065 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHINFO),
4057 4066 file, _cache->c_name, EC_WORD(shdr->sh_info));
4058 4067 return;
4059 4068 }
4060 4069
4061 4070 (void) strcpy(flgstrbuf, MSG_ORIG(MSG_STR_OSQBRKT));
4062 4071 if (grpdata[0] & GRP_COMDAT) {
4063 4072 (void) strcat(flgstrbuf, MSG_ORIG(MSG_GRP_COMDAT));
4064 4073 }
4065 4074 if ((unknown = (grpdata[0] & ~GRP_COMDAT)) != 0) {
4066 4075 size_t len = strlen(flgstrbuf);
4067 4076
4068 4077 (void) snprintf(&flgstrbuf[len],
4069 4078 (MSG_GRP_COMDAT_SIZE + 10 - len),
4070 4079 MSG_ORIG(MSG_GRP_UNKNOWN), unknown);
4071 4080 }
4072 4081 (void) strcat(flgstrbuf, MSG_ORIG(MSG_STR_CSQBRKT));
4073 4082 sym = (Sym *)(syms + shdr->sh_info);
4074 4083
4075 4084 /*
4076 4085 * The GNU assembler can use section symbols as the signature
4077 4086 * symbol as described by this comment in the gold linker
4078 4087 * (found via google):
4079 4088 *
4080 4089 * It seems that some versions of gas will create a
4081 4090 * section group associated with a section symbol, and
4082 4091 * then fail to give a name to the section symbol. In
4083 4092 * such a case, use the name of the section.
4084 4093 *
4085 4094 * In order to support such objects, we do the same.
4086 4095 */
4087 4096 grpnam = string(_cache, 0, strsec, file, sym->st_name);
4088 4097 if (((sym->st_name == 0) || (*grpnam == '\0')) &&
4089 4098 (ELF_ST_TYPE(sym->st_info) == STT_SECTION))
4090 4099 grpnam = cache[sym->st_shndx].c_name;
4091 4100
4092 4101 dbg_print(0, MSG_INTL(MSG_GRP_SIGNATURE), flgstrbuf,
4093 4102 demangle(grpnam, flags));
4094 4103
4095 4104 for (gcnt = 1; gcnt < grpcnt; gcnt++) {
4096 4105 char index[MAXNDXSIZE];
4097 4106 const char *name;
4098 4107
4099 4108 (void) snprintf(index, MAXNDXSIZE,
4100 4109 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(gcnt));
4101 4110
4102 4111 if (grpdata[gcnt] >= shnum)
4103 4112 name = MSG_INTL(MSG_GRP_INVALSCN);
4104 4113 else
4105 4114 name = cache[grpdata[gcnt]].c_name;
4106 4115
4107 4116 (void) printf(MSG_ORIG(MSG_GRP_ENTRY), index, name,
4108 4117 EC_XWORD(grpdata[gcnt]));
4109 4118 }
4110 4119 }
4111 4120 }
4112 4121
4113 4122 static void
4114 4123 got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file)
4115 4124 {
4116 4125 Cache *gotcache = NULL, *symtab = NULL;
4117 4126 Addr gotbgn, gotend;
4118 4127 Shdr *gotshdr;
4119 4128 Word cnt, gotents, gotndx;
4120 4129 size_t gentsize;
4121 4130 Got_info *gottable;
4122 4131 char *gotdata;
4123 4132 Sym *gotsym;
4124 4133 Xword gotsymaddr;
4125 4134 uint_t sys_encoding;
4126 4135
4127 4136 /*
4128 4137 * First, find the got.
4129 4138 */
4130 4139 for (cnt = 1; cnt < shnum; cnt++) {
4131 4140 if (strncmp(cache[cnt].c_name, MSG_ORIG(MSG_ELF_GOT),
4132 4141 MSG_ELF_GOT_SIZE) == 0) {
4133 4142 gotcache = &cache[cnt];
4134 4143 break;
4135 4144 }
4136 4145 }
4137 4146 if (gotcache == NULL)
4138 4147 return;
4139 4148
4140 4149 /*
4141 4150 * A got section within a relocatable object is suspicious.
4142 4151 */
4143 4152 if (ehdr->e_type == ET_REL) {
4144 4153 (void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file,
4145 4154 gotcache->c_name);
4146 4155 }
4147 4156
4148 4157 gotshdr = gotcache->c_shdr;
4149 4158 if (gotshdr->sh_size == 0) {
4150 4159 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
4151 4160 file, gotcache->c_name);
4152 4161 return;
4153 4162 }
4154 4163
4155 4164 gotbgn = gotshdr->sh_addr;
4156 4165 gotend = gotbgn + gotshdr->sh_size;
4157 4166
4158 4167 /*
4159 4168 * Some architectures don't properly set the sh_entsize for the GOT
4160 4169 * table. If it's not set, default to a size of a pointer.
4161 4170 */
4162 4171 if ((gentsize = gotshdr->sh_entsize) == 0)
4163 4172 gentsize = sizeof (Xword);
4164 4173
4165 4174 if (gotcache->c_data == NULL)
4166 4175 return;
4167 4176
4168 4177 /* LINTED */
4169 4178 gotents = (Word)(gotshdr->sh_size / gentsize);
4170 4179 gotdata = gotcache->c_data->d_buf;
4171 4180
4172 4181 if ((gottable = calloc(gotents, sizeof (Got_info))) == 0) {
4173 4182 int err = errno;
4174 4183 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC), file,
4175 4184 strerror(err));
4176 4185 return;
4177 4186 }
4178 4187
4179 4188 /*
4180 4189 * Now we scan through all the sections looking for any relocations
4181 4190 * that may be against the GOT. Since these may not be isolated to a
4182 4191 * .rel[a].got section we check them all.
4183 4192 * While scanning sections save the symbol table entry (a symtab
4184 4193 * overriding a dynsym) so that we can lookup _GLOBAL_OFFSET_TABLE_.
4185 4194 */
4186 4195 for (cnt = 1; cnt < shnum; cnt++) {
4187 4196 Word type, symnum;
4188 4197 Xword relndx, relnum, relsize;
4189 4198 void *rels;
4190 4199 Sym *syms;
4191 4200 Cache *symsec, *strsec;
4192 4201 Cache *_cache = &cache[cnt];
4193 4202 Shdr *shdr;
4194 4203
4195 4204 shdr = _cache->c_shdr;
4196 4205 type = shdr->sh_type;
4197 4206
4198 4207 if ((symtab == 0) && (type == SHT_DYNSYM)) {
4199 4208 symtab = _cache;
4200 4209 continue;
4201 4210 }
4202 4211 if (type == SHT_SYMTAB) {
4203 4212 symtab = _cache;
4204 4213 continue;
4205 4214 }
4206 4215 if ((type != SHT_RELA) && (type != SHT_REL))
4207 4216 continue;
4208 4217
4209 4218 /*
4210 4219 * Decide entry size.
4211 4220 */
4212 4221 if (((relsize = shdr->sh_entsize) == 0) ||
4213 4222 (relsize > shdr->sh_size)) {
4214 4223 if (type == SHT_RELA)
4215 4224 relsize = sizeof (Rela);
4216 4225 else
4217 4226 relsize = sizeof (Rel);
4218 4227 }
4219 4228
4220 4229 /*
4221 4230 * Determine the number of relocations available.
4222 4231 */
4223 4232 if (shdr->sh_size == 0) {
4224 4233 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ),
4225 4234 file, _cache->c_name);
4226 4235 continue;
4227 4236 }
4228 4237 if (_cache->c_data == NULL)
4229 4238 continue;
4230 4239
4231 4240 rels = _cache->c_data->d_buf;
4232 4241 relnum = shdr->sh_size / relsize;
4233 4242
4234 4243 /*
4235 4244 * Get the data buffer for the associated symbol table and
4236 4245 * string table.
4237 4246 */
4238 4247 if (stringtbl(cache, 1, cnt, shnum, file,
4239 4248 &symnum, &symsec, &strsec) == 0)
4240 4249 continue;
4241 4250
4242 4251 syms = symsec->c_data->d_buf;
4243 4252
4244 4253 /*
4245 4254 * Loop through the relocation entries.
4246 4255 */
4247 4256 for (relndx = 0; relndx < relnum; relndx++,
4248 4257 rels = (void *)((char *)rels + relsize)) {
4249 4258 char section[BUFSIZ];
4250 4259 Addr offset;
4251 4260 Got_info *gip;
4252 4261 Word symndx, reltype;
4253 4262 Rela *rela;
4254 4263 Rel *rel;
4255 4264
4256 4265 /*
4257 4266 * Unravel the relocation.
4258 4267 */
4259 4268 if (type == SHT_RELA) {
4260 4269 rela = (Rela *)rels;
4261 4270 symndx = ELF_R_SYM(rela->r_info);
4262 4271 reltype = ELF_R_TYPE(rela->r_info,
4263 4272 ehdr->e_machine);
4264 4273 offset = rela->r_offset;
4265 4274 } else {
4266 4275 rel = (Rel *)rels;
4267 4276 symndx = ELF_R_SYM(rel->r_info);
4268 4277 reltype = ELF_R_TYPE(rel->r_info,
4269 4278 ehdr->e_machine);
4270 4279 offset = rel->r_offset;
4271 4280 }
4272 4281
4273 4282 /*
4274 4283 * Only pay attention to relocations against the GOT.
4275 4284 */
4276 4285 if ((offset < gotbgn) || (offset >= gotend))
4277 4286 continue;
4278 4287
4279 4288 /* LINTED */
4280 4289 gotndx = (Word)((offset - gotbgn) /
4281 4290 gotshdr->sh_entsize);
4282 4291 gip = &gottable[gotndx];
4283 4292
4284 4293 if (gip->g_reltype != 0) {
4285 4294 (void) fprintf(stderr,
4286 4295 MSG_INTL(MSG_GOT_MULTIPLE), file,
4287 4296 EC_WORD(gotndx), EC_ADDR(offset));
4288 4297 continue;
4289 4298 }
4290 4299
4291 4300 if (symndx)
4292 4301 gip->g_symname = relsymname(cache, _cache,
4293 4302 strsec, symndx, symnum, relndx, syms,
4294 4303 section, BUFSIZ, file);
4295 4304 gip->g_reltype = reltype;
4296 4305 gip->g_rel = rels;
4297 4306 }
4298 4307 }
4299 4308
4300 4309 if (symlookup(MSG_ORIG(MSG_SYM_GOT), cache, shnum, &gotsym, NULL,
4301 4310 symtab, file))
4302 4311 gotsymaddr = gotsym->st_value;
4303 4312 else
4304 4313 gotsymaddr = gotbgn;
4305 4314
4306 4315 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
4307 4316 dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name);
4308 4317 Elf_got_title(0);
4309 4318
4310 4319 sys_encoding = _elf_sys_encoding();
4311 4320 for (gotndx = 0; gotndx < gotents; gotndx++) {
4312 4321 Got_info *gip;
4313 4322 Sword gindex;
4314 4323 Addr gaddr;
4315 4324 Xword gotentry;
4316 4325
4317 4326 gip = &gottable[gotndx];
4318 4327
4319 4328 gaddr = gotbgn + (gotndx * gentsize);
4320 4329 gindex = (Sword)(gaddr - gotsymaddr) / (Sword)gentsize;
4321 4330
4322 4331 if (gentsize == sizeof (Word))
4323 4332 /* LINTED */
4324 4333 gotentry = (Xword)(*((Word *)(gotdata) + gotndx));
4325 4334 else
4326 4335 /* LINTED */
4327 4336 gotentry = *((Xword *)(gotdata) + gotndx);
4328 4337
4329 4338 Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine,
4330 4339 ehdr->e_ident[EI_DATA], sys_encoding,
4331 4340 gip->g_reltype, gip->g_rel, gip->g_symname);
4332 4341 }
4333 4342 free(gottable);
4334 4343 }
4335 4344
4336 4345 void
4337 4346 checksum(Elf *elf)
4338 4347 {
4339 4348 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
4340 4349 dbg_print(0, MSG_INTL(MSG_STR_CHECKSUM), elf_checksum(elf));
4341 4350 }
4342 4351
4343 4352 /*
4344 4353 * This variable is used by regular() to communicate the address of
4345 4354 * the section header cache to sort_shdr_ndx_arr(). Unfortunately,
4346 4355 * the qsort() interface does not include a userdata argument by which
4347 4356 * such arbitrary data can be passed, so we are stuck using global data.
4348 4357 */
4349 4358 static Cache *sort_shdr_ndx_arr_cache;
4350 4359
4351 4360
4352 4361 /*
4353 4362 * Used with qsort() to sort the section indices so that they can be
4354 4363 * used to access the section headers in order of increasing data offset.
4355 4364 *
4356 4365 * entry:
4357 4366 * sort_shdr_ndx_arr_cache - Contains address of
4358 4367 * section header cache.
4359 4368 * v1, v2 - Point at elements of sort_shdr_bits array to be compared.
4360 4369 *
4361 4370 * exit:
4362 4371 * Returns -1 (less than), 0 (equal) or 1 (greater than).
4363 4372 */
4364 4373 static int
4365 4374 sort_shdr_ndx_arr(const void *v1, const void *v2)
4366 4375 {
4367 4376 Cache *cache1 = sort_shdr_ndx_arr_cache + *((size_t *)v1);
4368 4377 Cache *cache2 = sort_shdr_ndx_arr_cache + *((size_t *)v2);
4369 4378
4370 4379 if (cache1->c_shdr->sh_offset < cache2->c_shdr->sh_offset)
4371 4380 return (-1);
4372 4381
4373 4382 if (cache1->c_shdr->sh_offset > cache2->c_shdr->sh_offset)
4374 4383 return (1);
4375 4384
4376 4385 return (0);
4377 4386 }
4378 4387
4379 4388
4380 4389 static int
4381 4390 shdr_cache(const char *file, Elf *elf, Ehdr *ehdr, size_t shstrndx,
4382 4391 size_t shnum, Cache **cache_ret, Word flags)
4383 4392 {
4384 4393 Elf_Scn *scn;
4385 4394 Elf_Data *data;
4386 4395 size_t ndx;
4387 4396 Shdr *nameshdr;
4388 4397 char *names = NULL;
4389 4398 Cache *cache, *_cache;
4390 4399 size_t *shdr_ndx_arr, shdr_ndx_arr_cnt;
4391 4400
4392 4401
4393 4402 /*
4394 4403 * Obtain the .shstrtab data buffer to provide the required section
4395 4404 * name strings.
4396 4405 */
4397 4406 if (shstrndx == SHN_UNDEF) {
4398 4407 /*
4399 4408 * It is rare, but legal, for an object to lack a
4400 4409 * header string table section.
4401 4410 */
4402 4411 names = NULL;
4403 4412 (void) fprintf(stderr, MSG_INTL(MSG_ERR_NOSHSTRSEC), file);
4404 4413 } else if ((scn = elf_getscn(elf, shstrndx)) == NULL) {
4405 4414 failure(file, MSG_ORIG(MSG_ELF_GETSCN));
4406 4415 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SHDR),
4407 4416 EC_XWORD(shstrndx));
4408 4417
4409 4418 } else if ((data = elf_getdata(scn, NULL)) == NULL) {
4410 4419 failure(file, MSG_ORIG(MSG_ELF_GETDATA));
4411 4420 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_DATA),
4412 4421 EC_XWORD(shstrndx));
4413 4422
4414 4423 } else if ((nameshdr = elf_getshdr(scn)) == NULL) {
4415 4424 failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
4416 4425 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN),
4417 4426 EC_WORD(elf_ndxscn(scn)));
4418 4427
4419 4428 } else if ((names = data->d_buf) == NULL)
4420 4429 (void) fprintf(stderr, MSG_INTL(MSG_ERR_SHSTRNULL), file);
4421 4430
4422 4431 /*
4423 4432 * Allocate a cache to maintain a descriptor for each section.
4424 4433 */
4425 4434 if ((*cache_ret = cache = malloc(shnum * sizeof (Cache))) == NULL) {
4426 4435 int err = errno;
4427 4436 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
4428 4437 file, strerror(err));
4429 4438 return (0);
4430 4439 }
4431 4440
4432 4441 *cache = cache_init;
4433 4442 _cache = cache;
4434 4443 _cache++;
4435 4444
4436 4445 /*
4437 4446 * Allocate an array that will hold the section index for
4438 4447 * each section that has data in the ELF file:
4439 4448 *
4440 4449 * - Is not a NOBITS section
4441 4450 * - Data has non-zero length
4442 4451 *
4443 4452 * Note that shnum is an upper bound on the size required. It
4444 4453 * is likely that we won't use a few of these array elements.
4445 4454 * Allocating a modest amount of extra memory in this case means
4446 4455 * that we can avoid an extra loop to count the number of needed
4447 4456 * items, and can fill this array immediately in the first loop
4448 4457 * below.
4449 4458 */
4450 4459 if ((shdr_ndx_arr = malloc(shnum * sizeof (*shdr_ndx_arr))) == NULL) {
4451 4460 int err = errno;
4452 4461 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
4453 4462 file, strerror(err));
4454 4463 return (0);
4455 4464 }
4456 4465 shdr_ndx_arr_cnt = 0;
4457 4466
4458 4467 /*
4459 4468 * Traverse the sections of the file. This gathering of data is
4460 4469 * carried out in two passes. First, the section headers are captured
4461 4470 * and the section header names are evaluated. A verification pass is
4462 4471 * then carried out over the section information. Files have been
4463 4472 * known to exhibit overlapping (and hence erroneous) section header
4464 4473 * information.
4465 4474 *
4466 4475 * Finally, the data for each section is obtained. This processing is
4467 4476 * carried out after section verification because should any section
4468 4477 * header overlap occur, and a file needs translating (ie. xlate'ing
4469 4478 * information from a non-native architecture file), then the process
4470 4479 * of translation can corrupt the section header information. Of
4471 4480 * course, if there is any section overlap, the data related to the
4472 4481 * sections is going to be compromised. However, it is the translation
4473 4482 * of this data that has caused problems with elfdump()'s ability to
4474 4483 * extract the data.
4475 4484 */
4476 4485 for (ndx = 1, scn = NULL; scn = elf_nextscn(elf, scn);
4477 4486 ndx++, _cache++) {
4478 4487 char scnndxnm[100];
4479 4488
4480 4489 _cache->c_ndx = ndx;
4481 4490 _cache->c_scn = scn;
4482 4491
4483 4492 if ((_cache->c_shdr = elf_getshdr(scn)) == NULL) {
4484 4493 failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
4485 4494 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN),
4486 4495 EC_WORD(elf_ndxscn(scn)));
4487 4496 }
4488 4497
4489 4498 /*
4490 4499 * If this section has data in the file, include it in
4491 4500 * the array of sections to check for address overlap.
4492 4501 */
4493 4502 if ((_cache->c_shdr->sh_size != 0) &&
4494 4503 (_cache->c_shdr->sh_type != SHT_NOBITS))
4495 4504 shdr_ndx_arr[shdr_ndx_arr_cnt++] = ndx;
4496 4505
4497 4506 /*
4498 4507 * If a shstrtab exists, assign the section name.
4499 4508 */
4500 4509 if (names && _cache->c_shdr) {
4501 4510 if (_cache->c_shdr->sh_name &&
4502 4511 /* LINTED */
4503 4512 (nameshdr->sh_size > _cache->c_shdr->sh_name)) {
4504 4513 const char *symname;
4505 4514 char *secname;
4506 4515
4507 4516 secname = names + _cache->c_shdr->sh_name;
4508 4517
4509 4518 /*
4510 4519 * A SUN naming convention employs a "%" within
4511 4520 * a section name to indicate a section/symbol
4512 4521 * name. This originated from the compilers
4513 4522 * -xF option, that places functions into their
4514 4523 * own sections. This convention (which has no
4515 4524 * formal standard) has also been followed for
4516 4525 * COMDAT sections. To demangle the symbol
4517 4526 * name, the name must be separated from the
4518 4527 * section name.
4519 4528 */
4520 4529 if (((flags & FLG_CTL_DEMANGLE) == 0) ||
4521 4530 ((symname = strchr(secname, '%')) == NULL))
4522 4531 _cache->c_name = secname;
4523 4532 else {
4524 4533 size_t secsz = ++symname - secname;
4525 4534 size_t strsz;
4526 4535
4527 4536 symname = demangle(symname, flags);
4528 4537 strsz = secsz + strlen(symname) + 1;
4529 4538
4530 4539 if ((_cache->c_name =
4531 4540 malloc(strsz)) == NULL) {
4532 4541 int err = errno;
4533 4542 (void) fprintf(stderr,
4534 4543 MSG_INTL(MSG_ERR_MALLOC),
4535 4544 file, strerror(err));
4536 4545 return (0);
4537 4546 }
4538 4547 (void) snprintf(_cache->c_name, strsz,
4539 4548 MSG_ORIG(MSG_FMT_SECSYM),
4540 4549 EC_WORD(secsz), secname, symname);
4541 4550 }
4542 4551
4543 4552 continue;
4544 4553 }
4545 4554
4546 4555 /*
4547 4556 * Generate an error if the section name index is zero
4548 4557 * or exceeds the shstrtab data. Fall through to
4549 4558 * fabricate a section name.
4550 4559 */
4551 4560 if ((_cache->c_shdr->sh_name == 0) ||
4552 4561 /* LINTED */
4553 4562 (nameshdr->sh_size <= _cache->c_shdr->sh_name)) {
4554 4563 (void) fprintf(stderr,
4555 4564 MSG_INTL(MSG_ERR_BADSHNAME), file,
4556 4565 EC_WORD(ndx),
4557 4566 EC_XWORD(_cache->c_shdr->sh_name));
4558 4567 }
4559 4568 }
4560 4569
4561 4570 /*
4562 4571 * If there exists no shstrtab data, or a section header has no
4563 4572 * name (an invalid index of 0), then compose a name for the
4564 4573 * section.
4565 4574 */
4566 4575 (void) snprintf(scnndxnm, sizeof (scnndxnm),
4567 4576 MSG_INTL(MSG_FMT_SCNNDX), ndx);
4568 4577
4569 4578 if ((_cache->c_name = malloc(strlen(scnndxnm) + 1)) == NULL) {
4570 4579 int err = errno;
4571 4580 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
4572 4581 file, strerror(err));
4573 4582 return (0);
4574 4583 }
4575 4584 (void) strcpy(_cache->c_name, scnndxnm);
4576 4585 }
4577 4586
4578 4587 /*
4579 4588 * Having collected all the sections, validate their address range.
4580 4589 * Cases have existed where the section information has been invalid.
4581 4590 * This can lead to all sorts of other, hard to diagnose errors, as
4582 4591 * each section is processed individually (ie. with elf_getdata()).
4583 4592 * Here, we carry out some address comparisons to catch a family of
4584 4593 * overlapping memory issues we have observed (likely, there are others
4585 4594 * that we have yet to discover).
4586 4595 *
4587 4596 * Note, should any memory overlap occur, obtaining any additional
4588 4597 * data from the file is questionable. However, it might still be
4589 4598 * possible to inspect the ELF header, Programs headers, or individual
4590 4599 * sections, so rather than bailing on an error condition, continue
4591 4600 * processing to see if any data can be salvaged.
4592 4601 */
4593 4602 if (shdr_ndx_arr_cnt > 1) {
4594 4603 sort_shdr_ndx_arr_cache = cache;
4595 4604 qsort(shdr_ndx_arr, shdr_ndx_arr_cnt,
4596 4605 sizeof (*shdr_ndx_arr), sort_shdr_ndx_arr);
4597 4606 }
4598 4607 for (ndx = 0; ndx < shdr_ndx_arr_cnt; ndx++) {
4599 4608 Cache *_cache = cache + shdr_ndx_arr[ndx];
4600 4609 Shdr *shdr = _cache->c_shdr;
4601 4610 Off bgn1, bgn = shdr->sh_offset;
4602 4611 Off end1, end = shdr->sh_offset + shdr->sh_size;
4603 4612 size_t ndx1;
4604 4613
4605 4614 /*
4606 4615 * Check the section against all following ones, reporting
4607 4616 * any overlaps. Since we've sorted the sections by offset,
4608 4617 * we can stop after the first comparison that fails. There
4609 4618 * are no overlaps in a properly formed ELF file, in which
4610 4619 * case this algorithm runs in O(n) time. This will degenerate
4611 4620 * to O(n^2) for a completely broken file. Such a file is
4612 4621 * (1) highly unlikely, and (2) unusable, so it is reasonable
4613 4622 * for the analysis to take longer.
4614 4623 */
4615 4624 for (ndx1 = ndx + 1; ndx1 < shdr_ndx_arr_cnt; ndx1++) {
4616 4625 Cache *_cache1 = cache + shdr_ndx_arr[ndx1];
4617 4626 Shdr *shdr1 = _cache1->c_shdr;
4618 4627
4619 4628 bgn1 = shdr1->sh_offset;
4620 4629 end1 = shdr1->sh_offset + shdr1->sh_size;
4621 4630
4622 4631 if (((bgn1 <= bgn) && (end1 > bgn)) ||
4623 4632 ((bgn1 < end) && (end1 >= end))) {
4624 4633 (void) fprintf(stderr,
4625 4634 MSG_INTL(MSG_ERR_SECMEMOVER), file,
4626 4635 EC_WORD(elf_ndxscn(_cache->c_scn)),
4627 4636 _cache->c_name, EC_OFF(bgn), EC_OFF(end),
4628 4637 EC_WORD(elf_ndxscn(_cache1->c_scn)),
4629 4638 _cache1->c_name, EC_OFF(bgn1),
4630 4639 EC_OFF(end1));
4631 4640 } else { /* No overlap, so can stop */
4632 4641 break;
4633 4642 }
4634 4643 }
4635 4644
4636 4645 /*
4637 4646 * In addition to checking for sections overlapping
4638 4647 * each other (done above), we should also make sure
4639 4648 * the section doesn't overlap the section header array.
4640 4649 */
4641 4650 bgn1 = ehdr->e_shoff;
4642 4651 end1 = ehdr->e_shoff + (ehdr->e_shentsize * ehdr->e_shnum);
4643 4652
4644 4653 if (((bgn1 <= bgn) && (end1 > bgn)) ||
4645 4654 ((bgn1 < end) && (end1 >= end))) {
4646 4655 (void) fprintf(stderr,
4647 4656 MSG_INTL(MSG_ERR_SHDRMEMOVER), file, EC_OFF(bgn1),
4648 4657 EC_OFF(end1),
4649 4658 EC_WORD(elf_ndxscn(_cache->c_scn)),
4650 4659 _cache->c_name, EC_OFF(bgn), EC_OFF(end));
4651 4660 }
4652 4661 }
4653 4662
4654 4663 /*
4655 4664 * Obtain the data for each section.
4656 4665 */
4657 4666 for (ndx = 1; ndx < shnum; ndx++) {
4658 4667 Cache *_cache = &cache[ndx];
4659 4668 Elf_Scn *scn = _cache->c_scn;
4660 4669
4661 4670 if ((_cache->c_data = elf_getdata(scn, NULL)) == NULL) {
4662 4671 failure(file, MSG_ORIG(MSG_ELF_GETDATA));
4663 4672 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA),
4664 4673 EC_WORD(elf_ndxscn(scn)));
4665 4674 }
4666 4675
4667 4676 /*
4668 4677 * If a string table, verify that it has NULL first and
4669 4678 * final bytes.
4670 4679 */
4671 4680 if ((_cache->c_shdr->sh_type == SHT_STRTAB) &&
4672 4681 (_cache->c_data->d_buf != NULL) &&
4673 4682 (_cache->c_data->d_size > 0)) {
4674 4683 const char *s = _cache->c_data->d_buf;
4675 4684
4676 4685 if ((*s != '\0') ||
4677 4686 (*(s + _cache->c_data->d_size - 1) != '\0'))
4678 4687 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALSTR),
4679 4688 file, _cache->c_name);
4680 4689 }
4681 4690 }
4682 4691
4683 4692 return (1);
4684 4693 }
4685 4694
4686 4695
4687 4696
4688 4697 /*
4689 4698 * Generate a cache of section headers and related information
4690 4699 * for use by the rest of elfdump. If requested (or the file
4691 4700 * contains no section headers), we generate a fake set of
4692 4701 * headers from the information accessible from the program headers.
4693 4702 * Otherwise, we use the real section headers contained in the file.
4694 4703 */
4695 4704 static int
4696 4705 create_cache(const char *file, int fd, Elf *elf, Ehdr *ehdr, Cache **cache,
4697 4706 size_t shstrndx, size_t *shnum, uint_t *flags)
4698 4707 {
4699 4708 /*
4700 4709 * If there are no section headers, then resort to synthesizing
4701 4710 * section headers from the program headers. This is normally
4702 4711 * only done by explicit request, but in this case there's no
4703 4712 * reason not to go ahead, since the alternative is simply to quit.
4704 4713 */
4705 4714 if ((*shnum <= 1) && ((*flags & FLG_CTL_FAKESHDR) == 0)) {
4706 4715 (void) fprintf(stderr, MSG_INTL(MSG_ERR_NOSHDR), file);
4707 4716 *flags |= FLG_CTL_FAKESHDR;
4708 4717 }
4709 4718
4710 4719 if (*flags & FLG_CTL_FAKESHDR) {
4711 4720 if (fake_shdr_cache(file, fd, elf, ehdr, cache, shnum) == 0)
4712 4721 return (0);
4713 4722 } else {
4714 4723 if (shdr_cache(file, elf, ehdr, shstrndx, *shnum,
4715 4724 cache, *flags) == 0)
4716 4725 return (0);
4717 4726 }
4718 4727
4719 4728 return (1);
4720 4729 }
4721 4730
4722 4731 int
4723 4732 regular(const char *file, int fd, Elf *elf, uint_t flags,
4724 4733 const char *wname, int wfd, uchar_t osabi)
4725 4734 {
4726 4735 enum { CACHE_NEEDED, CACHE_OK, CACHE_FAIL} cache_state = CACHE_NEEDED;
4727 4736 Elf_Scn *scn;
4728 4737 Ehdr *ehdr;
4729 4738 size_t ndx, shstrndx, shnum, phnum;
4730 4739 Shdr *shdr;
4731 4740 Cache *cache;
4732 4741 VERSYM_STATE versym;
4733 4742 int ret = 0;
4734 4743 int addr_align;
4735 4744
4736 4745 if ((ehdr = elf_getehdr(elf)) == NULL) {
4737 4746 failure(file, MSG_ORIG(MSG_ELF_GETEHDR));
4738 4747 return (ret);
4739 4748 }
4740 4749
4741 4750 if (elf_getshdrnum(elf, &shnum) == -1) {
4742 4751 failure(file, MSG_ORIG(MSG_ELF_GETSHDRNUM));
4743 4752 return (ret);
4744 4753 }
4745 4754
4746 4755 if (elf_getshdrstrndx(elf, &shstrndx) == -1) {
4747 4756 failure(file, MSG_ORIG(MSG_ELF_GETSHDRSTRNDX));
4748 4757 return (ret);
4749 4758 }
4750 4759
4751 4760 if (elf_getphdrnum(elf, &phnum) == -1) {
4752 4761 failure(file, MSG_ORIG(MSG_ELF_GETPHDRNUM));
4753 4762 return (ret);
4754 4763 }
4755 4764 /*
4756 4765 * If the user requested section headers derived from the
4757 4766 * program headers (-P option) and this file doesn't have
4758 4767 * any program headers (i.e. ET_REL), then we can't do it.
4759 4768 */
4760 4769 if ((phnum == 0) && (flags & FLG_CTL_FAKESHDR)) {
4761 4770 (void) fprintf(stderr, MSG_INTL(MSG_ERR_PNEEDSPH), file);
4762 4771 return (ret);
4763 4772 }
4764 4773
4765 4774
4766 4775 if ((scn = elf_getscn(elf, 0)) != NULL) {
4767 4776 if ((shdr = elf_getshdr(scn)) == NULL) {
4768 4777 failure(file, MSG_ORIG(MSG_ELF_GETSHDR));
4769 4778 (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCN), 0);
4770 4779 return (ret);
4771 4780 }
4772 4781 } else
4773 4782 shdr = NULL;
4774 4783
4775 4784 /*
4776 4785 * Print the elf header.
4777 4786 */
4778 4787 if (flags & FLG_SHOW_EHDR)
4779 4788 Elf_ehdr(0, ehdr, shdr);
4780 4789
4781 4790 /*
4782 4791 * If the section headers or program headers have inadequate
4783 4792 * alignment for the class of object, print a warning. libelf
4784 4793 * can handle such files, but programs that use them can crash
4785 4794 * when they dereference unaligned items.
4786 4795 *
4787 4796 * Note that the AMD64 ABI, although it is a 64-bit architecture,
4788 4797 * allows access to data types smaller than 128-bits to be on
4789 4798 * word alignment.
4790 4799 */
4791 4800 if (ehdr->e_machine == EM_AMD64)
4792 4801 addr_align = sizeof (Word);
4793 4802 else
4794 4803 addr_align = sizeof (Addr);
4795 4804
4796 4805 if (ehdr->e_phoff & (addr_align - 1))
4797 4806 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADPHDRALIGN), file);
4798 4807 if (ehdr->e_shoff & (addr_align - 1))
4799 4808 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHDRALIGN), file);
4800 4809
4801 4810
4802 4811 /*
4803 4812 * Determine the Operating System ABI (osabi) we will use to
4804 4813 * interpret the object.
4805 4814 */
4806 4815 if (flags & FLG_CTL_OSABI) {
4807 4816 /*
4808 4817 * If the user explicitly specifies '-O none', we need
4809 4818 * to display a completely generic view of the file.
4810 4819 * However, libconv is written to assume that ELFOSABI_NONE
4811 4820 * is equivalent to ELFOSABI_SOLARIS. To get the desired
4812 4821 * effect, we use an osabi that libconv has no knowledge of.
4813 4822 */
4814 4823 if (osabi == ELFOSABI_NONE)
4815 4824 osabi = ELFOSABI_UNKNOWN4;
4816 4825 } else {
4817 4826 /* Determine osabi from file */
4818 4827 osabi = ehdr->e_ident[EI_OSABI];
4819 4828 if (osabi == ELFOSABI_NONE) {
4820 4829 /*
4821 4830 * Chicken/Egg scenario:
4822 4831 *
4823 4832 * Ideally, we wait to create the section header cache
4824 4833 * until after the program headers are printed. If we
4825 4834 * only output program headers, we can skip building
4826 4835 * the cache entirely.
4827 4836 *
4828 4837 * Proper interpretation of program headers requires
4829 4838 * the osabi, which is supposed to be in the ELF header.
4830 4839 * However, many systems (Solaris and Linux included)
4831 4840 * have a history of setting the osabi to the generic
4832 4841 * SysV ABI (ELFOSABI_NONE). We assume ELFOSABI_SOLARIS
4833 4842 * in such cases, but would like to check the object
4834 4843 * to see if it has a Linux .note.ABI-tag section,
4835 4844 * which implies ELFOSABI_LINUX. This requires a
4836 4845 * section header cache.
4837 4846 *
4838 4847 * To break the cycle, we create section headers now
4839 4848 * if osabi is ELFOSABI_NONE, and later otherwise.
4840 4849 * If it succeeds, we use them, if not, we defer
4841 4850 * exiting until after the program headers are out.
4842 4851 */
4843 4852 if (create_cache(file, fd, elf, ehdr, &cache,
4844 4853 shstrndx, &shnum, &flags) == 0) {
4845 4854 cache_state = CACHE_FAIL;
4846 4855 } else {
4847 4856 cache_state = CACHE_OK;
4848 4857 if (has_linux_abi_note(cache, shnum, file)) {
4849 4858 Conv_inv_buf_t ibuf1, ibuf2;
4850 4859
4851 4860 (void) fprintf(stderr,
4852 4861 MSG_INTL(MSG_INFO_LINUXOSABI), file,
4853 4862 conv_ehdr_osabi(osabi, 0, &ibuf1),
4854 4863 conv_ehdr_osabi(ELFOSABI_LINUX,
4855 4864 0, &ibuf2));
4856 4865 osabi = ELFOSABI_LINUX;
4857 4866 }
4858 4867 }
4859 4868 }
4860 4869 /*
4861 4870 * We treat ELFOSABI_NONE identically to ELFOSABI_SOLARIS.
4862 4871 * Mapping NONE to SOLARIS simplifies the required test.
4863 4872 */
4864 4873 if (osabi == ELFOSABI_NONE)
4865 4874 osabi = ELFOSABI_SOLARIS;
4866 4875 }
4867 4876
4868 4877 /*
4869 4878 * Print the program headers.
4870 4879 */
4871 4880 if ((flags & FLG_SHOW_PHDR) && (phnum != 0)) {
4872 4881 Phdr *phdr;
4873 4882
4874 4883 if ((phdr = elf_getphdr(elf)) == NULL) {
4875 4884 failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
4876 4885 return (ret);
4877 4886 }
4878 4887
4879 4888 for (ndx = 0; ndx < phnum; phdr++, ndx++) {
4880 4889 if (!match(MATCH_F_PHDR| MATCH_F_NDX | MATCH_F_TYPE,
4881 4890 NULL, ndx, phdr->p_type))
4882 4891 continue;
4883 4892
4884 4893 dbg_print(0, MSG_ORIG(MSG_STR_EMPTY));
4885 4894 dbg_print(0, MSG_INTL(MSG_ELF_PHDR), EC_WORD(ndx));
4886 4895 Elf_phdr(0, osabi, ehdr->e_machine, phdr);
4887 4896 }
4888 4897 }
4889 4898
4890 4899 /*
4891 4900 * If we have flag bits set that explicitly require a show or calc
4892 4901 * operation, but none of them require the section headers, then
4893 4902 * we are done and can return now.
4894 4903 */
4895 4904 if (((flags & (FLG_MASK_SHOW | FLG_MASK_CALC)) != 0) &&
4896 4905 ((flags & (FLG_MASK_SHOW_SHDR | FLG_MASK_CALC_SHDR)) == 0))
4897 4906 return (ret);
4898 4907
4899 4908 /*
4900 4909 * Everything from this point on requires section headers.
4901 4910 * If we have no section headers, there is no reason to continue.
4902 4911 *
4903 4912 * If we tried above to create the section header cache and failed,
4904 4913 * it is time to exit. Otherwise, create it if needed.
4905 4914 */
4906 4915 switch (cache_state) {
4907 4916 case CACHE_NEEDED:
4908 4917 if (create_cache(file, fd, elf, ehdr, &cache, shstrndx,
4909 4918 &shnum, &flags) == 0)
4910 4919 return (ret);
4911 4920 break;
4912 4921 case CACHE_FAIL:
4913 4922 return (ret);
4914 4923 }
4915 4924 if (shnum <= 1)
4916 4925 goto done;
4917 4926
4918 4927 /*
4919 4928 * If -w was specified, find and write out the section(s) data.
4920 4929 */
4921 4930 if (wfd) {
4922 4931 for (ndx = 1; ndx < shnum; ndx++) {
4923 4932 Cache *_cache = &cache[ndx];
4924 4933
4925 4934 if (match(MATCH_F_STRICT | MATCH_F_ALL, _cache->c_name,
4926 4935 ndx, _cache->c_shdr->sh_type) &&
4927 4936 _cache->c_data && _cache->c_data->d_buf) {
4928 4937 if (write(wfd, _cache->c_data->d_buf,
4929 4938 _cache->c_data->d_size) !=
4930 4939 _cache->c_data->d_size) {
4931 4940 int err = errno;
4932 4941 (void) fprintf(stderr,
4933 4942 MSG_INTL(MSG_ERR_WRITE), wname,
4934 4943 strerror(err));
4935 4944 /*
4936 4945 * Return an exit status of 1, because
4937 4946 * the failure is not related to the
4938 4947 * ELF file, but by system resources.
4939 4948 */
4940 4949 ret = 1;
4941 4950 goto done;
4942 4951 }
4943 4952 }
4944 4953 }
4945 4954 }
4946 4955
4947 4956 /*
4948 4957 * If we have no flag bits set that explicitly require a show or calc
4949 4958 * operation, but match options (-I, -N, -T) were used, then run
4950 4959 * through the section headers and see if we can't deduce show flags
4951 4960 * from the match options given.
4952 4961 *
4953 4962 * We don't do this if -w was specified, because (-I, -N, -T) used
4954 4963 * with -w in lieu of some other option is supposed to be quiet.
4955 4964 */
4956 4965 if ((wfd == 0) && (flags & FLG_CTL_MATCH) &&
4957 4966 ((flags & (FLG_MASK_SHOW | FLG_MASK_CALC)) == 0)) {
4958 4967 for (ndx = 1; ndx < shnum; ndx++) {
4959 4968 Cache *_cache = &cache[ndx];
4960 4969
4961 4970 if (!match(MATCH_F_STRICT | MATCH_F_ALL, _cache->c_name,
4962 4971 ndx, _cache->c_shdr->sh_type))
4963 4972 continue;
4964 4973
4965 4974 switch (_cache->c_shdr->sh_type) {
4966 4975 case SHT_PROGBITS:
4967 4976 /*
4968 4977 * Heuristic time: It is usually bad form
4969 4978 * to assume the meaning/format of a PROGBITS
4970 4979 * section based on its name. However, there
4971 4980 * are ABI mandated exceptions. Check for
4972 4981 * these special names.
4973 4982 */
4974 4983
4975 4984 /* The ELF ABI specifies .interp and .got */
4976 4985 if (strcmp(_cache->c_name,
4977 4986 MSG_ORIG(MSG_ELF_INTERP)) == 0) {
4978 4987 flags |= FLG_SHOW_INTERP;
4979 4988 break;
4980 4989 }
4981 4990 if (strcmp(_cache->c_name,
4982 4991 MSG_ORIG(MSG_ELF_GOT)) == 0) {
4983 4992 flags |= FLG_SHOW_GOT;
4984 4993 break;
4985 4994 }
4986 4995 /*
4987 4996 * The GNU compilers, and amd64 ABI, define
4988 4997 * .eh_frame and .eh_frame_hdr. The Sun
4989 4998 * C++ ABI defines .exception_ranges.
4990 4999 */
4991 5000 if ((strncmp(_cache->c_name,
4992 5001 MSG_ORIG(MSG_SCN_FRM),
4993 5002 MSG_SCN_FRM_SIZE) == 0) ||
4994 5003 (strncmp(_cache->c_name,
4995 5004 MSG_ORIG(MSG_SCN_EXRANGE),
4996 5005 MSG_SCN_EXRANGE_SIZE) == 0)) {
4997 5006 flags |= FLG_SHOW_UNWIND;
4998 5007 break;
4999 5008 }
5000 5009 break;
5001 5010
5002 5011 case SHT_SYMTAB:
5003 5012 case SHT_DYNSYM:
5004 5013 case SHT_SUNW_LDYNSYM:
5005 5014 case SHT_SUNW_versym:
5006 5015 case SHT_SYMTAB_SHNDX:
5007 5016 flags |= FLG_SHOW_SYMBOLS;
5008 5017 break;
5009 5018
5010 5019 case SHT_RELA:
5011 5020 case SHT_REL:
5012 5021 flags |= FLG_SHOW_RELOC;
5013 5022 break;
5014 5023
5015 5024 case SHT_HASH:
5016 5025 flags |= FLG_SHOW_HASH;
5017 5026 break;
5018 5027
5019 5028 case SHT_DYNAMIC:
5020 5029 flags |= FLG_SHOW_DYNAMIC;
5021 5030 break;
5022 5031
5023 5032 case SHT_NOTE:
5024 5033 flags |= FLG_SHOW_NOTE;
5025 5034 break;
5026 5035
5027 5036 case SHT_GROUP:
5028 5037 flags |= FLG_SHOW_GROUP;
5029 5038 break;
5030 5039
5031 5040 case SHT_SUNW_symsort:
5032 5041 case SHT_SUNW_tlssort:
5033 5042 flags |= FLG_SHOW_SORT;
5034 5043 break;
5035 5044
5036 5045 case SHT_SUNW_cap:
5037 5046 flags |= FLG_SHOW_CAP;
5038 5047 break;
5039 5048
5040 5049 case SHT_SUNW_move:
5041 5050 flags |= FLG_SHOW_MOVE;
5042 5051 break;
5043 5052
5044 5053 case SHT_SUNW_syminfo:
5045 5054 flags |= FLG_SHOW_SYMINFO;
5046 5055 break;
5047 5056
5048 5057 case SHT_SUNW_verdef:
5049 5058 case SHT_SUNW_verneed:
5050 5059 flags |= FLG_SHOW_VERSIONS;
5051 5060 break;
5052 5061
5053 5062 case SHT_AMD64_UNWIND:
5054 5063 flags |= FLG_SHOW_UNWIND;
5055 5064 break;
5056 5065 }
5057 5066 }
5058 5067 }
5059 5068
5060 5069
5061 5070 if (flags & FLG_SHOW_SHDR)
5062 5071 sections(file, cache, shnum, ehdr, osabi);
5063 5072
5064 5073 if (flags & FLG_SHOW_INTERP)
5065 5074 interp(file, cache, shnum, phnum, elf);
5066 5075
5067 5076 if ((osabi == ELFOSABI_SOLARIS) || (osabi == ELFOSABI_LINUX))
5068 5077 versions(cache, shnum, file, flags, &versym);
5069 5078
5070 5079 if (flags & FLG_SHOW_SYMBOLS)
5071 5080 symbols(cache, shnum, ehdr, osabi, &versym, file, flags);
5072 5081
5073 5082 if ((flags & FLG_SHOW_SORT) && (osabi == ELFOSABI_SOLARIS))
5074 5083 sunw_sort(cache, shnum, ehdr, osabi, &versym, file, flags);
5075 5084
5076 5085 if (flags & FLG_SHOW_HASH)
5077 5086 hash(cache, shnum, file, flags);
5078 5087
5079 5088 if (flags & FLG_SHOW_GOT)
5080 5089 got(cache, shnum, ehdr, file);
5081 5090
5082 5091 if (flags & FLG_SHOW_GROUP)
5083 5092 group(cache, shnum, file, flags);
5084 5093
5085 5094 if (flags & FLG_SHOW_SYMINFO)
5086 5095 syminfo(cache, shnum, ehdr, osabi, file);
5087 5096
5088 5097 if (flags & FLG_SHOW_RELOC)
5089 5098 reloc(cache, shnum, ehdr, file);
5090 5099
5091 5100 if (flags & FLG_SHOW_DYNAMIC)
5092 5101 dynamic(cache, shnum, ehdr, osabi, file);
5093 5102
5094 5103 if (flags & FLG_SHOW_NOTE) {
5095 5104 Word note_cnt;
5096 5105 size_t note_shnum;
5097 5106 Cache *note_cache;
5098 5107
5099 5108 note_cnt = note(cache, shnum, ehdr, file);
5100 5109
5101 5110 /*
5102 5111 * Solaris core files have section headers, but these
5103 5112 * headers do not include SHT_NOTE sections that reference
5104 5113 * the core note sections. This means that note() won't
5105 5114 * find the core notes. Fake section headers (-P option)
5106 5115 * recover these sections, but it is inconvenient to require
5107 5116 * users to specify -P in this situation. If the following
5108 5117 * are all true:
5109 5118 *
5110 5119 * - No note sections were found
5111 5120 * - This is a core file
5112 5121 * - We are not already using fake section headers
5113 5122 *
5114 5123 * then we will automatically generate fake section headers
5115 5124 * and then process them in a second call to note().
5116 5125 */
5117 5126 if ((note_cnt == 0) && (ehdr->e_type == ET_CORE) &&
5118 5127 !(flags & FLG_CTL_FAKESHDR) &&
5119 5128 (fake_shdr_cache(file, fd, elf, ehdr,
5120 5129 ¬e_cache, ¬e_shnum) != 0)) {
5121 5130 (void) note(note_cache, note_shnum, ehdr, file);
5122 5131 fake_shdr_cache_free(note_cache, note_shnum);
5123 5132 }
5124 5133 }
5125 5134
5126 5135 if ((flags & FLG_SHOW_MOVE) && (osabi == ELFOSABI_SOLARIS))
5127 5136 move(cache, shnum, file, flags);
5128 5137
5129 5138 if (flags & FLG_CALC_CHECKSUM)
5130 5139 checksum(elf);
5131 5140
5132 5141 if ((flags & FLG_SHOW_CAP) && (osabi == ELFOSABI_SOLARIS))
5133 5142 cap(file, cache, shnum, phnum, ehdr, osabi, elf, flags);
5134 5143
5135 5144 if ((flags & FLG_SHOW_UNWIND) &&
5136 5145 ((osabi == ELFOSABI_SOLARIS) || (osabi == ELFOSABI_LINUX)))
5137 5146 unwind(cache, shnum, phnum, ehdr, osabi, file, elf, flags);
5138 5147
5139 5148
5140 5149 /* Release the memory used to cache section headers */
5141 5150 done:
5142 5151 if (flags & FLG_CTL_FAKESHDR)
5143 5152 fake_shdr_cache_free(cache, shnum);
5144 5153 else
5145 5154 free(cache);
5146 5155
5147 5156 return (ret);
5148 5157 }
↓ open down ↓ |
4259 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX