]> git.saurik.com Git - apple/xnu.git/blobdiff - libkern/kxld/kxld_kext.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / libkern / kxld / kxld_kext.c
index a9ef4779820b2b6d4e41abb83d73f5ba4a761878..eafc9d5915754b9dce54f6c2ef1f2818bc082c91 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008, 2013 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>
@@ -45,6 +45,7 @@
     #include <mach/mach_init.h>
     #include <mach-o/arch.h>
     #include <mach-o/swap.h>
+
 #endif /* KERNEL */
 
 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
 #include "kxld_util.h"
 #include "kxld_vtable.h"
 
+extern boolean_t isSplitKext;
+
 struct symtab_command;
 
 struct kxld_kext {
-    KXLDObject *kext;
-    KXLDObject *interface;
-    KXLDArray vtables;
-    KXLDDict vtable_index;
-    boolean_t vtables_created;
-    boolean_t vtable_index_created;
+       KXLDObject *kext;
+       KXLDObject *interface;
+       KXLDArray vtables;
+       KXLDDict vtable_index;
+       boolean_t vtables_created;
+       boolean_t vtable_index_created;
 };
 
 /*******************************************************************************
@@ -77,28 +80,28 @@ struct kxld_kext {
 *******************************************************************************/
 
 static kern_return_t export_symbols_through_interface(
-    const KXLDObject *kext, const KXLDObject *interface, 
-    KXLDDict *defined_symbols_by_name, 
-    KXLDDict *defined_cxx_symbol_by_value,
-    KXLDDict *obsolete_symbols_by_name);
+       const KXLDObject *kext, const KXLDObject *interface,
+       KXLDDict *defined_symbols_by_name,
+       KXLDDict *defined_cxx_symbol_by_value,
+       KXLDDict *obsolete_symbols_by_name);
 static kern_return_t export_symbols(const KXLDObject *kext,
-    KXLDDict *defined_symbols_by_name, 
+    KXLDDict *defined_symbols_by_name,
     KXLDDict *defined_cxx_symbols_by_value);
 
 static kern_return_t create_vtables(KXLDKext *kext,
     const KXLDDict *defined_symbols, const KXLDDict *defined_cxx_symbols);
-static kern_return_t get_vtable_syms_from_smcp(KXLDKext *kext, 
-    const KXLDDict *defined_symbols, KXLDSym *super_metaclass_ptr_sym, 
+static kern_return_t get_vtable_syms_from_smcp(KXLDKext *kext,
+    const KXLDDict *defined_symbols, KXLDSym *super_metaclass_ptr_sym,
     KXLDSym **vtable_sym_out, KXLDSym **meta_vtable_sym_out);
 
-static kern_return_t resolve_symbols(KXLDKext *kext, 
+static kern_return_t resolve_symbols(KXLDKext *kext,
     const KXLDDict *defined_symbols, const KXLDDict *obsolete_symbols);
 
 static kern_return_t patch_vtables(KXLDKext *kext, KXLDDict *patched_vtables,
     const KXLDDict *defined_symbols);
-static const KXLDSym *get_metaclass_symbol_from_super_meta_class_pointer_symbol(
-    KXLDKext *kext, KXLDSym *super_metaclass_pointer_sym);
 static kern_return_t create_vtable_index(KXLDKext *kext);
+static const KXLDSym *get_metaclass_symbol_from_super_meta_class_pointer_symbol(
+       KXLDKext *kext, KXLDSym *super_metaclass_pointer_sym);
 
 static kern_return_t validate_symbols(KXLDKext *kext);
 
@@ -107,32 +110,32 @@ static kern_return_t validate_symbols(KXLDKext *kext);
 size_t
 kxld_kext_sizeof(void)
 {
-    return sizeof(KXLDKext);
+       return sizeof(KXLDKext);
 }
 
 /*******************************************************************************
 *******************************************************************************/
 kern_return_t
-kxld_kext_init(KXLDKext *kext, KXLDObject *kext_object, 
+kxld_kext_init(KXLDKext *kext, KXLDObject *kext_object,
     KXLDObject *interface_object)
 {
-    kern_return_t rval = KERN_FAILURE;
+       kern_return_t rval = KERN_FAILURE;
 
-    check(kext);
-    check(kext_object);
+       check(kext);
+       check(kext_object);
 
-    kext->kext = kext_object;
+       kext->kext = kext_object;
 
-    if (interface_object) {
-        kext->interface = interface_object;
+       if (interface_object) {
+               kext->interface = interface_object;
 
-        rval = kxld_object_index_symbols_by_name(kext->kext);
-        require_noerr(rval, finish);
-    }
-    
-    rval = KERN_SUCCESS;
+               rval = kxld_object_index_symbols_by_name(kext->kext);
+               require_noerr(rval, finish);
+       }
+
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -140,71 +143,71 @@ finish:
 void
 kxld_kext_clear(KXLDKext *kext)
 {
-    KXLDVTable *vtable = NULL;
-    u_int i;
-
-    check(kext);
-
-    for (i = 0; i < kext->vtables.nitems; ++i) {
-        vtable = kxld_array_get_item(&kext->vtables, i);
-        kxld_vtable_clear(vtable);
-    }
-    kxld_array_reset(&kext->vtables);
-    kxld_dict_clear(&kext->vtable_index);
-
-    kext->kext = NULL;
-    kext->interface = NULL;
-    kext->vtables_created = FALSE;
-    kext->vtable_index_created = FALSE;
+       KXLDVTable *vtable = NULL;
+       u_int i;
+
+       check(kext);
+
+       for (i = 0; i < kext->vtables.nitems; ++i) {
+               vtable = kxld_array_get_item(&kext->vtables, i);
+               kxld_vtable_clear(vtable);
+       }
+       kxld_array_reset(&kext->vtables);
+       kxld_dict_clear(&kext->vtable_index);
+
+       kext->kext = NULL;
+       kext->interface = NULL;
+       kext->vtables_created = FALSE;
+       kext->vtable_index_created = FALSE;
 }
 
 
 /*******************************************************************************
 *******************************************************************************/
-void 
+void
 kxld_kext_deinit(KXLDKext *kext)
 {
-    KXLDVTable *vtable = NULL;
-    u_int i;
+       KXLDVTable *vtable = NULL;
+       u_int i;
 
-    check(kext);
+       check(kext);
 
-    for (i = 0; i < kext->vtables.maxitems; ++i) {
-        vtable = kxld_array_get_slot(&kext->vtables, i);
-        kxld_vtable_deinit(vtable);
-    }
-    kxld_array_deinit(&kext->vtables);
-    kxld_dict_deinit(&kext->vtable_index);
+       for (i = 0; i < kext->vtables.maxitems; ++i) {
+               vtable = kxld_array_get_slot(&kext->vtables, i);
+               kxld_vtable_deinit(vtable);
+       }
+       kxld_array_deinit(&kext->vtables);
+       kxld_dict_deinit(&kext->vtable_index);
 
-    bzero(kext, sizeof(*kext));
+       bzero(kext, sizeof(*kext));
 }
 
 /*******************************************************************************
 *******************************************************************************/
-kern_return_t 
-kxld_kext_export_symbols(const KXLDKext *kext, 
+kern_return_t
+kxld_kext_export_symbols(const KXLDKext *kext,
     KXLDDict *defined_symbols_by_name,
     KXLDDict *obsolete_symbols_by_name,
     KXLDDict *defined_cxx_symbols_by_value)
 {
-    kern_return_t rval = KERN_FAILURE;
-
-    check(kext);
-
-    if (kext->interface) {
-        rval = export_symbols_through_interface(kext->kext, kext->interface, 
-            defined_symbols_by_name, obsolete_symbols_by_name,
-            defined_cxx_symbols_by_value);
-        require_noerr(rval, finish);
-    } else {
-        rval = export_symbols(kext->kext, defined_symbols_by_name,
-            defined_cxx_symbols_by_value);
-        require_noerr(rval, finish);
-    }
-
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+
+       check(kext);
+
+       if (kext->interface) {
+               rval = export_symbols_through_interface(kext->kext, kext->interface,
+                   defined_symbols_by_name, obsolete_symbols_by_name,
+                   defined_cxx_symbols_by_value);
+               require_noerr(rval, finish);
+       } else {
+               rval = export_symbols(kext->kext, defined_symbols_by_name,
+                   defined_cxx_symbols_by_value);
+               require_noerr(rval, finish);
+       }
+
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -214,84 +217,84 @@ export_symbols_through_interface(const KXLDObject *kext,
     const KXLDObject *interface, KXLDDict *defined_symbols_by_name,
     KXLDDict *obsolete_symbols_by_name, KXLDDict *defined_cxx_symbols_by_value)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSymtabIterator iter;
-    const KXLDSymtab *kext_symtab = NULL;
-    const KXLDSymtab *interface_symtab = NULL;
-    KXLDSym *kext_sym = NULL;
-    const KXLDSym *interface_sym = NULL;
-
-    check(kext);
-    check(interface);
-
-    kext_symtab = kxld_object_get_symtab(kext);
-    interface_symtab = kxld_object_get_symtab(interface);
-
-    if (defined_symbols_by_name) {
-        /* Add exported symbols */
-        (void) kxld_symtab_iterator_init(&iter, interface_symtab, 
-            kxld_sym_is_undefined, FALSE);
-        while ((interface_sym = kxld_symtab_iterator_get_next(&iter))) {
-            kext_sym = kxld_symtab_get_locally_defined_symbol_by_name(kext_symtab, 
-                interface_sym->name);
-            if (!kext_sym) {
-                kxld_log(kKxldLogLinking, kKxldLogWarn,
-                    "In interface %s of %s, couldn't find symbol %s\n", 
-                    kxld_object_get_name(interface), kxld_object_get_name(kext),
-                    interface_sym->name);
-                continue;
-            }
-
-            rval = kxld_dict_insert(defined_symbols_by_name, 
-                kext_sym->name, kext_sym);
-            require_noerr(rval, finish);
-        }
-
-        /* Add indirect symbols */
-        (void) kxld_symtab_iterator_init(&iter, interface_symtab, 
-            kxld_sym_is_indirect, FALSE);
-        while ((interface_sym = kxld_symtab_iterator_get_next(&iter))) {
-            kext_sym = kxld_symtab_get_locally_defined_symbol_by_name(kext_symtab, 
-                interface_sym->alias);
-            if (!kext_sym) {
-                kxld_log(kKxldLogLinking, kKxldLogWarn,
-                    "In interface %s of %s, couldn't find indirect symbol %s (%s)\n", 
-                    kxld_object_get_name(interface), kxld_object_get_name(kext),
-                    interface_sym->alias, interface_sym->name);
-                continue;
-            }
-
-            rval = kxld_dict_insert(defined_symbols_by_name, 
-                interface_sym->name, kext_sym);
-            require_noerr(rval, finish);
-        }
-    }
-
-    /* Add obsolete symbols */
-    if (obsolete_symbols_by_name) {
-        (void) kxld_symtab_iterator_init(&iter, interface_symtab, 
-            kxld_sym_is_obsolete, FALSE);
-        while ((kext_sym = kxld_symtab_iterator_get_next(&iter))) {
-            rval = kxld_dict_insert(obsolete_symbols_by_name, 
-                kext_sym->name, kext_sym);
-            require_noerr(rval, finish);
-        }
-    }
-
-    /* Add C++ symbols */
-    if (defined_cxx_symbols_by_value) {
-        (void) kxld_symtab_iterator_init(&iter, kext_symtab,
-            kxld_sym_is_cxx, FALSE);
-        while ((kext_sym = kxld_symtab_iterator_get_next(&iter))) {
-            rval = kxld_dict_insert(defined_cxx_symbols_by_value,
-                &kext_sym->link_addr, kext_sym);
-            require_noerr(rval, finish);
-        }
-    }
-
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSymtabIterator iter;
+       const KXLDSymtab *kext_symtab = NULL;
+       const KXLDSymtab *interface_symtab = NULL;
+       KXLDSym *kext_sym = NULL;
+       const KXLDSym *interface_sym = NULL;
+
+       check(kext);
+       check(interface);
+
+       kext_symtab = kxld_object_get_symtab(kext);
+       interface_symtab = kxld_object_get_symtab(interface);
+
+       if (defined_symbols_by_name) {
+               /* Add exported symbols */
+               (void) kxld_symtab_iterator_init(&iter, interface_symtab,
+                   kxld_sym_is_undefined, FALSE);
+               while ((interface_sym = kxld_symtab_iterator_get_next(&iter))) {
+                       kext_sym = kxld_symtab_get_locally_defined_symbol_by_name(kext_symtab,
+                           interface_sym->name);
+                       if (!kext_sym) {
+                               kxld_log(kKxldLogLinking, kKxldLogWarn,
+                                   "In interface %s of %s, couldn't find symbol %s\n",
+                                   kxld_object_get_name(interface), kxld_object_get_name(kext),
+                                   interface_sym->name);
+                               continue;
+                       }
+
+                       rval = kxld_dict_insert(defined_symbols_by_name,
+                           kext_sym->name, kext_sym);
+                       require_noerr(rval, finish);
+               }
+
+               /* Add indirect symbols */
+               (void) kxld_symtab_iterator_init(&iter, interface_symtab,
+                   kxld_sym_is_indirect, FALSE);
+               while ((interface_sym = kxld_symtab_iterator_get_next(&iter))) {
+                       kext_sym = kxld_symtab_get_locally_defined_symbol_by_name(kext_symtab,
+                           interface_sym->alias);
+                       if (!kext_sym) {
+                               kxld_log(kKxldLogLinking, kKxldLogWarn,
+                                   "In interface %s of %s, couldn't find indirect symbol %s (%s)\n",
+                                   kxld_object_get_name(interface), kxld_object_get_name(kext),
+                                   interface_sym->alias, interface_sym->name);
+                               continue;
+                       }
+
+                       rval = kxld_dict_insert(defined_symbols_by_name,
+                           interface_sym->name, kext_sym);
+                       require_noerr(rval, finish);
+               }
+       }
+
+       /* Add obsolete symbols */
+       if (obsolete_symbols_by_name) {
+               (void) kxld_symtab_iterator_init(&iter, interface_symtab,
+                   kxld_sym_is_obsolete, FALSE);
+               while ((kext_sym = kxld_symtab_iterator_get_next(&iter))) {
+                       rval = kxld_dict_insert(obsolete_symbols_by_name,
+                           kext_sym->name, kext_sym);
+                       require_noerr(rval, finish);
+               }
+       }
+
+       /* Add C++ symbols */
+       if (defined_cxx_symbols_by_value) {
+               (void) kxld_symtab_iterator_init(&iter, kext_symtab,
+                   kxld_sym_is_cxx, FALSE);
+               while ((kext_sym = kxld_symtab_iterator_get_next(&iter))) {
+                       rval = kxld_dict_insert(defined_cxx_symbols_by_value,
+                           &kext_sym->link_addr, kext_sym);
+                       require_noerr(rval, finish);
+               }
+       }
+
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -300,147 +303,163 @@ kern_return_t
 export_symbols(const KXLDObject *kext, KXLDDict *defined_symbols_by_name,
     KXLDDict *defined_cxx_symbols_by_value)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSymtabIterator iter;
-    KXLDSym *sym = NULL;
-
-    (void) kxld_symtab_iterator_init(&iter, kxld_object_get_symtab(kext), 
-        kxld_sym_is_exported, FALSE);
-    while ((sym = kxld_symtab_iterator_get_next(&iter))) {
-        if (defined_symbols_by_name) {
-            rval = kxld_dict_insert(defined_symbols_by_name, sym->name, sym);
-            require_noerr(rval, finish);
-        }
-
-        if (kxld_sym_is_cxx(sym) && defined_cxx_symbols_by_value) {
-            rval = kxld_dict_insert(defined_cxx_symbols_by_value,
-                &sym->link_addr, sym);
-            require_noerr(rval, finish);
-        }
-    }
-
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSymtabIterator iter;
+       KXLDSym *sym = NULL;
+
+       (void) kxld_symtab_iterator_init(&iter, kxld_object_get_symtab(kext),
+           kxld_sym_is_exported, FALSE);
+       while ((sym = kxld_symtab_iterator_get_next(&iter))) {
+               if (defined_symbols_by_name) {
+                       rval = kxld_dict_insert(defined_symbols_by_name, sym->name, sym);
+                       require_noerr(rval, finish);
+               }
+
+               if (kxld_sym_is_cxx(sym) && defined_cxx_symbols_by_value) {
+                       rval = kxld_dict_insert(defined_cxx_symbols_by_value,
+                           &sym->link_addr, sym);
+                       require_noerr(rval, finish);
+               }
+       }
+
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
 *******************************************************************************/
-kern_return_t 
+kern_return_t
 kxld_kext_export_vtables(KXLDKext *kext, const KXLDDict *defined_cxx_symbols,
     const KXLDDict *defined_symbols, KXLDDict *vtables)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDVTable *vtable = NULL;
-    u_int i = 0;
-
-    check(kext);
-    check(defined_symbols);
-    check(defined_cxx_symbols);
-    check(vtables);
-
-    rval = create_vtables(kext, defined_cxx_symbols, defined_symbols);
-    require_noerr(rval, finish);
-
-    for (i = 0; i < kext->vtables.nitems; ++i) {
-        vtable = kxld_array_get_item(&kext->vtables, i);
-
-        rval = kxld_dict_insert(vtables, vtable->name, vtable);
-        require_noerr(rval, finish);
-    }
-    
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDVTable *vtable = NULL;
+       u_int i = 0;
+
+       check(kext);
+       check(defined_symbols);
+       check(defined_cxx_symbols);
+       check(vtables);
+
+       rval = create_vtables(kext, defined_cxx_symbols, defined_symbols);
+       require_noerr(rval, finish);
+
+       for (i = 0; i < kext->vtables.nitems; ++i) {
+               vtable = kxld_array_get_item(&kext->vtables, i);
+
+               rval = kxld_dict_insert(vtables, vtable->name, vtable);
+               require_noerr(rval, finish);
+       }
+
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
+}
+
+/*******************************************************************************
+*******************************************************************************/
+void
+kxld_kext_get_vmsize_for_seg_by_name(const KXLDKext *kext,
+    const char *segname,
+    u_long *vmsize)
+{
+       (void) kxld_object_get_vmsize_for_seg_by_name(kext->kext, segname, vmsize);
 }
 
 /*******************************************************************************
 *******************************************************************************/
-void 
-kxld_kext_get_vmsize(const KXLDKext *kext, 
+void
+kxld_kext_get_vmsize(const KXLDKext *kext,
     u_long *header_size, u_long *vmsize)
 {
-    (void) kxld_object_get_vmsize(kext->kext, header_size, vmsize);
+       (void) kxld_object_get_vmsize(kext->kext, header_size, vmsize);
 }
 
 /*******************************************************************************
- *******************************************************************************/
-void 
+*******************************************************************************/
+void
 kxld_kext_set_linked_object_size(KXLDKext *kext, u_long vmsize)
 {
-    (void) kxld_object_set_linked_object_size(kext->kext, vmsize);
+       (void) kxld_object_set_linked_object_size(kext->kext, vmsize);
 }
 
-
 /*******************************************************************************
 *******************************************************************************/
-kern_return_t 
-kxld_kext_export_linked_object(const KXLDKext *kext, 
-    u_char *linked_object, kxld_addr_t *kmod_info)
+kern_return_t
+kxld_kext_export_linked_object(const KXLDKext *kext,
+    void *linked_object,
+    kxld_addr_t *kmod_info)
 {
-    kern_return_t rval = KERN_FAILURE;
-    const KXLDSym *kmodsym = NULL;
+       kern_return_t rval = KERN_FAILURE;
+       const KXLDSym *kmodsym = NULL;
+
+       kmodsym = kxld_symtab_get_locally_defined_symbol_by_name(
+               kxld_object_get_symtab(kext->kext), KXLD_KMOD_INFO_SYMBOL);
+
+       require_action(kmodsym, finish, rval = KERN_FAILURE;
+           kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogNoKmodInfo));
 
-    kmodsym = kxld_symtab_get_locally_defined_symbol_by_name(
-        kxld_object_get_symtab(kext->kext), KXLD_KMOD_INFO_SYMBOL);
-    require_action(kmodsym, finish, rval=KERN_FAILURE;
-        kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogNoKmodInfo));
-    *kmod_info = kmodsym->link_addr;
+       *kmod_info = kmodsym->link_addr;
 
-    rval = kxld_object_export_linked_object(kext->kext, linked_object);
+       rval = kxld_object_export_linked_object(kext->kext, linked_object);
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
 *******************************************************************************/
 kern_return_t
-kxld_kext_relocate(KXLDKext *kext, kxld_addr_t link_address,
-    KXLDDict *patched_vtables, const KXLDDict *defined_symbols, 
-    const KXLDDict *obsolete_symbols, const KXLDDict *defined_cxx_symbols)
+kxld_kext_relocate(KXLDKext *kext,
+    kxld_addr_t link_address,
+    KXLDDict *patched_vtables,
+    const KXLDDict *defined_symbols,
+    const KXLDDict *obsolete_symbols,
+    const KXLDDict *defined_cxx_symbols)
 {
-    kern_return_t rval = KERN_FAILURE;
+       kern_return_t rval = KERN_FAILURE;
 
-    check(kext);
-    check(patched_vtables);
-    check(defined_symbols);
-    check(obsolete_symbols);
+       check(kext);
+       check(patched_vtables);
+       check(defined_symbols);
+       check(obsolete_symbols);
 
-    /* Kexts that are being relocated need symbols indexed by value for vtable
-     * creation and patching. Note that we don't need to index by value for
-     * dependencies that have already been linked because their symbols are
-     * already in the global cxx value table. It's important to index the
-     * symbols by value before we relocate the symbols because the vtable
-     * entries will still have unrelocated values.
-     */
-    rval = kxld_object_index_cxx_symbols_by_value(kext->kext);
-    require_noerr(rval, finish);
+       /* Kexts that are being relocated need symbols indexed by value for vtable
+        * creation and patching. Note that we don't need to index by value for
+        * dependencies that have already been linked because their symbols are
+        * already in the global cxx value table. It's important to index the
+        * symbols by value before we relocate the symbols because the vtable
+        * entries will still have unrelocated values.
+        */
+       rval = kxld_object_index_cxx_symbols_by_value(kext->kext);
+       require_noerr(rval, finish);
 
-    rval = kxld_object_index_symbols_by_name(kext->kext);
-    require_noerr(rval, finish);
+       rval = kxld_object_index_symbols_by_name(kext->kext);
+       require_noerr(rval, finish);
 
-    rval = kxld_object_relocate(kext->kext, link_address);
-    require_noerr(rval, finish);
+       rval = kxld_object_relocate(kext->kext, link_address);
+       require_noerr(rval, finish);
 
-    rval = resolve_symbols(kext, defined_symbols, obsolete_symbols);
-    require_noerr(rval, finish);
+       rval = resolve_symbols(kext, defined_symbols, obsolete_symbols);
+       require_noerr(rval, finish);
 
-    rval = create_vtables(kext, defined_cxx_symbols, /* defined_symbols */ NULL);
-    require_noerr(rval, finish);
+       rval = create_vtables(kext, defined_cxx_symbols, /* defined_symbols */ NULL);
+       require_noerr(rval, finish);
 
-    rval = patch_vtables(kext, patched_vtables, defined_symbols);
-    require_noerr(rval, finish);
-    
-    rval = validate_symbols(kext);
-    require_noerr(rval, finish);
+       if (isSplitKext == FALSE) {
+               rval = patch_vtables(kext, patched_vtables, defined_symbols);
+               require_noerr(rval, finish);
+       }
 
-    rval = kxld_object_process_relocations(kext->kext, patched_vtables);
-    require_noerr(rval, finish);
+       rval = validate_symbols(kext);
+       require_noerr(rval, finish);
 
-    rval = KERN_SUCCESS;
+       rval = kxld_object_process_relocations(kext->kext, patched_vtables);
+       require_noerr(rval, finish);
+
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -453,317 +472,317 @@ finish:
 * linked kexts export their symbols into the global symbol table that is used
 * for symbol resolution, so we can look there for vtable symbols without
 * having to index their local symbol table separately.
-* 
+*
 * Unlinked kexts haven't yet had their symbols exported into the global table,
 * so we have to index their local symbol table separately.
 *******************************************************************************/
-static kern_return_t 
+static kern_return_t
 create_vtables(KXLDKext *kext, const KXLDDict *defined_cxx_symbols,
     const KXLDDict *defined_symbols)
 {
-    kern_return_t rval = KERN_FAILURE;
-    const KXLDSymtab *symtab = NULL;
-    KXLDSymtabIterator iter;
-    KXLDSym *sym = NULL;
-    KXLDSym *vtable_sym = NULL;
-    KXLDSym *meta_vtable_sym = NULL;
-    KXLDVTable *vtable = NULL;
-    KXLDVTable *meta_vtable = NULL;
-    u_int i = 0;
-    u_int nvtables = 0;
-
-    if (kext->vtables_created) {
-        rval = KERN_SUCCESS;
-        goto finish;
-    }
-
-    symtab = kxld_object_get_symtab(kext->kext);
-
-    if (kxld_object_is_linked(kext->kext)) {
-        /* Create a vtable object for every vtable symbol */
-        kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_vtable, FALSE);
-        nvtables = kxld_symtab_iterator_get_num_remaining(&iter);
-    } else {
-        /* We walk over the super metaclass pointer symbols because classes
-         * with them are the only ones that need patching.  Then we double the
-         * number of vtables we're expecting, because every pointer will have a
-         * class vtable and a MetaClass vtable.
-         */
-        kxld_symtab_iterator_init(&iter, symtab, 
-            kxld_sym_is_super_metaclass_pointer, FALSE);
-        nvtables = kxld_symtab_iterator_get_num_remaining(&iter) * 2;
-    }
-
-    rval = kxld_array_init(&kext->vtables, sizeof(KXLDVTable), nvtables);
-    require_noerr(rval, finish);
-
-    while ((sym = kxld_symtab_iterator_get_next(&iter))) {
-        if (kxld_object_is_linked(kext->kext)) {
-            vtable_sym = sym;
-            meta_vtable_sym = NULL;
-            meta_vtable = NULL;
-        } else {
-            rval = get_vtable_syms_from_smcp(kext, defined_symbols, sym,
-                &vtable_sym, &meta_vtable_sym);
-            require_noerr(rval, finish);
-        }
-
-        vtable = kxld_array_get_item(&kext->vtables, i++);
-        rval = kxld_vtable_init(vtable, vtable_sym, kext->kext, 
-            defined_cxx_symbols);
-        require_noerr(rval, finish);
-
-        /* meta_vtable_sym will be null when we don't support strict
-         * patching and can't find the metaclass vtable. If that's the
-         * case, we just reduce the expect number of vtables by 1.
-         */
-        if (!kxld_object_is_linked(kext->kext)) {
-            if (meta_vtable_sym) {
-                meta_vtable = kxld_array_get_item(&kext->vtables, i++);
-                rval = kxld_vtable_init(meta_vtable, meta_vtable_sym, 
-                    kext->kext, defined_cxx_symbols);
-                require_noerr(rval, finish);
-            } else {
-                kxld_array_resize(&kext->vtables, --nvtables);
-                meta_vtable = NULL;
-            }
-        }
-    }
-    require_action(i == kext->vtables.nitems, finish, 
-        rval=KERN_FAILURE);
-
-    kext->vtables_created = TRUE;
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+       const KXLDSymtab *symtab = NULL;
+       KXLDSymtabIterator iter;
+       KXLDSym *sym = NULL;
+       KXLDSym *vtable_sym = NULL;
+       KXLDSym *meta_vtable_sym = NULL;
+       KXLDVTable *vtable = NULL;
+       KXLDVTable *meta_vtable = NULL;
+       u_int i = 0;
+       u_int nvtables = 0;
+
+       if (kext->vtables_created) {
+               rval = KERN_SUCCESS;
+               goto finish;
+       }
+
+       symtab = kxld_object_get_symtab(kext->kext);
+
+       if (kxld_object_is_linked(kext->kext)) {
+               /* Create a vtable object for every vtable symbol */
+               kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_vtable, FALSE);
+               nvtables = kxld_symtab_iterator_get_num_remaining(&iter);
+       } else {
+               /* We walk over the super metaclass pointer symbols because classes
+                * with them are the only ones that need patching.  Then we double the
+                * number of vtables we're expecting, because every pointer will have a
+                * class vtable and a MetaClass vtable.
+                */
+               kxld_symtab_iterator_init(&iter, symtab,
+                   kxld_sym_is_super_metaclass_pointer, FALSE);
+               nvtables = kxld_symtab_iterator_get_num_remaining(&iter) * 2;
+       }
+
+       rval = kxld_array_init(&kext->vtables, sizeof(KXLDVTable), nvtables);
+       require_noerr(rval, finish);
+
+       while ((sym = kxld_symtab_iterator_get_next(&iter))) {
+               if (kxld_object_is_linked(kext->kext)) {
+                       vtable_sym = sym;
+                       meta_vtable_sym = NULL;
+                       meta_vtable = NULL;
+               } else {
+                       rval = get_vtable_syms_from_smcp(kext, defined_symbols, sym,
+                           &vtable_sym, &meta_vtable_sym);
+                       require_noerr(rval, finish);
+               }
+
+               vtable = kxld_array_get_item(&kext->vtables, i++);
+               rval = kxld_vtable_init(vtable, vtable_sym, kext->kext,
+                   defined_cxx_symbols);
+               require_noerr(rval, finish);
+
+               /* meta_vtable_sym will be null when we don't support strict
+                * patching and can't find the metaclass vtable. If that's the
+                * case, we just reduce the expect number of vtables by 1.
+                */
+               if (!kxld_object_is_linked(kext->kext)) {
+                       if (meta_vtable_sym) {
+                               meta_vtable = kxld_array_get_item(&kext->vtables, i++);
+                               rval = kxld_vtable_init(meta_vtable, meta_vtable_sym,
+                                   kext->kext, defined_cxx_symbols);
+                               require_noerr(rval, finish);
+                       } else {
+                               kxld_array_resize(&kext->vtables, --nvtables);
+                               meta_vtable = NULL;
+                       }
+               }
+       }
+       require_action(i == kext->vtables.nitems, finish,
+           rval = KERN_FAILURE);
+
+       kext->vtables_created = TRUE;
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
 *******************************************************************************/
 static kern_return_t
 get_vtable_syms_from_smcp(KXLDKext *kext, const KXLDDict *defined_symbols,
-    KXLDSym *super_metaclass_ptr_sym, KXLDSym **vtable_sym_out, 
+    KXLDSym *super_metaclass_ptr_sym, KXLDSym **vtable_sym_out,
     KXLDSym **meta_vtable_sym_out)
 {
-    kern_return_t rval = KERN_FAILURE;
-    const KXLDSymtab *symtab = NULL;
-    KXLDSym *vtable_sym = NULL;
-    KXLDSym *meta_vtable_sym = NULL;
-    char class_name[KXLD_MAX_NAME_LEN];
-    char vtable_name[KXLD_MAX_NAME_LEN];
-    char meta_vtable_name[KXLD_MAX_NAME_LEN];
-    char *demangled_name1 = NULL;
-    char *demangled_name2 = NULL;
-    size_t demangled_length1 = 0;
-    size_t demangled_length2 = 0;
-
-    check(kext);
-    check(vtable_sym_out);
-    check(meta_vtable_sym_out);
-
-    require(!kxld_object_is_kernel(kext->kext), finish);
-
-    symtab = kxld_object_get_symtab(kext->kext);
-
-    /* Get the class name from the smc pointer */
-    rval = kxld_sym_get_class_name_from_super_metaclass_pointer(
-        super_metaclass_ptr_sym, class_name, sizeof(class_name));
-    require_noerr(rval, finish);
-
-    /* Get the vtable name from the class name */
-    rval = kxld_sym_get_vtable_name_from_class_name(class_name,
-        vtable_name, sizeof(vtable_name));
-    require_noerr(rval, finish);
-
-    /* Get the vtable symbol */
-    if (defined_symbols) {
-        vtable_sym = kxld_dict_find(defined_symbols, vtable_name);
-    } else {
-        vtable_sym = kxld_symtab_get_locally_defined_symbol_by_name(symtab, 
-            vtable_name);
-    }
-    require_action(vtable_sym, finish, rval=KERN_FAILURE;
-        kxld_log(kKxldLogPatching, kKxldLogErr, kKxldLogMissingVtable,
-        vtable_name, class_name));
-
-    /* Get the meta vtable name from the class name */
-    rval = kxld_sym_get_meta_vtable_name_from_class_name(class_name,
-        meta_vtable_name, sizeof(meta_vtable_name));
-    require_noerr(rval, finish);
-
-    /* Get the meta vtable symbol */
-    if (defined_symbols) {
-        meta_vtable_sym = kxld_dict_find(defined_symbols, meta_vtable_name);
-    } else {
-        meta_vtable_sym = kxld_symtab_get_locally_defined_symbol_by_name(symtab,
-            meta_vtable_name);
-    }
-    if (!meta_vtable_sym) {
-        if (kxld_object_target_supports_strict_patching(kext->kext)) {
-            kxld_log(kKxldLogPatching, kKxldLogErr, 
-                kKxldLogMissingVtable, 
-                meta_vtable_name, class_name);
-            rval = KERN_FAILURE;
-            goto finish;
-        } else {
-            kxld_log(kKxldLogPatching, kKxldLogErr, 
-                "Warning: " kKxldLogMissingVtable, 
-                kxld_demangle(meta_vtable_name, &demangled_name1, 
-                    &demangled_length1), 
-                kxld_demangle(class_name, &demangled_name2, 
-                    &demangled_length2));
-        }
-    }
-    
-    *vtable_sym_out = vtable_sym;
-    *meta_vtable_sym_out = meta_vtable_sym;
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+       const KXLDSymtab *symtab = NULL;
+       KXLDSym *vtable_sym = NULL;
+       KXLDSym *meta_vtable_sym = NULL;
+       char class_name[KXLD_MAX_NAME_LEN];
+       char vtable_name[KXLD_MAX_NAME_LEN];
+       char meta_vtable_name[KXLD_MAX_NAME_LEN];
+       char *demangled_name1 = NULL;
+       char *demangled_name2 = NULL;
+       size_t demangled_length1 = 0;
+       size_t demangled_length2 = 0;
+
+       check(kext);
+       check(vtable_sym_out);
+       check(meta_vtable_sym_out);
+
+       require(!kxld_object_is_kernel(kext->kext), finish);
+
+       symtab = kxld_object_get_symtab(kext->kext);
+
+       /* Get the class name from the smc pointer */
+       rval = kxld_sym_get_class_name_from_super_metaclass_pointer(
+               super_metaclass_ptr_sym, class_name, sizeof(class_name));
+       require_noerr(rval, finish);
+
+       /* Get the vtable name from the class name */
+       rval = kxld_sym_get_vtable_name_from_class_name(class_name,
+           vtable_name, sizeof(vtable_name));
+       require_noerr(rval, finish);
+
+       /* Get the vtable symbol */
+       if (defined_symbols) {
+               vtable_sym = kxld_dict_find(defined_symbols, vtable_name);
+       } else {
+               vtable_sym = kxld_symtab_get_locally_defined_symbol_by_name(symtab,
+                   vtable_name);
+       }
+       require_action(vtable_sym, finish, rval = KERN_FAILURE;
+           kxld_log(kKxldLogPatching, kKxldLogErr, kKxldLogMissingVtable,
+           vtable_name, class_name));
+
+       /* Get the meta vtable name from the class name */
+       rval = kxld_sym_get_meta_vtable_name_from_class_name(class_name,
+           meta_vtable_name, sizeof(meta_vtable_name));
+       require_noerr(rval, finish);
+
+       /* Get the meta vtable symbol */
+       if (defined_symbols) {
+               meta_vtable_sym = kxld_dict_find(defined_symbols, meta_vtable_name);
+       } else {
+               meta_vtable_sym = kxld_symtab_get_locally_defined_symbol_by_name(symtab,
+                   meta_vtable_name);
+       }
+       if (!meta_vtable_sym) {
+               if (kxld_object_target_supports_strict_patching(kext->kext)) {
+                       kxld_log(kKxldLogPatching, kKxldLogErr,
+                           kKxldLogMissingVtable,
+                           meta_vtable_name, class_name);
+                       rval = KERN_FAILURE;
+                       goto finish;
+               } else {
+                       kxld_log(kKxldLogPatching, kKxldLogErr,
+                           "Warning: " kKxldLogMissingVtable,
+                           kxld_demangle(meta_vtable_name, &demangled_name1,
+                           &demangled_length1),
+                           kxld_demangle(class_name, &demangled_name2,
+                           &demangled_length2));
+               }
+       }
+
+       *vtable_sym_out = vtable_sym;
+       *meta_vtable_sym_out = meta_vtable_sym;
+       rval = KERN_SUCCESS;
 finish:
-    if (demangled_name1) kxld_free(demangled_name1, demangled_length1);
-    if (demangled_name2) kxld_free(demangled_name2, demangled_length2);
-
-    return rval;
+       if (demangled_name1) {
+               kxld_free(demangled_name1, demangled_length1);
+       }
+       if (demangled_name2) {
+               kxld_free(demangled_name2, demangled_length2);
+       }
+
+       return rval;
 }
 
 /*******************************************************************************
 *******************************************************************************/
 static kern_return_t
-resolve_symbols(KXLDKext *kext, const KXLDDict *defined_symbols, 
+resolve_symbols(KXLDKext *kext, const KXLDDict *defined_symbols,
     const KXLDDict *obsolete_symbols)
 {
-    kern_return_t rval = KERN_FAILURE;
-    const KXLDSymtab *symtab = NULL;
-    KXLDSymtabIterator iter;
-    KXLDSym *sym = NULL;
-    KXLDSym *defined_sym = NULL;
-    const char *name = NULL;
-    boolean_t tests_for_weak = FALSE;
-    boolean_t error = FALSE;
-    char *demangled_name = NULL;
-    size_t demangled_length = 0;
-
-    check(kext->kext);
-    check(defined_symbols);
-    check(obsolete_symbols);
-
-    symtab = kxld_object_get_symtab(kext->kext);
-
-    /* Check if the kext tests for weak symbols */
-    sym = kxld_symtab_get_symbol_by_name(symtab, KXLD_WEAK_TEST_SYMBOL);
-    tests_for_weak = (sym != NULL);
-
-    /* Check for duplicate symbols */
-    kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_exported, FALSE);
-    while ((sym = kxld_symtab_iterator_get_next(&iter))) {
-        defined_sym = kxld_dict_find(defined_symbols, sym->name);
-        if (defined_sym) { 
-            /* Not a problem if the symbols have the same address */
-            if (defined_sym->link_addr == sym->link_addr) {
-                continue;
-            }
-
-            if (!error) {
-                error = TRUE;
-                kxld_log(kKxldLogLinking, kKxldLogErr,
-                    "The following symbols were defined more than once:");
-            }
-
-            kxld_log(kKxldLogLinking, kKxldLogErr, "\t%s: %p - %p", 
-                kxld_demangle(sym->name, &demangled_name, &demangled_length),
-                (void *) (uintptr_t) sym->link_addr, 
-                (void *) (uintptr_t) defined_sym->link_addr);
-        }
-    }
-    require_noerr_action(error, finish, rval=KERN_FAILURE);
-
-    /* Resolve undefined and indirect symbols */
-
-    /* Iterate over all unresolved symbols */
-    kxld_symtab_iterator_init(&iter, symtab, 
-        kxld_sym_is_unresolved, FALSE);
-    while ((sym = kxld_symtab_iterator_get_next(&iter))) {
-
-        /* Common symbols are not supported */
-        if (kxld_sym_is_common(sym)) {
-
-            if (!error) {
-                error = TRUE;
-                if (kxld_object_target_supports_common_symbols(kext->kext)) {
-                    kxld_log(kKxldLogLinking, kKxldLogErr, 
-                        "The following common symbols were not resolved:");
-                } else {
-                    kxld_log(kKxldLogLinking, kKxldLogErr, 
-                        "Common symbols are not supported in kernel extensions. " 
-                         "Use -fno-common to build your kext. "
-                         "The following are common symbols:");
-                }
-            }
-            kxld_log(kKxldLogLinking, kKxldLogErr, "\t%s", 
-                kxld_demangle(sym->name, &demangled_name, &demangled_length));
-
-        } else {
-
-            /* Find the address of the defined symbol */
-            if (kxld_sym_is_undefined(sym)) {
-                name = sym->name;
-            } else {
-                name = sym->alias;
-            }
-            defined_sym = kxld_dict_find(defined_symbols, name);
-            
-            /* Resolve the symbol.  If a definition cannot be found, then:
-             * 1) Psuedokexts log a warning and proceed
-             * 2) Actual kexts delay the error until validation in case vtable
-             *    patching replaces the undefined symbol.
-             */
-
-            if (defined_sym) {
-
-                rval = kxld_sym_resolve(sym, defined_sym->link_addr);
-                require_noerr(rval, finish);
-
-                if (obsolete_symbols && kxld_dict_find(obsolete_symbols, name)) {
-                    kxld_log(kKxldLogLinking, kKxldLogWarn, 
-                        "This kext uses obsolete symbol %s.", 
-                        kxld_demangle(name, &demangled_name, &demangled_length));
-                }
-
-            } else if (kxld_sym_is_weak(sym)) {
-                kxld_addr_t addr = 0;
-
-                /* Make sure that the kext has referenced gOSKextUnresolved.
-                 */
-                require_action(tests_for_weak, finish, 
-                   rval=KERN_FAILURE;
-                   kxld_log(kKxldLogLinking, kKxldLogErr, 
-                      "This kext has weak references but does not test for "
-                      "them. Test for weak references with "
-                      "OSKextIsSymbolResolved()."));
+       kern_return_t rval = KERN_FAILURE;
+       const KXLDSymtab *symtab = NULL;
+       KXLDSymtabIterator iter;
+       KXLDSym *sym = NULL;
+       KXLDSym *defined_sym = NULL;
+       const char *name = NULL;
+       boolean_t tests_for_weak = FALSE;
+       boolean_t error = FALSE;
+       char *demangled_name = NULL;
+       size_t demangled_length = 0;
+
+       check(kext->kext);
+       check(defined_symbols);
+       check(obsolete_symbols);
+
+       symtab = kxld_object_get_symtab(kext->kext);
+
+       /* Check if the kext tests for weak symbols */
+       sym = kxld_symtab_get_symbol_by_name(symtab, KXLD_WEAK_TEST_SYMBOL);
+       tests_for_weak = (sym != NULL);
+
+       /* Check for duplicate symbols */
+       kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_exported, FALSE);
+       while ((sym = kxld_symtab_iterator_get_next(&iter))) {
+               defined_sym = kxld_dict_find(defined_symbols, sym->name);
+               if (defined_sym) {
+                       /* Not a problem if the symbols have the same address */
+                       if (defined_sym->link_addr == sym->link_addr) {
+                               continue;
+                       }
+
+                       if (!error) {
+                               error = TRUE;
+                               kxld_log(kKxldLogLinking, kKxldLogErr,
+                                   "The following symbols were defined more than once:");
+                       }
+
+                       kxld_log(kKxldLogLinking, kKxldLogErr, "\t%s: %p - %p",
+                           kxld_demangle(sym->name, &demangled_name, &demangled_length),
+                           (void *) (uintptr_t) sym->link_addr,
+                           (void *) (uintptr_t) defined_sym->link_addr);
+               }
+       }
+       require_noerr_action(error, finish, rval = KERN_FAILURE);
+
+       /* Resolve undefined and indirect symbols */
+
+       /* Iterate over all unresolved symbols */
+       kxld_symtab_iterator_init(&iter, symtab,
+           kxld_sym_is_unresolved, FALSE);
+       while ((sym = kxld_symtab_iterator_get_next(&iter))) {
+               /* Common symbols are not supported */
+               if (kxld_sym_is_common(sym)) {
+                       if (!error) {
+                               error = TRUE;
+                               if (kxld_object_target_supports_common_symbols(kext->kext)) {
+                                       kxld_log(kKxldLogLinking, kKxldLogErr,
+                                           "The following common symbols were not resolved:");
+                               } else {
+                                       kxld_log(kKxldLogLinking, kKxldLogErr,
+                                           "Common symbols are not supported in kernel extensions. "
+                                           "Use -fno-common to build your kext. "
+                                           "The following are common symbols:");
+                               }
+                       }
+                       kxld_log(kKxldLogLinking, kKxldLogErr, "\t%s",
+                           kxld_demangle(sym->name, &demangled_name, &demangled_length));
+               } else {
+                       /* Find the address of the defined symbol */
+                       if (kxld_sym_is_undefined(sym)) {
+                               name = sym->name;
+                       } else {
+                               name = sym->alias;
+                       }
+                       defined_sym = kxld_dict_find(defined_symbols, name);
+
+                       /* Resolve the symbol.  If a definition cannot be found, then:
+                        * 1) Psuedokexts log a warning and proceed
+                        * 2) Actual kexts delay the error until validation in case vtable
+                        *    patching replaces the undefined symbol.
+                        */
+
+                       if (defined_sym) {
+                               rval = kxld_sym_resolve(sym, defined_sym->link_addr);
+                               require_noerr(rval, finish);
+
+                               if (obsolete_symbols && kxld_dict_find(obsolete_symbols, name)) {
+                                       kxld_log(kKxldLogLinking, kKxldLogWarn,
+                                           "This kext uses obsolete symbol %s.",
+                                           kxld_demangle(name, &demangled_name, &demangled_length));
+                               }
+                       } else if (kxld_sym_is_weak(sym)) {
+                               kxld_addr_t addr = 0;
+
+                               /* Make sure that the kext has referenced gOSKextUnresolved.
+                                */
+                               require_action(tests_for_weak, finish,
+                                   rval = KERN_FAILURE;
+                                   kxld_log(kKxldLogLinking, kKxldLogErr,
+                                   "This kext has weak references but does not test for "
+                                   "them. Test for weak references with "
+                                   "OSKextSymbolIsResolved(). (found in <libkern/OSKextLib.h>)"));
 
 #if KERNEL
-                /* Get the address of the default weak address.
-                 */
-                addr = (kxld_addr_t) &kext_weak_symbol_referenced;
-#else  
-                /* This is run during symbol generation only, so we only 
-                 * need a filler value here.
-                 */
-                addr = 0xF00DD00D;
+                               /* Get the address of the default weak address.
+                                */
+                               addr = (kxld_addr_t) &kext_weak_symbol_referenced;
+#else
+                               /* This is run during symbol generation only, so we only
+                                * need a filler value here.
+                                */
+                               addr = 0xF00DD00D;
 #endif /* KERNEL */
 
-                rval = kxld_sym_resolve(sym, addr);
-                require_noerr(rval, finish);
-            }
-        }
-    }
-    require_noerr_action(error, finish, rval=KERN_FAILURE);
+                               rval = kxld_sym_resolve(sym, addr);
+                               require_noerr(rval, finish);
+                       }
+               }
+       }
+       require_noerr_action(error, finish, rval = KERN_FAILURE);
 
-    rval = KERN_SUCCESS;
+       rval = KERN_SUCCESS;
 
 finish:
-    if (demangled_name) kxld_free(demangled_name, demangled_length);
+       if (demangled_name) {
+               kxld_free(demangled_name, demangled_length);
+       }
 
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -792,197 +811,203 @@ finish:
 #define kOSMetaClassVTableName "__ZTV11OSMetaClass"
 
 static kern_return_t
-patch_vtables(KXLDKext *kext, KXLDDict *patched_vtables, 
+patch_vtables(KXLDKext *kext, KXLDDict *patched_vtables,
     const KXLDDict *defined_symbols)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSymtabIterator iter;
-    const KXLDSymtab *symtab = NULL;
-    const KXLDSym *metaclass = NULL;
-    KXLDSym *super_metaclass_pointer = NULL;
-    KXLDSym *final_sym = NULL;
-    KXLDVTable *vtable = NULL;
-    KXLDVTable *super_vtable = NULL;
-    char class_name[KXLD_MAX_NAME_LEN];
-    char super_class_name[KXLD_MAX_NAME_LEN];
-    char vtable_name[KXLD_MAX_NAME_LEN];
-    char super_vtable_name[KXLD_MAX_NAME_LEN];
-    char final_sym_name[KXLD_MAX_NAME_LEN];
-    char *demangled_name1 = NULL;
-    char *demangled_name2 = NULL;
-    size_t demangled_length1 = 0;;
-    size_t demangled_length2 = 0;
-    size_t len = 0;
-    u_int nvtables = 0;
-    u_int npatched = 0;
-    u_int nprogress = 0;
-    boolean_t failure = FALSE;
-
-    check(kext);
-    check(patched_vtables);
-
-    symtab = kxld_object_get_symtab(kext->kext);
-
-    rval = create_vtable_index(kext);
-    require_noerr(rval, finish);
-
-    /* Find each super meta class pointer symbol */
-
-    kxld_symtab_iterator_init(&iter, symtab, 
-        kxld_sym_is_super_metaclass_pointer, FALSE);
-    nvtables = kxld_symtab_iterator_get_num_remaining(&iter);
-
-    while (npatched < nvtables) {
-        npatched = 0;
-        nprogress = 0;
-        kxld_symtab_iterator_reset(&iter);
-        while((super_metaclass_pointer = kxld_symtab_iterator_get_next(&iter))) 
-        {
-            /* Get the class name from the smc pointer */
-            rval = kxld_sym_get_class_name_from_super_metaclass_pointer(
-                super_metaclass_pointer, class_name, sizeof(class_name));
-            require_noerr(rval, finish);
-
-            /* Get the vtable name from the class name */
-            rval = kxld_sym_get_vtable_name_from_class_name(class_name,
-                vtable_name, sizeof(vtable_name));
-            require_noerr(rval, finish);
-
-            /* Get the vtable and make sure it hasn't been patched */
-            vtable = kxld_dict_find(&kext->vtable_index, vtable_name);
-            require_action(vtable, finish, rval=KERN_FAILURE;
-                kxld_log(kKxldLogPatching, kKxldLogErr, kKxldLogMissingVtable,
-                    vtable_name, class_name));
-
-            if (!vtable->is_patched) {
-
-                /* Find the SMCP's meta class symbol */
-                metaclass = get_metaclass_symbol_from_super_meta_class_pointer_symbol(
-                    kext, super_metaclass_pointer);
-                require_action(metaclass, finish, rval=KERN_FAILURE);
-
-                /* Get the super class name from the super metaclass */
-                rval = kxld_sym_get_class_name_from_metaclass(metaclass,
-                    super_class_name, sizeof(super_class_name));
-                require_noerr(rval, finish);
-
-                /* Get the super vtable name from the class name */
-                rval = kxld_sym_get_vtable_name_from_class_name(super_class_name,
-                    super_vtable_name, sizeof(super_vtable_name));
-                require_noerr(rval, finish);
-
-                /* Get the super vtable if it's been patched */
-                super_vtable = kxld_dict_find(patched_vtables, super_vtable_name);
-
-                if (failure) {
-                    const KXLDVTable *unpatched_super_vtable;
-                    unpatched_super_vtable = kxld_dict_find(&kext->vtable_index,
-                        super_vtable_name);
-
-                    /* If the parent's vtable hasn't been patched, warn that
-                     * this vtable is unpatchable because of the parent.
-                     */
-                    if (!super_vtable) {
-                        kxld_log(kKxldLogPatching, kKxldLogErr, 
-                            "The %s was not patched because its parent, "
-                            "the %s, was not %s.",
-                            kxld_demangle(vtable_name, &demangled_name1, 
-                                &demangled_length1), 
-                            kxld_demangle(super_vtable_name, &demangled_name2, 
-                                &demangled_length2),
-                            (unpatched_super_vtable) ? "patchable" : "found");
-                    }
-                    continue;
-                }
-
-                if (!super_vtable) continue;
-
-                /* Get the final symbol's name from the super vtable */
-                rval = kxld_sym_get_final_sym_name_from_class_name(super_class_name, 
-                    final_sym_name, sizeof(final_sym_name));
-                require_noerr(rval, finish);
-
-                /* Verify that the final symbol does not exist.  First check
-                 * all the externally defined symbols, then check locally.
-                 */
-                final_sym = kxld_dict_find(defined_symbols, final_sym_name);
-                if (!final_sym) {
-                    final_sym = kxld_symtab_get_locally_defined_symbol_by_name(
-                        symtab, final_sym_name);
-                }
-                if (final_sym) {
-                    kxld_log(kKxldLogPatching, kKxldLogErr, 
-                        "Class '%s' is a subclass of final class '%s'.",
-                        kxld_demangle(class_name, &demangled_name1, 
-                            &demangled_length1), 
-                        kxld_demangle(super_class_name, &demangled_name2, 
-                            &demangled_length2));
-                    continue;
-                }
-
-                /* Patch the class's vtable */
-                rval = kxld_vtable_patch(vtable, super_vtable, kext->kext);
-                if (rval) continue;
-
-                /* Add the class's vtable to the set of patched vtables */
-                rval = kxld_dict_insert(patched_vtables, vtable->name, vtable);
-                require_noerr(rval, finish);
-
-                /* Get the meta vtable name from the class name */
-                rval = kxld_sym_get_meta_vtable_name_from_class_name(class_name,
-                    vtable_name, sizeof(vtable_name));
-                require_noerr(rval, finish);
-
-                /* Get the meta vtable.  Whether or not it should exist has already
-                 * been tested in create_vtables(), so if it doesn't exist and we're
-                 * still running, we can safely skip it.
-                 */
-                vtable = kxld_dict_find(&kext->vtable_index, vtable_name);
-                if (!vtable) {
-                    ++nprogress;
-                    ++npatched;
-                    continue;
-                }
-                require_action(!vtable->is_patched, finish, rval=KERN_FAILURE);
-
-                /* There is no way to look up a metaclass vtable at runtime, but
-                 * we know that every class's metaclass inherits directly from 
-                 * OSMetaClass, so we just hardcode that vtable name here.
-                 */
-                len = strlcpy(super_vtable_name, kOSMetaClassVTableName,
-                    sizeof(super_vtable_name));
-                require_action(len == const_strlen(kOSMetaClassVTableName),
-                    finish, rval=KERN_FAILURE);
-                       
-                /* Get the super meta vtable */
-                super_vtable = kxld_dict_find(patched_vtables, super_vtable_name);
-                require_action(super_vtable && super_vtable->is_patched, 
-                    finish, rval=KERN_FAILURE);
-
-                /* Patch the meta class's vtable */
-                rval = kxld_vtable_patch(vtable, super_vtable, kext->kext);
-                require_noerr(rval, finish);
-
-                /* Add the MetaClass's vtable to the set of patched vtables */
-                rval = kxld_dict_insert(patched_vtables, vtable->name, vtable);
-                require_noerr(rval, finish);
-                
-                ++nprogress;
-            }
-
-            ++npatched;
-        }
-
-        require_action(!failure, finish, rval=KERN_FAILURE);
-        failure = (nprogress == 0);
-    }
-
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSymtabIterator iter;
+       const KXLDSymtab *symtab = NULL;
+       const KXLDSym *metaclass = NULL;
+       KXLDSym *super_metaclass_pointer = NULL;
+       KXLDSym *final_sym = NULL;
+       KXLDVTable *vtable = NULL;
+       KXLDVTable *super_vtable = NULL;
+       char class_name[KXLD_MAX_NAME_LEN];
+       char super_class_name[KXLD_MAX_NAME_LEN];
+       char vtable_name[KXLD_MAX_NAME_LEN];
+       char super_vtable_name[KXLD_MAX_NAME_LEN];
+       char final_sym_name[KXLD_MAX_NAME_LEN];
+       char *demangled_name1 = NULL;
+       char *demangled_name2 = NULL;
+       size_t demangled_length1 = 0;;
+       size_t demangled_length2 = 0;
+       size_t len = 0;
+       u_int nvtables = 0;
+       u_int npatched = 0;
+       u_int nprogress = 0;
+       boolean_t failure = FALSE;
+
+       check(kext);
+       check(patched_vtables);
+
+       symtab = kxld_object_get_symtab(kext->kext);
+
+       rval = create_vtable_index(kext);
+       require_noerr(rval, finish);
+
+       /* Find each super meta class pointer symbol */
+
+       kxld_symtab_iterator_init(&iter, symtab,
+           kxld_sym_is_super_metaclass_pointer, FALSE);
+       nvtables = kxld_symtab_iterator_get_num_remaining(&iter);
+
+       while (npatched < nvtables) {
+               npatched = 0;
+               nprogress = 0;
+               kxld_symtab_iterator_reset(&iter);
+               while ((super_metaclass_pointer = kxld_symtab_iterator_get_next(&iter))) {
+                       /* Get the class name from the smc pointer */
+                       rval = kxld_sym_get_class_name_from_super_metaclass_pointer(
+                               super_metaclass_pointer, class_name, sizeof(class_name));
+                       require_noerr(rval, finish);
+
+                       /* Get the vtable name from the class name */
+                       rval = kxld_sym_get_vtable_name_from_class_name(class_name,
+                           vtable_name, sizeof(vtable_name));
+                       require_noerr(rval, finish);
+
+                       /* Get the vtable and make sure it hasn't been patched */
+                       vtable = kxld_dict_find(&kext->vtable_index, vtable_name);
+                       require_action(vtable, finish, rval = KERN_FAILURE;
+                           kxld_log(kKxldLogPatching, kKxldLogErr, kKxldLogMissingVtable,
+                           vtable_name, class_name));
+
+                       if (!vtable->is_patched) {
+                               /* Find the SMCP's meta class symbol */
+                               metaclass = get_metaclass_symbol_from_super_meta_class_pointer_symbol(
+                                       kext, super_metaclass_pointer);
+                               require_action(metaclass, finish, rval = KERN_FAILURE);
+
+                               /* Get the super class name from the super metaclass */
+                               rval = kxld_sym_get_class_name_from_metaclass(metaclass,
+                                   super_class_name, sizeof(super_class_name));
+                               require_noerr(rval, finish);
+
+                               /* Get the super vtable name from the class name */
+                               rval = kxld_sym_get_vtable_name_from_class_name(super_class_name,
+                                   super_vtable_name, sizeof(super_vtable_name));
+                               require_noerr(rval, finish);
+
+                               /* Get the super vtable if it's been patched */
+                               super_vtable = kxld_dict_find(patched_vtables, super_vtable_name);
+
+                               if (failure) {
+                                       const KXLDVTable *unpatched_super_vtable;
+                                       unpatched_super_vtable = kxld_dict_find(&kext->vtable_index,
+                                           super_vtable_name);
+
+                                       /* If the parent's vtable hasn't been patched, warn that
+                                        * this vtable is unpatchable because of the parent.
+                                        */
+                                       if (!super_vtable) {
+                                               kxld_log(kKxldLogPatching, kKxldLogErr,
+                                                   "The %s was not patched because its parent, "
+                                                   "the %s, was not %s.",
+                                                   kxld_demangle(vtable_name, &demangled_name1,
+                                                   &demangled_length1),
+                                                   kxld_demangle(super_vtable_name, &demangled_name2,
+                                                   &demangled_length2),
+                                                   (unpatched_super_vtable) ? "patchable" : "found");
+                                       }
+                                       continue;
+                               }
+
+                               if (!super_vtable) {
+                                       continue;
+                               }
+
+                               /* Get the final symbol's name from the super vtable */
+                               rval = kxld_sym_get_final_sym_name_from_class_name(super_class_name,
+                                   final_sym_name, sizeof(final_sym_name));
+                               require_noerr(rval, finish);
+
+                               /* Verify that the final symbol does not exist.  First check
+                                * all the externally defined symbols, then check locally.
+                                */
+                               final_sym = kxld_dict_find(defined_symbols, final_sym_name);
+                               if (!final_sym) {
+                                       final_sym = kxld_symtab_get_locally_defined_symbol_by_name(
+                                               symtab, final_sym_name);
+                               }
+                               if (final_sym) {
+                                       kxld_log(kKxldLogPatching, kKxldLogErr,
+                                           "Class '%s' is a subclass of final class '%s'.",
+                                           kxld_demangle(class_name, &demangled_name1,
+                                           &demangled_length1),
+                                           kxld_demangle(super_class_name, &demangled_name2,
+                                           &demangled_length2));
+                                       continue;
+                               }
+
+                               /* Patch the class's vtable */
+                               rval = kxld_vtable_patch(vtable, super_vtable, kext->kext);
+                               if (rval) {
+                                       continue;
+                               }
+
+                               /* Add the class's vtable to the set of patched vtables */
+                               rval = kxld_dict_insert(patched_vtables, vtable->name, vtable);
+                               require_noerr(rval, finish);
+
+                               /* Get the meta vtable name from the class name */
+                               rval = kxld_sym_get_meta_vtable_name_from_class_name(class_name,
+                                   vtable_name, sizeof(vtable_name));
+                               require_noerr(rval, finish);
+
+                               /* Get the meta vtable.  Whether or not it should exist has already
+                                * been tested in create_vtables(), so if it doesn't exist and we're
+                                * still running, we can safely skip it.
+                                */
+                               vtable = kxld_dict_find(&kext->vtable_index, vtable_name);
+                               if (!vtable) {
+                                       ++nprogress;
+                                       ++npatched;
+                                       continue;
+                               }
+                               require_action(!vtable->is_patched, finish, rval = KERN_FAILURE);
+
+                               /* There is no way to look up a metaclass vtable at runtime, but
+                                * we know that every class's metaclass inherits directly from
+                                * OSMetaClass, so we just hardcode that vtable name here.
+                                */
+                               len = strlcpy(super_vtable_name, kOSMetaClassVTableName,
+                                   sizeof(super_vtable_name));
+                               require_action(len == const_strlen(kOSMetaClassVTableName),
+                                   finish, rval = KERN_FAILURE);
+
+                               /* Get the super meta vtable */
+                               super_vtable = kxld_dict_find(patched_vtables, super_vtable_name);
+                               require_action(super_vtable && super_vtable->is_patched,
+                                   finish, rval = KERN_FAILURE);
+
+                               /* Patch the meta class's vtable */
+                               rval = kxld_vtable_patch(vtable, super_vtable, kext->kext);
+                               require_noerr(rval, finish);
+
+                               /* Add the MetaClass's vtable to the set of patched vtables */
+                               rval = kxld_dict_insert(patched_vtables, vtable->name, vtable);
+                               require_noerr(rval, finish);
+
+                               ++nprogress;
+                       }
+
+                       ++npatched;
+               }
+
+               require_action(!failure, finish, rval = KERN_FAILURE);
+               failure = (nprogress == 0);
+       }
+
+       rval = KERN_SUCCESS;
 finish:
-    if (demangled_name1) kxld_free(demangled_name1, demangled_length1);
-    if (demangled_name2) kxld_free(demangled_name2, demangled_length2);
-
-    return rval;
+       if (demangled_name1) {
+               kxld_free(demangled_name1, demangled_length1);
+       }
+       if (demangled_name2) {
+               kxld_free(demangled_name2, demangled_length2);
+       }
+
+       return rval;
 }
 
 /*******************************************************************************
@@ -990,30 +1015,30 @@ finish:
 static kern_return_t
 create_vtable_index(KXLDKext *kext)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDVTable *vtable = NULL;
-    u_int i = 0;
-
-    if (kext->vtable_index_created) {
-        rval = KERN_SUCCESS;
-        goto finish;
-    }
-
-    /* Map vtable names to the vtable structures */
-    rval = kxld_dict_init(&kext->vtable_index, kxld_dict_string_hash, 
-        kxld_dict_string_cmp, kext->vtables.nitems);
-    require_noerr(rval, finish);
-
-    for (i = 0; i < kext->vtables.nitems; ++i) {
-        vtable = kxld_array_get_item(&kext->vtables, i);
-        rval = kxld_dict_insert(&kext->vtable_index, vtable->name, vtable);
-        require_noerr(rval, finish);
-    }
-
-    kext->vtable_index_created = TRUE;
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDVTable *vtable = NULL;
+       u_int i = 0;
+
+       if (kext->vtable_index_created) {
+               rval = KERN_SUCCESS;
+               goto finish;
+       }
+
+       /* Map vtable names to the vtable structures */
+       rval = kxld_dict_init(&kext->vtable_index, kxld_dict_string_hash,
+           kxld_dict_string_cmp, kext->vtables.nitems);
+       require_noerr(rval, finish);
+
+       for (i = 0; i < kext->vtables.nitems; ++i) {
+               vtable = kxld_array_get_item(&kext->vtables, i);
+               rval = kxld_dict_insert(&kext->vtable_index, vtable->name, vtable);
+               require_noerr(rval, finish);
+       }
+
+       kext->vtable_index_created = TRUE;
+       rval = KERN_SUCCESS;
 finish:
-    return rval;
+       return rval;
 }
 
 /*******************************************************************************
@@ -1022,60 +1047,69 @@ static const KXLDSym *
 get_metaclass_symbol_from_super_meta_class_pointer_symbol(KXLDKext *kext,
     KXLDSym *super_metaclass_pointer_sym)
 {
-    kern_return_t rval = KERN_FAILURE;
-    const KXLDReloc *reloc = NULL;
-    const KXLDSect *sect = NULL;
-    const KXLDSym *metaclass = NULL;
-    
-    check(kext);
-    check(super_metaclass_pointer_sym);
-
-    /* Get the relocation entry that fills in the super metaclass pointer. */
-    reloc = kxld_object_get_reloc_at_symbol(kext->kext,
-        super_metaclass_pointer_sym);
-    require_action(reloc, finish, rval=KERN_FAILURE);
-
-    /* Get the section of the super metaclass pointer. */
-    sect = kxld_object_get_section_by_index(kext->kext,
-        super_metaclass_pointer_sym->sectnum);
-    require_action(sect, finish, rval=KERN_FAILURE);
-
-    /* Get the symbol that will be filled into the super metaclass pointer. */
-    metaclass = kxld_object_get_symbol_of_reloc(kext->kext, reloc, sect);
+       kern_return_t rval = KERN_FAILURE;
+       const KXLDReloc *reloc = NULL;
+       const KXLDSect *sect = NULL;
+       const KXLDSym *metaclass = NULL;
+
+       check(kext);
+       check(super_metaclass_pointer_sym);
+
+       /* Get the relocation entry that fills in the super metaclass pointer. */
+       reloc = kxld_object_get_reloc_at_symbol(kext->kext,
+           super_metaclass_pointer_sym);
+       require_action(reloc, finish, rval = KERN_FAILURE);
+
+       /* Get the section of the super metaclass pointer. */
+       sect = kxld_object_get_section_by_index(kext->kext,
+           super_metaclass_pointer_sym->sectnum);
+       require_action(sect, finish, rval = KERN_FAILURE);
+
+       /* Get the symbol that will be filled into the super metaclass pointer. */
+       metaclass = kxld_object_get_symbol_of_reloc(kext->kext, reloc, sect);
+
+
 finish:
-    return metaclass;
+       if (metaclass == NULL) {
+               kxld_log(kKxldLogLinking, kKxldLogErr,
+                   "metaclass == NULL kxld_sym %s <%s>",
+                   super_metaclass_pointer_sym->name, __func__);
+       }
+       return metaclass;
 }
 
+
 /*******************************************************************************
 *******************************************************************************/
 static kern_return_t
 validate_symbols(KXLDKext *kext)
 {
-    kern_return_t rval = KERN_FAILURE;
-    KXLDSymtabIterator iter;
-    KXLDSym *sym = NULL;
-    u_int error = FALSE;
-    char *demangled_name = NULL;
-    size_t demangled_length = 0;
-    
-    /* Check for any unresolved symbols */
-    kxld_symtab_iterator_init(&iter, kxld_object_get_symtab(kext->kext), 
-        kxld_sym_is_unresolved, FALSE);
-    while ((sym = kxld_symtab_iterator_get_next(&iter))) {
-        if (!error) {
-            error = TRUE;
-            kxld_log(kKxldLogLinking, kKxldLogErr, 
-                "The following symbols are unresolved for this kext:");
-        }
-        kxld_log(kKxldLogLinking, kKxldLogErr, "\t%s", 
-            kxld_demangle(sym->name, &demangled_name, &demangled_length));
-    }
-    require_noerr_action(error, finish, rval=KERN_FAILURE);
-
-    rval = KERN_SUCCESS;
+       kern_return_t rval = KERN_FAILURE;
+       KXLDSymtabIterator iter;
+       KXLDSym *sym = NULL;
+       u_int error = FALSE;
+       char *demangled_name = NULL;
+       size_t demangled_length = 0;
+
+       /* Check for any unresolved symbols */
+       kxld_symtab_iterator_init(&iter, kxld_object_get_symtab(kext->kext),
+           kxld_sym_is_unresolved, FALSE);
+       while ((sym = kxld_symtab_iterator_get_next(&iter))) {
+               if (!error) {
+                       error = TRUE;
+                       kxld_log(kKxldLogLinking, kKxldLogErr,
+                           "The following symbols are unresolved for this kext:");
+               }
+               kxld_log(kKxldLogLinking, kKxldLogErr, "\t%s",
+                   kxld_demangle(sym->name, &demangled_name, &demangled_length));
+       }
+       require_noerr_action(error, finish, rval = KERN_FAILURE);
+
+       rval = KERN_SUCCESS;
 
 finish:
-    if (demangled_name) kxld_free(demangled_name, demangled_length);
-    return rval;
+       if (demangled_name) {
+               kxld_free(demangled_name, demangled_length);
+       }
+       return rval;
 }
-