From 41d616a6372486e387891f9a0f060b2b75d2151a Mon Sep 17 00:00:00 2001 From: blacktop Date: Thu, 25 Jun 2020 12:45:44 -0400 Subject: [PATCH] update cpu subtype and add new loadcmd --- types/commands.go | 27 ++++++++++++++++--- types/cpu.go | 69 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/types/commands.go b/types/commands.go index 51731e0..a1699f9 100644 --- a/types/commands.go +++ b/types/commands.go @@ -75,6 +75,7 @@ const ( LC_BUILD_VERSION LoadCmd = 0x32 // build for platform min OS version LC_DYLD_EXPORTS_TRIE LoadCmd = (0x33 | LC_REQ_DYLD) // used with linkedit_data_command, payload is trie LC_DYLD_CHAINED_FIXUPS LoadCmd = (0x34 | LC_REQ_DYLD) // used with linkedit_data_command + LC_FILESET_ENTRY LoadCmd = (0x35 | LC_REQ_DYLD) /* used with fileset_entry_command */ ) type SegFlag uint32 @@ -420,14 +421,19 @@ type SourceVersionCmd struct { // A DylibCodeSignDrsCmd is a Mach-O code signing DRs copied from linked dylibs command. type DylibCodeSignDrsCmd LinkEditDataCmd // LC_DYLIB_CODE_SIGN_DRS + +type EncryptionSystem uint32 + +const NOT_ENCRYPTED_YET EncryptionSystem = 0 + // A EncryptionInfo64Cmd is a Mach-O 64-bit encrypted segment information command. type EncryptionInfo64Cmd struct { LoadCmd // LC_ENCRYPTION_INFO_64 Len uint32 - Offset uint32 // file offset of encrypted range - Size uint32 // file size of encrypted range - CryptID uint32 // which enryption system, 0 means not-encrypted yet - Pad uint32 // padding to make this struct's size a multiple of 8 bytes + Offset uint32 // file offset of encrypted range + Size uint32 // file size of encrypted range + CryptID EncryptionSystem // which enryption system, 0 means not-encrypted yet + Pad uint32 // padding to make this struct's size a multiple of 8 bytes } // A LinkerOptionCmd is a Mach-O main command. @@ -471,3 +477,16 @@ type BuildVersionCmd struct { type DyldExportsTrieCmd LinkEditDataCmd // LC_DYLD_EXPORTS_TRIE // A DyldChainedFixupsCmd is used with linkedit_data_command command. type DyldChainedFixupsCmd LinkEditDataCmd // LC_DYLD_CHAINED_FIXUPS + +// FilesetEntryCmd commands describe constituent Mach-O files that are part +// of a fileset. In one implementation, entries are dylibs with individual +// mach headers and repositionable text and data segments. Each entry is +// further described by its own mach header. +type FilesetEntryCmd struct { + LoadCmd // LC_FILESET_ENTRY + Len uint32 + Addr uint64 // memory address of the entry + Offset uint64 // file offset of the entry + EntryID uint32 // contained entry id + Reserved uint32 // reserved +} diff --git a/types/cpu.go b/types/cpu.go index 83b6c2e..15822a4 100644 --- a/types/cpu.go +++ b/types/cpu.go @@ -1,9 +1,12 @@ package types +import "fmt" + // A CPU is a Mach-O cpu type. type CPU uint32 const ( + cpuArchMask = 0xff000000 // mask for architecture bits cpuArch64 = 0x01000000 // 64 bit ABI cpuArch6432 = 0x02000000 // ABI for 64-bit hardware with 32-bit types; LP32 ) @@ -65,6 +68,22 @@ const ( CPUSubtypeArm64E CPUSubtype = 2 ) +// Capability bits used in the definition of cpu_subtype. +const ( + CpuSubtypeFeatureMask CPUSubtype = 0xff000000 /* mask for feature flags */ + CpuSubtypeMask = CPUSubtype(^CpuSubtypeFeatureMask) /* mask for cpu subtype */ + CpuSubtypeLib64 = 0x80000000 /* 64 bit libraries */ + CpuSubtypePtrauthAbi = 0x80000000 /* pointer authentication with versioned ABI */ + CpuSubtypePtrauthAbiUser = 0x40000000 /* pointer authentication with userspace versioned ABI */ + CpuSubtypeArm64PtrAuthMask = 0x0f000000 + /* + * When selecting a slice, ANY will pick the slice with the best + * grading for the selected cpu_type_t, unlike the "ALL" subtypes, + * which are the slices that can run on any hardware for that cpu type. + */ + CpuSubtypeAny = -1 +) + var cpuSubtypeX86Strings = []intName{ // {uint32(CPUSubtypeX86All), "x86"}, {uint32(CPUSubtypeX8664All), "x86_64"}, @@ -73,19 +92,19 @@ var cpuSubtypeX86Strings = []intName{ } var cpuSubtypeArmStrings = []intName{ {uint32(CPUSubtypeArmAll), "ArmAll"}, - {uint32(CPUSubtypeArmV4T), "ArmV4T"}, - {uint32(CPUSubtypeArmV6), "ArmV6"}, - {uint32(CPUSubtypeArmV5Tej), "ArmV5Tej"}, - {uint32(CPUSubtypeArmXscale), "ArmXscale"}, - {uint32(CPUSubtypeArmV7), "ArmV7"}, - {uint32(CPUSubtypeArmV7F), "ArmV7F"}, - {uint32(CPUSubtypeArmV7S), "ArmV7S"}, - {uint32(CPUSubtypeArmV7K), "ArmV7K"}, - {uint32(CPUSubtypeArmV8), "ArmV8"}, - {uint32(CPUSubtypeArmV6M), "rmV6M"}, - {uint32(CPUSubtypeArmV7M), "ArmV7M"}, - {uint32(CPUSubtypeArmV7Em), "ArmV7Em"}, - {uint32(CPUSubtypeArmV8M), "ArmV8M"}, + {uint32(CPUSubtypeArmV4T), "ARMv4t"}, + {uint32(CPUSubtypeArmV6), "ARMv6"}, + {uint32(CPUSubtypeArmV5Tej), "ARMv5tej"}, + {uint32(CPUSubtypeArmXscale), "ARMXScale"}, + {uint32(CPUSubtypeArmV7), "ARMv7"}, + {uint32(CPUSubtypeArmV7F), "ARMv7f"}, + {uint32(CPUSubtypeArmV7S), "ARMv7s"}, + {uint32(CPUSubtypeArmV7K), "ARMv7k"}, + {uint32(CPUSubtypeArmV8), "ARMv8"}, + {uint32(CPUSubtypeArmV6M), "ARMv6m"}, + {uint32(CPUSubtypeArmV7M), "ARMv7m"}, + {uint32(CPUSubtypeArmV7Em), "ARMv7em"}, + {uint32(CPUSubtypeArmV8M), "ARMv8m"}, } var cpuSubtypeArm64Strings = []intName{ {uint32(CPUSubtypeArm64All), "ARM64"}, @@ -97,25 +116,31 @@ func (st CPUSubtype) String(cpu CPU) string { switch cpu { case CPU386: case CPUAmd64: - // TODO: this is a hack and this should be fully fleshed out - return stringName(uint32(st&0xFF), cpuSubtypeX86Strings, false) + return stringName(uint32(st&CpuSubtypeMask), cpuSubtypeX86Strings, false) case CPUArm: - return stringName(uint32(st), cpuSubtypeArmStrings, false) + return stringName(uint32(st&CpuSubtypeMask), cpuSubtypeArmStrings, false) case CPUArm64: - return stringName(uint32(st), cpuSubtypeArm64Strings, false) + var feature string + caps := st & CpuSubtypeFeatureMask + if caps&CpuSubtypePtrauthAbiUser == 0 { + feature = fmt.Sprintf(" caps: PAC%02d", (caps&CpuSubtypeArm64PtrAuthMask)>>24) + } else { + feature = fmt.Sprintf(" caps: PAK%02d", (caps&CpuSubtypeArm64PtrAuthMask)>>24) + } + return stringName(uint32(st&CpuSubtypeMask), cpuSubtypeArm64Strings, false) + feature } - return "" + return "UNKNOWN" } func (st CPUSubtype) GoString(cpu CPU) string { switch cpu { case CPU386: case CPUAmd64: - return stringName(uint32(st), cpuSubtypeX86Strings, true) + return stringName(uint32(st&CpuSubtypeMask), cpuSubtypeX86Strings, true) case CPUArm: - return stringName(uint32(st), cpuSubtypeArmStrings, true) + return stringName(uint32(st&CpuSubtypeMask), cpuSubtypeArmStrings, true) case CPUArm64: - return stringName(uint32(st), cpuSubtypeArm64Strings, true) + return stringName(uint32(st&CpuSubtypeMask), cpuSubtypeArm64Strings, true) } - return "" + return "UNKNOWN" }