]>
git.saurik.com Git - apple/boot.git/blob - i386/libsaio/load.c
77f9f8dd0feec29bd45637f4f0bcc8c8e803e379
2 * Copyright (c) 2003 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 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.
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 * load.c - Functions for decoding a Mach-o Kernel.
25 * Copyright (c) 1998-2003 Apple Computer, Inc.
29 #include <mach-o/fat.h>
30 #include <mach-o/loader.h>
31 #include <mach/machine/thread_status.h>
35 static long DecodeSegment(long cmdBase
, unsigned int*load_addr
, unsigned int *load_size
);
36 static long DecodeUnixThread(long cmdBase
, unsigned int *entry
);
39 static unsigned long gBinaryAddress
;
40 BOOL gHaveKernelCache
;
44 long ThinFatFile(void **binary
, unsigned long *length
)
46 unsigned long nfat
, swapped
, size
= 0;
47 struct fat_header
*fhp
= (struct fat_header
*)*binary
;
48 struct fat_arch
*fap
=
49 (struct fat_arch
*)((unsigned long)*binary
+ sizeof(struct fat_header
));
51 if (fhp
->magic
== FAT_MAGIC
) {
52 nfat
= fhp
->nfat_arch
;
54 } else if (fhp
->magic
== FAT_CIGAM
) {
55 nfat
= OSSwapInt32(fhp
->nfat_arch
);
61 for (; nfat
> 0; nfat
--, fap
++) {
63 fap
->cputype
= OSSwapInt32(fap
->cputype
);
64 fap
->offset
= OSSwapInt32(fap
->offset
);
65 fap
->size
= OSSwapInt32(fap
->size
);
68 if (fap
->cputype
== CPU_TYPE_I386
) {
69 *binary
= (void *) ((unsigned long)*binary
+ fap
->offset
);
75 if (length
!= 0) *length
= size
;
80 long DecodeMachO(void *binary
, entry_t
*rentry
, char **raddr
, int *rsize
)
82 struct mach_header
*mH
;
83 unsigned long ncmds
, cmdBase
, cmd
, cmdsize
;
84 // long headerBase, headerAddr, headerSize;
85 unsigned int vmaddr
= ~0;
86 unsigned int vmend
= 0;
91 gBinaryAddress
= (unsigned long)binary
;
93 // headerBase = gBinaryAddress;
94 cmdBase
= (unsigned long)gBinaryAddress
+ sizeof(struct mach_header
);
96 mH
= (struct mach_header
*)(gBinaryAddress
);
97 if (mH
->magic
!= MH_MAGIC
) {
98 error("Mach-O file has bad magic number\n");
103 printf("magic: %x\n", (unsigned)mH
->magic
);
104 printf("cputype: %x\n", (unsigned)mH
->cputype
);
105 printf("cpusubtype: %x\n", (unsigned)mH
->cpusubtype
);
106 printf("filetype: %x\n", (unsigned)mH
->filetype
);
107 printf("ncmds: %x\n", (unsigned)mH
->ncmds
);
108 printf("sizeofcmds: %x\n", (unsigned)mH
->sizeofcmds
);
109 printf("flags: %x\n", (unsigned)mH
->flags
);
115 for (cnt
= 0; cnt
< ncmds
; cnt
++) {
116 cmd
= ((long *)cmdBase
)[0];
117 cmdsize
= ((long *)cmdBase
)[1];
118 unsigned int load_addr
;
119 unsigned int load_size
;
124 ret
= DecodeSegment(cmdBase
, &load_addr
, &load_size
);
125 if (ret
== 0 && load_size
!= 0 && load_addr
>= KERNEL_ADDR
) {
126 vmaddr
= min(vmaddr
, load_addr
);
127 vmend
= max(vmend
, load_addr
+ load_size
);
132 ret
= DecodeUnixThread(cmdBase
, &entry
);
137 printf("Ignoring cmd type %d.\n", (unsigned)cmd
);
142 if (ret
!= 0) return -1;
147 *rentry
= (entry_t
)( (unsigned long) entry
& 0x3fffffff );
148 *rsize
= vmend
- vmaddr
;
149 *raddr
= (char *)vmaddr
;
156 static long DecodeSegment(long cmdBase
, unsigned int *load_addr
, unsigned int *load_size
)
158 struct segment_command
*segCmd
;
159 unsigned long vmaddr
, fileaddr
;
160 long vmsize
, filesize
;
162 segCmd
= (struct segment_command
*)cmdBase
;
164 vmaddr
= (segCmd
->vmaddr
& 0x3fffffff);
165 vmsize
= segCmd
->vmsize
;
167 fileaddr
= (gBinaryAddress
+ segCmd
->fileoff
);
168 filesize
= segCmd
->filesize
;
177 printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",
178 segCmd
->segname
, (unsigned)vmaddr
, (unsigned)vmsize
, (unsigned)fileaddr
, (unsigned)filesize
,
179 (unsigned) segCmd
->nsects
, (unsigned)segCmd
->flags
);
183 if (! ((vmaddr
>= KERNEL_ADDR
&&
184 (vmaddr
+ vmsize
) <= (KERNEL_ADDR
+ KERNEL_LEN
)) ||
185 (vmaddr
>= HIB_ADDR
&&
186 (vmaddr
+ vmsize
) <= (HIB_ADDR
+ HIB_LEN
)))) {
187 stop("Kernel overflows available space");
190 if (vmsize
&& (strcmp(segCmd
->segname
, "__PRELINK") == 0)) {
191 gHaveKernelCache
= 1;
194 // Copy from file load area.
195 bcopy((char *)fileaddr
, (char *)vmaddr
, filesize
);
197 // Zero space at the end of the segment.
198 bzero((char *)(vmaddr
+ filesize
), vmsize
- filesize
);
207 static long DecodeUnixThread(long cmdBase
, unsigned int *entry
)
209 i386_thread_state_t
*i386ThreadState
;
211 i386ThreadState
= (i386_thread_state_t
*)
212 (cmdBase
+ sizeof(struct thread_command
) + 8);
214 *entry
= i386ThreadState
->eip
;