]>
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 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * macho.c - Functions for decoding a Mach-o Kernel.
25 * Copyright (c) 1998-2003 Apple Computer, Inc.
30 #define __srr0 srr0 // so we can build in both (conformant/not) worlds
31 #include <mach-o/fat.h>
32 #include <mach-o/loader.h>
33 #include <mach/machine/thread_status.h>
37 static long DecodeSegment(long cmdBase
);
38 static long DecodeUnixThread(long cmdBase
);
39 static long DecodeSymbolTable(long cmdBase
);
41 static unsigned long gPPCAddress
;
45 long ThinFatBinaryMachO(void **binary
, unsigned long *length
)
47 unsigned long nfat
, swapped
, size
= 0;
48 struct fat_header
*fhp
= (struct fat_header
*)*binary
;
49 struct fat_arch
*fap
=
50 (struct fat_arch
*)((unsigned long)*binary
+ sizeof(struct fat_header
));
52 if (fhp
->magic
== FAT_MAGIC
) {
53 nfat
= fhp
->nfat_arch
;
55 } else if (fhp
->magic
== FAT_CIGAM
) {
56 nfat
= NXSwapInt(fhp
->nfat_arch
);
62 for (; nfat
> 0; nfat
--, fap
++) {
64 fap
->cputype
= NXSwapInt(fap
->cputype
);
65 fap
->offset
= NXSwapInt(fap
->offset
);
66 fap
->size
= NXSwapInt(fap
->size
);
69 if (fap
->cputype
== CPU_TYPE_POWERPC
) {
70 *binary
= (void *) ((unsigned long)*binary
+ fap
->offset
);
76 if (length
!= 0) *length
= size
;
81 long DecodeMachO(void *binary
)
83 struct mach_header
*mH
;
84 long ncmds
, cmdBase
, cmd
, cmdsize
, headerBase
, headerAddr
, headerSize
;
87 gPPCAddress
= (unsigned long)binary
;
89 headerBase
= gPPCAddress
;
90 cmdBase
= headerBase
+ sizeof(struct mach_header
);
92 mH
= (struct mach_header
*)(headerBase
);
93 if (mH
->magic
!= MH_MAGIC
) return -1;
96 printf("magic: %x\n", mH
->magic
);
97 printf("cputype: %x\n", mH
->cputype
);
98 printf("cpusubtype: %x\n", mH
->cpusubtype
);
99 printf("filetype: %x\n", mH
->filetype
);
100 printf("ncmds: %x\n", mH
->ncmds
);
101 printf("sizeofcmds: %x\n", mH
->sizeofcmds
);
102 printf("flags: %x\n", mH
->flags
);
107 for (cnt
= 0; cnt
< ncmds
; cnt
++) {
108 cmd
= ((long *)cmdBase
)[0];
109 cmdsize
= ((long *)cmdBase
)[1];
114 ret
= DecodeSegment(cmdBase
);
118 ret
= DecodeUnixThread(cmdBase
);
122 ret
= DecodeSymbolTable(cmdBase
);
126 printf("Ignoring cmd type %d.\n", cmd
);
130 if (ret
!= 0) return -1;
135 // Save the mach-o header.
136 headerSize
= cmdBase
- headerBase
;
137 headerAddr
= AllocateKernelMemory(headerSize
);
138 bcopy((char *)headerBase
, (char *)headerAddr
, headerSize
);
140 // Add the Mach-o header to the memory-map.
141 AllocateMemoryRange("Kernel-__HEADER", headerAddr
, headerSize
);
148 static long DecodeSegment(long cmdBase
)
150 struct segment_command
*segCmd
;
152 char *vmaddr
, *fileaddr
;
153 long vmsize
, filesize
;
155 segCmd
= (struct segment_command
*)cmdBase
;
157 vmaddr
= (char *)segCmd
->vmaddr
;
158 vmsize
= segCmd
->vmsize
;
160 fileaddr
= (char *)(gPPCAddress
+ segCmd
->fileoff
);
161 filesize
= segCmd
->filesize
;
164 printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",
165 segCmd
->segname
, vmaddr
, vmsize
, fileaddr
, filesize
,
166 segCmd
->nsects
, segCmd
->flags
);
169 // Add the Segment to the memory-map.
170 sprintf(rangeName
, "Kernel-%s", segCmd
->segname
);
171 AllocateMemoryRange(rangeName
, (long)vmaddr
, vmsize
);
173 if (vmsize
&& (strcmp(segCmd
->segname
, "__PRELINK") == 0))
174 gHaveKernelCache
= 1;
176 // Handle special segments first.
178 // If it is the vectors, save them in their special place.
179 if ((strcmp(segCmd
->segname
, "__VECTORS") == 0) &&
180 ((long)vmaddr
< (kVectorAddr
+ kVectorSize
)) &&
181 (vmsize
!= 0) && (filesize
!= 0)) {
183 // Copy the first part into the save area.
184 bcopy(fileaddr
, gVectorSaveAddr
,
185 (filesize
<= kVectorSize
) ? filesize
: kVectorSize
);
187 // Copy the rest into memory.
188 if (filesize
> kVectorSize
)
189 bcopy(fileaddr
+ kVectorSize
, (char *)kVectorSize
,
190 filesize
- kVectorSize
);
195 // It is nothing special, so do the usual. Only copy sections
196 // that have a filesize. Others are handle by the original bzero.
198 bcopy(fileaddr
, vmaddr
, filesize
);
201 // Adjust the last address used by the kernel
202 if ((long)vmaddr
+ vmsize
> AllocateKernelMemory(0)) {
203 AllocateKernelMemory((long)vmaddr
+ vmsize
- AllocateKernelMemory(0));
210 static long DecodeUnixThread(long cmdBase
)
212 ppc_thread_state_t
*ppcThreadState
;
214 // The PPC Thread State starts after the thread command stuct plus,
215 // 2 longs for the flaver an num longs.
216 ppcThreadState
= (ppc_thread_state_t
*)
217 (cmdBase
+ sizeof(struct thread_command
) + 8);
219 gKernelEntryPoint
= ppcThreadState
->srr0
;
222 printf("gKernelEntryPoint = %x\n", gKernelEntryPoint
);
229 static long DecodeSymbolTable(long cmdBase
)
231 struct symtab_command
*symTab
, *symTableSave
;
232 long tmpAddr
, symsSize
, totalSize
;
234 symTab
= (struct symtab_command
*)cmdBase
;
237 printf("symoff: %x, nsyms: %x, stroff: %x, strsize: %x\n",
238 symTab
->symoff
, symTab
->nsyms
, symTab
->stroff
, symTab
->strsize
);
241 symsSize
= symTab
->stroff
- symTab
->symoff
;
242 totalSize
= symsSize
+ symTab
->strsize
;
244 gSymbolTableSize
= totalSize
+ sizeof(struct symtab_command
);
245 gSymbolTableAddr
= AllocateKernelMemory(gSymbolTableSize
);
247 // Add the SymTab to the memory-map.
248 AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr
, gSymbolTableSize
);
250 symTableSave
= (struct symtab_command
*)gSymbolTableAddr
;
251 tmpAddr
= gSymbolTableAddr
+ sizeof(struct symtab_command
);
253 symTableSave
->symoff
= tmpAddr
;
254 symTableSave
->nsyms
= symTab
->nsyms
;
255 symTableSave
->stroff
= tmpAddr
+ symsSize
;
256 symTableSave
->strsize
= symTab
->strsize
;
258 bcopy((char *)(gPPCAddress
+ symTab
->symoff
),
259 (char *)tmpAddr
, totalSize
);