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@
31 #include <libkern/OSByteOrder.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_kext.h"
40 #include "kxld_state.h"
42 #include "kxld_symtab.h"
43 #include "kxld_util.h"
44 #include "kxld_vtable.h"
46 #define LINK_STATE_MAGIC 0xF00DD00D
47 #define CIGAM_ETATS_KNIL 0x0DD00DF0
49 #define LINK_STATE_MAGIC_64 0xCAFEF00D
50 #define CIGAM_ETATS_KNIL_64 0x0DF0FECA
52 #define LINK_STATE_VERSION 1
54 static kern_return_t
init_string_index(KXLDDict
*strings
, KXLDArray
*tmps
,
55 KXLDSymtabIterator
*iter
, const KXLDArray
*vtables
, u_int nsymentries
,
57 static kern_return_t
add_string_to_index(KXLDDict
*strings
, const char *str
,
58 KXLDArray
*tmps
, u_int
*tmpi
, u_long
*stroff
);
59 static kern_return_t
create_link_state(u_char
**_file
, u_long
*_filesize
,
60 const KXLDKext
*kext
, KXLDSymtabIterator
*iter
, const KXLDArray
*vtables
,
61 KXLDDict
*strings
, u_int nsyms
, u_int nsymentries
, u_long strsize
);
62 static boolean_t
state_is_32_bit(KXLDLinkStateHdr
*state
);
64 #if KXLD_USER_OR_ILP32
65 static kern_return_t
get_symbols_32(KXLDState
*state
, KXLDDict
*defined_symbols
,
66 KXLDDict
*obsolete_symbols
);
67 static kern_return_t
copy_symbols_32(u_char
*file
, u_long
*data_offset
,
68 KXLDSymtabIterator
*iter
, const KXLDDict
*strings
);
69 static kern_return_t
copy_vtables_32(u_char
*file
, u_long
*header_offset
,
70 u_long
*data_offset
, const KXLDArray
*vtables
, const KXLDDict
*strings
);
71 #endif /* KXLD_USER_OR_ILP32*/
73 static kern_return_t
get_symbols_64(KXLDState
*state
, KXLDDict
*defined_symbols
,
74 KXLDDict
*obsolete_symbols
);
75 static kern_return_t
copy_symbols_64(u_char
*file
, u_long
*data_offset
,
76 KXLDSymtabIterator
*iter
, const KXLDDict
*strings
);
77 static kern_return_t
copy_vtables_64(u_char
*file
, u_long
*header_offset
,
78 u_long
*data_offset
, const KXLDArray
*vtables
, const KXLDDict
*strings
);
79 #endif /* KXLD_USER_OR_ILP64 */
82 static boolean_t
swap_link_state(u_char
*state
);
83 static void swap_link_state_32(u_char
*state
);
84 static void swap_link_state_64(u_char
*state
);
85 static boolean_t
unswap_link_state(u_char
*state
);
86 static void unswap_link_state_32(u_char
*state
);
87 static void unswap_link_state_64(u_char
*state
);
88 static void swap_state_hdr(KXLDLinkStateHdr
*state_hdr
);
89 static void swap_vtable_hdr(KXLDVTableHdr
*vtable_hdr
);
90 static void swap_sym_entry_32(KXLDSymEntry32
*entry
);
91 static void swap_sym_entry_64(KXLDSymEntry64
*entry
);
94 /*******************************************************************************
95 *******************************************************************************/
97 kxld_state_init_from_file(KXLDState
*state
, u_char
*file
,
98 KXLDArray
*section_order __unused
)
100 kern_return_t rval
= KERN_FAILURE
;
101 KXLDLinkStateHdr
*hdr
= (KXLDLinkStateHdr
*) file
;
102 #if KXLD_USER_OR_OBJECT
103 KXLDSectionName
*dstname
= NULL
;
104 KXLDSectionName
*srcname
= NULL
;
106 KXLDVTableHdr
*vhdr
= NULL
;
107 KXLDVTable
*vtable
= NULL
;
114 /* Swap the link state file to host byte order for as long this kxld_state
115 * object owns the file.
117 state
->swap
= swap_link_state(file
);
119 require_action(hdr
->magic
== LINK_STATE_MAGIC
||
120 hdr
->magic
== LINK_STATE_MAGIC_64
,
121 finish
, rval
=KERN_FAILURE
);
125 #if KXLD_USER_OR_OBJECT
126 if (section_order
&& !section_order
->nitems
&& hdr
->nsects
) {
127 rval
= kxld_array_init(section_order
, sizeof(*dstname
), hdr
->nsects
);
128 require_noerr(rval
, finish
);
130 srcname
= (KXLDSectionName
*) (file
+ hdr
->sectoff
);
131 for (i
= 0; i
< hdr
->nsects
; ++i
, ++srcname
) {
132 dstname
= kxld_array_get_item(section_order
, i
);
133 memcpy(dstname
, srcname
, sizeof(*srcname
));
138 rval
= kxld_array_init(&state
->vtables
, sizeof(*vtable
), hdr
->nvtables
);
139 require_noerr(rval
, finish
);
141 vhdr
= (KXLDVTableHdr
*) (file
+ hdr
->voff
);
142 for (i
= 0; i
< hdr
->nvtables
; ++i
, ++vhdr
) {
143 vtable
= kxld_array_get_item(&state
->vtables
, i
);
144 KXLD_3264_FUNC(kxld_is_32_bit(hdr
->cputype
), rval
,
145 kxld_vtable_init_from_link_state_32
,
146 kxld_vtable_init_from_link_state_64
,
148 require_noerr(rval
, finish
);
157 /*******************************************************************************
158 *******************************************************************************/
160 kxld_state_clear(KXLDState
*state
)
162 KXLDVTable
*vtable
= NULL
;
168 /* We use kxld_state objects to wrap the link state files. Whenever the
169 * file is wrapped by a kxld_state object, the file is kept in host byte
170 * order. Once we are done, we must return it to target byte order.
172 if (state
->swap
) (void)unswap_link_state(state
->file
);
177 for (i
= 0; i
< state
->vtables
.nitems
; ++i
) {
178 vtable
= kxld_array_get_item(&state
->vtables
, i
);
179 kxld_vtable_clear(vtable
);
181 kxld_array_reset(&state
->vtables
);
184 /*******************************************************************************
185 *******************************************************************************/
187 kxld_state_deinit(KXLDState
*state
)
189 KXLDVTable
*vtable
= NULL
;
195 if (state
->file
&& state
->swap
) (void)unswap_link_state(state
->file
);
198 for (i
= 0; i
< state
->vtables
.maxitems
; ++i
) {
199 vtable
= kxld_array_get_slot(&state
->vtables
, i
);
200 kxld_vtable_deinit(vtable
);
202 kxld_array_deinit(&state
->vtables
);
203 bzero(state
, sizeof(*state
));
206 /*******************************************************************************
207 *******************************************************************************/
209 kxld_state_get_num_symbols(KXLDState
*state
)
211 KXLDLinkStateHdr
*hdr
= (KXLDLinkStateHdr
*) state
->file
;
216 /*******************************************************************************
217 *******************************************************************************/
219 kxld_state_get_symbols(KXLDState
*state
, KXLDDict
*defined_symbols
,
220 KXLDDict
*obsolete_symbols
)
222 KXLDLinkStateHdr
* hdr
= (KXLDLinkStateHdr
*) state
->file
;
223 kern_return_t rval
= KERN_FAILURE
;
226 check(defined_symbols
);
227 check(obsolete_symbols
);
229 require_action(hdr
->magic
== LINK_STATE_MAGIC
||
230 hdr
->magic
== LINK_STATE_MAGIC_64
,
231 finish
, rval
=KERN_FAILURE
);
233 KXLD_3264_FUNC(state_is_32_bit(hdr
), rval
,
234 get_symbols_32
, get_symbols_64
,
235 state
, defined_symbols
, obsolete_symbols
);
236 require_noerr(rval
, finish
);
244 #if KXLD_USER_OR_ILP32
245 /*******************************************************************************
246 *******************************************************************************/
248 get_symbols_32(KXLDState
*state
, KXLDDict
*defined_symbols
,
249 KXLDDict
*obsolete_symbols
)
251 kern_return_t rval
= KERN_FAILURE
;
252 KXLDLinkStateHdr
*hdr
= (KXLDLinkStateHdr
*) state
->file
;
253 KXLDSymEntry32
*entry
= NULL
;
254 const char *name
= NULL
;
257 entry
= (KXLDSymEntry32
*) (state
->file
+ hdr
->symoff
);
258 for (i
= 0; i
< hdr
->nsyms
; ++i
, ++entry
) {
259 name
= (const char *) (state
->file
+ entry
->nameoff
);
260 rval
= kxld_dict_insert(defined_symbols
, name
, &entry
->addr
);
261 require_noerr(rval
, finish
);
263 if (entry
->flags
& KXLD_SYM_OBSOLETE
) {
264 rval
= kxld_dict_insert(obsolete_symbols
, name
, &entry
->addr
);
265 require_noerr(rval
, finish
);
274 #endif /* KXLD_USER_OR_ILP32 */
276 #if KXLD_USER_OR_LP64
277 /*******************************************************************************
278 *******************************************************************************/
280 get_symbols_64(KXLDState
*state
, KXLDDict
*defined_symbols
,
281 KXLDDict
*obsolete_symbols
)
283 kern_return_t rval
= KERN_FAILURE
;
284 KXLDLinkStateHdr
*hdr
= (KXLDLinkStateHdr
*) state
->file
;
285 KXLDSymEntry64
*entry
= NULL
;
286 const char *name
= NULL
;
289 entry
= (KXLDSymEntry64
*) (state
->file
+ hdr
->symoff
);
290 for (i
= 0; i
< hdr
->nsyms
; ++i
, ++entry
) {
291 name
= (const char *) (state
->file
+ entry
->nameoff
);
292 rval
= kxld_dict_insert(defined_symbols
, name
, &entry
->addr
);
293 require_noerr(rval
, finish
);
295 if (entry
->flags
& KXLD_SYM_OBSOLETE
) {
296 rval
= kxld_dict_insert(obsolete_symbols
, name
, &entry
->addr
);
297 require_noerr(rval
, finish
);
306 #endif /* KXLD_USER_OR_LP64 */
308 /*******************************************************************************
309 *******************************************************************************/
311 kxld_state_get_num_vtables(KXLDState
*state
)
313 return state
->vtables
.nitems
;
316 /*******************************************************************************
317 *******************************************************************************/
319 kxld_state_get_vtables(KXLDState
*state
, KXLDDict
*patched_vtables
)
321 kern_return_t rval
= KERN_FAILURE
;
322 KXLDVTable
*vtable
= NULL
;
326 check(patched_vtables
);
328 for (i
= 0; i
< state
->vtables
.nitems
; ++i
) {
329 vtable
= kxld_array_get_item(&state
->vtables
, i
);
330 rval
= kxld_dict_insert(patched_vtables
, vtable
->name
, vtable
);
331 require_noerr(rval
, finish
);
340 /*******************************************************************************
341 *******************************************************************************/
343 kxld_state_get_cputype(const KXLDState
*state
, cpu_type_t
*cputype
,
344 cpu_subtype_t
*cpusubtype
)
346 KXLDLinkStateHdr
*hdr
= (KXLDLinkStateHdr
*) state
->file
;
352 *cputype
= hdr
->cputype
;
353 *cpusubtype
= hdr
->cpusubtype
;
356 /*******************************************************************************
357 *******************************************************************************/
359 kxld_state_export_kext_to_file(KXLDKext
*kext
, u_char
**file
, u_long
*filesize
,
360 KXLDDict
*strings
, KXLDArray
*tmps
)
362 kern_return_t rval
= KERN_FAILURE
;
363 KXLDSymtabIterator iter
;
364 const KXLDSymtab
*symtab
= NULL
;
365 const KXLDArray
*vtables
= NULL
;
366 const KXLDVTable
*vtable
= NULL
;
368 u_int nsymentries
= 0;
376 bzero(&iter
, sizeof(iter
));
378 /* Get the vtables and symbol tables from the kext */
380 kxld_kext_get_vtables(kext
, &vtables
);
381 symtab
= kxld_kext_get_symtab(kext
);
382 require_action(symtab
, finish
, rval
=KERN_FAILURE
);
384 /* Count the number of symentries we'll need in the linkstate */
386 kxld_symtab_iterator_init(&iter
, symtab
, kxld_sym_is_exported
, FALSE
);
388 nsyms
= kxld_symtab_iterator_get_num_remaining(&iter
);
390 for (i
= 0; i
< vtables
->nitems
; ++i
) {
391 vtable
= kxld_array_get_item(vtables
, i
);
392 nsymentries
+= vtable
->entries
.nitems
;
395 /* Initialize the string index */
397 rval
= init_string_index(strings
, tmps
, &iter
, vtables
, nsymentries
,
399 require_noerr(rval
, finish
);
401 /* Create the linkstate file */
403 rval
= create_link_state(file
, filesize
, kext
, &iter
, vtables
,
404 strings
, nsyms
, nsymentries
, strsize
);
405 require_noerr(rval
, finish
);
407 /* Swap if necessary */
410 if (kxld_kext_target_needs_swap(kext
)) unswap_link_state(*file
);
419 /*******************************************************************************
420 *******************************************************************************/
422 init_string_index(KXLDDict
*strings
, KXLDArray
*tmps
, KXLDSymtabIterator
*iter
,
423 const KXLDArray
*vtables
, u_int nsymentries
, u_long
*_strsize
)
425 kern_return_t rval
= KERN_SUCCESS
;
426 const KXLDSym
*sym
= NULL
;
427 const KXLDVTable
*vtable
= NULL
;
428 const KXLDVTableEntry
*ventry
= NULL
;
442 /* Initialize the string dictionary and string offset array */
444 rval
= kxld_dict_init(strings
, kxld_dict_string_hash
, kxld_dict_string_cmp
,
446 require_noerr(rval
, finish
);
448 rval
= kxld_array_init(tmps
, sizeof(u_long
), nsymentries
);
449 require_noerr(rval
, finish
);
451 /* Add all of the strings from the symbol table to the dictionary */
453 kxld_symtab_iterator_reset(iter
);
454 while ((sym
= kxld_symtab_iterator_get_next(iter
))) {
455 rval
= add_string_to_index(strings
, sym
->name
, tmps
, &tmpi
, &strsize
);
456 require_noerr(rval
, finish
);
459 /* Add all of the strings from the vtables entries to the dictionary */
461 for (i
= 0; i
< vtables
->nitems
; ++i
) {
462 vtable
= kxld_array_get_item(vtables
, i
);
463 rval
= add_string_to_index(strings
, vtable
->name
, tmps
, &tmpi
, &strsize
);
464 require_noerr(rval
, finish
);
466 for (j
= 0; j
< vtable
->entries
.nitems
; ++j
) {
467 ventry
= kxld_array_get_item(&vtable
->entries
, j
);
468 if (ventry
->patched
.name
) {
469 rval
= add_string_to_index(strings
, ventry
->patched
.name
, tmps
,
471 require_noerr(rval
, finish
);
483 /*******************************************************************************
484 *******************************************************************************/
486 add_string_to_index(KXLDDict
*strings
, const char *str
, KXLDArray
*tmps
,
487 u_int
*tmpi
, u_long
*stroff
)
489 kern_return_t rval
= KERN_FAILURE
;
492 if (!kxld_dict_find(strings
, str
)) {
493 tmpp
= kxld_array_get_item(tmps
, (*tmpi
)++);
496 rval
= kxld_dict_insert(strings
, str
, tmpp
);
497 require_noerr(rval
, finish
);
499 *stroff
+= strlen(str
) + 1;
508 /*******************************************************************************
509 *******************************************************************************/
511 state_is_32_bit(KXLDLinkStateHdr
*state
)
513 return kxld_is_32_bit(state
->cputype
);
516 /*******************************************************************************
517 *******************************************************************************/
519 create_link_state(u_char
**_file
, u_long
*_filesize
, const KXLDKext
*kext
,
520 KXLDSymtabIterator
*iter
, const KXLDArray
*vtables
, KXLDDict
*strings
,
521 u_int nsyms
, u_int nsymentries
, u_long strsize
)
523 kern_return_t rval
= KERN_SUCCESS
;
525 KXLDLinkStateHdr
*hdr
= NULL
;
526 KXLDDictIterator striter
;
527 #if KXLD_USER_OR_OBJECT
528 KXLDSectionName
*dstsectname
= NULL
;
529 KXLDSectionName
*srcsectname
= NULL
;
530 const KXLDArray
*section_order
= NULL
;
533 const char *name
= NULL
;
534 char *dstname
= NULL
;
551 #if KXLD_USER_OR_OBJECT
552 section_order
= kxld_kext_get_section_order(kext
);
555 /* Calculate header and data size */
557 hsize
= sizeof(KXLDLinkStateHdr
);
558 hsize
+= vtables
->nitems
* sizeof(KXLDVTableHdr
);
559 #if KXLD_USER_OR_OBJECT
561 hsize
+= section_order
->nitems
* sizeof(KXLDSectionName
);
565 if (kxld_kext_is_32_bit(kext
)) {
566 dsize
= nsymentries
* sizeof(KXLDSymEntry32
);
568 dsize
= nsymentries
* sizeof(KXLDSymEntry64
);
571 filesize
= hsize
+ dsize
+ strsize
;
575 stroff
= hsize
+ dsize
;
577 /* Allocate the link state */
579 file
= kxld_alloc_pageable(filesize
);
580 require_action(file
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
582 /* Initialize link state header */
584 hdr
= (KXLDLinkStateHdr
*) file
;
585 hoff
+= sizeof(*hdr
);
587 if (state_is_32_bit(hdr
)) {
588 hdr
->magic
= LINK_STATE_MAGIC
;
590 hdr
->magic
= LINK_STATE_MAGIC_64
;
592 hdr
->version
= LINK_STATE_VERSION
;
593 kxld_kext_get_cputype(kext
, &hdr
->cputype
, &hdr
->cpusubtype
);
595 hdr
->nvtables
= vtables
->nitems
;
598 #if KXLD_USER_OR_OBJECT
600 hdr
->nsects
= section_order
->nitems
;
601 hdr
->sectoff
= (uint32_t) hoff
;
603 dstsectname
= (KXLDSectionName
*) (file
+ hoff
);
604 hoff
+= section_order
->nitems
* sizeof(*dstsectname
);
606 for (i
= 0; i
< section_order
->nitems
; ++i
, ++dstsectname
) {
607 srcsectname
= kxld_array_get_item(section_order
, i
);
608 memcpy(dstsectname
, srcsectname
, sizeof(*srcsectname
));
613 hdr
->voff
= (uint32_t) hoff
;
614 hdr
->symoff
= (uint32_t) doff
;
618 kxld_dict_iterator_init(&striter
, strings
);
619 kxld_dict_iterator_get_next(&striter
, (const void **) &name
, (void **) &stridx
);
622 dstname
= (char *) (file
+ *stridx
);
623 strlcpy(dstname
, name
, filesize
- *stridx
);
624 kxld_dict_iterator_get_next(&striter
, (const void **) &name
, (void **) &stridx
);
629 KXLD_3264_FUNC(state_is_32_bit(hdr
), rval
,
630 copy_symbols_32
, copy_symbols_64
,
631 file
, &doff
, iter
, strings
);
632 require_noerr(rval
, finish
);
636 KXLD_3264_FUNC(state_is_32_bit(hdr
), rval
,
637 copy_vtables_32
, copy_vtables_64
,
638 file
, &hoff
, &doff
, vtables
, strings
);
639 require_noerr(rval
, finish
);
642 *_filesize
= filesize
;
649 kxld_page_free(file
, filesize
);
656 #if KXLD_USER_OR_ILP32
657 /*******************************************************************************
658 *******************************************************************************/
660 copy_symbols_32(u_char
*file
, u_long
*data_offset
, KXLDSymtabIterator
*iter
,
661 const KXLDDict
*strings
)
663 kern_return_t rval
= KERN_FAILURE
;
664 KXLDSymEntry32
*symentry
= NULL
;
665 const KXLDSym
*sym
= NULL
;
668 kxld_symtab_iterator_reset(iter
);
669 while ((sym
= kxld_symtab_iterator_get_next(iter
))) {
670 symentry
= (KXLDSymEntry32
*) (file
+ *data_offset
);
671 stridx
= kxld_dict_find(strings
, sym
->name
);
672 require_action(stridx
, finish
, rval
=KERN_FAILURE
);
674 /* Initialize the symentry */
676 symentry
->nameoff
= (uint32_t) *stridx
;
677 if (sym
->predicates
.is_thumb
) {
678 symentry
->addr
= (uint32_t) sym
->link_addr
| 1;
680 symentry
->addr
= (uint32_t) sym
->link_addr
;
686 symentry
->flags
|= (kxld_sym_is_obsolete(sym
)) ? KXLD_SYM_OBSOLETE
: 0;
688 *data_offset
+= sizeof(*symentry
);
696 #endif /* KXLD_USER_OR_ILP32 */
698 #if KXLD_USER_OR_LP64
699 /*******************************************************************************
700 *******************************************************************************/
702 copy_symbols_64(u_char
*file
, u_long
*data_offset
, KXLDSymtabIterator
*iter
,
703 const KXLDDict
*strings
)
705 kern_return_t rval
= KERN_FAILURE
;
706 KXLDSymEntry64
*symentry
= NULL
;
707 const KXLDSym
*sym
= NULL
;
710 kxld_symtab_iterator_reset(iter
);
711 while ((sym
= kxld_symtab_iterator_get_next(iter
))) {
712 symentry
= (KXLDSymEntry64
*) (file
+ *data_offset
);
713 stridx
= kxld_dict_find(strings
, sym
->name
);
714 require_action(stridx
, finish
, rval
=KERN_FAILURE
);
716 /* Initialize the symentry */
718 symentry
->nameoff
= (uint32_t) *stridx
;
719 symentry
->addr
= (uint64_t) sym
->link_addr
;
724 symentry
->flags
|= (kxld_sym_is_obsolete(sym
)) ? KXLD_SYM_OBSOLETE
: 0;
726 *data_offset
+= sizeof(*symentry
);
734 #endif /* KXLD_USER_OR_LP64 */
736 #if KXLD_USER_OR_ILP32
737 /*******************************************************************************
738 *******************************************************************************/
740 copy_vtables_32(u_char
*file
, u_long
*header_offset
, u_long
*data_offset
,
741 const KXLDArray
*vtables
, const KXLDDict
*strings
)
743 kern_return_t rval
= KERN_FAILURE
;
744 KXLDVTable
*vtable
= NULL
;
745 KXLDVTableHdr
*vhdr
= NULL
;
746 KXLDVTableEntry
*ventry
= NULL
;
747 KXLDSymEntry32
*symentry
= NULL
;
752 for (i
= 0; i
< vtables
->nitems
; ++i
) {
753 vtable
= kxld_array_get_item(vtables
, i
);
754 stridx
= kxld_dict_find(strings
, vtable
->name
);
755 require_action(stridx
, finish
, rval
=KERN_FAILURE
);
757 vhdr
= (KXLDVTableHdr
*) (file
+ *header_offset
);
758 vhdr
->nameoff
= (uint32_t) *stridx
;
759 vhdr
->nentries
= vtable
->entries
.nitems
;
760 vhdr
->vtableoff
= (uint32_t) (*data_offset
);
762 *header_offset
+= sizeof(*vhdr
);
764 for(j
= 0; j
< vtable
->entries
.nitems
; ++j
) {
766 ventry
= kxld_array_get_item(&vtable
->entries
, j
);
767 symentry
= (KXLDSymEntry32
*) (file
+ *data_offset
);
769 if (ventry
->patched
.name
) {
770 stridx
= kxld_dict_find(strings
, ventry
->patched
.name
);
771 require_action(stridx
, finish
, rval
=KERN_FAILURE
);
773 symentry
->nameoff
= (uint32_t) *stridx
;
774 symentry
->addr
= (uint32_t) ventry
->patched
.addr
;
776 symentry
->nameoff
= 0;
780 *data_offset
+= sizeof(*symentry
);
789 #endif /* KXLD_USER_OR_ILP32 */
791 #if KXLD_USER_OR_LP64
792 /*******************************************************************************
793 *******************************************************************************/
795 copy_vtables_64(u_char
*file
, u_long
*header_offset
, u_long
*data_offset
,
796 const KXLDArray
*vtables
, const KXLDDict
*strings
)
798 kern_return_t rval
= KERN_FAILURE
;
799 KXLDVTable
*vtable
= NULL
;
800 KXLDVTableHdr
*vhdr
= NULL
;
801 KXLDVTableEntry
*ventry
= NULL
;
802 KXLDSymEntry64
*symentry
= NULL
;
807 for (i
= 0; i
< vtables
->nitems
; ++i
) {
808 vtable
= kxld_array_get_item(vtables
, i
);
809 stridx
= kxld_dict_find(strings
, vtable
->name
);
810 require_action(stridx
, finish
, rval
=KERN_FAILURE
);
812 vhdr
= (KXLDVTableHdr
*) (file
+ *header_offset
);
813 vhdr
->nameoff
= (uint32_t) *stridx
;
814 vhdr
->nentries
= vtable
->entries
.nitems
;
815 vhdr
->vtableoff
= (uint32_t) (*data_offset
);
817 *header_offset
+= sizeof(*vhdr
);
819 for(j
= 0; j
< vtable
->entries
.nitems
; ++j
) {
821 ventry
= kxld_array_get_item(&vtable
->entries
, j
);
822 symentry
= (KXLDSymEntry64
*) (file
+ *data_offset
);
824 if (ventry
->patched
.name
) {
825 stridx
= kxld_dict_find(strings
, ventry
->patched
.name
);
826 require_action(stridx
, finish
, rval
=KERN_FAILURE
);
828 symentry
->nameoff
= (uint32_t) *stridx
;
829 symentry
->addr
= (uint64_t) ventry
->patched
.addr
;
831 symentry
->nameoff
= 0;
835 *data_offset
+= sizeof(*symentry
);
844 #endif /* KXLD_USER_OR_LP64 */
847 /*******************************************************************************
848 *******************************************************************************/
850 swap_link_state(u_char
*state
)
852 KXLDLinkStateHdr
*state_hdr
= (KXLDLinkStateHdr
*) state
;
854 if (state_hdr
->magic
== CIGAM_ETATS_KNIL
) {
855 swap_link_state_32(state
);
857 } else if (state_hdr
->magic
== CIGAM_ETATS_KNIL_64
) {
858 swap_link_state_64(state
);
865 /*******************************************************************************
866 *******************************************************************************/
868 swap_link_state_32(u_char
*state
)
870 KXLDLinkStateHdr
*state_hdr
= NULL
;
871 KXLDVTableHdr
*vtable_hdr
= NULL
;
872 KXLDSymEntry32
*entry
= NULL
;
876 state_hdr
= (KXLDLinkStateHdr
*) state
;
878 if (state_hdr
->magic
!= CIGAM_ETATS_KNIL
) return;
880 /* Swap the header */
881 swap_state_hdr(state_hdr
);
883 /* Swap the symbols */
884 entry
= (KXLDSymEntry32
*) (state
+ state_hdr
->symoff
);
885 for (i
= 0; i
< state_hdr
->nsyms
; ++i
, ++entry
) {
886 swap_sym_entry_32(entry
);
889 /* Swap the vtable headers and entries */
890 vtable_hdr
= (KXLDVTableHdr
*) (state
+ state_hdr
->voff
);
891 for (i
= 0; i
< state_hdr
->nvtables
; ++i
, ++vtable_hdr
) {
892 swap_vtable_hdr(vtable_hdr
);
894 entry
= (KXLDSymEntry32
*) (state
+ vtable_hdr
->vtableoff
);
895 for (j
= 0; j
< vtable_hdr
->nentries
; ++j
, ++entry
) {
896 swap_sym_entry_32(entry
);
901 /*******************************************************************************
902 *******************************************************************************/
904 swap_link_state_64(u_char
*state
)
906 KXLDLinkStateHdr
*state_hdr
= NULL
;
907 KXLDVTableHdr
*vtable_hdr
= NULL
;
908 KXLDSymEntry64
*entry
= NULL
;
912 state_hdr
= (KXLDLinkStateHdr
*) state
;
914 if (state_hdr
->magic
!= CIGAM_ETATS_KNIL_64
) return;
916 /* Swap the header */
917 swap_state_hdr(state_hdr
);
919 /* Swap the symbols */
920 entry
= (KXLDSymEntry64
*) (state
+ state_hdr
->symoff
);
921 for (i
= 0; i
< state_hdr
->nsyms
; ++i
, ++entry
) {
922 swap_sym_entry_64(entry
);
925 /* Swap the vtable headers and entries */
926 vtable_hdr
= (KXLDVTableHdr
*) (state
+ state_hdr
->voff
);
927 for (i
= 0; i
< state_hdr
->nvtables
; ++i
, ++vtable_hdr
) {
928 swap_vtable_hdr(vtable_hdr
);
930 entry
= (KXLDSymEntry64
*) (state
+ vtable_hdr
->vtableoff
);
931 for (j
= 0; j
< vtable_hdr
->nentries
; ++j
, ++entry
) {
932 swap_sym_entry_64(entry
);
937 /*******************************************************************************
938 *******************************************************************************/
940 unswap_link_state(u_char
*state
)
942 KXLDLinkStateHdr
*state_hdr
= (KXLDLinkStateHdr
*) state
;
944 if (state_hdr
->magic
== LINK_STATE_MAGIC
) {
945 unswap_link_state_32(state
);
947 } else if (state_hdr
->magic
== LINK_STATE_MAGIC_64
) {
948 unswap_link_state_64(state
);
955 /*******************************************************************************
956 *******************************************************************************/
958 unswap_link_state_32(u_char
*state
)
960 KXLDLinkStateHdr
*state_hdr
= NULL
;
961 KXLDVTableHdr
*vtable_hdr
= NULL
;
962 KXLDSymEntry32
*entry
= NULL
;
966 state_hdr
= (KXLDLinkStateHdr
*) state
;
968 if (state_hdr
->magic
!= LINK_STATE_MAGIC
) return;
970 /* Unswap the vtables and their headers */
971 vtable_hdr
= (KXLDVTableHdr
*) (state
+ state_hdr
->voff
);
972 for (i
= 0; i
< state_hdr
->nvtables
; ++i
, ++vtable_hdr
) {
973 entry
= (KXLDSymEntry32
*) (state
+ vtable_hdr
->vtableoff
);
974 for (j
= 0; j
< vtable_hdr
->nentries
; ++j
, ++entry
) {
975 swap_sym_entry_32(entry
);
978 swap_vtable_hdr(vtable_hdr
);
981 /* Unswap the symbols themselves */
982 entry
= (KXLDSymEntry32
*) (state
+ state_hdr
->symoff
);
983 for (i
= 0; i
< state_hdr
->nsyms
; ++i
, ++entry
) {
984 swap_sym_entry_32(entry
);
987 /* Unswap the header */
988 swap_state_hdr(state_hdr
);
991 /*******************************************************************************
992 *******************************************************************************/
994 unswap_link_state_64(u_char
*state
)
996 KXLDLinkStateHdr
*state_hdr
= NULL
;
997 KXLDVTableHdr
*vtable_hdr
= NULL
;
998 KXLDSymEntry64
*entry
= NULL
;
1002 state_hdr
= (KXLDLinkStateHdr
*) state
;
1004 if (state_hdr
->magic
!= LINK_STATE_MAGIC_64
) return;
1006 /* Unswap the vtables and their headers */
1007 vtable_hdr
= (KXLDVTableHdr
*) (state
+ state_hdr
->voff
);
1008 for (i
= 0; i
< state_hdr
->nvtables
; ++i
, ++vtable_hdr
) {
1009 entry
= (KXLDSymEntry64
*) (state
+ vtable_hdr
->vtableoff
);
1010 for (j
= 0; j
< vtable_hdr
->nentries
; ++j
, ++entry
) {
1011 swap_sym_entry_64(entry
);
1014 swap_vtable_hdr(vtable_hdr
);
1017 /* Unswap the symbols themselves */
1018 entry
= (KXLDSymEntry64
*) (state
+ state_hdr
->symoff
);
1019 for (i
= 0; i
< state_hdr
->nsyms
; ++i
, ++entry
) {
1020 swap_sym_entry_64(entry
);
1023 /* Unswap the header */
1024 swap_state_hdr(state_hdr
);
1027 /*******************************************************************************
1028 *******************************************************************************/
1030 swap_state_hdr(KXLDLinkStateHdr
*state_hdr
)
1032 state_hdr
->magic
= OSSwapInt32(state_hdr
->magic
);
1033 state_hdr
->version
= OSSwapInt32(state_hdr
->version
);
1034 state_hdr
->cputype
= OSSwapInt32(state_hdr
->cputype
);
1035 state_hdr
->cpusubtype
= OSSwapInt32(state_hdr
->cpusubtype
);
1036 state_hdr
->nsects
= OSSwapInt32(state_hdr
->nsects
);
1037 state_hdr
->sectoff
= OSSwapInt32(state_hdr
->sectoff
);
1038 state_hdr
->nvtables
= OSSwapInt32(state_hdr
->nvtables
);
1039 state_hdr
->voff
= OSSwapInt32(state_hdr
->voff
);
1040 state_hdr
->nsyms
= OSSwapInt32(state_hdr
->nsyms
);
1041 state_hdr
->symoff
= OSSwapInt32(state_hdr
->symoff
);
1044 /*******************************************************************************
1045 *******************************************************************************/
1047 swap_vtable_hdr(KXLDVTableHdr
*vtable_hdr
)
1049 vtable_hdr
->nameoff
= OSSwapInt32(vtable_hdr
->nameoff
);
1050 vtable_hdr
->vtableoff
= OSSwapInt32(vtable_hdr
->vtableoff
);
1051 vtable_hdr
->nentries
= OSSwapInt32(vtable_hdr
->nentries
);
1054 /*******************************************************************************
1055 *******************************************************************************/
1057 swap_sym_entry_32(KXLDSymEntry32
*entry
)
1059 entry
->nameoff
= OSSwapInt32(entry
->nameoff
);
1060 entry
->addr
= OSSwapInt32(entry
->addr
);
1063 /*******************************************************************************
1064 *******************************************************************************/
1066 swap_sym_entry_64(KXLDSymEntry64
*entry
)
1068 entry
->nameoff
= OSSwapInt32(entry
->nameoff
);
1069 entry
->addr
= OSSwapInt64(entry
->addr
);
1071 #endif /* !KERNEL */