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