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

Archive Download this file

Revision: 2385