[PATCH] Handle DWARF 5 separate debug sections
Tom Tromey
tom@tromey.com
Sun Feb 21 23:18:10 GMT 2021
DWARF 5 standardized the .gnu_debugaltlink section that dwz emits in
multi-file mode. This is handled via some new forms, and a new
.debug_sup section.
This patch adds support for this to gdb. It is largely
straightforward, I think, though one oddity is that I chose not to
have this code search the system build-id directories for the
supplementary file. My feeling was that, while it makes sense for a
distro to unify the build-id concept with the hash stored in the
.debug_sup section, there's no intrinsic need to do so.
I also chose to put the .debug_sup parsing directly in gdb rather than
in BFD. This is perhaps cheating a bit.
This patch requires my earlier 'dwz' series.
gdb/ChangeLog
2021-02-21 Tom Tromey <tom@tromey.com>
* dwarf2/read.c (struct partial_die_info) <is_dwz, spec_is_dwz>:
Update comments.
(skip_one_die): Add DWARF 5 forms.
(process_imported_unit_die, partial_die_info::read)
(partial_die_info::read): Update.
(read_attribute_value, dwarf2_const_value_attr): Add DWARF 5
forms.
(lookup_die_type): Update.
(dump_die_shallow): Add DWARF 5 forms.
(follow_die_ref): Update.
(dwarf2_fetch_constant_bytes): Add DWARF 5 forms.
* dwarf2/macro.c (skip_form_bytes): Add DWARF 5 form.
* dwarf2/dwz.c (get_debug_sup_info, verify_id, read_alt_info): New
functions.
(dwz_search_other_debugdirs): Add 'dwarf5' parameter.
(dwarf2_get_dwz_file): Update.
* dwarf2/attribute.h (form_is_ref): Add DWARF 5 forms.
(form_is_alt): New method.
* dwarf2/attribute.c (attribute::form_is_string)
(attribute::form_is_unsigned): Add DWARF 5 forms.
gdb/testsuite/ChangeLog
2021-02-21 Tom Tromey <tom@tromey.com>
* gdb.dwarf2/dwznolink.exp: Update expected output.
* gdb.dwarf2/dwzbuildid.exp: Also test .debug_sup.
---
gdb/ChangeLog | 23 +++
gdb/dwarf2/attribute.c | 5 +-
gdb/dwarf2/attribute.h | 14 +-
gdb/dwarf2/dwz.c | 172 ++++++++++++++---
gdb/dwarf2/macro.c | 1 +
gdb/dwarf2/read.c | 30 ++-
gdb/testsuite/ChangeLog | 5 +
gdb/testsuite/gdb.dwarf2/dwzbuildid.exp | 245 +++++++++++++-----------
gdb/testsuite/gdb.dwarf2/dwznolink.exp | 2 +-
gdb/testsuite/lib/dwarf.exp | 18 ++
10 files changed, 357 insertions(+), 158 deletions(-)
diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c
index 3205b0f7d29..7a73b20cc38 100644
--- a/gdb/dwarf2/attribute.c
+++ b/gdb/dwarf2/attribute.c
@@ -74,7 +74,8 @@ attribute::form_is_string () const
|| form == DW_FORM_strx3
|| form == DW_FORM_strx4
|| form == DW_FORM_GNU_str_index
- || form == DW_FORM_GNU_strp_alt);
+ || form == DW_FORM_GNU_strp_alt
+ || form == DW_FORM_strp_sup);
}
/* See attribute.h. */
@@ -170,6 +171,8 @@ attribute::form_is_unsigned () const
{
return (form == DW_FORM_ref_addr
|| form == DW_FORM_GNU_ref_alt
+ || form == DW_FORM_ref_sup4
+ || form == DW_FORM_ref_sup8
|| form == DW_FORM_data2
|| form == DW_FORM_data4
|| form == DW_FORM_data8
diff --git a/gdb/dwarf2/attribute.h b/gdb/dwarf2/attribute.h
index 56776d64ed3..5490b670ffa 100644
--- a/gdb/dwarf2/attribute.h
+++ b/gdb/dwarf2/attribute.h
@@ -133,7 +133,9 @@ struct attribute
|| form == DW_FORM_ref4
|| form == DW_FORM_ref8
|| form == DW_FORM_ref_udata
- || form == DW_FORM_GNU_ref_alt);
+ || form == DW_FORM_GNU_ref_alt
+ || form == DW_FORM_ref_sup4
+ || form == DW_FORM_ref_sup8);
}
/* Check if the attribute's form is a DW_FORM_block*
@@ -147,6 +149,16 @@ struct attribute
/* Check if the attribute's form is an unsigned integer form. */
bool form_is_unsigned () const;
+ /* Check if attribute's form refers to the separate "dwz" file.
+ This is only useful for references to the .debug_info section,
+ not to the supplementary .debug_str section. */
+ bool form_is_alt () const
+ {
+ return (form == DW_FORM_GNU_ref_alt
+ || form == DW_FORM_ref_sup4
+ || form == DW_FORM_ref_sup8);
+ }
+
/* Check if the attribute's form is a form that requires
"reprocessing". */
bool form_requires_reprocessing () const;
diff --git a/gdb/dwarf2/dwz.c b/gdb/dwarf2/dwz.c
index f9d5db6b48a..3cde6ff3477 100644
--- a/gdb/dwarf2/dwz.c
+++ b/gdb/dwarf2/dwz.c
@@ -22,6 +22,7 @@
#include "build-id.h"
#include "debuginfod-support.h"
+#include "dwarf2/leb.h"
#include "dwarf2/read.h"
#include "dwarf2/sect-names.h"
#include "filenames.h"
@@ -93,6 +94,125 @@ locate_dwz_sections (bfd *abfd, asection *sectp, dwz_file *dwz_file)
}
}
+/* Like bfd_get_alt_debug_link_info, but looks at the .debug_sup
+ section. Returns true on success and fills in the out parameters;
+ false on failure. */
+
+static bool
+get_debug_sup_info (bfd *abfd,
+ gdb::unique_xmalloc_ptr<char> *filename,
+ size_t *buildid_len,
+ gdb::unique_xmalloc_ptr<bfd_byte> *buildid)
+{
+ asection *sect = bfd_get_section_by_name (abfd, ".debug_sup");
+ if (sect == nullptr)
+ return false;
+
+ bfd_byte *contents;
+ if (!bfd_malloc_and_get_section (abfd, sect, &contents))
+ return false;
+
+ gdb::unique_xmalloc_ptr<bfd_byte> content_holder (contents);
+ bfd_size_type size = bfd_section_size (sect);
+
+ /* Version of this section. */
+ if (size < 4)
+ return false;
+ unsigned int version = read_2_bytes (abfd, contents);
+ contents += 2;
+ size -= 2;
+ if (version != 5)
+ return false;
+
+ /* Skip the is_supplementary value. We already ensured there were
+ enough bytes, above. */
+ ++contents;
+ --size;
+
+ /* The spec says that in the supplementary file, this must be \0,
+ but it doesn't seem very important. */
+ *filename = make_unique_xstrdup ((const char *) contents);
+ int len = strlen (filename->get ());
+ contents += len + 1;
+ size -= len + 1;
+
+ if (size == 0)
+ return false;
+
+ unsigned int bytes_read;
+ *buildid_len = read_unsigned_leb128 (abfd, contents, &bytes_read);
+ contents += bytes_read;
+ size -= bytes_read;
+
+ if (size < *buildid_len)
+ return false;
+
+ if (*buildid_len != 0)
+ buildid->reset ((bfd_byte *) xmemdup (contents, *buildid_len,
+ *buildid_len));
+
+ return true;
+}
+
+/* Validate that ABFD matches the given BUILDID. If DWARF5 is true,
+ then this is done by examining the .debug_sup data. */
+
+static bool
+verify_id (bfd *abfd, size_t len, const bfd_byte *buildid, bool dwarf5)
+{
+ if (!bfd_check_format (abfd, bfd_object))
+ return false;
+
+ if (dwarf5)
+ {
+ size_t new_len;
+ gdb::unique_xmalloc_ptr<bfd_byte> new_id;
+ gdb::unique_xmalloc_ptr<char> ignore;
+
+ if (!get_debug_sup_info (abfd, &ignore, &new_len, &new_id))
+ return false;
+ return (len == new_len
+ && memcmp (buildid, new_id.get (), len) == 0);
+ }
+ else
+ return build_id_verify (abfd, len, buildid);
+}
+
+/* Find either the .debug_sup or .gnu_debugaltlink section and return
+ its contents. Returns true on success and sets out parameters, or
+ false if nothing is found. */
+
+static bool
+read_alt_info (bfd *abfd, gdb::unique_xmalloc_ptr<char> *filename,
+ size_t *buildid_len,
+ gdb::unique_xmalloc_ptr<bfd_byte> *buildid,
+ bool *dwarf5)
+{
+ if (get_debug_sup_info (abfd, filename, buildid_len, buildid))
+ {
+ *dwarf5 = true;
+ return true;
+ }
+
+ bfd_size_type buildid_len_arg;
+ bfd_set_error (bfd_error_no_error);
+ bfd_byte *buildid_out;
+ filename->reset (bfd_get_alt_debug_link_info (abfd, &buildid_len_arg,
+ &buildid_out));
+ if (*filename == nullptr)
+ {
+ if (bfd_get_error () == bfd_error_no_error)
+ return false;
+ error (_("could not read '.gnu_debugaltlink' section: %s"),
+ bfd_errmsg (bfd_get_error ()));
+ }
+
+ *buildid_len = buildid_len_arg;
+ buildid->reset (buildid_out);
+ *dwarf5 = false;
+ return true;
+}
+
/* Attempt to find a .dwz file (whose full path is represented by
FILENAME) in all of the specified debug file directories provided.
@@ -101,7 +221,7 @@ locate_dwz_sections (bfd *abfd, asection *sectp, dwz_file *dwz_file)
static gdb_bfd_ref_ptr
dwz_search_other_debugdirs (std::string &filename, bfd_byte *buildid,
- size_t buildid_len)
+ size_t buildid_len, bool dwarf5)
{
/* Let's assume that the path represented by FILENAME has the
"/.dwz/" subpath in it. This is what (most) GNU/Linux
@@ -169,7 +289,7 @@ dwz_search_other_debugdirs (std::string &filename, bfd_byte *buildid,
if (dwz_bfd == nullptr)
continue;
- if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+ if (!verify_id (dwz_bfd.get (), buildid_len, buildid, dwarf5))
{
dwz_bfd.reset (nullptr);
continue;
@@ -187,33 +307,20 @@ dwz_search_other_debugdirs (std::string &filename, bfd_byte *buildid,
struct dwz_file *
dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd, bool require)
{
- bfd_size_type buildid_len_arg;
- size_t buildid_len;
- bfd_byte *buildid;
-
if (per_bfd->dwz_file != NULL)
return per_bfd->dwz_file.get ();
- bfd_set_error (bfd_error_no_error);
- gdb::unique_xmalloc_ptr<char> data
- (bfd_get_alt_debug_link_info (per_bfd->obfd,
- &buildid_len_arg, &buildid));
- if (data == NULL)
+ size_t buildid_len;
+ gdb::unique_xmalloc_ptr<bfd_byte> buildid;
+ gdb::unique_xmalloc_ptr<char> data;
+ bool dwarf5;
+ if (!read_alt_info (per_bfd->obfd, &data, &buildid_len, &buildid, &dwarf5))
{
- if (bfd_get_error () == bfd_error_no_error)
- {
- if (!require)
- return nullptr;
- error (_("could not read '.gnu_debugaltlink' section"));
- }
- error (_("could not read '.gnu_debugaltlink' section: %s"),
- bfd_errmsg (bfd_get_error ()));
+ if (!require)
+ return nullptr;
+ error (_("could not read '.debug_sup' or '.gnu_debugaltlink' section"));
}
- gdb::unique_xmalloc_ptr<bfd_byte> buildid_holder (buildid);
-
- buildid_len = (size_t) buildid_len_arg;
-
std::string filename = data.get ();
if (!IS_ABSOLUTE_PATH (filename.c_str ()))
@@ -229,18 +336,22 @@ dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd, bool require)
gdb_bfd_ref_ptr dwz_bfd (gdb_bfd_open (filename.c_str (), gnutarget));
if (dwz_bfd != NULL)
{
- if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+ if (!verify_id (dwz_bfd.get (), buildid_len, buildid.get (), dwarf5))
dwz_bfd.reset (nullptr);
}
- if (dwz_bfd == NULL)
- dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid);
+ /* In DWARF 5, the filename in the main debug file is either
+ absolute, or relative to the debug file -- so we don't search the
+ system directories. */
+ if (dwz_bfd == NULL && !dwarf5)
+ dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid.get ());
if (dwz_bfd == nullptr)
{
/* If the user has provided us with different
debug file directories, we can try them in order. */
- dwz_bfd = dwz_search_other_debugdirs (filename, buildid, buildid_len);
+ dwz_bfd = dwz_search_other_debugdirs (filename, buildid.get (),
+ buildid_len, dwarf5);
}
if (dwz_bfd == nullptr)
@@ -248,7 +359,7 @@ dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd, bool require)
gdb::unique_xmalloc_ptr<char> alt_filename;
const char *origname = bfd_get_filename (per_bfd->obfd);
- scoped_fd fd (debuginfod_debuginfo_query (buildid,
+ scoped_fd fd (debuginfod_debuginfo_query (buildid.get (),
buildid_len,
origname,
&alt_filename));
@@ -261,13 +372,14 @@ dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd, bool require)
if (dwz_bfd == nullptr)
warning (_("File \"%s\" from debuginfod cannot be opened as bfd"),
alt_filename.get ());
- else if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+ else if (!verify_id (dwz_bfd.get (), buildid_len, buildid.get (),
+ dwarf5))
dwz_bfd.reset (nullptr);
}
}
if (dwz_bfd == NULL)
- error (_("could not find '.gnu_debugaltlink' file for %s"),
+ error (_("could not find supplementary DWARF file for %s"),
bfd_get_filename (per_bfd->obfd));
std::unique_ptr<struct dwz_file> result
diff --git a/gdb/dwarf2/macro.c b/gdb/dwarf2/macro.c
index 2ecebe6173c..b23ae611963 100644
--- a/gdb/dwarf2/macro.c
+++ b/gdb/dwarf2/macro.c
@@ -266,6 +266,7 @@ skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end,
case DW_FORM_sec_offset:
case DW_FORM_strp:
case DW_FORM_GNU_strp_alt:
+ case DW_FORM_strp_sup:
bytes += offset_size;
break;
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 31f34dc6047..32212401bde 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1080,10 +1080,12 @@ struct partial_die_info : public allocate_on_obstack
/* Flag set if fixup has been called on this die. */
unsigned int fixup_called : 1;
- /* Flag set if DW_TAG_imported_unit uses DW_FORM_GNU_ref_alt. */
+ /* Flag set if DW_TAG_imported_unit uses DW_FORM_GNU_ref_alt,
+ DW_FORM_ref_sup4, or DW_FORM_ref_sup8. */
unsigned int is_dwz : 1;
- /* Flag set if spec_offset uses DW_FORM_GNU_ref_alt. */
+ /* Flag set if spec_offset uses DW_FORM_GNU_ref_alt,
+ DW_FORM_ref_sup4, or DW_FORM_ref_sup8. */
unsigned int spec_is_dwz : 1;
unsigned int canonical_name : 1;
@@ -8811,11 +8813,13 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
case DW_FORM_data4:
case DW_FORM_ref4:
case DW_FORM_strx4:
+ case DW_FORM_ref_sup4:
info_ptr += 4;
break;
case DW_FORM_data8:
case DW_FORM_ref8:
case DW_FORM_ref_sig8:
+ case DW_FORM_ref_sup8:
info_ptr += 8;
break;
case DW_FORM_data16:
@@ -8828,6 +8832,7 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
case DW_FORM_sec_offset:
case DW_FORM_strp:
case DW_FORM_GNU_strp_alt:
+ case DW_FORM_strp_sup:
info_ptr += cu->header.offset_size;
break;
case DW_FORM_exprloc:
@@ -9985,7 +9990,7 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
if (attr != NULL)
{
sect_offset sect_off = attr->get_ref_die_offset ();
- bool is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
+ bool is_dwz = attr->form_is_alt () || cu->per_cu->is_dwz;
dwarf2_per_objfile *per_objfile = cu->per_objfile;
dwarf2_per_cu_data *per_cu
= dwarf2_find_containing_comp_unit (sect_off, is_dwz, per_objfile);
@@ -19541,8 +19546,7 @@ partial_die_info::read (const struct die_reader_specs *reader,
case DW_AT_extension:
has_specification = 1;
spec_offset = attr.get_ref_die_offset ();
- spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
- || cu->per_cu->is_dwz);
+ spec_is_dwz = attr.form_is_alt () || cu->per_cu->is_dwz;
break;
case DW_AT_sibling:
/* Ignore absolute siblings, they might point outside of
@@ -19601,8 +19605,7 @@ partial_die_info::read (const struct die_reader_specs *reader,
if (tag == DW_TAG_imported_unit)
{
d.sect_off = attr.get_ref_die_offset ();
- is_dwz = (attr.form == DW_FORM_GNU_ref_alt
- || cu->per_cu->is_dwz);
+ is_dwz = attr.form_is_alt () || cu->per_cu->is_dwz;
}
break;
@@ -20233,10 +20236,12 @@ read_attribute_value (const struct die_reader_specs *reader,
info_ptr += 2;
break;
case DW_FORM_data4:
+ case DW_FORM_ref_sup4:
attr->set_unsigned (read_4_bytes (abfd, info_ptr));
info_ptr += 4;
break;
case DW_FORM_data8:
+ case DW_FORM_ref_sup8:
attr->set_unsigned (read_8_bytes (abfd, info_ptr));
info_ptr += 8;
break;
@@ -20286,6 +20291,7 @@ read_attribute_value (const struct die_reader_specs *reader,
}
/* FALLTHROUGH */
case DW_FORM_GNU_strp_alt:
+ case DW_FORM_strp_sup:
{
dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd, true);
LONGEST str_offset = cu_header->read_offset (abfd, info_ptr,
@@ -22381,6 +22387,7 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type,
case DW_FORM_strx:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
+ case DW_FORM_strp_sup:
/* The string is already allocated on the objfile obstack, point
directly to it. */
*bytes = (const gdb_byte *) attr->as_string ();
@@ -22584,7 +22591,7 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
/* First see if we have it cached. */
- if (attr->form == DW_FORM_GNU_ref_alt)
+ if (attr->form_is_alt ())
{
struct dwarf2_per_cu_data *per_cu;
sect_offset sect_off = attr->get_ref_die_offset ();
@@ -23265,6 +23272,8 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
fputs_filtered (hex_string (die->attrs[i].as_unsigned ()), f);
break;
case DW_FORM_GNU_ref_alt:
+ case DW_FORM_ref_sup4:
+ case DW_FORM_ref_sup8:
fprintf_unfiltered (f, "alt ref address: ");
fputs_filtered (hex_string (die->attrs[i].as_unsigned ()), f);
break;
@@ -23298,6 +23307,7 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
case DW_FORM_strx:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
+ case DW_FORM_strp_sup:
fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
die->attrs[i].as_string ()
? die->attrs[i].as_string () : "",
@@ -23500,8 +23510,7 @@ follow_die_ref (struct die_info *src_die, const struct attribute *attr,
struct die_info *die;
die = follow_die_offset (sect_off,
- (attr->form == DW_FORM_GNU_ref_alt
- || cu->per_cu->is_dwz),
+ attr->form_is_alt () || cu->per_cu->is_dwz,
ref_cu);
if (!die)
error (_("Dwarf Error: Cannot find DIE at %s referenced from DIE "
@@ -23710,6 +23719,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
case DW_FORM_strx:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
+ case DW_FORM_strp_sup:
/* The string is already allocated on the objfile obstack, point
directly to it. */
{
diff --git a/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp b/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp
index 3b6315642fe..c78c25011f7 100644
--- a/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp
+++ b/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp
@@ -25,146 +25,161 @@ if {[is_remote host]} {
return 0
}
+foreach_with_prefix scenario {gnu dwarf5} {
+ # Lots of source files since we test a few cases and make new files
+ # for each.
+ # The tests are:
+ # ok - the main file refers to a dwz and the buildids match
+ # mismatch - the buildids do not match
+ # fallback - the buildids do not match but a match is found via buildid
+ standard_testfile main.c \
+ dwzbuildid-ok-base.S dwzbuildid-ok-sep.S \
+ dwzbuildid-mismatch-base.S dwzbuildid-mismatch-sep.S \
+ dwzbuildid-fallback-base.S dwzbuildid-fallback-sep.S \
+ dwzbuildid-fallback-ok.S
+
+ # Write some assembly that just has a .gnu_debugaltlink section.
+ proc write_just_debugaltlink {filename dwzname buildid} {
+ set asm_file [standard_output_file $filename]
+
+ Dwarf::assemble $asm_file {
+ upvar dwzname dwzname
+ upvar buildid buildid
+ global scenario
+
+ if {$scenario == "gnu"} {
+ gnu_debugaltlink $dwzname $buildid
+ } else {
+ debug_sup 0 $dwzname $buildid
+ }
-# Lots of source files since we test a few cases and make new files
-# for each.
-# The tests are:
-# ok - the main file refers to a dwz and the buildids match
-# mismatch - the buildids do not match
-# fallback - the buildids do not match but a match is found via buildid
-standard_testfile main.c \
- dwzbuildid-ok-base.S dwzbuildid-ok-sep.S \
- dwzbuildid-mismatch-base.S dwzbuildid-mismatch-sep.S \
- dwzbuildid-fallback-base.S dwzbuildid-fallback-sep.S \
- dwzbuildid-fallback-ok.S
-
-# Write some assembly that just has a .gnu_debugaltlink section.
-proc write_just_debugaltlink {filename dwzname buildid} {
- set asm_file [standard_output_file $filename]
-
- Dwarf::assemble $asm_file {
- upvar dwzname dwzname
- upvar buildid buildid
-
- gnu_debugaltlink $dwzname $buildid
-
- # Only the DWARF reader checks .gnu_debugaltlink, so make sure
- # there is a bit of DWARF in here.
- cu {} {
- compile_unit {{language @DW_LANG_C}} {
+ # Only the DWARF reader checks .gnu_debugaltlink, so make sure
+ # there is a bit of DWARF in here.
+ cu {} {
+ compile_unit {{language @DW_LANG_C}} {
+ }
}
}
}
-}
-# Write some DWARF that also sets the buildid.
-proc write_dwarf_file {filename buildid {value 99}} {
- set asm_file [standard_output_file $filename]
+ # Write some DWARF that also sets the buildid.
+ proc write_dwarf_file {filename buildid {value 99}} {
+ set asm_file [standard_output_file $filename]
- Dwarf::assemble $asm_file {
- declare_labels int_label int_label2
+ Dwarf::assemble $asm_file {
+ declare_labels int_label int_label2
- upvar buildid buildid
- upvar value value
+ global scenario
+ upvar buildid buildid
+ upvar value value
- build_id $buildid
-
- cu {} {
- compile_unit {{language @DW_LANG_C}} {
- int_label2: base_type {
- {name int}
- {byte_size 4 sdata}
- {encoding @DW_ATE_signed}
- }
+ if {$scenario == "gnu"} {
+ build_id $buildid
+ } else {
+ debug_sup 1 "" $buildid
+ }
- constant {
- {name the_int}
- {type :$int_label2}
- {const_value $value data1}
+ cu {} {
+ compile_unit {{language @DW_LANG_C}} {
+ int_label2: base_type {
+ {name int}
+ {byte_size 4 sdata}
+ {encoding @DW_ATE_signed}
+ }
+
+ constant {
+ {name the_int}
+ {type :$int_label2}
+ {const_value $value data1}
+ }
}
}
}
}
-}
-
-if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile}1.o \
- object {nodebug}] != "" } {
- return -1
-}
-# The values don't really matter, just whether they are equal.
-set ok_prefix 01
-set ok_suffix 0203040506
-set ok_suffix2 02030405ff
-set ok_buildid ${ok_prefix}${ok_suffix}
-set ok_buildid2 ${ok_prefix}${ok_suffix2}
-set bad_buildid ffffffffffff
-
-set debugdir [standard_output_file {}]
-set basedir $debugdir/.build-id
-file mkdir $basedir $basedir/$ok_prefix
-
-# Test where the separate debuginfo's buildid matches.
-write_just_debugaltlink $srcfile2 ${binfile}3.o $ok_buildid
-write_dwarf_file $srcfile3 $ok_buildid
-
-# Test where the separate debuginfo's buildid does not match.
-write_just_debugaltlink $srcfile4 ${binfile}5.o $ok_buildid
-write_dwarf_file $srcfile5 $bad_buildid
-
-# Test where the separate debuginfo's buildid does not match, but then
-# we find a match in the .build-id directory.
-write_just_debugaltlink $srcfile6 ${binfile}7.o $ok_buildid2
-# Use 77 as the value so that if we load the bad debuginfo, we will
-# see the wrong result.
-write_dwarf_file $srcfile7 $bad_buildid 77
-write_dwarf_file $srcfile8 $ok_buildid2
-
-# Compile everything.
-for {set i 2} {$i <= 8} {incr i} {
- if {[gdb_compile [standard_output_file [set srcfile$i]] \
- ${binfile}$i.o object nodebug] != ""} {
+ if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile}1.o \
+ object {nodebug}] != "" } {
return -1
}
-}
-# Copy a file into the .build-id place for the "fallback" test.
-file copy -force -- ${binfile}8.o $basedir/$ok_prefix/$ok_suffix2.debug
+ # The values don't really matter, just whether they are equal.
+ set ok_prefix 01
+ set ok_suffix 0203040506
+ set ok_suffix2 02030405ff
+ set ok_buildid ${ok_prefix}${ok_suffix}
+ set ok_buildid2 ${ok_prefix}${ok_suffix2}
+ set bad_buildid ffffffffffff
+
+ set debugdir [standard_output_file {}]
+ set basedir $debugdir/.build-id
+ file mkdir $basedir $basedir/$ok_prefix
+
+ # Test where the separate debuginfo's buildid matches.
+ write_just_debugaltlink $srcfile2 ${binfile}3.o $ok_buildid
+ write_dwarf_file $srcfile3 $ok_buildid
+
+ # Test where the separate debuginfo's buildid does not match.
+ write_just_debugaltlink $srcfile4 ${binfile}5.o $ok_buildid
+ write_dwarf_file $srcfile5 $bad_buildid
+
+ # Test where the separate debuginfo's buildid does not match, but then
+ # we find a match in the .build-id directory.
+ write_just_debugaltlink $srcfile6 ${binfile}7.o $ok_buildid2
+ # Use 77 as the value so that if we load the bad debuginfo, we will
+ # see the wrong result.
+ write_dwarf_file $srcfile7 $bad_buildid 77
+ write_dwarf_file $srcfile8 $ok_buildid2
+
+ # Compile everything.
+ for {set i 2} {$i <= 8} {incr i} {
+ if {[gdb_compile [standard_output_file [set srcfile$i]] \
+ ${binfile}$i.o object nodebug] != ""} {
+ return -1
+ }
+ }
-# Link the executables.
-if {[gdb_compile [list ${binfile}1.o ${binfile}2.o] ${binfile}-ok \
- executable {}] != ""} {
- return -1
-}
+ # Copy a file into the .build-id place for the "fallback" test.
+ file copy -force -- ${binfile}8.o $basedir/$ok_prefix/$ok_suffix2.debug
-if {[gdb_compile [list ${binfile}1.o ${binfile}4.o] ${binfile}-mismatch \
- executable {quiet}] != ""} {
- return -1
-}
+ # Link the executables.
+ if {[gdb_compile [list ${binfile}1.o ${binfile}2.o] ${binfile}-ok \
+ executable {}] != ""} {
+ return -1
+ }
-if {[gdb_compile [list ${binfile}1.o ${binfile}6.o] ${binfile}-fallback \
- executable {}] != ""} {
- return -1
-}
+ if {[gdb_compile [list ${binfile}1.o ${binfile}4.o] ${binfile}-mismatch \
+ executable {quiet}] != ""} {
+ return -1
+ }
+ if {[gdb_compile [list ${binfile}1.o ${binfile}6.o] ${binfile}-fallback \
+ executable {}] != ""} {
+ return -1
+ }
+
+ set tests {ok mismatch}
+ if {$scenario == "gnu"} {
+ lappend tests fallback
+ }
-foreach testname {ok mismatch fallback} {
- with_test_prefix $testname {
- gdb_exit
- gdb_start
- gdb_reinitialize_dir $srcdir/$subdir
+ foreach testname $tests {
+ with_test_prefix $testname {
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
- gdb_test_no_output "set debug-file-directory $debugdir" \
- "set debug-file-directory"
+ gdb_test_no_output "set debug-file-directory $debugdir" \
+ "set debug-file-directory"
- gdb_load ${binfile}-${testname}
+ gdb_load ${binfile}-${testname}
- if {[runto_main]} {
- if {$testname == "mismatch"} {
- gdb_test "print the_int" \
- "(No symbol table is loaded|No symbol \"the_int\" in current context).*"
- } else {
- gdb_test "print the_int" " = 99"
+ if {[runto_main]} {
+ if {$testname == "mismatch"} {
+ gdb_test "print the_int" \
+ "(No symbol table is loaded|No symbol \"the_int\" in current context).*"
+ } else {
+ gdb_test "print the_int" " = 99"
+ }
}
}
}
diff --git a/gdb/testsuite/gdb.dwarf2/dwznolink.exp b/gdb/testsuite/gdb.dwarf2/dwznolink.exp
index 98976d7e59c..8c3a0106caa 100644
--- a/gdb/testsuite/gdb.dwarf2/dwznolink.exp
+++ b/gdb/testsuite/gdb.dwarf2/dwznolink.exp
@@ -56,5 +56,5 @@ gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_test "file -readnow $binfile" \
- "could not read '.gnu_debugaltlink' section" \
+ "could not read '.debug_sup' or '.gnu_debugaltlink' section" \
"file $testfile"
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index f8fbd381810..3b310abd952 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -1992,6 +1992,24 @@ namespace eval Dwarf {
}
}
+ # Emit a .debug_sup section with the given file name and build-id.
+ # The buildid should be represented as a hexadecimal string, like
+ # "ffeeddcc".
+ proc debug_sup {is_sup filename buildid} {
+ _defer_output .debug_sup {
+ # The version.
+ _op .2byte 0x5
+ # Supplementary marker.
+ _op .byte $is_sup
+ _op .ascii [_quote $filename]
+ set len [expr {[string length $buildid] / 2}]
+ _op .uleb128 $len
+ foreach {a b} [split $buildid {}] {
+ _op .byte 0x$a$b
+ }
+ }
+ }
+
proc _note {type name hexdata} {
set namelen [expr [string length $name] + 1]
--
2.26.2
More information about the Gdb-patches
mailing list