From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 687fMz7qMmDpSwAAWB0awg (envelope-from ) for ; Sun, 21 Feb 2021 18:18:22 -0500 Received: by simark.ca (Postfix, from userid 112) id C74061EF78; Sun, 21 Feb 2021 18:18:22 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=0.4 required=5.0 tests=DKIM_SIGNED,MAILING_LIST_MULTI, RDNS_NONE,T_DKIM_INVALID,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.2 Received: from sourceware.org (unknown [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id AB63F1E54D for ; Sun, 21 Feb 2021 18:18:21 -0500 (EST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EE80638618F6; Sun, 21 Feb 2021 23:18:20 +0000 (GMT) Received: from gateway21.websitewelcome.com (gateway21.websitewelcome.com [192.185.45.147]) by sourceware.org (Postfix) with ESMTPS id 109E83854830 for ; Sun, 21 Feb 2021 23:18:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 109E83854830 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=tromey.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=tom@tromey.com Received: from cm13.websitewelcome.com (cm13.websitewelcome.com [100.42.49.6]) by gateway21.websitewelcome.com (Postfix) with ESMTP id 6142C400D2822 for ; Sun, 21 Feb 2021 17:18:15 -0600 (CST) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id DxzTlan2ioE4DDxzTlWxZ6; Sun, 21 Feb 2021 17:18:15 -0600 X-Authority-Reason: nr=8 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=Content-Transfer-Encoding:MIME-Version:Message-Id:Date:Subject: Cc:To:From:Sender:Reply-To:Content-Type:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=HvQVyEKePq+Nb8wPLpRKvLSH62yEUY2RRNkv7voq+mE=; b=V/RWfMaxC7hHwoMk9yMt8tFojs kM06N3tpwzhsXyasznKV2cHolYEe50sQwSdEO4rt+HmIU+hHzQ28+/RkpPLAtaOFywSPLIgIiLKgm 2eP8yL4EtmFX2fWUxkNVDXh84; Received: from 97-122-70-152.hlrn.qwest.net ([97.122.70.152]:37210 helo=localhost.localdomain) by box5379.bluehost.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1lDxzT-00410g-23; Sun, 21 Feb 2021 16:18:15 -0700 From: Tom Tromey To: gdb-patches@sourceware.org Subject: [PATCH] Handle DWARF 5 separate debug sections Date: Sun, 21 Feb 2021 16:18:10 -0700 Message-Id: <20210221231810.1062175-1-tom@tromey.com> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - box5379.bluehost.com X-AntiAbuse: Original Domain - sourceware.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - tromey.com X-BWhitelist: no X-Source-IP: 97.122.70.152 X-Source-L: No X-Exim-ID: 1lDxzT-00410g-23 X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: 97-122-70-152.hlrn.qwest.net (localhost.localdomain) [97.122.70.152]:37210 X-Source-Auth: tom+tromey.com X-Email-Count: 1 X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tom Tromey Errors-To: gdb-patches-bounces@sourceware.org Sender: "Gdb-patches" 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 * dwarf2/read.c (struct partial_die_info) : 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 * 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 *filename, + size_t *buildid_len, + gdb::unique_xmalloc_ptr *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 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 new_id; + gdb::unique_xmalloc_ptr 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 *filename, + size_t *buildid_len, + gdb::unique_xmalloc_ptr *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 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 buildid; + gdb::unique_xmalloc_ptr 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 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 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 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