[gdb/symtab] Fix Dwarf Error: cannot find DIE
authorTom de Vries <tdevries@suse.de>
Thu, 27 May 2021 13:22:38 +0000 (15:22 +0200)
committerTom de Vries <tdevries@suse.de>
Thu, 27 May 2021 13:22:38 +0000 (15:22 +0200)
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.

gdb/ChangeLog:

2021-05-27  Tom de Vries  <tdevries@suse.de>

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, find_partial_die): Update.
* 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/ChangeLog
gdb/dwarf2/cu.c
gdb/dwarf2/cu.h
gdb/dwarf2/read.c
gdb/dwarf2/read.h

index 39f444e1f78ebf289534aee5a445f5b0c189e441..3154a8d0ed19c080da0eaace83c483b6c3173210 100644 (file)
@@ -1,3 +1,13 @@
+2021-05-27  Tom de Vries  <tdevries@suse.de>
+
+       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, find_partial_die): Update.
+       * 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.
+
 2021-05-26  Simon Marchi  <simon.marchi@efficios.com>
 
        * regcache.c (reg_buffer::reg_buffer): Default-initialize
index 2451df4f5b63f1970b2e8a97bb36f6cc6ddfbcf6..1031ed3aa00d0894a332c6cbe1d9b994c077bd29 100644 (file)
@@ -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)
 {
 }
 
index ff56ec5527b456659466c4781cbf24289c793b7f..b4a5b08d5a611bc63e55195a154a59d663b8f72c 100644 (file)
@@ -264,6 +264,12 @@ public:
 
   bool processing_has_namespace_info : 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.  */
+  bool load_all_dies : 1;
+
   struct partial_die_info *find_partial_die (sect_offset sect_off);
 
   /* If this CU was inherited by another CU (via specification,
index d3b5b89c1c3282a967e27d46d9b6b4259aefd5f6..3f496347cce22ae3160585235d8ae27928b31a0b 100644 (file)
@@ -18817,7 +18817,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
@@ -19385,9 +19385,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
index 6af1f44bd47c74f57d28c7dd04edb124bd1c9d91..0bb3da5a34ab4b719305668411efeb2e0ef9a53f 100644 (file)
@@ -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.  */