]>
git.saurik.com Git - apple/boot.git/blob - i386/libsaio/load.c
a5be78083b047b6bd59c819d0d67c3ef7384b08e
2 * Copyright (c) 2003 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 * load.c - Functions for decoding a Mach-o Kernel.
28 * Copyright (c) 1998-2003 Apple Computer, Inc.
32 #include <mach-o/fat.h>
33 #include <mach-o/loader.h>
34 #include <mach/machine/thread_status.h>
38 static long DecodeSegment(long cmdBase
, unsigned int*load_addr
, unsigned int *load_size
);
39 static long DecodeUnixThread(long cmdBase
, unsigned int *entry
);
42 static unsigned long gBinaryAddress
;
43 BOOL gHaveKernelCache
;
47 long ThinFatFile(void **binary
, unsigned long *length
)
49 unsigned long nfat
, swapped
, size
= 0;
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_I386
) {
72 *binary
= (void *) ((unsigned long)*binary
+ fap
->offset
);
78 if (length
!= 0) *length
= size
;
83 long DecodeMachO(void *binary
, entry_t
*rentry
, char **raddr
, int *rsize
)
85 struct mach_header
*mH
;
86 unsigned long ncmds
, cmdBase
, cmd
, cmdsize
;
87 // long headerBase, headerAddr, headerSize;
88 unsigned int vmaddr
= ~0;
89 unsigned int vmend
= 0;
94 gBinaryAddress
= (unsigned long)binary
;
96 // headerBase = gBinaryAddress;
97 cmdBase
= (unsigned long)gBinaryAddress
+ sizeof(struct mach_header
);
99 mH
= (struct mach_header
*)(gBinaryAddress
);
100 if (mH
->magic
!= MH_MAGIC
) {
101 error("Mach-O file has bad magic number\n");
106 printf("magic: %x\n", (unsigned)mH
->magic
);
107 printf("cputype: %x\n", (unsigned)mH
->cputype
);
108 printf("cpusubtype: %x\n", (unsigned)mH
->cpusubtype
);
109 printf("filetype: %x\n", (unsigned)mH
->filetype
);
110 printf("ncmds: %x\n", (unsigned)mH
->ncmds
);
111 printf("sizeofcmds: %x\n", (unsigned)mH
->sizeofcmds
);
112 printf("flags: %x\n", (unsigned)mH
->flags
);
118 for (cnt
= 0; cnt
< ncmds
; cnt
++) {
119 cmd
= ((long *)cmdBase
)[0];
120 cmdsize
= ((long *)cmdBase
)[1];
121 unsigned int load_addr
;
122 unsigned int load_size
;
127 ret
= DecodeSegment(cmdBase
, &load_addr
, &load_size
);
128 if (ret
== 0 && load_size
!= 0) {
129 vmaddr
= min(vmaddr
, load_addr
);
130 vmend
= max(vmend
, load_addr
+ load_size
);
135 ret
= DecodeUnixThread(cmdBase
, &entry
);
140 printf("Ignoring cmd type %d.\n", (unsigned)cmd
);
145 if (ret
!= 0) return -1;
150 *rentry
= (entry_t
)( (unsigned long) entry
& 0x3fffffff );
151 *rsize
= vmend
- vmaddr
;
152 *raddr
= (char *)vmaddr
;
159 static long DecodeSegment(long cmdBase
, unsigned int *load_addr
, unsigned int *load_size
)
161 struct segment_command
*segCmd
;
162 unsigned long vmaddr
, fileaddr
;
163 long vmsize
, filesize
;
165 segCmd
= (struct segment_command
*)cmdBase
;
167 vmaddr
= (segCmd
->vmaddr
& 0x3fffffff);
168 vmsize
= segCmd
->vmsize
;
170 fileaddr
= (gBinaryAddress
+ segCmd
->fileoff
);
171 filesize
= segCmd
->filesize
;
180 printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",
181 segCmd
->segname
, (unsigned)vmaddr
, (unsigned)vmsize
, (unsigned)fileaddr
, (unsigned)filesize
,
182 (unsigned) segCmd
->nsects
, (unsigned)segCmd
->flags
);
186 if (vmaddr
< KERNEL_ADDR
||
187 (vmaddr
+ vmsize
) > (KERNEL_ADDR
+ KERNEL_LEN
)) {
188 stop("Kernel overflows available space");
191 if (vmsize
&& (strcmp(segCmd
->segname
, "__PRELINK") == 0)) {
192 gHaveKernelCache
= 1;
195 // Copy from file load area.
196 bcopy((char *)fileaddr
, (char *)vmaddr
, filesize
);
198 // Zero space at the end of the segment.
199 bzero((char *)(vmaddr
+ filesize
), vmsize
- filesize
);
208 static long DecodeUnixThread(long cmdBase
, unsigned int *entry
)
210 i386_thread_state_t
*i386ThreadState
;
212 i386ThreadState
= (i386_thread_state_t
*)
213 (cmdBase
+ sizeof(struct thread_command
) + 8);
215 *entry
= i386ThreadState
->eip
;