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