2022-01-01 22:56:03 +08:00
|
|
|
/* Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
gdb/riscv: introduce bare metal core dump support
This commit adds the ability for bare metal RISC-V target to generate
core files from within GDB.
The intended use case is that a user will connect to a remote bare
metal target, debug up to some error condition, then generate a core
file in the normal way using:
(gdb) generate-core-file
This core file can then be used to revisit the state of the remote
target without having to reconnect to the remote target.
The core file creation code is split between two new files. In
elf-none-tdep.c is code for any architecture with the none
ABI (i.e. bare metal) when the BFD library is built with ELF support.
In riscv-none-tdep.c are the RISC-V specific parts. This is where the
regset and regcache_map_entry structures are defined that control how
registers are laid out in the core file. As this file could (in
theory at least) be used for a non-ELF bare metal RISC-V target, the
calls into elf-none-tdep.c are guarded with '#ifdef HAVE_ELF'.
Currently for RISC-V only the x-regs and f-regs (if present) are
written out. In future commits I plan to add support for writing out
the RISC-V CSRs.
The core dump format is based around generating an ELF containing
sections for the writable regions of memory that a user could be
using. Which regions are dumped rely on GDB's existing common core
dumping code, GDB will attempt to figure out the stack and heap as
well as copying out writable data sections as identified by the
original ELF.
Register information is added to the core dump using notes, just as it
is for Linux of FreeBSD core dumps. The note types used consist of
the 3 basic types you would expect in a OS based core dump,
NT_PRPSINFO, NT_PRSTATUS, NT_FPREGSET.
The layout of these notes differs slightly (due to field sizes)
between RV32 and RV64. Below I describe the data layout for each
note. In all cases, all padding fields should be set to zero.
Note NT_PRPSINFO is optional. Its data layout is:
struct prpsinfo32_t /* For RV32. */
{
uint8_t padding[32];
char fname[16];
char psargs[80];
}
struct prpsinfo64_t /* For RV64. */
{
uint8_t padding[40];
char fname[16];
char psargs[80];
}
Field 'fname' - null terminated string consisting of the basename of
(up to the fist 15 characters of) the executable. Any additional
space should be set to zero. If there's no executable name then
this field can be set to all zero.
Field 'psargs' - a null terminated string up to 80 characters in
length. Any additional space should be filled with zero. This
field contains the full executable path and any arguments passed
to the executable. If there's nothing sensible to write in this
field then fill it with zero.
Note NT_PRSTATUS is required, its data layout is:
struct prstatus32_t /* For RV32. */
{
uint8_t padding_1[12];
uint16_t sig;
uint8_t padding_2[10];
uint32_t thread_id;
uint8_t padding_3[44];
uint32_t x_regs[32];
uint8_t padding_4[4];
}
struct prstatus64_t /* For RV64. */
{
uint8_t padding_1[12];
uint16_t sig;
uint8_t padding_2[18];
uint32_t thread_id;
uint8_t padding_3[76];
uint64_t x_regs[32];
uint8_t padding_4[4];
}
Field 'sig' - the signal that stopped this thread. It's implementation
defined what this field actually means. Within GDB this will be
the signal number that the remote target reports as the stop
reason for this thread.
Field 'thread_is' - the thread id for this thread. It's implementation
defined what this field actually means. Within GDB this will be
thread thread-id that is assigned to each remote thread.
Field 'x_regs' - at index 0 we store the program counter, and at
indices 1 to 31 we store x-registers 1 to 31. x-register 0 is not
stored, its value is always zero anyway.
Note NT_FPREGSET is optional, its data layout is:
fpregset32_t /* For targets with 'F' extension. */
{
uint32_t f_regs[32];
uint32_t fcsr;
}
fpregset64_t /* For targets with 'D' extension . */
{
uint64_t f_regs[32];
uint32_t fcsr;
}
Field 'f_regs' - stores f-registers 0 to 31.
Field 'fcsr' - stores the fcsr CSR register, and is always 4-bytes.
The rules for ordering the notes is the same as for Linux. The
NT_PRSTATUS note must come before any other notes about additional
register sets. And for multi-threaded targets all registers for a
single thread should be grouped together. This is because only
NT_PRSTATUS includes a thread-id, all additional register notes after
a NT_PRSTATUS are assumed to belong to the same thread until a
different NT_PRSTATUS is seen.
gdb/ChangeLog:
* Makefile.in (ALL_TARGET_OBS): Add riscv-none-tdep.o.
(ALLDEPFILES): Add riscv-none-tdep.c.
* configure: Regenerate.
* configure.ac (CONFIG_OBS): Add elf-none-tdep.o when BFD has ELF
support.
* configure.tgt (riscv*-*-*): Include riscv-none-tdep.c.
* elf-none-tdep.c: New file.
* elf-none-tdep.h: New file.
* riscv-none-tdep.c: New file.
2020-11-30 20:15:08 +08:00
|
|
|
|
|
|
|
This file is part of GDB.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
/* This file contain code that is specific for bare-metal RISC-V targets. */
|
|
|
|
|
|
|
|
#include "defs.h"
|
|
|
|
#include "arch-utils.h"
|
|
|
|
#include "regcache.h"
|
|
|
|
#include "riscv-tdep.h"
|
|
|
|
#include "elf-bfd.h"
|
|
|
|
#include "regset.h"
|
2020-11-27 22:39:23 +08:00
|
|
|
#include "user-regs.h"
|
|
|
|
#include "target-descriptions.h"
|
gdb/riscv: introduce bare metal core dump support
This commit adds the ability for bare metal RISC-V target to generate
core files from within GDB.
The intended use case is that a user will connect to a remote bare
metal target, debug up to some error condition, then generate a core
file in the normal way using:
(gdb) generate-core-file
This core file can then be used to revisit the state of the remote
target without having to reconnect to the remote target.
The core file creation code is split between two new files. In
elf-none-tdep.c is code for any architecture with the none
ABI (i.e. bare metal) when the BFD library is built with ELF support.
In riscv-none-tdep.c are the RISC-V specific parts. This is where the
regset and regcache_map_entry structures are defined that control how
registers are laid out in the core file. As this file could (in
theory at least) be used for a non-ELF bare metal RISC-V target, the
calls into elf-none-tdep.c are guarded with '#ifdef HAVE_ELF'.
Currently for RISC-V only the x-regs and f-regs (if present) are
written out. In future commits I plan to add support for writing out
the RISC-V CSRs.
The core dump format is based around generating an ELF containing
sections for the writable regions of memory that a user could be
using. Which regions are dumped rely on GDB's existing common core
dumping code, GDB will attempt to figure out the stack and heap as
well as copying out writable data sections as identified by the
original ELF.
Register information is added to the core dump using notes, just as it
is for Linux of FreeBSD core dumps. The note types used consist of
the 3 basic types you would expect in a OS based core dump,
NT_PRPSINFO, NT_PRSTATUS, NT_FPREGSET.
The layout of these notes differs slightly (due to field sizes)
between RV32 and RV64. Below I describe the data layout for each
note. In all cases, all padding fields should be set to zero.
Note NT_PRPSINFO is optional. Its data layout is:
struct prpsinfo32_t /* For RV32. */
{
uint8_t padding[32];
char fname[16];
char psargs[80];
}
struct prpsinfo64_t /* For RV64. */
{
uint8_t padding[40];
char fname[16];
char psargs[80];
}
Field 'fname' - null terminated string consisting of the basename of
(up to the fist 15 characters of) the executable. Any additional
space should be set to zero. If there's no executable name then
this field can be set to all zero.
Field 'psargs' - a null terminated string up to 80 characters in
length. Any additional space should be filled with zero. This
field contains the full executable path and any arguments passed
to the executable. If there's nothing sensible to write in this
field then fill it with zero.
Note NT_PRSTATUS is required, its data layout is:
struct prstatus32_t /* For RV32. */
{
uint8_t padding_1[12];
uint16_t sig;
uint8_t padding_2[10];
uint32_t thread_id;
uint8_t padding_3[44];
uint32_t x_regs[32];
uint8_t padding_4[4];
}
struct prstatus64_t /* For RV64. */
{
uint8_t padding_1[12];
uint16_t sig;
uint8_t padding_2[18];
uint32_t thread_id;
uint8_t padding_3[76];
uint64_t x_regs[32];
uint8_t padding_4[4];
}
Field 'sig' - the signal that stopped this thread. It's implementation
defined what this field actually means. Within GDB this will be
the signal number that the remote target reports as the stop
reason for this thread.
Field 'thread_is' - the thread id for this thread. It's implementation
defined what this field actually means. Within GDB this will be
thread thread-id that is assigned to each remote thread.
Field 'x_regs' - at index 0 we store the program counter, and at
indices 1 to 31 we store x-registers 1 to 31. x-register 0 is not
stored, its value is always zero anyway.
Note NT_FPREGSET is optional, its data layout is:
fpregset32_t /* For targets with 'F' extension. */
{
uint32_t f_regs[32];
uint32_t fcsr;
}
fpregset64_t /* For targets with 'D' extension . */
{
uint64_t f_regs[32];
uint32_t fcsr;
}
Field 'f_regs' - stores f-registers 0 to 31.
Field 'fcsr' - stores the fcsr CSR register, and is always 4-bytes.
The rules for ordering the notes is the same as for Linux. The
NT_PRSTATUS note must come before any other notes about additional
register sets. And for multi-threaded targets all registers for a
single thread should be grouped together. This is because only
NT_PRSTATUS includes a thread-id, all additional register notes after
a NT_PRSTATUS are assumed to belong to the same thread until a
different NT_PRSTATUS is seen.
gdb/ChangeLog:
* Makefile.in (ALL_TARGET_OBS): Add riscv-none-tdep.o.
(ALLDEPFILES): Add riscv-none-tdep.c.
* configure: Regenerate.
* configure.ac (CONFIG_OBS): Add elf-none-tdep.o when BFD has ELF
support.
* configure.tgt (riscv*-*-*): Include riscv-none-tdep.c.
* elf-none-tdep.c: New file.
* elf-none-tdep.h: New file.
* riscv-none-tdep.c: New file.
2020-11-30 20:15:08 +08:00
|
|
|
|
|
|
|
#ifdef HAVE_ELF
|
|
|
|
#include "elf-none-tdep.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Define the general register mapping. This follows the same format as
|
|
|
|
the RISC-V linux corefile. The linux kernel puts the PC at offset 0,
|
|
|
|
gdb puts it at offset 32. Register x0 is always 0 and can be ignored.
|
|
|
|
Registers x1 to x31 are in the same place. */
|
|
|
|
|
|
|
|
static const struct regcache_map_entry riscv_gregmap[] =
|
|
|
|
{
|
|
|
|
{ 1, RISCV_PC_REGNUM, 0 },
|
|
|
|
{ 31, RISCV_RA_REGNUM, 0 }, /* x1 to x31 */
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Define the FP register mapping. This follows the same format as the
|
|
|
|
RISC-V linux corefile. The kernel puts the 32 FP regs first, and then
|
|
|
|
FCSR. */
|
|
|
|
|
|
|
|
static const struct regcache_map_entry riscv_fregmap[] =
|
|
|
|
{
|
|
|
|
{ 32, RISCV_FIRST_FP_REGNUM, 0 },
|
|
|
|
{ 1, RISCV_CSR_FCSR_REGNUM, 4 }, /* Always stored as 4-bytes. */
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Define the general register regset. */
|
|
|
|
|
|
|
|
static const struct regset riscv_gregset =
|
|
|
|
{
|
|
|
|
riscv_gregmap, riscv_supply_regset, regcache_collect_regset
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Define the FP register regset. */
|
|
|
|
|
|
|
|
static const struct regset riscv_fregset =
|
|
|
|
{
|
|
|
|
riscv_fregmap, riscv_supply_regset, regcache_collect_regset
|
|
|
|
};
|
|
|
|
|
2020-11-27 22:39:23 +08:00
|
|
|
/* Define the CSR regset, this is not constant as the regmap field is
|
|
|
|
updated dynamically based on the current target description. */
|
|
|
|
|
|
|
|
static struct regset riscv_csrset =
|
|
|
|
{
|
|
|
|
nullptr, regcache_supply_regset, regcache_collect_regset
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Update the regmap field of RISCV_CSRSET based on the CSRs available in
|
|
|
|
the current target description. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
riscv_update_csrmap (struct gdbarch *gdbarch,
|
|
|
|
const struct tdesc_feature *feature_csr)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
/* Release any previously defined map. */
|
|
|
|
delete[] ((struct regcache_map_entry *) riscv_csrset.regmap);
|
|
|
|
|
|
|
|
/* Now create a register map for every csr found in the target
|
|
|
|
description. */
|
|
|
|
struct regcache_map_entry *riscv_csrmap
|
|
|
|
= new struct regcache_map_entry[feature_csr->registers.size() + 1];
|
|
|
|
for (auto &csr : feature_csr->registers)
|
|
|
|
{
|
|
|
|
int regnum = user_reg_map_name_to_regnum (gdbarch, csr->name.c_str(),
|
|
|
|
csr->name.length());
|
|
|
|
riscv_csrmap[i++] = {1, regnum, 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Mark the end of the array. */
|
|
|
|
riscv_csrmap[i] = {0};
|
|
|
|
riscv_csrset.regmap = riscv_csrmap;
|
|
|
|
}
|
|
|
|
|
gdb/riscv: introduce bare metal core dump support
This commit adds the ability for bare metal RISC-V target to generate
core files from within GDB.
The intended use case is that a user will connect to a remote bare
metal target, debug up to some error condition, then generate a core
file in the normal way using:
(gdb) generate-core-file
This core file can then be used to revisit the state of the remote
target without having to reconnect to the remote target.
The core file creation code is split between two new files. In
elf-none-tdep.c is code for any architecture with the none
ABI (i.e. bare metal) when the BFD library is built with ELF support.
In riscv-none-tdep.c are the RISC-V specific parts. This is where the
regset and regcache_map_entry structures are defined that control how
registers are laid out in the core file. As this file could (in
theory at least) be used for a non-ELF bare metal RISC-V target, the
calls into elf-none-tdep.c are guarded with '#ifdef HAVE_ELF'.
Currently for RISC-V only the x-regs and f-regs (if present) are
written out. In future commits I plan to add support for writing out
the RISC-V CSRs.
The core dump format is based around generating an ELF containing
sections for the writable regions of memory that a user could be
using. Which regions are dumped rely on GDB's existing common core
dumping code, GDB will attempt to figure out the stack and heap as
well as copying out writable data sections as identified by the
original ELF.
Register information is added to the core dump using notes, just as it
is for Linux of FreeBSD core dumps. The note types used consist of
the 3 basic types you would expect in a OS based core dump,
NT_PRPSINFO, NT_PRSTATUS, NT_FPREGSET.
The layout of these notes differs slightly (due to field sizes)
between RV32 and RV64. Below I describe the data layout for each
note. In all cases, all padding fields should be set to zero.
Note NT_PRPSINFO is optional. Its data layout is:
struct prpsinfo32_t /* For RV32. */
{
uint8_t padding[32];
char fname[16];
char psargs[80];
}
struct prpsinfo64_t /* For RV64. */
{
uint8_t padding[40];
char fname[16];
char psargs[80];
}
Field 'fname' - null terminated string consisting of the basename of
(up to the fist 15 characters of) the executable. Any additional
space should be set to zero. If there's no executable name then
this field can be set to all zero.
Field 'psargs' - a null terminated string up to 80 characters in
length. Any additional space should be filled with zero. This
field contains the full executable path and any arguments passed
to the executable. If there's nothing sensible to write in this
field then fill it with zero.
Note NT_PRSTATUS is required, its data layout is:
struct prstatus32_t /* For RV32. */
{
uint8_t padding_1[12];
uint16_t sig;
uint8_t padding_2[10];
uint32_t thread_id;
uint8_t padding_3[44];
uint32_t x_regs[32];
uint8_t padding_4[4];
}
struct prstatus64_t /* For RV64. */
{
uint8_t padding_1[12];
uint16_t sig;
uint8_t padding_2[18];
uint32_t thread_id;
uint8_t padding_3[76];
uint64_t x_regs[32];
uint8_t padding_4[4];
}
Field 'sig' - the signal that stopped this thread. It's implementation
defined what this field actually means. Within GDB this will be
the signal number that the remote target reports as the stop
reason for this thread.
Field 'thread_is' - the thread id for this thread. It's implementation
defined what this field actually means. Within GDB this will be
thread thread-id that is assigned to each remote thread.
Field 'x_regs' - at index 0 we store the program counter, and at
indices 1 to 31 we store x-registers 1 to 31. x-register 0 is not
stored, its value is always zero anyway.
Note NT_FPREGSET is optional, its data layout is:
fpregset32_t /* For targets with 'F' extension. */
{
uint32_t f_regs[32];
uint32_t fcsr;
}
fpregset64_t /* For targets with 'D' extension . */
{
uint64_t f_regs[32];
uint32_t fcsr;
}
Field 'f_regs' - stores f-registers 0 to 31.
Field 'fcsr' - stores the fcsr CSR register, and is always 4-bytes.
The rules for ordering the notes is the same as for Linux. The
NT_PRSTATUS note must come before any other notes about additional
register sets. And for multi-threaded targets all registers for a
single thread should be grouped together. This is because only
NT_PRSTATUS includes a thread-id, all additional register notes after
a NT_PRSTATUS are assumed to belong to the same thread until a
different NT_PRSTATUS is seen.
gdb/ChangeLog:
* Makefile.in (ALL_TARGET_OBS): Add riscv-none-tdep.o.
(ALLDEPFILES): Add riscv-none-tdep.c.
* configure: Regenerate.
* configure.ac (CONFIG_OBS): Add elf-none-tdep.o when BFD has ELF
support.
* configure.tgt (riscv*-*-*): Include riscv-none-tdep.c.
* elf-none-tdep.c: New file.
* elf-none-tdep.h: New file.
* riscv-none-tdep.c: New file.
2020-11-30 20:15:08 +08:00
|
|
|
/* Implement the "iterate_over_regset_sections" gdbarch method. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
riscv_iterate_over_regset_sections (struct gdbarch *gdbarch,
|
|
|
|
iterate_over_regset_sections_cb *cb,
|
|
|
|
void *cb_data,
|
|
|
|
const struct regcache *regcache)
|
|
|
|
{
|
|
|
|
/* Write out the GPRs. */
|
|
|
|
int sz = 32 * riscv_isa_xlen (gdbarch);
|
|
|
|
cb (".reg", sz, sz, &riscv_gregset, NULL, cb_data);
|
|
|
|
|
|
|
|
/* Write out the FPRs, but only if present. */
|
|
|
|
if (riscv_isa_flen (gdbarch) > 0)
|
|
|
|
{
|
|
|
|
sz = (32 * riscv_isa_flen (gdbarch)
|
|
|
|
+ register_size (gdbarch, RISCV_CSR_FCSR_REGNUM));
|
|
|
|
cb (".reg2", sz, sz, &riscv_fregset, NULL, cb_data);
|
|
|
|
}
|
2020-11-27 22:39:23 +08:00
|
|
|
|
|
|
|
/* Read or write the CSRs. The set of CSRs is defined by the current
|
|
|
|
target description. The user is responsible for ensuring that the
|
|
|
|
same target description is in use when reading the core file as was
|
|
|
|
in use when writing the core file. */
|
|
|
|
const struct target_desc *tdesc = gdbarch_target_desc (gdbarch);
|
|
|
|
|
|
|
|
/* Do not dump/load any CSRs if there is no target description or the target
|
|
|
|
description does not contain any CSRs. */
|
|
|
|
if (tdesc != nullptr)
|
|
|
|
{
|
|
|
|
const struct tdesc_feature *feature_csr
|
|
|
|
= tdesc_find_feature (tdesc, riscv_feature_name_csr);
|
|
|
|
if (feature_csr != nullptr && feature_csr->registers.size () > 0)
|
|
|
|
{
|
|
|
|
riscv_update_csrmap (gdbarch, feature_csr);
|
|
|
|
cb (".reg-riscv-csr",
|
|
|
|
(feature_csr->registers.size() * riscv_isa_xlen (gdbarch)),
|
|
|
|
(feature_csr->registers.size() * riscv_isa_xlen (gdbarch)),
|
|
|
|
&riscv_csrset, NULL, cb_data);
|
|
|
|
}
|
|
|
|
}
|
gdb/riscv: introduce bare metal core dump support
This commit adds the ability for bare metal RISC-V target to generate
core files from within GDB.
The intended use case is that a user will connect to a remote bare
metal target, debug up to some error condition, then generate a core
file in the normal way using:
(gdb) generate-core-file
This core file can then be used to revisit the state of the remote
target without having to reconnect to the remote target.
The core file creation code is split between two new files. In
elf-none-tdep.c is code for any architecture with the none
ABI (i.e. bare metal) when the BFD library is built with ELF support.
In riscv-none-tdep.c are the RISC-V specific parts. This is where the
regset and regcache_map_entry structures are defined that control how
registers are laid out in the core file. As this file could (in
theory at least) be used for a non-ELF bare metal RISC-V target, the
calls into elf-none-tdep.c are guarded with '#ifdef HAVE_ELF'.
Currently for RISC-V only the x-regs and f-regs (if present) are
written out. In future commits I plan to add support for writing out
the RISC-V CSRs.
The core dump format is based around generating an ELF containing
sections for the writable regions of memory that a user could be
using. Which regions are dumped rely on GDB's existing common core
dumping code, GDB will attempt to figure out the stack and heap as
well as copying out writable data sections as identified by the
original ELF.
Register information is added to the core dump using notes, just as it
is for Linux of FreeBSD core dumps. The note types used consist of
the 3 basic types you would expect in a OS based core dump,
NT_PRPSINFO, NT_PRSTATUS, NT_FPREGSET.
The layout of these notes differs slightly (due to field sizes)
between RV32 and RV64. Below I describe the data layout for each
note. In all cases, all padding fields should be set to zero.
Note NT_PRPSINFO is optional. Its data layout is:
struct prpsinfo32_t /* For RV32. */
{
uint8_t padding[32];
char fname[16];
char psargs[80];
}
struct prpsinfo64_t /* For RV64. */
{
uint8_t padding[40];
char fname[16];
char psargs[80];
}
Field 'fname' - null terminated string consisting of the basename of
(up to the fist 15 characters of) the executable. Any additional
space should be set to zero. If there's no executable name then
this field can be set to all zero.
Field 'psargs' - a null terminated string up to 80 characters in
length. Any additional space should be filled with zero. This
field contains the full executable path and any arguments passed
to the executable. If there's nothing sensible to write in this
field then fill it with zero.
Note NT_PRSTATUS is required, its data layout is:
struct prstatus32_t /* For RV32. */
{
uint8_t padding_1[12];
uint16_t sig;
uint8_t padding_2[10];
uint32_t thread_id;
uint8_t padding_3[44];
uint32_t x_regs[32];
uint8_t padding_4[4];
}
struct prstatus64_t /* For RV64. */
{
uint8_t padding_1[12];
uint16_t sig;
uint8_t padding_2[18];
uint32_t thread_id;
uint8_t padding_3[76];
uint64_t x_regs[32];
uint8_t padding_4[4];
}
Field 'sig' - the signal that stopped this thread. It's implementation
defined what this field actually means. Within GDB this will be
the signal number that the remote target reports as the stop
reason for this thread.
Field 'thread_is' - the thread id for this thread. It's implementation
defined what this field actually means. Within GDB this will be
thread thread-id that is assigned to each remote thread.
Field 'x_regs' - at index 0 we store the program counter, and at
indices 1 to 31 we store x-registers 1 to 31. x-register 0 is not
stored, its value is always zero anyway.
Note NT_FPREGSET is optional, its data layout is:
fpregset32_t /* For targets with 'F' extension. */
{
uint32_t f_regs[32];
uint32_t fcsr;
}
fpregset64_t /* For targets with 'D' extension . */
{
uint64_t f_regs[32];
uint32_t fcsr;
}
Field 'f_regs' - stores f-registers 0 to 31.
Field 'fcsr' - stores the fcsr CSR register, and is always 4-bytes.
The rules for ordering the notes is the same as for Linux. The
NT_PRSTATUS note must come before any other notes about additional
register sets. And for multi-threaded targets all registers for a
single thread should be grouped together. This is because only
NT_PRSTATUS includes a thread-id, all additional register notes after
a NT_PRSTATUS are assumed to belong to the same thread until a
different NT_PRSTATUS is seen.
gdb/ChangeLog:
* Makefile.in (ALL_TARGET_OBS): Add riscv-none-tdep.o.
(ALLDEPFILES): Add riscv-none-tdep.c.
* configure: Regenerate.
* configure.ac (CONFIG_OBS): Add elf-none-tdep.o when BFD has ELF
support.
* configure.tgt (riscv*-*-*): Include riscv-none-tdep.c.
* elf-none-tdep.c: New file.
* elf-none-tdep.h: New file.
* riscv-none-tdep.c: New file.
2020-11-30 20:15:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize RISC-V bare-metal ABI info. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
riscv_none_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_ELF
|
|
|
|
elf_none_init_abi (gdbarch);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Iterate over registers for reading and writing bare metal RISC-V core
|
|
|
|
files. */
|
|
|
|
set_gdbarch_iterate_over_regset_sections
|
|
|
|
(gdbarch, riscv_iterate_over_regset_sections);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize RISC-V bare-metal target support. */
|
|
|
|
|
|
|
|
void _initialize_riscv_none_tdep ();
|
|
|
|
void
|
|
|
|
_initialize_riscv_none_tdep ()
|
|
|
|
{
|
|
|
|
gdbarch_register_osabi (bfd_arch_riscv, 0, GDB_OSABI_NONE,
|
|
|
|
riscv_none_init_abi);
|
|
|
|
}
|