mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-19 09:14:14 +08:00
gdb: or1k: add single step for linux native debugging
Needed for single stepping in Linux, this adds the or1k implementation of or1k_software_single_step. Most of the implementation is borrowed from the bare metal single step code from or1k_single_step_through_delay which has been extracted and shared in helper function or1k_delay_slot_p.
This commit is contained in:
@ -154,6 +154,8 @@ or1k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|||||||
/* GNU/Linux uses the dynamic linker included in the GNU C Library. */
|
/* GNU/Linux uses the dynamic linker included in the GNU C Library. */
|
||||||
set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
|
set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
|
||||||
|
|
||||||
|
set_gdbarch_software_single_step (gdbarch, or1k_software_single_step);
|
||||||
|
|
||||||
/* Enable TLS support. */
|
/* Enable TLS support. */
|
||||||
set_gdbarch_fetch_tls_load_module_address (gdbarch,
|
set_gdbarch_fetch_tls_load_module_address (gdbarch,
|
||||||
svr4_fetch_objfile_link_map);
|
svr4_fetch_objfile_link_map);
|
||||||
|
@ -346,33 +346,16 @@ constexpr gdb_byte or1k_break_insn[] = {0x21, 0x00, 0x00, 0x01};
|
|||||||
|
|
||||||
typedef BP_MANIPULATION (or1k_break_insn) or1k_breakpoint;
|
typedef BP_MANIPULATION (or1k_break_insn) or1k_breakpoint;
|
||||||
|
|
||||||
/* Implement the single_step_through_delay gdbarch method. */
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
or1k_single_step_through_delay (struct gdbarch *gdbarch,
|
or1k_delay_slot_p (struct gdbarch *gdbarch, CORE_ADDR pc)
|
||||||
struct frame_info *this_frame)
|
|
||||||
{
|
{
|
||||||
ULONGEST val;
|
|
||||||
CORE_ADDR ppc;
|
|
||||||
CORE_ADDR npc;
|
|
||||||
CGEN_FIELDS tmp_fields;
|
|
||||||
const CGEN_INSN *insn;
|
const CGEN_INSN *insn;
|
||||||
struct regcache *regcache = get_current_regcache ();
|
CGEN_FIELDS tmp_fields;
|
||||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||||
|
|
||||||
/* Get the previous and current instruction addresses. If they are not
|
|
||||||
adjacent, we cannot be in a delay slot. */
|
|
||||||
regcache_cooked_read_unsigned (regcache, OR1K_PPC_REGNUM, &val);
|
|
||||||
ppc = (CORE_ADDR) val;
|
|
||||||
regcache_cooked_read_unsigned (regcache, OR1K_NPC_REGNUM, &val);
|
|
||||||
npc = (CORE_ADDR) val;
|
|
||||||
|
|
||||||
if (0x4 != (npc - ppc))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
insn = cgen_lookup_insn (tdep->gdb_cgen_cpu_desc,
|
insn = cgen_lookup_insn (tdep->gdb_cgen_cpu_desc,
|
||||||
NULL,
|
NULL,
|
||||||
or1k_fetch_instruction (gdbarch, ppc),
|
or1k_fetch_instruction (gdbarch, pc),
|
||||||
NULL, 32, &tmp_fields, 0);
|
NULL, 32, &tmp_fields, 0);
|
||||||
|
|
||||||
/* NULL here would mean the last instruction was not understood by cgen.
|
/* NULL here would mean the last instruction was not understood by cgen.
|
||||||
@ -390,6 +373,51 @@ or1k_single_step_through_delay (struct gdbarch *gdbarch,
|
|||||||
|| (CGEN_INSN_NUM (insn) == OR1K_INSN_L_BF));
|
|| (CGEN_INSN_NUM (insn) == OR1K_INSN_L_BF));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Implement the single_step_through_delay gdbarch method. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
or1k_single_step_through_delay (struct gdbarch *gdbarch,
|
||||||
|
struct frame_info *this_frame)
|
||||||
|
{
|
||||||
|
ULONGEST val;
|
||||||
|
CORE_ADDR ppc;
|
||||||
|
CORE_ADDR npc;
|
||||||
|
struct regcache *regcache = get_current_regcache ();
|
||||||
|
|
||||||
|
/* Get the previous and current instruction addresses. If they are not
|
||||||
|
adjacent, we cannot be in a delay slot. */
|
||||||
|
regcache_cooked_read_unsigned (regcache, OR1K_PPC_REGNUM, &val);
|
||||||
|
ppc = (CORE_ADDR) val;
|
||||||
|
regcache_cooked_read_unsigned (regcache, OR1K_NPC_REGNUM, &val);
|
||||||
|
npc = (CORE_ADDR) val;
|
||||||
|
|
||||||
|
if (0x4 != (npc - ppc))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return or1k_delay_slot_p (gdbarch, ppc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* or1k_software_single_step() is called just before we want to resume
|
||||||
|
the inferior, if we want to single-step it but there is no hardware
|
||||||
|
or kernel single-step support (OpenRISC on GNU/Linux for example). We
|
||||||
|
find the target of the coming instruction skipping over delay slots
|
||||||
|
and breakpoint it. */
|
||||||
|
|
||||||
|
std::vector<CORE_ADDR>
|
||||||
|
or1k_software_single_step (struct regcache *regcache)
|
||||||
|
{
|
||||||
|
struct gdbarch *gdbarch = regcache->arch ();
|
||||||
|
CORE_ADDR pc, next_pc;
|
||||||
|
|
||||||
|
pc = regcache_read_pc (regcache);
|
||||||
|
next_pc = pc + 4;
|
||||||
|
|
||||||
|
if (or1k_delay_slot_p (gdbarch, pc))
|
||||||
|
next_pc += 4;
|
||||||
|
|
||||||
|
return {next_pc};
|
||||||
|
}
|
||||||
|
|
||||||
/* Name for or1k general registers. */
|
/* Name for or1k general registers. */
|
||||||
|
|
||||||
static const char *const or1k_reg_names[OR1K_NUM_REGS] = {
|
static const char *const or1k_reg_names[OR1K_NUM_REGS] = {
|
||||||
|
@ -52,4 +52,9 @@
|
|||||||
#define OR1K_NUM_TAP_RECORDS 8
|
#define OR1K_NUM_TAP_RECORDS 8
|
||||||
#define OR1K_FRAME_RED_ZONE_SIZE 2536
|
#define OR1K_FRAME_RED_ZONE_SIZE 2536
|
||||||
|
|
||||||
|
/* Single step based on where the current instruction will take us. */
|
||||||
|
extern std::vector<CORE_ADDR> or1k_software_single_step
|
||||||
|
(struct regcache *regcache);
|
||||||
|
|
||||||
|
|
||||||
#endif /* OR1K_TDEP_H */
|
#endif /* OR1K_TDEP_H */
|
||||||
|
Reference in New Issue
Block a user