2 * Copyright (c) 2007-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@
30 #include <mach-o/loader.h>
31 #include <mach-o/nlist.h>
32 #include <mach-o/reloc.h>
34 #include <kern/kalloc.h>
35 #include <libkern/libkern.h>
36 #include <mach/vm_param.h>
37 #include <vm/vm_kern.h>
41 #include <mach/mach_init.h>
42 #include <mach-o/swap.h>
45 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
46 #include <AssertMacros.h>
48 #include "kxld_util.h"
51 static void unswap_macho_32(u_char
*file
, enum NXByteOrder host_order
,
52 enum NXByteOrder target_order
);
53 static void unswap_macho_64(u_char
*file
, enum NXByteOrder host_order
,
54 enum NXByteOrder target_order
);
58 static unsigned long num_allocations
= 0;
59 static unsigned long num_frees
= 0;
60 static unsigned long bytes_allocated
= 0;
61 static unsigned long bytes_freed
= 0;
64 static KXLDLoggingCallback s_logging_callback
= NULL
;
65 static const char *s_callback_name
= NULL
;
66 static void *s_callback_data
= NULL
;
68 /*******************************************************************************
69 *******************************************************************************/
71 kxld_set_logging_callback(KXLDLoggingCallback logging_callback
)
73 s_logging_callback
= logging_callback
;
76 /*******************************************************************************
77 *******************************************************************************/
79 kxld_set_logging_callback_data(const char *name
, void *user_data
)
81 s_callback_name
= name
;
82 s_callback_data
= user_data
;
85 /*******************************************************************************
86 *******************************************************************************/
88 kxld_log(KXLDLogSubsystem subsystem
, KXLDLogLevel level
,
89 const char *in_format
, ...)
91 char stack_buffer
[256];
92 char *alloc_buffer
= NULL
;
93 char *format
= stack_buffer
;
94 const char *name
= (s_callback_name
) ? s_callback_name
: "internal";
98 if (s_logging_callback
) {
100 length
= snprintf(stack_buffer
, sizeof(stack_buffer
), "kxld[%s]: %s",
103 if (length
>= sizeof(stack_buffer
)) {
105 alloc_buffer
= kxld_alloc(length
);
106 if (!alloc_buffer
) return;
108 snprintf(alloc_buffer
, length
, "kxld[%s]: %s",
110 format
= alloc_buffer
;
113 va_start(ap
, in_format
);
114 s_logging_callback(subsystem
, level
, format
, ap
, s_callback_data
);
118 kxld_free(alloc_buffer
, length
);
123 /* We'll use kalloc for any page-based allocations under this threshold, and
124 * kmem_alloc otherwise.
126 #define KALLOC_MAX 16 * 1024
128 /*******************************************************************************
129 *******************************************************************************/
131 kxld_alloc(size_t size
)
144 bytes_allocated
+= size
;
151 /*******************************************************************************
152 *******************************************************************************/
154 kxld_page_alloc_untracked(size_t size
)
158 kern_return_t rval
= 0;
159 vm_offset_t addr
= 0;
162 size
= round_page(size
);
165 if (size
< KALLOC_MAX
) {
168 rval
= kmem_alloc(kernel_map
, &addr
, size
);
169 if (!rval
) ptr
= (void *) addr
;
178 /*******************************************************************************
179 *******************************************************************************/
181 kxld_page_alloc(size_t size
)
185 ptr
= kxld_page_alloc_untracked(size
);
189 bytes_allocated
+= round_page(size
);
196 /*******************************************************************************
197 *******************************************************************************/
199 kxld_alloc_pageable(size_t size
)
201 size
= round_page(size
);
204 kern_return_t rval
= 0;
207 rval
= kmem_alloc_pageable(kernel_map
, &ptr
, size
);
212 return kxld_page_alloc_untracked(size
);
216 /*******************************************************************************
217 *******************************************************************************/
219 kxld_free(void *ptr
, size_t size __unused
)
233 /*******************************************************************************
234 *******************************************************************************/
236 kxld_page_free_untracked(void *ptr
, size_t size __unused
)
239 size
= round_page(size
);
241 if (size
< KALLOC_MAX
) {
244 kmem_free(kernel_map
, (vm_offset_t
) ptr
, size
);
252 /*******************************************************************************
253 *******************************************************************************/
255 kxld_page_free(void *ptr
, size_t size
)
259 bytes_freed
+= round_page(size
);
261 kxld_page_free_untracked(ptr
, size
);
264 /*******************************************************************************
265 *******************************************************************************/
267 validate_and_swap_macho_32(u_char
*file
, u_long size
269 , enum NXByteOrder host_order
273 kern_return_t rval
= KERN_FAILURE
;
274 struct mach_header
*mach_hdr
= (struct mach_header
*) ((void *) file
);
275 struct load_command
*load_hdr
= NULL
;
276 struct segment_command
*seg_hdr
= NULL
;
277 struct section
*sects
= NULL
;
278 struct relocation_info
*relocs
= NULL
;
279 struct symtab_command
*symtab_hdr
= NULL
;
280 struct nlist
*symtab
= NULL
;
287 boolean_t swap
= FALSE
;
293 /* Verify that the file is big enough for the mach header */
294 require_action(size
>= sizeof(*mach_hdr
), finish
,
296 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
297 offset
= sizeof(*mach_hdr
);
300 /* Swap the mach header if necessary */
301 if (mach_hdr
->magic
== MH_CIGAM
) {
303 (void) swap_mach_header(mach_hdr
, host_order
);
307 /* Validate the mach_header's magic number */
308 require_action(mach_hdr
->magic
== MH_MAGIC
, finish
,
310 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogMalformedMachO
311 "Invalid magic number: 0x%x.", mach_hdr
->magic
));
313 /* If in the running kernel, and asked to validate the kernel
314 * (which is the only file of type MH_EXECUTE we should ever see),
315 * then just assume it's ok or we wouldn't be running to begin with.
318 if (mach_hdr
->filetype
== MH_EXECUTE
) {
324 /* Validate and potentially swap the load commands */
325 for(i
= 0; i
< mach_hdr
->ncmds
; ++i
, offset
+= cmdsize
) {
327 /* Get the load command and size */
328 load_hdr
= (struct load_command
*) ((void *) (file
+ offset
));
330 cmdsize
= load_hdr
->cmdsize
;
334 cmd
= OSSwapInt32(load_hdr
->cmd
);
335 cmdsize
= OSSwapInt32(load_hdr
->cmdsize
);
339 /* Verify that the file is big enough to contain the load command */
340 require_action(size
>= offset
+ cmdsize
, finish
,
342 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
346 /* Get and swap the segment header */
347 seg_hdr
= (struct segment_command
*) load_hdr
;
349 if (swap
) swap_segment_command(seg_hdr
, host_order
);
352 /* Get and swap the section headers */
353 sects
= (struct section
*) &seg_hdr
[1];
355 if (swap
) swap_section(sects
, seg_hdr
->nsects
, host_order
);
358 /* Ignore segments with no vm size */
359 if (!seg_hdr
->vmsize
) continue;
361 /* Verify that the file is big enough for the segment data. */
362 require_action(size
>= seg_hdr
->fileoff
+ seg_hdr
->filesize
, finish
,
364 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
366 for (j
= 0; j
< seg_hdr
->nsects
; ++j
) {
368 /* Verify that, if the section is not to be zero filled on
369 * demand, that file is big enough for the section's data.
371 require_action((sects
[j
].flags
& S_ZEROFILL
) ||
372 (size
>= sects
[j
].offset
+ sects
[j
].size
), finish
,
374 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
376 /* Verify that the file is big enough for the section's
377 * relocation entries.
379 require_action(size
>=
380 sects
[j
].reloff
+ sects
[j
].nreloc
* sizeof(*relocs
), finish
,
382 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
384 /* Swap the relocation entries */
385 relocs
= (struct relocation_info
*) ((void *) (file
+ sects
[j
].reloff
));
388 swap_relocation_info(relocs
, sects
[j
].nreloc
,
396 /* Get and swap the symtab header */
397 symtab_hdr
= (struct symtab_command
*) load_hdr
;
399 if (swap
) swap_symtab_command(symtab_hdr
, host_order
);
402 /* Verify that the file is big enough for the symbol table */
403 require_action(size
>=
404 symtab_hdr
->symoff
+ symtab_hdr
->nsyms
* sizeof(*symtab
), finish
,
406 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
408 /* Verify that the file is big enough for the string table */
409 require_action(size
>= symtab_hdr
->stroff
+ symtab_hdr
->strsize
, finish
,
411 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
414 /* Swap the symbol table entries */
415 symtab
= (struct nlist
*) ((void *) (file
+ symtab_hdr
->symoff
));
416 if (swap
) swap_nlist(symtab
, symtab_hdr
->nsyms
, host_order
);
422 /* Swap the load command */
423 if (swap
) swap_load_command(load_hdr
, host_order
);
435 /*******************************************************************************
436 *******************************************************************************/
438 validate_and_swap_macho_64(u_char
*file
, u_long size
440 , enum NXByteOrder host_order
444 kern_return_t rval
= KERN_FAILURE
;
445 struct mach_header_64
*mach_hdr
= (struct mach_header_64
*) ((void *) file
);
446 struct load_command
*load_hdr
= NULL
;
447 struct segment_command_64
*seg_hdr
= NULL
;
448 struct section_64
*sects
= NULL
;
449 struct relocation_info
*relocs
= NULL
;
450 struct symtab_command
*symtab_hdr
= NULL
;
451 struct nlist_64
*symtab
= NULL
;
458 boolean_t swap
= FALSE
;
464 /* Verify that the file is big enough for the mach header */
465 require_action(size
>= sizeof(*mach_hdr
), finish
,
467 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
468 offset
= sizeof(*mach_hdr
);
471 /* Swap the mach header if necessary */
472 if (mach_hdr
->magic
== MH_CIGAM_64
) {
474 (void) swap_mach_header_64(mach_hdr
, host_order
);
478 /* Validate the mach_header's magic number */
479 require_action(mach_hdr
->magic
== MH_MAGIC_64
, finish
,
481 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogMalformedMachO
482 "Invalid magic number: 0x%x.", mach_hdr
->magic
));
484 /* If in the running kernel, and asked to validate the kernel
485 * (which is the only file of type MH_EXECUTE we should ever see),
486 * then just assume it's ok or we wouldn't be running to begin with.
489 if (mach_hdr
->filetype
== MH_EXECUTE
) {
495 /* Validate and potentially swap the load commands */
496 for(i
= 0; i
< mach_hdr
->ncmds
; ++i
, offset
+= cmdsize
) {
497 /* Get the load command and size */
498 load_hdr
= (struct load_command
*) ((void *) (file
+ offset
));
500 cmdsize
= load_hdr
->cmdsize
;
504 cmd
= OSSwapInt32(load_hdr
->cmd
);
505 cmdsize
= OSSwapInt32(load_hdr
->cmdsize
);
509 /* Verify that the file is big enough to contain the load command */
510 require_action(size
>= offset
+ cmdsize
, finish
,
512 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
515 /* Get and swap the segment header */
516 seg_hdr
= (struct segment_command_64
*) ((void *) load_hdr
);
518 if (swap
) swap_segment_command_64(seg_hdr
, host_order
);
521 /* Get and swap the section headers */
522 sects
= (struct section_64
*) &seg_hdr
[1];
524 if (swap
) swap_section_64(sects
, seg_hdr
->nsects
, host_order
);
527 /* If the segment has no vm footprint, skip it */
528 if (!seg_hdr
->vmsize
) continue;
530 /* Verify that the file is big enough for the segment data. */
531 require_action(size
>= seg_hdr
->fileoff
+ seg_hdr
->filesize
, finish
,
533 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
535 for (j
= 0; j
< seg_hdr
->nsects
; ++j
) {
537 /* Verify that, if the section is not to be zero filled on
538 * demand, that file is big enough for the section's data.
540 require_action((sects
[j
].flags
& S_ZEROFILL
) ||
541 (size
>= sects
[j
].offset
+ sects
[j
].size
), finish
,
543 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
545 /* Verify that the file is big enough for the section's
546 * relocation entries.
548 require_action(size
>=
549 sects
[j
].reloff
+ sects
[j
].nreloc
* sizeof(*relocs
), finish
,
551 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
553 /* Swap the relocation entries */
554 relocs
= (struct relocation_info
*) ((void *) (file
+ sects
[j
].reloff
));
557 swap_relocation_info(relocs
, sects
[j
].nreloc
,
565 /* Get and swap the symtab header */
566 symtab_hdr
= (struct symtab_command
*) load_hdr
;
568 if (swap
) swap_symtab_command(symtab_hdr
, host_order
);
571 /* Verify that the file is big enough for the symbol table */
572 require_action(size
>=
573 symtab_hdr
->symoff
+ symtab_hdr
->nsyms
* sizeof(*symtab
), finish
,
575 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
577 /* Verify that the file is big enough for the string table */
578 require_action(size
>= symtab_hdr
->stroff
+ symtab_hdr
->strsize
, finish
,
580 kxld_log(kKxldLogLinking
, kKxldLogErr
, kKxldLogTruncatedMachO
));
583 /* Swap the symbol table entries */
584 symtab
= (struct nlist_64
*) ((void *) (file
+ symtab_hdr
->symoff
));
585 if (swap
) swap_nlist_64(symtab
, symtab_hdr
->nsyms
, host_order
);
591 /* Swap the load command */
592 if (swap
) swap_load_command(load_hdr
, host_order
);
605 /*******************************************************************************
606 *******************************************************************************/
607 void unswap_macho(u_char
*file
, enum NXByteOrder host_order
,
608 enum NXByteOrder target_order
)
610 struct mach_header
*hdr
= (struct mach_header
*) ((void *) file
);
614 if (hdr
->magic
== MH_MAGIC
) {
615 unswap_macho_32(file
, host_order
, target_order
);
616 } else if (hdr
->magic
== MH_MAGIC_64
) {
617 unswap_macho_64(file
, host_order
, target_order
);
621 /*******************************************************************************
622 *******************************************************************************/
624 unswap_macho_32(u_char
*file
, enum NXByteOrder host_order
,
625 enum NXByteOrder target_order
)
627 struct mach_header
*mach_hdr
= (struct mach_header
*) ((void *) file
);
628 struct load_command
*load_hdr
= NULL
;
629 struct segment_command
*seg_hdr
= NULL
;
630 struct section
*sects
= NULL
;
631 struct symtab_command
*symtab_hdr
= NULL
;
632 struct nlist
*symtab
= NULL
;
640 if (target_order
== host_order
) return;
642 offset
= sizeof(*mach_hdr
);
643 for(i
= 0; i
< mach_hdr
->ncmds
; ++i
, offset
+= size
) {
644 load_hdr
= (struct load_command
*) ((void *) (file
+ offset
));
646 size
= load_hdr
->cmdsize
;
650 seg_hdr
= (struct segment_command
*) load_hdr
;
651 sects
= (struct section
*) &seg_hdr
[1];
653 /* We don't need to unswap relocations because this function is
654 * called when linking is completed (so there are no relocations).
657 swap_section(sects
, seg_hdr
->nsects
, target_order
);
658 swap_segment_command(seg_hdr
, target_order
);
661 symtab_hdr
= (struct symtab_command
*) load_hdr
;
662 symtab
= (struct nlist
*) ((void *) (file
+ symtab_hdr
->symoff
));
664 swap_nlist(symtab
, symtab_hdr
->nsyms
, target_order
);
665 swap_symtab_command(symtab_hdr
, target_order
);
669 swap_load_command(load_hdr
, target_order
);
674 (void) swap_mach_header(mach_hdr
, target_order
);
677 /*******************************************************************************
678 *******************************************************************************/
680 unswap_macho_64(u_char
*file
, enum NXByteOrder host_order
,
681 enum NXByteOrder target_order
)
683 struct mach_header_64
*mach_hdr
= (struct mach_header_64
*) ((void *) file
);
684 struct load_command
*load_hdr
= NULL
;
685 struct segment_command_64
*seg_hdr
= NULL
;
686 struct section_64
*sects
= NULL
;
687 struct symtab_command
*symtab_hdr
= NULL
;
688 struct nlist_64
*symtab
= NULL
;
696 if (target_order
== host_order
) return;
698 offset
= sizeof(*mach_hdr
);
699 for(i
= 0; i
< mach_hdr
->ncmds
; ++i
, offset
+= size
) {
700 load_hdr
= (struct load_command
*) ((void *) (file
+ offset
));
702 size
= load_hdr
->cmdsize
;
706 seg_hdr
= (struct segment_command_64
*) ((void *) load_hdr
);
707 sects
= (struct section_64
*) &seg_hdr
[1];
709 /* We don't need to unswap relocations because this function is
710 * called when linking is completed (so there are no relocations).
713 swap_section_64(sects
, seg_hdr
->nsects
, target_order
);
714 swap_segment_command_64(seg_hdr
, target_order
);
717 symtab_hdr
= (struct symtab_command
*) load_hdr
;
718 symtab
= (struct nlist_64
*) ((void *) (file
+ symtab_hdr
->symoff
));
720 swap_nlist_64(symtab
, symtab_hdr
->nsyms
, target_order
);
721 swap_symtab_command(symtab_hdr
, target_order
);
725 swap_load_command(load_hdr
, target_order
);
730 (void) swap_mach_header_64(mach_hdr
, target_order
);
734 /*******************************************************************************
735 *******************************************************************************/
737 kxld_align_address(kxld_addr_t address
, u_int align
)
739 kxld_addr_t alignment
= (1 << align
);
740 kxld_addr_t low_bits
= 0;
742 if (!align
) return address
;
744 low_bits
= (address
) & (alignment
- 1);
746 address
+= (alignment
- low_bits
);
752 /*******************************************************************************
753 *******************************************************************************/
755 kxld_is_32_bit(cpu_type_t cputype
)
757 return !(cputype
& CPU_ARCH_ABI64
);
760 /*******************************************************************************
761 * Borrowed (and slightly modified) the libc implementation for the kernel
762 * until the kernel has a supported strstr().
763 * Find the first occurrence of find in s.
764 *******************************************************************************/
767 const char *s
, *find
;
773 if ((c
= *find
++) != 0) {
777 if ((sc
= *s
++) == 0)
780 } while (strncmp(s
, find
, len
) != 0);
785 return strstr(s
, find
);
789 /*******************************************************************************
790 *******************************************************************************/
792 kxld_print_memory_report(void)
795 kxld_log(kKxldLogLinking
, kKxldLogExplicit
, "kxld memory usage report:\n"
796 "\tNumber of allocations: %8lu\n"
797 "\tNumber of frees: %8lu\n"
798 "\tAverage allocation size: %8lu\n"
799 "\tTotal bytes allocated: %8lu\n"
800 "\tTotal bytes freed: %8lu\n"
801 "\tTotal bytes leaked: %8lu",
802 num_allocations
, num_frees
, bytes_allocated
/ num_allocations
,
803 bytes_allocated
, bytes_freed
, bytes_allocated
- bytes_freed
);