gdb/corefile: write NT_GDB_TDESC based on signalled thread
authorAndrew Burgess <aburgess@redhat.com>
Mon, 25 Sep 2023 09:32:14 +0000 (10:32 +0100)
committerAndrew Burgess <aburgess@redhat.com>
Tue, 3 Oct 2023 16:43:50 +0000 (17:43 +0100)
When creating a core file from within GDB we include a NT_GDB_TDESC
that includes the target description of the architecture in use.

For architectures with dynamic architectures (e.g. AArch64 with
sve/sme) the original architecture, calculated from the original
target description, might not match the per-thread architecture.

In the general case, where each thread has a different architecture,
then we really need a separate NT_GDB_TDESC for each thread, however,
there's currently no way to read in multiple NT_GDB_TDESC.

This commit is a step towards per-thread NT_GDB_TDESC.  In this commit
I have updated the function that writes the NT_GDB_TDESC to accept a
gdbarch (rather than calling target_gdbarch() to find a gdbarch), and
I now pass in the gdbarch of the signalled thread.

In many cases (though NOT all) targets with dynamic architectures
really only use a single architecture, even when there are multiple
threads, so in the common case, this should ensure that GDB emits an
architecture that is more likely to be correct.

Additional work will be needed in order to support corefiles with
truly per-thread architectures, but that will need to be done in the
future.

gdb/elf-none-tdep.c
gdb/fbsd-tdep.c
gdb/gcore-elf.c
gdb/gcore-elf.h
gdb/linux-tdep.c

index ce2db02aa9d8dfea870bc44603b92a29bd9a6f0c..cae66004a260410976df854f587140b54d1b98de 100644 (file)
@@ -110,8 +110,12 @@ elf_none_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd,
     }
 
 
-  /* Target description.  */
-  gcore_elf_make_tdesc_note (obfd, &note_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, &note_data, note_size);
 
   return note_data;
 }
index dc5020d92d20bd77c610c23796b934aba13dde02..d166d7857365673da4737ab9906eb61c5804a94a 100644 (file)
@@ -773,8 +773,12 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
        return NULL;
     }
 
-  /* Include the target description when possible.  */
-  gcore_elf_make_tdesc_note (obfd, &note_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, &note_data, note_size);
 
   return note_data;
 }
index 643426d911b954789875e0eddbf4118fdb32466f..0142db82670d9a2e6449ca334c0df103ceddf2a9 100644 (file)
@@ -139,12 +139,12 @@ gcore_elf_build_thread_register_notes
 /* See gcore-elf.h.  */
 
 void
-gcore_elf_make_tdesc_note (bfd *obfd,
+gcore_elf_make_tdesc_note (struct gdbarch *gdbarch, bfd *obfd,
                           gdb::unique_xmalloc_ptr<char> *note_data,
                           int *note_size)
 {
   /* Append the target description to the core file.  */
-  const struct target_desc *tdesc = gdbarch_target_desc (target_gdbarch ());
+  const struct target_desc *tdesc = gdbarch_target_desc (gdbarch);
   const char *tdesc_xml
     = tdesc == nullptr ? nullptr : tdesc_get_features_xml (tdesc);
   if (tdesc_xml != nullptr && *tdesc_xml != '\0')
index 2cfeb3e85504b88b64d2e6b67483854d8719019e..826e3bebceeee8d2c26d6140602ccf487ddef77f 100644 (file)
@@ -37,11 +37,12 @@ extern void gcore_elf_build_thread_register_notes
    bfd *obfd, gdb::unique_xmalloc_ptr<char> *note_data, int *note_size);
 
 /* Add content to *NOTE_DATA (and update *NOTE_SIZE) to include a note
-   containing the current target's target description.  The core file is
+   containing the target description for GDBARCH.  The core file is
    being written to OBFD.  If something goes wrong then *NOTE_DATA can be
    set to nullptr.  */
 
 extern void gcore_elf_make_tdesc_note
-  (bfd *obfd, gdb::unique_xmalloc_ptr<char> *note_data, int *note_size);
+  (struct gdbarch *gdbarch, bfd *obfd,
+   gdb::unique_xmalloc_ptr<char> *note_data, int *note_size);
 
 #endif /* GCORE_ELF_H */
index 22bb9686e8daddeb8aee1d7e3a46a4057a7da0c5..98658fa5a3f72816250d481d91e5ec3293b0172d 100644 (file)
@@ -2128,8 +2128,12 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
   /* File mappings.  */
   linux_make_mappings_corefile_notes (gdbarch, obfd, note_data, note_size);
 
-  /* Target description.  */
-  gcore_elf_make_tdesc_note (obfd, &note_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, &note_data, note_size);
 
   return note_data;
 }