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