in jvm/src/main/kotlin/com/jetbrains/util/filetype/FileTypeDetector.kt [171:222]
fun ReadHeader(magic: Long): Pair<EnumSet<FileProperties>, List<ProcessorArchitecture>>? {
// Note: See https://opensource.apple.com/source/xnu/xnu-2050.18.24/EXTERNAL_HEADERS/mach-o/loader.h
val isLe32 = magic == 0xFEEDFACE // MH_MAGIC
val isLe64 = magic == 0xFEEDFACF // MH_MAGIC_64
val isBe32 = magic == 0xCEFAEDFE // MH_CIGAM
val isBe64 = magic == 0xCFFAEDFE // MH_CIGAM_64
if (isLe32 || isLe64 || isBe32 || isBe64) {
// Machine types:
val CPU_ARCH_ABI64 = 0x01000000
val CPU_TYPE_X86 = 7
val CPU_TYPE_X86_64 = CPU_TYPE_X86 or CPU_ARCH_ABI64
val CPU_TYPE_ARM64 = 12 or CPU_ARCH_ABI64
val cputype =
when (reader.ReadUInt32Le(isBe32 || isBe64).toInt()) // mach_header::cputype / mach_header_64::cputype
{
CPU_TYPE_X86 -> ProcessorArchitecture.PROCESSOR_ARCHITECTURE_INTEL // CPU_TYPE_X86
CPU_TYPE_X86_64 -> ProcessorArchitecture.PROCESSOR_ARCHITECTURE_AMD64 // CPU_TYPE_X86_64
CPU_TYPE_ARM64 -> ProcessorArchitecture.PROCESSOR_ARCHITECTURE_ARM64 // CPU_TYPE_ARM64
else -> ProcessorArchitecture.PROCESSOR_ARCHITECTURE_UNKNOWN
}
stream.Seek(4, SeekOrigin.Current)
val fileProperties = enumSetOf(
when (reader.ReadUInt32Le(isBe32 || isBe64).toInt()) // mach_header::filetype / mach_header_64::filetype
{
0x2 -> FileProperties.ExecutableType // MH_EXECUTE
0x6 -> FileProperties.SharedLibraryType // MH_DYLIB
0x8 -> FileProperties.BundleType // MH_BUNDLE
else -> FileProperties.UnknownType
}
)
var ncmds = reader.ReadUInt32Le(isBe32 || isBe64).toInt() // mach_header::ncmds / mach_header_64::ncmds
stream.Seek(if (isLe64 || isBe64) 0xC else 0x8, SeekOrigin.Current) // load_command[0]
while (ncmds-- > 0) {
val cmd = reader.ReadUInt32Le(isBe32 || isBe64) // load_command::cmd
val cmdsize = reader.ReadUInt32Le(isBe32 || isBe64) // load_command::cmdsize
stream.Seek((cmdsize - 8u).toLong(), SeekOrigin.Current)
if (cmd == 0x1Du) // LC_CODE_SIGNATURE
fileProperties += FileProperties.Signed
}
return fileProperties to listOf(cputype)
}
return null
}