package utils import ( "bytes" "encoding/binary" "io" "github.com/blacktop/arm64-cgo/disassemble" "github.com/blacktop/go-macho" ) // mteMnemonics is the complete list of all MTE instruction mnemonics var mteMnemonics = map[disassemble.Operation]bool{ disassemble.ARM64_ADDG: true, // Add with Tag disassemble.ARM64_SUBG: true, // Subtract with Tag disassemble.ARM64_IRG: true, // Insert Random Tag disassemble.ARM64_GMI: true, // Tag Mask Insert disassemble.ARM64_LDG: true, // Load Allocation Tag disassemble.ARM64_STG: true, // Store Allocation Tag disassemble.ARM64_ST2G: true, // Store Allocation Tags disassemble.ARM64_STZG: true, // Store Allocation Tag and Zero disassemble.ARM64_STZ2G: true, // Store Allocation Tags and Zero disassemble.ARM64_STGP: true, // Store Allocation Tag and Pair disassemble.ARM64_LDGM: true, // Load Tag Multiple disassemble.ARM64_STGM: true, // Store Tag Multiple disassemble.ARM64_STZGM: true, // Store Tag and Zero Multiple disassemble.ARM64_SUBP: true, // Subtract Pointer disassemble.ARM64_SUBPS: true, // Subtract Pointer, setting Flags disassemble.ARM64_CMPP: true, // Compare Pointer (alias of SUBPS) } // HasMTEInstructions scans a Mach-O file for MTE (Memory Tagging Extension) instructions. // Returns true and the first address if any MTE instructions are found in the executable sections. func HasMTEInstructions(m *macho.File) (bool, uint64) { var instrValue uint32 var decoder disassemble.Decoder sections := m.GetSectionsForSegment("__TEXT") if len(sections) == 0 { return false, 0 } for _, sec := range sections { if !sec.Flags.IsPureInstructions() && !sec.Flags.IsSomeInstructions() { continue } data := make([]byte, sec.Size) if _, err := m.ReadAtAddr(data, sec.Addr); err != nil { continue } r := bytes.NewReader(data) startAddr := sec.Addr for { err := binary.Read(r, binary.LittleEndian, &instrValue) if err == io.EOF { break } var inst disassemble.Inst if err := decoder.DecomposeInto(startAddr, instrValue, &inst); err != nil { startAddr += uint64(binary.Size(uint32(0))) continue } if isMTE, found := mteMnemonics[inst.Operation]; found { return isMTE, startAddr } startAddr += uint64(binary.Size(uint32(0))) } } return false, 0 }