xref: /illumos-gate/usr/src/cmd/sgs/elfdump/common/fake_shdr.c (revision 99dda20867d903eec23291ba1ecb18a82d70096b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Generate a cache of section header information for an ELF
30  * object from the information found in its program headers.
31  *
32  * Malicious code can remove or corrupt section headers. The
33  * resulting program will be difficult to analyze, but is still
34  * runnable. Hence, scribbling on the section headers or removing
35  * them is an effective form of obfuscation. On the other hand,
36  * program headers must be accurate or the program will not run.
37  * Section headers derived from them will necessarily lack information
38  * found in the originals (particularly for non-allocable sections),
39  * but will provide essential symbol information. The focus is on
40  * recovering information that elfdump knows how to display, and that
41  * might be interesting in a forensic situation.
42  *
43  * There are some things we don't attempt to create sections for:
44  *
45  *	plt, got
46  *		We have no way to determine the length of either of
47  *		these sections from the information available via
48  *		the program headers or dynamic section. The data in
49  *		the PLT is of little use to elfdump. The data in the
50  *		GOT might be somewhat more interesting, especially as
51  *		it pertains to relocations. However, the sizing issue
52  *		remains.
53  *
54  *	text, data, bss
55  *		Although we could create these, there is little value
56  *		to doing so. elfdump cannot display the arbitrary
57  *		data in these sections, so this would amount to a
58  *		simple repetition of the information already displayed
59  *		in the program headers, with no additional benefit.
60  */
61 
62 
63 
64 #include	<sys/elf_amd64.h>
65 #include	<stdio.h>
66 #include	<unistd.h>
67 #include	<errno.h>
68 #include	<string.h>
69 #include	<strings.h>
70 #include	<conv.h>
71 #include	<msg.h>
72 #include	<_elfdump.h>
73 
74 
75 
76 /*
77  * Common information about the object that is needed by
78  * all the routines in this module.
79  */
80 typedef struct {
81 	const char	*file;
82 	int		fd;
83 	Ehdr		*ehdr;
84 	Phdr		*phdr;
85 	size_t		phnum;
86 } FSTATE;
87 
88 
89 
90 /*
91  * These values uniquely identify the sections that we know
92  * how to recover.
93  *
94  * Note: We write the sections to the cache array in this same order.
95  * It simplifies this code if the dynamic, dynstr, dynsym, and ldynsym
96  * sections occupy known slots in the cache array. Other sections reference
97  * them by index, and if they are at a known spot, there is no need
98  * for a fixup pass. Putting them in positions [1-4] solves this.
99  *
100  * The order they are in was chosen such that if any one of them exists,
101  * all of the ones before it must also exist. This means that if the
102  * desired section exists, it will end up in the desired index in the
103  * cache array.
104  *
105  * The order of the other sections is arbitrary. I've arranged them
106  * in roughly related groups.
107  */
108 typedef enum {
109 	SINFO_T_NULL =		0,
110 	SINFO_T_DYN =		1,
111 	SINFO_T_DYNSTR = 	2,
112 	SINFO_T_DYNSYM =	3,
113 	SINFO_T_LDYNSYM =	4,
114 
115 	SINFO_T_HASH =		5,
116 	SINFO_T_SYMINFO =	6,
117 	SINFO_T_SYMSORT =	7,
118 	SINFO_T_TLSSORT =	8,
119 	SINFO_T_VERNEED =	9,
120 	SINFO_T_VERDEF =	10,
121 	SINFO_T_VERSYM =	11,
122 	SINFO_T_INTERP =	12,
123 	SINFO_T_CAP =		13,
124 	SINFO_T_UNWIND =	14,
125 	SINFO_T_MOVE =		15,
126 	SINFO_T_REL =		16,
127 	SINFO_T_RELA =		17,
128 	SINFO_T_PREINITARR =	18,
129 	SINFO_T_INITARR =	19,
130 	SINFO_T_FINIARR =	20,
131 	SINFO_T_NOTE =		21,
132 
133 	SINFO_T_NUM =		22 /* Count of items. Must come last */
134 } SINFO_TYPE;
135 
136 
137 
138 /*
139  * Table of per-section constant data used to set up the section
140  * header cache and the various sub-parts it references. Indexed by
141  * SINFO_T value.
142  *
143  * note: The sh_flags value should be either SHF_ALLOC, or 0.
144  *	get_data() sets SHF_WRITE if the program header containing the
145  *	section is writable. The other flags require information that
146  *	the program headers don't contain (i.e. SHF_STRINGS, etc) so
147  *	we don't set them.
148  */
149 typedef struct {
150 	const char	*name;
151 	Word		sh_type;
152 	Word		sh_flags;
153 	Word		sh_addralign;
154 	Word		sh_entsize;
155 	Elf_Type	libelf_type;
156 } SINFO_DATA;
157 
158 /*
159  * Many of these sections use an alignment given by M_WORD_ALIGN, a
160  * value that varies depending on the object target machine. Since we
161  * don't know that value at compile time, we settle for a value of
162  * 4 for ELFCLASS32 objects, and 8 for ELFCLASS64. This matches the
163  * platforms we current support (sparc and x86), and is good enough for
164  * a fake section header in any event, as the resulting object is only
165  * analyzed, and is not executed.
166  */
167 #ifdef _ELF64
168 #define	FAKE_M_WORD_ALIGN 8
169 #else
170 #define	FAKE_M_WORD_ALIGN 4
171 #endif
172 
173 static SINFO_DATA sinfo_data[SINFO_T_NUM] = {
174 	/* SINFO_T_NULL */
175 	{ 0 },
176 
177 	/* SINFO_T_DYN */
178 	{ MSG_ORIG(MSG_PHDRNAM_DYN), SHT_DYNAMIC, SHF_ALLOC,
179 	    FAKE_M_WORD_ALIGN, sizeof (Dyn), ELF_T_DYN },
180 
181 	/* SINFO_T_DYNSTR */
182 	{ MSG_ORIG(MSG_PHDRNAM_DYNSTR), SHT_STRTAB, SHF_ALLOC,
183 	    1, 0, ELF_T_BYTE },
184 
185 	/* SINFO_T_DYNSYM */
186 	{ MSG_ORIG(MSG_PHDRNAM_DYNSYM), SHT_DYNSYM, SHF_ALLOC,
187 	    FAKE_M_WORD_ALIGN, sizeof (Sym), ELF_T_SYM },
188 
189 	/* SINFO_T_LDYNSYM */
190 	{ MSG_ORIG(MSG_PHDRNAM_LDYNSYM), SHT_SUNW_LDYNSYM, SHF_ALLOC,
191 	    FAKE_M_WORD_ALIGN, sizeof (Sym), ELF_T_SYM },
192 
193 	/* SINFO_T_HASH */
194 	{ MSG_ORIG(MSG_PHDRNAM_HASH), SHT_HASH, SHF_ALLOC,
195 	    FAKE_M_WORD_ALIGN, sizeof (Word), ELF_T_WORD },
196 
197 	/* SINFO_T_SYMINFO */
198 	{ MSG_ORIG(MSG_PHDRNAM_SYMINFO),  SHT_SUNW_syminfo, SHF_ALLOC,
199 	    FAKE_M_WORD_ALIGN, sizeof (Syminfo), ELF_T_SYMINFO },
200 
201 	/* SINFO_T_SYMSORT */
202 	{ MSG_ORIG(MSG_PHDRNAM_SYMSORT), SHT_SUNW_symsort, SHF_ALLOC,
203 	    FAKE_M_WORD_ALIGN, sizeof (Word), ELF_T_WORD },
204 
205 	/* SINFO_T_TLSSORT */
206 	{ MSG_ORIG(MSG_PHDRNAM_TLSSORT), SHT_SUNW_tlssort, SHF_ALLOC,
207 	    FAKE_M_WORD_ALIGN, sizeof (Word), ELF_T_WORD },
208 
209 	/* SINFO_T_VERNEED */
210 	{ MSG_ORIG(MSG_PHDRNAM_VER), SHT_SUNW_verneed, SHF_ALLOC,
211 	    FAKE_M_WORD_ALIGN, 1, ELF_T_VNEED },
212 
213 	/* SINFO_T_VERDEF */
214 	{ MSG_ORIG(MSG_PHDRNAM_VER), SHT_SUNW_verdef, SHF_ALLOC,
215 	    FAKE_M_WORD_ALIGN, 1, ELF_T_VDEF },
216 
217 	/* SINFO_T_VERSYM */
218 	{ MSG_ORIG(MSG_PHDRNAM_VER), SHT_SUNW_versym, SHF_ALLOC,
219 	    FAKE_M_WORD_ALIGN, sizeof (Versym), ELF_T_HALF },
220 
221 	/* SINFO_T_INTERP */
222 	{ MSG_ORIG(MSG_PHDRNAM_INTERP), SHT_PROGBITS, SHF_ALLOC,
223 	    1, 0, ELF_T_BYTE },
224 
225 	/* SINFO_T_CAP */
226 	{ MSG_ORIG(MSG_PHDRNAM_CAP), SHT_SUNW_cap, SHF_ALLOC,
227 	    sizeof (Addr), sizeof (Cap), ELF_T_CAP },
228 
229 	/* SINFO_T_UNWIND */
230 	{ MSG_ORIG(MSG_PHDRNAM_UNWIND), SHT_AMD64_UNWIND, SHF_ALLOC,
231 	    sizeof (Addr), 0, ELF_T_BYTE },
232 
233 	/* SINFO_T_MOVE */
234 	{ MSG_ORIG(MSG_PHDRNAM_MOVE), SHT_SUNW_move, SHF_ALLOC,
235 	    sizeof (Lword), sizeof (Move),  ELF_T_MOVE },
236 
237 	/* SINFO_T_REL */
238 	{ MSG_ORIG(MSG_PHDRNAM_REL), SHT_REL, SHF_ALLOC,
239 	    FAKE_M_WORD_ALIGN, sizeof (Rel), ELF_T_REL },
240 
241 	/* SINFO_T_RELA */
242 	{ MSG_ORIG(MSG_PHDRNAM_RELA), SHT_RELA, SHF_ALLOC,
243 	    FAKE_M_WORD_ALIGN, sizeof (Rela), ELF_T_RELA },
244 
245 	/* SINFO_T_PREINITARR */
246 	{ MSG_ORIG(MSG_PHDRNAM_PREINITARR), SHT_PREINIT_ARRAY, SHF_ALLOC,
247 	    sizeof (Addr), sizeof (Addr), ELF_T_ADDR },
248 
249 	/* SINFO_T_INITARR */
250 	{ MSG_ORIG(MSG_PHDRNAM_INITARR), SHT_INIT_ARRAY, SHF_ALLOC,
251 	    sizeof (Addr), sizeof (Addr),  ELF_T_ADDR },
252 
253 	/* SINFO_T_FINIARR */
254 	{ MSG_ORIG(MSG_PHDRNAM_FINIARR), SHT_FINI_ARRAY, SHF_ALLOC,
255 	    sizeof (Addr), sizeof (Addr), ELF_T_ADDR },
256 
257 	/* SINFO_T_NOTE */
258 	{ MSG_ORIG(MSG_PHDRNAM_NOTE), SHT_NOTE, 0,
259 	    FAKE_M_WORD_ALIGN, 1, ELF_T_NOTE }
260 };
261 
262 
263 
264 
265 
266 /*
267  * As we read program headers and dynamic elements, we build up
268  * the data for our fake section headers in variables of the
269  * SINFO type. SINFO is used to track the sections that can only
270  * appear a fixed number of times (usually once).
271  *
272  * SINFO_LISTELT is used for sections that can occur an arbitrary
273  * number of times. They are kept in a doubly linked circular
274  * buffer.
275  */
276 typedef struct {
277 	SINFO_TYPE	type;	/* Our type code for the section */
278 	Addr		vaddr;	/* Virtual memory address */
279 	Off		offset;	/* File offset of data. Ignored unless */
280 				/*	vaddr is 0. Used by program headers */
281 	size_t		size;	/* # bytes in section */
282 	size_t		vercnt;	/* Used by verdef and verneed to hold count */
283 	Shdr		*shdr;	/* Constructed shdr */
284 	Elf_Data	*data;	/* Constructed data descriptor */
285 } SINFO;
286 
287 typedef struct _sinfo_listelt {
288 	struct _sinfo_listelt	*next;
289 	struct _sinfo_listelt	*prev;
290 	SINFO			sinfo;
291 } SINFO_LISTELT;
292 
293 
294 
295 /*
296  * Free dynamic memory used by SINFO structures.
297  *
298  * entry:
299  *	sinfo - Address of first SINFO structure to free
300  *	n - # of structures to clear
301  *
302  * exit:
303  *	For each SINFO struct, the section header, data descriptor,
304  *	and data buffer are freed if non-NULL. The relevant
305  *	fields are set to NULL, and the type is set to SINFO_T_NULL.
306  */
307 static void
308 sinfo_free(SINFO *sinfo, size_t n)
309 {
310 	for (; n-- > 0; sinfo++) {
311 		if (sinfo->data != NULL) {
312 			if (sinfo->data->d_buf != NULL)
313 				free(sinfo->data->d_buf);
314 			free(sinfo->data);
315 			sinfo->data = NULL;
316 		}
317 
318 		if (sinfo->shdr) {
319 			free(sinfo->shdr);
320 			sinfo->shdr = NULL;
321 		}
322 		sinfo->type = SINFO_T_NULL;
323 	}
324 }
325 
326 
327 
328 /*
329  * Allocate a new SINFO_LISTELT and put it at the end of the
330  * doubly linked list anchored by the given list root node.
331  *
332  * On success, a new node has been put at the end of the circular
333  * doubly linked list, and a pointer to the SINFO sub-structure is
334  * returned. On failure, an error is printed, and NULL is returned.
335  */
336 
337 static SINFO *
338 sinfo_list_alloc(FSTATE *fstate, SINFO_LISTELT *root)
339 {
340 	SINFO_LISTELT *elt;
341 
342 	if ((elt = malloc(sizeof (*elt))) == NULL) {
343 		int err = errno;
344 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
345 		    fstate->file, strerror(err));
346 		return (0);
347 	}
348 
349 	elt->next = root;
350 	elt->prev = root->prev;
351 
352 	root->prev = elt;
353 	elt->prev->next = elt;
354 
355 	bzero(&elt->sinfo, sizeof (elt->sinfo));
356 	return (&elt->sinfo);
357 }
358 
359 
360 
361 /*
362  * Release the memory used by the given list, restoring it to
363  * an empty list.
364  */
365 static void
366 sinfo_list_free_all(SINFO_LISTELT *root)
367 {
368 	SINFO_LISTELT *elt;
369 
370 	for (elt = root->next; elt != root; elt = elt->next)
371 		sinfo_free(&elt->sinfo, 1);
372 
373 	root->next = root->prev = root;
374 }
375 
376 
377 
378 /*
379  * Given a virtual address and desired size of the data to be found
380  * at that address, look through the program headers for the PT_LOAD
381  * segment that contains it and return the offset within the ELF file
382  * at which it resides.
383  *
384  * entry:
385  *	fstate - Object state
386  *	addr - virtual address to be translated
387  *	size - Size of the data to be found at that address, in bytes
388  *	zero_bytes - NULL, or address to receive the number of data
389  *		bytes at the end of the data that are not contained
390  *		in the file, and which must be zero filled by the caller.
391  *		If zero_bytes is NULL, the file must contain all of the
392  *		desired data. If zero_bytes is not NULL, then the program
393  *		header must reserve the space for all of the data (p_memsz)
394  *		but it is acceptable for only part of the data to be in
395  *		the file (p_filesz). *zero_bytes is set to the difference
396  *		in size, and is the number of bytes the caller must
397  *		set to 0 rather than reading from the file.
398  *	phdr_ret - NULL, or address of variable to receive pointer
399  *		to program header that contains offset.
400  * exit:
401  *	On success: If zero_bytes is non-NULL, it is updated. If phdr_ret
402  *	is non-NULL, it is updated. The file offset is returned.
403  *
404  *	On failure, 0 is returned. Since any ELF file we can understand
405  *	must start with an ELF magic number, 0 cannot be a valid file
406  *	offset for a virtual address, and is therefore unambiguous as
407  *	a failure indication.
408  */
409 static Off
410 map_addr_to_offset(FSTATE *fstate, Addr addr, size_t size, size_t *zero_bytes,
411     Phdr **phdr_ret)
412 {
413 	Off	offset;
414 	Addr	end_addr = addr + size;
415 	size_t	avail_file;
416 	Phdr	*phdr = fstate->phdr;
417 	size_t	phnum = fstate->phnum;
418 
419 	for (; phnum--; phdr++) {
420 		if (phdr->p_type != PT_LOAD)
421 			continue;
422 
423 		if ((addr >= phdr->p_vaddr) &&
424 		    (end_addr <= (phdr->p_vaddr + phdr->p_memsz))) {
425 			/*
426 			 * Subtract segment virtual address, leaving the
427 			 * offset relative to the segment (not the file).
428 			 */
429 			offset = addr - phdr->p_vaddr;
430 			avail_file = phdr->p_filesz - offset;
431 
432 			/*
433 			 * The addr/size are in bounds for this segment.
434 			 * Is there enough data in the file to satisfy
435 			 * the request? If zero_bytes is NULL, it must
436 			 * all be in the file. Otherwise it can be
437 			 * zero filled.
438 			 */
439 			if (zero_bytes == NULL) {
440 				if (size > avail_file)
441 					continue;
442 			} else {
443 				*zero_bytes = (size > avail_file) ?
444 				    (size - avail_file) : 0;
445 			}
446 
447 			if (phdr_ret != NULL)
448 				*phdr_ret = phdr;
449 
450 			/* Add segment file offset, giving overall offset */
451 			return (phdr->p_offset + offset);
452 		}
453 	}
454 
455 	/* If we get here, the mapping failed */
456 	return (0);
457 }
458 
459 
460 
461 /*
462  * This routine is the same thing as map_addr_to_offset(), except that
463  * it goes the other way, mapping from offset to virtual address.
464  *
465  * The comments for map_addr_to_offset() are applicable if you
466  * reverse offset and address.
467  */
468 
469 static Addr
470 map_offset_to_addr(FSTATE *fstate, Off offset, size_t size, size_t *zero_bytes,
471     Phdr **phdr_ret)
472 {
473 	Off	end_offset = offset + size;
474 	size_t	avail_file;
475 	Phdr	*phdr = fstate->phdr;
476 	size_t	phnum = fstate->phnum;
477 
478 	for (; phnum--; phdr++) {
479 		if (phdr->p_type != PT_LOAD)
480 			continue;
481 
482 		if ((offset >= phdr->p_offset) &&
483 		    (end_offset <= (phdr->p_offset + phdr->p_memsz))) {
484 			/*
485 			 * Subtract segment offset, leaving the
486 			 * offset relative to the segment (not the file).
487 			 */
488 			offset -= phdr->p_offset;
489 			avail_file = phdr->p_filesz - offset;
490 
491 			/*
492 			 * The offset/size are in bounds for this segment.
493 			 * Is there enough data in the file to satisfy
494 			 * the request? If zero_bytes is NULL, it must
495 			 * all be in the file. Otherwise it can be
496 			 * zero filled.
497 			 */
498 			if (zero_bytes == NULL) {
499 				if (size > avail_file)
500 					continue;
501 			} else {
502 				*zero_bytes = (size > avail_file) ?
503 				    (size - avail_file) : 0;
504 			}
505 
506 			if (phdr_ret != NULL)
507 				*phdr_ret = phdr;
508 
509 			/* Add segment virtual address, giving overall addr */
510 			return (phdr->p_vaddr + offset);
511 		}
512 	}
513 
514 	/* If we get here, the mapping failed */
515 	return (0);
516 }
517 
518 
519 
520 /*
521  * Use elf_xlatetom() to convert the bytes in buf from their
522  * in-file representation to their in-memory representation.
523  *
524  * Returns True(1) for success. On failure, an error message is printed
525  * and False(0) is returned.
526  */
527 static int
528 xlate_data(FSTATE *fstate, void *buf, size_t nbyte, Elf_Type xlate_type)
529 {
530 	Elf_Data	data;
531 
532 	data.d_type = xlate_type;
533 	data.d_size = nbyte;
534 	data.d_off = 0;
535 	data.d_align = 0;
536 	data.d_version = fstate->ehdr->e_version;
537 	data.d_buf = buf;
538 
539 	if (elf_xlatetom(&data, &data,
540 	    fstate->ehdr->e_ident[EI_DATA]) == NULL) {
541 		failure(fstate->file, MSG_ORIG(MSG_ELF_XLATETOM));
542 		return (0);
543 	}
544 
545 	return (1);
546 }
547 
548 
549 /*
550  * Read nbytes of data into buf, starting at the specified offset
551  * within the ELF file.
552  *
553  * entry:
554  *	fstate - Object state
555  *	offset - Offset within the file at which desired data resides.
556  *	buf - Buffer to receive the data
557  *	nbyte - # of bytes to read into buf
558  *	xlate_type - An ELF xlate type, specifying the type of data
559  *		being input. If xlate_type is ELF_T_BYTE, xlate is not
560  *		done. Otherwise, xlate_data() is called to convert the
561  *		data into its in-memory representation.
562  * exit:
563  *	On success, the data has been written into buf, xlate_data()
564  *	called on it if required, and True(1) is returned. Otherwise
565  *	False(0) is returned.
566  *
567  * note:
568  *	This routine does not move the file pointer.
569  */
570 static int
571 read_data(FSTATE *fstate, Off offset, void *buf, size_t nbyte,
572     Elf_Type xlate_type)
573 {
574 	if (pread(fstate->fd, buf, nbyte, offset) != nbyte) {
575 		int err = errno;
576 
577 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_READ),
578 		    fstate->file, strerror(err));
579 		return (0);
580 	}
581 
582 	if (xlate_type != ELF_T_BYTE)
583 		return (xlate_data(fstate, buf, nbyte, xlate_type));
584 
585 	return (1);
586 }
587 
588 
589 
590 /*
591  * Read the hash nbucket/nchain values from the start of the hash
592  * table found at the given virtual address in the mapped ELF object.
593  *
594  * On success, *nbucket, and *nchain have been filled in with their
595  * values, *total contains the number of elements in the hash table,
596  * and this routine returns True (1).
597  *
598  * On failure, False (0) is returned.
599  */
600 static int
601 hash_size(FSTATE *fstate, SINFO *hash_sinfo,
602     Word *nbucket, Word *nchain, size_t *total)
603 {
604 	Off		offset;
605 	Word		buf[2];
606 
607 	offset = map_addr_to_offset(fstate, hash_sinfo->vaddr,
608 	    sizeof (buf), NULL, NULL);
609 	if (offset == 0)
610 		return (0);
611 
612 	if (read_data(fstate, offset, buf, sizeof (buf), ELF_T_WORD) == 0)
613 		return (0);
614 
615 	*nbucket = buf[0];
616 	*nchain = buf[1];
617 	*total = 2 + *nbucket + *nchain;
618 	return (1);
619 }
620 
621 
622 
623 /*
624  * Read a Verdef structure at the specified file offset and return
625  * its vd_cnt, vd_aux, and vd_next fields.
626  */
627 static int
628 read_verdef(FSTATE *fstate, Off offset, Half *cnt, Word *aux, Word *next)
629 {
630 	Verdef		verdef;
631 
632 	if (read_data(fstate, offset, &verdef, sizeof (verdef),
633 	    ELF_T_BYTE) == 0)
634 		return (0);
635 
636 	/* xlate vd_cnt */
637 	if (xlate_data(fstate, &verdef.vd_cnt, sizeof (verdef.vd_cnt),
638 	    ELF_T_HALF) == 0)
639 		return (0);
640 
641 	/*
642 	 * xlate vd_aux and vd_next. These items are adjacent and are
643 	 * both Words, so they can be handled in a single operation.
644 	 */
645 	if (xlate_data(fstate, &verdef.vd_aux,
646 	    2 * sizeof (Word), ELF_T_WORD) == 0)
647 		return (0);
648 
649 	*cnt = verdef.vd_cnt;
650 	*aux = verdef.vd_aux;
651 	*next = verdef.vd_next;
652 
653 	return (1);
654 }
655 
656 
657 
658 /*
659  * Read a Verdaux structure at the specified file offset and return
660  * its vda_next field.
661  */
662 static int
663 read_verdaux(FSTATE *fstate, Off offset, Word *next)
664 {
665 	Verdaux		verdaux;
666 
667 	if (read_data(fstate, offset, &verdaux, sizeof (verdaux),
668 	    ELF_T_BYTE) == 0)
669 		return (0);
670 
671 	/* xlate vda_next */
672 	if (xlate_data(fstate, &verdaux.vda_next, sizeof (verdaux.vda_next),
673 	    ELF_T_WORD) == 0)
674 		return (0);
675 
676 	*next = verdaux.vda_next;
677 
678 	return (1);
679 }
680 
681 
682 
683 /*
684  * Read a Verneed structure at the specified file offset and return
685  * its vn_cnt, vn_aux, and vn_next fields.
686  */
687 static int
688 read_verneed(FSTATE *fstate, Off offset, Half *cnt, Word *aux, Word *next)
689 {
690 	Verneed		verneed;
691 
692 	if (read_data(fstate, offset, &verneed, sizeof (verneed),
693 	    ELF_T_BYTE) == 0)
694 		return (0);
695 
696 	/* xlate vn_cnt */
697 	if (xlate_data(fstate, &verneed.vn_cnt, sizeof (verneed.vn_cnt),
698 	    ELF_T_HALF) == 0)
699 		return (0);
700 
701 	/*
702 	 * xlate vn_aux and vn_next. These items are adjacent and are
703 	 * both Words, so they can be handled in a single operation.
704 	 */
705 	if (xlate_data(fstate, &verneed.vn_aux,
706 	    2 * sizeof (Word), ELF_T_WORD) == 0)
707 		return (0);
708 
709 	*cnt = verneed.vn_cnt;
710 	*aux = verneed.vn_aux;
711 	*next = verneed.vn_next;
712 
713 	return (1);
714 }
715 
716 
717 
718 /*
719  * Read a Vernaux structure at the specified file offset and return
720  * its vna_next field.
721  */
722 static int
723 read_vernaux(FSTATE *fstate, Off offset, Word *next)
724 {
725 	Vernaux		vernaux;
726 
727 	if (read_data(fstate, offset, &vernaux, sizeof (vernaux),
728 	    ELF_T_BYTE) == 0)
729 		return (0);
730 
731 	/* xlate vna_next */
732 	if (xlate_data(fstate, &vernaux.vna_next, sizeof (vernaux.vna_next),
733 	    ELF_T_WORD) == 0)
734 		return (0);
735 
736 	*next = vernaux.vna_next;
737 
738 	return (1);
739 }
740 
741 
742 
743 /*
744  * Compute the size of Verdef and Verneed sections. Both of these
745  * sections are made up of interleaved main nodes (Verdef and Verneed)
746  * and auxiliary blocks (Verdaux and Vernaux). These nodes refer to
747  * each other by relative offsets. The linker has a lot of flexibility
748  * in how it lays out these items, and we cannot assume a standard
749  * layout. To determine the size of the section, we must read each
750  * main node and compute the high water mark of the memory it and its
751  * auxiliary structs access.
752  *
753  * Although Verdef/Verdaux and Verneed/Vernaux are different types,
754  * their logical organization is the same. Each main block has
755  * a cnt field that tells how many auxiliary blocks it has, an
756  * aux field that gives the offset of the first auxiliary block, and
757  * an offset to the next main block. Each auxiliary block contains
758  * an offset to the next auxiliary block. By breaking the type specific
759  * code into separate sub-functions, we can process both Verdef and
760  * sections Verdaux from a single routine.
761  *
762  * entry:
763  *	fstate - Object state
764  *	sec - Section to be processed (SINFO_T_VERDEF or SINFO_T_VERNEED).
765  *
766  * exit:
767  *	On success, sec->size is set to the section size in bytes, and
768  *	True (1) is returned. On failure, False (0) is returned.
769  */
770 static int
771 verdefneed_size(FSTATE *fstate, SINFO *sec)
772 {
773 	int (* read_main)(FSTATE *, Off, Half *, Word *, Word *);
774 	int (* read_aux)(FSTATE *, Off, Word *);
775 	size_t	size_main, size_aux;
776 
777 	Off	offset, aux_offset;
778 	Off	highwater, extent;
779 	size_t	num_main = sec->vercnt;
780 	Half	v_cnt;
781 	Word	v_aux, v_next, va_next;
782 
783 
784 	/*
785 	 * Set up the function pointers to the type-specific code
786 	 * for fetching data from the main and auxiliary blocks.
787 	 */
788 	if (sec->type == SINFO_T_VERDEF) {
789 		read_main = read_verdef;
790 		read_aux = read_verdaux;
791 		size_main = sizeof (Verdef);
792 		size_aux = sizeof (Verdaux);
793 	} else {			/* SINFO_T_VERNEED */
794 		read_main = read_verneed;
795 		read_aux = read_vernaux;
796 		size_main = sizeof (Verneed);
797 		size_aux = sizeof (Vernaux);
798 	}
799 
800 	/*
801 	 * Map starting address to file offset. Save the starting offset
802 	 * in the SINFO size field. Once we have the high water offset, we
803 	 * can subtract this from it to get the size.
804 	 *
805 	 * Note: The size argument set here is a lower bound --- the
806 	 * size of the main blocks without any auxiliary ones. It's
807 	 * the best we can do until the size has been determined for real.
808 	 */
809 	offset = highwater = map_addr_to_offset(fstate, sec->vaddr,
810 	    size_main * num_main, NULL, NULL);
811 	if (offset == 0)
812 		return (0);
813 	sec->size = offset;
814 
815 	for (; num_main-- > 0; offset += v_next) {
816 		/* Does this move the high water mark up? */
817 		extent = offset + size_main;
818 		if (extent > highwater)
819 			highwater = extent;
820 
821 		if ((*read_main)(fstate, offset, &v_cnt, &v_aux, &v_next) == 0)
822 			return (0);
823 
824 		/*
825 		 * If there are auxiliary structures referenced,
826 		 * check their position to see if it pushes
827 		 * the high water mark.
828 		 */
829 		aux_offset = offset + v_aux;
830 		for (; v_cnt-- > 0; aux_offset += va_next) {
831 			extent = aux_offset + size_aux;
832 			if (extent > highwater)
833 				highwater = extent;
834 
835 			if ((*read_aux)(fstate, aux_offset, &va_next) == 0)
836 				return (0);
837 		}
838 	}
839 
840 	sec->size = highwater - sec->size;
841 	return (1);
842 }
843 
844 
845 /*
846  * Allocate and fill in a fake section header, data descriptor,
847  * and data buffer for the given section. Fill them in and read
848  * the associated data into the buffer.
849  *
850  * entry:
851  *	fstate - Object state
852  *	sec - Section information
853  *
854  * exit:
855  *	On success, the actions described above are complete, and
856  *	True (1) is returned.
857  *
858  *	On failure, an error is reported, all resources used by sec
859  *	are released, and sec->type is set to SINFO_T_NULL, effectively
860  *	eliminating its contents from any further use. False (0) is
861  *	returned.
862  */
863 static int
864 get_data(FSTATE *fstate, SINFO *sec)
865 {
866 
867 	SINFO_DATA	*tinfo;
868 	size_t		read_bytes, zero_bytes;
869 	Phdr		*phdr = NULL;
870 
871 	/*
872 	 * If this is a NULL section, or if we've already processed
873 	 * this item, then we are already done.
874 	 */
875 	if ((sec->type == SINFO_T_NULL) || (sec->shdr != NULL))
876 		return (1);
877 
878 	if (((sec->shdr = malloc(sizeof (*sec->shdr))) == NULL) ||
879 	    ((sec->data = malloc(sizeof (*sec->data))) == NULL)) {
880 		int err = errno;
881 		sinfo_free(sec, 1);
882 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
883 		    fstate->file, strerror(err));
884 		return (0);
885 	}
886 	tinfo = &sinfo_data[sec->type];
887 
888 
889 
890 	/*
891 	 * Fill in fake section header
892 	 *
893 	 * sh_name should be the offset of the name in the shstrtab
894 	 * section referenced by the ELF header. There is no
895 	 * value to elfdump in creating shstrtab, so we set
896 	 * sh_name to 0, knowing that elfdump doesn't look at it.
897 	 */
898 	sec->shdr->sh_name = 0;
899 	sec->shdr->sh_type = tinfo->sh_type;
900 	sec->shdr->sh_flags = tinfo->sh_flags;
901 	if ((tinfo->sh_flags & SHF_ALLOC) == 0) {
902 		/*
903 		 * Non-allocable section: Pass the addr (which is probably
904 		 * 0) and offset through without inspection.
905 		 */
906 		sec->shdr->sh_addr = sec->vaddr;
907 		sec->shdr->sh_offset = sec->offset;
908 		zero_bytes = 0;
909 	} else if (sec->vaddr == 0) {
910 		/*
911 		 * Allocable section with a 0 vaddr. Figure out the
912 		 * real address by mapping the offset to it using the
913 		 * program headers.
914 		 */
915 		sec->shdr->sh_addr = map_offset_to_addr(fstate, sec->offset,
916 		    sec->size, &zero_bytes, &phdr);
917 		sec->shdr->sh_offset = sec->offset;
918 	} else {
919 		/*
920 		 * Allocable section with non-0 vaddr. Use the vaddr
921 		 * to derive the offset.
922 		 */
923 		sec->shdr->sh_addr = sec->vaddr;
924 		sec->shdr->sh_offset = map_addr_to_offset(fstate,
925 		    sec->vaddr, sec->size, &zero_bytes, &phdr);
926 	}
927 	if (sec->shdr->sh_offset == 0) {
928 		sinfo_free(sec, 1);
929 		return (0);
930 	}
931 	/*
932 	 * If the program header has its write flags set, then set
933 	 * the section write flag.
934 	 */
935 	if (phdr && ((phdr->p_flags & PF_W) != 0))
936 		sec->shdr->sh_flags |= SHF_WRITE;
937 	sec->shdr->sh_size = sec->size;
938 	sec->shdr->sh_link = 0;
939 	sec->shdr->sh_info = 0;
940 	sec->shdr->sh_addralign = tinfo->sh_addralign;
941 	sec->shdr->sh_entsize = tinfo->sh_entsize;
942 
943 	/*
944 	 * Some sections define special meanings for sh_link and sh_info.
945 	 */
946 	switch (tinfo->sh_type) {
947 	case SHT_DYNAMIC:
948 		sec->shdr->sh_link = SINFO_T_DYNSTR;
949 		break;
950 
951 	case SHT_DYNSYM:
952 		sec->shdr->sh_link = SINFO_T_DYNSTR;
953 		sec->shdr->sh_info = 1;	/* First global symbol */
954 		break;
955 
956 	case SHT_SUNW_LDYNSYM:
957 		sec->shdr->sh_link = SINFO_T_DYNSTR;
958 		/*
959 		 * ldynsym is all local symbols, so the index of the
960 		 * first global is equivalent to the number of symbols.
961 		 */
962 		sec->shdr->sh_info = sec->shdr->sh_size / sizeof (Sym);
963 		break;
964 
965 	case SHT_HASH:
966 	case SHT_SUNW_move:
967 	case SHT_REL:
968 	case SHT_RELA:
969 	case SHT_SUNW_versym:
970 		sec->shdr->sh_link = SINFO_T_DYNSYM;
971 		break;
972 
973 	case SHT_SUNW_verdef:
974 	case SHT_SUNW_verneed:
975 		sec->shdr->sh_link = SINFO_T_DYNSTR;
976 		sec->shdr->sh_info = sec->vercnt;
977 		break;
978 
979 	case SHT_SUNW_syminfo:
980 		sec->shdr->sh_link = SINFO_T_DYNSYM;
981 		sec->shdr->sh_info = SINFO_T_DYN;
982 		break;
983 
984 	case SHT_SUNW_symsort:
985 	case SHT_SUNW_tlssort:
986 		sec->shdr->sh_link = SINFO_T_LDYNSYM;
987 		break;
988 	}
989 
990 
991 
992 	/* Fill in fake Elf_Data descriptor */
993 	sec->data->d_type = tinfo->libelf_type;
994 	sec->data->d_size = sec->size;
995 	sec->data->d_off = 0;
996 	sec->data->d_align = tinfo->sh_addralign;
997 	sec->data->d_version = fstate->ehdr->e_version;
998 
999 	if (sec->size == 0) {
1000 		sec->data->d_buf = NULL;
1001 		return (1);
1002 	}
1003 
1004 	if ((sec->data->d_buf = malloc(sec->size)) == NULL) {
1005 		int err = errno;
1006 
1007 		sinfo_free(sec, 1);
1008 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
1009 		    fstate->file, strerror(err));
1010 		return (0);
1011 	}
1012 
1013 	read_bytes = sec->size - zero_bytes;
1014 	if ((read_bytes > 0) &&
1015 	    (read_data(fstate, sec->shdr->sh_offset, sec->data->d_buf,
1016 	    read_bytes, ELF_T_BYTE) == 0)) {
1017 		sinfo_free(sec, 1);
1018 		return (0);
1019 	}
1020 	if (zero_bytes > 0)
1021 		bzero(read_bytes + (char *)sec->data->d_buf, zero_bytes);
1022 
1023 	if ((tinfo->libelf_type != ELF_T_BYTE) &&
1024 	    (elf_xlatetom(sec->data, sec->data,
1025 	    fstate->ehdr->e_ident[EI_DATA]) == NULL)) {
1026 		sinfo_free(sec, 1);
1027 		failure(fstate->file, MSG_ORIG(MSG_ELF_XLATETOM));
1028 		return (0);
1029 	}
1030 
1031 	return (1);
1032 }
1033 
1034 
1035 
1036 /*
1037  * Generate a section header cache made up of information derived
1038  * from the program headers.
1039  *
1040  * entry:
1041  *	file - Name of object
1042  *	fd - Open file handle for object
1043  *	elf - ELF descriptor
1044  *	ehdr - Elf header
1045  *	cache, shnum - Addresses of variables to receive resulting
1046  *		cache and number of sections.
1047  *
1048  * exit:
1049  *	On success, *cache and *shnum are set, and True (1) is returned.
1050  *	On failure, False (0) is returned.
1051  *
1052  * note:
1053  *	The cache returned by this routine must be freed using
1054  *	fake_shdr_cache_free(), and not by a direct call to free().
1055  *	Otherwise, memory will leak.
1056  */
1057 int
1058 fake_shdr_cache(const char *file, int fd, Elf *elf, Ehdr *ehdr,
1059     Cache **cache, size_t *shnum)
1060 {
1061 	/*
1062 	 * The C language guarantees that a structure of homogeneous
1063 	 * items will receive exactly the same layout in a structure
1064 	 * as a plain array of the same type. Hence, this structure, which
1065 	 * gives us by-name or by-index access to the various section
1066 	 * info descriptors we maintain.
1067 	 *
1068 	 * We use this for sections where
1069 	 *	- Only one instance is allowed
1070 	 *	- We need to be able to access them easily by
1071 	 *		name (for instance, when mining the .dynamic
1072 	 *		section for information to build them up.
1073 	 *
1074 	 * NOTE: These fields must be in the same order as the
1075 	 * SINFO_T_ type codes that correspond to them. Otherwise,
1076 	 * they will end up in the wrong order in the cache array,
1077 	 * and the sh_link/sh_info fields may be wrong.
1078 	 */
1079 	struct {
1080 		/* Note: No entry is needed for SINFO_T_NULL */
1081 		SINFO	dyn;
1082 		SINFO	dynstr;
1083 		SINFO	dynsym;
1084 		SINFO	ldynsym;
1085 
1086 		SINFO	hash;
1087 		SINFO	syminfo;
1088 		SINFO	symsort;
1089 		SINFO	tlssort;
1090 		SINFO	verneed;
1091 		SINFO	verdef;
1092 		SINFO	versym;
1093 		SINFO	interp;
1094 		SINFO	cap;
1095 		SINFO	unwind;
1096 		SINFO	move;
1097 		SINFO	rel;
1098 		SINFO	rela;
1099 		SINFO	preinitarr;
1100 		SINFO	initarr;
1101 		SINFO	finiarr;
1102 	} sec;
1103 	static const size_t sinfo_n = sizeof (sec) / sizeof (sec.dyn);
1104 	SINFO *secarr = (SINFO *) &sec;
1105 
1106 	/*
1107 	 * Doubly linked circular list, used to track sections
1108 	 * where multiple sections of a given type can exist.
1109 	 * seclist is the root of the list. Its sinfo field is not
1110 	 * used --- it serves to anchor the root of the list, allowing
1111 	 * rapid access to the first and last element in the list.
1112 	 */
1113 	SINFO_LISTELT	seclist;
1114 
1115 	FSTATE		fstate;
1116 	size_t		ndx;
1117 	size_t		num_sinfo, num_list_sinfo;
1118 	SINFO		*sinfo;
1119 	SINFO_LISTELT	*sinfo_list;
1120 	Cache		*_cache;
1121 
1122 
1123 	fstate.file = file;
1124 	fstate.fd = fd;
1125 	fstate.ehdr = ehdr;
1126 	if (elf_getphnum(elf, &fstate.phnum) == 0) {
1127 		failure(file, MSG_ORIG(MSG_ELF_GETPHNUM));
1128 		return (0);
1129 	}
1130 	if ((fstate.phdr = elf_getphdr(elf)) == NULL) {
1131 		failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
1132 		return (0);
1133 	}
1134 
1135 	bzero(&sec, sizeof (sec));	/* Initialize "by-name" sec info */
1136 	seclist.next = seclist.prev = &seclist;	  /* Empty circular list */
1137 
1138 	/*
1139 	 * Go through the program headers and look for information
1140 	 * we can use to synthesize section headers. By far the most
1141 	 * valuable thing is a dynamic section, the contents of
1142 	 * which point at all sections used by ld.so.1.
1143 	 */
1144 	for (ndx = 0; ndx < fstate.phnum; ndx++) {
1145 		/*
1146 		 * A program header with no file size does
1147 		 * not have a backing section.
1148 		 */
1149 		if (fstate.phdr[ndx].p_filesz == 0)
1150 			continue;
1151 
1152 
1153 		switch (fstate.phdr[ndx].p_type) {
1154 		default:
1155 			/* Header we can't use. Move on to next one */
1156 			continue;
1157 
1158 		case PT_DYNAMIC:
1159 			sec.dyn.type = SINFO_T_DYN;
1160 			sinfo = &sec.dyn;
1161 			break;
1162 
1163 		case PT_INTERP:
1164 			sec.interp.type = SINFO_T_INTERP;
1165 			sinfo = &sec.interp;
1166 			break;
1167 
1168 		case PT_NOTE:
1169 			if ((sinfo = sinfo_list_alloc(&fstate, &seclist)) ==
1170 			    NULL)
1171 				continue;
1172 			sinfo->type = SINFO_T_NOTE;
1173 			break;
1174 
1175 		case PT_SUNW_UNWIND:
1176 			sec.unwind.type = SINFO_T_UNWIND;
1177 			sinfo = &sec.unwind;
1178 			break;
1179 
1180 		case PT_SUNWCAP:
1181 			sec.cap.type = SINFO_T_CAP;
1182 			sinfo = &sec.cap;
1183 			break;
1184 		}
1185 
1186 		/*
1187 		 * Capture the position/extent information for
1188 		 * the header in the SINFO struct set up by the
1189 		 * switch statement above.
1190 		 */
1191 		sinfo->vaddr = fstate.phdr[ndx].p_vaddr;
1192 		sinfo->offset = fstate.phdr[ndx].p_offset;
1193 		sinfo->size = fstate.phdr[ndx].p_filesz;
1194 	}
1195 
1196 	/*
1197 	 * If we found a dynamic section, look through it and
1198 	 * gather information about the sections it references.
1199 	 */
1200 	if (sec.dyn.type == SINFO_T_DYN)
1201 		(void) get_data(&fstate, &sec.dyn);
1202 	if ((sec.dyn.type == SINFO_T_DYN) && (sec.dyn.data->d_buf != NULL)) {
1203 		Dyn *dyn;
1204 		for (dyn = sec.dyn.data->d_buf; dyn->d_tag != DT_NULL; dyn++) {
1205 			switch (dyn->d_tag) {
1206 			case DT_HASH:
1207 				sec.hash.type = SINFO_T_HASH;
1208 				sec.hash.vaddr = dyn->d_un.d_ptr;
1209 				break;
1210 
1211 			case DT_STRTAB:
1212 				sec.dynstr.type = SINFO_T_DYNSTR;
1213 				sec.dynstr.vaddr = dyn->d_un.d_ptr;
1214 				break;
1215 
1216 			case DT_SYMTAB:
1217 				sec.dynsym.type = SINFO_T_DYNSYM;
1218 				sec.dynsym.vaddr = dyn->d_un.d_ptr;
1219 				break;
1220 
1221 			case DT_RELA:
1222 				sec.rela.type = SINFO_T_RELA;
1223 				sec.rela.vaddr = dyn->d_un.d_ptr;
1224 				break;
1225 
1226 			case DT_RELASZ:
1227 				sec.rela.size = dyn->d_un.d_val;
1228 				break;
1229 
1230 			case DT_STRSZ:
1231 				sec.dynstr.size = dyn->d_un.d_val;
1232 				break;
1233 
1234 			case DT_REL:
1235 				sec.rel.type = SINFO_T_REL;
1236 				sec.rel.vaddr = dyn->d_un.d_ptr;
1237 				break;
1238 
1239 			case DT_RELSZ:
1240 				sec.rel.size = dyn->d_un.d_val;
1241 				break;
1242 
1243 			case DT_INIT_ARRAY:
1244 				sec.initarr.type = SINFO_T_INITARR;
1245 				sec.initarr.vaddr = dyn->d_un.d_ptr;
1246 				break;
1247 
1248 			case DT_INIT_ARRAYSZ:
1249 				sec.initarr.size = dyn->d_un.d_val;
1250 				break;
1251 
1252 			case DT_FINI_ARRAY:
1253 				sec.finiarr.type = SINFO_T_FINIARR;
1254 				sec.finiarr.vaddr = dyn->d_un.d_ptr;
1255 				break;
1256 
1257 			case DT_FINI_ARRAYSZ:
1258 				sec.finiarr.size = dyn->d_un.d_val;
1259 				break;
1260 
1261 			case DT_PREINIT_ARRAY:
1262 				sec.preinitarr.type = SINFO_T_PREINITARR;
1263 				sec.preinitarr.vaddr = dyn->d_un.d_ptr;
1264 				break;
1265 
1266 			case DT_PREINIT_ARRAYSZ:
1267 				sec.preinitarr.size = dyn->d_un.d_val;
1268 				break;
1269 
1270 			case DT_SUNW_SYMTAB:
1271 				sec.ldynsym.type = SINFO_T_LDYNSYM;
1272 				sec.ldynsym.vaddr = dyn->d_un.d_ptr;
1273 				break;
1274 
1275 			case DT_SUNW_SYMSZ:
1276 				sec.ldynsym.size = dyn->d_un.d_val;
1277 				break;
1278 
1279 			case DT_SUNW_SYMSORT:
1280 				sec.symsort.type = SINFO_T_SYMSORT;
1281 				sec.symsort.vaddr = dyn->d_un.d_ptr;
1282 				break;
1283 
1284 			case DT_SUNW_SYMSORTSZ:
1285 				sec.symsort.size = dyn->d_un.d_val;
1286 				break;
1287 
1288 			case DT_SUNW_TLSSORT:
1289 				sec.tlssort.type = SINFO_T_TLSSORT;
1290 				sec.tlssort.vaddr = dyn->d_un.d_ptr;
1291 				break;
1292 
1293 			case DT_SUNW_TLSSORTSZ:
1294 				sec.tlssort.size = dyn->d_un.d_val;
1295 				break;
1296 
1297 			case DT_MOVETAB:
1298 				sec.move.type = SINFO_T_MOVE;
1299 				sec.move.vaddr = dyn->d_un.d_ptr;
1300 				break;
1301 
1302 			case DT_MOVESZ:
1303 				sec.move.size = dyn->d_un.d_val;
1304 				break;
1305 
1306 			case DT_SYMINFO:
1307 				sec.syminfo.type = SINFO_T_SYMINFO;
1308 				sec.syminfo.vaddr = dyn->d_un.d_ptr;
1309 				break;
1310 
1311 			case DT_SYMINSZ:
1312 				sec.syminfo.size = dyn->d_un.d_val;
1313 				break;
1314 
1315 			case DT_VERSYM:
1316 				sec.versym.type = SINFO_T_VERSYM;
1317 				sec.versym.vaddr = dyn->d_un.d_ptr;
1318 				break;
1319 
1320 			case DT_VERDEF:
1321 				sec.verdef.type = SINFO_T_VERDEF;
1322 				sec.verdef.vaddr = dyn->d_un.d_ptr;
1323 				break;
1324 
1325 			case DT_VERDEFNUM:
1326 				sec.verdef.vercnt = dyn->d_un.d_val;
1327 				sec.verdef.size = sizeof (Verdef) *
1328 				    dyn->d_un.d_val;
1329 				break;
1330 
1331 			case DT_VERNEED:
1332 				sec.verneed.type = SINFO_T_VERNEED;
1333 				sec.verneed.vaddr = dyn->d_un.d_ptr;
1334 				break;
1335 
1336 			case DT_VERNEEDNUM:
1337 				sec.verneed.vercnt = dyn->d_un.d_val;
1338 				sec.verneed.size = sizeof (Verneed) *
1339 				    dyn->d_un.d_val;
1340 				break;
1341 			}
1342 		}
1343 	}
1344 
1345 	/*
1346 	 * Different sections depend on each other, and are meaningless
1347 	 * without them. For instance, even if a .dynsym exists,
1348 	 * no use can be made of it without a dynstr. These relationships
1349 	 * fan out: Disqualifying the .dynsym will disqualify the hash
1350 	 * section, and so forth.
1351 	 *
1352 	 * Disqualify sections that don't have the necessary prerequisites.
1353 	 */
1354 
1355 	/* Things that need the dynamic string table */
1356 	if (sec.dynstr.size == 0)
1357 		sec.dynstr.type = SINFO_T_NULL;
1358 	if (sec.dynstr.type != SINFO_T_DYNSTR) {
1359 		sinfo_free(&sec.dyn, 1);	/* Data already fetched */
1360 		sec.dynsym.type =  SINFO_T_NULL;
1361 		sec.dynsym.type =  SINFO_T_NULL;
1362 		sec.verdef.type =  SINFO_T_NULL;
1363 		sec.verneed.type =  SINFO_T_NULL;
1364 	}
1365 
1366 	/*
1367 	 * The length of the hash section is encoded in its first two
1368 	 * elements (nbucket, and nchain). The length of the dynsym,
1369 	 * ldynsym, and versym are not given in the dynamic section,
1370 	 * but are known to be the same as nchain.
1371 	 *
1372 	 * If we don't have a hash table, or cannot read nbuckets and
1373 	 * nchain, we have to invalidate all of these.
1374 	 */
1375 	if (sec.hash.type == SINFO_T_HASH) {
1376 		Word nbucket;
1377 		Word nchain;
1378 		size_t total;
1379 
1380 		if (hash_size(&fstate, &sec.hash,
1381 		    &nbucket, &nchain, &total) == 0) {
1382 			sec.hash.type = SINFO_T_NULL;
1383 		} else {
1384 			/* Use these counts to set sizes for related sections */
1385 			sec.hash.size = total * sizeof (Word);
1386 			sec.dynsym.size = nchain * sizeof (Sym);
1387 			sec.versym.size = nchain * sizeof (Versym);
1388 
1389 			/*
1390 			 * The ldynsym size received the DT_SUNW_SYMSZ
1391 			 * value, which is the combined size of .dynsym
1392 			 * and .ldynsym. Now that we have the dynsym size,
1393 			 * use it to lower the ldynsym size to its real size.
1394 			 */
1395 			if (sec.ldynsym.size > sec.dynsym.size)
1396 				sec.ldynsym.size  -= sec.dynsym.size;
1397 		}
1398 	}
1399 	/*
1400 	 * If the hash table is not present, or if the call to
1401 	 * hash_size() failed, then discard the sections that
1402 	 * need it to determine their length.
1403 	 */
1404 	if (sec.hash.type != SINFO_T_HASH) {
1405 		sec.dynsym.type = SINFO_T_NULL;
1406 		sec.ldynsym.type = SINFO_T_NULL;
1407 		sec.versym.type = SINFO_T_NULL;
1408 	}
1409 
1410 	/*
1411 	 * The runtime linker does not receive size information for
1412 	 * Verdef and Verneed sections. We have to read their data
1413 	 * in pieces and calculate it.
1414 	 */
1415 	if ((sec.verdef.type == SINFO_T_VERDEF) &&
1416 	    (verdefneed_size(&fstate, &sec.verdef) == 0))
1417 		sec.verdef.type = SINFO_T_NULL;
1418 	if ((sec.verneed.type == SINFO_T_VERNEED) &&
1419 	    (verdefneed_size(&fstate, &sec.verneed) == 0))
1420 		sec.verneed.type = SINFO_T_NULL;
1421 
1422 	/* Discard any section with a zero length */
1423 	ndx = sinfo_n;
1424 	for (sinfo = secarr; ndx-- > 0; sinfo++)
1425 		if ((sinfo->type != SINFO_T_NULL) && (sinfo->size == 0))
1426 			sinfo->type = SINFO_T_NULL;
1427 
1428 	/* Things that need the dynamic symbol table */
1429 	if (sec.dynsym.type != SINFO_T_DYNSYM) {
1430 		sec.ldynsym.type = SINFO_T_NULL;
1431 		sec.hash.type = SINFO_T_NULL;
1432 		sec.syminfo.type = SINFO_T_NULL;
1433 		sec.versym.type = SINFO_T_NULL;
1434 		sec.move.type = SINFO_T_NULL;
1435 		sec.rel.type = SINFO_T_NULL;
1436 		sec.rela.type = SINFO_T_NULL;
1437 	}
1438 
1439 	/* Things that need the dynamic local symbol table */
1440 	if (sec.ldynsym.type != SINFO_T_DYNSYM) {
1441 		sec.symsort.type = SINFO_T_NULL;
1442 		sec.tlssort.type = SINFO_T_NULL;
1443 	}
1444 
1445 	/*
1446 	 * Look through the results and fetch the data for any sections
1447 	 * we have found. At the same time, count the number.
1448 	 */
1449 	num_sinfo = num_list_sinfo = 0;
1450 	ndx = sinfo_n;
1451 	for (sinfo = secarr; ndx-- > 0; sinfo++) {
1452 		if ((sinfo->type != SINFO_T_NULL) && (sinfo->data == NULL))
1453 			(void) get_data(&fstate, sinfo);
1454 		if (sinfo->data != NULL)
1455 			num_sinfo++;
1456 	}
1457 	for (sinfo_list = seclist.next; sinfo_list != &seclist;
1458 	    sinfo_list = sinfo_list->next) {
1459 		sinfo = &sinfo_list->sinfo;
1460 		if ((sinfo->type != SINFO_T_NULL) && (sinfo->data == NULL))
1461 			(void) get_data(&fstate, sinfo);
1462 		if (sinfo->data != NULL)
1463 			num_list_sinfo++;
1464 	}
1465 
1466 	/*
1467 	 * Allocate the cache array and fill it in. The cache array
1468 	 * ends up taking all the dynamic memory we've allocated
1469 	 * to build up sec and seclist, so on success, we have nothing
1470 	 * left to clean up. If we can't allocate the cache array
1471 	 * though, we have to free up everything else.
1472 	 */
1473 	*shnum = num_sinfo + num_list_sinfo + 1; /* Extra for 1st NULL sec. */
1474 	if ((*cache = _cache = malloc((*shnum) * sizeof (Cache))) == NULL) {
1475 		int err = errno;
1476 		(void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
1477 		    file, strerror(err));
1478 		sinfo_free(secarr, num_sinfo);
1479 		sinfo_list_free_all(&seclist);
1480 		return (0);
1481 	}
1482 	*_cache = cache_init;
1483 	_cache++;
1484 	ndx = 1;
1485 	for (sinfo = secarr; num_sinfo > 0; sinfo++) {
1486 		if (sinfo->data != NULL) {
1487 			_cache->c_scn = NULL;
1488 			_cache->c_shdr = sinfo->shdr;
1489 			_cache->c_data = sinfo->data;
1490 			_cache->c_name = (char *)sinfo_data[sinfo->type].name;
1491 			_cache->c_ndx = ndx++;
1492 			_cache++;
1493 			num_sinfo--;
1494 		}
1495 	}
1496 	for (sinfo_list = seclist.next; num_list_sinfo > 0;
1497 	    sinfo_list = sinfo_list->next) {
1498 		sinfo = &sinfo_list->sinfo;
1499 		if (sinfo->data != NULL) {
1500 			_cache->c_scn = NULL;
1501 			_cache->c_shdr = sinfo->shdr;
1502 			_cache->c_data = sinfo->data;
1503 			_cache->c_name = (char *)sinfo_data[sinfo->type].name;
1504 			_cache->c_ndx = ndx++;
1505 			_cache++;
1506 			num_list_sinfo--;
1507 		}
1508 	}
1509 
1510 	return (1);
1511 }
1512 
1513 
1514 
1515 
1516 
1517 /*
1518  * Release all the memory referenced by a cache array allocated
1519  * by fake_shdr_cache().
1520  */
1521 void
1522 fake_shdr_cache_free(Cache *cache, size_t shnum)
1523 {
1524 	Cache *_cache;
1525 
1526 	for (_cache = cache; shnum--; _cache++) {
1527 		if (_cache->c_data != NULL) {
1528 			if (_cache->c_data->d_buf != NULL)
1529 				free(_cache->c_data->d_buf);
1530 			free(_cache->c_data);
1531 		}
1532 		if (_cache->c_shdr)
1533 			free(_cache->c_shdr);
1534 	}
1535 
1536 	free(cache);
1537 }
1538