Chameleon

Chameleon Svn Source Tree

Root/tags/2.0/i386/libsaio/load.c

Source at commit 1808 created 12 years 3 months ago.
By blackosx, Revise layout of package installer 'Welcome' file so it looks cleaner. Change the copyright notice to begin from 2009 as seen in the Chameleon 2.0 r431 installer. Should this date be set earlier?
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
35static long DecodeSegment(long cmdBase, unsigned int*load_addr, unsigned int *load_size);
36static long DecodeUnixThread(long cmdBase, unsigned int *entry);
37static long DecodeSymbolTable(long cmdBase);
38
39
40static unsigned long gBinaryAddress;
41bool gHaveKernelCache;/* XXX aserebln: uninitialized? and only set to true, never to false */
42cpu_type_t archCpuType=CPU_TYPE_I386;
43
44// Public Functions
45
46long 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 }
72else
73{
74fapcputype = fap->cputype;
75fapoffset = fap->offset;
76fapsize = 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
91long 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{
107case CPU_TYPE_I386:
108if (mH->magic != MH_MAGIC) {
109error("Mach-O file has bad magic number\n");
110return -1;
111}
112cmdstart = (unsigned long)gBinaryAddress + sizeof(struct mach_header);
113break;
114case CPU_TYPE_X86_64:
115if (mH->magic != MH_MAGIC_64 && mH->magic == MH_MAGIC)
116return -1;
117if (mH->magic != MH_MAGIC_64) {
118error("Mach-O file has bad magic number\n");
119return -1;
120}
121cmdstart = (unsigned long)gBinaryAddress + sizeof(struct mach_header_64);
122break;
123default:
124error("Unknown CPU type\n");
125return -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 getchar();
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) {
150case 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++) {
184cmd = ((long *)cmdBase)[0];
185cmdsize = ((long *)cmdBase)[1];
186
187if(cmd==LC_SYMTAB)
188 if (DecodeSymbolTable(cmdBase)!=0)
189return -1;
190
191cmdBase += cmdsize;
192 }
193
194 return ret;
195}
196
197// Private Functions
198
199static 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#ifdef DEBUG
219 printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",
220 segCmd->segname, (unsigned)vmaddr, (unsigned)vmsize, (unsigned)fileaddr, (unsigned)filesize,
221 (unsigned) segCmd->nsects, (unsigned)segCmd->flags);
222 getchar();
223#endif
224 }
225 else
226 {
227 struct segment_command *segCmd;
228
229 segCmd = (struct segment_command *)cmdBase;
230
231 vmaddr = (segCmd->vmaddr & 0x3fffffff);
232 vmsize = segCmd->vmsize;
233 fileaddr = (gBinaryAddress + segCmd->fileoff);
234 filesize = segCmd->filesize;
235
236 segname=segCmd->segname;
237
238#ifdef 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 getchar();
243#endif
244 }
245
246 if (vmsize == 0 || filesize == 0) {
247 *load_addr = ~0;
248 *load_size = 0;
249 return 0;
250 }
251
252 if (! ((vmaddr >= KERNEL_ADDR &&
253 (vmaddr + vmsize) <= (KERNEL_ADDR + KERNEL_LEN)) ||
254 (vmaddr >= HIB_ADDR &&
255 (vmaddr + vmsize) <= (HIB_ADDR + HIB_LEN)))) {
256 stop("Kernel overflows available space");
257 }
258
259 if (vmsize && ((strcmp(segname, "__PRELINK_INFO") == 0) || (strcmp(segname, "__PRELINK") == 0)))
260 gHaveKernelCache = true;
261
262 // Copy from file load area.
263 if (vmsize>0 && filesize>0)
264 bcopy((char *)fileaddr, (char *)vmaddr, vmsize>filesize?filesize:vmsize);
265
266 // Zero space at the end of the segment.
267 if (vmsize > filesize)
268 bzero((char *)(vmaddr + filesize), vmsize - filesize);
269
270 *load_addr = vmaddr;
271 *load_size = vmsize;
272
273 return 0;
274}
275
276static long DecodeUnixThread(long cmdBase, unsigned int *entry)
277{
278switch (archCpuType)
279{
280case CPU_TYPE_I386:
281{
282i386_thread_state_t *i386ThreadState;
283
284i386ThreadState = (i386_thread_state_t *)
285(cmdBase + sizeof(struct thread_command) + 8);
286
287*entry = i386ThreadState->eip;
288return 0;
289}
290
291case CPU_TYPE_X86_64:
292{
293x86_thread_state64_t *x86_64ThreadState;
294
295x86_64ThreadState = (x86_thread_state64_t *)
296(cmdBase + sizeof(struct thread_command) + 8);
297
298*entry = x86_64ThreadState->rip;
299return 0;
300}
301
302default:
303error("Unknown CPU type\n");
304return -1;
305}
306}
307
308static long DecodeSymbolTable(long cmdBase)
309{
310 struct symtab_command *symTab, *symTableSave;
311 long tmpAddr, symsSize, totalSize;
312 long gSymbolTableAddr;
313 long gSymbolTableSize;
314
315 symTab = (struct symtab_command *)cmdBase;
316
317#if DEBUG
318 printf("symoff: %x, nsyms: %x, stroff: %x, strsize: %x\n",
319 symTab->symoff, symTab->nsyms, symTab->stroff, symTab->strsize);
320 getchar();
321#endif
322
323 symsSize = symTab->stroff - symTab->symoff;
324 totalSize = symsSize + symTab->strsize;
325
326 gSymbolTableSize = totalSize + sizeof(struct symtab_command);
327 gSymbolTableAddr = AllocateKernelMemory(gSymbolTableSize);
328 // Add the SymTab to the memory-map.
329 AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr, gSymbolTableSize, -1);
330
331 symTableSave = (struct symtab_command *)gSymbolTableAddr;
332 tmpAddr = gSymbolTableAddr + sizeof(struct symtab_command);
333
334 symTableSave->symoff = tmpAddr;
335 symTableSave->nsyms = symTab->nsyms;
336 symTableSave->stroff = tmpAddr + symsSize;
337 symTableSave->strsize = symTab->strsize;
338
339 bcopy((char *)(gBinaryAddress + symTab->symoff),
340(char *)tmpAddr, totalSize);
341 return 0;
342}
343

Archive Download this file

Revision: 1808