[PATCH 3/8] gdb: write target description into core file

Andrew Burgess
2020-12-02T17:40:08Z

When a core file is created from within GDB add the target description
into a note within the core file.

When loading a core file, if the target description note is present
then load the target description from the core file.

The benefit of this is that we can be sure that, when analysing the
core file within GDB, that we are using the exact same target
description as was in use at the time the core file was created.

In future commits I intend to add support for bare metal core dumps
for some targets. These core dumps will include auxiliary registers,
the availability of which can only be established by looking at the
target description.

gdb/ChangeLog:

* corelow.c: Add 'xml-tdesc.h' include.
(core_target::read_description): Load the target description from
the core file when possible.
* gcore.c: Add 'gdbsupport/tdesc.h' include.
(write_gcore_file_1): Write out the target description.
---
gdb/ChangeLog | 9 +++++++++
gdb/corelow.c | 22 ++++++++++++++++++++++
gdb/gcore.c | 20 ++++++++++++++++++++
3 files changed, 51 insertions(+)

diff --git a/gdb/corelow.c b/gdb/corelow.c
index 4c1f068053d..a35c829c55b 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -49,6 +49,7 @@
#include <unordered_map>
#include <unordered_set>
#include "gdbcmd.h"
+#include "xml-tdesc.h"

#ifndef O_LARGEFILE
#define O_LARGEFILE 0
@@ -1000,6 +1001,27 @@ 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)
+ {
+ gdb::char_vector contents (tdesc_note_size);
+ if (bfd_get_section_contents (core_bfd, tdesc_note_section,
+ contents.data(), (file_ptr) 0,
+ tdesc_note_size))
+ {
+ const struct target_desc *result
+ = string_read_description_xml (contents.data ());
+ if (result != NULL)
+ return result;
+ }
+ }
+
if (m_core_gdbarch && gdbarch_core_read_description_p (m_core_gdbarch))
{
const struct target_desc *result;
diff --git a/gdb/gcore.c b/gdb/gcore.c
index 9a22b1005f0..bf6f44213bb 100644
--- a/gdb/gcore.c
+++ b/gdb/gcore.c
@@ -38,6 +38,7 @@
#include "gdbsupport/gdb_unlinker.h"
#include "gdbsupport/byte-vector.h"
#include "gdbsupport/scope-exit.h"
+#include "gdbsupport/tdesc.h"

/* The largest amount of memory to read from the target at once. We
must throttle it to limit the amount of memory used by GDB during
@@ -82,6 +83,25 @@ write_gcore_file_1 (bfd *obfd)
note_data = gdbarch_make_corefile_notes (target_gdbarch (), obfd,
&note_size);

+ /* Append the target description to the core file. */
+ const struct target_desc *tdesc = gdbarch_target_desc (target_gdbarch ());
+ const char *tdesc_xml = tdesc_get_features_xml (tdesc);
+ if (tdesc_xml != nullptr && *tdesc_xml != '\0')
+ {
+ /* Skip the leading '@'. */
+ if (*tdesc_xml == '@')
+ ++tdesc_xml;
+
+ /* Include the null terminator in the length. */
+ size_t tdesc_len = strlen (tdesc_xml) + 1;
+
+ /* Now add the target description into the core file. */
+ note_data.reset (elfcore_write_register_note (obfd,
+ note_data.release (),
+ &note_size, ".gdb-tdesc",
+ tdesc_xml, tdesc_len));
+ }
+
if (note_data == NULL || note_size == 0)
error (_("Target does not support core file generation."));

--
2.25.4