]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: Revamp where, step 1
authorPetr Machata <pmachata@redhat.com>
Tue, 12 Apr 2011 19:24:35 +0000 (21:24 +0200)
committerPetr Machata <pmachata@redhat.com>
Tue, 12 Apr 2011 19:24:35 +0000 (21:24 +0200)
21 files changed:
dwarflint/Makefile.am
dwarflint/addr-record.cc
dwarflint/addr-record.hh
dwarflint/check_debug_abbrev.cc
dwarflint/check_debug_aranges.cc
dwarflint/check_debug_info.cc
dwarflint/check_debug_info.hh
dwarflint/check_debug_line.cc
dwarflint/check_debug_loc_range.cc
dwarflint/check_debug_pub.cc
dwarflint/checked_read.cc
dwarflint/checked_read.hh
dwarflint/messages.cc
dwarflint/messages.hh
dwarflint/misc.cc
dwarflint/reloc.cc
dwarflint/section_id.hh
dwarflint/tests/run-bad.sh
dwarflint/where.c [deleted file]
dwarflint/where.cc [new file with mode: 0644]
dwarflint/where.h

index 56e261152c839bfe63fdb7b197e027514d63d883..e3f518d4902897ef683ba607a65a868e44cfc62f 100644 (file)
@@ -69,7 +69,7 @@ dwarflint_SOURCES = \
        reloc.cc reloc.hh \
        section_id.cc section_id.hh \
        sections.cc sections.hh sections_i.hh \
-       where.c where.h \
+       where.cc where.h \
        wrap.cc wrap.hh \
        \
        check_debug_abbrev.cc check_debug_abbrev.hh check_debug_abbrev_i.hh \
@@ -96,7 +96,7 @@ locstats_SOURCES = \
        files.cc files.hh \
        option.cc option.hh option_i.hh \
        pri.cc pri.hh \
-       where.c where.h
+       where.cc where.h
 
 tests_test_coverage_SOURCES = tests/test-coverage.cc coverage.cc pri.cc \
        ../src/dwarfstrings.c
index ec31eba2e1969ba000ef75386f87aba30b2f6837..c2f68be1cb4a7b78e482edbe8f2e8568a0394693 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
@@ -81,19 +81,3 @@ 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);
-}
index 1542ff3141b60ca1ef9ed8847b6eafdb1ca0c3fe..e22ae6500e01d41d79d57f10f8888d3d3f85b54f 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 <vector>
+
 #include "where.h"
-#ifdef __cplusplus
-extern "C"
+
+/* 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.  */
+
+struct addr_record
+{
+  size_t size;
+  size_t alloc;
+  uint64_t *addrs;
+};
+
+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);
+
+/* 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.  */
+
+struct ref
+{
+  uint64_t addr; // Referree address
+  ::where who;  // Referrer
+
+  ref ()
+    : addr (-1)
+    , who ()
+  {}
+
+  ref (uint64_t a_addr, where const &a_who)
+    : addr (a_addr)
+    , who (a_who)
+  {}
+};
+
+class ref_record
+  : private std::vector<struct ref>
 {
-#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.  */
-
-  struct addr_record
-  {
-    size_t size;
-    size_t alloc;
-    uint64_t *addrs;
-  };
-
-  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);
-
-  /* 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.  */
-
-  struct ref
-  {
-    uint64_t addr; // Referree address
-    struct where who;  // Referrer
-  };
-
-  struct ref_record
-  {
-    size_t size;
-    size_t alloc;
-    struct ref *refs;
-  };
-
-  void ref_record_add (struct ref_record *rr, uint64_t addr,
-                      struct where *referrer);
-  void ref_record_free (struct ref_record *rr);
-
-#ifdef __cplusplus
-}
-#endif
+  typedef std::vector<struct ref> _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..771c506d5488e7117927661532fd47f632542918 100644 (file)
 #include "messages.hh"
 #include "misc.hh"
 
+class ll_where
+  : public locus
+{
+};
+
 checkdescriptor const *
 check_debug_abbrev::descriptor ()
 {
@@ -153,12 +158,13 @@ namespace
 
     struct abbrev_table *section = NULL;
     uint64_t first_attr_off = 0;
-    struct where where = WHERE (sec_abbrev, NULL);
+    section_id const sec_id = sec_abbrev;
+    where where = WHERE (sec_id, NULL);
 
     // Tolerate failure here.
     dwarf_version const *ver = NULL;
     static dwarf_version const *latest_ver = dwarf_version::get_latest ();
-    where.addr1 = 0;
+    where_reset_1 (&where, 0);
 
     bool failed = false;
     while (true)
@@ -184,7 +190,7 @@ namespace
              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, where, "abbrev code"))
                throw check_base::failed ();
 
              /* Note: we generally can't tell the difference between
@@ -212,9 +218,9 @@ namespace
 
          if (zero_seq_off != (uint64_t)-1)
            {
-             struct where wh = WHERE (where.section, NULL);
+             struct where wh = WHERE (sec_id, NULL);
              wr_message_padding_0 (mc_abbrevs | mc_header,
-                                   &wh, zero_seq_off, abbr_off);
+                                   wh, zero_seq_off, abbr_off);
            }
        }
 
@@ -308,13 +314,14 @@ namespace
        else
          cur = &fake;
        WIPE (*cur);
+       new (&cur->where) class where ();
 
        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)
@@ -362,11 +369,11 @@ namespace
            where_reset_3 (&where, attr_off);
 
            /* Load attribute name and form.  */
-           if (!checked_read_uleb128 (&ctx, &attrib_name, &where,
+           if (!checked_read_uleb128 (&ctx, &attrib_name, where,
                                       "attribute name"))
              throw check_base::failed ();
 
-           if (!checked_read_uleb128 (&ctx, &attrib_form, &where,
+           if (!checked_read_uleb128 (&ctx, &attrib_form, where,
                                       "attribute form"))
              throw check_base::failed ();
 
@@ -377,6 +384,7 @@ namespace
 
            struct abbrev_attrib *acur = cur->attribs + cur->size++;
            WIPE (*acur);
+           new (&acur->where) class where ();
            acur->name = attrib_name;
            acur->form = attrib_form;
            acur->where = where;
@@ -458,7 +466,7 @@ namespace
          }
        while (!null_attrib);
 
-       where_reset_2 (&where, where.addr2); // drop addr 3
+       where_reset_3 (&where, -1); // 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."
index b955970228f0c42d53cf8c5053dae77511ac9261..7373626ec736352b4039e1ddd93294c8d708a9e5 100644 (file)
@@ -196,7 +196,8 @@ check_aranges_structural (struct elf_file *file,
 
   while (!read_ctx_eof (&ctx))
     {
-      struct where where = WHERE (sec_aranges, NULL);
+      section_id const sec_id = sec_aranges;
+      struct where where = WHERE (sec_id, NULL);
       where_reset_1 (&where, read_ctx_get_offset (&ctx));
       const unsigned char *atab_begin = ctx.ptr;
 
@@ -268,13 +269,32 @@ 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;
+      class cudie_locus
+       : public locus
+      {
+       uint64_t _m_offset;
+
+      public:
+       cudie_locus (uint64_t offset)
+         : _m_offset (offset)
+       {}
+
+       std::string
+       format (bool) const
+       {
+         std::stringstream ss;
+         if (_m_offset != (uint64_t)-1)
+           ss << "CU DIE " << _m_offset;
+         else
+           ss << "unknown CU";
+         return ss.str ();
+       }
+      };
+
+      cudie_locus cudie_loc (cu != NULL ? cu->cudie_offset : -1);
+      where.ref = &cudie_loc;
       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;
          if (cu->has_arange)
            wr_error (where)
              << "there has already been arange section for this CU."
@@ -395,12 +415,12 @@ check_aranges_structural (struct elf_file *file,
       if (sub_ctx.ptr != sub_ctx.end)
        {
          uint64_t start, end;
-         struct where wh = WHERE (where.section, NULL);
+         struct where wh = WHERE (sec_id, NULL);
          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 46d4ec512301ff0b31726c29db4983971c38ac51..2ee494c31c76f8db11d0e2928a31dfd1f1f3435c 100644 (file)
@@ -114,17 +114,15 @@ namespace
                        struct 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 (!addr_record_has_addr (&cu->die_addrs, it->addr))
+       {
+         wr_error (it->who)
+           << "unresolved reference to " << pri::DIE (it->addr)
+           << '.' << std::endl;
+         retval = false;
+       }
     return retval;
   }
 
@@ -133,12 +131,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 (addr_record_has_addr (&jt->die_addrs, rt->addr))
              {
                ref_cu = jt;
                break;
@@ -146,9 +144,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 +154,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;
        }
 
@@ -179,10 +177,11 @@ namespace
       {
        const unsigned char *cu_begin = ctx.ptr;
        struct where where = WHERE (sec_info, NULL);
-       where_reset_1 (&where, read_ctx_get_offset (&ctx));
+       uint64_t offset = read_ctx_get_offset (&ctx);
+       where_reset_1 (&where, offset);
 
        cu_head head;
-       head.offset = where.addr1;
+       head.offset = offset;
        head.where = where;
 
        /* Reading CU head is a bit tricky, because we don't know if
@@ -192,7 +191,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, where,
                                  off_start, off_end);
            break;
          }
@@ -211,7 +210,7 @@ namespace
        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, where,
                                  off_start, off_end);
            break;
          }
@@ -426,15 +425,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 +478,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.  */
@@ -497,13 +496,13 @@ namespace
   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.
@@ -571,7 +570,7 @@ namespace
 
        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                                                 \
@@ -688,7 +687,7 @@ 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
@@ -843,7 +842,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.
@@ -1033,7 +1032,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);
@@ -1052,8 +1051,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,
@@ -1071,7 +1069,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;
 }
 
@@ -1088,7 +1085,6 @@ check_debug_info::check_debug_info (checkstack &stack, dwarflint &lint)
   Elf_Data *const strings = _m_sec_str->sect.data;
 
   struct ref_record die_refs;
-  WIPE (die_refs);
 
   bool success = true;
 
@@ -1137,13 +1133,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);
            }
        }
 
@@ -1200,7 +1196,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)
     {
@@ -1224,13 +1219,7 @@ 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);
-    }
+    addr_record_free (&it->die_addrs);
 }
 
 cu *
@@ -1276,8 +1265,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..d71f1a2a134edb501d886b9cb3c80f4a2934d998 100644 (file)
@@ -43,11 +43,23 @@ struct cu_head
   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.
+  ::where where;                // Where this section was defined.
   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_head ()
+    : offset (0)
+    , size (0)
+    , head_size (0)
+    , total_size (0)
+    , offset_size (0)
+    , where ()
+    , abbrev_offset (0)
+    , version (0)
+    , address_size (0)
+  {}
 };
 
 struct cu
index 93637238e90c6a3a4732293400aa100b5db77d1e..7dc722ab354c0cb6211153f65f26641b31634c43 100644 (file)
@@ -101,7 +101,7 @@ namespace
   {
     size_t nfile = files.size () + 1;
     if (!checked_read_uleb128 (ctx, ptr,
-                              where, "directory index"))
+                              *where, "directory index"))
       return false;
 
     if (*name == '/' && *ptr != 0)
@@ -128,11 +128,11 @@ namespace
 
   bool
   use_file (files_t &files, uint64_t file_idx,
-           where *where, char const *msg = "")
+           where const &where, char const *msg = "")
   {
     if (file_idx == 0 || file_idx > files.size ())
       {
-       wr_error (*where)
+       wr_error (where)
          << msg << "invalid file index " << file_idx << '.'
          << std::endl;
        return false;
@@ -316,13 +316,13 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
          /* 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 +340,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)
@@ -371,10 +371,10 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
          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, wh,
                                  off_start, off_end);
          else
-           wr_message_padding_n0 (mc_line | mc_header, &wh,
+           wr_message_padding_n0 (mc_line | mc_header, wh,
                                   off_start, program_start - sub_ctx.begin);
          sub_ctx.ptr = program_start;
        }
@@ -400,7 +400,7 @@ 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, where,
                                           "length of extended opcode"))
                  goto skip;
                if (!read_ctx_need_data (&sub_ctx, skip_len))
@@ -466,7 +466,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, where,
                                                 "set_discriminator operand"))
                        goto skip;
 
@@ -533,10 +533,10 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint)
                        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,
+                         wr_message_padding_0 (mc_line, wh,
                                                off_start, off_end);
                        else
-                         wr_message_padding_n0 (mc_line, &wh,
+                         wr_message_padding_n0 (mc_line, wh,
                                                 off_start,
                                                 next - sub_ctx.begin);
                      }
@@ -550,7 +550,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, where,
                                           "DW_LNS_advance_line operand"))
                  goto skip;
              }
@@ -572,10 +572,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, 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, where, "DW_LNS_set_file: "))
                  success = false;
                first_file = false;
              }
@@ -616,13 +616,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, where, buf))
                goto skip;
            }
 
          if (first_file)
            {
-             if (!use_file (files, 1, &where,
+             if (!use_file (files, 1, where,
                             "initial value of `file' register: "))
                success = false;
              first_file = false;
@@ -670,9 +670,9 @@ 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, wh, off_start, off_end);
          else
-           wr_message_padding_n0 (mc_line, &wh,
+           wr_message_padding_n0 (mc_line, wh,
                                   off_start, sub_ctx.end - sub_ctx.begin);
        }
       }
index 74b4d272ee4db8a73fbb0ce57d5937a24fcb0a26..6719c3087da19dd97287054690dc907822791e41 100644 (file)
@@ -392,7 +392,8 @@ namespace
     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);
+       where_reset_1 (&where, offset);
 
 #define HAVE_OVERLAP                                           \
        do {                                                    \
@@ -542,7 +543,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;
       }
@@ -602,9 +603,10 @@ namespace
       {
        struct 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);
          }
       }
@@ -785,7 +787,7 @@ namespace
                form const *form,
                uint64_t *valuep,
                char const *str,
-               struct where *where)
+               struct where const &where)
   {
     if (form == NULL)
       return true;
@@ -797,7 +799,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;
@@ -810,19 +812,19 @@ namespace
 
     struct relocation *rel;
     if ((rel = relocation_next (reloc, off,
-                               where, skip_mismatched)))
+                               &where, skip_mismatched)))
       {
        if (storclass != sc_block)
          relocate_one (&file, reloc, rel,
-                       cu->head->address_size, valuep, where,
+                       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)
       {
        uint64_t off_block_end = read_ctx_get_offset (ctx) + init_off - 1;
-       relocation_next (reloc, off_block_end, where, skip_ok);
+       relocation_next (reloc, off_block_end, &where, skip_ok);
       }
 
     return true;
@@ -847,8 +849,7 @@ check_location_expression (dwarf_version const *ver,
       return false;
     }
 
-  struct ref_record oprefs;
-  WIPE (oprefs);
+  ref_record oprefs;
 
   struct addr_record opaddrs;
   WIPE (opaddrs);
@@ -879,9 +880,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 +909,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 (ref (off_after + skip, where));
              }
 
            break;
@@ -937,17 +938,15 @@ check_location_expression (dwarf_version const *ver,
     }
 
  out:
-  for (size_t i = 0; i < oprefs.size; ++i)
+  for (ref_record::const_iterator it = oprefs.begin ();
+       it != oprefs.end (); ++it)
     {
-      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);
+      if (!addr_record_has_addr (&opaddrs, it->addr))
+       wr_error (it->who) << "unresolved reference to opcode at "
+                          << pri::hex (it->addr) << ".\n";
     }
 
   addr_record_free (&opaddrs);
-  ref_record_free (&oprefs);
 
   return true;
 }
@@ -974,7 +973,7 @@ found_hole (uint64_t start, uint64_t length, void *data)
            && (length < info->align)))
        {
          struct where wh = WHERE (info->section, NULL);
-         wr_message_padding_0 (info->category, &wh, start, end);
+         wr_message_padding_0 (info->category, wh, start, end);
        }
     }
   else
@@ -982,7 +981,7 @@ found_hole (uint64_t start, uint64_t length, void *data)
       /* 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);
+      wr_message_padding_n0 (info->category, wh, start, end);
     }
 
   return true;
index c44cab4b0e9f380798ccea68e8c2a30fdb54a985..7bd9a7f59587b0d91208f3563fe19fc95c48b92d 100644 (file)
@@ -231,10 +231,10 @@ check_debug_pub<sec_id>::check_pub_structural ()
          {
            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);
+             wr_message_padding_0 (mc_pubtables, wh, off_start, off_end);
            else
              {
-               wr_message_padding_n0 (mc_pubtables | mc_error, &wh,
+               wr_message_padding_n0 (mc_pubtables | mc_error, wh,
                                       off_start, off_start + size);
                retval = false;
              }
index 14831ecb13d565c742deecf3049d905c37c4dbde..a4df0222a403eeadf14a3357787678f7f2429d8e 100644 (file)
@@ -45,7 +45,7 @@ read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep,
     {
       if (!read_ctx_read_8ubyte (ctx, sizep))
        {
-         wr_error (where, ": can't read 64bit CU length.\n");
+         wr_error (*where) << "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 (*where)
+       << "unrecognized CU length escape value: " << size32 << ".\n";
       return false;
     }
   else
@@ -75,7 +75,7 @@ read_address_size (struct read_ctx *ctx,
   uint8_t address_size;
   if (!read_ctx_read_ubyte (ctx, &address_size))
     {
-      wr_error (where, ": can't read address size.\n");
+      wr_error (*where) << "can't read address size.\n";
       return err_fatal;
     }
 
@@ -84,18 +84,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 (*where) << "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 (*where) << "CU reports address size of " << address_size
+                       << " in " << (addr_64 ? 64 : 32) << "-bit ELF.\n";
       ret = err_nohl;
     }
 
@@ -105,59 +103,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 +172,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 +183,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..3f4f5984bcee156e1955c925bfef3a2e635702cc 100644 (file)
@@ -49,17 +49,17 @@ error_code read_address_size (read_ctx *ctx,
                              where const *where);
 
 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 +68,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 a803a50a3dead3538ffd8093d2cb962bd0405d25..7ea65d280e71198939db58b076f3bc0c9895c1e5 100644 (file)
@@ -246,35 +246,45 @@ message_criteria::and_not (message_term const &term)
   *this *= tmp;
 }
 
+extern "C" bool show_refs ();
 static void
-wr_verror (const struct where *wh, const char *format, va_list ap)
+format_chain (locus const &loc, char const *severity)
 {
-  printf ("error: %s", where_fmt (wh, NULL));
+  if (show_refs ())
+    for (locus const *it = loc.next (); it != NULL; it = it->next ())
+      printf ("%s: %s: caused by this reference.\n",
+             severity, it->format ().c_str ());
+}
+
+static void
+wr_verror (locus const &loc, const char *format, va_list ap)
+{
+  printf ("error: %s", loc.format ().c_str ());
   vprintf (format, ap);
-  where_fmt_chain (wh, "error");
+  format_chain (loc, "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 ("warning: %s", where_fmt (wh, NULL));
+  printf ("warning: %s", loc.format ().c_str ());
   vprintf (format, ap);
-  where_fmt_chain (wh, "warning");
+  format_chain (loc, "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;
@@ -282,9 +292,9 @@ wr_message (unsigned long category, const struct where *wh,
   if (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);
 }
@@ -330,9 +340,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)
 {}
 
@@ -347,8 +357,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
@@ -405,22 +415,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
@@ -430,24 +441,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)
@@ -457,28 +468,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..fe9a9d1549a9b882232fac02bbe8d7d4cf60edb5 100644 (file)
@@ -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..82359bc1fd1ff3da3f27fabbdb609b56b638d09e 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
@@ -62,7 +62,7 @@ supported_version (unsigned version,
   va_end (ap);
 
   if (!retval)
-    wr_error (where, ": unsupported version %d.\n", version);
+    wr_error (*where) << "unsupported version " << version << ".\n";
 
   return retval;
 }
index 2e23248b8d6e5a2e0563f3a7c42b601623b58cec..e4a702254b38b80f235c28168ac26284ad76add1 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 *
@@ -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, *where, rel->offset);
              wr_error (reloc_where)
                << (st == skip_unref
                    ? "relocation targets unreferenced portion of the section."
@@ -126,7 +169,7 @@ do_one_relocation (elf_file const *file,
                   relocation *rel,
                   unsigned rel_width,
                   uint64_t *value,
-                  where const &reloc_where,
+                  reloc_locus const &reloc_where,
                   section_id offset_into,
                   GElf_Sym *symbol,
                   GElf_Sym **symptr)
@@ -263,10 +306,7 @@ relocate_one (struct elf_file const *file,
   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, *where, rel->offset);
 
   GElf_Sym symbol_mem, *symbol;
   if (symptr != NULL)
@@ -279,8 +319,8 @@ relocate_one (struct elf_file const *file,
 
   if (offset_into == 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,9 +354,9 @@ 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)
@@ -372,12 +412,10 @@ read_rel (struct elf_file *file,
   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;
 
   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++;
@@ -405,7 +443,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 4b937d7fd7f98e9b582c89c07643b9b618a27c6c..ec9c4daea5cbf6cdd04d5ff3cea796197eef6554 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
@@ -49,8 +49,6 @@ enum section_id
 #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:  */
@@ -63,6 +61,8 @@ enum section_id
     rel_exec,          /* Some as above, but we expect EXEC bit.  */
   };
 
+static const unsigned num_section_ids = rel_exec + 1;
+
 // section_name[0] is for sec_invalid.  The last index is for
 // count_debuginfo_sections and is NULL.
 extern char const *section_name[];
index 3080f3e9a25020ba12ffb7e96b3f663f55094707..bbaf95b58a8d38dfcd2b19dc7ef7a3eb8815dee1 100755 (executable)
@@ -105,19 +105,19 @@ error: .debug_info: DIE 0xab (abbreviation 113): DIE chain not terminated with n
 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 (abbr. attribute 0): relocation formed using STT_SECTION symbol with non-zero value.
+error: .rela 0x11 of .debug_info: DIE 0xb (abbr. attribute 0x4): 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
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.cc b/dwarflint/where.cc
new file mode 100644 (file)
index 0000000..cd11b01
--- /dev/null
@@ -0,0 +1,223 @@
+/* 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 <cinttypes>
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <array>
+
+class where::simple_formatter
+  : public where::formatter
+{
+  char const *_m_name;
+  char const *_m_fmt1;
+  char const *_m_fmt2;
+  char const *_m_fmt3;
+
+public:
+  simple_formatter (char const *name = NULL,
+                   char const *fmt1 = NULL,
+                   char const *fmt2 = NULL,
+                   char const *fmt3 = NULL)
+    : _m_name (name)
+    , _m_fmt1 (fmt1)
+    , _m_fmt2 (fmt2)
+    , _m_fmt3 (fmt3)
+  {}
+
+  virtual std::string
+  format (where const &wh, bool brief) const
+  {
+    std::string ret;
+
+    brief = brief || _m_name == NULL;
+    if (!brief)
+      ret += _m_name;
+
+    char const *const *formats = &_m_fmt1;
+    uint64_t const *addrs = &wh._m_addr1;
+
+    for (size_t i = 3; i > 0; --i)
+      {
+       size_t idx = i - 1;
+       if (addrs[idx] == (uint64_t)-1)
+         continue;
+
+       assert (formats[idx] != NULL);
+
+       /* 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;
+
+       if (!brief)
+         ret += ": ";
+       char *buf;
+       if (x_asprintf (&buf, formats[idx], addrs[idx]) >= 0)
+         {
+           ret += buf;
+           free (buf);
+         }
+       else
+         ret += formats[idx];
+
+       break;
+      }
+
+    if (wh.ref != NULL)
+      {
+       ret += " (";
+       ret += wh.ref->format (true);
+       ret += ')';
+      }
+
+    return ret;
+  }
+};
+
+namespace
+{
+  template<size_t size>
+  class simple_formatters
+    : public std::array<where::simple_formatter, size>
+  {
+  protected:
+    void
+    add (section_id id, char const *name,
+        char const *addr1f = NULL,
+        char const *addr2f = NULL,
+        char const *addr3f = NULL)
+    {
+      (*this)[id] = where::simple_formatter (name, addr1f, addr2f, addr3f);
+    }
+  };
+
+  class section_formatters
+    : public simple_formatters<num_section_ids>
+  {
+  public:
+    section_formatters ()
+    {
+      add (sec_info, ".debug_info", "CU %"PRId64, "DIE %#"PRIx64);
+
+      add (sec_abbrev, ".debug_abbrev",
+          "section %"PRId64, "abbreviation %"PRId64, "abbr. attribute %#"PRIx64);
+
+      add (sec_aranges, ".debug_aranges",
+          "table %"PRId64, "arange %#"PRIx64);
+
+      add (sec_pubnames, ".debug_pubnames",
+          "pubname table %"PRId64, "pubname %#"PRIx64);
+
+      add (sec_pubtypes, ".debug_pubtypes",
+          "pubtype table %"PRId64, "pubtype %#"PRIx64);
+
+      add (sec_str, ".debug_str", "offset %#"PRIx64);
+
+      add (sec_line, ".debug_line", "table %"PRId64, "offset %#"PRIx64);
+
+      add (sec_loc, ".debug_loc", "loclist %#"PRIx64, "offset %#"PRIx64);
+
+      add (sec_mac, ".debug_mac");
+
+      add (sec_ranges, ".debug_ranges", "rangelist %#"PRIx64, "offset %#"PRIx64);
+
+      add (sec_locexpr, "location expression", "offset %#"PRIx64);
+    }
+  } const section_names;
+}
+
+namespace
+{
+  where::formatter const *
+  wf_for_section (section_id sec)
+  {
+    return &section_names[sec];
+  }
+}
+
+where
+WHERE (section_id sec, where const *next)
+{
+  where::formatter const *fmt = wf_for_section (sec);
+  return where (fmt, next);
+}
+
+where::where (formatter const *fmt, locus const *nxt)
+  : _m_formatter (fmt)
+  , _m_addr1 ((uint64_t)-1)
+  , _m_addr2 ((uint64_t)-1)
+  , _m_addr3 ((uint64_t)-1)
+  , ref (NULL)
+  , _m_next (nxt)
+{
+}
+
+where &
+where::operator= (where const &copy)
+{
+  _m_formatter = copy._m_formatter;
+
+  _m_addr1 = copy._m_addr1;
+  _m_addr2 = copy._m_addr2;
+  _m_addr3 = copy._m_addr3;
+
+  ref = copy.ref;
+  _m_next = copy._m_next;
+
+  return *this;
+}
+
+std::string
+where::format (bool brief) const
+{
+  assert (_m_formatter != NULL);
+  return _m_formatter->format (*this, brief);
+}
+
+void
+where_reset_1 (struct where *wh, uint64_t addr)
+{
+  wh->_m_addr1 = addr;
+  wh->_m_addr2 = wh->_m_addr3 = (uint64_t)-1;
+}
+
+void
+where_reset_2 (struct where *wh, uint64_t addr)
+{
+  wh->_m_addr2 = addr;
+  wh->_m_addr3 = (uint64_t)-1;
+}
+
+void
+where_reset_3 (struct where *wh, uint64_t addr)
+{
+  wh->_m_addr3 = addr;
+}
index fb1dd47a536bd7a7a0ee15e96f9bc257b8c46a42..7087827ca6f729c7077791dbc3be5cfd057cd096 100644 (file)
 
 #include <stdint.h>
 #include <stdlib.h>
-
-#ifdef __cplusplus
 #include <iosfwd>
-extern "C"
+#include <iostream>
+#include <cassert>
+
+class locus
 {
-#endif
+public:
+  virtual std::string format (bool brief = false) const = 0;
 
-  enum where_formatting
+  virtual locus const *next () const
   {
-    wf_plain = 0, /* Default formatting for given section.  */
-    wf_cudie,
-  };
+    return NULL;
+  }
+
+  virtual ~locus () {}
+};
 
-  struct where
+struct where
+  : public locus
+{
+  class formatter
   {
-    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.
+  public:
+    virtual ~formatter () {}
+    virtual std::string format (where const &wh, bool brief = false) const = 0;
   };
 
-  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);
+  class simple_formatter;
 
-#ifdef __cplusplus
-}
+private:
+  formatter const *_m_formatter;
 
-#include <iostream>
+  uint64_t _m_addr1; // E.g. a CU offset.
+  uint64_t _m_addr2; // E.g. a DIE address.
+  uint64_t _m_addr3; // E.g. an attribute.
 
-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;
-}
+public:
+  locus const *ref; // Related reference, e.g. an abbrev related to
+                   // given DIE.
+  locus const *_m_next; // For forming "caused-by" chains.
 
+  explicit where (formatter const *fmt = NULL,
+                 locus const *nxt = NULL);
+
+  where &operator= (where const &copy);
+
+  std::string format (bool brief = false) const;
+
+  locus const *
+  next () const
+  {
+    return _m_next;
+  }
+
+  void
+  set_next (locus const *nxt)
+  {
+    assert (_m_next == NULL);
+    _m_next = nxt;
+  }
+
+  friend void where_reset_1 (struct where *wh, uint64_t addr);
+  friend void where_reset_2 (struct where *wh, uint64_t addr);
+  friend void where_reset_3 (struct where *wh, uint64_t addr);
+};
+
+void where_reset_1 (struct where *wh, uint64_t addr);
+void where_reset_2 (struct where *wh, uint64_t addr);
+void where_reset_3 (struct where *wh, uint64_t addr);
+
+where WHERE (section_id sec, where const *next = NULL);
 
 inline std::ostream &
 operator << (std::ostream &os, where const &wh)
 {
-  os << where_fmt (&wh, NULL);
+  os << wh.format ();
   return os;
 }
 
-#endif
-
 #endif//DWARFLINT_WHERE_H