Files
ipsw/internal/utils/mte.go

79 lines
2.3 KiB
Go

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
}