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"
52 /*******************************************************************************
54 *******************************************************************************/
56 static kern_return_t
init_macho(KXLDSymtab
*symtab
, u_char
*macho
,
57 struct symtab_command
*src
, kxld_addr_t linkedit_offset
, boolean_t is_32_bit
)
58 __attribute__((nonnull
));
60 #if KXLD_USER_OR_ILP32
61 static kern_return_t
init_syms_32(KXLDSymtab
*symtab
, u_char
*macho
, u_long offset
,
65 static kern_return_t
init_syms_64(KXLDSymtab
*symtab
, u_char
*macho
, u_long offset
,
69 static kern_return_t
make_cxx_index(KXLDSymtab
*symtab
)
70 __attribute__((nonnull
));
71 static boolean_t
sym_is_defined_cxx(const KXLDSym
*sym
);
72 static kern_return_t
make_name_index(KXLDSymtab
*symtab
)
73 __attribute__((nonnull
));
74 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
, u_char
*macho
,
90 struct symtab_command
*src
, kxld_addr_t linkedit_offset
)
92 return init_macho(symtab
, macho
, src
, linkedit_offset
, TRUE
);
94 #endif /* KXLD_USER_ILP32 */
97 /*******************************************************************************
98 *******************************************************************************/
100 kxld_symtab_init_from_macho_64(KXLDSymtab
*symtab
, u_char
*macho
,
101 struct symtab_command
*src
, kxld_addr_t linkedit_offset
)
103 return init_macho(symtab
, macho
, src
, linkedit_offset
, FALSE
);
105 #endif /* KXLD_USER_OR_LP64 */
107 /*******************************************************************************
108 *******************************************************************************/
110 init_macho(KXLDSymtab
*symtab
, u_char
*macho
, struct symtab_command
*src
,
111 kxld_addr_t linkedit_offset
, boolean_t is_32_bit __unused
)
113 kern_return_t rval
= KERN_FAILURE
;
119 /* Initialize the symbol array */
121 rval
= kxld_array_init(&symtab
->syms
, sizeof(KXLDSym
), src
->nsyms
);
122 require_noerr(rval
, finish
);
124 /* Initialize the string table */
126 symtab
->strings
= (char *) (macho
+ src
->stroff
+ linkedit_offset
);
127 symtab
->strsize
= src
->strsize
;
129 /* Initialize the symbols */
131 KXLD_3264_FUNC(is_32_bit
, rval
,
132 init_syms_32
, init_syms_64
,
133 symtab
, macho
, (u_long
) (src
->symoff
+ linkedit_offset
), src
->nsyms
);
134 require_noerr(rval
, finish
);
136 /* Create the C++ index */
138 rval
= make_cxx_index(symtab
);
139 require_noerr(rval
, finish
);
141 /* Create the name index */
143 rval
= make_name_index(symtab
);
144 require_noerr(rval
, finish
);
146 /* Save the output */
154 #if KXLD_USER_OR_ILP32
155 /*******************************************************************************
156 *******************************************************************************/
158 init_syms_32(KXLDSymtab
*symtab
, u_char
*macho
, u_long offset
, u_int nsyms
)
160 kern_return_t rval
= KERN_FAILURE
;
163 struct nlist
*src_syms
= (struct nlist
*) (macho
+ offset
);
165 for (i
= 0; i
< nsyms
; ++i
) {
166 sym
= kxld_array_get_item(&symtab
->syms
, i
);
167 require_action(sym
, finish
, rval
=KERN_FAILURE
);
169 rval
= kxld_sym_init_from_macho32(sym
, symtab
->strings
, &src_syms
[i
]);
170 require_noerr(rval
, finish
);
178 #endif /* KXLD_USER_OR_ILP32 */
180 #if KXLD_USER_OR_LP64
181 /*******************************************************************************
182 *******************************************************************************/
184 init_syms_64(KXLDSymtab
*symtab
, u_char
*macho
, u_long offset
, u_int nsyms
)
186 kern_return_t rval
= KERN_FAILURE
;
189 struct nlist_64
*src_syms
= (struct nlist_64
*) (macho
+ offset
);
191 for (i
= 0; i
< nsyms
; ++i
) {
192 sym
= kxld_array_get_item(&symtab
->syms
, i
);
193 require_action(sym
, finish
, rval
=KERN_FAILURE
);
195 rval
= kxld_sym_init_from_macho64(sym
, symtab
->strings
, &src_syms
[i
]);
196 require_noerr(rval
, finish
);
204 #endif /* KXLD_USER_OR_LP64 */
206 /*******************************************************************************
207 *******************************************************************************/
209 kxld_symtab_iterator_init(KXLDSymtabIterator
*iter
, const KXLDSymtab
*symtab
,
210 KXLDSymPredicateTest test
, boolean_t negate
)
216 iter
->symtab
= symtab
;
219 iter
->negate
= negate
;
222 /*******************************************************************************
223 *******************************************************************************/
225 kxld_symtab_clear(KXLDSymtab
*symtab
)
229 kxld_array_clear(&symtab
->syms
);
230 kxld_dict_clear(&symtab
->cxx_index
);
231 kxld_dict_clear(&symtab
->name_index
);
234 /*******************************************************************************
235 *******************************************************************************/
237 kxld_symtab_deinit(KXLDSymtab
*symtab
)
241 kxld_array_deinit(&symtab
->syms
);
242 kxld_dict_deinit(&symtab
->cxx_index
);
243 kxld_dict_deinit(&symtab
->name_index
);
246 /*******************************************************************************
247 *******************************************************************************/
249 kxld_symtab_get_num_symbols(const KXLDSymtab
*symtab
)
253 return symtab
->syms
.nitems
;
256 /*******************************************************************************
257 *******************************************************************************/
259 kxld_symtab_get_symbol_by_index(const KXLDSymtab
*symtab
, u_int idx
)
263 return kxld_array_get_item(&symtab
->syms
, idx
);
266 /*******************************************************************************
267 *******************************************************************************/
269 kxld_symtab_get_symbol_by_name(const KXLDSymtab
*symtab
, const char *name
)
274 return kxld_dict_find(&symtab
->name_index
, name
);
277 /*******************************************************************************
278 *******************************************************************************/
280 kxld_symtab_get_cxx_symbol_by_value(const KXLDSymtab
*symtab
, kxld_addr_t value
)
285 * value may hold a THUMB address (with bit 0 set to 1) but the index will
286 * have the real address (bit 0 set to 0). So if bit 0 is set here,
287 * we clear it (should impact no architectures but ARM).
289 kxld_addr_t v
= value
& ~1;
291 return kxld_dict_find(&symtab
->cxx_index
, &v
);
294 /*******************************************************************************
295 *******************************************************************************/
297 kxld_symtab_get_sym_index(const KXLDSymtab
*symtab
, const KXLDSym
*sym
,
300 kern_return_t rval
= KERN_FAILURE
;
302 rval
= kxld_array_get_index(&symtab
->syms
, sym
, symindex
);
303 require_noerr(rval
, finish
);
311 /*******************************************************************************
312 *******************************************************************************/
314 kxld_symtab_get_macho_header_size(void)
316 return sizeof(struct symtab_command
);
319 /*******************************************************************************
320 *******************************************************************************/
322 kxld_symtab_get_macho_data_size(const KXLDSymtab
*symtab
,
323 boolean_t is_link_state
, boolean_t is_32_bit
)
325 KXLDSymtabIterator iter
;
327 u_long size
= 1; /* strtab start padding */
333 kxld_symtab_iterator_init(&iter
, symtab
, kxld_sym_is_exported
, FALSE
);
335 kxld_symtab_iterator_init(&iter
, symtab
,
336 kxld_sym_is_defined_locally
, FALSE
);
339 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
340 size
+= strlen(sym
->name
) + 1;
345 size
+= nsyms
* sizeof(struct nlist
);
347 size
+= nsyms
* sizeof(struct nlist_64
);
353 /*******************************************************************************
354 *******************************************************************************/
356 kxld_symtab_export_macho(const KXLDSymtab
*symtab
, u_char
*buf
,
357 u_long
*header_offset
, u_long header_size
,
358 u_long
*data_offset
, u_long data_size
,
359 boolean_t is_link_state
, boolean_t is_32_bit
)
361 kern_return_t rval
= KERN_FAILURE
;
362 KXLDSymtabIterator iter
;
364 struct symtab_command
*symtabhdr
= NULL
;
366 u_long nlistsize
= 0;
368 u_long stroff
= 1; /* strtab start padding */
372 check(header_offset
);
375 require_action(sizeof(*symtabhdr
) <= header_size
- *header_offset
,
376 finish
, rval
=KERN_FAILURE
);
377 symtabhdr
= (struct symtab_command
*) (buf
+ *header_offset
);
378 *header_offset
+= sizeof(*symtabhdr
);
380 /* Initialize the symbol table header */
382 symtabhdr
->cmd
= LC_SYMTAB
;
383 symtabhdr
->cmdsize
= (uint32_t) sizeof(*symtabhdr
);
384 symtabhdr
->symoff
= (uint32_t) *data_offset
;
385 symtabhdr
->strsize
= 1; /* strtab start padding */
387 /* Find the size of the symbol and string tables */
390 kxld_symtab_iterator_init(&iter
, symtab
, kxld_sym_is_exported
, FALSE
);
392 kxld_symtab_iterator_init(&iter
, symtab
,
393 kxld_sym_is_defined_locally
, FALSE
);
396 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
398 symtabhdr
->strsize
+= (uint32_t) (strlen(sym
->name
) + 1);
402 nlistsize
= sizeof(struct nlist
);
404 nlistsize
= sizeof(struct nlist_64
);
407 symtabhdr
->stroff
= (uint32_t) (symtabhdr
->symoff
+
408 (symtabhdr
->nsyms
* nlistsize
));
409 require_action(symtabhdr
->stroff
+ symtabhdr
->strsize
<= data_size
, finish
,
412 /* Get pointers to the symbol and string tables */
414 nl
= buf
+ symtabhdr
->symoff
;
415 strtab
= (char *) (buf
+ symtabhdr
->stroff
);
417 /* Copy over the symbols */
419 kxld_symtab_iterator_reset(&iter
);
420 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
422 KXLD_3264_FUNC(is_32_bit
, rval
,
423 kxld_sym_export_macho_32
, kxld_sym_export_macho_64
,
424 sym
, nl
, strtab
, &stroff
, symtabhdr
->strsize
, is_link_state
);
425 require_noerr(rval
, finish
);
431 /* Update the data offset */
432 *data_offset
+= (symtabhdr
->nsyms
* nlistsize
) + stroff
;
440 /*******************************************************************************
441 *******************************************************************************/
443 kxld_symtab_iterator_get_num_remaining(const KXLDSymtabIterator
*iter
)
452 for (idx
= iter
->idx
; idx
< iter
->symtab
->syms
.nitems
; ++idx
) {
453 count
+= iter
->test(kxld_array_get_item(&iter
->symtab
->syms
, idx
));
459 /*******************************************************************************
460 *******************************************************************************/
462 make_cxx_index(KXLDSymtab
*symtab
)
464 kern_return_t rval
= KERN_FAILURE
;
465 KXLDSymtabIterator iter
;
471 /* Count the number of C++ symbols */
472 kxld_symtab_iterator_init(&iter
, symtab
, sym_is_defined_cxx
, FALSE
);
473 nsyms
= kxld_symtab_iterator_get_num_remaining(&iter
);
475 /* Create the dictionary */
476 rval
= kxld_dict_init(&symtab
->cxx_index
, kxld_dict_kxldaddr_hash
,
477 kxld_dict_kxldaddr_cmp
, nsyms
);
478 require_noerr(rval
, finish
);
480 /* Insert the non-stab symbols */
481 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
482 rval
= kxld_dict_insert(&symtab
->cxx_index
, &sym
->base_addr
, sym
);
483 require_noerr(rval
, finish
);
493 /*******************************************************************************
494 *******************************************************************************/
496 sym_is_defined_cxx(const KXLDSym
*sym
)
498 return (kxld_sym_is_defined_locally(sym
) && kxld_sym_is_cxx(sym
));
501 /*******************************************************************************
502 *******************************************************************************/
504 make_name_index(KXLDSymtab
*symtab
)
506 kern_return_t rval
= KERN_FAILURE
;
507 KXLDSymtabIterator iter
;
513 /* Count the number of symbols we need to index by name */
514 kxld_symtab_iterator_init(&iter
, symtab
, sym_is_name_indexed
, FALSE
);
515 nsyms
= kxld_symtab_iterator_get_num_remaining(&iter
);
517 /* Create the dictionary */
518 rval
= kxld_dict_init(&symtab
->name_index
, kxld_dict_string_hash
,
519 kxld_dict_string_cmp
, nsyms
);
520 require_noerr(rval
, finish
);
522 /* Insert the non-stab symbols */
523 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
524 rval
= kxld_dict_insert(&symtab
->name_index
, sym
->name
, sym
);
525 require_noerr(rval
, finish
);
535 /*******************************************************************************
536 *******************************************************************************/
538 sym_is_name_indexed(const KXLDSym
*sym
)
540 return (kxld_sym_is_vtable(sym
) ||
541 streq_safe(sym
->name
, KXLD_KMOD_INFO_SYMBOL
,
542 const_strlen(KXLD_KMOD_INFO_SYMBOL
)) ||
543 streq_safe(sym
->name
, KXLD_WEAK_TEST_SYMBOL
,
544 const_strlen(KXLD_WEAK_TEST_SYMBOL
)));
547 /*******************************************************************************
548 *******************************************************************************/
550 kxld_symtab_relocate(KXLDSymtab
*symtab
, const KXLDArray
*sectarray
)
552 kern_return_t rval
= KERN_FAILURE
;
553 KXLDSymtabIterator iter
;
555 const KXLDSect
*sect
= NULL
;
560 kxld_symtab_iterator_init(&iter
, symtab
, kxld_sym_is_section
, FALSE
);
562 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
563 sect
= kxld_array_get_item(sectarray
, sym
->sectnum
);
564 require_action(sect
, finish
, rval
=KERN_FAILURE
);
565 kxld_sym_relocate(sym
, sect
);
575 /*******************************************************************************
576 * This extends the symbol table and initializes the new symbol. We insert the
577 * symbol into the name index, but we don't bother with the c++ value index
578 * because it is based on the base_addr of the symbol, and the base_addr of
579 * all synthesized symbols will be 0.
580 *******************************************************************************/
582 kxld_symtab_add_symbol(KXLDSymtab
*symtab
, char *name
, kxld_addr_t link_addr
,
585 kern_return_t rval
= KERN_FAILURE
;
587 u_int symindex
= symtab
->syms
.nitems
;
589 rval
= kxld_array_resize(&symtab
->syms
, symindex
+ 1);
590 require_noerr(rval
, finish
);
592 sym
= kxld_array_get_item(&symtab
->syms
, symindex
);
593 kxld_sym_init_absolute(sym
, name
, link_addr
);
595 rval
= kxld_dict_insert(&symtab
->name_index
, sym
->name
, sym
);
596 require_noerr(rval
, finish
);
605 /*******************************************************************************
606 *******************************************************************************/
608 kxld_symtab_iterator_get_next(KXLDSymtabIterator
*iter
)
612 boolean_t cmp
= FALSE
;
616 for (; iter
->idx
< iter
->symtab
->syms
.nitems
; ++iter
->idx
) {
617 tmp
= kxld_array_get_item(&iter
->symtab
->syms
, iter
->idx
);
618 cmp
= iter
->test(tmp
);
619 if (iter
->negate
) cmp
= !cmp
;
632 /*******************************************************************************
633 *******************************************************************************/
635 kxld_symtab_iterator_reset(KXLDSymtabIterator
*iter
)