]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: Revamp location reporting
authorPetr Machata <pmachata@redhat.com>
Tue, 19 Apr 2011 15:29:41 +0000 (17:29 +0200)
committerPetr Machata <pmachata@redhat.com>
Tue, 19 Apr 2011 15:29:41 +0000 (17:29 +0200)
- Drop struct where, introduce class locus, which is an abstract interface
  that the real locus classes implement.  Locus classes are still used as
  values, no heap allocation was necessary, although if polymorphism is
  necessary, loci can simply be new'ed and put in a vector etc.

- Formatting of most loci was kept the way it was, but some formats have
  been improved.  For example, DIE and abbrev loci now use attribute
  name directly to point to the attribute in question.

- Low-level allocation helpers (mostly WIPE) were dropped and replaced
  with constructors on those structures.  Placement new has to be used
  in a couple places to initialize data where REALLOC is still used.

- Functions that used to take struct where * now take locus const &.  The
  code was updated throughout.

- Values not corresponding to sections were removed from enum section_id.
  Part was dropped outright, because they were there just to support WHEREs,
  rel_* was moved to new class rel_target.

- Convert addr_recort, ref_record to classes inheriting off std::vector.
  ref_record in fact became ref_record_T and is now parametrized by
  locus type.

54 files changed:
dwarflint/Makefile.am
dwarflint/addr-record.cc
dwarflint/addr-record.hh
dwarflint/check_debug_abbrev.cc
dwarflint/check_debug_abbrev.hh
dwarflint/check_debug_aranges.cc
dwarflint/check_debug_aranges.hh
dwarflint/check_debug_info.cc
dwarflint/check_debug_info.hh
dwarflint/check_debug_line.cc
dwarflint/check_debug_loc_range.cc
dwarflint/check_debug_loc_range.hh
dwarflint/check_debug_pub.cc
dwarflint/check_debug_pub.hh
dwarflint/check_die_decl_call.cc
dwarflint/check_die_line_info.cc
dwarflint/check_die_tree.cc
dwarflint/check_duplicate_DW_tag_variable.cc
dwarflint/check_dups_abstract_origin.cc
dwarflint/check_expected_trees.cc
dwarflint/check_linkage_external_die.cc
dwarflint/check_matching_ranges.cc
dwarflint/check_nodebug.cc
dwarflint/check_range_out_of_scope.cc
dwarflint/check_self_referential_die.cc
dwarflint/checked_read.cc
dwarflint/checked_read.hh
dwarflint/checks.hh
dwarflint/coverage.cc
dwarflint/cu_coverage.cc
dwarflint/die_locus.cc [new file with mode: 0644]
dwarflint/die_locus.hh [new file with mode: 0644]
dwarflint/elf_file.hh
dwarflint/highlevel_check.hh
dwarflint/locstats.cc
dwarflint/locus.cc [new file with mode: 0644]
dwarflint/locus.hh [new file with mode: 0644]
dwarflint/lowlevel_checks.cc
dwarflint/main.cc
dwarflint/messages.cc
dwarflint/messages.hh
dwarflint/misc.cc
dwarflint/misc.hh
dwarflint/pri.cc
dwarflint/pri.hh
dwarflint/readctx.hh
dwarflint/reloc.cc
dwarflint/reloc.hh
dwarflint/section_id.hh
dwarflint/sections.cc
dwarflint/tests/run-DW_AT-later-version.sh
dwarflint/tests/run-bad.sh
dwarflint/where.c [deleted file]
dwarflint/where.h [deleted file]

index 2a964603c8a3ee0efbb77d0541f38d7749d903ef..8b2f99fc6c7b7009d5071c0187ccd60e73c98072 100644 (file)
@@ -48,6 +48,7 @@ dwarflint_SOURCES = \
        checks.hh checks_i.hh \
        coverage.cc coverage.hh \
        cu_coverage.cc cu_coverage.hh cu_coverage_i.hh \
+       die_locus.cc die_locus.hh \
        dwarf_2.cc dwarf_2.hh \
        dwarf_3.cc dwarf_3.hh \
        dwarf_4.cc dwarf_4.hh \
@@ -60,6 +61,7 @@ dwarflint_SOURCES = \
        expected-at.cc expected.hh \
        files.cc files.hh \
        highlevel_check.cc highlevel_check.hh highlevel_check_i.hh \
+       locus.cc locus.hh \
        main.cc \
        messages.cc messages.hh \
        misc.cc misc.hh \
@@ -69,7 +71,6 @@ dwarflint_SOURCES = \
        reloc.cc reloc.hh \
        section_id.cc section_id.hh \
        sections.cc sections.hh sections_i.hh \
-       where.c where.h \
        wrap.cc wrap.hh \
        \
        check_debug_abbrev.cc check_debug_abbrev.hh check_debug_abbrev_i.hh \
@@ -95,10 +96,12 @@ dwarflint_SOURCES = \
 
 locstats_SOURCES = \
        locstats.cc \
+       die_locus.cc die_locus.hh \
        files.cc files.hh \
+       locus.cc locus.hh \
        option.cc option.hh option_i.hh \
-       pri.cc pri.hh \
-       where.c where.h
+       section_id.cc section_id.hh \
+       pri.cc pri.hh
 
 tests_test_coverage_SOURCES = tests/test-coverage.cc coverage.cc pri.cc \
        ../src/dwarfstrings.c
index ec31eba2e1969ba000ef75386f87aba30b2f6837..220f4b1dc6bb74de352ae4026de0a2a92549e273 100644 (file)
@@ -1,5 +1,5 @@
 /* Pedantic checking of DWARF files
-   Copyright (C) 2009,2010 Red Hat, Inc.
+   Copyright (C) 2009,2010,2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
    <http://www.openinventionnetwork.com>.  */
 
 #include "addr-record.hh"
-#include "misc.hh"
 
 size_t
-addr_record_find_addr (struct addr_record *ar, uint64_t addr)
+addr_record::find (uint64_t addr) const
 {
   size_t a = 0;
-  size_t b = ar->size;
+  size_t b = size ();
 
   while (a < b)
     {
       size_t i = (a + b) / 2;
-      uint64_t v = ar->addrs[i];
+      uint64_t v = (*this)[i];
 
       if (v > addr)
        b = i;
@@ -49,51 +48,21 @@ addr_record_find_addr (struct addr_record *ar, uint64_t addr)
 }
 
 bool
-addr_record_has_addr (struct addr_record *ar, uint64_t addr)
+addr_record::has_addr (uint64_t addr) const
 {
-  if (ar->size == 0
-      || addr < ar->addrs[0]
-      || addr > ar->addrs[ar->size - 1])
+  if (begin () == end ()
+      || addr < front ()
+      || addr > back ())
     return false;
 
-  size_t a = addr_record_find_addr (ar, addr);
-  return a < ar->size && ar->addrs[a] == addr;
+  const_iterator it = begin () + find (addr);
+  return it != end () && *it == addr;
 }
 
 void
-addr_record_add (struct addr_record *ar, uint64_t addr)
+addr_record::add (uint64_t addr)
 {
-  size_t a = addr_record_find_addr (ar, addr);
-  if (a >= ar->size || ar->addrs[a] != addr)
-    {
-      REALLOC (ar, addrs);
-      size_t len = ar->size - a;
-      memmove (ar->addrs + a + 1, ar->addrs + a, len * sizeof (*ar->addrs));
-
-      ar->addrs[a] = addr;
-      ar->size++;
-    }
-}
-
-void
-addr_record_free (struct addr_record *ar)
-{
-  if (ar != NULL)
-    free (ar->addrs);
-}
-
-void
-ref_record_add (struct ref_record *rr, uint64_t addr, struct where *referrer)
-{
-  REALLOC (rr, refs);
-  struct ref *ref = rr->refs + rr->size++;
-  ref->addr = addr;
-  ref->who = *referrer;
-}
-
-void
-ref_record_free (struct ref_record *rr)
-{
-  if (rr != NULL)
-    free (rr->refs);
+  iterator it = begin () + find (addr);
+  if (it == end () || *it != addr)
+    insert (it, addr);
 }
index 1542ff3141b60ca1ef9ed8847b6eafdb1ca0c3fe..4bbd0c51d0e5c0e6cc44ac119a6b8d5dd011ea07 100644 (file)
@@ -1,5 +1,5 @@
 /* Pedantic checking of DWARF files
-   Copyright (C) 2009,2010 Red Hat, Inc.
+   Copyright (C) 2009,2010,2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
 
 #include <stdlib.h>
 #include <stdint.h>
-#include "where.h"
-#ifdef __cplusplus
-extern "C"
-{
-#else
-# include <stdbool.h>
-#endif
-
-  /* Functions and data structures for address record handling.  We
-     use that to check that all DIE references actually point to an
-     existing die, not somewhere mid-DIE, where it just happens to be
-     interpretable as a DIE.  */
+#include <vector>
 
-  struct addr_record
-  {
-    size_t size;
-    size_t alloc;
-    uint64_t *addrs;
-  };
+#include "locus.hh"
 
-  size_t addr_record_find_addr (struct addr_record *ar, uint64_t addr);
-  bool addr_record_has_addr (struct addr_record *ar, uint64_t addr);
-  void addr_record_add (struct addr_record *ar, uint64_t addr);
-  void addr_record_free (struct addr_record *ar);
+/// Address record is used to check that all DIE references actually
+/// point to an existing die, not somewhere mid-DIE, where it just
+/// happens to be interpretable as a DIE.  This is stored as sorted
+/// array for quick lookup and duplicate removal.
+struct addr_record
+  : private std::vector<uint64_t>
+{
+  typedef std::vector<uint64_t> _super_t;
+  size_t find (uint64_t addr) const;
 
-  /* Functions and data structures for reference handling.  Just like
-     the above, we use this to check validity of DIE references.
-     Unlike the above, this is not stored as sorted set, but simply as
-     an array of records, because duplicates are unlikely.  */
+public:
+  bool has_addr (uint64_t addr) const;
+  void add (uint64_t addr);
+};
 
-  struct ref
-  {
-    uint64_t addr; // Referree address
-    struct where who;  // Referrer
-  };
+/// One reference for use in ref_record, parametrized by locus type.
+template <class L>
+struct ref_T
+{
+  uint64_t addr; // Referee address
+  L who;         // Referrer
 
-  struct ref_record
-  {
-    size_t size;
-    size_t alloc;
-    struct ref *refs;
-  };
+  ref_T ()
+    : addr (-1)
+  {}
 
-  void ref_record_add (struct ref_record *rr, uint64_t addr,
-                      struct where *referrer);
-  void ref_record_free (struct ref_record *rr);
+  ref_T (uint64_t a_addr, L const &a_who)
+    : addr (a_addr)
+    , who (a_who)
+  {}
+};
 
-#ifdef __cplusplus
-}
-#endif
+/// Reference record is used to check validity of DIE references.
+/// Unlike the above, this is not stored as sorted set, but simply as
+/// an array of records, because duplicates are unlikely.
+template <class L>
+class ref_record_T
+  : private std::vector<ref_T<L> >
+{
+  typedef std::vector<ref_T<L> > _super_t;
+public:
+  using _super_t::const_iterator;
+  using _super_t::begin;
+  using _super_t::end;
+  using _super_t::push_back;
+};
 
 #endif//DWARFLINT_ADDR_RECORD_H
index 3b5e3bab6ffbfbc9015b1a0d1cb2432ef32c89eb..849e50533f20259cefc70943cca0e16ea520f601 100644 (file)
 #include "messages.hh"
 #include "misc.hh"
 
+char const *
+locus_simple_fmt::abbr_offset_n ()
+{
+  return "abbr. offset";
+}
+
+abbrev_attrib_locus::abbrev_attrib_locus (uint64_t abbr_offset,
+                                         uint64_t attr_offset,
+                                         int a_name)
+  : _m_abbr_offset (abbr_offset)
+  , _m_attr_offset (attr_offset)
+  , _m_name (a_name)
+{}
+
+abbrev_attrib_locus::abbrev_attrib_locus (abbrev_attrib_locus const &copy)
+  : _m_abbr_offset (copy._m_abbr_offset)
+  , _m_attr_offset (copy._m_attr_offset)
+  , _m_name (copy._m_name)
+{}
+
+std::string
+abbrev_attrib_locus::name () const
+{
+  return pri::attr_name (_m_name);
+}
+
+void
+abbrev_attrib_locus::set_name (int a_name)
+{
+  _m_name = a_name;
+}
+
+abbrev_attrib_locus
+abbrev_attrib_locus::non_symbolic ()
+{
+  return abbrev_attrib_locus (_m_abbr_offset, _m_attr_offset);
+}
+
+std::string
+abbrev_attrib_locus::format (bool brief) const
+{
+  std::stringstream ss;
+  if (!brief)
+    ss << section_name[sec_abbrev] << ": ";
+  if (_m_name != -1)
+    ss << "abbr. 0x" << std::hex << _m_abbr_offset << ", attr. " << name ();
+  else
+    ss << "abbr. attribute 0x" << std::hex << _m_attr_offset;
+  return ss.str ();
+}
+
 checkdescriptor const *
 check_debug_abbrev::descriptor ()
 {
@@ -114,14 +165,12 @@ namespace
   };
 
   void
-  complain (where const *where,
-           int attrib_name, int form_name,
+  complain (locus const &loc, int form_name,
            bool indirect, char const *qualifier)
   {
-    wr_error (*where)
-      << "attribute " << elfutils::dwarf::attributes::name (attrib_name)
-      << " with " << qualifier << (indirect ? " indirect" : "")
-      << " form " << elfutils::dwarf::forms::name (form_name)
+    wr_error (loc)
+      << "attribute with " << qualifier << (indirect ? " indirect" : "")
+      << " form " << elfutils::dwarf::forms::identifier (form_name)
       << '.' << std::endl;
   }
 
@@ -134,11 +183,9 @@ namespace
     // But since we got here, apparently there was a .debug_abbrev
     // section with size of more than 0 bytes, which is wasteful.
     if (ret)
-      {
-       where wh = WHERE (sec_abbrev, NULL);
-       wr_message (wh, mc_abbrevs | mc_impact_1 | mc_acc_bloat)
-         << "no abbreviations." << std::endl;
-      }
+      wr_message (section_locus (sec_abbrev),
+                 mc_abbrevs | mc_impact_1 | mc_acc_bloat)
+       << "no abbreviations." << std::endl;
     return ret;
   }
 
@@ -153,12 +200,10 @@ namespace
 
     struct abbrev_table *section = NULL;
     uint64_t first_attr_off = 0;
-    struct where where = WHERE (sec_abbrev, NULL);
 
     // Tolerate failure here.
     dwarf_version const *ver = NULL;
     static dwarf_version const *latest_ver = dwarf_version::get_latest ();
-    where.addr1 = 0;
 
     bool failed = false;
     while (true)
@@ -168,7 +213,8 @@ namespace
        if (read_ctx_eof (&ctx))
          {
            if (!check_no_abbreviations (abbrevs))
-             wr_error (&where, ": missing zero to mark end-of-table.\n");
+             wr_error (section_locus (sec_abbrev))
+               << "missing zero to mark end-of-table.\n";
            break;
          }
 
@@ -181,10 +227,11 @@ namespace
          do
            {
              abbr_off = read_ctx_get_offset (&ctx);
-             where_reset_2 (&where, abbr_off);
 
              /* Abbreviation code.  */
-             if (!checked_read_uleb128 (&ctx, &abbr_code, &where, "abbrev code"))
+             if (!checked_read_uleb128 (&ctx, &abbr_code,
+                                        section_locus (sec_abbrev, abbr_off),
+                                        "abbrev code"))
                throw check_base::failed ();
 
              /* Note: we generally can't tell the difference between
@@ -211,11 +258,9 @@ namespace
                 || ((abbr_off += 1), false));
 
          if (zero_seq_off != (uint64_t)-1)
-           {
-             struct where wh = WHERE (where.section, NULL);
-             wr_message_padding_0 (mc_abbrevs | mc_header,
-                                   &wh, zero_seq_off, abbr_off);
-           }
+           wr_message_padding_0 (mc_abbrevs | mc_header,
+                                 section_locus (sec_abbrev),
+                                 zero_seq_off, abbr_off);
        }
 
        if (read_ctx_eof (&ctx))
@@ -225,18 +270,16 @@ namespace
            break;
          }
 
+       abbrev_locus where (abbr_off);
+
        /* OK, we got some genuine abbreviation.  See if we need to
           allocate a new section.  */
        if (section == NULL)
          {
            abbrev_table t;
-           WIPE (t);
            section = &abbrevs.insert (std::make_pair (abbr_off, t)).first->second;
            section->offset = abbr_off;
 
-           where_reset_1 (&where, abbr_off);
-           where_reset_2 (&where, abbr_off);
-
            // Find CU that uses this abbrev table, so that we know what
            // version to validate against.
            if (cu_headers != NULL)
@@ -278,10 +321,9 @@ namespace
                    ver = dwarf_version::get_latest ();
                  }
              }
-           else if (ver == NULL)
+           else if (ver == NULL) // Only emit this once.
              {
-               struct where wh = WHERE (sec_info, NULL);
-               wr_error (wh)
+               wr_error (section_locus (sec_info))
                  << "couldn't load CU headers for processing .debug_abbrev; "
                     "assuming latest DWARF flavor."
                  << std::endl;
@@ -291,30 +333,28 @@ namespace
            assert (ver != NULL);
          }
 
-       struct abbrev *original = section->find_abbrev (abbr_code);
+       abbrev *original = section->find_abbrev (abbr_code);
+       abbrev *cur;
+       abbrev fake (where);
        if (unlikely (original != NULL))
-         wr_error (where)
-           << "duplicate abbrev code " << abbr_code
-           << "; already defined at " << original->where << '.' << std::endl;
-
-       struct abbrev fake;
-       struct abbrev *cur;
-       /* Don't actually save this abbrev if it's duplicate.  */
-       if (likely (original == NULL))
+         {
+           wr_error (where) << "duplicate abbrev code (first was at "
+                            << original->where << ").\n";
+           /* Don't actually save this abbrev if it's duplicate.  */
+           cur = &fake;
+         }
+       else
          {
            REALLOC (section, abbr);
            cur = section->abbr + section->size++;
+           new (cur) abbrev (where);
          }
-       else
-         cur = &fake;
-       WIPE (*cur);
 
        cur->code = abbr_code;
-       cur->where = where;
 
        /* Abbreviation tag.  */
        uint64_t abbr_tag;
-       if (!checked_read_uleb128 (&ctx, &abbr_tag, &where, "abbrev tag"))
+       if (!checked_read_uleb128 (&ctx, &abbr_tag, where, "abbrev tag"))
          throw check_base::failed ();
 
        if (abbr_tag > DW_TAG_hi_user)
@@ -359,14 +399,14 @@ namespace
 
            /* Shift to match elfutils reporting.  */
            attr_off -= first_attr_off;
-           where_reset_3 (&where, attr_off);
+           abbrev_attrib_locus attr_locus (abbr_off, attr_off);
 
            /* Load attribute name and form.  */
-           if (!checked_read_uleb128 (&ctx, &attrib_name, &where,
+           if (!checked_read_uleb128 (&ctx, &attrib_name, attr_locus,
                                       "attribute name"))
              throw check_base::failed ();
 
-           if (!checked_read_uleb128 (&ctx, &attrib_form, &where,
+           if (!checked_read_uleb128 (&ctx, &attrib_form, attr_locus,
                                       "attribute form"))
              throw check_base::failed ();
 
@@ -375,11 +415,12 @@ namespace
 
            REALLOC (cur, attribs);
 
+           attr_locus.set_name (attrib_name);
            struct abbrev_attrib *acur = cur->attribs + cur->size++;
-           WIPE (*acur);
+           new (acur) abbrev_attrib ();
            acur->name = attrib_name;
            acur->form = attrib_form;
-           acur->where = where;
+           acur->where = attr_locus;
 
            if (null_attrib)
              break;
@@ -387,7 +428,8 @@ namespace
            /* Otherwise validate name and form.  */
            if (attrib_name == 0)
              {
-               wr_error (where) << "invalid attribute code 0." << std::endl;
+               wr_error (attr_locus.non_symbolic ())
+                 << "invalid attribute code 0." << std::endl;
                // We can handle this, so keep going.  But this is not
                // kosher for high-level checks.
                failed = true;
@@ -407,18 +449,18 @@ namespace
                if (attribute == NULL)
                  // libdw should handle unknown attribute, as long as
                  // the form is kosher, so don't fail the check.
-                 wr_message (where, mc_abbrevs | mc_impact_1)
+                 wr_message (attr_locus.non_symbolic (),
+                             mc_abbrevs | mc_impact_1)
                    << "invalid or unknown name " << pri::hex (attrib_name)
                    << '.' << std::endl;
                else if (opt_nognu)
-                 wr_message (where, mc_abbrevs | mc_impact_1)
-                   << "attribute " << *attribute
-                   << " from later DWARF version."
+                 wr_message (attr_locus, mc_abbrevs | mc_impact_1)
+                   << "attribute from later DWARF version."
                    << std::endl;
              }
 
            form const *form = check_debug_abbrev::check_form
-             (ver, attribute, attrib_form, &where, false);
+             (ver, attribute, attrib_form, attr_locus, false);
            if (form == NULL)
              {
                // Error message has been emitted in check_form.
@@ -430,11 +472,11 @@ namespace
              = seen.insert (std::make_pair (attrib_name, attr_off));
            if (!inserted.second)
              {
-               wr_error (where)
-                 << "duplicate attribute "
-                 << elfutils::dwarf::attributes::name (attrib_name)
+               wr_error (attr_locus.non_symbolic ())
+                 << "duplicate attribute " << attr_locus.name ()
                  << " (first was at " << pri::hex (inserted.first->second)
                  << ")." << std::endl;
+
                // I think we may allow such files for high-level
                // consumption, so don't fail the check...
                if (attrib_name == DW_AT_sibling)
@@ -442,13 +484,10 @@ namespace
                  failed = true;
              }
 
-           if (attrib_name == DW_AT_sibling)
-             {
-               if (!cur->has_children)
-                 wr_message (where, mc_die_rel | mc_acc_bloat | mc_impact_1)
-                   << "superfluous DW_AT_sibling attribute at childless abbrev."
-                   << std::endl;
-             }
+           if (attrib_name == DW_AT_sibling && !cur->has_children)
+             wr_message (attr_locus, mc_die_rel | mc_acc_bloat | mc_impact_1)
+               << "superfluous DW_AT_sibling attribute at childless abbrev."
+               << std::endl;
            if (attrib_name == DW_AT_ranges)
              ranges = true;
            else if (attrib_name == DW_AT_low_pc)
@@ -458,7 +497,6 @@ namespace
          }
        while (!null_attrib);
 
-       where_reset_2 (&where, where.addr2); // drop addr 3
        if (high_pc && !low_pc)
          wr_error (where)
            << "the abbrev has DW_AT_high_pc without also having DW_AT_low_pc."
@@ -499,13 +537,12 @@ check_debug_abbrev::check_debug_abbrev (checkstack &stack, dwarflint &lint)
 form const *
 check_debug_abbrev::check_form (dwarf_version const *ver,
                                attribute const *attribute,
-                               int form_name,
-                               where const *where, bool indirect)
+                               int form_name, locus const &loc, bool indirect)
 {
   form const *form = ver->get_form (form_name);
   if (form == NULL)
     {
-      wr_error (*where)
+      wr_error (loc)
        << "invalid form " << pri::hex (form_name)
        << '.' << std::endl;
       return NULL;
@@ -517,12 +554,12 @@ check_debug_abbrev::check_form (dwarf_version const *ver,
       int attrib_name = attribute->name ();
       if (!ver->form_allowed (attribute, form))
        {
-         complain (where, attrib_name, form_name, indirect, "invalid");
+         complain (loc, form_name, indirect, "invalid");
          return NULL;
        }
       else if (attrib_name == DW_AT_sibling
               && sibling_form_suitable (ver, form) == sfs_long)
-       complain (where, attrib_name, form_name, indirect, "unsuitable");
+       complain (loc, form_name, indirect, "unsuitable");
     }
 
   return form;
index 7fc1aefdf454bde03594ffb527f28a7b91eab1d7..54d03ce872512b8c3cb092c2819f0882cf95c619 100644 (file)
@@ -1,5 +1,5 @@
 /* Low-level checking of .debug_abbrev.
-   Copyright (C) 2009, 2010 Red Hat, Inc.
+   Copyright (C) 2009, 2010, 2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
 #include "check_debug_info_i.hh"
 #include "dwarf_version_i.hh"
 
+namespace locus_simple_fmt
+{
+  char const *abbr_offset_n ();
+}
+
+typedef fixed_locus<sec_abbrev,
+                   locus_simple_fmt::abbr_offset_n,
+                   locus_simple_fmt::hex> abbrev_locus;
+
+class abbrev_attrib_locus
+  : public locus
+{
+  uint64_t _m_abbr_offset;
+  uint64_t _m_attr_offset;
+  int _m_name;
+
+public:
+  explicit abbrev_attrib_locus (uint64_t abbr_offset = -1,
+                               uint64_t attr_offset = -1,
+                               int name = -1);
+
+  abbrev_attrib_locus (abbrev_attrib_locus const &copy);
+
+  abbrev_attrib_locus non_symbolic ();
+
+  void set_name (int name);
+  std::string format (bool brief = false) const;
+  std::string name () const;
+};
+
 struct abbrev_attrib
 {
-  struct where where;
+  abbrev_attrib_locus where;
   uint16_t name;
   uint8_t form;
+
+  abbrev_attrib ()
+    : where ()
+    , name (0)
+    , form (0)
+  {}
 };
 
 struct abbrev
 {
+  abbrev_locus where;
   uint64_t code;
-  struct where where;
 
   /* Attributes.  */
-  struct abbrev_attrib *attribs;
+  abbrev_attrib *attribs;
   size_t size;
   size_t alloc;
 
@@ -56,6 +92,17 @@ struct abbrev
 
   /* Whether some DIE uses this abbrev.  */
   bool used;
+
+  explicit abbrev (abbrev_locus const &loc)
+    : where (loc)
+    , code (0)
+    , attribs (0)
+    , size (0)
+    , alloc (0)
+    , tag (0)
+    , has_children (false)
+    , used (false)
+  {}
 };
 
 struct abbrev_table
@@ -68,6 +115,15 @@ struct abbrev_table
   bool used;           /* There are CUs using this table.  */
 
   abbrev *find_abbrev (uint64_t abbrev_code) const;
+
+  abbrev_table ()
+    : next (NULL)
+    , abbr (NULL)
+    , offset (0)
+    , size (0)
+    , alloc (0)
+    , used (false)
+  {}
 };
 
 class check_debug_abbrev
@@ -87,7 +143,7 @@ public:
   static form const *check_form (dwarf_version const *ver,
                                 attribute const *attr,
                                 int form_name,
-                                where const *where,
+                                locus const &loc,
                                 bool indirect);
 
   ~check_debug_abbrev ();
index b955970228f0c42d53cf8c5053dae77511ac9261..cc2ce8c8f03013bf087cc1d9475c208e28b4dd90 100644 (file)
 #include "misc.hh"
 #include "pri.hh"
 
+char const *
+locus_simple_fmt::cudie_n ()
+{
+  return "CU DIE";
+}
+
+std::string
+arange_locus::format (bool brief) const
+{
+  std::stringstream ss;
+  if (!brief)
+    ss << section_name[sec_aranges] << ": ";
+
+  if (_m_arange_offset != (Dwarf_Off)-1)
+    ss << "arange 0x" << std::hex << _m_arange_offset;
+  else if (_m_table_offset != (Dwarf_Off)-1)
+    ss << "table " << std::dec << _m_table_offset;
+  else
+    ss << "arange";
+
+  if (_m_cudie_locus != NULL)
+    ss << " (" << _m_cudie_locus->format (true) << ')';
+
+  return ss.str ();
+}
+
 checkdescriptor const *
 check_debug_aranges::descriptor ()
 {
@@ -119,7 +145,6 @@ hole (uint64_t start, uint64_t length, void *user)
       || !necessary_alignment (start, length, sec->shdr.sh_addralign))
     {
       char buf[128];
-      where where = WHERE (info.id, NULL);
       char const *what = info.what;
       char const *cu = "CU DIEs";
       if (info.reverse)
@@ -128,7 +153,7 @@ hole (uint64_t start, uint64_t length, void *user)
          what = cu;
          cu = tmp;
        }
-      wr_message (where, mc_aranges | mc_impact_3)
+      wr_message (section_locus (info.id), mc_aranges | mc_impact_3)
        << "addresses " << range_fmt (buf, sizeof (buf), start, start + length)
        << " are covered with " << cu << ", but not with " << what << "."
        << std::endl;
@@ -163,13 +188,13 @@ compare_coverage (struct elf_file *file,
 inline static void
 aranges_coverage_add (struct coverage *aranges_coverage,
                      uint64_t begin, uint64_t length,
-                     struct where *where)
+                     locus const &loc)
 {
   if (aranges_coverage->is_overlap (begin, length))
     {
       char buf[128];
       /* Not a show stopper, this shouldn't derail high-level.  */
-      wr_message (*where, mc_aranges | mc_impact_2 | mc_error)
+      wr_message (loc, mc_aranges | mc_impact_2 | mc_error)
        << "the range " << range_fmt (buf, sizeof buf, begin, begin + length)
        << " overlaps with another one." << std::endl;
     }
@@ -196,8 +221,7 @@ check_aranges_structural (struct elf_file *file,
 
   while (!read_ctx_eof (&ctx))
     {
-      struct where where = WHERE (sec_aranges, NULL);
-      where_reset_1 (&where, read_ctx_get_offset (&ctx));
+      arange_locus where (read_ctx_get_offset (&ctx));
       const unsigned char *atab_begin = ctx.ptr;
 
       /* Size.  */
@@ -209,7 +233,7 @@ check_aranges_structural (struct elf_file *file,
          wr_error (&where, ": can't read table length.\n");
          return false;
        }
-      if (!read_size_extra (&ctx, size32, &size, &offset_size, &where))
+      if (!read_size_extra (&ctx, size32, &size, &offset_size, where))
        return false;
 
       struct read_ctx sub_ctx;
@@ -239,7 +263,7 @@ check_aranges_structural (struct elf_file *file,
          retval = false;
          goto next;
        }
-      if (!supported_version (version, 1, &where, 2))
+      if (!supported_version (version, 1, where, 2))
        {
          retval = false;
          goto next;
@@ -257,9 +281,9 @@ check_aranges_structural (struct elf_file *file,
 
       struct relocation *rel;
       if ((rel = relocation_next (&sec->rel, ctx_offset,
-                                 &where, skip_mismatched)))
+                                 where, skip_mismatched)))
        relocate_one (file, &sec->rel, rel, offset_size,
-                     &cu_offset, &where, sec_info, NULL);
+                     &cu_offset, where, sec_info, NULL);
       else if (file->ehdr.e_type == ET_REL)
        wr_message (mc_impact_2 | mc_aranges | mc_reloc | mc_header, &where,
                    PRI_LACK_RELOCATION, "debug info offset");
@@ -268,13 +292,10 @@ check_aranges_structural (struct elf_file *file,
       if (cu_chain != NULL && (cu = cu_find_cu (cu_chain, cu_offset)) == NULL)
        wr_error (&where, ": unresolved reference to " PRI_CU ".\n", cu_offset);
 
-      struct where where_cudie;
+      cudie_locus cudie_loc (cu != NULL ? cu->cudie_offset : -1);
       if (cu != NULL)
        {
-         where_cudie = WHERE (sec_info, NULL);
-         where_reset_1 (&where_cudie, cu->cudie_offset);
-         where.ref = &where_cudie;
-         where_cudie.formatting = wf_cudie;
+         where.set_cudie (&cudie_loc);
          if (cu->has_arange)
            wr_error (where)
              << "there has already been arange section for this CU."
@@ -286,7 +307,7 @@ check_aranges_structural (struct elf_file *file,
       /* Address size.  */
       int address_size;
       error_code err = read_address_size (&sub_ctx, file->addr_64,
-                                         &address_size, &where);
+                                         &address_size, where);
       if (err != err_ok)
        retval = false;
       if (err == err_fatal)
@@ -346,7 +367,7 @@ check_aranges_structural (struct elf_file *file,
             way, the better to catch structural errors accurately.
             So report arange offset instead.  If this becomes a
             problem, we will achieve this by two-pass analysis.  */
-         where_reset_2 (&where, read_ctx_get_offset (&sub_ctx));
+         where.set_arange (read_ctx_get_offset (&sub_ctx));
 
          /* Record address.  */
          uint64_t address;
@@ -360,11 +381,11 @@ check_aranges_structural (struct elf_file *file,
            }
 
          if ((rel = relocation_next (&sec->rel, ctx_offset,
-                                     &where, skip_mismatched)))
+                                     where, skip_mismatched)))
            {
              address_relocated = true;
              relocate_one (file, &sec->rel, rel, address_size,
-                           &address, &where, rel_address, NULL);
+                           &address, where, rel_target::rel_address, NULL);
            }
          else if (file->ehdr.e_type == ET_REL && address != 0)
            wr_message (mc_impact_2 | mc_aranges | mc_reloc, &where,
@@ -389,18 +410,18 @@ check_aranges_structural (struct elf_file *file,
            wr_error (&where, ": zero-length address range.\n");
          /* Skip coverage analysis if we have errors.  */
          else if (retval && aranges_coverage != NULL)
-           aranges_coverage_add (aranges_coverage, address, length, &where);
+           aranges_coverage_add (aranges_coverage, address, length, where);
        }
 
       if (sub_ctx.ptr != sub_ctx.end)
        {
          uint64_t start, end;
-         struct where wh = WHERE (where.section, NULL);
+         section_locus wh (sec_aranges);
          if (read_check_zero_padding (&sub_ctx, &start, &end))
-           wr_message_padding_0 (mc_aranges, &wh, start, end);
+           wr_message_padding_0 (mc_aranges, wh, start, end);
          else
            {
-             wr_message_padding_n0 (mc_aranges | mc_error, &wh,
+             wr_message_padding_n0 (mc_aranges | mc_error, wh,
                                     start, start + size);
              retval = false;
            }
index ea18350b9f5f3b4b94bc3c3d62af79ce221e51fd..109cf0bc97d4dfb15b8fa2801dd2c980c855d0f4 100644 (file)
@@ -1,5 +1,5 @@
 /* Low-level checking of .debug_aranges.
-   Copyright (C) 2009, 2010 Red Hat, Inc.
+   Copyright (C) 2009, 2010, 2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
 #include "check_debug_info_i.hh"
 #include "cu_coverage_i.hh"
 
+namespace locus_simple_fmt
+{
+  char const *cudie_n ();
+};
+
+class cudie_locus
+  : public fixed_locus<sec_info,
+                      locus_simple_fmt::cudie_n,
+                      locus_simple_fmt::dec>
+{
+  typedef fixed_locus<sec_info,
+                     locus_simple_fmt::cudie_n,
+                     locus_simple_fmt::dec> _super_t;
+public:
+  template <class T>
+  cudie_locus (T const &die)
+    : _super_t (die.offset ())
+  {}
+
+  cudie_locus (Dwarf_Off offset)
+    : _super_t (offset)
+  {}
+};
+
+class arange_locus
+  : public locus
+{
+  Dwarf_Off _m_table_offset;
+  Dwarf_Off _m_arange_offset;
+  locus const *_m_cudie_locus;
+
+public:
+  explicit arange_locus (Dwarf_Off table_offset = -1,
+                        Dwarf_Off arange_offset = -1)
+    : _m_table_offset (table_offset)
+    , _m_arange_offset (arange_offset)
+    , _m_cudie_locus (NULL)
+  {}
+
+  explicit arange_locus (locus const &cudie_locus)
+    : _m_table_offset (-1)
+    , _m_arange_offset (-1)
+    , _m_cudie_locus (&cudie_locus)
+  {}
+
+  void
+  set_cudie (locus const *cudie_locus)
+  {
+    _m_cudie_locus = cudie_locus;
+  }
+
+  void
+  set_arange (Dwarf_Off arange_offset)
+  {
+    _m_arange_offset = arange_offset;
+  }
+
+  std::string format (bool brief = false) const;
+};
+
 class check_debug_aranges
   : public check<check_debug_aranges>
 {
index c880fd92fcf712c5c2e079ea30ae9c4f319d7d81..e415fb180a7f26ca3ec0a4452437b730bc3f4087 100644 (file)
@@ -43,7 +43,6 @@
 #include "check_debug_info.hh"
 #include "check_debug_line.hh"
 #include "check_debug_aranges.hh"
-#include "misc.hh"
 
 checkdescriptor const *
 read_cu_headers::descriptor ()
@@ -110,21 +109,18 @@ namespace
   }
 
   bool
-  check_die_references (struct cu *cu,
-                       struct ref_record *die_refs)
+  check_die_references (cu *cu, ref_record *die_refs)
   {
     bool retval = true;
-    for (size_t i = 0; i < die_refs->size; ++i)
-      {
-       struct ref *ref = die_refs->refs + i;
-       if (!addr_record_has_addr (&cu->die_addrs, ref->addr))
-         {
-           wr_error (ref->who)
-             << "unresolved reference to " << pri::DIE (ref->addr)
-             << '.' << std::endl;
-           retval = false;
-         }
-      }
+    for (ref_record::const_iterator it = die_refs->begin ();
+        it != die_refs->end (); ++it)
+      if (!cu->die_addrs.has_addr (it->addr))
+       {
+         wr_error (it->who)
+           << "unresolved reference to " << pri::DIE (it->addr)
+           << '.' << std::endl;
+         retval = false;
+       }
     return retval;
   }
 
@@ -133,12 +129,12 @@ namespace
   {
     bool retval = true;
     for (struct cu *it = cu_chain; it != NULL; it = it->next)
-      for (size_t i = 0; i < it->die_refs.size; ++i)
+      for (ref_record::const_iterator rt = it->die_refs.begin ();
+          rt != it->die_refs.end (); ++rt)
        {
-         struct ref *ref = it->die_refs.refs + i;
          struct cu *ref_cu = NULL;
          for (struct cu *jt = cu_chain; jt != NULL; jt = jt->next)
-           if (addr_record_has_addr (&jt->die_addrs, ref->addr))
+           if (jt->die_addrs.has_addr (rt->addr))
              {
                ref_cu = jt;
                break;
@@ -146,9 +142,9 @@ namespace
 
          if (ref_cu == NULL)
            {
-             wr_error (ref->who)
+             wr_error (rt->who)
                << "unresolved (non-CU-local) reference to "
-               << pri::hex (ref->addr) << '.' << std::endl;
+               << pri::hex (rt->addr) << '.' << std::endl;
              retval = false;
            }
          else if (ref_cu == it)
@@ -156,8 +152,8 @@ namespace
               reference is valid, which it is.  But warn about this
               anyway, perhaps local reference could be formed on
               smaller number of bytes.  */
-           wr_message (ref->who, mc_impact_2 | mc_acc_suboptimal | mc_die_rel)
-             << "local reference to " << pri::DIE (ref->addr)
+           wr_message (rt->who, mc_impact_2 | mc_acc_suboptimal | mc_die_rel)
+             << "local reference to " << pri::DIE (rt->addr)
              << " formed as global." << std::endl;
        }
 
@@ -178,12 +174,8 @@ namespace
     while (!read_ctx_eof (&ctx))
       {
        const unsigned char *cu_begin = ctx.ptr;
-       struct where where = WHERE (sec_info, NULL);
-       where_reset_1 (&where, read_ctx_get_offset (&ctx));
-
-       cu_head head;
-       head.offset = where.addr1;
-       head.where = where;
+       uint64_t offset = read_ctx_get_offset (&ctx);
+       cu_head head (offset);
 
        /* Reading CU head is a bit tricky, because we don't know if
           we have run into (superfluous but allowed) zero padding
@@ -192,7 +184,7 @@ namespace
        if (!read_ctx_need_data (&ctx, 4)
            && read_check_zero_padding (&ctx, &off_start, &off_end))
          {
-           wr_message_padding_0 (mc_info | mc_header, &where,
+           wr_message_padding_0 (mc_info | mc_header, head.where,
                                  off_start, off_end);
            break;
          }
@@ -205,25 +197,25 @@ namespace
        uint32_t size32;
        if (!read_ctx_read_4ubyte (&ctx, &size32))
          {
-           wr_error (where) << "can't read CU length." << std::endl;
+           wr_error (head.where) << "can't read CU length." << std::endl;
            throw check_base::failed ();
          }
        if (size32 == 0
            && read_check_zero_padding (&ctx, &off_start, &off_end))
          {
-           wr_message_padding_0 (mc_info | mc_header, &where,
+           wr_message_padding_0 (mc_info | mc_header, head.where,
                                  off_start, off_end);
            break;
          }
 
        Dwarf_Off cu_size;
        if (!read_size_extra (&ctx, size32, &cu_size,
-                             &head.offset_size, &where))
+                             &head.offset_size, head.where))
          throw check_base::failed ();
 
        if (!read_ctx_need_data (&ctx, cu_size))
          {
-           wr_error (where)
+           wr_error (head.where)
              << "section doesn't have enough data to read CU of size "
              << cu_size << '.' << std::endl;
            throw check_base::failed ();
@@ -243,7 +235,7 @@ namespace
        if (dwarf_version::get (version) == NULL)
          {
            wr_error (head.where) << "unsupported CU version "
-                                 << version << '.' << std::endl;
+                            << version << '.' << std::endl;
            throw check_base::failed ();
          }
        if (version == 2 && head.offset_size == 8) // xxx?
@@ -264,11 +256,11 @@ namespace
          }
 
        struct relocation *rel
-         = relocation_next (reloc, ctx_offset, &head.where, skip_ok);
+         = relocation_next (reloc, ctx_offset, head.where, skip_ok);
        if (rel != NULL)
          {
            relocate_one (file, reloc, rel, head.offset_size,
-                         &head.abbrev_offset, &head.where, sec_abbrev, NULL);
+                         &head.abbrev_offset, head.where, sec_abbrev, NULL);
            rel->invalid = true; // mark as invalid so it's skipped
                                 // next time we pass by this
          }
@@ -278,7 +270,7 @@ namespace
 
        /* Address size.  */
        error_code err = read_address_size (&ctx, file->addr_64,
-                                           &head.address_size, &head.where);
+                                           &head.address_size, head.where);
        if (err == err_fatal)
          throw check_base::failed ();
        else if (err == err_nohl)
@@ -290,7 +282,7 @@ namespace
 
        if (!read_ctx_skip (&ctx, head.size))
          {
-           wr_error (where) << pri::not_enough ("next CU") << std::endl;
+           wr_error (head.where) << pri::not_enough ("next CU") << std::endl;
            throw check_base::failed ();
          }
 
@@ -303,7 +295,7 @@ namespace
     return ret;
   }
 
-  section_id
+  rel_target
   reloc_target (form const *form, attribute const *attribute)
   {
     switch (form->name ())
@@ -318,12 +310,12 @@ namespace
          case DW_AT_low_pc:
          case DW_AT_high_pc:
          case DW_AT_entry_pc:
-           return rel_exec;
+           return rel_target::rel_exec;
 
          case DW_AT_const_value:
            /* Appears in some kernel modules.  It's not allowed by the
               standard, but leave that for high-level checks.  */
-           return rel_address;
+           return rel_target::rel_address;
          };
 
        break;
@@ -391,15 +383,15 @@ namespace
     std::cout << "XXX don't know how to handle form=" << *form
              << ", at=" << *attribute << std::endl;
 
-    return rel_value;
+    return rel_target::rel_value;
   }
 
   struct value_check_cb_ctx
   {
     struct read_ctx *const ctx;
-    struct where *const where;
+    die_locus const *where;
     struct cu *const cu;
-    struct ref_record *local_die_refs;
+    ref_record *local_die_refs;
     Elf_Data *strings;
     struct coverage *strings_coverage;
     struct coverage *pc_coverage;
@@ -426,15 +418,15 @@ namespace
     if (ctx->local_die_refs != NULL)
       /* Address holds a CU-local reference, so add CU offset
         to turn it into section offset.  */
-      ref_record_add (ctx->local_die_refs,
-                     addr + ctx->cu->head->offset, ctx->where);
+      ctx->local_die_refs->push_back (ref (addr + ctx->cu->head->offset,
+                                          *ctx->where));
   }
 
   /* Callback for global DIE references.  */
   void
   check_die_ref_global (uint64_t addr, struct value_check_cb_ctx const *ctx)
   {
-    ref_record_add (&ctx->cu->die_refs, addr, ctx->where);
+    ctx->cu->die_refs.push_back (ref (addr, *ctx->where));
   }
 
   /* Callback for strp values.  */
@@ -479,7 +471,7 @@ namespace
        << "rangeptr value " << pri::hex (value)
        << " not aligned to CU address size." << std::endl;
     *ctx->need_rangesp = true;
-    ref_record_add (&ctx->cu->range_refs, value, ctx->where);
+    ctx->cu->range_refs.push_back (ref (value, *ctx->where));
   }
 
   /* Callback for lineptr values.  */
@@ -489,21 +481,20 @@ namespace
     if (ctx->cu->stmt_list.addr != (uint64_t)-1)
       wr_error (*ctx->where)
        << "DW_AT_stmt_list mentioned twice in a CU." << std::endl;
-    ctx->cu->stmt_list.addr = value;
-    ctx->cu->stmt_list.who = *ctx->where;
+    ctx->cu->stmt_list = ref (value, *ctx->where);
   }
 
   /* Callback for locptr values.  */
   void
   check_locptr (uint64_t value, struct value_check_cb_ctx const *ctx)
   {
-    ref_record_add (&ctx->cu->loc_refs, value, ctx->where);
+    ctx->cu->loc_refs.push_back (ref (value, *ctx->where));
   }
 
   void
   check_decl_file (uint64_t value, struct value_check_cb_ctx const *ctx)
   {
-    ref_record_add (&ctx->cu->decl_file_refs, value, ctx->where);
+    ctx->cu->decl_file_refs.push_back (ref (value, *ctx->where));
   }
 
   /* The real sibling checking takes place down in read_die_chain.
@@ -515,7 +506,7 @@ namespace
     if (addr == 0)
       {
        wr_error (*ctx->where)
-         << "DW_AT_sibling with a value of 0." << std::endl;
+         << "has a value of 0." << std::endl;
        // Don't let this up.
        *ctx->retval_p = -2;
       }
@@ -533,14 +524,14 @@ namespace
   int
   read_die_chain (dwarf_version const *ver,
                  elf_file const &file,
-                 struct read_ctx *ctx,
-                 struct cu *cu,
-                 struct abbrev_table const *abbrevs,
+                 read_ctx *ctx,
+                 cu *cu,
+                 abbrev_table const *abbrevs,
                  Elf_Data *strings,
-                 struct ref_record *local_die_refs,
-                 struct coverage *strings_coverage,
-                 struct relocation_data *reloc,
-                 struct coverage *pc_coverage,
+                 ref_record *local_die_refs,
+                 coverage *strings_coverage,
+                 relocation_data *reloc,
+                 coverage *pc_coverage,
                  bool *need_rangesp,
                  unsigned level)
   {
@@ -548,12 +539,11 @@ namespace
     uint64_t sibling_addr = 0;
     uint64_t die_off, prev_die_off = 0;
     struct abbrev *abbrev = NULL;
-    struct where where = WHERE (sec_info, NULL);
     unsigned long die_count = 0;
     int retval = 0;
 
     struct value_check_cb_ctx cb_ctx = {
-      ctx, &where, cu,
+      ctx, NULL, cu,
       local_die_refs,
       strings, strings_coverage,
       pc_coverage,
@@ -563,20 +553,18 @@ namespace
 
     while (!read_ctx_eof (ctx))
       {
-       where = cu->head->where;
        die_off = read_ctx_get_offset (ctx);
        /* Shift reported DIE offset by CU offset, to match the way
           readelf reports DIEs.  */
-       where_reset_2 (&where, die_off + cu->head->offset);
+       die_locus where (cu->head->offset + die_off);
+       cb_ctx.where = &where;
 
        uint64_t abbr_code;
 
-       if (!checked_read_uleb128 (ctx, &abbr_code, &where, "abbrev code"))
+       if (!checked_read_uleb128 (ctx, &abbr_code, where, "abbrev code"))
          return -1;
 
-#define DEF_PREV_WHERE                                                 \
-       struct where prev_where = where;                                \
-       where_reset_2 (&prev_where, prev_die_off + cu->head->offset)
+#define DEF_PREV_WHERE die_locus prev_where (cu->head->offset + prev_die_off)
 
        /* Check sibling value advertised last time through the loop.  */
        if (sibling_addr != 0)
@@ -662,7 +650,7 @@ namespace
              }
          }
 
-       addr_record_add (&cu->die_addrs, cu->head->offset + die_off);
+       cu->die_addrs.add (cu->head->offset + die_off);
 
        uint64_t low_pc = (uint64_t)-1, high_pc = (uint64_t)-1;
        bool low_pc_relocated = false, high_pc_relocated = false;
@@ -674,7 +662,7 @@ namespace
        for (struct abbrev_attrib *it = abbrev->attribs;
             it->name != 0 || it->form != 0; ++it)
          {
-           where.ref = &it->where;
+           where.set_attrib_name (it->name);
            int form_name = it->form;
 
            // In following, attribute may be NULL, but form never
@@ -688,11 +676,11 @@ namespace
              {
                uint64_t value;
                if (!read_sc_value (&value, form->width (cu->head),
-                                   ctx, &where))
+                                   ctx, where))
                  return -1;
                form_name = value;
                form = check_debug_abbrev::check_form
-                 (ver, attribute, form_name, &where, true);
+                 (ver, attribute, form_name, where, true);
                // N.B. check_form emits appropriate error messages.
                if (form == NULL)
                  return -1;
@@ -846,7 +834,7 @@ namespace
 
            storage_class_t storclass = form->storage_class ();
            if (!read_generic_value (ctx, form->width (cu->head), storclass,
-                                    &where, &value, &block))
+                                    where, &value, &block))
              {
                // Note that for fw_uleb and fw_sleb we report the
                // error the second time now.
@@ -866,18 +854,18 @@ namespace
                    // field?  See check_debug_loc_range::op_read_form
                    if (!check_location_expression
                        (ver, file, &block, cu,
-                        expr_start, reloc, value, &where))
+                        expr_start, reloc, value, where))
                      return -1;
                  }
                else
                  relocation_skip (reloc, read_ctx_get_offset (ctx),
-                                  &where, skip_mismatched);
+                                  where, skip_mismatched);
              }
 
            /* Relocate the value if appropriate.  */
            struct relocation *rel;
            if ((rel = relocation_next (reloc, ctx_offset,
-                                       &where, skip_mismatched)))
+                                       where, skip_mismatched)))
              {
                if (relocate == rel_no)
                  wr_message (where, (mc_impact_4 | mc_die_other
@@ -889,7 +877,7 @@ namespace
                if (attribute != NULL)
                  {
                    form_width_t width = form->width (cu->head);
-                   relocate_one (&file, reloc, rel, width, &value, &where,
+                   relocate_one (&file, reloc, rel, width, &value, where,
                                  reloc_target (form, attribute), symbolp);
                  }
 
@@ -899,7 +887,7 @@ namespace
            else
              {
                if (symbolp != NULL)
-                 WIPE (*symbolp);
+                 memset (*symbolp, 0, sizeof (**symbolp));
                if (type_is_rel
                    && (relocate == rel_require
                        || (relocate == rel_nonzero
@@ -931,7 +919,7 @@ namespace
            if (valuep != NULL)
              *valuep = value;
          }
-       where.ref = NULL;
+       where.set_attrib_name (-1);
 
        if (high_pc != (uint64_t)-1 && low_pc != (uint64_t)-1
            && high_pc_relative)
@@ -963,7 +951,7 @@ namespace
            else
              {
                if (!high_pc_relative)
-                 check_range_relocations (mc_die_other, &where,
+                 check_range_relocations (where, mc_die_other,
                                           &file,
                                           low_pc_symbol, high_pc_symbol,
                                           "DW_AT_low_pc and DW_AT_high_pc");
@@ -976,8 +964,6 @@ namespace
              }
          }
 
-       where.ref = &abbrev->where;
-
        if (abbrev->has_children)
          {
            int st = read_die_chain (ver, file, ctx, cu, abbrevs, strings,
@@ -1007,7 +993,7 @@ namespace
       }
 
     if (sibling_addr != 0)
-      wr_error (where)
+      wr_error (die_locus (cu->head->offset + prev_die_off))
        << "this DIE should have had its sibling at " << pri::hex (sibling_addr)
        << ", but the DIE chain ended." << std::endl;
 
@@ -1036,7 +1022,7 @@ check_debug_info::check_cu_structural (struct read_ctx *ctx,
   check_debug_abbrev::abbrev_map const &abbrev_tables = _m_abbrevs->abbrevs;
 
   if (dump_die_offsets)
-    fprintf (stderr, "%s: CU starts\n", where_fmt (&cu->head->where, NULL));
+    fprintf (stderr, "%s: CU starts\n", cu->head->where.format ().c_str ());
   bool retval = true;
 
   dwarf_version const *ver = dwarf_version::get (cu->head->version);
@@ -1055,8 +1041,7 @@ check_debug_info::check_cu_structural (struct read_ctx *ctx,
   struct abbrev_table const &abbrevs = abbrev_it->second;
 
   /* Read DIEs.  */
-  struct ref_record local_die_refs;
-  WIPE (local_die_refs);
+  ref_record local_die_refs;
 
   cu->cudie_offset = read_ctx_get_offset (ctx) + cu->head->offset;
   int st = read_die_chain (ver, _m_file, ctx, cu, &abbrevs, strings,
@@ -1074,7 +1059,6 @@ check_debug_info::check_cu_structural (struct read_ctx *ctx,
   else if (!check_die_references (cu, &local_die_refs))
     retval = false;
 
-  ref_record_free (&local_die_refs);
   return retval;
 }
 
@@ -1090,8 +1074,7 @@ check_debug_info::check_debug_info (checkstack &stack, dwarflint &lint)
   sec &sec = _m_sec_info->sect;
   Elf_Data *const strings = _m_sec_str->sect.data;
 
-  struct ref_record die_refs;
-  WIPE (die_refs);
+  ref_record die_refs;
 
   bool success = true;
 
@@ -1109,7 +1092,7 @@ check_debug_info::check_debug_info (checkstack &stack, dwarflint &lint)
        it != cu_headers.end (); ++it)
     {
       cu_head const &head = *it;
-      where const &where = head.where;
+      cu_locus where = head.where;
       {
        cu cur;
        memset (&cur, 0, sizeof (cur));
@@ -1140,13 +1123,13 @@ check_debug_info::check_debug_info (checkstack &stack, dwarflint &lint)
        {
          uint64_t off_start, off_end;
          if (read_check_zero_padding (&cu_ctx, &off_start, &off_end))
-           wr_message_padding_0 (mc_info, &where, off_start, off_end);
+           wr_message_padding_0 (mc_info, where, off_start, off_end);
          else
            {
              // Garbage coordinates:
              uint64_t start = read_ctx_get_offset (&ctx) + off_start;
              uint64_t end = read_ctx_get_offset (&ctx) + head.total_size;
-             wr_message_padding_n0 (mc_info, &where, start, end);
+             wr_message_padding_n0 (mc_info, where, start, end);
            }
        }
 
@@ -1156,16 +1139,14 @@ check_debug_info::check_debug_info (checkstack &stack, dwarflint &lint)
 
   if (success)
     {
+      section_locus wh (sec_info);
       if (ctx.ptr != ctx.end)
        /* Did we read up everything?  */
-       {
-         where wh = WHERE (sec_info, NULL);
-         wr_message (mc_die_other | mc_impact_4, &wh,
-                     ": CU lengths don't exactly match Elf_Data contents.");
-       }
+       wr_message (mc_die_other | mc_impact_4, &wh,
+                   ": CU lengths don't exactly match Elf_Data contents.");
       else
        /* Did we consume all the relocations?  */
-       relocation_skip_rest (&sec.rel, sec.id);
+       relocation_skip_rest (&sec.rel, wh);
 
       /* If we managed to read up everything, now do abbrev usage
         analysis.  */
@@ -1203,7 +1184,6 @@ check_debug_info::check_debug_info (checkstack &stack, dwarflint &lint)
      that's not necessary anymore.  */
 
   check_global_die_references (!cus.empty () ? &cus.front () : NULL);
-  ref_record_free (&die_refs);
 
   if (strings_coverage != NULL)
     {
@@ -1225,15 +1205,6 @@ check_debug_info::check_debug_info (checkstack &stack, dwarflint &lint)
 
 check_debug_info::~check_debug_info ()
 {
-  for (std::vector<cu>::iterator it = cus.begin ();
-       it != cus.end (); ++it)
-    {
-      addr_record_free (&it->die_addrs);
-      ref_record_free (&it->die_refs);
-      ref_record_free (&it->range_refs);
-      ref_record_free (&it->loc_refs);
-      ref_record_free (&it->decl_file_refs);
-    }
 }
 
 cu *
@@ -1279,8 +1250,9 @@ check_debug_info_refs::check_debug_info_refs (checkstack &stack,
        it != _m_info->cus.end (); ++it)
     {
       if (it->stmt_list.addr == (uint64_t)-1)
-       for (size_t i = 0; i < it->decl_file_refs.size; ++i)
-         wr_error (it->decl_file_refs.refs[i].who)
+       for (ref_record::const_iterator jt = it->decl_file_refs.begin ();
+            jt != it->decl_file_refs.end (); ++jt)
+         wr_error (jt->who)
            << "references .debug_line table, but CU DIE lacks DW_AT_stmt_list."
            << std::endl;
       else if (_m_line == NULL
index 2c93f09c720a14fe61ffa2228e27070935d03034..e8dc8506930d5f9aa064d3129adb5d7285ba199f 100644 (file)
 #include "check_debug_line_i.hh"
 #include "check_debug_aranges_i.hh"
 #include "sections_i.hh"
+#include "die_locus.hh"
+
+typedef ref_T<die_locus> ref;
+typedef ref_record_T<die_locus> ref_record;
 
 struct cu_head
 {
-  uint64_t offset;
+  Dwarf_Off offset;
   Dwarf_Off size;               // Size of this CU.
   Dwarf_Off head_size;          // Size from begin to 1st byte of CU.
   Dwarf_Off total_size;         // size + head_size
 
-  int offset_size;               // Offset size in this CU.
-  struct where where;           // Where this section was defined.
+  int offset_size;              // Offset size in this CU.
   Dwarf_Off abbrev_offset;      // Abbreviation section that this CU uses.
   int version;                  // CU version
   int address_size;             // Address size in bytes on the target machine.
+
+  cu_locus where;
+
+  explicit cu_head (Dwarf_Off a_offset)
+    : offset (a_offset)
+    , size (0)
+    , head_size (0)
+    , total_size (0)
+    , offset_size (0)
+    , abbrev_offset (0)
+    , version (0)
+    , address_size (0)
+    , where (a_offset)
+  {}
 };
 
 struct cu
 {
   struct cu *next;              // For compatibility with C level.
                                 // xxx will probably go away eventually
-  struct cu_head const *head;
+  cu_head const *head;
   uint64_t cudie_offset;
   uint64_t low_pc;              // DW_AT_low_pc value of CU DIE, -1 if not present.
-  struct ref stmt_list;
-  struct addr_record die_addrs; // Addresses where DIEs begin in this CU.
-  struct ref_record die_refs;   // DIE references into other CUs from this CU.
-  struct ref_record loc_refs;   // references into .debug_loc from this CU.
-  struct ref_record range_refs; // references into .debug_ranges from this CU.
-  struct ref_record decl_file_refs;  // values of DW_AT_decl_file in this CU.
+  ::ref stmt_list;
+  addr_record die_addrs;        // Addresses where DIEs begin in this CU.
+  ref_record die_refs;          // DIE references into other CUs from this CU.
+  ref_record loc_refs;          // references into .debug_loc from this CU.
+  ref_record range_refs;        // references into .debug_ranges from this CU.
+  ref_record decl_file_refs;    // values of DW_AT_decl_file in this CU.
   bool has_arange;              // Whether we saw arange section pointing at this CU.
   bool has_pubnames;            // Likewise for pubnames.
   bool has_pubtypes;            // Likewise for pubtypes.
+
+  cu ()
+    : next (NULL)
+    , head (NULL)
+    , cudie_offset (0)
+    , low_pc (0)
+    , has_arange (false)
+    , has_pubnames (false)
+    , has_pubtypes (false)
+  {}
 };
 
 /** The pass for reading basic .debug_info data -- the layout of
index 93637238e90c6a3a4732293400aa100b5db77d1e..d75aed2bd034f41dfc267dcfdef0dabebc5215a9 100644 (file)
    Network licensing program, please visit www.openinventionnetwork.com
    <http://www.openinventionnetwork.com>.  */
 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
 #include "check_debug_line.hh"
 #include "check_debug_info.hh"
 #include "sections.hh"
@@ -97,15 +101,15 @@ namespace
   bool read_directory_index (include_directories_t &include_directories,
                             files_t &files, read_ctx *ctx,
                             const char *name, uint64_t *ptr,
-                            where *where, bool &retval)
+                            locus const &loc, bool &retval)
   {
     size_t nfile = files.size () + 1;
     if (!checked_read_uleb128 (ctx, ptr,
-                              where, "directory index"))
+                              loc, "directory index"))
       return false;
 
     if (*name == '/' && *ptr != 0)
-      wr_message (*where, mc_impact_2 | mc_line | mc_header)
+      wr_message (loc, mc_impact_2 | mc_line | mc_header)
        << "file #" << nfile
        << " has absolute pathname, but refers to directory != 0."
        << std::endl;
@@ -113,7 +117,7 @@ namespace
     if (*ptr > include_directories.size ())
       /* Not >=, dirs are indexed from 1.  */
       {
-       wr_message (*where, mc_impact_4 | mc_line | mc_header)
+       wr_message (loc, mc_impact_4 | mc_line | mc_header)
          << "file #" << nfile
          << " refers to directory #" << *ptr
          << ", which wasn't defined." << std::endl;
@@ -128,11 +132,11 @@ namespace
 
   bool
   use_file (files_t &files, uint64_t file_idx,
-           where *where, char const *msg = "")
+           locus const &loc, char const *msg = "")
   {
     if (file_idx == 0 || file_idx > files.size ())
       {
-       wr_error (*where)
+       wr_error (loc)
          << msg << "invalid file index " << file_idx << '.'
          << std::endl;
        return false;
@@ -143,6 +147,18 @@ namespace
   }
 }
 
+namespace
+{
+  char const *
+  table_n ()
+  {
+    return "table";
+  }
+
+  typedef fixed_locus<sec_line, table_n,
+                     locus_simple_fmt::dec> line_table_locus;
+}
+
 check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
   : _m_sec (lint.check (stack, _m_sec))
   , _m_info (lint.toplev_check (stack, _m_info))
@@ -156,9 +172,8 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
 
   while (!read_ctx_eof (&ctx))
     {
-      struct where where = WHERE (_m_sec->sect.id, NULL);
       uint64_t set_offset = read_ctx_get_offset (&ctx);
-      where_reset_1 (&where, set_offset);
+      line_table_locus where (set_offset);
       _m_line_tables.insert ((Dwarf_Off)set_offset);
       const unsigned char *set_begin = ctx.ptr;
 
@@ -171,7 +186,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
          wr_error (where) << "can't read table length." << std::endl;
          throw check_base::failed ();
        }
-      if (!read_size_extra (&ctx, size32, &size, &offset_size, &where))
+      if (!read_size_extra (&ctx, size32, &size, &offset_size, where))
        throw check_base::failed ();
 
       struct read_ctx sub_ctx;
@@ -196,7 +211,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
          success = false;
          goto next;
        }
-      if (!supported_version (version, 2, &where, 2, 3))
+      if (!supported_version (version, 2, where, 2, 3))
        goto skip;
 
       /* Header length.  */
@@ -310,19 +325,19 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
 
          uint64_t dir_idx;
          if (!read_directory_index (include_directories, files,
-                                    &sub_ctx, name, &dir_idx, &where, success))
+                                    &sub_ctx, name, &dir_idx, where, success))
            goto skip;
 
          /* Time of last modification.  */
          uint64_t timestamp;
          if (!checked_read_uleb128 (&sub_ctx, &timestamp,
-                                    &where, "timestamp of file entry"))
+                                    where, "timestamp of file entry"))
            goto skip;
 
          /* Size of the file.  */
          uint64_t file_size;
          if (!checked_read_uleb128 (&sub_ctx, &file_size,
-                                    &where, "file size of file entry"))
+                                    where, "file size of file entry"))
            goto skip;
 
          files.push_back ((struct file_t){name, dir_idx, false});
@@ -340,10 +355,10 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
            if (it->stmt_list.addr == set_offset)
              {
                found = true;
-               for (size_t i = 0; i < it->decl_file_refs.size; ++i)
-                 if (!use_file (files,
-                                it->decl_file_refs.refs[i].addr,
-                                &it->decl_file_refs.refs[i].who))
+               for (ref_record::const_iterator
+                      jt = it->decl_file_refs.begin ();
+                    jt != it->decl_file_refs.end (); ++jt)
+                 if (!use_file (files, jt->addr, jt->who))
                    success = false;
              }
          if (!found)
@@ -368,14 +383,14 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
       else if (sub_ctx.ptr < program_start)
        {
          /* Skip the rest of the header.  */
-         struct where wh = WHERE (sec_line, NULL);
          uint64_t off_start, off_end;
          if (read_check_zero_padding (&sub_ctx, &off_start, &off_end))
-           wr_message_padding_0 (mc_line | mc_header, &wh,
+           wr_message_padding_0 (mc_line | mc_header, section_locus (sec_line),
                                  off_start, off_end);
          else
-           wr_message_padding_n0 (mc_line | mc_header, &wh,
-                                  off_start, program_start - sub_ctx.begin);
+           wr_message_padding_n0
+             (mc_line | mc_header, section_locus (sec_line),
+              off_start, program_start - sub_ctx.begin);
          sub_ctx.ptr = program_start;
        }
 
@@ -384,11 +399,11 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
       bool seen_opcode = false;
       while (!read_ctx_eof (&sub_ctx))
        {
-         where_reset_2 (&where, read_ctx_get_offset (&sub_ctx));
+         section_locus op_where (sec_line, read_ctx_get_offset (&sub_ctx));
          uint8_t opcode;
          if (!read_ctx_read_ubyte (&sub_ctx, &opcode))
            {
-             wr_error (where) << "can't read opcode." << std::endl;
+             wr_error (op_where) << "can't read opcode." << std::endl;
              goto skip;
            }
 
@@ -400,12 +415,12 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
            case 0:
              {
                uint64_t skip_len;
-               if (!checked_read_uleb128 (&sub_ctx, &skip_len, &where,
+               if (!checked_read_uleb128 (&sub_ctx, &skip_len, op_where,
                                           "length of extended opcode"))
                  goto skip;
                if (!read_ctx_need_data (&sub_ctx, skip_len))
                  {
-                   wr_error (where)
+                   wr_error (op_where)
                      << "not enough data to read an opcode of length "
                      << skip_len << '.' << std::endl;
                    goto skip;
@@ -414,7 +429,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
                const unsigned char *next = sub_ctx.ptr + skip_len;
                if (!read_ctx_read_ubyte (&sub_ctx, &extended))
                  {
-                   wr_error (where)
+                   wr_error (op_where)
                      << "can't read extended opcode." << std::endl;
                    goto skip;
                  }
@@ -432,7 +447,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
                      uint64_t addr;
                      if (!read_ctx_read_offset (&sub_ctx, addr_64, &addr))
                        {
-                         wr_error (where)
+                         wr_error (op_where)
                            << "can't read operand of DW_LNE_set_address."
                            << std::endl;
                          goto skip;
@@ -440,13 +455,14 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
 
                      struct relocation *rel;
                      if ((rel = relocation_next (&_m_sec->sect.rel, ctx_offset,
-                                                 &where, skip_mismatched)))
+                                                 op_where, skip_mismatched)))
                        relocate_one (&_m_sec->file, &_m_sec->sect.rel, rel,
-                                     addr_64 ? 8 : 4,
-                                     &addr, &where, rel_address, NULL);
+                                     addr_64 ? 8 : 4, &addr, op_where,
+                                     rel_target::rel_address, NULL);
                      else if (_m_sec->file.ehdr.e_type == ET_REL)
                        {
-                         wr_message (where, mc_impact_2 | mc_line | mc_reloc)
+                         wr_message (op_where,
+                                     mc_impact_2 | mc_line | mc_reloc)
                            << pri::lacks_relocation ("DW_LNE_set_address")
                            << '.' << std::endl;
 
@@ -455,7 +471,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
                        }
 
                      if (addr == 0)
-                       wr_message (where, mc_line | mc_impact_1)
+                       wr_message (op_where, mc_line | mc_impact_1)
                          << "DW_LNE_set_address with zero operand."
                          << std::endl;
                      break;
@@ -466,7 +482,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
                      /* XXX Is there anything interesting we should
                         check here?  */
                      uint64_t disc;
-                     if (!checked_read_uleb128 (&sub_ctx, &disc, &where,
+                     if (!checked_read_uleb128 (&sub_ctx, &disc, op_where,
                                                 "set_discriminator operand"))
                        goto skip;
 
@@ -474,7 +490,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
                         sequence change.  So setting to zero is never
                         necessary.  */
                      if (disc == 0)
-                       wr_message (where, mc_line | mc_impact_1)
+                       wr_message (op_where, mc_line | mc_impact_1)
                          << "DW_LNE_set_discriminator with zero operand."
                          << std::endl;
                      break;
@@ -485,7 +501,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
                      const char *name;
                      if ((name = read_ctx_read_str (&sub_ctx)) == NULL)
                        {
-                         wr_error (where)
+                         wr_error (op_where)
                            << "can't read filename operand of DW_LNE_define_file."
                            << std::endl;
                          goto skip;
@@ -493,7 +509,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
                      uint64_t dir_idx;
                      if (!read_directory_index (include_directories,
                                                 files, &sub_ctx, name,
-                                                &dir_idx, &where, success))
+                                                &dir_idx, op_where, success))
                        goto skip;
                      files.push_back
                        ((struct file_t){name, dir_idx, false});
@@ -510,7 +526,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
 #undef ONE_KNOWN_DW_LNE
                      default:
                        /* No we don't, emit a warning.  */
-                       wr_message (where, mc_impact_2 | mc_line)
+                       wr_message (op_where, mc_impact_2 | mc_line)
                          << "unknown extended opcode 0x"
                          << std::hex << +extended << std::dec
                          << '.' << std::endl;
@@ -519,7 +535,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
 
                if (sub_ctx.ptr > next)
                  {
-                   wr_error (where)
+                   wr_error (op_where)
                      << "opcode claims that it has a size of " << skip_len
                      << ", but in fact it has a size of "
                      << (skip_len + (next - sub_ctx.ptr)) << '.' << std::endl;
@@ -530,15 +546,15 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
                    uint64_t off_start, off_end;
                    if (handled)
                      {
-                       struct where wh = WHERE (sec_line, NULL);
                        if (read_check_zero_padding (&sub_ctx,
                                                     &off_start, &off_end))
-                         wr_message_padding_0 (mc_line, &wh,
-                                               off_start, off_end);
+                         wr_message_padding_0
+                           (mc_line, section_locus (sec_line),
+                            off_start, off_end);
                        else
-                         wr_message_padding_n0 (mc_line, &wh,
-                                                off_start,
-                                                next - sub_ctx.begin);
+                         wr_message_padding_n0
+                           (mc_line, section_locus (sec_line),
+                            off_start, next - sub_ctx.begin);
                      }
                    sub_ctx.ptr = next;
                  }
@@ -550,7 +566,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
            case DW_LNS_advance_line:
              {
                int64_t line_delta;
-               if (!checked_read_sleb128 (&sub_ctx, &line_delta, &where,
+               if (!checked_read_sleb128 (&sub_ctx, &line_delta, op_where,
                                           "DW_LNS_advance_line operand"))
                  goto skip;
              }
@@ -561,7 +577,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
                uint16_t a;
                if (!read_ctx_read_2ubyte (&sub_ctx, &a))
                  {
-                   wr_error (where)
+                   wr_error (op_where)
                      << "can't read operand of DW_LNS_fixed_advance_pc."
                      << std::endl;
                    goto skip;
@@ -572,10 +588,10 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
            case DW_LNS_set_file:
              {
                uint64_t file_idx;
-               if (!checked_read_uleb128 (&sub_ctx, &file_idx, &where,
+               if (!checked_read_uleb128 (&sub_ctx, &file_idx, op_where,
                                           "DW_LNS_set_file operand"))
                  goto skip;
-               if (!use_file (files, file_idx, &where, "DW_LNS_set_file: "))
+               if (!use_file (files, file_idx, op_where, "DW_LNS_set_file: "))
                  success = false;
                first_file = false;
              }
@@ -599,7 +615,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
 
                default:
                  if (opcode < opcode_base)
-                   wr_message (where, mc_impact_2 | mc_line)
+                   wr_message (op_where, mc_impact_2 | mc_line)
                      << "unknown standard opcode 0x"
                      << std::hex << +opcode << std::dec
                      << '.' << std::endl;
@@ -616,13 +632,13 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
              else
                sprintf (buf, "operand #%d of DW_LNE_%s",
                         i, dwarf_line_extended_opcode_string (extended));
-             if (!checked_read_uleb128 (&sub_ctx, &operand, &where, buf))
+             if (!checked_read_uleb128 (&sub_ctx, &operand, op_where, buf))
                goto skip;
            }
 
          if (first_file)
            {
-             if (!use_file (files, 1, &where,
+             if (!use_file (files, 1, op_where,
                             "initial value of `file' register: "))
                success = false;
              first_file = false;
@@ -661,7 +677,6 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
              << std::endl;
        }
 
-      struct where wh = WHERE (sec_line, NULL);
       if (!terminated && seen_opcode)
        wr_error (where)
          << "sequence of opcodes not terminated with DW_LNE_end_sequence."
@@ -670,9 +685,10 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
        {
          uint64_t off_start, off_end;
          if (read_check_zero_padding (&sub_ctx, &off_start, &off_end))
-           wr_message_padding_0 (mc_line, &wh, off_start, off_end);
+           wr_message_padding_0
+             (mc_line, section_locus (sec_line), off_start, off_end);
          else
-           wr_message_padding_n0 (mc_line, &wh,
+           wr_message_padding_n0 (mc_line, section_locus (sec_line),
                                   off_start, sub_ctx.end - sub_ctx.begin);
        }
       }
@@ -683,7 +699,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
     }
 
   if (success)
-    relocation_skip_rest (&_m_sec->sect.rel, _m_sec->sect.id);
+    relocation_skip_rest (&_m_sec->sect.rel, section_locus (_m_sec->sect.id));
   else
     throw check_base::failed ();
 }
index 74b4d272ee4db8a73fbb0ce57d5937a24fcb0a26..5d680815e73d4d3bff19fe97639f37c188849e22 100644 (file)
 
 bool do_range_coverage = false; // currently no option
 
+global_opt<void_option>
+  opt_show_refs("\
+When validating .debug_loc and .debug_ranges, display information about \
+the DIE referring to the entry in consideration", "ref");
+
+std::string
+loc_range_locus::format (bool brief) const
+{
+  std::stringstream ss;
+  if (!brief)
+    ss << section_name[_m_sec] << ": ";
+
+  if (_m_sec == sec_loc)
+    ss << "loclist";
+  else
+    ss << "rangelist";
+
+  if (_m_offset != (Dwarf_Off)-1)
+    ss << " 0x" << std::hex << _m_offset;
+
+  if (opt_show_refs)
+    ss << ", ref. by " << _m_refby.format (true);
+
+  return ss.str ();
+}
+
 checkdescriptor const *
 check_debug_ranges::descriptor ()
 {
@@ -143,7 +169,7 @@ namespace
 
   struct hole_env
   {
-    struct where *where;
+    locus const &loc;
     uint64_t address;
     uint64_t end;
   };
@@ -154,7 +180,7 @@ namespace
     hole_env *env = (hole_env *)xenv;
     char buf[128], buf2[128];
     assert (h_length != 0);
-    wr_error (env->where,
+    wr_error (&env->loc,
              ": portion %s of the range %s "
              "doesn't fall into any ALLOC section.\n",
              range_fmt (buf, sizeof buf,
@@ -176,7 +202,6 @@ namespace
   {
     struct coverage_map_hole_info *info = (struct coverage_map_hole_info *)user;
 
-    struct where where = WHERE (info->info.section, NULL);
     const char *scnname = sco->sec->name;
 
     struct sec *sec = sco->sec;
@@ -215,9 +240,10 @@ namespace
       return true;
 
     char buf[128];
-    wr_message (info->info.category | mc_acc_suboptimal | mc_impact_4, &where,
-               ": addresses %s of section %s are not covered.\n",
-               range_fmt (buf, sizeof buf, begin + base, end + base), scnname);
+    wr_message (section_locus (info->info.section),
+               info->info.category | mc_acc_suboptimal | mc_impact_4)
+      << "addresses " << range_fmt (buf, sizeof buf, begin + base, end + base)
+      << " of section " << scnname << " are not covered.\n";
     return true;
   }
 
@@ -257,7 +283,7 @@ namespace
   coverage_map_add (struct coverage_map *coverage_map,
                    uint64_t address,
                    uint64_t length,
-                   struct where *where,
+                   locus const &loc,
                    enum message_category cat)
   {
     bool found = false;
@@ -285,7 +311,7 @@ namespace
        if (found && !crosses_boundary)
          {
            /* While probably not an error, it's very suspicious.  */
-           wr_message (cat | mc_impact_2, where,
+           wr_message (cat | mc_impact_2, &loc,
                        ": the range %s crosses section boundaries.\n",
                        range_fmt (buf, sizeof buf, address, end));
            crosses_boundary = true;
@@ -313,14 +339,14 @@ namespace
            && cov->is_overlap (cov_begin, cov_end - cov_begin))
          {
            /* Not a show stopper, this shouldn't derail high-level.  */
-           wr_message (*where, cat | mc_aranges | mc_impact_2 | mc_error)
+           wr_message (loc, cat | mc_aranges | mc_impact_2 | mc_error)
              << "the range " << range_fmt (buf, sizeof buf, address, end)
              << " overlaps with another one." << std::endl;
            overlap = true;
          }
 
        if (sco->warn)
-         wr_message (cat | mc_impact_2, where,
+         wr_message (cat | mc_impact_2, &loc,
                      ": the range %s covers section %s.\n",
                      range_fmt (buf, sizeof buf, address, end), sco->sec->name);
 
@@ -334,12 +360,12 @@ namespace
 
     if (!found)
       /* Not a show stopper.  */
-      wr_error (where,
+      wr_error (&loc,
                ": couldn't find a section that the range %s covers.\n",
                range_fmt (buf, sizeof buf, address, end));
     else if (length > 0)
       {
-       hole_env env = {where, address, end};
+       hole_env env = {loc, address, end};
        range_cov.find_holes (0, length, range_hole, &env);
       }
   }
@@ -354,7 +380,7 @@ namespace
                          struct coverage_map *coverage_map,
                          struct coverage *pc_coverage,
                          uint64_t addr,
-                         struct where const *wh,
+                         locus const &loc,
                          enum message_category cat)
   {
     char buf[128]; // messages
@@ -368,7 +394,7 @@ namespace
     read_ctx_init (&ctx, parent_ctx->data, file->other_byte_order);
     if (!read_ctx_skip (&ctx, addr))
       {
-       wr_error (wh, ": invalid reference outside the section "
+       wr_error (&loc, ": invalid reference outside the section "
                  "%#" PRIx64 ", size only %#tx.\n",
                  addr, ctx.end - ctx.begin);
        return false;
@@ -379,7 +405,7 @@ namespace
 
     if (coverage->is_covered (addr, 1))
       {
-       wr_error (wh, ": reference to %#" PRIx64
+       wr_error (&loc, ": reference to %#" PRIx64
                  " points into another location or range list.\n", addr);
        retval = false;
       }
@@ -391,8 +417,8 @@ namespace
     uint64_t base = cu->low_pc;
     while (!read_ctx_eof (&ctx))
       {
-       struct where where = WHERE (sec->id, wh);
-       where_reset_1 (&where, read_ctx_get_offset (&ctx));
+       uint64_t offset = read_ctx_get_offset (&ctx);
+       loc_range_locus where (sec->id, loc, offset);
 
 #define HAVE_OVERLAP                                           \
        do {                                                    \
@@ -418,11 +444,12 @@ namespace
 
        struct relocation *rel;
        if ((rel = relocation_next (&sec->rel, begin_off,
-                                   &where, skip_mismatched)))
+                                   where, skip_mismatched)))
          {
            begin_relocated = true;
            relocate_one (file, &sec->rel, rel, cu->head->address_size,
-                         &begin_addr, &where, rel_value,       &begin_symbol);
+                         &begin_addr, where, rel_target::rel_value,
+                         &begin_symbol);
          }
 
        /* end address */
@@ -442,18 +469,18 @@ namespace
          }
 
        if ((rel = relocation_next (&sec->rel, end_off,
-                                   &where, skip_mismatched)))
+                                   where, skip_mismatched)))
          {
            end_relocated = true;
            relocate_one (file, &sec->rel, rel, cu->head->address_size,
-                         &end_addr, &where, rel_value, &end_symbol);
+                         &end_addr, where, rel_target::rel_value, &end_symbol);
            if (begin_addr != escape)
              {
                if (!begin_relocated)
                  wr_message (cat | mc_impact_2 | mc_reloc, &where,
                              ": end of address range is relocated, but the beginning wasn't.\n");
                else
-                 check_range_relocations (cat, &where, file,
+                 check_range_relocations (where, cat, file,
                                           begin_symbol, end_symbol,
                                           "begin and end address");
              }
@@ -492,7 +519,7 @@ namespace
                uint64_t address = begin_addr + base;
                uint64_t length = end_addr - begin_addr;
                if (coverage_map != NULL)
-                 coverage_map_add (coverage_map, address, length, &where, cat);
+                 coverage_map_add (coverage_map, address, length, where, cat);
                if (pc_coverage != NULL)
                  pc_coverage->add (address, length);
              }
@@ -516,7 +543,7 @@ namespace
                /* location expression itself */
                uint64_t expr_start = read_ctx_get_offset (&ctx);
                if (!check_location_expression
-                   (ver, *file, &ctx, cu, expr_start, &sec->rel, len, &where))
+                   (ver, *file, &ctx, cu, expr_start, &sec->rel, len, where))
                  return false;
                uint64_t expr_end = read_ctx_get_offset (&ctx);
                if (!overlap
@@ -542,7 +569,7 @@ namespace
          }
 #undef HAVE_OVERLAP
 
-       coverage->add (where.addr1, read_ctx_get_offset (&ctx) - where.addr1);
+       coverage->add (offset, read_ctx_get_offset (&ctx) - offset);
        if (done)
          break;
       }
@@ -552,9 +579,12 @@ namespace
 
   struct ref_cu
   {
-    struct ref ref;
-    struct cu *cu;
-    bool operator < (ref_cu const& other) const {
+    ::ref ref;
+    ::cu *cu;
+
+    bool
+    operator < (ref_cu const& other) const
+    {
       return ref.addr < other.ref.addr;
     }
   };
@@ -581,7 +611,7 @@ namespace
        && (coverage_map
            = coverage_map_alloc_XA (file, sec->id == sec_loc)) == NULL)
       {
-       wr_error (WHERE (sec->id, NULL))
+       wr_error (section_locus (sec->id))
          << "couldn't read ELF, skipping coverage analysis." << std::endl;
        retval = false;
       }
@@ -600,11 +630,12 @@ namespace
     ref_cu_vect refs;
     for (struct cu *cu = cu_chain; cu != NULL; cu = cu->next)
       {
-       struct ref_record *rec
+       ref_record *rec
          = sec->id == sec_loc ? &cu->loc_refs : &cu->range_refs;
-       for (size_t i = 0; i < rec->size; ++i)
+       for (ref_record::const_iterator it = rec->begin ();
+            it != rec->end (); ++it)
          {
-           ref_cu ref = {rec->refs[i], cu};
+           ref_cu ref = {*it, cu};
            refs.push_back (ref);
          }
       }
@@ -619,8 +650,8 @@ namespace
          {
            if (off == last_off)
              continue;
-           struct where wh = WHERE (sec->id, NULL);
-           relocation_skip (&sec->rel, off, &wh, skip_unref);
+           relocation_skip (&sec->rel, off, section_locus (sec->id),
+                            skip_unref);
          }
 
        // xxx right now this is just so that we can ver->get_form
@@ -636,7 +667,7 @@ namespace
           Perhaps that's undesirable.  */
        if (!check_loc_or_range_ref (ver, file, &ctx, it->cu, sec,
                                     &coverage, coverage_map, pc_coverage,
-                                    off, &it->ref.who, cat))
+                                    off, it->ref.who, cat))
          retval = false;
        last_off = off;
       }
@@ -644,7 +675,7 @@ namespace
 
     if (retval)
       {
-       relocation_skip_rest (&sec->rel, sec->id);
+       relocation_skip_rest (&sec->rel, section_locus (sec->id));
 
        /* We check that all CUs have the same address size when building
           the CU chain.  So just take the address size of the first CU in
@@ -753,7 +784,7 @@ namespace
     return true;
   }
 
-  static enum section_id
+  static rel_target
   reloc_target_loc (uint8_t opcode)
   {
     switch (opcode)
@@ -763,7 +794,7 @@ namespace
        return sec_info;
 
       case DW_OP_addr:
-       return rel_address;
+       return rel_target::rel_address;
 
       case DW_OP_call_ref:
        assert (!"Can't handle call_ref!");
@@ -772,7 +803,7 @@ namespace
     std::cout << "XXX don't know how to handle opcode="
              << elfutils::dwarf::ops::name (opcode) << std::endl;
 
-    return rel_value;
+    return rel_target::rel_value;
   }
 
   bool
@@ -785,7 +816,7 @@ namespace
                form const *form,
                uint64_t *valuep,
                char const *str,
-               struct where *where)
+               locus const &where)
   {
     if (form == NULL)
       return true;
@@ -797,7 +828,7 @@ namespace
     if (!read_generic_value (ctx, form->width (cu->head), storclass,
                             where, valuep, NULL))
       {
-       wr_error (*where)
+       wr_error (where)
          << "opcode \"" << elfutils::dwarf::ops::name (opcode)
          << "\": can't read " << str << " (form \""
          << *form << "\")." << std::endl;
@@ -817,7 +848,7 @@ namespace
                        cu->head->address_size, valuep, where,
                        reloc_target_loc (opcode), NULL);
        else
-         wr_error (where, ": relocation relocates a length field.\n");
+         wr_error (where) << "relocation relocates a length field.\n";
       }
     if (storclass == sc_block)
       {
@@ -829,6 +860,28 @@ namespace
   }
 }
 
+class locexpr_locus
+  : public locus
+{
+  uint64_t _m_offset;
+  locus const *_m_context;
+
+public:
+  explicit locexpr_locus (uint64_t offset, locus const *context)
+    : _m_offset (offset)
+    , _m_context (context)
+  {}
+
+  std::string
+  format (bool) const
+  {
+    std::stringstream ss;
+    ss << _m_context
+       << " (location expression offset 0x" << std::hex << _m_offset << ")";
+    return ss.str ();
+  }
+};
+
 bool
 check_location_expression (dwarf_version const *ver,
                           elf_file const &file,
@@ -837,28 +890,26 @@ check_location_expression (dwarf_version const *ver,
                           uint64_t init_off,
                           struct relocation_data *reloc,
                           size_t length,
-                          struct where *wh)
+                          locus const &loc)
 {
   struct read_ctx ctx;
   if (!read_ctx_init_sub (&ctx, parent_ctx, parent_ctx->ptr,
                          parent_ctx->ptr + length))
     {
-      wr_error (wh, PRI_NOT_ENOUGH, "location expression");
+      wr_error (&loc, PRI_NOT_ENOUGH, "location expression");
       return false;
     }
 
-  struct ref_record oprefs;
-  WIPE (oprefs);
-
-  struct addr_record opaddrs;
-  WIPE (opaddrs);
+  typedef ref_T<locexpr_locus> locexpr_ref;
+  typedef ref_record_T<locexpr_locus> locexpr_ref_record;
+  locexpr_ref_record oprefs;
+  addr_record opaddrs;
 
   while (!read_ctx_eof (&ctx))
     {
-      struct where where = WHERE (sec_locexpr, wh);
       uint64_t opcode_off = read_ctx_get_offset (&ctx) + init_off;
-      where_reset_1 (&where, opcode_off);
-      addr_record_add (&opaddrs, opcode_off);
+      locexpr_locus where (opcode_off, &loc);
+      opaddrs.add (opcode_off);
 
       uint8_t opcode;
       if (!read_ctx_read_ubyte (&ctx, &opcode))
@@ -879,9 +930,9 @@ check_location_expression (dwarf_version const *ver,
 
       uint64_t value1, value2;
       if (!op_read_form (file, &ctx, cu, init_off, reloc,
-                        opcode, form1, &value1, "1st operand", &where)
+                        opcode, form1, &value1, "1st operand", where)
          || !op_read_form (file, &ctx, cu, init_off, reloc,
-                           opcode, form2, &value2, "2st operand", &where))
+                           opcode, form2, &value2, "2st operand", where))
        goto out;
 
       switch (opcode)
@@ -908,7 +959,7 @@ check_location_expression (dwarf_version const *ver,
            else
              {
                uint64_t off_after = read_ctx_get_offset (&ctx) + init_off;
-               ref_record_add (&oprefs, off_after + skip, &where);
+               oprefs.push_back (locexpr_ref (off_after + skip, where));
              }
 
            break;
@@ -937,17 +988,11 @@ check_location_expression (dwarf_version const *ver,
     }
 
  out:
-  for (size_t i = 0; i < oprefs.size; ++i)
-    {
-      struct ref *ref = oprefs.refs + i;
-      if (!addr_record_has_addr (&opaddrs, ref->addr))
-       wr_error (&ref->who,
-                 ": unresolved reference to opcode at %#" PRIx64 ".\n",
-                 ref->addr);
-    }
-
-  addr_record_free (&opaddrs);
-  ref_record_free (&oprefs);
+  for (locexpr_ref_record::const_iterator it = oprefs.begin ();
+       it != oprefs.end (); ++it)
+    if (!opaddrs.has_addr (it->addr))
+      wr_error (it->who) << "unresolved reference to opcode at "
+                        << pri::hex (it->addr) << ".\n";
 
   return true;
 }
@@ -978,19 +1023,17 @@ found_hole (uint64_t start, uint64_t length, void *data)
        }
     }
   else
-    {
-      /* XXX: This actually lies when the unreferenced portion is
-        composed of sequences of zeroes and non-zeroes.  */
-      struct where wh = WHERE (info->section, NULL);
-      wr_message_padding_n0 (info->category, &wh, start, end);
-    }
+    /* XXX: This actually lies when the unreferenced portion is
+       composed of sequences of zeroes and non-zeroes.  */
+    wr_message_padding_n0 (info->category, section_locus (info->section),
+                          start, end);
 
   return true;
 }
 
 void
-check_range_relocations (enum message_category cat,
-                        struct where *where,
+check_range_relocations (locus const &loc,
+                        enum message_category cat,
                         struct elf_file const *file,
                         GElf_Sym *begin_symbol,
                         GElf_Sym *end_symbol,
@@ -999,7 +1042,7 @@ check_range_relocations (enum message_category cat,
   if (begin_symbol != NULL
       && end_symbol != NULL
       && begin_symbol->st_shndx != end_symbol->st_shndx)
-    wr_message (cat | mc_impact_2 | mc_reloc, where,
+    wr_message (cat | mc_impact_2 | mc_reloc, &loc,
                ": %s relocated against different sections (%s and %s).\n",
                description,
                file->sec[begin_symbol->st_shndx].name,
index 442191e63dd6f049338a1ec86d245449cd845b0d..2b04e6c031d539f90c87c3a957397283ef198f5c 100644 (file)
@@ -1,5 +1,5 @@
 /* Low-level checking of .debug_loc and .debug_range.
-   Copyright (C) 2009, 2010 Red Hat, Inc.
+   Copyright (C) 2009, 2010, 2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
 #include "coverage.hh"
 #include "dwarf_version_i.hh"
 
+class loc_range_locus
+  : public locus
+{
+  locus const &_m_refby;
+  Dwarf_Off _m_offset;
+  section_id _m_sec;
+
+public:
+  loc_range_locus (section_id sec, locus const &refby, Dwarf_Off offset = -1)
+    : _m_refby (refby)
+    , _m_offset (offset)
+    , _m_sec ((assert (sec == sec_loc || sec == sec_ranges), sec))
+  {}
+
+  std::string format (bool brief) const;
+};
+
 struct section_coverage
 {
   struct sec *sec;
@@ -93,10 +110,10 @@ bool check_location_expression (dwarf_version const *ver,
                                uint64_t init_off,
                                struct relocation_data *reloc,
                                size_t length,
-                               struct where *wh);
+                               locus const &loc);
 
-void check_range_relocations (enum message_category cat,
-                             struct where *where,
+void check_range_relocations (locus const &loc,
+                             enum message_category cat,
                              struct elf_file const *file,
                              GElf_Sym *begin_symbol,
                              GElf_Sym *end_symbol,
index c44cab4b0e9f380798ccea68e8c2a30fdb54a985..3991814a30b2b18bbf071481b1722ebd7a1323b9 100644 (file)
    Network licensing program, please visit www.openinventionnetwork.com
    <http://www.openinventionnetwork.com>.  */
 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
 #include "check_debug_pub.hh"
 #include "check_debug_info.hh"
 #include "sections.hh"
 #include "messages.hh"
 #include "misc.hh"
 
+namespace
+{
+  bool check_pub_structural (elf_file const &file, sec &sect,
+                            check_debug_info *cus);
+}
+
 template<section_id sec_id>
 check_debug_pub<sec_id>::check_debug_pub (checkstack &stack, dwarflint &lint)
   : _m_sec (lint.check (stack, _m_sec))
   , _m_file (_m_sec->file)
   , _m_cus (lint.toplev_check (stack, _m_cus))
 {
-  check_pub_structural ();
+  check_pub_structural (_m_file, _m_sec->sect, _m_cus);
 }
 
 
@@ -83,175 +93,176 @@ template check_debug_pub<sec_pubtypes>::check_debug_pub (checkstack &stack,
 
 static reg<check_debug_pubtypes> reg_debug_pubtypes;
 
-
-template <section_id sec_id>
-bool
-check_debug_pub<sec_id>::check_pub_structural ()
+namespace
 {
-  struct read_ctx ctx;
-  read_ctx_init (&ctx, _m_sec->sect.data, _m_file.other_byte_order);
-  bool retval = true;
-
-  while (!read_ctx_eof (&ctx))
-    {
-      enum section_id sid = _m_sec->sect.id;
-      struct where where = WHERE (sid, NULL);
-      where_reset_1 (&where, read_ctx_get_offset (&ctx));
-      const unsigned char *set_begin = ctx.ptr;
-
-      /* Size.  */
-      uint32_t size32;
-      uint64_t size;
-      int offset_size;
-      if (!read_ctx_read_4ubyte (&ctx, &size32))
-       {
-         wr_error (&where, ": can't read table length.\n");
-         return false;
-       }
-      if (!read_size_extra (&ctx, size32, &size, &offset_size, &where))
-       return false;
-
+  bool
+  check_pub_structural (elf_file const &file, sec &sect,
+                       check_debug_info *cus)
+  {
+    struct read_ctx ctx;
+    read_ctx_init (&ctx, sect.data, file.other_byte_order);
+    bool retval = true;
+
+    while (!read_ctx_eof (&ctx))
       {
-      struct read_ctx sub_ctx;
-      const unsigned char *set_end = ctx.ptr + size;
-      if (!read_ctx_init_sub (&sub_ctx, &ctx, set_begin, set_end))
-       goto not_enough;
-      sub_ctx.ptr = ctx.ptr;
-
-      /* Version.  */
-      uint16_t version;
-      if (!read_ctx_read_2ubyte (&sub_ctx, &version))
-       {
-         wr_error (&where, ": can't read set version.\n");
-         retval = false;
-         goto next;
-       }
-      if (!supported_version (version, 1, &where, 2))
-       {
-         retval = false;
-         goto next;
-       }
+       enum section_id sid = sect.id;
+       section_locus where (sid, read_ctx_get_offset (&ctx));
+       const unsigned char *set_begin = ctx.ptr;
+
+       /* Size.  */
+       uint32_t size32;
+       uint64_t size;
+       int offset_size;
+       if (!read_ctx_read_4ubyte (&ctx, &size32))
+         {
+           wr_error (&where, ": can't read table length.\n");
+           return false;
+         }
+       if (!read_size_extra (&ctx, size32, &size, &offset_size, where))
+         return false;
 
-      /* CU offset.  */
-      uint64_t cu_offset;  /* Offset of related CU.  */
-      uint64_t ctx_offset = sub_ctx.ptr - ctx.begin;
-      if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &cu_offset))
        {
-         wr_error (&where, ": can't read debug info offset.\n");
-         retval = false;
-         goto next;
-       }
+         struct read_ctx sub_ctx;
+         const unsigned char *set_end = ctx.ptr + size;
+         if (!read_ctx_init_sub (&sub_ctx, &ctx, set_begin, set_end))
+           goto not_enough;
+         sub_ctx.ptr = ctx.ptr;
+
+         /* Version.  */
+         uint16_t version;
+         if (!read_ctx_read_2ubyte (&sub_ctx, &version))
+           {
+             wr_error (&where, ": can't read set version.\n");
+             retval = false;
+             goto next;
+           }
+         if (!supported_version (version, 1, where, 2))
+           {
+             retval = false;
+             goto next;
+           }
 
-      struct relocation *rel;
-      if ((rel = relocation_next (&_m_sec->sect.rel, ctx_offset,
-                                 &where, skip_mismatched)))
-       relocate_one (&_m_file, &_m_sec->sect.rel, rel, offset_size,
-                     &cu_offset, &where, sec_info, NULL);
-      else if (_m_file.ehdr.e_type == ET_REL)
-       wr_message (mc_impact_2 | mc_pubtables | mc_reloc | mc_header, &where,
-                   PRI_LACK_RELOCATION, "debug info offset");
-
-      struct cu *cu = NULL;
-      if (_m_cus != NULL && (cu = _m_cus->find_cu (cu_offset)) == NULL)
-       wr_error (where)
-         << "unresolved reference to " << pri::CU (cu_offset)
-         << '.' << std::endl;
-      // xxx this can be checked even without CU
-      if (cu != NULL)
-       {
-         where.ref = &cu->head->where;
-         bool *has = _m_sec->sect.id == sec_pubnames
-           ? &cu->has_pubnames : &cu->has_pubtypes;
-         if (*has)
-           wr_message (mc_impact_2 | mc_pubtables | mc_header, &where,
-                       ": there has already been section for this CU.\n");
-         else
-           *has = true;
-       }
+         /* CU offset.  */
+         uint64_t cu_offset;  /* Offset of related CU.  */
+         {
+         uint64_t ctx_offset = sub_ctx.ptr - ctx.begin;
+         if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &cu_offset))
+           {
+             wr_error (&where, ": can't read debug info offset.\n");
+             retval = false;
+             goto next;
+           }
 
-      /* Covered length.  */
-      uint64_t cu_len;
-      if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &cu_len))
-       {
-         wr_error (&where, ": can't read covered length.\n");
-         retval = false;
-         goto next;
-       }
-      if (cu != NULL && cu_len != cu->head->total_size)
-       {
-         wr_error (where)
-           << "the table covers length " << cu_len << " but CU has length "
-           << cu->head->total_size << '.' << std::endl;
-         retval = false;
-         goto next;
-       }
+         struct relocation *rel;
+         if ((rel = relocation_next (&sect.rel, ctx_offset,
+                                     where, skip_mismatched)))
+           relocate_one (&file, &sect.rel, rel, offset_size,
+                         &cu_offset, where, sec_info, NULL);
+         else if (file.ehdr.e_type == ET_REL)
+           wr_message (mc_impact_2 | mc_pubtables | mc_reloc | mc_header, &where,
+                       PRI_LACK_RELOCATION, "debug info offset");
+         }
 
-      /* Records... */
-      while (!read_ctx_eof (&sub_ctx))
-       {
-         ctx_offset = sub_ctx.ptr - ctx.begin;
-         where_reset_2 (&where, ctx_offset);
+         struct cu *cu = NULL;
+         if (cus != NULL && (cu = cus->find_cu (cu_offset)) == NULL)
+           wr_error (where)
+             << "unresolved reference to " << pri::CU (cu_offset)
+             << '.' << std::endl;
+         // xxx this can be checked even without CU
+         if (cu != NULL)
+           {
+             //where.ref = &cu->head->where;
+             bool *has = sect.id == sec_pubnames
+               ? &cu->has_pubnames : &cu->has_pubtypes;
+             if (*has)
+               wr_message (mc_impact_2 | mc_pubtables | mc_header, &where,
+                           ": there has already been section for this CU.\n");
+             else
+               *has = true;
+           }
 
-         uint64_t offset;
-         if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &offset))
+         /* Covered length.  */
+         uint64_t cu_len;
+         if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &cu_len))
            {
-             wr_error (&where, ": can't read offset field.\n");
+             wr_error (&where, ": can't read covered length.\n");
              retval = false;
              goto next;
            }
-         if (offset == 0)
-           break;
-
-         if (cu != NULL
-             && !addr_record_has_addr (&cu->die_addrs,
-                                       offset + cu->head->offset))
+         if (cu != NULL && cu_len != cu->head->total_size)
            {
              wr_error (where)
-               << "unresolved reference to " << pri::DIE (offset)
-               << '.' << std::endl;
+               << "the table covers length " << cu_len << " but CU has length "
+               << cu->head->total_size << '.' << std::endl;
              retval = false;
              goto next;
            }
 
-         // xxx read_ctx_read_str???
-         uint8_t c;
-         do
-           if (!read_ctx_read_ubyte (&sub_ctx, &c))
-             {
-               wr_error (&where, ": can't read symbol name.\n");
-               retval = false;
-               goto next;
-             }
-         while (c);
-       }
+         /* Records... */
+         while (!read_ctx_eof (&sub_ctx))
+           {
+             section_locus rec_where (sect.id, sub_ctx.ptr - ctx.begin);
+
+             uint64_t offset;
+             if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &offset))
+               {
+                 wr_error (&rec_where, ": can't read offset field.\n");
+                 retval = false;
+                 goto next;
+               }
+             if (offset == 0)
+               break;
+
+             if (cu != NULL
+                 && !cu->die_addrs.has_addr (offset + cu->head->offset))
+               {
+                 wr_error (rec_where)
+                   << "unresolved reference to " << pri::DIE (offset)
+                   << '.' << std::endl;
+                 retval = false;
+                 goto next;
+               }
+
+             // xxx read_ctx_read_str???
+             uint8_t c;
+             do
+               if (!read_ctx_read_ubyte (&sub_ctx, &c))
+                 {
+                   wr_error (&rec_where, ": can't read symbol name.\n");
+                   retval = false;
+                   goto next;
+                 }
+             while (c);
+           }
 
-       sid = _m_sec->sect.id;
-       struct where wh = WHERE (sid, NULL);
-       if (sub_ctx.ptr != sub_ctx.end)
-         {
-           uint64_t off_start, off_end;
-           if (read_check_zero_padding (&sub_ctx, &off_start, &off_end))
-             wr_message_padding_0 (mc_pubtables, &wh, off_start, off_end);
-           else
-             {
-               wr_message_padding_n0 (mc_pubtables | mc_error, &wh,
-                                      off_start, off_start + size);
-               retval = false;
-             }
-         }
-      }
+         if (sub_ctx.ptr != sub_ctx.end)
+           {
+             uint64_t off_start, off_end;
+             if (read_check_zero_padding (&sub_ctx, &off_start, &off_end))
+               wr_message_padding_0 (mc_pubtables, section_locus (sect.id),
+                                     off_start, off_end);
+             else
+               {
+                 wr_message_padding_n0 (mc_pubtables | mc_error,
+                                        section_locus (sect.id),
+                                        off_start, off_start + size);
+                 retval = false;
+               }
+           }
+       }
 
-    next:
-      if (read_ctx_skip (&ctx, size))
-       continue;
+      next:
+       if (read_ctx_skip (&ctx, size))
+         continue;
 
-    not_enough:
-      wr_error (&where, PRI_NOT_ENOUGH, "next set");
-      return false;
-    }
+      not_enough:
+       wr_error (&where, PRI_NOT_ENOUGH, "next set");
+       return false;
+      }
 
-  if (retval)
-    relocation_skip_rest (&_m_sec->sect.rel, _m_sec->sect.id);
+    if (retval)
+      relocation_skip_rest (&sect.rel, section_locus (sect.id));
 
-  return retval;
+    return retval;
+  }
 }
index 86e430427506d0fdba6f4a6f53cf23b9525b7dd5..01caed5a1e8cde05d1f0459746480e36e9433791 100644 (file)
@@ -41,8 +41,6 @@ protected:
   elf_file const &_m_file;
   check_debug_info *_m_cus;
 
-  bool check_pub_structural ();
-
 public:
   // instantiated in .cc for each subclass
   check_debug_pub (checkstack &stack, dwarflint &lint);
index 7bddad0d7ea6b9c6a893dc5d3d35a4b8ca6c2a51..05f4b726f54e572464fda1ef3350d78c8ba6d7cc 100644 (file)
@@ -64,19 +64,19 @@ namespace
        decl_file = attrs.find (DW_AT_decl_file);
 
       if (decl_column != attrs.end () && decl_line == attrs.end ())
-       wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal)
+       wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal)
          .id (descriptor ())
          << elfutils::dwarf::tags::name (entry.tag ())
          << " has decl_column, but NOT decl_line" << std::endl;
 
       if (decl_line != attrs.end () && decl_file == attrs.end ())
-       wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal)
+       wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal)
          .id (descriptor ())
          << elfutils::dwarf::tags::name (entry.tag ())
          << " has decl_line, but NOT decl_file" << std::endl;
 
       if (decl_file != attrs.end () && decl_line == attrs.end ())
-       wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal)
+       wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal)
          .id (descriptor ())
          << elfutils::dwarf::tags::name (entry.tag ())
          << " has decl_file, but NOT decl_line" << std::endl;
@@ -90,19 +90,19 @@ namespace
        call_file = attrs.find (DW_AT_call_file);
 
       if (call_column != attrs.end () && call_line == attrs.end ())
-       wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal)
+       wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal)
          .id (descriptor ())
          << elfutils::dwarf::tags::name (entry.tag ())
          << " has call_column, but NOT call_line" << std::endl;
 
       if (call_line != attrs.end () && call_file == attrs.end ())
-       wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal)
+       wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal)
          .id (descriptor ())
          << elfutils::dwarf::tags::name (entry.tag ())
          << " has call_line, but NOT call_file" << std::endl;
 
       if (call_file != attrs.end () && call_line == attrs.end ())
-       wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal)
+       wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal)
          .id (descriptor ())
          << elfutils::dwarf::tags::name (entry.tag ())
          << " has call_file, but NOT call_line" << std::endl;
index d30453216f85507de0463253c618c3c38b42a60d..4f19113a723354f70638c6600652a52f959202ff 100644 (file)
@@ -98,7 +98,7 @@ namespace
        }
 
       if (! found)
-       wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal)
+       wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal)
          .id (descriptor ())
          << elfutils::dwarf::tags::name (entry.tag ())
          << " " << dwarf::attributes::name (pc.first) << "=0x"
index 0e0b38d499a57cd23fa472f346ad61d9e8584959..5aeea9eb53bb66eef67fbee9011a7094f65515d6 100644 (file)
@@ -97,7 +97,7 @@ public:
        r += reason;
       }
 
-    wr_error (to_where (*a_d_it))
+    wr_error (die_locus (*a_d_it))
       << "A check failed: " << (_m_cd->name () ?: "(nil)")
       << r << std::endl;
   }
index 838e3f69340e0a6ea247d1bcd119bbf66dc4a774..f916ac0377dbdda5b5f4577b03360f27e2706e22 100644 (file)
@@ -108,14 +108,14 @@ namespace
                  varinfo &i = old->second;
                  if ((declaration && i.decl != children.end ())
                      || (!declaration && i.def != children.end ()))
-                   wr_message (to_where (*jt), mc_impact_3 | mc_die_other)
+                   wr_message (die_locus (*jt), mc_impact_3 | mc_die_other)
                      .id (descriptor ())
                      << "Re" << (declaration ? "declaration" : "definition")
                      << " of variable '" << name << "', originally seen at "
                      << pri::ref (declaration ? *i.decl : *i.def)
                      << '.' << std::endl;
                  else
-                   wr_message (to_where (*jt), mc_impact_3 | mc_die_other)
+                   wr_message (die_locus (*jt), mc_impact_3 | mc_die_other)
                      .id (descriptor ())
                      << "Found "
                      << (declaration ? "declaration" : "definition")
index acb4274f8fac3f0486ab34e15a77f442d0a47aab..47297ea7a672126dfcb52cb18d3900be3a15a2b9 100644 (file)
@@ -122,7 +122,7 @@ namespace
        if ((at2 = m.find ((*at).first)) != m.end ()
            && ! duplicate_ok (entry.tag (), at2->first, attr.first,
                               referree.tag (), at2->second == (*at).second))
-         wr_message (to_where (entry), mc_impact_3 | mc_acc_bloat | mc_die_rel)
+         wr_message (die_locus (entry), mc_impact_3 | mc_acc_bloat | mc_die_rel)
            .id (descriptor ())
            << dwarf::tags::name (entry.tag ())
            << " attribute " << dwarf::attributes::name (at2->first)
index a758c7c3f27aa643d1358fff78388e095d0b9ce7..1b8cb4e970d5a5e48b667ee8d41472eb32c08667 100644 (file)
@@ -104,9 +104,7 @@ check_expected_trees::check_expected_trees (checkstack &stack, dwarflint &lint)
        void operator () (dwarf::compile_unit const &cu,
                          dwarf::debug_info_entry const &parent)
        {
-         struct where where = WHERE (sec_info, NULL);
-         where_reset_1 (&where, cu.offset ());
-         where_reset_2 (&where, parent.offset ());
+         die_locus where (parent);
 
          int parent_tag = parent.tag ();
 
@@ -204,7 +202,7 @@ check_expected_trees::check_expected_trees (checkstack &stack, dwarflint &lint)
   // XXX more specific class when <dwarf> has it
   catch (std::runtime_error &exc)
     {
-      wr_error (WHERE (sec_info, NULL))
+      wr_error (section_locus (sec_info))
        << "Exception while checking expected trees: " << exc.what ()
        << std::endl;
       throw check_base::failed ();
index d615afaefafda64aa2d08b01c9a61b00a4b68ed0..74d2ad4be6c69cdf17d43b6c5e6d3f0f93f75d2c 100644 (file)
@@ -133,7 +133,7 @@ namespace
                      && entry.tag () != DW_TAG_union_type)
                      || attrs.find (DW_AT_name) != attrs.end ()))
                {
-                 wr_message (to_where (entry),
+                 wr_message (die_locus (entry),
                              mc_impact_3 | mc_acc_suboptimal | mc_die_other)
                    .id (descriptor ())
                    << elfutils::dwarf::tags::name (entry.tag ())
@@ -152,7 +152,7 @@ namespace
              if (attrs.find (DW_AT_declaration) == attrs.end ()
                  && is_external (it))
                {
-                 wr_message (to_where (entry),
+                 wr_message (die_locus (entry),
                              mc_impact_3 | mc_acc_suboptimal | mc_die_other)
                    .id (descriptor ())
                    << elfutils::dwarf::tags::name (entry.tag ())
@@ -165,7 +165,7 @@ namespace
            {
              // Global symbol in symbol table, not marked external.
              // Always bad.
-             wr_message (to_where (entry),
+             wr_message (die_locus (entry),
                          mc_impact_3 | mc_acc_suboptimal | mc_die_other)
                .id (descriptor ())
                << elfutils::dwarf::tags::name (entry.tag ())
index 6f2f4eb67f3bdd274f451385c00474b00ba2c41a..12e2d06cb2fc0a936344d068f298ce7e85a5d54f 100644 (file)
@@ -43,8 +43,7 @@ namespace
       static checkdescriptor cd
        (checkdescriptor::create ("check_matching_ranges")
         .description (
-"Check that the ranges in .debug_aranges and .debug_ranges match.\n"
-));
+"Check that the ranges in .debug_aranges and .debug_ranges match.\n"));
       return &cd;
     }
 
@@ -63,20 +62,15 @@ check_matching_ranges::check_matching_ranges (checkstack &stack,
 
   try
     {
-      struct where where_ref = WHERE (sec_info, NULL);
-      struct where where_ar = WHERE (sec_aranges, NULL);
-      where_ar.ref = &where_ref;
-      struct where where_r = WHERE (sec_ranges, NULL);
-      where_r.ref = &where_ref;
       char buf[128];
-
       const dwarf::aranges_map &aranges = dw.aranges ();
       for (dwarf::aranges_map::const_iterator i = aranges.begin ();
           i != aranges.end (); ++i)
        {
          const dwarf::compile_unit &cu = i->first;
-         where_reset_1 (&where_ref, 0);
-         where_reset_2 (&where_ref, cu.offset ());
+         cudie_locus where_ref (cu);
+         loc_range_locus where_r (sec_ranges, where_ref);
+         arange_locus where_ar (where_ref);
 
          std::set<dwarf::ranges::key_type>
            cu_aranges = i->second,
@@ -114,7 +108,7 @@ check_matching_ranges::check_matching_ranges (checkstack &stack,
   // XXX more specific class when <dwarf> has it
   catch (std::runtime_error &exc)
     {
-      wr_error (WHERE (sec_info, NULL))
+      wr_error (section_locus (sec_info))
        << "Exception while checking matching ranges: " << exc.what ()
        << std::endl;
       throw check_base::failed ();
index a5ed1c19acf86bc2146f107af8e10c0166e66955..e5443976aa610442e867f1ce1a6bf73e7e0c52dc 100644 (file)
@@ -1,5 +1,5 @@
 /* Pedantic checking of DWARF files
-   Copyright (C) 2009,2010 Red Hat, Inc.
+   Copyright (C) 2009,2010,2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -53,7 +53,7 @@ public:
 private:
   void not_available (section_id sec_id)
   {
-    wr_error (WHERE (sec_id, NULL))
+    wr_error (section_locus (sec_id))
       << "data not found." << std::endl;
   }
 
index c0312917af2d32d6a0ac4c7fe16fecae952f5260..cae7c84436d36b679c1126739d2ce7b5d7d18820 100644 (file)
@@ -31,7 +31,6 @@
 #include "coverage.hh"
 #include "pri.hh"
 #include "check_debug_loc_range.hh"
-#include "misc.hh"
 
 using elfutils::dwarf;
 
@@ -46,7 +45,7 @@ namespace
     static void recursively_validate (dwarf::compile_unit const &cu,
                                      dwarf::debug_info_entry const &die,
                                      ranges_t const &ranges,
-                                     where const &wh_parent);
+                                     locus const &wh_parent);
 
   public:
     static checkdescriptor const *descriptor () {
@@ -73,7 +72,7 @@ check_range_out_of_scope::check_range_out_of_scope (checkstack &stack, dwarflint
       class dwarf::compile_units_type const &cus = dw.compile_units ();
       ranges_t r;
       r.push_back (std::make_pair (0, -1));
-      where wh = WHERE (sec_info, NULL);
+      section_locus wh (sec_info);
       for (dwarf::compile_units_type::const_iterator it = cus.begin ();
           it != cus.end (); ++it)
        recursively_validate (*it, *it, r, wh);
@@ -81,7 +80,7 @@ check_range_out_of_scope::check_range_out_of_scope (checkstack &stack, dwarflint
   // XXX more specific class when <dwarf> has it
   catch (std::runtime_error &exc)
     {
-      wr_error (WHERE (sec_info, NULL))
+      wr_error (section_locus (sec_info))
        << "Exception while checking ranges out of scope: " << exc.what ()
        << std::endl;
       throw check_base::failed ();
@@ -93,11 +92,9 @@ check_range_out_of_scope::recursively_validate
   (dwarf::compile_unit const &cu,
    dwarf::debug_info_entry const &die,
    ranges_t const &ranges,
-   where const &wh_parent)
+   locus const &wh_parent)
 {
-  where wh = WHERE (sec_info, NULL);
-  where_reset_1 (&wh, cu.offset ());
-  where_reset_2 (&wh, die.offset ());
+  die_locus wh (die);
 
   ::Dwarf_Addr low_pc = 0;
   ::Dwarf_Addr high_pc = ::noaddr;
index e81560aa62348ef69633a52d9ed15689d2ac7769..752fdfbb2e5cd42a710b36a2178be73ef7a89c1b 100644 (file)
@@ -65,7 +65,7 @@ namespace
            {
              dwarf::debug_info_entry ref = *val.reference ();
              if (ref.identity () == entry.identity ())
-               wr_message (to_where (entry),
+               wr_message (die_locus (entry),
                            mc_impact_3 | mc_acc_suboptimal | mc_die_rel)
                  .id (descriptor ())
                  << dwarf::tags::name (entry.tag ())
index 14831ecb13d565c742deecf3049d905c37c4dbde..b2b14682ceb0c8cbac25b74240b707f5db9c1509 100644 (file)
 
 bool
 read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep,
-                int *offset_sizep, struct where *where)
+                int *offset_sizep, locus const &loc)
 {
   if (size32 == DWARF3_LENGTH_64_BIT)
     {
       if (!read_ctx_read_8ubyte (ctx, sizep))
        {
-         wr_error (where, ": can't read 64bit CU length.\n");
+         wr_error (loc) << "can't read 64bit CU length.\n";
          return false;
        }
 
@@ -53,8 +53,8 @@ read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep,
     }
   else if (size32 >= DWARF3_LENGTH_MIN_ESCAPE_CODE)
     {
-      wr_error (where, ": unrecognized CU length escape value: "
-               "%" PRIx32 ".\n", size32);
+      wr_error (loc)
+       << "unrecognized CU length escape value: " << size32 << ".\n";
       return false;
     }
   else
@@ -67,15 +67,13 @@ read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep,
 }
 
 error_code
-read_address_size (struct read_ctx *ctx,
-                  bool addr_64,
-                  int *address_sizep,
-                  struct where const *where)
+read_address_size (struct read_ctx *ctx, bool addr_64,
+                  int *address_sizep, locus const &loc)
 {
   uint8_t address_size;
   if (!read_ctx_read_ubyte (ctx, &address_size))
     {
-      wr_error (where, ": can't read address size.\n");
+      wr_error (loc) << "can't read address size.\n";
       return err_fatal;
     }
 
@@ -84,18 +82,16 @@ read_address_size (struct read_ctx *ctx,
     {
       /* Keep going.  Deduce the address size from ELF header, and try
         to parse it anyway.  */
-      wr_error (where,
-               ": invalid address size: %d (only 4 or 8 allowed).\n",
-               address_size);
+      wr_error (loc) << "invalid address size: " << (int)address_size
+                    << " (only 4 or 8 allowed).\n";
       address_size = addr_64 ? 8 : 4;
       ret = err_nohl;
     }
   else if ((address_size == 8) != addr_64)
     {
       /* Keep going, we may still be able to parse it.  */
-      wr_error (where,
-               ": CU reports address size of %d in %d-bit ELF.\n",
-               address_size, addr_64 ? 64 : 32);
+      wr_error (loc) << "CU reports address size of " << address_size
+                    << " in " << (addr_64 ? 64 : 32) << "-bit ELF.\n";
       ret = err_nohl;
     }
 
@@ -105,59 +101,59 @@ read_address_size (struct read_ctx *ctx,
 
 bool
 checked_read_uleb128 (read_ctx *ctx, uint64_t *ret,
-                     where const *where, const char *what)
+                     locus const &loc, const char *what)
 {
   const unsigned char *ptr = ctx->ptr;
   int st = read_ctx_read_uleb128 (ctx, ret);
   if (st < 0)
-    wr_error (where, ": can't read %s.\n", what);
+    wr_error (loc) << "can't read " << what << ".\n";
   else if (st > 0)
     {
       char buf[19]; // 16 hexa digits, "0x", terminating zero
       sprintf (buf, "%#" PRIx64, *ret);
-      wr_format_leb128_message (where, what, buf, ptr, ctx->ptr);
+      wr_format_leb128_message (loc, what, buf, ptr, ctx->ptr);
     }
   return st >= 0;
 }
 
 bool
 checked_read_sleb128 (read_ctx *ctx, int64_t *ret,
-                     where const *where, const char *what)
+                     locus const &loc, const char *what)
 {
   const unsigned char *ptr = ctx->ptr;
   int st = read_ctx_read_sleb128 (ctx, ret);
   if (st < 0)
-    wr_error (where, ": can't read %s.\n", what);
+    wr_error (loc) << "can't read " << what << ".\n";
   else if (st > 0)
     {
       char buf[20]; // sign, "0x", 16 hexa digits, terminating zero
       int64_t val = *ret;
       sprintf (buf, "%s%#" PRIx64, val < 0 ? "-" : "", val < 0 ? -val : val);
-      wr_format_leb128_message (where, what, buf, ptr, ctx->ptr);
+      wr_format_leb128_message (loc, what, buf, ptr, ctx->ptr);
     }
   return st >= 0;
 }
 
 bool
 checked_read_leb128 (read_ctx *ctx, form_width_t width, uint64_t *ret,
-                    where const *where, const char *what)
+                    locus const &loc, const char *what)
 {
   assert (width == fw_sleb || width == fw_uleb);
   if (width == fw_sleb)
     {
       int64_t svalue;
-      if (!checked_read_sleb128 (ctx, &svalue, where, what))
+      if (!checked_read_sleb128 (ctx, &svalue, loc, what))
        return false;
       *ret = (uint64_t) svalue;
       return true;
     }
   else
-    return checked_read_uleb128 (ctx, ret, where, what);
+    return checked_read_uleb128 (ctx, ret, loc, what);
 }
 
 bool
 read_sc_value (uint64_t *valuep, form_width_t width,
-              read_ctx *ctx, where const *where)
+              read_ctx *ctx, locus const &loc)
 {
   switch (width)
     {
@@ -174,7 +170,7 @@ read_sc_value (uint64_t *valuep, form_width_t width,
     case fw_uleb:
     case fw_sleb:
       return checked_read_leb128 (ctx, width, valuep,
-                                 where, "attribute value");
+                                 loc, "attribute value");
 
     case fw_unknown:
       ;
@@ -185,13 +181,13 @@ read_sc_value (uint64_t *valuep, form_width_t width,
 bool
 read_generic_value (read_ctx *ctx,
                    form_width_t width, storage_class_t storclass,
-                   where const *where, uint64_t *valuep, read_ctx *blockp)
+                   locus const &loc, uint64_t *valuep, read_ctx *blockp)
 {
   uint64_t value;
   if (storclass == sc_value
       || storclass == sc_block)
     {
-      if (!read_sc_value (&value, width, ctx, where))
+      if (!read_sc_value (&value, width, ctx, loc))
        return false;
       if (valuep != NULL)
        *valuep = value;
index 1e0deda8c0ef505a5cf98b4731f6cc0ebdf8aaf1..99941e8a265d4f6dfcda436e03a089dadeb33896 100644 (file)
@@ -27,7 +27,7 @@
 #define DWARFLINT_CHECKED_READ_HH
 
 #include "readctx.hh"
-#include "where.h"
+#include "locus.hh"
 #include "dwarf_version.hh"
 
 enum error_code
@@ -38,28 +38,26 @@ enum error_code
   };
 
 bool read_size_extra (read_ctx *ctx, uint32_t size32, uint64_t *sizep,
-                     int *offset_sizep, where *where);
+                     int *offset_sizep, locus const &loc);
 
 /// Read address size and return it via address_sizep and return 0.
 /// Address size may be 4 or 8; for other values it's set depending or
 /// addr_64, and err_nohl is returned.
-error_code read_address_size (read_ctx *ctx,
-                             bool addr_64,
-                             int *address_sizep,
-                             where const *where);
+error_code read_address_size (read_ctx *ctx, bool addr_64,
+                             int *address_sizep, locus const &loc);
 
 bool checked_read_uleb128 (read_ctx *ctx, uint64_t *ret,
-                          where const *where, const char *what);
+                          locus const &loc, const char *what);
 
 bool checked_read_sleb128 (read_ctx *ctx, int64_t *ret,
-                          where const *where, const char *what);
+                          locus const &loc, const char *what);
 
 bool checked_read_leb128 (read_ctx *ctx, form_width_t width, uint64_t *ret,
-                         where const *where, const char *what);
+                         locus const &loc, const char *what);
 
 /// Read value depending on the form width and storage class.
 bool read_sc_value (uint64_t *valuep, form_width_t width,
-                   read_ctx *ctx, where const *where);
+                   read_ctx *ctx, locus const &loc);
 
 /// Read value depending on the form width and storage class.
 /// Value is returned via VALUEP, if that is non-NULL; for block
@@ -68,7 +66,7 @@ bool read_sc_value (uint64_t *valuep, form_width_t width,
 /// itself.
 bool read_generic_value (read_ctx *ctx,
                         form_width_t width, storage_class_t storclass,
-                        where const *where, uint64_t *valuep,
+                        locus const &loc, uint64_t *valuep,
                         read_ctx *blockp);
 
 #endif//DWARFLINT_CHECKED_READ_HH
index a280dfd639fde44da1f70e55530d68b0360ab59c..4827cb7f485204c026c040453c5979ed2f83b8ff 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef DWARFLINT_CHECKS_HH
 #define DWARFLINT_CHECKS_HH
 
-#include "where.h"
+#include "locus.hh"
 #include "dwarflint.hh"
 #include "checkdescriptor.hh"
 #include "messages.hh"
index 6d4109b963a4481bc9336fb91ce997866c4b5334..f9194057a7bb21c771665a256e89a457700063df 100644 (file)
@@ -29,7 +29,6 @@
 #endif
 
 #include "coverage.hh"
-#include "misc.hh"
 #include "pri.hh"
 
 #include <stdbool.h>
index c09ecabda651832040e9d7442aecb9bbaa42b1b4..4f87e0c4f9819217fed947fab79c2e34ef17dcf1 100644 (file)
    Network licensing program, please visit www.openinventionnetwork.com
    <http://www.openinventionnetwork.com>.  */
 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
 #include "cu_coverage.hh"
 #include "check_debug_info.hh"
 #include "check_debug_loc_range.hh"
diff --git a/dwarflint/die_locus.cc b/dwarflint/die_locus.cc
new file mode 100644 (file)
index 0000000..e27d0e2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+   Copyright (C) 2011 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "die_locus.hh"
+#include "pri.hh"
+
+char const *
+locus_simple_fmt::cu_n ()
+{
+  return "CU";
+}
+
+std::string
+die_locus::format (bool brief) const
+{
+  std::stringstream ss;
+  if (!brief)
+    ss << section_name[sec_info] << ": ";
+
+  ss << "DIE 0x" << std::hex << _m_offset;
+
+  if (_m_attrib_name != -1)
+    ss << ", attr. " << pri::attr_name (_m_attrib_name);
+
+  return ss.str ();
+}
+
diff --git a/dwarflint/die_locus.hh b/dwarflint/die_locus.hh
new file mode 100644 (file)
index 0000000..0c57d4f
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+   Copyright (C) 2011 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifndef _DWARFLINT_DIE_LOCUS_H_
+#define _DWARFLINT_DIE_LOCUS_H_
+
+#include "locus.hh"
+#include "../libdw/c++/dwarf"
+
+namespace locus_simple_fmt
+{
+  char const *cu_n ();
+};
+
+typedef fixed_locus<sec_info,
+                   locus_simple_fmt::cu_n,
+                   locus_simple_fmt::dec> cu_locus;
+
+class die_locus
+  : public locus
+{
+  Dwarf_Off _m_offset;
+  int _m_attrib_name;
+
+public:
+  explicit die_locus (Dwarf_Off offset = -1, int attrib_name = -1)
+    : _m_offset (offset)
+    , _m_attrib_name (attrib_name)
+  {}
+
+  template <class T>
+  explicit die_locus (T const &die, int attrib_name = -1)
+    : _m_offset (die.offset ())
+    , _m_attrib_name (attrib_name)
+  {}
+
+  void
+  set_attrib_name (int attrib_name)
+  {
+    _m_attrib_name = attrib_name;
+  }
+
+  std::string format (bool brief = false) const;
+};
+
+#endif /* _DWARFLINT_DIE_LOCUS_H_ */
index d283e7877b764426edf7f3d8e72afa0581eb4593..e315247ec1cb7ed8eb1524918a7b262052f1f9fe 100644 (file)
@@ -1,5 +1,5 @@
 /* Pedantic checking of DWARF files.
-   Copyright (C) 2008, 2009, 2010 Red Hat, Inc.
+   Copyright (C) 2008, 2009, 2010, 2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -40,6 +40,13 @@ struct sec
   Elf_Data *data;      /* May be NULL if data in this section are
                           missing or not substantial.  */
   enum section_id id;
+
+  sec ()
+    : scn (NULL)
+    , name (NULL)
+    , data (NULL)
+    , id (sec_invalid)
+  {}
 };
 
 struct elf_file
index 007756a41f9e5aca13ea25287e1cf2ba450f5c39..66d6e38c25d71e4992069c80bb6bf955e220638b 100644 (file)
@@ -31,6 +31,8 @@
 #endif
 
 #include "checks.hh"
+#include "check_debug_info.hh"
+
 #include "../libdw/c++/dwarf"
 #include "../libdwfl/libdwfl.h"
 
@@ -82,14 +84,4 @@ public:
   {}
 };
 
-template <class T>
-inline where
-to_where (T const &die)
-{
-  where ret = WHERE (sec_info, NULL);
-  where_reset_1 (&ret, 0);
-  where_reset_2 (&ret, die.offset ());
-  return ret;
-}
-
 #endif//DWARFLINT_CHECKS_HIGH_HH
index 614563eb4f480f550fb417c320b9cfbf0587c475..8a8a05284eaac4571746d97b3a2613b382bf07f7 100644 (file)
@@ -513,10 +513,7 @@ process(Dwarf *c_dw, dwarf const &dw)
            }
          catch (::error const &e)
            {
-             struct where where = WHERE (sec_info, NULL);
-             where_reset_1 (&where, it.cu ().offset ());
-             where_reset_2 (&where, die.offset ());
-             std::cerr << "error: " << where << ": "
+             std::cerr << "error: " << die_locus (die) << ": "
                        << e.what () << '.' << std::endl;
              continue;
            }
diff --git a/dwarflint/locus.cc b/dwarflint/locus.cc
new file mode 100644 (file)
index 0000000..553e7d8
--- /dev/null
@@ -0,0 +1,72 @@
+/* Pedantic checking of DWARF files
+   Copyright (C) 2008,2009,2010,2011 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#include "locus.hh"
+#include "section_id.hh"
+#include <sstream>
+#include <iostream>
+
+std::ostream &
+operator << (std::ostream &os, locus const &loc)
+{
+  os << loc.format ();
+  return os;
+}
+
+char const *
+locus_simple_fmt::offset_n ()
+{
+  return "offset";
+}
+
+void
+locus_simple_fmt::hex (std::ostream &ss, uint64_t off)
+{
+  ss << "0x" << std::hex << off;
+}
+
+void
+locus_simple_fmt::dec (std::ostream &ss, uint64_t off)
+{
+  ss << std::dec << off;
+}
+
+std::string
+simple_locus_aux::format_simple_locus (char const *(*N) (),
+                                      void (*F) (std::ostream &, uint64_t),
+                                      bool brief, section_id sec, uint64_t off)
+{
+  std::stringstream ss;
+  if (!brief)
+    ss << section_name[sec];
+  if (off != (uint64_t)-1)
+    {
+      if (!brief)
+       ss << ": ";
+      ss << N() << " ";
+      F (ss, off);
+    }
+  return ss.str ();
+}
diff --git a/dwarflint/locus.hh b/dwarflint/locus.hh
new file mode 100644 (file)
index 0000000..4557c2a
--- /dev/null
@@ -0,0 +1,112 @@
+/* Pedantic checking of DWARF files
+   Copyright (C) 2009,2010,2011 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifndef DWARFLINT_WHERE_HH
+#define DWARFLINT_WHERE_HH
+
+#include "section_id.hh"
+
+#include <stdint.h>
+#include <iosfwd>
+#include <string>
+
+/// Instances of the locus subclasses are used as pointers into
+/// debuginfo for documentation purposes (messages and errors).  They
+/// are usually tiny structures, and should be used as values, but we
+/// need the abstract interface to be able to format them, and copy
+/// them into ref_record.
+class locus
+{
+public:
+  virtual std::string format (bool brief = false) const = 0;
+  virtual ~locus () {}
+};
+
+std::ostream &operator << (std::ostream &os, locus const &loc);
+
+/// Helper class for simple_locus to reduce the template bloat.
+class simple_locus_aux
+{
+protected:
+  static std::string format_simple_locus (char const *(*N) (),
+                                         void (*F) (std::ostream &, uint64_t),
+                                         bool brief, section_id sec,
+                                         uint64_t off);
+};
+
+/// Template for quick construction of straightforward locus
+/// subclasses (one address, one way of formatting).  N should be a
+/// function that returns the name of the argument.
+/// locus_simple_fmt::hex, locus_simple_fmt::dec would be candidate
+/// parameters for argument F.
+template<char const *(*N) (),
+        void (*F) (std::ostream &, uint64_t)>
+class simple_locus
+  : public locus
+  , private simple_locus_aux
+{
+  section_id _m_sec;
+  uint64_t _m_offset;
+
+public:
+  explicit simple_locus (section_id sec, uint64_t offset = -1)
+    : _m_sec (sec)
+    , _m_offset (offset)
+  {}
+
+  std::string
+  format (bool brief = false) const
+  {
+    return format_simple_locus (N, F, brief, _m_sec, _m_offset);
+  }
+};
+
+/// Constructor of simple_locus that fixes the section_id argument.
+template<section_id S,
+        char const *(*N) (),
+        void (*F) (std::ostream &, uint64_t)>
+class fixed_locus
+  : public simple_locus<N, F>
+{
+public:
+  explicit fixed_locus (uint64_t offset = -1)
+    : simple_locus<N, F> (S, offset)
+  {}
+};
+
+namespace locus_simple_fmt
+{
+  char const *offset_n ();
+  void hex (std::ostream &ss, uint64_t off);
+  void dec (std::ostream &ss, uint64_t off);
+}
+
+/// Straightforward locus for cases where either offset is not
+/// necessary at all, or if it is present, it's simply shown as
+/// "offset: 0xf00".
+typedef simple_locus<locus_simple_fmt::offset_n,
+                    locus_simple_fmt::hex> section_locus;
+
+#endif//DWARFLINT_WHERE_HH
index 987c56dfb253db9480cf891f9a69ed343ada3c80..bbfe6764a5ef66e47ea24a57e56097434b3d8057 100644 (file)
    Network licensing program, please visit www.openinventionnetwork.com
    <http://www.openinventionnetwork.com>.  */
 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
 #include "lowlevel_checks.hh"
 #include "sections.hh"
 #include "check_debug_info.hh"
index 548a15f5409c0f6c74783bd029007bd0aa50513d..70bea21b921fc9f1f2795c928a59a2059311dfc2 100644 (file)
@@ -135,13 +135,6 @@ global_opt<void_option>
 global_opt<void_option>
   be_tolerant ("Be somewhat more tolerant.", "tolerant");
 
-// xxx as soon as where is in c++, this can move there
-global_opt<void_option>
-  opt_show_refs("\
-When validating .debug_loc and .debug_ranges, display information about \
-the DIE referring to the entry in consideration", "ref");
-extern "C" bool show_refs () { return (bool)opt_show_refs; }
-
 int
 main (int argc, char *argv[])
 {
index 995220c3ff8c08bbe085df1db63dd45af7f8d64f..c696aca4d82b4f97477f5551ebc60b809cad0de5 100644 (file)
@@ -24,7 +24,6 @@
    <http://www.openinventionnetwork.com>.  */
 
 #include "messages.hh"
-#include "misc.hh"
 #include "coverage.hh"
 #include "option.hh"
 
@@ -217,9 +216,7 @@ operator<< (std::ostream &o, __attribute__ ((unused)) message_criteria const &cr
 void
 message_criteria::operator *= (message_criteria const &rhs)
 {
-  struct message_criteria ret;
-  WIPE (ret);
-
+  message_criteria ret;
   for (size_t i = 0; i < size (); ++i)
     for (size_t j = 0; j < rhs.size (); ++j)
       {
@@ -247,34 +244,32 @@ message_criteria::and_not (message_term const &term)
 }
 
 static void
-wr_verror (const struct where *wh, const char *format, va_list ap)
+wr_verror (locus const &loc, const char *format, va_list ap)
 {
-  printf ("error: %s", where_fmt (wh, NULL));
+  printf ("error: %s", loc.format ().c_str ());
   vprintf (format, ap);
-  where_fmt_chain (wh, "error");
   ++error_count;
 }
 
 static void
-wr_vwarning (const struct where *wh, const char *format, va_list ap)
+wr_vwarning (locus const &loc, const char *format, va_list ap)
 {
-  printf ("%s", where_fmt (wh, NULL));
+  printf ("%s", loc.format ().c_str ());
   vprintf (format, ap);
-  where_fmt_chain (wh, "warning");
   ++error_count;
 }
 
 void
-wr_error (const struct where *wh, const char *format, ...)
+wr_error (locus const *loc, const char *format, ...)
 {
   va_list ap;
   va_start (ap, format);
-  wr_verror (wh, format, ap);
+  wr_verror (*loc, format, ap);
   va_end (ap);
 }
 
 void
-wr_message (unsigned long category, const struct where *wh,
+wr_message (unsigned long category, locus const *loc,
            const char *format, ...)
 {
   va_list ap;
@@ -286,9 +281,9 @@ wr_message (unsigned long category, const struct where *wh,
   if (whether && message_accept (&warning_criteria, category))
     {
       if (message_accept (&error_criteria, category))
-       wr_verror (wh, format, ap);
+       wr_verror (*loc, format, ap);
       else
-       wr_vwarning (wh, format, ap);
+       wr_vwarning (*loc, format, ap);
     }
   va_end (ap);
 }
@@ -336,9 +331,9 @@ message_count_filter::should_emit (void const *key)
 }
 
 message_context::message_context (message_count_filter *filter,
-                                 where const *where, char const *prefix)
+                                 locus const *loc, char const *prefix)
   : _m_filter (filter)
-  , _m_where (where)
+  , _m_loc (loc)
   , _m_prefix (prefix)
 {}
 
@@ -353,8 +348,8 @@ message_context::when (bool whether) const
 
       std::ostream &ret = get_stream ();
       ret << _m_prefix;
-      if (_m_where)
-       ret << *_m_where << ": ";
+      if (_m_loc != NULL)
+       ret << _m_loc->format () << ": ";
       return ret;
     }
   else
@@ -412,22 +407,23 @@ wr_error ()
 }
 
 std::ostream &
-wr_error (where const &wh)
+wr_error (locus const &loc)
 {
-  return wr_error () << wh << ": ";
+  std::string fmt = loc.format ();
+  return wr_error () << fmt << ": ";
 }
 
 message_context
-message_context::filter_message (where const *wh, message_category category)
+message_context::filter_message (locus const *loc, message_category category)
 {
   if (!message_accept (&warning_criteria, category))
     return message_context (NULL, NULL, NULL);
   else if (message_accept (&error_criteria, category))
     return message_context (message_count_filter::inst (),
-                           wh, "error: ");
+                           loc, "error: ");
   else
     return message_context (message_count_filter::inst (),
-                           wh, "warning: ");
+                           loc, "warning: ");
 }
 
 message_context
@@ -437,24 +433,24 @@ wr_message (message_category category)
 }
 
 message_context
-wr_message (where const &wh, message_category category)
+wr_message (locus const &loc, message_category category)
 {
-  return message_context::filter_message (&wh, category);
+  return message_context::filter_message (&loc, category);
 }
 
 void
 wr_format_padding_message (message_category category,
-                          struct where const *wh,
+                          locus const &loc,
                           uint64_t start, uint64_t end, char const *kind)
 {
   char msg[128];
-  wr_message (*wh, category)
+  wr_message (loc, category)
     << range_fmt (msg, sizeof msg, start, end)
     << ": " << kind << "." << std::endl;
 }
 
 void
-wr_format_leb128_message (struct where const *where,
+wr_format_leb128_message (locus const &loc,
                          const char *what,
                          const char *purpose,
                          const unsigned char *begin, const unsigned char *end)
@@ -464,28 +460,28 @@ wr_format_leb128_message (struct where const *where,
   char *ptr = buf;
   for (; begin < end; ++begin)
     ptr += sprintf (ptr, " %02x", *begin);
-  wr_message (*where, category)
+  wr_message (loc, category)
     << what << ": value " << purpose << " encoded as `"
     << (buf + 1) << "'." << std::endl;
 }
 
 void
 wr_message_padding_0 (message_category category,
-                     struct where const *wh,
+                     locus const &loc,
                      uint64_t start, uint64_t end)
 {
   wr_format_padding_message (category | mc_acc_bloat | mc_impact_1,
-                            wh, start, end,
+                            loc, start, end,
                             "unnecessary padding with zero bytes");
 }
 
 void
 wr_message_padding_n0 (message_category category,
-                      struct where const *wh,
+                      locus const &loc,
                       uint64_t start, uint64_t end)
 {
   wr_format_padding_message (category | mc_acc_bloat | mc_impact_1,
-                            wh, start, end,
+                            loc, start, end,
                             "unreferenced non-zero bytes");
 }
 
index 6e85d4299d6b11488fe98459a03b78fb73ebd2ea..88ed3a849c4fa2514dc071ad9bd2b6d1a63c656b 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef DWARFLINT_MESSAGES_HH
 #define DWARFLINT_MESSAGES_HH
 
-#include "where.h"
+#include "locus.hh"
 #include "libdw.h"
 #include <string>
 #include <iosfwd>
@@ -114,30 +114,30 @@ std::ostream &operator<< (std::ostream &o, message_criteria const &criteria);
 
 message_criteria operator ! (message_term const &);
 
-extern void wr_error (const struct where *wh, const char *format, ...)
+extern void wr_error (locus const *wh, const char *format, ...)
   __attribute__ ((format (printf, 2, 3)));
 
-extern void wr_message (unsigned long category, const struct where *wh,
+extern void wr_message (unsigned long category, locus const *loc,
                        const char *format, ...)
   __attribute__ ((format (printf, 3, 4)));
 
 extern void wr_format_padding_message (message_category category,
-                                      struct where const *wh,
+                                      locus const &loc,
                                       uint64_t start, uint64_t end,
                                       char const *kind);
 
-extern void wr_format_leb128_message (struct where const *where,
+extern void wr_format_leb128_message (locus const &loc,
                                      const char *what,
                                      const char *purpose,
                                      const unsigned char *begin,
                                      const unsigned char *end);
 
 extern void wr_message_padding_0 (message_category category,
-                                 struct where const *wh,
+                                 locus const &loc,
                                  uint64_t start, uint64_t end);
 
 extern void wr_message_padding_n0 (message_category category,
-                                  struct where const *wh,
+                                  locus const &loc,
                                   uint64_t start, uint64_t end);
 
 extern bool message_accept (struct message_criteria const *cri,
@@ -191,18 +191,18 @@ class message_context
   static bool _m_last_emitted;
 
   message_count_filter *_m_filter;
-  where const *_m_where;
+  locus const *_m_loc;
   char const *_m_prefix;
 
-  friend message_context wr_message (where const &wh, message_category cat);
+  friend message_context wr_message (locus const &loc, message_category cat);
   friend message_context wr_message (message_category cat);
   friend bool wr_prev_emitted ();
 
   message_context (message_count_filter *filter,
-                  where const *where, char const *prefix);
+                  locus const *loc, char const *prefix);
 
 public:
-  static message_context filter_message (where const *wh,
+  static message_context filter_message (locus const *loc,
                                         message_category category);
 
   std::ostream &operator << (char const *message);
@@ -231,9 +231,9 @@ public:
   std::ostream &when_prev () const;
 };
 
-std::ostream &wr_error (where const &wh);
+std::ostream &wr_error (locus const &loc);
 std::ostream &wr_error ();
-message_context wr_message (where const &wh, message_category cat);
+message_context wr_message (locus const &loc, message_category cat);
 message_context wr_message (message_category cat);
 void wr_reset_counters ();
 bool wr_prev_emitted ();
index 497ee114ef90f3d566b94aa1c46a14939aae7af4..895732fc93daf95803e9978e99ee7cb75731e3d4 100644 (file)
@@ -1,5 +1,5 @@
 /* Pedantic checking of DWARF files
-   Copyright (C) 2008, 2009, 2010 Red Hat, Inc.
+   Copyright (C) 2008, 2009, 2010, 2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -45,11 +45,11 @@ necessary_alignment (uint64_t start, uint64_t length, uint64_t align)
 
 bool
 supported_version (unsigned version,
-                  size_t num_supported, struct where *where, ...)
+                  size_t num_supported, locus const &loc, ...)
 {
   bool retval = false;
   va_list ap;
-  va_start (ap, where);
+  va_start (ap, loc);
   for (size_t i = 0; i < num_supported; ++i)
     {
       unsigned v = va_arg (ap, unsigned);
@@ -62,7 +62,7 @@ supported_version (unsigned version,
   va_end (ap);
 
   if (!retval)
-    wr_error (where, ": unsupported version %d.\n", version);
+    wr_error (loc) << "unsupported version " << version << ".\n";
 
   return retval;
 }
index fac9526d260f074a8074bd1a757c9cae22bf8e98..6be3dbd5ade2462b307adfce8efe68402fa2b32f 100644 (file)
@@ -27,7 +27,7 @@
 #define DWARFLINT_MISC_HH
 
 #include <cstring>
-#include "where.h"
+#include "locus.hh"
 
 extern "C"
 {
@@ -49,14 +49,12 @@ extern "C"
       }                                                        \
   } while (0)
 
-#define WIPE(OBJ) memset (&OBJ, 0, sizeof (OBJ))
-
 bool address_aligned (uint64_t addr, uint64_t align);
 bool necessary_alignment (uint64_t start, uint64_t length,
                          uint64_t align);
 
 bool supported_version (unsigned version,
-                       size_t num_supported, struct where *where, ...);
+                       size_t num_supported, locus const &loc, ...);
 
 #define UNREACHABLE assert (!"unreachable")
 
index de01463f9b26b2d496634417ca5f6c2fd5b0484a..6f289ab8dfec6c38df249c7e7b27be089cc5e5c3 100644 (file)
@@ -64,3 +64,10 @@ pri::operator << (std::ostream &os, pri::range const &obj)
   return os << "[" << pri::addr (obj.start)
            << ", " << pri::addr (obj.end) << ")";
 }
+
+std::string
+pri::attr_name (int name)
+{
+  assert (name != -1);
+  return elfutils::dwarf::attributes::name (name);
+}
index 67705f40c658dc2c00dfd6e83e41f0c3333bd7f3..cef1ba9a6805c4ce2f42912809fa38ad632c4f2c 100644 (file)
@@ -114,6 +114,8 @@ namespace pri
     friend std::ostream &operator << (std::ostream &os, range const &obj);
   };
   std::ostream &operator << (std::ostream &os, range const &obj);
+
+  std::string attr_name (int name);
 }
 
 #endif//DWARFLINT_PRI_H
index 29fc451c03ad5a1d8d011feb460037b2876bb261..2a1a39f3bfc457477d5fe88ec001f24b5066c9c0 100644 (file)
 #include <stdbool.h>
 #include "../libelf/libelf.h"
 
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
 /* Functions and data structures related to bounds-checked
    reading.  */
 
@@ -82,8 +77,5 @@ bool read_ctx_eof (struct read_ctx *ctx);
 bool read_check_zero_padding (struct read_ctx *ctx,
                              uint64_t *ret_off_start,
                              uint64_t *ret_off_end);
-#ifdef __cplusplus
-}
-#endif
 
 #endif
index 2e23248b8d6e5a2e0563f3a7c42b601623b58cec..563077cc4a96194d01748a2f8897b863e5469291 100644 (file)
 #include "messages.hh"
 #include "misc.hh"
 #include "readctx.hh"
+#include "pri.hh"
 
 #include <sstream>
 #include <libebl.h>
 #include <cassert>
-#include <inttypes.h>
+#include <cinttypes>
 
-static struct where
-where_from_reloc (struct relocation_data *reloc, struct where const *ref)
+namespace
 {
-  struct where where
-    = WHERE (reloc->type == SHT_REL ? sec_rel : sec_rela, NULL);
-  where_reset_1 (&where, reloc->rel[reloc->index].offset);
-  where.ref = ref;
-  return where;
+  class reloc_locus
+    : public locus
+  {
+    locus const &_m_ref;
+    size_t _m_index;
+    uint64_t _m_offset;
+    int _m_type;
+
+  public:
+    reloc_locus (int type, locus const &ref, uint64_t offset)
+      : _m_ref (ref)
+      , _m_index (-1)
+      , _m_offset (offset)
+      , _m_type (type)
+    {
+    }
+
+    reloc_locus (int type, locus const &ref, unsigned index)
+      : _m_ref (ref)
+      , _m_index (index)
+      , _m_offset (-1)
+      , _m_type (type)
+    {
+    }
+
+    void
+    set_offset (uint64_t offset)
+    {
+      _m_offset = offset;
+    }
+
+    virtual std::string
+    format (bool) const
+    {
+      std::stringstream ss;
+      ss << (_m_type == SHT_REL ? ".rel" : ".rela") << " ";
+      if (_m_offset != (uint64_t)-1)
+       ss << pri::hex (_m_offset);
+      else
+       {
+         assert (_m_index != (size_t)-1);
+         ss << "#" << _m_index;
+       }
+
+      // Do non-brief formatting of referee
+      ss << " of " << _m_ref.format ();
+      return ss.str ();
+    }
+  };
 }
 
 relocation *
 relocation_next (relocation_data *reloc, uint64_t offset,
-                struct where const *where, enum skip_type st)
+                locus const &loc, enum skip_type st)
 {
   if (reloc == NULL || reloc->rel == NULL)
     return NULL;
@@ -71,8 +115,7 @@ relocation_next (relocation_data *reloc, uint64_t offset,
        {
          if (st != skip_ok)
            {
-             struct where reloc_where = where_from_reloc (reloc, where);
-             where_reset_2 (&reloc_where, rel->offset);
+             reloc_locus reloc_where (reloc->type, loc, rel->offset);
              wr_error (reloc_where)
                << (st == skip_unref
                    ? "relocation targets unreferenced portion of the section."
@@ -94,10 +137,10 @@ relocation_next (relocation_data *reloc, uint64_t offset,
    matching that offset is immediately yielded.  */
 void
 relocation_skip (struct relocation_data *reloc, uint64_t offset,
-                struct where const *where, enum skip_type st)
+                locus const &loc, enum skip_type st)
 {
   if (reloc != NULL && reloc->rel != NULL)
-    relocation_next (reloc, offset - 1, where, st);
+    relocation_next (reloc, offset - 1, loc, st);
 }
 
 void
@@ -109,15 +152,11 @@ relocation_reset (struct relocation_data *reloc)
 
 /* Skip all the remaining relocations.  */
 void
-relocation_skip_rest (struct relocation_data *reloc,
-                     enum section_id id)
+relocation_skip_rest (relocation_data *reloc,
+                     locus const &loc)
 {
   if (reloc->rel != NULL)
-    {
-      where wh = WHERE (id, NULL);
-      relocation_next (reloc, (uint64_t)-1, &wh,
-                      skip_mismatched);
-    }
+    relocation_next (reloc, (uint64_t)-1, loc, skip_mismatched);
 }
 
 static void
@@ -126,8 +165,8 @@ do_one_relocation (elf_file const *file,
                   relocation *rel,
                   unsigned rel_width,
                   uint64_t *value,
-                  where const &reloc_where,
-                  section_id offset_into,
+                  reloc_locus const &reloc_where,
+                  rel_target reltgt,
                   GElf_Sym *symbol,
                   GElf_Sym **symptr)
 {
@@ -189,23 +228,23 @@ do_one_relocation (elf_file const *file,
     }
 
   /* It's target value, not section offset.  */
-  if (offset_into == rel_value
-      || offset_into == rel_address
-      || offset_into == rel_exec)
+  if (reltgt == rel_target::rel_value
+      || reltgt == rel_target::rel_address
+      || reltgt == rel_target::rel_exec)
     {
       /* If a target value is what's expected, then complain if
         it's not either SHN_ABS, an SHF_ALLOC section, or
         SHN_UNDEF.  For data forms of address_size, an SHN_UNDEF
         reloc is acceptable, otherwise reject it.  */
       if (!(section_index == SHN_ABS
-           || (offset_into == rel_address
+           || (reltgt == rel_target::rel_address
                && (section_index == SHN_UNDEF
                    || section_index == SHN_COMMON))))
        {
-         if (offset_into != rel_address && section_index == SHN_UNDEF)
+         if (reltgt != rel_target::rel_address && section_index == SHN_UNDEF)
            wr_error (&reloc_where,
-                       ": relocation of an address is formed using SHN_UNDEF symbol"
-                       " (symtab index %d).\n", rel->symndx);
+                     ": relocation of an address is formed using SHN_UNDEF symbol"
+                     " (symtab index %d).\n", rel->symndx);
          else
            {
              require_valid_section_index;
@@ -214,7 +253,7 @@ do_one_relocation (elf_file const *file,
                wr_message (mc_reloc | mc_impact_3, &reloc_where,
                            ": associated section %s isn't SHF_ALLOC.\n",
                            file->sec[section_index].name);
-             if (offset_into == rel_exec
+             if (reltgt == rel_target::rel_exec
                  && (shdr->sh_flags & SHF_EXECINSTR) != SHF_EXECINSTR)
                /* This may still be kosher, but it's suspicious.  */
                wr_message (mc_reloc | mc_impact_2, &reloc_where,
@@ -226,13 +265,14 @@ do_one_relocation (elf_file const *file,
   else
     {
       require_valid_section_index;
-      if (file->sec[section_index].id != offset_into)
+      section_id secid = file->sec[section_index].id;
+      if (reltgt != secid)
        // If symtab[symndx].st_shndx does not match the expected
        // debug section's index, complain.
        wr_error (reloc_where)
          << "relocation references section "
          << (file->sec[section_index].name ?: "<invalid>") << ", but "
-         << WHERE (offset_into, NULL) << " was expected." << std::endl;
+         << section_locus (secid) << " was expected." << std::endl;
     }
 
   /* Only do the actual relocation if we have ET_REL files.  For
@@ -257,16 +297,14 @@ relocate_one (struct elf_file const *file,
              struct relocation_data *reloc,
              struct relocation *rel,
              unsigned width, uint64_t *value,
-             struct where const *where,
-             enum section_id offset_into, GElf_Sym **symptr)
+             locus const &loc,
+             rel_target reltgt,
+             GElf_Sym **symptr)
 {
   if (rel->invalid)
     return;
 
-  struct where reloc_where = where_from_reloc (reloc, where);
-  where_reset_2 (&reloc_where, rel->offset);
-  struct where reloc_ref_where = reloc_where;
-  reloc_ref_where.next = where;
+  reloc_locus reloc_where (reloc->type, loc, rel->offset);
 
   GElf_Sym symbol_mem, *symbol;
   if (symptr != NULL)
@@ -277,10 +315,10 @@ relocate_one (struct elf_file const *file,
   else
     symbol = &symbol_mem;
 
-  if (offset_into == sec_invalid)
+  if (reltgt == sec_invalid)
     {
-      wr_message (mc_impact_3 | mc_reloc, &reloc_ref_where,
-                 ": relocates a datum that shouldn't be relocated.\n");
+      wr_message (reloc_where, mc_impact_3 | mc_reloc)
+       << "relocates a datum that shouldn't be relocated.\n";
       return;
     }
 
@@ -314,14 +352,14 @@ relocate_one (struct elf_file const *file,
     };
 
   if (rel_width != width)
-    wr_error (&reloc_ref_where,
-             ": %d-byte relocation relocates %d-byte datum.\n",
-             rel_width, width);
+    wr_error (reloc_where)
+      << rel_width << "-byte relocation relocates "
+      << width << "-byte datum.\n";
 
   // Tolerate if we failed to obtain the symbol table.
   if (reloc->symdata != NULL)
     do_one_relocation (file, reloc, rel, rel_width, value,
-                      reloc_where, offset_into, symbol, symptr);
+                      reloc_where, reltgt, symbol, symptr);
 }
 
 static GElf_Rela *
@@ -371,17 +409,15 @@ read_rel (struct elf_file *file,
     : (is_rela ? sizeof (Elf32_Rela) : sizeof (Elf32_Rel));
   size_t count = reldata->d_size / entrysize;
 
-  struct where parent = WHERE (sec->id, NULL);
-  struct where where = WHERE (is_rela ? sec_rela : sec_rel, NULL);
-  where.ref = &parent;
+  section_locus parent (sec->id);
 
   for (unsigned i = 0; i < count; ++i)
     {
-      where_reset_1 (&where, i);
+      reloc_locus where (sec->rel.type, parent, i);
 
       REALLOC (&sec->rel, rel);
       struct relocation *cur = sec->rel.rel + sec->rel.size++;
-      WIPE (*cur);
+      new (cur) relocation ();
 
       GElf_Rela rela_mem, *rela
        = get_rel_or_rela (reldata, i, &rela_mem, sec->rel.type);
@@ -405,7 +441,7 @@ read_rel (struct elf_file *file,
       cur->symndx = GELF_R_SYM (rela->r_info);
       cur->type = cur_type;
 
-      where_reset_2 (&where, cur->offset);
+      where.set_offset (cur->offset);
 
       Elf_Type type = ebl_reloc_simple_type (file->ebl, cur->type);
       int width;
index d7685c6fe67754c54120faf755dc67d8dc4c0d39..d35580fceadacd1d0a684a55d0db318fd6dc2c9d 100644 (file)
@@ -1,5 +1,5 @@
 /* Pedantic checking of DWARF files.
-   Copyright (C) 2008, 2009, 2010 Red Hat, Inc.
+   Copyright (C) 2008, 2009, 2010, 2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
 #ifndef DWARFLINT_RELOC_H
 #define DWARFLINT_RELOC_H
 
-#include "where.h"
+#include "locus.hh"
 #include "elf_file_i.hh"
 #include <libelf.h>
 #include <gelf.h>
@@ -40,6 +40,14 @@ struct relocation
   bool invalid;        /* Whether this one relocation should be
                   ignored.  Necessary so that we don't report
                   invalid & missing relocation twice.  */
+
+  relocation ()
+    : offset (0)
+    , addend (0)
+    , symndx (0)
+    , type (0)
+    , invalid (false)
+  {}
 };
 
 struct relocation_data
@@ -54,6 +62,15 @@ struct relocation_data
   size_t size;
   size_t alloc;
   size_t index;            /* Current index. */
+
+  relocation_data ()
+    : symdata (NULL)
+    , type (SHT_NULL)
+    , rel (NULL)
+    , size (0)
+    , alloc (0)
+    , index (0)
+  {}
 };
 
 enum skip_type
@@ -63,28 +80,79 @@ enum skip_type
     skip_ok,
   };
 
+struct rel_target
+{
+  enum target
+    {
+      rel_value,       /* For relocations, this denotes that the
+                          relocation is applied to target value, not a
+                          section offset.  */
+      rel_address,     /* Same as above, but for addresses.  */
+      rel_exec,                /* Some as above, but we expect EXEC bit.  */
+    };
+
+private:
+  bool _m_is_section;
+  union
+  {
+    section_id _m_section;
+    target _m_target;
+  };
+
+public:
+  rel_target (section_id sec)
+    : _m_is_section (true)
+    , _m_section (sec)
+  {}
+
+  rel_target (target t)
+    : _m_is_section (false)
+    , _m_target (t)
+  {}
+
+  bool
+  operator== (section_id sec)
+  {
+    return _m_is_section && _m_section == sec;
+  }
+
+  bool
+  operator== (target tgt)
+  {
+    return !_m_is_section && _m_target == tgt;
+  }
+
+  template<class T>
+  bool
+  operator!= (T t)
+  {
+    return !(*this == t);
+  }
+};
+
 bool read_rel (struct elf_file *file, struct sec *sec,
               Elf_Data *reldata, bool elf_64);
 
 relocation *relocation_next (struct relocation_data *reloc,
                             uint64_t offset,
-                            struct where const *where,
+                            locus const &loc,
                             enum skip_type st);
 
 void relocation_reset (struct relocation_data *reloc);
 
 void relocation_skip (struct relocation_data *reloc, uint64_t offset,
-                     struct where const *where, enum skip_type st);
+                     locus const &loc, enum skip_type st);
 
 void relocation_skip_rest (struct relocation_data *reloc,
-                          enum section_id id);
+                          locus const &loc);
 
 void relocate_one (struct elf_file const *file,
                   struct relocation_data *reloc,
                   struct relocation *rel,
                   unsigned width, uint64_t *value,
-                  struct where const *where,
-                  enum section_id offset_into, GElf_Sym **symptr);
+                  locus const &loc,
+                  rel_target reltgt,
+                  GElf_Sym **symptr);
 
 #define PRI_LACK_RELOCATION ": %s seems to lack a relocation.\n"
 
index 4b937d7fd7f98e9b582c89c07643b9b618a27c6c..bd005c302e4cea23f8aecec68f80c90707b12998 100644 (file)
@@ -1,5 +1,5 @@
 /* Pedantic checking of DWARF files
-   Copyright (C) 2009, 2010 Red Hat, Inc.
+   Copyright (C) 2009, 2010, 2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -45,22 +45,9 @@ enum section_id
     /* Debuginfo sections:  */
 #define SEC(n) sec_##n,
     DEBUGINFO_SECTIONS
-    count_debuginfo_sections,
 #undef SEC
 
-    /* Non-debuginfo sections:  */
-    sec_rel = count_debuginfo_sections,
-    sec_rela,
-
-    // XXX the following should really be split out to different enum
-    /* Non-sections:  */
-    sec_locexpr,       /* Not a section, but a portion of file that
-                          contains a location expression.  */
-    rel_value,         /* For relocations, this denotes that the
-                          relocation is applied to taget value, not a
-                          section offset.  */
-    rel_address,       /* Same as above, but for addresses.  */
-    rel_exec,          /* Some as above, but we expect EXEC bit.  */
+    count_debuginfo_sections
   };
 
 // section_name[0] is for sec_invalid.  The last index is for
index 6f9f2546146c0f7e2977dde61b60a11aba867c07..a1c1aab9514c160d7db0527701219f5a28b38f24 100644 (file)
@@ -246,7 +246,7 @@ namespace
 
     /* Section 0 is special, skip it.  */
     REALLOC (file, sec);
-    file->sec[file->size++].id = sec_invalid;
+    new (file->sec + file->size++) sec ();
 
     if (false)
       {
@@ -266,6 +266,7 @@ namespace
        REALLOC (file, sec);
        size_t curndx = file->size++;
        struct sec *cursec = file->sec + curndx;
+       new (cursec) sec ();
 
        GElf_Shdr *shdr = gelf_getshdr (scn, &cursec->shdr);
        if (shdr == NULL)
@@ -285,9 +286,9 @@ namespace
 
        secentry *entry = secinfo.get (scnname);
        cursec->scn = scn;
-       cursec->id = entry != NULL ? entry->id : sec_invalid;
+       if (entry != NULL)
+         cursec->id = entry->id;
        cursec->name = scnname;
-       cursec->rel = (struct relocation_data){NULL, SHT_NULL, NULL, 0, 0, 0};
 
        /* Dwarf section.  */
        if (entry != NULL)
@@ -385,7 +386,7 @@ namespace
                struct sec *sec = file->sec + cur->secndx;
                sec->rel.type = cur->reltype;
                if (sec->data == NULL)
-                 wr_error (WHERE (sec->id, NULL))
+                 wr_error (section_locus (sec->id))
                    << "this data-less section has a relocation section."
                    << std::endl;
                else if (read_rel (file, sec, cur->reldata, file->addr_64))
@@ -395,7 +396,7 @@ namespace
 
        if (secentry *str = secinfo.get (".debug_str"))
          if (str->reldata != NULL)
-           wr_message (WHERE (sec_str, NULL), mc_impact_2 | mc_elf)
+           wr_message (section_locus (sec_str), mc_impact_2 | mc_elf)
              << "there's a relocation section associated with this section."
              << std::endl;
       }
index 3565dc88c03e126024d4df8921c6ae60498bc941..00b9a35339567273e295a39f7528ed97a3ccd2be 100755 (executable)
@@ -30,7 +30,7 @@ srcdir=$srcdir/tests
 testfiles DW_AT-later-version
 
 testrun_compare ./dwarflint --nognu DW_AT-later-version <<EOF
-warning: .debug_abbrev: abbr. attribute 0x15: attribute DW_AT_endianity from later DWARF version.
+warning: .debug_abbrev: abbr. 0x11, attr. endianity: attribute from later DWARF version.
 warning: .debug_info: DIE 0xb: DW_AT_low_pc value not below DW_AT_high_pc.
 warning: .debug_info: DIE 0x29: variable has decl_file, but NOT decl_line
 EOF
index 3080f3e9a25020ba12ffb7e96b3f663f55094707..fa06499da2307eef48b08296d47833805b617b45 100755 (executable)
@@ -49,7 +49,7 @@ EOF
 testrun_compare ./dwarflint empty-1 <<EOF
 warning: .debug_info: DIE 0xb: DW_AT_low_pc value not below DW_AT_high_pc.
 warning: .debug_line: table 0: no CU uses this line table.
-error: .debug_info: DIE 0x29 (abbr. attribute 0x13): references .debug_line table, but CU DIE lacks DW_AT_stmt_list.
+error: .debug_info: DIE 0x29, attr. decl_file: references .debug_line table, but CU DIE lacks DW_AT_stmt_list.
 EOF
 
 testrun_compare ./dwarflint garbage-1 <<EOF
@@ -60,7 +60,7 @@ EOF
 
 testrun_compare ./dwarflint garbage-2 <<EOF
 error: .debug_info: CU 0: toplevel DIE must be either compile_unit or partial_unit.
-error: .debug_info: DIE 0xab (abbreviation 113): DIE chain not terminated with null entry.
+error: .debug_info: DIE 0xab: DIE chain not terminated with null entry.
 EOF
 
 testrun_compare ./dwarflint --check=@low garbage-3 <<EOF
@@ -69,62 +69,62 @@ EOF
 
 testrun_compare ./dwarflint garbage-4 <<EOF
 error: .debug_info: DIE 0x6c: this DIE claims that its sibling is 0x80000085 but it's actually 0x85.
-error: .debug_info: DIE 0xab (abbreviation 113): DIE chain not terminated with null entry.
+error: .debug_info: DIE 0xab: DIE chain not terminated with null entry.
 EOF
 
 testrun_compare ./dwarflint garbage-5 <<EOF
-error: .debug_info: DIE 0xab (abbreviation 113): DIE chain not terminated with null entry.
+error: .debug_info: DIE 0xab: DIE chain not terminated with null entry.
 error: .debug_line: offset 0x3e: not enough data to read an opcode of length 5.
-error: .debug_info: DIE 0xb (abbr. attribute 0xc): unresolved reference to .debug_line table 0x0.
+error: .debug_info: DIE 0xb, attr. stmt_list: unresolved reference to .debug_line table 0x0.
 EOF
 
 testrun_compare ./dwarflint garbage-6 <<EOF
 error: .debug_info: CU 0: invalid address size: 9 (only 4 or 8 allowed).
 error: .debug_info: couldn't load CU headers for processing .debug_abbrev; assuming latest DWARF flavor.
-error: .debug_abbrev: abbr. attribute 0xc: attribute stmt_list with invalid form data4.
-error: .debug_abbrev: abbr. attribute 0x23: attribute frame_base with invalid form block1.
-error: .debug_abbrev: abbr. attribute 0x34: attribute location with invalid form block1.
+error: .debug_abbrev: abbr. 0x0, attr. stmt_list: attribute with invalid form DW_FORM_data4.
+error: .debug_abbrev: abbr. 0x13, attr. frame_base: attribute with invalid form DW_FORM_block1.
+error: .debug_abbrev: abbr. 0x2c, attr. location: attribute with invalid form DW_FORM_block1.
 EOF
 
 testrun_compare ./dwarflint garbage-7 <<EOF
 warning: .debug_abbrev: abbr. attribute 0x7e: invalid or unknown name 0x703.
-error: .debug_abbrev: abbr. attribute 0x7e: invalid form 0x0.
-error: .debug_abbrev: abbreviation 122: missing zero to mark end-of-table.
+error: .debug_abbrev: abbr. 0x7a, attr. 0x703: invalid form 0x0.
+error: .debug_abbrev: missing zero to mark end-of-table.
 EOF
 
 testrun_compare ./dwarflint garbage-8 <<EOF
-error: .debug_info: DIE 0x6c (abbr. attribute 0x43): DW_AT_sibling with a value of 0.
+error: .debug_info: DIE 0x6c, attr. sibling: has a value of 0.
 error: .debug_info: DIE 0x6c: This DIE had children, but no DW_AT_sibling attribute.
-error: .debug_info: DIE 0xab (abbreviation 113): DIE chain not terminated with null entry.
+error: .debug_info: DIE 0xab: DIE chain not terminated with null entry.
 EOF
 
 testrun_compare ./dwarflint garbage-9 <<EOF
-error: .debug_info: DIE 0x84 (abbr. attribute 0x5f): invalid reference outside the CU: 0xef00ab.
+error: .debug_info: DIE 0x84, attr. type: invalid reference outside the CU: 0xef00ab.
 error: .debug_info: DIE 0x6c: is the last sibling in chain, but has a DW_AT_sibling attribute.
-error: .debug_info: DIE 0xab (abbreviation 113): DIE chain not terminated with null entry.
+error: .debug_info: DIE 0xab: DIE chain not terminated with null entry.
 EOF
 
 testrun_compare ./dwarflint garbage-10 <<EOF
-warning: .rela.debug_info: offset 0xc: relocation formed using STT_SECTION symbol with non-zero value.
-error: .rela.debug_info: offset 0x11: couldn't obtain symbol #7208969: invalid section index.
+warning: .rela 0xc of .debug_info: DIE 0xb, attr. producer: relocation formed using STT_SECTION symbol with non-zero value.
+error: .rela 0x11 of .debug_info: DIE 0xb, attr. comp_dir: couldn't obtain symbol #7208969: invalid section index.
 warning: .debug_info: DIE 0xb: DW_AT_low_pc value not below DW_AT_high_pc.
 EOF
 
 testrun_compare ./dwarflint garbage-11 <<EOF
-error: .rela.debug_info: offset 0x600: invalid relocation 2560 (<INVALID RELOC>).
-error: .rela.debug_info: offset 0xc00: invalid relocation 2560 (<INVALID RELOC>).
-error: .rela.debug_info: offset 0x1100: invalid relocation 2560 (<INVALID RELOC>).
-error: .rela.debug_info: offset 0x1500: invalid relocation 256 (<INVALID RELOC>).
-error: .rela.debug_info: offset 0x1d00: invalid relocation 256 (<INVALID RELOC>).
-error: .rela.debug_info: offset 0x2500: invalid relocation 2560 (<INVALID RELOC>).
-error: .rela.debug_info: offset 0x3600: invalid relocation 256 (<INVALID RELOC>).
+error: .rela 0x600 of .debug_info: invalid relocation 2560 (<INVALID RELOC>).
+error: .rela 0xc00 of .debug_info: invalid relocation 2560 (<INVALID RELOC>).
+error: .rela 0x1100 of .debug_info: invalid relocation 2560 (<INVALID RELOC>).
+error: .rela 0x1500 of .debug_info: invalid relocation 256 (<INVALID RELOC>).
+error: .rela 0x1d00 of .debug_info: invalid relocation 256 (<INVALID RELOC>).
+error: .rela 0x2500 of .debug_info: invalid relocation 2560 (<INVALID RELOC>).
+error: .rela 0x3600 of .debug_info: invalid relocation 256 (<INVALID RELOC>).
 warning: .debug_info: CU 0: abbrev table offset seems to lack a relocation
-warning: .debug_info: DIE 0xb (abbr. attribute 0): strp seems to lack a relocation
-warning: .debug_info: DIE 0xb (abbr. attribute 0x4): strp seems to lack a relocation
-warning: .debug_info: DIE 0xb (abbr. attribute 0xa): data4 seems to lack a relocation
+warning: .debug_info: DIE 0xb, attr. producer: strp seems to lack a relocation
+warning: .debug_info: DIE 0xb, attr. comp_dir: strp seems to lack a relocation
+warning: .debug_info: DIE 0xb, attr. stmt_list: data4 seems to lack a relocation
 warning: .debug_info: DIE 0xb: DW_AT_low_pc value not below DW_AT_high_pc.
 error: .debug_line: table 0: header claims that it has a size of 542, but in fact it has a size of 30.
-error: .debug_info: DIE 0xb (abbr. attribute 0xa): unresolved reference to .debug_line table 0x0.
+error: .debug_info: DIE 0xb, attr. stmt_list: unresolved reference to .debug_line table 0x0.
 EOF
 
 testrun_compare ./dwarflint garbage-12 <<EOF
diff --git a/dwarflint/where.c b/dwarflint/where.c
deleted file mode 100644 (file)
index e7547f7..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/* Pedantic checking of DWARF files
-   Copyright (C) 2008,2009,2010,2011 Red Hat, Inc.
-   This file is part of Red Hat elfutils.
-
-   Red Hat elfutils is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by the
-   Free Software Foundation; version 2 of the License.
-
-   Red Hat elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along
-   with Red Hat elfutils; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
-
-   Red Hat elfutils is an included package of the Open Invention Network.
-   An included package of the Open Invention Network is a package for which
-   Open Invention Network licensees cross-license their patents.  No patent
-   license is granted, either expressly or impliedly, by designation as an
-   included package.  Should you wish to participate in the Open Invention
-   Network licensing program, please visit www.openinventionnetwork.com
-   <http://www.openinventionnetwork.com>.  */
-
-#include "where.h"
-
-#include <inttypes.h>
-#include <assert.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
-extern bool show_refs (void);
-
-struct section_info
-{
-  const char *name;
-  const char *addr1f;
-  const char *addr2f;
-  const char *addr3f;
-};
-
-static struct section_info section_names[] =
-  {
-    [sec_info] = {".debug_info", "CU %"PRId64, "DIE %#"PRIx64, NULL},
-
-    [sec_abbrev] = {".debug_abbrev", "section %"PRId64,
-                   "abbreviation %"PRId64, "abbr. attribute %#"PRIx64},
-
-    [sec_aranges] = {".debug_aranges", "table %"PRId64,
-                    "arange %#"PRIx64, NULL},
-
-    [sec_pubnames] = {".debug_pubnames", "pubname table %"PRId64,
-                     "pubname %#"PRIx64, NULL},
-
-    [sec_pubtypes] = {".debug_pubtypes", "pubtype table %"PRId64,
-                     "pubtype %#"PRIx64, NULL},
-
-    [sec_str] = {".debug_str", "offset %#"PRIx64, NULL, NULL},
-
-    [sec_line] = {".debug_line", "table %"PRId64, "offset %#"PRIx64, NULL},
-
-    [sec_loc] = {".debug_loc", "loclist %#"PRIx64, "offset %#"PRIx64, NULL},
-
-    [sec_mac] = {".debug_mac", NULL, NULL, NULL},
-
-    [sec_ranges] = {".debug_ranges", "rangelist %#"PRIx64,
-                   "offset %#"PRIx64, NULL},
-
-    [sec_locexpr] = {"location expression", "offset %#"PRIx64, NULL, NULL},
-
-    [sec_rel] = {".rel", "relocation %"PRId64, "offset %#"PRIx64, NULL},
-
-    [sec_rela] = {".rela", "relocation %"PRId64, "offset %#"PRIx64, NULL},
-  };
-
-const char *
-where_fmt (const struct where *wh, char *ptr)
-{
-  if (wh == NULL)
-    return "";
-
-  static char buf[256];
-
-  static struct section_info special_formats[] =
-    {
-      [wf_cudie] = {".debug_info", "CU DIE %"PRId64, NULL, NULL}
-    };
-
-  assert (wh->section < sizeof (section_names) / sizeof (*section_names));
-  struct section_info *inf
-    = (wh->formatting == wf_plain)
-    ? section_names + wh->section
-    : special_formats + wh->formatting;
-
-  assert (inf->name);
-
-  assert ((wh->addr1 != (uint64_t)-1) ? inf->addr1f != NULL : true);
-  assert ((wh->addr2 != (uint64_t)-1) ? inf->addr2f != NULL : true);
-  assert ((wh->addr3 != (uint64_t)-1) ? inf->addr3f != NULL : true);
-
-  assert ((wh->addr3 != (uint64_t)-1) ? (wh->addr2 != (uint64_t)-1) : true);
-  assert ((wh->addr2 != (uint64_t)-1) ? (wh->addr1 != (uint64_t)-1) : true);
-
-  /* GCC insists on checking format parameters and emits a warning
-     when we don't use string literal.  With -Werror this ends up
-     being hard error.  So instead we walk around this warning by
-     using function pointer.  */
-  int (*x_asprintf)(char **strp, const char *fmt, ...) = asprintf;
-
-#define SETUP_ADDR(N)                                                  \
-  char *addr##N##s;                                                    \
-  bool free_s##N = false;                                              \
-  if (wh->addr##N == (uint64_t)-1)                                     \
-    addr##N##s = NULL;                                                 \
-  else if (x_asprintf (&addr##N##s, inf->addr##N##f, wh->addr##N) >= 0)        \
-    free_s##N = true;                                                  \
-  else                                                                 \
-    addr##N##s = "(fmt error)"
-
-  SETUP_ADDR (1);
-  SETUP_ADDR (2);
-  SETUP_ADDR (3);
-#undef SETUP_ADDR
-
-  char *orig = ptr;
-  bool is_reloc = wh->section == sec_rel || wh->section == sec_rela;
-  if (ptr == NULL)
-    {
-      ptr = stpcpy (buf, inf->name);
-      if (is_reloc)
-       {
-         struct where const *ref = wh->ref;
-         assert (ref != NULL);
-         if (ref->section == sec_locexpr)
-           {
-             ref = ref->next;
-             assert (ref != NULL);
-             assert (ref->section != sec_locexpr);
-           }
-         ptr = stpcpy (ptr, section_names[ref->section].name);
-       }
-
-      if (addr1s != NULL)
-       ptr = stpcpy (ptr, ": ");
-    }
-
-  if (addr3s != NULL)
-    ptr = stpcpy (ptr, addr3s);
-  else if (addr2s != NULL)
-    ptr = stpcpy (ptr, addr2s);
-  else if (addr1s != NULL)
-    ptr = stpcpy (ptr, addr1s);
-
-  if (free_s1)
-    free (addr1s);
-  if (free_s2)
-    free (addr2s);
-  if (free_s3)
-    free (addr3s);
-
-  if (wh->ref != NULL && !is_reloc)
-    {
-      ptr = stpcpy (ptr, " (");
-      ptr = (char *)where_fmt (wh->ref, ptr);
-      *ptr++ = ')';
-      *ptr = 0;
-    }
-
-  if (orig == NULL)
-    return buf;
-  else
-    return ptr;
-}
-
-void
-where_fmt_chain (const struct where *wh, const char *severity)
-{
-  if (wh != NULL && show_refs ())
-    for (struct where const *it = wh->next; it != NULL; it = it->next)
-      printf ("%s: %s: caused by this reference.\n",
-             severity, where_fmt (it, NULL));
-}
-
-void
-where_reset_1 (struct where *wh, uint64_t addr)
-{
-  wh->addr1 = addr;
-  wh->addr2 = wh->addr3 = (uint64_t)-1;
-}
-
-void
-where_reset_2 (struct where *wh, uint64_t addr)
-{
-  wh->addr2 = addr;
-  wh->addr3 = (uint64_t)-1;
-}
-
-void
-where_reset_3 (struct where *wh, uint64_t addr)
-{
-  wh->addr3 = addr;
-}
diff --git a/dwarflint/where.h b/dwarflint/where.h
deleted file mode 100644 (file)
index fb1dd47..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/* Pedantic checking of DWARF files
-   Copyright (C) 2009,2010,2011 Red Hat, Inc.
-   This file is part of Red Hat elfutils.
-
-   Red Hat elfutils is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by the
-   Free Software Foundation; version 2 of the License.
-
-   Red Hat elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along
-   with Red Hat elfutils; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
-
-   Red Hat elfutils is an included package of the Open Invention Network.
-   An included package of the Open Invention Network is a package for which
-   Open Invention Network licensees cross-license their patents.  No patent
-   license is granted, either expressly or impliedly, by designation as an
-   included package.  Should you wish to participate in the Open Invention
-   Network licensing program, please visit www.openinventionnetwork.com
-   <http://www.openinventionnetwork.com>.  */
-
-#ifndef DWARFLINT_WHERE_H
-#define DWARFLINT_WHERE_H
-
-#include "section_id.hh"
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#ifdef __cplusplus
-#include <iosfwd>
-extern "C"
-{
-#endif
-
-  enum where_formatting
-  {
-    wf_plain = 0, /* Default formatting for given section.  */
-    wf_cudie,
-  };
-
-  struct where
-  {
-    enum section_id section;
-    enum where_formatting formatting;
-    uint64_t addr1; // E.g. a CU offset.
-    uint64_t addr2; // E.g. a DIE address.
-    uint64_t addr3; // E.g. an attribute.
-    struct where const *ref; // Related reference, e.g. an abbrev
-                            // related to given DIE.
-    struct where const *next; // For forming "caused-by" chains.
-  };
-
-  extern const char *where_fmt (const struct where *wh,        char *ptr);
-  extern void where_fmt_chain (const struct where *wh, const char *severity);
-  extern void where_reset_1 (struct where *wh, uint64_t addr);
-  extern void where_reset_2 (struct where *wh, uint64_t addr);
-  extern void where_reset_3 (struct where *wh, uint64_t addr);
-
-#ifdef __cplusplus
-}
-
-#include <iostream>
-
-inline where
-WHERE (section_id sec, where const *next = NULL)
-{
-  where ret = {sec, wf_plain,
-              (uint64_t)-1,
-              (uint64_t)-1,
-              (uint64_t)-1,
-              NULL, next};
-  return ret;
-}
-
-
-inline std::ostream &
-operator << (std::ostream &os, where const &wh)
-{
-  os << where_fmt (&wh, NULL);
-  return os;
-}
-
-#endif
-
-#endif//DWARFLINT_WHERE_H