Root/
Source at commit 214 created 13 years 5 months ago. By ifabio, update to chameleon trunk 630, and now the pakage folder is the same as blackosx branch, also add Icon "building" into buildpkg script, and add mint theme info into the English localizable.strings. | |
---|---|
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 | ␊ |
35 | static long DecodeSegment(long cmdBase, unsigned int*load_addr, unsigned int *load_size);␊ |
36 | static long DecodeUnixThread(long cmdBase, unsigned int *entry);␊ |
37 | static long DecodeSymbolTable(long cmdBase);␊ |
38 | ␊ |
39 | ␊ |
40 | static unsigned long gBinaryAddress;␊ |
41 | bool gHaveKernelCache;␉␉␉/* XXX aserebln: uninitialized? and only set to true, never to false */␊ |
42 | cpu_type_t archCpuType=CPU_TYPE_I386;␊ |
43 | ␊ |
44 | // Public Functions␊ |
45 | ␊ |
46 | long ThinFatFile(void **binary, unsigned long *length)␊ |
47 | {␊ |
48 | unsigned long nfat, swapped, size = 0;␊ |
49 | struct fat_header *fhp = (struct fat_header *)*binary;␊ |
50 | struct fat_arch *fap =␊ |
51 | (struct fat_arch *)((unsigned long)*binary + sizeof(struct fat_header));␊ |
52 | cpu_type_t fapcputype;␊ |
53 | uint32_t fapoffset;␊ |
54 | uint32_t fapsize;␉␊ |
55 | ␊ |
56 | if (fhp->magic == FAT_MAGIC) {␊ |
57 | nfat = fhp->nfat_arch;␊ |
58 | swapped = 0;␊ |
59 | } else if (fhp->magic == FAT_CIGAM) {␊ |
60 | nfat = OSSwapInt32(fhp->nfat_arch);␊ |
61 | swapped = 1;␊ |
62 | } else {␊ |
63 | return -1;␊ |
64 | }␊ |
65 | ␊ |
66 | for (; nfat > 0; nfat--, fap++) {␊ |
67 | if (swapped) {␊ |
68 | fapcputype = OSSwapInt32(fap->cputype);␊ |
69 | fapoffset = OSSwapInt32(fap->offset);␊ |
70 | fapsize = OSSwapInt32(fap->size);␊ |
71 | }␊ |
72 | ␉else␊ |
73 | ␉{␊ |
74 | ␉␉fapcputype = fap->cputype;␊ |
75 | ␉␉fapoffset = fap->offset;␊ |
76 | ␉␉fapsize = fap->size;␊ |
77 | ␉}␊ |
78 | ␊ |
79 | if (fapcputype == archCpuType) {␊ |
80 | *binary = (void *) ((unsigned long)*binary + fapoffset);␊ |
81 | ␉ size = fapsize;␊ |
82 | ␉ break;␊ |
83 | }␊ |
84 | }␊ |
85 | ␊ |
86 | if (length != 0) *length = size;␊ |
87 | ␊ |
88 | return 0;␊ |
89 | }␊ |
90 | ␊ |
91 | long DecodeMachO(void *binary, entry_t *rentry, char **raddr, int *rsize)␊ |
92 | {␊ |
93 | struct mach_header *mH;␊ |
94 | unsigned long ncmds, cmdBase, cmd, cmdsize, cmdstart;␊ |
95 | // long headerBase, headerAddr, headerSize;␊ |
96 | unsigned int vmaddr = ~0;␊ |
97 | unsigned int vmend = 0;␊ |
98 | unsigned long cnt;␊ |
99 | long ret = -1;␊ |
100 | unsigned int entry = 0;␊ |
101 | ␊ |
102 | gBinaryAddress = (unsigned long)binary;␊ |
103 | ␊ |
104 | mH = (struct mach_header *)(gBinaryAddress);␊ |
105 | switch (archCpuType)␊ |
106 | ␉{␊ |
107 | ␉␉case CPU_TYPE_I386:␊ |
108 | ␉␉␉if (mH->magic != MH_MAGIC) {␊ |
109 | ␉␉␉␉error("Mach-O file has bad magic number\n");␊ |
110 | ␉␉␉␉return -1;␊ |
111 | ␉␉␉}␊ |
112 | ␉␉␉cmdstart = (unsigned long)gBinaryAddress + sizeof(struct mach_header);␊ |
113 | ␉␉␉break;␊ |
114 | ␉␉case CPU_TYPE_X86_64:␊ |
115 | ␉␉␉if (mH->magic != MH_MAGIC_64 && mH->magic == MH_MAGIC) ␊ |
116 | ␉␉␉␉return -1;␊ |
117 | ␉␉␉if (mH->magic != MH_MAGIC_64) {␊ |
118 | ␉␉␉␉error("Mach-O file has bad magic number\n");␊ |
119 | ␉␉␉␉return -1;␊ |
120 | ␉␉␉}␊ |
121 | ␉␉␉cmdstart = (unsigned long)gBinaryAddress + sizeof(struct mach_header_64);␊ |
122 | ␉␉␉break;␊ |
123 | ␉␉default:␊ |
124 | ␉␉␉error("Unknown CPU type\n");␊ |
125 | ␉␉␉return -1;␊ |
126 | ␉}␊ |
127 | ␉␉␉␊ |
128 | cmdBase = cmdstart;␊ |
129 | ␊ |
130 | #if DEBUG␊ |
131 | printf("magic: %x\n", (unsigned)mH->magic);␊ |
132 | printf("cputype: %x\n", (unsigned)mH->cputype);␊ |
133 | printf("cpusubtype: %x\n", (unsigned)mH->cpusubtype);␊ |
134 | printf("filetype: %x\n", (unsigned)mH->filetype);␊ |
135 | printf("ncmds: %x\n", (unsigned)mH->ncmds);␊ |
136 | printf("sizeofcmds: %x\n", (unsigned)mH->sizeofcmds);␊ |
137 | printf("flags: %x\n", (unsigned)mH->flags);␊ |
138 | getc();␊ |
139 | #endif␊ |
140 | ␊ |
141 | ncmds = mH->ncmds;␊ |
142 | ␊ |
143 | for (cnt = 0; cnt < ncmds; cnt++) {␊ |
144 | cmd = ((long *)cmdBase)[0];␊ |
145 | cmdsize = ((long *)cmdBase)[1];␊ |
146 | unsigned int load_addr;␊ |
147 | unsigned int load_size;␊ |
148 | ␊ |
149 | switch (cmd) {␊ |
150 | ␉case LC_SEGMENT_64: ␊ |
151 | case LC_SEGMENT:␊ |
152 | ret = DecodeSegment(cmdBase, &load_addr, &load_size);␊ |
153 | if (ret == 0 && load_size != 0 && load_addr >= KERNEL_ADDR) {␊ |
154 | vmaddr = min(vmaddr, load_addr);␊ |
155 | vmend = max(vmend, load_addr + load_size);␊ |
156 | }␊ |
157 | break;␊ |
158 | ␊ |
159 | case LC_UNIXTHREAD:␊ |
160 | ret = DecodeUnixThread(cmdBase, &entry);␊ |
161 | break;␊ |
162 | ␊ |
163 | case LC_SYMTAB:␊ |
164 | break;␊ |
165 | ␊ |
166 | default:␊ |
167 | #if NOTDEF␊ |
168 | printf("Ignoring cmd type %d.\n", (unsigned)cmd);␊ |
169 | #endif␊ |
170 | break;␊ |
171 | }␊ |
172 | ␊ |
173 | if (ret != 0) return -1;␊ |
174 | ␊ |
175 | cmdBase += cmdsize;␊ |
176 | }␊ |
177 | ␊ |
178 | *rentry = (entry_t)( (unsigned long) entry & 0x3fffffff );␊ |
179 | *rsize = vmend - vmaddr;␊ |
180 | *raddr = (char *)vmaddr;␊ |
181 | ␊ |
182 | cmdBase = cmdstart;␊ |
183 | for (cnt = 0; cnt < ncmds; cnt++) {␊ |
184 | ␉cmd = ((long *)cmdBase)[0];␊ |
185 | ␉cmdsize = ((long *)cmdBase)[1];␊ |
186 | ␉␉␊ |
187 | ␉if(cmd==LC_SYMTAB) ␊ |
188 | ␉ if (DecodeSymbolTable(cmdBase)!=0)␊ |
189 | ␉␉return -1;␊ |
190 | ␉␉␊ |
191 | ␉cmdBase += cmdsize;␊ |
192 | }␉␊ |
193 | ␉␊ |
194 | return ret;␊ |
195 | }␊ |
196 | ␊ |
197 | // Private Functions␊ |
198 | ␊ |
199 | static long DecodeSegment(long cmdBase, unsigned int *load_addr, unsigned int *load_size)␊ |
200 | {␊ |
201 | unsigned long vmaddr, fileaddr;␊ |
202 | long vmsize, filesize;␊ |
203 | char *segname;␊ |
204 | ␊ |
205 | if (((long *)cmdBase)[0]==LC_SEGMENT_64)␊ |
206 | {␊ |
207 | ␉ struct segment_command_64 *segCmd;␊ |
208 | ␉ ␊ |
209 | ␉ segCmd = (struct segment_command_64 *)cmdBase;␊ |
210 | ␉ ␊ |
211 | ␉ vmaddr = (segCmd->vmaddr & 0x3fffffff);␊ |
212 | ␉ vmsize = segCmd->vmsize;␉ ␊ |
213 | ␉ fileaddr = (gBinaryAddress + segCmd->fileoff);␊ |
214 | ␉ filesize = segCmd->filesize;␊ |
215 | ␊ |
216 | ␉ segname=segCmd->segname;␉ ␊ |
217 | }␊ |
218 | else␊ |
219 | {␊ |
220 | ␉ struct segment_command *segCmd;␊ |
221 | ␊ |
222 | ␉ segCmd = (struct segment_command *)cmdBase;␊ |
223 | ␊ |
224 | ␉ vmaddr = (segCmd->vmaddr & 0x3fffffff);␊ |
225 | ␉ vmsize = segCmd->vmsize;␊ |
226 | ␉ fileaddr = (gBinaryAddress + segCmd->fileoff);␊ |
227 | ␉ filesize = segCmd->filesize;␊ |
228 | ␉ ␊ |
229 | ␉ segname=segCmd->segname;␉ ␊ |
230 | }␊ |
231 | ␊ |
232 | if (vmsize == 0 || filesize == 0) {␊ |
233 | *load_addr = ~0;␊ |
234 | *load_size = 0;␊ |
235 | return 0;␊ |
236 | }␊ |
237 | ␊ |
238 | #if DEBUG␊ |
239 | printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",␊ |
240 | ␉ segCmd->segname, (unsigned)vmaddr, (unsigned)vmsize, (unsigned)fileaddr, (unsigned)filesize,␊ |
241 | (unsigned) segCmd->nsects, (unsigned)segCmd->flags);␊ |
242 | getc();␊ |
243 | #endif␊ |
244 | ␊ |
245 | if (! ((vmaddr >= KERNEL_ADDR &&␊ |
246 | (vmaddr + vmsize) <= (KERNEL_ADDR + KERNEL_LEN)) ||␊ |
247 | (vmaddr >= HIB_ADDR &&␊ |
248 | (vmaddr + vmsize) <= (HIB_ADDR + HIB_LEN)))) {␊ |
249 | stop("Kernel overflows available space");␊ |
250 | }␊ |
251 | ␊ |
252 | if (vmsize && (strcmp(segname, "__PRELINK") == 0))␊ |
253 | gHaveKernelCache = true;␊ |
254 | ␊ |
255 | // Copy from file load area.␊ |
256 | if (vmsize>0 && filesize>0)␊ |
257 | ␉ bcopy((char *)fileaddr, (char *)vmaddr, vmsize>filesize?filesize:vmsize);␊ |
258 | ␊ |
259 | // Zero space at the end of the segment.␊ |
260 | if (vmsize > filesize)␊ |
261 | bzero((char *)(vmaddr + filesize), vmsize - filesize);␊ |
262 | ␊ |
263 | *load_addr = vmaddr;␊ |
264 | *load_size = vmsize;␊ |
265 | ␊ |
266 | return 0;␊ |
267 | }␊ |
268 | ␊ |
269 | static long DecodeUnixThread(long cmdBase, unsigned int *entry)␊ |
270 | {␊ |
271 | ␉switch (archCpuType)␊ |
272 | ␉{␊ |
273 | ␉␉case CPU_TYPE_I386:␊ |
274 | ␉␉{␊ |
275 | ␉␉␉i386_thread_state_t *i386ThreadState;␊ |
276 | ␊ |
277 | ␉␉␉i386ThreadState = (i386_thread_state_t *)␊ |
278 | ␉␉␉␉(cmdBase + sizeof(struct thread_command) + 8);␊ |
279 | ␊ |
280 | ␉␉#if defined(__DARWIN_UNIX03) && __DARWIN_UNIX03␊ |
281 | ␉␉␉*entry = i386ThreadState->__eip;␊ |
282 | ␉␉#else␊ |
283 | ␉␉␉*entry = i386ThreadState->eip;␊ |
284 | ␉␉#endif␊ |
285 | ␉␉␉return 0;␊ |
286 | ␉␉}␊ |
287 | ␉␉␉␊ |
288 | ␉␉case CPU_TYPE_X86_64:␊ |
289 | ␉␉{␊ |
290 | ␉␉␉x86_thread_state64_t *x86_64ThreadState;␊ |
291 | ␉␉␉␊ |
292 | ␉␉␉x86_64ThreadState = (x86_thread_state64_t *)␊ |
293 | ␉␉␉(cmdBase + sizeof(struct thread_command) + 8);␊ |
294 | ␉␉␉␊ |
295 | ␉␉#if defined(__DARWIN_UNIX03) && __DARWIN_UNIX03␊ |
296 | ␉␉␉*entry = x86_64ThreadState->__rip;␊ |
297 | ␉␉#else␊ |
298 | ␉␉␉*entry = x86_64ThreadState->rip;␊ |
299 | ␉␉#endif␊ |
300 | ␉␉␉return 0;␊ |
301 | ␉␉}␊ |
302 | ␉␉␉␊ |
303 | ␉␉default:␊ |
304 | ␉␉␉error("Unknown CPU type\n");␊ |
305 | ␉␉␉return -1;␊ |
306 | ␉}␊ |
307 | }␊ |
308 | ␊ |
309 | static long DecodeSymbolTable(long cmdBase)␊ |
310 | {␊ |
311 | struct symtab_command *symTab, *symTableSave;␊ |
312 | long tmpAddr, symsSize, totalSize;␊ |
313 | long gSymbolTableAddr;␊ |
314 | long gSymbolTableSize;␊ |
315 | ␊ |
316 | symTab = (struct symtab_command *)cmdBase;␊ |
317 | ␊ |
318 | #if DEBUG␊ |
319 | printf("symoff: %x, nsyms: %x, stroff: %x, strsize: %x\n",␊ |
320 | ␉ symTab->symoff, symTab->nsyms, symTab->stroff, symTab->strsize);␊ |
321 | ␉getc ();␊ |
322 | #endif␊ |
323 | ␊ |
324 | symsSize = symTab->stroff - symTab->symoff;␊ |
325 | totalSize = symsSize + symTab->strsize;␊ |
326 | ␊ |
327 | gSymbolTableSize = totalSize + sizeof(struct symtab_command);␊ |
328 | gSymbolTableAddr = AllocateKernelMemory(gSymbolTableSize);␊ |
329 | // Add the SymTab to the memory-map.␊ |
330 | AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr, gSymbolTableSize, -1);␊ |
331 | ␊ |
332 | symTableSave = (struct symtab_command *)gSymbolTableAddr;␊ |
333 | tmpAddr = gSymbolTableAddr + sizeof(struct symtab_command);␊ |
334 | ␊ |
335 | symTableSave->symoff = tmpAddr;␊ |
336 | symTableSave->nsyms = symTab->nsyms;␊ |
337 | symTableSave->stroff = tmpAddr + symsSize;␊ |
338 | symTableSave->strsize = symTab->strsize;␊ |
339 | ␉␊ |
340 | bcopy((char *)(gBinaryAddress + symTab->symoff),␊ |
341 | ␉(char *)tmpAddr, totalSize);␊ |
342 | return 0;␊ |
343 | }␊ |
344 |