Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2706