[gdb/symtab] Handle DW_AT_ranges with DW_FORM_sec_off in partial DIE
[deliverable/binutils-gdb.git] / gdb / dwarf2 / read.c
index 9032186ef89ea0f42b80b454f7e3e5c24eef2e75..0a00f89cf6dec93d968b1f3569c4977af05321f9 100644 (file)
@@ -9179,7 +9179,12 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu,
 
   /* If it's already on the queue, we have nothing to do.  */
   if (per_cu->queued)
-    return 0;
+    {
+      /* Verify the invariant that if a CU is queued for expansion, its DIEs are
+        loaded.  */
+      gdb_assert (per_objfile->get_cu (per_cu) != nullptr);
+      return 0;
+    }
 
   /* If the compilation unit is already loaded, just mark it as
      used.  */
@@ -18223,6 +18228,46 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
   return this_type;
 }
 
+/* Helper for get_dwarf2_rational_constant that computes the value of
+   a given gmp_mpz given an attribute.  */
+
+static void
+get_mpz (struct dwarf2_cu *cu, gdb_mpz *value, struct attribute *attr)
+{
+  /* GCC will sometimes emit a 16-byte constant value as a DWARF
+     location expression that pushes an implicit value.  */
+  if (attr->form == DW_FORM_exprloc)
+    {
+      dwarf_block *blk = attr->as_block ();
+      if (blk->size > 0 && blk->data[0] == DW_OP_implicit_value)
+       {
+         uint64_t len;
+         const gdb_byte *ptr = safe_read_uleb128 (blk->data + 1,
+                                                  blk->data + blk->size,
+                                                  &len);
+         if (ptr - blk->data + len <= blk->size)
+           {
+             mpz_import (value->val, len,
+                         bfd_big_endian (cu->per_objfile->objfile->obfd) ? 1 : -1,
+                         1, 0, 0, ptr);
+             return;
+           }
+       }
+
+      /* On failure set it to 1.  */
+      *value = gdb_mpz (1);
+    }
+  else if (attr->form_is_block ())
+    {
+      dwarf_block *blk = attr->as_block ();
+      mpz_import (value->val, blk->size,
+                 bfd_big_endian (cu->per_objfile->objfile->obfd) ? 1 : -1,
+                 1, 0, 0, blk->data);
+    }
+  else
+    *value = gdb_mpz (attr->constant_value (1));
+}
+
 /* Assuming DIE is a rational DW_TAG_constant, read the DIE's
    numerator and denominator into NUMERATOR and DENOMINATOR (resp).
 
@@ -18249,25 +18294,8 @@ get_dwarf2_rational_constant (struct die_info *die, struct dwarf2_cu *cu,
   if (num_attr == nullptr || denom_attr == nullptr)
     return;
 
-  if (num_attr->form_is_block ())
-    {
-      dwarf_block *blk = num_attr->as_block ();
-      mpz_import (numerator->val, blk->size,
-                 bfd_big_endian (cu->per_objfile->objfile->obfd) ? 1 : -1,
-                 1, 0, 0, blk->data);
-    }
-  else
-    *numerator = gdb_mpz (num_attr->constant_value (1));
-
-  if (denom_attr->form_is_block ())
-    {
-      dwarf_block *blk = denom_attr->as_block ();
-      mpz_import (denominator->val, blk->size,
-                 bfd_big_endian (cu->per_objfile->objfile->obfd) ? 1 : -1,
-                 1, 0, 0, blk->data);
-    }
-  else
-    *denominator = gdb_mpz (denom_attr->constant_value (1));
+  get_mpz (cu, numerator, num_attr);
+  get_mpz (cu, denominator, denom_attr);
 }
 
 /* Same as get_dwarf2_rational_constant, but extracting an unsigned
@@ -19805,7 +19833,7 @@ partial_die_info::read (const struct die_reader_specs *reader,
            /* It would be nice to reuse dwarf2_get_pc_bounds here,
               but that requires a full DIE, so instead we just
               reimplement it.  */
-           unsigned int ranges_offset = (attr.constant_value (0)
+           unsigned int ranges_offset = (attr.as_unsigned ()
                                          + (need_ranges_base
                                             ? cu->ranges_base
                                             : 0));
@@ -23574,6 +23602,12 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
 
   target_cu = cu;
 
+  dwarf_read_debug_printf_v ("source CU offset: %s, target offset: %s, "
+                            "source CU contains target offset: %d",
+                            sect_offset_str (cu->per_cu->sect_off),
+                            sect_offset_str (sect_off),
+                            cu->header.offset_in_cu_p (sect_off));
+
   if (cu->per_cu->is_debug_types)
     {
       /* .debug_types CUs cannot reference anything outside their CU.
@@ -23590,6 +23624,11 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
       per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
                                                 per_objfile);
 
+      dwarf_read_debug_printf_v ("target CU offset: %s, "
+                                "target CU DIEs loaded: %d",
+                                sect_offset_str (per_cu->sect_off),
+                                per_objfile->get_cu (per_cu) != nullptr);
+
       /* If necessary, add it to the queue and load its DIEs.  */
       if (maybe_queue_comp_unit (cu, per_cu, per_objfile, cu->language))
        load_full_comp_unit (per_cu, per_objfile, per_objfile->get_cu (per_cu),
@@ -24970,6 +25009,8 @@ dwarf2_per_objfile::set_cu (dwarf2_per_cu_data *per_cu, dwarf2_cu *cu)
 void
 dwarf2_per_objfile::age_comp_units ()
 {
+  dwarf_read_debug_printf_v ("running");
+
   /* Start by clearing all marks.  */
   for (auto pair : m_dwarf2_cus)
     pair.second->mark = false;
@@ -24992,6 +25033,8 @@ dwarf2_per_objfile::age_comp_units ()
 
       if (!cu->mark)
        {
+         dwarf_read_debug_printf_v ("deleting old CU %s",
+                                    sect_offset_str (cu->per_cu->sect_off));
          delete cu;
          it = m_dwarf2_cus.erase (it);
        }
This page took 0.030659 seconds and 4 git commands to generate.