]> git.saurik.com Git - apple/xnu.git/blame - libkern/kxld/kxld_splitinfolc.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / libkern / kxld / kxld_splitinfolc.c
CommitLineData
39037602
A
1/*
2 * Copyright (c) 2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
39037602
A
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.
0a7de745 14 *
39037602
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
39037602
A
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.
0a7de745 25 *
39037602
A
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28#include <string.h>
29#include <mach-o/loader.h>
30#include <sys/types.h>
31
32#define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
33#include <AssertMacros.h>
34
35#include "kxld_util.h"
36#include "kxld_splitinfolc.h"
37
38/*******************************************************************************
0a7de745 39*******************************************************************************/
39037602
A
40void
41kxld_splitinfolc_init_from_macho(KXLDsplitinfolc *splitinfolc, struct linkedit_data_command *src)
42{
0a7de745
A
43 check(splitinfolc);
44 check(src);
39037602 45
0a7de745
A
46 splitinfolc->cmdsize = src->cmdsize;
47 splitinfolc->dataoff = src->dataoff;
48 splitinfolc->datasize = src->datasize;
49 splitinfolc->has_splitinfolc = TRUE;
39037602
A
50}
51
52/*******************************************************************************
0a7de745 53*******************************************************************************/
39037602
A
54void
55kxld_splitinfolc_clear(KXLDsplitinfolc *splitinfolc)
56{
0a7de745 57 bzero(splitinfolc, sizeof(*splitinfolc));
39037602
A
58}
59
60/*******************************************************************************
0a7de745 61*******************************************************************************/
39037602
A
62u_long
63kxld_splitinfolc_get_macho_header_size(void)
64{
0a7de745 65 return sizeof(struct linkedit_data_command);
39037602
A
66}
67
68/*******************************************************************************
0a7de745 69*******************************************************************************/
39037602
A
70kern_return_t
71kxld_splitinfolc_export_macho(const KXLDsplitinfolc *splitinfolc,
0a7de745
A
72 splitKextLinkInfo *linked_object,
73 u_long *header_offset,
74 u_long header_size,
75 u_long *data_offset,
76 u_long size)
39037602
A
77{
78 kern_return_t rval = KERN_FAILURE;
79 struct linkedit_data_command *splitinfolc_hdr = NULL;
80 u_char * buf;
81
82 check(splitinfolc);
83 check(linked_object);
84 check(header_offset);
85 check(data_offset);
86
87 buf = (u_char *)(linked_object->linkedKext);
88 require_action(sizeof(*splitinfolc_hdr) <= header_size - *header_offset,
0a7de745
A
89 finish,
90 rval = KERN_FAILURE);
39037602
A
91 splitinfolc_hdr = (struct linkedit_data_command *)((void *)(buf + *header_offset));
92 *header_offset += sizeof(*splitinfolc_hdr);
93
0a7de745
A
94 if (buf + *data_offset > buf + size) {
95 kxld_log(kKxldLogLinking, kKxldLogErr,
96 "\n OVERFLOW! linkedKext %p to %p (%lu) copy %p to %p (%u) <%s>",
97 (void *) buf,
98 (void *) (buf + size),
99 size,
100 (void *) (buf + *data_offset),
101 (void *) (buf + *data_offset + splitinfolc->datasize),
102 splitinfolc->datasize,
103 __func__);
104 goto finish;
105 }
106
39037602
A
107 // copy in the split info reloc data from kextExecutable. For example dataoff
108 // in LC_SEGMENT_SPLIT_INFO load command points to the reloc data in the
109 // __LINKEDIT segment. In this case 65768 into the kextExecutable file is
110 // the split seg reloc info (for 920 bytes)
111// Load command 9
112// cmd LC_SEGMENT_SPLIT_INFO
113// cmdsize 16
114// dataoff 65768
115// datasize 920
116
0a7de745 117
39037602
A
118 memcpy(buf + *data_offset, linked_object->kextExecutable + splitinfolc->dataoff, splitinfolc->datasize);
119
120#if SPLIT_KEXTS_DEBUG
0a7de745
A
121 u_char *dataPtr = buf + *data_offset;
122
123 kxld_log(kKxldLogLinking, kKxldLogErr,
124 "\n\n linkedKext %p to %p (%lu) copy %p to %p (%u) <%s>",
125 (void *) buf,
126 (void *) (buf + size),
127 size,
128 (void *) (dataPtr),
129 (void *) (dataPtr + splitinfolc->datasize),
130 splitinfolc->datasize,
131 __func__);
132
133 if (*(dataPtr + 0) != 0x7F) {
134 kxld_log(kKxldLogLinking, kKxldLogErr,
135 "\n\n bad LC_SEGMENT_SPLIT_INFO: 0x%02X %02X %02X %02X %02X %02X %02X %02X at %p (buf %p + %lu) <%s>",
136 *(dataPtr + 0),
137 *(dataPtr + 1),
138 *(dataPtr + 2),
139 *(dataPtr + 3),
140 *(dataPtr + 4),
141 *(dataPtr + 5),
142 *(dataPtr + 6),
143 *(dataPtr + 7),
144 (void *) dataPtr,
145 (void *) buf,
146 *data_offset, __func__);
147 }
39037602
A
148#endif
149
150 // update the load command header
151 splitinfolc_hdr->cmd = LC_SEGMENT_SPLIT_INFO;
152 splitinfolc_hdr->cmdsize = (uint32_t) sizeof(*splitinfolc_hdr);
153 splitinfolc_hdr->dataoff = (uint32_t)(*data_offset);
154 splitinfolc_hdr->datasize = splitinfolc->datasize;
155
156 *data_offset += splitinfolc->datasize;
157
158 rval = KERN_SUCCESS;
159
160finish:
161 return rval;
162}