]> git.saurik.com Git - apple/xnu.git/blobdiff - libkern/kxld/kxld_object.c
xnu-6153.11.26.tar.gz
[apple/xnu.git] / libkern / kxld / kxld_object.c
index 36383e41e03a729c98b8cbfde74dd6907346f7b7..f83f0f3213139e353a4673d22a4bf5ea60c5b035 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2009-2014 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -22,7 +22,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 #include <string.h>
@@ -34,9 +34,9 @@
     #include <mach/vm_param.h>
     #include <mach-o/fat.h>
 #else /* !KERNEL */
-    /* Get machine.h from the kernel source so we can support all platforms
    * that the kernel supports. Otherwise we're at the mercy of the host.
    */
+/* Get machine.h from the kernel source so we can support all platforms
+ * that the kernel supports. Otherwise we're at the mercy of the host.
+ */
     #include "../../osfmk/mach/machine.h"
 
     #include <architecture/byte_order.h>
@@ -48,6 +48,7 @@
 #include <mach-o/loader.h>
 #include <mach-o/nlist.h>
 #include <mach-o/reloc.h>
+#include <os/overflow.h>
 
 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
 #include <AssertMacros.h>
 #include "kxld_uuid.h"
 #include "kxld_versionmin.h"
 #include "kxld_vtable.h"
+#include "kxld_splitinfolc.h"
 
 #include "kxld_object.h"
 
+extern boolean_t isSplitKext;
+extern boolean_t isOldInterface;
+
 /*******************************************************************************
 * Data structures
 *******************************************************************************/
 
 struct kxld_object {
-    u_char *file;
-    u_long size;
-    const char *name;
-    uint32_t filetype;
-    cpu_type_t cputype;
-    cpu_subtype_t cpusubtype;
-    KXLDArray segs;
-    KXLDArray sects;
-    KXLDArray extrelocs;
-    KXLDArray locrelocs;
-    KXLDRelocator relocator;
-    KXLDuuid uuid;
-    KXLDversionmin versionmin;
-    KXLDsrcversion srcversion;
-    KXLDSymtab *symtab;
-    struct dysymtab_command *dysymtab_hdr;
-    kxld_addr_t link_addr;
-    u_long    output_buffer_size;
-    boolean_t is_kernel;
-    boolean_t is_final_image;
-    boolean_t is_linked;
-    boolean_t got_is_created;
+       u_char *file;   // used by old interface
+       u_long size;    // used by old interface
+       const char *name;
+       uint32_t filetype;
+       cpu_type_t cputype;
+       cpu_subtype_t cpusubtype;
+       KXLDArray segs;
+       KXLDArray sects;
+       KXLDArray extrelocs;
+       KXLDArray locrelocs;
+       KXLDRelocator relocator;
+       KXLDuuid uuid;
+       KXLDversionmin versionmin;
+       KXLDsrcversion srcversion;
+       KXLDSymtab *symtab;
+       struct dysymtab_command *dysymtab_hdr;
+       KXLDsplitinfolc splitinfolc;
+       splitKextLinkInfo split_info;
+       kxld_addr_t link_addr;
+       u_long    output_buffer_size;
+       boolean_t is_kernel;
+       boolean_t is_final_image;
+       boolean_t is_linked;
+       boolean_t got_is_created;
 #if KXLD_USER_OR_OBJECT
-    KXLDArray *section_order;
+       KXLDArray *section_order;
 #endif
 #if KXLD_PIC_KEXTS
-    boolean_t include_kaslr_relocs;
+       boolean_t include_kaslr_relocs;
 #endif
 #if !KERNEL
-    enum NXByteOrder host_order;
-    enum NXByteOrder target_order;
+       enum NXByteOrder host_order;
+       enum NXByteOrder target_order;
 #endif
 };
 
@@ -109,25 +116,25 @@ struct kxld_object {
 * Prototypes
 *******************************************************************************/
 
-static kern_return_t get_target_machine_info(KXLDObject *object, 
+static kern_return_t get_target_machine_info(KXLDObject *object,
     cpu_type_t cputype, cpu_subtype_t cpusubtype);
-static kern_return_t get_macho_slice_for_arch(KXLDObject *object, 
+static kern_return_t get_macho_slice_for_arch(KXLDObject *object,
     u_char *file, u_long size);
 
 static u_long get_macho_header_size(const KXLDObject *object);
 static u_long get_macho_data_size(const KXLDObject *object) __unused;
 
 static kern_return_t init_from_execute(KXLDObject *object);
-static kern_return_t init_from_final_linked_image(KXLDObject *object, 
+static kern_return_t init_from_final_linked_image(KXLDObject *object,
     u_int *filetype_out, struct symtab_command **symtab_hdr_out);
 
 static boolean_t target_supports_protected_segments(const KXLDObject *object)
-    __attribute__((pure));
+__attribute__((pure));
 static void set_is_object_linked(KXLDObject *object);
 
 #if KXLD_USER_OR_BUNDLE
-static boolean_t target_supports_bundle(const KXLDObject *object) 
-    __attribute((pure));
+static boolean_t target_supports_bundle(const KXLDObject *object)
+__attribute((pure));
 static kern_return_t init_from_bundle(KXLDObject *object);
 static kern_return_t process_relocs_from_tables(KXLDObject *object);
 static KXLDSeg *get_seg_by_base_addr(KXLDObject *object,
@@ -137,8 +144,8 @@ static void add_to_ptr(u_char *symptr, kxld_addr_t val, boolean_t is_32_bit);
 #endif /* KXLD_USER_OR_BUNDLE */
 
 #if KXLD_USER_OR_OBJECT
-static boolean_t target_supports_object(const KXLDObject *object) 
-    __attribute((pure));
+static boolean_t target_supports_object(const KXLDObject *object)
+__attribute((pure));
 static kern_return_t init_from_object(KXLDObject *object);
 static kern_return_t process_relocs_from_sections(KXLDObject *object);
 #endif /* KXLD_USER_OR_OBJECT */
@@ -148,18 +155,18 @@ static boolean_t target_supports_slideable_kexts(const KXLDObject *object);
 #endif  /* KXLD_PIC_KEXTS */
 
 
-static kern_return_t export_macho_header(const KXLDObject *object, u_char *buf, 
+static kern_return_t export_macho_header(const KXLDObject *object, u_char *buf,
     u_int ncmds, u_long *header_offset, u_long header_size);
 #if KXLD_USER_OR_ILP32
-static u_long get_macho_cmd_data_32(u_char *file, u_long offset, 
+static u_long get_macho_cmd_data_32(u_char *file, u_long offset,
     u_int *filetype, u_int *ncmds);
-static kern_return_t export_macho_header_32(const KXLDObject *object, 
+static kern_return_t export_macho_header_32(const KXLDObject *object,
     u_char *buf, u_int ncmds, u_long *header_offset, u_long header_size);
 #endif /* KXLD_USER_OR_ILP32 */
 #if KXLD_USER_OR_LP64
 static u_long get_macho_cmd_data_64(u_char *file, u_long offset,
     u_int *filetype, u_int *ncmds);
-static kern_return_t export_macho_header_64(const KXLDObject *object, 
+static kern_return_t export_macho_header_64(const KXLDObject *object,
     u_char *buf, u_int ncmds, u_long *header_offset, u_long header_size);
 #endif /* KXLD_USER_OR_LP64 */
 
@@ -186,231 +193,278 @@ static kern_return_t populate_kmod_info(KXLDObject *object);
 *******************************************************************************/
 static boolean_t kxld_object_target_needs_swap(const KXLDObject *object __unused);
 static KXLDSeg * kxld_object_get_seg_by_name(const KXLDObject *object, const char *segname);
-static KXLDSect * kxld_object_get_sect_by_name(const KXLDObject *object, const char *segname, 
+static KXLDSect * kxld_object_get_sect_by_name(const KXLDObject *object, const char *segname,
     const char *sectname);
 
 /*******************************************************************************
 *******************************************************************************/
-size_t 
+size_t
 kxld_object_sizeof(void)
 {
-    return sizeof(KXLDObject);
+       return sizeof(KXLDObject);
 }
 
 /*******************************************************************************
 *******************************************************************************/
-kern_return_t 
+kern_return_t
 kxld_object_init_from_macho(KXLDObject *object, u_char *file, u_long size,
-    const char *name, KXLDArray *section_order __unused, 
+    const char *name, KXLDArray *section_order __unused,
     cpu_type_t cputype, cpu_subtype_t cpusubtype, KXLDFlags flags __unused)
 {
-    kern_return_t       rval    = KERN_FAILURE;
-    KXLDSeg           * seg     = NULL;
-    u_int               i       = 0;
+       kern_return_t       rval    = KERN_FAILURE;
+       KXLDSeg           * seg     = NULL;
+       u_int               i       = 0;
+       u_char *            my_file;
 
-    check(object);
-    check(file);
-    check(name);
+       check(object);
+       check(file);
+       check(name);
 
-    object->name = name;
+       object->name = name;
 
 #if KXLD_USER_OR_OBJECT
-    object->section_order = section_order;
+       object->section_order = section_order;
 #endif
 #if KXLD_PIC_KEXTS
-    object->include_kaslr_relocs = ((flags & kKXLDFlagIncludeRelocs) == kKXLDFlagIncludeRelocs);
+       object->include_kaslr_relocs = ((flags & kKXLDFlagIncludeRelocs) == kKXLDFlagIncludeRelocs);
 #endif
-    
-    /* Find the local architecture */
 
-    rval = get_target_machine_info(object, cputype, cpusubtype);
-    require_noerr(rval, finish);
+       /* Find the local architecture */
 
-    /* Find the Mach-O slice for the target architecture */
+       rval = get_target_machine_info(object, cputype, cpusubtype);
+       require_noerr(rval, finish);
 
-    rval = get_macho_slice_for_arch(object, file, size);
-    require_noerr(rval, finish);
+       /* Find the Mach-O slice for the target architecture */
 
-    /* Allocate the symbol table */
+       rval = get_macho_slice_for_arch(object, file, size);
+       require_noerr(rval, finish);
 
-    if (!object->symtab) {
-        object->symtab = kxld_alloc(kxld_symtab_sizeof());
-        require_action(object->symtab, finish, rval=KERN_RESOURCE_SHORTAGE);
-        bzero(object->symtab, kxld_symtab_sizeof());
-    }
+       if (isOldInterface) {
+               my_file = object->file;
+       } else {
+               my_file = object->split_info.kextExecutable;
+       }
 
-    /* Build the relocator */
+       /* Allocate the symbol table */
 
-    rval = kxld_relocator_init(&object->relocator, object->file,
-        object->symtab, &object->sects, object->cputype, 
-        object->cpusubtype, kxld_object_target_needs_swap(object));
-    require_noerr(rval, finish);
+       if (!object->symtab) {
+               object->symtab = kxld_calloc(kxld_symtab_sizeof());
+               require_action(object->symtab, finish, rval = KERN_RESOURCE_SHORTAGE);
+       }
 
-    /* There are four types of Mach-O files that we can support:
-     *   1) 32-bit MH_OBJECT      - Snow Leopard and earlier
-     *   2) 32-bit MH_KEXT_BUNDLE - Lion and Later
-     *   3) 64-bit MH_OBJECT      - Unsupported
-     *   4) 64-bit MH_KEXT_BUNDLE - Snow Leopard and Later
-     */
+       /* Build the relocator */
 
-    if (kxld_object_is_32_bit(object)) {
-        struct mach_header *mach_hdr = (struct mach_header *) ((void *) object->file);
-        object->filetype = mach_hdr->filetype;
-    } else {
-        struct mach_header_64 *mach_hdr = (struct mach_header_64 *) ((void *) object->file);
-        object->filetype = mach_hdr->filetype;
-    }
+       rval = kxld_relocator_init(&object->relocator,
+           my_file,
+           object->symtab, &object->sects,
+           object->cputype,
+           object->cpusubtype,
+           kxld_object_target_needs_swap(object));
+       require_noerr(rval, finish);
 
-    switch (object->filetype) {
+       /* There are four types of Mach-O files that we can support:
+        *   1) 32-bit MH_OBJECT      - Snow Leopard and earlier
+        *   2) 32-bit MH_KEXT_BUNDLE - Lion and Later
+        *   3) 64-bit MH_OBJECT      - Unsupported
+        *   4) 64-bit MH_KEXT_BUNDLE - Snow Leopard and Later
+        */
+
+       if (kxld_object_is_32_bit(object)) {
+               struct mach_header *mach_hdr = (struct mach_header *) ((void *) my_file);
+               object->filetype = mach_hdr->filetype;
+       } else {
+               struct mach_header_64 *mach_hdr = (struct mach_header_64 *) ((void *) my_file);
+               object->filetype = mach_hdr->filetype;
+       }
+
+       switch (object->filetype) {
 #if KXLD_USER_OR_BUNDLE
-    case MH_KEXT_BUNDLE:
-        rval = init_from_bundle(object);
-        require_noerr(rval, finish);
-        break;
+       case MH_KEXT_BUNDLE:
+               rval = init_from_bundle(object);
+               require_noerr(rval, finish);
+               break;
 #endif /* KXLD_USER_OR_BUNDLE */
 #if KXLD_USER_OR_OBJECT
-    case MH_OBJECT:
-        rval = init_from_object(object);
-        require_noerr(rval, finish);
-        break;
+       case MH_OBJECT:
+               rval = init_from_object(object);
+               require_noerr(rval, finish);
+               break;
 #endif /* KXLD_USER_OR_OBJECT */
-    case MH_EXECUTE:
-        object->is_kernel = TRUE;
-        rval = init_from_execute(object);
-        require_noerr(rval, finish);
-        break;
-    default:
-        rval = KERN_FAILURE;
-        kxld_log(kKxldLogLinking, kKxldLogErr,
-            kKxldLogFiletypeNotSupported, object->filetype);
-        goto finish;
-    }
-
-    if (!kxld_object_is_kernel(object)) {
-        for (i = 0; i < object->segs.nitems; ++i) {
-            seg = kxld_array_get_item(&object->segs, i);
-            kxld_seg_set_vm_protections(seg, 
-                target_supports_protected_segments(object));
-        }
-
-        seg = kxld_object_get_seg_by_name(object, SEG_LINKEDIT);
-        if (seg) {
-            (void) kxld_seg_populate_linkedit(seg, object->symtab,
-                kxld_object_is_32_bit(object)
+       case MH_EXECUTE:
+               object->is_kernel = TRUE;
+               rval = init_from_execute(object);
+               require_noerr(rval, finish);
+               break;
+       default:
+               rval = KERN_FAILURE;
+               kxld_log(kKxldLogLinking, kKxldLogErr,
+                   kKxldLogFiletypeNotSupported, object->filetype);
+               goto finish;
+       }
+
+       if (!kxld_object_is_kernel(object)) {
+               for (i = 0; i < object->segs.nitems; ++i) {
+                       seg = kxld_array_get_item(&object->segs, i);
+                       kxld_seg_set_vm_protections(seg,
+                           target_supports_protected_segments(object));
+               }
+
+               seg = kxld_object_get_seg_by_name(object, SEG_LINKEDIT);
+               if (seg) {
+                       (void) kxld_seg_populate_linkedit(seg, object->symtab,
+                           kxld_object_is_32_bit(object)
 #if KXLD_PIC_KEXTS
-                , &object->locrelocs, &object->extrelocs,
-                target_supports_slideable_kexts(object)
+                           , &object->locrelocs, &object->extrelocs,
+                           target_supports_slideable_kexts(object)
 #endif
-                );
-        }
-    }
+                           , isOldInterface ? 0 : object->splitinfolc.datasize
+                           );
+               }
+       }
 
-    (void) set_is_object_linked(object);
+       (void) set_is_object_linked(object);
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
+}
+
+/*******************************************************************************
+*******************************************************************************/
+splitKextLinkInfo *
+kxld_object_get_link_info(KXLDObject *object)
+{
+       check(object);
+
+       return &object->split_info;
+}
+
+
+/*******************************************************************************
+*******************************************************************************/
+void
+kxld_object_set_link_info(KXLDObject *object, splitKextLinkInfo *link_info)
+{
+       check(object);
+       check(link_info);
+
+       object->split_info.vmaddr_TEXT = link_info->vmaddr_TEXT;
+       object->split_info.vmaddr_TEXT_EXEC = link_info->vmaddr_TEXT_EXEC;
+       object->split_info.vmaddr_DATA = link_info->vmaddr_DATA;
+       object->split_info.vmaddr_DATA_CONST = link_info->vmaddr_DATA_CONST;
+       object->split_info.vmaddr_LLVM_COV = link_info->vmaddr_LLVM_COV;
+       object->split_info.vmaddr_LINKEDIT = link_info->vmaddr_LINKEDIT;
+
+       return;
 }
 
 /*******************************************************************************
 *******************************************************************************/
 kern_return_t
-get_target_machine_info(KXLDObject *object, cpu_type_t cputype __unused, 
+get_target_machine_info(KXLDObject *object, cpu_type_t cputype __unused,
     cpu_subtype_t cpusubtype __unused)
 {
 #if KERNEL
 
-    /* Because the kernel can only link for its own architecture, we know what
-     * the host and target architectures are at compile time, so we can use
-     * a vastly simplified version of this function.
-     */ 
+       /* Because the kernel can only link for its own architecture, we know what
+        * the host and target architectures are at compile time, so we can use
+        * a vastly simplified version of this function.
+        */
 
-    check(object);
+       check(object);
 
 #if   defined(__x86_64__)
-    object->cputype = CPU_TYPE_X86_64;
+       object->cputype = CPU_TYPE_X86_64;
 /* FIXME: we need clang to provide a __x86_64h__ macro for the sub-type. Using
  * __AVX2__ is a temporary solution until this is available. */
 #if   defined(__AVX2__)
-    object->cpusubtype = CPU_SUBTYPE_X86_64_H;
+       object->cpusubtype = CPU_SUBTYPE_X86_64_H;
 #else
-    object->cpusubtype = CPU_SUBTYPE_X86_64_ALL;
+       object->cpusubtype = CPU_SUBTYPE_X86_64_ALL;
 #endif
-    return KERN_SUCCESS;
-#else 
-    kxld_log(kKxldLogLinking, kKxldLogErr, 
-        kKxldLogArchNotSupported, _mh_execute_header->cputype);
-    return KERN_NOT_SUPPORTED;
+       return KERN_SUCCESS;
+#elif defined(__arm__)
+       object->cputype = CPU_TYPE_ARM;
+       object->cpusubtype = CPU_SUBTYPE_ARM_ALL;
+       return KERN_SUCCESS;
+#elif defined(__arm64__)
+       object->cputype = CPU_TYPE_ARM64;
+       object->cpusubtype = CPU_SUBTYPE_ARM64_ALL;
+       return KERN_SUCCESS;
+#else
+       kxld_log(kKxldLogLinking, kKxldLogErr,
+           kKxldLogArchNotSupported, _mh_execute_header->cputype);
+       return KERN_NOT_SUPPORTED;
 #endif /* Supported architecture defines */
 
 
 #else /* !KERNEL */
 
-    /* User-space must look up the architecture it's running on and the target
-     * architecture at run-time.
-     */
-
-    kern_return_t rval = KERN_FAILURE;
-    const NXArchInfo *host_arch = NULL;
-
-    check(object);
-
-    host_arch = NXGetLocalArchInfo();
-    require_action(host_arch, finish, rval=KERN_FAILURE);
-
-    object->host_order = host_arch->byteorder;
-
-    /* If the user did not specify a cputype, use the local architecture.
-     */
-
-    if (cputype) {
-        object->cputype = cputype;
-        object->cpusubtype = cpusubtype;
-    } else {
-        object->cputype = host_arch->cputype;
-        object->target_order = object->host_order;
-
-        switch (object->cputype) {
-        case CPU_TYPE_I386:
-            object->cpusubtype = CPU_SUBTYPE_I386_ALL;
-            break;
-        case CPU_TYPE_X86_64:
-            object->cpusubtype = CPU_SUBTYPE_X86_64_ALL;
-            break;
-        case CPU_TYPE_ARM:
-            object->cpusubtype = CPU_SUBTYPE_ARM_ALL;
-            break;
-        case CPU_TYPE_ARM64:
-            object->cpusubtype = CPU_SUBTYPE_ARM64_ALL;
-            break;
-        default:
-            object->cpusubtype = 0;
-            break;
-        }
-    }
-
-    /* Validate that we support the target architecture and record its 
-     * endianness.
-     */
-
-    switch(object->cputype) {
-    case CPU_TYPE_ARM:
-    case CPU_TYPE_ARM64:
-    case CPU_TYPE_I386:
-    case CPU_TYPE_X86_64:
-        object->target_order = NX_LittleEndian;
-        break;
-    default:
-        rval = KERN_NOT_SUPPORTED;
-        kxld_log(kKxldLogLinking, kKxldLogErr, 
-            kKxldLogArchNotSupported, object->cputype);
-        goto finish;
-    }
-
-    rval = KERN_SUCCESS;
+       /* User-space must look up the architecture it's running on and the target
+        * architecture at run-time.
+        */
+
+       kern_return_t rval = KERN_FAILURE;
+       const NXArchInfo *host_arch = NULL;
+
+       check(object);
+
+       host_arch = NXGetLocalArchInfo();
+       require_action(host_arch, finish, rval = KERN_FAILURE);
+
+       object->host_order = host_arch->byteorder;
+
+       /* If the user did not specify a cputype, use the local architecture.
+        */
+
+       if (cputype) {
+               object->cputype = cputype;
+               object->cpusubtype = cpusubtype;
+       } else {
+               object->cputype = host_arch->cputype;
+               object->target_order = object->host_order;
+
+               switch (object->cputype) {
+               case CPU_TYPE_I386:
+                       object->cpusubtype = CPU_SUBTYPE_I386_ALL;
+                       break;
+               case CPU_TYPE_X86_64:
+                       object->cpusubtype = CPU_SUBTYPE_X86_64_ALL;
+                       break;
+               case CPU_TYPE_ARM:
+                       object->cpusubtype = CPU_SUBTYPE_ARM_ALL;
+                       break;
+               case CPU_TYPE_ARM64:
+                       object->cpusubtype = CPU_SUBTYPE_ARM64_ALL;
+                       break;
+               default:
+                       object->cpusubtype = 0;
+                       break;
+               }
+       }
+
+       /* Validate that we support the target architecture and record its
+        * endianness.
+        */
+
+       switch (object->cputype) {
+       case CPU_TYPE_ARM:
+       case CPU_TYPE_ARM64:
+       case CPU_TYPE_I386:
+       case CPU_TYPE_X86_64:
+               object->target_order = NX_LittleEndian;
+               break;
+       default:
+               rval = KERN_NOT_SUPPORTED;
+               kxld_log(kKxldLogLinking, kKxldLogErr,
+                   kKxldLogArchNotSupported, object->cputype);
+               goto finish;
+       }
+
+       rval = KERN_SUCCESS;
 
 finish:
-    return rval;
+       return rval;
 #endif /* KERNEL */
 }
 
@@ -419,86 +473,95 @@ finish:
 static kern_return_t
 get_macho_slice_for_arch(KXLDObject *object, u_char *file, u_long size)
 {
-    kern_return_t rval = KERN_FAILURE;
-    struct mach_header *mach_hdr = NULL;
+       kern_return_t rval = KERN_FAILURE;
+       struct mach_header *mach_hdr = NULL;
 #if !KERNEL
-    struct fat_header *fat = (struct fat_header *) ((void *) file);
-    struct fat_arch *archs = (struct fat_arch *) &fat[1];
-    boolean_t swap = FALSE;
+       struct fat_header *fat = (struct fat_header *) ((void *) file);
+       struct fat_arch *archs = (struct fat_arch *) &fat[1];
+       boolean_t swap = FALSE;
 #endif /* KERNEL */
+       u_char *my_file = file;
+       u_long my_file_size = size;
 
-    check(object);
-    check(file);
-    check(size);
+       check(object);
+       check(file);
+       check(size);
 
-    object->file = file;
-    object->size = size;
-
-    /* We are assuming that we will never receive a fat file in the kernel */
+       /* We are assuming that we will never receive a fat file in the kernel */
 
 #if !KERNEL
-    require_action(size >= sizeof(*fat), finish, 
-        rval=KERN_FAILURE;
-        kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogTruncatedMachO));
-
-    /* The fat header is always big endian, so swap if necessary */
-    if (fat->magic == FAT_CIGAM) {
-        (void) swap_fat_header(fat, object->host_order);
-        swap = TRUE;
-    }
-
-    if (fat->magic == FAT_MAGIC) {
-        struct fat_arch *arch = NULL;
-
-        require_action(size >= (sizeof(*fat) + (fat->nfat_arch * sizeof(*archs))),
-            finish, 
-            rval=KERN_FAILURE;
-            kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogTruncatedMachO));
-
-        /* Swap the fat_arch structures if necessary */
-        if (swap) {
-            (void) swap_fat_arch(archs, fat->nfat_arch, object->host_order);
-        }
-
-        /* Locate the Mach-O for the requested architecture */
-
-        arch = NXFindBestFatArch(object->cputype, object->cpusubtype, archs, fat->nfat_arch);
-        require_action(arch, finish, rval=KERN_FAILURE;
-            kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogArchNotFound));
-        require_action(size >= arch->offset + arch->size, finish, 
-            rval=KERN_FAILURE;
-            kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogTruncatedMachO));
-
-        object->file = file + arch->offset;
-        object->size = arch->size;
-    }
+       require_action(size >= sizeof(*fat), finish,
+           rval = KERN_FAILURE;
+           kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogTruncatedMachO));
+
+       /* The fat header is always big endian, so swap if necessary */
+       if (fat->magic == FAT_CIGAM) {
+               (void) swap_fat_header(fat, object->host_order);
+               swap = TRUE;
+       }
+
+       if (fat->magic == FAT_MAGIC) {
+               struct fat_arch *arch = NULL;
+               u_long arch_size;
+               boolean_t ovr = os_mul_and_add_overflow(fat->nfat_arch, sizeof(*archs), sizeof(*fat), &arch_size);
+
+               require_action(!ovr && size >= arch_size,
+                   finish,
+                   rval = KERN_FAILURE;
+                   kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogTruncatedMachO));
+
+               /* Swap the fat_arch structures if necessary */
+               if (swap) {
+                       (void) swap_fat_arch(archs, fat->nfat_arch, object->host_order);
+               }
+
+               /* Locate the Mach-O for the requested architecture */
+
+               arch = NXFindBestFatArch(object->cputype, object->cpusubtype, archs, fat->nfat_arch);
+               require_action(arch, finish, rval = KERN_FAILURE;
+                   kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogArchNotFound));
+               require_action(size >= arch->offset + arch->size, finish,
+                   rval = KERN_FAILURE;
+                   kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogTruncatedMachO));
+
+               my_file = my_file + arch->offset;
+               my_file_size = arch->size;
+       }
 #endif /* !KERNEL */
 
-    /* Swap the Mach-O's headers to this architecture if necessary */
-    if (kxld_object_is_32_bit(object)) {
-        rval = validate_and_swap_macho_32(object->file, object->size
+       /* Swap the Mach-O's headers to this architecture if necessary */
+       if (kxld_object_is_32_bit(object)) {
+               rval = validate_and_swap_macho_32(my_file, my_file_size
 #if !KERNEL
-            , object->host_order
+                   , object->host_order
 #endif /* !KERNEL */
-            );
-    } else {
-        rval = validate_and_swap_macho_64(object->file, object->size
+                   );
+       } else {
+               rval = validate_and_swap_macho_64(my_file, my_file_size
 #if !KERNEL
-            , object->host_order
+                   , object->host_order
 #endif /* !KERNEL */
-            );
-    }
-    require_noerr(rval, finish);
-
-    mach_hdr = (struct mach_header *) ((void *) object->file);
-    require_action(object->cputype == mach_hdr->cputype, finish,
-        rval=KERN_FAILURE;
-        kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogTruncatedMachO));
-    object->cpusubtype = mach_hdr->cpusubtype;  /* <rdar://problem/16008438> */
-
-    rval = KERN_SUCCESS;
+                   );
+       }
+       require_noerr(rval, finish);
+
+       mach_hdr = (struct mach_header *) ((void *) my_file);
+       require_action(object->cputype == mach_hdr->cputype, finish,
+           rval = KERN_FAILURE;
+           kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogTruncatedMachO));
+       object->cpusubtype = mach_hdr->cpusubtype; /* <rdar://problem/16008438> */
+
+       if (isOldInterface) {
+               object->file = my_file;
+               object->size = my_file_size;
+       } else {
+               object->split_info.kextExecutable = my_file;
+               object->split_info.kextSize = my_file_size;
+       }
+
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -507,207 +570,239 @@ static kern_return_t
 init_from_final_linked_image(KXLDObject *object, u_int *filetype_out,
     struct symtab_command **symtab_hdr_out)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSeg *seg = NULL;
-    KXLDSect *sect = NULL;
-    struct load_command *cmd_hdr = NULL;
-    struct symtab_command *symtab_hdr = NULL;
-    struct uuid_command *uuid_hdr = NULL;
-    struct version_min_command *versionmin_hdr = NULL;
-    struct source_version_command *source_version_hdr = NULL;
-    u_long base_offset = 0;
-    u_long offset = 0;
-    u_long sect_offset = 0;
-    u_int filetype = 0;
-    u_int i = 0;
-    u_int j = 0;
-    u_int segi = 0;
-    u_int secti = 0;
-    u_int nsegs = 0;
-    u_int nsects = 0;
-    u_int ncmds = 0;
-
-    KXLD_3264_FUNC(kxld_object_is_32_bit(object), base_offset,
-        get_macho_cmd_data_32, get_macho_cmd_data_64,
-        object->file, offset, &filetype, &ncmds);
-
-    /* First pass to count segments and sections */
-
-    offset = base_offset;
-    for (i = 0; i < ncmds; ++i, offset += cmd_hdr->cmdsize) {
-        cmd_hdr = (struct load_command *) ((void *) (object->file + offset));
-
-        switch(cmd_hdr->cmd) {
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSeg *seg = NULL;
+       KXLDSect *sect = NULL;
+       struct load_command *cmd_hdr = NULL;
+       struct symtab_command *symtab_hdr = NULL;
+       struct uuid_command *uuid_hdr = NULL;
+       struct version_min_command *versionmin_hdr = NULL;
+       struct build_version_command *build_version_hdr = NULL;
+       struct source_version_command *source_version_hdr = NULL;
+       u_long base_offset = 0;
+       u_long offset = 0;
+       u_long sect_offset = 0;
+       u_int filetype = 0;
+       u_int i = 0;
+       u_int j = 0;
+       u_int segi = 0;
+       u_int secti = 0;
+       u_int nsegs = 0;
+       u_int nsects = 0;
+       u_int ncmds = 0;
+       u_char *my_file;
+
+       if (isOldInterface) {
+               my_file = object->file;
+       } else {
+               my_file = object->split_info.kextExecutable;
+       }
+
+       KXLD_3264_FUNC(kxld_object_is_32_bit(object), base_offset,
+           get_macho_cmd_data_32, get_macho_cmd_data_64,
+           my_file, offset, &filetype, &ncmds);
+
+       /* First pass to count segments and sections */
+
+       offset = base_offset;
+       for (i = 0; i < ncmds; ++i, offset += cmd_hdr->cmdsize) {
+               cmd_hdr = (struct load_command *) ((void *) (my_file + offset));
+
+               switch (cmd_hdr->cmd) {
 #if KXLD_USER_OR_ILP32
-        case LC_SEGMENT:
-            {
-                struct segment_command *seg_hdr = 
-                    (struct segment_command *) cmd_hdr;
-
-                /* Ignore segments with no vm size */
-                if (!seg_hdr->vmsize) continue;
-
-                ++nsegs;
-                nsects += seg_hdr->nsects;
-            }
-            break;
+               case LC_SEGMENT:
+               {
+                       struct segment_command *seg_hdr =
+                           (struct segment_command *) cmd_hdr;
+
+                       /* Ignore segments with no vm size */
+                       if (!seg_hdr->vmsize) {
+                               continue;
+                       }
+
+                       ++nsegs;
+                       nsects += seg_hdr->nsects;
+               }
+               break;
 #endif /* KXLD_USER_OR_ILP32 */
 #if KXLD_USER_OR_LP64
-        case LC_SEGMENT_64:
-            {
-                struct segment_command_64 *seg_hdr = 
-                    (struct segment_command_64 *) ((void *) cmd_hdr);
-
-                /* Ignore segments with no vm size */
-                if (!seg_hdr->vmsize) continue;
-
-                ++nsegs;
-                nsects += seg_hdr->nsects;
-            }
-            break;
+               case LC_SEGMENT_64:
+               {
+                       struct segment_command_64 *seg_hdr =
+                           (struct segment_command_64 *) ((void *) cmd_hdr);
+
+                       /* Ignore segments with no vm size */
+                       if (!seg_hdr->vmsize) {
+                               continue;
+                       }
+
+                       ++nsegs;
+                       nsects += seg_hdr->nsects;
+               }
+               break;
 #endif /* KXLD_USER_OR_LP64 */
-        default:
-            continue;
-        }
-    }
+               default:
+                       continue;
+               }
+       }
 
-    /* Allocate the segments and sections */
+       /* Allocate the segments and sections */
 
-    if (nsegs) {
-        rval = kxld_array_init(&object->segs, sizeof(KXLDSeg), nsegs);
-        require_noerr(rval, finish);
+       if (nsegs) {
+               rval = kxld_array_init(&object->segs, sizeof(KXLDSeg), nsegs);
+               require_noerr(rval, finish);
 
-        rval = kxld_array_init(&object->sects, sizeof(KXLDSect), nsects);
-        require_noerr(rval, finish);
-    }
+               rval = kxld_array_init(&object->sects, sizeof(KXLDSect), nsects);
+               require_noerr(rval, finish);
+       }
 
-    /* Initialize the segments and sections */
+       /* Initialize the segments and sections */
 
-    offset = base_offset;
-    for (i = 0; i < ncmds; ++i, offset += cmd_hdr->cmdsize) {
-        cmd_hdr = (struct load_command *) ((void *) (object->file + offset)); 
-        seg = NULL;
+       offset = base_offset;
+       for (i = 0; i < ncmds; ++i, offset += cmd_hdr->cmdsize) {
+               cmd_hdr = (struct load_command *) ((void *) (my_file + offset));
+               seg = NULL;
 
-        switch(cmd_hdr->cmd) {
+               switch (cmd_hdr->cmd) {
 #if KXLD_USER_OR_ILP32
-        case LC_SEGMENT:
-            {
-                struct segment_command *seg_hdr =
-                    (struct segment_command *) cmd_hdr;
+               case LC_SEGMENT:
+               {
+                       struct segment_command *seg_hdr =
+                           (struct segment_command *) cmd_hdr;
 
-                /* Ignore segments with no vm size */
-                if (!seg_hdr->vmsize) continue;
+                       /* Ignore segments with no vm size */
+                       if (!seg_hdr->vmsize) {
+                               continue;
+                       }
 
-                seg = kxld_array_get_item(&object->segs, segi++);
+                       seg = kxld_array_get_item(&object->segs, segi++);
 
-                rval = kxld_seg_init_from_macho_32(seg, seg_hdr);
-                require_noerr(rval, finish);
+                       rval = kxld_seg_init_from_macho_32(seg, seg_hdr);
+                       require_noerr(rval, finish);
 
-                sect_offset = offset + sizeof(*seg_hdr);
-            }
-            break;
+                       sect_offset = offset + sizeof(*seg_hdr);
+               }
+               break;
 #endif /* KXLD_USER_OR_ILP32 */
 #if KXLD_USER_OR_LP64
-        case LC_SEGMENT_64:
-            {
-                struct segment_command_64 *seg_hdr = 
-                    (struct segment_command_64 *) ((void *) cmd_hdr);
+               case LC_SEGMENT_64:
+               {
+                       struct segment_command_64 *seg_hdr =
+                           (struct segment_command_64 *) ((void *) cmd_hdr);
 
-                /* Ignore segments with no vm size */
-                if (!seg_hdr->vmsize) continue;
+                       /* Ignore segments with no vm size */
+                       if (!seg_hdr->vmsize) {
+                               continue;
+                       }
 
-                seg = kxld_array_get_item(&object->segs, segi++);
+                       seg = kxld_array_get_item(&object->segs, segi++);
 
-                rval = kxld_seg_init_from_macho_64(seg, seg_hdr);
-                require_noerr(rval, finish);
+                       rval = kxld_seg_init_from_macho_64(seg, seg_hdr);
+                       require_noerr(rval, finish);
 
-                sect_offset = offset + sizeof(*seg_hdr);
-            }
-            break;
+                       sect_offset = offset + sizeof(*seg_hdr);
+               }
+               break;
 #endif /* KXLD_USER_OR_LP64 */
-        case LC_SYMTAB:
-            symtab_hdr = (struct symtab_command *) cmd_hdr;
-            break;
-        case LC_UUID:
-            uuid_hdr = (struct uuid_command *) cmd_hdr;
-            kxld_uuid_init_from_macho(&object->uuid, uuid_hdr);
-            break;
-        case LC_VERSION_MIN_MACOSX:
-        case LC_VERSION_MIN_IPHONEOS:
-        case LC_VERSION_MIN_WATCHOS:
-            versionmin_hdr = (struct version_min_command *) cmd_hdr;
-            kxld_versionmin_init_from_macho(&object->versionmin, versionmin_hdr);
-            break;
-        case LC_SOURCE_VERSION:
-            source_version_hdr = (struct source_version_command *) (void *) cmd_hdr;
-            kxld_srcversion_init_from_macho(&object->srcversion, source_version_hdr);
-            break;
-        case LC_DYSYMTAB:
-            object->dysymtab_hdr = (struct dysymtab_command *) cmd_hdr;            
-
-            rval = kxld_reloc_create_macho(&object->extrelocs, &object->relocator,
-                (struct relocation_info *) ((void *) (object->file + object->dysymtab_hdr->extreloff)), 
-                object->dysymtab_hdr->nextrel);
-            require_noerr(rval, finish);
-
-            rval = kxld_reloc_create_macho(&object->locrelocs, &object->relocator,
-                (struct relocation_info *) ((void *) (object->file + object->dysymtab_hdr->locreloff)), 
-                object->dysymtab_hdr->nlocrel);
-            require_noerr(rval, finish);
-
-            break;
-        case LC_UNIXTHREAD:
-        case LC_MAIN:
-            /* Don't need to do anything with UNIXTHREAD or MAIN for the kernel */
-            require_action(kxld_object_is_kernel(object), 
-                finish, rval=KERN_FAILURE;
-                kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
-                    "LC_UNIXTHREAD/LC_MAIN segment is not valid in a kext."));
-            break;
-        case LC_SEGMENT_SPLIT_INFO:
-            /* To be implemented later; treat as uninteresting for now */
-        case LC_CODE_SIGNATURE:
-        case LC_DYLD_INFO:
-        case LC_DYLD_INFO_ONLY:
-        case LC_FUNCTION_STARTS:
-        case LC_DATA_IN_CODE:
-        case LC_DYLIB_CODE_SIGN_DRS:
-            /* Various metadata that might be stored in the linkedit segment */
-            break;
-        default:
-            rval=KERN_FAILURE;
-            kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
-                "Invalid load command type in MH_KEXT_BUNDLE kext: %u.", cmd_hdr->cmd);
-            goto finish;
-        }
-
-        if (seg) {
-
-            /* Initialize the sections */
-            for (j = 0; j < seg->sects.nitems; ++j, ++secti) {
-                sect = kxld_array_get_item(&object->sects, secti);
-                KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
-                    kxld_sect_init_from_macho_32, kxld_sect_init_from_macho_64,
-                    sect, object->file, &sect_offset, secti, &object->relocator);
-                require_noerr(rval, finish);
-
-                /* Add the section to the segment.  This will also make sure
-                 * that the sections and segments have the same segname.
-                 */
-                rval = kxld_seg_add_section(seg, sect);
-                require_noerr(rval, finish);
-            }
-            rval = kxld_seg_finish_init(seg);
-            require_noerr(rval, finish);
-        }
-    }
-
-    if (filetype_out) *filetype_out = filetype;
-    if (symtab_hdr_out) *symtab_hdr_out = symtab_hdr;
-    object->is_final_image = TRUE;
-    rval = KERN_SUCCESS;
+               case LC_SYMTAB:
+                       symtab_hdr = (struct symtab_command *) cmd_hdr;
+                       break;
+               case LC_UUID:
+                       uuid_hdr = (struct uuid_command *) cmd_hdr;
+                       kxld_uuid_init_from_macho(&object->uuid, uuid_hdr);
+                       break;
+               case LC_VERSION_MIN_MACOSX:
+               case LC_VERSION_MIN_IPHONEOS:
+               case LC_VERSION_MIN_TVOS:
+               case LC_VERSION_MIN_WATCHOS:
+                       versionmin_hdr = (struct version_min_command *) cmd_hdr;
+                       kxld_versionmin_init_from_macho(&object->versionmin, versionmin_hdr);
+                       break;
+               case LC_BUILD_VERSION:
+                       build_version_hdr = (struct build_version_command *)cmd_hdr;
+                       kxld_versionmin_init_from_build_cmd(&object->versionmin, build_version_hdr);
+                       break;
+               case LC_SOURCE_VERSION:
+                       source_version_hdr = (struct source_version_command *) (void *) cmd_hdr;
+                       kxld_srcversion_init_from_macho(&object->srcversion, source_version_hdr);
+                       break;
+               case LC_DYSYMTAB:
+                       object->dysymtab_hdr = (struct dysymtab_command *) cmd_hdr;
+                       rval = kxld_reloc_create_macho(&object->extrelocs, &object->relocator,
+                           (struct relocation_info *) ((void *) (my_file + object->dysymtab_hdr->extreloff)),
+                           object->dysymtab_hdr->nextrel);
+                       require_noerr(rval, finish);
+
+                       rval = kxld_reloc_create_macho(&object->locrelocs, &object->relocator,
+                           (struct relocation_info *) ((void *) (my_file + object->dysymtab_hdr->locreloff)),
+                           object->dysymtab_hdr->nlocrel);
+                       require_noerr(rval, finish);
+
+                       break;
+               case LC_UNIXTHREAD:
+               case LC_MAIN:
+                       /* Don't need to do anything with UNIXTHREAD or MAIN for the kernel */
+                       require_action(kxld_object_is_kernel(object),
+                           finish, rval = KERN_FAILURE;
+                           kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
+                           "LC_UNIXTHREAD/LC_MAIN segment is not valid in a kext."));
+                       break;
+               case LC_SEGMENT_SPLIT_INFO:
+                       if (isSplitKext) {
+                               struct linkedit_data_command *split_info_hdr = NULL;
+                               split_info_hdr = (struct linkedit_data_command *) (void *) cmd_hdr;
+                               kxld_splitinfolc_init_from_macho(&object->splitinfolc, split_info_hdr);
+                       }
+                       break;
+               case LC_NOTE:
+                       /* binary blob of data */
+                       break;
+               case LC_CODE_SIGNATURE:
+               case LC_DYLD_INFO:
+               case LC_DYLD_INFO_ONLY:
+               case LC_FUNCTION_STARTS:
+               case LC_DATA_IN_CODE:
+               case LC_DYLIB_CODE_SIGN_DRS:
+                       /* Various metadata that might be stored in the linkedit segment */
+                       break;
+               default:
+                       rval = KERN_FAILURE;
+                       kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
+                           "Invalid load command type in MH_KEXT_BUNDLE kext: %u.", cmd_hdr->cmd);
+                       goto finish;
+               }
+
+               if (seg) {
+                       /* Initialize the sections */
+                       for (j = 0; j < seg->sects.nitems; ++j, ++secti) {
+                               sect = kxld_array_get_item(&object->sects, secti);
+
+                               KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
+                                   kxld_sect_init_from_macho_32, kxld_sect_init_from_macho_64,
+                                   sect, my_file, &sect_offset, secti, &object->relocator);
+                               require_noerr(rval, finish);
+
+                               /* Add the section to the segment.  This will also make sure
+                                * that the sections and segments have the same segname.
+                                */
+                               rval = kxld_seg_add_section(seg, sect);
+                               require_noerr(rval, finish);
+                       }
+                       rval = kxld_seg_finish_init(seg);
+                       require_noerr(rval, finish);
+               }
+       }
+
+       if (filetype_out) {
+               *filetype_out = filetype;
+       }
+       if (symtab_hdr_out) {
+               *symtab_hdr_out = symtab_hdr;
+       }
+       object->is_final_image = TRUE;
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -715,73 +810,79 @@ finish:
 static kern_return_t
 init_from_execute(KXLDObject *object)
 {
-    kern_return_t rval = KERN_FAILURE;
-    struct symtab_command *symtab_hdr = NULL;
-    u_int filetype = 0;
-    KXLDSeg * kernel_linkedit_seg = NULL;  // used if running kernel
+       kern_return_t rval = KERN_FAILURE;
+       struct symtab_command *symtab_hdr = NULL;
+       u_int filetype = 0;
+       KXLDSeg * kernel_linkedit_seg = NULL; // used if running kernel
 #if KXLD_USER_OR_OBJECT
-    KXLDSeg *seg = NULL;
-    KXLDSect *sect = NULL;
-    KXLDSectionName *sname = NULL;
-    u_int i = 0, j = 0, k = 0;
+       KXLDSeg *seg = NULL;
+       KXLDSect *sect = NULL;
+       KXLDSectionName *sname = NULL;
+       u_int i = 0, j = 0, k = 0;
 #endif /* KXLD_USER_OR_OBJECT */
+       u_char *my_file;
+
+       check(object);
 
-    check(object);
+       if (isOldInterface) {
+               my_file = object->file;
+       } else {
+               my_file = object->split_info.kextExecutable;
+       }
 
-    require_action(kxld_object_is_kernel(object), finish, rval=KERN_FAILURE);
+       require_action(kxld_object_is_kernel(object), finish, rval = KERN_FAILURE);
 
-    rval = init_from_final_linked_image(object, &filetype, &symtab_hdr);
-    require_noerr(rval, finish);
+       rval = init_from_final_linked_image(object, &filetype, &symtab_hdr);
+       require_noerr(rval, finish);
 
-    require_action(filetype == MH_EXECUTE, finish, rval=KERN_FAILURE;
-        kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO 
-            "The kernel file is not of type MH_EXECUTE."));
+       require_action(filetype == MH_EXECUTE, finish, rval = KERN_FAILURE;
+           kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
+           "The kernel file is not of type MH_EXECUTE."));
 
-   /* Initialize the symbol table. If this is the running kernel
-    * we  will work from the in-memory linkedit segment;
-    * otherwise we work from the whole mach-o image.
-    */
+       /* Initialize the symbol table. If this is the running kernel
+        * we  will work from the in-memory linkedit segment;
+        * otherwise we work from the whole mach-o image.
+        */
 #if KERNEL
-    kernel_linkedit_seg = kxld_object_get_seg_by_name(object, SEG_LINKEDIT);
-    require_action(kernel_linkedit_seg, finish, rval=KERN_FAILURE;
-        kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO));
+       kernel_linkedit_seg = kxld_object_get_seg_by_name(object, SEG_LINKEDIT);
+       require_action(kernel_linkedit_seg, finish, rval = KERN_FAILURE;
+           kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO));
 #endif
 
-    KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
-        kxld_symtab_init_from_macho_32, kxld_symtab_init_from_macho_64,
-        object->symtab, symtab_hdr, object->file, kernel_linkedit_seg);
-    require_noerr(rval, finish);
+       KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
+           kxld_symtab_init_from_macho_32, kxld_symtab_init_from_macho_64,
+           object->symtab, symtab_hdr, my_file, kernel_linkedit_seg);
+       require_noerr(rval, finish);
 
 #if KXLD_USER_OR_OBJECT
-    /* Save off the order of section names so that we can lay out kext 
-     * sections for MH_OBJECT-based systems.
-     */
-    if (target_supports_object(object)) {
-
-        rval = kxld_array_init(object->section_order, sizeof(KXLDSectionName), 
-            object->sects.nitems);
-        require_noerr(rval, finish);
-
-        /* Copy the section names into the section_order array for future kext
-         * section ordering.
-         */
-        for (i = 0, k = 0; i < object->segs.nitems; ++i) {
-            seg = kxld_array_get_item(&object->segs, i);
-
-            for (j = 0; j < seg->sects.nitems; ++j, ++k) {
-                sect = *(KXLDSect **) kxld_array_get_item(&seg->sects, j);
-                sname = kxld_array_get_item(object->section_order, k);
-
-                strlcpy(sname->segname, sect->segname, sizeof(sname->segname));
-                strlcpy(sname->sectname, sect->sectname, sizeof(sname->sectname));
-            }
-        }
-    }
+       /* Save off the order of section names so that we can lay out kext
+        * sections for MH_OBJECT-based systems.
+        */
+       if (target_supports_object(object)) {
+               rval = kxld_array_init(object->section_order, sizeof(KXLDSectionName),
+                   object->sects.nitems);
+               require_noerr(rval, finish);
+
+               /* Copy the section names into the section_order array for future kext
+                * section ordering.
+                */
+               for (i = 0, k = 0; i < object->segs.nitems; ++i) {
+                       seg = kxld_array_get_item(&object->segs, i);
+
+                       for (j = 0; j < seg->sects.nitems; ++j, ++k) {
+                               sect = *(KXLDSect **) kxld_array_get_item(&seg->sects, j);
+                               sname = kxld_array_get_item(object->section_order, k);
+
+                               strlcpy(sname->segname, sect->segname, sizeof(sname->segname));
+                               strlcpy(sname->sectname, sect->sectname, sizeof(sname->sectname));
+                       }
+               }
+       }
 #endif /* KXLD_USER_OR_OBJECT */
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 #if KXLD_USER_OR_BUNDLE
@@ -790,233 +891,260 @@ finish:
 static boolean_t
 target_supports_bundle(const KXLDObject *object __unused)
 {
-    return TRUE;
+       return TRUE;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-static kern_return_t 
+static kern_return_t
 init_from_bundle(KXLDObject *object)
 {
-    kern_return_t rval = KERN_FAILURE;
-    struct symtab_command *symtab_hdr = NULL;
-    u_int filetype = 0;
+       kern_return_t rval = KERN_FAILURE;
+       struct symtab_command *symtab_hdr = NULL;
+       u_int filetype = 0;
+       u_char *my_file;
+
+       check(object);
 
-    check(object);
+       if (isOldInterface) {
+               my_file = object->file;
+       } else {
+               my_file = object->split_info.kextExecutable;
+       }
 
-    require_action(target_supports_bundle(object), finish,
-        rval=KERN_FAILURE;
-        kxld_log(kKxldLogLinking, kKxldLogErr,
-            kKxldLogFiletypeNotSupported, MH_KEXT_BUNDLE));
+       require_action(target_supports_bundle(object), finish,
+           rval = KERN_FAILURE;
+           kxld_log(kKxldLogLinking, kKxldLogErr,
+           kKxldLogFiletypeNotSupported, MH_KEXT_BUNDLE));
 
-    rval = init_from_final_linked_image(object, &filetype, &symtab_hdr);
-    require_noerr(rval, finish);
+       rval = init_from_final_linked_image(object, &filetype, &symtab_hdr);
+       require_noerr(rval, finish);
 
-    require_action(filetype == MH_KEXT_BUNDLE, finish, 
-        rval=KERN_FAILURE);
+       require_action(filetype == MH_KEXT_BUNDLE, finish,
+           rval = KERN_FAILURE);
 
-    KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
-        kxld_symtab_init_from_macho_32, kxld_symtab_init_from_macho_64,
-        object->symtab, symtab_hdr, object->file,
-        /* kernel_linkedit_seg */ NULL);
-    require_noerr(rval, finish);
+       KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
+           kxld_symtab_init_from_macho_32, kxld_symtab_init_from_macho_64,
+           object->symtab, symtab_hdr, my_file,
+           /* kernel_linkedit_seg */ NULL);
+       require_noerr(rval, finish);
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 #endif /* KXLD_USER_OR_BUNDLE */
 
 #if KXLD_USER_OR_OBJECT
 /*******************************************************************************
 *******************************************************************************/
-static boolean_t target_supports_object(const KXLDObject *object)
+static boolean_t
+target_supports_object(const KXLDObject *object)
 {
-    return (object->cputype == CPU_TYPE_I386);
+       return object->cputype == CPU_TYPE_I386;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-static kern_return_t 
+static kern_return_t
 init_from_object(KXLDObject *object)
 {
-    kern_return_t rval = KERN_FAILURE;
-    struct load_command *cmd_hdr = NULL;
-    struct symtab_command *symtab_hdr = NULL;
-    struct uuid_command *uuid_hdr = NULL;
-    KXLDSect *sect = NULL;
-    u_long offset = 0;
-    u_long sect_offset = 0;
-    u_int filetype = 0;
-    u_int ncmds = 0;
-    u_int nsects = 0;
-    u_int i = 0;
-    boolean_t has_segment = FALSE;
-
-    check(object);
-
-    require_action(target_supports_object(object),
-        finish, rval=KERN_FAILURE;
-        kxld_log(kKxldLogLinking, kKxldLogErr,
-            kKxldLogFiletypeNotSupported, MH_OBJECT));
-
-    KXLD_3264_FUNC(kxld_object_is_32_bit(object), offset,
-        get_macho_cmd_data_32, get_macho_cmd_data_64,
-        object->file, offset, &filetype, &ncmds);
-
-    require_action(filetype == MH_OBJECT, finish, rval=KERN_FAILURE);
-
-    /* MH_OBJECTs use one unnamed segment to contain all of the sections.  We
-     * loop over all of the load commands to initialize the structures we
-     * expect.  Then, we'll use the unnamed segment to get to all of the
-     * sections, and then use those sections to create the actual segments.
-     */
-
-    for (; i < ncmds; ++i, offset += cmd_hdr->cmdsize) {
-        cmd_hdr = (struct load_command *) ((void *) (object->file + offset));
-
-        switch(cmd_hdr->cmd) {
+       kern_return_t rval = KERN_FAILURE;
+       struct load_command *cmd_hdr = NULL;
+       struct symtab_command *symtab_hdr = NULL;
+       struct uuid_command *uuid_hdr = NULL;
+       KXLDSect *sect = NULL;
+       u_long offset = 0;
+       u_long sect_offset = 0;
+       u_int filetype = 0;
+       u_int ncmds = 0;
+       u_int nsects = 0;
+       u_int i = 0;
+       boolean_t has_segment = FALSE;
+       u_char *my_file;
+
+       check(object);
+
+       if (isOldInterface) {
+               my_file = object->file;
+       } else {
+               my_file = object->split_info.kextExecutable;
+       }
+
+       require_action(target_supports_object(object),
+           finish, rval = KERN_FAILURE;
+           kxld_log(kKxldLogLinking, kKxldLogErr,
+           kKxldLogFiletypeNotSupported, MH_OBJECT));
+
+       KXLD_3264_FUNC(kxld_object_is_32_bit(object), offset,
+           get_macho_cmd_data_32, get_macho_cmd_data_64,
+           my_file, offset, &filetype, &ncmds);
+
+       require_action(filetype == MH_OBJECT, finish, rval = KERN_FAILURE);
+
+       /* MH_OBJECTs use one unnamed segment to contain all of the sections.  We
+        * loop over all of the load commands to initialize the structures we
+        * expect.  Then, we'll use the unnamed segment to get to all of the
+        * sections, and then use those sections to create the actual segments.
+        */
+
+       for (; i < ncmds; ++i, offset += cmd_hdr->cmdsize) {
+               cmd_hdr = (struct load_command *) ((void *) (my_file + offset));
+
+               switch (cmd_hdr->cmd) {
 #if KXLD_USER_OR_ILP32
-        case LC_SEGMENT:
-            {
-                struct segment_command *seg_hdr = 
-                    (struct segment_command *) cmd_hdr;
-
-                /* Ignore segments with no vm size */
-                if (!seg_hdr->vmsize) continue;
-
-                /* Ignore LINKEDIT segments */
-                if (streq_safe(seg_hdr->segname, SEG_LINKEDIT, 
-                        const_strlen(SEG_LINKEDIT))) 
-                {
-                    continue;
-                }
-
-                require_action(kxld_object_is_32_bit(object), finish, rval=KERN_FAILURE;
-                    kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
-                        "LC_SEGMENT in 64-bit kext."));
-                require_action(!has_segment, finish, rval=KERN_FAILURE;
-                    kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
-                        "Multiple segments in an MH_OBJECT kext."));
-
-                nsects = seg_hdr->nsects;
-                sect_offset = offset + sizeof(*seg_hdr);
-                has_segment = TRUE;
-            }
-            break;
+               case LC_SEGMENT:
+               {
+                       struct segment_command *seg_hdr =
+                           (struct segment_command *) cmd_hdr;
+
+                       /* Ignore segments with no vm size */
+                       if (!seg_hdr->vmsize) {
+                               continue;
+                       }
+
+                       /* Ignore LINKEDIT segments */
+                       if (streq_safe(seg_hdr->segname, SEG_LINKEDIT,
+                           const_strlen(SEG_LINKEDIT))) {
+                               continue;
+                       }
+
+                       require_action(kxld_object_is_32_bit(object), finish, rval = KERN_FAILURE;
+                           kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
+                           "LC_SEGMENT in 64-bit kext."));
+                       require_action(!has_segment, finish, rval = KERN_FAILURE;
+                           kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
+                           "Multiple segments in an MH_OBJECT kext."));
+
+                       nsects = seg_hdr->nsects;
+                       sect_offset = offset + sizeof(*seg_hdr);
+                       has_segment = TRUE;
+               }
+               break;
 #endif /* KXLD_USER_OR_ILP32 */
 #if KXLD_USER_OR_LP64
-        case LC_SEGMENT_64:
-            {
-                struct segment_command_64 *seg_hdr =
-                    (struct segment_command_64 *) ((void *) cmd_hdr);
-
-                /* Ignore segments with no vm size */
-                if (!seg_hdr->vmsize) continue;
-
-                /* Ignore LINKEDIT segments */
-                if (streq_safe(seg_hdr->segname, SEG_LINKEDIT, 
-                        const_strlen(SEG_LINKEDIT))) 
-                {
-                    continue;
-                }
-
-                require_action(!kxld_object_is_32_bit(object), finish, rval=KERN_FAILURE;
-                    kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
-                        "LC_SEGMENT_64 in a 32-bit kext."));
-                require_action(!has_segment, finish, rval=KERN_FAILURE;
-                    kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
-                        "Multiple segments in an MH_OBJECT kext."));
-
-                nsects = seg_hdr->nsects;
-                sect_offset = offset + sizeof(*seg_hdr);
-                has_segment = TRUE;
-            }
-            break;
+               case LC_SEGMENT_64:
+               {
+                       struct segment_command_64 *seg_hdr =
+                           (struct segment_command_64 *) ((void *) cmd_hdr);
+
+                       /* Ignore segments with no vm size */
+                       if (!seg_hdr->vmsize) {
+                               continue;
+                       }
+
+                       /* Ignore LINKEDIT segments */
+                       if (streq_safe(seg_hdr->segname, SEG_LINKEDIT,
+                           const_strlen(SEG_LINKEDIT))) {
+                               continue;
+                       }
+
+                       require_action(!kxld_object_is_32_bit(object), finish, rval = KERN_FAILURE;
+                           kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
+                           "LC_SEGMENT_64 in a 32-bit kext."));
+                       require_action(!has_segment, finish, rval = KERN_FAILURE;
+                           kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
+                           "Multiple segments in an MH_OBJECT kext."));
+
+                       nsects = seg_hdr->nsects;
+                       sect_offset = offset + sizeof(*seg_hdr);
+                       has_segment = TRUE;
+               }
+               break;
 #endif /* KXLD_USER_OR_LP64 */
-        case LC_SYMTAB:
-            symtab_hdr = (struct symtab_command *) cmd_hdr;
-
-            KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
-                kxld_symtab_init_from_macho_32, kxld_symtab_init_from_macho_64,
-                object->symtab, symtab_hdr, object->file,
-                /* kernel_linkedit_seg */ NULL);
-            require_noerr(rval, finish);
-            break;
-        case LC_UUID:
-            uuid_hdr = (struct uuid_command *) cmd_hdr;
-            kxld_uuid_init_from_macho(&object->uuid, uuid_hdr);
-            break;
-        case LC_UNIXTHREAD:
-        case LC_MAIN:
-            /* Don't need to do anything with UNIXTHREAD or MAIN */
-            break;
-        case LC_CODE_SIGNATURE:
-        case LC_DYLD_INFO:
-        case LC_DYLD_INFO_ONLY:
-        case LC_FUNCTION_STARTS:
-        case LC_DATA_IN_CODE:
-        case LC_DYLIB_CODE_SIGN_DRS:
-            /* Various metadata that might be stored in the linkedit segment */
-            break;
-        case LC_VERSION_MIN_MACOSX:
-        case LC_VERSION_MIN_IPHONEOS:
-        case LC_VERSION_MIN_WATCHOS:
-        case LC_SOURCE_VERSION:
-            /* Not supported for object files, fall through */
-        default:
-            rval = KERN_FAILURE;
-            kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
-                "Invalid load command type in MH_OBJECT kext: %u.", cmd_hdr->cmd);
-            goto finish;
-        }
-    }
-
-    if (has_segment) {
-
-        /* Get the number of sections from the segment and build the section index */
-
-        rval = kxld_array_init(&object->sects, sizeof(KXLDSect), nsects);
-        require_noerr(rval, finish);
-
-        /* Loop over all of the sections to initialize the section index */
-
-        for (i = 0; i < nsects; ++i) {
-            sect = kxld_array_get_item(&object->sects, i);
-            KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
-                kxld_sect_init_from_macho_32, kxld_sect_init_from_macho_64,
-                sect, object->file, &sect_offset, i, &object->relocator); 
-            require_noerr(rval, finish);
-        }
-
-        /* Create special sections */
+               case LC_SYMTAB:
+                       symtab_hdr = (struct symtab_command *) cmd_hdr;
+
+                       KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
+                           kxld_symtab_init_from_macho_32, kxld_symtab_init_from_macho_64,
+                           object->symtab, symtab_hdr, my_file,
+                           /* kernel_linkedit_seg */ NULL);
+                       require_noerr(rval, finish);
+                       break;
+               case LC_UUID:
+                       uuid_hdr = (struct uuid_command *) cmd_hdr;
+                       kxld_uuid_init_from_macho(&object->uuid, uuid_hdr);
+                       break;
+               case LC_UNIXTHREAD:
+               case LC_MAIN:
+                       /* Don't need to do anything with UNIXTHREAD or MAIN */
+                       break;
+               case LC_CODE_SIGNATURE:
+               case LC_DYLD_INFO:
+               case LC_DYLD_INFO_ONLY:
+               case LC_FUNCTION_STARTS:
+               case LC_DATA_IN_CODE:
+               case LC_DYLIB_CODE_SIGN_DRS:
+                       /* Various metadata that might be stored in the linkedit segment */
+                       break;
+               case LC_NOTE:
+                       /* bag-of-bits carried with the binary: ignore */
+                       break;
+               case LC_BUILD_VERSION:
+                       /* should be able to ignore build version commands */
+                       kxld_log(kKxldLogLinking, kKxldLogWarn,
+                           "Ignoring LC_BUILD_VERSION (%u) in MH_OBJECT kext: (platform:%d)",
+                           cmd_hdr->cmd, ((struct build_version_command *)cmd_hdr)->platform);
+                       break;
+               case LC_VERSION_MIN_MACOSX:
+               case LC_VERSION_MIN_IPHONEOS:
+               case LC_VERSION_MIN_TVOS:
+               case LC_VERSION_MIN_WATCHOS:
+               case LC_SOURCE_VERSION:
+               /* Not supported for object files, fall through */
+               default:
+                       rval = KERN_FAILURE;
+                       kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
+                           "Invalid load command type in MH_OBJECT kext: %u.", cmd_hdr->cmd);
+                       goto finish;
+               }
+       }
+
+       if (has_segment) {
+               /* Get the number of sections from the segment and build the section index */
+
+               rval = kxld_array_init(&object->sects, sizeof(KXLDSect), nsects);
+               require_noerr(rval, finish);
+
+               /* Loop over all of the sections to initialize the section index */
+
+               for (i = 0; i < nsects; ++i) {
+                       sect = kxld_array_get_item(&object->sects, i);
+
+                       KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
+                           kxld_sect_init_from_macho_32, kxld_sect_init_from_macho_64,
+                           sect, my_file, &sect_offset, i, &object->relocator);
+                       require_noerr(rval, finish);
+               }
+
+               /* Create special sections */
 
 #if KXLD_USER_OR_GOT
-        rval = create_got(object);
-        require_noerr(rval, finish);
+               rval = create_got(object);
+               require_noerr(rval, finish);
 #endif /* KXLD_USER_OR_GOT */
 
 #if KXLD_USER_OR_COMMON
-        rval = resolve_common_symbols(object);
-        require_noerr(rval, finish);
+               rval = resolve_common_symbols(object);
+               require_noerr(rval, finish);
 #endif /* KXLD_USER_OR_COMMON */
 
-        /* Create the segments from the section index */
+               /* Create the segments from the section index */
 
-        rval = kxld_seg_create_seg_from_sections(&object->segs, &object->sects);
-        require_noerr(rval, finish);
+               rval = kxld_seg_create_seg_from_sections(&object->segs, &object->sects);
+               require_noerr(rval, finish);
 
-        rval = kxld_seg_finalize_object_segment(&object->segs, 
-            object->section_order, get_macho_header_size(object));
-        require_noerr(rval, finish);
+               rval = kxld_seg_finalize_object_segment(&object->segs,
+                   object->section_order, get_macho_header_size(object));
+               require_noerr(rval, finish);
 
-        rval = kxld_seg_init_linkedit(&object->segs);
-        require_noerr(rval, finish);
-    }
+               rval = kxld_seg_init_linkedit(&object->segs);
+               require_noerr(rval, finish);
+       }
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 #endif /* KXLD_USER_OR_OBJECT */
 
@@ -1026,12 +1154,16 @@ finish:
 static u_long
 get_macho_cmd_data_32(u_char *file, u_long offset, u_int *filetype, u_int *ncmds)
 {
-    struct mach_header *mach_hdr = (struct mach_header *) ((void *) (file + offset));
+       struct mach_header *mach_hdr = (struct mach_header *) ((void *) (file + offset));
 
-    if (filetype) *filetype = mach_hdr->filetype;
-    if (ncmds) *ncmds = mach_hdr->ncmds;
+       if (filetype) {
+               *filetype = mach_hdr->filetype;
+       }
+       if (ncmds) {
+               *ncmds = mach_hdr->ncmds;
+       }
 
-    return sizeof(*mach_hdr);
+       return sizeof(*mach_hdr);
 }
 
 #endif /* KXLD_USER_OR_ILP32 */
@@ -1040,14 +1172,18 @@ get_macho_cmd_data_32(u_char *file, u_long offset, u_int *filetype, u_int *ncmds
 /*******************************************************************************
 *******************************************************************************/
 static u_long
-get_macho_cmd_data_64(u_char *file, u_long offset, u_int *filetype,  u_int *ncmds)
+get_macho_cmd_data_64(u_char *file, u_long offset, u_int *filetype, u_int *ncmds)
 {
-    struct mach_header_64 *mach_hdr = (struct mach_header_64 *) ((void *) (file + offset));
+       struct mach_header_64 *mach_hdr = (struct mach_header_64 *) ((void *) (file + offset));
 
-    if (filetype) *filetype = mach_hdr->filetype;
-    if (ncmds) *ncmds = mach_hdr->ncmds;
+       if (filetype) {
+               *filetype = mach_hdr->filetype;
+       }
+       if (ncmds) {
+               *ncmds = mach_hdr->ncmds;
+       }
 
-    return sizeof(*mach_hdr);
+       return sizeof(*mach_hdr);
 }
 #endif /* KXLD_USER_OR_LP64 */
 
@@ -1056,43 +1192,47 @@ get_macho_cmd_data_64(u_char *file, u_long offset, u_int *filetype,  u_int *ncmd
 static u_long
 get_macho_header_size(const KXLDObject *object)
 {
-    KXLDSeg *seg = NULL;
-    u_long header_size = 0;
-    u_int i = 0;
-    boolean_t   object_is_32_bit = kxld_object_is_32_bit(object);
+       KXLDSeg *seg = NULL;
+       u_long header_size = 0;
+       u_int i = 0;
+       boolean_t   object_is_32_bit = kxld_object_is_32_bit(object);
 
-    check(object);
+       check(object);
 
-    /* Mach, segment, symtab, and UUID headers */
+       /* Mach, segment, symtab, and UUID headers */
 
-    header_size += object_is_32_bit ? sizeof(struct mach_header) : sizeof(struct mach_header_64);
+       header_size += object_is_32_bit ? sizeof(struct mach_header) : sizeof(struct mach_header_64);
 
-    for (i = 0; i < object->segs.nitems; ++i) {
-        seg = kxld_array_get_item(&object->segs, i);
-        header_size += kxld_seg_get_macho_header_size(seg, object_is_32_bit);
-    }
+       for (i = 0; i < object->segs.nitems; ++i) {
+               seg = kxld_array_get_item(&object->segs, i);
+               header_size += kxld_seg_get_macho_header_size(seg, object_is_32_bit);
+       }
 
-    header_size += kxld_symtab_get_macho_header_size();
+       header_size += kxld_symtab_get_macho_header_size();
 
 #if KXLD_PIC_KEXTS
-    if (target_supports_slideable_kexts(object)) {
-        header_size += kxld_reloc_get_macho_header_size();
-    }
-#endif /* KXLD_PIC_KEXTS */
+       if (target_supports_slideable_kexts(object)) {
+               header_size += kxld_reloc_get_macho_header_size();
+       }
+#endif  /* KXLD_PIC_KEXTS */
 
-    if (object->uuid.has_uuid) {
-        header_size += kxld_uuid_get_macho_header_size();
-    }
+       if (object->uuid.has_uuid) {
+               header_size += kxld_uuid_get_macho_header_size();
+       }
 
-    if (object->versionmin.has_versionmin) {
-        header_size += kxld_versionmin_get_macho_header_size();
-    }
+       if (object->versionmin.has_versionmin) {
+               header_size += kxld_versionmin_get_macho_header_size(&object->versionmin);
+       }
 
-    if (object->srcversion.has_srcversion) {
-        header_size += kxld_srcversion_get_macho_header_size();
-    }
-    
-    return header_size;
+       if (object->srcversion.has_srcversion) {
+               header_size += kxld_srcversion_get_macho_header_size();
+       }
+
+       if (isSplitKext && object->splitinfolc.has_splitinfolc) {
+               header_size += kxld_splitinfolc_get_macho_header_size();
+       }
+
+       return header_size;
 }
 
 /*******************************************************************************
@@ -1100,66 +1240,67 @@ get_macho_header_size(const KXLDObject *object)
 static u_long
 get_macho_data_size(const KXLDObject *object)
 {
-    KXLDSeg *seg = NULL;
-    u_long data_size = 0;
-    u_int i = 0;
+       KXLDSeg *seg = NULL;
+       u_long data_size = 0;
+       u_int i = 0;
 
-    check(object);
+       check(object);
 
-    /* total all segment vmsize values */
-    for (i = 0; i < object->segs.nitems; ++i) {
-        seg = kxld_array_get_item(&object->segs, i);
-        data_size += (u_long) kxld_seg_get_vmsize(seg);
-    }
+       /* total all segment vmsize values */
+       for (i = 0; i < object->segs.nitems; ++i) {
+               seg = kxld_array_get_item(&object->segs, i);
+               data_size += (u_long) kxld_seg_get_vmsize(seg);
+       }
 
 #if KXLD_PIC_KEXTS
-    {
-        /* ensure that when we eventually emit the final linked object, 
-         * appending the __DYSYMTAB data after the __LINKEDIT data will
-         * not overflow the space allocated for the __LINKEDIT segment
-         */
-        
-        u_long  seg_vmsize = 0;
-        u_long  symtab_size = 0;
-        u_long  reloc_size = 0;
-        
-        /* get current __LINKEDIT sizes */
-        seg = kxld_object_get_seg_by_name(object, SEG_LINKEDIT);
-        seg_vmsize = (u_long) kxld_seg_get_vmsize(seg);
-        
-        /* get size of symbol table data that will eventually be dumped
-         * into the __LINKEDIT segment
-         */
-        symtab_size = kxld_symtab_get_macho_data_size(object->symtab, kxld_object_is_32_bit(object));
-        
-        if (target_supports_slideable_kexts(object)) {
-            /* get size of __DYSYMTAB relocation entries */
-            reloc_size = kxld_reloc_get_macho_data_size(&object->locrelocs, &object->extrelocs);
-        }
-        
-        /* combine, and ensure they'll both fit within the page(s)
-         * allocated for the __LINKEDIT segment. If they'd overflow,
-         * increase the vmsize appropriately so no overflow will occur
-         */
-        if ((symtab_size + reloc_size) > seg_vmsize) {
-            u_long  overflow = (symtab_size + reloc_size) - seg_vmsize;
-            data_size += kxld_round_page_cross_safe(overflow);
-        }
-    }
+       {
+               /* ensure that when we eventually emit the final linked object,
+                * appending the __DYSYMTAB data after the __LINKEDIT data will
+                * not overflow the space allocated for the __LINKEDIT segment
+                */
+
+               u_long  seg_vmsize = 0;
+               u_long  symtab_size = 0;
+               u_long  reloc_size = 0;
+
+               /* get current __LINKEDIT sizes */
+               seg = kxld_object_get_seg_by_name(object, SEG_LINKEDIT);
+
+               seg_vmsize = (u_long) kxld_seg_get_vmsize(seg);
+
+               /* get size of symbol table data that will eventually be dumped
+                * into the __LINKEDIT segment
+                */
+               symtab_size = kxld_symtab_get_macho_data_size(object->symtab, kxld_object_is_32_bit(object));
+
+               if (target_supports_slideable_kexts(object)) {
+                       /* get size of __DYSYMTAB relocation entries */
+                       reloc_size = kxld_reloc_get_macho_data_size(&object->locrelocs, &object->extrelocs);
+               }
+
+               /* combine, and ensure they'll both fit within the page(s)
+                * allocated for the __LINKEDIT segment. If they'd overflow,
+                * increase the vmsize appropriately so no overflow will occur
+                */
+               if ((symtab_size + reloc_size) > seg_vmsize) {
+                       u_long  overflow = (symtab_size + reloc_size) - seg_vmsize;
+                       data_size += kxld_round_page_cross_safe(overflow);
+               }
+       }
 #endif  // KXLD_PIC_KEXTS
 
-    return data_size;
+       return data_size;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-boolean_t 
+boolean_t
 kxld_object_target_needs_swap(const KXLDObject *object __unused)
 {
 #if KERNEL
-    return FALSE;
+       return FALSE;
 #else
-    return (object->target_order != object->host_order);
+       return object->target_order != object->host_order;
 #endif /* KERNEL */
 }
 
@@ -1168,132 +1309,139 @@ kxld_object_target_needs_swap(const KXLDObject *object __unused)
 KXLDSeg *
 kxld_object_get_seg_by_name(const KXLDObject *object, const char *segname)
 {
-    KXLDSeg *seg = NULL;
-    u_int i = 0;
+       KXLDSeg *seg = NULL;
+       u_int i = 0;
 
-    for (i = 0; i < object->segs.nitems; ++i) {
-        seg = kxld_array_get_item(&object->segs, i);
+       for (i = 0; i < object->segs.nitems; ++i) {
+               seg = kxld_array_get_item(&object->segs, i);
 
-        if (streq_safe(segname, seg->segname, sizeof(seg->segname))) break;
+               if (streq_safe(segname, seg->segname, sizeof(seg->segname))) {
+                       break;
+               }
 
-        seg = NULL;
-    }
+               seg = NULL;
+       }
 
-    return seg;
+       return seg;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-const KXLDRelocator * 
+const KXLDRelocator *
 kxld_object_get_relocator(const KXLDObject * object)
 {
-    check(object);
+       check(object);
 
-    return &object->relocator;
+       return &object->relocator;
 }
 
 /*******************************************************************************
 *******************************************************************************/
 KXLDSect *
-kxld_object_get_sect_by_name(const KXLDObject *object, const char *segname, 
+kxld_object_get_sect_by_name(const KXLDObject *object, const char *segname,
     const char *sectname)
 {
-    KXLDSect *sect = NULL;
-    u_int i = 0;
+       KXLDSect *sect = NULL;
+       u_int i = 0;
 
-    for (i = 0; i < object->sects.nitems; ++i) {
-        sect = kxld_array_get_item(&object->sects, i);
+       for (i = 0; i < object->sects.nitems; ++i) {
+               sect = kxld_array_get_item(&object->sects, i);
 
-        if (streq_safe(segname, sect->segname, sizeof(sect->segname)) && 
-            streq_safe(sectname, sect->sectname, sizeof(sect->sectname))) 
-        {
-            break;
-        }
+               if (streq_safe(segname, sect->segname, sizeof(sect->segname)) &&
+                   streq_safe(sectname, sect->sectname, sizeof(sect->sectname))) {
+                       break;
+               }
 
-        sect = NULL;
-    }
+               sect = NULL;
+       }
 
-    return sect;
+       return sect;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-const KXLDReloc * 
+const KXLDReloc *
 kxld_object_get_reloc_at_symbol(const KXLDObject *object, const KXLDSym *sym)
 {
-    const KXLDReloc *reloc = NULL;
-    const KXLDSect *sect = NULL;
-    uint32_t offset = 0;
-
-    check(object);
-    check(sym);
-
-    sect = kxld_object_get_section_by_index(object, sym->sectnum);
-    require(sect, finish);
-
-    if (kxld_object_is_final_image(object)) {
-        reloc = kxld_reloc_get_reloc_by_offset(&object->extrelocs, 
-            sym->base_addr);
-        if (!reloc) {
-            reloc = kxld_reloc_get_reloc_by_offset(&object->locrelocs, 
-                sym->base_addr);
-        }
-    } else {
-        offset = kxld_sym_get_section_offset(sym, sect);
-        reloc = kxld_reloc_get_reloc_by_offset(&sect->relocs, offset);
-    }
+       const KXLDReloc *reloc = NULL;
+       const KXLDSect *sect = NULL;
+       uint32_t offset = 0;
+
+       check(object);
+       check(sym);
+
+       sect = kxld_object_get_section_by_index(object, sym->sectnum);
+       require(sect, finish);
+
+       if (kxld_object_is_final_image(object)) {
+               reloc = kxld_reloc_get_reloc_by_offset(&object->extrelocs,
+                   sym->base_addr);
+               if (!reloc) {
+                       reloc = kxld_reloc_get_reloc_by_offset(&object->locrelocs,
+                           sym->base_addr);
+               }
+       } else {
+               offset = kxld_sym_get_section_offset(sym, sect);
+               reloc = kxld_reloc_get_reloc_by_offset(&sect->relocs, offset);
+       }
 
 finish:
-    return reloc;
+       return reloc;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-const KXLDSym * 
-kxld_object_get_symbol_of_reloc(const KXLDObject *object, 
+const KXLDSym *
+kxld_object_get_symbol_of_reloc(const KXLDObject *object,
     const KXLDReloc *reloc, const KXLDSect *sect)
 {
-    const KXLDSym *sym = NULL;
-
-    if (kxld_object_is_final_image(object)) {
-        sym = kxld_reloc_get_symbol(&object->relocator, reloc, object->file);
-    } else {
-        sym = kxld_reloc_get_symbol(&object->relocator, reloc, sect->data);
-    }
-
-    return sym;
+       const KXLDSym *sym = NULL;
+       u_char *my_file;
+
+       if (isOldInterface) {
+               my_file = object->file;
+       } else {
+               my_file = object->split_info.kextExecutable;
+       }
+
+       if (kxld_object_is_final_image(object)) {
+               sym = kxld_reloc_get_symbol(&object->relocator, reloc, my_file);
+       } else {
+               sym = kxld_reloc_get_symbol(&object->relocator, reloc, sect->data);
+       }
+       return sym;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-const KXLDSect * 
+const KXLDSect *
 kxld_object_get_section_by_index(const KXLDObject *object, u_int sectnum)
 {
-    KXLDSect *sect = NULL;
-    
-    check(object);
+       KXLDSect *sect = NULL;
 
-    if (sectnum < object->sects.nitems) {
-        sect = kxld_array_get_item(&object->sects, sectnum);
-    }
+       check(object);
 
-    return sect;
+       if (sectnum < object->sects.nitems) {
+               sect = kxld_array_get_item(&object->sects, sectnum);
+       }
+
+       return sect;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-const KXLDArray  * 
+const KXLDArray  *
 kxld_object_get_extrelocs(const KXLDObject *object)
 {
-    const KXLDArray *rval = NULL;
-    
-    check(object);
+       const KXLDArray *rval = NULL;
+
+       check(object);
 
-    if (kxld_object_is_final_image(object)) {
-        rval = &object->extrelocs;
-    }
+       if (kxld_object_is_final_image(object)) {
+               rval = &object->extrelocs;
+       }
 
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -1301,9 +1449,9 @@ kxld_object_get_extrelocs(const KXLDObject *object)
 const KXLDSymtab *
 kxld_object_get_symtab(const KXLDObject *object)
 {
-    check(object);
+       check(object);
 
-    return object->symtab;
+       return object->symtab;
 }
 
 #if KXLD_USER_OR_GOT || KXLD_USER_OR_COMMON
@@ -1312,18 +1460,18 @@ kxld_object_get_symtab(const KXLDObject *object)
 static kern_return_t
 add_section(KXLDObject *object, KXLDSect **sect)
 {
-    kern_return_t rval = KERN_FAILURE;
-    u_int nsects = object->sects.nitems;
+       kern_return_t rval = KERN_FAILURE;
+       u_int nsects = object->sects.nitems;
 
-    rval = kxld_array_resize(&object->sects, nsects + 1);
-    require_noerr(rval, finish);
+       rval = kxld_array_resize(&object->sects, nsects + 1);
+       require_noerr(rval, finish);
 
-    *sect = kxld_array_get_item(&object->sects, nsects);
+       *sect = kxld_array_get_item(&object->sects, nsects);
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 
 finish:
-    return rval;
+       return rval;
 }
 #endif /* KXLD_USER_OR_GOT || KXLD_USER_OR_COMMON */
 
@@ -1336,72 +1484,74 @@ finish:
 static kern_return_t
 resolve_common_symbols(KXLDObject *object)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSymtabIterator iter;
-    KXLDSym *sym = NULL;
-    KXLDSect *sect = NULL;
-    kxld_addr_t base_addr = 0;
-    kxld_size_t size = 0;
-    kxld_size_t total_size = 0;
-    u_int align = 0;
-    u_int max_align = 0;
-    u_int sectnum = 0;
-
-    if (!kxld_object_target_supports_common_symbols(object)) {
-        rval = KERN_SUCCESS;
-        goto finish;
-    }
-
-    /* Iterate over the common symbols to calculate their total aligned size */
-    kxld_symtab_iterator_init(&iter, object->symtab, kxld_sym_is_common, FALSE);
-    while ((sym = kxld_symtab_iterator_get_next(&iter))) {
-        align = kxld_sym_get_common_align(sym);
-        size = kxld_sym_get_common_size(sym);
-
-        if (align > max_align) max_align = align;
-
-        total_size = kxld_align_address(total_size, align) + size;
-    }
-
-    /* If there are common symbols, grow or create the __DATA __common section
-     * to hold them.
-     */
-    if (total_size) {
-        sect = kxld_object_get_sect_by_name(object, SEG_DATA, SECT_COMMON);
-        if (sect) {
-            base_addr = sect->base_addr + sect->size;
-
-            kxld_sect_grow(sect, total_size, max_align);
-        } else {
-            base_addr = 0;
-
-            rval = add_section(object, &sect);
-            require_noerr(rval, finish);
-
-            kxld_sect_init_zerofill(sect, SEG_DATA, SECT_COMMON, 
-                total_size, max_align);
-        }
-
-        /* Resolve the common symbols against the new section */
-        rval = kxld_array_get_index(&object->sects, sect, &sectnum);
-        require_noerr(rval, finish);
-
-        kxld_symtab_iterator_reset(&iter);
-        while ((sym = kxld_symtab_iterator_get_next(&iter))) {
-            align = kxld_sym_get_common_align(sym);
-            size = kxld_sym_get_common_size(sym);
-
-            base_addr = kxld_align_address(base_addr, align);
-            kxld_sym_resolve_common(sym, sectnum, base_addr);
-
-            base_addr += size;
-        }
-    }
-
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSymtabIterator iter;
+       KXLDSym *sym = NULL;
+       KXLDSect *sect = NULL;
+       kxld_addr_t base_addr = 0;
+       kxld_size_t size = 0;
+       kxld_size_t total_size = 0;
+       u_int align = 0;
+       u_int max_align = 0;
+       u_int sectnum = 0;
+
+       if (!kxld_object_target_supports_common_symbols(object)) {
+               rval = KERN_SUCCESS;
+               goto finish;
+       }
+
+       /* Iterate over the common symbols to calculate their total aligned size */
+       kxld_symtab_iterator_init(&iter, object->symtab, kxld_sym_is_common, FALSE);
+       while ((sym = kxld_symtab_iterator_get_next(&iter))) {
+               align = kxld_sym_get_common_align(sym);
+               size = kxld_sym_get_common_size(sym);
+
+               if (align > max_align) {
+                       max_align = align;
+               }
+
+               total_size = kxld_align_address(total_size, align) + size;
+       }
+
+       /* If there are common symbols, grow or create the __DATA __common section
+        * to hold them.
+        */
+       if (total_size) {
+               sect = kxld_object_get_sect_by_name(object, SEG_DATA, SECT_COMMON);
+               if (sect) {
+                       base_addr = sect->base_addr + sect->size;
+
+                       kxld_sect_grow(sect, total_size, max_align);
+               } else {
+                       base_addr = 0;
+
+                       rval = add_section(object, &sect);
+                       require_noerr(rval, finish);
+
+                       kxld_sect_init_zerofill(sect, SEG_DATA, SECT_COMMON,
+                           total_size, max_align);
+               }
+
+               /* Resolve the common symbols against the new section */
+               rval = kxld_array_get_index(&object->sects, sect, &sectnum);
+               require_noerr(rval, finish);
+
+               kxld_symtab_iterator_reset(&iter);
+               while ((sym = kxld_symtab_iterator_get_next(&iter))) {
+                       align = kxld_sym_get_common_align(sym);
+                       size = kxld_sym_get_common_size(sym);
+
+                       base_addr = kxld_align_address(base_addr, align);
+                       kxld_sym_resolve_common(sym, sectnum, base_addr);
+
+                       base_addr += size;
+               }
+       }
+
+       rval = KERN_SUCCESS;
 
 finish:
-    return rval;
+       return rval;
 }
 #endif /* KXLD_USER_OR_COMMON */
 
@@ -1411,7 +1561,7 @@ finish:
 static boolean_t
 target_has_got(const KXLDObject *object)
 {
-    return FALSE:
+       return FALSE:
 }
 
 /*******************************************************************************
@@ -1420,33 +1570,33 @@ target_has_got(const KXLDObject *object)
 static kern_return_t
 create_got(KXLDObject *object)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSect *sect = NULL;
-    u_int ngots = 0;
-    u_int i = 0;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSect *sect = NULL;
+       u_int ngots = 0;
+       u_int i = 0;
 
-    if (!target_has_got(object)) {
-        rval = KERN_SUCCESS;
-        goto finish;
-    }
+       if (!target_has_got(object)) {
+               rval = KERN_SUCCESS;
+               goto finish;
+       }
 
-    for (i = 0; i < object->sects.nitems; ++i) {
-        sect = kxld_array_get_item(&object->sects, i);
-        ngots += kxld_sect_get_ngots(sect, &object->relocator, 
-            object->symtab);
-    }
+       for (i = 0; i < object->sects.nitems; ++i) {
+               sect = kxld_array_get_item(&object->sects, i);
+               ngots += kxld_sect_get_ngots(sect, &object->relocator,
+                   object->symtab);
+       }
 
-    rval = add_section(object, &sect);
-    require_noerr(rval, finish);
+       rval = add_section(object, &sect);
+       require_noerr(rval, finish);
 
-    rval = kxld_sect_init_got(sect, ngots);
-    require_noerr(rval, finish);
+       rval = kxld_sect_init_got(sect, ngots);
+       require_noerr(rval, finish);
 
-    object->got_is_created = TRUE;
-    rval = KERN_SUCCESS;
+       object->got_is_created = TRUE;
+       rval = KERN_SUCCESS;
 
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -1454,32 +1604,31 @@ finish:
 static kern_return_t
 populate_got(KXLDObject *object)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSect *sect = NULL;
-    u_int i = 0;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSect *sect = NULL;
+       u_int i = 0;
 
-    if (!target_has_got(object) || !object->got_is_created) {
-        rval = KERN_SUCCESS;
-        goto finish;
-    }
+       if (!target_has_got(object) || !object->got_is_created) {
+               rval = KERN_SUCCESS;
+               goto finish;
+       }
 
-    for (i = 0; i < object->sects.nitems; ++i) {
-        sect = kxld_array_get_item(&object->sects, i);
-        if (streq_safe(sect->segname, KXLD_SEG_GOT, sizeof(KXLD_SEG_GOT)) &&
-            streq_safe(sect->sectname, KXLD_SECT_GOT, sizeof(KXLD_SECT_GOT)))
-        {
-            kxld_sect_populate_got(sect, object->symtab,
-                kxld_object_target_needs_swap(object));
-            break;
-        }
-    }
+       for (i = 0; i < object->sects.nitems; ++i) {
+               sect = kxld_array_get_item(&object->sects, i);
+               if (streq_safe(sect->segname, KXLD_SEG_GOT, sizeof(KXLD_SEG_GOT)) &&
+                   streq_safe(sect->sectname, KXLD_SECT_GOT, sizeof(KXLD_SECT_GOT))) {
+                       kxld_sect_populate_got(sect, object->symtab,
+                           kxld_object_target_needs_swap(object));
+                       break;
+               }
+       }
 
-    require_action(i < object->sects.nitems, finish, rval=KXLD_MISSING_GOT);
+       require_action(i < object->sects.nitems, finish, rval = KXLD_MISSING_GOT);
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 
 finish:
-    return rval;
+       return rval;
 }
 #endif /* KXLD_USER_OR_GOT */
 
@@ -1488,10 +1637,10 @@ finish:
 static boolean_t
 target_supports_protected_segments(const KXLDObject *object)
 {
-    return (object->is_final_image && 
-            (object->cputype == CPU_TYPE_X86_64 ||
-             object->cputype == CPU_TYPE_ARM ||
-             object->cputype == CPU_TYPE_ARM64));
+       return object->is_final_image &&
+              (object->cputype == CPU_TYPE_X86_64 ||
+              object->cputype == CPU_TYPE_ARM ||
+              object->cputype == CPU_TYPE_ARM64);
 }
 
 /*******************************************************************************
@@ -1499,122 +1648,146 @@ target_supports_protected_segments(const KXLDObject *object)
 static void
 set_is_object_linked(KXLDObject *object)
 {
-    u_int i = 0;
-
-    if (kxld_object_is_kernel(object)) {
-        object->is_linked = TRUE;
-        return;
-    }
-
-    if (object->is_final_image) {
-        object->is_linked = !object->extrelocs.nitems;
-        return;
-    }
-
-    object->is_linked = TRUE;
-    for (i = 0; i < object->sects.nitems; ++i) {
-        KXLDSect *sect = kxld_array_get_item(&object->sects, i);
-        if (sect->relocs.nitems) {
-            object->is_linked = FALSE;
-            break;
-        }
-    }
+       u_int i = 0;
+
+       if (kxld_object_is_kernel(object)) {
+               object->is_linked = TRUE;
+               return;
+       }
+
+       if (object->is_final_image) {
+               object->is_linked = !object->extrelocs.nitems;
+               return;
+       }
+
+       object->is_linked = TRUE;
+       for (i = 0; i < object->sects.nitems; ++i) {
+               KXLDSect *sect = kxld_array_get_item(&object->sects, i);
+               if (sect->relocs.nitems) {
+                       object->is_linked = FALSE;
+                       break;
+               }
+       }
 }
 
 
 /*******************************************************************************
 *******************************************************************************/
-void kxld_object_clear(KXLDObject *object __unused)
+void
+kxld_object_clear(KXLDObject *object)
 {
-    KXLDSeg *seg = NULL;
-    KXLDSect *sect = NULL;
-    u_int i;
+       KXLDSeg *seg = NULL;
+       KXLDSect *sect = NULL;
+       u_int i;
+       u_char *my_file;
 
-    check(object);
+       check(object);
+
+       if (isOldInterface) {
+               my_file = object->file;
+       } else {
+               my_file = object->split_info.kextExecutable;
+       }
 
 #if !KERNEL
-    if (kxld_object_is_kernel(object)) {
-        unswap_macho(object->file, object->host_order, object->target_order);
-    }
+       if (kxld_object_is_kernel(object)) {
+               unswap_macho(my_file, object->host_order, object->target_order);
+       }
 #endif /* !KERNEL */
 
-    for (i = 0; i < object->segs.nitems; ++i) {
-        seg = kxld_array_get_item(&object->segs, i);
-        kxld_seg_clear(seg);
-    }
-    kxld_array_reset(&object->segs);
-
-    for (i = 0; i < object->sects.nitems; ++i) {
-        sect = kxld_array_get_item(&object->sects, i);
-        kxld_sect_clear(sect);
-    }
-    kxld_array_reset(&object->sects);
-
-    kxld_array_reset(&object->extrelocs);
-    kxld_array_reset(&object->locrelocs);
-    kxld_relocator_clear(&object->relocator);
-    kxld_uuid_clear(&object->uuid);
-    kxld_versionmin_clear(&object->versionmin);
-    kxld_srcversion_clear(&object->srcversion);
-
-    if (object->symtab) kxld_symtab_clear(object->symtab);
-
-    object->file = NULL;
-    object->size = 0;
-    object->filetype = 0;
-    object->cputype = 0;
-    object->cpusubtype = 0;
-    object->is_kernel = FALSE;
-    object->is_final_image = FALSE;
-    object->is_linked = FALSE;
-    object->got_is_created = FALSE;
+       for (i = 0; i < object->segs.nitems; ++i) {
+               seg = kxld_array_get_item(&object->segs, i);
+               kxld_seg_clear(seg);
+       }
+       kxld_array_reset(&object->segs);
+
+       for (i = 0; i < object->sects.nitems; ++i) {
+               sect = kxld_array_get_item(&object->sects, i);
+               kxld_sect_clear(sect);
+       }
+       kxld_array_reset(&object->sects);
+
+       kxld_array_reset(&object->extrelocs);
+       kxld_array_reset(&object->locrelocs);
+       kxld_relocator_clear(&object->relocator);
+       kxld_uuid_clear(&object->uuid);
+       kxld_versionmin_clear(&object->versionmin);
+       kxld_srcversion_clear(&object->srcversion);
+
+       if (object->symtab) {
+               kxld_symtab_clear(object->symtab);
+       }
+
+       if (isOldInterface) {
+               object->file = NULL;
+               object->size = 0;
+       } else {
+               kxld_splitinfolc_clear(&object->splitinfolc);
+               object->split_info.kextExecutable = NULL;
+               object->split_info.kextSize = 0;
+       }
+       object->filetype = 0;
+       object->cputype = 0;
+       object->cpusubtype = 0;
+       object->is_kernel = FALSE;
+       object->is_final_image = FALSE;
+       object->is_linked = FALSE;
+       object->got_is_created = FALSE;
 
 #if KXLD_USER_OR_OBJECT
-    object->section_order = NULL;
+       object->section_order = NULL;
 #endif
 #if !KERNEL
-    object->host_order = 0;
-    object->target_order = 0;
+       object->host_order = 0;
+       object->target_order = 0;
 #endif
 }
 
 /*******************************************************************************
 *******************************************************************************/
-void kxld_object_deinit(KXLDObject *object __unused)
+void
+kxld_object_deinit(KXLDObject *object __unused)
 {
-    KXLDSeg *seg = NULL;
-    KXLDSect *sect = NULL;
-    u_int i;
+       KXLDSeg *seg = NULL;
+       KXLDSect *sect = NULL;
+       u_int i;
+       u_char *my_file;
 
-    check(object);
+       check(object);
+
+       if (isOldInterface) {
+               my_file = object->file;
+       } else {
+               my_file = object->split_info.kextExecutable;
+       }
 
 #if !KERNEL
-    if (object->file && kxld_object_is_kernel(object)) {
-        unswap_macho(object->file, object->host_order, object->target_order);
-    }
+       if (my_file && kxld_object_is_kernel(object)) {
+               unswap_macho(my_file, object->host_order, object->target_order);
+       }
 #endif /* !KERNEL */
 
-    for (i = 0; i < object->segs.maxitems; ++i) {
-        seg = kxld_array_get_slot(&object->segs, i);
-        kxld_seg_deinit(seg);
-    }
-    kxld_array_deinit(&object->segs);
+       for (i = 0; i < object->segs.maxitems; ++i) {
+               seg = kxld_array_get_slot(&object->segs, i);
+               kxld_seg_deinit(seg);
+       }
+       kxld_array_deinit(&object->segs);
 
-    for (i = 0; i < object->sects.maxitems; ++i) {
-        sect = kxld_array_get_slot(&object->sects, i);
-        kxld_sect_deinit(sect);
-    }
-    kxld_array_deinit(&object->sects);
+       for (i = 0; i < object->sects.maxitems; ++i) {
+               sect = kxld_array_get_slot(&object->sects, i);
+               kxld_sect_deinit(sect);
+       }
+       kxld_array_deinit(&object->sects);
 
-    kxld_array_deinit(&object->extrelocs);
-    kxld_array_deinit(&object->locrelocs);
+       kxld_array_deinit(&object->extrelocs);
+       kxld_array_deinit(&object->locrelocs);
 
-    if (object->symtab) {
-        kxld_symtab_deinit(object->symtab);
-        kxld_free(object->symtab, kxld_symtab_sizeof());
-    }
+       if (object->symtab) {
+               kxld_symtab_deinit(object->symtab);
+               kxld_free(object->symtab, kxld_symtab_sizeof());
+       }
 
-    bzero(object, sizeof(*object));
+       bzero(object, sizeof(*object));
 }
 
 /*******************************************************************************
@@ -1622,9 +1795,17 @@ void kxld_object_deinit(KXLDObject *object __unused)
 const u_char *
 kxld_object_get_file(const KXLDObject *object)
 {
-    check(object);
+       const u_char *my_file;
+
+       check(object);
 
-    return object->file;
+       if (isOldInterface) {
+               my_file = object->file;
+       } else {
+               my_file = object->split_info.kextExecutable;
+       }
+
+       return my_file;
 }
 
 /*******************************************************************************
@@ -1632,49 +1813,49 @@ kxld_object_get_file(const KXLDObject *object)
 const char *
 kxld_object_get_name(const KXLDObject *object)
 {
-    check(object);
+       check(object);
 
-    return object->name;
+       return object->name;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-boolean_t 
+boolean_t
 kxld_object_is_32_bit(const KXLDObject *object)
 {
-    check(object);
+       check(object);
 
-    return kxld_is_32_bit(object->cputype);
+       return kxld_is_32_bit(object->cputype);
 }
 
 /*******************************************************************************
 *******************************************************************************/
-boolean_t 
+boolean_t
 kxld_object_is_final_image(const KXLDObject *object)
 {
-    check(object);
+       check(object);
 
-    return object->is_final_image;
+       return object->is_final_image;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-boolean_t 
+boolean_t
 kxld_object_is_kernel(const KXLDObject *object)
 {
-    check(object);
+       check(object);
 
-    return object->is_kernel;
+       return object->is_kernel;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-boolean_t 
+boolean_t
 kxld_object_is_linked(const KXLDObject *object)
 {
-    check(object);
+       check(object);
 
-    return object->is_linked;
+       return object->is_linked;
 }
 
 /*******************************************************************************
@@ -1682,9 +1863,9 @@ kxld_object_is_linked(const KXLDObject *object)
 boolean_t
 kxld_object_target_supports_strict_patching(const KXLDObject *object)
 {
-    check(object);
+       check(object);
 
-    return (object->cputype != CPU_TYPE_I386);
+       return object->cputype != CPU_TYPE_I386;
 }
 
 /*******************************************************************************
@@ -1692,138 +1873,216 @@ kxld_object_target_supports_strict_patching(const KXLDObject *object)
 boolean_t
 kxld_object_target_supports_common_symbols(const KXLDObject *object)
 {
-    check(object);
+       check(object);
 
-    return (object->cputype == CPU_TYPE_I386);
+       return object->cputype == CPU_TYPE_I386;
 }
 
+
 /*******************************************************************************
 *******************************************************************************/
 void
-kxld_object_get_vmsize(const KXLDObject *object, u_long *header_size, 
+kxld_object_get_vmsize_for_seg_by_name(const KXLDObject *object,
+    const char *segname,
     u_long *vmsize)
 {
-    check(object);
-    check(header_size);
-    check(vmsize);
-    *header_size = 0;
-    *vmsize = 0;
+       check(object);
+       check(segname);
+       check(vmsize);
 
-    /* vmsize is the padded header page(s) + segment vmsizes */
+       KXLDSeg *seg = NULL;
+       u_long  my_size = 0;
 
-    *header_size = (object->is_final_image) ?
-        0 : (u_long)kxld_round_page_cross_safe(get_macho_header_size(object));
-    *vmsize = *header_size + get_macho_data_size(object);
+       /* segment vmsize */
+       seg = kxld_object_get_seg_by_name(object, segname);
 
+       my_size = (u_long) kxld_seg_get_vmsize(seg);
+
+#if KXLD_PIC_KEXTS
+       if (kxld_seg_is_linkedit_seg(seg)) {
+               u_long  reloc_size = 0;
+
+               if (target_supports_slideable_kexts(object)) {
+                       /* get size of __DYSYMTAB relocation entries */
+                       reloc_size = kxld_reloc_get_macho_data_size(&object->locrelocs, &object->extrelocs);
+                       my_size += reloc_size;
+               }
+       }
+#endif
+
+       *vmsize = my_size;
+}
+
+/*******************************************************************************
+*******************************************************************************/
+void
+kxld_object_get_vmsize(const KXLDObject *object, u_long *header_size,
+    u_long *vmsize)
+{
+       check(object);
+       check(header_size);
+       check(vmsize);
+       *header_size = 0;
+       *vmsize = 0;
+
+       /* vmsize is the padded header page(s) + segment vmsizes */
+
+       *header_size = (object->is_final_image) ?
+           0 : (u_long)kxld_round_page_cross_safe(get_macho_header_size(object));
+
+       *vmsize = *header_size + get_macho_data_size(object);
 }
 
 /*******************************************************************************
- *******************************************************************************/
+*******************************************************************************/
 void
 kxld_object_set_linked_object_size(KXLDObject *object, u_long vmsize)
 {
-    object->output_buffer_size = vmsize;       /* cache this for use later */
-    return;
+       check(object);
+
+       if (isOldInterface) {
+               object->output_buffer_size = vmsize; /* cache this for use later */
+       } else {
+               object->split_info.linkedKextSize = vmsize;
+       }
+       return;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-kern_return_t 
-kxld_object_export_linked_object(const KXLDObject *object, 
-    u_char *linked_object)
+kern_return_t
+kxld_object_export_linked_object(const KXLDObject *object,
+    void *linked_object
+    )
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSeg *seg = NULL;
-    u_long size = 0;
-    u_long header_size = 0;
-    u_long header_offset = 0;
-    u_long data_offset = 0;
-    u_int ncmds = 0;
-    u_int i = 0;
-    boolean_t   is_32bit_object = kxld_object_is_32_bit(object);
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSeg *seg = NULL;
+       u_long size = 0;
+       u_long header_size = 0;
+       u_long header_offset = 0;
+       u_long data_offset = 0;
+       u_int ncmds = 0;
+       u_int i = 0;
+       boolean_t   is_32bit_object = kxld_object_is_32_bit(object);
+       kxld_addr_t link_addr;
+       u_char *my_linked_object;
+
+       check(object);
+       check(linked_object);
+
+       if (isOldInterface) {
+               size = object->output_buffer_size;
+               link_addr = object->link_addr;
+               my_linked_object = (u_char *) linked_object;
+       } else {
+               size = ((splitKextLinkInfo *)linked_object)->linkedKextSize;
+               link_addr = ((splitKextLinkInfo *)linked_object)->vmaddr_TEXT;
+               my_linked_object = ((splitKextLinkInfo *)linked_object)->linkedKext;
+       }
+
+       /* Calculate the size of the headers and data */
+
+       header_size = get_macho_header_size(object);
+
+       /* Copy data to the file */
+
+       ncmds = object->segs.nitems + 1 /* LC_SYMTAB */;
 
-    check(object);
-    check(linked_object);
+#if KXLD_PIC_KEXTS
+       /* don't write out a DYSYMTAB segment for targets that can't digest it
+        */
+       if (target_supports_slideable_kexts(object)) {
+               ncmds++; /* dysymtab */
+       }
+#endif  /* KXLD_PIC_KEXTS */
 
-    /* Calculate the size of the headers and data */
+       if (object->uuid.has_uuid == TRUE) {
+               ncmds++;
+       }
 
-    header_size = get_macho_header_size(object);
-    size = object->output_buffer_size;
+       if (object->versionmin.has_versionmin == TRUE) {
+               ncmds++;
+       }
 
-    /* Copy data to the file */
+       if (object->srcversion.has_srcversion == TRUE) {
+               ncmds++;
+       }
 
-    ncmds = object->segs.nitems + 1 /* LC_SYMTAB */;
+       if (isSplitKext && object->splitinfolc.has_splitinfolc) {
+               ncmds++;
+       }
 
-#if KXLD_PIC_KEXTS
-    /* don't write out a DYSYMTAB segment for targets that can't digest it
-     */
-    if (target_supports_slideable_kexts(object)) {
-        ncmds++; /* dysymtab */
-    }
-#endif /* KXLD_PIC_KEXTS */
-
-    if (object->uuid.has_uuid == TRUE) {
-        ncmds++;
-    }
-
-    if (object->versionmin.has_versionmin == TRUE) {
-        ncmds++;
-    }
-
-    if (object->srcversion.has_srcversion == TRUE) {
-        ncmds++;
-    }
-    
-    rval = export_macho_header(object, linked_object, ncmds, &header_offset, header_size);
-    require_noerr(rval, finish);
-
-    for (i = 0; i < object->segs.nitems; ++i) {
-        seg = kxld_array_get_item(&object->segs, i);
-
-        rval = kxld_seg_export_macho_to_vm(seg, linked_object, &header_offset,
-            header_size, size, object->link_addr, is_32bit_object);
-        require_noerr(rval, finish);
-    }
-
-    seg = kxld_object_get_seg_by_name(object, SEG_LINKEDIT);
-    data_offset = (u_long) (seg->link_addr - object->link_addr);
-    
-    rval = kxld_symtab_export_macho(object->symtab, linked_object, &header_offset,
-        header_size, &data_offset, size, is_32bit_object);
-    require_noerr(rval, finish);
+       rval = export_macho_header(object, my_linked_object, ncmds, &header_offset, header_size);
+       require_noerr(rval, finish);
+
+       for (i = 0; i < object->segs.nitems; ++i) {
+               seg = kxld_array_get_item(&object->segs, i);
+
+               rval = kxld_seg_export_macho_to_vm(seg, my_linked_object, &header_offset,
+                   header_size, size, link_addr, is_32bit_object);
+               require_noerr(rval, finish);
+       }
+
+       seg = kxld_object_get_seg_by_name(object, SEG_LINKEDIT);
+       data_offset = (u_long) (seg->link_addr - link_addr);
+
+       // data_offset is used to set the fileoff in the macho header load commands
+       rval = kxld_symtab_export_macho(object->symtab,
+           my_linked_object,
+           &header_offset,
+           header_size,
+           &data_offset, size, is_32bit_object);
+       require_noerr(rval, finish);
+
+       // data_offset now points past the symbol tab and strings data in the linkedit
+       // segment - (it was used to set new values for symoff and stroff)
 
 #if KXLD_PIC_KEXTS
-    if (target_supports_slideable_kexts(object)) {
-        rval = kxld_reloc_export_macho(&object->relocator, &object->locrelocs,
-            &object->extrelocs, linked_object, &header_offset, header_size,
-            &data_offset, size);
-        require_noerr(rval, finish);
-    }
-#endif /* KXLD_PIC_KEXTS */
-
-    if (object->uuid.has_uuid) {
-        rval = kxld_uuid_export_macho(&object->uuid, linked_object, &header_offset, header_size);
-        require_noerr(rval, finish);
-    }
-
-    if (object->versionmin.has_versionmin) {
-        rval = kxld_versionmin_export_macho(&object->versionmin, linked_object, &header_offset, header_size);
-        require_noerr(rval, finish);
-    }
-
-    if (object->srcversion.has_srcversion) {
-        rval = kxld_srcversion_export_macho(&object->srcversion, linked_object, &header_offset, header_size);
-        require_noerr(rval, finish);
-    }
-    
+       if (target_supports_slideable_kexts(object)) {
+               rval = kxld_reloc_export_macho(&object->relocator,
+                   &object->locrelocs,
+                   &object->extrelocs,
+                   my_linked_object,
+                   &header_offset,
+                   header_size,
+                   &data_offset, size);
+               require_noerr(rval, finish);
+       }
+#endif  /* KXLD_PIC_KEXTS */
+
+       if (object->uuid.has_uuid) {
+               rval = kxld_uuid_export_macho(&object->uuid, my_linked_object, &header_offset, header_size);
+               require_noerr(rval, finish);
+       }
+
+       if (object->versionmin.has_versionmin) {
+               rval = kxld_versionmin_export_macho(&object->versionmin, my_linked_object, &header_offset, header_size);
+               require_noerr(rval, finish);
+       }
+
+       if (object->srcversion.has_srcversion) {
+               rval = kxld_srcversion_export_macho(&object->srcversion, my_linked_object, &header_offset, header_size);
+               require_noerr(rval, finish);
+       }
+
+       if (isSplitKext && object->splitinfolc.has_splitinfolc) {
+               rval = kxld_splitinfolc_export_macho(&object->splitinfolc,
+                   linked_object,
+                   &header_offset,
+                   header_size,
+                   &data_offset,
+                   size);
+               require_noerr(rval, finish);
+       }
+
 #if !KERNEL
-    unswap_macho(linked_object, object->host_order, object->target_order);
+       unswap_macho(my_linked_object, object->host_order, object->target_order);
 #endif /* KERNEL */
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -1832,21 +2091,21 @@ static kern_return_t
 export_macho_header(const KXLDObject *object, u_char *buf, u_int ncmds,
     u_long *header_offset, u_long header_size)
 {
-    kern_return_t rval = KERN_FAILURE;
+       kern_return_t rval = KERN_FAILURE;
 
-    check(object);
-    check(buf);
-    check(header_offset);
+       check(object);
+       check(buf);
+       check(header_offset);
 
-    KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval, 
-        export_macho_header_32, export_macho_header_64, 
-        object, buf, ncmds, header_offset, header_size);
-    require_noerr(rval, finish);
+       KXLD_3264_FUNC(kxld_object_is_32_bit(object), rval,
+           export_macho_header_32, export_macho_header_64,
+           object, buf, ncmds, header_offset, header_size);
+       require_noerr(rval, finish);
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 
 finish:
-    return rval;
+       return rval;
 }
 
 #if KXLD_USER_OR_ILP32
@@ -1856,31 +2115,31 @@ static kern_return_t
 export_macho_header_32(const KXLDObject *object, u_char *buf, u_int ncmds,
     u_long *header_offset, u_long header_size)
 {
-    kern_return_t rval = KERN_FAILURE;
-    struct mach_header *mach = NULL;
+       kern_return_t rval = KERN_FAILURE;
+       struct mach_header *mach = NULL;
 
-    check(object);
-    check(buf);
-    check(header_offset);
+       check(object);
+       check(buf);
+       check(header_offset);
 
-    require_action(sizeof(*mach) <= header_size - *header_offset, finish,
-        rval=KERN_FAILURE);
-    mach = (struct mach_header *) ((void *) (buf + *header_offset));
+       require_action(sizeof(*mach) <= header_size - *header_offset, finish,
+           rval = KERN_FAILURE);
+       mach = (struct mach_header *) ((void *) (buf + *header_offset));
 
-    mach->magic = MH_MAGIC;
-    mach->cputype = object->cputype;
-    mach->cpusubtype = object->cpusubtype;
-    mach->filetype = object->filetype;
-    mach->ncmds = ncmds;
-    mach->sizeofcmds = (uint32_t) (header_size - sizeof(*mach));
-    mach->flags = MH_NOUNDEFS;
+       mach->magic = MH_MAGIC;
+       mach->cputype = object->cputype;
+       mach->cpusubtype = object->cpusubtype;
+       mach->filetype = object->filetype;
+       mach->ncmds = ncmds;
+       mach->sizeofcmds = (uint32_t) (header_size - sizeof(*mach));
+       mach->flags = MH_NOUNDEFS;
 
-    *header_offset += sizeof(*mach);
+       *header_offset += sizeof(*mach);
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 
 finish:
-    return rval;
+       return rval;
 }
 #endif /* KXLD_USER_OR_ILP32 */
 
@@ -1891,76 +2150,90 @@ static kern_return_t
 export_macho_header_64(const KXLDObject *object, u_char *buf, u_int ncmds,
     u_long *header_offset, u_long header_size)
 {
-    kern_return_t rval = KERN_FAILURE;
-    struct mach_header_64 *mach = NULL;
-
-    check(object);
-    check(buf);
-    check(header_offset);
-    
-    require_action(sizeof(*mach) <= header_size - *header_offset, finish,
-        rval=KERN_FAILURE);
-    mach = (struct mach_header_64 *) ((void *) (buf + *header_offset));
-    
-    mach->magic = MH_MAGIC_64;
-    mach->cputype = object->cputype;
-    mach->cpusubtype = object->cpusubtype;
-    mach->filetype = object->filetype;
-    mach->ncmds = ncmds;
-    mach->sizeofcmds = (uint32_t) (header_size - sizeof(*mach));
-    mach->flags = MH_NOUNDEFS;
-
-    *header_offset += sizeof(*mach);
-
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+       struct mach_header_64 *mach = NULL;
+
+       check(object);
+       check(buf);
+       check(header_offset);
+
+       require_action(sizeof(*mach) <= header_size - *header_offset, finish,
+           rval = KERN_FAILURE);
+       mach = (struct mach_header_64 *) ((void *) (buf + *header_offset));
+
+       mach->magic = MH_MAGIC_64;
+       mach->cputype = object->cputype;
+       mach->cpusubtype = object->cpusubtype;
+       mach->filetype = object->filetype;
+       mach->ncmds = ncmds;
+       mach->sizeofcmds = (uint32_t) (header_size - sizeof(*mach));
+       mach->flags = MH_NOUNDEFS;
+
+       *header_offset += sizeof(*mach);
+
+#if SPLIT_KEXTS_DEBUG
+       {
+               kxld_log(kKxldLogLinking, kKxldLogErr,
+                   " %p >>> Start of macho header (size %lu) <%s>",
+                   (void *) mach,
+                   sizeof(*mach),
+                   __func__);
+               kxld_log(kKxldLogLinking, kKxldLogErr,
+                   " %p <<< End of macho header <%s>",
+                   (void *) ((u_char *)mach + sizeof(*mach)),
+                   __func__);
+       }
+#endif
+
+       rval = KERN_SUCCESS;
 
 finish:
-    return rval;
+       return rval;
 }
 #endif /* KXLD_USER_OR_LP64 */
 
 /*******************************************************************************
 *******************************************************************************/
-kern_return_t 
+kern_return_t
 kxld_object_index_symbols_by_name(KXLDObject *object)
 {
-    return kxld_symtab_index_symbols_by_name(object->symtab);
+       return kxld_symtab_index_symbols_by_name(object->symtab);
 }
 
 /*******************************************************************************
 *******************************************************************************/
-kern_return_t 
+kern_return_t
 kxld_object_index_cxx_symbols_by_value(KXLDObject *object)
 {
-    return kxld_symtab_index_cxx_symbols_by_value(object->symtab);
+       return kxld_symtab_index_cxx_symbols_by_value(object->symtab);
 }
 
 /*******************************************************************************
 *******************************************************************************/
-kern_return_t 
+kern_return_t
 kxld_object_relocate(KXLDObject *object, kxld_addr_t link_address)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSeg *seg = NULL;
-    u_int i = 0;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSeg *seg = NULL;
+       u_int i = 0;
 
-    check(object);
+       check(object);
 
-    object->link_addr = link_address;
+       object->link_addr = link_address;
 
-    /* Relocate segments (which relocates the sections) */
-    for (i = 0; i < object->segs.nitems; ++i) {
-        seg = kxld_array_get_item(&object->segs, i);
-        kxld_seg_relocate(seg, link_address);
-    }
+       /* Relocate segments (which relocates the sections) */
+       for (i = 0; i < object->segs.nitems; ++i) {
+               seg = kxld_array_get_item(&object->segs, i);
+               kxld_seg_relocate(seg, link_address);
+       } // for...
 
-    /* Relocate symbols */
-    rval = kxld_symtab_relocate(object->symtab, &object->sects);
-    require_noerr(rval, finish);
+       /* Relocate symbols */
+       rval = kxld_symtab_relocate(object->symtab, &object->sects);
+       require_noerr(rval, finish);
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -1968,130 +2241,134 @@ finish:
 static KXLDSym *
 get_mutable_sym(const KXLDObject *object, const KXLDSym *sym)
 {
-    KXLDSym *rval = NULL;
-    kern_return_t result = KERN_FAILURE;
-    u_int i = 0;
+       KXLDSym *rval = NULL;
+       kern_return_t result = KERN_FAILURE;
+       u_int i = 0;
 
-    result = kxld_symtab_get_sym_index(object->symtab, sym, &i);
-    require_noerr(result, finish);
+       result = kxld_symtab_get_sym_index(object->symtab, sym, &i);
+       require_noerr(result, finish);
 
-    rval = kxld_symtab_get_symbol_by_index(object->symtab, i);
-    require_action(rval == sym, finish, rval=NULL);
+       rval = kxld_symtab_get_symbol_by_index(object->symtab, i);
+       require_action(rval == sym, finish, rval = NULL);
 
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-kern_return_t 
-kxld_object_resolve_symbol(KXLDObject *object, 
+kern_return_t
+kxld_object_resolve_symbol(KXLDObject *object,
     const KXLDSym *sym, kxld_addr_t addr)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSym *resolved_sym = NULL;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSym *resolved_sym = NULL;
 
-    resolved_sym = get_mutable_sym(object, sym);
-    require_action(resolved_sym, finish, rval=KERN_FAILURE);
+       resolved_sym = get_mutable_sym(object, sym);
+       require_action(resolved_sym, finish, rval = KERN_FAILURE);
 
-    rval = kxld_sym_resolve(resolved_sym, addr);
-    require_noerr(rval, finish);
+       rval = kxld_sym_resolve(resolved_sym, addr);
+       require_noerr(rval, finish);
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-kern_return_t 
+kern_return_t
 kxld_object_patch_symbol(KXLDObject *object, const struct kxld_sym *sym)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSym *patched_sym = NULL;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSym *patched_sym = NULL;
 
-    patched_sym = get_mutable_sym(object, sym);
-    require_action(patched_sym, finish, rval=KERN_FAILURE);
+       patched_sym = get_mutable_sym(object, sym);
+       require_action(patched_sym, finish, rval = KERN_FAILURE);
 
-    (void) kxld_sym_patch(patched_sym);
-    rval = KERN_SUCCESS;
+       (void) kxld_sym_patch(patched_sym);
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-kern_return_t 
-kxld_object_add_symbol(KXLDObject *object, char *name, kxld_addr_t link_addr, 
+kern_return_t
+kxld_object_add_symbol(KXLDObject *object, char *name, kxld_addr_t link_addr,
     const KXLDSym **sym_out)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSym *sym = NULL;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSym *sym = NULL;
 
-    rval = kxld_symtab_add_symbol(object->symtab, name, link_addr, &sym);
-    require_noerr(rval, finish);
+       rval = kxld_symtab_add_symbol(object->symtab, name, link_addr, &sym);
+       require_noerr(rval, finish);
 
-    *sym_out = sym;
-    rval = KERN_SUCCESS;
+       *sym_out = sym;
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-kern_return_t 
-kxld_object_process_relocations(KXLDObject *object, 
+kern_return_t
+kxld_object_process_relocations(KXLDObject *object,
     const KXLDDict *patched_vtables)
 {
-    kern_return_t rval = KERN_FAILURE;
-
-    (void) kxld_relocator_set_vtables(&object->relocator, patched_vtables);
-
-    /* Process relocation entries and populate the global offset table.
-     *
-     * For final linked images: the relocation entries are contained in a couple
-     * of tables hanging off the end of the symbol table.  The GOT has its own
-     * section created by the linker; we simply need to fill it.
-     *
-     * For object files: the relocation entries are bound to each section.
-     * The GOT, if it exists for the target architecture, is created by kxld,
-     * and we must populate it according to our internal structures.
-     */
-    if (object->is_final_image) {
+       kern_return_t rval = KERN_FAILURE;
+
+       (void) kxld_relocator_set_vtables(&object->relocator, patched_vtables);
+
+       /* Process relocation entries and populate the global offset table.
+        *
+        * For final linked images: the relocation entries are contained in a couple
+        * of tables hanging off the end of the symbol table.  The GOT has its own
+        * section created by the linker; we simply need to fill it.
+        *
+        * For object files: the relocation entries are bound to each section.
+        * The GOT, if it exists for the target architecture, is created by kxld,
+        * and we must populate it according to our internal structures.
+        */
+       if (object->is_final_image) {
 #if KXLD_USER_OR_BUNDLE
-        rval = process_symbol_pointers(object);
-        require_noerr(rval, finish);
+               rval = process_symbol_pointers(object);
+               require_noerr(rval, finish);
 
-        rval = process_relocs_from_tables(object);
-        require_noerr(rval, finish);
+               rval = process_relocs_from_tables(object);
+               require_noerr(rval, finish);
 #else
-        require_action(FALSE, finish, rval=KERN_FAILURE);
+               require_action(FALSE, finish, rval = KERN_FAILURE);
 #endif /* KXLD_USER_OR_BUNDLE */
-    } else {
+       } else {
 #if KXLD_USER_OR_GOT
-        /* Populate GOT */
-        rval = populate_got(object);
-        require_noerr(rval, finish);
+               /* Populate GOT */
+               rval = populate_got(object);
+               require_noerr(rval, finish);
 #endif /* KXLD_USER_OR_GOT */
 #if KXLD_USER_OR_OBJECT
-        rval = process_relocs_from_sections(object);
-        require_noerr(rval, finish);
+               rval = process_relocs_from_sections(object);
+               require_noerr(rval, finish);
 #else
-        require_action(FALSE, finish, rval=KERN_FAILURE);
+               require_action(FALSE, finish, rval = KERN_FAILURE);
 #endif /* KXLD_USER_OR_OBJECT */
-    }
+       }
 
-    /* Populate kmod info structure */
-    rval = populate_kmod_info(object);
-    require_noerr(rval, finish);
-    rval = KERN_SUCCESS;
+       /* Populate kmod info structure */
+       rval = populate_kmod_info(object);
+       require_noerr(rval, finish);
+
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 #if KXLD_USER_OR_BUNDLE
 
+#if SPLIT_KEXTS_DEBUG
+static boolean_t  kxld_show_ptr_value;
+#endif
+
 #define SECT_SYM_PTRS "__nl_symbol_ptr"
 
 /*******************************************************************************
@@ -2104,76 +2381,91 @@ finish:
 static kern_return_t
 process_symbol_pointers(KXLDObject *object)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSect *sect = NULL;
-    KXLDSym *sym = NULL;
-    int32_t *symidx = NULL;
-    u_char *symptr = NULL;
-    u_long symptrsize = 0;
-    u_int nsyms = 0;
-    u_int firstsym = 0;
-    u_int i = 0;
-
-    check(object);
-
-    require_action(object->is_final_image && object->dysymtab_hdr, 
-        finish, rval=KERN_FAILURE);
-
-    /* Get the __DATA,__nl_symbol_ptr section.  If it doesn't exist, we have
-     * nothing to do.
-     */
-
-    sect = kxld_object_get_sect_by_name(object, SEG_DATA, SECT_SYM_PTRS);
-    if (!sect || !(sect->flags & S_NON_LAZY_SYMBOL_POINTERS)) {
-        rval = KERN_SUCCESS;
-        goto finish;
-    }
-
-    /* Calculate the table offset and number of entries in the section */
-
-    if (kxld_object_is_32_bit(object)) {
-        symptrsize = sizeof(uint32_t);
-    } else {
-        symptrsize = sizeof(uint64_t);
-    }
-
-    nsyms = (u_int) (sect->size / symptrsize);
-    firstsym = sect->reserved1;
-
-    require_action(firstsym + nsyms <= object->dysymtab_hdr->nindirectsyms,
-        finish, rval=KERN_FAILURE;
-        kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
-            "firstsym + nsyms > object->dysymtab_hdr->nindirectsyms"));
-
-    /* Iterate through the indirect symbol table and fill in the section of
-     * symbol pointers.  There are three cases:
-     *   1) A normal symbol - put its value directly in the table
-     *   2) An INDIRECT_SYMBOL_LOCAL - symbols that are local and already have
-     *      their offset from the start of the file in the section.  Simply
-     *      add the file's link address to fill this entry.
-     *   3) An INDIRECT_SYMBOL_ABS - prepopulated absolute symbols.  No
-     *      action is required.
-     */
-
-    symidx = (int32_t *) ((void *) (object->file + object->dysymtab_hdr->indirectsymoff));
-    symidx += firstsym;
-    symptr = sect->data;
-    for (i = 0; i < nsyms; ++i, ++symidx, symptr+=symptrsize) {
-        if (*symidx & INDIRECT_SYMBOL_LOCAL) {
-            if (*symidx & INDIRECT_SYMBOL_ABS) continue;
-
-            add_to_ptr(symptr, object->link_addr, kxld_object_is_32_bit(object));
-        } else {
-            sym = kxld_symtab_get_symbol_by_index(object->symtab, *symidx);
-            require_action(sym, finish, rval=KERN_FAILURE);
-
-            add_to_ptr(symptr, sym->link_addr, kxld_object_is_32_bit(object));
-        }
-    }
-
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSect *sect = NULL;
+       KXLDSym *sym = NULL;
+       int32_t *symidx = NULL;
+       u_char *symptr = NULL;
+       u_long symptrsize = 0;
+       u_int nsyms = 0;
+       u_int firstsym = 0;
+       u_int i = 0;
+
+       check(object);
+
+       require_action(object->is_final_image && object->dysymtab_hdr,
+           finish, rval = KERN_FAILURE);
+
+       /* Get the __DATA,__nl_symbol_ptr section.  If it doesn't exist, we have
+        * nothing to do.
+        */
+
+       sect = kxld_object_get_sect_by_name(object, SEG_DATA, SECT_SYM_PTRS);
+       if (!sect || !(sect->flags & S_NON_LAZY_SYMBOL_POINTERS)) {
+               rval = KERN_SUCCESS;
+               goto finish;
+       }
+
+       /* Calculate the table offset and number of entries in the section */
+
+       if (kxld_object_is_32_bit(object)) {
+               symptrsize = sizeof(uint32_t);
+       } else {
+               symptrsize = sizeof(uint64_t);
+       }
+
+       nsyms = (u_int) (sect->size / symptrsize);
+       firstsym = sect->reserved1;
+
+       require_action(firstsym + nsyms <= object->dysymtab_hdr->nindirectsyms,
+           finish, rval = KERN_FAILURE;
+           kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
+           "firstsym + nsyms > object->dysymtab_hdr->nindirectsyms"));
+
+       /* Iterate through the indirect symbol table and fill in the section of
+        * symbol pointers.  There are three cases:
+        *   1) A normal symbol - put its value directly in the table
+        *   2) An INDIRECT_SYMBOL_LOCAL - symbols that are local and already have
+        *      their offset from the start of the file in the section.  Simply
+        *      add the file's link address to fill this entry.
+        *   3) An INDIRECT_SYMBOL_ABS - prepopulated absolute symbols.  No
+        *      action is required.
+        */
+
+       if (isOldInterface) {
+               symidx = (int32_t *) ((void *) (object->file + object->dysymtab_hdr->indirectsymoff));
+       } else {
+               symidx = (int32_t *) ((void *) (object->split_info.kextExecutable + object->dysymtab_hdr->indirectsymoff));
+       }
+
+       symidx += firstsym;
+       symptr = sect->data;
+       for (i = 0; i < nsyms; ++i, ++symidx, symptr += symptrsize) {
+               if (*symidx & INDIRECT_SYMBOL_LOCAL) {
+                       if (*symidx & INDIRECT_SYMBOL_ABS) {
+                               continue;
+                       }
+
+                       if (isOldInterface) {
+                               add_to_ptr(symptr, object->link_addr, kxld_object_is_32_bit(object));
+                       } else {
+                               add_to_ptr(symptr, object->split_info.vmaddr_TEXT, kxld_object_is_32_bit(object));
+                       }
+               } else {
+                       sym = kxld_symtab_get_symbol_by_index(object->symtab, *symidx);
+                       require_action(sym, finish, rval = KERN_FAILURE);
+
+                       if (isOldInterface) {
+                               add_to_ptr(symptr, sym->link_addr, kxld_object_is_32_bit(object));
+                       } else {
+                               add_to_ptr(symptr, object->split_info.vmaddr_TEXT, kxld_object_is_32_bit(object));
+                       }
+               }
+       }
+
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -2181,20 +2473,22 @@ finish:
 static KXLDSeg *
 get_seg_by_base_addr(KXLDObject *object, kxld_addr_t base_addr)
 {
-    KXLDSeg *seg = NULL;
-    kxld_addr_t start = 0;
-    kxld_addr_t end = 0;
-    u_int i = 0;
-
-    for (i = 0; i < object->segs.nitems; ++i) {
-        seg = kxld_array_get_item(&object->segs, i);
-        start = seg->base_addr;
-        end = seg->base_addr + seg->vmsize;
-
-        if (start <= base_addr && base_addr < end) return seg;
-    }
-
-    return NULL;
+       KXLDSeg *seg = NULL;
+       kxld_addr_t start = 0;
+       kxld_addr_t end = 0;
+       u_int i = 0;
+
+       for (i = 0; i < object->segs.nitems; ++i) {
+               seg = kxld_array_get_item(&object->segs, i);
+               start = seg->base_addr;
+               end = seg->base_addr + seg->vmsize;
+
+               if (start <= base_addr && base_addr < end) {
+                       return seg;
+               }
+       }
+
+       return NULL;
 }
 
 /*******************************************************************************
@@ -2202,38 +2496,80 @@ get_seg_by_base_addr(KXLDObject *object, kxld_addr_t base_addr)
 static kern_return_t
 process_relocs_from_tables(KXLDObject *object)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDReloc *reloc = NULL;
-    KXLDSeg *seg = NULL;
-    u_int i = 0;
-
-    /* Process external relocations */
-    for (i = 0; i < object->extrelocs.nitems; ++i) {
-        reloc = kxld_array_get_item(&object->extrelocs, i);
-
-        seg = get_seg_by_base_addr(object, reloc->address);
-        require_action(seg, finish, rval=KERN_FAILURE);
-
-        rval = kxld_relocator_process_table_reloc(&object->relocator, reloc,
-            seg, object->link_addr);
-        require_noerr(rval, finish);
-    }
-
-    /* Process local relocations */
-    for (i = 0; i < object->locrelocs.nitems; ++i) {
-        reloc = kxld_array_get_item(&object->locrelocs, i);
-
-        seg = get_seg_by_base_addr(object, reloc->address);
-        require_action(seg, finish, rval=KERN_FAILURE);
-
-        rval = kxld_relocator_process_table_reloc(&object->relocator, reloc,
-            seg, object->link_addr);
-        require_noerr(rval, finish);
-    }
-
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDReloc *reloc = NULL;
+       KXLDSeg *seg = NULL;
+       u_int i = 0;
+
+       /* Process external relocations */
+       for (i = 0; i < object->extrelocs.nitems; ++i) {
+               reloc = kxld_array_get_item(&object->extrelocs, i);
+
+               seg = get_seg_by_base_addr(object, reloc->address);
+               require_action(seg, finish, rval = KERN_FAILURE);
+
+               if (isOldInterface) {
+                       rval = kxld_relocator_process_table_reloc(&object->relocator, reloc,
+                           seg, object->link_addr);
+               } else {
+                       kxld_addr_t my_link_addr = object->split_info.vmaddr_TEXT;
+                       if (isSplitKext) {
+                               if (kxld_seg_is_text_exec_seg(seg)) {
+                                       my_link_addr = object->split_info.vmaddr_TEXT_EXEC;
+                               } else if (kxld_seg_is_data_seg(seg)) {
+                                       my_link_addr = object->split_info.vmaddr_DATA;
+                               } else if (kxld_seg_is_data_const_seg(seg)) {
+                                       my_link_addr = object->split_info.vmaddr_DATA_CONST;
+                               } else if (kxld_seg_is_llvm_cov_seg(seg)) {
+                                       my_link_addr = object->split_info.vmaddr_LLVM_COV;
+                               } else if (kxld_seg_is_linkedit_seg(seg)) {
+                                       my_link_addr = object->split_info.vmaddr_LINKEDIT;
+                               }
+                       }
+                       rval = kxld_relocator_process_table_reloc(&object->relocator,
+                           reloc,
+                           seg,
+                           my_link_addr);
+               }
+               require_noerr(rval, finish);
+       }
+
+       /* Process local relocations */
+       for (i = 0; i < object->locrelocs.nitems; ++i) {
+               reloc = kxld_array_get_item(&object->locrelocs, i);
+
+               seg = get_seg_by_base_addr(object, reloc->address);
+               require_action(seg, finish, rval = KERN_FAILURE);
+
+               if (isOldInterface) {
+                       rval = kxld_relocator_process_table_reloc(&object->relocator, reloc,
+                           seg, object->link_addr);
+               } else {
+                       kxld_addr_t my_link_addr = object->split_info.vmaddr_TEXT;
+                       if (isSplitKext) {
+                               if (kxld_seg_is_text_exec_seg(seg)) {
+                                       my_link_addr = object->split_info.vmaddr_TEXT_EXEC;
+                               } else if (kxld_seg_is_data_seg(seg)) {
+                                       my_link_addr = object->split_info.vmaddr_DATA;
+                               } else if (kxld_seg_is_data_const_seg(seg)) {
+                                       my_link_addr = object->split_info.vmaddr_DATA_CONST;
+                               } else if (kxld_seg_is_llvm_cov_seg(seg)) {
+                                       my_link_addr = object->split_info.vmaddr_LLVM_COV;
+                               } else if (kxld_seg_is_linkedit_seg(seg)) {
+                                       my_link_addr = object->split_info.vmaddr_LINKEDIT;
+                               }
+                       }
+                       rval = kxld_relocator_process_table_reloc(&object->relocator,
+                           reloc,
+                           seg,
+                           my_link_addr);
+               }
+               require_noerr(rval, finish);
+       }
+
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -2241,13 +2577,19 @@ finish:
 static void
 add_to_ptr(u_char *symptr, kxld_addr_t val, boolean_t is_32_bit)
 {
-    if (is_32_bit) {
-        uint32_t *ptr = (uint32_t *) ((void *) symptr);
-        *ptr += (uint32_t) val;
-    } else {
-        uint64_t *ptr = (uint64_t *) ((void *) symptr);
-        *ptr += (uint64_t) val;
-    }
+       if (is_32_bit) {
+               uint32_t *ptr = (uint32_t *) ((void *) symptr);
+
+               *ptr += (uint32_t) val;
+       } else {
+               uint64_t *ptr = (uint64_t *) ((void *) symptr);
+
+               *ptr += (uint64_t) val;
+       }
+
+#if SPLIT_KEXTS_DEBUG
+       kxld_show_ptr_value = FALSE;
+#endif
 }
 #endif /* KXLD_USER_OR_BUNDLE */
 
@@ -2257,19 +2599,19 @@ add_to_ptr(u_char *symptr, kxld_addr_t val, boolean_t is_32_bit)
 static kern_return_t
 process_relocs_from_sections(KXLDObject *object)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSect *sect = NULL;
-    u_int i = 0;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSect *sect = NULL;
+       u_int i = 0;
 
-    for (i = 0; i < object->sects.nitems; ++i) {
-        sect = kxld_array_get_item(&object->sects, i);
-        rval = kxld_sect_process_relocs(sect, &object->relocator);
-        require_noerr(rval, finish);
-    }
+       for (i = 0; i < object->sects.nitems; ++i) {
+               sect = kxld_array_get_item(&object->sects, i);
+               rval = kxld_sect_process_relocs(sect, &object->relocator);
+               require_noerr(rval, finish);
+       }
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 #endif /* KXLD_USER_OR_OBJECT */
 
@@ -2278,73 +2620,106 @@ finish:
 static kern_return_t
 populate_kmod_info(KXLDObject *object)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSect *kmodsect = NULL;
-    KXLDSym *kmodsym = NULL;
-    kmod_info_t *kmod_info = NULL;
-    u_long kmod_offset = 0;
-    u_long header_size;
-    u_long size;
-
-    if (kxld_object_is_kernel(object)) {
-        rval = KERN_SUCCESS;
-        goto finish;
-    }
-
-    kxld_object_get_vmsize(object, &header_size, &size);
-
-    kmodsym = kxld_symtab_get_locally_defined_symbol_by_name(object->symtab, 
-        KXLD_KMOD_INFO_SYMBOL);
-    require_action(kmodsym, finish, rval=KERN_FAILURE;
-        kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogNoKmodInfo));
-    kmodsect = kxld_array_get_item(&object->sects, kmodsym->sectnum);
-    kmod_offset = (u_long) (kmodsym->base_addr -  kmodsect->base_addr);
-    kmod_info = (kmod_info_t *) ((void *) (kmodsect->data + kmod_offset));
-
-    if (kxld_object_is_32_bit(object)) {
-        kmod_info_32_v1_t *kmod = (kmod_info_32_v1_t *) (kmod_info);
-        kmod->address = (uint32_t) object->link_addr;
-        kmod->size = (uint32_t) size;
-        kmod->hdr_size = (uint32_t) header_size;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSect *kmodsect = NULL;
+       KXLDSym *kmodsym = NULL;
+       kmod_info_t *kmod_info = NULL;
+       u_long kmod_offset = 0;
+       u_long header_size;
+       u_long size;
+
+       if (kxld_object_is_kernel(object)) {
+               rval = KERN_SUCCESS;
+               goto finish;
+       }
+
+       kxld_object_get_vmsize(object, &header_size, &size);
+
+       kmodsym = kxld_symtab_get_locally_defined_symbol_by_name(object->symtab,
+           KXLD_KMOD_INFO_SYMBOL);
+       require_action(kmodsym, finish, rval = KERN_FAILURE;
+           kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogNoKmodInfo));
+
+       kmodsect = kxld_array_get_item(&object->sects, kmodsym->sectnum);
+
+       kmod_offset = (u_long) (kmodsym->base_addr -  kmodsect->base_addr);
+       kmod_info = (kmod_info_t *) ((void *) (kmodsect->data + kmod_offset));
+
+       if (kxld_object_is_32_bit(object)) {
+               kmod_info_32_v1_t *kmod = (kmod_info_32_v1_t *) (kmod_info);
+
+               if (isOldInterface) {
+                       kmod->address = (uint32_t) object->link_addr;
+               } else {
+                       kmod->address = (uint32_t) object->split_info.vmaddr_TEXT;
+               }
+
+               kmod->size = (uint32_t) size;
+               kmod->hdr_size = (uint32_t) header_size;
 
 #if !KERNEL
-        if (kxld_object_target_needs_swap(object)) {
-            kmod->address = OSSwapInt32(kmod->address);
-            kmod->size = OSSwapInt32(kmod->size);
-            kmod->hdr_size = OSSwapInt32(kmod->hdr_size);
-        }
+               if (kxld_object_target_needs_swap(object)) {
+                       kmod->address = OSSwapInt32(kmod->address);
+                       kmod->size = OSSwapInt32(kmod->size);
+                       kmod->hdr_size = OSSwapInt32(kmod->hdr_size);
+               }
 #endif /* !KERNEL */
-    } else {
-        kmod_info_64_v1_t *kmod = (kmod_info_64_v1_t *) (kmod_info);
-        kmod->address = object->link_addr;
-        kmod->size = size;
-        kmod->hdr_size = header_size;
+       } else {
+               kmod_info_64_v1_t *kmod = (kmod_info_64_v1_t *) (kmod_info);
+
+               if (isOldInterface) {
+                       kmod->address = object->link_addr;
+               } else {
+                       kmod->address = object->split_info.vmaddr_TEXT;
+               }
+
+               kmod->size = size;
+               kmod->hdr_size = header_size;
 
 #if !KERNEL
-        if (kxld_object_target_needs_swap(object)) {
-            kmod->address = OSSwapInt64(kmod->address);
-            kmod->size = OSSwapInt64(kmod->size);
-            kmod->hdr_size = OSSwapInt64(kmod->hdr_size);
-        }
+               if (kxld_object_target_needs_swap(object)) {
+                       kmod->address = OSSwapInt64(kmod->address);
+                       kmod->size = OSSwapInt64(kmod->size);
+                       kmod->hdr_size = OSSwapInt64(kmod->hdr_size);
+               }
 #endif /* !KERNEL */
-    }
 
+#if SPLIT_KEXTS_DEBUG
+               {
+                       kxld_log(kKxldLogLinking, kKxldLogErr,
+                           " kmodsect %p kmod_info %p = kmodsect->data %p + kmod_offset %lu <%s>",
+                           (void *) kmodsect,
+                           (void *) kmod_info,
+                           (void *) kmodsect->data,
+                           kmod_offset,
+                           __func__);
+
+                       kxld_log(kKxldLogLinking, kKxldLogErr,
+                           " kmod_info data: address %p size %llu hdr_size %llu start_addr %p stop_addr %p <%s>",
+                           (void *) kmod->address,
+                           kmod->size,
+                           kmod->hdr_size,
+                           (void *) kmod->start_addr,
+                           (void *) kmod->stop_addr,
+                           __func__);
+               }
+#endif
+       }
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 
 finish:
-    return rval;
+       return rval;
 }
 
 #if KXLD_PIC_KEXTS
 /*******************************************************************************
- *******************************************************************************/
+*******************************************************************************/
 static boolean_t
 target_supports_slideable_kexts(const KXLDObject *object)
 {
-    check(object);
+       check(object);
 
-    return (object->cputype != CPU_TYPE_I386 && object->include_kaslr_relocs);
+       return object->cputype != CPU_TYPE_I386 && object->include_kaslr_relocs;
 }
 #endif  /* KXLD_PIC_KEXTS */