]> git.saurik.com Git - apple/xnu.git/blob - libkern/kxld/kxld_state.c
xnu-1504.7.4.tar.gz
[apple/xnu.git] / libkern / kxld / kxld_state.c
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
30 #if !KERNEL
31 #include <libkern/OSByteOrder.h>
32 #endif
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_kext.h"
40 #include "kxld_state.h"
41 #include "kxld_sym.h"
42 #include "kxld_symtab.h"
43 #include "kxld_util.h"
44 #include "kxld_vtable.h"
45
46 #define LINK_STATE_MAGIC 0xF00DD00D
47 #define CIGAM_ETATS_KNIL 0x0DD00DF0
48
49 #define LINK_STATE_MAGIC_64 0xCAFEF00D
50 #define CIGAM_ETATS_KNIL_64 0x0DF0FECA
51
52 #define LINK_STATE_VERSION 1
53
54 static kern_return_t init_string_index(KXLDDict *strings, KXLDArray *tmps,
55 KXLDSymtabIterator *iter, const KXLDArray *vtables, u_int nsymentries,
56 u_long *strsize);
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);
63
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*/
72 #if KXLD_USER_OR_LP64
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 */
80
81 #if !KERNEL
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);
92 #endif
93
94 /*******************************************************************************
95 *******************************************************************************/
96 kern_return_t
97 kxld_state_init_from_file(KXLDState *state, u_char *file,
98 KXLDArray *section_order __unused)
99 {
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;
105 #endif
106 KXLDVTableHdr *vhdr = NULL;
107 KXLDVTable *vtable = NULL;
108 u_int i = 0;
109
110 check(state);
111 check(file);
112
113 #if !KERNEL
114 /* Swap the link state file to host byte order for as long this kxld_state
115 * object owns the file.
116 */
117 state->swap = swap_link_state(file);
118 #endif
119 require_action(hdr->magic == LINK_STATE_MAGIC ||
120 hdr->magic == LINK_STATE_MAGIC_64,
121 finish, rval=KERN_FAILURE);
122
123 state->file = file;
124
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);
129
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));
134 }
135 }
136 #endif
137
138 rval = kxld_array_init(&state->vtables, sizeof(*vtable), hdr->nvtables);
139 require_noerr(rval, finish);
140
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,
147 vtable, file, vhdr);
148 require_noerr(rval, finish);
149 }
150
151 rval = KERN_SUCCESS;
152
153 finish:
154 return rval;
155 }
156
157 /*******************************************************************************
158 *******************************************************************************/
159 void
160 kxld_state_clear(KXLDState *state)
161 {
162 KXLDVTable *vtable = NULL;
163 u_int i = 0;
164
165 check(state);
166
167 #if !KERNEL
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.
171 */
172 if (state->swap) (void)unswap_link_state(state->file);
173 #endif
174
175 state->file = NULL;
176 state->swap = FALSE;
177 for (i = 0; i < state->vtables.nitems; ++i) {
178 vtable = kxld_array_get_item(&state->vtables, i);
179 kxld_vtable_clear(vtable);
180 }
181 kxld_array_reset(&state->vtables);
182 }
183
184 /*******************************************************************************
185 *******************************************************************************/
186 void
187 kxld_state_deinit(KXLDState *state)
188 {
189 KXLDVTable *vtable = NULL;
190 u_int i = 0;
191
192 check(state);
193
194 #if !KERNEL
195 if (state->file && state->swap) (void)unswap_link_state(state->file);
196 #endif
197
198 for (i = 0; i < state->vtables.maxitems; ++i) {
199 vtable = kxld_array_get_slot(&state->vtables, i);
200 kxld_vtable_deinit(vtable);
201 }
202 kxld_array_deinit(&state->vtables);
203 bzero(state, sizeof(*state));
204 }
205
206 /*******************************************************************************
207 *******************************************************************************/
208 u_int
209 kxld_state_get_num_symbols(KXLDState *state)
210 {
211 KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) state->file;
212
213 return hdr->nsyms;
214 }
215
216 /*******************************************************************************
217 *******************************************************************************/
218 kern_return_t
219 kxld_state_get_symbols(KXLDState *state, KXLDDict *defined_symbols,
220 KXLDDict *obsolete_symbols)
221 {
222 KXLDLinkStateHdr * hdr = (KXLDLinkStateHdr *) state->file;
223 kern_return_t rval = KERN_FAILURE;
224
225 check(state);
226 check(defined_symbols);
227 check(obsolete_symbols);
228
229 require_action(hdr->magic == LINK_STATE_MAGIC ||
230 hdr->magic == LINK_STATE_MAGIC_64,
231 finish, rval=KERN_FAILURE);
232
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);
237
238 rval = KERN_SUCCESS;
239
240 finish:
241 return rval;
242 }
243
244 #if KXLD_USER_OR_ILP32
245 /*******************************************************************************
246 *******************************************************************************/
247 static kern_return_t
248 get_symbols_32(KXLDState *state, KXLDDict *defined_symbols,
249 KXLDDict *obsolete_symbols)
250 {
251 kern_return_t rval = KERN_FAILURE;
252 KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) state->file;
253 KXLDSymEntry32 *entry = NULL;
254 const char *name = NULL;
255 u_int i = 0;
256
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);
262
263 if (entry->flags & KXLD_SYM_OBSOLETE) {
264 rval = kxld_dict_insert(obsolete_symbols, name, &entry->addr);
265 require_noerr(rval, finish);
266 }
267 }
268
269 rval = KERN_SUCCESS;
270
271 finish:
272 return rval;
273 }
274 #endif /* KXLD_USER_OR_ILP32 */
275
276 #if KXLD_USER_OR_LP64
277 /*******************************************************************************
278 *******************************************************************************/
279 static kern_return_t
280 get_symbols_64(KXLDState *state, KXLDDict *defined_symbols,
281 KXLDDict *obsolete_symbols)
282 {
283 kern_return_t rval = KERN_FAILURE;
284 KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) state->file;
285 KXLDSymEntry64 *entry = NULL;
286 const char *name = NULL;
287 u_int i = 0;
288
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);
294
295 if (entry->flags & KXLD_SYM_OBSOLETE) {
296 rval = kxld_dict_insert(obsolete_symbols, name, &entry->addr);
297 require_noerr(rval, finish);
298 }
299 }
300
301 rval = KERN_SUCCESS;
302
303 finish:
304 return rval;
305 }
306 #endif /* KXLD_USER_OR_LP64 */
307
308 /*******************************************************************************
309 *******************************************************************************/
310 u_int
311 kxld_state_get_num_vtables(KXLDState *state)
312 {
313 return state->vtables.nitems;
314 }
315
316 /*******************************************************************************
317 *******************************************************************************/
318 kern_return_t
319 kxld_state_get_vtables(KXLDState *state, KXLDDict *patched_vtables)
320 {
321 kern_return_t rval = KERN_FAILURE;
322 KXLDVTable *vtable = NULL;
323 u_int i = 0;
324
325 check(state);
326 check(patched_vtables);
327
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);
332 }
333
334 rval = KERN_SUCCESS;
335
336 finish:
337 return rval;
338 }
339
340 /*******************************************************************************
341 *******************************************************************************/
342 void
343 kxld_state_get_cputype(const KXLDState *state, cpu_type_t *cputype,
344 cpu_subtype_t *cpusubtype)
345 {
346 KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) state->file;
347
348 check(state);
349 check(cputype);
350 check(cpusubtype);
351
352 *cputype = hdr->cputype;
353 *cpusubtype = hdr->cpusubtype;
354 }
355
356 /*******************************************************************************
357 *******************************************************************************/
358 kern_return_t
359 kxld_state_export_kext_to_file(KXLDKext *kext, u_char **file, u_long *filesize,
360 KXLDDict *strings, KXLDArray *tmps)
361 {
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;
367 u_int nsyms = 0;
368 u_int nsymentries = 0;
369 u_int i = 0;
370 u_long strsize = 0;
371
372 check(kext);
373 check(file);
374 check(tmps);
375
376 bzero(&iter, sizeof(iter));
377
378 /* Get the vtables and symbol tables from the kext */
379
380 kxld_kext_get_vtables(kext, &vtables);
381 symtab = kxld_kext_get_symtab(kext);
382 require_action(symtab, finish, rval=KERN_FAILURE);
383
384 /* Count the number of symentries we'll need in the linkstate */
385
386 kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_exported, FALSE);
387
388 nsyms = kxld_symtab_iterator_get_num_remaining(&iter);
389 nsymentries = nsyms;
390 for (i = 0; i < vtables->nitems; ++i) {
391 vtable = kxld_array_get_item(vtables, i);
392 nsymentries += vtable->entries.nitems;
393 }
394
395 /* Initialize the string index */
396
397 rval = init_string_index(strings, tmps, &iter, vtables, nsymentries,
398 &strsize);
399 require_noerr(rval, finish);
400
401 /* Create the linkstate file */
402
403 rval = create_link_state(file, filesize, kext, &iter, vtables,
404 strings, nsyms, nsymentries, strsize);
405 require_noerr(rval, finish);
406
407 /* Swap if necessary */
408
409 #if !KERNEL
410 if (kxld_kext_target_needs_swap(kext)) unswap_link_state(*file);
411 #endif /* !KERNEL */
412
413 rval = KERN_SUCCESS;
414
415 finish:
416 return rval;
417 }
418
419 /*******************************************************************************
420 *******************************************************************************/
421 static kern_return_t
422 init_string_index(KXLDDict *strings, KXLDArray *tmps, KXLDSymtabIterator *iter,
423 const KXLDArray *vtables, u_int nsymentries, u_long *_strsize)
424 {
425 kern_return_t rval = KERN_SUCCESS;
426 const KXLDSym *sym = NULL;
427 const KXLDVTable *vtable = NULL;
428 const KXLDVTableEntry *ventry = NULL;
429 u_long strsize = 0;
430 u_int tmpi = 0;
431 u_int i = 0;
432 u_int j = 0;
433
434 check(strings);
435 check(tmps);
436 check(iter);
437 check(vtables);
438 check(_strsize);
439
440 *_strsize = 0;
441
442 /* Initialize the string dictionary and string offset array */
443
444 rval = kxld_dict_init(strings, kxld_dict_string_hash, kxld_dict_string_cmp,
445 nsymentries);
446 require_noerr(rval, finish);
447
448 rval = kxld_array_init(tmps, sizeof(u_long), nsymentries);
449 require_noerr(rval, finish);
450
451 /* Add all of the strings from the symbol table to the dictionary */
452
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);
457 }
458
459 /* Add all of the strings from the vtables entries to the dictionary */
460
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);
465
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,
470 &tmpi, &strsize);
471 require_noerr(rval, finish);
472 }
473 }
474 }
475
476 *_strsize = strsize;
477 rval = KERN_SUCCESS;
478
479 finish:
480 return rval;
481 }
482
483 /*******************************************************************************
484 *******************************************************************************/
485 static kern_return_t
486 add_string_to_index(KXLDDict *strings, const char *str, KXLDArray *tmps,
487 u_int *tmpi, u_long *stroff)
488 {
489 kern_return_t rval = KERN_FAILURE;
490 u_long *tmpp = NULL;
491
492 if (!kxld_dict_find(strings, str)) {
493 tmpp = kxld_array_get_item(tmps, (*tmpi)++);
494 *tmpp = *stroff;
495
496 rval = kxld_dict_insert(strings, str, tmpp);
497 require_noerr(rval, finish);
498
499 *stroff += strlen(str) + 1;
500 }
501
502 rval = KERN_SUCCESS;
503
504 finish:
505 return rval;
506 }
507
508 /*******************************************************************************
509 *******************************************************************************/
510 static boolean_t
511 state_is_32_bit(KXLDLinkStateHdr *state)
512 {
513 return kxld_is_32_bit(state->cputype);
514 }
515
516 /*******************************************************************************
517 *******************************************************************************/
518 static kern_return_t
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)
522 {
523 kern_return_t rval = KERN_SUCCESS;
524 u_char *file = NULL;
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;
531 u_int i = 0;
532 #endif
533 const char *name = NULL;
534 char *dstname = NULL;
535 u_long *stridx = 0;
536 u_long hsize = 0;
537 u_long dsize = 0;
538 u_long filesize = 0;
539 u_long hoff = 0;
540 u_long doff = 0;
541 u_long stroff = 0;
542
543 check(_file);
544 check(iter);
545 check(vtables);
546 check(strings);
547
548 *_file = NULL;
549 *_filesize = 0;
550
551 #if KXLD_USER_OR_OBJECT
552 section_order = kxld_kext_get_section_order(kext);
553 #endif
554
555 /* Calculate header and data size */
556
557 hsize = sizeof(KXLDLinkStateHdr);
558 hsize += vtables->nitems * sizeof(KXLDVTableHdr);
559 #if KXLD_USER_OR_OBJECT
560 if (section_order) {
561 hsize += section_order->nitems * sizeof(KXLDSectionName);
562 }
563 #endif
564
565 if (kxld_kext_is_32_bit(kext)) {
566 dsize = nsymentries * sizeof(KXLDSymEntry32);
567 } else {
568 dsize = nsymentries * sizeof(KXLDSymEntry64);
569 }
570
571 filesize = hsize + dsize + strsize;
572
573 hoff = 0;
574 doff = hsize;
575 stroff = hsize + dsize;
576
577 /* Allocate the link state */
578
579 file = kxld_alloc_pageable(filesize);
580 require_action(file, finish, rval=KERN_RESOURCE_SHORTAGE);
581
582 /* Initialize link state header */
583
584 hdr = (KXLDLinkStateHdr *) file;
585 hoff += sizeof(*hdr);
586
587 if (state_is_32_bit(hdr)) {
588 hdr->magic = LINK_STATE_MAGIC;
589 } else {
590 hdr->magic = LINK_STATE_MAGIC_64;
591 }
592 hdr->version = LINK_STATE_VERSION;
593 kxld_kext_get_cputype(kext, &hdr->cputype, &hdr->cpusubtype);
594 hdr->nsects = 0;
595 hdr->nvtables = vtables->nitems;
596 hdr->nsyms = nsyms;
597
598 #if KXLD_USER_OR_OBJECT
599 if (section_order) {
600 hdr->nsects = section_order->nitems;
601 hdr->sectoff = (uint32_t) hoff;
602
603 dstsectname = (KXLDSectionName *) (file + hoff);
604 hoff += section_order->nitems * sizeof(*dstsectname);
605
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));
609 }
610 }
611 #endif
612
613 hdr->voff = (uint32_t) hoff;
614 hdr->symoff = (uint32_t) doff;
615
616 /* Copy strings */
617
618 kxld_dict_iterator_init(&striter, strings);
619 kxld_dict_iterator_get_next(&striter, (const void **) &name, (void **) &stridx);
620 while (name) {
621 *stridx += stroff;
622 dstname = (char *) (file + *stridx);
623 strlcpy(dstname, name, filesize - *stridx);
624 kxld_dict_iterator_get_next(&striter, (const void **) &name, (void **) &stridx);
625 }
626
627 /* Copy symbols */
628
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);
633
634 /* Copy vtables */
635
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);
640
641 *_file = file;
642 *_filesize = filesize;
643 file = NULL;
644 rval = KERN_SUCCESS;
645
646 finish:
647
648 if (file) {
649 kxld_page_free(file, filesize);
650 file = NULL;
651 }
652
653 return rval;
654 }
655
656 #if KXLD_USER_OR_ILP32
657 /*******************************************************************************
658 *******************************************************************************/
659 static kern_return_t
660 copy_symbols_32(u_char *file, u_long *data_offset, KXLDSymtabIterator *iter,
661 const KXLDDict *strings)
662 {
663 kern_return_t rval = KERN_FAILURE;
664 KXLDSymEntry32 *symentry = NULL;
665 const KXLDSym *sym = NULL;
666 u_long *stridx = 0;
667
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);
673
674 /* Initialize the symentry */
675
676 symentry->nameoff = (uint32_t) *stridx;
677 if (sym->predicates.is_thumb) {
678 symentry->addr = (uint32_t) sym->link_addr | 1;
679 } else {
680 symentry->addr = (uint32_t) sym->link_addr;
681 }
682 symentry->flags = 0;
683
684 /* Set any flags */
685
686 symentry->flags |= (kxld_sym_is_obsolete(sym)) ? KXLD_SYM_OBSOLETE : 0;
687
688 *data_offset += sizeof(*symentry);
689 }
690
691 rval = KERN_SUCCESS;
692
693 finish:
694 return rval;
695 }
696 #endif /* KXLD_USER_OR_ILP32 */
697
698 #if KXLD_USER_OR_LP64
699 /*******************************************************************************
700 *******************************************************************************/
701 static kern_return_t
702 copy_symbols_64(u_char *file, u_long *data_offset, KXLDSymtabIterator *iter,
703 const KXLDDict *strings)
704 {
705 kern_return_t rval = KERN_FAILURE;
706 KXLDSymEntry64 *symentry = NULL;
707 const KXLDSym *sym = NULL;
708 u_long *stridx = 0;
709
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);
715
716 /* Initialize the symentry */
717
718 symentry->nameoff = (uint32_t) *stridx;
719 symentry->addr = (uint64_t) sym->link_addr;
720 symentry->flags = 0;
721
722 /* Set any flags */
723
724 symentry->flags |= (kxld_sym_is_obsolete(sym)) ? KXLD_SYM_OBSOLETE : 0;
725
726 *data_offset += sizeof(*symentry);
727 }
728
729 rval = KERN_SUCCESS;
730
731 finish:
732 return rval;
733 }
734 #endif /* KXLD_USER_OR_LP64 */
735
736 #if KXLD_USER_OR_ILP32
737 /*******************************************************************************
738 *******************************************************************************/
739 static kern_return_t
740 copy_vtables_32(u_char *file, u_long *header_offset, u_long *data_offset,
741 const KXLDArray *vtables, const KXLDDict *strings)
742 {
743 kern_return_t rval = KERN_FAILURE;
744 KXLDVTable *vtable = NULL;
745 KXLDVTableHdr *vhdr = NULL;
746 KXLDVTableEntry *ventry = NULL;
747 KXLDSymEntry32 *symentry = NULL;
748 u_long *stridx = 0;
749 u_int i = 0;
750 u_int j = 0;
751
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);
756
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);
761
762 *header_offset += sizeof(*vhdr);
763
764 for(j = 0; j < vtable->entries.nitems; ++j) {
765
766 ventry = kxld_array_get_item(&vtable->entries, j);
767 symentry = (KXLDSymEntry32 *) (file + *data_offset);
768
769 if (ventry->patched.name) {
770 stridx = kxld_dict_find(strings, ventry->patched.name);
771 require_action(stridx, finish, rval=KERN_FAILURE);
772
773 symentry->nameoff = (uint32_t) *stridx;
774 symentry->addr = (uint32_t) ventry->patched.addr;
775 } else {
776 symentry->nameoff = 0;
777 symentry->addr = 0;
778 }
779
780 *data_offset += sizeof(*symentry);
781 }
782 }
783
784 rval = KERN_SUCCESS;
785
786 finish:
787 return rval;
788 }
789 #endif /* KXLD_USER_OR_ILP32 */
790
791 #if KXLD_USER_OR_LP64
792 /*******************************************************************************
793 *******************************************************************************/
794 static kern_return_t
795 copy_vtables_64(u_char *file, u_long *header_offset, u_long *data_offset,
796 const KXLDArray *vtables, const KXLDDict *strings)
797 {
798 kern_return_t rval = KERN_FAILURE;
799 KXLDVTable *vtable = NULL;
800 KXLDVTableHdr *vhdr = NULL;
801 KXLDVTableEntry *ventry = NULL;
802 KXLDSymEntry64 *symentry = NULL;
803 u_long *stridx = 0;
804 u_int i = 0;
805 u_int j = 0;
806
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);
811
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);
816
817 *header_offset += sizeof(*vhdr);
818
819 for(j = 0; j < vtable->entries.nitems; ++j) {
820
821 ventry = kxld_array_get_item(&vtable->entries, j);
822 symentry = (KXLDSymEntry64 *) (file + *data_offset);
823
824 if (ventry->patched.name) {
825 stridx = kxld_dict_find(strings, ventry->patched.name);
826 require_action(stridx, finish, rval=KERN_FAILURE);
827
828 symentry->nameoff = (uint32_t) *stridx;
829 symentry->addr = (uint64_t) ventry->patched.addr;
830 } else {
831 symentry->nameoff = 0;
832 symentry->addr = 0;
833 }
834
835 *data_offset += sizeof(*symentry);
836 }
837 }
838
839 rval = KERN_SUCCESS;
840
841 finish:
842 return rval;
843 }
844 #endif /* KXLD_USER_OR_LP64 */
845
846 #if !KERNEL
847 /*******************************************************************************
848 *******************************************************************************/
849 static boolean_t
850 swap_link_state(u_char *state)
851 {
852 KXLDLinkStateHdr *state_hdr = (KXLDLinkStateHdr *) state;
853
854 if (state_hdr->magic == CIGAM_ETATS_KNIL) {
855 swap_link_state_32(state);
856 return TRUE;
857 } else if (state_hdr->magic == CIGAM_ETATS_KNIL_64) {
858 swap_link_state_64(state);
859 return TRUE;
860 }
861
862 return FALSE;
863 }
864
865 /*******************************************************************************
866 *******************************************************************************/
867 static void
868 swap_link_state_32(u_char *state)
869 {
870 KXLDLinkStateHdr *state_hdr = NULL;
871 KXLDVTableHdr *vtable_hdr = NULL;
872 KXLDSymEntry32 *entry = NULL;
873 u_int i = 0;
874 u_int j = 0;
875
876 state_hdr = (KXLDLinkStateHdr *) state;
877
878 if (state_hdr->magic != CIGAM_ETATS_KNIL) return;
879
880 /* Swap the header */
881 swap_state_hdr(state_hdr);
882
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);
887 }
888
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);
893
894 entry = (KXLDSymEntry32 *) (state + vtable_hdr->vtableoff);
895 for (j = 0; j < vtable_hdr->nentries; ++j, ++entry) {
896 swap_sym_entry_32(entry);
897 }
898 }
899 }
900
901 /*******************************************************************************
902 *******************************************************************************/
903 static void
904 swap_link_state_64(u_char *state)
905 {
906 KXLDLinkStateHdr *state_hdr = NULL;
907 KXLDVTableHdr *vtable_hdr = NULL;
908 KXLDSymEntry64 *entry = NULL;
909 u_int i = 0;
910 u_int j = 0;
911
912 state_hdr = (KXLDLinkStateHdr *) state;
913
914 if (state_hdr->magic != CIGAM_ETATS_KNIL_64) return;
915
916 /* Swap the header */
917 swap_state_hdr(state_hdr);
918
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);
923 }
924
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);
929
930 entry = (KXLDSymEntry64 *) (state + vtable_hdr->vtableoff);
931 for (j = 0; j < vtable_hdr->nentries; ++j, ++entry) {
932 swap_sym_entry_64(entry);
933 }
934 }
935 }
936
937 /*******************************************************************************
938 *******************************************************************************/
939 static boolean_t
940 unswap_link_state(u_char *state)
941 {
942 KXLDLinkStateHdr *state_hdr = (KXLDLinkStateHdr *) state;
943
944 if (state_hdr->magic == LINK_STATE_MAGIC) {
945 unswap_link_state_32(state);
946 return TRUE;
947 } else if (state_hdr->magic == LINK_STATE_MAGIC_64) {
948 unswap_link_state_64(state);
949 return TRUE;
950 }
951
952 return FALSE;
953 }
954
955 /*******************************************************************************
956 *******************************************************************************/
957 static void
958 unswap_link_state_32(u_char *state)
959 {
960 KXLDLinkStateHdr *state_hdr = NULL;
961 KXLDVTableHdr *vtable_hdr = NULL;
962 KXLDSymEntry32 *entry = NULL;
963 u_int i = 0;
964 u_int j = 0;
965
966 state_hdr = (KXLDLinkStateHdr *) state;
967
968 if (state_hdr->magic != LINK_STATE_MAGIC) return;
969
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);
976 }
977
978 swap_vtable_hdr(vtable_hdr);
979 }
980
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);
985 }
986
987 /* Unswap the header */
988 swap_state_hdr(state_hdr);
989 }
990
991 /*******************************************************************************
992 *******************************************************************************/
993 static void
994 unswap_link_state_64(u_char *state)
995 {
996 KXLDLinkStateHdr *state_hdr = NULL;
997 KXLDVTableHdr *vtable_hdr = NULL;
998 KXLDSymEntry64 *entry = NULL;
999 u_int i = 0;
1000 u_int j = 0;
1001
1002 state_hdr = (KXLDLinkStateHdr *) state;
1003
1004 if (state_hdr->magic != LINK_STATE_MAGIC_64) return;
1005
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);
1012 }
1013
1014 swap_vtable_hdr(vtable_hdr);
1015 }
1016
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);
1021 }
1022
1023 /* Unswap the header */
1024 swap_state_hdr(state_hdr);
1025 }
1026
1027 /*******************************************************************************
1028 *******************************************************************************/
1029 static void
1030 swap_state_hdr(KXLDLinkStateHdr *state_hdr)
1031 {
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);
1042 }
1043
1044 /*******************************************************************************
1045 *******************************************************************************/
1046 static void
1047 swap_vtable_hdr(KXLDVTableHdr *vtable_hdr)
1048 {
1049 vtable_hdr->nameoff = OSSwapInt32(vtable_hdr->nameoff);
1050 vtable_hdr->vtableoff = OSSwapInt32(vtable_hdr->vtableoff);
1051 vtable_hdr->nentries = OSSwapInt32(vtable_hdr->nentries);
1052 }
1053
1054 /*******************************************************************************
1055 *******************************************************************************/
1056 static void
1057 swap_sym_entry_32(KXLDSymEntry32 *entry)
1058 {
1059 entry->nameoff = OSSwapInt32(entry->nameoff);
1060 entry->addr = OSSwapInt32(entry->addr);
1061 }
1062
1063 /*******************************************************************************
1064 *******************************************************************************/
1065 static void
1066 swap_sym_entry_64(KXLDSymEntry64 *entry)
1067 {
1068 entry->nameoff = OSSwapInt32(entry->nameoff);
1069 entry->addr = OSSwapInt64(entry->addr);
1070 }
1071 #endif /* !KERNEL */
1072