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_seg.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 #include <mach/vm_prot.h>
   30 #include <mach-o/loader.h>
   31 #include <sys/types.h>
   32 
   33 #if KERNEL
   34     #include <mach/vm_param.h>
   35 #else
   36     #include <mach/mach_init.h>
   37 #endif /* KERNEL */
   38 
   39 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
   40 #include <AssertMacros.h>
   41 
   42 #include "kxld_sect.h"
   43 #include "kxld_seg.h"
   44 #include "kxld_util.h"
   45 
   46 #define MAX_SEGS 20
   47 
   48 #define TEXT_SEG_PROT (VM_PROT_READ | VM_PROT_EXECUTE)
   49 #define DATA_SEG_PROT (VM_PROT_READ | VM_PROT_WRITE)
   50 
   51 #if KXLD_USER_OR_OBJECT
   52 static kern_return_t reorder_sections(KXLDSeg *seg, KXLDArray *section_order);
   53 static void reorder_section(KXLDArray *sects, u_int *sect_reorder_index, 
   54     KXLDSect **reorder_buffer, u_int reorder_buffer_index);
   55 #endif /* KXLD_USER_OR_OBJECT */
   56 
   57 #if 0
   58 static KXLDSeg * get_segment_by_name(KXLDArray *segarray, const char *name);
   59 #endif
   60 
   61 #if KXLD_USER_OR_ILP32
   62 static kern_return_t seg_export_macho_header_32(const KXLDSeg *seg, u_char *buf,
   63     u_long *header_offset, u_long header_size, u_long data_offset);
   64 #endif
   65 #if KXLD_USER_OR_LP64
   66 static kern_return_t seg_export_macho_header_64(const KXLDSeg *seg, u_char *buf,
   67     u_long *header_offset, u_long header_size, u_long data_offset);
   68 #endif
   69 
   70 static KXLDSect * get_sect_by_index(const KXLDSeg *seg, u_int idx);
   71 
   72 #if KXLD_USER_OR_ILP32
   73 /*******************************************************************************
   74 *******************************************************************************/
   75 kern_return_t
   76 kxld_seg_init_from_macho_32(KXLDSeg *seg, struct segment_command *src)
   77 {
   78     kern_return_t rval = KERN_FAILURE;
   79     check(seg);
   80     check(src);
   81 
   82     strlcpy(seg->segname, src->segname, sizeof(seg->segname));
   83     seg->base_addr = src->vmaddr;
   84     seg->link_addr = src->vmaddr;
   85     seg->vmsize = src->vmsize;
   86     seg->fileoff = src->fileoff;
   87     seg->maxprot = src->maxprot;
   88     seg->initprot = src->initprot;
   89     seg->flags = src->flags;
   90 
   91     rval = kxld_array_init(&seg->sects, sizeof(KXLDSect *), src->nsects);
   92     require_noerr(rval, finish);
   93 
   94     rval = KERN_SUCCESS;
   95 
   96 finish:
   97     return rval;
   98 }
   99 #endif /* KXLD_USER_OR_ILP32 */
  100 
  101 #if KXLD_USER_OR_LP64
  102 /*******************************************************************************
  103 *******************************************************************************/
  104 kern_return_t
  105 kxld_seg_init_from_macho_64(KXLDSeg *seg, struct segment_command_64 *src)
  106 {
  107     kern_return_t rval = KERN_FAILURE;
  108     check(seg);
  109     check(src);
  110 
  111     strlcpy(seg->segname, src->segname, sizeof(seg->segname));
  112     seg->base_addr = src->vmaddr;
  113     seg->link_addr = src->vmaddr;
  114     seg->vmsize = src->vmsize;
  115     seg->fileoff = src->fileoff;
  116     seg->maxprot = src->maxprot;
  117     seg->initprot = src->initprot;
  118     seg->flags = src->flags;
  119 
  120     rval = kxld_array_init(&seg->sects, sizeof(KXLDSect *), src->nsects);
  121     require_noerr(rval, finish);
  122 
  123     rval = KERN_SUCCESS;
  124 
  125 finish:
  126     return rval;
  127 }
  128 #endif /* KXLD_USER_OR_LP64 */
  129 
  130 #if KXLD_USER_OR_OBJECT
  131 /*******************************************************************************
  132 *******************************************************************************/
  133 kern_return_t
  134 kxld_seg_create_seg_from_sections(KXLDArray *segarray, KXLDArray *sectarray)
  135 {
  136     kern_return_t rval = KERN_FAILURE;
  137     KXLDSeg *seg = NULL;
  138     KXLDSect *sect = NULL;
  139     KXLDSect **sectp = NULL;
  140     u_int i = 0;
  141 
  142     /* Initialize the segment array to one segment */
  143 
  144     rval = kxld_array_init(segarray, sizeof(KXLDSeg), 1);
  145     require_noerr(rval, finish);
  146 
  147     /* Initialize the segment */
  148 
  149     seg = kxld_array_get_item(segarray, 0);
  150     seg->initprot = VM_PROT_ALL;
  151     seg->maxprot = VM_PROT_ALL;
  152     seg->link_addr = 0;
  153 
  154     /* Add the sections to the segment */
  155 
  156     rval = kxld_array_init(&seg->sects, sizeof(KXLDSect *), sectarray->nitems);
  157     require_noerr(rval, finish);
  158 
  159     for (i = 0; i < sectarray->nitems; ++i) {
  160         sect = kxld_array_get_item(sectarray, i);
  161         sectp = kxld_array_get_item(&seg->sects, i);
  162 
  163         *sectp = sect;
  164     }
  165 
  166     rval = KERN_SUCCESS;
  167 finish:
  168     return rval;
  169 }
  170 
  171 /*******************************************************************************
  172 *******************************************************************************/
  173 kern_return_t
  174 kxld_seg_finalize_object_segment(KXLDArray *segarray, KXLDArray *section_order,
  175     u_long hdrsize)
  176 {
  177     kern_return_t rval = KERN_FAILURE;
  178     KXLDSeg *seg = NULL;
  179     KXLDSect *sect = NULL;
  180     u_long sect_offset = 0;
  181     u_int i = 0;
  182 
  183     check(segarray);
  184     check(section_order);
  185     require_action(segarray->nitems == 1, finish, rval=KERN_FAILURE);
  186 
  187     seg = kxld_array_get_item(segarray, 0);
  188     
  189     /* Reorder the sections */
  190     
  191     rval = reorder_sections(seg, section_order);
  192     require_noerr(rval, finish);
  193 
  194     /* Set the initial link address at the end of the header pages */
  195 
  196     seg->link_addr = round_page(hdrsize);
  197 
  198     /* Fix up all of the section addresses */
  199 
  200     sect_offset = (u_long) seg->link_addr;
  201     for (i = 0; i < seg->sects.nitems; ++i) {
  202         sect = *(KXLDSect **)kxld_array_get_item(&seg->sects, i);
  203 
  204         sect->link_addr = kxld_sect_align_address(sect, sect_offset);
  205         sect_offset = (u_long) (sect->link_addr + sect->size);
  206     }
  207 
  208     /* Finish initializing the segment */
  209 
  210     seg->vmsize = round_page(sect_offset) - seg->link_addr;
  211 
  212     rval = KERN_SUCCESS;
  213 finish:
  214     return rval;
  215 }
  216 
  217 /*******************************************************************************
  218 * The legacy section ordering used by kld was based of the order of sections
  219 * in the kernel file.  To achieve the same layout, we save the kernel's
  220 * section ordering as an array of section names when the kernel file itself
  221 * is linked.  Then, when kexts are linked with the KXLD_LEGACY_LAYOUT flag,
  222 * we refer to the kernel's section layout to order the kext's sections.
  223 *
  224 * The algorithm below is as follows.  We iterate through all of the kernel's
  225 * sections grouped by segment name, so that we are processing all of the __TEXT
  226 * sections, then all of the __DATA sections, etc.  We then iterate through the
  227 * kext's sections with a similar grouping, looking for sections that match
  228 * the current kernel's section.  In this way, we order all of the matching
  229 * kext sections in the order in which they appear in the kernel, and then place
  230 * all remaining kext sections at the end of the current segment grouping in
  231 * the order in which they originally appeared.  Sections that only appear in
  232 * the kernel are not created.  segments that only appear in the kext are
  233 * left in their original ordering.
  234 *
  235 * An example:
  236 *
  237 * Kernel sections:
  238 * __TEXT,__text
  239 * __TEXT,__initcode
  240 * __TEXT,__const
  241 * __DATA,__data
  242 *
  243 * Kext sections:
  244 * __TEXT,__const
  245 * __TEXT,__literal4
  246 * __TEXT,__text
  247 * __DATA,__const
  248 * __DATA,__data
  249 *
  250 * Reordered kext sections:
  251 * __TEXT,__text
  252 * __TEXT,__const
  253 * __TEXT,__literal4
  254 * __DATA,__data
  255 * __DATA,__const
  256 *
  257 * In the implementation below, we use a reorder buffer to hold pointers to the
  258 * sections of the current working segment.  We scan this buffer looking for
  259 * matching sections, placing them in the segment's section index as we find them.
  260 * If this function must exit early, the segment's section index is left in an
  261 * unusable state.
  262 *******************************************************************************/
  263 static kern_return_t
  264 reorder_sections(KXLDSeg *seg, KXLDArray *section_order)
  265 {
  266     kern_return_t rval = KERN_FAILURE;
  267     KXLDSect *sect = NULL;
  268     KXLDSect **reorder_buffer = NULL;
  269     KXLDSectionName *section_name = NULL;
  270     const char *segname = NULL;
  271     u_int sect_index = 0, legacy_index = 0, sect_reorder_index = 0;
  272     u_int i = 0, j = 0;
  273     u_int sect_start = 0, sect_end = 0, legacy_start = 0, legacy_end = 0;
  274     u_int nsects = 0;
  275 
  276     check(seg);
  277     check(section_order);
  278 
  279     /* Allocate the reorder buffer with enough space to hold all of the 
  280      * sections.
  281      */
  282 
  283     reorder_buffer = kxld_alloc(
  284         seg->sects.nitems * sizeof(*reorder_buffer));
  285     require_action(reorder_buffer, finish, rval=KERN_RESOURCE_SHORTAGE);
  286 
  287     while (legacy_index < section_order->nitems) {
  288 
  289         /* Find the next group of sections with a common segment in the
  290          * section_order array.
  291          */
  292 
  293         legacy_start = legacy_index++;
  294         legacy_end = legacy_index;
  295 
  296         section_name = kxld_array_get_item(section_order, legacy_start);
  297         segname = section_name->segname;
  298         while (legacy_index < section_order->nitems) {
  299             section_name = kxld_array_get_item(section_order, legacy_index);
  300             if (!streq_safe(segname, section_name->segname, 
  301                     sizeof(section_name->segname))) 
  302             {
  303                 break;
  304             }
  305 
  306             ++legacy_index;
  307             ++legacy_end;
  308         }
  309 
  310         /* Find a group of sections in the kext that match the current
  311          * section_order segment.
  312          */
  313 
  314         sect_start = sect_index;
  315         sect_end = sect_index;
  316 
  317         while (sect_index < seg->sects.nitems) {
  318             sect = *(KXLDSect **) kxld_array_get_item(&seg->sects, sect_index);
  319             if (!streq_safe(segname, sect->segname, sizeof(sect->segname))) {
  320                 break;
  321             }
  322 
  323             ++sect_index;
  324             ++sect_end;
  325         }
  326         nsects = sect_end - sect_start;
  327         
  328         if (!nsects) continue;
  329 
  330         /* Populate the reorder buffer with the current group of kext sections */
  331 
  332         for (i = sect_start; i < sect_end; ++i) {
  333             reorder_buffer[i - sect_start] = 
  334                 *(KXLDSect **) kxld_array_get_item(&seg->sects, i);
  335         }
  336 
  337         /* For each section_order section, scan the reorder buffer for a matching
  338          * kext section.  If one is found, copy it into the next slot in the
  339          * segment's section index.
  340          */
  341 
  342         sect_reorder_index = sect_start;
  343         for (i = legacy_start; i < legacy_end; ++i) {
  344             section_name = kxld_array_get_item(section_order, i);
  345             sect = NULL;
  346 
  347             for (j = 0; j < nsects; ++j) {
  348                 sect = reorder_buffer[j];
  349                 if (!sect) continue;
  350 
  351                 if (streq_safe(section_name->sectname, sect->sectname, 
  352                         sizeof(section_name->sectname))) 
  353                 {
  354                     break;
  355                 }
  356 
  357                 sect = NULL;
  358             }
  359 
  360             if (sect) { 
  361                 (void) reorder_section(&seg->sects, &sect_reorder_index, 
  362                     reorder_buffer, j);
  363             }
  364         }
  365 
  366         /* If any sections remain in the reorder buffer, they are not specified
  367          * in the section_order array, so append them to the section index in
  368          * in the order they are found.
  369          */
  370 
  371         for (i = 0; i < nsects; ++i) {
  372             if (!reorder_buffer[i]) continue;
  373             reorder_section(&seg->sects, &sect_reorder_index, reorder_buffer, i);
  374         }
  375     }
  376 
  377     rval = KERN_SUCCESS;
  378 
  379 finish:
  380 
  381     if (reorder_buffer) {
  382         kxld_free(reorder_buffer, seg->sects.nitems * sizeof(*reorder_buffer));
  383         reorder_buffer = NULL;
  384     }
  385 
  386     return rval;
  387 }
  388 
  389 /*******************************************************************************
  390 *******************************************************************************/
  391 static void
  392 reorder_section(KXLDArray *sects, u_int *sect_reorder_index, 
  393     KXLDSect **reorder_buffer, u_int reorder_buffer_index)
  394 {
  395     KXLDSect **tmp = NULL;
  396 
  397     tmp = kxld_array_get_item(sects, *sect_reorder_index);
  398 
  399     *tmp = reorder_buffer[reorder_buffer_index];
  400     reorder_buffer[reorder_buffer_index]->sectnum = *sect_reorder_index;
  401     reorder_buffer[reorder_buffer_index] = NULL;
  402 
  403     ++(*sect_reorder_index);
  404 }
  405 #endif /* KXLD_USER_OR_OBJECT */
  406 
  407 /*******************************************************************************
  408 *******************************************************************************/
  409 void
  410 kxld_seg_clear(KXLDSeg *seg)
  411 {
  412     check(seg);
  413 
  414     bzero(seg->segname, sizeof(seg->segname));
  415     seg->base_addr = 0;
  416     seg->link_addr = 0;
  417     seg->vmsize = 0;
  418     seg->flags = 0;
  419     seg->maxprot = 0;
  420     seg->initprot = 0;
  421 
  422     /* Don't clear the individual sections here because kxld_kext.c will take
  423      * care of that.
  424      */
  425     kxld_array_clear(&seg->sects);
  426 }
  427 
  428 /*******************************************************************************
  429 *******************************************************************************/
  430 void 
  431 kxld_seg_deinit(KXLDSeg *seg)
  432 {
  433     check(seg);
  434 
  435     kxld_array_deinit(&seg->sects);
  436     bzero(seg, sizeof(*seg));
  437 }
  438 
  439 /*******************************************************************************
  440 *******************************************************************************/
  441 kxld_size_t 
  442 kxld_seg_get_vmsize(const KXLDSeg *seg)
  443 {
  444     check(seg);
  445 
  446     return seg->vmsize;
  447 }
  448 
  449 /*******************************************************************************
  450 *******************************************************************************/
  451 u_long
  452 kxld_seg_get_macho_header_size(const KXLDSeg *seg, boolean_t is_32_bit)
  453 {
  454     u_long size = 0;
  455     
  456     check(seg);
  457 
  458     if (is_32_bit) {
  459         size += sizeof(struct segment_command);
  460     } else {
  461         size += sizeof(struct segment_command_64);
  462     }
  463     size += seg->sects.nitems * kxld_sect_get_macho_header_size(is_32_bit);
  464 
  465     return size;
  466 }
  467 
  468 /*******************************************************************************
  469 *******************************************************************************/
  470 u_long
  471 kxld_seg_get_macho_data_size(const KXLDSeg *seg)
  472 {
  473     u_long size = 0;
  474     u_int i = 0;
  475     KXLDSect *sect = NULL;
  476 
  477     check(seg);
  478 
  479     for (i = 0; i < seg->sects.nitems; ++i) {
  480         sect = get_sect_by_index(seg, i);
  481         size = (u_long) kxld_sect_align_address(sect, size);
  482         size += kxld_sect_get_macho_data_size(sect);
  483     }
  484 
  485     return round_page(size);
  486 }
  487 
  488 /*******************************************************************************
  489 *******************************************************************************/
  490 static KXLDSect * 
  491 get_sect_by_index(const KXLDSeg *seg, u_int idx)
  492 {
  493     check(seg);
  494 
  495     return *(KXLDSect **) kxld_array_get_item(&seg->sects, idx);
  496 }
  497 
  498 /*******************************************************************************
  499 *******************************************************************************/
  500 kern_return_t
  501 kxld_seg_export_macho_to_file_buffer(const KXLDSeg *seg, u_char *buf,
  502     u_long *header_offset, u_long header_size, 
  503     u_long *data_offset, u_long data_size,
  504     boolean_t is_32_bit)
  505 {
  506     kern_return_t rval = KERN_FAILURE;
  507     KXLDSect *sect = NULL;
  508     u_long base_data_offset = *data_offset;
  509     u_int i = 0;
  510     struct segment_command *hdr32 = 
  511         (struct segment_command *) (buf + *header_offset);
  512     struct segment_command_64 *hdr64 = 
  513         (struct segment_command_64 *) (buf + *header_offset);
  514 
  515     check(seg);
  516     check(buf);
  517     check(header_offset);
  518     check(data_offset);
  519 
  520     /* Write out the header */
  521 
  522     KXLD_3264_FUNC(is_32_bit, rval,
  523         seg_export_macho_header_32, seg_export_macho_header_64,
  524         seg, buf, header_offset, header_size, *data_offset);
  525     require_noerr(rval, finish);
  526 
  527     /* Write out each section */
  528 
  529     for (i = 0; i < seg->sects.nitems; ++i) {
  530         sect = get_sect_by_index(seg, i);
  531 
  532         rval = kxld_sect_export_macho_to_file_buffer(sect, buf, header_offset, 
  533             header_size, data_offset, data_size, is_32_bit);
  534         require_noerr(rval, finish);
  535     }
  536 
  537     /* Update the filesize */
  538 
  539     if (is_32_bit) {
  540         hdr32->filesize = (uint32_t) (*data_offset - base_data_offset);
  541     } else {
  542         hdr64->filesize = (uint64_t) (*data_offset - base_data_offset);
  543     }
  544 
  545     *data_offset = round_page(*data_offset);
  546 
  547     rval = KERN_SUCCESS;
  548 
  549 finish:
  550     return rval;
  551 
  552 }
  553 
  554 /*******************************************************************************
  555 *******************************************************************************/
  556 kern_return_t
  557 kxld_seg_export_macho_to_vm(const KXLDSeg *seg, u_char *buf,
  558     u_long *header_offset, u_long header_size, 
  559     u_long data_size, kxld_addr_t file_link_addr, 
  560     boolean_t is_32_bit)
  561 {
  562     kern_return_t rval = KERN_FAILURE;
  563     KXLDSect *sect = NULL;
  564     u_long data_offset = (u_long) (seg->link_addr - file_link_addr);
  565     u_int i = 0;
  566 
  567     check(seg);
  568     check(buf);
  569     check(header_offset);
  570 
  571     /* Write out the header */
  572 
  573     KXLD_3264_FUNC(is_32_bit, rval,
  574         seg_export_macho_header_32, seg_export_macho_header_64,
  575         seg, buf, header_offset, header_size, data_offset);
  576     require_noerr(rval, finish);
  577 
  578     /* Write out each section */
  579 
  580     for (i = 0; i < seg->sects.nitems; ++i) {
  581         sect = get_sect_by_index(seg, i);
  582 
  583         rval = kxld_sect_export_macho_to_vm(sect, buf, header_offset, 
  584             header_size, file_link_addr, data_size, is_32_bit);
  585         require_noerr(rval, finish);
  586     }
  587 
  588     rval = KERN_SUCCESS;
  589 
  590 finish:
  591     return rval;
  592 }
  593 
  594 #if KXLD_USER_OR_ILP32
  595 /*******************************************************************************
  596 *******************************************************************************/
  597 static kern_return_t
  598 seg_export_macho_header_32(const KXLDSeg *seg, u_char *buf,
  599     u_long *header_offset, u_long header_size, u_long data_offset)
  600 {
  601     kern_return_t rval = KERN_FAILURE;
  602     struct segment_command *seghdr = NULL;
  603 
  604     check(seg);
  605     check(buf);
  606     check(header_offset);
  607 
  608     require_action(sizeof(*seghdr) <= header_size - *header_offset, finish,
  609         rval=KERN_FAILURE);
  610     seghdr = (struct segment_command *) (buf + *header_offset);
  611     *header_offset += sizeof(*seghdr);
  612 
  613     seghdr->cmd = LC_SEGMENT;
  614     seghdr->cmdsize = (uint32_t) sizeof(*seghdr);
  615     seghdr->cmdsize += 
  616         (uint32_t) (seg->sects.nitems * kxld_sect_get_macho_header_size(TRUE));
  617     strlcpy(seghdr->segname, seg->segname, sizeof(seghdr->segname));
  618     seghdr->vmaddr = (uint32_t) seg->link_addr;
  619     seghdr->vmsize = (uint32_t) seg->vmsize;
  620     seghdr->fileoff = (uint32_t) data_offset;
  621     seghdr->filesize = (uint32_t) seg->vmsize;
  622     seghdr->maxprot = seg->maxprot;
  623     seghdr->initprot = seg->initprot;
  624     seghdr->nsects = seg->sects.nitems;
  625     seghdr->flags = 0;
  626 
  627     rval = KERN_SUCCESS;
  628 
  629 finish:
  630     return rval;
  631 }
  632 #endif /* KXLD_USER_OR_ILP32 */
  633 
  634 #if KXLD_USER_OR_LP64 
  635 /*******************************************************************************
  636 *******************************************************************************/
  637 static kern_return_t
  638 seg_export_macho_header_64(const KXLDSeg *seg, u_char *buf,
  639     u_long *header_offset, u_long header_size, u_long data_offset)
  640 {
  641     kern_return_t rval = KERN_FAILURE;
  642     struct segment_command_64 *seghdr = NULL;
  643 
  644     check(seg);
  645     check(buf);
  646     check(header_offset);
  647 
  648     require_action(sizeof(*seghdr) <= header_size - *header_offset, finish,
  649         rval=KERN_FAILURE);
  650     seghdr = (struct segment_command_64 *) (buf + *header_offset);
  651     *header_offset += sizeof(*seghdr);
  652 
  653     seghdr->cmd = LC_SEGMENT_64;
  654     seghdr->cmdsize = (uint32_t) sizeof(*seghdr);
  655     seghdr->cmdsize += 
  656         (uint32_t) (seg->sects.nitems * kxld_sect_get_macho_header_size(FALSE));
  657     strlcpy(seghdr->segname, seg->segname, sizeof(seghdr->segname));
  658     seghdr->vmaddr = (uint64_t) seg->link_addr;
  659     seghdr->vmsize = (uint64_t) seg->vmsize;
  660     seghdr->fileoff = (uint64_t) data_offset;
  661     seghdr->filesize = (uint64_t) seg->vmsize;
  662     seghdr->maxprot = seg->maxprot;
  663     seghdr->initprot = seg->initprot;
  664     seghdr->nsects = seg->sects.nitems;
  665     seghdr->flags = 0;
  666 
  667     rval = KERN_SUCCESS;
  668 
  669 finish:
  670     return rval;
  671 }
  672 #endif /* KXLD_USER_OR_LP64 */
  673 
  674 /*******************************************************************************
  675 *******************************************************************************/
  676 kern_return_t
  677 kxld_seg_add_section(KXLDSeg *seg, KXLDSect *sect)
  678 {
  679     kern_return_t rval = KERN_FAILURE;
  680     KXLDSect **sectp = NULL;
  681     u_int i;
  682 
  683     check(seg);
  684     check(sect);
  685     require_action(streq_safe(seg->segname, sect->segname, sizeof(seg->segname)),
  686         finish, rval=KERN_FAILURE);
  687     
  688     /* Add the section into the section index */
  689 
  690     for (i = 0; i < seg->sects.nitems; ++i) {
  691         sectp = kxld_array_get_item(&seg->sects, i);
  692         if (NULL == *sectp) {
  693             *sectp = sect;
  694             break;
  695         }
  696     }
  697     require_action(i < seg->sects.nitems, finish, rval=KERN_FAILURE);
  698 
  699     rval = KERN_SUCCESS;
  700 
  701 finish:
  702 
  703     return rval;
  704 }
  705 
  706 /*******************************************************************************
  707 *******************************************************************************/
  708 kern_return_t
  709 kxld_seg_finish_init(KXLDSeg *seg)
  710 {
  711     kern_return_t rval = KERN_FAILURE;
  712     u_int i = 0;
  713     KXLDSect *sect = NULL;
  714     kxld_addr_t maxaddr = 0;
  715     kxld_size_t maxsize = 0;
  716     
  717     if (seg->sects.nitems) {
  718         for (i = 0; i < seg->sects.nitems; ++i) {
  719             sect = get_sect_by_index(seg, i);
  720             require_action(sect, finish, rval=KERN_FAILURE);
  721             if (sect->base_addr > maxaddr) {
  722                 maxaddr = sect->base_addr;
  723                 maxsize = sect->size;
  724             }
  725         }
  726 
  727         /* XXX Cross architecture linking will fail if the page size ever differs
  728          * from 4096.  (As of this writing, we're fine on ppc, i386, x86_64, and
  729          * arm.)
  730          */
  731         seg->vmsize = round_page(maxaddr + maxsize - seg->base_addr);
  732     }
  733 
  734     rval = KERN_SUCCESS;
  735     
  736 finish:
  737     return rval;
  738 }
  739 
  740 /*******************************************************************************
  741 *******************************************************************************/
  742 void
  743 kxld_seg_set_vm_protections(KXLDSeg *seg, boolean_t strict_protections)
  744 {
  745     if (strict_protections) {
  746         if (streq_safe(seg->segname, SEG_TEXT, sizeof(SEG_TEXT))) {
  747             seg->initprot = TEXT_SEG_PROT;
  748             seg->maxprot = VM_PROT_ALL;
  749         } else {
  750             seg->initprot = DATA_SEG_PROT;
  751             seg->maxprot = DATA_SEG_PROT;
  752         }
  753     } else {
  754         seg->initprot = VM_PROT_ALL;
  755         seg->maxprot = VM_PROT_ALL;
  756     }
  757 }
  758 
  759 /*******************************************************************************
  760 *******************************************************************************/
  761 void
  762 kxld_seg_relocate(KXLDSeg *seg, kxld_addr_t link_addr)
  763 {
  764     KXLDSect *sect = NULL;
  765     u_int i = 0;
  766 
  767     seg->link_addr += link_addr;
  768     for (i = 0; i < seg->sects.nitems; ++i) {
  769         sect = get_sect_by_index(seg, i);
  770         kxld_sect_relocate(sect, link_addr);
  771     }
  772 }
  773 

Cache object: dd07e7d4901fcccff8da6dffaf5bd85b


[ 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.