コード例 #1
0
ファイル: kxld_kext.c プロジェクト: Prajna/xnu
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;
finish:
    return rval;
}
コード例 #2
0
ファイル: kxld_kext.c プロジェクト: Prajna/xnu
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;
finish:
    return rval;
}
コード例 #3
0
ファイル: kxld_kext.c プロジェクト: Prajna/xnu
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;
finish:
    return rval;
}
コード例 #4
0
ファイル: kxld.c プロジェクト: aglab2/darwin-xnu
kern_return_t
kxld_create_context(KXLDContext **_context, 
    KXLDAllocateCallback allocate_callback, KXLDLoggingCallback logging_callback,
    KXLDFlags flags, cpu_type_t cputype, cpu_subtype_t cpusubtype,
    vm_size_t pagesize __KXLD_KERNEL_UNUSED)
{
    kern_return_t rval = KERN_FAILURE;
    KXLDContext       * context         = NULL;
    KXLDArray         * section_order   = NULL;
#if !KERNEL
    cpu_type_t        * cputype_p       = NULL;
#endif

    check(_context);
    if (isOldInterface) {
        check(allocate_callback);
    }
    check(logging_callback);
    *_context = NULL;

    context = kxld_alloc(sizeof(*context));
    require_action(context, finish, rval=KERN_RESOURCE_SHORTAGE);
    bzero(context, sizeof(*context));

    context->flags = flags;
    context->allocate_callback = allocate_callback;
    context->cputype = cputype;
    context->cpusubtype = cpusubtype;

#if !KERNEL
    if (pagesize) {
        kxld_set_cross_link_page_size(pagesize);
    }
#endif /* !KERNEL */

    kxld_set_logging_callback(logging_callback);

    context->kext = kxld_alloc(kxld_kext_sizeof());
    require_action(context->kext, finish, rval=KERN_RESOURCE_SHORTAGE);
    bzero(context->kext, kxld_kext_sizeof());

    /* Check if we already have an order array for this arch */

#if KXLD_USER_OR_OBJECT
#if KERNEL   
    context->section_order = s_section_order;
#else
    /* In userspace, create the dictionary if it doesn't already exist */
    if (!s_order_dict) {
        s_order_dict = kxld_alloc(sizeof(*s_order_dict));
        require_action(s_order_dict, finish, rval=KERN_RESOURCE_SHORTAGE);
        bzero(s_order_dict, sizeof(*s_order_dict));

        rval = kxld_dict_init(s_order_dict, kxld_dict_uint32_hash,
            kxld_dict_uint32_cmp, 0);
        require_noerr(rval, finish);
    }

    context->section_order = kxld_dict_find(s_order_dict, &cputype);
#endif /* KERNEL */

    /* Create an order array for this arch if needed */
    
    if (!context->section_order) {

        section_order = kxld_alloc(sizeof(*section_order));
        require_action(section_order, finish, rval=KERN_RESOURCE_SHORTAGE);
        bzero(section_order, sizeof(*section_order));

#if KERNEL
        s_section_order = section_order;
#else
        /* In userspace, add the new array to the order dictionary */
        cputype_p = kxld_alloc(sizeof(*cputype_p));
        require_action(cputype_p, finish, rval=KERN_RESOURCE_SHORTAGE);
        *cputype_p = cputype;

        rval = kxld_dict_insert(s_order_dict, cputype_p, section_order);
        require_noerr(rval, finish);

        cputype_p = NULL;
#endif /* KERNEL */

        context->section_order = section_order;

        section_order = NULL;
    }
#endif /* KXLD_USER_OR_OBJECT */

    rval = KERN_SUCCESS;
    *_context = context;
    context = NULL;

finish:
    if (context) kxld_destroy_context(context);
    if (section_order) kxld_free(section_order, sizeof(*section_order));
#if !KERNEL
    if (cputype_p) kxld_free(cputype_p, sizeof(*cputype_p));
#endif

    return rval;
}
コード例 #5
0
ファイル: kxld_kext.c プロジェクト: Prajna/xnu
static kern_return_t
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;
finish:
    if (demangled_name1) kxld_free(demangled_name1, demangled_length1);
    if (demangled_name2) kxld_free(demangled_name2, demangled_length2);

    return rval;
}
コード例 #6
0
ファイル: kxld_kext.c プロジェクト: Prajna/xnu
kern_return_t
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;
finish:
    return rval;
}