Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazi/i386/libsaio/load.c

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

Archive Download this file

Revision: 621