2019-09-03 11:58:42 +02:00
|
|
|
/**
|
|
|
|
|
|
|
|
Basic functions for parsing Mach-O kernel.
|
|
|
|
|
|
|
|
by dmazar
|
|
|
|
|
|
|
|
**/
|
|
|
|
|
2020-07-21 08:33:43 +02:00
|
|
|
//#include <IndustryStandard/MachO-loader.h>
|
|
|
|
#include <UefiLoader.h>
|
2019-09-03 11:58:42 +02:00
|
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
|
|
|
|
|
|
#include <Library/UefiLib.h>
|
|
|
|
#include <Library/DebugLib.h>
|
|
|
|
#include <Library/PrintLib.h>
|
|
|
|
|
2020-07-21 08:33:43 +02:00
|
|
|
//#include "UefiLoader.h"
|
2019-09-03 11:58:42 +02:00
|
|
|
#include "Mach-O.h"
|
|
|
|
|
|
|
|
|
|
|
|
// DBG_TO: 0=no debug, 1=serial, 2=console
|
|
|
|
// serial requires
|
|
|
|
// [PcdsFixedAtBuild]
|
|
|
|
// gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x07
|
|
|
|
// gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xFFFFFFFF
|
|
|
|
// in package DSC file
|
|
|
|
#define DBG_TO 0
|
|
|
|
|
|
|
|
#if DBG_TO == 2
|
|
|
|
#define DBG(...) AsciiPrint(__VA_ARGS__);
|
|
|
|
#elif DBG_TO == 1
|
|
|
|
#define DBG(...) DebugPrint(1, __VA_ARGS__);
|
|
|
|
#else
|
|
|
|
#define DBG(...)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/** Adds Offset bytes to SourcePtr and returns new pointer as ReturnType. */
|
|
|
|
#define PTR_OFFSET(SourcePtr, Offset, ReturnType) ((ReturnType)(((UINT8*)SourcePtr) + Offset))
|
|
|
|
|
|
|
|
|
|
|
|
/** Returns Mach-O entry point from LC_UNIXTHREAD loader command. */
|
|
|
|
UINTN
|
|
|
|
EFIAPI
|
|
|
|
MachOGetEntryAddress(IN VOID *MachOImage)
|
|
|
|
{
|
|
|
|
struct mach_header *MHdr;
|
|
|
|
struct mach_header_64 *MHdr64;
|
|
|
|
BOOLEAN Is64Bit;
|
|
|
|
UINT32 NCmds;
|
|
|
|
struct load_command *LCmd;
|
|
|
|
UINTN Index;
|
|
|
|
i386_thread_state_t *ThreadState;
|
|
|
|
x86_thread_state64_t *ThreadState64;
|
|
|
|
UINTN Address;
|
|
|
|
|
|
|
|
|
|
|
|
Address = 0;
|
|
|
|
MHdr = (struct mach_header *)MachOImage;
|
|
|
|
MHdr64 = (struct mach_header_64 *)MachOImage;
|
|
|
|
DBG("MachOImage: %p, magic: %x", MachOImage, MHdr->magic);
|
|
|
|
|
|
|
|
if (MHdr->magic == MH_MAGIC || MHdr->magic == MH_CIGAM) {
|
|
|
|
// 32 bit header
|
|
|
|
DBG(" -> 32 bit\n");
|
|
|
|
Is64Bit = FALSE;
|
|
|
|
NCmds = MHdr->ncmds;
|
|
|
|
LCmd = PTR_OFFSET(MachOImage, sizeof(struct mach_header), struct load_command *);
|
|
|
|
} else if (MHdr64->magic == MH_MAGIC_64 || MHdr64->magic == MH_CIGAM_64) {
|
|
|
|
// 64 bit header
|
|
|
|
DBG(" -> 64 bit\n");
|
|
|
|
Is64Bit = TRUE;
|
|
|
|
NCmds = MHdr64->ncmds;
|
|
|
|
LCmd = PTR_OFFSET(MachOImage, sizeof(struct mach_header_64), struct load_command *);
|
|
|
|
} else {
|
|
|
|
// invalid MachOImage
|
|
|
|
return Address;
|
|
|
|
}
|
|
|
|
DBG("ncmds: %d\n", NCmds, LCmd);
|
|
|
|
//gBS->Stall(10 * 1000000);
|
|
|
|
|
|
|
|
// iterate over load commands
|
|
|
|
for (Index = 0; Index < NCmds; Index++) {
|
|
|
|
|
|
|
|
DBG("%d. LCmd: %p, cmd: %x, size: %d\n", Index, LCmd, LCmd->cmd, LCmd->cmdsize);
|
|
|
|
|
|
|
|
if (LCmd->cmd == LC_UNIXTHREAD) {
|
|
|
|
|
|
|
|
DBG("LC_UNIXTHREAD\n");
|
|
|
|
//
|
|
|
|
// extract thread state
|
|
|
|
// LCmd =
|
|
|
|
// struct load_command {
|
|
|
|
// uint32_t cmd
|
|
|
|
// uint32_t cmdsize
|
|
|
|
// }
|
|
|
|
// uint32_t flavor flavor of thread state */
|
|
|
|
// uint32_t count count of longs in thread state */
|
|
|
|
// struct XXX_thread_state state thread state for this flavor */
|
|
|
|
//
|
|
|
|
ThreadState = PTR_OFFSET(LCmd, sizeof(struct load_command) + 2 * sizeof(UINT32), i386_thread_state_t *);
|
|
|
|
ThreadState64 = (x86_thread_state64_t *)ThreadState;
|
|
|
|
|
|
|
|
if (Is64Bit) {
|
|
|
|
Address = (UINTN)ThreadState64->rip;
|
|
|
|
} else {
|
|
|
|
Address = (UINTN)ThreadState->eip;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// next command
|
|
|
|
LCmd = PTR_OFFSET(LCmd, LCmd->cmdsize, struct load_command *);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("Address: %lx\n", Address);
|
|
|
|
//gBS->Stall(20 * 1000000);
|
|
|
|
return Address;
|
|
|
|
}
|