mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-21 04:42:53 +08:00
4a94e36819
This commit brings all the changes made by running gdb/copyright.py as per GDB's Start of New Year Procedure. For the avoidance of doubt, all changes in this commits were performed by the script.
167 lines
5.4 KiB
C
167 lines
5.4 KiB
C
/* Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
|
|
|
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/>. */
|
|
|
|
#include "defs.h"
|
|
#include "gcore-elf.h"
|
|
#include "elf-bfd.h"
|
|
#include "target.h"
|
|
#include "regcache.h"
|
|
#include "gdbarch.h"
|
|
#include "gdbthread.h"
|
|
#include "inferior.h"
|
|
#include "regset.h"
|
|
#include "gdbsupport/tdesc.h"
|
|
|
|
/* Structure for passing information from GCORE_COLLECT_THREAD_REGISTERS
|
|
via an iterator to GCORE_COLLECT_REGSET_SECTION_CB. */
|
|
|
|
struct gcore_elf_collect_regset_section_cb_data
|
|
{
|
|
gcore_elf_collect_regset_section_cb_data
|
|
(struct gdbarch *gdbarch, const struct regcache *regcache,
|
|
bfd *obfd, ptid_t ptid, gdb_signal stop_signal,
|
|
gdb::unique_xmalloc_ptr<char> *note_data, int *note_size)
|
|
: gdbarch (gdbarch), regcache (regcache), obfd (obfd),
|
|
note_data (note_data), note_size (note_size),
|
|
stop_signal (stop_signal)
|
|
{
|
|
/* The LWP is often not available for bare metal target, in which case
|
|
use the tid instead. */
|
|
if (ptid.lwp_p ())
|
|
lwp = ptid.lwp ();
|
|
else
|
|
lwp = ptid.tid ();
|
|
}
|
|
|
|
struct gdbarch *gdbarch;
|
|
const struct regcache *regcache;
|
|
bfd *obfd;
|
|
gdb::unique_xmalloc_ptr<char> *note_data;
|
|
int *note_size;
|
|
unsigned long lwp;
|
|
enum gdb_signal stop_signal;
|
|
bool abort_iteration = false;
|
|
};
|
|
|
|
/* Callback for ITERATE_OVER_REGSET_SECTIONS that records a single
|
|
regset in the core file note section. */
|
|
|
|
static void
|
|
gcore_elf_collect_regset_section_cb (const char *sect_name,
|
|
int supply_size, int collect_size,
|
|
const struct regset *regset,
|
|
const char *human_name, void *cb_data)
|
|
{
|
|
struct gcore_elf_collect_regset_section_cb_data *data
|
|
= (struct gcore_elf_collect_regset_section_cb_data *) cb_data;
|
|
bool variable_size_section = (regset != nullptr
|
|
&& regset->flags & REGSET_VARIABLE_SIZE);
|
|
|
|
gdb_assert (variable_size_section || supply_size == collect_size);
|
|
|
|
if (data->abort_iteration)
|
|
return;
|
|
|
|
gdb_assert (regset != nullptr && regset->collect_regset != nullptr);
|
|
|
|
/* This is intentionally zero-initialized by using std::vector, so
|
|
that any padding bytes in the core file will show as 0. */
|
|
std::vector<gdb_byte> buf (collect_size);
|
|
|
|
regset->collect_regset (regset, data->regcache, -1, buf.data (),
|
|
collect_size);
|
|
|
|
/* PRSTATUS still needs to be treated specially. */
|
|
if (strcmp (sect_name, ".reg") == 0)
|
|
data->note_data->reset (elfcore_write_prstatus
|
|
(data->obfd, data->note_data->release (),
|
|
data->note_size, data->lwp,
|
|
gdb_signal_to_host (data->stop_signal),
|
|
buf.data ()));
|
|
else
|
|
data->note_data->reset (elfcore_write_register_note
|
|
(data->obfd, data->note_data->release (),
|
|
data->note_size, sect_name, buf.data (),
|
|
collect_size));
|
|
|
|
if (*data->note_data == nullptr)
|
|
data->abort_iteration = true;
|
|
}
|
|
|
|
/* Records the register state of thread PTID out of REGCACHE into the note
|
|
buffer represented by *NOTE_DATA and NOTE_SIZE. OBFD is the bfd into
|
|
which the core file is being created, and STOP_SIGNAL is the signal that
|
|
cause thread PTID to stop. */
|
|
|
|
static void
|
|
gcore_elf_collect_thread_registers
|
|
(const struct regcache *regcache, ptid_t ptid, bfd *obfd,
|
|
gdb::unique_xmalloc_ptr<char> *note_data, int *note_size,
|
|
enum gdb_signal stop_signal)
|
|
{
|
|
struct gdbarch *gdbarch = regcache->arch ();
|
|
gcore_elf_collect_regset_section_cb_data data (gdbarch, regcache, obfd,
|
|
ptid, stop_signal,
|
|
note_data, note_size);
|
|
gdbarch_iterate_over_regset_sections
|
|
(gdbarch, gcore_elf_collect_regset_section_cb, &data, regcache);
|
|
}
|
|
|
|
/* See gcore-elf.h. */
|
|
|
|
void
|
|
gcore_elf_build_thread_register_notes
|
|
(struct gdbarch *gdbarch, struct thread_info *info, gdb_signal stop_signal,
|
|
bfd *obfd, gdb::unique_xmalloc_ptr<char> *note_data, int *note_size)
|
|
{
|
|
struct regcache *regcache
|
|
= get_thread_arch_regcache (info->inf->process_target (),
|
|
info->ptid, gdbarch);
|
|
target_fetch_registers (regcache, -1);
|
|
gcore_elf_collect_thread_registers (regcache, info->ptid, obfd,
|
|
note_data, note_size, stop_signal);
|
|
}
|
|
|
|
/* See gcore-elf.h. */
|
|
|
|
void
|
|
gcore_elf_make_tdesc_note (bfd *obfd,
|
|
gdb::unique_xmalloc_ptr<char> *note_data,
|
|
int *note_size)
|
|
{
|
|
/* Append the target description to the core file. */
|
|
const struct target_desc *tdesc = gdbarch_target_desc (target_gdbarch ());
|
|
const char *tdesc_xml
|
|
= tdesc == nullptr ? nullptr : tdesc_get_features_xml (tdesc);
|
|
if (tdesc_xml != nullptr && *tdesc_xml != '\0')
|
|
{
|
|
/* Skip the leading '@'. */
|
|
if (*tdesc_xml == '@')
|
|
++tdesc_xml;
|
|
|
|
/* Include the null terminator in the length. */
|
|
size_t tdesc_len = strlen (tdesc_xml) + 1;
|
|
|
|
/* Now add the target description into the core file. */
|
|
note_data->reset (elfcore_write_register_note (obfd,
|
|
note_data->release (),
|
|
note_size,
|
|
".gdb-tdesc", tdesc_xml,
|
|
tdesc_len));
|
|
}
|
|
}
|