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
);
96 if (rval
) kxld_sect_deinit(sect
);
100 #endif /* KXLD_USER_OR_ILP32 */
102 #if KXLD_USER_OR_LP64
103 /*******************************************************************************
104 *******************************************************************************/
106 kxld_sect_init_from_macho_64(KXLDSect
*sect
, u_char
*macho
, u_long
*sect_offset
,
107 u_int sectnum
, const KXLDRelocator
*relocator
)
109 kern_return_t rval
= KERN_FAILURE
;
110 struct section_64
*src
= (struct section_64
*) ((void *) (macho
+ *sect_offset
));
111 struct relocation_info
*relocs
= NULL
;
117 strlcpy(sect
->segname
, src
->segname
, sizeof(sect
->segname
));
118 strlcpy(sect
->sectname
, src
->sectname
, sizeof(sect
->sectname
));
119 sect
->base_addr
= src
->addr
;
120 sect
->link_addr
= src
->addr
;
121 sect
->size
= src
->size
;
122 sect
->sectnum
= sectnum
;
123 sect
->flags
= src
->flags
;
124 sect
->align
= src
->align
;
125 sect
->reserved1
= src
->reserved1
;
126 sect
->reserved2
= src
->reserved2
;
129 sect
->data
= macho
+ src
->offset
;
134 relocs
= (struct relocation_info
*) ((void *) (macho
+ src
->reloff
));
136 rval
= kxld_reloc_create_macho(§
->relocs
, relocator
,
137 relocs
, src
->nreloc
);
138 require_noerr(rval
, finish
);
140 *sect_offset
+= sizeof(*src
);
144 if (rval
) kxld_sect_deinit(sect
);
148 #endif /* KXLD_USER_OR_LP64 */
151 /*******************************************************************************
152 * Assumes GOT is comprised of kxld_addr_t entries
153 *******************************************************************************/
155 kxld_sect_init_got(KXLDSect
*sect
, u_int ngots
)
157 kern_return_t rval
= KERN_FAILURE
;
161 strlcpy(sect
->segname
, KXLD_SEG_GOT
, sizeof(sect
->segname
));
162 strlcpy(sect
->sectname
, KXLD_SECT_GOT
, sizeof(sect
->sectname
));
170 sect
->size
= ngots
* sizeof(kxld_addr_t
);
171 sect
->data
= kxld_alloc((u_long
) sect
->size
);
172 require_action(sect
->data
, finish
, rval
=KERN_RESOURCE_SHORTAGE
);
174 sect
->allocated
= TRUE
;
181 #endif /* KXLD_USER_OR_GOT */
183 #if KXLD_USER_OR_COMMON
184 /*******************************************************************************
185 *******************************************************************************/
187 kxld_sect_init_zerofill(KXLDSect
*sect
, const char *segname
,
188 const char *sectname
, kxld_size_t size
, u_int align
)
194 strlcpy(sect
->segname
, segname
, sizeof(sect
->segname
));
195 strlcpy(sect
->sectname
, sectname
, sizeof(sect
->sectname
));
200 sect
->flags
= S_ZEROFILL
;
202 #endif /* KXLD_USER_OR_COMMON */
204 /*******************************************************************************
205 *******************************************************************************/
207 kxld_sect_clear(KXLDSect
*sect
)
211 if (sect
->allocated
) {
212 kxld_free(sect
->data
, (u_long
) sect
->size
);
213 sect
->allocated
= FALSE
;
216 bzero(sect
->sectname
, sizeof(sect
->sectname
));
217 bzero(sect
->segname
, sizeof(sect
->segname
));
226 kxld_array_clear(§
->relocs
);
229 /*******************************************************************************
230 *******************************************************************************/
232 kxld_sect_deinit(KXLDSect
*sect
)
236 if (streq_safe(sect
->sectname
, KXLD_SECT_GOT
, sizeof(KXLD_SECT_GOT
))) {
237 kxld_free(sect
->data
, (u_long
) sect
->size
);
240 kxld_array_deinit(§
->relocs
);
241 bzero(sect
, sizeof(*sect
));
244 /*******************************************************************************
245 *******************************************************************************/
247 kxld_sect_get_num_relocs(const KXLDSect
*sect
)
251 return sect
->relocs
.nitems
;
254 /*******************************************************************************
255 *******************************************************************************/
257 kxld_sect_get_macho_header_size(boolean_t is_32_bit
)
260 return sizeof(struct section
);
262 return sizeof(struct section_64
);
266 /*******************************************************************************
267 *******************************************************************************/
269 kxld_sect_get_macho_data_size(const KXLDSect
*sect
)
276 size
= (u_long
) sect
->size
;
283 /*******************************************************************************
284 *******************************************************************************/
286 kxld_sect_get_ngots(const KXLDSect
*sect
, const KXLDRelocator
*relocator
,
287 const KXLDSymtab
*symtab
)
289 const KXLDReloc
*reloc
= NULL
;
294 for (i
= 0; i
< sect
->relocs
.nitems
; ++i
) {
295 reloc
= kxld_array_get_item(§
->relocs
, i
);
297 if (relocator
->reloc_has_got(reloc
->reloc_type
)) {
298 /* @TODO This assumes 64-bit symbols (which is valid at the
299 * moment since only x86_64 has a GOT)
301 sym
= kxld_reloc_get_symbol(relocator
, reloc
, sect
->data
, symtab
);
302 if (!kxld_sym_is_got(sym
)) {
303 kxld_sym_set_got(sym
);
311 #endif /* KXLD_USER_OR_GOT */
313 /*******************************************************************************
314 * Each section must be aligned at a certain power of two. To figure out that
315 * alignment, we mask for the low bits that may need to be adjusted. If they are
316 * non zero, we then subtract them from the target alignment to find the offset,
317 * and then add that offset to the link address.
318 *******************************************************************************/
320 kxld_sect_align_address(const KXLDSect
*sect
, kxld_addr_t address
)
322 return kxld_align_address(address
, sect
->align
);
325 /*******************************************************************************
326 *******************************************************************************/
328 kxld_sect_export_macho_to_file_buffer(const KXLDSect
*sect
, u_char
*buf
,
329 u_long
*header_offset
, u_long header_size
, u_long
*data_offset
,
330 u_long data_size
, boolean_t is_32_bit __unused
)
332 kern_return_t rval
= KERN_FAILURE
;
336 check(header_offset
);
339 /* If there is no data to export, we only need to write the header. We
340 * make it a separate call so that we don't modify data_offset.
343 KXLD_3264_FUNC(is_32_bit
, rval
,
344 sect_export_macho_header_32
, sect_export_macho_header_64
,
345 sect
, buf
, header_offset
, header_size
, /* data_offset */ 0);
346 require_noerr(rval
, finish
);
348 *data_offset
= (u_long
) kxld_sect_align_address(sect
, *data_offset
);
350 KXLD_3264_FUNC(is_32_bit
, rval
,
351 sect_export_macho_header_32
, sect_export_macho_header_64
,
352 sect
, buf
, header_offset
, header_size
, *data_offset
);
353 require_noerr(rval
, finish
);
355 rval
= export_macho(sect
, buf
, *data_offset
, data_size
);
356 require_noerr(rval
, finish
);
358 *data_offset
+= (u_long
) sect
->size
;
366 /*******************************************************************************
367 *******************************************************************************/
369 kxld_sect_export_macho_to_vm(const KXLDSect
*sect
,
371 u_long
*header_offset
,
373 kxld_addr_t link_addr
,
375 boolean_t is_32_bit __unused
)
377 kern_return_t rval
= KERN_FAILURE
;
382 check(header_offset
);
384 data_offset
= (u_long
) (sect
->link_addr
- link_addr
);
386 KXLD_3264_FUNC(is_32_bit
, rval
,
387 sect_export_macho_header_32
, sect_export_macho_header_64
,
388 sect
, buf
, header_offset
, header_size
, data_offset
);
389 require_noerr(rval
, finish
);
391 rval
= export_macho(sect
, buf
, data_offset
, data_size
);
392 require_noerr(rval
, finish
);
400 /*******************************************************************************
401 *******************************************************************************/
403 export_macho(const KXLDSect
*sect
, u_char
*buf
, u_long offset
, u_long bufsize
)
405 kern_return_t rval
= KERN_FAILURE
;
416 /* Verify that the section is properly aligned */
417 if (kxld_sect_align_address(sect
, offset
) != offset
) {
418 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogMalformedMachO
419 "Alignment error: %llu != %lu for %s %s <%s>",
420 kxld_sect_align_address(sect
, offset
), offset
,
421 sect
->segname
, sect
->sectname
, __func__
);
426 /* Verify that we have enough space to copy */
427 if (buf
+ offset
+ sect
->size
> buf
+ bufsize
) {
428 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogMalformedMachO
429 "Overflow: offset %lu + sect->size %llu > bufsize %lu for %s %s",
430 offset
, sect
->size
, bufsize
,
431 sect
->segname
, sect
->sectname
);
435 /* Copy section data */
436 switch (sect
->flags
& SECTION_TYPE
) {
437 case S_NON_LAZY_SYMBOL_POINTERS
:
438 case S_MOD_INIT_FUNC_POINTERS
:
439 case S_MOD_TERM_FUNC_POINTERS
:
441 case S_CSTRING_LITERALS
:
442 case S_4BYTE_LITERALS
:
443 case S_8BYTE_LITERALS
:
444 case S_LITERAL_POINTERS
:
446 case S_16BYTE_LITERALS
:
448 #if SPLIT_KEXTS_DEBUG
449 kxld_log(kKxldLogLinking
, kKxldLogErr
,
450 " sectname %s copy from %p (sect->data) for %llu bytes (sect->size) to %p (buf %p + offset %lu <%s>",
451 sect
->sectname
[0] ? sect
->sectname
: "none",
454 (void *) (buf
+ offset
),
459 kxld_log(kKxldLogLinking
, kKxldLogErr
,
460 " %p >>> Start of %s section data (sect->size %llu) <%s>",
461 (void *) (buf
+ offset
),
462 sect
->sectname
[0] ? sect
->sectname
: "none",
465 kxld_log(kKxldLogLinking
, kKxldLogErr
,
466 " %p <<< End of %s section data <%s>",
467 (void *) (buf
+ offset
+ sect
->size
),
468 sect
->sectname
[0] ? sect
->sectname
: "none",
471 memcpy(buf
+ offset
, sect
->data
, (size_t)sect
->size
);
473 case S_ZEROFILL
: /* sect->data should be NULL, so we'll never get here */
474 case S_LAZY_SYMBOL_POINTERS
:
480 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogMalformedMachO
481 "Invalid section type: %u.", sect
->flags
& SECTION_TYPE
);
491 #if KXLD_USER_OR_ILP32
492 /*******************************************************************************
493 *******************************************************************************/
495 sect_export_macho_header_32(const KXLDSect
*sect
, u_char
*buf
,
496 u_long
*header_offset
, u_long header_size
, u_long data_offset
)
498 kern_return_t rval
= KERN_FAILURE
;
499 struct section
*secthdr
= NULL
;
503 check(header_offset
);
505 require_action(sizeof(*secthdr
) <= header_size
- *header_offset
, finish
,
507 secthdr
= (struct section
*) ((void *) (buf
+ *header_offset
));
508 *header_offset
+= sizeof(*secthdr
);
510 /* Initalize header */
512 strlcpy(secthdr
->sectname
, sect
->sectname
, sizeof(secthdr
->sectname
));
513 strlcpy(secthdr
->segname
, sect
->segname
, sizeof(secthdr
->segname
));
514 secthdr
->addr
= (uint32_t) sect
->link_addr
;
515 secthdr
->size
= (uint32_t) sect
->size
;
516 secthdr
->offset
= (uint32_t) ((sect
->data
) ? data_offset
: 0);
517 secthdr
->align
= sect
->align
;
520 secthdr
->flags
= sect
->flags
;
521 secthdr
->reserved1
= sect
->reserved1
;
522 secthdr
->reserved2
= sect
->reserved2
;
524 #if SPLIT_KEXTS_DEBUG
526 kxld_log(kKxldLogLinking
, kKxldLogErr
,
527 "sectname %s secthdr: %p addr %p size %02X %u offset %02X %u <%s>",
528 sect
->sectname
[0] ? sect
->sectname
: "none",
530 (void *) ((uint64_t)secthdr
->addr
),
544 #endif /* KXLD_USER_OR_ILP32 */
546 #if KXLD_USER_OR_LP64
547 /*******************************************************************************
548 *******************************************************************************/
550 sect_export_macho_header_64(const KXLDSect
*sect
, u_char
*buf
,
551 u_long
*header_offset
, u_long header_size
, u_long data_offset
)
553 kern_return_t rval
= KERN_FAILURE
;
554 struct section_64
*secthdr
= NULL
;
558 check(header_offset
);
561 require_action(sizeof(*secthdr
) <= header_size
- *header_offset
, finish
,
563 secthdr
= (struct section_64
*) ((void *) (buf
+ *header_offset
));
564 *header_offset
+= sizeof(*secthdr
);
566 /* Initalize header */
568 strlcpy(secthdr
->sectname
, sect
->sectname
, sizeof(secthdr
->sectname
));
569 strlcpy(secthdr
->segname
, sect
->segname
, sizeof(secthdr
->segname
));
570 secthdr
->addr
= (uint64_t) sect
->link_addr
;
571 secthdr
->size
= (uint64_t) sect
->size
;
572 secthdr
->offset
= (uint32_t) ((sect
->data
) ? data_offset
: 0);
573 secthdr
->align
= sect
->align
;
576 secthdr
->flags
= sect
->flags
;
577 secthdr
->reserved1
= sect
->reserved1
;
578 secthdr
->reserved2
= sect
->reserved2
;
580 #if SPLIT_KEXTS_DEBUG
581 kxld_log(kKxldLogLinking
, kKxldLogErr
,
582 " %p >>> Start of %s secthdr (size %lu) <%s>",
584 sect
->sectname
[0] ? sect
->sectname
: "none",
587 kxld_log(kKxldLogLinking
, kKxldLogErr
,
588 " %p <<< End of %s secthdr <%s>",
589 (void *) ((u_char
*)secthdr
+ sizeof(*secthdr
)),
590 sect
->sectname
[0] ? sect
->sectname
: "none",
592 kxld_log(kKxldLogLinking
, kKxldLogErr
,
593 " secthdr: addr %p size %llu offset %u sectname %s <%s>",
594 (void *) secthdr
->addr
,
597 sect
->sectname
[0] ? sect
->sectname
: "none",
606 #endif /* KXLD_USER_OR_LP64 */
608 #if KXLD_USER_OR_COMMON
609 /*******************************************************************************
610 *******************************************************************************/
612 kxld_sect_grow(KXLDSect
*sect
, kxld_size_t nbytes
, u_int align
)
614 kxld_size_t size
= kxld_align_address(sect
->size
, align
);
616 if (align
> sect
->align
) sect
->align
= align
;
617 sect
->size
= size
+ nbytes
;
621 #endif /* KXLD_USER_OR_COMMON */
623 /*******************************************************************************
624 *******************************************************************************/
626 kxld_sect_relocate(KXLDSect
*sect
, kxld_addr_t link_addr
)
628 #if SPLIT_KEXTS_DEBUG
630 kxld_log(kKxldLogLinking
, kKxldLogErr
,
631 "%p >>> Start of %s section (sect->size %llu) <%s>",
632 (void *) (kxld_sect_align_address(sect
, sect
->link_addr
+ link_addr
)),
633 sect
->sectname
[0] ? sect
->sectname
: "none",
636 kxld_log(kKxldLogLinking
, kKxldLogErr
,
637 "%p <<< End of %s section <%s>",
638 (void *) (kxld_sect_align_address(sect
, sect
->link_addr
+ link_addr
) + sect
->size
),
639 sect
->sectname
[0] ? sect
->sectname
: "none",
644 sect
->link_addr
= kxld_sect_align_address(sect
,
645 sect
->link_addr
+ link_addr
);
649 /*******************************************************************************
650 *******************************************************************************/
652 kxld_sect_populate_got(KXLDSect
*sect
, KXLDSymtab
*symtab
,
653 boolean_t swap __unused
)
655 kern_return_t rval
= KERN_FAILURE
;
656 KXLDSymtabIterator iter
;
658 kxld_addr_t
*entry
= NULL
;
659 kxld_addr_t entry_addr
= 0;
663 require(streq_safe(sect
->segname
, KXLD_SEG_GOT
, sizeof(KXLD_SEG_GOT
)),
665 require(streq_safe(sect
->sectname
, KXLD_SECT_GOT
, sizeof(KXLD_SECT_GOT
)),
668 kxld_symtab_iterator_init(&iter
, symtab
, kxld_sym_is_got
, FALSE
);
670 entry
= (kxld_addr_t
*) sect
->data
;
671 entry_addr
= sect
->link_addr
;
672 while ((sym
= kxld_symtab_iterator_get_next(&iter
))) {
673 *entry
= sym
->link_addr
;
674 sym
->got_addr
= entry_addr
;
677 if (swap
) *entry
= OSSwapInt64(*entry
);
681 entry_addr
+= sizeof(*entry
);
689 #endif /* KXLD_USER_OR_GOT */
691 /*******************************************************************************
692 *******************************************************************************/
694 kxld_sect_process_relocs(KXLDSect
*sect
, KXLDRelocator
*relocator
)
696 kern_return_t rval
= KERN_FAILURE
;
697 KXLDReloc
*reloc
= NULL
;
700 for (i
= 0; i
< sect
->relocs
.nitems
; ++i
) {
701 reloc
= kxld_array_get_item(§
->relocs
, i
);
702 rval
= kxld_relocator_process_sect_reloc(relocator
, reloc
, sect
);
703 require_noerr(rval
, finish
);