]> git.saurik.com Git - apple/xnu.git/blame - libkern/kxld/kxld_symtab.c
xnu-1699.22.73.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@
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
44struct kxld_symtab {
45 KXLDArray syms;
46 KXLDDict cxx_index;
47 KXLDDict name_index;
48 char *strings;
49 u_int strsize;
6d2010ae
A
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)
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)
b0d623f7
A
73 __attribute__((nonnull));
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{
82 return sizeof(KXLDSymtab);
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{
6d2010ae
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{
6d2010ae
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
A
115{
116 kern_return_t rval = KERN_FAILURE;
6d2010ae
A
117 u_long symoff;
118 u_char * macho_or_linkedit = macho;
b0d623f7
A
119
120 check(symtab);
b0d623f7 121 check(src);
6d2010ae 122 check(macho);
b0d623f7
A
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
6d2010ae
A
131 if (kernel_linkedit_seg) {
132
133 /* If initing the kernel file in memory, we can't trust
134 * the symtab offsets directly, because the kernel file has been mapped
135 * into memory and the mach-o offsets are disk-based.
136 *
137 * The symoff is an offset relative to the linkedit segment
138 * so we just subtract the fileoffset of the linkedit segment
139 * to get its relative start.
140 *
141 * The strings table is an actual pointer, so we calculate that from
142 * the linkedit's vmaddr.
143 *
144 * Further, the init_syms_... functions need an adjusted base
145 * pointer instead of the beginning of the macho, so we substitute
146 * the base of the linkedit segment.
147 */
148
149 symoff = (u_long)(src->symoff - kernel_linkedit_seg->fileoff);
150 symtab->strings = (char *)(uintptr_t)kernel_linkedit_seg->base_addr +
151 src->stroff - kernel_linkedit_seg->fileoff;
152 macho_or_linkedit = (u_char *)(uintptr_t)kernel_linkedit_seg->base_addr;
153 } else {
154 symoff = (u_long)src->symoff;
155 symtab->strings = (char *) (macho + src->stroff);
156 }
157
b0d623f7
A
158 symtab->strsize = src->strsize;
159
160 /* Initialize the symbols */
161
162 KXLD_3264_FUNC(is_32_bit, rval,
163 init_syms_32, init_syms_64,
6d2010ae 164 symtab, macho_or_linkedit, symoff, src->nsyms);
b0d623f7
A
165 require_noerr(rval, finish);
166
6d2010ae
A
167 /* Some symbols must be forced private for compatibility */
168 (void) restrict_private_symbols(symtab);
169
b0d623f7
A
170 /* Save the output */
171
172 rval = KERN_SUCCESS;
173
174finish:
175 return rval;
176}
177
178#if KXLD_USER_OR_ILP32
179/*******************************************************************************
6d2010ae 180* In the running kernel, 'macho' is actually the start of the linkedit segment.
b0d623f7
A
181*******************************************************************************/
182static kern_return_t
183init_syms_32(KXLDSymtab *symtab, u_char *macho, u_long offset, u_int nsyms)
184{
185 kern_return_t rval = KERN_FAILURE;
186 KXLDSym *sym = NULL;
187 u_int i = 0;
188 struct nlist *src_syms = (struct nlist *) (macho + offset);
189
190 for (i = 0; i < nsyms; ++i) {
191 sym = kxld_array_get_item(&symtab->syms, i);
192 require_action(sym, finish, rval=KERN_FAILURE);
193
194 rval = kxld_sym_init_from_macho32(sym, symtab->strings, &src_syms[i]);
195 require_noerr(rval, finish);
196 }
197
198 rval = KERN_SUCCESS;
199
200finish:
201 return rval;
202}
203#endif /* KXLD_USER_OR_ILP32 */
204
205#if KXLD_USER_OR_LP64
206/*******************************************************************************
6d2010ae 207* In the running kernel, 'macho' is actually the start of the linkedit segment.
b0d623f7
A
208*******************************************************************************/
209static kern_return_t
210init_syms_64(KXLDSymtab *symtab, u_char *macho, u_long offset, u_int nsyms)
211{
212 kern_return_t rval = KERN_FAILURE;
213 KXLDSym *sym = NULL;
214 u_int i = 0;
215 struct nlist_64 *src_syms = (struct nlist_64 *) (macho + offset);
216
217 for (i = 0; i < nsyms; ++i) {
218 sym = kxld_array_get_item(&symtab->syms, i);
219 require_action(sym, finish, rval=KERN_FAILURE);
220
221 rval = kxld_sym_init_from_macho64(sym, symtab->strings, &src_syms[i]);
222 require_noerr(rval, finish);
223 }
224
225 rval = KERN_SUCCESS;
226
227finish:
228 return rval;
229}
230#endif /* KXLD_USER_OR_LP64 */
231
6d2010ae
A
232/*******************************************************************************
233* Temporary workaround for PR-6668105
234* new, new[], delete, and delete[] may be overridden globally in a kext.
235* We should do this with some sort of weak symbols, but we'll use a whitelist
236* for now to minimize risk.
237*******************************************************************************/
238static void
239restrict_private_symbols(KXLDSymtab *symtab)
240{
241 const char *private_symbols[] = {
242 KXLD_KMOD_INFO_SYMBOL,
243 KXLD_OPERATOR_NEW_SYMBOL,
244 KXLD_OPERATOR_NEW_ARRAY_SYMBOL,
245 KXLD_OPERATOR_DELETE_SYMBOL,
246 KXLD_OPERATOR_DELETE_ARRAY_SYMBOL
247 };
248 KXLDSymtabIterator iter;
249 KXLDSym *sym = NULL;
250 const char *name = NULL;
251 u_int i = 0;
252
253 kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_exported, FALSE);
254 while ((sym = kxld_symtab_iterator_get_next(&iter))) {
255 for (i = 0; i < const_array_len(private_symbols); ++i) {
256 name = private_symbols[i];
257 if (!streq(sym->name, name)) {
258 continue;
259 }
260
261 kxld_sym_mark_private(sym);
262 }
263 }
264}
265
266
b0d623f7
A
267/*******************************************************************************
268*******************************************************************************/
269void
270kxld_symtab_iterator_init(KXLDSymtabIterator *iter, const KXLDSymtab *symtab,
271 KXLDSymPredicateTest test, boolean_t negate)
272{
273 check(iter);
274 check(symtab);
275 check(test);
276
277 iter->symtab = symtab;
278 iter->idx = 0;
279 iter->test = test;
280 iter->negate = negate;
281}
282
283/*******************************************************************************
284*******************************************************************************/
285void
286kxld_symtab_clear(KXLDSymtab *symtab)
287{
288 check(symtab);
289
290 kxld_array_clear(&symtab->syms);
291 kxld_dict_clear(&symtab->cxx_index);
292 kxld_dict_clear(&symtab->name_index);
6d2010ae
A
293 symtab->strings = NULL;
294 symtab->strsize = 0;
295 symtab->cxx_index_initialized = 0;
296 symtab->name_index_initialized = 0;
b0d623f7
A
297}
298
299/*******************************************************************************
300*******************************************************************************/
301void
302kxld_symtab_deinit(KXLDSymtab *symtab)
303{
304 check(symtab);
305
306 kxld_array_deinit(&symtab->syms);
307 kxld_dict_deinit(&symtab->cxx_index);
308 kxld_dict_deinit(&symtab->name_index);
6d2010ae 309 bzero(symtab, sizeof(*symtab));
b0d623f7
A
310}
311
312/*******************************************************************************
313*******************************************************************************/
314u_int
315kxld_symtab_get_num_symbols(const KXLDSymtab *symtab)
316{
317 check(symtab);
318
319 return symtab->syms.nitems;
320}
321
322/*******************************************************************************
323*******************************************************************************/
324KXLDSym *
325kxld_symtab_get_symbol_by_index(const KXLDSymtab *symtab, u_int idx)
326{
327 check(symtab);
328
329 return kxld_array_get_item(&symtab->syms, idx);
330}
331
332/*******************************************************************************
333*******************************************************************************/
6d2010ae 334KXLDSym *
b0d623f7 335kxld_symtab_get_symbol_by_name(const KXLDSymtab *symtab, const char *name)
6d2010ae
A
336{
337 KXLDSym *sym = NULL;
338 u_int i = 0;
339
340 for (i = 0; i < symtab->syms.nitems; ++i) {
341 sym = kxld_array_get_item(&symtab->syms, i);
342
343 if (streq(sym->name, name)) {
344 return sym;
345 }
346 }
347
348 return NULL;
349}
350
351/*******************************************************************************
352*******************************************************************************/
353KXLDSym *
354kxld_symtab_get_locally_defined_symbol_by_name(const KXLDSymtab *symtab,
355 const char *name)
b0d623f7
A
356{
357 check(symtab);
358 check(name);
359
360 return kxld_dict_find(&symtab->name_index, name);
361}
362
363/*******************************************************************************
364*******************************************************************************/
365KXLDSym *
366kxld_symtab_get_cxx_symbol_by_value(const KXLDSymtab *symtab, kxld_addr_t value)
367{
368 check(symtab);
369
6d2010ae 370 return kxld_dict_find(&symtab->cxx_index, &value);
b0d623f7
A
371}
372
373/*******************************************************************************
374*******************************************************************************/
375kern_return_t
376kxld_symtab_get_sym_index(const KXLDSymtab *symtab, const KXLDSym *sym,
377 u_int *symindex)
378{
379 kern_return_t rval = KERN_FAILURE;
380
381 rval = kxld_array_get_index(&symtab->syms, sym, symindex);
382 require_noerr(rval, finish);
383
384 rval = KERN_SUCCESS;
385
386finish:
387 return rval;
388}
389
390/*******************************************************************************
391*******************************************************************************/
392u_long
393kxld_symtab_get_macho_header_size(void)
394{
395 return sizeof(struct symtab_command);
396}
397
398/*******************************************************************************
399*******************************************************************************/
400u_long
6d2010ae 401kxld_symtab_get_macho_data_size(const KXLDSymtab *symtab, boolean_t is_32_bit)
b0d623f7
A
402{
403 KXLDSymtabIterator iter;
404 KXLDSym *sym = NULL;
405 u_long size = 1; /* strtab start padding */
406 u_int nsyms = 0;
407
408 check(symtab);
409
6d2010ae
A
410 kxld_symtab_iterator_init(&iter, symtab,
411 kxld_sym_is_defined_locally, FALSE);
b0d623f7
A
412
413 while ((sym = kxld_symtab_iterator_get_next(&iter))) {
414 size += strlen(sym->name) + 1;
415 ++nsyms;
416 }
417
418 if (is_32_bit) {
419 size += nsyms * sizeof(struct nlist);
420 } else {
421 size += nsyms * sizeof(struct nlist_64);
422 }
423
424 return size;
425}
426
427/*******************************************************************************
428*******************************************************************************/
429kern_return_t
430kxld_symtab_export_macho(const KXLDSymtab *symtab, u_char *buf,
431 u_long *header_offset, u_long header_size,
432 u_long *data_offset, u_long data_size,
6d2010ae 433 boolean_t is_32_bit)
b0d623f7
A
434{
435 kern_return_t rval = KERN_FAILURE;
436 KXLDSymtabIterator iter;
437 KXLDSym *sym = NULL;
438 struct symtab_command *symtabhdr = NULL;
439 u_char *nl = NULL;
440 u_long nlistsize = 0;
441 char *strtab = NULL;
442 u_long stroff = 1; /* strtab start padding */
443
444 check(symtab);
445 check(buf);
446 check(header_offset);
447 check(data_offset);
448
449 require_action(sizeof(*symtabhdr) <= header_size - *header_offset,
450 finish, rval=KERN_FAILURE);
451 symtabhdr = (struct symtab_command *) (buf + *header_offset);
452 *header_offset += sizeof(*symtabhdr);
453
454 /* Initialize the symbol table header */
455
456 symtabhdr->cmd = LC_SYMTAB;
457 symtabhdr->cmdsize = (uint32_t) sizeof(*symtabhdr);
458 symtabhdr->symoff = (uint32_t) *data_offset;
459 symtabhdr->strsize = 1; /* strtab start padding */
460
461 /* Find the size of the symbol and string tables */
462
6d2010ae
A
463 kxld_symtab_iterator_init(&iter, symtab,
464 kxld_sym_is_defined_locally, FALSE);
b0d623f7
A
465
466 while ((sym = kxld_symtab_iterator_get_next(&iter))) {
467 symtabhdr->nsyms++;
468 symtabhdr->strsize += (uint32_t) (strlen(sym->name) + 1);
469 }
470
471 if (is_32_bit) {
472 nlistsize = sizeof(struct nlist);
473 } else {
474 nlistsize = sizeof(struct nlist_64);
475 }
476
477 symtabhdr->stroff = (uint32_t) (symtabhdr->symoff +
478 (symtabhdr->nsyms * nlistsize));
479 require_action(symtabhdr->stroff + symtabhdr->strsize <= data_size, finish,
480 rval=KERN_FAILURE);
481
482 /* Get pointers to the symbol and string tables */
483
484 nl = buf + symtabhdr->symoff;
485 strtab = (char *) (buf + symtabhdr->stroff);
486
487 /* Copy over the symbols */
488
489 kxld_symtab_iterator_reset(&iter);
490 while ((sym = kxld_symtab_iterator_get_next(&iter))) {
491
492 KXLD_3264_FUNC(is_32_bit, rval,
493 kxld_sym_export_macho_32, kxld_sym_export_macho_64,
6d2010ae 494 sym, nl, strtab, &stroff, symtabhdr->strsize);
b0d623f7
A
495 require_noerr(rval, finish);
496
497 nl += nlistsize;
498 stroff += rval;
499 }
500
501 /* Update the data offset */
502 *data_offset += (symtabhdr->nsyms * nlistsize) + stroff;
503
504 rval = KERN_SUCCESS;
505
506finish:
507 return rval;
508}
509
510/*******************************************************************************
511*******************************************************************************/
512u_int
513kxld_symtab_iterator_get_num_remaining(const KXLDSymtabIterator *iter)
514{
515 u_int idx = 0;
516 u_int count = 0;
517
518 check(iter);
519
b0d623f7
A
520 for (idx = iter->idx; idx < iter->symtab->syms.nitems; ++idx) {
521 count += iter->test(kxld_array_get_item(&iter->symtab->syms, idx));
522 }
523
524 return count;
525}
526
527/*******************************************************************************
528*******************************************************************************/
6d2010ae
A
529kern_return_t
530kxld_symtab_index_cxx_symbols_by_value(KXLDSymtab *symtab)
b0d623f7
A
531{
532 kern_return_t rval = KERN_FAILURE;
533 KXLDSymtabIterator iter;
534 KXLDSym *sym = NULL;
535 u_int nsyms = 0;
536
537 check(symtab);
538
6d2010ae
A
539 if (symtab->cxx_index_initialized) {
540 rval = KERN_SUCCESS;
541 goto finish;
542 }
543
b0d623f7
A
544 /* Count the number of C++ symbols */
545 kxld_symtab_iterator_init(&iter, symtab, sym_is_defined_cxx, FALSE);
546 nsyms = kxld_symtab_iterator_get_num_remaining(&iter);
547
548 /* Create the dictionary */
549 rval = kxld_dict_init(&symtab->cxx_index, kxld_dict_kxldaddr_hash,
550 kxld_dict_kxldaddr_cmp, nsyms);
551 require_noerr(rval, finish);
552
553 /* Insert the non-stab symbols */
554 while ((sym = kxld_symtab_iterator_get_next(&iter))) {
555 rval = kxld_dict_insert(&symtab->cxx_index, &sym->base_addr, sym);
556 require_noerr(rval, finish);
557 }
558
6d2010ae 559 symtab->cxx_index_initialized = TRUE;
b0d623f7 560 rval = KERN_SUCCESS;
b0d623f7 561finish:
b0d623f7
A
562 return rval;
563}
564
565/*******************************************************************************
566*******************************************************************************/
567static boolean_t
568sym_is_defined_cxx(const KXLDSym *sym)
569{
570 return (kxld_sym_is_defined_locally(sym) && kxld_sym_is_cxx(sym));
571}
572
573/*******************************************************************************
574*******************************************************************************/
6d2010ae
A
575kern_return_t
576kxld_symtab_index_symbols_by_name(KXLDSymtab *symtab)
b0d623f7
A
577{
578 kern_return_t rval = KERN_FAILURE;
579 KXLDSymtabIterator iter;
580 KXLDSym *sym = NULL;
581 u_int nsyms = 0;
582
583 check(symtab);
584
6d2010ae
A
585 if (symtab->name_index_initialized) {
586 rval = KERN_SUCCESS;
587 goto finish;
588 }
589
b0d623f7
A
590 /* Count the number of symbols we need to index by name */
591 kxld_symtab_iterator_init(&iter, symtab, sym_is_name_indexed, FALSE);
592 nsyms = kxld_symtab_iterator_get_num_remaining(&iter);
593
594 /* Create the dictionary */
595 rval = kxld_dict_init(&symtab->name_index, kxld_dict_string_hash,
596 kxld_dict_string_cmp, nsyms);
597 require_noerr(rval, finish);
598
599 /* Insert the non-stab symbols */
600 while ((sym = kxld_symtab_iterator_get_next(&iter))) {
601 rval = kxld_dict_insert(&symtab->name_index, sym->name, sym);
602 require_noerr(rval, finish);
603 }
604
6d2010ae 605 symtab->name_index_initialized = TRUE;
b0d623f7 606 rval = KERN_SUCCESS;
b0d623f7
A
607finish:
608
609 return rval;
610}
b0d623f7
A
611/*******************************************************************************
612*******************************************************************************/
613static boolean_t
614sym_is_name_indexed(const KXLDSym *sym)
615{
6d2010ae 616 return (kxld_sym_is_defined_locally(sym) && !kxld_sym_is_stab(sym));
b0d623f7
A
617}
618
619/*******************************************************************************
620*******************************************************************************/
621kern_return_t
622kxld_symtab_relocate(KXLDSymtab *symtab, const KXLDArray *sectarray)
623{
624 kern_return_t rval = KERN_FAILURE;
625 KXLDSymtabIterator iter;
626 KXLDSym *sym = NULL;
627 const KXLDSect *sect = NULL;
628
629 check(symtab);
630 check(sectarray);
631
632 kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_section, FALSE);
633
634 while ((sym = kxld_symtab_iterator_get_next(&iter))) {
635 sect = kxld_array_get_item(sectarray, sym->sectnum);
636 require_action(sect, finish, rval=KERN_FAILURE);
637 kxld_sym_relocate(sym, sect);
638 }
639
640 rval = KERN_SUCCESS;
641
642finish:
643
644 return rval;
645}
646
647/*******************************************************************************
648* This extends the symbol table and initializes the new symbol. We insert the
649* symbol into the name index, but we don't bother with the c++ value index
650* because it is based on the base_addr of the symbol, and the base_addr of
651* all synthesized symbols will be 0.
652*******************************************************************************/
653kern_return_t
654kxld_symtab_add_symbol(KXLDSymtab *symtab, char *name, kxld_addr_t link_addr,
655 KXLDSym **symout)
656{
657 kern_return_t rval = KERN_FAILURE;
658 KXLDSym *sym = NULL;
659 u_int symindex = symtab->syms.nitems;
660
661 rval = kxld_array_resize(&symtab->syms, symindex + 1);
662 require_noerr(rval, finish);
663
664 sym = kxld_array_get_item(&symtab->syms, symindex);
665 kxld_sym_init_absolute(sym, name, link_addr);
666
667 rval = kxld_dict_insert(&symtab->name_index, sym->name, sym);
668 require_noerr(rval, finish);
669
670 rval = KERN_SUCCESS;
671 *symout = sym;
672
673finish:
674 return rval;
675}
676
677/*******************************************************************************
678*******************************************************************************/
679KXLDSym *
680kxld_symtab_iterator_get_next(KXLDSymtabIterator *iter)
681{
682 KXLDSym *sym = NULL;
683 KXLDSym *tmp = NULL;
684 boolean_t cmp = FALSE;
685
686 check(iter);
687
688 for (; iter->idx < iter->symtab->syms.nitems; ++iter->idx) {
689 tmp = kxld_array_get_item(&iter->symtab->syms, iter->idx);
690 cmp = iter->test(tmp);
691 if (iter->negate) cmp = !cmp;
692
693 if (cmp) {
694 sym = tmp;
695 ++iter->idx;
696 break;
697 }
698 }
699
700 return sym;
701}
702
703
704/*******************************************************************************
705*******************************************************************************/
706void
707kxld_symtab_iterator_reset(KXLDSymtabIterator *iter)
708{
709 check(iter);
710 iter->idx = 0;
711}
712