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