Beispiel #1
0
unsigned long Adler32(unsigned char *buf, long len)
{
	#define BASE 65521L // largest prime smaller than 65536
	#define NMAX 5000
	// NMAX (was 5521) the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
	
	#define DO1(buf, i)  {s1 += buf[i]; s2 += s1;}
	#define DO2(buf, i)  DO1(buf, i); DO1(buf, i + 1);
	#define DO4(buf, i)  DO2(buf, i); DO2(buf, i + 2);
	#define DO8(buf, i)  DO4(buf, i); DO4(buf, i + 4);
	#define DO16(buf)   DO8(buf, 0); DO8(buf, 8);

	int k;

	unsigned long s1 = 1;	// adler & 0xffff;
	unsigned long s2 = 0;	// (adler >> 16) & 0xffff;
	unsigned long result;

	
	while (len > 0)
	{
		k = len < NMAX ? len : NMAX;
		len -= k;

        while (k >= 16)
		{
			DO16(buf);
			buf += 16;
			k -= 16;
		}

		if (k != 0)
		{
			do
			{
				s1 += *buf++;
				s2 += s1;
			} while (--k);
		}

		s1 %= BASE;
		s2 %= BASE;
	}

	result = (s2 << 16) | s1;

	return OSSwapHostToBigInt32(result);
}
Beispiel #2
0
// Most of this is stolen from Apple's CAStreamBasicDescription::Print()
std::ostream& operator<<(std::ostream& out, const AudioStreamBasicDescription& format)
{
	unsigned char formatID [5];
	*(UInt32 *)formatID = OSSwapHostToBigInt32(format.mFormatID);
	formatID[4] = '\0';
	
	// General description
	out << format.mChannelsPerFrame << " ch, " << format.mSampleRate << " Hz, '" << formatID << "' (0x" << std::hex << std::setw(8) << std::setfill('0') << format.mFormatFlags << std::dec << ") ";
	
	if(kAudioFormatLinearPCM == format.mFormatID) {
		// Bit depth
		UInt32 fractionalBits = ((0x3f << 7)/*kLinearPCMFormatFlagsSampleFractionMask*/ & format.mFormatFlags) >> 7/*kLinearPCMFormatFlagsSampleFractionShift*/;
		if(0 < fractionalBits)
			out << (format.mBitsPerChannel - fractionalBits) << "." << fractionalBits;
		else
			out << format.mBitsPerChannel;
		
		out << "-bit";
		
		// Endianness
		bool isInterleaved = !(kAudioFormatFlagIsNonInterleaved & format.mFormatFlags);
		UInt32 interleavedChannelCount = (isInterleaved ? format.mChannelsPerFrame : 1);
		UInt32 sampleSize = (0 < format.mBytesPerFrame && 0 < interleavedChannelCount ? format.mBytesPerFrame / interleavedChannelCount : 0);
		if(1 < sampleSize)
			out << ((kLinearPCMFormatFlagIsBigEndian & format.mFormatFlags) ? " big-endian" : " little-endian");
		
		// Sign
		bool isInteger = !(kLinearPCMFormatFlagIsFloat & format.mFormatFlags);
		if(isInteger)
			out << ((kLinearPCMFormatFlagIsSignedInteger & format.mFormatFlags) ? " signed" : " unsigned");
		
		// Integer or floating
		out << (isInteger ? " integer" : " float");
		
		// Packedness
		if(0 < sampleSize && ((sampleSize << 3) != format.mBitsPerChannel))
			out << ((kLinearPCMFormatFlagIsPacked & format.mFormatFlags) ? ", packed in " : ", unpacked in ") << sampleSize << " bytes";
		
		// Alignment
		if((0 < sampleSize && ((sampleSize << 3) != format.mBitsPerChannel)) || (0 != (format.mBitsPerChannel & 7)))
			out << ((kLinearPCMFormatFlagIsAlignedHigh & format.mFormatFlags) ? " high-aligned" : " low-aligned");
		
		if(!isInterleaved)
			out << ", deinterleaved";
	}
void IOFireWireIRM::allocateBroadcastChannel( void )
{
	IOReturn status = kIOReturnSuccess;
	
	FWLOCALKLOG(( "IOFireWireIRM::allocateBroadcastChannel() - attempting to allocate broadcast channel\n" ));

	FWAddress address( kCSRRegisterSpaceBaseAddressHi, kCSRChannelsAvailable31_0 );
	address.nodeID = fIRMNodeID;

	UInt32 host_channels_available = OSSwapBigToHostInt32( fOldChannelsAvailable31_0 );
	host_channels_available &= ~kChannel31Mask;
	fNewChannelsAvailable31_0 = OSSwapHostToBigInt32( host_channels_available );
	
	fLockCmd->reinit( fGeneration, address, &fOldChannelsAvailable31_0, &fNewChannelsAvailable31_0, 1, IOFireWireIRM::lockCompleteStatic, this );
	
	// the standard async commands call complete with an error before
	// returning an error from submit. 
	
	fLockCmdInUse = true;
	status = fLockCmd->submit();
}
IOReturn IOFireWirePCRSpace::updatePlug(UInt32 plug, UInt32 oldVal, UInt32 newVal)
{
	//IOLog( "IOFireWirePCRSpace::updatePlug (0x%08X)\n",(int) this);

	IOReturn res;
    fControl->closeGate();
    if(oldVal == OSSwapBigToHostInt32(fBuf[plug])) {
        fBuf[plug] = OSSwapHostToBigInt32(newVal);
        res = kIOReturnSuccess;

		// Notify target space object of plug value modification
		if ((fAVCTargetSpace) && (plug > 0) && (plug < 32))
			fAVCTargetSpace->pcrModified(IOFWAVCPlugIsochOutputType,(plug-1),newVal);
		else if ((fAVCTargetSpace) && (plug > 32) && (plug < 64))
			fAVCTargetSpace->pcrModified(IOFWAVCPlugIsochInputType,(plug-33),newVal);
    }
    else
        res = kIOReturnCannotLock;
    fControl->openGate();
    return res;
}
bool IOFireWireIRM::initWithController(IOFireWireController * control)
{
	IOReturn status = kIOReturnSuccess;
	
	bool success = OSObject::init();
	FWPANICASSERT( success == true );
	
	fControl = control;

	fIRMNodeID = kFWBadNodeID;
	fOurNodeID = kFWBadNodeID;
	fGeneration = 0;
	
	//
    // create BROADCAST_CHANNEL register
	//
	
	fBroadcastChannelBuffer = OSSwapHostToBigInt32( kBroadcastChannelInitialValues );
    fBroadcastChannelAddressSpace = IOFWPseudoAddressSpace::simpleRWFixed( fControl, FWAddress(kCSRRegisterSpaceBaseAddressHi, kCSRBroadcastChannel), 
																			 sizeof(fBroadcastChannelBuffer), &fBroadcastChannelBuffer );
	FWPANICASSERT( fBroadcastChannelAddressSpace != NULL );
    
	status = fBroadcastChannelAddressSpace->activate();
	FWPANICASSERT( status == kIOReturnSuccess );

	//
	// create lock command
	//
	
	fLockCmdInUse = false;
	fLockCmd = OSTypeAlloc( IOFWCompareAndSwapCommand );
	FWPANICASSERT( fLockCmd != NULL );
	fLockCmd->initAll( fControl, 0, FWAddress(), NULL, NULL, 0, IOFireWireIRM::lockCompleteStatic, this );

	FWLOCALKLOG(( "IOFireWireIRM::initWithController() - IRM intialized\n" ));

	return true;
}
/*
 * acl_t -> external representation, portable endianity
 */
ssize_t
acl_copy_ext(void *buf, acl_t acl, ssize_t size)
{
	struct kauth_filesec *ext = (struct kauth_filesec *)buf;
	ssize_t		reqsize;
	int		i;

	/* validate arguments, compute required size */
	reqsize = acl_size(acl);
	if (reqsize < 0)
		return(-1);
	if (reqsize > size) {
		errno = ERANGE;
		return(-1);
	}

	bzero(ext, reqsize);
	ext->fsec_magic = OSSwapHostToBigInt32(KAUTH_FILESEC_MAGIC);

	/* special case for _FILESEC_REMOVE_ACL */
	if (acl == (acl_t)_FILESEC_REMOVE_ACL) {
		ext->fsec_entrycount = OSSwapHostToBigInt32(KAUTH_FILESEC_NOACL);
		return(reqsize);
	}
		
	/* export the header */
	ext->fsec_entrycount = OSSwapHostToBigInt32(acl->a_entries);
	ext->fsec_flags = OSSwapHostToBigInt32(acl->a_flags);
	
	/* copy ACEs */
	for (i = 0; i < acl->a_entries; i++) {
		/* ACE contents are almost identical */
		ext->fsec_ace[i].ace_applicable = acl->a_ace[i].ae_applicable;
		ext->fsec_ace[i].ace_flags =
		    OSSwapHostToBigInt32((acl->a_ace[i].ae_tag & KAUTH_ACE_KINDMASK) | (acl->a_ace[i].ae_flags & ~KAUTH_ACE_KINDMASK));
		ext->fsec_ace[i].ace_rights = OSSwapHostToBigInt32(acl->a_ace[i].ae_perms);
	}		

	return(reqsize);
}
CFDataRef createMkext1ForArch(const NXArchInfo * arch, CFArrayRef archiveKexts,
    boolean_t compress)
{
    CFMutableDataRef       result            = NULL;
    CFMutableDictionaryRef kextsByIdentifier = NULL;
    Mkext1Context          context;
    mkext1_header        * mkextHeader       = NULL;  // do not free
    const uint8_t        * adler_point = 0;
    CFIndex count, i;

    result = CFDataCreateMutable(kCFAllocatorDefault, /* capaacity */ 0);
    if (!result || !createCFMutableDictionary(&kextsByIdentifier)) {
        OSKextLogMemError();
        goto finish;
    }

   /* mkext1 can only contain 1 kext for a given bundle identifier, so we
    * have to pick out the most recent versions.
    */
    count = CFArrayGetCount(archiveKexts);
    for (i = 0; i < count; i++) {
        OSKextRef   theKext = (OSKextRef)CFArrayGetValueAtIndex(archiveKexts, i);
        CFStringRef bundleIdentifier = OSKextGetIdentifier(theKext);
        OSKextRef   savedKext = (OSKextRef)CFDictionaryGetValue(kextsByIdentifier,
            bundleIdentifier);
        OSKextVersion thisVersion, savedVersion;


        if (!OSKextSupportsArchitecture(theKext, arch)) {
            continue;
        }

        if (!savedKext) {
            CFDictionarySetValue(kextsByIdentifier, bundleIdentifier, theKext);
            continue;
        }
        
        thisVersion = OSKextGetVersion(theKext);
        savedVersion = OSKextGetVersion(savedKext);
        
        if (thisVersion > savedVersion) {
            CFDictionarySetValue(kextsByIdentifier, bundleIdentifier, theKext);
        }
    }

   /* Add room for the mkext header and kext descriptors.
    */
    CFDataSetLength(result, sizeof(mkext1_header) +
        CFDictionaryGetCount(kextsByIdentifier) * sizeof(mkext_kext));

    context.mkext = result;
    context.kextIndex = 0;
    context.compressOffset = (uint32_t)CFDataGetLength(result);
    context.arch = arch;
    context.fatal = false;
    context.compress = compress;
    CFDictionaryApplyFunction(kextsByIdentifier, addToMkext1, &context);
    if (context.fatal) {
        SAFE_RELEASE_NULL(result);
        goto finish;
    }

    mkextHeader = (mkext1_header *)CFDataGetBytePtr(result);
    mkextHeader->magic = OSSwapHostToBigInt32(MKEXT_MAGIC);
    mkextHeader->signature = OSSwapHostToBigInt32(MKEXT_SIGN);
    mkextHeader->version = OSSwapHostToBigInt32(0x01008000);   // 'vers' 1.0.0
    mkextHeader->numkexts =
        OSSwapHostToBigInt32((__uint32_t)CFDictionaryGetCount(kextsByIdentifier));
    mkextHeader->cputype = OSSwapHostToBigInt32(arch->cputype);
    mkextHeader->cpusubtype = OSSwapHostToBigInt32(arch->cpusubtype);
    mkextHeader->length = OSSwapHostToBigInt32((__uint32_t)CFDataGetLength(result));

    adler_point = (UInt8 *)&mkextHeader->version;
    mkextHeader->adler32 = OSSwapHostToBigInt32(local_adler32(
        (UInt8 *)&mkextHeader->version,
        (int)(CFDataGetLength(result) - (adler_point - (uint8_t *)mkextHeader))));

    OSKextLog(/* kext */ NULL, kOSKextLogProgressLevel | kOSKextLogArchiveFlag,
        "Created mkext for %s containing %lu kexts.",
        arch->name,
        CFDictionaryGetCount(kextsByIdentifier));

finish:
    SAFE_RELEASE(kextsByIdentifier);
    return result;
}
Beispiel #8
0
MODULE_SCOPE int
TclpLoadMemory(
    Tcl_Interp *interp,		/* Used for error reporting. */
    void *buffer,		/* Buffer containing the desired code
				 * (allocated with TclpLoadMemoryGetBuffer). */
    int size,			/* Allocation size of buffer. */
    int codeSize,		/* Size of code data read into buffer or -1 if
				 * an error occurred and the buffer should
				 * just be freed. */
    Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
				 * file which will be passed back to
				 * (*unloadProcPtr)() to unload the file. */
    Tcl_FSUnloadFileProc **unloadProcPtr)
				/* Filled with address of Tcl_FSUnloadFileProc
				 * function which should be used for this
				 * file. */
{
    Tcl_DyldLoadHandle *dyldLoadHandle;
    NSObjectFileImage dyldObjFileImage = NULL;
    Tcl_DyldModuleHandle *modulePtr;
    NSModule module;
    const char *objFileImageErrMsg = NULL;

    /*
     * Try to create an object file image that we can load from.
     */

    if (codeSize >= 0) {
	NSObjectFileImageReturnCode err = NSObjectFileImageSuccess;
	const struct fat_header *fh = buffer;
	uint32_t ms = 0;
#ifndef __LP64__
	const struct mach_header *mh = NULL;
	#define mh_size  sizeof(struct mach_header)
	#define mh_magic MH_MAGIC
	#define arch_abi 0
#else
	const struct mach_header_64 *mh = NULL;
	#define mh_size  sizeof(struct mach_header_64)
	#define mh_magic MH_MAGIC_64
	#define arch_abi CPU_ARCH_ABI64
#endif

	if ((size_t) codeSize >= sizeof(struct fat_header)
		&& fh->magic == OSSwapHostToBigInt32(FAT_MAGIC)) {
	    uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch);

	    /*
	     * Fat binary, try to find mach_header for our architecture
	     */

	    TclLoadDbgMsg("Fat binary, %d archs", fh_nfat_arch);
	    if ((size_t) codeSize >= sizeof(struct fat_header) +
		    fh_nfat_arch * sizeof(struct fat_arch)) {
		void *fatarchs = (char*)buffer + sizeof(struct fat_header);
		const NXArchInfo *arch = NXGetLocalArchInfo();
		struct fat_arch *fa;

		if (fh->magic != FAT_MAGIC) {
		    swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
		}
		fa = NXFindBestFatArch(arch->cputype | arch_abi,
			arch->cpusubtype, fatarchs, fh_nfat_arch);
		if (fa) {
		    TclLoadDbgMsg("NXFindBestFatArch() successful: "
			    "local cputype %d subtype %d, "
			    "fat cputype %d subtype %d",
			    arch->cputype | arch_abi, arch->cpusubtype,
			    fa->cputype, fa->cpusubtype);
		    mh = (void*)((char*)buffer + fa->offset);
		    ms = fa->size;
		} else {
		    TclLoadDbgMsg("NXFindBestFatArch() failed");
		    err = NSObjectFileImageInappropriateFile;
		}
		if (fh->magic != FAT_MAGIC) {
		    swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
		}
	    } else {
		TclLoadDbgMsg("Fat binary header failure");
		err = NSObjectFileImageInappropriateFile;
	    }
	} else {
	    /*
	     * Thin binary
	     */

	    TclLoadDbgMsg("Thin binary");
	    mh = buffer;
	    ms = codeSize;
	}
	if (ms && !(ms >= mh_size && mh->magic == mh_magic &&
		 mh->filetype == MH_BUNDLE)) {
	    TclLoadDbgMsg("Inappropriate file: magic %x filetype %d",
		    mh->magic, mh->filetype);
	    err = NSObjectFileImageInappropriateFile;
	}
	if (err == NSObjectFileImageSuccess) {
	    err = NSCreateObjectFileImageFromMemory(buffer, codeSize,
		    &dyldObjFileImage);
	    if (err == NSObjectFileImageSuccess) {
		TclLoadDbgMsg("NSCreateObjectFileImageFromMemory() "
			"successful");
	    } else {
		objFileImageErrMsg = DyldOFIErrorMsg(err);
		TclLoadDbgMsg("NSCreateObjectFileImageFromMemory() failed: %s",
			objFileImageErrMsg);
	    }
	} else {
	    objFileImageErrMsg = DyldOFIErrorMsg(err);
	}
    }

    /*
     * If it went wrong (or we were asked to just deallocate), get rid of the
     * memory block and create an error message.
     */

    if (dyldObjFileImage == NULL) {
	vm_deallocate(mach_task_self(), (vm_address_t) buffer, size);
	if (objFileImageErrMsg != NULL) {
	    Tcl_AppendResult(interp, "NSCreateObjectFileImageFromMemory() "
		    "error: ", objFileImageErrMsg, NULL);
	}
	return TCL_ERROR;
    }

    /*
     * Extract the module we want from the image of the object file.
     */

    module = NSLinkModule(dyldObjFileImage, "[Memory Based Bundle]",
	    NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
    NSDestroyObjectFileImage(dyldObjFileImage);
    if (module) {
	TclLoadDbgMsg("NSLinkModule() successful");
    } else {
	NSLinkEditErrors editError;
	int errorNumber;
	const char *errorName, *errMsg;

	NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
	TclLoadDbgMsg("NSLinkModule() failed: %s", errMsg);
	Tcl_AppendResult(interp, errMsg, NULL);
	return TCL_ERROR;
    }

    /*
     * Stash the module reference within the load handle we create and return.
     */

    modulePtr = (Tcl_DyldModuleHandle *) ckalloc(sizeof(Tcl_DyldModuleHandle));
    modulePtr->module = module;
    modulePtr->nextPtr = NULL;
    dyldLoadHandle = (Tcl_DyldLoadHandle *)
	    ckalloc(sizeof(Tcl_DyldLoadHandle));
#if TCL_DYLD_USE_DLFCN
    dyldLoadHandle->dlHandle = NULL;
#endif
    dyldLoadHandle->dyldLibHeader = NULL;
    dyldLoadHandle->modulePtr = modulePtr;
    *loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
    *unloadProcPtr = &TclpUnloadFile;
    return TCL_OK;
}
Beispiel #9
0
int main ( int argc, char **argv){

    unsigned long *itArray;
    MandelbrotIterationRec	info;
    int xLoc, yLoc, width, height;
    int useVector;
    int vectorTypeAvailable;
    int hasAltivec = FALSE;
    
    int counter = 1;
	
    if ( argc != 11){
        fprintf( stderr, "Usage: \n%s xLocInPixels yLocInPixels pixWidth pixHeight imgWidthFloat imgHeightFloat imgLeftFloat imgTopFloat maxIterations useAltivec[0|1]\n",argv[0]);
        exit(-1);
    }

    xLoc = atoi(argv[1]);
    yLoc = atoi(argv[2]);
    width = atoi(argv[3]);
    height = atoi(argv[4]);
    
    itArray = (unsigned long *)malloc( sizeof(long) * width * height );

    info.itArray   = itArray;
    info.pixwidth  = width;
    info.pixheight = height ;
    info.imgwidth  = atof( argv[5] ) ;
    info.imgheight = atof( argv[6] ) ;
    info.imgleft   = atof( argv[7] ) ;
    info.imgtop    = atof( argv[8] ) ;
    info.maxIterations = atoi( argv[9] );

    useVector = atoi( argv[10] );

    vectorTypeAvailable = GetVectorTypeAvailable();
    
    if (vectorTypeAvailable == kAltiVec) hasAltivec = TRUE;
    
    while (counter--) {
    
        if (useVector && hasAltivec) {
                vectorcalc(&info);
        } else {
                scalarcalc(&info);
        }

    }
    
    uint32_t xLocSwapped = OSSwapHostToBigInt32(xLoc);
    uint32_t yLocSwapped = OSSwapHostToBigInt32(yLoc);
    uint32_t widthSwapped = OSSwapHostToBigInt32(width);
    uint32_t heightSwapped = OSSwapHostToBigInt32(height);
    
    fwrite( &xLocSwapped,   sizeof(uint32_t), 1, stdout);
    fwrite( &yLocSwapped,   sizeof(uint32_t), 1, stdout);
    fwrite( &widthSwapped,  sizeof(uint32_t), 1, stdout);
    fwrite( &heightSwapped, sizeof(uint32_t), 1, stdout);

    fwrite(info.itArray, sizeof(long), info.pixwidth * info.pixheight, stdout);

    return 0;
}
Beispiel #10
0
uint32_t tobe32(uint32_t x) { return OSSwapHostToBigInt32(x);    }
static void	RunTalkingDCLEngine( UInt32* packetHeader, DCLCommand** ppCurrentDCLCommand, 
		UInt8** pPacketBuffer, UInt32* pPacketSize, bool* pGetNextPacket)
{
	DCLCommand*				pCurrentDCLCommand;
	DCLCallProc*			pDCLCallProc;
	DCLJump*				pDCLJump;
	DCLSetTagSyncBits*		pDCLSetTagSyncBits;
	UInt32					host_header;
	
	// Run the current DCL command.
	pCurrentDCLCommand = *ppCurrentDCLCommand;
	switch (pCurrentDCLCommand->opcode & ~kFWDCLOpFlagMask)
	{
		case kDCLSendPacketStartOp :
		case kDCLSendPacketOp :
			DCLSendPacket (
							 &pCurrentDCLCommand,
							 pPacketBuffer,
							 pPacketSize,
							 pGetNextPacket);
			break;

		case kDCLSendBufferOp :
			DCLSendBuffer (
							 &pCurrentDCLCommand,
							 pPacketBuffer,
							 pPacketSize,
							 pGetNextPacket);
			break;

		case kDCLCallProcOp :
                        pDCLCallProc = (DCLCallProc*) pCurrentDCLCommand;
                        // Call the handler if there is one.
                        if (pDCLCallProc->proc != NULL)
                            (*(pDCLCallProc->proc)) ((DCLCommand*) pDCLCallProc);
			pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
			*pGetNextPacket = false;
			break;

		case kDCLJumpOp :
			pDCLJump = (DCLJump*) pCurrentDCLCommand;
			pCurrentDCLCommand = (DCLCommand*) pDCLJump->pJumpDCLLabel;
			*pGetNextPacket = false;
			break;

		case kDCLLabelOp :
			pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
			*pGetNextPacket = false;
			break;

		case kDCLSetTagSyncBitsOp :
			pDCLSetTagSyncBits = (DCLSetTagSyncBits*) pCurrentDCLCommand;
			host_header = OSSwapBigToHostInt32( *packetHeader );
			host_header &= ~(kFWIsochTag | kFWIsochSy);
			host_header |= (pDCLSetTagSyncBits->tagBits << kFWIsochTagPhase);
			host_header |= (pDCLSetTagSyncBits->syncBits << kFWIsochSyPhase);
			*packetHeader = OSSwapHostToBigInt32( host_header );
			pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
			*pGetNextPacket = false;
			break;

		default :
			pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
			*pGetNextPacket = false;
			break;
	}

	// Update current DCL command.
	*ppCurrentDCLCommand = pCurrentDCLCommand;
}
Beispiel #12
0
int main(int argc, char * const argv[])
{
    ExitStatus           result             = EX_SOFTWARE;
    KctoolArgs           toolArgs;
    int                  kernelcache_fd     = -1;  // must close()
    void               * fat_header         = NULL;  // must unmapFatHeaderPage()
    struct fat_arch    * fat_arch           = NULL;
    CFDataRef            rawKernelcache     = NULL;  // must release
    CFDataRef            kernelcacheImage   = NULL;  // must release

    void               * prelinkInfoSect    = NULL;

    const char         * prelinkInfoBytes   = NULL;
    CFPropertyListRef    prelinkInfoPlist   = NULL;  // must release

    bzero(&toolArgs, sizeof(toolArgs));

   /*****
    * Find out what the program was invoked as.
    */
    progname = rindex(argv[0], '/');
    if (progname) {
        progname++;   // go past the '/'
    } else {
        progname = (char *)argv[0];
    }

   /* Set the OSKext log callback right away.
    */
    OSKextSetLogOutputFunction(&tool_log);

   /*****
    * Process args & check for permission to load.
    */
    result = readArgs(&argc, &argv, &toolArgs);
    if (result != EX_OK) {
        if (result == kKctoolExitHelp) {
            result = EX_OK;
        }
        goto finish;
    }

    kernelcache_fd = open(toolArgs.kernelcachePath, O_RDONLY);
    if (kernelcache_fd == -1) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
            "Can't open %s: %s.", toolArgs.kernelcachePath, strerror(errno));
        result = EX_OSERR;
        goto finish;
    }
    fat_header = mapAndSwapFatHeaderPage(kernelcache_fd);
    if (!fat_header) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
            "Can't map %s: %s.", toolArgs.kernelcachePath, strerror(errno));
        result = EX_OSERR;
        goto finish;
    }
    
    fat_arch = getFirstFatArch(fat_header);
    if (fat_arch && !toolArgs.archInfo) {
        toolArgs.archInfo = NXGetArchInfoFromCpuType(fat_arch->cputype, fat_arch->cpusubtype);
    }
    
    rawKernelcache = readMachOSliceForArch(toolArgs.kernelcachePath, toolArgs.archInfo,
        /* checkArch */ FALSE);
    if (!rawKernelcache) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
            "Can't read arch %s from %s.", toolArgs.archInfo->name, toolArgs.kernelcachePath);
        goto finish;
    }

    if (MAGIC32(CFDataGetBytePtr(rawKernelcache)) == OSSwapHostToBigInt32('comp')) {
        kernelcacheImage = uncompressPrelinkedSlice(rawKernelcache);
        if (!kernelcacheImage) {
            OSKextLog(/* kext */ NULL,
                kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
                "Can't uncompress kernelcache slice.");
            goto finish;
        }
    } else {
        kernelcacheImage = CFRetain(rawKernelcache);
    }

    toolArgs.kernelcacheImageBytes = CFDataGetBytePtr(kernelcacheImage);
    
    if (ISMACHO64(MAGIC32(toolArgs.kernelcacheImageBytes))) {
        prelinkInfoSect = (void *)macho_get_section_by_name_64(
            (struct mach_header_64 *)toolArgs.kernelcacheImageBytes,
            "__PRELINK_INFO", "__info");

    } else {
        prelinkInfoSect = (void *)macho_get_section_by_name(
            (struct mach_header *)toolArgs.kernelcacheImageBytes,
            "__PRELINK_INFO", "__info");
    }

    if (!prelinkInfoSect) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
            "Can't find prelink info section.");
        goto finish;
    }

    if (ISMACHO64(MAGIC32(toolArgs.kernelcacheImageBytes))) {
        prelinkInfoBytes = ((char *)toolArgs.kernelcacheImageBytes) +
            ((struct section_64 *)prelinkInfoSect)->offset;
    } else {
        prelinkInfoBytes = ((char *)toolArgs.kernelcacheImageBytes) +
            ((struct section *)prelinkInfoSect)->offset;
    }

    toolArgs.kernelcacheInfoPlist = (CFPropertyListRef)IOCFUnserialize(prelinkInfoBytes,
        kCFAllocatorDefault, /* options */ 0, /* errorString */ NULL);
    if (!toolArgs.kernelcacheInfoPlist) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
            "Can't unserialize prelink info.");
        goto finish;
    }

    result = printKextInfo(&toolArgs);
    if (result != EX_OK) {
        goto finish;
    }

    result = EX_OK;

finish:

    SAFE_RELEASE(toolArgs.kernelcacheInfoPlist);
    SAFE_RELEASE(kernelcacheImage);
    SAFE_RELEASE(rawKernelcache);

    if (fat_header) {
        unmapFatHeaderPage(fat_header);
    }

    if (kernelcache_fd != -1) {
        close(kernelcache_fd);
    }
    return result;
}