| /* Common code for targets with the none ABI (bare-metal), but where the | 
 |    BFD library is build with ELF support. | 
 |  | 
 |    Copyright (C) 2020-2024 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 "elf-none-tdep.h" | 
 | #include "exceptions.h" | 
 | #include "regset.h" | 
 | #include "elf-bfd.h" | 
 | #include "inferior.h" | 
 | #include "regcache.h" | 
 | #include "gdbarch.h" | 
 | #include "gcore.h" | 
 | #include "gcore-elf.h" | 
 |  | 
 | /* Build the note section for a corefile, and return it in a malloc | 
 |    buffer.  Currently this just dumps all available registers for each | 
 |    thread.  */ | 
 |  | 
 | static gdb::unique_xmalloc_ptr<char> | 
 | elf_none_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, | 
 | 			      int *note_size) | 
 | { | 
 |   gdb::unique_xmalloc_ptr<char> note_data; | 
 |  | 
 |   /* Add note information about the executable and its arguments.  */ | 
 |   std::string fname; | 
 |   std::string psargs; | 
 |   static const size_t fname_len = 16; | 
 |   static const size_t psargs_len = 80; | 
 |   if (current_program_space->exec_filename () != nullptr) | 
 |     { | 
 |       const char *exe = current_program_space->exec_filename (); | 
 |       fname = lbasename (exe); | 
 |       psargs = std::string (exe); | 
 |  | 
 |       const std::string &infargs = current_inferior ()->args (); | 
 |       if (!infargs.empty ()) | 
 | 	psargs += ' ' + infargs; | 
 |  | 
 |       /* All existing targets that handle writing out prpsinfo expect the | 
 | 	 fname and psargs strings to be at least 16 and 80 characters long | 
 | 	 respectively, including a null terminator at the end.  Resize to | 
 | 	 the expected length minus one to ensure there is a null within the | 
 | 	 required length.  */ | 
 |       fname.resize (fname_len - 1); | 
 |       psargs.resize (psargs_len - 1); | 
 |     } | 
 |  | 
 |   /* Resize the buffers up to their required lengths.  This will fill any | 
 |      remaining space with the null character.  */ | 
 |   fname.resize (fname_len); | 
 |   psargs.resize (psargs_len); | 
 |  | 
 |   /* Now write out the prpsinfo structure.  */ | 
 |   note_data.reset (elfcore_write_prpsinfo (obfd, note_data.release (), | 
 | 					   note_size, fname.c_str (), | 
 | 					   psargs.c_str ())); | 
 |   if (note_data == nullptr) | 
 |     return nullptr; | 
 |  | 
 |   /* Thread register information.  */ | 
 |   try | 
 |     { | 
 |       update_thread_list (); | 
 |     } | 
 |   catch (const gdb_exception_error &e) | 
 |     { | 
 |       exception_print (gdb_stderr, e); | 
 |     } | 
 |  | 
 |   /* Like the Linux kernel, prefer dumping the signalled thread first. | 
 |      "First thread" is what tools use to infer the signalled thread.  */ | 
 |   thread_info *signalled_thr = gcore_find_signalled_thread (); | 
 |  | 
 |   /* All threads are reported as having been stopped by the same signal | 
 |      that stopped SIGNALLED_THR.  */ | 
 |   gdb_signal stop_signal; | 
 |   if (signalled_thr != nullptr) | 
 |     stop_signal = signalled_thr->stop_signal (); | 
 |   else | 
 |     stop_signal = GDB_SIGNAL_0; | 
 |  | 
 |   if (signalled_thr != nullptr) | 
 |     gcore_elf_build_thread_register_notes (gdbarch, signalled_thr, | 
 | 					   stop_signal, obfd, ¬e_data, | 
 | 					   note_size); | 
 |   for (thread_info *thr : current_inferior ()->non_exited_threads ()) | 
 |     { | 
 |       if (thr == signalled_thr) | 
 | 	continue; | 
 |  | 
 |       gcore_elf_build_thread_register_notes (gdbarch, thr, stop_signal, obfd, | 
 | 					     ¬e_data, note_size); | 
 |     } | 
 |  | 
 |  | 
 |   /* Include the target description when possible.  Some architectures | 
 |      allow for per-thread gdbarch so we should really be emitting a tdesc | 
 |      per-thread, however, we don't currently support reading in a | 
 |      per-thread tdesc, so just emit the tdesc for the signalled thread.  */ | 
 |   gdbarch = target_thread_architecture (signalled_thr->ptid); | 
 |   gcore_elf_make_tdesc_note (gdbarch, obfd, ¬e_data, note_size); | 
 |  | 
 |   return note_data; | 
 | } | 
 |  | 
 | /* See none-tdep.h.  */ | 
 |  | 
 | void | 
 | elf_none_init_abi (struct gdbarch *gdbarch) | 
 | { | 
 |   /* Default core file support.  */ | 
 |   set_gdbarch_make_corefile_notes (gdbarch, elf_none_make_corefile_notes); | 
 | } |