#include "dwarf2-frame.h"
#include "user-regs.h"
#include "valprint.h"
-#include "common/common-defs.h"
+#include "gdbsupport/common-defs.h"
#include "opcode/riscv-opc.h"
#include "cli/cli-decode.h"
#include "observable.h"
#include "prologue-value.h"
#include "arch/riscv.h"
+#include "riscv-ravenscar-thread.h"
/* The stack must be 16-byte aligned. */
#define SP_ALIGNMENT 16
{
struct value_print_options opts;
const gdb_byte *valaddr = value_contents_for_printing (val);
- enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (regtype));
+ enum bfd_endian byte_order = type_byte_order (regtype);
get_user_print_options (&opts);
opts.deref_ref = 1;
LUI,
SD,
SW,
- /* These are needed for software breakopint support. */
+ /* These are needed for software breakpoint support. */
JAL,
JALR,
BEQ,
struct type *value_type, CORE_ADDR *real_pc,
CORE_ADDR *bp_addr, struct regcache *regcache)
{
+ /* A nop instruction is 'add x0, x0, 0'. */
+ static const gdb_byte nop_insn[] = { 0x13, 0x00, 0x00, 0x00 };
+
/* Allocate space for a breakpoint, and keep the stack correctly
- aligned. */
+ aligned. The space allocated here must be at least big enough to
+ accommodate the NOP_INSN defined above. */
sp -= 16;
*bp_addr = sp;
*real_pc = funaddr;
+
+ /* When we insert a breakpoint we select whether to use a compressed
+ breakpoint or not based on the existing contents of the memory.
+
+ If the breakpoint is being placed onto the stack as part of setting up
+ for an inferior call from GDB, then the existing stack contents may
+ randomly appear to be a compressed instruction, causing GDB to insert
+ a compressed breakpoint. If this happens on a target that does not
+ support compressed instructions then this could cause problems.
+
+ To prevent this issue we write an uncompressed nop onto the stack at
+ the location where the breakpoint will be inserted. In this way we
+ ensure that we always use an uncompressed breakpoint, which should
+ work on all targets.
+
+ We call TARGET_WRITE_MEMORY here so that if the write fails we don't
+ throw an exception. Instead we ignore the error and move on. The
+ assumption is that either GDB will error later when actually trying to
+ insert a software breakpoint, or GDB will use hardware breakpoints and
+ there will be no need to write to memory later. */
+ int status = target_write_memory (*bp_addr, nop_insn, sizeof (nop_insn));
+
+ if (riscv_debug_breakpoints || riscv_debug_infcall)
+ fprintf_unfiltered (gdb_stdlog,
+ "Writing %s-byte nop instruction to %s: %s\n",
+ plongest (sizeof (nop_insn)),
+ paddress (gdbarch, *bp_addr),
+ (status == 0 ? "success" : "failed"));
+
return sp;
}
return -1;
}
+/* Implement the gcc_target_options method. We have to select the arch and abi
+ from the feature info. We have enough feature info to select the abi, but
+ not enough info for the arch given all of the possible architecture
+ extensions. So choose reasonable defaults for now. */
+
+static std::string
+riscv_gcc_target_options (struct gdbarch *gdbarch)
+{
+ int isa_xlen = riscv_isa_xlen (gdbarch);
+ int isa_flen = riscv_isa_flen (gdbarch);
+ int abi_xlen = riscv_abi_xlen (gdbarch);
+ int abi_flen = riscv_abi_flen (gdbarch);
+ std::string target_options;
+
+ target_options = "-march=rv";
+ if (isa_xlen == 8)
+ target_options += "64";
+ else
+ target_options += "32";
+ if (isa_flen == 8)
+ target_options += "gc";
+ else if (isa_flen == 4)
+ target_options += "imafc";
+ else
+ target_options += "imac";
+
+ target_options += " -mabi=";
+ if (abi_xlen == 8)
+ target_options += "lp64";
+ else
+ target_options += "ilp32";
+ if (abi_flen == 8)
+ target_options += "d";
+ else if (abi_flen == 4)
+ target_options += "f";
+
+ /* The gdb loader doesn't handle link-time relaxation relocations. */
+ target_options += " -mno-relax";
+
+ return target_options;
+}
+
+/* Implement the gnu_triplet_regexp method. A single compiler supports both
+ 32-bit and 64-bit code, and may be named riscv32 or riscv64 or (not
+ recommended) riscv. */
+
+static const char *
+riscv_gnu_triplet_regexp (struct gdbarch *gdbarch)
+{
+ return "riscv(32|64)?";
+}
+
/* Initialize the current architecture based on INFO. If possible,
re-use an architecture from ARCHES, which is a list of
architectures already created during this debugging session.
riscv_setup_register_aliases (gdbarch, &riscv_freg_feature);
riscv_setup_register_aliases (gdbarch, &riscv_csr_feature);
+ /* Compile command hooks. */
+ set_gdbarch_gcc_target_options (gdbarch, riscv_gcc_target_options);
+ set_gdbarch_gnu_triplet_regexp (gdbarch, riscv_gnu_triplet_regexp);
+
/* Hook in OS ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);
+ register_riscv_ravenscar_ops (gdbarch);
+
return gdbarch;
}