]>
git.saurik.com Git - apple/bootx.git/blob - bootx.tproj/sl.subproj/macho.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * macho.c - Functions for decoding a Mach-o Kernel.
28 * Copyright (c) 1998-2003 Apple Computer, Inc.
33 #include <mach-o/fat.h>
34 #include <mach-o/loader.h>
35 #include <mach/machine/thread_status.h>
39 static long DecodeSegment(long cmdBase
);
40 static long DecodeUnixThread(long cmdBase
);
41 static long DecodeSymbolTable(long cmdBase
);
43 static unsigned long gPPCAddress
;
47 long ThinFatBinaryMachO(void **binary
, unsigned long *length
)
49 unsigned long nfat
, swapped
, size
;
50 struct fat_header
*fhp
= (struct fat_header
*)*binary
;
51 struct fat_arch
*fap
=
52 (struct fat_arch
*)((unsigned long)*binary
+ sizeof(struct fat_header
));
54 if (fhp
->magic
== FAT_MAGIC
) {
55 nfat
= fhp
->nfat_arch
;
57 } else if (fhp
->magic
== FAT_CIGAM
) {
58 nfat
= NXSwapInt(fhp
->nfat_arch
);
64 for (; nfat
> 0; nfat
--, fap
++) {
66 fap
->cputype
= NXSwapInt(fap
->cputype
);
67 fap
->offset
= NXSwapInt(fap
->offset
);
68 fap
->size
= NXSwapInt(fap
->size
);
71 if (fap
->cputype
== CPU_TYPE_POWERPC
) {
72 *binary
= (void *) ((unsigned long)*binary
+ fap
->offset
);
78 if (length
!= 0) *length
= size
;
83 long DecodeMachO(void *binary
)
85 struct mach_header
*mH
;
86 long ncmds
, cmdBase
, cmd
, cmdsize
, headerBase
, headerAddr
, headerSize
;
89 gPPCAddress
= (unsigned long)binary
;
91 headerBase
= gPPCAddress
;
92 cmdBase
= headerBase
+ sizeof(struct mach_header
);
94 mH
= (struct mach_header
*)(headerBase
);
95 if (mH
->magic
!= MH_MAGIC
) return -1;
98 printf("magic: %x\n", mH
->magic
);
99 printf("cputype: %x\n", mH
->cputype
);
100 printf("cpusubtype: %x\n", mH
->cpusubtype
);
101 printf("filetype: %x\n", mH
->filetype
);
102 printf("ncmds: %x\n", mH
->ncmds
);
103 printf("sizeofcmds: %x\n", mH
->sizeofcmds
);
104 printf("flags: %x\n", mH
->flags
);
109 for (cnt
= 0; cnt
< ncmds
; cnt
++) {
110 cmd
= ((long *)cmdBase
)[0];
111 cmdsize
= ((long *)cmdBase
)[1];
116 ret
= DecodeSegment(cmdBase
);
120 ret
= DecodeUnixThread(cmdBase
);
124 ret
= DecodeSymbolTable(cmdBase
);
128 printf("Ignoring cmd type %d.\n", cmd
);
132 if (ret
!= 0) return -1;
137 // Save the mach-o header.
138 headerSize
= cmdBase
- headerBase
;
139 headerAddr
= AllocateKernelMemory(headerSize
);
140 bcopy((char *)headerBase
, (char *)headerAddr
, headerSize
);
142 // Add the Mach-o header to the memory-map.
143 AllocateMemoryRange("Kernel-__HEADER", headerAddr
, headerSize
);
150 static long DecodeSegment(long cmdBase
)
152 struct segment_command
*segCmd
;
154 char *vmaddr
, *fileaddr
;
155 long vmsize
, filesize
;
157 segCmd
= (struct segment_command
*)cmdBase
;
159 vmaddr
= (char *)segCmd
->vmaddr
;
160 vmsize
= segCmd
->vmsize
;
162 fileaddr
= (char *)(gPPCAddress
+ segCmd
->fileoff
);
163 filesize
= segCmd
->filesize
;
166 printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",
167 segCmd
->segname
, vmaddr
, vmsize
, fileaddr
, filesize
,
168 segCmd
->nsects
, segCmd
->flags
);
171 // Add the Segment to the memory-map.
172 sprintf(rangeName
, "Kernel-%s", segCmd
->segname
);
173 AllocateMemoryRange(rangeName
, (long)vmaddr
, vmsize
);
175 if (vmsize
&& (strcmp(segCmd
->segname
, "__PRELINK") == 0))
176 gHaveKernelCache
= 1;
178 // Handle special segments first.
180 // If it is the vectors, save them in their special place.
181 if ((strcmp(segCmd
->segname
, "__VECTORS") == 0) &&
182 ((long)vmaddr
< (kVectorAddr
+ kVectorSize
)) &&
183 (vmsize
!= 0) && (filesize
!= 0)) {
185 // Copy the first part into the save area.
186 bcopy(fileaddr
, gVectorSaveAddr
,
187 (filesize
<= kVectorSize
) ? filesize
: kVectorSize
);
189 // Copy the rest into memory.
190 if (filesize
> kVectorSize
)
191 bcopy(fileaddr
+ kVectorSize
, (char *)kVectorSize
,
192 filesize
- kVectorSize
);
197 // It is nothing special, so do the usual. Only copy sections
198 // that have a filesize. Others are handle by the original bzero.
200 bcopy(fileaddr
, vmaddr
, filesize
);
203 // Adjust the last address used by the kernel
204 if ((long)vmaddr
+ vmsize
> AllocateKernelMemory(0)) {
205 AllocateKernelMemory((long)vmaddr
+ vmsize
- AllocateKernelMemory(0));
212 static long DecodeUnixThread(long cmdBase
)
214 struct ppc_thread_state
*ppcThreadState
;
216 // The PPC Thread State starts after the thread command stuct plus,
217 // 2 longs for the flaver an num longs.
218 ppcThreadState
= (struct ppc_thread_state
*)
219 (cmdBase
+ sizeof(struct thread_command
) + 8);
221 gKernelEntryPoint
= ppcThreadState
->srr0
;
224 printf("gKernelEntryPoint = %x\n", gKernelEntryPoint
);
231 static long DecodeSymbolTable(long cmdBase
)
233 struct symtab_command
*symTab
, *symTableSave
;
234 long tmpAddr
, symsSize
, totalSize
;
236 symTab
= (struct symtab_command
*)cmdBase
;
239 printf("symoff: %x, nsyms: %x, stroff: %x, strsize: %x\n",
240 symTab
->symoff
, symTab
->nsyms
, symTab
->stroff
, symTab
->strsize
);
243 symsSize
= symTab
->stroff
- symTab
->symoff
;
244 totalSize
= symsSize
+ symTab
->strsize
;
246 gSymbolTableSize
= totalSize
+ sizeof(struct symtab_command
);
247 gSymbolTableAddr
= AllocateKernelMemory(gSymbolTableSize
);
249 // Add the SymTab to the memory-map.
250 AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr
, gSymbolTableSize
);
252 symTableSave
= (struct symtab_command
*)gSymbolTableAddr
;
253 tmpAddr
= gSymbolTableAddr
+ sizeof(struct symtab_command
);
255 symTableSave
->symoff
= tmpAddr
;
256 symTableSave
->nsyms
= symTab
->nsyms
;
257 symTableSave
->stroff
= tmpAddr
+ symsSize
;
258 symTableSave
->strsize
= symTab
->strsize
;
260 bcopy((char *)(gPPCAddress
+ symTab
->symoff
),
261 (char *)tmpAddr
, totalSize
);