The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/libkern/kxld/kxld_state.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2008 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 #include <string.h>
   29 
   30 #if !KERNEL
   31     #include <libkern/OSByteOrder.h>
   32 #endif
   33 
   34 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
   35 #include <AssertMacros.h>
   36 
   37 #include "kxld_array.h"
   38 #include "kxld_dict.h"
   39 #include "kxld_kext.h"
   40 #include "kxld_state.h"
   41 #include "kxld_sym.h"
   42 #include "kxld_symtab.h"
   43 #include "kxld_util.h"
   44 #include "kxld_vtable.h"
   45 
   46 #define LINK_STATE_MAGIC 0xF00DD00D
   47 #define CIGAM_ETATS_KNIL 0x0DD00DF0
   48 
   49 #define LINK_STATE_MAGIC_64 0xCAFEF00D
   50 #define CIGAM_ETATS_KNIL_64 0x0DF0FECA
   51 
   52 #define LINK_STATE_VERSION 1
   53 
   54 static kern_return_t init_string_index(KXLDDict *strings, KXLDArray *tmps, 
   55     KXLDSymtabIterator *iter, const KXLDArray *vtables, u_int nsymentries, 
   56     u_long *strsize);
   57 static kern_return_t add_string_to_index(KXLDDict *strings, const char *str, 
   58     KXLDArray *tmps, u_int *tmpi, u_long *stroff);
   59 static kern_return_t create_link_state(u_char **_file, u_long *_filesize, 
   60     const KXLDKext *kext,  KXLDSymtabIterator *iter, const KXLDArray *vtables, 
   61     KXLDDict *strings, u_int nsyms, u_int nsymentries, u_long strsize);
   62 static boolean_t state_is_32_bit(KXLDLinkStateHdr *state);
   63 
   64 #if KXLD_USER_OR_ILP32
   65 static kern_return_t get_symbols_32(KXLDState *state, KXLDDict *defined_symbols,
   66     KXLDDict *obsolete_symbols);
   67 static kern_return_t copy_symbols_32(u_char *file, u_long *data_offset, 
   68     KXLDSymtabIterator *iter, const KXLDDict *strings);
   69 static kern_return_t copy_vtables_32(u_char *file, u_long *header_offset, 
   70     u_long *data_offset, const KXLDArray *vtables, const KXLDDict *strings);
   71 #endif /* KXLD_USER_OR_ILP32*/
   72 #if KXLD_USER_OR_LP64
   73 static kern_return_t get_symbols_64(KXLDState *state, KXLDDict *defined_symbols,
   74     KXLDDict *obsolete_symbols);
   75 static kern_return_t copy_symbols_64(u_char *file, u_long *data_offset, 
   76     KXLDSymtabIterator *iter, const KXLDDict *strings);
   77 static kern_return_t copy_vtables_64(u_char *file, u_long *header_offset, 
   78     u_long *data_offset, const KXLDArray *vtables, const KXLDDict *strings);
   79 #endif /* KXLD_USER_OR_ILP64 */
   80 
   81 #if !KERNEL
   82 static boolean_t swap_link_state(u_char *state);
   83 static void swap_link_state_32(u_char *state);
   84 static void swap_link_state_64(u_char *state);
   85 static boolean_t unswap_link_state(u_char *state);
   86 static void unswap_link_state_32(u_char *state);
   87 static void unswap_link_state_64(u_char *state);
   88 static void swap_state_hdr(KXLDLinkStateHdr *state_hdr);
   89 static void swap_vtable_hdr(KXLDVTableHdr *vtable_hdr);
   90 static void swap_sym_entry_32(KXLDSymEntry32 *entry);
   91 static void swap_sym_entry_64(KXLDSymEntry64 *entry);
   92 #endif
   93 
   94 /*******************************************************************************
   95 *******************************************************************************/
   96 kern_return_t
   97 kxld_state_init_from_file(KXLDState *state, u_char *file, 
   98     KXLDArray *section_order __unused)
   99 {
  100     kern_return_t rval = KERN_FAILURE;
  101     KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) file;
  102 #if KXLD_USER_OR_OBJECT
  103     KXLDSectionName *dstname = NULL;
  104     KXLDSectionName *srcname = NULL;
  105 #endif
  106     KXLDVTableHdr *vhdr = NULL;
  107     KXLDVTable *vtable = NULL;
  108     u_int i = 0;
  109 
  110     check(state);
  111     check(file);
  112 
  113 #if !KERNEL
  114     /* Swap the link state file to host byte order for as long this kxld_state
  115      * object owns the file.
  116      */
  117     state->swap = swap_link_state(file);
  118 #endif
  119     require_action(hdr->magic == LINK_STATE_MAGIC || 
  120         hdr->magic == LINK_STATE_MAGIC_64,
  121         finish, rval=KERN_FAILURE);
  122 
  123     state->file = file;
  124 
  125 #if KXLD_USER_OR_OBJECT
  126     if (section_order && !section_order->nitems && hdr->nsects) {
  127         rval = kxld_array_init(section_order, sizeof(*dstname), hdr->nsects);
  128         require_noerr(rval, finish);
  129 
  130         srcname = (KXLDSectionName *) (file + hdr->sectoff);
  131         for (i = 0; i < hdr->nsects; ++i, ++srcname) {
  132             dstname = kxld_array_get_item(section_order, i);
  133             memcpy(dstname, srcname, sizeof(*srcname));
  134         }
  135     }
  136 #endif
  137 
  138     rval = kxld_array_init(&state->vtables, sizeof(*vtable), hdr->nvtables);
  139     require_noerr(rval, finish);
  140     
  141     vhdr = (KXLDVTableHdr *) (file + hdr->voff);
  142     for (i = 0; i < hdr->nvtables; ++i, ++vhdr) {
  143         vtable = kxld_array_get_item(&state->vtables, i);
  144         KXLD_3264_FUNC(kxld_is_32_bit(hdr->cputype), rval,
  145             kxld_vtable_init_from_link_state_32,
  146             kxld_vtable_init_from_link_state_64,
  147             vtable, file, vhdr);
  148         require_noerr(rval, finish);
  149     }
  150 
  151     rval = KERN_SUCCESS;
  152 
  153 finish:
  154     return rval;
  155 }
  156 
  157 /*******************************************************************************
  158 *******************************************************************************/
  159 void 
  160 kxld_state_clear(KXLDState *state)
  161 {
  162     KXLDVTable *vtable = NULL;
  163     u_int i = 0;
  164 
  165     check(state);
  166 
  167 #if !KERNEL
  168     /* We use kxld_state objects to wrap the link state files.  Whenever the
  169      * file is wrapped by a kxld_state object, the file is kept in host byte
  170      * order.  Once we are done, we must return it to target byte order.
  171      */
  172     if (state->swap) (void)unswap_link_state(state->file);
  173 #endif
  174 
  175     state->file = NULL;
  176     state->swap = FALSE;
  177     for (i = 0; i < state->vtables.nitems; ++i) {
  178         vtable = kxld_array_get_item(&state->vtables, i);
  179         kxld_vtable_clear(vtable);
  180     }
  181     kxld_array_reset(&state->vtables);
  182 }
  183 
  184 /*******************************************************************************
  185 *******************************************************************************/
  186 void 
  187 kxld_state_deinit(KXLDState *state)
  188 {
  189     KXLDVTable *vtable = NULL;
  190     u_int i = 0;
  191 
  192     check(state);
  193 
  194 #if !KERNEL
  195     if (state->file && state->swap) (void)unswap_link_state(state->file);
  196 #endif
  197    
  198     for (i = 0; i < state->vtables.maxitems; ++i) {
  199         vtable = kxld_array_get_slot(&state->vtables, i);
  200         kxld_vtable_deinit(vtable);
  201     }
  202     kxld_array_deinit(&state->vtables);
  203     bzero(state, sizeof(*state));
  204 }
  205 
  206 /*******************************************************************************
  207 *******************************************************************************/
  208 u_int 
  209 kxld_state_get_num_symbols(KXLDState *state)
  210 {
  211     KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) state->file;
  212 
  213     return hdr->nsyms;
  214 }
  215 
  216 /*******************************************************************************
  217 *******************************************************************************/
  218 kern_return_t 
  219 kxld_state_get_symbols(KXLDState *state, KXLDDict *defined_symbols,
  220     KXLDDict *obsolete_symbols)
  221 {
  222     KXLDLinkStateHdr * hdr = (KXLDLinkStateHdr *) state->file;
  223     kern_return_t rval = KERN_FAILURE;
  224 
  225     check(state);
  226     check(defined_symbols);
  227     check(obsolete_symbols);
  228 
  229     require_action(hdr->magic == LINK_STATE_MAGIC || 
  230         hdr->magic == LINK_STATE_MAGIC_64,
  231         finish, rval=KERN_FAILURE);
  232 
  233     KXLD_3264_FUNC(state_is_32_bit(hdr), rval,
  234         get_symbols_32, get_symbols_64,
  235         state, defined_symbols, obsolete_symbols);
  236     require_noerr(rval, finish);
  237 
  238     rval = KERN_SUCCESS;
  239 
  240 finish:
  241     return rval;
  242 }
  243 
  244 #if KXLD_USER_OR_ILP32
  245 /*******************************************************************************
  246 *******************************************************************************/
  247 static kern_return_t
  248 get_symbols_32(KXLDState *state, KXLDDict *defined_symbols,
  249     KXLDDict *obsolete_symbols)
  250 {
  251     kern_return_t rval = KERN_FAILURE;
  252     KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) state->file;
  253     KXLDSymEntry32 *entry = NULL;
  254     const char *name = NULL;
  255     u_int i = 0;
  256 
  257     entry = (KXLDSymEntry32 *) (state->file + hdr->symoff);
  258     for (i = 0; i < hdr->nsyms; ++i, ++entry) {
  259         name = (const char *) (state->file + entry->nameoff);
  260         rval = kxld_dict_insert(defined_symbols, name, &entry->addr);
  261         require_noerr(rval, finish);
  262 
  263         if (entry->flags & KXLD_SYM_OBSOLETE) {
  264             rval = kxld_dict_insert(obsolete_symbols, name, &entry->addr);
  265             require_noerr(rval, finish);
  266         }
  267     }
  268 
  269     rval = KERN_SUCCESS;
  270 
  271 finish:
  272     return rval;
  273 }
  274 #endif /* KXLD_USER_OR_ILP32 */
  275 
  276 #if KXLD_USER_OR_LP64
  277 /*******************************************************************************
  278 *******************************************************************************/
  279 static kern_return_t
  280 get_symbols_64(KXLDState *state, KXLDDict *defined_symbols,
  281     KXLDDict *obsolete_symbols)
  282 {
  283     kern_return_t rval = KERN_FAILURE;
  284     KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) state->file;
  285     KXLDSymEntry64 *entry = NULL;
  286     const char *name = NULL;
  287     u_int i = 0;
  288 
  289     entry = (KXLDSymEntry64 *) (state->file + hdr->symoff);
  290     for (i = 0; i < hdr->nsyms; ++i, ++entry) {
  291         name = (const char *) (state->file + entry->nameoff);
  292         rval = kxld_dict_insert(defined_symbols, name, &entry->addr);
  293         require_noerr(rval, finish);
  294 
  295         if (entry->flags & KXLD_SYM_OBSOLETE) {
  296             rval = kxld_dict_insert(obsolete_symbols, name, &entry->addr);
  297             require_noerr(rval, finish);
  298         }
  299     }
  300 
  301     rval = KERN_SUCCESS;
  302 
  303 finish:
  304     return rval;
  305 }
  306 #endif /* KXLD_USER_OR_LP64 */
  307 
  308 /*******************************************************************************
  309 *******************************************************************************/
  310 u_int 
  311 kxld_state_get_num_vtables(KXLDState *state)
  312 {
  313     return state->vtables.nitems;
  314 }
  315 
  316 /*******************************************************************************
  317 *******************************************************************************/
  318 kern_return_t 
  319 kxld_state_get_vtables(KXLDState *state, KXLDDict *patched_vtables)
  320 {
  321     kern_return_t rval = KERN_FAILURE;
  322     KXLDVTable *vtable = NULL;
  323     u_int i = 0;
  324 
  325     check(state);
  326     check(patched_vtables);
  327 
  328     for (i = 0; i < state->vtables.nitems; ++i) {
  329         vtable = kxld_array_get_item(&state->vtables, i);
  330         rval = kxld_dict_insert(patched_vtables, vtable->name, vtable);
  331         require_noerr(rval, finish);
  332     }
  333 
  334     rval = KERN_SUCCESS;
  335 
  336 finish:
  337     return rval;
  338 }
  339 
  340 /*******************************************************************************
  341 *******************************************************************************/
  342 void
  343 kxld_state_get_cputype(const KXLDState *state, cpu_type_t *cputype, 
  344     cpu_subtype_t *cpusubtype)
  345 {
  346     KXLDLinkStateHdr *hdr = (KXLDLinkStateHdr *) state->file;
  347     
  348     check(state);
  349     check(cputype);
  350     check(cpusubtype);
  351 
  352     *cputype = hdr->cputype;
  353     *cpusubtype = hdr->cpusubtype;
  354 }
  355 
  356 /*******************************************************************************
  357 *******************************************************************************/
  358 kern_return_t 
  359 kxld_state_export_kext_to_file(KXLDKext *kext, u_char **file, u_long *filesize, 
  360     KXLDDict *strings, KXLDArray *tmps)
  361 {
  362     kern_return_t rval = KERN_FAILURE;
  363     KXLDSymtabIterator iter;
  364     const KXLDSymtab *symtab = NULL;
  365     const KXLDArray *vtables = NULL;
  366     const KXLDVTable *vtable = NULL;
  367     u_int nsyms = 0;
  368     u_int nsymentries = 0;
  369     u_int i = 0;
  370     u_long strsize = 0;
  371 
  372     check(kext);
  373     check(file);
  374     check(tmps);
  375 
  376     bzero(&iter, sizeof(iter));
  377 
  378     /* Get the vtables and symbol tables from the kext */
  379 
  380     kxld_kext_get_vtables(kext, &vtables);
  381     symtab = kxld_kext_get_symtab(kext);
  382     require_action(symtab, finish, rval=KERN_FAILURE);
  383 
  384     /* Count the number of symentries we'll need in the linkstate */
  385 
  386     kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_exported, FALSE);
  387 
  388     nsyms = kxld_symtab_iterator_get_num_remaining(&iter);
  389     nsymentries = nsyms;
  390     for (i = 0; i < vtables->nitems; ++i) {
  391         vtable = kxld_array_get_item(vtables, i);
  392         nsymentries += vtable->entries.nitems;
  393     }
  394 
  395     /* Initialize the string index */
  396 
  397     rval = init_string_index(strings, tmps, &iter, vtables, nsymentries, 
  398         &strsize);
  399     require_noerr(rval, finish);
  400 
  401     /* Create the linkstate file */
  402 
  403     rval = create_link_state(file, filesize, kext, &iter, vtables, 
  404         strings, nsyms, nsymentries, strsize);
  405     require_noerr(rval, finish);
  406 
  407     /* Swap if necessary */
  408 
  409 #if !KERNEL
  410     if (kxld_kext_target_needs_swap(kext)) unswap_link_state(*file);
  411 #endif /* !KERNEL */
  412     
  413     rval = KERN_SUCCESS;
  414 
  415 finish:
  416     return rval;
  417 }
  418 
  419 /*******************************************************************************
  420 *******************************************************************************/
  421 static kern_return_t
  422 init_string_index(KXLDDict *strings, KXLDArray *tmps, KXLDSymtabIterator *iter,
  423     const KXLDArray *vtables, u_int nsymentries, u_long *_strsize)
  424 {
  425     kern_return_t rval = KERN_SUCCESS;
  426     const KXLDSym *sym = NULL;
  427     const KXLDVTable *vtable = NULL;
  428     const KXLDVTableEntry *ventry = NULL;
  429     u_long strsize = 0;
  430     u_int tmpi = 0;
  431     u_int i = 0;
  432     u_int j = 0;
  433 
  434     check(strings);
  435     check(tmps);
  436     check(iter);
  437     check(vtables);
  438     check(_strsize);
  439 
  440     *_strsize = 0;
  441 
  442     /* Initialize the string dictionary and string offset array */
  443     
  444     rval = kxld_dict_init(strings, kxld_dict_string_hash, kxld_dict_string_cmp,
  445         nsymentries);
  446     require_noerr(rval, finish);
  447 
  448     rval = kxld_array_init(tmps, sizeof(u_long), nsymentries);
  449     require_noerr(rval, finish);
  450 
  451     /* Add all of the strings from the symbol table to the dictionary */
  452 
  453     kxld_symtab_iterator_reset(iter);
  454     while ((sym = kxld_symtab_iterator_get_next(iter))) {
  455         rval = add_string_to_index(strings, sym->name, tmps, &tmpi, &strsize);
  456         require_noerr(rval, finish);
  457     }
  458 
  459     /* Add all of the strings from the vtables entries to the dictionary */
  460 
  461     for (i = 0; i < vtables->nitems; ++i) {
  462         vtable = kxld_array_get_item(vtables, i);
  463         rval = add_string_to_index(strings, vtable->name, tmps, &tmpi, &strsize);
  464         require_noerr(rval, finish);
  465 
  466         for (j = 0; j < vtable->entries.nitems; ++j) {
  467             ventry = kxld_array_get_item(&vtable->entries, j);
  468             if (ventry->patched.name) {
  469                 rval = add_string_to_index(strings, ventry->patched.name, tmps, 
  470                     &tmpi, &strsize);
  471                 require_noerr(rval, finish);
  472             }
  473         }
  474     }
  475 
  476     *_strsize = strsize;
  477     rval = KERN_SUCCESS;
  478 
  479 finish:
  480     return rval;
  481 }
  482 
  483 /*******************************************************************************
  484 *******************************************************************************/
  485 static kern_return_t
  486 add_string_to_index(KXLDDict *strings, const char *str, KXLDArray *tmps,
  487     u_int *tmpi, u_long *stroff)
  488 {
  489     kern_return_t rval = KERN_FAILURE;
  490     u_long *tmpp = NULL;
  491 
  492     if (!kxld_dict_find(strings, str)) {
  493         tmpp = kxld_array_get_item(tmps, (*tmpi)++);
  494         *tmpp = *stroff;
  495         
  496         rval = kxld_dict_insert(strings, str, tmpp);
  497         require_noerr(rval, finish);
  498     
  499         *stroff += strlen(str) + 1;
  500     }
  501 
  502     rval = KERN_SUCCESS;
  503 
  504 finish:
  505     return rval;
  506 }
  507 
  508 /*******************************************************************************
  509 *******************************************************************************/
  510 static boolean_t
  511 state_is_32_bit(KXLDLinkStateHdr *state)
  512 {
  513     return kxld_is_32_bit(state->cputype);
  514 }
  515 
  516 /*******************************************************************************
  517 *******************************************************************************/
  518 static kern_return_t
  519 create_link_state(u_char **_file, u_long *_filesize, const KXLDKext *kext,
  520     KXLDSymtabIterator *iter, const KXLDArray *vtables, KXLDDict *strings, 
  521     u_int nsyms, u_int nsymentries, u_long strsize)
  522 {
  523     kern_return_t rval = KERN_SUCCESS;
  524     u_char *file = NULL;
  525     KXLDLinkStateHdr *hdr = NULL;
  526     KXLDDictIterator striter;
  527 #if KXLD_USER_OR_OBJECT
  528     KXLDSectionName *dstsectname = NULL;
  529     KXLDSectionName *srcsectname = NULL;
  530     const KXLDArray *section_order = NULL;
  531     u_int i = 0;
  532 #endif
  533     const char *name = NULL;
  534     char *dstname = NULL;
  535     u_long *stridx = 0;
  536     u_long hsize = 0;
  537     u_long dsize = 0;
  538     u_long filesize = 0;
  539     u_long hoff = 0;
  540     u_long doff = 0;
  541     u_long stroff = 0;
  542 
  543     check(_file);
  544     check(iter);
  545     check(vtables);
  546     check(strings);
  547 
  548     *_file = NULL;
  549     *_filesize = 0;
  550 
  551 #if KXLD_USER_OR_OBJECT
  552     section_order = kxld_kext_get_section_order(kext);
  553 #endif
  554 
  555     /* Calculate header and data size */
  556 
  557     hsize = sizeof(KXLDLinkStateHdr);
  558     hsize += vtables->nitems * sizeof(KXLDVTableHdr);
  559 #if KXLD_USER_OR_OBJECT
  560     if (section_order) {
  561         hsize += section_order->nitems * sizeof(KXLDSectionName);
  562     }
  563 #endif
  564 
  565     if (kxld_kext_is_32_bit(kext)) {
  566         dsize = nsymentries * sizeof(KXLDSymEntry32);
  567     } else {
  568         dsize = nsymentries * sizeof(KXLDSymEntry64);
  569     }
  570 
  571     filesize = hsize + dsize + strsize;
  572 
  573     hoff = 0;
  574     doff = hsize;
  575     stroff = hsize + dsize;
  576 
  577     /* Allocate the link state */
  578 
  579     file = kxld_alloc_pageable(filesize);
  580     require_action(file, finish, rval=KERN_RESOURCE_SHORTAGE);
  581 
  582     /* Initialize link state header */
  583 
  584     hdr = (KXLDLinkStateHdr *) file;
  585     hoff += sizeof(*hdr); 
  586 
  587     if (state_is_32_bit(hdr)) {
  588         hdr->magic = LINK_STATE_MAGIC;
  589     } else {
  590         hdr->magic = LINK_STATE_MAGIC_64;
  591     }
  592     hdr->version = LINK_STATE_VERSION;
  593     kxld_kext_get_cputype(kext, &hdr->cputype, &hdr->cpusubtype);
  594     hdr->nsects = 0;
  595     hdr->nvtables = vtables->nitems;
  596     hdr->nsyms = nsyms;
  597 
  598 #if KXLD_USER_OR_OBJECT
  599     if (section_order) {
  600         hdr->nsects = section_order->nitems;
  601         hdr->sectoff = (uint32_t) hoff;
  602 
  603         dstsectname = (KXLDSectionName *) (file + hoff);
  604         hoff += section_order->nitems * sizeof(*dstsectname);
  605 
  606         for (i = 0; i < section_order->nitems; ++i, ++dstsectname) {
  607             srcsectname = kxld_array_get_item(section_order, i);
  608             memcpy(dstsectname, srcsectname, sizeof(*srcsectname));
  609         }
  610     }
  611 #endif
  612 
  613     hdr->voff = (uint32_t) hoff;
  614     hdr->symoff = (uint32_t) doff;
  615 
  616     /* Copy strings */
  617     
  618     kxld_dict_iterator_init(&striter, strings);
  619     kxld_dict_iterator_get_next(&striter, (const void **) &name, (void **) &stridx);
  620     while (name) {
  621         *stridx += stroff;
  622         dstname = (char *) (file + *stridx);
  623         strlcpy(dstname, name, filesize - *stridx);
  624         kxld_dict_iterator_get_next(&striter, (const void **) &name, (void **) &stridx);
  625     }
  626 
  627     /* Copy symbols */
  628 
  629     KXLD_3264_FUNC(state_is_32_bit(hdr), rval,
  630         copy_symbols_32, copy_symbols_64,
  631         file, &doff, iter, strings);
  632     require_noerr(rval, finish);
  633 
  634     /* Copy vtables */
  635 
  636     KXLD_3264_FUNC(state_is_32_bit(hdr), rval,
  637         copy_vtables_32, copy_vtables_64,
  638         file, &hoff, &doff, vtables, strings);
  639     require_noerr(rval, finish);
  640 
  641     *_file = file;
  642     *_filesize = filesize;
  643     file = NULL;
  644     rval = KERN_SUCCESS;
  645 
  646 finish:
  647 
  648     if (file) {
  649         kxld_page_free(file, filesize);
  650         file = NULL;
  651     }
  652 
  653     return rval;
  654 }
  655 
  656 #if KXLD_USER_OR_ILP32
  657 /*******************************************************************************
  658 *******************************************************************************/
  659 static kern_return_t
  660 copy_symbols_32(u_char *file, u_long *data_offset, KXLDSymtabIterator *iter, 
  661     const KXLDDict *strings)
  662 {
  663     kern_return_t rval = KERN_FAILURE;
  664     KXLDSymEntry32 *symentry = NULL;
  665     const KXLDSym *sym = NULL;
  666     u_long *stridx = 0;
  667 
  668     kxld_symtab_iterator_reset(iter);
  669     while ((sym = kxld_symtab_iterator_get_next(iter))) {
  670         symentry = (KXLDSymEntry32 *) (file + *data_offset);
  671         stridx = kxld_dict_find(strings, sym->name);
  672         require_action(stridx, finish, rval=KERN_FAILURE);
  673 
  674         /* Initialize the symentry */
  675 
  676         symentry->nameoff = (uint32_t) *stridx;
  677         if (sym->predicates.is_thumb) {
  678             symentry->addr = (uint32_t) sym->link_addr | 1;
  679         } else {            
  680             symentry->addr = (uint32_t) sym->link_addr;
  681         }
  682         symentry->flags = 0;
  683 
  684         /* Set any flags */
  685 
  686         symentry->flags |= (kxld_sym_is_obsolete(sym)) ? KXLD_SYM_OBSOLETE : 0;
  687 
  688         *data_offset += sizeof(*symentry);
  689     }
  690 
  691     rval = KERN_SUCCESS;
  692 
  693 finish:
  694     return rval;
  695 }
  696 #endif /* KXLD_USER_OR_ILP32 */
  697 
  698 #if KXLD_USER_OR_LP64
  699 /*******************************************************************************
  700 *******************************************************************************/
  701 static kern_return_t
  702 copy_symbols_64(u_char *file, u_long *data_offset, KXLDSymtabIterator *iter, 
  703     const KXLDDict *strings)
  704 {
  705     kern_return_t rval = KERN_FAILURE;
  706     KXLDSymEntry64 *symentry = NULL;
  707     const KXLDSym *sym = NULL;
  708     u_long *stridx = 0;
  709 
  710     kxld_symtab_iterator_reset(iter);
  711     while ((sym = kxld_symtab_iterator_get_next(iter))) {
  712         symentry = (KXLDSymEntry64 *) (file + *data_offset);
  713         stridx = kxld_dict_find(strings, sym->name);
  714         require_action(stridx, finish, rval=KERN_FAILURE);
  715 
  716         /* Initialize the symentry */
  717 
  718         symentry->nameoff = (uint32_t) *stridx;
  719         symentry->addr = (uint64_t) sym->link_addr;
  720         symentry->flags = 0;
  721 
  722         /* Set any flags */
  723 
  724         symentry->flags |= (kxld_sym_is_obsolete(sym)) ? KXLD_SYM_OBSOLETE : 0;
  725 
  726         *data_offset += sizeof(*symentry);
  727     }
  728 
  729     rval = KERN_SUCCESS;
  730 
  731 finish:
  732     return rval;
  733 }
  734 #endif /* KXLD_USER_OR_LP64 */
  735 
  736 #if KXLD_USER_OR_ILP32
  737 /*******************************************************************************
  738 *******************************************************************************/
  739 static kern_return_t
  740 copy_vtables_32(u_char *file, u_long *header_offset, u_long *data_offset,
  741     const KXLDArray *vtables, const KXLDDict *strings)
  742 {
  743     kern_return_t rval = KERN_FAILURE;
  744     KXLDVTable *vtable = NULL;
  745     KXLDVTableHdr *vhdr = NULL;
  746     KXLDVTableEntry *ventry = NULL;
  747     KXLDSymEntry32 *symentry = NULL;
  748     u_long *stridx = 0;
  749     u_int i = 0;
  750     u_int j = 0;
  751 
  752     for (i = 0; i < vtables->nitems; ++i) {
  753         vtable = kxld_array_get_item(vtables, i);
  754         stridx = kxld_dict_find(strings, vtable->name);
  755         require_action(stridx, finish, rval=KERN_FAILURE);
  756 
  757         vhdr = (KXLDVTableHdr *) (file + *header_offset);
  758         vhdr->nameoff = (uint32_t) *stridx;
  759         vhdr->nentries = vtable->entries.nitems;
  760         vhdr->vtableoff = (uint32_t) (*data_offset);
  761 
  762         *header_offset += sizeof(*vhdr);
  763 
  764         for(j = 0; j < vtable->entries.nitems; ++j) {
  765 
  766             ventry = kxld_array_get_item(&vtable->entries, j);
  767             symentry = (KXLDSymEntry32 *) (file + *data_offset);
  768             
  769             if (ventry->patched.name) {
  770                 stridx = kxld_dict_find(strings, ventry->patched.name);
  771                 require_action(stridx, finish, rval=KERN_FAILURE);
  772 
  773                 symentry->nameoff = (uint32_t) *stridx;
  774                 symentry->addr = (uint32_t) ventry->patched.addr;
  775             } else {
  776                 symentry->nameoff = 0;
  777                 symentry->addr = 0;
  778             }
  779 
  780             *data_offset += sizeof(*symentry);
  781         }
  782     }
  783 
  784     rval = KERN_SUCCESS;
  785 
  786 finish:
  787     return rval;
  788 }
  789 #endif /* KXLD_USER_OR_ILP32 */
  790 
  791 #if KXLD_USER_OR_LP64
  792 /*******************************************************************************
  793 *******************************************************************************/
  794 static kern_return_t
  795 copy_vtables_64(u_char *file, u_long *header_offset, u_long *data_offset,
  796     const KXLDArray *vtables, const KXLDDict *strings)
  797 {
  798     kern_return_t rval = KERN_FAILURE;
  799     KXLDVTable *vtable = NULL;
  800     KXLDVTableHdr *vhdr = NULL;
  801     KXLDVTableEntry *ventry = NULL;
  802     KXLDSymEntry64 *symentry = NULL;
  803     u_long *stridx = 0;
  804     u_int i = 0;
  805     u_int j = 0;
  806 
  807     for (i = 0; i < vtables->nitems; ++i) {
  808         vtable = kxld_array_get_item(vtables, i);
  809         stridx = kxld_dict_find(strings, vtable->name);
  810         require_action(stridx, finish, rval=KERN_FAILURE);
  811 
  812         vhdr = (KXLDVTableHdr *) (file + *header_offset);
  813         vhdr->nameoff = (uint32_t) *stridx;
  814         vhdr->nentries = vtable->entries.nitems;
  815         vhdr->vtableoff = (uint32_t) (*data_offset);
  816 
  817         *header_offset += sizeof(*vhdr);
  818 
  819         for(j = 0; j < vtable->entries.nitems; ++j) {
  820 
  821             ventry = kxld_array_get_item(&vtable->entries, j);
  822             symentry = (KXLDSymEntry64 *) (file + *data_offset);
  823             
  824             if (ventry->patched.name) {
  825                 stridx = kxld_dict_find(strings, ventry->patched.name);
  826                 require_action(stridx, finish, rval=KERN_FAILURE);
  827 
  828                 symentry->nameoff = (uint32_t) *stridx;
  829                 symentry->addr = (uint64_t) ventry->patched.addr;
  830             } else {
  831                 symentry->nameoff = 0;
  832                 symentry->addr = 0;
  833             }
  834 
  835             *data_offset += sizeof(*symentry);
  836         }
  837     }
  838 
  839     rval = KERN_SUCCESS;
  840 
  841 finish:
  842     return rval;
  843 }
  844 #endif /* KXLD_USER_OR_LP64 */
  845 
  846 #if !KERNEL
  847 /*******************************************************************************
  848 *******************************************************************************/
  849 static boolean_t
  850 swap_link_state(u_char *state)
  851 {
  852     KXLDLinkStateHdr *state_hdr = (KXLDLinkStateHdr *) state;
  853 
  854     if (state_hdr->magic == CIGAM_ETATS_KNIL) {
  855         swap_link_state_32(state);
  856         return TRUE;
  857     } else if (state_hdr->magic == CIGAM_ETATS_KNIL_64) {
  858         swap_link_state_64(state);
  859         return TRUE;
  860     }
  861 
  862     return FALSE;
  863 }
  864 
  865 /*******************************************************************************
  866 *******************************************************************************/
  867 static void
  868 swap_link_state_32(u_char *state)
  869 {
  870     KXLDLinkStateHdr *state_hdr = NULL;
  871     KXLDVTableHdr *vtable_hdr = NULL;
  872     KXLDSymEntry32 *entry = NULL;
  873     u_int i = 0;
  874     u_int j = 0;
  875     
  876     state_hdr = (KXLDLinkStateHdr *) state;
  877 
  878     if (state_hdr->magic != CIGAM_ETATS_KNIL) return;
  879 
  880     /* Swap the header */
  881     swap_state_hdr(state_hdr);
  882 
  883     /* Swap the symbols */
  884     entry = (KXLDSymEntry32 *) (state + state_hdr->symoff);
  885     for (i = 0; i < state_hdr->nsyms; ++i, ++entry) {
  886         swap_sym_entry_32(entry);
  887     }
  888 
  889     /* Swap the vtable headers and entries */
  890     vtable_hdr = (KXLDVTableHdr *) (state + state_hdr->voff);
  891     for (i = 0; i < state_hdr->nvtables; ++i, ++vtable_hdr) {
  892         swap_vtable_hdr(vtable_hdr);
  893 
  894         entry = (KXLDSymEntry32 *) (state + vtable_hdr->vtableoff);
  895         for (j = 0; j < vtable_hdr->nentries; ++j, ++entry) {
  896             swap_sym_entry_32(entry);
  897         }
  898     }
  899 }
  900 
  901 /*******************************************************************************
  902 *******************************************************************************/
  903 static void
  904 swap_link_state_64(u_char *state)
  905 {
  906     KXLDLinkStateHdr *state_hdr = NULL;
  907     KXLDVTableHdr *vtable_hdr = NULL;
  908     KXLDSymEntry64 *entry = NULL;
  909     u_int i = 0;
  910     u_int j = 0;
  911     
  912     state_hdr = (KXLDLinkStateHdr *) state;
  913 
  914     if (state_hdr->magic != CIGAM_ETATS_KNIL_64) return;
  915 
  916     /* Swap the header */
  917     swap_state_hdr(state_hdr);
  918 
  919     /* Swap the symbols */
  920     entry = (KXLDSymEntry64 *) (state + state_hdr->symoff);
  921     for (i = 0; i < state_hdr->nsyms; ++i, ++entry) {
  922         swap_sym_entry_64(entry);
  923     }
  924 
  925     /* Swap the vtable headers and entries */
  926     vtable_hdr = (KXLDVTableHdr *) (state + state_hdr->voff);
  927     for (i = 0; i < state_hdr->nvtables; ++i, ++vtable_hdr) {
  928         swap_vtable_hdr(vtable_hdr);
  929 
  930         entry = (KXLDSymEntry64 *) (state + vtable_hdr->vtableoff);
  931         for (j = 0; j < vtable_hdr->nentries; ++j, ++entry) {
  932             swap_sym_entry_64(entry);
  933         }
  934     }
  935 }
  936 
  937 /*******************************************************************************
  938 *******************************************************************************/
  939 static boolean_t
  940 unswap_link_state(u_char *state)
  941 {
  942     KXLDLinkStateHdr *state_hdr = (KXLDLinkStateHdr *) state;
  943 
  944     if (state_hdr->magic == LINK_STATE_MAGIC) {
  945         unswap_link_state_32(state);
  946         return TRUE;
  947     } else if (state_hdr->magic == LINK_STATE_MAGIC_64) {
  948         unswap_link_state_64(state);
  949         return TRUE;
  950     }
  951 
  952     return FALSE;
  953 }
  954 
  955 /*******************************************************************************
  956 *******************************************************************************/
  957 static void
  958 unswap_link_state_32(u_char *state)
  959 {
  960     KXLDLinkStateHdr *state_hdr = NULL;
  961     KXLDVTableHdr *vtable_hdr = NULL;
  962     KXLDSymEntry32 *entry = NULL;
  963     u_int i = 0;
  964     u_int j = 0;
  965     
  966     state_hdr = (KXLDLinkStateHdr *) state;
  967 
  968     if (state_hdr->magic != LINK_STATE_MAGIC) return;
  969 
  970     /* Unswap the vtables and their headers */
  971     vtable_hdr = (KXLDVTableHdr *) (state + state_hdr->voff);
  972     for (i = 0; i < state_hdr->nvtables; ++i, ++vtable_hdr) {
  973         entry = (KXLDSymEntry32 *) (state + vtable_hdr->vtableoff);
  974         for (j = 0; j < vtable_hdr->nentries; ++j, ++entry) {
  975             swap_sym_entry_32(entry);
  976         }
  977 
  978         swap_vtable_hdr(vtable_hdr);
  979     }
  980 
  981     /* Unswap the symbols themselves */
  982     entry = (KXLDSymEntry32 *) (state + state_hdr->symoff);
  983     for (i = 0; i < state_hdr->nsyms; ++i, ++entry) {
  984         swap_sym_entry_32(entry);
  985     }
  986 
  987     /* Unswap the header */
  988     swap_state_hdr(state_hdr);
  989 }
  990 
  991 /*******************************************************************************
  992 *******************************************************************************/
  993 static void
  994 unswap_link_state_64(u_char *state)
  995 {
  996     KXLDLinkStateHdr *state_hdr = NULL;
  997     KXLDVTableHdr *vtable_hdr = NULL;
  998     KXLDSymEntry64 *entry = NULL;
  999     u_int i = 0;
 1000     u_int j = 0;
 1001     
 1002     state_hdr = (KXLDLinkStateHdr *) state;
 1003 
 1004     if (state_hdr->magic != LINK_STATE_MAGIC_64) return;
 1005 
 1006     /* Unswap the vtables and their headers */
 1007     vtable_hdr = (KXLDVTableHdr *) (state + state_hdr->voff);
 1008     for (i = 0; i < state_hdr->nvtables; ++i, ++vtable_hdr) {
 1009         entry = (KXLDSymEntry64 *) (state + vtable_hdr->vtableoff);
 1010         for (j = 0; j < vtable_hdr->nentries; ++j, ++entry) {
 1011             swap_sym_entry_64(entry);
 1012         }
 1013 
 1014         swap_vtable_hdr(vtable_hdr);
 1015     }
 1016 
 1017     /* Unswap the symbols themselves */
 1018     entry = (KXLDSymEntry64 *) (state + state_hdr->symoff);
 1019     for (i = 0; i < state_hdr->nsyms; ++i, ++entry) {
 1020         swap_sym_entry_64(entry);
 1021     }
 1022 
 1023     /* Unswap the header */
 1024     swap_state_hdr(state_hdr);
 1025 }
 1026 
 1027 /*******************************************************************************
 1028 *******************************************************************************/
 1029 static void
 1030 swap_state_hdr(KXLDLinkStateHdr *state_hdr)
 1031 {
 1032     state_hdr->magic = OSSwapInt32(state_hdr->magic);
 1033     state_hdr->version = OSSwapInt32(state_hdr->version);
 1034     state_hdr->cputype = OSSwapInt32(state_hdr->cputype);
 1035     state_hdr->cpusubtype = OSSwapInt32(state_hdr->cpusubtype);
 1036     state_hdr->nsects = OSSwapInt32(state_hdr->nsects);
 1037     state_hdr->sectoff = OSSwapInt32(state_hdr->sectoff);
 1038     state_hdr->nvtables = OSSwapInt32(state_hdr->nvtables);
 1039     state_hdr->voff = OSSwapInt32(state_hdr->voff);
 1040     state_hdr->nsyms = OSSwapInt32(state_hdr->nsyms);
 1041     state_hdr->symoff = OSSwapInt32(state_hdr->symoff);
 1042 }
 1043 
 1044 /*******************************************************************************
 1045 *******************************************************************************/
 1046 static void
 1047 swap_vtable_hdr(KXLDVTableHdr *vtable_hdr)
 1048 {
 1049     vtable_hdr->nameoff = OSSwapInt32(vtable_hdr->nameoff);
 1050     vtable_hdr->vtableoff = OSSwapInt32(vtable_hdr->vtableoff);
 1051     vtable_hdr->nentries = OSSwapInt32(vtable_hdr->nentries);
 1052 }
 1053 
 1054 /*******************************************************************************
 1055 *******************************************************************************/
 1056 static void
 1057 swap_sym_entry_32(KXLDSymEntry32 *entry)
 1058 {
 1059     entry->nameoff = OSSwapInt32(entry->nameoff);
 1060     entry->addr = OSSwapInt32(entry->addr);
 1061 }
 1062 
 1063 /*******************************************************************************
 1064 *******************************************************************************/
 1065 static void
 1066 swap_sym_entry_64(KXLDSymEntry64 *entry)
 1067 {
 1068     entry->nameoff = OSSwapInt32(entry->nameoff);
 1069     entry->addr = OSSwapInt64(entry->addr);
 1070 }
 1071 #endif /* !KERNEL */
 1072 

Cache object: c74074a2084d605332e9f9d129798fca


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.