mirror of https://github.com/pwndbg/pwndbg.git
Update register definitions + manually emulated register set (#2927)
* Update register definitions to describe register size and subregisters. Create PsuedoEmulatedRegisterFile * comments * comment typo * Typos * Add subregisters to .all list * Typo * comment fix * Comments * Comment * Use itertool.chain and rename variables for clarity.pull/2948/head
parent
a532b2b6f1
commit
59e570033f
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,232 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pwndbg.lib.regs import PsuedoEmulatedRegisterFile
|
||||
from pwndbg.lib.regs import aarch64
|
||||
from pwndbg.lib.regs import amd64
|
||||
from pwndbg.lib.regs import mips
|
||||
|
||||
|
||||
def test_emulated_register_set_amd64():
|
||||
"""
|
||||
These tests check that register writes and reads are implemented correctly.
|
||||
|
||||
RAX = 64-bits
|
||||
EAX = low 32-bits // All writes EAX will zero out the high 32-bits of RAX
|
||||
AX = low 16-bits
|
||||
AH = top half of AX
|
||||
AL = bottom half of AX
|
||||
"""
|
||||
new = PsuedoEmulatedRegisterFile(amd64, 8)
|
||||
|
||||
new.write_register("rax", -1)
|
||||
|
||||
assert new.read_register("al") == 0xFF
|
||||
assert new.read_register("ah") == 0xFF
|
||||
assert new.read_register("ax") == 0xFFFF
|
||||
assert new.read_register("eax") == 0xFFFF_FFFF
|
||||
assert new.read_register("rax") == 0xFFFF_FFFF_FFFF_FFFF
|
||||
|
||||
new.invalidate_all_registers()
|
||||
|
||||
new.write_register("al", 0b1111)
|
||||
|
||||
assert new.read_register("al") == 0b1111
|
||||
assert new.read_register("ah") is None
|
||||
assert new.read_register("ax") is None
|
||||
assert new.read_register("eax") is None
|
||||
assert new.read_register("rax") is None
|
||||
|
||||
new.invalidate_all_registers()
|
||||
|
||||
new.write_register("eax", 0xFFFF_AABB)
|
||||
|
||||
assert new.read_register("al") == 0xBB
|
||||
assert new.read_register("ah") == 0xAA
|
||||
assert new.read_register("ax") == 0xAABB
|
||||
assert new.read_register("eax") == 0xFFFF_AABB
|
||||
# The 32-bit write here zero-extends to the entire register so we can read RAX
|
||||
assert new.read_register("rax") == 0x000_0000_FFFF_AABB
|
||||
|
||||
new.invalidate_all_registers()
|
||||
|
||||
new.write_register("ah", 0x11)
|
||||
assert new.read_register("al") is None
|
||||
assert new.read_register("ah") == 0x11
|
||||
assert new.read_register("ax") is None
|
||||
assert new.read_register("eax") is None
|
||||
assert new.read_register("rax") is None
|
||||
|
||||
new.invalidate_all_registers()
|
||||
|
||||
new.write_register("ax", 0x1234)
|
||||
assert new.read_register("al") == 0x34
|
||||
assert new.read_register("ah") == 0x12
|
||||
assert new.read_register("ax") == 0x1234
|
||||
assert new.read_register("eax") is None
|
||||
assert new.read_register("rax") is None
|
||||
|
||||
|
||||
def test_emulated_register_set_amd64_more():
|
||||
new = PsuedoEmulatedRegisterFile(amd64, 8)
|
||||
|
||||
# Unwritten value should return None
|
||||
assert new.read_register("rbx") is None
|
||||
|
||||
new.write_register("ah", 0x22)
|
||||
new.write_register("al", 0x11)
|
||||
|
||||
assert new.read_register("al") == 0x11
|
||||
assert new.read_register("ah") == 0x22
|
||||
assert new.read_register("ax") == 0x2211
|
||||
assert new.read_register("eax") is None
|
||||
assert new.read_register("rax") is None
|
||||
|
||||
new.write_register("eax", 0xFF00_0000)
|
||||
|
||||
assert new.read_register("al") == 0x00
|
||||
assert new.read_register("ah") == 0x00
|
||||
assert new.read_register("ax") == 0x0000
|
||||
assert new.read_register("eax") == 0xFF00_0000
|
||||
# Writes to 32-bit registers zero-extend to the entire register
|
||||
assert new.read_register("rax") == 0xFF00_0000
|
||||
|
||||
new.write_register("al", 0x01)
|
||||
|
||||
assert new.read_register("al") == 0x01
|
||||
assert new.read_register("ah") == 0x00
|
||||
assert new.read_register("ax") == 0x0001
|
||||
assert new.read_register("eax") == 0xFF00_0001
|
||||
assert new.read_register("rax") == 0xFF00_0001
|
||||
|
||||
new.write_register("rax", 0x01)
|
||||
|
||||
assert new.read_register("al") == 0x01
|
||||
assert new.read_register("ah") == 0x00
|
||||
assert new.read_register("ax") == 0x0001
|
||||
assert new.read_register("eax") == 0x0000_0001
|
||||
assert new.read_register("rax") == 0x0000_0001
|
||||
|
||||
new.invalidate_all_registers()
|
||||
|
||||
new.write_register("rax", -1)
|
||||
new.write_register("eax", -1)
|
||||
|
||||
# The 32-bit write here zero-extends to the entire register.
|
||||
assert new.read_register("eax") == 0xFFFF_FFFF
|
||||
assert new.read_register("rax") == 0xFFFF_FFFF
|
||||
|
||||
new.invalidate_all_registers()
|
||||
|
||||
assert new.read_register("al") is None
|
||||
assert new.read_register("ah") is None
|
||||
assert new.read_register("ax") is None
|
||||
assert new.read_register("eax") is None
|
||||
assert new.read_register("rax") is None
|
||||
|
||||
new.write_register("ah", -1)
|
||||
|
||||
assert new.read_register("al") is None
|
||||
assert new.read_register("ah") == 0xFF
|
||||
assert new.read_register("ax") is None
|
||||
assert new.read_register("eax") is None
|
||||
assert new.read_register("rax") is None
|
||||
|
||||
new.write_register("bh", 0xFF)
|
||||
|
||||
assert new.read_register("bl") is None
|
||||
assert new.read_register("bh") == 0xFF
|
||||
assert new.read_register("bx") is None
|
||||
assert new.read_register("ebx") is None
|
||||
assert new.read_register("rbx") is None
|
||||
|
||||
|
||||
def test_emulated_register_set_amd64_invalidate():
|
||||
new = PsuedoEmulatedRegisterFile(amd64, 8)
|
||||
|
||||
new.write_register("rax", -1)
|
||||
|
||||
new.invalidate_register("eax")
|
||||
|
||||
assert new.read_register("al") is None
|
||||
assert new.read_register("ah") is None
|
||||
assert new.read_register("ax") is None
|
||||
assert new.read_register("eax") is None
|
||||
assert new.read_register("rax") is None
|
||||
|
||||
new.write_register("rax", -1)
|
||||
new.invalidate_register("al")
|
||||
|
||||
# "ah" register doesn't overlap with "al"
|
||||
assert new.read_register("al") is None
|
||||
assert new.read_register("ah") == 0xFF
|
||||
assert new.read_register("ax") is None
|
||||
assert new.read_register("eax") is None
|
||||
assert new.read_register("rax") is None
|
||||
|
||||
# Write a value back to al. All the others bits are still preserved
|
||||
new.write_register("al", 0xAA)
|
||||
|
||||
assert new.read_register("al") == 0xAA
|
||||
assert new.read_register("ah") == 0xFF
|
||||
assert new.read_register("ax") == 0xFFAA
|
||||
assert new.read_register("eax") == 0xFFFF_FFAA
|
||||
assert new.read_register("rax") == 0xFFFF_FFFF_FFFF_FFAA
|
||||
|
||||
new.invalidate_register("eax")
|
||||
new.write_register("eax", -1)
|
||||
|
||||
assert new.read_register("al") == 0xFF
|
||||
assert new.read_register("ah") == 0xFF
|
||||
assert new.read_register("ax") == 0xFFFF
|
||||
assert new.read_register("eax") == 0xFFFF_FFFF
|
||||
assert new.read_register("rax") == 0xFFFF_FFFF
|
||||
|
||||
|
||||
def test_emulate_register_file_amd64_sign_extension():
|
||||
new = PsuedoEmulatedRegisterFile(amd64, 8)
|
||||
|
||||
# This will sign extend the value to EAX, since the top bit in 0xFF is 1.
|
||||
new.write_register("eax", 0xFF, source_width=1, sign_extend=True)
|
||||
|
||||
assert new.read_register("al") == 0xFF
|
||||
assert new.read_register("ah") == 0xFF
|
||||
assert new.read_register("ax") == 0xFFFF
|
||||
assert new.read_register("eax") == 0xFFFF_FFFF
|
||||
assert new.read_register("rax") == 0xFFFF_FFFF
|
||||
|
||||
new.write_register("eax", 0xFF, source_width=2, sign_extend=True)
|
||||
|
||||
assert new.read_register("al") == 0xFF
|
||||
assert new.read_register("ah") == 0x00
|
||||
assert new.read_register("ax") == 0x00FF
|
||||
assert new.read_register("eax") == 0x0000_00FF
|
||||
assert new.read_register("rax") == 0x0000_00FF
|
||||
|
||||
|
||||
def test_emulated_register_set_aarch64():
|
||||
new = PsuedoEmulatedRegisterFile(aarch64, 8)
|
||||
|
||||
new.write_register("w0", 0xFFFF_AABB)
|
||||
|
||||
# The 32-bit write here zero-extends to the entire register
|
||||
assert new.read_register("x0") == 0x000_0000_FFFF_AABB
|
||||
assert new.read_register("w0") == 0xFFFF_AABB
|
||||
|
||||
new.write_register("x0", -1)
|
||||
|
||||
assert new.read_register("w0") == 0xFFFF_FFFF
|
||||
assert new.read_register("x0") == 0xFFFF_FFFF_FFFF_FFFF
|
||||
|
||||
|
||||
def test_emulated_register_set_mips():
|
||||
new = PsuedoEmulatedRegisterFile(mips, 4)
|
||||
|
||||
new.write_register("v0", 0xFFFF_AABB)
|
||||
|
||||
assert new.read_register("v0") == 0xFFFF_AABB
|
||||
|
||||
new = PsuedoEmulatedRegisterFile(mips, 8)
|
||||
|
||||
new.write_register("v0", 0xFF_FFFF_AABB)
|
||||
|
||||
assert new.read_register("v0") == 0xFF_FFFF_AABB
|
||||
Loading…
Reference in new issue