X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/060df5ea7c632b1ac8cc8aac1fb59758165c2084..6d2010ae8f7a6078e10b361c6962983bab233e0f:/libkern/kxld/kxld_state.c diff --git a/libkern/kxld/kxld_state.c b/libkern/kxld/kxld_state.c deleted file mode 100644 index d3a06da19..000000000 --- a/libkern/kxld/kxld_state.c +++ /dev/null @@ -1,1072 +0,0 @@ -/* - * Copyright (c) 2008 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 - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * 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, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * 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 - -#if !KERNEL - #include -#endif - -#define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld" -#include - -#include "kxld_array.h" -#include "kxld_dict.h" -#include "kxld_kext.h" -#include "kxld_state.h" -#include "kxld_sym.h" -#include "kxld_symtab.h" -#include "kxld_util.h" -#include "kxld_vtable.h" - -#define LINK_STATE_MAGIC 0xF00DD00D -#define CIGAM_ETATS_KNIL 0x0DD00DF0 - -#define LINK_STATE_MAGIC_64 0xCAFEF00D -#define CIGAM_ETATS_KNIL_64 0x0DF0FECA - -#define LINK_STATE_VERSION 1 - -static kern_return_t init_string_index(KXLDDict *strings, KXLDArray *tmps, - KXLDSymtabIterator *iter, const KXLDArray *vtables, u_int nsymentries, - u_long *strsize); -static kern_return_t add_string_to_index(KXLDDict *strings, const char *str, - KXLDArray *tmps, u_int *tmpi, u_long *stroff); -static kern_return_t create_link_state(u_char **_file, u_long *_filesize, - const KXLDKext *kext, KXLDSymtabIterator *iter, const KXLDArray *vtables, - KXLDDict *strings, u_int nsyms, u_int nsymentries, u_long strsize); -static boolean_t state_is_32_bit(KXLDLinkStateHdr *state); - -#if KXLD_USER_OR_ILP32 -static kern_return_t get_symbols_32(KXLDState *state, KXLDDict *defined_symbols, - KXLDDict *obsolete_symbols); -static kern_return_t copy_symbols_32(u_char *file, u_long *data_offset, - KXLDSymtabIterator *iter, const KXLDDict *strings); -static kern_return_t copy_vtables_32(u_char *file, u_long *header_offset, - u_long *data_offset, const KXLDArray *vtables, const KXLDDict *strings); -#endif /* KXLD_USER_OR_ILP32*/ -#if KXLD_USER_OR_LP64 -static kern_return_t get_symbols_64(KXLDState *state, KXLDDict *defined_symbols, - KXLDDict *obsolete_symbols); -static kern_return_t copy_symbols_64(u_char *file, u_long *data_offset, - KXLDSymtabIterator *iter, const KXLDDict *strings); -static kern_return_t copy_vtables_64(u_char *file, u_long *header_offset, - u_long *data_offset, const KXLDArray *vtables, const KXLDDict *strings); -#endif /* KXLD_USER_OR_ILP64 */ - -#if !KERNEL -static boolean_t swap_link_state(u_char *state); -static void swap_link_state_32(u_char *state); -static void swap_link_state_64(u_char *state); -static boolean_t unswap_link_state(u_char *state); -static void unswap_link_state_32(u_char *state); -static void unswap_link_state_64(u_char *state); -static void swap_state_hdr(KXLDLinkStateHdr *state_hdr); -static void swap_vtable_hdr(KXLDVTableHdr *vtable_hdr); -static void swap_sym_entry_32(KXLDSymEntry32 *entry); -static void swap_sym_entry_64(KXLDSymEntry64 *entry); -#endif - -/******************************************************************************* -*******************************************************************************/ -kern_return_t -kxld_state_init_from_file(KXLDState *state, u_char *file, - KXLDArray *section_order __unused) -{ - kern_return_t rval = KERN_FAILURE; - KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) file; -#if KXLD_USER_OR_OBJECT - KXLDSectionName *dstname = NULL; - KXLDSectionName *srcname = NULL; -#endif - KXLDVTableHdr *vhdr = NULL; - KXLDVTable *vtable = NULL; - u_int i = 0; - - check(state); - check(file); - -#if !KERNEL - /* Swap the link state file to host byte order for as long this kxld_state - * object owns the file. - */ - state->swap = swap_link_state(file); -#endif - require_action(hdr->magic == LINK_STATE_MAGIC || - hdr->magic == LINK_STATE_MAGIC_64, - finish, rval=KERN_FAILURE); - - state->file = file; - -#if KXLD_USER_OR_OBJECT - if (section_order && !section_order->nitems && hdr->nsects) { - rval = kxld_array_init(section_order, sizeof(*dstname), hdr->nsects); - require_noerr(rval, finish); - - srcname = (KXLDSectionName *) (file + hdr->sectoff); - for (i = 0; i < hdr->nsects; ++i, ++srcname) { - dstname = kxld_array_get_item(section_order, i); - memcpy(dstname, srcname, sizeof(*srcname)); - } - } -#endif - - rval = kxld_array_init(&state->vtables, sizeof(*vtable), hdr->nvtables); - require_noerr(rval, finish); - - vhdr = (KXLDVTableHdr *) (file + hdr->voff); - for (i = 0; i < hdr->nvtables; ++i, ++vhdr) { - vtable = kxld_array_get_item(&state->vtables, i); - KXLD_3264_FUNC(kxld_is_32_bit(hdr->cputype), rval, - kxld_vtable_init_from_link_state_32, - kxld_vtable_init_from_link_state_64, - vtable, file, vhdr); - require_noerr(rval, finish); - } - - rval = KERN_SUCCESS; - -finish: - return rval; -} - -/******************************************************************************* -*******************************************************************************/ -void -kxld_state_clear(KXLDState *state) -{ - KXLDVTable *vtable = NULL; - u_int i = 0; - - check(state); - -#if !KERNEL - /* We use kxld_state objects to wrap the link state files. Whenever the - * file is wrapped by a kxld_state object, the file is kept in host byte - * order. Once we are done, we must return it to target byte order. - */ - if (state->swap) (void)unswap_link_state(state->file); -#endif - - state->file = NULL; - state->swap = FALSE; - for (i = 0; i < state->vtables.nitems; ++i) { - vtable = kxld_array_get_item(&state->vtables, i); - kxld_vtable_clear(vtable); - } - kxld_array_reset(&state->vtables); -} - -/******************************************************************************* -*******************************************************************************/ -void -kxld_state_deinit(KXLDState *state) -{ - KXLDVTable *vtable = NULL; - u_int i = 0; - - check(state); - -#if !KERNEL - if (state->file && state->swap) (void)unswap_link_state(state->file); -#endif - - for (i = 0; i < state->vtables.maxitems; ++i) { - vtable = kxld_array_get_slot(&state->vtables, i); - kxld_vtable_deinit(vtable); - } - kxld_array_deinit(&state->vtables); - bzero(state, sizeof(*state)); -} - -/******************************************************************************* -*******************************************************************************/ -u_int -kxld_state_get_num_symbols(KXLDState *state) -{ - KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) state->file; - - return hdr->nsyms; -} - -/******************************************************************************* -*******************************************************************************/ -kern_return_t -kxld_state_get_symbols(KXLDState *state, KXLDDict *defined_symbols, - KXLDDict *obsolete_symbols) -{ - KXLDLinkStateHdr * hdr = (KXLDLinkStateHdr *) state->file; - kern_return_t rval = KERN_FAILURE; - - check(state); - check(defined_symbols); - check(obsolete_symbols); - - require_action(hdr->magic == LINK_STATE_MAGIC || - hdr->magic == LINK_STATE_MAGIC_64, - finish, rval=KERN_FAILURE); - - KXLD_3264_FUNC(state_is_32_bit(hdr), rval, - get_symbols_32, get_symbols_64, - state, defined_symbols, obsolete_symbols); - require_noerr(rval, finish); - - rval = KERN_SUCCESS; - -finish: - return rval; -} - -#if KXLD_USER_OR_ILP32 -/******************************************************************************* -*******************************************************************************/ -static kern_return_t -get_symbols_32(KXLDState *state, KXLDDict *defined_symbols, - KXLDDict *obsolete_symbols) -{ - kern_return_t rval = KERN_FAILURE; - KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) state->file; - KXLDSymEntry32 *entry = NULL; - const char *name = NULL; - u_int i = 0; - - entry = (KXLDSymEntry32 *) (state->file + hdr->symoff); - for (i = 0; i < hdr->nsyms; ++i, ++entry) { - name = (const char *) (state->file + entry->nameoff); - rval = kxld_dict_insert(defined_symbols, name, &entry->addr); - require_noerr(rval, finish); - - if (entry->flags & KXLD_SYM_OBSOLETE) { - rval = kxld_dict_insert(obsolete_symbols, name, &entry->addr); - require_noerr(rval, finish); - } - } - - rval = KERN_SUCCESS; - -finish: - return rval; -} -#endif /* KXLD_USER_OR_ILP32 */ - -#if KXLD_USER_OR_LP64 -/******************************************************************************* -*******************************************************************************/ -static kern_return_t -get_symbols_64(KXLDState *state, KXLDDict *defined_symbols, - KXLDDict *obsolete_symbols) -{ - kern_return_t rval = KERN_FAILURE; - KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) state->file; - KXLDSymEntry64 *entry = NULL; - const char *name = NULL; - u_int i = 0; - - entry = (KXLDSymEntry64 *) (state->file + hdr->symoff); - for (i = 0; i < hdr->nsyms; ++i, ++entry) { - name = (const char *) (state->file + entry->nameoff); - rval = kxld_dict_insert(defined_symbols, name, &entry->addr); - require_noerr(rval, finish); - - if (entry->flags & KXLD_SYM_OBSOLETE) { - rval = kxld_dict_insert(obsolete_symbols, name, &entry->addr); - require_noerr(rval, finish); - } - } - - rval = KERN_SUCCESS; - -finish: - return rval; -} -#endif /* KXLD_USER_OR_LP64 */ - -/******************************************************************************* -*******************************************************************************/ -u_int -kxld_state_get_num_vtables(KXLDState *state) -{ - return state->vtables.nitems; -} - -/******************************************************************************* -*******************************************************************************/ -kern_return_t -kxld_state_get_vtables(KXLDState *state, KXLDDict *patched_vtables) -{ - kern_return_t rval = KERN_FAILURE; - KXLDVTable *vtable = NULL; - u_int i = 0; - - check(state); - check(patched_vtables); - - for (i = 0; i < state->vtables.nitems; ++i) { - vtable = kxld_array_get_item(&state->vtables, i); - rval = kxld_dict_insert(patched_vtables, vtable->name, vtable); - require_noerr(rval, finish); - } - - rval = KERN_SUCCESS; - -finish: - return rval; -} - -/******************************************************************************* -*******************************************************************************/ -void -kxld_state_get_cputype(const KXLDState *state, cpu_type_t *cputype, - cpu_subtype_t *cpusubtype) -{ - KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) state->file; - - check(state); - check(cputype); - check(cpusubtype); - - *cputype = hdr->cputype; - *cpusubtype = hdr->cpusubtype; -} - -/******************************************************************************* -*******************************************************************************/ -kern_return_t -kxld_state_export_kext_to_file(KXLDKext *kext, u_char **file, u_long *filesize, - KXLDDict *strings, KXLDArray *tmps) -{ - kern_return_t rval = KERN_FAILURE; - KXLDSymtabIterator iter; - const KXLDSymtab *symtab = NULL; - const KXLDArray *vtables = NULL; - const KXLDVTable *vtable = NULL; - u_int nsyms = 0; - u_int nsymentries = 0; - u_int i = 0; - u_long strsize = 0; - - check(kext); - check(file); - check(tmps); - - bzero(&iter, sizeof(iter)); - - /* Get the vtables and symbol tables from the kext */ - - kxld_kext_get_vtables(kext, &vtables); - symtab = kxld_kext_get_symtab(kext); - require_action(symtab, finish, rval=KERN_FAILURE); - - /* Count the number of symentries we'll need in the linkstate */ - - kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_exported, FALSE); - - nsyms = kxld_symtab_iterator_get_num_remaining(&iter); - nsymentries = nsyms; - for (i = 0; i < vtables->nitems; ++i) { - vtable = kxld_array_get_item(vtables, i); - nsymentries += vtable->entries.nitems; - } - - /* Initialize the string index */ - - rval = init_string_index(strings, tmps, &iter, vtables, nsymentries, - &strsize); - require_noerr(rval, finish); - - /* Create the linkstate file */ - - rval = create_link_state(file, filesize, kext, &iter, vtables, - strings, nsyms, nsymentries, strsize); - require_noerr(rval, finish); - - /* Swap if necessary */ - -#if !KERNEL - if (kxld_kext_target_needs_swap(kext)) unswap_link_state(*file); -#endif /* !KERNEL */ - - rval = KERN_SUCCESS; - -finish: - return rval; -} - -/******************************************************************************* -*******************************************************************************/ -static kern_return_t -init_string_index(KXLDDict *strings, KXLDArray *tmps, KXLDSymtabIterator *iter, - const KXLDArray *vtables, u_int nsymentries, u_long *_strsize) -{ - kern_return_t rval = KERN_SUCCESS; - const KXLDSym *sym = NULL; - const KXLDVTable *vtable = NULL; - const KXLDVTableEntry *ventry = NULL; - u_long strsize = 0; - u_int tmpi = 0; - u_int i = 0; - u_int j = 0; - - check(strings); - check(tmps); - check(iter); - check(vtables); - check(_strsize); - - *_strsize = 0; - - /* Initialize the string dictionary and string offset array */ - - rval = kxld_dict_init(strings, kxld_dict_string_hash, kxld_dict_string_cmp, - nsymentries); - require_noerr(rval, finish); - - rval = kxld_array_init(tmps, sizeof(u_long), nsymentries); - require_noerr(rval, finish); - - /* Add all of the strings from the symbol table to the dictionary */ - - kxld_symtab_iterator_reset(iter); - while ((sym = kxld_symtab_iterator_get_next(iter))) { - rval = add_string_to_index(strings, sym->name, tmps, &tmpi, &strsize); - require_noerr(rval, finish); - } - - /* Add all of the strings from the vtables entries to the dictionary */ - - for (i = 0; i < vtables->nitems; ++i) { - vtable = kxld_array_get_item(vtables, i); - rval = add_string_to_index(strings, vtable->name, tmps, &tmpi, &strsize); - require_noerr(rval, finish); - - for (j = 0; j < vtable->entries.nitems; ++j) { - ventry = kxld_array_get_item(&vtable->entries, j); - if (ventry->patched.name) { - rval = add_string_to_index(strings, ventry->patched.name, tmps, - &tmpi, &strsize); - require_noerr(rval, finish); - } - } - } - - *_strsize = strsize; - rval = KERN_SUCCESS; - -finish: - return rval; -} - -/******************************************************************************* -*******************************************************************************/ -static kern_return_t -add_string_to_index(KXLDDict *strings, const char *str, KXLDArray *tmps, - u_int *tmpi, u_long *stroff) -{ - kern_return_t rval = KERN_FAILURE; - u_long *tmpp = NULL; - - if (!kxld_dict_find(strings, str)) { - tmpp = kxld_array_get_item(tmps, (*tmpi)++); - *tmpp = *stroff; - - rval = kxld_dict_insert(strings, str, tmpp); - require_noerr(rval, finish); - - *stroff += strlen(str) + 1; - } - - rval = KERN_SUCCESS; - -finish: - return rval; -} - -/******************************************************************************* -*******************************************************************************/ -static boolean_t -state_is_32_bit(KXLDLinkStateHdr *state) -{ - return kxld_is_32_bit(state->cputype); -} - -/******************************************************************************* -*******************************************************************************/ -static kern_return_t -create_link_state(u_char **_file, u_long *_filesize, const KXLDKext *kext, - KXLDSymtabIterator *iter, const KXLDArray *vtables, KXLDDict *strings, - u_int nsyms, u_int nsymentries, u_long strsize) -{ - kern_return_t rval = KERN_SUCCESS; - u_char *file = NULL; - KXLDLinkStateHdr *hdr = NULL; - KXLDDictIterator striter; -#if KXLD_USER_OR_OBJECT - KXLDSectionName *dstsectname = NULL; - KXLDSectionName *srcsectname = NULL; - const KXLDArray *section_order = NULL; - u_int i = 0; -#endif - const char *name = NULL; - char *dstname = NULL; - u_long *stridx = 0; - u_long hsize = 0; - u_long dsize = 0; - u_long filesize = 0; - u_long hoff = 0; - u_long doff = 0; - u_long stroff = 0; - - check(_file); - check(iter); - check(vtables); - check(strings); - - *_file = NULL; - *_filesize = 0; - -#if KXLD_USER_OR_OBJECT - section_order = kxld_kext_get_section_order(kext); -#endif - - /* Calculate header and data size */ - - hsize = sizeof(KXLDLinkStateHdr); - hsize += vtables->nitems * sizeof(KXLDVTableHdr); -#if KXLD_USER_OR_OBJECT - if (section_order) { - hsize += section_order->nitems * sizeof(KXLDSectionName); - } -#endif - - if (kxld_kext_is_32_bit(kext)) { - dsize = nsymentries * sizeof(KXLDSymEntry32); - } else { - dsize = nsymentries * sizeof(KXLDSymEntry64); - } - - filesize = hsize + dsize + strsize; - - hoff = 0; - doff = hsize; - stroff = hsize + dsize; - - /* Allocate the link state */ - - file = kxld_alloc_pageable(filesize); - require_action(file, finish, rval=KERN_RESOURCE_SHORTAGE); - - /* Initialize link state header */ - - hdr = (KXLDLinkStateHdr *) file; - hoff += sizeof(*hdr); - - if (state_is_32_bit(hdr)) { - hdr->magic = LINK_STATE_MAGIC; - } else { - hdr->magic = LINK_STATE_MAGIC_64; - } - hdr->version = LINK_STATE_VERSION; - kxld_kext_get_cputype(kext, &hdr->cputype, &hdr->cpusubtype); - hdr->nsects = 0; - hdr->nvtables = vtables->nitems; - hdr->nsyms = nsyms; - -#if KXLD_USER_OR_OBJECT - if (section_order) { - hdr->nsects = section_order->nitems; - hdr->sectoff = (uint32_t) hoff; - - dstsectname = (KXLDSectionName *) (file + hoff); - hoff += section_order->nitems * sizeof(*dstsectname); - - for (i = 0; i < section_order->nitems; ++i, ++dstsectname) { - srcsectname = kxld_array_get_item(section_order, i); - memcpy(dstsectname, srcsectname, sizeof(*srcsectname)); - } - } -#endif - - hdr->voff = (uint32_t) hoff; - hdr->symoff = (uint32_t) doff; - - /* Copy strings */ - - kxld_dict_iterator_init(&striter, strings); - kxld_dict_iterator_get_next(&striter, (const void **) &name, (void **) &stridx); - while (name) { - *stridx += stroff; - dstname = (char *) (file + *stridx); - strlcpy(dstname, name, filesize - *stridx); - kxld_dict_iterator_get_next(&striter, (const void **) &name, (void **) &stridx); - } - - /* Copy symbols */ - - KXLD_3264_FUNC(state_is_32_bit(hdr), rval, - copy_symbols_32, copy_symbols_64, - file, &doff, iter, strings); - require_noerr(rval, finish); - - /* Copy vtables */ - - KXLD_3264_FUNC(state_is_32_bit(hdr), rval, - copy_vtables_32, copy_vtables_64, - file, &hoff, &doff, vtables, strings); - require_noerr(rval, finish); - - *_file = file; - *_filesize = filesize; - file = NULL; - rval = KERN_SUCCESS; - -finish: - - if (file) { - kxld_page_free(file, filesize); - file = NULL; - } - - return rval; -} - -#if KXLD_USER_OR_ILP32 -/******************************************************************************* -*******************************************************************************/ -static kern_return_t -copy_symbols_32(u_char *file, u_long *data_offset, KXLDSymtabIterator *iter, - const KXLDDict *strings) -{ - kern_return_t rval = KERN_FAILURE; - KXLDSymEntry32 *symentry = NULL; - const KXLDSym *sym = NULL; - u_long *stridx = 0; - - kxld_symtab_iterator_reset(iter); - while ((sym = kxld_symtab_iterator_get_next(iter))) { - symentry = (KXLDSymEntry32 *) (file + *data_offset); - stridx = kxld_dict_find(strings, sym->name); - require_action(stridx, finish, rval=KERN_FAILURE); - - /* Initialize the symentry */ - - symentry->nameoff = (uint32_t) *stridx; - if (sym->predicates.is_thumb) { - symentry->addr = (uint32_t) sym->link_addr | 1; - } else { - symentry->addr = (uint32_t) sym->link_addr; - } - symentry->flags = 0; - - /* Set any flags */ - - symentry->flags |= (kxld_sym_is_obsolete(sym)) ? KXLD_SYM_OBSOLETE : 0; - - *data_offset += sizeof(*symentry); - } - - rval = KERN_SUCCESS; - -finish: - return rval; -} -#endif /* KXLD_USER_OR_ILP32 */ - -#if KXLD_USER_OR_LP64 -/******************************************************************************* -*******************************************************************************/ -static kern_return_t -copy_symbols_64(u_char *file, u_long *data_offset, KXLDSymtabIterator *iter, - const KXLDDict *strings) -{ - kern_return_t rval = KERN_FAILURE; - KXLDSymEntry64 *symentry = NULL; - const KXLDSym *sym = NULL; - u_long *stridx = 0; - - kxld_symtab_iterator_reset(iter); - while ((sym = kxld_symtab_iterator_get_next(iter))) { - symentry = (KXLDSymEntry64 *) (file + *data_offset); - stridx = kxld_dict_find(strings, sym->name); - require_action(stridx, finish, rval=KERN_FAILURE); - - /* Initialize the symentry */ - - symentry->nameoff = (uint32_t) *stridx; - symentry->addr = (uint64_t) sym->link_addr; - symentry->flags = 0; - - /* Set any flags */ - - symentry->flags |= (kxld_sym_is_obsolete(sym)) ? KXLD_SYM_OBSOLETE : 0; - - *data_offset += sizeof(*symentry); - } - - rval = KERN_SUCCESS; - -finish: - return rval; -} -#endif /* KXLD_USER_OR_LP64 */ - -#if KXLD_USER_OR_ILP32 -/******************************************************************************* -*******************************************************************************/ -static kern_return_t -copy_vtables_32(u_char *file, u_long *header_offset, u_long *data_offset, - const KXLDArray *vtables, const KXLDDict *strings) -{ - kern_return_t rval = KERN_FAILURE; - KXLDVTable *vtable = NULL; - KXLDVTableHdr *vhdr = NULL; - KXLDVTableEntry *ventry = NULL; - KXLDSymEntry32 *symentry = NULL; - u_long *stridx = 0; - u_int i = 0; - u_int j = 0; - - for (i = 0; i < vtables->nitems; ++i) { - vtable = kxld_array_get_item(vtables, i); - stridx = kxld_dict_find(strings, vtable->name); - require_action(stridx, finish, rval=KERN_FAILURE); - - vhdr = (KXLDVTableHdr *) (file + *header_offset); - vhdr->nameoff = (uint32_t) *stridx; - vhdr->nentries = vtable->entries.nitems; - vhdr->vtableoff = (uint32_t) (*data_offset); - - *header_offset += sizeof(*vhdr); - - for(j = 0; j < vtable->entries.nitems; ++j) { - - ventry = kxld_array_get_item(&vtable->entries, j); - symentry = (KXLDSymEntry32 *) (file + *data_offset); - - if (ventry->patched.name) { - stridx = kxld_dict_find(strings, ventry->patched.name); - require_action(stridx, finish, rval=KERN_FAILURE); - - symentry->nameoff = (uint32_t) *stridx; - symentry->addr = (uint32_t) ventry->patched.addr; - } else { - symentry->nameoff = 0; - symentry->addr = 0; - } - - *data_offset += sizeof(*symentry); - } - } - - rval = KERN_SUCCESS; - -finish: - return rval; -} -#endif /* KXLD_USER_OR_ILP32 */ - -#if KXLD_USER_OR_LP64 -/******************************************************************************* -*******************************************************************************/ -static kern_return_t -copy_vtables_64(u_char *file, u_long *header_offset, u_long *data_offset, - const KXLDArray *vtables, const KXLDDict *strings) -{ - kern_return_t rval = KERN_FAILURE; - KXLDVTable *vtable = NULL; - KXLDVTableHdr *vhdr = NULL; - KXLDVTableEntry *ventry = NULL; - KXLDSymEntry64 *symentry = NULL; - u_long *stridx = 0; - u_int i = 0; - u_int j = 0; - - for (i = 0; i < vtables->nitems; ++i) { - vtable = kxld_array_get_item(vtables, i); - stridx = kxld_dict_find(strings, vtable->name); - require_action(stridx, finish, rval=KERN_FAILURE); - - vhdr = (KXLDVTableHdr *) (file + *header_offset); - vhdr->nameoff = (uint32_t) *stridx; - vhdr->nentries = vtable->entries.nitems; - vhdr->vtableoff = (uint32_t) (*data_offset); - - *header_offset += sizeof(*vhdr); - - for(j = 0; j < vtable->entries.nitems; ++j) { - - ventry = kxld_array_get_item(&vtable->entries, j); - symentry = (KXLDSymEntry64 *) (file + *data_offset); - - if (ventry->patched.name) { - stridx = kxld_dict_find(strings, ventry->patched.name); - require_action(stridx, finish, rval=KERN_FAILURE); - - symentry->nameoff = (uint32_t) *stridx; - symentry->addr = (uint64_t) ventry->patched.addr; - } else { - symentry->nameoff = 0; - symentry->addr = 0; - } - - *data_offset += sizeof(*symentry); - } - } - - rval = KERN_SUCCESS; - -finish: - return rval; -} -#endif /* KXLD_USER_OR_LP64 */ - -#if !KERNEL -/******************************************************************************* -*******************************************************************************/ -static boolean_t -swap_link_state(u_char *state) -{ - KXLDLinkStateHdr *state_hdr = (KXLDLinkStateHdr *) state; - - if (state_hdr->magic == CIGAM_ETATS_KNIL) { - swap_link_state_32(state); - return TRUE; - } else if (state_hdr->magic == CIGAM_ETATS_KNIL_64) { - swap_link_state_64(state); - return TRUE; - } - - return FALSE; -} - -/******************************************************************************* -*******************************************************************************/ -static void -swap_link_state_32(u_char *state) -{ - KXLDLinkStateHdr *state_hdr = NULL; - KXLDVTableHdr *vtable_hdr = NULL; - KXLDSymEntry32 *entry = NULL; - u_int i = 0; - u_int j = 0; - - state_hdr = (KXLDLinkStateHdr *) state; - - if (state_hdr->magic != CIGAM_ETATS_KNIL) return; - - /* Swap the header */ - swap_state_hdr(state_hdr); - - /* Swap the symbols */ - entry = (KXLDSymEntry32 *) (state + state_hdr->symoff); - for (i = 0; i < state_hdr->nsyms; ++i, ++entry) { - swap_sym_entry_32(entry); - } - - /* Swap the vtable headers and entries */ - vtable_hdr = (KXLDVTableHdr *) (state + state_hdr->voff); - for (i = 0; i < state_hdr->nvtables; ++i, ++vtable_hdr) { - swap_vtable_hdr(vtable_hdr); - - entry = (KXLDSymEntry32 *) (state + vtable_hdr->vtableoff); - for (j = 0; j < vtable_hdr->nentries; ++j, ++entry) { - swap_sym_entry_32(entry); - } - } -} - -/******************************************************************************* -*******************************************************************************/ -static void -swap_link_state_64(u_char *state) -{ - KXLDLinkStateHdr *state_hdr = NULL; - KXLDVTableHdr *vtable_hdr = NULL; - KXLDSymEntry64 *entry = NULL; - u_int i = 0; - u_int j = 0; - - state_hdr = (KXLDLinkStateHdr *) state; - - if (state_hdr->magic != CIGAM_ETATS_KNIL_64) return; - - /* Swap the header */ - swap_state_hdr(state_hdr); - - /* Swap the symbols */ - entry = (KXLDSymEntry64 *) (state + state_hdr->symoff); - for (i = 0; i < state_hdr->nsyms; ++i, ++entry) { - swap_sym_entry_64(entry); - } - - /* Swap the vtable headers and entries */ - vtable_hdr = (KXLDVTableHdr *) (state + state_hdr->voff); - for (i = 0; i < state_hdr->nvtables; ++i, ++vtable_hdr) { - swap_vtable_hdr(vtable_hdr); - - entry = (KXLDSymEntry64 *) (state + vtable_hdr->vtableoff); - for (j = 0; j < vtable_hdr->nentries; ++j, ++entry) { - swap_sym_entry_64(entry); - } - } -} - -/******************************************************************************* -*******************************************************************************/ -static boolean_t -unswap_link_state(u_char *state) -{ - KXLDLinkStateHdr *state_hdr = (KXLDLinkStateHdr *) state; - - if (state_hdr->magic == LINK_STATE_MAGIC) { - unswap_link_state_32(state); - return TRUE; - } else if (state_hdr->magic == LINK_STATE_MAGIC_64) { - unswap_link_state_64(state); - return TRUE; - } - - return FALSE; -} - -/******************************************************************************* -*******************************************************************************/ -static void -unswap_link_state_32(u_char *state) -{ - KXLDLinkStateHdr *state_hdr = NULL; - KXLDVTableHdr *vtable_hdr = NULL; - KXLDSymEntry32 *entry = NULL; - u_int i = 0; - u_int j = 0; - - state_hdr = (KXLDLinkStateHdr *) state; - - if (state_hdr->magic != LINK_STATE_MAGIC) return; - - /* Unswap the vtables and their headers */ - vtable_hdr = (KXLDVTableHdr *) (state + state_hdr->voff); - for (i = 0; i < state_hdr->nvtables; ++i, ++vtable_hdr) { - entry = (KXLDSymEntry32 *) (state + vtable_hdr->vtableoff); - for (j = 0; j < vtable_hdr->nentries; ++j, ++entry) { - swap_sym_entry_32(entry); - } - - swap_vtable_hdr(vtable_hdr); - } - - /* Unswap the symbols themselves */ - entry = (KXLDSymEntry32 *) (state + state_hdr->symoff); - for (i = 0; i < state_hdr->nsyms; ++i, ++entry) { - swap_sym_entry_32(entry); - } - - /* Unswap the header */ - swap_state_hdr(state_hdr); -} - -/******************************************************************************* -*******************************************************************************/ -static void -unswap_link_state_64(u_char *state) -{ - KXLDLinkStateHdr *state_hdr = NULL; - KXLDVTableHdr *vtable_hdr = NULL; - KXLDSymEntry64 *entry = NULL; - u_int i = 0; - u_int j = 0; - - state_hdr = (KXLDLinkStateHdr *) state; - - if (state_hdr->magic != LINK_STATE_MAGIC_64) return; - - /* Unswap the vtables and their headers */ - vtable_hdr = (KXLDVTableHdr *) (state + state_hdr->voff); - for (i = 0; i < state_hdr->nvtables; ++i, ++vtable_hdr) { - entry = (KXLDSymEntry64 *) (state + vtable_hdr->vtableoff); - for (j = 0; j < vtable_hdr->nentries; ++j, ++entry) { - swap_sym_entry_64(entry); - } - - swap_vtable_hdr(vtable_hdr); - } - - /* Unswap the symbols themselves */ - entry = (KXLDSymEntry64 *) (state + state_hdr->symoff); - for (i = 0; i < state_hdr->nsyms; ++i, ++entry) { - swap_sym_entry_64(entry); - } - - /* Unswap the header */ - swap_state_hdr(state_hdr); -} - -/******************************************************************************* -*******************************************************************************/ -static void -swap_state_hdr(KXLDLinkStateHdr *state_hdr) -{ - state_hdr->magic = OSSwapInt32(state_hdr->magic); - state_hdr->version = OSSwapInt32(state_hdr->version); - state_hdr->cputype = OSSwapInt32(state_hdr->cputype); - state_hdr->cpusubtype = OSSwapInt32(state_hdr->cpusubtype); - state_hdr->nsects = OSSwapInt32(state_hdr->nsects); - state_hdr->sectoff = OSSwapInt32(state_hdr->sectoff); - state_hdr->nvtables = OSSwapInt32(state_hdr->nvtables); - state_hdr->voff = OSSwapInt32(state_hdr->voff); - state_hdr->nsyms = OSSwapInt32(state_hdr->nsyms); - state_hdr->symoff = OSSwapInt32(state_hdr->symoff); -} - -/******************************************************************************* -*******************************************************************************/ -static void -swap_vtable_hdr(KXLDVTableHdr *vtable_hdr) -{ - vtable_hdr->nameoff = OSSwapInt32(vtable_hdr->nameoff); - vtable_hdr->vtableoff = OSSwapInt32(vtable_hdr->vtableoff); - vtable_hdr->nentries = OSSwapInt32(vtable_hdr->nentries); -} - -/******************************************************************************* -*******************************************************************************/ -static void -swap_sym_entry_32(KXLDSymEntry32 *entry) -{ - entry->nameoff = OSSwapInt32(entry->nameoff); - entry->addr = OSSwapInt32(entry->addr); -} - -/******************************************************************************* -*******************************************************************************/ -static void -swap_sym_entry_64(KXLDSymEntry64 *entry) -{ - entry->nameoff = OSSwapInt32(entry->nameoff); - entry->addr = OSSwapInt64(entry->addr); -} -#endif /* !KERNEL */ -