diff --git a/qiling/debugger/gdb/gdb.py b/qiling/debugger/gdb/gdb.py
index f6d6498d8..11d7cf7c0 100644
--- a/qiling/debugger/gdb/gdb.py
+++ b/qiling/debugger/gdb/gdb.py
@@ -184,6 +184,7 @@ def handle_qmark(subcmd: str) -> Reply:
from unicorn.arm64_const import UC_ARM64_REG_X29
from unicorn.mips_const import UC_MIPS_REG_INVALID
from unicorn.ppc_const import UC_PPC_REG_31
+ from unicorn.riscv_const import UC_RISCV_REG_S0
arch_uc_bp = {
QL_ARCH.X86 : UC_X86_REG_EBP,
@@ -193,7 +194,9 @@ def handle_qmark(subcmd: str) -> Reply:
QL_ARCH.MIPS : UC_MIPS_REG_INVALID, # skipped
QL_ARCH.A8086 : UC_X86_REG_EBP,
QL_ARCH.CORTEX_M : UC_ARM_REG_R11,
- QL_ARCH.PPC : UC_PPC_REG_31
+ QL_ARCH.PPC : UC_PPC_REG_31,
+ QL_ARCH.RISCV : UC_RISCV_REG_S0,
+ QL_ARCH.RISCV64 : UC_RISCV_REG_S0
}[self.ql.arch.type]
def __get_reg_idx(ucreg: int) -> int:
diff --git a/qiling/debugger/gdb/utils.py b/qiling/debugger/gdb/utils.py
index 5e3b208bf..4a836d521 100644
--- a/qiling/debugger/gdb/utils.py
+++ b/qiling/debugger/gdb/utils.py
@@ -20,10 +20,12 @@ def __init__(self, ql: Qiling, entry_point: int, exit_point: int):
self.exit_point = exit_point
self.swbp = set()
self.last_bp = None
+ self._need_flush_tb = False
def __entry_point_hook(ql: Qiling):
ql.hook_del(ep_hret)
ql.hook_code(self.dbg_hook)
+ self._need_flush_tb = True
ql.log.info(f'{PROMPT} stopped at entry point: {ql.arch.regs.arch_pc:#x}')
ql.stop()
@@ -32,6 +34,13 @@ def __entry_point_hook(ql: Qiling):
# that hook will be used to set up the breakpoint handling hook
ep_hret = ql.hook_address(__entry_point_hook, entry_point)
+ def flush_tb(self):
+ """Flush Unicorn translation blocks after GDB hook or breakpoint updates."""
+ flush_tb = getattr(self.ql.uc, 'ctl_flush_tb', None)
+
+ if flush_tb is not None:
+ flush_tb()
+
def dbg_hook(self, ql: Qiling, address: int, size: int):
if getattr(ql.arch, 'is_thumb', False):
address |= 1
@@ -56,6 +65,8 @@ def bp_insert(self, addr: int, size: int):
for bp in targets:
self.swbp.add(bp)
+ self._need_flush_tb = True
+
self.ql.log.info(f'{PROMPT} breakpoint added at {addr:#x}')
return True
@@ -69,6 +80,8 @@ def bp_remove(self, addr: int, size: int) -> bool:
for bp in targets:
self.swbp.remove(bp)
+ self._need_flush_tb = True
+
self.ql.log.info(f'{PROMPT} breakpoint removed from {addr:#x}')
return True
@@ -80,6 +93,10 @@ def resume_emu(self, address: Optional[int] = None, steps: int = 0):
if getattr(self.ql.arch, 'is_thumb', False):
address |= 0b1
+ if self._need_flush_tb:
+ self.flush_tb()
+ self._need_flush_tb = False
+
op = f'stepping {steps} instructions' if steps else 'resuming'
self.ql.log.info(f'{PROMPT} {op} from {address:#x}')
diff --git a/qiling/debugger/gdb/xml/riscv/riscv-core.xml b/qiling/debugger/gdb/xml/riscv/riscv-core.xml
new file mode 100644
index 000000000..76180b824
--- /dev/null
+++ b/qiling/debugger/gdb/xml/riscv/riscv-core.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/qiling/debugger/gdb/xml/riscv/riscv-fpu.xml b/qiling/debugger/gdb/xml/riscv/riscv-fpu.xml
new file mode 100644
index 000000000..1e1838e99
--- /dev/null
+++ b/qiling/debugger/gdb/xml/riscv/riscv-fpu.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/qiling/debugger/gdb/xml/riscv/target.xml b/qiling/debugger/gdb/xml/riscv/target.xml
new file mode 100644
index 000000000..1d0eb2b00
--- /dev/null
+++ b/qiling/debugger/gdb/xml/riscv/target.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ riscv:rv32
+ GNU/Linux
+
+
+
+
diff --git a/qiling/debugger/gdb/xml/riscv64/riscv64-core.xml b/qiling/debugger/gdb/xml/riscv64/riscv64-core.xml
new file mode 100644
index 000000000..61ec01e1d
--- /dev/null
+++ b/qiling/debugger/gdb/xml/riscv64/riscv64-core.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/qiling/debugger/gdb/xml/riscv64/riscv64-fpu.xml b/qiling/debugger/gdb/xml/riscv64/riscv64-fpu.xml
new file mode 100644
index 000000000..1e1838e99
--- /dev/null
+++ b/qiling/debugger/gdb/xml/riscv64/riscv64-fpu.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/qiling/debugger/gdb/xml/riscv64/target.xml b/qiling/debugger/gdb/xml/riscv64/target.xml
new file mode 100644
index 000000000..3f51b9352
--- /dev/null
+++ b/qiling/debugger/gdb/xml/riscv64/target.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ riscv:rv64
+ GNU/Linux
+
+
+
+
diff --git a/qiling/debugger/gdb/xmlregs.py b/qiling/debugger/gdb/xmlregs.py
index 6bc2371f4..a84ec6700 100644
--- a/qiling/debugger/gdb/xmlregs.py
+++ b/qiling/debugger/gdb/xmlregs.py
@@ -42,6 +42,12 @@
reg_map as ppc_regs
)
+from qiling.arch.riscv_const import (
+ reg_csr_map as riscv_regs_csr,
+ reg_float_map as riscv_regs_float,
+ reg_map as riscv_regs
+)
+
from qiling.const import QL_ARCH, QL_OS
RegEntry = Tuple[Optional[int], int, int]
@@ -147,7 +153,9 @@ def __load_regsmap(archtype: QL_ARCH, xmltree: ElementTree.ElementTree) -> Seque
QL_ARCH.CORTEX_M: dict(**cortex_m_regs),
QL_ARCH.ARM64: dict(**arm64_regs, **arm64_regs_v, **arm64_reg_map_fp),
QL_ARCH.MIPS: dict(**mips_regs_gpr),
- QL_ARCH.PPC: dict(**ppc_regs)
+ QL_ARCH.PPC: dict(**ppc_regs),
+ QL_ARCH.RISCV: dict(**riscv_regs, **riscv_regs_float, **riscv_regs_csr),
+ QL_ARCH.RISCV64: dict(**riscv_regs, **riscv_regs_float, **riscv_regs_csr)
}[archtype]
regsinfo = sorted(QlGdbFeatures.__walk_xml_regs(xmltree))