Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2323