From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id WHo5IRTYtV/5NAAAWB0awg (envelope-from ) for ; Wed, 18 Nov 2020 21:27:32 -0500 Received: by simark.ca (Postfix, from userid 112) id 830D91F08B; Wed, 18 Nov 2020 21:27:32 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-1.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,MAILING_LIST_MULTI,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.2 Received: from sourceware.org (server2.sourceware.org [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 28E8D1E552 for ; Wed, 18 Nov 2020 21:27:32 -0500 (EST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3B6823857C61; Thu, 19 Nov 2020 02:27:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3B6823857C61 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1605752851; bh=aiPsF6Gfd1raA/CiWkuWLC+3ZhQa9cwajzf1fkUwCkc=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=Rbp5XF5nI4w03BD6p37oKNfB+kDjVjAHGvBjHxcmXdItMd/mYIhrIz4EWuyBXZcCw ZV9cjaQg6LCYDxYcgFYZ1/rYRna3A9tZCf1fq59cnGJI+J9+OUbs1AkMuJSZynpBFu vwpPj0uL9oJ1QI0EPfouQPxK+PMnRbXbu9Rl2Z9I= Received: from mail.sergiodj.net (mail.sergiodj.net [IPv6:2607:5300:60:3666::3]) by sourceware.org (Postfix) with ESMTPS id B2E653857C61 for ; Thu, 19 Nov 2020 02:27:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org B2E653857C61 Received: from localhost (bras-base-toroon1016w-grc-37-76-65-22-220.dsl.bell.ca [76.65.22.220]) by mail.sergiodj.net (Postfix) with ESMTPSA id E5DB4A04EF; Wed, 18 Nov 2020 21:27:09 -0500 (EST) To: gdb-patches@sourceware.org Subject: [PATCH v2] Search for DWZ files in debug-file-directories as well Date: Wed, 18 Nov 2020 21:27:08 -0500 Message-Id: <20201119022708.3627287-1-sergiodj@sergiodj.net> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201114234842.2334396-1-sergiodj@sergiodj.net> References: <20201114234842.2334396-1-sergiodj@sergiodj.net> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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: , From: Sergio Durigan Junior via Gdb-patches Reply-To: Sergio Durigan Junior Cc: Simon Marchi , Mark Wielaard , Sergio Durigan Junior Errors-To: gdb-patches-bounces@sourceware.org Sender: "Gdb-patches" Changes from v1: - Addressed Simon's comments (new comment explaining how we try to match for the current debug-file-directory; properly use .erase/.insert methods -- keeping in mind that they modify the string in-place). When Debian (and Ubuntu) builds its binaries, it (still) doesn't use dwz's "--relative" option. This causes their debuginfo files to carry a .gnu_debugaltlink section containing a full pathname to the DWZ alt debug file, like this: $ readelf -wk /usr/bin/cat Contents of the .gnu_debugaltlink section: Separate debug info file: /usr/lib/debug/.dwz/x86_64-linux-gnu/coreutils.debug Build-ID (0x14 bytes): ee 76 5d 71 97 37 ce 46 99 44 32 bb e8 a9 1a ef 99 96 88 db Contents of the .gnu_debuglink section: Separate debug info file: 06d3bee37b8c7e67b31cb2689cb351102ae73b.debug CRC value: 0x53267655 This usually works OK, because most of the debuginfo files installed via apt will be present in /usr/lib/debug anyway. However, imagine the following scenario: - You are using /usr/bin/cat, it crashes on you and generates a corefile. - You don't want/need to "apt install" the debuginfo file for coreutils from the repositories. Instead, you already have the debuginfo files in a separate directory (e.g., $HOME/dbgsym). - You start GDB and "set debug-file-directory $HOME/dbgsym". You then get the following message: $ gdb -ex 'set debug-file-directory ./dbgsym/usr/lib/debug' -ex 'file /bin/cat' -ex 'core-file ./cat.core' GNU gdb (Ubuntu 10.1-0ubuntu1) 10.1 ... Reading symbols from /bin/cat... Reading symbols from /home/sergio/gdb/dbgsym/usr/lib/debug/.build-id/bc/06d3bee37b8c7e67b31cb2689cb351102ae73b.debug... could not find '.gnu_debugaltlink' file for /home/sergio/gdb/dbgsym/usr/lib/debug/.build-id/bc/06d3bee37b8c7e67b31cb2689cb351102ae73b.debug This error happens because GDB is trying to locate the build-id link (inside /home/sergio/gdb/dbgsym/usr/lib/debug/.build-id) for the DWZ alt debug file, which doesn't exist. Arguably, this is a problem with how dh_dwz works in Debian, and it's something I'm also planning to tackle. But, back at the problem at hand. Besides not being able to find the build-id link in the directory mentioned above, GDB also tried to open the DWZ alt file using its filename. The problem here is that, since we don't have the distro's debuginfo installed, it can't find anything under /usr/lib/debug that satisfies it. It occurred to me that a good way to workaround this problem is to actually try to locate the DWZ alt debug file inside the debug-file-directories (that were likely provided by the user). So this is what the proposed patch does. The idea here is simple: get the filename extracted from the .gnu_debugaltlink section, and manipulate it in order to replace the initial part of the path (everything before "/.dwz/") by whatever debug-file-directories the user might have provided. I talked with Mark Wielaard and he agrees this is a sensible approach. In fact, apparently this is something that eu-readelf also does. I regtested this code, and no regressions were found. 2020-11-14 Sergio Durigan Junior * dwarf2/read.c (dwarf2_get_dwz_file): Convert 'filename' to a std::string. Implement ability to search for DWZ files in the debug-file-directories provided by the user as well. --- gdb/dwarf2/read.c | 73 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 3c59826291..c462b9bb2c 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -2190,7 +2190,7 @@ locate_dwz_sections (bfd *abfd, asection *sectp, dwz_file *dwz_file) struct dwz_file * dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd) { - const char *filename; + std::string filename; bfd_size_type buildid_len_arg; size_t buildid_len; bfd_byte *buildid; @@ -2216,19 +2216,17 @@ dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd) filename = data.get (); - std::string abs_storage; - if (!IS_ABSOLUTE_PATH (filename)) + if (!IS_ABSOLUTE_PATH (filename.c_str ())) { gdb::unique_xmalloc_ptr abs = gdb_realpath (bfd_get_filename (per_bfd->obfd)); - abs_storage = ldirname (abs.get ()) + SLASH_STRING + filename; - filename = abs_storage.c_str (); + filename = ldirname (abs.get ()) + SLASH_STRING + filename; } /* First try the file name given in the section. If that doesn't work, try to use the build-id instead. */ - gdb_bfd_ref_ptr dwz_bfd (gdb_bfd_open (filename, gnutarget)); + 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)) @@ -2238,6 +2236,69 @@ dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd) if (dwz_bfd == NULL) dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid); + if (dwz_bfd == nullptr) + { + /* If the user has provided us with different + debug-file-directories, we can try them in order. */ + size_t dwz_pos = filename.find ("/.dwz/"); + + if (dwz_pos != std::string::npos) + { + std::vector> debugdir_vec + = dirnames_to_char_ptr_vec (debug_file_directory); + + for (const gdb::unique_xmalloc_ptr &debugdir : debugdir_vec) + { + /* The idea is to iterate over the + debug-file-directories provided by the user and + replace the hard-coded path in the "filename" by each + debug-file-directory. + + For example, suppose that filename is: + + /usr/lib/debug/.dwz/foo.dwz + + And suppose that we have "$HOME/bar" as the + debug-file-directory. We would then adjust filename + to look like: + + $HOME/bar/.dwz/foo.dwz + + which would hopefully allow us to find the alt debug + file. */ + std::string ddir = debugdir.get (); + + /* Check whether the beginning of FILENAME is DDIR. If + it is, then we are dealing with a file which we + already attempted to open before, so we just skip it + and continue processing the reamining + debug-file-directories. */ + if (filename.size () > ddir.size () + && filename.compare (0, ddir.size (), ddir) == 0) + continue; + + /* Replace FILENAME's default debug-file-directory with + DDIR. */ + std::string new_filename = filename; + new_filename.erase (0, dwz_pos); + new_filename.insert (0, ddir); + + dwz_bfd = gdb_bfd_open (new_filename.c_str (), gnutarget); + + if (dwz_bfd != nullptr) + { + if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid)) + { + dwz_bfd.reset (nullptr); + continue; + } + /* Found it. */ + break; + } + } + } + } + if (dwz_bfd == nullptr) { gdb::unique_xmalloc_ptr alt_filename; -- 2.28.0