/* Target-dependent code for the RISC-V architecture, for GDB.
- Copyright (C) 2018-2019 Free Software Foundation, Inc.
+ Copyright (C) 2018-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "floatformat.h"
#include "remote.h"
#include "target-descriptions.h"
-#include "dwarf2-frame.h"
+#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
{
"org.gnu.gdb.riscv.csr",
{
-#define DECLARE_CSR(NAME,VALUE) \
+#define DECLARE_CSR(NAME,VALUE,CLASS,DEFINE_VER,ABORT_VER) \
{ RISCV_ ## VALUE ## _REGNUM, { # NAME }, false },
#include "opcode/riscv-opc.h"
#undef DECLARE_CSR
static struct cmd_list_element *setriscvcmdlist = NULL;
static struct cmd_list_element *showriscvcmdlist = NULL;
-/* The show callback for the 'show riscv' prefix command. */
-
-static void
-show_riscv_command (const char *args, int from_tty)
-{
- help_list (showriscvcmdlist, "show riscv ", all_commands, gdb_stdout);
-}
-
-/* The set callback for the 'set riscv' prefix command. */
-
-static void
-set_riscv_command (const char *args, int from_tty)
-{
- printf_unfiltered
- (_("\"set riscv\" must be followed by an appropriate subcommand.\n"));
- help_list (setriscvcmdlist, "set riscv ", all_commands, gdb_stdout);
-}
-
/* The set and show lists for 'set riscv' and 'show riscv' prefixes. */
static struct cmd_list_element *setdebugriscvcmdlist = NULL;
static struct cmd_list_element *showdebugriscvcmdlist = NULL;
-/* The show callback for the 'show debug riscv' prefix command. */
-
-static void
-show_debug_riscv_command (const char *args, int from_tty)
-{
- help_list (showdebugriscvcmdlist, "show debug riscv ", all_commands, gdb_stdout);
-}
-
-/* The set callback for the 'set debug riscv' prefix command. */
-
-static void
-set_debug_riscv_command (const char *args, int from_tty)
-{
- printf_unfiltered
- (_("\"set debug riscv\" must be followed by an appropriate subcommand.\n"));
- help_list (setdebugriscvcmdlist, "set debug riscv ", all_commands, gdb_stdout);
-}
-
/* The show callback for all 'show debug riscv VARNAME' variables. */
static void
if (regnum >= RISCV_FIRST_CSR_REGNUM && regnum <= RISCV_LAST_CSR_REGNUM)
{
-#define DECLARE_CSR(NAME,VALUE) \
+#define DECLARE_CSR(NAME,VALUE,CLASS,DEFINE_VER,ABORT_VER) \
case RISCV_ ## VALUE ## _REGNUM: return # NAME;
switch (regnum)
append_composite_type_field (t, "float", bt->builtin_float);
append_composite_type_field (t, "double", bt->builtin_double);
TYPE_VECTOR (t) = 1;
- TYPE_NAME (t) = "builtin_type_fpreg_d";
+ t->set_name ("builtin_type_fpreg_d");
tdep->riscv_fpreg_d_type = t;
}
present the registers using a union type. */
int flen = riscv_isa_flen (gdbarch);
if (flen == 8
- && TYPE_CODE (type) == TYPE_CODE_FLT
+ && type->code () == TYPE_CODE_FLT
&& TYPE_LENGTH (type) == flen
- && (strcmp (TYPE_NAME (type), "builtin_type_ieee_double") == 0
- || strcmp (TYPE_NAME (type), "double") == 0))
+ && (strcmp (type->name (), "builtin_type_ieee_double") == 0
+ || strcmp (type->name (), "double") == 0))
type = riscv_fpreg_d_type (gdbarch);
}
|| regnum == RISCV_SP_REGNUM
|| regnum == RISCV_GP_REGNUM
|| regnum == RISCV_TP_REGNUM)
- && TYPE_CODE (type) == TYPE_CODE_INT
+ && type->code () == TYPE_CODE_INT
&& TYPE_LENGTH (type) == xlen)
{
/* This spots the case where some interesting registers are defined
print_raw_format = (value_entirely_available (val)
&& !value_optimized_out (val));
- if (TYPE_CODE (regtype) == TYPE_CODE_FLT
- || (TYPE_CODE (regtype) == TYPE_CODE_UNION
- && TYPE_NFIELDS (regtype) == 2
- && TYPE_CODE (TYPE_FIELD_TYPE (regtype, 0)) == TYPE_CODE_FLT
- && TYPE_CODE (TYPE_FIELD_TYPE (regtype, 1)) == TYPE_CODE_FLT)
- || (TYPE_CODE (regtype) == TYPE_CODE_UNION
- && TYPE_NFIELDS (regtype) == 3
- && TYPE_CODE (TYPE_FIELD_TYPE (regtype, 0)) == TYPE_CODE_FLT
- && TYPE_CODE (TYPE_FIELD_TYPE (regtype, 1)) == TYPE_CODE_FLT
- && TYPE_CODE (TYPE_FIELD_TYPE (regtype, 2)) == TYPE_CODE_FLT))
+ if (regtype->code () == TYPE_CODE_FLT
+ || (regtype->code () == TYPE_CODE_UNION
+ && regtype->num_fields () == 2
+ && regtype->field (0).type ()->code () == TYPE_CODE_FLT
+ && regtype->field (1).type ()->code () == TYPE_CODE_FLT)
+ || (regtype->code () == TYPE_CODE_UNION
+ && regtype->num_fields () == 3
+ && regtype->field (0).type ()->code () == TYPE_CODE_FLT
+ && regtype->field (1).type ()->code () == TYPE_CODE_FLT
+ && regtype->field (2).type ()->code () == TYPE_CODE_FLT))
{
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;
- val_print (regtype,
- value_embedded_offset (val), 0,
- file, 0, val, &opts, current_language);
+ common_val_print (val, file, 0, &opts, current_language);
if (print_raw_format)
{
/* Print the register in hex. */
get_formatted_print_options (&opts, 'x');
opts.deref_ref = 1;
- val_print (regtype,
- value_embedded_offset (val), 0,
- file, 0, val, &opts, current_language);
+ common_val_print (val, file, 0, &opts, current_language);
if (print_raw_format)
{
get_user_print_options (&opts);
opts.deref_ref = 1;
fprintf_filtered (file, "\t");
- val_print (regtype,
- value_embedded_offset (val), 0,
- file, 0, val, &opts, current_language);
+ common_val_print (val, file, 0, &opts, current_language);
}
}
}
switch (regnum)
{
-#define DECLARE_CSR(name, num) case RISCV_ ## num ## _REGNUM:
+#define DECLARE_CSR(name, num, class, define_ver, abort_ver) case RISCV_ ## num ## _REGNUM:
#include "opcode/riscv-opc.h"
#undef DECLARE_CSR
return true;
LUI,
SD,
SW,
- /* These are needed for software breakopint support. */
+ /* These are needed for software breakpoint support. */
JAL,
JALR,
BEQ,
m_opcode = OTHER;
}
else
- internal_error (__FILE__, __LINE__,
- _("unable to decode %d byte instructions in "
- "prologue at %s"), m_length,
- core_addr_to_string (pc));
+ {
+ /* This must be a 6 or 8 byte instruction, we don't currently decode
+ any of these, so just ignore it. */
+ gdb_assert (m_length == 6 || m_length == 8);
+ m_opcode = OTHER;
+ }
}
/* The prologue scanner. This is currently only used for skipping the
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;
}
riscv_type_align (gdbarch *gdbarch, type *type)
{
type = check_typedef (type);
- if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type))
+ if (type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type))
return std::min (TYPE_LENGTH (type), (ULONGEST) BIGGEST_ALIGNMENT);
/* Anything else will be aligned by the generic code. */
will go. */
int c_length;
- /* The offset within CONTENTS for this part of the argument. Will
- always be 0 for the first part. For the second part of the
+ /* The offset within CONTENTS for this part of the argument. This can
+ be non-zero even for the first part (the first field of a struct can
+ have a non-zero offset due to padding). For the second part of the
argument, this might be the C_LENGTH value of the first part,
however, if we are passing a structure in two registers, and there's
is padding between the first and second field, then this offset
void
riscv_struct_info::analyse_inner (struct type *type, int offset)
{
- unsigned int count = TYPE_NFIELDS (type);
+ unsigned int count = type->num_fields ();
unsigned int i;
for (i = 0; i < count; ++i)
if (TYPE_FIELD_LOC_KIND (type, i) != FIELD_LOC_KIND_BITPOS)
continue;
- struct type *field_type = TYPE_FIELD_TYPE (type, i);
+ struct type *field_type = type->field (i).type ();
field_type = check_typedef (field_type);
int field_offset
= offset + TYPE_FIELD_BITPOS (type, i) / TARGET_CHAR_BIT;
- switch (TYPE_CODE (field_type))
+ switch (field_type->code ())
{
case TYPE_CODE_STRUCT:
analyse_inner (field_type, field_offset);
sinfo.analyse (ainfo->type);
if (sinfo.number_of_fields () == 1
- && TYPE_CODE (sinfo.field_type (0)) == TYPE_CODE_COMPLEX)
+ && sinfo.field_type(0)->code () == TYPE_CODE_COMPLEX)
{
/* The following is similar to RISCV_CALL_ARG_COMPLEX_FLOAT,
except we use the type of the complex field instead of the
}
if (sinfo.number_of_fields () == 1
- && TYPE_CODE (sinfo.field_type (0)) == TYPE_CODE_FLT)
+ && sinfo.field_type(0)->code () == TYPE_CODE_FLT)
{
/* The following is similar to RISCV_CALL_ARG_SCALAR_FLOAT,
except we use the type of the first scalar field instead of
}
if (sinfo.number_of_fields () == 2
- && TYPE_CODE (sinfo.field_type (0)) == TYPE_CODE_FLT
+ && sinfo.field_type(0)->code () == TYPE_CODE_FLT
&& TYPE_LENGTH (sinfo.field_type (0)) <= cinfo->flen
- && TYPE_CODE (sinfo.field_type (1)) == TYPE_CODE_FLT
+ && sinfo.field_type(1)->code () == TYPE_CODE_FLT
&& TYPE_LENGTH (sinfo.field_type (1)) <= cinfo->flen
&& riscv_arg_regs_available (&cinfo->float_regs) >= 2)
{
if (sinfo.number_of_fields () == 2
&& riscv_arg_regs_available (&cinfo->int_regs) >= 1
- && (TYPE_CODE (sinfo.field_type (0)) == TYPE_CODE_FLT
+ && (sinfo.field_type(0)->code () == TYPE_CODE_FLT
&& TYPE_LENGTH (sinfo.field_type (0)) <= cinfo->flen
&& is_integral_type (sinfo.field_type (1))
&& TYPE_LENGTH (sinfo.field_type (1)) <= cinfo->xlen))
&& riscv_arg_regs_available (&cinfo->int_regs) >= 1
&& (is_integral_type (sinfo.field_type (0))
&& TYPE_LENGTH (sinfo.field_type (0)) <= cinfo->xlen
- && TYPE_CODE (sinfo.field_type (1)) == TYPE_CODE_FLT
+ && sinfo.field_type(1)->code () == TYPE_CODE_FLT
&& TYPE_LENGTH (sinfo.field_type (1)) <= cinfo->flen))
{
int len0 = TYPE_LENGTH (sinfo.field_type (0));
ainfo->argloc[0].c_length = 0;
ainfo->argloc[1].c_length = 0;
- switch (TYPE_CODE (ainfo->type))
+ switch (ainfo->type->code ())
{
case TYPE_CODE_INT:
case TYPE_CODE_BOOL:
}
}
+/* Wrapper around REGCACHE->cooked_write. Places the LEN bytes of DATA
+ into a buffer that is at least as big as the register REGNUM, padding
+ out the DATA with either 0x00, or 0xff. For floating point registers
+ 0xff is used, for everyone else 0x00 is used. */
+
+static void
+riscv_regcache_cooked_write (int regnum, const gdb_byte *data, int len,
+ struct regcache *regcache, int flen)
+{
+ gdb_byte tmp [sizeof (ULONGEST)];
+
+ /* FP values in FP registers must be NaN-boxed. */
+ if (riscv_is_fp_regno_p (regnum) && len < flen)
+ memset (tmp, -1, sizeof (tmp));
+ else
+ memset (tmp, 0, sizeof (tmp));
+ memcpy (tmp, data, len);
+ regcache->cooked_write (regnum, tmp);
+}
+
/* Implement the push dummy call gdbarch callback. */
static CORE_ADDR
struct type *ftype = check_typedef (value_type (function));
- if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
+ if (ftype->code () == TYPE_CODE_PTR)
ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
/* We'll use register $a0 if we're returning a struct. */
arg_type = check_typedef (value_type (arg_value));
riscv_arg_location (gdbarch, info, &call_info, arg_type,
- TYPE_VARARGS (ftype) && i >= TYPE_NFIELDS (ftype));
+ TYPE_VARARGS (ftype) && i >= ftype->num_fields ());
if (info->type != arg_type)
arg_value = value_cast (info->type, arg_value);
{
case riscv_arg_info::location::in_reg:
{
- gdb_byte tmp [sizeof (ULONGEST)];
-
gdb_assert (info->argloc[0].c_length <= info->length);
- /* FP values in FP registers must be NaN-boxed. */
- if (riscv_is_fp_regno_p (info->argloc[0].loc_data.regno)
- && info->argloc[0].c_length < call_info.flen)
- memset (tmp, -1, sizeof (tmp));
- else
- memset (tmp, 0, sizeof (tmp));
- memcpy (tmp, (info->contents + info->argloc[0].c_offset),
- info->argloc[0].c_length);
- regcache->cooked_write (info->argloc[0].loc_data.regno, tmp);
+
+ riscv_regcache_cooked_write (info->argloc[0].loc_data.regno,
+ (info->contents
+ + info->argloc[0].c_offset),
+ info->argloc[0].c_length,
+ regcache, call_info.flen);
second_arg_length =
(((info->argloc[0].c_length + info->argloc[0].c_offset) < info->length)
? info->argloc[1].c_length : 0);
{
case riscv_arg_info::location::in_reg:
{
- gdb_byte tmp [sizeof (ULONGEST)];
-
gdb_assert ((riscv_is_fp_regno_p (info->argloc[1].loc_data.regno)
&& second_arg_length <= call_info.flen)
|| second_arg_length <= call_info.xlen);
- /* FP values in FP registers must be NaN-boxed. */
- if (riscv_is_fp_regno_p (info->argloc[1].loc_data.regno)
- && second_arg_length < call_info.flen)
- memset (tmp, -1, sizeof (tmp));
- else
- memset (tmp, 0, sizeof (tmp));
- memcpy (tmp, second_arg_data, second_arg_length);
- regcache->cooked_write (info->argloc[1].loc_data.regno, tmp);
+ riscv_regcache_cooked_write (info->argloc[1].loc_data.regno,
+ second_arg_data,
+ second_arg_length,
+ regcache, call_info.flen);
}
break;
if (writebuf)
{
const gdb_byte *ptr = writebuf + info.argloc[0].c_offset;
- regcache->cooked_write_part (regnum, 0,
+ riscv_regcache_cooked_write (regnum, ptr,
info.argloc[0].c_length,
- ptr);
+ regcache, call_info.flen);
}
/* A return value in register can have a second part in a
if (writebuf)
{
- writebuf += info.argloc[1].c_offset;
- regcache->cooked_write_part (regnum, 0,
- info.argloc[1].c_length,
- writebuf);
+ const gdb_byte *ptr
+ = writebuf + info.argloc[1].c_offset;
+ riscv_regcache_cooked_write
+ (regnum, ptr, info.argloc[1].c_length,
+ regcache, call_info.flen);
}
break;
else if (e_flags & EF_RISCV_FLOAT_ABI_SINGLE)
features.flen = 4;
}
- else
- {
- const struct bfd_arch_info *binfo = info.bfd_arch_info;
-
- if (binfo->bits_per_word == 32)
- features.xlen = 4;
- else if (binfo->bits_per_word == 64)
- features.xlen = 8;
- else
- internal_error (__FILE__, __LINE__, _("unknown bits_per_word %d"),
- binfo->bits_per_word);
- }
return features;
}
features.xlen = 8;
/* Now build a target description based on the feature set. */
- return riscv_create_target_description (features);
+ return riscv_lookup_target_description (features);
}
/* All of the registers in REG_SET are checked for in FEATURE, TDESC_DATA
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;
}
csr_reggroup = reggroup_new ("csr", USER_REGGROUP);
}
+void _initialize_riscv_tdep ();
void
-_initialize_riscv_tdep (void)
+_initialize_riscv_tdep ()
{
riscv_create_csr_aliases ();
riscv_init_reggroups ();
/* Add root prefix command for all "set debug riscv" and "show debug
riscv" commands. */
- add_prefix_cmd ("riscv", no_class, set_debug_riscv_command,
- _("RISC-V specific debug commands."),
- &setdebugriscvcmdlist, "set debug riscv ", 0,
- &setdebuglist);
+ add_basic_prefix_cmd ("riscv", no_class,
+ _("RISC-V specific debug commands."),
+ &setdebugriscvcmdlist, "set debug riscv ", 0,
+ &setdebuglist);
- add_prefix_cmd ("riscv", no_class, show_debug_riscv_command,
- _("RISC-V specific debug commands."),
- &showdebugriscvcmdlist, "show debug riscv ", 0,
- &showdebuglist);
+ add_show_prefix_cmd ("riscv", no_class,
+ _("RISC-V specific debug commands."),
+ &showdebugriscvcmdlist, "show debug riscv ", 0,
+ &showdebuglist);
add_setshow_zuinteger_cmd ("breakpoints", class_maintenance,
&riscv_debug_breakpoints, _("\
&setdebugriscvcmdlist, &showdebugriscvcmdlist);
/* Add root prefix command for all "set riscv" and "show riscv" commands. */
- add_prefix_cmd ("riscv", no_class, set_riscv_command,
- _("RISC-V specific commands."),
- &setriscvcmdlist, "set riscv ", 0, &setlist);
+ add_basic_prefix_cmd ("riscv", no_class,
+ _("RISC-V specific commands."),
+ &setriscvcmdlist, "set riscv ", 0, &setlist);
- add_prefix_cmd ("riscv", no_class, show_riscv_command,
- _("RISC-V specific commands."),
- &showriscvcmdlist, "show riscv ", 0, &showlist);
+ add_show_prefix_cmd ("riscv", no_class,
+ _("RISC-V specific commands."),
+ &showriscvcmdlist, "show riscv ", 0, &showlist);
use_compressed_breakpoints = AUTO_BOOLEAN_AUTO;