1 | /*␊ |
2 | * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * @APPLE_LICENSE_HEADER_START@␊ |
5 | * ␊ |
6 | * The contents of this file constitute Original Code as defined in and␊ |
7 | * are subject to the Apple Public Source License Version 2.0 (the␊ |
8 | * "License"). You may not use this file except in compliance with the␊ |
9 | * License. Please obtain a copy of the License at␊ |
10 | * http://www.apple.com/publicsource and read it before using this file.␊ |
11 | * ␊ |
12 | * This Original Code and all software distributed under the License are␊ |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the␊ |
17 | * License for the specific language governing rights and limitations␊ |
18 | * under the License.␊ |
19 | * ␊ |
20 | * @APPLE_LICENSE_HEADER_END@␊ |
21 | */␊ |
22 | /*␊ |
23 | * load.c - Functions for decoding a Mach-o Kernel.␊ |
24 | *␊ |
25 | * Copyright (c) 1998-2003 Apple Computer, Inc.␊ |
26 | *␊ |
27 | */␊ |
28 | ␊ |
29 | #include <mach-o/fat.h>␊ |
30 | #include <mach-o/loader.h>␊ |
31 | #include <mach/machine/thread_status.h>␊ |
32 | ␊ |
33 | #include "sl.h"␊ |
34 | #include "platform.h"␊ |
35 | ␊ |
36 | static long DecodeSegment(long cmdBase, unsigned int*load_addr, unsigned int *load_size);␊ |
37 | static long DecodeUnixThread(long cmdBase, unsigned int *entry);␊ |
38 | static long DecodeSymbolTable(long cmdBase);␊ |
39 | static unsigned long gBinaryAddress;␊ |
40 | ␊ |
41 | // Public Functions␊ |
42 | ␊ |
43 | long ThinFatFile(void **binary, unsigned long *length)␊ |
44 | {␊ |
45 | ␉unsigned long nfat, swapped, size = 0;␊ |
46 | ␉struct fat_arch *fap =␊ |
47 | ␉␉(struct fat_arch *)((unsigned long)*binary + sizeof(struct fat_header));␊ |
48 | ␉␊ |
49 | ␉{␊ |
50 | ␉␉struct fat_header *fhp = (struct fat_header *)*binary;␊ |
51 | ␊ |
52 | ␉␉if (fhp->magic == FAT_MAGIC)␊ |
53 | ␉␉{␊ |
54 | ␉␉␉nfat = fhp->nfat_arch;␊ |
55 | ␉␉␉swapped = 0;␊ |
56 | ␉␉}␊ |
57 | ␉␉else if (fhp->magic == FAT_CIGAM)␊ |
58 | ␉␉{␊ |
59 | ␉␉␉nfat = OSSwapInt32(fhp->nfat_arch);␊ |
60 | ␉␉␉swapped = 1;␊ |
61 | ␉␉}␊ |
62 | ␉␉else␊ |
63 | ␉␉{␊ |
64 | ␉␉␉return -1;␊ |
65 | ␉␉}␊ |
66 | ␉} ␊ |
67 | ␉␊ |
68 | ␉{␊ |
69 | ␉␉cpu_type_t fapcputype;␊ |
70 | ␉␉uint32_t fapoffset;␊ |
71 | ␉␉uint32_t fapsize;␊ |
72 | ␉␉for (; nfat > 0; nfat--, fap++)␊ |
73 | ␉␉{␊ |
74 | ␉␉␉if (swapped)␊ |
75 | ␉␉␉{␊ |
76 | ␉␉␉␉fapcputype = OSSwapInt32(fap->cputype);␊ |
77 | ␉␉␉␉fapoffset = OSSwapInt32(fap->offset);␊ |
78 | ␉␉␉␉fapsize = OSSwapInt32(fap->size);␊ |
79 | ␉␉␉}␊ |
80 | ␉␉␉else␊ |
81 | ␉␉␉{␊ |
82 | ␉␉␉␉fapcputype = fap->cputype;␊ |
83 | ␉␉␉␉fapoffset = fap->offset;␊ |
84 | ␉␉␉␉fapsize = fap->size;␊ |
85 | ␉␉␉}␊ |
86 | ␉␉␉␊ |
87 | ␉␉␉if (fapcputype == get_env(envarchCpuType))␊ |
88 | ␉␉␉{␊ |
89 | ␉␉␉␉*binary = (void *) ((unsigned long)*binary + fapoffset);␊ |
90 | ␉␉␉␉size = fapsize;␊ |
91 | ␉␉␉␉break;␊ |
92 | ␉␉␉}␊ |
93 | ␉␉}␊ |
94 | ␉}␊ |
95 | ␉␊ |
96 | ␉if (length != 0) *length = size;␊ |
97 | ␉␊ |
98 | ␉return 0; ␊ |
99 | ␊ |
100 | }␊ |
101 | ␊ |
102 | long DecodeMachO(void *binary, entry_t *rentry, char **raddr, int *rsize)␊ |
103 | {␊ |
104 | ␉unsigned long ncmds, cmdBase, cmdstart; ␊ |
105 | ␉long ret = -1;␊ |
106 | ␉gBinaryAddress = (unsigned long)binary; ␊ |
107 | ␉␊ |
108 | ␉{␊ |
109 | ␉␉struct mach_header *mH;␊ |
110 | ␉␉mH = (struct mach_header *)(gBinaryAddress);␊ |
111 | ␉␉switch (get_env(envarchCpuType))␊ |
112 | ␉␉{␊ |
113 | ␉␉␉case CPU_TYPE_I386:␊ |
114 | ␉␉␉␉if (mH->magic != MH_MAGIC)␊ |
115 | ␉␉␉␉{␊ |
116 | ␉␉␉␉␉error("Mach-O file has bad magic number\n");␊ |
117 | ␉␉␉␉␉return -1;␊ |
118 | ␉␉␉␉}␊ |
119 | ␉␉␉␉cmdstart = (unsigned long)gBinaryAddress + sizeof(struct mach_header);␊ |
120 | ␉␉␉␉break;␊ |
121 | ␉␉␉case CPU_TYPE_X86_64:␊ |
122 | ␉␉␉␉if (mH->magic != MH_MAGIC_64 && mH->magic == MH_MAGIC) ␊ |
123 | ␉␉␉␉␉return -1;␊ |
124 | ␉␉␉␉if (mH->magic != MH_MAGIC_64)␊ |
125 | ␉␉␉␉{␊ |
126 | ␉␉␉␉␉error("Mach-O file has bad magic number\n");␊ |
127 | ␉␉␉␉␉return -1;␊ |
128 | ␉␉␉␉}␊ |
129 | ␉␉␉␉cmdstart = (unsigned long)gBinaryAddress + sizeof(struct mach_header_64);␊ |
130 | ␉␉␉␉break;␊ |
131 | ␉␉␉default:␊ |
132 | ␉␉␉␉error("Unknown CPU type\n");␊ |
133 | ␉␉␉␉return -1;␊ |
134 | ␉␉}␊ |
135 | ␉␉␊ |
136 | ␉␉cmdBase = cmdstart;␊ |
137 | ␉␉␊ |
138 | #if DEBUG␊ |
139 | ␉␉printf("magic: %x\n", (unsigned)mH->magic);␊ |
140 | ␉␉printf("cputype: %x\n", (unsigned)mH->cputype);␊ |
141 | ␉␉printf("cpusubtype: %x\n", (unsigned)mH->cpusubtype);␊ |
142 | ␉␉printf("filetype: %x\n", (unsigned)mH->filetype);␊ |
143 | ␉␉printf("ncmds: %x\n", (unsigned)mH->ncmds);␊ |
144 | ␉␉printf("sizeofcmds: %x\n", (unsigned)mH->sizeofcmds);␊ |
145 | ␉␉printf("flags: %x\n", (unsigned)mH->flags);␊ |
146 | ␉␉getc();␊ |
147 | #endif␊ |
148 | ␉␉␊ |
149 | ␉␉ncmds = mH->ncmds;␊ |
150 | ␉}␊ |
151 | ␊ |
152 | ␉{␊ |
153 | ␉␉unsigned int vmaddr = ~0;␊ |
154 | ␉␉unsigned int vmend = 0;␊ |
155 | ␉␉unsigned int entry = 0;␊ |
156 | ␉␉unsigned long cnt;␉␉␊ |
157 | ␉␉unsigned long cmd, cmdsize;␊ |
158 | ␉␉␊ |
159 | ␉␉for (cnt = 0; cnt < ncmds; cnt++)␊ |
160 | ␉␉{␊ |
161 | ␉␉␉cmd = ((long *)cmdBase)[0];␊ |
162 | ␉␉␉cmdsize = ((long *)cmdBase)[1];␊ |
163 | ␉␉␉unsigned int load_addr;␊ |
164 | ␉␉␉unsigned int load_size;␊ |
165 | ␉␉␉␊ |
166 | ␉␉␉switch (cmd) {␊ |
167 | ␉␉␉␉case LC_SEGMENT_64: ␊ |
168 | ␉␉␉␉case LC_SEGMENT:␊ |
169 | ␉␉␉␉␉ret = DecodeSegment(cmdBase, &load_addr, &load_size);␊ |
170 | ␉␉␉␉␉if (ret == 0 && load_size != 0 && load_addr >= KERNEL_ADDR)␊ |
171 | ␉␉␉␉␉{␊ |
172 | ␉␉␉␉␉␉vmaddr = min(vmaddr, load_addr);␊ |
173 | ␉␉␉␉␉␉vmend = max(vmend, load_addr + load_size);␊ |
174 | ␉␉␉␉␉}␊ |
175 | ␉␉␉␉␉break;␊ |
176 | ␉␉␉␉␉␊ |
177 | ␉␉␉␉case LC_UNIXTHREAD:␊ |
178 | ␉␉␉␉␉ret = DecodeUnixThread(cmdBase, &entry);␊ |
179 | ␉␉␉␉␉break;␊ |
180 | ␉␉␉␉␉␊ |
181 | ␉␉␉␉case LC_SYMTAB:␊ |
182 | ␉␉␉␉␉break;␊ |
183 | ␉␉␉␉␉␊ |
184 | ␉␉␉␉default:␊ |
185 | #if NOTDEF␊ |
186 | ␉␉␉␉␉printf("Ignoring cmd type %d.\n", (unsigned)cmd);␊ |
187 | #endif␊ |
188 | ␉␉␉␉␉break;␊ |
189 | ␉␉␉}␊ |
190 | ␉␉␉␊ |
191 | ␉␉␉if (ret != 0) return -1;␊ |
192 | ␉␉␉␊ |
193 | ␉␉␉cmdBase += cmdsize;␊ |
194 | ␉␉}␊ |
195 | ␉␉␊ |
196 | ␉␉*rentry = (entry_t)( (unsigned long) entry & 0x3fffffff );␊ |
197 | ␉␉*rsize = vmend - vmaddr;␊ |
198 | ␉␉*raddr = (char *)vmaddr;␊ |
199 | ␉␉␊ |
200 | ␉␉cmdBase = cmdstart;␊ |
201 | ␉␉for (cnt = 0; cnt < ncmds; cnt++)␊ |
202 | ␉␉{␊ |
203 | ␉␉␉cmd = ((long *)cmdBase)[0];␊ |
204 | ␉␉␉cmdsize = ((long *)cmdBase)[1];␊ |
205 | ␉␉␉␊ |
206 | ␉␉␉if(cmd==LC_SYMTAB) ␊ |
207 | ␉␉␉␉if (DecodeSymbolTable(cmdBase)!=0)␊ |
208 | ␉␉␉␉␉return -1;␊ |
209 | ␉␉␉␊ |
210 | ␉␉␉cmdBase += cmdsize;␊ |
211 | ␉␉}␉␊ |
212 | ␉}␊ |
213 | ␉␊ |
214 | ␉return ret;␉␊ |
215 | ␊ |
216 | }␊ |
217 | ␊ |
218 | // Private Functions␊ |
219 | ␊ |
220 | static long DecodeSegment(long cmdBase, unsigned int *load_addr, unsigned int *load_size)␊ |
221 | {␊ |
222 | ␉unsigned long vmaddr, fileaddr;␊ |
223 | ␉long vmsize, filesize;␊ |
224 | ␉char *segname;␊ |
225 | ␉␊ |
226 | ␉if (((long *)cmdBase)[0]==LC_SEGMENT_64)␊ |
227 | ␉{␊ |
228 | ␉␉struct segment_command_64 *segCmd;␊ |
229 | ␉␉␊ |
230 | ␉␉segCmd = (struct segment_command_64 *)cmdBase;␊ |
231 | ␉␉␊ |
232 | ␉␉vmaddr = (segCmd->vmaddr & 0x3fffffff);␊ |
233 | ␉␉vmsize = segCmd->vmsize;␉ ␊ |
234 | ␉␉fileaddr = (gBinaryAddress + segCmd->fileoff);␊ |
235 | ␉␉filesize = segCmd->filesize;␊ |
236 | ␉␉␊ |
237 | ␉␉segname=segCmd->segname;␉ ␊ |
238 | ␉}␊ |
239 | ␉else␊ |
240 | ␉{␊ |
241 | ␉␉struct segment_command *segCmd;␊ |
242 | ␉␉␊ |
243 | ␉␉segCmd = (struct segment_command *)cmdBase;␊ |
244 | ␉␉␊ |
245 | ␉␉vmaddr = (segCmd->vmaddr & 0x3fffffff);␊ |
246 | ␉␉vmsize = segCmd->vmsize;␊ |
247 | ␉␉fileaddr = (gBinaryAddress + segCmd->fileoff);␊ |
248 | ␉␉filesize = segCmd->filesize;␊ |
249 | ␉␉␊ |
250 | ␉␉segname=segCmd->segname;␉ ␊ |
251 | ␉}␊ |
252 | ␉␊ |
253 | ␉if (vmsize == 0 || filesize == 0)␊ |
254 | ␉{␊ |
255 | ␉␉*load_addr = ~0;␊ |
256 | ␉␉*load_size = 0;␊ |
257 | ␉␉return 0;␊ |
258 | ␉}␊ |
259 | ␉␊ |
260 | #if 0␊ |
261 | ␉printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",␊ |
262 | ␉␉ segCmd->segname, (unsigned)vmaddr, (unsigned)vmsize, (unsigned)fileaddr, (unsigned)filesize,␊ |
263 | ␉␉ (unsigned) segCmd->nsects, (unsigned)segCmd->flags);␊ |
264 | ␉getc();␊ |
265 | #endif␊ |
266 | ␉␊ |
267 | ␉if (! ((vmaddr >= KERNEL_ADDR &&␊ |
268 | ␉␉␉(vmaddr + vmsize) <= (KERNEL_ADDR + KERNEL_LEN)) ||␊ |
269 | ␉␉ (vmaddr >= HIB_ADDR &&␊ |
270 | ␉␉␉(vmaddr + vmsize) <= (HIB_ADDR + HIB_LEN))))␊ |
271 | ␉{␊ |
272 | *load_addr = ~0;␊ |
273 | ␉␉*load_size = 0;␊ |
274 | stop("Kernel overflows available space");␊ |
275 | return -1;␊ |
276 | ␉}␊ |
277 | ␉␊ |
278 | ␉if (vmsize && (strncmp(segname, "__PRELINK", sizeof("__PRELINK")) == 0 || strncmp(segname, "__PRELINK_INFO", sizeof("__PRELINK_INFO")) == 0))␊ |
279 | ␉␉safe_set_env(envgHaveKernelCache, true);␊ |
280 | ␉␊ |
281 | ␉// Copy from file load area.␊ |
282 | ␉if (vmsize>0 && filesize>0)␊ |
283 | ␉␉bcopy((char *)fileaddr, (char *)vmaddr, vmsize>filesize?filesize:vmsize);␊ |
284 | ␉␊ |
285 | ␉// Zero space at the end of the segment.␊ |
286 | ␉if (vmsize > filesize)␊ |
287 | ␉␉bzero((char *)(vmaddr + filesize), vmsize - filesize);␊ |
288 | ␉␊ |
289 | ␉*load_addr = vmaddr;␊ |
290 | ␉*load_size = vmsize;␊ |
291 | ␉␊ |
292 | ␉return 0; ␊ |
293 | }␊ |
294 | ␊ |
295 | static long DecodeUnixThread(long cmdBase, unsigned int *entry)␊ |
296 | {␊ |
297 | ␉switch (get_env(envarchCpuType))␊ |
298 | ␉{␊ |
299 | ␉␉case CPU_TYPE_I386:␊ |
300 | ␉␉{␊ |
301 | ␉␉␉i386_thread_state_t *i386ThreadState;␊ |
302 | ␊ |
303 | ␉␉␉i386ThreadState = (i386_thread_state_t *)␊ |
304 | ␉␉␉␉(cmdBase + sizeof(struct thread_command) + 8);␊ |
305 | ␊ |
306 | ␉␉#if defined(__DARWIN_UNIX03) && __DARWIN_UNIX03␊ |
307 | ␉␉␉*entry = i386ThreadState->__eip;␊ |
308 | ␉␉#else␊ |
309 | ␉␉␉*entry = i386ThreadState->eip;␊ |
310 | ␉␉#endif␊ |
311 | ␉␉␉return 0;␊ |
312 | ␉␉}␊ |
313 | ␉␉␉␊ |
314 | ␉␉case CPU_TYPE_X86_64:␊ |
315 | ␉␉{␊ |
316 | ␉␉␉x86_thread_state64_t *x86_64ThreadState;␊ |
317 | ␉␉␉␊ |
318 | ␉␉␉x86_64ThreadState = (x86_thread_state64_t *)␊ |
319 | ␉␉␉(cmdBase + sizeof(struct thread_command) + 8);␊ |
320 | ␉␉␉␊ |
321 | ␉␉#if defined(__DARWIN_UNIX03) && __DARWIN_UNIX03␊ |
322 | ␉␉␉*entry = x86_64ThreadState->__rip;␊ |
323 | ␉␉#else␊ |
324 | ␉␉␉*entry = x86_64ThreadState->rip;␊ |
325 | ␉␉#endif␊ |
326 | ␉␉␉return 0;␊ |
327 | ␉␉}␊ |
328 | ␉␉␉␊ |
329 | ␉␉default:␊ |
330 | ␉␉␉error("Unknown CPU type\n");␊ |
331 | ␉␉␉return -1;␊ |
332 | ␉}␊ |
333 | }␊ |
334 | ␊ |
335 | static long DecodeSymbolTable(long cmdBase)␊ |
336 | { ␊ |
337 | ␉struct symtab_command *symTab, *symTableSave;␊ |
338 | ␉long tmpAddr, symsSize, totalSize; ␊ |
339 | ␉␊ |
340 | ␉symTab = (struct symtab_command *)cmdBase;␊ |
341 | ␉␊ |
342 | #if DEBUG␊ |
343 | ␉printf("symoff: %x, nsyms: %x, stroff: %x, strsize: %x\n",␊ |
344 | ␉␉ symTab->symoff, symTab->nsyms, symTab->stroff, symTab->strsize);␊ |
345 | ␉getc ();␊ |
346 | #endif␊ |
347 | ␉␊ |
348 | ␉symsSize = symTab->stroff - symTab->symoff;␊ |
349 | ␉totalSize = symsSize + symTab->strsize; ␊ |
350 | ␊ |
351 | ␉{␊ |
352 | ␉␉long gSymbolTableAddr;␊ |
353 | ␉␉long gSymbolTableSize;␊ |
354 | ␉␉gSymbolTableSize = totalSize + sizeof(struct symtab_command);␊ |
355 | ␉␉gSymbolTableAddr = AllocateKernelMemory(gSymbolTableSize);␊ |
356 | ␉␉// Add the SymTab to the memory-map.␊ |
357 | #if UNUSED␊ |
358 | ␉␉AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr, gSymbolTableSize, -1); ␊ |
359 | #else␊ |
360 | ␉␉AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr, gSymbolTableSize);␊ |
361 | #endif␊ |
362 | ␉␉symTableSave = (struct symtab_command *)gSymbolTableAddr;␊ |
363 | ␉␉tmpAddr = gSymbolTableAddr + sizeof(struct symtab_command);␊ |
364 | ␉}␉␊ |
365 | ␊ |
366 | ␉symTableSave->symoff = tmpAddr;␊ |
367 | ␉symTableSave->nsyms = symTab->nsyms;␊ |
368 | ␉symTableSave->stroff = tmpAddr + symsSize;␊ |
369 | ␉symTableSave->strsize = symTab->strsize;␊ |
370 | ␉␊ |
371 | ␉bcopy((char *)(gBinaryAddress + symTab->symoff),␊ |
372 | ␉␉ (char *)tmpAddr, totalSize);␊ |
373 | ␉␊ |
374 | ␉return 0;␊ |
375 | }␊ |
376 | |