Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Trunk/i386/libsaio/load.c

1/*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 *
5 * The contents of this file constitute Original Code as defined in and
6 * are subject to the Apple Public Source License Version 2.0 (the
7 * "License"). You may not use this file except in compliance with the
8 * License. Please obtain a copy of the License at
9 * http://www.apple.com/publicsource and read it before using this file.
10 *
11 * This Original Code and all software distributed under the License are
12 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
13 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
14 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
16 * License for the specific language governing rights and limitations
17 * under the License.
18 *
19 *
20 * load.c - Functions for decoding a Mach-o Kernel.
21 *
22 * Copyright (c) 1998-2003 Apple Computer, Inc.
23 *
24 */
25
26#include <mach-o/fat.h>
27#include <mach-o/loader.h>
28#include <mach/machine/thread_status.h>
29
30#include <sl.h>
31
32/*
33 * Backward compatibility fix for the SDK 10.7 version of loader.h
34 */
35
36#ifndef LC_MAIN
37#define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */
38#endif
39
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)
64{
65nfat = fhp->nfat_arch;
66swapped = 0;
67}
68else if (fhp->magic == FAT_CIGAM)
69{
70nfat = OSSwapInt32(fhp->nfat_arch);
71swapped = 1;
72}
73else
74{
75return -1;
76}
77
78for (; nfat > 0; nfat--, fap++)
79{
80if (swapped)
81{
82fapcputype = OSSwapInt32(fap->cputype);
83fapoffset = OSSwapInt32(fap->offset);
84fapsize = OSSwapInt32(fap->size);
85}
86else
87{
88fapcputype = fap->cputype;
89fapoffset = fap->offset;
90fapsize = fap->size;
91}
92
93if (fapcputype == archCpuType)
94{
95*binary = (void *) ((unsigned long)*binary + fapoffset);
96size = fapsize;
97break;
98}
99}
100
101if (length != 0)
102{
103*length = size;
104}
105
106return 0;
107}
108
109
110//==============================================================================
111
112long DecodeMachO(void *binary, entry_t *rentry, char **raddr, int *rsize)
113{
114struct mach_header *mH;
115unsigned long ncmds, cmdBase, cmd, cmdsize, cmdstart;
116// long headerBase, headerAddr, headerSize;
117unsigned int vmaddr = ~0;
118unsigned int vmend = 0;
119unsigned long cnt;
120long ret = -1;
121unsigned int entry = 0;
122
123gBinaryAddress = (unsigned long)binary;
124mH = (struct mach_header *)(gBinaryAddress);
125
126#if DEBUG
127printf("magic: %x\n", (unsigned)mH->magic);
128printf("cputype: %x\n", (unsigned)mH->cputype);
129printf("cpusubtype: %x\n", (unsigned)mH->cpusubtype);
130printf("filetype: %x\n", (unsigned)mH->filetype);
131printf("ncmds: %x\n", (unsigned)mH->ncmds);
132printf("sizeofcmds: %x\n", (unsigned)mH->sizeofcmds);
133printf("flags: %x\n", (unsigned)mH->flags);
134getchar();
135#endif
136
137switch (archCpuType)
138{
139case CPU_TYPE_I386:
140
141if (mH->magic != MH_MAGIC)
142{
143error("Mach-O file has bad magic number\n");
144return -1;
145}
146
147cmdstart = (unsigned long)gBinaryAddress + sizeof(struct mach_header);
148break;
149
150case CPU_TYPE_X86_64:
151
152if (mH->magic != MH_MAGIC_64 && mH->magic == MH_MAGIC)
153{
154return -1;
155}
156
157if (mH->magic != MH_MAGIC_64)
158{
159error("Mach-O file has bad magic number\n");
160return -1;
161}
162
163cmdstart = (unsigned long)gBinaryAddress + sizeof(struct mach_header_64);
164break;
165
166default:
167
168error("Unknown CPU type\n");
169return -1;
170}
171
172cmdBase = cmdstart;
173ncmds = mH->ncmds;
174
175for (cnt = 0; cnt < ncmds; cnt++)
176{
177cmd = ((long *)cmdBase)[0];
178cmdsize = ((long *)cmdBase)[1];
179unsigned int load_addr;
180unsigned int load_size;
181
182switch (cmd)
183{
184case LC_SEGMENT_64:
185case LC_SEGMENT:
186
187ret = DecodeSegment(cmdBase, &load_addr, &load_size);
188
189if (ret == 0 && load_size != 0 && load_addr >= KERNEL_ADDR)
190{
191vmaddr = MIN(vmaddr, load_addr);
192vmend = MAX(vmend, load_addr + load_size);
193}
194break;
195
196case LC_MAIN:/* Mountain Lion's replacement for LC_UNIXTHREAD */
197case LC_UNIXTHREAD:
198ret = DecodeUnixThread(cmdBase, &entry);
199break;
200
201case LC_SYMTAB:
202break;
203
204default:
205#if NOTDEF
206printf("Ignoring cmd type %d.\n", (unsigned)cmd);
207#endif
208 break;
209}
210
211
212if (ret != 0) return -1;
213
214cmdBase += cmdsize;
215}
216
217*rentry = (entry_t)( (unsigned long) entry & 0x3fffffff );
218*rsize = vmend - vmaddr;
219*raddr = (char *)vmaddr;
220
221cmdBase = cmdstart;
222
223for (cnt = 0; cnt < ncmds; cnt++)
224{
225cmd = ((long *)cmdBase)[0];
226cmdsize = ((long *)cmdBase)[1];
227
228if (cmd == LC_SYMTAB)
229 {
230if (DecodeSymbolTable(cmdBase) != 0)
231{
232return -1;
233}
234 }
235
236cmdBase += cmdsize;
237 }
238
239return ret;
240}
241
242
243//==============================================================================
244// Private function.
245
246
247static long DecodeSegment(long cmdBase, unsigned int *load_addr, unsigned int *load_size)
248{
249char *segname;
250long vmsize, filesize;
251unsigned long vmaddr, fileaddr;
252
253if (((long *)cmdBase)[0] == LC_SEGMENT_64)
254{
255struct segment_command_64 *segCmd;
256segCmd = (struct segment_command_64 *)cmdBase;
257vmaddr = (segCmd->vmaddr & 0x3fffffff);
258vmsize = segCmd->vmsize;
259fileaddr = (gBinaryAddress + segCmd->fileoff);
260filesize = segCmd->filesize;
261segname = segCmd->segname;
262
263#ifdef DEBUG
264 printf("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);
267 getchar();
268#endif
269}
270else
271{
272struct segment_command *segCmd;
273
274segCmd = (struct segment_command *)cmdBase;
275
276vmaddr = (segCmd->vmaddr & 0x3fffffff);
277vmsize = segCmd->vmsize;
278fileaddr = (gBinaryAddress + segCmd->fileoff);
279filesize = segCmd->filesize;
280segname = segCmd->segname;
281
282#ifdef DEBUG
283printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",
284segCmd->segname, (unsigned)vmaddr, (unsigned)vmsize, (unsigned)fileaddr, (unsigned)filesize, (unsigned) segCmd->nsects, (unsigned)segCmd->flags);
285getchar();
286#endif
287}
288
289if (vmsize == 0 || filesize == 0)
290{
291*load_addr = ~0;
292*load_size = 0;
293return 0;
294}
295
296if (! ((vmaddr >= KERNEL_ADDR && (vmaddr + vmsize) <= (KERNEL_ADDR + KERNEL_LEN)) ||
297 (vmaddr >= HIB_ADDR && (vmaddr + vmsize) <= (HIB_ADDR + HIB_LEN))))
298{
299stop("Kernel overflows available space");
300}
301
302if (vmsize && ((strcmp(segname, "__PRELINK_INFO") == 0) || (strcmp(segname, "__PRELINK") == 0)))
303{
304gHaveKernelCache = true;
305}
306
307// Copy from file load area.
308if (vmsize>0 && filesize>0)
309{
310bcopy((char *)fileaddr, (char *)vmaddr, vmsize>filesize?filesize:vmsize);
311}
312
313// Zero space at the end of the segment.
314if (vmsize > filesize)
315{
316bzero((char *)(vmaddr + filesize), vmsize - filesize);
317}
318
319*load_addr = vmaddr;
320*load_size = vmsize;
321
322return 0;
323}
324
325
326//==============================================================================
327
328static long DecodeUnixThread(long cmdBase, unsigned int *entry)
329{
330switch (archCpuType)
331{
332case CPU_TYPE_I386:
333{
334i386_thread_state_t *i386ThreadState;
335i386ThreadState = (i386_thread_state_t *) (cmdBase + sizeof(struct thread_command) + 8);
336
337*entry = i386ThreadState->eip;
338return 0;
339}
340
341case CPU_TYPE_X86_64:
342{
343x86_thread_state64_t *x86_64ThreadState;
344x86_64ThreadState = (x86_thread_state64_t *) (cmdBase + sizeof(struct thread_command) + 8);
345*entry = x86_64ThreadState->rip;
346return 0;
347}
348
349default:
350error("Unknown CPU type\n");
351return -1;
352}
353}
354
355
356//==============================================================================
357
358static long DecodeSymbolTable(long cmdBase)
359{
360long tmpAddr, symsSize, totalSize;
361long gSymbolTableAddr;
362long gSymbolTableSize;
363
364struct symtab_command *symTab, *symTableSave;
365
366symTab = (struct symtab_command *)cmdBase;
367
368#if DEBUG
369
370printf("symoff: %x, nsyms: %x, stroff: %x, strsize: %x\n", symTab->symoff, symTab->nsyms, symTab->stroff, symTab->strsize);
371getchar();
372#endif
373
374symsSize = symTab->stroff - symTab->symoff;
375totalSize = symsSize + symTab->strsize;
376
377gSymbolTableSize = totalSize + sizeof(struct symtab_command);
378gSymbolTableAddr = AllocateKernelMemory(gSymbolTableSize);
379// Add the SymTab to the memory-map.
380AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr, gSymbolTableSize, -1);
381
382symTableSave = (struct symtab_command *)gSymbolTableAddr;
383tmpAddr = gSymbolTableAddr + sizeof(struct symtab_command);
384
385symTableSave->symoff = tmpAddr;
386symTableSave->nsyms = symTab->nsyms;
387symTableSave->stroff = tmpAddr + symsSize;
388symTableSave->strsize = symTab->strsize;
389
390bcopy((char *)(gBinaryAddress + symTab->symoff), (char *)tmpAddr, totalSize);
391
392return 0;
393}
394

Archive Download this file

Revision: 2045