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

Archive Download this file

Revision: 2469