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