aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-08-14 00:44:09 -0700
committeriximeow <me@iximeow.net>2021-08-14 00:48:02 -0700
commit9bc4eca4b8269cb8e0898dfe05c3ed4059cf4fd5 (patch)
tree4c2cb8bdf632ea80fc09fc3f3526ce1a80559775
parentcf63d91ac22230ff5e97928f5bd319746fc49590 (diff)
relative branches should be shown as $+offset, not just plain offset
while x86 branches of immediates are all relative to PC, other architectures may have absolute branches to immediate addresses, leaving this syntax ambiguous and potentially confusing. yaxpeax prefers to write relative offsets `$+...` as a rule, so uphold that here.
-rw-r--r--src/long_mode/display.rs28
-rw-r--r--src/protected_mode/display.rs28
-rw-r--r--src/real_mode/display.rs28
-rw-r--r--test/long_mode/mod.rs17
-rw-r--r--test/protected_mode/mod.rs17
-rw-r--r--test/real_mode/mod.rs17
6 files changed, 111 insertions, 24 deletions
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs
index 68189f0..59efe38 100644
--- a/src/long_mode/display.rs
+++ b/src/long_mode/display.rs
@@ -3338,6 +3338,34 @@ fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors:
out.write_str(" ")?;
let x = Operand::from_spec(instr, instr.operands[0]);
+
+ const RELATIVE_BRANCHES: [Opcode; 21] = [
+ Opcode::JMP, Opcode::JRCXZ,
+ Opcode::LOOP, Opcode::LOOPZ, Opcode::LOOPNZ,
+ Opcode::JO, Opcode::JNO,
+ Opcode::JB, Opcode::JNB,
+ Opcode::JZ, Opcode::JNZ,
+ Opcode::JNA, Opcode::JA,
+ Opcode::JS, Opcode::JNS,
+ Opcode::JP, Opcode::JNP,
+ Opcode::JL, Opcode::JGE,
+ Opcode::JLE, Opcode::JG,
+ ];
+
+ if instr.operands[0] == OperandSpec::ImmI8 || instr.operands[0] == OperandSpec::ImmI32 {
+ if RELATIVE_BRANCHES.contains(&instr.opcode) {
+ return match x {
+ Operand::ImmediateI8(rel) => {
+ write!(out, "$+{}", colors.number(signed_i32_hex(rel as i32)))
+ }
+ Operand::ImmediateI32(rel) => {
+ write!(out, "$+{}", colors.number(signed_i32_hex(rel)))
+ }
+ _ => { unreachable!() }
+ };
+ }
+ }
+
if x.is_memory() {
out.write_str(MEM_SIZE_STRINGS[instr.mem_size as usize - 1])?;
out.write_str(" ")?;
diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs
index 987221e..72bfcb4 100644
--- a/src/protected_mode/display.rs
+++ b/src/protected_mode/display.rs
@@ -3351,6 +3351,34 @@ fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors:
out.write_str(" ")?;
let x = Operand::from_spec(instr, instr.operands[0]);
+
+ const RELATIVE_BRANCHES: [Opcode; 21] = [
+ Opcode::JMP, Opcode::JECXZ,
+ Opcode::LOOP, Opcode::LOOPZ, Opcode::LOOPNZ,
+ Opcode::JO, Opcode::JNO,
+ Opcode::JB, Opcode::JNB,
+ Opcode::JZ, Opcode::JNZ,
+ Opcode::JNA, Opcode::JA,
+ Opcode::JS, Opcode::JNS,
+ Opcode::JP, Opcode::JNP,
+ Opcode::JL, Opcode::JGE,
+ Opcode::JLE, Opcode::JG,
+ ];
+
+ if instr.operands[0] == OperandSpec::ImmI8 || instr.operands[0] == OperandSpec::ImmI32 {
+ if RELATIVE_BRANCHES.contains(&instr.opcode) {
+ return match x {
+ Operand::ImmediateI8(rel) => {
+ write!(out, "$+{}", colors.number(signed_i32_hex(rel as i32)))
+ }
+ Operand::ImmediateI32(rel) => {
+ write!(out, "$+{}", colors.number(signed_i32_hex(rel)))
+ }
+ _ => { unreachable!() }
+ };
+ }
+ }
+
if x.is_memory() {
out.write_str(MEM_SIZE_STRINGS[instr.mem_size as usize - 1])?;
out.write_str(" ")?;
diff --git a/src/real_mode/display.rs b/src/real_mode/display.rs
index 9ba8284..f514974 100644
--- a/src/real_mode/display.rs
+++ b/src/real_mode/display.rs
@@ -3351,6 +3351,34 @@ fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors:
out.write_str(" ")?;
let x = Operand::from_spec(instr, instr.operands[0]);
+
+ const RELATIVE_BRANCHES: [Opcode; 21] = [
+ Opcode::JMP, Opcode::JCXZ,
+ Opcode::LOOP, Opcode::LOOPZ, Opcode::LOOPNZ,
+ Opcode::JO, Opcode::JNO,
+ Opcode::JB, Opcode::JNB,
+ Opcode::JZ, Opcode::JNZ,
+ Opcode::JNA, Opcode::JA,
+ Opcode::JS, Opcode::JNS,
+ Opcode::JP, Opcode::JNP,
+ Opcode::JL, Opcode::JGE,
+ Opcode::JLE, Opcode::JG,
+ ];
+
+ if instr.operands[0] == OperandSpec::ImmI8 || instr.operands[0] == OperandSpec::ImmI32 {
+ if RELATIVE_BRANCHES.contains(&instr.opcode) {
+ return match x {
+ Operand::ImmediateI8(rel) => {
+ write!(out, "$+{}", colors.number(signed_i32_hex(rel as i32)))
+ }
+ Operand::ImmediateI32(rel) => {
+ write!(out, "$+{}", colors.number(signed_i32_hex(rel)))
+ }
+ _ => { unreachable!() }
+ };
+ }
+ }
+
if x.is_memory() {
out.write_str(MEM_SIZE_STRINGS[instr.mem_size as usize - 1])?;
out.write_str(" ")?;
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index bfe21bd..61ea63d 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -1208,10 +1208,10 @@ fn test_prefixes() {
#[test]
fn test_control_flow() {
- test_display(&[0x73, 0x31], "jnb 0x31");
- test_display(&[0x72, 0x5a], "jb 0x5a");
- test_display(&[0x0f, 0x86, 0x8b, 0x01, 0x00, 0x00], "jna 0x18b");
- test_display(&[0x74, 0x47], "jz 0x47");
+ test_display(&[0x73, 0x31], "jnb $+0x31");
+ test_display(&[0x72, 0x5a], "jb $+0x5a");
+ test_display(&[0x0f, 0x86, 0x8b, 0x01, 0x00, 0x00], "jna $+0x18b");
+ test_display(&[0x74, 0x47], "jz $+0x47");
test_display(&[0xff, 0x15, 0x7e, 0x72, 0x24, 0x00], "call qword [rip + 0x24727e]");
test_display(&[0xff, 0x24, 0xcd, 0x70, 0xa0, 0xbc, 0x01], "jmp qword [rcx * 8 + 0x1bca070]");
test_display(&[0xff, 0xe0], "jmp rax");
@@ -1219,10 +1219,11 @@ fn test_control_flow() {
test_display(&[0x67, 0xff, 0xe0], "jmp rax");
test_invalid(&[0xff, 0xd8]);
test_display(&[0xff, 0x18], "callf mword [rax]");
- test_display(&[0xe0, 0x12], "loopnz 0x12");
- test_display(&[0xe1, 0x12], "loopz 0x12");
- test_display(&[0xe2, 0x12], "loop 0x12");
- test_display(&[0xe3, 0x12], "jrcxz 0x12");
+ test_display(&[0xe0, 0x12], "loopnz $+0x12");
+ test_display(&[0xe1, 0x12], "loopz $+0x12");
+ test_display(&[0xe2, 0x12], "loop $+0x12");
+ test_display(&[0xe3, 0x12], "jrcxz $+0x12");
+ test_display(&[0xe3, 0xf0], "jrcxz $+-0x10");
test_display(&[0xc3], "ret");
}
diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs
index c03a19d..5ed69ed 100644
--- a/test/protected_mode/mod.rs
+++ b/test/protected_mode/mod.rs
@@ -1094,10 +1094,10 @@ fn test_prefixes() {
#[test]
fn test_control_flow() {
- test_display(&[0x73, 0x31], "jnb 0x31");
- test_display(&[0x72, 0x5a], "jb 0x5a");
- test_display(&[0x0f, 0x86, 0x8b, 0x01, 0x00, 0x00], "jna 0x18b");
- test_display(&[0x74, 0x47], "jz 0x47");
+ test_display(&[0x73, 0x31], "jnb $+0x31");
+ test_display(&[0x72, 0x5a], "jb $+0x5a");
+ test_display(&[0x0f, 0x86, 0x8b, 0x01, 0x00, 0x00], "jna $+0x18b");
+ test_display(&[0x74, 0x47], "jz $+0x47");
test_display(&[0xff, 0x15, 0x7e, 0x72, 0x24, 0x00], "call dword [0x24727e]");
test_display(&[0xff, 0x24, 0xcd, 0x70, 0xa0, 0xbc, 0x01], "jmp dword [ecx * 8 + 0x1bca070]");
test_display(&[0xff, 0xe0], "jmp eax");
@@ -1105,10 +1105,11 @@ fn test_control_flow() {
test_display(&[0x67, 0xff, 0xe0], "jmp eax");
test_invalid(&[0xff, 0xd8]);
test_display(&[0xff, 0x18], "callf far [eax]");
- test_display(&[0xe0, 0x12], "loopnz 0x12");
- test_display(&[0xe1, 0x12], "loopz 0x12");
- test_display(&[0xe2, 0x12], "loop 0x12");
- test_display(&[0xe3, 0x12], "jecxz 0x12");
+ test_display(&[0xe0, 0x12], "loopnz $+0x12");
+ test_display(&[0xe1, 0x12], "loopz $+0x12");
+ test_display(&[0xe2, 0x12], "loop $+0x12");
+ test_display(&[0xe3, 0x12], "jecxz $+0x12");
+ test_display(&[0xe3, 0xf0], "jecxz $+-0x10");
test_display(&[0xc3], "ret");
}
diff --git a/test/real_mode/mod.rs b/test/real_mode/mod.rs
index 82ccfab..6005f07 100644
--- a/test/real_mode/mod.rs
+++ b/test/real_mode/mod.rs
@@ -262,7 +262,7 @@ fn test_real_mode() {
test_display(&[0x0f, 0x7e, 0xcf], "movd edi, mm1");
test_display(&[0x0f, 0x7f, 0x0f], "movq qword [bx], mm1");
test_display(&[0x0f, 0x7f, 0xcf], "movq mm7, mm1");
- test_display(&[0x0f, 0x86, 0x8b, 0x01], "jna 0x18b");
+ test_display(&[0x0f, 0x86, 0x8b, 0x01], "jna $+0x18b");
test_display(&[0x0f, 0x97, 0x00], "seta byte [bx + si]");
test_display(&[0x0f, 0x97, 0x08], "seta byte [bx + si]");
test_display(&[0x0f, 0x97, 0xc0], "seta al");
@@ -16924,9 +16924,9 @@ fn test_real_mode() {
test_display(&[0x67, 0xff, 0xe0], "jmp ax");
test_display(&[0x68, 0x7f, 0x63], "push 0x637f");
test_display(&[0x6b, 0x43, 0x6f, 0x6d], "imul ax, word [bp + di + 0x6f], 0x6d");
- test_display(&[0x72, 0x5a], "jb 0x5a");
- test_display(&[0x73, 0x31], "jnb 0x31");
- test_display(&[0x74, 0x47], "jz 0x47");
+ test_display(&[0x72, 0x5a], "jb $+0x5a");
+ test_display(&[0x73, 0x31], "jnb $+0x31");
+ test_display(&[0x74, 0x47], "jz $+0x47");
test_display(&[0x81, 0xec, 0x10, 0x03], "sub sp, 0x310");
test_display(&[0x66, 0x81, 0xec, 0x10, 0x03, 0x00, 0x00], "sub esp, 0x310");
test_display(&[0x83, 0xf8, 0xff], "cmp ax, -0x1");
@@ -17752,10 +17752,11 @@ fn test_real_mode() {
test_display(&[0xdf, 0xe0], "fnstsw ax");
test_display(&[0xdf, 0xeb], "fucomip st(0), st(3)");
test_display(&[0xdf, 0xf3], "fcomip st(0), st(3)");
- test_display(&[0xe0, 0x12], "loopnz 0x12");
- test_display(&[0xe1, 0x12], "loopz 0x12");
- test_display(&[0xe2, 0x12], "loop 0x12");
- test_display(&[0xe3, 0x12], "jcxz 0x12");
+ test_display(&[0xe0, 0x12], "loopnz $+0x12");
+ test_display(&[0xe1, 0x12], "loopz $+0x12");
+ test_display(&[0xe2, 0x12], "loop $+0x12");
+ test_display(&[0xe3, 0x12], "jcxz $+0x12");
+ test_display(&[0xe3, 0xf0], "jcxz $+-0x10");
test_display(&[0xe4, 0x99], "in al, 0x99");
test_display(&[0xe5, 0x99], "in ax, 0x99");
test_display(&[0xe6, 0x99], "out 0x99, al");