Move RzBreakpoint into RzDebug (#5124)

- Move trap/sw breakpoint into RzArch
- Remove RzBreakpointPlugin & RzBreakpointArch
- Add get_sw_breakpoint_at/get_sw_breakpoint_size_at binds
- Remove `dbh-`
- Change `dbh` to just list supported archs for sw breakpoints
- Implement correct PPC traps
- Add missing x86 breakpoint callback
This commit is contained in:
Giovanni 2025-05-13 01:57:37 +08:00 committed by GitHub
parent 9bac8855bb
commit 144b47d455
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
55 changed files with 299 additions and 610 deletions

View file

@ -6,7 +6,6 @@ rz_deps = [
dependency('rz_flag'),
dependency('rz_hash'),
dependency('rz_bin'),
dependency('rz_bp'),
dependency('rz_io'),
dependency('rz_search'),
dependency('rz_sign'),

View file

@ -12,7 +12,6 @@ rizin_exe = executable('rizin', 'rizin.c',
rz_arch_dep,
rz_debug_dep,
rz_config_dep,
rz_bp_dep,
rz_reg_dep,
rz_syscall_dep,
rz_egg_dep,

View file

@ -9,7 +9,6 @@ executable('rz-gg', 'rz-gg.c',
rz_hash_dep,
rz_debug_dep,
rz_config_dep,
rz_bp_dep,
rz_crypto_dep
],
install: true,

View file

@ -723,6 +723,25 @@ RZ_API void rz_asm_list_directives(void) {
}
}
/**
* \brief Returns the software breakpoint instruction (binary encoded) of the current selected arch
*
* \param a The RzAsm structure to use
* \param op The RzAsmOp to fill.
*
* \return On success true, otherwise false.
*/
RZ_API bool rz_asm_software_breakpoint(RZ_NONNULL RzAsm *a, RZ_NONNULL RzAsmOp *op) {
rz_return_val_if_fail(a && op, false);
memset(op, 0, sizeof(RzAsmOp));
if (a->cur && a->cur->sw_breakpoint) {
return a->cur->sw_breakpoint(a, op);
}
return false;
}
// returns instruction size
RZ_API int rz_asm_assemble(RzAsm *a, RzAsmOp *op, const char *buf) {
rz_return_val_if_fail(a && op && buf, 0);

View file

@ -285,7 +285,7 @@ static char *mnemonics(RzAsm *a, int id, bool json) {
return rz_strbuf_drain(buf);
}
char **arm_cpu_descriptions() {
static char **arm_cpu_descriptions() {
static char *cpu_desc[] = {
"v8", "ARMv8 version",
"cortexm", "ARM Cortex-M family",
@ -297,6 +297,36 @@ char **arm_cpu_descriptions() {
return cpu_desc;
}
static bool arm_sw_breakpoint(RzAsm *a, RzAsmOp *op) {
if (a->bits == 64) {
// arm64/aarch64
// { 64, 4, 0, "\x00\x00\x20\xd4" }, // le - arm64 brk0
// { 64, 4, 1, "\xd4\x20\x00\x00" }, // be - arm64
// { 64, 1, 0, "\xfe\xde\xff\xe7" }, // le - arm64 - hacky fix
rz_asm_op_set_buf(op, a->big_endian ? (const ut8 *)"\xd4\x20\x00\x00" : (const ut8 *)"\x00\x00\x20\xd4", 4);
return true;
} else if (a->bits == 32) {
// arm32
// { 4, 0, "\xfe\xde\xff\xe7" }, // arm-le - from a gdb patch
// { 4, 1, "\xe7\xff\xde\xfe" }, // arm-be
// { 4, 0, "\xf0\x01\xf0\xe7" }, // eabi-le - undefined instruction - for all kernels
// { 4, 1, "\xe7\xf0\x01\xf0" }, // eabi-be
// eabi - undefined instruction - for all kernels
rz_asm_op_set_buf(op, a->big_endian ? (const ut8 *)"\xe7\xf0\x01\xf0" : (const ut8 *)"\xf0\x01\xf0\xe7", 4);
return true;
}
// arm32 - thumb mode
// { 16, 2, 0, "\x01\xbe" }, // thumb-le
// { 16, 2, 1, "\xbe\x01" }, // thumb-be
// { 16, 2, 0, "\xfe\xdf" }, // arm-thumb-le
// { 16, 2, 1, "\xdf\xfe" }, // arm-thumb-be
// { 16, 4, 0, "\xff\xff\xff\xff" }, // arm-thumb-le
// { 16, 4, 1, "\xff\xff\xff\xff" }, // arm-thumb-be
rz_asm_op_set_buf(op, a->big_endian ? (const ut8 *)"\xbe\x01" : (const ut8 *)"\x01\xbe", 2);
return true;
}
RzAsmPlugin rz_asm_plugin_arm_cs = {
.name = "arm",
.desc = "ARM Capstone-based disassembler",
@ -313,6 +343,7 @@ RzAsmPlugin rz_asm_plugin_arm_cs = {
.init = &arm_init,
.fini = &arm_fini,
.get_cpu_desc = arm_cpu_descriptions,
.sw_breakpoint = arm_sw_breakpoint,
#if 0
// arm32 and arm64
"crypto,databarrier,divide,fparmv8,multpro,neon,t2extractpack,"

View file

@ -37,7 +37,7 @@ static int assemble(RzAsm *a, RzAsmOp *ao, const char *str) {
return (int)written;
}
char **avr_cpu_descriptions() {
static char **avr_cpu_descriptions() {
static char *cpu_desc[] = {
"ATmega8", "8-bit AVR microcontroller with 8KB Flash, 1KB SRAM",
"ATmega1280", "8-bit AVR microcontroller with 128KB Flash, 8KB SRAM",

View file

@ -187,6 +187,13 @@ static bool bf_fini(void *user) {
return true;
}
static bool bf_sw_breakpoint(RzAsm *a, RzAsmOp *op) {
// { 0, 1, 0, (const ut8 *)"\xff" },
// { 0, 1, 0, (const ut8 *)"\x00" },
rz_asm_op_set_buf(op, (const ut8 *)"\xff", 1);
return true;
}
RzAsmPlugin rz_asm_plugin_bf = {
.name = "bf",
.author = "pancake, nibble",
@ -199,5 +206,6 @@ RzAsmPlugin rz_asm_plugin_bf = {
.init = bf_init,
.fini = bf_fini,
.disassemble = &disassemble,
.assemble = &assemble
.assemble = &assemble,
.sw_breakpoint = bf_sw_breakpoint,
};

View file

@ -79,7 +79,7 @@ static int m680x_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) {
return op->size;
}
char **m680x_cpu_descriptions() {
static char **m680x_cpu_descriptions() {
static char *cpu_desc[] = {
"6800", "Motorola 6800: 8-bit microprocessor launched in 1974",
"6801", "Motorola 6801: Enhanced version of the 6800 with additional features like on-chip RAM and timers.",

View file

@ -103,7 +103,7 @@ beach:
return ret;
}
char **m68k_cpu_descriptions() {
static char **m68k_cpu_descriptions() {
static char *cpu_desc[] = {
"68000", "Motorola 68000: 16/32-bit CISC microprocessor",
"68010", "Motorola 68010: 16/32-bit microprocessors. Successor to Motoroloa 68000",

View file

@ -82,7 +82,7 @@ static int mips_assemble(RzAsm *a, RzAsmOp *op, const char *str) {
return mips_assemble_opcode(str, a->pc, &op->buf, a->big_endian);
}
char **mips_cpu_descriptions() {
static char **mips_cpu_descriptions() {
static char *cpu_desc[] = {
"mips3", "MIPS III architecture.",
"mips1", "MIPS I architecture",
@ -121,6 +121,16 @@ char **mips_cpu_descriptions() {
return cpu_desc;
}
static bool mips_sw_breakpoint(RzAsm *a, RzAsmOp *op) {
// mips32/64
// { 32, 4, 0, "\x0d\x00\x00\x00" },
// { 32, 4, 1, "\x00\x00\x00\x0d" },
// { 64, 4, 0, "\x0d\x00\x00\x00" },
// { 64, 4, 1, "\x00\x00\x00\x0d" },
rz_asm_op_set_buf(op, a->big_endian ? (const ut8 *)"\x00\x00\x00\x0d" : (const ut8 *)"\x0d\x00\x00\x00", 4);
return true;
}
RzAsmPlugin rz_asm_plugin_mips_cs = {
.name = "mips",
.desc = "MIPS Capstone-based disassembler",
@ -135,6 +145,7 @@ RzAsmPlugin rz_asm_plugin_mips_cs = {
.mnemonics = mips_asm_mnemonics,
.assemble = &mips_assemble,
.get_cpu_desc = mips_cpu_descriptions,
.sw_breakpoint = mips_sw_breakpoint,
};
#ifndef RZ_PLUGIN_INCORE

View file

@ -29,7 +29,7 @@ static int asm_pic_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *b, int l) {
return -1;
}
char **pic_cpu_descriptions() {
static char **pic_cpu_descriptions() {
static char *cpu_desc[] = {
"baseline", "Baseline 12-bit instruction set microcontrollers: PIC10Fxxx, PIC12Fxxx, and PIC16Fxxx",
"midrange", "Mid-Range 14-bit instruction set microcontrollers: PIC10Fxxx, PIC12Fxxx, and PIC16Fxxx",

View file

@ -116,7 +116,7 @@ static int ppc_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) {
return op->size;
}
char **ppc_cpu_descriptions() {
static char **ppc_cpu_descriptions() {
static char *cpu_desc[] = {
"ppc", "Generic PowerPC CPU",
"vle", "PowerPC with Variable Length Encoding extension",
@ -127,6 +127,14 @@ char **ppc_cpu_descriptions() {
return cpu_desc;
}
static bool ppc_sw_breakpoint(RzAsm *a, RzAsmOp *op) {
// ppc | tw 31, 0, 0 | trap
// { 0x7f, 0xe0, 0x00, 0x08 } | big endian
// { 0x08, 0x00, 0xe0, 0x7f } | little endian
rz_asm_op_set_buf(op, a->big_endian ? (const ut8 *)"\x7f\xe0\x00\x08" : (const ut8 *)"\x08\x00\xe0\x7f", 4);
return true;
}
RzAsmPlugin rz_asm_plugin_ppc_cs = {
.name = "ppc",
.desc = "PowerPC Capstone-based disassembler",
@ -141,6 +149,7 @@ RzAsmPlugin rz_asm_plugin_ppc_cs = {
.disassemble = &ppc_disassemble,
.mnemonics = ppc_asm_mnemonics,
.get_cpu_desc = ppc_cpu_descriptions,
.sw_breakpoint = ppc_sw_breakpoint,
};
#ifndef RZ_PLUGIN_INCORE

View file

@ -35,6 +35,13 @@ static int assemble(RzAsm *a, RzAsmOp *ao, const char *str) {
return 2;
}
static bool sh_sw_breakpoint(RzAsm *a, RzAsmOp *op) {
// { 32, 2, 1, "\xc3\x20" }, // Big endian
// { 32, 2, 0, "\x20\xc3" }, // Little endian
rz_asm_op_set_buf(op, a->big_endian ? (const ut8 *)"\xc3\x20" : (const ut8 *)"\x20\xc3", 2);
return true;
}
RzAsmPlugin rz_asm_plugin_sh = {
.name = "sh",
.arch = "sh",
@ -44,5 +51,6 @@ RzAsmPlugin rz_asm_plugin_sh = {
.endian = RZ_SYS_ENDIAN_LITTLE | RZ_SYS_ENDIAN_BIG,
.desc = "Hitachi/Renesas SuperH-4 disassembler",
.disassemble = &disassemble,
.assemble = &assemble
.assemble = &assemble,
.sw_breakpoint = sh_sw_breakpoint,
};

View file

@ -65,7 +65,7 @@ fin:
return ret;
}
char **sparc_cpu_descriptions() {
static char **sparc_cpu_descriptions() {
static char *cpu_desc[] = {
"v9", "SPARC V9: 64-bit RISC architecture specification",
NULL

View file

@ -61,7 +61,7 @@ static char *tms320_mnemonics(RzAsm *a, int id, bool json) {
return tms320_c64x_mnemonics(a, id, json, ctx->c64x);
}
char **tms320_cpu_descriptions() {
static char **tms320_cpu_descriptions() {
static char *cpu_desc[] = {
"c54x", "Texas Instruments TMS320C54x DSP family",
"c55x", "Texas Instruments TMS320C55x DSP family",

View file

@ -103,7 +103,7 @@ static bool fini(void *u) {
return true;
}
char **tricore_cpu_descriptions() {
static char **tricore_cpu_descriptions() {
static char *cpu_desc[] = {
"tricore", "Generic TriCore CPU family by Infineon",
NULL

View file

@ -131,6 +131,13 @@ static int x86_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) {
return op->size;
}
static bool x86_sw_breakpoint(RzAsm *a, RzAsmOp *op) {
// { 0, 1, 0, "\xcc" }, // valid for 16, 32, 64
// { 0, 2, 0, "\xcd\x03" },
rz_asm_op_set_buf(op, (const ut8 *)"\xcc", 1);
return true;
}
RzAsmPlugin rz_asm_plugin_x86_cs = {
.name = "x86",
.desc = "X86/X86_64 Capstone-based disassembler",
@ -144,6 +151,7 @@ RzAsmPlugin rz_asm_plugin_x86_cs = {
.fini = x86_asm_fini,
.mnemonics = x86_asm_mnemonics,
.disassemble = &x86_disassemble,
.sw_breakpoint = x86_sw_breakpoint,
.features = "vm,3dnow,aes,adx,avx,avx2,avx512,bmi,bmi2,cmov,"
"f16c,fma,fma4,fsgsbase,hle,mmx,rtm,sha,sse1,sse2,"
"sse3,sse41,sse42,sse4a,ssse3,pclmul,xop"

View file

@ -29,7 +29,7 @@ beach:
return -1;
}
char **xtensa_cpu_descriptions() {
static char **xtensa_cpu_descriptions() {
static char *cpu_desc[] = {
"esp32", "Xtensa microcontroller with Wi-Fi and Bluetooth capabilities",
"esp32s2", "Xtensa microcontroller with Wi-Fi and USB OTG support",

View file

View file

@ -1,82 +0,0 @@
// SPDX-FileCopyrightText: 2009-2015 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_bp.h>
#include <rz_lib.h>
#include <rz_util/ht_sp.h>
#include <rz_util/rz_iterator.h>
RZ_API int rz_bp_plugin_del_byname(RzBreakpoint *bp, RZ_NONNULL const char *name) {
rz_return_val_if_fail(bp && name, false);
bool found = false;
RzBreakpointPlugin *bp_plugin = ht_sp_find(bp->plugins, name, &found);
if (!found) {
return false;
}
if (bp_plugin == bp->cur) {
bp->cur = NULL;
}
ht_sp_delete(bp->plugins, name);
bp->nbps--;
return true;
}
RZ_API bool rz_bp_plugin_add(RzBreakpoint *bp, RZ_BORROW RZ_NONNULL RzBreakpointPlugin *plugin) {
rz_return_val_if_fail(bp && plugin, false);
if (!ht_sp_insert(bp->plugins, plugin->name, plugin)) {
RZ_LOG_WARN("Plugin '%s' was already added.\n", plugin->name);
}
return true;
}
RZ_API bool rz_bp_plugin_del(RzBreakpoint *bp, RZ_BORROW RZ_NONNULL RzBreakpointPlugin *plugin) {
rz_return_val_if_fail(bp && plugin, false);
bool res = ht_sp_delete(bp->plugins, plugin->name);
if (res) {
bp->nbps--;
if (bp->cur == plugin) {
bp->cur = NULL;
}
}
return res;
}
/**
* Switch to the registered breakpoint plugin called \p name
*/
RZ_API int rz_bp_use(RZ_NONNULL RzBreakpoint *bp, RZ_NONNULL const char *name) {
rz_return_val_if_fail(bp && name, false);
RzIterator *iter = ht_sp_as_iter(bp->plugins);
RzBreakpointPlugin **val;
rz_iterator_foreach(iter, val) {
RzBreakpointPlugin *h = *val;
if (!strcmp(h->name, name)) {
bp->cur = h;
rz_iterator_free(iter);
return true;
}
}
rz_iterator_free(iter);
return false;
}
RZ_DEPRECATE RZ_API void rz_bp_plugin_print(RZ_NONNULL RzBreakpoint *bp) {
rz_return_if_fail(bp);
RzIterator *iter = ht_sp_as_iter(bp->plugins);
RzList *plugin_list = rz_list_new_from_iterator(iter);
if (!plugin_list) {
rz_iterator_free(iter);
return;
}
rz_list_sort(plugin_list, (RzListComparator)rz_breakpoint_plugin_cmp, NULL);
RzListIter *it;
RzBreakpointPlugin *b;
rz_list_foreach (plugin_list, it, b) {
bp->cb_printf("bp %c %s\n",
(bp->cur && !strcmp(bp->cur->name, b->name)) ? '*' : '-',
b->name);
}
rz_list_free(plugin_list);
rz_iterator_free(iter);
}

View file

@ -1,51 +0,0 @@
bp_plugins_list = [
'arm',
'bf',
'mips',
'ppc',
'sh',
'x86'
]
bp_plugins = {
'base_name': 'rz_bp',
'base_struct': 'RzBreakpointPlugin',
'list': bp_plugins_list,
}
rz_bp_sources = [
'bp.c',
'bp_io.c',
'bp_plugin.c',
'bp_traptrace.c',
'bp_watch.c',
'serialize_bp.c',
'p/bp_arm.c',
'p/bp_bf.c',
'p/bp_mips.c',
'p/bp_ppc.c',
'p/bp_sh.c',
'p/bp_x86.c'
]
rz_bp = library('rz_bp', rz_bp_sources,
include_directories: [platform_inc],
dependencies: [rz_util_dep],
install: true,
implicit_include_directories: false,
install_rpath: rpath_lib,
soversion: rizin_libversion,
version: rizin_version,
name_suffix: lib_name_suffix,
name_prefix: lib_name_prefix,
)
rz_bp_dep = declare_dependency(link_with: rz_bp,
include_directories: [platform_inc])
meson.override_dependency('rz_bp', rz_bp_dep)
modules += { 'rz_bp': {
'target': rz_bp,
'dependencies': ['rz_util'],
'plugins': [bp_plugins]
}}

View file

@ -1,47 +0,0 @@
// SPDX-FileCopyrightText: 2009-2017 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_bp.h>
#include <rz_lib.h>
static struct rz_bp_arch_t rz_bp_plugin_arm_bps[] = {
{ 64, 4, 0, (const ut8 *)"\x00\x00\x20\xd4" }, // le - arm64 brk0
{ 64, 4, 1, (const ut8 *)"\xd4\x20\x00\x00" }, // be - arm64
//{ 64, 1, 0, (const ut8*)"\xfe\xde\xff\xe7" }, // le - arm64 // hacky fix
{ 32, 4, 0, (const ut8 *)"\xf0\x01\xf0\xe7" }, // eabi-le - undefined instruction - for all kernels
{ 32, 4, 1, (const ut8 *)"\xe7\xf0\x01\xf0" }, // eabi-be
// { 32, 1, 0, (const ut8*)"\xff\xff\xff\xff" }, // le - linux only? (undefined instruction)
// { 32, 1, 1, (const ut8*)"\xff\xff\xff\xff" }, // be - linux only? (undefined instruction)
// { 32, 4, 0, (const ut8*)"\x01\x00\x9f\xef" }, // le - linux only? (undefined instruction)
// { 32, 4, 1, (const ut8*)"\xef\x9f\x00\x01" }, // be
#if 0
{ 4, 0, (const ut8*)"\xfe\xde\xff\xe7" }, // arm-le - from a gdb patch
{ 4, 1, (const ut8*)"\xe7\xff\xde\xfe" }, // arm-be
{ 4, 0, (const ut8*)"\xf0\x01\xf0\xe7" }, // eabi-le - undefined instruction - for all kernels
{ 4, 1, (const ut8*)"\xe7\xf0\x01\xf0" }, // eabi-be
#endif
{ 16, 2, 0, (const ut8 *)"\x01\xbe" }, // thumb-le
{ 16, 2, 1, (const ut8 *)"\xbe\x01" }, // thumb-be
{ 16, 2, 0, (const ut8 *)"\xfe\xdf" }, // arm-thumb-le
{ 16, 2, 1, (const ut8 *)"\xdf\xfe" }, // arm-thumb-be
{ 16, 4, 0, (const ut8 *)"\xff\xff\xff\xff" }, // arm-thumb-le
{ 16, 4, 1, (const ut8 *)"\xff\xff\xff\xff" }, // arm-thumb-be
{ 0, 0, 0, NULL }
};
struct rz_bp_plugin_t rz_bp_plugin_arm = {
.name = "arm",
.arch = "arm",
.nbps = 9,
.bps = rz_bp_plugin_arm_bps,
};
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_BP,
.data = &rz_bp_plugin_arm,
.version = RZ_VERSION
};
#endif

View file

@ -1,26 +0,0 @@
// SPDX-FileCopyrightText: 2011 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_bp.h>
#include <rz_lib.h>
static struct rz_bp_arch_t rz_bp_plugin_bf_bps[] = {
{ 0, 1, 0, (const ut8 *)"\xff" },
{ 0, 1, 0, (const ut8 *)"\x00" },
{ 0, 0, 0, NULL },
};
struct rz_bp_plugin_t rz_bp_plugin_bf = {
.name = "bf",
.arch = "bf",
.nbps = 2,
.bps = rz_bp_plugin_bf_bps,
};
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_BP,
.data = &rz_bp_plugin_bf,
.version = RZ_VERSION
};
#endif

View file

@ -1,28 +0,0 @@
// SPDX-FileCopyrightText: 2010-2015 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_bp.h>
#include <rz_lib.h>
static struct rz_bp_arch_t rz_bp_plugin_mips_bps[] = {
{ 32, 4, 0, (const ut8 *)"\x0d\x00\x00\x00" },
{ 32, 4, 1, (const ut8 *)"\x00\x00\x00\x0d" },
{ 64, 4, 0, (const ut8 *)"\x0d\x00\x00\x00" },
{ 64, 4, 1, (const ut8 *)"\x00\x00\x00\x0d" },
{ 0, 0, 0, NULL }
};
struct rz_bp_plugin_t rz_bp_plugin_mips = {
.name = "mips",
.arch = "mips",
.nbps = 10,
.bps = rz_bp_plugin_mips_bps,
};
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_BP,
.data = &rz_bp_plugin_mips,
.version = RZ_VERSION
};
#endif

View file

@ -1,27 +0,0 @@
// SPDX-FileCopyrightText: 2010 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_bp.h>
#include <rz_lib.h>
static struct rz_bp_arch_t rz_bp_plugin_ppc_bps[] = {
/* XXX: FIX those are not really breakpoint opcodes at all */
{ 32, 4, 0, (const ut8 *)"\x00\x00\x00\x0d" }, // little endian
{ 32, 4, 1, (const ut8 *)"\x0d\x00\x00\x00" }, // big endian
{ 0, 0, 0, NULL }
};
struct rz_bp_plugin_t rz_bp_plugin_ppc = {
.name = "ppc",
.arch = "ppc",
.nbps = 2,
.bps = rz_bp_plugin_ppc_bps,
};
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_BP,
.data = &rz_bp_plugin_ppc,
.version = RZ_VERSION
};
#endif

View file

@ -1,26 +0,0 @@
// SPDX-FileCopyrightText: 2009-2015 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_bp.h>
#include <rz_lib.h>
static struct rz_bp_arch_t rz_bp_plugin_sh_bps[] = {
{ 32, 2, 0, (const ut8 *)"\x20\xc3" }, // Little endian bp
{ 32, 2, 1, (const ut8 *)"\xc3\x20" }, // Big endian bp
{ 0, 0, 0, NULL },
};
struct rz_bp_plugin_t rz_bp_plugin_sh = {
.name = "sh",
.arch = "sh",
.nbps = 2,
.bps = rz_bp_plugin_sh_bps,
};
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_BP,
.data = &rz_bp_plugin_sh,
.version = RZ_VERSION
};
#endif

View file

@ -1,26 +0,0 @@
// SPDX-FileCopyrightText: 2009-2015 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_bp.h>
#include <rz_lib.h>
static struct rz_bp_arch_t rz_bp_plugin_x86_bps[] = {
{ 0, 1, 0, (const ut8 *)"\xcc" }, // valid for 16, 32, 64
{ 0, 2, 0, (const ut8 *)"\xcd\x03" },
{ 0, 0, 0, NULL },
};
struct rz_bp_plugin_t rz_bp_plugin_x86 = {
.name = "x86",
.arch = "x86",
.nbps = 2,
.bps = rz_bp_plugin_x86_bps,
};
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_BP,
.data = &rz_bp_plugin_x86,
.version = RZ_VERSION
};
#endif

View file

@ -690,9 +690,6 @@ static bool cb_asmbits(void *user, void *data) {
}
update_syscall_ns(core);
__setsegoff(core->config, asmarch, core->analysis->bits);
if (core->dbg) {
rz_bp_use(core->dbg->bp, asmarch);
}
/* set pcalign */
int v = rz_analysis_archinfo(core->analysis, RZ_ANALYSIS_ARCHINFO_TEXT_ALIGN);
rz_config_set_i(core->config, "asm.pcalign", (v != -1) ? v : 1);

View file

@ -1981,24 +1981,29 @@ RZ_IPI RzCmdStatus rz_cmd_debug_toggle_bp_trace_index_handler(RzCore *core, int
// dbh
RZ_IPI RzCmdStatus rz_cmd_debug_bp_plugin_handler(RzCore *core, int argc, const char **argv) {
if (argc == 1) {
rz_bp_plugin_print(core->dbg->bp);
} else if (argc == 2) {
if (!rz_bp_use(core->dbg->bp, argv[1])) {
RZ_LOG_ERROR("Failed to set breakpoint plugin handler to %s\n", argv[1]);
return RZ_CMD_STATUS_ERROR;
}
}
return RZ_CMD_STATUS_OK;
}
rz_return_val_if_fail(core, RZ_CMD_STATUS_ERROR);
RzAsm *a = core->rasm;
// dbh-
RZ_IPI RzCmdStatus rz_cmd_debug_remove_bp_plugin_handler(RzCore *core, int argc, const char **argv) {
for (int i = 1; i < argc; i++) {
if (!rz_bp_plugin_del_byname(core->dbg->bp, argv[i])) {
RZ_LOG_ERROR("Failed to delete breakpoint plugin handler: %s\n", argv[i]);
}
RzIterator *iter = ht_sp_as_iter(a->plugins);
RzList *plugin_list = rz_list_new_from_iterator(iter);
if (!plugin_list) {
rz_iterator_free(iter);
return RZ_CMD_STATUS_ERROR;
}
rz_list_sort(plugin_list, (RzListComparator)rz_asm_plugin_cmp, NULL);
RzListIter *it;
RzAsmPlugin *ap;
rz_list_foreach (plugin_list, it, ap) {
if (!ap->sw_breakpoint) {
continue;
}
rz_cons_printf("%s\n", ap->name);
}
rz_list_free(plugin_list);
rz_iterator_free(iter);
return RZ_CMD_STATUS_OK;
}

View file

@ -163,18 +163,9 @@ commands:
- name: idx
type: RZ_CMD_ARG_TYPE_RZNUM
- name: dbh
summary: List breakpoint plugin handlers / Set breakpoint plugin handler
summary: List archs which supports software breakpoints
cname: cmd_debug_bp_plugin
args:
- name: handler
type: RZ_CMD_ARG_TYPE_STRING
optional: true
- name: dbh-
summary: Remove breakpoint plugin handler
cname: cmd_debug_remove_bp_plugin
args:
- name: handler
type: RZ_CMD_ARG_TYPE_STRING
args: []
- name: dbt
summary: Backtrace commands
subcommands:

View file

@ -450,8 +450,6 @@ static const RzCmdDescArg cmd_debug_toggle_bp_index_args[2];
static const RzCmdDescArg cmd_debug_enable_bp_trace_index_args[2];
static const RzCmdDescArg cmd_debug_disable_bp_trace_index_args[2];
static const RzCmdDescArg cmd_debug_toggle_bp_trace_index_args[2];
static const RzCmdDescArg cmd_debug_bp_plugin_args[2];
static const RzCmdDescArg cmd_debug_remove_bp_plugin_args[2];
static const RzCmdDescArg cmd_debug_display_bt_oneline_args[2];
static const RzCmdDescArg cmd_debug_bp_set_expr_cur_offset_args[2];
static const RzCmdDescArg cmd_debug_add_watchpoint_args[3];
@ -9258,34 +9256,13 @@ static const RzCmdDescHelp cmd_debug_toggle_bp_trace_index_help = {
};
static const RzCmdDescArg cmd_debug_bp_plugin_args[] = {
{
.name = "handler",
.type = RZ_CMD_ARG_TYPE_STRING,
.flags = RZ_CMD_ARG_FLAG_LAST,
.optional = true,
},
{ 0 },
};
static const RzCmdDescHelp cmd_debug_bp_plugin_help = {
.summary = "List breakpoint plugin handlers / Set breakpoint plugin handler",
.summary = "List archs which supports software breakpoints",
.args = cmd_debug_bp_plugin_args,
};
static const RzCmdDescArg cmd_debug_remove_bp_plugin_args[] = {
{
.name = "handler",
.type = RZ_CMD_ARG_TYPE_STRING,
.flags = RZ_CMD_ARG_FLAG_LAST,
},
{ 0 },
};
static const RzCmdDescHelp cmd_debug_remove_bp_plugin_help = {
.summary = "Remove breakpoint plugin handler",
.args = cmd_debug_remove_bp_plugin_args,
};
static const RzCmdDescHelp dbt_help = {
.summary = "Backtrace commands",
};
@ -22677,9 +22654,6 @@ RZ_IPI void rzshell_cmddescs_init(RzCore *core) {
RzCmdDesc *cmd_debug_bp_plugin_cd = rz_cmd_desc_argv_new(core->rcmd, db_cd, "dbh", rz_cmd_debug_bp_plugin_handler, &cmd_debug_bp_plugin_help);
rz_warn_if_fail(cmd_debug_bp_plugin_cd);
RzCmdDesc *cmd_debug_remove_bp_plugin_cd = rz_cmd_desc_argv_new(core->rcmd, db_cd, "dbh-", rz_cmd_debug_remove_bp_plugin_handler, &cmd_debug_remove_bp_plugin_help);
rz_warn_if_fail(cmd_debug_remove_bp_plugin_cd);
RzCmdDesc *dbt_cd = rz_cmd_desc_group_state_new(core->rcmd, db_cd, "dbt", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON | RZ_OUTPUT_MODE_TABLE | RZ_OUTPUT_MODE_RIZIN | RZ_OUTPUT_MODE_QUIET, rz_cmd_debug_display_bt_handler, &cmd_debug_display_bt_help, &dbt_help);
rz_warn_if_fail(dbt_cd);
RzCmdDesc *cmd_debug_display_bt_oneline_cd = rz_cmd_desc_argv_new(core->rcmd, dbt_cd, "dbt=", rz_cmd_debug_display_bt_oneline_handler, &cmd_debug_display_bt_oneline_help);

View file

@ -1133,8 +1133,6 @@ RZ_IPI RzCmdStatus rz_cmd_debug_disable_bp_trace_index_handler(RzCore *core, int
RZ_IPI RzCmdStatus rz_cmd_debug_toggle_bp_trace_index_handler(RzCore *core, int argc, const char **argv);
// "dbh"
RZ_IPI RzCmdStatus rz_cmd_debug_bp_plugin_handler(RzCore *core, int argc, const char **argv);
// "dbh-"
RZ_IPI RzCmdStatus rz_cmd_debug_remove_bp_plugin_handler(RzCore *core, int argc, const char **argv);
// "dbt"
RZ_IPI RzCmdStatus rz_cmd_debug_display_bt_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state);
// "dbt="

View file

@ -1456,11 +1456,52 @@ static void bp_maps_sync(void *user) {
}
}
static int bp_bits_at(ut64 addr, void *user) {
RzCore *core = user;
int r = 0;
rz_core_arch_bits_at(core, addr, &r, NULL);
return r ? r : core->analysis->bits;
static void core_set_rz_asm_by_hint(RzCore *core, ut64 addr) {
int bits = 0;
const char *arch = NULL;
rz_core_arch_bits_at(core, addr, &bits, &arch);
rz_asm_set_arch(core->rasm, arch, bits);
}
static void core_set_rz_asm_by_config(RzCore *core) {
const char *arch = rz_config_get(core->config, "asm.arch");
int bits = rz_config_get_i(core->config, "asm.bits");
rz_asm_set_arch(core->rasm, arch, bits);
}
static RzStrBuf *bp_get_sw_breakpoint_at(ut64 addr, void *user) {
RzCore *core = (RzCore *)user;
RzStrBuf *opcode = NULL;
RzAsmOp op = { 0 };
core_set_rz_asm_by_hint(core, addr);
rz_asm_op_init(&op);
if (rz_asm_software_breakpoint(core->rasm, &op) &&
(opcode = rz_strbuf_new(NULL))) {
rz_strbuf_copy(opcode, &op.buf);
}
rz_asm_op_fini(&op);
core_set_rz_asm_by_config(core);
return opcode;
}
static size_t bp_get_sw_breakpoint_size_at(ut64 addr, void *user) {
RzCore *core = (RzCore *)user;
size_t length = 0;
RzAsmOp op = { 0 };
core_set_rz_asm_by_hint(core, addr);
rz_asm_op_init(&op);
if (rz_asm_software_breakpoint(core->rasm, &op)) {
length = rz_strbuf_length(&op.buf);
}
rz_asm_op_fini(&op);
core_set_rz_asm_by_config(core);
return length;
}
static void ev_iowrite_cb(RzEvent *ev, int type, void *user, void *data) {
@ -1670,7 +1711,8 @@ RZ_API bool rz_core_init(RzCore *core) {
.user = core,
.is_mapped = bp_is_mapped,
.maps_sync = bp_maps_sync,
.bits_at = bp_bits_at
.get_sw_breakpoint_at = bp_get_sw_breakpoint_at,
.get_sw_breakpoint_size_at = bp_get_sw_breakpoint_size_at,
};
core->dbg = rz_debug_new(&bp_ctx);
@ -1705,7 +1747,6 @@ RZ_API bool rz_core_init(RzCore *core) {
}
}
rz_config_set(core->config, "asm.arch", RZ_SYS_ARCH);
rz_bp_use(core->dbg->bp, RZ_SYS_ARCH);
update_sdb(core);
{
char *a = rz_path_system(RZ_FLAGS);

View file

@ -29,7 +29,6 @@ static bool lib_core_dt(RzLibPlugin *pl, void *user, void *data) {
CB(io, io)
CB(crypto, crypto)
CB(debug, dbg)
CB(bp, dbg->bp)
CB(lang, lang)
CB(analysis, analysis)
CB(asm, rasm)
@ -112,7 +111,6 @@ RZ_API void rz_core_loadlibs_init(RzCore *core) {
DF(CORE, "core plugins", core);
DF(CRYPTO, "crypto plugins", crypto);
DF(DBG, "debugger plugins", debug);
DF(BP, "debugger breakpoint plugins", bp);
DF(LANG, "language plugins", lang);
DF(ANALYSIS, "analysis plugins", analysis);
DF(ASM, "(dis)assembler plugins", asm);

View file

@ -151,7 +151,6 @@ rz_core_deps = [
rz_crypto_dep,
rz_io_dep,
rz_reg_dep,
rz_bp_dep,
rz_syscall_dep,
rz_egg_dep,
rz_search_dep,
@ -209,7 +208,6 @@ modules += { 'rz_core': {
'rz_config',
'rz_bin',
'rz_arch',
'rz_bp',
'rz_sign',
'rz_il'
],

View file

@ -2,11 +2,6 @@
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_bp.h>
#include "rz_bp_plugins.h"
RZ_LIB_VERSION(rz_bp);
static struct rz_bp_plugin_t *bp_static_plugins[] = { RZ_BP_STATIC_PLUGINS };
static void rz_bp_item_free(RzBreakpointItem *b) {
free(b->name);
@ -24,7 +19,8 @@ static void rz_bp_item_free(RzBreakpointItem *b) {
* \param ctx global context in which the instance will operate (giving mappings, etc)
*/
RZ_API RzBreakpoint *rz_bp_new(RZ_BORROW RZ_NONNULL RzBreakpointContext *ctx) {
int i;
rz_return_val_if_fail(ctx, NULL);
RzBreakpoint *bp = RZ_NEW0(RzBreakpoint);
if (!bp) {
return NULL;
@ -35,65 +31,50 @@ RZ_API RzBreakpoint *rz_bp_new(RZ_BORROW RZ_NONNULL RzBreakpointContext *ctx) {
bp->stepcont = RZ_BP_CONT_NORMAL;
bp->traces = rz_bp_traptrace_new();
bp->cb_printf = (PrintfCallback)printf;
bp->opcode = NULL;
bp->bps = rz_list_newf((RzListFree)rz_bp_item_free);
bp->plugins = ht_sp_new(HT_STR_DUP, NULL, NULL);
bp->nhwbps = 0;
for (i = 0; i < RZ_ARRAY_SIZE(bp_static_plugins); i++) {
rz_bp_plugin_add(bp, bp_static_plugins[i]);
}
memset(&bp->iob, 0, sizeof(bp->iob));
return bp;
}
RZ_API RzBreakpoint *rz_bp_free(RzBreakpoint *bp) {
RZ_API void rz_bp_free(RzBreakpoint *bp) {
if (!bp) {
return;
}
rz_list_free(bp->bps);
ht_sp_free(bp->plugins);
rz_list_free(bp->traces);
rz_strbuf_free(bp->opcode);
free(bp->bps_idx);
free(bp);
return NULL;
}
RZ_API bool rz_bp_set_opcode(RZ_NONNULL RzBreakpoint *bp, ut64 addr) {
rz_return_val_if_fail(bp, false);
RZ_FREE_CUSTOM(bp->opcode, rz_strbuf_free);
if (!bp->ctx.get_sw_breakpoint_at) {
return false;
}
bp->opcode = bp->ctx.get_sw_breakpoint_at(addr, bp->ctx.user);
return bp->opcode != NULL;
}
/**
* Get the bytes to place at \p addr in order to set a sw breakpoint there
* \p return the length of bytes or 0 on failure
*/
RZ_API int rz_bp_get_bytes(RZ_NONNULL RzBreakpoint *bp, ut64 addr, RZ_NONNULL ut8 *buf, int len) {
RZ_API size_t rz_bp_get_bytes(RZ_NONNULL RzBreakpoint *bp, ut64 addr, RZ_NONNULL ut8 *buf, int len) {
rz_return_val_if_fail(bp && buf, 0);
int endian = bp->endian;
int bits = bp->ctx.bits_at ? bp->ctx.bits_at(addr, bp->ctx.user) : 0;
struct rz_bp_arch_t *b;
if (!bp->cur) {
if (!rz_bp_set_opcode(bp, addr)) {
// cannot use get bytes of the opcode.
return 0;
}
// find matching size breakpoint
repeat:
for (int i = 0; i < bp->cur->nbps; i++) {
b = &bp->cur->bps[i];
if (bp->cur->bps[i].bits) {
if (!bits || bits != bp->cur->bps[i].bits) {
continue;
}
}
if (bp->cur->bps[i].length == len && bp->cur->bps[i].endian == endian) {
memcpy(buf, b->bytes, b->length);
return b->length;
}
}
if (len != 4) {
len = 4;
goto repeat;
}
/* if not found try to pad with the first one */
b = &bp->cur->bps[0];
if (len % b->length) {
RZ_LOG_ERROR("No matching bpsize\n");
return 0;
}
for (int i = 0; i < len; i++) {
memcpy(buf + i, b->bytes, b->length);
}
return b->length;
size_t length = 0;
const ut8 *bytes = rz_strbuf_getbin(bp->opcode, &length);
memcpy(buf, bytes, RZ_MIN(length, len));
return length;
}
/**
@ -168,14 +149,8 @@ RZ_API bool rz_bp_enable_all(RzBreakpoint *bp, int set) {
return true;
}
RZ_API int rz_bp_stepy_continuation(RzBreakpoint *bp) {
// TODO: implement
return bp->stepcont;
}
static void unlinkBreakpoint(RzBreakpoint *bp, RzBreakpointItem *b) {
int i;
for (i = 0; i < bp->bps_idx_count; i++) {
for (int i = 0; i < bp->bps_idx_count; i++) {
if (bp->bps_idx[i] == b) {
bp->bps_idx[i] = NULL;
}
@ -257,7 +232,7 @@ static RzBreakpointItem *rz_bp_add(RzBreakpoint *bp, const ut8 *obytes, ut64 add
}
int ret = rz_bp_get_bytes(bp, b->addr, b->bbytes, size);
if (ret != size) {
RZ_LOG_ERROR("Cannot get breakpoint bytes. Incorrect architecture/bits selected for software breakpoints?\n");
RZ_LOG_ERROR("Cannot get breakpoint bytes at 0x%08" PFMT64x "\n", b->addr);
goto err;
}
}
@ -268,11 +243,6 @@ err:
return NULL;
}
RZ_API int rz_bp_add_fault(RzBreakpoint *bp, ut64 addr, int size, int perm) {
// TODO
return false;
}
/**
* \brief Add a software breakpoint
* \p size preferred size of the breakpoint, or 0 to determine automatically
@ -301,10 +271,9 @@ RZ_API RzBreakpointItem *rz_bp_add_hw(RzBreakpoint *bp, ut64 addr, int size, int
}
RZ_API bool rz_bp_del_all(RzBreakpoint *bp) {
int i;
if (!rz_list_empty(bp->bps)) {
rz_list_purge(bp->bps);
for (i = 0; i < bp->bps_idx_count; i++) {
for (int i = 0; i < bp->bps_idx_count; i++) {
bp->bps_idx[i] = NULL;
}
return true;
@ -352,8 +321,7 @@ RZ_API RzBreakpointItem *rz_bp_get_index(RzBreakpoint *bp, int idx) {
}
RZ_API int rz_bp_get_index_at(RzBreakpoint *bp, ut64 addr) {
int i;
for (i = 0; i < bp->bps_idx_count; i++) {
for (int i = 0; i < bp->bps_idx_count; i++) {
if (bp->bps_idx[i] && bp->bps_idx[i]->addr == addr) {
return i;
}
@ -371,35 +339,29 @@ RZ_API int rz_bp_del_index(RzBreakpoint *bp, int idx) {
}
/**
* \brief Predict the software breakpoint size to use for the given arch-bitness
* \brief Current software breakpoint size
* \param bits bitness or 0 if unspecified
*/
RZ_API int rz_bp_size(RZ_NONNULL RzBreakpoint *bp, int bits) {
RZ_API size_t rz_bp_size(RZ_NONNULL RzBreakpoint *bp) {
rz_return_val_if_fail(bp, 0);
RzBreakpointArch *bpa;
int i, bpsize = 8;
if (!bp || !bp->cur) {
if (!bp->opcode) {
// cannot use get the size of the opcode.
return 0;
}
for (i = 0; bp->cur->bps[i].bytes; i++) {
bpa = &bp->cur->bps[i];
if (bpa->bits && bpa->bits != bits) {
continue;
}
if (bpa->length < bpsize) {
bpsize = bpa->length;
}
}
return bpsize;
return rz_strbuf_length(bp->opcode);
}
/**
* \brief Predict the software breakpoint size to use when placing a breakpoint at \p addr
* \brief Get the software breakpoint size at a given address
*/
RZ_API int rz_bp_size_at(RZ_NONNULL RzBreakpoint *bp, ut64 addr) {
RZ_API size_t rz_bp_size_at(RZ_NONNULL RzBreakpoint *bp, ut64 addr) {
rz_return_val_if_fail(bp, 0);
int bits = bp->ctx.bits_at ? bp->ctx.bits_at(addr, bp->ctx.user) : 0;
return rz_bp_size(bp, bits);
if (!bp->ctx.get_sw_breakpoint_size_at) {
// cannot use get the size of the opcode.
return 0;
}
return bp->ctx.get_sw_breakpoint_size_at(addr, bp->ctx.user);
}
// Check if the breakpoint is in a valid map

View file

@ -321,13 +321,13 @@ RZ_API RZ_BORROW RzBreakpointItem *rz_debug_bp_add(RZ_NONNULL RzDebug *dbg, ut64
}
perm = ((map->perm & 1) << 2) | (map->perm & 2) | ((map->perm & 4) >> 2);
if (!(perm & RZ_PERM_X)) {
eprintf("WARNING: setting bp within mapped memory without exec perm\n");
RZ_LOG_WARN("setting bp within mapped memory without exec perm\n");
}
break;
}
}
if (!valid) {
eprintf("WARNING: module's base addr + delta is not a valid address\n");
RZ_LOG_WARN("module's base addr + delta is not a valid address\n");
return NULL;
}
}
@ -422,33 +422,33 @@ RZ_API void rz_debug_tracenodes_reset(RzDebug *dbg) {
dbg->tracenodes = ht_up_new(NULL, free);
}
RZ_API RzDebug *rz_debug_free(RzDebug *dbg) {
if (dbg) {
rz_hash_free(dbg->hash);
rz_bp_free(dbg->bp);
free(dbg->snap_path);
rz_list_free(dbg->maps);
rz_list_free(dbg->maps_user);
rz_list_free(dbg->threads);
rz_num_free(dbg->num);
sdb_free(dbg->sgnls);
rz_tree_free(dbg->tree);
ht_up_free(dbg->tracenodes);
ht_sp_free(dbg->plugins);
rz_list_free(dbg->call_frames);
free(dbg->btalgo);
rz_debug_trace_free(dbg->trace);
rz_debug_session_free(dbg->session);
rz_analysis_op_free(dbg->cur_op);
dbg->trace = NULL;
rz_egg_free(dbg->egg);
rz_reg_free(dbg->reg);
free(dbg->arch);
free(dbg->glob_libs);
free(dbg->glob_unlibs);
free(dbg);
RZ_API void rz_debug_free(RzDebug *dbg) {
if (!dbg) {
return;
}
return NULL;
rz_hash_free(dbg->hash);
rz_bp_free(dbg->bp);
free(dbg->snap_path);
rz_list_free(dbg->maps);
rz_list_free(dbg->maps_user);
rz_list_free(dbg->threads);
rz_num_free(dbg->num);
sdb_free(dbg->sgnls);
rz_tree_free(dbg->tree);
ht_up_free(dbg->tracenodes);
ht_sp_free(dbg->plugins);
rz_list_free(dbg->call_frames);
free(dbg->btalgo);
rz_debug_trace_free(dbg->trace);
rz_debug_session_free(dbg->session);
rz_analysis_op_free(dbg->cur_op);
dbg->trace = NULL;
rz_egg_free(dbg->egg);
rz_reg_free(dbg->reg);
free(dbg->arch);
free(dbg->glob_libs);
free(dbg->glob_unlibs);
free(dbg);
}
RZ_API int rz_debug_attach(RzDebug *dbg, int pid) {

View file

@ -51,6 +51,11 @@ rz_debug_sources = [
#'p/native/darwin.c',
#'p/native/drx.c',
#'p/native/maps/darwin.c',
'bp.c',
'bp_io.c',
'bp_traptrace.c',
'bp_watch.c',
'serialize_bp.c',
]
rz_debug_deps = [
@ -62,7 +67,6 @@ rz_debug_deps = [
rz_io_dep,
rz_bin_dep,
rz_reg_dep,
rz_bp_dep,
rz_syscall_dep,
rz_egg_dep,
rz_arch_dep,
@ -161,7 +165,6 @@ modules += { 'rz_debug': {
'rz_arch',
'rz_io',
'rz_bin',
'rz_bp',
'rz_cons',
'rz_egg',
'rz_type'

View file

@ -144,6 +144,7 @@ typedef struct rz_asm_plugin_t {
const char *features;
const char *platforms;
char **(*get_cpu_desc)();
bool (*sw_breakpoint)(RzAsm *a, RzAsmOp *op);
} RzAsmPlugin;
/**
@ -181,6 +182,7 @@ RZ_API int rz_asm_syntax_from_string(const char *name);
RZ_API int rz_asm_set_pc(RzAsm *a, ut64 pc);
RZ_API int rz_asm_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len);
RZ_API int rz_asm_assemble(RzAsm *a, RzAsmOp *op, const char *buf);
RZ_API bool rz_asm_software_breakpoint(RZ_NONNULL RzAsm *a, RZ_NONNULL RzAsmOp *op);
RZ_API RzAsmCode *rz_asm_mdisassemble(RzAsm *a, const ut8 *buf, int len);
RZ_API RzAsmCode *rz_asm_mdisassemble_hexstr(RzAsm *a, RzParse *p, const char *hexstr);
RZ_API RzAsmCode *rz_asm_massemble(RzAsm *a, const char *buf);

View file

@ -10,18 +10,9 @@
extern "C" {
#endif
RZ_LIB_VERSION_HEADER(rz_bp);
#define RZ_BP_MAXPIDS 10
#define RZ_BP_CONT_NORMAL 0
typedef struct rz_bp_arch_t {
int bits;
int length;
int endian;
const ut8 *bytes;
} RzBreakpointArch;
enum {
RZ_BP_TYPE_SW,
RZ_BP_TYPE_HW,
@ -30,14 +21,6 @@ enum {
RZ_BP_TYPE_DELETE,
};
typedef struct rz_bp_plugin_t {
char *name;
char *arch;
int type; // RZ_BP_TYPE_SW
int nbps;
RzBreakpointArch *bps;
} RzBreakpointPlugin;
typedef struct rz_bp_item_t {
char *name;
char *module_name; /*module where you get the base address*/
@ -72,7 +55,8 @@ typedef struct rz_bp_context_t {
void *user;
bool (*is_mapped)(ut64 addr, int perm, void *user); ///< check if the address is mapped and has the given permissions
void (*maps_sync)(void *user); ///< synchronize any maps from the debugee
int (*bits_at)(ut64 addr, void *user); ///< get the arch-bitness to use at the given address (e.g. thumb or 32)
RzStrBuf *(*get_sw_breakpoint_at)(ut64 addr, void *user); ///< get the software breakpoint based on the address hints
size_t (*get_sw_breakpoint_size_at)(ut64 addr, void *user); ///< get the software breakpoint based on the address hints
} RzBreakpointContext;
typedef struct rz_bp_t {
@ -82,9 +66,8 @@ typedef struct rz_bp_t {
int endian;
bool bpinmaps; /* Only enable breakpoints inside a valid map */
RzIOBind iob; // compile time dependency
RzBreakpointPlugin *cur;
RzStrBuf *opcode;
RzList /*<RzBreakpointTrace *>*/ *traces; // XXX
HtSP /*<RzBreakpointPlugin *>*/ *plugins;
PrintfCallback cb_printf;
RzBreakpointCallback breakpoint;
/* storage of breakpoints */
@ -106,38 +89,19 @@ typedef struct rz_bp_trace_t {
int bitlen;
} RzBreakpointTrace;
/**
* \brief Compare plugins by name (via strcmp).
*/
static inline int rz_breakpoint_plugin_cmp(RZ_NULLABLE const RzBreakpointPlugin *a, RZ_NULLABLE const RzBreakpointPlugin *b) {
if (!a && !b) {
return 0;
} else if (!a) {
return -1;
} else if (!b) {
return 1;
}
return rz_str_cmp(a->name, b->name, -1);
}
#ifdef RZ_API
RZ_API RzBreakpoint *rz_bp_new(RZ_BORROW RZ_NONNULL RzBreakpointContext *ctx);
RZ_API RzBreakpoint *rz_bp_free(RzBreakpoint *bp);
RZ_API void rz_bp_free(RzBreakpoint *bp);
RZ_API bool rz_bp_set_opcode(RZ_NONNULL RzBreakpoint *bp, ut64 addr);
RZ_API bool rz_bp_del(RzBreakpoint *bp, ut64 addr);
RZ_API bool rz_bp_del_all(RzBreakpoint *bp);
RZ_API bool rz_bp_plugin_add(RzBreakpoint *bp, RZ_BORROW RZ_NONNULL RzBreakpointPlugin *plugin);
RZ_API bool rz_bp_plugin_del(RzBreakpoint *bp, RZ_BORROW RZ_NONNULL RzBreakpointPlugin *plugin);
RZ_API int rz_bp_use(RZ_NONNULL RzBreakpoint *bp, RZ_NONNULL const char *name);
RZ_API int rz_bp_plugin_del_byname(RzBreakpoint *bp, RZ_NONNULL const char *name);
RZ_DEPRECATE RZ_API void rz_bp_plugin_print(RZ_NONNULL RzBreakpoint *bp);
RZ_API int rz_bp_size(RZ_NONNULL RzBreakpoint *bp, int bits);
RZ_API int rz_bp_size_at(RZ_NONNULL RzBreakpoint *bp, ut64 addr);
RZ_API size_t rz_bp_size(RZ_NONNULL RzBreakpoint *bp);
RZ_API size_t rz_bp_size_at(RZ_NONNULL RzBreakpoint *bp, ut64 addr);
/* bp item attribs setters */
RZ_API int rz_bp_get_bytes(RZ_NONNULL RzBreakpoint *bp, ut64 addr, RZ_NONNULL ut8 *buf, int len);
RZ_API size_t rz_bp_get_bytes(RZ_NONNULL RzBreakpoint *bp, ut64 addr, RZ_NONNULL ut8 *buf, int len);
RZ_API int rz_bp_set_trace(RzBreakpoint *bp, ut64 addr, int set);
RZ_API int rz_bp_set_trace_all(RzBreakpoint *bp, int set);
RZ_API RzBreakpointItem *rz_bp_enable(RzBreakpoint *bp, ut64 addr, int set, int count);
@ -158,8 +122,6 @@ RZ_API bool rz_bp_item_set_data(RZ_NONNULL RzBreakpointItem *item, RZ_NULLABLE c
RZ_API bool rz_bp_item_set_expr(RZ_NONNULL RzBreakpointItem *item, RZ_NULLABLE const char *expr);
RZ_API bool rz_bp_item_set_name(RZ_NONNULL RzBreakpointItem *item, RZ_NULLABLE const char *name);
RZ_API int rz_bp_add_fault(RzBreakpoint *bp, ut64 addr, int size, int perm);
RZ_API RZ_BORROW RzBreakpointItem *rz_bp_add_sw(RZ_NONNULL RzBreakpoint *bp, ut64 addr, int size, int perm);
RZ_API RzBreakpointItem *rz_bp_add_hw(RzBreakpoint *bp, ut64 addr, int size, int perm);
RZ_API void rz_bp_restore_one(RzBreakpoint *bp, RzBreakpointItem *b, bool set);

View file

@ -445,7 +445,7 @@ static inline int rz_debug_plugin_cmp(RZ_NULLABLE const RzDebugPlugin *a, RZ_NUL
}
RZ_API RZ_OWN RzDebug *rz_debug_new(RZ_BORROW RZ_NONNULL RzBreakpointContext *bp_ctx);
RZ_API RzDebug *rz_debug_free(RzDebug *dbg);
RZ_API void rz_debug_free(RzDebug *dbg);
RZ_API int rz_debug_attach(RzDebug *dbg, int pid);
RZ_API int rz_debug_detach(RzDebug *dbg, int pid);

View file

@ -19,7 +19,7 @@ RZ_API RzStrBuf *rz_strbuf_new(const char *s);
RZ_API const char *rz_strbuf_set(RzStrBuf *sb, const char *s); // return = the string or NULL on fail
RZ_API bool rz_strbuf_slice(RZ_NONNULL RzStrBuf *sb, size_t from, size_t len);
RZ_API bool rz_strbuf_setbin(RzStrBuf *sb, const ut8 *s, size_t len);
RZ_API ut8 *rz_strbuf_getbin(RzStrBuf *sb, int *len);
RZ_API ut8 *rz_strbuf_getbin(RzStrBuf *sb, size_t *len);
RZ_API const char *rz_strbuf_setf(RzStrBuf *sb, const char *fmt, ...) RZ_PRINTF_CHECK(2, 3); // return = the string or NULL on fail
RZ_API const char *rz_strbuf_vsetf(RzStrBuf *sb, const char *fmt, va_list ap); // return = the string or NULL on fail
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s);

View file

@ -24,7 +24,6 @@ rz_main_deps = [
rz_il_dep,
rz_io_dep,
rz_reg_dep,
rz_bp_dep,
rz_syscall_dep,
rz_arch_dep,
rz_egg_dep,

View file

@ -45,7 +45,6 @@ static int rz_main_version_verify(int show) {
{ "rz_flag", rz_flag_version },
{ "rz_core", rz_core_version },
{ "rz_crypto", rz_crypto_version },
{ "rz_bp", rz_bp_version },
{ "rz_debug", rz_debug_version },
{ "rz_main", rz_main_version },
{ "rz_hash", rz_hash_version },

View file

@ -12,7 +12,6 @@ subdir('crypto')
subdir('cons')
subdir('diff')
subdir('io')
subdir('bp')
subdir('syscall')
subdir('magic')
subdir('search')

View file

@ -301,7 +301,7 @@ RZ_API char *rz_strbuf_get(RzStrBuf *sb) {
return sb->ptr ? sb->ptr : sb->buf;
}
RZ_API ut8 *rz_strbuf_getbin(RzStrBuf *sb, int *len) {
RZ_API ut8 *rz_strbuf_getbin(RzStrBuf *sb, size_t *len) {
rz_return_val_if_fail(sb, NULL);
if (len) {
*len = sb->len;

View file

@ -1549,7 +1549,7 @@ RZ_API int rz_subprocess_ret(RzSubprocess *proc) {
}
RZ_API ut8 *rz_subprocess_out(RzSubprocess *proc, int *length) {
int bin_len = 0;
size_t bin_len = 0;
const ut8 *bin = rz_strbuf_getbin(&proc->out, &bin_len);
ut8 *buf = (ut8 *)rz_str_newlen((const char *)bin, bin_len);
if (length) {
@ -1560,7 +1560,7 @@ RZ_API ut8 *rz_subprocess_out(RzSubprocess *proc, int *length) {
}
RZ_API ut8 *rz_subprocess_err(RzSubprocess *proc, int *length) {
int bin_len = 0;
size_t bin_len = 0;
const ut8 *bin = rz_strbuf_getbin(&proc->err, &bin_len);
ut8 *buf = (ut8 *)rz_str_newlen((const char *)bin, bin_len);
if (length) {

View file

@ -727,7 +727,6 @@ if host_machine.system() == 'windows'
test_env_common_path += [
build_root / 'librz' / 'arch',
build_root / 'librz' / 'bin',
build_root / 'librz' / 'bp',
build_root / 'librz' / 'config',
build_root / 'librz' / 'cons',
build_root / 'librz' / 'signature',
@ -859,7 +858,6 @@ summary({
'Arch Plugins': arch_plugins.get('list'),
'Binary Plugins': bin_plugins.get('list'),
'BinXtr Plugins': bin_xtr_plugins.get('list'),
'Breakpoint Plugins': bp_plugins.get('list'),
'Core Plugins': core_plugins.get('list'),
'Crypto Plugins': crypto_plugins.get('list'),
'Debug Plugins': debug_plugins.get('list'),

View file

@ -51,7 +51,6 @@ if get_option('enable_tests') and cli_enabled
rz_arch_dep,
rz_debug_dep,
rz_config_dep,
rz_bp_dep,
rz_reg_dep,
rz_syscall_dep,
rz_type_dep,

View file

@ -139,7 +139,6 @@ if get_option('enable_tests')
rz_arch_dep,
rz_debug_dep,
rz_config_dep,
rz_bp_dep,
rz_reg_dep,
rz_syscall_dep,
rz_type_dep,

View file

@ -273,24 +273,22 @@ static RzDebugPlugin dbg_mock_plugin = {
.reg_profile = dbg_mock_reg_profile
};
static RzBreakpointArch bp_mock_plugin_bps[] = {
{ .bits = 0, .length = 4, .endian = 0, .bytes = (const ut8 *)"STOP" },
{ 0, 0, 0, NULL }
};
static RzBreakpointPlugin bp_mock_plugin = {
.name = "mock_bp",
.arch = "moch_arch",
.nbps = 1,
.bps = bp_mock_plugin_bps,
};
bool bp_everything_is_mapped(ut64 addr, int perm, void *user) {
static bool bp_everything_is_mapped(ut64 addr, int perm, void *user) {
return true;
}
static RzStrBuf *bp_mock_sw_opcode_at(ut64 addr, void *user) {
return rz_strbuf_new("STOP");
}
static size_t bp_mock_sw_opcode_size_at(ut64 addr, void *user) {
return 4;
}
static RzBreakpointContext bp_ctx = {
.is_mapped = bp_everything_is_mapped,
.get_sw_breakpoint_at = bp_mock_sw_opcode_at,
.get_sw_breakpoint_size_at = bp_mock_sw_opcode_size_at,
};
/// @}
@ -392,37 +390,20 @@ static RzDebugPlugin dbg_mock_multibits_plugin = {
.reg_profile = dbg_mock_reg_profile
};
static RzBreakpointArch bp_mock_multibits_plugin_bps[] = {
{ .bits = 16, .length = 2, .endian = 0, .bytes = (const ut8 *)"st" },
{ .bits = 32, .length = 4, .endian = 0, .bytes = (const ut8 *)"STOP" },
{ 0, 0, 0, NULL }
};
static RzBreakpointPlugin bp_mock_multibits_plugin = {
.name = "mock_multibits_bp",
.arch = "moch_multibits_arch",
.nbps = 2,
.bps = bp_mock_multibits_plugin_bps,
};
/// @}
#define SETUP_DEBUG(dbg_plugin, bp_plugin, bp_ctx) \
#define SETUP_DEBUG(dbg_plugin, bp_ctx) \
do { \
dbg_mock_failed = false; \
dbg = rz_debug_new(bp_ctx); \
mu_assert_notnull(dbg, "create debug"); \
bool succ = rz_debug_plugin_add(dbg, dbg_plugin); \
mu_assert_true(succ, "add mock debug plugin"); \
succ = rz_bp_plugin_add(dbg->bp, bp_plugin); \
mu_assert_true(succ, "add mock bp plugin"); \
io = rz_io_new(); \
rz_io_bind(io, &dbg->iob); \
rz_io_bind(io, &dbg->bp->iob); \
succ = rz_debug_use(dbg, (dbg_plugin)->name); \
mu_assert_true(succ, "use mock debug plugin"); \
rz_bp_use(dbg->bp, (bp_plugin)->name); \
mu_assert_true(succ, "use mock bp plugin"); \
} while (0)
/**
@ -432,7 +413,7 @@ static RzBreakpointPlugin bp_mock_multibits_plugin = {
static bool test_debug_sw_bp(void) {
RzDebug *dbg;
RzIO *io;
SETUP_DEBUG(&dbg_mock_plugin, &bp_mock_plugin, &bp_ctx);
SETUP_DEBUG(&dbg_mock_plugin, &bp_ctx);
rz_io_open_at(io, "malloc://0x1000", RZ_PERM_RW, 0644, 0x0, NULL);
rz_io_write_at(io, 0x50, (const ut8 *)"PRNT", 4);
@ -473,26 +454,32 @@ static bool test_debug_sw_bp(void) {
}
/**
* \name Thumb/Non-thumb software breakpoint test
* Set up some mixed thumb and non-thumb code, put breakpoints in both parts and check that
* all of them are set up correctly (selecting the right byte patterns from the bp plugin) and hit.
* @{
*/
int sw_bp_multibits_bits_at(ut64 addr, void *user) {
static RzStrBuf *bp_mock_sw_bp_multibits_opcode_at(ut64 addr, void *user) {
// this corresponds to the instruction of the program written into io in test_debug_sw_bp_multibits()
return addr >= 0x58 && addr < 0x60 ? 16 : 32;
if (addr >= 0x58 && addr < 0x60) {
return rz_strbuf_new("st");
}
return rz_strbuf_new("STOP");
}
static size_t bp_mock_sw_bp_multibits_size_at(ut64 addr, void *user) {
// this corresponds to the instruction of the program written into io in test_debug_sw_bp_multibits()
return addr >= 0x58 && addr < 0x60 ? 2 : 4;
}
static bool test_debug_sw_bp_multibits(void) {
RzBreakpointContext bp_ctx = {
.is_mapped = bp_everything_is_mapped,
.bits_at = sw_bp_multibits_bits_at
.get_sw_breakpoint_at = bp_mock_sw_bp_multibits_opcode_at,
.get_sw_breakpoint_size_at = bp_mock_sw_bp_multibits_size_at,
};
RzDebug *dbg;
RzIO *io;
SETUP_DEBUG(&dbg_mock_multibits_plugin, &bp_mock_multibits_plugin, &bp_ctx);
SETUP_DEBUG(&dbg_mock_multibits_plugin, &bp_ctx);
rz_io_open_at(io, "malloc://0x1000", RZ_PERM_RW, 0644, 0x0, NULL);
// program is some non-thumb code with a chunk of thumb in between
@ -651,7 +638,7 @@ static bool test_debug_sw_bp_multibits(void) {
static bool test_debug_hw_bp(void) {
RzDebug *dbg;
RzIO *io;
SETUP_DEBUG(&dbg_mock_plugin, &bp_mock_plugin, &bp_ctx);
SETUP_DEBUG(&dbg_mock_plugin, &bp_ctx);
rz_io_open_at(io, "malloc://0x1000", RZ_PERM_RW, 0644, 0x0, NULL);
rz_io_write_at(io, 0x50, (const ut8 *)"PRNT", 4);
@ -713,7 +700,7 @@ static bool test_debug_hw_bp(void) {
static bool test_debug_hw_watch(void) {
RzDebug *dbg;
RzIO *io;
SETUP_DEBUG(&dbg_mock_plugin, &bp_mock_plugin, &bp_ctx);
SETUP_DEBUG(&dbg_mock_plugin, &bp_ctx);
rz_io_open_at(io, "malloc://0x1000", RZ_PERM_RW, 0644, 0x0, NULL);
const char *code =