* 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
* 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,
* 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 "kxld_symtab.h"
#include "kxld_util.h"
-static kern_return_t export_macho(const KXLDSect *sect, u_char *buf, u_long offset,
+static kern_return_t export_macho(const KXLDSect *sect, u_char *buf, u_long offset,
u_long bufsize);
#if KXLD_USER_OR_ILP32
-static kern_return_t sect_export_macho_header_32(const KXLDSect *sect, u_char *buf,
+static kern_return_t sect_export_macho_header_32(const KXLDSect *sect, 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 sect_export_macho_header_64(const KXLDSect *sect, u_char *buf,
+static kern_return_t sect_export_macho_header_64(const KXLDSect *sect, u_char *buf,
u_long *header_offset, u_long header_size, u_long data_offset);
#endif
extern boolean_t isSplitKext;
kxld_sect_init_from_macho_32(KXLDSect *sect, u_char *macho, u_long *sect_offset,
u_int sectnum, const KXLDRelocator *relocator)
{
- kern_return_t rval = KERN_FAILURE;
- struct section *src = (struct section *) ((void *) (macho + *sect_offset));
- struct relocation_info *relocs = NULL;
-
- check(sect);
- check(macho);
- check(src);
-
- strlcpy(sect->segname, src->segname, sizeof(sect->segname));
- strlcpy(sect->sectname, src->sectname, sizeof(sect->sectname));
- sect->base_addr = src->addr;
- sect->link_addr = src->addr;
- sect->size = src->size;
- sect->sectnum = sectnum;
- sect->flags = src->flags;
- sect->align = src->align;
- sect->reserved1 = src->reserved1;
- sect->reserved2 = src->reserved2;
-
- if (src->offset) {
- sect->data = macho + src->offset;
- } else {
- sect->data = NULL;
- }
-
- relocs = (struct relocation_info *) ((void *) (macho + src->reloff));
-
- rval = kxld_reloc_create_macho(§->relocs, relocator,
- relocs, src->nreloc);
- require_noerr(rval, finish);
-
- *sect_offset += sizeof(*src);
- rval = KERN_SUCCESS;
+ kern_return_t rval = KERN_FAILURE;
+ struct section *src = (struct section *) ((void *) (macho + *sect_offset));
+ struct relocation_info *relocs = NULL;
+
+ check(sect);
+ check(macho);
+ check(src);
+
+ strlcpy(sect->segname, src->segname, sizeof(sect->segname));
+ strlcpy(sect->sectname, src->sectname, sizeof(sect->sectname));
+ sect->base_addr = src->addr;
+ sect->link_addr = src->addr;
+ sect->size = src->size;
+ sect->sectnum = sectnum;
+ sect->flags = src->flags;
+ sect->align = src->align;
+ sect->reserved1 = src->reserved1;
+ sect->reserved2 = src->reserved2;
+
+ if (src->offset) {
+ sect->data = macho + src->offset;
+ } else {
+ sect->data = NULL;
+ }
+
+ relocs = (struct relocation_info *) ((void *) (macho + src->reloff));
+
+ rval = kxld_reloc_create_macho(§->relocs, relocator,
+ relocs, src->nreloc);
+ require_noerr(rval, finish);
+
+ *sect_offset += sizeof(*src);
+ rval = KERN_SUCCESS;
finish:
- if (rval) kxld_sect_deinit(sect);
+ if (rval) {
+ kxld_sect_deinit(sect);
+ }
- return rval;
+ return rval;
}
#endif /* KXLD_USER_OR_ILP32 */
kxld_sect_init_from_macho_64(KXLDSect *sect, u_char *macho, u_long *sect_offset,
u_int sectnum, const KXLDRelocator *relocator)
{
- kern_return_t rval = KERN_FAILURE;
- struct section_64 *src = (struct section_64 *) ((void *) (macho + *sect_offset));
- struct relocation_info *relocs = NULL;
-
- check(sect);
- check(macho);
- check(src);
-
- strlcpy(sect->segname, src->segname, sizeof(sect->segname));
- strlcpy(sect->sectname, src->sectname, sizeof(sect->sectname));
- sect->base_addr = src->addr;
- sect->link_addr = src->addr;
- sect->size = src->size;
- sect->sectnum = sectnum;
- sect->flags = src->flags;
- sect->align = src->align;
- sect->reserved1 = src->reserved1;
- sect->reserved2 = src->reserved2;
-
- if (src->offset) {
- sect->data = macho + src->offset;
- } else {
- sect->data = NULL;
- }
-
- relocs = (struct relocation_info *) ((void *) (macho + src->reloff));
-
- rval = kxld_reloc_create_macho(§->relocs, relocator,
- relocs, src->nreloc);
- require_noerr(rval, finish);
-
- *sect_offset += sizeof(*src);
- rval = KERN_SUCCESS;
+ kern_return_t rval = KERN_FAILURE;
+ struct section_64 *src = (struct section_64 *) ((void *) (macho + *sect_offset));
+ struct relocation_info *relocs = NULL;
+
+ check(sect);
+ check(macho);
+ check(src);
+
+ strlcpy(sect->segname, src->segname, sizeof(sect->segname));
+ strlcpy(sect->sectname, src->sectname, sizeof(sect->sectname));
+ sect->base_addr = src->addr;
+ sect->link_addr = src->addr;
+ sect->size = src->size;
+ sect->sectnum = sectnum;
+ sect->flags = src->flags;
+ sect->align = src->align;
+ sect->reserved1 = src->reserved1;
+ sect->reserved2 = src->reserved2;
+
+ if (src->offset) {
+ sect->data = macho + src->offset;
+ } else {
+ sect->data = NULL;
+ }
+
+ relocs = (struct relocation_info *) ((void *) (macho + src->reloff));
+
+ rval = kxld_reloc_create_macho(§->relocs, relocator,
+ relocs, src->nreloc);
+ require_noerr(rval, finish);
+
+ *sect_offset += sizeof(*src);
+ rval = KERN_SUCCESS;
finish:
- if (rval) kxld_sect_deinit(sect);
+ if (rval) {
+ kxld_sect_deinit(sect);
+ }
- return rval;
+ return rval;
}
#endif /* KXLD_USER_OR_LP64 */
kern_return_t
kxld_sect_init_got(KXLDSect *sect, u_int ngots)
{
- kern_return_t rval = KERN_FAILURE;
+ kern_return_t rval = KERN_FAILURE;
- check(sect);
+ check(sect);
- strlcpy(sect->segname, KXLD_SEG_GOT, sizeof(sect->segname));
- strlcpy(sect->sectname, KXLD_SECT_GOT, sizeof(sect->sectname));
- sect->base_addr = 0;
- sect->link_addr = 0;
- sect->flags = 0;
- sect->align = 4;
- sect->reserved1 = 0;
- sect->reserved2 = 0;
+ strlcpy(sect->segname, KXLD_SEG_GOT, sizeof(sect->segname));
+ strlcpy(sect->sectname, KXLD_SECT_GOT, sizeof(sect->sectname));
+ sect->base_addr = 0;
+ sect->link_addr = 0;
+ sect->flags = 0;
+ sect->align = 4;
+ sect->reserved1 = 0;
+ sect->reserved2 = 0;
- sect->size = ngots * sizeof(kxld_addr_t);
- sect->data = kxld_alloc((u_long) sect->size);
- require_action(sect->data, finish, rval=KERN_RESOURCE_SHORTAGE);
+ sect->size = ngots * sizeof(kxld_addr_t);
+ sect->data = kxld_alloc((u_long) sect->size);
+ require_action(sect->data, finish, rval = KERN_RESOURCE_SHORTAGE);
- sect->allocated = TRUE;
+ sect->allocated = TRUE;
- rval = KERN_SUCCESS;
+ rval = KERN_SUCCESS;
finish:
- return rval;
+ return rval;
}
#endif /* KXLD_USER_OR_GOT */
/*******************************************************************************
*******************************************************************************/
void
-kxld_sect_init_zerofill(KXLDSect *sect, const char *segname,
+kxld_sect_init_zerofill(KXLDSect *sect, const char *segname,
const char *sectname, kxld_size_t size, u_int align)
{
- check(sect);
- check(segname);
- check(sectname);
-
- strlcpy(sect->segname, segname, sizeof(sect->segname));
- strlcpy(sect->sectname, sectname, sizeof(sect->sectname));
- sect->size = size;
- sect->align = align;
- sect->base_addr = 0;
- sect->link_addr = 0;
- sect->flags = S_ZEROFILL;
+ check(sect);
+ check(segname);
+ check(sectname);
+
+ strlcpy(sect->segname, segname, sizeof(sect->segname));
+ strlcpy(sect->sectname, sectname, sizeof(sect->sectname));
+ sect->size = size;
+ sect->align = align;
+ sect->base_addr = 0;
+ sect->link_addr = 0;
+ sect->flags = S_ZEROFILL;
}
#endif /* KXLD_USER_OR_COMMON */
void
kxld_sect_clear(KXLDSect *sect)
{
- check(sect);
-
- if (sect->allocated) {
- kxld_free(sect->data, (u_long) sect->size);
- sect->allocated = FALSE;
- }
-
- bzero(sect->sectname, sizeof(sect->sectname));
- bzero(sect->segname, sizeof(sect->segname));
- sect->data = NULL;
- sect->base_addr = 0;
- sect->link_addr = 0;
- sect->size = 0;
- sect->flags = 0;
- sect->align = 0;
- sect->reserved1 = 0;
- sect->reserved2 = 0;
- kxld_array_clear(§->relocs);
+ check(sect);
+
+ if (sect->allocated) {
+ kxld_free(sect->data, (u_long) sect->size);
+ sect->allocated = FALSE;
+ }
+
+ bzero(sect->sectname, sizeof(sect->sectname));
+ bzero(sect->segname, sizeof(sect->segname));
+ sect->data = NULL;
+ sect->base_addr = 0;
+ sect->link_addr = 0;
+ sect->size = 0;
+ sect->flags = 0;
+ sect->align = 0;
+ sect->reserved1 = 0;
+ sect->reserved2 = 0;
+ kxld_array_clear(§->relocs);
}
/*******************************************************************************
void
kxld_sect_deinit(KXLDSect *sect)
{
- check(sect);
+ check(sect);
- if (streq_safe(sect->sectname, KXLD_SECT_GOT, sizeof(KXLD_SECT_GOT))) {
- kxld_free(sect->data, (u_long) sect->size);
- }
+ if (streq_safe(sect->sectname, KXLD_SECT_GOT, sizeof(KXLD_SECT_GOT))) {
+ kxld_free(sect->data, (u_long) sect->size);
+ }
- kxld_array_deinit(§->relocs);
- bzero(sect, sizeof(*sect));
+ kxld_array_deinit(§->relocs);
+ bzero(sect, sizeof(*sect));
}
/*******************************************************************************
*******************************************************************************/
-u_int
+u_int
kxld_sect_get_num_relocs(const KXLDSect *sect)
{
- check(sect);
+ check(sect);
- return sect->relocs.nitems;
+ return sect->relocs.nitems;
}
/*******************************************************************************
u_long
kxld_sect_get_macho_header_size(boolean_t is_32_bit)
{
- if (is_32_bit) {
- return sizeof(struct section);
- } else {
- return sizeof(struct section_64);
- }
+ if (is_32_bit) {
+ return sizeof(struct section);
+ } else {
+ return sizeof(struct section_64);
+ }
}
/*******************************************************************************
u_long
kxld_sect_get_macho_data_size(const KXLDSect *sect)
{
- u_long size = 0;
+ u_long size = 0;
- check(sect);
+ check(sect);
- if (sect->data) {
- size = (u_long) sect->size;
- }
+ if (sect->data) {
+ size = (u_long) sect->size;
+ }
- return size;
+ return size;
}
#if KXLD_USER_OR_GOT
kxld_sect_get_ngots(const KXLDSect *sect, const KXLDRelocator *relocator,
const KXLDSymtab *symtab)
{
- const KXLDReloc *reloc = NULL;
- KXLDSym *sym = NULL;
- u_int ngots = 0;
- u_int i = 0;
-
- for (i = 0; i < sect->relocs.nitems; ++i) {
- reloc = kxld_array_get_item(§->relocs, i);
-
- if (relocator->reloc_has_got(reloc->reloc_type)) {
- /* @TODO This assumes 64-bit symbols (which is valid at the
- * moment since only x86_64 has a GOT)
- */
- sym = kxld_reloc_get_symbol(relocator, reloc, sect->data, symtab);
- if (!kxld_sym_is_got(sym)) {
- kxld_sym_set_got(sym);
- ++ngots;
- }
- }
- }
-
- return ngots;
+ const KXLDReloc *reloc = NULL;
+ KXLDSym *sym = NULL;
+ u_int ngots = 0;
+ u_int i = 0;
+
+ for (i = 0; i < sect->relocs.nitems; ++i) {
+ reloc = kxld_array_get_item(§->relocs, i);
+
+ if (relocator->reloc_has_got(reloc->reloc_type)) {
+ /* @TODO This assumes 64-bit symbols (which is valid at the
+ * moment since only x86_64 has a GOT)
+ */
+ sym = kxld_reloc_get_symbol(relocator, reloc, sect->data, symtab);
+ if (!kxld_sym_is_got(sym)) {
+ kxld_sym_set_got(sym);
+ ++ngots;
+ }
+ }
+ }
+
+ return ngots;
}
#endif /* KXLD_USER_OR_GOT */
/*******************************************************************************
-* Each section must be aligned at a certain power of two. To figure out that
-* alignment, we mask for the low bits that may need to be adjusted. If they are
-* non zero, we then subtract them from the target alignment to find the offset,
+* Each section must be aligned at a certain power of two. To figure out that
+* alignment, we mask for the low bits that may need to be adjusted. If they are
+* non zero, we then subtract them from the target alignment to find the offset,
* and then add that offset to the link address.
*******************************************************************************/
kxld_addr_t
kxld_sect_align_address(const KXLDSect *sect, kxld_addr_t address)
{
- return kxld_align_address(address, sect->align);
+ return kxld_align_address(address, sect->align);
}
/*******************************************************************************
*******************************************************************************/
kern_return_t
kxld_sect_export_macho_to_file_buffer(const KXLDSect *sect, u_char *buf,
- u_long *header_offset, u_long header_size, u_long *data_offset,
+ u_long *header_offset, u_long header_size, u_long *data_offset,
u_long data_size, boolean_t is_32_bit __unused)
{
- kern_return_t rval = KERN_FAILURE;
-
- check(sect);
- check(buf);
- check(header_offset);
- check(data_offset);
-
- /* If there is no data to export, we only need to write the header. We
- * make it a separate call so that we don't modify data_offset.
- */
- if (!sect->data) {
- KXLD_3264_FUNC(is_32_bit, rval,
- sect_export_macho_header_32, sect_export_macho_header_64,
- sect, buf, header_offset, header_size, /* data_offset */ 0);
- require_noerr(rval, finish);
- } else {
- *data_offset = (u_long) kxld_sect_align_address(sect, *data_offset);
-
- KXLD_3264_FUNC(is_32_bit, rval,
- sect_export_macho_header_32, sect_export_macho_header_64,
- sect, buf, header_offset, header_size, *data_offset);
- require_noerr(rval, finish);
-
- rval = export_macho(sect, buf, *data_offset, data_size);
- require_noerr(rval, finish);
-
- *data_offset += (u_long) sect->size;
- }
- rval = KERN_SUCCESS;
+ kern_return_t rval = KERN_FAILURE;
+
+ check(sect);
+ check(buf);
+ check(header_offset);
+ check(data_offset);
+
+ /* If there is no data to export, we only need to write the header. We
+ * make it a separate call so that we don't modify data_offset.
+ */
+ if (!sect->data) {
+ KXLD_3264_FUNC(is_32_bit, rval,
+ sect_export_macho_header_32, sect_export_macho_header_64,
+ sect, buf, header_offset, header_size, /* data_offset */ 0);
+ require_noerr(rval, finish);
+ } else {
+ *data_offset = (u_long) kxld_sect_align_address(sect, *data_offset);
+
+ KXLD_3264_FUNC(is_32_bit, rval,
+ sect_export_macho_header_32, sect_export_macho_header_64,
+ sect, buf, header_offset, header_size, *data_offset);
+ require_noerr(rval, finish);
+
+ rval = export_macho(sect, buf, *data_offset, data_size);
+ require_noerr(rval, finish);
+
+ *data_offset += (u_long) sect->size;
+ }
+ rval = KERN_SUCCESS;
finish:
- return rval;
+ return rval;
}
/*******************************************************************************
- *******************************************************************************/
+*******************************************************************************/
kern_return_t
kxld_sect_export_macho_to_vm(const KXLDSect *sect,
- u_char *buf,
- u_long *header_offset,
- u_long header_size,
- kxld_addr_t link_addr,
- u_long data_size,
- boolean_t is_32_bit __unused)
+ u_char *buf,
+ u_long *header_offset,
+ u_long header_size,
+ kxld_addr_t link_addr,
+ u_long data_size,
+ boolean_t is_32_bit __unused)
{
- kern_return_t rval = KERN_FAILURE;
- u_long data_offset;
-
- check(sect);
- check(buf);
- check(header_offset);
-
- data_offset = (u_long) (sect->link_addr - link_addr);
-
- KXLD_3264_FUNC(is_32_bit, rval,
- sect_export_macho_header_32, sect_export_macho_header_64,
- sect, buf, header_offset, header_size, data_offset);
- require_noerr(rval, finish);
-
- rval = export_macho(sect, buf, data_offset, data_size);
- require_noerr(rval, finish);
-
- rval = KERN_SUCCESS;
-
+ kern_return_t rval = KERN_FAILURE;
+ u_long data_offset;
+
+ check(sect);
+ check(buf);
+ check(header_offset);
+
+ data_offset = (u_long) (sect->link_addr - link_addr);
+
+ KXLD_3264_FUNC(is_32_bit, rval,
+ sect_export_macho_header_32, sect_export_macho_header_64,
+ sect, buf, header_offset, header_size, data_offset);
+ require_noerr(rval, finish);
+
+ rval = export_macho(sect, buf, data_offset, data_size);
+ require_noerr(rval, finish);
+
+ rval = KERN_SUCCESS;
+
finish:
- return rval;
+ return rval;
}
/*******************************************************************************
static kern_return_t
export_macho(const KXLDSect *sect, u_char *buf, u_long offset, u_long bufsize)
{
- kern_return_t rval = KERN_FAILURE;
-
- check(sect);
- check(buf);
-
- if (!sect->data) {
- rval = KERN_SUCCESS;
- goto finish;
- }
-
- if (!isSplitKext) {
- /* Verify that the section is properly aligned */
- if (kxld_sect_align_address(sect, offset) != offset) {
- kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
- "Alignment error: %llu != %lu for %s %s <%s>",
- kxld_sect_align_address(sect, offset), offset,
- sect->segname, sect->sectname, __func__);
- goto finish;
- }
- }
-
- /* Verify that we have enough space to copy */
- if (buf + offset + sect->size > buf + bufsize) {
- kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
- "Overflow: offset %lu + sect->size %llu > bufsize %lu for %s %s",
- offset, sect->size, bufsize,
- sect->segname, sect->sectname);
- goto finish;
- }
-
- /* Copy section data */
- switch (sect->flags & SECTION_TYPE) {
- case S_NON_LAZY_SYMBOL_POINTERS:
- case S_MOD_INIT_FUNC_POINTERS:
- case S_MOD_TERM_FUNC_POINTERS:
- case S_REGULAR:
- case S_CSTRING_LITERALS:
- case S_4BYTE_LITERALS:
- case S_8BYTE_LITERALS:
- case S_LITERAL_POINTERS:
- case S_COALESCED:
- case S_16BYTE_LITERALS:
- case S_SYMBOL_STUBS:
+ kern_return_t rval = KERN_FAILURE;
+
+ check(sect);
+ check(buf);
+
+ if (!sect->data) {
+ rval = KERN_SUCCESS;
+ goto finish;
+ }
+
+ if (!isSplitKext) {
+ /* Verify that the section is properly aligned */
+ if (kxld_sect_align_address(sect, offset) != offset) {
+ kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
+ "Alignment error: %llu != %lu for %s %s <%s>",
+ kxld_sect_align_address(sect, offset), offset,
+ sect->segname, sect->sectname, __func__);
+ goto finish;
+ }
+ }
+
+ /* Verify that we have enough space to copy */
+ if (buf + offset + sect->size > buf + bufsize) {
+ kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
+ "Overflow: offset %lu + sect->size %llu > bufsize %lu for %s %s",
+ offset, sect->size, bufsize,
+ sect->segname, sect->sectname);
+ goto finish;
+ }
+
+ /* Copy section data */
+ switch (sect->flags & SECTION_TYPE) {
+ case S_NON_LAZY_SYMBOL_POINTERS:
+ case S_MOD_INIT_FUNC_POINTERS:
+ case S_MOD_TERM_FUNC_POINTERS:
+ case S_REGULAR:
+ case S_CSTRING_LITERALS:
+ case S_4BYTE_LITERALS:
+ case S_8BYTE_LITERALS:
+ case S_LITERAL_POINTERS:
+ case S_COALESCED:
+ case S_16BYTE_LITERALS:
+ case S_SYMBOL_STUBS:
#if SPLIT_KEXTS_DEBUG
- kxld_log(kKxldLogLinking, kKxldLogErr,
- " sectname %s copy from %p (sect->data) for %llu bytes (sect->size) to %p (buf %p + offset %lu <%s>",
- sect->sectname[0] ? sect->sectname : "none",
- (void *) sect->data,
- sect->size,
- (void *) (buf + offset),
- (void *) buf,
- offset,
- __func__);
-
- kxld_log(kKxldLogLinking, kKxldLogErr,
- " %p >>> Start of %s section data (sect->size %llu) <%s>",
- (void *) (buf + offset),
- sect->sectname[0] ? sect->sectname : "none",
- sect->size,
- __func__);
- kxld_log(kKxldLogLinking, kKxldLogErr,
- " %p <<< End of %s section data <%s>",
- (void *) (buf + offset + sect->size),
- sect->sectname[0] ? sect->sectname : "none",
- __func__);
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ " sectname %s copy from %p (sect->data) for %llu bytes (sect->size) to %p (buf %p + offset %lu <%s>",
+ sect->sectname[0] ? sect->sectname : "none",
+ (void *) sect->data,
+ sect->size,
+ (void *) (buf + offset),
+ (void *) buf,
+ offset,
+ __func__);
+
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ " %p >>> Start of %s section data (sect->size %llu) <%s>",
+ (void *) (buf + offset),
+ sect->sectname[0] ? sect->sectname : "none",
+ sect->size,
+ __func__);
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ " %p <<< End of %s section data <%s>",
+ (void *) (buf + offset + sect->size),
+ sect->sectname[0] ? sect->sectname : "none",
+ __func__);
#endif
- memcpy(buf + offset, sect->data, (size_t)sect->size);
- break;
- case S_ZEROFILL: /* sect->data should be NULL, so we'll never get here */
- case S_LAZY_SYMBOL_POINTERS:
- case S_GB_ZEROFILL:
- case S_INTERPOSING:
- case S_DTRACE_DOF:
- default:
- rval = KERN_FAILURE;
- kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
- "Invalid section type: %u.", sect->flags & SECTION_TYPE);
- goto finish;
- }
-
- rval = KERN_SUCCESS;
+ memcpy(buf + offset, sect->data, (size_t)sect->size);
+ break;
+ case S_ZEROFILL: /* sect->data should be NULL, so we'll never get here */
+ case S_LAZY_SYMBOL_POINTERS:
+ case S_GB_ZEROFILL:
+ case S_INTERPOSING:
+ case S_DTRACE_DOF:
+ default:
+ rval = KERN_FAILURE;
+ kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
+ "Invalid section type: %u.", sect->flags & SECTION_TYPE);
+ goto finish;
+ }
+
+ rval = KERN_SUCCESS;
finish:
- return rval;
+ return rval;
}
#if KXLD_USER_OR_ILP32
/*******************************************************************************
*******************************************************************************/
static kern_return_t
-sect_export_macho_header_32(const KXLDSect *sect, u_char *buf,
+sect_export_macho_header_32(const KXLDSect *sect, u_char *buf,
u_long *header_offset, u_long header_size, u_long data_offset)
{
- kern_return_t rval = KERN_FAILURE;
- struct section *secthdr = NULL;
-
- check(sect);
- check(buf);
- check(header_offset);
-
- require_action(sizeof(*secthdr) <= header_size - *header_offset, finish,
- rval=KERN_FAILURE);
- secthdr = (struct section *) ((void *) (buf + *header_offset));
- *header_offset += sizeof(*secthdr);
-
- /* Initalize header */
-
- strlcpy(secthdr->sectname, sect->sectname, sizeof(secthdr->sectname));
- strlcpy(secthdr->segname, sect->segname, sizeof(secthdr->segname));
- secthdr->addr = (uint32_t) sect->link_addr;
- secthdr->size = (uint32_t) sect->size;
- secthdr->offset = (uint32_t) ((sect->data) ? data_offset : 0);
- secthdr->align = sect->align;
- secthdr->reloff = 0;
- secthdr->nreloc = 0;
- secthdr->flags = sect->flags;
- secthdr->reserved1 = sect->reserved1;
- secthdr->reserved2 = sect->reserved2;
+ kern_return_t rval = KERN_FAILURE;
+ struct section *secthdr = NULL;
+
+ check(sect);
+ check(buf);
+ check(header_offset);
+
+ require_action(sizeof(*secthdr) <= header_size - *header_offset, finish,
+ rval = KERN_FAILURE);
+ secthdr = (struct section *) ((void *) (buf + *header_offset));
+ *header_offset += sizeof(*secthdr);
+
+ /* Initalize header */
+
+ strlcpy(secthdr->sectname, sect->sectname, sizeof(secthdr->sectname));
+ strlcpy(secthdr->segname, sect->segname, sizeof(secthdr->segname));
+ secthdr->addr = (uint32_t) sect->link_addr;
+ secthdr->size = (uint32_t) sect->size;
+ secthdr->offset = (uint32_t) ((sect->data) ? data_offset : 0);
+ secthdr->align = sect->align;
+ secthdr->reloff = 0;
+ secthdr->nreloc = 0;
+ secthdr->flags = sect->flags;
+ secthdr->reserved1 = sect->reserved1;
+ secthdr->reserved2 = sect->reserved2;
#if SPLIT_KEXTS_DEBUG
- {
- kxld_log(kKxldLogLinking, kKxldLogErr,
- "sectname %s secthdr: %p addr %p size %02X %u offset %02X %u <%s>",
- sect->sectname[0] ? sect->sectname : "none",
- (void *) secthdr,
- (void *) ((uint64_t)secthdr->addr),
- secthdr->size,
- secthdr->size,
- secthdr->offset,
- secthdr->offset,
- __func__);
- }
+ {
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ "sectname %s secthdr: %p addr %p size %02X %u offset %02X %u <%s>",
+ sect->sectname[0] ? sect->sectname : "none",
+ (void *) secthdr,
+ (void *) ((uint64_t)secthdr->addr),
+ secthdr->size,
+ secthdr->size,
+ secthdr->offset,
+ secthdr->offset,
+ __func__);
+ }
#endif
- rval = KERN_SUCCESS;
+ rval = KERN_SUCCESS;
finish:
- return rval;
+ return rval;
}
#endif /* KXLD_USER_OR_ILP32 */
/*******************************************************************************
*******************************************************************************/
static kern_return_t
-sect_export_macho_header_64(const KXLDSect *sect, u_char *buf,
+sect_export_macho_header_64(const KXLDSect *sect, u_char *buf,
u_long *header_offset, u_long header_size, u_long data_offset)
{
- kern_return_t rval = KERN_FAILURE;
- struct section_64 *secthdr = NULL;
-
- check(sect);
- check(buf);
- check(header_offset);
-
-
- require_action(sizeof(*secthdr) <= header_size - *header_offset, finish,
- rval=KERN_FAILURE);
- secthdr = (struct section_64 *) ((void *) (buf + *header_offset));
- *header_offset += sizeof(*secthdr);
-
- /* Initalize header */
-
- strlcpy(secthdr->sectname, sect->sectname, sizeof(secthdr->sectname));
- strlcpy(secthdr->segname, sect->segname, sizeof(secthdr->segname));
- secthdr->addr = (uint64_t) sect->link_addr;
- secthdr->size = (uint64_t) sect->size;
- secthdr->offset = (uint32_t) ((sect->data) ? data_offset : 0);
- secthdr->align = sect->align;
- secthdr->reloff = 0;
- secthdr->nreloc = 0;
- secthdr->flags = sect->flags;
- secthdr->reserved1 = sect->reserved1;
- secthdr->reserved2 = sect->reserved2;
+ kern_return_t rval = KERN_FAILURE;
+ struct section_64 *secthdr = NULL;
+
+ check(sect);
+ check(buf);
+ check(header_offset);
+
+
+ require_action(sizeof(*secthdr) <= header_size - *header_offset, finish,
+ rval = KERN_FAILURE);
+ secthdr = (struct section_64 *) ((void *) (buf + *header_offset));
+ *header_offset += sizeof(*secthdr);
+
+ /* Initalize header */
+
+ strlcpy(secthdr->sectname, sect->sectname, sizeof(secthdr->sectname));
+ strlcpy(secthdr->segname, sect->segname, sizeof(secthdr->segname));
+ secthdr->addr = (uint64_t) sect->link_addr;
+ secthdr->size = (uint64_t) sect->size;
+ secthdr->offset = (uint32_t) ((sect->data) ? data_offset : 0);
+ secthdr->align = sect->align;
+ secthdr->reloff = 0;
+ secthdr->nreloc = 0;
+ secthdr->flags = sect->flags;
+ secthdr->reserved1 = sect->reserved1;
+ secthdr->reserved2 = sect->reserved2;
#if SPLIT_KEXTS_DEBUG
- kxld_log(kKxldLogLinking, kKxldLogErr,
- " %p >>> Start of %s secthdr (size %lu) <%s>",
- (void *) secthdr,
- sect->sectname[0] ? sect->sectname : "none",
- sizeof(*secthdr),
- __func__);
- kxld_log(kKxldLogLinking, kKxldLogErr,
- " %p <<< End of %s secthdr <%s>",
- (void *) ((u_char *)secthdr + sizeof(*secthdr)),
- sect->sectname[0] ? sect->sectname : "none",
- __func__);
- kxld_log(kKxldLogLinking, kKxldLogErr,
- " secthdr: addr %p size %llu offset %u sectname %s <%s>",
- (void *) secthdr->addr,
- secthdr->size,
- secthdr->offset,
- sect->sectname[0] ? sect->sectname : "none",
- __func__);
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ " %p >>> Start of %s secthdr (size %lu) <%s>",
+ (void *) secthdr,
+ sect->sectname[0] ? sect->sectname : "none",
+ sizeof(*secthdr),
+ __func__);
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ " %p <<< End of %s secthdr <%s>",
+ (void *) ((u_char *)secthdr + sizeof(*secthdr)),
+ sect->sectname[0] ? sect->sectname : "none",
+ __func__);
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ " secthdr: addr %p size %llu offset %u sectname %s <%s>",
+ (void *) secthdr->addr,
+ secthdr->size,
+ secthdr->offset,
+ sect->sectname[0] ? sect->sectname : "none",
+ __func__);
#endif
-
- rval = KERN_SUCCESS;
+
+ rval = KERN_SUCCESS;
finish:
- return rval;
+ return rval;
}
#endif /* KXLD_USER_OR_LP64 */
kxld_size_t
kxld_sect_grow(KXLDSect *sect, kxld_size_t nbytes, u_int align)
{
- kxld_size_t size = kxld_align_address(sect->size, align);
+ kxld_size_t size = kxld_align_address(sect->size, align);
- if (align > sect->align) sect->align = align;
- sect->size = size + nbytes;
+ if (align > sect->align) {
+ sect->align = align;
+ }
+ sect->size = size + nbytes;
- return size;
+ return size;
}
#endif /* KXLD_USER_OR_COMMON */
kxld_sect_relocate(KXLDSect *sect, kxld_addr_t link_addr)
{
#if SPLIT_KEXTS_DEBUG
- {
- kxld_log(kKxldLogLinking, kKxldLogErr,
- "%p >>> Start of %s section (sect->size %llu) <%s>",
- (void *) (kxld_sect_align_address(sect, sect->link_addr + link_addr)),
- sect->sectname[0] ? sect->sectname : "none",
- sect->size,
- __func__);
- kxld_log(kKxldLogLinking, kKxldLogErr,
- "%p <<< End of %s section <%s>",
- (void *) (kxld_sect_align_address(sect, sect->link_addr + link_addr) + sect->size),
- sect->sectname[0] ? sect->sectname : "none",
- __func__);
- }
+ {
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ "%p >>> Start of %s section (sect->size %llu) <%s>",
+ (void *) (kxld_sect_align_address(sect, sect->link_addr + link_addr)),
+ sect->sectname[0] ? sect->sectname : "none",
+ sect->size,
+ __func__);
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ "%p <<< End of %s section <%s>",
+ (void *) (kxld_sect_align_address(sect, sect->link_addr + link_addr) + sect->size),
+ sect->sectname[0] ? sect->sectname : "none",
+ __func__);
+ }
#endif
- sect->link_addr = kxld_sect_align_address(sect,
- sect->link_addr + link_addr);
+ sect->link_addr = kxld_sect_align_address(sect,
+ sect->link_addr + link_addr);
}
#if KXLD_USER_OR_GOT
/*******************************************************************************
*******************************************************************************/
kern_return_t
-kxld_sect_populate_got(KXLDSect *sect, KXLDSymtab *symtab,
+kxld_sect_populate_got(KXLDSect *sect, KXLDSymtab *symtab,
boolean_t swap __unused)
{
- kern_return_t rval = KERN_FAILURE;
- KXLDSymtabIterator iter;
- KXLDSym *sym = NULL;
- kxld_addr_t *entry = NULL;
- kxld_addr_t entry_addr = 0;
-
- check(sect);
- check(symtab);
- require(streq_safe(sect->segname, KXLD_SEG_GOT, sizeof(KXLD_SEG_GOT)),
- finish);
- require(streq_safe(sect->sectname, KXLD_SECT_GOT, sizeof(KXLD_SECT_GOT)),
- finish);
-
- kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_got, FALSE);
-
- entry = (kxld_addr_t *) sect->data;
- entry_addr = sect->link_addr;
- while ((sym = kxld_symtab_iterator_get_next(&iter))) {
- *entry = sym->link_addr;
- sym->got_addr = entry_addr;
+ kern_return_t rval = KERN_FAILURE;
+ KXLDSymtabIterator iter;
+ KXLDSym *sym = NULL;
+ kxld_addr_t *entry = NULL;
+ kxld_addr_t entry_addr = 0;
+
+ check(sect);
+ check(symtab);
+ require(streq_safe(sect->segname, KXLD_SEG_GOT, sizeof(KXLD_SEG_GOT)),
+ finish);
+ require(streq_safe(sect->sectname, KXLD_SECT_GOT, sizeof(KXLD_SECT_GOT)),
+ finish);
+
+ kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_got, FALSE);
+
+ entry = (kxld_addr_t *) sect->data;
+ entry_addr = sect->link_addr;
+ while ((sym = kxld_symtab_iterator_get_next(&iter))) {
+ *entry = sym->link_addr;
+ sym->got_addr = entry_addr;
#if !KERNEL
- if (swap) *entry = OSSwapInt64(*entry);
+ if (swap) {
+ *entry = OSSwapInt64(*entry);
+ }
#endif /* !KERNEL */
- ++entry;
- entry_addr += sizeof(*entry);
- }
+ ++entry;
+ entry_addr += sizeof(*entry);
+ }
- rval = KERN_SUCCESS;
+ rval = KERN_SUCCESS;
finish:
- return rval;
+ return rval;
}
#endif /* KXLD_USER_OR_GOT */
kern_return_t
kxld_sect_process_relocs(KXLDSect *sect, KXLDRelocator *relocator)
{
- kern_return_t rval = KERN_FAILURE;
- KXLDReloc *reloc = NULL;
- u_int i = 0;
+ kern_return_t rval = KERN_FAILURE;
+ KXLDReloc *reloc = NULL;
+ u_int i = 0;
- for (i = 0; i < sect->relocs.nitems; ++i) {
- reloc = kxld_array_get_item(§->relocs, i);
- rval = kxld_relocator_process_sect_reloc(relocator, reloc, sect);
- require_noerr(rval, finish);
- }
+ for (i = 0; i < sect->relocs.nitems; ++i) {
+ reloc = kxld_array_get_item(§->relocs, i);
+ rval = kxld_relocator_process_sect_reloc(relocator, reloc, sect);
+ require_noerr(rval, finish);
+ }
- rval = KERN_SUCCESS;
+ rval = KERN_SUCCESS;
finish:
- return rval;
+ return rval;
}
-