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/reloc.h>
31 #include <sys/types.h>
33 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
34 #include <AssertMacros.h>
36 #include "kxld_reloc.h"
37 #include "kxld_sect.h"
39 #include "kxld_symtab.h"
40 #include "kxld_util.h"
42 static kern_return_t
export_macho(const KXLDSect
*sect
, u_char
*buf
, u_long offset
,
44 #if KXLD_USER_OR_ILP32
45 static kern_return_t
sect_export_macho_header_32(const KXLDSect
*sect
, u_char
*buf
,
46 u_long
*header_offset
, u_long header_size
, u_long data_offset
);
49 static kern_return_t
sect_export_macho_header_64(const KXLDSect
*sect
, u_char
*buf
,
50 u_long
*header_offset
, u_long header_size
, u_long data_offset
);
52 extern boolean_t isSplitKext
;
54 #if KXLD_USER_OR_ILP32
55 /*******************************************************************************
56 *******************************************************************************/
58 kxld_sect_init_from_macho_32(KXLDSect
*sect
, u_char
*macho
, u_long
*sect_offset
,
59 u_int sectnum
, const KXLDRelocator
*relocator
)
61 kern_return_t rval
= KERN_FAILURE
;
62 struct section
*src
= (struct section
*) ((void *) (macho
+ *sect_offset
));
63 struct relocation_info
*relocs
= NULL
;
69 strlcpy(sect
->segname
, src
->segname
, sizeof(sect
->segname
));
70 strlcpy(sect
->sectname
, src
->sectname
, sizeof(sect
->sectname
));
71 sect
->base_addr
= src
->addr
;
72 sect
->link_addr
= src
->addr
;
73 sect
->size
= src
->size
;
74 sect
->sectnum
= sectnum
;
75 sect
->flags
= src
->flags
;
76 sect
->align
= src
->align
;
77 sect
->reserved1
= src
->reserved1
;
78 sect
->reserved2
= src
->reserved2
;
81 sect
->data
= macho
+ src
->offset
;
86 relocs
= (struct relocation_info
*) ((void *) (macho
+ src
->reloff
));
88 rval
= kxld_reloc_create_macho(§
->relocs
, relocator
,
90 require_noerr(rval
, finish
);
92 *sect_offset
+= sizeof(*src
);
97 kxld_sect_deinit(sect
);
102 #endif /* KXLD_USER_OR_ILP32 */
104 #if KXLD_USER_OR_LP64
105 /*******************************************************************************
106 *******************************************************************************/
108 kxld_sect_init_from_macho_64(KXLDSect
*sect
, u_char
*macho
, u_long
*sect_offset
,
109 u_int sectnum
, const KXLDRelocator
*relocator
)
111 kern_return_t rval
= KERN_FAILURE
;
112 struct section_64
*src
= (struct section_64
*) ((void *) (macho
+ *sect_offset
));
113 struct relocation_info
*relocs
= NULL
;
119 strlcpy(sect
->segname
, src
->segname
, sizeof(sect
->segname
));
120 strlcpy(sect
->sectname
, src
->sectname
, sizeof(sect
->sectname
));
121 sect
->base_addr
= src
->addr
;
122 sect
->link_addr
= src
->addr
;
123 sect
->size
= src
->size
;
124 sect
->sectnum
= sectnum
;
125 sect
->flags
= src
->flags
;
126 sect
->align
= src
->align
;
127 sect
->reserved1
= src
->reserved1
;
128 sect
->reserved2
= src
->reserved2
;
131 sect
->data
= macho
+ src
->offset
;
136 relocs
= (struct relocation_info
*) ((void *) (macho
+ src
->reloff
));
138 rval
= kxld_reloc_create_macho(§
->relocs
, relocator
,
139 relocs
, src
->nreloc
);
140 require_noerr(rval
, finish
);
142 *sect_offset
+= sizeof(*src
);
147 kxld_sect_deinit(sect
);
152 #endif /* KXLD_USER_OR_LP64 */
155 /*******************************************************************************
156 * Assumes GOT is comprised of kxld_addr_t entries
157 *******************************************************************************/
159 kxld_sect_init_got(KXLDSect
*sect
, u_int ngots
)
161 kern_return_t rval
= KERN_FAILURE
;
165 strlcpy(sect
->segname
, KXLD_SEG_GOT
, sizeof(sect
->segname
));
166 strlcpy(sect
->sectname
, KXLD_SECT_GOT
, sizeof(sect
->sectname
));
174 sect
->size
= ngots
* sizeof(kxld_addr_t
);
175 sect
->data
= kxld_alloc((u_long
) sect
->size
);
176 require_action(sect
->data
, finish
, rval
= KERN_RESOURCE_SHORTAGE
);
178 sect
->allocated
= TRUE
;
185 #endif /* KXLD_USER_OR_GOT */
187 #if KXLD_USER_OR_COMMON
188 /*******************************************************************************
189 *******************************************************************************/
191 kxld_sect_init_zerofill(KXLDSect
*sect
, const char *segname
,
192 const char *sectname
, kxld_size_t size
, u_int align
)
198 strlcpy(sect
->segname
, segname
, sizeof(sect
->segname
));
199 strlcpy(sect
->sectname
, sectname
, sizeof(sect
->sectname
));
204 sect
->flags
= S_ZEROFILL
;
206 #endif /* KXLD_USER_OR_COMMON */
208 /*******************************************************************************
209 *******************************************************************************/
211 kxld_sect_clear(KXLDSect
*sect
)
215 if (sect
->allocated
) {
216 kxld_free(sect
->data
, (u_long
) sect
->size
);
217 sect
->allocated
= FALSE
;
220 bzero(sect
->sectname
, sizeof(sect
->sectname
));
221 bzero(sect
->segname
, sizeof(sect
->segname
));
230 kxld_array_clear(§
->relocs
);
233 /*******************************************************************************
234 *******************************************************************************/
236 kxld_sect_deinit(KXLDSect
*sect
)
240 if (streq_safe(sect
->sectname
, KXLD_SECT_GOT
, sizeof(KXLD_SECT_GOT
))) {
241 kxld_free(sect
->data
, (u_long
) sect
->size
);
244 kxld_array_deinit(§
->relocs
);
245 bzero(sect
, sizeof(*sect
));
248 /*******************************************************************************
249 *******************************************************************************/
251 kxld_sect_get_num_relocs(const KXLDSect
*sect
)
255 return sect
->relocs
.nitems
;
258 /*******************************************************************************
259 *******************************************************************************/
261 kxld_sect_get_macho_header_size(boolean_t is_32_bit
)
264 return sizeof(struct section
);
266 return sizeof(struct section_64
);
270 /*******************************************************************************
271 *******************************************************************************/
273 kxld_sect_get_macho_data_size(const KXLDSect
*sect
)
280 size
= (u_long
) sect
->size
;
287 /*******************************************************************************
288 *******************************************************************************/
290 kxld_sect_get_ngots(const KXLDSect
*sect
, const KXLDRelocator
*relocator
,
291 const KXLDSymtab
*symtab
)
293 const KXLDReloc
*reloc
= NULL
;
298 for (i
= 0; i
< sect
->relocs
.nitems
; ++i
) {
299 reloc
= kxld_array_get_item(§
->relocs
, i
);
301 if (relocator
->reloc_has_got(reloc
->reloc_type
)) {
302 /* @TODO This assumes 64-bit symbols (which is valid at the
303 * moment since only x86_64 has a GOT)
305 sym
= kxld_reloc_get_symbol(relocator
, reloc
, sect
->data
, symtab
);
306 if (!kxld_sym_is_got(sym
)) {
307 kxld_sym_set_got(sym
);
315 #endif /* KXLD_USER_OR_GOT */
317 /*******************************************************************************
318 * Each section must be aligned at a certain power of two. To figure out that
319 * alignment, we mask for the low bits that may need to be adjusted. If they are
320 * non zero, we then subtract them from the target alignment to find the offset,
321 * and then add that offset to the link address.
322 *******************************************************************************/
324 kxld_sect_align_address(const KXLDSect
*sect
, kxld_addr_t address
)
326 return kxld_align_address(address
, sect
->align
);
329 /*******************************************************************************
330 *******************************************************************************/
332 kxld_sect_export_macho_to_file_buffer(const KXLDSect
*sect
, u_char
*buf
,
333 u_long
*header_offset
, u_long header_size
, u_long
*data_offset
,
334 u_long data_size
, boolean_t is_32_bit __unused
)
336 kern_return_t rval
= KERN_FAILURE
;
340 check(header_offset
);
343 /* If there is no data to export, we only need to write the header. We
344 * make it a separate call so that we don't modify data_offset.
347 KXLD_3264_FUNC(is_32_bit
, rval
,
348 sect_export_macho_header_32
, sect_export_macho_header_64
,
349 sect
, buf
, header_offset
, header_size
, /* data_offset */ 0);
350 require_noerr(rval
, finish
);
352 *data_offset
= (u_long
) kxld_sect_align_address(sect
, *data_offset
);
354 KXLD_3264_FUNC(is_32_bit
, rval
,
355 sect_export_macho_header_32
, sect_export_macho_header_64
,
356 sect
, buf
, header_offset
, header_size
, *data_offset
);
357 require_noerr(rval
, finish
);
359 rval
= export_macho(sect
, buf
, *data_offset
, data_size
);
360 require_noerr(rval
, finish
);
362 *data_offset
+= (u_long
) sect
->size
;
370 /*******************************************************************************
371 *******************************************************************************/
373 kxld_sect_export_macho_to_vm(const KXLDSect
*sect
,
375 u_long
*header_offset
,
377 kxld_addr_t link_addr
,
379 boolean_t is_32_bit __unused
)
381 kern_return_t rval
= KERN_FAILURE
;
386 check(header_offset
);
388 data_offset
= (u_long
) (sect
->link_addr
- link_addr
);
390 KXLD_3264_FUNC(is_32_bit
, rval
,
391 sect_export_macho_header_32
, sect_export_macho_header_64
,
392 sect
, buf
, header_offset
, header_size
, data_offset
);
393 require_noerr(rval
, finish
);
395 rval
= export_macho(sect
, buf
, data_offset
, data_size
);
396 require_noerr(rval
, finish
);
404 /*******************************************************************************
405 *******************************************************************************/
407 export_macho(const KXLDSect
*sect
, u_char
*buf
, u_long offset
, u_long bufsize
)
409 kern_return_t rval
= KERN_FAILURE
;
420 /* Verify that the section is properly aligned */
421 if (kxld_sect_align_address(sect
, offset
) != offset
) {
422 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogMalformedMachO
423 "Alignment error: %llu != %lu for %s %s <%s>",
424 kxld_sect_align_address(sect
, offset
), offset
,
425 sect
->segname
, sect
->sectname
, __func__
);
430 /* Verify that we have enough space to copy */
431 if (buf
+ offset
+ sect
->size
> buf
+ bufsize
) {
432 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogMalformedMachO
433 "Overflow: offset %lu + sect->size %llu > bufsize %lu for %s %s",
434 offset
, sect
->size
, bufsize
,
435 sect
->segname
, sect
->sectname
);
439 /* Copy section data */
440 switch (sect
->flags
& SECTION_TYPE
) {
441 case S_NON_LAZY_SYMBOL_POINTERS
:
442 case S_MOD_INIT_FUNC_POINTERS
:
443 case S_MOD_TERM_FUNC_POINTERS
:
445 case S_CSTRING_LITERALS
:
446 case S_4BYTE_LITERALS
:
447 case S_8BYTE_LITERALS
:
448 case S_LITERAL_POINTERS
:
450 case S_16BYTE_LITERALS
:
452 #if SPLIT_KEXTS_DEBUG
453 kxld_log(kKxldLogLinking
, kKxldLogErr
,
454 " sectname %s copy from %p (sect->data) for %llu bytes (sect->size) to %p (buf %p + offset %lu <%s>",
455 sect
->sectname
[0] ? sect
->sectname
: "none",
458 (void *) (buf
+ offset
),
463 kxld_log(kKxldLogLinking
, kKxldLogErr
,
464 " %p >>> Start of %s section data (sect->size %llu) <%s>",
465 (void *) (buf
+ offset
),
466 sect
->sectname
[0] ? sect
->sectname
: "none",
469 kxld_log(kKxldLogLinking
, kKxldLogErr
,
470 " %p <<< End of %s section data <%s>",
471 (void *) (buf
+ offset
+ sect
->size
),
472 sect
->sectname
[0] ? sect
->sectname
: "none",
475 memcpy(buf
+ offset
, sect
->data
, (size_t)sect
->size
);
477 case S_ZEROFILL
: /* sect->data should be NULL, so we'll never get here */
478 case S_LAZY_SYMBOL_POINTERS
:
484 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogMalformedMachO
485 "Invalid section type: %u.", sect
->flags
& SECTION_TYPE
);
495 #if KXLD_USER_OR_ILP32
496 /*******************************************************************************
497 *******************************************************************************/
499 sect_export_macho_header_32(const KXLDSect
*sect
, u_char
*buf
,
500 u_long
*header_offset
, u_long header_size
, u_long data_offset
)
502 kern_return_t rval
= KERN_FAILURE
;
503 struct section
*secthdr
= NULL
;
507 check(header_offset
);
509 require_action(sizeof(*secthdr
) <= header_size
- *header_offset
, finish
,
510 rval
= KERN_FAILURE
);
511 secthdr
= (struct section
*) ((void *) (buf
+ *header_offset
));
512 *header_offset
+= sizeof(*secthdr
);
514 /* Initalize header */
516 strlcpy(secthdr
->sectname
, sect
->sectname
, sizeof(secthdr
->sectname
));
517 strlcpy(secthdr
->segname
, sect
->segname
, sizeof(secthdr
->segname
));
518 secthdr
->addr
= (uint32_t) sect
->link_addr
;
519 secthdr
->size
= (uint32_t) sect
->size
;
520 secthdr
->offset
= (uint32_t) ((sect
->data
) ? data_offset
: 0);
521 secthdr
->align
= sect
->align
;
524 secthdr
->flags
= sect
->flags
;
525 secthdr
->reserved1
= sect
->reserved1
;
526 secthdr
->reserved2
= sect
->reserved2
;
528 #if SPLIT_KEXTS_DEBUG
530 kxld_log(kKxldLogLinking
, kKxldLogErr
,
531 "sectname %s secthdr: %p addr %p size %02X %u offset %02X %u <%s>",
532 sect
->sectname
[0] ? sect
->sectname
: "none",
534 (void *) ((uint64_t)secthdr
->addr
),
548 #endif /* KXLD_USER_OR_ILP32 */
550 #if KXLD_USER_OR_LP64
551 /*******************************************************************************
552 *******************************************************************************/
554 sect_export_macho_header_64(const KXLDSect
*sect
, u_char
*buf
,
555 u_long
*header_offset
, u_long header_size
, u_long data_offset
)
557 kern_return_t rval
= KERN_FAILURE
;
558 struct section_64
*secthdr
= NULL
;
562 check(header_offset
);
565 require_action(sizeof(*secthdr
) <= header_size
- *header_offset
, finish
,
566 rval
= KERN_FAILURE
);
567 secthdr
= (struct section_64
*) ((void *) (buf
+ *header_offset
));
568 *header_offset
+= sizeof(*secthdr
);
570 /* Initalize header */
572 strlcpy(secthdr
->sectname
, sect
->sectname
, sizeof(secthdr
->sectname
));
573 strlcpy(secthdr
->segname
, sect
->segname
, sizeof(secthdr
->segname
));
574 secthdr
->addr
= (uint64_t) sect
->link_addr
;
575 secthdr
->size
= (uint64_t) sect
->size
;
576 secthdr
->offset
= (uint32_t) ((sect
->data
) ? data_offset
: 0);
577 secthdr
->align
= sect
->align
;
580 secthdr
->flags
= sect
->flags
;
581 secthdr
->reserved1
= sect
->reserved1
;
582 secthdr
->reserved2
= sect
->reserved2
;
584 #if SPLIT_KEXTS_DEBUG
585 kxld_log(kKxldLogLinking
, kKxldLogErr
,
586 " %p >>> Start of %s secthdr (size %lu) <%s>",
588 sect
->sectname
[0] ? sect
->sectname
: "none",
591 kxld_log(kKxldLogLinking
, kKxldLogErr
,
592 " %p <<< End of %s secthdr <%s>",
593 (void *) ((u_char
*)secthdr
+ sizeof(*secthdr
)),
594 sect
->sectname
[0] ? sect
->sectname
: "none",
596 kxld_log(kKxldLogLinking
, kKxldLogErr
,
597 " secthdr: addr %p size %llu offset %u sectname %s <%s>",
598 (void *) secthdr
->addr
,
601 sect
->sectname
[0] ? sect
->sectname
: "none",
610 #endif /* KXLD_USER_OR_LP64 */
612 #if KXLD_USER_OR_COMMON
613 /*******************************************************************************
614 *******************************************************************************/
616 kxld_sect_grow(KXLDSect
*sect
, kxld_size_t nbytes
, u_int align
)
618 kxld_size_t size
= kxld_align_address(sect
->size
, align
);
620 if (align
> sect
->align
) {
623 sect
->size
= size
+ nbytes
;
627 #endif /* KXLD_USER_OR_COMMON */
629 /*******************************************************************************
630 *******************************************************************************/
632 kxld_sect_relocate(KXLDSect
*sect
, kxld_addr_t link_addr
)
634 #if SPLIT_KEXTS_DEBUG
636 kxld_log(kKxldLogLinking
, kKxldLogErr
,
637 "%p >>> Start of %s section (sect->size %llu) <%s>",
638 (void *) (kxld_sect_align_address(sect
, sect
->link_addr
+ link_addr
)),
639 sect
->sectname
[0] ? sect
->sectname
: "none",
642 kxld_log(kKxldLogLinking
, kKxldLogErr
,
643 "%p <<< End of %s section <%s>",
644 (void *) (kxld_sect_align_address(sect
, sect
->link_addr
+ link_addr
) + sect
->size
),
645 sect
->sectname
[0] ? sect
->sectname
: "none",
650 sect
->link_addr
= kxld_sect_align_address(sect
,
651 sect
->link_addr
+ link_addr
);
655 /*******************************************************************************
656 *******************************************************************************/
658 kxld_sect_populate_got(KXLDSect
*sect
, KXLDSymtab
*symtab
,
659 boolean_t swap __unused
)
661 kern_return_t rval
= KERN_FAILURE
;
662 KXLDSymtabIterator iter
;
664 kxld_addr_t
*entry
= NULL
;
665 kxld_addr_t entry_addr
= 0;
669 require(streq_safe(sect
->segname
, KXLD_SEG_GOT
, sizeof(KXLD_SEG_GOT
)),
671 require(streq_safe(sect
->sectname
, KXLD_SECT_GOT
, sizeof(KXLD_SECT_GOT
)),
674 kxld_symtab_iterator_init(&iter
, symtab
, kxld_sym_is_got
, FALSE
);
676 entry
= (kxld_addr_t
*) sect
->data
;
677 entry_addr
= sect
->link_addr
;
678 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
679 *entry
= sym
->link_addr
;
680 sym
->got_addr
= entry_addr
;
684 *entry
= OSSwapInt64(*entry
);
689 entry_addr
+= sizeof(*entry
);
697 #endif /* KXLD_USER_OR_GOT */
699 /*******************************************************************************
700 *******************************************************************************/
702 kxld_sect_process_relocs(KXLDSect
*sect
, KXLDRelocator
*relocator
)
704 kern_return_t rval
= KERN_FAILURE
;
705 KXLDReloc
*reloc
= NULL
;
708 for (i
= 0; i
< sect
->relocs
.nitems
; ++i
) {
709 reloc
= kxld_array_get_item(§
->relocs
, i
);
710 rval
= kxld_relocator_process_sect_reloc(relocator
, reloc
, sect
);
711 require_noerr(rval
, finish
);