/*
* macho.c - Functions for decoding a Mach-o Kernel.
*
- * Copyright (c) 1998-2000 Apple Computer, Inc.
+ * Copyright (c) 1998-2003 Apple Computer, Inc.
*
* DRI: Josh de Cesare
*/
+#define __srr0 srr0 // so we can build in both (conformant/not) worlds
#include <mach-o/fat.h>
#include <mach-o/loader.h>
#include <mach/machine/thread_status.h>
static long DecodeUnixThread(long cmdBase);
static long DecodeSymbolTable(long cmdBase);
-static long gPPCOffset;
+static unsigned long gPPCAddress;
// Public Functions
-long DecodeMachO(void)
+long ThinFatBinaryMachO(void **binary, unsigned long *length)
{
- struct fat_header *fH;
- struct fat_arch *fA;
- struct mach_header *mH;
- long ncmds, cmdBase, cmd, cmdsize, headerBase, headerAddr, headerSize;
- long cnt, ret;
-
- // Test for a fat header.
- fH = (struct fat_header *)kLoadAddr;
- if (fH->magic == FAT_MAGIC) {
- fA = (struct fat_arch *)(kLoadAddr + sizeof(struct fat_header));
- // see if the there is one for PPC.
- for (cnt = 0; cnt < fH->nfat_arch; cnt++) {
- if (fA[cnt].cputype == CPU_TYPE_POWERPC) {
- gPPCOffset = fA[cnt].offset;
- }
+ unsigned long nfat, swapped, size = 0;
+ struct fat_header *fhp = (struct fat_header *)*binary;
+ struct fat_arch *fap =
+ (struct fat_arch *)((unsigned long)*binary + sizeof(struct fat_header));
+
+ if (fhp->magic == FAT_MAGIC) {
+ nfat = fhp->nfat_arch;
+ swapped = 0;
+ } else if (fhp->magic == FAT_CIGAM) {
+ nfat = NXSwapInt(fhp->nfat_arch);
+ swapped = 1;
+ } else {
+ return -1;
+ }
+
+ for (; nfat > 0; nfat--, fap++) {
+ if (swapped) {
+ fap->cputype = NXSwapInt(fap->cputype);
+ fap->offset = NXSwapInt(fap->offset);
+ fap->size = NXSwapInt(fap->size);
+ }
+
+ if (fap->cputype == CPU_TYPE_POWERPC) {
+ *binary = (void *) ((unsigned long)*binary + fap->offset);
+ size = fap->size;
+ break;
}
}
- // offset will be the start of the
- headerBase = kLoadAddr + gPPCOffset;
- cmdBase = headerBase+ sizeof(struct mach_header);
+ if (length != 0) *length = size;
+
+ return 0;
+}
+
+long DecodeMachO(void *binary)
+{
+ struct mach_header *mH;
+ long ncmds, cmdBase, cmd, cmdsize, headerBase, headerAddr, headerSize;
+ long cnt, ret = 0;
+
+ gPPCAddress = (unsigned long)binary;
+
+ headerBase = gPPCAddress;
+ cmdBase = headerBase + sizeof(struct mach_header);
mH = (struct mach_header *)(headerBase);
if (mH->magic != MH_MAGIC) return -1;
vmaddr = (char *)segCmd->vmaddr;
vmsize = segCmd->vmsize;
- fileaddr = (char *)(kLoadAddr + gPPCOffset + segCmd->fileoff);
+ fileaddr = (char *)(gPPCAddress + segCmd->fileoff);
filesize = segCmd->filesize;
#if 0
// Add the Segment to the memory-map.
sprintf(rangeName, "Kernel-%s", segCmd->segname);
AllocateMemoryRange(rangeName, (long)vmaddr, vmsize);
+
+ if (vmsize && (strcmp(segCmd->segname, "__PRELINK") == 0))
+ gHaveKernelCache = 1;
// Handle special segments first.
static long DecodeUnixThread(long cmdBase)
{
- struct ppc_thread_state *ppcThreadState;
+ ppc_thread_state_t *ppcThreadState;
// The PPC Thread State starts after the thread command stuct plus,
// 2 longs for the flaver an num longs.
- ppcThreadState = (struct ppc_thread_state *)
+ ppcThreadState = (ppc_thread_state_t *)
(cmdBase + sizeof(struct thread_command) + 8);
gKernelEntryPoint = ppcThreadState->srr0;
symTableSave->stroff = tmpAddr + symsSize;
symTableSave->strsize = symTab->strsize;
- bcopy((char *)(kLoadAddr + gPPCOffset + symTab->symoff),
+ bcopy((char *)(gPPCAddress + symTab->symoff),
(char *)tmpAddr, totalSize);
return 0;