return tags;
}
+/* AArch64 Linux implementation of the
+ gdbarch_use_target_description_from_corefile_notes hook. */
+
+static bool
+aarch64_use_target_description_from_corefile_notes (gdbarch *gdbarch,
+ bfd *obfd)
+{
+ /* Sanity check. */
+ gdb_assert (obfd != nullptr);
+
+ /* If the corefile contains any SVE or SME register data, we don't want to
+ use the target description note, as it may be incorrect.
+
+ Currently the target description note contains a potentially incorrect
+ target description if the originating program changed the SVE or SME
+ vector lengths mid-execution.
+
+ Once we support per-thread target description notes in the corefiles, we
+ can always trust those notes whenever they are available. */
+ if (bfd_get_section_by_name (obfd, ".reg-aarch-sve") != nullptr
+ || bfd_get_section_by_name (obfd, ".reg-aarch-za") != nullptr
+ || bfd_get_section_by_name (obfd, ".reg-aarch-zt") != nullptr)
+ return false;
+
+ return true;
+}
+
static void
aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
aarch64_displaced_step_hw_singlestep);
set_gdbarch_gcc_target_options (gdbarch, aarch64_linux_gcc_target_options);
+
+ /* Hook to decide if the target description should be obtained from
+ corefile target description note(s) or inferred from the corefile
+ sections. */
+ set_gdbarch_use_target_description_from_corefile_notes (gdbarch,
+ aarch64_use_target_description_from_corefile_notes);
}
#if GDB_SELF_TEST
{
}
+/* See arch-utils.h. */
+bool
+default_use_target_description_from_corefile_notes (struct gdbarch *gdbarch,
+ struct bfd *corefile_bfd)
+{
+ /* Always trust the corefile target description contained in the target
+ description note. */
+ return true;
+}
+
CORE_ADDR
default_get_return_buf_addr (struct type *val_type, frame_info_ptr cur_frame)
{
read_core_file_mappings_pre_loop_ftype pre_loop_cb,
read_core_file_mappings_loop_ftype loop_cb);
+/* Default implementation of gdbarch
+ use_target_description_from_corefile_notes. */
+extern bool default_use_target_description_from_corefile_notes
+ (struct gdbarch *gdbarch,
+ struct bfd *corefile_bfd);
+
/* Default implementation of gdbarch default_get_return_buf_addr method. */
extern CORE_ADDR default_get_return_buf_addr (struct type *val_typegdbarch,
frame_info_ptr cur_frame);
const struct target_desc *
core_target::read_description ()
{
- /* If the core file contains a target description note then we will use
- that in preference to anything else. */
- bfd_size_type tdesc_note_size = 0;
- struct bfd_section *tdesc_note_section
- = bfd_get_section_by_name (core_bfd, ".gdb-tdesc");
- if (tdesc_note_section != nullptr)
- tdesc_note_size = bfd_section_size (tdesc_note_section);
- if (tdesc_note_size > 0)
+ /* First check whether the target wants us to use the corefile target
+ description notes. */
+ if (gdbarch_use_target_description_from_corefile_notes (m_core_gdbarch,
+ core_bfd))
{
- gdb::char_vector contents (tdesc_note_size + 1);
- if (bfd_get_section_contents (core_bfd, tdesc_note_section,
- contents.data (), (file_ptr) 0,
- tdesc_note_size))
+ /* If the core file contains a target description note then go ahead and
+ use that. */
+ bfd_size_type tdesc_note_size = 0;
+ struct bfd_section *tdesc_note_section
+ = bfd_get_section_by_name (core_bfd, ".gdb-tdesc");
+ if (tdesc_note_section != nullptr)
+ tdesc_note_size = bfd_section_size (tdesc_note_section);
+ if (tdesc_note_size > 0)
{
- /* Ensure we have a null terminator. */
- contents[tdesc_note_size] = '\0';
- const struct target_desc *result
- = string_read_description_xml (contents.data ());
- if (result != nullptr)
- return result;
+ gdb::char_vector contents (tdesc_note_size + 1);
+ if (bfd_get_section_contents (core_bfd, tdesc_note_section,
+ contents.data (), (file_ptr) 0,
+ tdesc_note_size))
+ {
+ /* Ensure we have a null terminator. */
+ contents[tdesc_note_size] = '\0';
+ const struct target_desc *result
+ = string_read_description_xml (contents.data ());
+ if (result != nullptr)
+ return result;
+ }
}
}
+ /* If the architecture provides a corefile target description hook, use
+ it now. Even if the core file contains a target description in a note
+ section, it is not useful for targets that can potentially have distinct
+ descriptions for each thread. One example is AArch64's SVE/SME
+ extensions that allow per-thread vector length changes, resulting in
+ registers with different sizes. */
if (m_core_gdbarch && gdbarch_core_read_description_p (m_core_gdbarch))
{
const struct target_desc *result;
result = gdbarch_core_read_description (m_core_gdbarch, this, core_bfd);
- if (result != NULL)
+ if (result != nullptr)
return result;
}
typedef void (gdbarch_read_core_file_mappings_ftype) (struct gdbarch *gdbarch, struct bfd *cbfd, read_core_file_mappings_pre_loop_ftype pre_loop_cb, read_core_file_mappings_loop_ftype loop_cb);
extern void gdbarch_read_core_file_mappings (struct gdbarch *gdbarch, struct bfd *cbfd, read_core_file_mappings_pre_loop_ftype pre_loop_cb, read_core_file_mappings_loop_ftype loop_cb);
extern void set_gdbarch_read_core_file_mappings (struct gdbarch *gdbarch, gdbarch_read_core_file_mappings_ftype *read_core_file_mappings);
+
+/* Return true if the target description for all threads should be read from the
+ target description core file note(s). Return false if the target description
+ for all threads should be inferred from the core file contents/sections.
+
+ The corefile's bfd is passed through COREFILE_BFD. */
+
+typedef bool (gdbarch_use_target_description_from_corefile_notes_ftype) (struct gdbarch *gdbarch, struct bfd *corefile_bfd);
+extern bool gdbarch_use_target_description_from_corefile_notes (struct gdbarch *gdbarch, struct bfd *corefile_bfd);
+extern void set_gdbarch_use_target_description_from_corefile_notes (struct gdbarch *gdbarch, gdbarch_use_target_description_from_corefile_notes_ftype *use_target_description_from_corefile_notes);
gdbarch_type_align_ftype *type_align = default_type_align;
gdbarch_get_pc_address_flags_ftype *get_pc_address_flags = default_get_pc_address_flags;
gdbarch_read_core_file_mappings_ftype *read_core_file_mappings = default_read_core_file_mappings;
+ gdbarch_use_target_description_from_corefile_notes_ftype *use_target_description_from_corefile_notes = default_use_target_description_from_corefile_notes;
};
/* Create a new ``struct gdbarch'' based on information provided by
/* Skip verify of type_align, invalid_p == 0 */
/* Skip verify of get_pc_address_flags, invalid_p == 0 */
/* Skip verify of read_core_file_mappings, invalid_p == 0 */
+ /* Skip verify of use_target_description_from_corefile_notes, invalid_p == 0 */
if (!log.empty ())
internal_error (_("verify_gdbarch: the following are invalid ...%s"),
log.c_str ());
gdb_printf (file,
"gdbarch_dump: read_core_file_mappings = <%s>\n",
host_address_to_string (gdbarch->read_core_file_mappings));
+ gdb_printf (file,
+ "gdbarch_dump: use_target_description_from_corefile_notes = <%s>\n",
+ host_address_to_string (gdbarch->use_target_description_from_corefile_notes));
if (gdbarch->dump_tdep != NULL)
gdbarch->dump_tdep (gdbarch, file);
}
{
gdbarch->read_core_file_mappings = read_core_file_mappings;
}
+
+bool
+gdbarch_use_target_description_from_corefile_notes (struct gdbarch *gdbarch, struct bfd *corefile_bfd)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->use_target_description_from_corefile_notes != NULL);
+ if (gdbarch_debug >= 2)
+ gdb_printf (gdb_stdlog, "gdbarch_use_target_description_from_corefile_notes called\n");
+ return gdbarch->use_target_description_from_corefile_notes (gdbarch, corefile_bfd);
+}
+
+void
+set_gdbarch_use_target_description_from_corefile_notes (struct gdbarch *gdbarch,
+ gdbarch_use_target_description_from_corefile_notes_ftype use_target_description_from_corefile_notes)
+{
+ gdbarch->use_target_description_from_corefile_notes = use_target_description_from_corefile_notes;
+}
predefault="default_read_core_file_mappings",
invalid=False,
)
+
+Method(
+ comment="""
+Return true if the target description for all threads should be read from the
+target description core file note(s). Return false if the target description
+for all threads should be inferred from the core file contents/sections.
+
+The corefile's bfd is passed through COREFILE_BFD.
+""",
+ type="bool",
+ name="use_target_description_from_corefile_notes",
+ params=[("struct bfd *", "corefile_bfd")],
+ predefault="default_use_target_description_from_corefile_notes",
+ invalid=False,
+)