123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- /* 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));
- }
- }
|