Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2537