xref: /xnu-11417.140.69/libkern/kxld/kxld_symtab.c (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1 /*
2  * Copyright (c) 2008 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 #include <string.h>
29 #include <mach-o/loader.h>
30 #include <mach-o/nlist.h>
31 #include <sys/queue.h>
32 #include <sys/types.h>
33 
34 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
35 #include <AssertMacros.h>
36 
37 #include "kxld_array.h"
38 #include "kxld_dict.h"
39 #include "kxld_sect.h"
40 #include "kxld_sym.h"
41 #include "kxld_symtab.h"
42 #include "kxld_util.h"
43 
44 struct kxld_symtab {
45 	KXLDArray syms;
46 	KXLDDict cxx_index;
47 	KXLDDict name_index;
48 	char *strings;
49 	u_int strsize;
50 	boolean_t cxx_index_initialized;
51 	boolean_t name_index_initialized;
52 };
53 
54 /*******************************************************************************
55 * Prototypes
56 *******************************************************************************/
57 
58 static kern_return_t init_macho(KXLDSymtab *symtab, struct symtab_command *src,
59     u_char *macho, KXLDSeg * kernel_linkedit_seg,
60     boolean_t is_32_bit)
61 __attribute__((nonnull(1, 2)));
62 
63 #if KXLD_USER_OR_ILP32
64 static kern_return_t init_syms_32(KXLDSymtab *symtab, u_char *macho, u_long offset,
65     u_int nsyms);
66 #endif
67 #if KXLD_USER_OR_LP64
68 static kern_return_t init_syms_64(KXLDSymtab *symtab, u_char *macho, u_long offset,
69     u_int nsyms);
70 #endif
71 
72 static void restrict_private_symbols(KXLDSymtab *symtab)
73 __attribute__((nonnull));
74 static boolean_t sym_is_defined_cxx(const KXLDSym *sym);
75 static boolean_t sym_is_name_indexed(const KXLDSym *sym);
76 
77 /*******************************************************************************
78 *******************************************************************************/
79 size_t
kxld_symtab_sizeof(void)80 kxld_symtab_sizeof(void)
81 {
82 	return sizeof(KXLDSymtab);
83 }
84 
85 #if KXLD_USER_OR_ILP32
86 /*******************************************************************************
87 *******************************************************************************/
88 kern_return_t
kxld_symtab_init_from_macho_32(KXLDSymtab * symtab,struct symtab_command * src,u_char * macho,KXLDSeg * kernel_linkedit_seg)89 kxld_symtab_init_from_macho_32(KXLDSymtab *symtab, struct symtab_command *src,
90     u_char *macho, KXLDSeg * kernel_linkedit_seg)
91 {
92 	return init_macho(symtab, src, macho, kernel_linkedit_seg,
93 	           /* is_32_bit */ TRUE);
94 }
95 #endif /* KXLD_USER_ILP32 */
96 
97 #if KXLD_USER_OR_LP64
98 /*******************************************************************************
99 *******************************************************************************/
100 kern_return_t
kxld_symtab_init_from_macho_64(KXLDSymtab * symtab,struct symtab_command * src,u_char * macho,KXLDSeg * kernel_linkedit_seg)101 kxld_symtab_init_from_macho_64(KXLDSymtab *symtab, struct symtab_command *src,
102     u_char *macho, KXLDSeg * kernel_linkedit_seg)
103 {
104 	return init_macho(symtab, src, macho, kernel_linkedit_seg,
105 	           /* is_32_bit */ FALSE);
106 }
107 #endif /* KXLD_USER_OR_LP64 */
108 
109 /*******************************************************************************
110 *******************************************************************************/
111 static kern_return_t
init_macho(KXLDSymtab * symtab,struct symtab_command * src,u_char * macho,KXLDSeg * kernel_linkedit_seg,boolean_t is_32_bit __unused)112 init_macho(KXLDSymtab *symtab, struct symtab_command *src,
113     u_char *macho, KXLDSeg * kernel_linkedit_seg,
114     boolean_t is_32_bit __unused)
115 {
116 	kern_return_t rval = KERN_FAILURE;
117 	u_long symoff;
118 	u_char * macho_or_linkedit = macho;
119 
120 	check(symtab);
121 	check(src);
122 	check(macho);
123 
124 	/* Initialize the symbol array */
125 
126 	rval = kxld_array_init(&symtab->syms, sizeof(KXLDSym), src->nsyms);
127 	require_noerr(rval, finish);
128 
129 	/* Initialize the string table */
130 
131 	if (kernel_linkedit_seg) {
132 		/* If initing the kernel file in memory, we can't trust
133 		 * the symtab offsets directly, because the kernel file has been mapped
134 		 * into memory and the mach-o offsets are disk-based.
135 		 *
136 		 * The symoff is an offset relative to the linkedit segment
137 		 * so we just subtract the fileoffset of the linkedit segment
138 		 * to get its relative start.
139 		 *
140 		 * The strings table is an actual pointer, so we calculate that from
141 		 * the linkedit's vmaddr.
142 		 *
143 		 * Further, the init_syms_... functions need an adjusted base
144 		 * pointer instead of the beginning of the macho, so we substitute
145 		 * the base of the linkedit segment.
146 		 */
147 
148 		symoff = (u_long)(src->symoff - kernel_linkedit_seg->fileoff);
149 		symtab->strings = (char *)(uintptr_t)kernel_linkedit_seg->base_addr +
150 		    src->stroff - kernel_linkedit_seg->fileoff;
151 		macho_or_linkedit = (u_char *)(uintptr_t)kernel_linkedit_seg->base_addr;
152 	} else {
153 		symoff = (u_long)src->symoff;
154 		symtab->strings = (char *) (macho + src->stroff);
155 	}
156 
157 	symtab->strsize = src->strsize;
158 
159 	/* Initialize the symbols */
160 
161 	KXLD_3264_FUNC(is_32_bit, rval,
162 	    init_syms_32, init_syms_64,
163 	    symtab, macho_or_linkedit, symoff, src->nsyms);
164 	require_noerr(rval, finish);
165 
166 	/* Some symbols must be forced private for compatibility */
167 	(void) restrict_private_symbols(symtab);
168 
169 	/* Save the output */
170 
171 	rval = KERN_SUCCESS;
172 
173 finish:
174 	return rval;
175 }
176 
177 #if KXLD_USER_OR_ILP32
178 /*******************************************************************************
179 * In the running kernel, 'macho' is actually the start of the linkedit segment.
180 *******************************************************************************/
181 static kern_return_t
init_syms_32(KXLDSymtab * symtab,u_char * macho,u_long offset,u_int nsyms)182 init_syms_32(KXLDSymtab *symtab, u_char *macho, u_long offset, u_int nsyms)
183 {
184 	kern_return_t rval = KERN_FAILURE;
185 	KXLDSym *sym = NULL;
186 	u_int i = 0;
187 	struct nlist *src_syms = (struct nlist *) ((void *) (macho + offset));
188 
189 	for (i = 0; i < nsyms; ++i) {
190 		sym = kxld_array_get_item(&symtab->syms, i);
191 		require_action(sym, finish, rval = KERN_FAILURE);
192 
193 		rval = kxld_sym_init_from_macho32(sym, symtab->strings, &src_syms[i]);
194 		require_noerr(rval, finish);
195 	}
196 
197 	rval = KERN_SUCCESS;
198 
199 finish:
200 	return rval;
201 }
202 #endif /* KXLD_USER_OR_ILP32 */
203 
204 #if KXLD_USER_OR_LP64
205 /*******************************************************************************
206 * In the running kernel, 'macho' is actually the start of the linkedit segment.
207 *******************************************************************************/
208 static kern_return_t
init_syms_64(KXLDSymtab * symtab,u_char * macho,u_long offset,u_int nsyms)209 init_syms_64(KXLDSymtab *symtab, u_char *macho, u_long offset, u_int nsyms)
210 {
211 	kern_return_t rval = KERN_FAILURE;
212 	KXLDSym *sym = NULL;
213 	u_int i = 0;
214 	struct nlist_64 *src_syms = (struct nlist_64 *) ((void *) (macho + offset));
215 
216 	for (i = 0; i < nsyms; ++i) {
217 		sym = kxld_array_get_item(&symtab->syms, i);
218 		require_action(sym, finish, rval = KERN_FAILURE);
219 
220 		rval = kxld_sym_init_from_macho64(sym, symtab->strings, &src_syms[i]);
221 		require_noerr(rval, finish);
222 	}
223 
224 	rval = KERN_SUCCESS;
225 
226 finish:
227 	return rval;
228 }
229 #endif /* KXLD_USER_OR_LP64 */
230 
231 /*******************************************************************************
232 * Temporary workaround for PR-6668105
233 * new, new[], delete, and delete[] may be overridden globally in a kext.
234 * We should do this with some sort of weak symbols, but we'll flag these
235 * symbols as private for now to minimize risk.
236 *******************************************************************************/
237 static void
restrict_private_symbols(KXLDSymtab * symtab)238 restrict_private_symbols(KXLDSymtab *symtab)
239 {
240 	const char *private_symbols[] = {
241 		KXLD_KMOD_INFO_SYMBOL,
242 		KXLD_OPERATOR_NEW_SYMBOL,
243 		KXLD_OPERATOR_NEW_ARRAY_SYMBOL,
244 		KXLD_OPERATOR_DELETE_SYMBOL,
245 		KXLD_OPERATOR_DELETE_ARRAY_SYMBOL
246 	};
247 	KXLDSymtabIterator iter;
248 	KXLDSym *sym = NULL;
249 	const char *name = NULL;
250 	u_int i = 0;
251 
252 	kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_exported, FALSE);
253 	while ((sym = kxld_symtab_iterator_get_next(&iter))) {
254 		for (i = 0; i < const_array_len(private_symbols); ++i) {
255 			name = private_symbols[i];
256 			if (!streq(sym->name, name)) {
257 				continue;
258 			}
259 
260 			kxld_sym_mark_private(sym);
261 		}
262 	}
263 }
264 
265 
266 /*******************************************************************************
267 *******************************************************************************/
268 void
kxld_symtab_iterator_init(KXLDSymtabIterator * iter,const KXLDSymtab * symtab,KXLDSymPredicateTest test,boolean_t negate)269 kxld_symtab_iterator_init(KXLDSymtabIterator *iter, const KXLDSymtab *symtab,
270     KXLDSymPredicateTest test, boolean_t negate)
271 {
272 	check(iter);
273 	check(symtab);
274 	check(test);
275 
276 	iter->symtab = symtab;
277 	iter->idx = 0;
278 	iter->test = test;
279 	iter->negate = negate;
280 }
281 
282 /*******************************************************************************
283 *******************************************************************************/
284 void
kxld_symtab_clear(KXLDSymtab * symtab)285 kxld_symtab_clear(KXLDSymtab *symtab)
286 {
287 	check(symtab);
288 
289 	kxld_array_clear(&symtab->syms);
290 	kxld_dict_clear(&symtab->cxx_index);
291 	kxld_dict_clear(&symtab->name_index);
292 	symtab->strings = NULL;
293 	symtab->strsize = 0;
294 	symtab->cxx_index_initialized = 0;
295 	symtab->name_index_initialized = 0;
296 }
297 
298 /*******************************************************************************
299 *******************************************************************************/
300 void
kxld_symtab_deinit(KXLDSymtab * symtab)301 kxld_symtab_deinit(KXLDSymtab *symtab)
302 {
303 	check(symtab);
304 
305 	kxld_array_deinit(&symtab->syms);
306 	kxld_dict_deinit(&symtab->cxx_index);
307 	kxld_dict_deinit(&symtab->name_index);
308 	bzero(symtab, sizeof(*symtab));
309 }
310 
311 /*******************************************************************************
312 *******************************************************************************/
313 u_int
kxld_symtab_get_num_symbols(const KXLDSymtab * symtab)314 kxld_symtab_get_num_symbols(const KXLDSymtab *symtab)
315 {
316 	check(symtab);
317 
318 	return symtab->syms.nitems;
319 }
320 
321 /*******************************************************************************
322 *******************************************************************************/
323 KXLDSym *
kxld_symtab_get_symbol_by_index(const KXLDSymtab * symtab,u_int idx)324 kxld_symtab_get_symbol_by_index(const KXLDSymtab *symtab, u_int idx)
325 {
326 	check(symtab);
327 
328 	return kxld_array_get_item(&symtab->syms, idx);
329 }
330 
331 /*******************************************************************************
332 *******************************************************************************/
333 KXLDSym *
kxld_symtab_get_symbol_by_name(const KXLDSymtab * symtab,const char * name)334 kxld_symtab_get_symbol_by_name(const KXLDSymtab *symtab, const char *name)
335 {
336 	KXLDSym *sym = NULL;
337 	u_int i = 0;
338 
339 	for (i = 0; i < symtab->syms.nitems; ++i) {
340 		sym = kxld_array_get_item(&symtab->syms, i);
341 
342 		if (streq(sym->name, name)) {
343 			return sym;
344 		}
345 	}
346 
347 	return NULL;
348 }
349 
350 /*******************************************************************************
351 *******************************************************************************/
352 KXLDSym *
kxld_symtab_get_locally_defined_symbol_by_name(const KXLDSymtab * symtab,const char * name)353 kxld_symtab_get_locally_defined_symbol_by_name(const KXLDSymtab *symtab,
354     const char *name)
355 {
356 	check(symtab);
357 	check(name);
358 
359 	return kxld_dict_find(&symtab->name_index, name);
360 }
361 
362 /*******************************************************************************
363 *******************************************************************************/
364 KXLDSym *
kxld_symtab_get_cxx_symbol_by_value(const KXLDSymtab * symtab,kxld_addr_t value)365 kxld_symtab_get_cxx_symbol_by_value(const KXLDSymtab *symtab, kxld_addr_t value)
366 {
367 	check(symtab);
368 
369 	return kxld_dict_find(&symtab->cxx_index, &value);
370 }
371 
372 /*******************************************************************************
373 *******************************************************************************/
374 kern_return_t
kxld_symtab_get_sym_index(const KXLDSymtab * symtab,const KXLDSym * sym,u_int * symindex)375 kxld_symtab_get_sym_index(const KXLDSymtab *symtab, const KXLDSym *sym,
376     u_int *symindex)
377 {
378 	kern_return_t rval = KERN_FAILURE;
379 
380 	rval = kxld_array_get_index(&symtab->syms, sym, symindex);
381 	require_noerr(rval, finish);
382 
383 	rval = KERN_SUCCESS;
384 
385 finish:
386 	return rval;
387 }
388 
389 /*******************************************************************************
390 *******************************************************************************/
391 u_long
kxld_symtab_get_macho_header_size(void)392 kxld_symtab_get_macho_header_size(void)
393 {
394 	return sizeof(struct symtab_command);
395 }
396 
397 /*******************************************************************************
398 *******************************************************************************/
399 u_long
kxld_symtab_get_macho_data_size(const KXLDSymtab * symtab,boolean_t is_32_bit)400 kxld_symtab_get_macho_data_size(const KXLDSymtab *symtab, boolean_t is_32_bit)
401 {
402 	KXLDSymtabIterator iter;
403 	KXLDSym *sym = NULL;
404 	u_long size = 1; /* strtab start padding */
405 	u_int nsyms = 0;
406 
407 	check(symtab);
408 
409 	kxld_symtab_iterator_init(&iter, symtab,
410 	    kxld_sym_is_defined_locally, FALSE);
411 
412 	while ((sym = kxld_symtab_iterator_get_next(&iter))) {
413 		size += strlen(sym->name) + 1;
414 		++nsyms;
415 	}
416 
417 	if (is_32_bit) {
418 		size += nsyms * sizeof(struct nlist);
419 	} else {
420 		size += nsyms * sizeof(struct nlist_64);
421 	}
422 
423 	size = (size + 7) & ~7;
424 
425 	return size;
426 }
427 
428 /*******************************************************************************
429 *******************************************************************************/
430 kern_return_t
kxld_symtab_export_macho(const KXLDSymtab * symtab,u_char * buf,u_long * header_offset,u_long header_size,u_long * data_offset,u_long data_size,boolean_t is_32_bit)431 kxld_symtab_export_macho(const KXLDSymtab *symtab, u_char *buf,
432     u_long *header_offset, u_long header_size,
433     u_long *data_offset, u_long data_size,
434     boolean_t is_32_bit)
435 {
436 	kern_return_t rval = KERN_FAILURE;
437 	KXLDSymtabIterator iter;
438 	KXLDSym *sym = NULL;
439 	struct symtab_command *symtabhdr = NULL;
440 	u_char *nl = NULL;
441 	u_long nlistsize = 0;
442 	char *strtab = NULL;
443 	u_long stroff = 1; /* strtab start padding */
444 
445 	check(symtab);
446 	check(buf);
447 	check(header_offset);
448 	check(data_offset);
449 
450 	require_action(sizeof(*symtabhdr) <= header_size - *header_offset,
451 	    finish, rval = KERN_FAILURE);
452 	symtabhdr = (struct symtab_command *) ((void *) (buf + *header_offset));
453 	*header_offset += sizeof(*symtabhdr);
454 
455 	/* Initialize the symbol table header */
456 
457 	// note - this assumes LC_SYMTAB is always before the LC_DYSYMTAB in the
458 	// macho header we are processing.
459 	symtabhdr->cmd = LC_SYMTAB;
460 	symtabhdr->cmdsize = (uint32_t) sizeof(*symtabhdr);
461 	symtabhdr->symoff = (uint32_t) *data_offset;
462 	symtabhdr->strsize = 1; /* strtab start padding */
463 
464 	/* Find the size of the symbol and string tables */
465 
466 	kxld_symtab_iterator_init(&iter, symtab,
467 	    kxld_sym_is_defined_locally, FALSE);
468 
469 	while ((sym = kxld_symtab_iterator_get_next(&iter))) {
470 		symtabhdr->nsyms++;
471 		symtabhdr->strsize += (uint32_t) (strlen(sym->name) + 1);
472 	}
473 
474 	if (is_32_bit) {
475 		nlistsize = sizeof(struct nlist);
476 	} else {
477 		nlistsize = sizeof(struct nlist_64);
478 	}
479 
480 	symtabhdr->stroff = (uint32_t) (symtabhdr->symoff +
481 	    (symtabhdr->nsyms * nlistsize));
482 	require_action(symtabhdr->stroff + symtabhdr->strsize <= data_size, finish,
483 	    rval = KERN_FAILURE);
484 
485 	/* Get pointers to the symbol and string tables */
486 	nl = buf + symtabhdr->symoff;
487 	strtab = (char *) (buf + symtabhdr->stroff);
488 
489 	/* Copy over the symbols */
490 
491 	kxld_symtab_iterator_reset(&iter);
492 	while ((sym = kxld_symtab_iterator_get_next(&iter))) {
493 		KXLD_3264_FUNC(is_32_bit, rval,
494 		    kxld_sym_export_macho_32, kxld_sym_export_macho_64,
495 		    sym, nl, strtab, &stroff, symtabhdr->strsize);
496 		require_noerr(rval, finish);
497 
498 		nl += nlistsize;
499 		stroff += rval;
500 	}
501 
502 	/* Update the data offset */
503 	*data_offset += (symtabhdr->nsyms * nlistsize) + stroff;
504 
505 	*data_offset = (*data_offset + 7) & ~7;
506 	// at this point data_offset will be the offset just past the
507 	// symbols and strings in the __LINKEDIT data
508 
509 
510 #if SPLIT_KEXTS_DEBUG
511 	{
512 		kxld_log(kKxldLogLinking, kKxldLogErr,
513 		    " %p to %p (size %lu) symtabhdr <%s>",
514 		    (void *) symtabhdr,
515 		    (void *) ((u_char *)symtabhdr + sizeof(*symtabhdr)),
516 		    sizeof(*symtabhdr),
517 		    __func__);
518 
519 		kxld_log(kKxldLogLinking, kKxldLogErr,
520 		    " symtabhdr %p cmdsize %u symoff %u nsyms %u stroff %u strsize %u <%s>",
521 		    (void *) symtabhdr,
522 		    symtabhdr->cmdsize,
523 		    symtabhdr->symoff,
524 		    symtabhdr->nsyms,
525 		    symtabhdr->stroff,
526 		    symtabhdr->strsize,
527 		    __func__);
528 	}
529 #endif
530 
531 	rval = KERN_SUCCESS;
532 
533 finish:
534 	return rval;
535 }
536 
537 /*******************************************************************************
538 *******************************************************************************/
539 u_int
kxld_symtab_iterator_get_num_remaining(const KXLDSymtabIterator * iter)540 kxld_symtab_iterator_get_num_remaining(const KXLDSymtabIterator *iter)
541 {
542 	u_int idx = 0;
543 	u_int count = 0;
544 
545 	check(iter);
546 
547 	for (idx = iter->idx; idx < iter->symtab->syms.nitems; ++idx) {
548 		count += iter->test(kxld_array_get_item(&iter->symtab->syms, idx));
549 	}
550 
551 	return count;
552 }
553 
554 /*******************************************************************************
555 *******************************************************************************/
556 kern_return_t
kxld_symtab_index_cxx_symbols_by_value(KXLDSymtab * symtab)557 kxld_symtab_index_cxx_symbols_by_value(KXLDSymtab *symtab)
558 {
559 	kern_return_t rval = KERN_FAILURE;
560 	KXLDSymtabIterator iter;
561 	KXLDSym *sym = NULL;
562 	u_int nsyms = 0;
563 
564 	check(symtab);
565 
566 	if (symtab->cxx_index_initialized) {
567 		rval = KERN_SUCCESS;
568 		goto finish;
569 	}
570 
571 	/* Count the number of C++ symbols */
572 	kxld_symtab_iterator_init(&iter, symtab, sym_is_defined_cxx, FALSE);
573 	nsyms = kxld_symtab_iterator_get_num_remaining(&iter);
574 
575 	/* Create the dictionary */
576 	rval = kxld_dict_init(&symtab->cxx_index, kxld_dict_kxldaddr_hash,
577 	    kxld_dict_kxldaddr_cmp, nsyms);
578 	require_noerr(rval, finish);
579 
580 	/* Insert the non-stab symbols */
581 	while ((sym = kxld_symtab_iterator_get_next(&iter))) {
582 		rval = kxld_dict_insert(&symtab->cxx_index, &sym->base_addr, sym);
583 		require_noerr(rval, finish);
584 	}
585 
586 
587 	symtab->cxx_index_initialized = TRUE;
588 	rval = KERN_SUCCESS;
589 finish:
590 	return rval;
591 }
592 
593 /*******************************************************************************
594 *******************************************************************************/
595 static boolean_t
sym_is_defined_cxx(const KXLDSym * sym)596 sym_is_defined_cxx(const KXLDSym *sym)
597 {
598 	return kxld_sym_is_defined_locally(sym) && kxld_sym_is_cxx(sym);
599 }
600 
601 /*******************************************************************************
602 *******************************************************************************/
603 kern_return_t
kxld_symtab_index_symbols_by_name(KXLDSymtab * symtab)604 kxld_symtab_index_symbols_by_name(KXLDSymtab *symtab)
605 {
606 	kern_return_t rval = KERN_FAILURE;
607 	KXLDSymtabIterator iter;
608 	KXLDSym *sym = NULL;
609 	u_int nsyms = 0;
610 
611 	check(symtab);
612 
613 	if (symtab->name_index_initialized) {
614 		rval = KERN_SUCCESS;
615 		goto finish;
616 	}
617 
618 	/* Count the number of symbols we need to index by name */
619 	kxld_symtab_iterator_init(&iter, symtab, sym_is_name_indexed, FALSE);
620 	nsyms = kxld_symtab_iterator_get_num_remaining(&iter);
621 
622 	/* Create the dictionary */
623 	rval = kxld_dict_init(&symtab->name_index, kxld_dict_string_hash,
624 	    kxld_dict_string_cmp, nsyms);
625 	require_noerr(rval, finish);
626 
627 	/* Insert the non-stab symbols */
628 	while ((sym = kxld_symtab_iterator_get_next(&iter))) {
629 		rval = kxld_dict_insert(&symtab->name_index, sym->name, sym);
630 		require_noerr(rval, finish);
631 	}
632 
633 	symtab->name_index_initialized = TRUE;
634 	rval = KERN_SUCCESS;
635 finish:
636 
637 	return rval;
638 }
639 /*******************************************************************************
640 *******************************************************************************/
641 static boolean_t
sym_is_name_indexed(const KXLDSym * sym)642 sym_is_name_indexed(const KXLDSym *sym)
643 {
644 	return kxld_sym_is_defined_locally(sym) && !kxld_sym_is_stab(sym);
645 }
646 
647 /*******************************************************************************
648 *******************************************************************************/
649 kern_return_t
kxld_symtab_relocate(KXLDSymtab * symtab,const KXLDArray * sectarray)650 kxld_symtab_relocate(KXLDSymtab *symtab, const KXLDArray *sectarray)
651 {
652 	kern_return_t rval = KERN_FAILURE;
653 	KXLDSymtabIterator iter;
654 	KXLDSym *sym = NULL;
655 	const KXLDSect *sect = NULL;
656 
657 	check(symtab);
658 	check(sectarray);
659 
660 	kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_section, FALSE);
661 
662 	while ((sym = kxld_symtab_iterator_get_next(&iter))) {
663 		sect = kxld_array_get_item(sectarray, sym->sectnum);
664 		require_action(sect, finish, rval = KERN_FAILURE);
665 		kxld_sym_relocate(sym, sect);
666 	}
667 
668 	rval = KERN_SUCCESS;
669 
670 finish:
671 
672 	return rval;
673 }
674 
675 /*******************************************************************************
676 * This extends the symbol table and initializes the new symbol.  We insert the
677 * symbol into the name index, but we don't bother with the c++ value index
678 * because it is based on the base_addr of the symbol, and the base_addr of
679 * all synthesized symbols will be 0.
680 *******************************************************************************/
681 kern_return_t
kxld_symtab_add_symbol(KXLDSymtab * symtab,char * name,kxld_addr_t link_addr,KXLDSym ** symout)682 kxld_symtab_add_symbol(KXLDSymtab *symtab, char *name, kxld_addr_t link_addr,
683     KXLDSym **symout)
684 {
685 	kern_return_t rval = KERN_FAILURE;
686 	KXLDSym *sym = NULL;
687 	u_int symindex = symtab->syms.nitems;
688 
689 	rval = kxld_array_resize(&symtab->syms, symindex + 1);
690 	require_noerr(rval, finish);
691 
692 	sym = kxld_array_get_item(&symtab->syms, symindex);
693 	kxld_sym_init_absolute(sym, name, link_addr);
694 
695 	rval = kxld_dict_insert(&symtab->name_index, sym->name, sym);
696 	require_noerr(rval, finish);
697 
698 	rval = KERN_SUCCESS;
699 	*symout = sym;
700 
701 finish:
702 	return rval;
703 }
704 
705 /*******************************************************************************
706 *******************************************************************************/
707 KXLDSym *
kxld_symtab_iterator_get_next(KXLDSymtabIterator * iter)708 kxld_symtab_iterator_get_next(KXLDSymtabIterator *iter)
709 {
710 	KXLDSym *sym = NULL;
711 	KXLDSym *tmp = NULL;
712 	boolean_t cmp = FALSE;
713 
714 	check(iter);
715 
716 	for (; iter->idx < iter->symtab->syms.nitems; ++iter->idx) {
717 		tmp = kxld_array_get_item(&iter->symtab->syms, iter->idx);
718 		cmp = iter->test(tmp);
719 		if (iter->negate) {
720 			cmp = !cmp;
721 		}
722 
723 		if (cmp) {
724 			sym = tmp;
725 			++iter->idx;
726 			break;
727 		}
728 	}
729 
730 	return sym;
731 }
732 
733 
734 /*******************************************************************************
735 *******************************************************************************/
736 void
kxld_symtab_iterator_reset(KXLDSymtabIterator * iter)737 kxld_symtab_iterator_reset(KXLDSymtabIterator *iter)
738 {
739 	check(iter);
740 	iter->idx = 0;
741 }
742