--- /dev/null
+/*
+ * 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 <string.h>
+#include <mach/vm_prot.h>
+#include <mach-o/loader.h>
+#include <sys/types.h>
+
+#if KERNEL
+ #include <mach/vm_param.h>
+#else
+ #include <mach/mach_init.h>
+#endif /* KERNEL */
+
+#define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
+#include <AssertMacros.h>
+
+#include "kxld_sect.h"
+#include "kxld_seg.h"
+#include "kxld_util.h"
+
+#define MAX_SEGS 20
+
+#define TEXT_SEG_PROT (VM_PROT_READ | VM_PROT_EXECUTE)
+#define DATA_SEG_PROT (VM_PROT_READ | VM_PROT_WRITE)
+
+#if KXLD_USER_OR_OBJECT
+static kern_return_t reorder_sections(KXLDSeg *seg, KXLDArray *section_order);
+static void reorder_section(KXLDArray *sects, u_int *sect_reorder_index,
+ KXLDSect **reorder_buffer, u_int reorder_buffer_index);
+#endif /* KXLD_USER_OR_OBJECT */
+
+#if 0
+static KXLDSeg * get_segment_by_name(KXLDArray *segarray, const char *name);
+#endif
+
+#if KXLD_USER_OR_ILP32
+static kern_return_t seg_export_macho_header_32(const KXLDSeg *seg, u_char *buf,
+ u_long *header_offset, u_long header_size, u_long data_offset);
+#endif
+#if KXLD_USER_OR_LP64
+static kern_return_t seg_export_macho_header_64(const KXLDSeg *seg, u_char *buf,
+ u_long *header_offset, u_long header_size, u_long data_offset);
+#endif
+
+static KXLDSect * get_sect_by_index(const KXLDSeg *seg, u_int idx);
+
+#if KXLD_USER_OR_ILP32
+/*******************************************************************************
+*******************************************************************************/
+kern_return_t
+kxld_seg_init_from_macho_32(KXLDSeg *seg, struct segment_command *src)
+{
+ kern_return_t rval = KERN_FAILURE;
+ check(seg);
+ check(src);
+
+ strlcpy(seg->segname, src->segname, sizeof(seg->segname));
+ seg->base_addr = src->vmaddr;
+ seg->link_addr = src->vmaddr;
+ seg->vmsize = src->vmsize;
+ seg->fileoff = src->fileoff;
+ seg->maxprot = src->maxprot;
+ seg->initprot = src->initprot;
+ seg->flags = src->flags;
+
+ rval = kxld_array_init(&seg->sects, sizeof(KXLDSect *), src->nsects);
+ require_noerr(rval, finish);
+
+ rval = KERN_SUCCESS;
+
+finish:
+ return rval;
+}
+#endif /* KXLD_USER_OR_ILP32 */
+
+#if KXLD_USER_OR_LP64
+/*******************************************************************************
+*******************************************************************************/
+kern_return_t
+kxld_seg_init_from_macho_64(KXLDSeg *seg, struct segment_command_64 *src)
+{
+ kern_return_t rval = KERN_FAILURE;
+ check(seg);
+ check(src);
+
+ strlcpy(seg->segname, src->segname, sizeof(seg->segname));
+ seg->base_addr = src->vmaddr;
+ seg->link_addr = src->vmaddr;
+ seg->vmsize = src->vmsize;
+ seg->fileoff = src->fileoff;
+ seg->maxprot = src->maxprot;
+ seg->initprot = src->initprot;
+ seg->flags = src->flags;
+
+ rval = kxld_array_init(&seg->sects, sizeof(KXLDSect *), src->nsects);
+ require_noerr(rval, finish);
+
+ rval = KERN_SUCCESS;
+
+finish:
+ return rval;
+}
+#endif /* KXLD_USER_OR_LP64 */
+
+#if KXLD_USER_OR_OBJECT
+/*******************************************************************************
+*******************************************************************************/
+kern_return_t
+kxld_seg_create_seg_from_sections(KXLDArray *segarray, KXLDArray *sectarray)
+{
+ kern_return_t rval = KERN_FAILURE;
+ KXLDSeg *seg = NULL;
+ KXLDSect *sect = NULL;
+ KXLDSect **sectp = NULL;
+ u_int i = 0;
+
+ /* Initialize the segment array to one segment */
+
+ rval = kxld_array_init(segarray, sizeof(KXLDSeg), 1);
+ require_noerr(rval, finish);
+
+ /* Initialize the segment */
+
+ seg = kxld_array_get_item(segarray, 0);
+ seg->initprot = VM_PROT_ALL;
+ seg->maxprot = VM_PROT_ALL;
+ seg->link_addr = 0;
+
+ /* Add the sections to the segment */
+
+ rval = kxld_array_init(&seg->sects, sizeof(KXLDSect *), sectarray->nitems);
+ require_noerr(rval, finish);
+
+ for (i = 0; i < sectarray->nitems; ++i) {
+ sect = kxld_array_get_item(sectarray, i);
+ sectp = kxld_array_get_item(&seg->sects, i);
+
+ *sectp = sect;
+ }
+
+ rval = KERN_SUCCESS;
+finish:
+ return rval;
+}
+
+/*******************************************************************************
+*******************************************************************************/
+kern_return_t
+kxld_seg_finalize_object_segment(KXLDArray *segarray, KXLDArray *section_order,
+ u_long hdrsize)
+{
+ kern_return_t rval = KERN_FAILURE;
+ KXLDSeg *seg = NULL;
+ KXLDSect *sect = NULL;
+ u_long sect_offset = 0;
+ u_int i = 0;
+
+ check(segarray);
+ check(section_order);
+ require_action(segarray->nitems == 1, finish, rval=KERN_FAILURE);
+
+ seg = kxld_array_get_item(segarray, 0);
+
+ /* Reorder the sections */
+
+ rval = reorder_sections(seg, section_order);
+ require_noerr(rval, finish);
+
+ /* Set the initial link address at the end of the header pages */
+
+ seg->link_addr = round_page(hdrsize);
+
+ /* Fix up all of the section addresses */
+
+ sect_offset = (u_long) seg->link_addr;
+ for (i = 0; i < seg->sects.nitems; ++i) {
+ sect = *(KXLDSect **)kxld_array_get_item(&seg->sects, i);
+
+ sect->link_addr = kxld_sect_align_address(sect, sect_offset);
+ sect_offset = (u_long) (sect->link_addr + sect->size);
+ }
+
+ /* Finish initializing the segment */
+
+ seg->vmsize = round_page(sect_offset) - seg->link_addr;
+
+ rval = KERN_SUCCESS;
+finish:
+ return rval;
+}
+
+/*******************************************************************************
+* The legacy section ordering used by kld was based of the order of sections
+* in the kernel file. To achieve the same layout, we save the kernel's
+* section ordering as an array of section names when the kernel file itself
+* is linked. Then, when kexts are linked with the KXLD_LEGACY_LAYOUT flag,
+* we refer to the kernel's section layout to order the kext's sections.
+*
+* The algorithm below is as follows. We iterate through all of the kernel's
+* sections grouped by segment name, so that we are processing all of the __TEXT
+* sections, then all of the __DATA sections, etc. We then iterate through the
+* kext's sections with a similar grouping, looking for sections that match
+* the current kernel's section. In this way, we order all of the matching
+* kext sections in the order in which they appear in the kernel, and then place
+* all remaining kext sections at the end of the current segment grouping in
+* the order in which they originally appeared. Sections that only appear in
+* the kernel are not created. segments that only appear in the kext are
+* left in their original ordering.
+*
+* An example:
+*
+* Kernel sections:
+* __TEXT,__text
+* __TEXT,__initcode
+* __TEXT,__const
+* __DATA,__data
+*
+* Kext sections:
+* __TEXT,__const
+* __TEXT,__literal4
+* __TEXT,__text
+* __DATA,__const
+* __DATA,__data
+*
+* Reordered kext sections:
+* __TEXT,__text
+* __TEXT,__const
+* __TEXT,__literal4
+* __DATA,__data
+* __DATA,__const
+*
+* In the implementation below, we use a reorder buffer to hold pointers to the
+* sections of the current working segment. We scan this buffer looking for
+* matching sections, placing them in the segment's section index as we find them.
+* If this function must exit early, the segment's section index is left in an
+* unusable state.
+*******************************************************************************/
+static kern_return_t
+reorder_sections(KXLDSeg *seg, KXLDArray *section_order)
+{
+ kern_return_t rval = KERN_FAILURE;
+ KXLDSect *sect = NULL;
+ KXLDSect **reorder_buffer = NULL;
+ KXLDSectionName *section_name = NULL;
+ const char *segname = NULL;
+ u_int sect_index = 0, legacy_index = 0, sect_reorder_index = 0;
+ u_int i = 0, j = 0;
+ u_int sect_start = 0, sect_end = 0, legacy_start = 0, legacy_end = 0;
+ u_int nsects = 0;
+
+ check(seg);
+ check(section_order);
+
+ /* Allocate the reorder buffer with enough space to hold all of the
+ * sections.
+ */
+
+ reorder_buffer = kxld_alloc(
+ seg->sects.nitems * sizeof(*reorder_buffer));
+ require_action(reorder_buffer, finish, rval=KERN_RESOURCE_SHORTAGE);
+
+ while (legacy_index < section_order->nitems) {
+
+ /* Find the next group of sections with a common segment in the
+ * section_order array.
+ */
+
+ legacy_start = legacy_index++;
+ legacy_end = legacy_index;
+
+ section_name = kxld_array_get_item(section_order, legacy_start);
+ segname = section_name->segname;
+ while (legacy_index < section_order->nitems) {
+ section_name = kxld_array_get_item(section_order, legacy_index);
+ if (!streq_safe(segname, section_name->segname,
+ sizeof(section_name->segname)))
+ {
+ break;
+ }
+
+ ++legacy_index;
+ ++legacy_end;
+ }
+
+ /* Find a group of sections in the kext that match the current
+ * section_order segment.
+ */
+
+ sect_start = sect_index;
+ sect_end = sect_index;
+
+ while (sect_index < seg->sects.nitems) {
+ sect = *(KXLDSect **) kxld_array_get_item(&seg->sects, sect_index);
+ if (!streq_safe(segname, sect->segname, sizeof(sect->segname))) {
+ break;
+ }
+
+ ++sect_index;
+ ++sect_end;
+ }
+ nsects = sect_end - sect_start;
+
+ if (!nsects) continue;
+
+ /* Populate the reorder buffer with the current group of kext sections */
+
+ for (i = sect_start; i < sect_end; ++i) {
+ reorder_buffer[i - sect_start] =
+ *(KXLDSect **) kxld_array_get_item(&seg->sects, i);
+ }
+
+ /* For each section_order section, scan the reorder buffer for a matching
+ * kext section. If one is found, copy it into the next slot in the
+ * segment's section index.
+ */
+
+ sect_reorder_index = sect_start;
+ for (i = legacy_start; i < legacy_end; ++i) {
+ section_name = kxld_array_get_item(section_order, i);
+ sect = NULL;
+
+ for (j = 0; j < nsects; ++j) {
+ sect = reorder_buffer[j];
+ if (!sect) continue;
+
+ if (streq_safe(section_name->sectname, sect->sectname,
+ sizeof(section_name->sectname)))
+ {
+ break;
+ }
+
+ sect = NULL;
+ }
+
+ if (sect) {
+ (void) reorder_section(&seg->sects, §_reorder_index,
+ reorder_buffer, j);
+ }
+ }
+
+ /* If any sections remain in the reorder buffer, they are not specified
+ * in the section_order array, so append them to the section index in
+ * in the order they are found.
+ */
+
+ for (i = 0; i < nsects; ++i) {
+ if (!reorder_buffer[i]) continue;
+ reorder_section(&seg->sects, §_reorder_index, reorder_buffer, i);
+ }
+ }
+
+ rval = KERN_SUCCESS;
+
+finish:
+
+ if (reorder_buffer) {
+ kxld_free(reorder_buffer, seg->sects.nitems * sizeof(*reorder_buffer));
+ reorder_buffer = NULL;
+ }
+
+ return rval;
+}
+
+/*******************************************************************************
+*******************************************************************************/
+static void
+reorder_section(KXLDArray *sects, u_int *sect_reorder_index,
+ KXLDSect **reorder_buffer, u_int reorder_buffer_index)
+{
+ KXLDSect **tmp = NULL;
+
+ tmp = kxld_array_get_item(sects, *sect_reorder_index);
+
+ *tmp = reorder_buffer[reorder_buffer_index];
+ reorder_buffer[reorder_buffer_index]->sectnum = *sect_reorder_index;
+ reorder_buffer[reorder_buffer_index] = NULL;
+
+ ++(*sect_reorder_index);
+}
+#endif /* KXLD_USER_OR_OBJECT */
+
+/*******************************************************************************
+*******************************************************************************/
+void
+kxld_seg_clear(KXLDSeg *seg)
+{
+ check(seg);
+
+ bzero(seg->segname, sizeof(seg->segname));
+ seg->base_addr = 0;
+ seg->link_addr = 0;
+ seg->vmsize = 0;
+ seg->flags = 0;
+ seg->maxprot = 0;
+ seg->initprot = 0;
+
+ /* Don't clear the individual sections here because kxld_kext.c will take
+ * care of that.
+ */
+ kxld_array_clear(&seg->sects);
+}
+
+/*******************************************************************************
+*******************************************************************************/
+void
+kxld_seg_deinit(KXLDSeg *seg)
+{
+ check(seg);
+
+ kxld_array_deinit(&seg->sects);
+ bzero(seg, sizeof(*seg));
+}
+
+/*******************************************************************************
+*******************************************************************************/
+kxld_size_t
+kxld_seg_get_vmsize(const KXLDSeg *seg)
+{
+ check(seg);
+
+ return seg->vmsize;
+}
+
+/*******************************************************************************
+*******************************************************************************/
+u_long
+kxld_seg_get_macho_header_size(const KXLDSeg *seg, boolean_t is_32_bit)
+{
+ u_long size = 0;
+
+ check(seg);
+
+ if (is_32_bit) {
+ size += sizeof(struct segment_command);
+ } else {
+ size += sizeof(struct segment_command_64);
+ }
+ size += seg->sects.nitems * kxld_sect_get_macho_header_size(is_32_bit);
+
+ return size;
+}
+
+/*******************************************************************************
+*******************************************************************************/
+u_long
+kxld_seg_get_macho_data_size(const KXLDSeg *seg)
+{
+ u_long size = 0;
+ u_int i = 0;
+ KXLDSect *sect = NULL;
+
+ check(seg);
+
+ for (i = 0; i < seg->sects.nitems; ++i) {
+ sect = get_sect_by_index(seg, i);
+ size = (u_long) kxld_sect_align_address(sect, size);
+ size += kxld_sect_get_macho_data_size(sect);
+ }
+
+ return round_page(size);
+}
+
+/*******************************************************************************
+*******************************************************************************/
+static KXLDSect *
+get_sect_by_index(const KXLDSeg *seg, u_int idx)
+{
+ check(seg);
+
+ return *(KXLDSect **) kxld_array_get_item(&seg->sects, idx);
+}
+
+/*******************************************************************************
+*******************************************************************************/
+kern_return_t
+kxld_seg_export_macho_to_file_buffer(const KXLDSeg *seg, u_char *buf,
+ u_long *header_offset, u_long header_size,
+ u_long *data_offset, u_long data_size,
+ boolean_t is_32_bit)
+{
+ kern_return_t rval = KERN_FAILURE;
+ KXLDSect *sect = NULL;
+ u_long base_data_offset = *data_offset;
+ u_int i = 0;
+ struct segment_command *hdr32 =
+ (struct segment_command *) (buf + *header_offset);
+ struct segment_command_64 *hdr64 =
+ (struct segment_command_64 *) (buf + *header_offset);
+
+ check(seg);
+ check(buf);
+ check(header_offset);
+ check(data_offset);
+
+ /* Write out the header */
+
+ KXLD_3264_FUNC(is_32_bit, rval,
+ seg_export_macho_header_32, seg_export_macho_header_64,
+ seg, buf, header_offset, header_size, *data_offset);
+ require_noerr(rval, finish);
+
+ /* Write out each section */
+
+ for (i = 0; i < seg->sects.nitems; ++i) {
+ sect = get_sect_by_index(seg, i);
+
+ rval = kxld_sect_export_macho_to_file_buffer(sect, buf, header_offset,
+ header_size, data_offset, data_size, is_32_bit);
+ require_noerr(rval, finish);
+ }
+
+ /* Update the filesize */
+
+ if (is_32_bit) {
+ hdr32->filesize = (uint32_t) (*data_offset - base_data_offset);
+ } else {
+ hdr64->filesize = (uint64_t) (*data_offset - base_data_offset);
+ }
+
+ *data_offset = round_page(*data_offset);
+
+ rval = KERN_SUCCESS;
+
+finish:
+ return rval;
+
+}
+
+/*******************************************************************************
+*******************************************************************************/
+kern_return_t
+kxld_seg_export_macho_to_vm(const KXLDSeg *seg, u_char *buf,
+ u_long *header_offset, u_long header_size,
+ u_long data_size, kxld_addr_t file_link_addr,
+ boolean_t is_32_bit)
+{
+ kern_return_t rval = KERN_FAILURE;
+ KXLDSect *sect = NULL;
+ u_long data_offset = (u_long) (seg->link_addr - file_link_addr);
+ u_int i = 0;
+
+ check(seg);
+ check(buf);
+ check(header_offset);
+
+ /* Write out the header */
+
+ KXLD_3264_FUNC(is_32_bit, rval,
+ seg_export_macho_header_32, seg_export_macho_header_64,
+ seg, buf, header_offset, header_size, data_offset);
+ require_noerr(rval, finish);
+
+ /* Write out each section */
+
+ for (i = 0; i < seg->sects.nitems; ++i) {
+ sect = get_sect_by_index(seg, i);
+
+ rval = kxld_sect_export_macho_to_vm(sect, buf, header_offset,
+ header_size, file_link_addr, data_size, is_32_bit);
+ require_noerr(rval, finish);
+ }
+
+ rval = KERN_SUCCESS;
+
+finish:
+ return rval;
+}
+
+#if KXLD_USER_OR_ILP32
+/*******************************************************************************
+*******************************************************************************/
+static kern_return_t
+seg_export_macho_header_32(const KXLDSeg *seg, u_char *buf,
+ u_long *header_offset, u_long header_size, u_long data_offset)
+{
+ kern_return_t rval = KERN_FAILURE;
+ struct segment_command *seghdr = NULL;
+
+ check(seg);
+ check(buf);
+ check(header_offset);
+
+ require_action(sizeof(*seghdr) <= header_size - *header_offset, finish,
+ rval=KERN_FAILURE);
+ seghdr = (struct segment_command *) (buf + *header_offset);
+ *header_offset += sizeof(*seghdr);
+
+ seghdr->cmd = LC_SEGMENT;
+ seghdr->cmdsize = (uint32_t) sizeof(*seghdr);
+ seghdr->cmdsize +=
+ (uint32_t) (seg->sects.nitems * kxld_sect_get_macho_header_size(TRUE));
+ strlcpy(seghdr->segname, seg->segname, sizeof(seghdr->segname));
+ seghdr->vmaddr = (uint32_t) seg->link_addr;
+ seghdr->vmsize = (uint32_t) seg->vmsize;
+ seghdr->fileoff = (uint32_t) data_offset;
+ seghdr->filesize = (uint32_t) seg->vmsize;
+ seghdr->maxprot = seg->maxprot;
+ seghdr->initprot = seg->initprot;
+ seghdr->nsects = seg->sects.nitems;
+ seghdr->flags = 0;
+
+ rval = KERN_SUCCESS;
+
+finish:
+ return rval;
+}
+#endif /* KXLD_USER_OR_ILP32 */
+
+#if KXLD_USER_OR_LP64
+/*******************************************************************************
+*******************************************************************************/
+static kern_return_t
+seg_export_macho_header_64(const KXLDSeg *seg, u_char *buf,
+ u_long *header_offset, u_long header_size, u_long data_offset)
+{
+ kern_return_t rval = KERN_FAILURE;
+ struct segment_command_64 *seghdr = NULL;
+
+ check(seg);
+ check(buf);
+ check(header_offset);
+
+ require_action(sizeof(*seghdr) <= header_size - *header_offset, finish,
+ rval=KERN_FAILURE);
+ seghdr = (struct segment_command_64 *) (buf + *header_offset);
+ *header_offset += sizeof(*seghdr);
+
+ seghdr->cmd = LC_SEGMENT_64;
+ seghdr->cmdsize = (uint32_t) sizeof(*seghdr);
+ seghdr->cmdsize +=
+ (uint32_t) (seg->sects.nitems * kxld_sect_get_macho_header_size(FALSE));
+ strlcpy(seghdr->segname, seg->segname, sizeof(seghdr->segname));
+ seghdr->vmaddr = (uint64_t) seg->link_addr;
+ seghdr->vmsize = (uint64_t) seg->vmsize;
+ seghdr->fileoff = (uint64_t) data_offset;
+ seghdr->filesize = (uint64_t) seg->vmsize;
+ seghdr->maxprot = seg->maxprot;
+ seghdr->initprot = seg->initprot;
+ seghdr->nsects = seg->sects.nitems;
+ seghdr->flags = 0;
+
+ rval = KERN_SUCCESS;
+
+finish:
+ return rval;
+}
+#endif /* KXLD_USER_OR_LP64 */
+
+/*******************************************************************************
+*******************************************************************************/
+kern_return_t
+kxld_seg_add_section(KXLDSeg *seg, KXLDSect *sect)
+{
+ kern_return_t rval = KERN_FAILURE;
+ KXLDSect **sectp = NULL;
+ u_int i;
+
+ check(seg);
+ check(sect);
+ require_action(streq_safe(seg->segname, sect->segname, sizeof(seg->segname)),
+ finish, rval=KERN_FAILURE);
+
+ /* Add the section into the section index */
+
+ for (i = 0; i < seg->sects.nitems; ++i) {
+ sectp = kxld_array_get_item(&seg->sects, i);
+ if (NULL == *sectp) {
+ *sectp = sect;
+ break;
+ }
+ }
+ require_action(i < seg->sects.nitems, finish, rval=KERN_FAILURE);
+
+ rval = KERN_SUCCESS;
+
+finish:
+
+ return rval;
+}
+
+/*******************************************************************************
+*******************************************************************************/
+kern_return_t
+kxld_seg_finish_init(KXLDSeg *seg)
+{
+ kern_return_t rval = KERN_FAILURE;
+ u_int i = 0;
+ KXLDSect *sect = NULL;
+ kxld_addr_t maxaddr = 0;
+ kxld_size_t maxsize = 0;
+
+ if (seg->sects.nitems) {
+ for (i = 0; i < seg->sects.nitems; ++i) {
+ sect = get_sect_by_index(seg, i);
+ require_action(sect, finish, rval=KERN_FAILURE);
+ if (sect->base_addr > maxaddr) {
+ maxaddr = sect->base_addr;
+ maxsize = sect->size;
+ }
+ }
+
+ /* XXX Cross architecture linking will fail if the page size ever differs
+ * from 4096. (As of this writing, we're fine on ppc, i386, x86_64, and
+ * arm.)
+ */
+ seg->vmsize = round_page(maxaddr + maxsize - seg->base_addr);
+ }
+
+ rval = KERN_SUCCESS;
+
+finish:
+ return rval;
+}
+
+/*******************************************************************************
+*******************************************************************************/
+void
+kxld_seg_set_vm_protections(KXLDSeg *seg, boolean_t strict_protections)
+{
+ if (strict_protections) {
+ if (streq_safe(seg->segname, SEG_TEXT, sizeof(SEG_TEXT))) {
+ seg->initprot = TEXT_SEG_PROT;
+ seg->maxprot = VM_PROT_ALL;
+ } else {
+ seg->initprot = DATA_SEG_PROT;
+ seg->maxprot = DATA_SEG_PROT;
+ }
+ } else {
+ seg->initprot = VM_PROT_ALL;
+ seg->maxprot = VM_PROT_ALL;
+ }
+}
+
+/*******************************************************************************
+*******************************************************************************/
+void
+kxld_seg_relocate(KXLDSeg *seg, kxld_addr_t link_addr)
+{
+ KXLDSect *sect = NULL;
+ u_int i = 0;
+
+ seg->link_addr += link_addr;
+ for (i = 0; i < seg->sects.nitems; ++i) {
+ sect = get_sect_by_index(seg, i);
+ kxld_sect_relocate(sect, link_addr);
+ }
+}
+