]> git.saurik.com Git - apple/xnu.git/blame - libkern/kxld/kxld_symtab.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / libkern / kxld / kxld_symtab.c
CommitLineData
b0d623f7
A
1/*
2 * Copyright (c) 2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
b0d623f7
A
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.
0a7de745 14 *
b0d623f7
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
b0d623f7
A
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.
0a7de745 25 *
b0d623f7
A
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
44struct kxld_symtab {
0a7de745
A
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;
b0d623f7
A
52};
53
54/*******************************************************************************
55* Prototypes
56*******************************************************************************/
57
6d2010ae
A
58static 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)
0a7de745 61__attribute__((nonnull(1, 2)));
b0d623f7
A
62
63#if KXLD_USER_OR_ILP32
6d2010ae 64static kern_return_t init_syms_32(KXLDSymtab *symtab, u_char *macho, u_long offset,
b0d623f7
A
65 u_int nsyms);
66#endif
67#if KXLD_USER_OR_LP64
6d2010ae 68static kern_return_t init_syms_64(KXLDSymtab *symtab, u_char *macho, u_long offset,
b0d623f7
A
69 u_int nsyms);
70#endif
71
6d2010ae 72static void restrict_private_symbols(KXLDSymtab *symtab)
0a7de745 73__attribute__((nonnull));
b0d623f7 74static boolean_t sym_is_defined_cxx(const KXLDSym *sym);
b0d623f7
A
75static boolean_t sym_is_name_indexed(const KXLDSym *sym);
76
b0d623f7
A
77/*******************************************************************************
78*******************************************************************************/
79size_t
80kxld_symtab_sizeof()
81{
0a7de745 82 return sizeof(KXLDSymtab);
b0d623f7
A
83}
84
85#if KXLD_USER_OR_ILP32
86/*******************************************************************************
87*******************************************************************************/
88kern_return_t
6d2010ae
A
89kxld_symtab_init_from_macho_32(KXLDSymtab *symtab, struct symtab_command *src,
90 u_char *macho, KXLDSeg * kernel_linkedit_seg)
b0d623f7 91{
0a7de745
A
92 return init_macho(symtab, src, macho, kernel_linkedit_seg,
93 /* is_32_bit */ TRUE);
b0d623f7
A
94}
95#endif /* KXLD_USER_ILP32 */
96
97#if KXLD_USER_OR_LP64
98/*******************************************************************************
99*******************************************************************************/
100kern_return_t
6d2010ae
A
101kxld_symtab_init_from_macho_64(KXLDSymtab *symtab, struct symtab_command *src,
102 u_char *macho, KXLDSeg * kernel_linkedit_seg)
b0d623f7 103{
0a7de745
A
104 return init_macho(symtab, src, macho, kernel_linkedit_seg,
105 /* is_32_bit */ FALSE);
b0d623f7
A
106}
107#endif /* KXLD_USER_OR_LP64 */
108
109/*******************************************************************************
110*******************************************************************************/
111static kern_return_t
6d2010ae
A
112init_macho(KXLDSymtab *symtab, struct symtab_command *src,
113 u_char *macho, KXLDSeg * kernel_linkedit_seg,
114 boolean_t is_32_bit __unused)
b0d623f7 115{
0a7de745
A
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;
b0d623f7
A
172
173finish:
0a7de745 174 return rval;
b0d623f7
A
175}
176
177#if KXLD_USER_OR_ILP32
178/*******************************************************************************
6d2010ae 179* In the running kernel, 'macho' is actually the start of the linkedit segment.
b0d623f7
A
180*******************************************************************************/
181static kern_return_t
182init_syms_32(KXLDSymtab *symtab, u_char *macho, u_long offset, u_int nsyms)
183{
0a7de745
A
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));
b0d623f7 188
0a7de745
A
189 for (i = 0; i < nsyms; ++i) {
190 sym = kxld_array_get_item(&symtab->syms, i);
191 require_action(sym, finish, rval = KERN_FAILURE);
b0d623f7 192
0a7de745
A
193 rval = kxld_sym_init_from_macho32(sym, symtab->strings, &src_syms[i]);
194 require_noerr(rval, finish);
195 }
b0d623f7 196
0a7de745 197 rval = KERN_SUCCESS;
b0d623f7
A
198
199finish:
0a7de745 200 return rval;
b0d623f7
A
201}
202#endif /* KXLD_USER_OR_ILP32 */
203
204#if KXLD_USER_OR_LP64
205/*******************************************************************************
6d2010ae 206* In the running kernel, 'macho' is actually the start of the linkedit segment.
b0d623f7
A
207*******************************************************************************/
208static kern_return_t
209init_syms_64(KXLDSymtab *symtab, u_char *macho, u_long offset, u_int nsyms)
210{
0a7de745
A
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));
b0d623f7 215
0a7de745
A
216 for (i = 0; i < nsyms; ++i) {
217 sym = kxld_array_get_item(&symtab->syms, i);
218 require_action(sym, finish, rval = KERN_FAILURE);
b0d623f7 219
0a7de745
A
220 rval = kxld_sym_init_from_macho64(sym, symtab->strings, &src_syms[i]);
221 require_noerr(rval, finish);
222 }
b0d623f7 223
0a7de745 224 rval = KERN_SUCCESS;
b0d623f7
A
225
226finish:
0a7de745 227 return rval;
b0d623f7
A
228}
229#endif /* KXLD_USER_OR_LP64 */
230
6d2010ae 231/*******************************************************************************
0a7de745 232* Temporary workaround for PR-6668105
6d2010ae 233* new, new[], delete, and delete[] may be overridden globally in a kext.
0a7de745
A
234* We should do this with some sort of weak symbols, but we'll use a whitelist
235* for now to minimize risk.
6d2010ae
A
236*******************************************************************************/
237static void
238restrict_private_symbols(KXLDSymtab *symtab)
239{
0a7de745
A
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 }
6d2010ae
A
263}
264
265
b0d623f7
A
266/*******************************************************************************
267*******************************************************************************/
268void
269kxld_symtab_iterator_init(KXLDSymtabIterator *iter, const KXLDSymtab *symtab,
270 KXLDSymPredicateTest test, boolean_t negate)
271{
0a7de745
A
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;
b0d623f7
A
280}
281
282/*******************************************************************************
283*******************************************************************************/
0a7de745 284void
b0d623f7
A
285kxld_symtab_clear(KXLDSymtab *symtab)
286{
0a7de745
A
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;
b0d623f7
A
296}
297
298/*******************************************************************************
299*******************************************************************************/
300void
301kxld_symtab_deinit(KXLDSymtab *symtab)
302{
0a7de745 303 check(symtab);
b0d623f7 304
0a7de745
A
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));
b0d623f7
A
309}
310
311/*******************************************************************************
312*******************************************************************************/
313u_int
314kxld_symtab_get_num_symbols(const KXLDSymtab *symtab)
315{
0a7de745 316 check(symtab);
b0d623f7 317
0a7de745 318 return symtab->syms.nitems;
b0d623f7
A
319}
320
321/*******************************************************************************
322*******************************************************************************/
323KXLDSym *
324kxld_symtab_get_symbol_by_index(const KXLDSymtab *symtab, u_int idx)
325{
0a7de745 326 check(symtab);
b0d623f7 327
0a7de745 328 return kxld_array_get_item(&symtab->syms, idx);
b0d623f7
A
329}
330
331/*******************************************************************************
332*******************************************************************************/
0a7de745 333KXLDSym *
b0d623f7 334kxld_symtab_get_symbol_by_name(const KXLDSymtab *symtab, const char *name)
6d2010ae 335{
0a7de745
A
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;
6d2010ae
A
348}
349
350/*******************************************************************************
351*******************************************************************************/
352KXLDSym *
0a7de745 353kxld_symtab_get_locally_defined_symbol_by_name(const KXLDSymtab *symtab,
6d2010ae 354 const char *name)
b0d623f7 355{
0a7de745
A
356 check(symtab);
357 check(name);
b0d623f7 358
0a7de745 359 return kxld_dict_find(&symtab->name_index, name);
b0d623f7
A
360}
361
362/*******************************************************************************
363*******************************************************************************/
364KXLDSym *
365kxld_symtab_get_cxx_symbol_by_value(const KXLDSymtab *symtab, kxld_addr_t value)
366{
0a7de745 367 check(symtab);
b0d623f7 368
0a7de745 369 return kxld_dict_find(&symtab->cxx_index, &value);
b0d623f7
A
370}
371
372/*******************************************************************************
373*******************************************************************************/
0a7de745 374kern_return_t
b0d623f7
A
375kxld_symtab_get_sym_index(const KXLDSymtab *symtab, const KXLDSym *sym,
376 u_int *symindex)
377{
0a7de745 378 kern_return_t rval = KERN_FAILURE;
b0d623f7 379
0a7de745
A
380 rval = kxld_array_get_index(&symtab->syms, sym, symindex);
381 require_noerr(rval, finish);
b0d623f7 382
0a7de745 383 rval = KERN_SUCCESS;
b0d623f7
A
384
385finish:
0a7de745 386 return rval;
b0d623f7
A
387}
388
389/*******************************************************************************
390*******************************************************************************/
391u_long
392kxld_symtab_get_macho_header_size(void)
393{
0a7de745 394 return sizeof(struct symtab_command);
b0d623f7
A
395}
396
397/*******************************************************************************
398*******************************************************************************/
0a7de745 399u_long
6d2010ae 400kxld_symtab_get_macho_data_size(const KXLDSymtab *symtab, boolean_t is_32_bit)
b0d623f7 401{
0a7de745
A
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;
b0d623f7
A
426}
427
428/*******************************************************************************
429*******************************************************************************/
430kern_return_t
0a7de745 431kxld_symtab_export_macho(const KXLDSymtab *symtab, u_char *buf,
b0d623f7
A
432 u_long *header_offset, u_long header_size,
433 u_long *data_offset, u_long data_size,
6d2010ae 434 boolean_t is_32_bit)
b0d623f7 435{
0a7de745
A
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
39037602
A
509
510#if SPLIT_KEXTS_DEBUG
0a7de745
A
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 }
39037602 529#endif
316670eb 530
0a7de745
A
531 rval = KERN_SUCCESS;
532
b0d623f7 533finish:
0a7de745 534 return rval;
b0d623f7
A
535}
536
537/*******************************************************************************
538*******************************************************************************/
539u_int
540kxld_symtab_iterator_get_num_remaining(const KXLDSymtabIterator *iter)
541{
0a7de745
A
542 u_int idx = 0;
543 u_int count = 0;
b0d623f7 544
0a7de745 545 check(iter);
b0d623f7 546
0a7de745
A
547 for (idx = iter->idx; idx < iter->symtab->syms.nitems; ++idx) {
548 count += iter->test(kxld_array_get_item(&iter->symtab->syms, idx));
549 }
b0d623f7 550
0a7de745 551 return count;
b0d623f7
A
552}
553
554/*******************************************************************************
555*******************************************************************************/
6d2010ae
A
556kern_return_t
557kxld_symtab_index_cxx_symbols_by_value(KXLDSymtab *symtab)
b0d623f7 558{
0a7de745
A
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;
b0d623f7 589finish:
0a7de745 590 return rval;
b0d623f7
A
591}
592
593/*******************************************************************************
594*******************************************************************************/
595static boolean_t
596sym_is_defined_cxx(const KXLDSym *sym)
597{
0a7de745 598 return kxld_sym_is_defined_locally(sym) && kxld_sym_is_cxx(sym);
b0d623f7
A
599}
600
601/*******************************************************************************
602*******************************************************************************/
6d2010ae
A
603kern_return_t
604kxld_symtab_index_symbols_by_name(KXLDSymtab *symtab)
b0d623f7 605{
0a7de745
A
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;
b0d623f7
A
635finish:
636
0a7de745 637 return rval;
b0d623f7 638}
b0d623f7
A
639/*******************************************************************************
640*******************************************************************************/
641static boolean_t
642sym_is_name_indexed(const KXLDSym *sym)
643{
0a7de745 644 return kxld_sym_is_defined_locally(sym) && !kxld_sym_is_stab(sym);
b0d623f7
A
645}
646
647/*******************************************************************************
648*******************************************************************************/
649kern_return_t
650kxld_symtab_relocate(KXLDSymtab *symtab, const KXLDArray *sectarray)
651{
0a7de745
A
652 kern_return_t rval = KERN_FAILURE;
653 KXLDSymtabIterator iter;
654 KXLDSym *sym = NULL;
655 const KXLDSect *sect = NULL;
b0d623f7 656
0a7de745
A
657 check(symtab);
658 check(sectarray);
b0d623f7 659
0a7de745 660 kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_section, FALSE);
b0d623f7 661
0a7de745
A
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;
b0d623f7
A
669
670finish:
671
0a7de745 672 return rval;
b0d623f7
A
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*******************************************************************************/
681kern_return_t
682kxld_symtab_add_symbol(KXLDSymtab *symtab, char *name, kxld_addr_t link_addr,
683 KXLDSym **symout)
684{
0a7de745
A
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);
b0d623f7 691
0a7de745
A
692 sym = kxld_array_get_item(&symtab->syms, symindex);
693 kxld_sym_init_absolute(sym, name, link_addr);
b0d623f7 694
0a7de745
A
695 rval = kxld_dict_insert(&symtab->name_index, sym->name, sym);
696 require_noerr(rval, finish);
b0d623f7 697
0a7de745
A
698 rval = KERN_SUCCESS;
699 *symout = sym;
b0d623f7 700
b0d623f7 701finish:
0a7de745 702 return rval;
b0d623f7
A
703}
704
705/*******************************************************************************
706*******************************************************************************/
707KXLDSym *
708kxld_symtab_iterator_get_next(KXLDSymtabIterator *iter)
709{
0a7de745
A
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;
b0d623f7
A
731}
732
733
734/*******************************************************************************
735*******************************************************************************/
736void
737kxld_symtab_iterator_reset(KXLDSymtabIterator *iter)
738{
0a7de745
A
739 check(iter);
740 iter->idx = 0;
b0d623f7 741}