]> git.saurik.com Git - apple/xnu.git/blob - libkern/kxld/kxld_splitinfolc.c
xnu-4903.241.1.tar.gz
[apple/xnu.git] / libkern / kxld / kxld_splitinfolc.c
1 /*
2 * Copyright (c) 2016 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-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 /*******************************************************************************
39 *******************************************************************************/
40 void
41 kxld_splitinfolc_init_from_macho(KXLDsplitinfolc *splitinfolc, struct linkedit_data_command *src)
42 {
43 check(splitinfolc);
44 check(src);
45
46 splitinfolc->cmdsize = src->cmdsize;
47 splitinfolc->dataoff = src->dataoff;
48 splitinfolc->datasize = src->datasize;
49 splitinfolc->has_splitinfolc = TRUE;
50 }
51
52 /*******************************************************************************
53 *******************************************************************************/
54 void
55 kxld_splitinfolc_clear(KXLDsplitinfolc *splitinfolc)
56 {
57 bzero(splitinfolc, sizeof(*splitinfolc));
58 }
59
60 /*******************************************************************************
61 *******************************************************************************/
62 u_long
63 kxld_splitinfolc_get_macho_header_size(void)
64 {
65 return sizeof(struct linkedit_data_command);
66 }
67
68 /*******************************************************************************
69 *******************************************************************************/
70 kern_return_t
71 kxld_splitinfolc_export_macho(const KXLDsplitinfolc *splitinfolc,
72 splitKextLinkInfo *linked_object,
73 u_long *header_offset,
74 u_long header_size,
75 u_long *data_offset,
76 u_long size)
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,
89 finish,
90 rval=KERN_FAILURE);
91 splitinfolc_hdr = (struct linkedit_data_command *)((void *)(buf + *header_offset));
92 *header_offset += sizeof(*splitinfolc_hdr);
93
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
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
117
118 memcpy(buf + *data_offset, linked_object->kextExecutable + splitinfolc->dataoff, splitinfolc->datasize);
119
120 #if SPLIT_KEXTS_DEBUG
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 }
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
160 finish:
161 return rval;
162 }
163