dyld-832.7.1.tar.gz
[apple/dyld.git] / testing / test-cases / kernel-helpers.h
1
2
3 #include <mach-o/fixup-chains.h>
4 #include <mach-o/loader.h>
5
6 #include "kernel-fixups.h"
7
8 #ifndef LC_FILESET_ENTRY
9 #define LC_FILESET_ENTRY (0x35 | LC_REQ_DYLD) /* used with fileset_entry_command */
10 struct fileset_entry_command {
11 uint32_t cmd; /* LC_FILESET_ENTRY */
12 uint32_t cmdsize; /* includes id string */
13 uint64_t vmaddr; /* memory address of the dylib */
14 uint64_t fileoff; /* file offset of the dylib */
15 union lc_str entry_id; /* contained entry id */
16 uint32_t reserved; /* entry_id is 32-bits long, so this is the reserved padding */
17 };
18 #endif
19
20 typedef int (*ModInitLogFunc)(const char*, ...);
21 static const int LogModInits = 0;
22
23 struct TestRunnerFunctions;
24 typedef int (*InitializerFunc)(const TestRunnerFunctions*);
25
26 #if __x86_64__
27 __attribute__((section(("__HIB, __text"))))
28 #else
29 __attribute__((section(("__TEXT_EXEC, __text"))))
30 #endif
31 static int getSlide(const struct mach_header* mh, ModInitLogFunc logFunc,
32 uintptr_t* slide) {
33 uint64_t textVMAddr = 0;
34
35 if (LogFixups) {
36 logFunc("[LOG] kernel-slide: mh %p\n", mh);
37 }
38
39 if (LogFixups) {
40 logFunc("[LOG] kernel-slide: parsing load commands\n");
41 }
42
43 const struct load_command* startCmds = 0;
44 if ( mh->magic == MH_MAGIC_64 )
45 startCmds = (struct load_command*)((char *)mh + sizeof(struct mach_header_64));
46 else if ( mh->magic == MH_MAGIC )
47 startCmds = (struct load_command*)((char *)mh + sizeof(struct mach_header));
48 else {
49 const uint32_t* h = (uint32_t*)mh;
50 //diag.error("file does not start with MH_MAGIC[_64]: 0x%08X 0x%08X", h[0], h [1]);
51 return 1; // not a mach-o file
52 }
53 const struct load_command* const cmdsEnd = (struct load_command*)((char*)startCmds + mh->sizeofcmds);
54 const struct load_command* cmd = startCmds;
55 for (uint32_t i = 0; i < mh->ncmds; ++i) {
56 if (LogFixups) {
57 logFunc("[LOG] kernel-slide: parsing load command %d with cmd=0x%x\n", i, cmd->cmd);
58 }
59 const struct load_command* nextCmd = (struct load_command*)((char *)cmd + cmd->cmdsize);
60 if ( cmd->cmdsize < 8 ) {
61 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) too small", i, this->ncmds, cmd, this, cmd->cmdsize);
62 return 1;
63 }
64 if ( (nextCmd > cmdsEnd) || (nextCmd < startCmds) ) {
65 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) is too large, load commands end at %p", i, this->ncmds, cmd, this, cmd->cmdsize, cmdsEnd);
66 return 1;
67 }
68 if ( cmd->cmd == LC_SEGMENT_64 ) {
69 const struct segment_command_64* seg = (const struct segment_command_64*)cmd;
70 if ( areEqual(seg->segname, "__TEXT") ) {
71 textVMAddr = seg->vmaddr;
72 }
73 }
74 cmd = nextCmd;
75 }
76
77 *slide = (uintptr_t)mh - textVMAddr;
78 return 0;
79 }
80
81 #if __x86_64__
82 __attribute__((section(("__HIB, __text"))))
83 #else
84 __attribute__((section(("__TEXT_EXEC, __text"))))
85 #endif
86 static int runAllModInitFunctions(const struct mach_header* mh, ModInitLogFunc logFunc,
87 const TestRunnerFunctions* funcs) {
88 uintptr_t slide = 0;
89 if ( getSlide(mh, logFunc, &slide) != 0 ) {
90 return 1;
91 }
92
93 const struct load_command* startCmds = 0;
94 if ( mh->magic == MH_MAGIC_64 )
95 startCmds = (struct load_command*)((char *)mh + sizeof(struct mach_header_64));
96 else if ( mh->magic == MH_MAGIC )
97 startCmds = (struct load_command*)((char *)mh + sizeof(struct mach_header));
98 else {
99 const uint32_t* h = (uint32_t*)mh;
100 //diag.error("file does not start with MH_MAGIC[_64]: 0x%08X 0x%08X", h[0], h [1]);
101 return 1; // not a mach-o file
102 }
103
104 const struct load_command* const cmdsEnd = (struct load_command*)((char*)startCmds + mh->sizeofcmds);
105 const struct load_command* cmd = startCmds;
106 for (uint32_t i = 0; i < mh->ncmds; ++i) {
107 if (LogModInits) {
108 logFunc("[LOG] kernel-mod-inits: parsing load command %d with cmd=0x%x\n", i, cmd->cmd);
109 }
110 const struct load_command* nextCmd = (struct load_command*)((char *)cmd + cmd->cmdsize);
111 if ( cmd->cmdsize < 8 ) {
112 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) too small", i, this->ncmds, cmd, this, cmd->cmdsize);
113 return 1;
114 }
115 if ( (nextCmd > cmdsEnd) || (nextCmd < startCmds) ) {
116 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) is too large, load commands end at %p", i, this->ncmds, cmd, this, cmd->cmdsize, cmdsEnd);
117 return 1;
118 }
119 if ( cmd->cmd == LC_SEGMENT_64 ) {
120 const struct segment_command_64* seg = (const struct segment_command_64*)cmd;
121 const struct section_64* const sectionsStart = (struct section_64*)((char*)seg + sizeof(struct segment_command_64));
122 const struct section_64* const sectionsEnd = &sectionsStart[seg->nsects];
123 for (const struct section_64* sect = sectionsStart; sect < sectionsEnd; ++sect) {
124 const uint8_t type = sect->flags & SECTION_TYPE;
125 if ( LogModInits ) {
126 logFunc("[LOG] kernel-mod-inits: section: %s %s\n", sect->segname, sect->sectname);
127 }
128 if ( type == S_MOD_INIT_FUNC_POINTERS ) {
129 InitializerFunc* inits = (InitializerFunc*)(sect->addr + slide);
130 const uintptr_t count = sect->size / sizeof(uintptr_t);
131 // Ensure __mod_init_func section is within segment
132 if ( (sect->addr < seg->vmaddr) || (sect->addr+sect->size > seg->vmaddr+seg->vmsize) || (sect->addr+sect->size < sect->addr) ) {
133 logFunc("[LOG] kernel-mod-inits: __mod_init_funcs section has malformed address range\n");
134 return 1;
135 }
136 for (uintptr_t j = 0; j < count; ++j) {
137 InitializerFunc func = inits[j];
138 #if __has_feature(ptrauth_calls)
139 func = (InitializerFunc)__builtin_ptrauth_sign_unauthenticated((void*)func, ptrauth_key_asia, 0);
140 #endif
141 if ( LogModInits ) {
142 logFunc("[LOG] kernel-mod-inits: running mod init %p\n", (const void*)func);
143 }
144 int initResult = func(funcs);
145 if ( initResult != 0 ) {
146 logFunc("[LOG] kernel-mod-inits: mod init %p, result = %d\n", (const void*)func, initResult);
147 return 1;
148 }
149 }
150 }
151 }
152 }
153 cmd = nextCmd;
154 }
155
156 return 0;
157 }
158
159 #if __x86_64__
160 __attribute__((section(("__HIB, __text"))))
161 #else
162 __attribute__((section(("__TEXT_EXEC, __text"))))
163 #endif
164 static int runAllModInitFunctionsForAppCache(const struct mach_header* appCacheMH, ModInitLogFunc logFunc,
165 const TestRunnerFunctions* funcs) {
166 uintptr_t slide = 0;
167 if ( getSlide(appCacheMH, logFunc, &slide) != 0 ) {
168 return 1;
169 }
170
171 if (LogFixups) {
172 logFunc("[LOG] mod-init: appCacheMH %p\n", appCacheMH);
173 }
174
175 if (LogFixups) {
176 logFunc("[LOG] mod-init: parsing load commands\n");
177 }
178
179 const struct load_command* startCmds = 0;
180 if ( appCacheMH->magic == MH_MAGIC_64 )
181 startCmds = (struct load_command*)((char *)appCacheMH + sizeof(struct mach_header_64));
182 else if ( appCacheMH->magic == MH_MAGIC )
183 startCmds = (struct load_command*)((char *)appCacheMH + sizeof(struct mach_header));
184 else {
185 const uint32_t* h = (uint32_t*)appCacheMH;
186 //diag.error("file does not start with MH_MAGIC[_64]: 0x%08X 0x%08X", h[0], h [1]);
187 return 1; // not a mach-o file
188 }
189 const struct load_command* const cmdsEnd = (struct load_command*)((char*)startCmds + appCacheMH->sizeofcmds);
190 const struct load_command* cmd = startCmds;
191 for (uint32_t i = 0; i < appCacheMH->ncmds; ++i) {
192 if (LogFixups) {
193 logFunc("[LOG] mod-init: parsing load command %d with cmd=0x%x\n", i, cmd->cmd);
194 }
195 const struct load_command* nextCmd = (struct load_command*)((char *)cmd + cmd->cmdsize);
196 if ( cmd->cmdsize < 8 ) {
197 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) too small", i, this->ncmds, cmd, this, cmd->cmdsize);
198 return 1;
199 }
200 if ( (nextCmd > cmdsEnd) || (nextCmd < startCmds) ) {
201 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) is too large, load commands end at %p", i, this->ncmds, cmd, this, cmd->cmdsize, cmdsEnd);
202 return 1;
203 }
204 if ( cmd->cmd == LC_FILESET_ENTRY ) {
205 const struct fileset_entry_command* app_cache_cmd = (const struct fileset_entry_command*)cmd;
206 const char* name = (char*)app_cache_cmd + app_cache_cmd->entry_id.offset;
207 const struct mach_header* mh = (const struct mach_header*)(app_cache_cmd->vmaddr + slide);
208 if ( LogModInits ) {
209 logFunc("[LOG] mod-init: Running mod inits for %p: %s\n", mh, name);
210 }
211 int result = runAllModInitFunctions(mh, logFunc, funcs);
212 if (result != 0) {
213 return 1;
214 }
215 }
216 cmd = nextCmd;
217 }
218
219 return 0;
220 }
221
222 #if __x86_64__
223 __attribute__((section(("__HIB, __text"))))
224 #else
225 __attribute__((section(("__TEXT_EXEC, __text"))))
226 #endif
227 static int slideKextsInsideKernelCollection(const struct mach_header* appCacheMH, const void* basePointers[4],
228 FixupsLogFunc logFunc, const TestRunnerFunctions* funcs) {
229 uintptr_t slideAmount = 0;
230 if ( getSlide(appCacheMH, logFunc, &slideAmount) != 0 ) {
231 return 1;
232 }
233
234 if (LogFixups) {
235 logFunc("[LOG] slide-pageable: appCacheMH %p\n", appCacheMH);
236 }
237
238 if (LogFixups) {
239 logFunc("[LOG] slide-pageable: parsing load commands\n");
240 }
241
242 const struct load_command* startCmds = 0;
243 if ( appCacheMH->magic == MH_MAGIC_64 )
244 startCmds = (struct load_command*)((char *)appCacheMH + sizeof(struct mach_header_64));
245 else if ( appCacheMH->magic == MH_MAGIC )
246 startCmds = (struct load_command*)((char *)appCacheMH + sizeof(struct mach_header));
247 else {
248 const uint32_t* h = (uint32_t*)appCacheMH;
249 //diag.error("file does not start with MH_MAGIC[_64]: 0x%08X 0x%08X", h[0], h [1]);
250 return 1; // not a mach-o file
251 }
252 const struct load_command* const cmdsEnd = (struct load_command*)((char*)startCmds + appCacheMH->sizeofcmds);
253 const struct load_command* cmd = startCmds;
254 for (uint32_t i = 0; i < appCacheMH->ncmds; ++i) {
255 if (LogFixups) {
256 logFunc("[LOG] slide-pageable: parsing load command %d with cmd=0x%x\n", i, cmd->cmd);
257 }
258 const struct load_command* nextCmd = (struct load_command*)((char *)cmd + cmd->cmdsize);
259 if ( cmd->cmdsize < 8 ) {
260 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) too small", i, this->ncmds, cmd, this, cmd->cmdsize);
261 return 1;
262 }
263 if ( (nextCmd > cmdsEnd) || (nextCmd < startCmds) ) {
264 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) is too large, load commands end at %p", i, this->ncmds, cmd, this, cmd->cmdsize, cmdsEnd);
265 return 1;
266 }
267 if ( cmd->cmd == LC_FILESET_ENTRY ) {
268 const struct fileset_entry_command* app_cache_cmd = (const struct fileset_entry_command*)cmd;
269 const char* name = (char*)app_cache_cmd + app_cache_cmd->entry_id.offset;
270 const struct mach_header* mh = (const struct mach_header*)(app_cache_cmd->vmaddr + slideAmount);
271 if ( LogModInits ) {
272 logFunc("[LOG] slide-pageable: Sliding %p: %s\n", mh, name);
273 }
274 int slideReturnCode = slide(mh, basePointers, logFunc);
275 if ( slideReturnCode != 0 ) {
276 FAIL("mh slide = %d\n", slideReturnCode);
277 return 1;
278 }
279 }
280 cmd = nextCmd;
281 }
282
283 return 0;
284 }