2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <mach-o/loader.h>
30 #include <mach-o/nlist.h>
31 #include <sys/queue.h>
32 #include <sys/types.h>
34 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
35 #include <AssertMacros.h>
37 #include "kxld_array.h"
38 #include "kxld_dict.h"
39 #include "kxld_sect.h"
41 #include "kxld_symtab.h"
42 #include "kxld_util.h"
50 boolean_t cxx_index_initialized
;
51 boolean_t name_index_initialized
;
54 /*******************************************************************************
56 *******************************************************************************/
58 static kern_return_t
init_macho(KXLDSymtab
*symtab
, struct symtab_command
*src
,
59 u_char
*macho
, KXLDSeg
* kernel_linkedit_seg
,
61 __attribute__((nonnull(1,2)));
63 #if KXLD_USER_OR_ILP32
64 static kern_return_t
init_syms_32(KXLDSymtab
*symtab
, u_char
*macho
, u_long offset
,
68 static kern_return_t
init_syms_64(KXLDSymtab
*symtab
, u_char
*macho
, u_long offset
,
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
);
77 /*******************************************************************************
78 *******************************************************************************/
82 return sizeof(KXLDSymtab
);
85 #if KXLD_USER_OR_ILP32
86 /*******************************************************************************
87 *******************************************************************************/
89 kxld_symtab_init_from_macho_32(KXLDSymtab
*symtab
, struct symtab_command
*src
,
90 u_char
*macho
, KXLDSeg
* kernel_linkedit_seg
)
92 return init_macho(symtab
, src
, macho
, kernel_linkedit_seg
,
93 /* is_32_bit */ TRUE
);
95 #endif /* KXLD_USER_ILP32 */
98 /*******************************************************************************
99 *******************************************************************************/
101 kxld_symtab_init_from_macho_64(KXLDSymtab
*symtab
, struct symtab_command
*src
,
102 u_char
*macho
, KXLDSeg
* kernel_linkedit_seg
)
104 return init_macho(symtab
, src
, macho
, kernel_linkedit_seg
,
105 /* is_32_bit */ FALSE
);
107 #endif /* KXLD_USER_OR_LP64 */
109 /*******************************************************************************
110 *******************************************************************************/
112 init_macho(KXLDSymtab
*symtab
, struct symtab_command
*src
,
113 u_char
*macho
, KXLDSeg
* kernel_linkedit_seg
,
114 boolean_t is_32_bit __unused
)
116 kern_return_t rval
= KERN_FAILURE
;
118 u_char
* macho_or_linkedit
= macho
;
124 /* Initialize the symbol array */
126 rval
= kxld_array_init(&symtab
->syms
, sizeof(KXLDSym
), src
->nsyms
);
127 require_noerr(rval
, finish
);
129 /* Initialize the string table */
131 if (kernel_linkedit_seg
) {
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.
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.
141 * The strings table is an actual pointer, so we calculate that from
142 * the linkedit's vmaddr.
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.
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
;
154 symoff
= (u_long
)src
->symoff
;
155 symtab
->strings
= (char *) (macho
+ src
->stroff
);
158 symtab
->strsize
= src
->strsize
;
160 /* Initialize the symbols */
162 KXLD_3264_FUNC(is_32_bit
, rval
,
163 init_syms_32
, init_syms_64
,
164 symtab
, macho_or_linkedit
, symoff
, src
->nsyms
);
165 require_noerr(rval
, finish
);
167 /* Some symbols must be forced private for compatibility */
168 (void) restrict_private_symbols(symtab
);
170 /* Save the output */
178 #if KXLD_USER_OR_ILP32
179 /*******************************************************************************
180 * In the running kernel, 'macho' is actually the start of the linkedit segment.
181 *******************************************************************************/
183 init_syms_32(KXLDSymtab
*symtab
, u_char
*macho
, u_long offset
, u_int nsyms
)
185 kern_return_t rval
= KERN_FAILURE
;
188 struct nlist
*src_syms
= (struct nlist
*) ((void *) (macho
+ offset
));
190 for (i
= 0; i
< nsyms
; ++i
) {
191 sym
= kxld_array_get_item(&symtab
->syms
, i
);
192 require_action(sym
, finish
, rval
=KERN_FAILURE
);
194 rval
= kxld_sym_init_from_macho32(sym
, symtab
->strings
, &src_syms
[i
]);
195 require_noerr(rval
, finish
);
203 #endif /* KXLD_USER_OR_ILP32 */
205 #if KXLD_USER_OR_LP64
206 /*******************************************************************************
207 * In the running kernel, 'macho' is actually the start of the linkedit segment.
208 *******************************************************************************/
210 init_syms_64(KXLDSymtab
*symtab
, u_char
*macho
, u_long offset
, u_int nsyms
)
212 kern_return_t rval
= KERN_FAILURE
;
215 struct nlist_64
*src_syms
= (struct nlist_64
*) ((void *) (macho
+ offset
));
217 for (i
= 0; i
< nsyms
; ++i
) {
218 sym
= kxld_array_get_item(&symtab
->syms
, i
);
219 require_action(sym
, finish
, rval
=KERN_FAILURE
);
221 rval
= kxld_sym_init_from_macho64(sym
, symtab
->strings
, &src_syms
[i
]);
222 require_noerr(rval
, finish
);
230 #endif /* KXLD_USER_OR_LP64 */
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 *******************************************************************************/
239 restrict_private_symbols(KXLDSymtab
*symtab
)
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
248 KXLDSymtabIterator iter
;
250 const char *name
= NULL
;
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
)) {
261 kxld_sym_mark_private(sym
);
267 /*******************************************************************************
268 *******************************************************************************/
270 kxld_symtab_iterator_init(KXLDSymtabIterator
*iter
, const KXLDSymtab
*symtab
,
271 KXLDSymPredicateTest test
, boolean_t negate
)
277 iter
->symtab
= symtab
;
280 iter
->negate
= negate
;
283 /*******************************************************************************
284 *******************************************************************************/
286 kxld_symtab_clear(KXLDSymtab
*symtab
)
290 kxld_array_clear(&symtab
->syms
);
291 kxld_dict_clear(&symtab
->cxx_index
);
292 kxld_dict_clear(&symtab
->name_index
);
293 symtab
->strings
= NULL
;
295 symtab
->cxx_index_initialized
= 0;
296 symtab
->name_index_initialized
= 0;
299 /*******************************************************************************
300 *******************************************************************************/
302 kxld_symtab_deinit(KXLDSymtab
*symtab
)
306 kxld_array_deinit(&symtab
->syms
);
307 kxld_dict_deinit(&symtab
->cxx_index
);
308 kxld_dict_deinit(&symtab
->name_index
);
309 bzero(symtab
, sizeof(*symtab
));
312 /*******************************************************************************
313 *******************************************************************************/
315 kxld_symtab_get_num_symbols(const KXLDSymtab
*symtab
)
319 return symtab
->syms
.nitems
;
322 /*******************************************************************************
323 *******************************************************************************/
325 kxld_symtab_get_symbol_by_index(const KXLDSymtab
*symtab
, u_int idx
)
329 return kxld_array_get_item(&symtab
->syms
, idx
);
332 /*******************************************************************************
333 *******************************************************************************/
335 kxld_symtab_get_symbol_by_name(const KXLDSymtab
*symtab
, const char *name
)
340 for (i
= 0; i
< symtab
->syms
.nitems
; ++i
) {
341 sym
= kxld_array_get_item(&symtab
->syms
, i
);
343 if (streq(sym
->name
, name
)) {
351 /*******************************************************************************
352 *******************************************************************************/
354 kxld_symtab_get_locally_defined_symbol_by_name(const KXLDSymtab
*symtab
,
360 return kxld_dict_find(&symtab
->name_index
, name
);
363 /*******************************************************************************
364 *******************************************************************************/
366 kxld_symtab_get_cxx_symbol_by_value(const KXLDSymtab
*symtab
, kxld_addr_t value
)
370 return kxld_dict_find(&symtab
->cxx_index
, &value
);
373 /*******************************************************************************
374 *******************************************************************************/
376 kxld_symtab_get_sym_index(const KXLDSymtab
*symtab
, const KXLDSym
*sym
,
379 kern_return_t rval
= KERN_FAILURE
;
381 rval
= kxld_array_get_index(&symtab
->syms
, sym
, symindex
);
382 require_noerr(rval
, finish
);
390 /*******************************************************************************
391 *******************************************************************************/
393 kxld_symtab_get_macho_header_size(void)
395 return sizeof(struct symtab_command
);
398 /*******************************************************************************
399 *******************************************************************************/
401 kxld_symtab_get_macho_data_size(const KXLDSymtab
*symtab
, boolean_t is_32_bit
)
403 KXLDSymtabIterator iter
;
405 u_long size
= 1; /* strtab start padding */
410 kxld_symtab_iterator_init(&iter
, symtab
,
411 kxld_sym_is_defined_locally
, FALSE
);
413 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
414 size
+= strlen(sym
->name
) + 1;
419 size
+= nsyms
* sizeof(struct nlist
);
421 size
+= nsyms
* sizeof(struct nlist_64
);
424 size
= (size
+ 7) & ~7;
429 /*******************************************************************************
430 *******************************************************************************/
432 kxld_symtab_export_macho(const KXLDSymtab
*symtab
, u_char
*buf
,
433 u_long
*header_offset
, u_long header_size
,
434 u_long
*data_offset
, u_long data_size
,
437 kern_return_t rval
= KERN_FAILURE
;
438 KXLDSymtabIterator iter
;
440 struct symtab_command
*symtabhdr
= NULL
;
442 u_long nlistsize
= 0;
444 u_long stroff
= 1; /* strtab start padding */
448 check(header_offset
);
451 require_action(sizeof(*symtabhdr
) <= header_size
- *header_offset
,
452 finish
, rval
=KERN_FAILURE
);
453 symtabhdr
= (struct symtab_command
*) ((void *) (buf
+ *header_offset
));
454 *header_offset
+= sizeof(*symtabhdr
);
456 /* Initialize the symbol table header */
458 symtabhdr
->cmd
= LC_SYMTAB
;
459 symtabhdr
->cmdsize
= (uint32_t) sizeof(*symtabhdr
);
460 symtabhdr
->symoff
= (uint32_t) *data_offset
;
461 symtabhdr
->strsize
= 1; /* strtab start padding */
463 /* Find the size of the symbol and string tables */
465 kxld_symtab_iterator_init(&iter
, symtab
,
466 kxld_sym_is_defined_locally
, FALSE
);
468 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
470 symtabhdr
->strsize
+= (uint32_t) (strlen(sym
->name
) + 1);
474 nlistsize
= sizeof(struct nlist
);
476 nlistsize
= sizeof(struct nlist_64
);
479 symtabhdr
->stroff
= (uint32_t) (symtabhdr
->symoff
+
480 (symtabhdr
->nsyms
* nlistsize
));
481 require_action(symtabhdr
->stroff
+ symtabhdr
->strsize
<= data_size
, finish
,
484 /* Get pointers to the symbol and string tables */
486 nl
= buf
+ symtabhdr
->symoff
;
487 strtab
= (char *) (buf
+ symtabhdr
->stroff
);
489 /* Copy over the symbols */
491 kxld_symtab_iterator_reset(&iter
);
492 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
494 KXLD_3264_FUNC(is_32_bit
, rval
,
495 kxld_sym_export_macho_32
, kxld_sym_export_macho_64
,
496 sym
, nl
, strtab
, &stroff
, symtabhdr
->strsize
);
497 require_noerr(rval
, finish
);
503 /* Update the data offset */
504 *data_offset
+= (symtabhdr
->nsyms
* nlistsize
) + stroff
;
506 *data_offset
= (*data_offset
+ 7) & ~7;
514 /*******************************************************************************
515 *******************************************************************************/
517 kxld_symtab_iterator_get_num_remaining(const KXLDSymtabIterator
*iter
)
524 for (idx
= iter
->idx
; idx
< iter
->symtab
->syms
.nitems
; ++idx
) {
525 count
+= iter
->test(kxld_array_get_item(&iter
->symtab
->syms
, idx
));
531 /*******************************************************************************
532 *******************************************************************************/
534 kxld_symtab_index_cxx_symbols_by_value(KXLDSymtab
*symtab
)
536 kern_return_t rval
= KERN_FAILURE
;
537 KXLDSymtabIterator iter
;
543 if (symtab
->cxx_index_initialized
) {
548 /* Count the number of C++ symbols */
549 kxld_symtab_iterator_init(&iter
, symtab
, sym_is_defined_cxx
, FALSE
);
550 nsyms
= kxld_symtab_iterator_get_num_remaining(&iter
);
552 /* Create the dictionary */
553 rval
= kxld_dict_init(&symtab
->cxx_index
, kxld_dict_kxldaddr_hash
,
554 kxld_dict_kxldaddr_cmp
, nsyms
);
555 require_noerr(rval
, finish
);
557 /* Insert the non-stab symbols */
558 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
559 rval
= kxld_dict_insert(&symtab
->cxx_index
, &sym
->base_addr
, sym
);
560 require_noerr(rval
, finish
);
563 symtab
->cxx_index_initialized
= TRUE
;
569 /*******************************************************************************
570 *******************************************************************************/
572 sym_is_defined_cxx(const KXLDSym
*sym
)
574 return (kxld_sym_is_defined_locally(sym
) && kxld_sym_is_cxx(sym
));
577 /*******************************************************************************
578 *******************************************************************************/
580 kxld_symtab_index_symbols_by_name(KXLDSymtab
*symtab
)
582 kern_return_t rval
= KERN_FAILURE
;
583 KXLDSymtabIterator iter
;
589 if (symtab
->name_index_initialized
) {
594 /* Count the number of symbols we need to index by name */
595 kxld_symtab_iterator_init(&iter
, symtab
, sym_is_name_indexed
, FALSE
);
596 nsyms
= kxld_symtab_iterator_get_num_remaining(&iter
);
598 /* Create the dictionary */
599 rval
= kxld_dict_init(&symtab
->name_index
, kxld_dict_string_hash
,
600 kxld_dict_string_cmp
, nsyms
);
601 require_noerr(rval
, finish
);
603 /* Insert the non-stab symbols */
604 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
605 rval
= kxld_dict_insert(&symtab
->name_index
, sym
->name
, sym
);
606 require_noerr(rval
, finish
);
609 symtab
->name_index_initialized
= TRUE
;
615 /*******************************************************************************
616 *******************************************************************************/
618 sym_is_name_indexed(const KXLDSym
*sym
)
620 return (kxld_sym_is_defined_locally(sym
) && !kxld_sym_is_stab(sym
));
623 /*******************************************************************************
624 *******************************************************************************/
626 kxld_symtab_relocate(KXLDSymtab
*symtab
, const KXLDArray
*sectarray
)
628 kern_return_t rval
= KERN_FAILURE
;
629 KXLDSymtabIterator iter
;
631 const KXLDSect
*sect
= NULL
;
636 kxld_symtab_iterator_init(&iter
, symtab
, kxld_sym_is_section
, FALSE
);
638 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
639 sect
= kxld_array_get_item(sectarray
, sym
->sectnum
);
640 require_action(sect
, finish
, rval
=KERN_FAILURE
);
641 kxld_sym_relocate(sym
, sect
);
651 /*******************************************************************************
652 * This extends the symbol table and initializes the new symbol. We insert the
653 * symbol into the name index, but we don't bother with the c++ value index
654 * because it is based on the base_addr of the symbol, and the base_addr of
655 * all synthesized symbols will be 0.
656 *******************************************************************************/
658 kxld_symtab_add_symbol(KXLDSymtab
*symtab
, char *name
, kxld_addr_t link_addr
,
661 kern_return_t rval
= KERN_FAILURE
;
663 u_int symindex
= symtab
->syms
.nitems
;
665 rval
= kxld_array_resize(&symtab
->syms
, symindex
+ 1);
666 require_noerr(rval
, finish
);
668 sym
= kxld_array_get_item(&symtab
->syms
, symindex
);
669 kxld_sym_init_absolute(sym
, name
, link_addr
);
671 rval
= kxld_dict_insert(&symtab
->name_index
, sym
->name
, sym
);
672 require_noerr(rval
, finish
);
681 /*******************************************************************************
682 *******************************************************************************/
684 kxld_symtab_iterator_get_next(KXLDSymtabIterator
*iter
)
688 boolean_t cmp
= FALSE
;
692 for (; iter
->idx
< iter
->symtab
->syms
.nitems
; ++iter
->idx
) {
693 tmp
= kxld_array_get_item(&iter
->symtab
->syms
, iter
->idx
);
694 cmp
= iter
->test(tmp
);
695 if (iter
->negate
) cmp
= !cmp
;
708 /*******************************************************************************
709 *******************************************************************************/
711 kxld_symtab_iterator_reset(KXLDSymtabIterator
*iter
)