Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 1984