diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index 47e5e1db641..21ac7ebdc56 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -2199,6 +2199,33 @@ aarch64_linux_decode_memtag_section (struct gdbarch *gdbarch, 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) { @@ -2469,6 +2496,12 @@ 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 diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 56c7fd2f5e7..2e597beb5d4 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -1092,6 +1092,16 @@ default_read_core_file_mappings { } +/* 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) { diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h index 2bdc3251c9c..e53950c4408 100644 --- a/gdb/arch-utils.h +++ b/gdb/arch-utils.h @@ -305,6 +305,12 @@ extern void default_read_core_file_mappings 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); diff --git a/gdb/corelow.c b/gdb/corelow.c index 202fe695cae..c0b26239fd9 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -1229,35 +1229,47 @@ core_target::thread_alive (ptid_t ptid) 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; } diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h index d62eefa1c5b..1d169c6e4f4 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -1717,3 +1717,13 @@ extern void set_gdbarch_get_pc_address_flags (struct gdbarch *gdbarch, gdbarch_g 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); diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 1fc254d3d6e..ea6e4c647b1 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -256,6 +256,7 @@ struct gdbarch 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 @@ -523,6 +524,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* 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 ()); @@ -1373,6 +1375,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) 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); } @@ -5409,3 +5414,20 @@ set_gdbarch_read_core_file_mappings (struct gdbarch *gdbarch, { 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; +} diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py index 846467b8d83..592d301ed35 100644 --- a/gdb/gdbarch_components.py +++ b/gdb/gdbarch_components.py @@ -2732,3 +2732,18 @@ Read core file mappings 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, +)