1*6881a400Schristos /* Copyright (C) 2021-2023 Free Software Foundation, Inc. 2*6881a400Schristos 3*6881a400Schristos This file is part of GDB. 4*6881a400Schristos 5*6881a400Schristos This program is free software; you can redistribute it and/or modify 6*6881a400Schristos it under the terms of the GNU General Public License as published by 7*6881a400Schristos the Free Software Foundation; either version 3 of the License, or 8*6881a400Schristos (at your option) any later version. 9*6881a400Schristos 10*6881a400Schristos This program is distributed in the hope that it will be useful, 11*6881a400Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 12*6881a400Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13*6881a400Schristos GNU General Public License for more details. 14*6881a400Schristos 15*6881a400Schristos You should have received a copy of the GNU General Public License 16*6881a400Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17*6881a400Schristos 18*6881a400Schristos #include "defs.h" 19*6881a400Schristos #include "gcore-elf.h" 20*6881a400Schristos #include "elf-bfd.h" 21*6881a400Schristos #include "target.h" 22*6881a400Schristos #include "regcache.h" 23*6881a400Schristos #include "gdbarch.h" 24*6881a400Schristos #include "gdbthread.h" 25*6881a400Schristos #include "inferior.h" 26*6881a400Schristos #include "regset.h" 27*6881a400Schristos #include "gdbsupport/tdesc.h" 28*6881a400Schristos 29*6881a400Schristos /* Structure for passing information from GCORE_COLLECT_THREAD_REGISTERS 30*6881a400Schristos via an iterator to GCORE_COLLECT_REGSET_SECTION_CB. */ 31*6881a400Schristos 32*6881a400Schristos struct gcore_elf_collect_regset_section_cb_data 33*6881a400Schristos { 34*6881a400Schristos gcore_elf_collect_regset_section_cb_data 35*6881a400Schristos (struct gdbarch *gdbarch, const struct regcache *regcache, 36*6881a400Schristos bfd *obfd, ptid_t ptid, gdb_signal stop_signal, 37*6881a400Schristos gdb::unique_xmalloc_ptr<char> *note_data, int *note_size) 38*6881a400Schristos : gdbarch (gdbarch), regcache (regcache), obfd (obfd), 39*6881a400Schristos note_data (note_data), note_size (note_size), 40*6881a400Schristos stop_signal (stop_signal) 41*6881a400Schristos { 42*6881a400Schristos /* The LWP is often not available for bare metal target, in which case 43*6881a400Schristos use the tid instead. */ 44*6881a400Schristos if (ptid.lwp_p ()) 45*6881a400Schristos lwp = ptid.lwp (); 46*6881a400Schristos else 47*6881a400Schristos lwp = ptid.tid (); 48*6881a400Schristos } 49*6881a400Schristos 50*6881a400Schristos struct gdbarch *gdbarch; 51*6881a400Schristos const struct regcache *regcache; 52*6881a400Schristos bfd *obfd; 53*6881a400Schristos gdb::unique_xmalloc_ptr<char> *note_data; 54*6881a400Schristos int *note_size; 55*6881a400Schristos unsigned long lwp; 56*6881a400Schristos enum gdb_signal stop_signal; 57*6881a400Schristos bool abort_iteration = false; 58*6881a400Schristos }; 59*6881a400Schristos 60*6881a400Schristos /* Callback for ITERATE_OVER_REGSET_SECTIONS that records a single 61*6881a400Schristos regset in the core file note section. */ 62*6881a400Schristos 63*6881a400Schristos static void 64*6881a400Schristos gcore_elf_collect_regset_section_cb (const char *sect_name, 65*6881a400Schristos int supply_size, int collect_size, 66*6881a400Schristos const struct regset *regset, 67*6881a400Schristos const char *human_name, void *cb_data) 68*6881a400Schristos { 69*6881a400Schristos struct gcore_elf_collect_regset_section_cb_data *data 70*6881a400Schristos = (struct gcore_elf_collect_regset_section_cb_data *) cb_data; 71*6881a400Schristos bool variable_size_section = (regset != nullptr 72*6881a400Schristos && regset->flags & REGSET_VARIABLE_SIZE); 73*6881a400Schristos 74*6881a400Schristos gdb_assert (variable_size_section || supply_size == collect_size); 75*6881a400Schristos 76*6881a400Schristos if (data->abort_iteration) 77*6881a400Schristos return; 78*6881a400Schristos 79*6881a400Schristos gdb_assert (regset != nullptr && regset->collect_regset != nullptr); 80*6881a400Schristos 81*6881a400Schristos /* This is intentionally zero-initialized by using std::vector, so 82*6881a400Schristos that any padding bytes in the core file will show as 0. */ 83*6881a400Schristos std::vector<gdb_byte> buf (collect_size); 84*6881a400Schristos 85*6881a400Schristos regset->collect_regset (regset, data->regcache, -1, buf.data (), 86*6881a400Schristos collect_size); 87*6881a400Schristos 88*6881a400Schristos /* PRSTATUS still needs to be treated specially. */ 89*6881a400Schristos if (strcmp (sect_name, ".reg") == 0) 90*6881a400Schristos data->note_data->reset (elfcore_write_prstatus 91*6881a400Schristos (data->obfd, data->note_data->release (), 92*6881a400Schristos data->note_size, data->lwp, 93*6881a400Schristos gdb_signal_to_host (data->stop_signal), 94*6881a400Schristos buf.data ())); 95*6881a400Schristos else 96*6881a400Schristos data->note_data->reset (elfcore_write_register_note 97*6881a400Schristos (data->obfd, data->note_data->release (), 98*6881a400Schristos data->note_size, sect_name, buf.data (), 99*6881a400Schristos collect_size)); 100*6881a400Schristos 101*6881a400Schristos if (*data->note_data == nullptr) 102*6881a400Schristos data->abort_iteration = true; 103*6881a400Schristos } 104*6881a400Schristos 105*6881a400Schristos /* Records the register state of thread PTID out of REGCACHE into the note 106*6881a400Schristos buffer represented by *NOTE_DATA and NOTE_SIZE. OBFD is the bfd into 107*6881a400Schristos which the core file is being created, and STOP_SIGNAL is the signal that 108*6881a400Schristos cause thread PTID to stop. */ 109*6881a400Schristos 110*6881a400Schristos static void 111*6881a400Schristos gcore_elf_collect_thread_registers 112*6881a400Schristos (const struct regcache *regcache, ptid_t ptid, bfd *obfd, 113*6881a400Schristos gdb::unique_xmalloc_ptr<char> *note_data, int *note_size, 114*6881a400Schristos enum gdb_signal stop_signal) 115*6881a400Schristos { 116*6881a400Schristos struct gdbarch *gdbarch = regcache->arch (); 117*6881a400Schristos gcore_elf_collect_regset_section_cb_data data (gdbarch, regcache, obfd, 118*6881a400Schristos ptid, stop_signal, 119*6881a400Schristos note_data, note_size); 120*6881a400Schristos gdbarch_iterate_over_regset_sections 121*6881a400Schristos (gdbarch, gcore_elf_collect_regset_section_cb, &data, regcache); 122*6881a400Schristos } 123*6881a400Schristos 124*6881a400Schristos /* See gcore-elf.h. */ 125*6881a400Schristos 126*6881a400Schristos void 127*6881a400Schristos gcore_elf_build_thread_register_notes 128*6881a400Schristos (struct gdbarch *gdbarch, struct thread_info *info, gdb_signal stop_signal, 129*6881a400Schristos bfd *obfd, gdb::unique_xmalloc_ptr<char> *note_data, int *note_size) 130*6881a400Schristos { 131*6881a400Schristos struct regcache *regcache 132*6881a400Schristos = get_thread_arch_regcache (info->inf->process_target (), 133*6881a400Schristos info->ptid, gdbarch); 134*6881a400Schristos target_fetch_registers (regcache, -1); 135*6881a400Schristos gcore_elf_collect_thread_registers (regcache, info->ptid, obfd, 136*6881a400Schristos note_data, note_size, stop_signal); 137*6881a400Schristos } 138*6881a400Schristos 139*6881a400Schristos /* See gcore-elf.h. */ 140*6881a400Schristos 141*6881a400Schristos void 142*6881a400Schristos gcore_elf_make_tdesc_note (bfd *obfd, 143*6881a400Schristos gdb::unique_xmalloc_ptr<char> *note_data, 144*6881a400Schristos int *note_size) 145*6881a400Schristos { 146*6881a400Schristos /* Append the target description to the core file. */ 147*6881a400Schristos const struct target_desc *tdesc = gdbarch_target_desc (target_gdbarch ()); 148*6881a400Schristos const char *tdesc_xml 149*6881a400Schristos = tdesc == nullptr ? nullptr : tdesc_get_features_xml (tdesc); 150*6881a400Schristos if (tdesc_xml != nullptr && *tdesc_xml != '\0') 151*6881a400Schristos { 152*6881a400Schristos /* Skip the leading '@'. */ 153*6881a400Schristos if (*tdesc_xml == '@') 154*6881a400Schristos ++tdesc_xml; 155*6881a400Schristos 156*6881a400Schristos /* Include the null terminator in the length. */ 157*6881a400Schristos size_t tdesc_len = strlen (tdesc_xml) + 1; 158*6881a400Schristos 159*6881a400Schristos /* Now add the target description into the core file. */ 160*6881a400Schristos note_data->reset (elfcore_write_register_note (obfd, 161*6881a400Schristos note_data->release (), 162*6881a400Schristos note_size, 163*6881a400Schristos ".gdb-tdesc", tdesc_xml, 164*6881a400Schristos tdesc_len)); 165*6881a400Schristos } 166*6881a400Schristos } 167