feat(disasm): name the CLDEMOTE encoding the decoder refuses
The hint NOP opcode 0F 1C /r with a memory operand is CLDEMOTE, a memory-only instruction the toolchain's own table carries; the decoder rejects the encoding instead of naming it. The rejected-encoding side of the supplementary table names it from the bytes, and the corpus row 0f1c03 pins the text in the unlisted fixture, round trip byte exact. Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
dd356b9e6a
commit
458d981f31
4 files changed
+36
-3
No files matched your search
@@ -68,6 +68,12 @@ func Decode(a arch.Arch, code []byte, addr uint64) (Instruction, error) {
|
|||||||
default: // amd64
|
default: // amd64
|
||||||
inst, err := x86asm.Decode(code, 64)
|
inst, err := x86asm.Decode(code, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// A few named families the decoder refuses outright live in
|
||||||
|
// the same supplementary table; anything else keeps the
|
||||||
|
// placeholder.
|
||||||
|
if text, n, ok := nameAMD64Rejected(code); ok {
|
||||||
|
return Instruction{Addr: addr, Text: text, Len: n}, nil
|
||||||
|
}
|
||||||
return Instruction{Addr: addr, Text: "???", Len: 1}, nil
|
return Instruction{Addr: addr, Text: "???", Len: 1}, nil
|
||||||
}
|
}
|
||||||
if inst.Op == 0 {
|
if inst.Op == 0 {
|
||||||
|
|||||||
@@ -318,3 +318,24 @@ func nameAMD64Endbr(p amd64Prefixes, tail []byte) (string, int, bool) {
|
|||||||
}
|
}
|
||||||
return "", 0, false
|
return "", 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nameAMD64Rejected names an amd64 encoding the decoder refuses outright,
|
||||||
|
// one family at a time as the corpus rows land. CLDEMOTE, NP 0F 1C /r
|
||||||
|
// with a memory operand, is the first: the toolchain's own table carries
|
||||||
|
// it as a memory-only instruction, and the decoder rejects the encoding
|
||||||
|
// instead of naming it. The register forms of the same opcode are the
|
||||||
|
// hint NOPs the corpus does not spell, and they stay rejected.
|
||||||
|
func nameAMD64Rejected(code []byte) (string, int, bool) {
|
||||||
|
p, ok := scanAMD64Prefixes(code)
|
||||||
|
if !ok || p.osz || p.rep || p.repne {
|
||||||
|
return "", 0, false
|
||||||
|
}
|
||||||
|
if len(code) < p.n+3 || code[p.n] != 0x0f || code[p.n+1] != 0x1c {
|
||||||
|
return "", 0, false
|
||||||
|
}
|
||||||
|
rm, ok := decodeAMD64RM(code[p.n+2:], p.rexR, p.rexX, p.rexB)
|
||||||
|
if !ok || rm.regForm {
|
||||||
|
return "", 0, false
|
||||||
|
}
|
||||||
|
return "CLDEMOTE " + rm.text(), p.n + 2 + rm.n, true
|
||||||
|
}
|
||||||
@@ -76,6 +76,10 @@ func TestDegenerateNaming(t *testing.T) {
|
|||||||
// toolchain spelling.
|
// toolchain spelling.
|
||||||
{[]byte{0xf3, 0x0f, 0x1e, 0xfa}, "ENDBR64"},
|
{[]byte{0xf3, 0x0f, 0x1e, 0xfa}, "ENDBR64"},
|
||||||
{[]byte{0xf3, 0x0f, 0x1e, 0xfb}, "ENDBR32"},
|
{[]byte{0xf3, 0x0f, 0x1e, 0xfb}, "ENDBR32"},
|
||||||
|
// amd64enc_extra.s: CLDEMOTE (BX) // 0f1c03. The decoder
|
||||||
|
// rejects the encoding outright; the table names it from the
|
||||||
|
// bytes.
|
||||||
|
{[]byte{0x0f, 0x1c, 0x03}, "CLDEMOTE 0(BX)"},
|
||||||
} {
|
} {
|
||||||
ins, err := Decode(arch.AMD64, tt.code, 0)
|
ins, err := Decode(arch.AMD64, tt.code, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -102,12 +106,13 @@ func TestDegenerateNamingBoundaries(t *testing.T) {
|
|||||||
text string
|
text string
|
||||||
}{
|
}{
|
||||||
// Rejected outright: RDSEED without the operand-size override
|
// Rejected outright: RDSEED without the operand-size override
|
||||||
// (the bare 0F C7 /7 register form), MONITORX and MWAITX, the
|
// (the bare 0F C7 /7 register form), MONITORX and MWAITX, and
|
||||||
// hint NOP CLDEMOTE.
|
// the register form of the hint NOP opcode, which the corpus
|
||||||
|
// does not spell.
|
||||||
{[]byte{0x0f, 0xc7, 0xfa}, "???"},
|
{[]byte{0x0f, 0xc7, 0xfa}, "???"},
|
||||||
{[]byte{0x0f, 0x01, 0xfa}, "???"},
|
{[]byte{0x0f, 0x01, 0xfa}, "???"},
|
||||||
{[]byte{0x0f, 0x01, 0xfb}, "???"},
|
{[]byte{0x0f, 0x01, 0xfb}, "???"},
|
||||||
{[]byte{0x0f, 0x1c, 0x03}, "???"},
|
{[]byte{0x0f, 0x1c, 0xc3}, "???"},
|
||||||
// Degenerate but outside the table's prefix gates: repne ADCX is
|
// Degenerate but outside the table's prefix gates: repne ADCX is
|
||||||
// no instruction the corpus names.
|
// no instruction the corpus names.
|
||||||
{[]byte{0xf2, 0x0f, 0x38, 0xf6, 0xd2}, "REPNE; Op(0)"},
|
{[]byte{0xf2, 0x0f, 0x38, 0xf6, 0xd2}, "REPNE; Op(0)"},
|
||||||
|
|||||||
+1
@@ -1228,3 +1228,4 @@ f3410fc7fb RDPID R11
|
|||||||
f30faef3 UMONITOR BX
|
f30faef3 UMONITOR BX
|
||||||
f20faef3 UMWAIT BX
|
f20faef3 UMWAIT BX
|
||||||
f30f1efa ENDBR64
|
f30f1efa ENDBR64
|
||||||
|
0f1c03 CLDEMOTE 0(BX)
|
||||||
Reference in new issue
Block a user