From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 5IYzFoDDrmDWKQAAWB0awg (envelope-from ) for ; Wed, 26 May 2021 17:54:08 -0400 Received: by simark.ca (Postfix, from userid 112) id 36F5C1F11C; Wed, 26 May 2021 17:54:08 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-0.5 required=5.0 tests=DKIM_SIGNED, MAILING_LIST_MULTI,RDNS_DYNAMIC,T_DKIM_INVALID,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (ip-8-43-85-97.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 CA63A1E813 for ; Wed, 26 May 2021 17:54:06 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3E0CB383F404; Wed, 26 May 2021 21:54:06 +0000 (GMT) Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by sourceware.org (Postfix) with ESMTPS id 74A32386F422 for ; Wed, 26 May 2021 21:54:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 74A32386F422 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tdevries@suse.de Received: from imap.suse.de (imap-alt.suse-dmz.suse.de [192.168.254.47]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id BE27C218DD; Wed, 26 May 2021 21:54:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1622066041; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=H/dU5svJ4jvEAWlyJuvBdr2lfpYSA71xUMSyzVjTKcc=; b=ES4o2VZoBw6qbPHwOTUGooeQnLTXhp98G34roJL4uzNtqVY5fa0Diljt+mGEuNeAMU2UqR gJqyeHC9rfg/5M2pNvnybPliCP7ECwDeR1voXJDuXjhkYlX1ibeYXyLKBgkQc3v7oPPd+4 ZYkFvSRmt92d3gEkjLHCos+0ym28qtM= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1622066041; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=H/dU5svJ4jvEAWlyJuvBdr2lfpYSA71xUMSyzVjTKcc=; b=3Zx4Q8D/dmeXu6g6MM6nYMbYFAIGKYmDjQZu6VZyDaigJGn52v0tYqXzwhq3da6n9LFFHg I/a3kyVXFCd22fCQ== Received: from director2.suse.de (director2.suse-dmz.suse.de [192.168.254.72]) by imap.suse.de (Postfix) with ESMTPSA id 9703E11A98; Wed, 26 May 2021 21:54:01 +0000 (UTC) Date: Wed, 26 May 2021 23:54:00 +0200 From: Tom de Vries To: gdb-patches@sourceware.org Subject: [PATCH][gdb/symtab] Fix Dwarf Error: cannot find DIE Message-ID: <20210526215358.GA19956@delia> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) 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" Hi, When loading the debug info package libLLVM.so.10-10.0.1-lp152.30.4.x86_64.debug from openSUSE Leap 15.2, we run into a dwarf error: ... $ gdb -q -batch libLLVM.so.10-10.0.1-lp152.30.4.x86_64.debug Dwarf Error: Cannot not find DIE at 0x18a936e7 \ [from module libLLVM.so.10-10.0.1-lp152.30.4.x86_64.debug] ... The DIE @ 0x18a936e7 does in fact exist, and is part of a CU @ 0x18a23e52. No error message is printed when using -readnow. What happens is the following: - a dwarf2_per_cu_data P is created for the CU. - a dwarf2_cu A is created for the same CU. - another dwarf2_cu B is created for the same CU. - the dwarf2_cu B is set in per_objfile->m_dwarf2_cus, such that per_objfile->get_cu (P) returns B. - P->load_all_dies is set to 1. - all dies are read into the A->partial_dies htab - dwarf2_cu A is destroyed. - we try to find the partial_die for the DIE @ 0x18a936e7 in B->partial_dies. We can't find it, but do not try to load all dies, because P->load_all_dies is already set to 1. - an error message is generated. The question is why we're creating dwarf2_cu A and B for the same CU. The dwarf2_cu A is created here: ... (gdb) bt #0 dwarf2_cu::dwarf2_cu (this=0x79a9660, per_cu=0x23c0b30, per_objfile=0x1ad01b0) at dwarf2/cu.c:38 #1 0x0000000000675799 in cutu_reader::cutu_reader (this=0x7fffffffd040, this_cu=0x23c0b30, per_objfile=0x1ad01b0, abbrev_table=0x0, existing_cu=0x0, skip_partial=false) at dwarf2/read.c:6487 #2 0x0000000000676eb3 in process_psymtab_comp_unit (this_cu=0x23c0b30, per_objfile=0x1ad01b0, want_partial_unit=false, pretend_language=language_minimal) at dwarf2/read.c:7028 ... And the dwarf2_cu B is created here: ... (gdb) bt #0 dwarf2_cu::dwarf2_cu (this=0x885e8c0, per_cu=0x23c0b30, per_objfile=0x1ad01b0) at dwarf2/cu.c:38 #1 0x0000000000675799 in cutu_reader::cutu_reader (this=0x7fffffffcc50, this_cu=0x23c0b30, per_objfile=0x1ad01b0, abbrev_table=0x0, existing_cu=0x0, skip_partial=false) at dwarf2/read.c:6487 #2 0x0000000000678118 in load_partial_comp_unit (this_cu=0x23c0b30, per_objfile=0x1ad01b0, existing_cu=0x0) at dwarf2/read.c:7436 #3 0x000000000069721d in find_partial_die (sect_off=(unknown: 0x18a55054), offset_in_dwz=0, cu=0x0) at dwarf2/read.c:19391 #4 0x000000000069755b in partial_die_info::fixup (this=0x9096900, cu=0xa6a85f0) at dwarf2/read.c:19512 #5 0x0000000000697586 in partial_die_info::fixup (this=0x8629bb0, cu=0xa6a85f0) at dwarf2/read.c:19516 #6 0x00000000006787b1 in scan_partial_symbols (first_die=0x8629b40, lowpc=0x7fffffffcf58, highpc=0x7fffffffcf50, set_addrmap=0, cu=0x79a9660) at dwarf2/read.c:7563 #7 0x0000000000678878 in scan_partial_symbols (first_die=0x796ebf0, lowpc=0x7fffffffcf58, highpc=0x7fffffffcf50, set_addrmap=0, cu=0x79a9660) at dwarf2/read.c:7580 #8 0x0000000000676b82 in process_psymtab_comp_unit_reader (reader=0x7fffffffd040, info_ptr=0x7fffc1b3f29b, comp_unit_die=0x6ea90f0, pretend_language=language_minimal) at dwarf2/read.c:6954 #9 0x0000000000676ffd in process_psymtab_comp_unit (this_cu=0x23c0b30, per_objfile=0x1ad01b0, want_partial_unit=false, pretend_language=language_minimal) at dwarf2/read.c:7057 ... So in frame #9, a cutu_reader is created with dwarf2_cu A. Then a fixup takes us to the following CU @ 0x18aa33d6, in frame #5. And a similar fixup in frame #4 takes us back to CU @ 0x18a23e52. At that point, there's no information available that we're already trying to read that CU, and we end up creating another cutu_reader with dwarf2_cu B. It seems that there are two related problems: - creating two dwarf2_cu's is not optimal - the unoptimal case is not handled correctly This patch addresses the last problem, by moving the load_all_dies flag from dwarf2_per_cu_data to dwarf2_cu, such that it is paired with the partial_dies field, which ensures that the two can be kept in sync. Tested on x86_64-linux. Any comments? Thanks, - Tom [gdb/symtab] Fix Dwarf Error: cannot find DIE gdb/ChangeLog: 2021-05-26 Tom de Vries PR symtab/27898 * dwarf2/cu.c (dwarf2_cu::dwarf2_cu): Add load_all_dies init. * dwarf2/cu.h (dwarf2_cu): Add load_all_dies field. * dwarf2/read.c (load_partial_dies): Update. (find_partial_die): * dwarf2/read.h (dwarf2_per_cu_data::dwarf2_per_cu_data): Remove load_all_dies init. (dwarf2_per_cu_data): Remove load_all_dies field. --- gdb/dwarf2/cu.c | 3 ++- gdb/dwarf2/cu.h | 6 ++++++ gdb/dwarf2/read.c | 6 +++--- gdb/dwarf2/read.h | 7 ------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/gdb/dwarf2/cu.c b/gdb/dwarf2/cu.c index 2451df4f5b6..1031ed3aa00 100644 --- a/gdb/dwarf2/cu.c +++ b/gdb/dwarf2/cu.c @@ -35,7 +35,8 @@ dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu, producer_is_icc (false), producer_is_icc_lt_14 (false), producer_is_codewarrior (false), - processing_has_namespace_info (false) + processing_has_namespace_info (false), + load_all_dies (false) { } diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h index ff56ec5527b..65a4cf8babf 100644 --- a/gdb/dwarf2/cu.h +++ b/gdb/dwarf2/cu.h @@ -283,6 +283,12 @@ struct dwarf2_cu return nullptr; } + + /* This flag will be set when reading partial DIEs if we need to load + absolutely all DIEs for this compilation unit, instead of just the ones + we think are interesting. It gets set if we look for a DIE in the + hash table and don't find it. */ + unsigned int load_all_dies : 1; }; #endif /* GDB_DWARF2_CU_H */ diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 2cd8a95658a..c23a8b99360 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -18831,7 +18831,7 @@ load_partial_dies (const struct die_reader_specs *reader, last_die = NULL; gdb_assert (cu->per_cu != NULL); - if (cu->per_cu->load_all_dies) + if (cu->load_all_dies) load_all = 1; cu->partial_dies @@ -19399,9 +19399,9 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu) /* If we didn't find it, and not all dies have been loaded, load them all and try again. */ - if (pd == NULL && cu->per_cu->load_all_dies == 0) + if (pd == NULL && cu->load_all_dies == 0) { - cu->per_cu->load_all_dies = 1; + cu->load_all_dies = 1; /* This is nasty. When we reread the DIEs, somewhere up the call chain THIS_CU->cu may already be in use. So we can't just free it and diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index 6af1f44bd47..0bb3da5a34a 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -421,7 +421,6 @@ struct dwarf2_per_cu_data { dwarf2_per_cu_data () : queued (false), - load_all_dies (false), is_debug_types (false), is_dwz (false), reading_dwo_directly (false), @@ -447,12 +446,6 @@ struct dwarf2_per_cu_data any of the current compilation units are processed. */ unsigned int queued : 1; - /* This flag will be set when reading partial DIEs if we need to load - absolutely all DIEs for this compilation unit, instead of just the ones - we think are interesting. It gets set if we look for a DIE in the - hash table and don't find it. */ - unsigned int load_all_dies : 1; - /* Non-zero if this CU is from .debug_types. Struct dwarf2_per_cu_data is contained in struct signatured_type iff this is non-zero. */