[gdb/symtab] Handle DW_AT_ranges with DW_FORM_sec_off in partial DIE
[deliverable/binutils-gdb.git] / gdb / dwarf2 / read.c
index 601a57194364782b1178aa2c6ffce82575a023ea..0a00f89cf6dec93d968b1f3569c4977af05321f9 100644 (file)
@@ -1,6 +1,6 @@
 /* DWARF 2 debugging format support for GDB.
 
-   Copyright (C) 1994-2020 Free Software Foundation, Inc.
+   Copyright (C) 1994-2021 Free Software Foundation, Inc.
 
    Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
    Inc.  with support from Florida State University (under contract
@@ -96,22 +96,14 @@ static unsigned int dwarf_read_debug = 0;
 /* Print a "dwarf-read" debug statement if dwarf_read_debug is >= 1.  */
 
 #define dwarf_read_debug_printf(fmt, ...) \
-  do \
-    { \
-      if (dwarf_read_debug >= 1) \
-       debug_prefixed_printf ("dwarf-read", __func__, fmt, ##__VA_ARGS__); \
-    } \
-  while (0)
+  debug_prefixed_printf_cond (dwarf_read_debug >= 1, "dwarf-read", fmt, \
+                             ##__VA_ARGS__)
 
 /* Print a "dwarf-read" debug statement if dwarf_read_debug is >= 2.  */
 
 #define dwarf_read_debug_printf_v(fmt, ...) \
-  do \
-    { \
-      if (dwarf_read_debug >= 2) \
-       debug_prefixed_printf ("dwarf-read", __func__, fmt, ##__VA_ARGS__); \
-    } \
-  while (0)
+  debug_prefixed_printf_cond (dwarf_read_debug >= 2, "dwarf-read", fmt, \
+                             ##__VA_ARGS__)
 
 /* When non-zero, dump DIEs after they are read in.  */
 static unsigned int dwarf_die_debug = 0;
@@ -2185,12 +2177,100 @@ locate_dwz_sections (bfd *abfd, asection *sectp, dwz_file *dwz_file)
     }
 }
 
+/* Attempt to find a .dwz file (whose full path is represented by
+   FILENAME) in all of the specified debug file directories provided.
+
+   Return the equivalent gdb_bfd_ref_ptr of the .dwz file found, or
+   nullptr if it could not find anything.  */
+
+static gdb_bfd_ref_ptr
+dwz_search_other_debugdirs (std::string &filename, bfd_byte *buildid,
+                           size_t buildid_len)
+{
+  /* Let's assume that the path represented by FILENAME has the
+     "/.dwz/" subpath in it.  This is what (most) GNU/Linux
+     distributions do, anyway.  */
+  size_t dwz_pos = filename.find ("/.dwz/");
+
+  if (dwz_pos == std::string::npos)
+    return nullptr;
+
+  /* This is an obvious assertion, but it's here more to educate
+     future readers of this code that FILENAME at DWZ_POS *must*
+     contain a directory separator.  */
+  gdb_assert (IS_DIR_SEPARATOR (filename[dwz_pos]));
+
+  gdb_bfd_ref_ptr dwz_bfd;
+  std::vector<gdb::unique_xmalloc_ptr<char>> debugdir_vec
+    = dirnames_to_char_ptr_vec (debug_file_directory);
+
+  for (const gdb::unique_xmalloc_ptr<char> &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 ();
+
+      if (ddir.empty ())
+       continue;
+
+      /* Make sure the current debug-file-directory ends with a
+        directory separator.  This is needed because, if FILENAME
+        contains something like "/usr/lib/abcde/.dwz/foo.dwz" and
+        DDIR is "/usr/lib/abc", then could wrongfully skip it
+        below.  */
+      if (!IS_DIR_SEPARATOR (ddir.back ()))
+       ddir += SLASH_STRING;
+
+      /* 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
+        remaining 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 = ddir + &filename[dwz_pos + 1];
+
+      dwz_bfd = gdb_bfd_open (new_filename.c_str (), gnutarget);
+
+      if (dwz_bfd == nullptr)
+       continue;
+
+      if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+       {
+         dwz_bfd.reset (nullptr);
+         continue;
+       }
+
+      /* Found it.  */
+      break;
+    }
+
+  return dwz_bfd;
+}
+
 /* See dwarf2read.h.  */
 
 struct dwz_file *
 dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd)
 {
-  const char *filename;
   bfd_size_type buildid_len_arg;
   size_t buildid_len;
   bfd_byte *buildid;
@@ -2214,21 +2294,19 @@ dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd)
 
   buildid_len = (size_t) buildid_len_arg;
 
-  filename = data.get ();
+  std::string filename = data.get ();
 
-  std::string abs_storage;
-  if (!IS_ABSOLUTE_PATH (filename))
+  if (!IS_ABSOLUTE_PATH (filename.c_str ()))
     {
       gdb::unique_xmalloc_ptr<char> 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 +2316,13 @@ 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.  */
+      dwz_bfd = dwz_search_other_debugdirs (filename, buildid, buildid_len);
+    }
+
   if (dwz_bfd == nullptr)
     {
       gdb::unique_xmalloc_ptr<char> alt_filename;
@@ -9094,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.  */
@@ -10464,6 +10554,7 @@ dwarf2_compute_name (const char *name,
              struct attribute *attr;
              struct die_info *child;
              int first = 1;
+             const language_defn *cplus_lang = language_def (cu->language);
 
              die->building_fullname = 1;
 
@@ -10498,8 +10589,8 @@ dwarf2_compute_name (const char *name,
 
                  if (child->tag == DW_TAG_template_type_param)
                    {
-                     c_print_type (type, "", &buf, -1, 0, cu->language,
-                                   &type_print_raw_options);
+                     cplus_lang->print_type (type, "", &buf, -1, 0,
+                                             &type_print_raw_options);
                      continue;
                    }
 
@@ -10519,7 +10610,7 @@ dwarf2_compute_name (const char *name,
                  if (type->has_no_signedness ())
                    /* GDB prints characters as NUMBER 'CHAR'.  If that's
                       changed, this can use value_print instead.  */
-                   c_printchar (value, type, &buf);
+                   cplus_lang->printchar (value, type, &buf);
                  else
                    {
                      struct value_print_options opts;
@@ -15805,6 +15896,55 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
   smash_to_methodptr_type (type, new_type);
 }
 
+/* Helper for quirk_ada_thick_pointer.  If TYPE is an array type that
+   requires rewriting, then copy it and return the updated copy.
+   Otherwise return nullptr.  */
+
+static struct type *
+rewrite_array_type (struct type *type)
+{
+  if (type->code () != TYPE_CODE_ARRAY)
+    return nullptr;
+
+  struct type *index_type = type->index_type ();
+  range_bounds *current_bounds = index_type->bounds ();
+
+  /* Handle multi-dimensional arrays.  */
+  struct type *new_target = rewrite_array_type (TYPE_TARGET_TYPE (type));
+  if (new_target == nullptr)
+    {
+      /* Maybe we don't need to rewrite this array.  */
+      if (current_bounds->low.kind () == PROP_CONST
+         && current_bounds->high.kind () == PROP_CONST)
+       return nullptr;
+    }
+
+  /* Either the target type was rewritten, or the bounds have to be
+     updated.  Either way we want to copy the type and update
+     everything.  */
+  struct type *copy = copy_type (type);
+  int nfields = copy->num_fields ();
+  field *new_fields
+    = ((struct field *) TYPE_ZALLOC (copy,
+                                    nfields * sizeof (struct field)));
+  memcpy (new_fields, copy->fields (), nfields * sizeof (struct field));
+  copy->set_fields (new_fields);
+  if (new_target != nullptr)
+    TYPE_TARGET_TYPE (copy) = new_target;
+
+  struct type *index_copy = copy_type (index_type);
+  range_bounds *bounds
+    = (struct range_bounds *) TYPE_ZALLOC (index_copy,
+                                          sizeof (range_bounds));
+  *bounds = *current_bounds;
+  bounds->low.set_const_val (1);
+  bounds->high.set_const_val (0);
+  index_copy->set_bounds (bounds);
+  copy->set_index_type (index_copy);
+
+  return copy;
+}
+
 /* While some versions of GCC will generate complicated DWARF for an
    array (see quirk_ada_thick_pointer), more recent versions were
    modified to emit an explicit thick pointer structure.  However, in
@@ -15831,20 +15971,16 @@ quirk_ada_thick_pointer_struct (struct die_info *die, struct dwarf2_cu *cu,
   /* Make sure we're looking at a pointer to an array.  */
   if (type->field (0).type ()->code () != TYPE_CODE_PTR)
     return;
-  struct type *ary_type = TYPE_TARGET_TYPE (type->field (0).type ());
-
-  while (ary_type->code () == TYPE_CODE_ARRAY)
-    {
-      /* The Ada code already knows how to handle these types, so all
-        that we need to do is turn the bounds into static bounds.  */
-      struct type *index_type = ary_type->index_type ();
-
-      index_type->bounds ()->low.set_const_val (1);
-      index_type->bounds ()->high.set_const_val (0);
 
-      /* Handle multi-dimensional arrays.  */
-      ary_type = TYPE_TARGET_TYPE (ary_type);
-    }
+  /* The Ada code already knows how to handle these types, so all that
+     we need to do is turn the bounds into static bounds.  However, we
+     don't want to rewrite existing array or index types in-place,
+     because those may be referenced in other contexts where this
+     rewriting is undesirable.  */
+  struct type *new_ary_type
+    = rewrite_array_type (TYPE_TARGET_TYPE (type->field (0).type ()));
+  if (new_ary_type != nullptr)
+    type->field (0).set_type (lookup_pointer_type (new_ary_type));
 }
 
 /* If the DIE has a DW_AT_alignment attribute, return its value, doing
@@ -18092,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).
 
@@ -18101,7 +18277,7 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
 
 static void
 get_dwarf2_rational_constant (struct die_info *die, struct dwarf2_cu *cu,
-                             LONGEST *numerator, LONGEST *denominator)
+                             gdb_mpz *numerator, gdb_mpz *denominator)
 {
   struct attribute *num_attr, *denom_attr;
 
@@ -18118,8 +18294,8 @@ get_dwarf2_rational_constant (struct die_info *die, struct dwarf2_cu *cu,
   if (num_attr == nullptr || denom_attr == nullptr)
     return;
 
-  *numerator = num_attr->constant_value (1);
-  *denominator = 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
@@ -18131,25 +18307,26 @@ get_dwarf2_rational_constant (struct die_info *die, struct dwarf2_cu *cu,
 static void
 get_dwarf2_unsigned_rational_constant (struct die_info *die,
                                       struct dwarf2_cu *cu,
-                                      ULONGEST *numerator,
-                                      ULONGEST *denominator)
+                                      gdb_mpz *numerator,
+                                      gdb_mpz *denominator)
 {
-  LONGEST num = 1, denom = 1;
+  gdb_mpz num (1);
+  gdb_mpz denom (1);
 
   get_dwarf2_rational_constant (die, cu, &num, &denom);
-  if (num < 0 && denom < 0)
+  if (mpz_sgn (num.val) == -1 && mpz_sgn (denom.val) == -1)
     {
-      num = -num;
-      denom = -denom;
+      mpz_neg (num.val, num.val);
+      mpz_neg (denom.val, denom.val);
     }
-  else if (num < 0)
+  else if (mpz_sgn (num.val) == -1)
     {
       complaint (_("unexpected negative value for DW_AT_GNU_numerator"
                   " in DIE at %s"),
                 sect_offset_str (die->sect_off));
       return;
     }
-  else if (denom < 0)
+  else if (mpz_sgn (denom.val) == -1)
     {
       complaint (_("unexpected negative value for DW_AT_GNU_denominator"
                   " in DIE at %s"),
@@ -18157,8 +18334,8 @@ get_dwarf2_unsigned_rational_constant (struct die_info *die,
       return;
     }
 
-  *numerator = num;
-  *denominator = denom;
+  *numerator = std::move (num);
+  *denominator = std::move (denom);
 }
 
 /* Assuming DIE corresponds to a fixed point type, finish the creation
@@ -18170,14 +18347,6 @@ finish_fixed_point_type (struct type *type, struct die_info *die,
                         struct dwarf2_cu *cu)
 {
   struct attribute *attr;
-  /* Numerator and denominator of our fixed-point type's scaling factor.
-     The default is a scaling factor of 1, which we use as a fallback
-     when we are not able to decode it (problem with the debugging info,
-     unsupported forms, bug in GDB, etc...).  Using that as the default
-     allows us to at least print the unscaled value, which might still
-     be useful to a user.  */
-  ULONGEST scale_num = 1;
-  ULONGEST scale_denom = 1;
 
   gdb_assert (type->code () == TYPE_CODE_FIXED_POINT
              && TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_FIXED_POINT);
@@ -18188,6 +18357,15 @@ finish_fixed_point_type (struct type *type, struct die_info *die,
   if (!attr)
     attr = dwarf2_attr (die, DW_AT_small, cu);
 
+  /* Numerator and denominator of our fixed-point type's scaling factor.
+     The default is a scaling factor of 1, which we use as a fallback
+     when we are not able to decode it (problem with the debugging info,
+     unsupported forms, bug in GDB, etc...).  Using that as the default
+     allows us to at least print the unscaled value, which might still
+     be useful to a user.  */
+  gdb_mpz scale_num (1);
+  gdb_mpz scale_denom (1);
+
   if (attr == nullptr)
     {
       /* Scaling factor not found.  Assume a scaling factor of 1,
@@ -18199,16 +18377,16 @@ finish_fixed_point_type (struct type *type, struct die_info *die,
   else if (attr->name == DW_AT_binary_scale)
     {
       LONGEST scale_exp = attr->constant_value (0);
-      ULONGEST *num_or_denom = scale_exp > 0 ? &scale_num : &scale_denom;
+      gdb_mpz *num_or_denom = scale_exp > 0 ? &scale_num : &scale_denom;
 
-      *num_or_denom = 1 << std::abs (scale_exp);
+      mpz_mul_2exp (num_or_denom->val, num_or_denom->val, std::abs (scale_exp));
     }
   else if (attr->name == DW_AT_decimal_scale)
     {
       LONGEST scale_exp = attr->constant_value (0);
-      ULONGEST *num_or_denom = scale_exp > 0 ? &scale_num : &scale_denom;
+      gdb_mpz *num_or_denom = scale_exp > 0 ? &scale_num : &scale_denom;
 
-      *num_or_denom = uinteger_pow (10, std::abs (scale_exp));
+      mpz_ui_pow_ui (num_or_denom->val, 10, std::abs (scale_exp));
     }
   else if (attr->name == DW_AT_small)
     {
@@ -18233,13 +18411,8 @@ finish_fixed_point_type (struct type *type, struct die_info *die,
     }
 
   gdb_mpq &scaling_factor = type->fixed_point_info ().scaling_factor;
-
-  gdb_mpz tmp_z (scale_num);
-  mpz_set (mpq_numref (scaling_factor.val), tmp_z.val);
-
-  tmp_z = scale_denom;
-  mpz_set (mpq_denref (scaling_factor.val), tmp_z.val);
-
+  mpz_set (mpq_numref (scaling_factor.val), scale_num.val);
+  mpz_set (mpq_denref (scaling_factor.val), scale_denom.val);
   mpq_canonicalize (scaling_factor.val);
 }
 
@@ -18305,9 +18478,9 @@ has_zero_over_zero_small_attribute (struct die_info *die,
   if (scale_die->tag != DW_TAG_constant)
     return false;
 
-  LONGEST num = 1, denom = 1;
+  gdb_mpz num (1), denom (1);
   get_dwarf2_rational_constant (scale_die, cu, &num, &denom);
-  return (num == 0 && denom == 0);
+  return mpz_sgn (num.val) == 0 && mpz_sgn (denom.val) == 0;
 }
 
 /* Initialise and return a floating point type of size BITS suitable for
@@ -19660,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));
@@ -23429,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.
@@ -23445,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),
@@ -24825,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;
@@ -24847,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.036442 seconds and 4 git commands to generate.