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

Archive Download this file

Revision: 1468