diff --git a/amoco/arch/x64/spec_ia32e.py b/amoco/arch/x64/spec_ia32e.py
index ce976ea..c84285c 100644
--- a/amoco/arch/x64/spec_ia32e.py
+++ b/amoco/arch/x64/spec_ia32e.py
@@ -36,6 +36,10 @@ def prefix_grp1(obj, _pfx):
setpfx(obj, _pfx, 0)
+# Because of the addition of CET_IBT, the 3e prefix has now two
+# possible meanings: DS: segment override, or notrack
+# We keep the traditional "DS: segment override" but will need to
+# hack the instructions where it means notrack: call & jmp
@ispec_ia32("8>[ {26} ]+", _pfx=("segreg", env.es))
@ispec_ia32("8>[ {2e} ]+", _pfx=("segreg", env.cs))
@ispec_ia32("8>[ {36} ]+", _pfx=("segreg", env.ss))
@@ -371,6 +375,14 @@ def ia32_rm64(obj, Mod, RM, data):
obj.operands = [op1]
obj.misc["absolute"] = True
obj.type = type_control_flow
+ # Because of the addition of CET_IBT, the 3e prefix has now two
+ # possible meanings: DS: segment override, or notrack
+ # We keep the traditional "DS: segment override" but will need to
+ # hack the instructions where it means notrack: this one
+ if obj.misc["segreg"] is env.ds:
+ del obj.misc["segreg"]
+ obj.misc["notrack"] = True
+ obj.misc["pfx"] = ["notrack", None, None, None]
# r/m32/48
diff --git a/amoco/arch/x86/parsers.py b/amoco/arch/x86/parsers.py
index 9bbccbe..8024347 100644
--- a/amoco/arch/x86/parsers.py
+++ b/amoco/arch/x86/parsers.py
@@ -81,6 +81,7 @@ def att_syntax_gen(env, CONDITION_CODES, cpu_addrsize, instruction):
"repe",
"repne",
"repnz",
+ "notrack",
]
)
@@ -321,13 +322,15 @@ def att_syntax_gen(env, CONDITION_CODES, cpu_addrsize, instruction):
i = instruction(b"")
i.mnemonic = toks[0].upper()
# Remove prefixes
- if i.mnemonic in ("REP", "REPZ", "REPNZ", "REPE", "REPNE", "LOCK"):
+ if i.mnemonic in ("REP", "REPZ", "REPNZ", "REPE", "REPNE", "LOCK", "NOTRACK"):
if i.mnemonic in ("REP", "REPZ", "REPE"):
i.misc.update({"pfx": ["rep", None, None, None], "rep": True})
if i.mnemonic in ("REPNZ", "REPNE"):
i.misc.update({"pfx": ["repne", None, None, None], "repne": True})
if i.mnemonic in ("LOCK",):
i.misc.update({"pfx": ["lock", None, None, None], "lock": True})
+ if i.mnemonic in ("NOTRACK",):
+ i.misc.update({"pfx": ["notrack", None, None, None], "notrack": True})
del toks[0] # toks.pop(0) is broken for pyparsing 2.0.2
# https://bugs.launchpad.net/ubuntu/+source/pyparsing/+bug/1381564
i.mnemonic = toks[0].upper()
diff --git a/amoco/arch/x86/spec_ia32.py b/amoco/arch/x86/spec_ia32.py
index f343675..9b20c97 100644
--- a/amoco/arch/x86/spec_ia32.py
+++ b/amoco/arch/x86/spec_ia32.py
@@ -34,6 +34,10 @@ def prefix_grp1(obj, _pfx):
setpfx(obj, _pfx, 0)
+# Because of the addition of CET_IBT, the 3e prefix has now two
+# possible meanings: DS: segment override, or notrack
+# We keep the traditional "DS: segment override" but will need to
+# hack the instructions where it means notrack: call & jmp
@ispec_ia32("8>[ {26} ]+", _pfx=("segreg", env.es))
@ispec_ia32("8>[ {2e} ]+", _pfx=("segreg", env.cs))
@ispec_ia32("8>[ {36} ]+", _pfx=("segreg", env.ss))
@@ -330,6 +334,14 @@ def ia32_rm32(obj, Mod, RM, data):
obj.operands = [op1]
if obj.mnemonic in ("JMP", "CALL"):
obj.misc["absolute"] = True
+ # Because of the addition of CET_IBT, the 3e prefix has now two
+ # possible meanings: DS: segment override, or notrack
+ # We keep the traditional "DS: segment override" but will need to
+ # hack the instructions where it means notrack: this one
+ if obj.misc["segreg"] is env.ds:
+ del obj.misc["segreg"]
+ obj.misc["notrack"] = True
+ obj.misc["pfx"] = ["notrack", None, None, None]
# r/m32/48
diff --git a/tests/test_arch_x64.py b/tests/test_arch_x64.py
index 8758829..2a2c673 100644
--- a/tests/test_arch_x64.py
+++ b/tests/test_arch_x64.py
@@ -207,3 +207,8 @@ def test_decoder_029():
i = cpu.disassemble(b'\xf3\x0f\x1e\xfa')
assert i.mnemonic=='ENDBR64'
assert str(i) == 'endbr64 '
+
+def test_decoder_030():
+ i = cpu.disassemble(b'\x3e\xff\xe0')
+ assert i.mnemonic=='JMP'
+ assert str(i) == 'notrack jmp rax'
Here is the patch I use