]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: Better support for emitting messages from C++
authorPetr Machata <pmachata@redhat.com>
Fri, 23 Oct 2009 15:08:43 +0000 (17:08 +0200)
committerPetr Machata <pmachata@redhat.com>
Wed, 18 Aug 2010 12:55:12 +0000 (14:55 +0200)
* tried to convert some code, and it seems to work fine

src/dwarflint/check_debug_line.cc
src/dwarflint/check_range_out_of_scope.cc
src/dwarflint/coverage.hh
src/dwarflint/messages.cc
src/dwarflint/messages.h
src/dwarflint/where.h

index a3993e521fc6665eb8da89f4aa0343ebf02257f1..a0b6233f286d252e267d6a706c7aefed679d4a79 100644 (file)
@@ -50,12 +50,9 @@ namespace
            {
              struct ref *ref = it->line_refs.refs + i;
              if (!addr_record_has_addr (&line_tables, ref->addr))
-               {
-                 std::stringstream ss;
-                 ss << ": unresolved reference to .debug_line table "
-                    << "0x" << std::hex << ref->addr << ".";
-                 wr_error (&ref->who, "%s\n", ss.str ().c_str ());
-               }
+               wr_error (ref->who)
+                 << ": unresolved reference to .debug_line table "
+                 << "0x" << std::hex << ref->addr << "." << std::endl;
            }
       addr_record_free (&line_tables);
     }
@@ -70,19 +67,19 @@ namespace
                                 where, "directory index"))
        return false;
       if (*name == '/' && *ptr != 0)
-       wr_message (mc_impact_2 | mc_line | mc_header, where,
-                   ": file #%zd has absolute pathname,"
-                   " but refers to directory != 0.\n", nfile);
+       wr_message (*where, cat (mc_impact_2, mc_line, mc_header))
+         << ": file #" << nfile
+         << " has absolute pathname, but refers to directory != 0."
+         << std::endl;
       if (*ptr > _m_include_directories.size ())
        /* Not >=, dirs are indexed from 1.  */
        {
-         std::stringstream ss;
-         ss << ": file #" << nfile
-            << " refers to directory #" << *ptr
-            << ", which wasn't defined.\n";
-         wr_message (mc_impact_4 | mc_line | mc_header, where,
-                     "%s\n", ss.str ().c_str ());
-         /* Consumer might choke on that.  */
+         wr_message (*where, cat (mc_impact_4, mc_line, mc_header))
+           << ": file #" << nfile
+           << " refers to directory #" << *ptr
+           << ", which wasn't defined." << std::endl;
+
+         /* Consumer might choke on that.  */
          retval = false;
        }
       else if (*ptr != 0)
@@ -95,9 +92,9 @@ namespace
     {
       if (file_idx == 0 || file_idx > _m_files.size ())
        {
-         std::stringstream ss;
-         ss << ": DW_LNS_set_file: invalid file index " << file_idx << '.';
-         wr_error (where, "%s\n", ss.str ().c_str ());
+         wr_error (*where)
+            << ": DW_LNS_set_file: invalid file index " << file_idx << '.'
+            << std::endl;
          return false;
        }
       else
@@ -137,7 +134,7 @@ check_debug_line::check_line_structural (struct elf_file *file,
       int offset_size;
       if (!read_ctx_read_4ubyte (&ctx, &size32))
        {
-         wr_error (&where, ": can't read table length.\n");
+         wr_error (where) << ": can't read table length." << std::endl;
          return false;
        }
       if (!read_size_extra (&ctx, size32, &size, &offset_size, &where))
@@ -148,7 +145,8 @@ check_debug_line::check_line_structural (struct elf_file *file,
       if (!read_ctx_init_sub (&sub_ctx, &ctx, set_begin, set_end))
        {
        not_enough:
-         wr_error (&where, PRI_NOT_ENOUGH, "next unit");
+         wr_error (where)
+           << ": " << pri::not_enough ("next unit") << '.' << std::endl;
          return false;
        }
       sub_ctx.ptr = ctx.ptr;
@@ -159,7 +157,7 @@ check_debug_line::check_line_structural (struct elf_file *file,
       uint16_t version;
       if (!read_ctx_read_2ubyte (&sub_ctx, &version))
        {
-         wr_error (&where, ": can't read set version.\n");
+         wr_error (where) << ": can't read set version." << std::endl;
        skip:
          retval = false;
          goto next;
@@ -171,7 +169,7 @@ check_debug_line::check_line_structural (struct elf_file *file,
       uint64_t header_length;
       if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &header_length))
        {
-         wr_error (&where, ": can't read attribute value.\n");
+         wr_error (where) << ": can't read attribute value." << std::endl;
          goto skip;
        }
       const unsigned char *program_start = sub_ctx.ptr + header_length;
@@ -180,7 +178,8 @@ check_debug_line::check_line_structural (struct elf_file *file,
       uint8_t minimum_i_length;
       if (!read_ctx_read_ubyte (&sub_ctx, &minimum_i_length))
        {
-         wr_error (&where, ": can't read minimum instruction length.\n");
+         wr_error (where)
+           << ": can't read minimum instruction length." << std::endl;
          goto skip;
        }
 
@@ -188,7 +187,7 @@ check_debug_line::check_line_structural (struct elf_file *file,
       uint8_t default_is_stmt;
       if (!read_ctx_read_ubyte (&sub_ctx, &default_is_stmt))
        {
-         wr_error (&where, ": can't read default_is_stmt.\n");
+         wr_error (where) << ": can't read default_is_stmt." << std::endl;
          goto skip;
        }
       /* 7.21: The boolean values "true" and "false" used by the line
@@ -197,15 +196,15 @@ check_debug_line::check_line_structural (struct elf_file *file,
         "true."  [But give a notice if it's not 0 or 1.]  */
       if (default_is_stmt != 0
          && default_is_stmt != 1)
-       wr_message (mc_line | mc_impact_2 | mc_header, &where,
-                   ": default_is_stmt should be 0 or 1, not %ud\n",
-                   default_is_stmt);
+       wr_message (where, cat (mc_line, mc_impact_2, mc_header))
+         << ": default_is_stmt should be 0 or 1, not "
+         << default_is_stmt << '.' << std::endl;
 
       /* Line base.  */
       int8_t line_base;
       if (!read_ctx_read_ubyte (&sub_ctx, (uint8_t *)&line_base))
        {
-         wr_error (&where, ": can't read line_base.\n");
+         wr_error (where) << ": can't read line_base." << std::endl;
          goto skip;
        }
 
@@ -213,7 +212,7 @@ check_debug_line::check_line_structural (struct elf_file *file,
       uint8_t line_range;
       if (!read_ctx_read_ubyte (&sub_ctx, &line_range))
        {
-         wr_error (&where, ": can't read line_range.\n");
+         wr_error (where) << ": can't read line_range." << std::endl;
          goto skip;
        }
 
@@ -221,22 +220,23 @@ check_debug_line::check_line_structural (struct elf_file *file,
       uint8_t opcode_base;
       if (!read_ctx_read_ubyte (&sub_ctx, &opcode_base))
        {
-         wr_error (&where, ": can't read opcode_base.\n");
+         wr_error (where) << ": can't read opcode_base." << std::endl;
          goto skip;
        }
 
       /* Standard opcode lengths.  */
       if (opcode_base == 0)
        {
-         wr_error (&where, ": opcode base set to 0.\n");
+         wr_error (where) << ": opcode base set to 0." << std::endl;
          opcode_base = 1; // so that in following, our -1s don't underrun
        }
       uint8_t std_opc_lengths[opcode_base - 1]; /* -1, opcodes go from 1.  */
       for (unsigned i = 0; i < (unsigned)(opcode_base - 1); ++i)
        if (!read_ctx_read_ubyte (&sub_ctx, std_opc_lengths + i))
          {
-           wr_error (&where,
-                     ": can't read length of standard opcode #%d.\n", i);
+           wr_error (where)
+             << ": can't read length of standard opcode #" << i << '.'
+             << std::endl;
            goto skip;
          }
 
@@ -245,10 +245,10 @@ check_debug_line::check_line_structural (struct elf_file *file,
          const char *name = read_ctx_read_str (&sub_ctx);
          if (name == NULL)
            {
-             wr_error (&where,
-                       ": can't read name of include directory #%zd.\n",
-                       /* Numbered from 1.  */
-                       _m_include_directories.size () + 1);
+             wr_error (where)
+               << ": can't read name of include directory #"
+               << _m_include_directories.size () + 1 // Numbered from 1.
+               << '.' << std::endl;
              goto skip;
            }
          if (*name == 0)
@@ -263,9 +263,10 @@ check_debug_line::check_line_structural (struct elf_file *file,
          const char *name = read_ctx_read_str (&sub_ctx);
          if (name == NULL)
            {
-             wr_error (&where,
-                       ": can't read name of file #%zd.\n",
-                       _m_files.size () + 1); /* Numbered from 1.  */
+             wr_error (where)
+               << ": can't read name of file #"
+               << _m_files.size () + 1 // Numbered from 1.
+               << '.' << std::endl;
              goto skip;
            }
          if (*name == 0)
@@ -293,13 +294,13 @@ check_debug_line::check_line_structural (struct elf_file *file,
       /* Skip the rest of the header.  */
       if (sub_ctx.ptr > program_start)
        {
-         std::stringstream ss;
-         ss << ": header claims that it has a size of 0x"
-            << std::hex << header_length
-            << ", but in fact it has a size of 0x"
-            << sub_ctx.ptr - program_start + header_length << '.';
+         wr_error (where)
+           << ": header claims that it has a size of 0x"
+           << std::hex << header_length
+           << ", but in fact it has a size of 0x"
+           << sub_ctx.ptr - program_start + header_length
+           << '.' << std::endl;
 
-         wr_error (&where, "%s\n", ss.str ().c_str ());
          /* Assume that the header lies, and what follows is in
             fact line number program.  */
          retval = false;
@@ -323,7 +324,7 @@ check_debug_line::check_line_structural (struct elf_file *file,
          uint8_t opcode;
          if (!read_ctx_read_ubyte (&sub_ctx, &opcode))
            {
-             wr_error (&where, ": can't read opcode.\n");
+             wr_error (where) << ": can't read opcode." << std::endl;
              goto skip;
            }
 
@@ -341,7 +342,8 @@ check_debug_line::check_line_structural (struct elf_file *file,
                const unsigned char *next = sub_ctx.ptr + skip_len;
                if (!read_ctx_read_ubyte (&sub_ctx, &extended))
                  {
-                   wr_error (&where, ": can't read extended opcode.\n");
+                   wr_error (where)
+                     << ": can't read extended opcode." << std::endl;
                    goto skip;
                  }
 
@@ -359,7 +361,9 @@ check_debug_line::check_line_structural (struct elf_file *file,
                      if (!read_ctx_read_offset (&sub_ctx,
                                                 file->addr_64, &addr))
                        {
-                         wr_error (&where, ": can't read operand of DW_LNE_set_address.\n");
+                         wr_error (where)
+                           << ": can't read operand of DW_LNE_set_address."
+                           << std::endl;
                          goto skip;
                        }
 
@@ -370,8 +374,9 @@ check_debug_line::check_line_structural (struct elf_file *file,
                                      file->addr_64 ? 8 : 4,
                                      &addr, &where, rel_address, NULL);
                      else if (file->ehdr.e_type == ET_REL)
-                       wr_message (mc_impact_2 | mc_line | mc_reloc, &where,
-                                   PRI_LACK_RELOCATION, "DW_LNE_set_address");
+                       wr_message (where, cat (mc_impact_2, mc_line, mc_reloc))
+                         << ": " << pri::lacks_relocation ("DW_LNE_set_address")
+                         << '.' << std::endl;
                      break;
                    }
 
@@ -380,8 +385,9 @@ check_debug_line::check_line_structural (struct elf_file *file,
                      const char *name;
                      if ((name = read_ctx_read_str (&sub_ctx)) == NULL)
                        {
-                         wr_error (&where,
-                                   ": can't read filename operand of DW_LNE_define_file.\n");
+                         wr_error (where)
+                           << ": can't read filename operand of DW_LNE_define_file."
+                           << std::endl;
                          goto skip;
                        }
                      uint64_t dir_idx;
@@ -403,19 +409,19 @@ check_debug_line::check_line_structural (struct elf_file *file,
 #undef ONE_KNOWN_DW_LNE
                      default:
                        /* No we don't, emit a warning.  */
-                       wr_message (mc_impact_2 | mc_line, &where,
-                                   ": unknown extended opcode #%d.\n", extended);
+                       wr_message (where, cat (mc_impact_2, mc_line))
+                         << ": unknown extended opcode #" << extended
+                         << '.' << std::endl;
                      };
                  };
 
                if (sub_ctx.ptr > next)
                  {
-                   std::stringstream ss;
-                   ss << ": opcode claims that it has a size of 0x"
-                      << std::hex << skip_len
-                      << ", but in fact it has a size of 0x"
-                      << (skip_len + (next - sub_ctx.ptr)) << '.';
-                   wr_error (&where, "%s\n", ss.str ().c_str ());
+                   wr_error (where)
+                     << ": opcode claims that it has a size of 0x"
+                     << std::hex << skip_len
+                     << ", but in fact it has a size of 0x"
+                     << (skip_len + (next - sub_ctx.ptr)) << '.' << std::endl;
                    retval = false;
                  }
                else if (sub_ctx.ptr < next)
@@ -440,7 +446,9 @@ check_debug_line::check_line_structural (struct elf_file *file,
                uint16_t a;
                if (!read_ctx_read_2ubyte (&sub_ctx, &a))
                  {
-                   wr_error (&where, ": can't read operand of DW_LNS_fixed_advance_pc.\n");
+                   wr_error (where)
+                     << ": can't read operand of DW_LNS_fixed_advance_pc."
+                     << std::endl;
                    goto skip;
                  }
                break;
@@ -476,8 +484,9 @@ check_debug_line::check_line_structural (struct elf_file *file,
 
                default:
                  if (opcode < opcode_base)
-                   wr_message (mc_impact_2 | mc_line, &where,
-                               ": unknown standard opcode #%d.\n", opcode);
+                   wr_message (where, cat (mc_impact_2, mc_line))
+                     << ": unknown standard opcode #" << opcode
+                     << '.' << std::endl;
                };
            };
 
@@ -508,24 +517,28 @@ check_debug_line::check_line_structural (struct elf_file *file,
 
       for (size_t i = 0; i < _m_include_directories.size (); ++i)
        if (!_m_include_directories[i].used)
-         wr_message (mc_impact_3 | mc_acc_bloat | mc_line | mc_header,
-                     &where, ": the include #%zd `%s' is not used.\n",
-                     i + 1, _m_include_directories[i].name.c_str ());
+         wr_message (where,
+                     cat (mc_impact_3, mc_acc_bloat, mc_line, mc_header))
+           << ": the include #" << i + 1
+           << " `" << _m_include_directories[i].name
+           << "' is not used." << std::endl;
 
       for (size_t i = 0; i < _m_files.size (); ++i)
        if (!_m_files[i].used)
-         wr_message (mc_impact_3 | mc_acc_bloat | mc_line | mc_header,
-                     &where, ": the file #%zd `%s' is not used.\n",
-                     i + 1, _m_files[i].name);
+         wr_message (where,
+                     cat (mc_impact_3, mc_acc_bloat, mc_line, mc_header))
+           << ": the file #" << i + 1
+           << " `" << _m_files[i].name << "' is not used." << std::endl;
 
       if (!seen_opcode)
-       wr_message (mc_line | mc_acc_bloat | mc_impact_3, &where,
-                   ": empty line number program.\n");
+       wr_message (where, cat (mc_line, mc_acc_bloat, mc_impact_3))
+         << ": empty line number program." << std::endl;
 
       struct where wh = WHERE (sec_line, NULL);
       if (!terminated)
-       wr_error (&where,
-                 ": sequence of opcodes not terminated with DW_LNE_end_sequence.\n");
+       wr_error (where)
+         << ": sequence of opcodes not terminated with DW_LNE_end_sequence."
+         << std::endl;
       else if (sub_ctx.ptr != sub_ctx.end
               && !check_zero_padding (&sub_ctx, mc_line, &wh))
        wr_message_padding_n0 (mc_line, &wh,
index 6e728f37ed569d67e525cc7a586003a4793e8a27..d62ce39a06c7f9d2a663a5e3f56f32ced377aa5e 100644 (file)
@@ -77,8 +77,9 @@ check_range_out_of_scope::check_range_out_of_scope (dwarflint &lint)
              if (high_pc != (::Dwarf_Addr)-1)
                {
                  if (my_ranges.size () != 0)
-                   wr_message (cat (mc_impact_4, mc_info, mc_error), &wh,
-                               ": both low_pc/high_pc pair and ranges present.\n");
+                   wr_message (wh, cat (mc_impact_4, mc_info, mc_error))
+                     << ": both low_pc/high_pc pair and ranges present."
+                     << std::endl;
                  else
                    my_ranges.push_back (std::make_pair (low_pc, high_pc));
                }
@@ -123,17 +124,14 @@ check_range_out_of_scope::check_range_out_of_scope (dwarflint &lint)
 
                    if (result.size > 0)
                      {
-                       std::string super_wh = where_fmt (&wh_parent);
-                       {
-                         std::string rs = cov::format_ranges (cov1);
-                         wr_error (&wh, ": PC range %s is not a sub-range of "
-                                   "containing scope.\n", rs.c_str ());
-                       }
-                       {
-                         std::string rs = cov::format_ranges (cov2);
-                         wr_error (&wh_parent, ": in this context: %s\n",
-                                   rs.c_str ());
-                       }
+                       wr_error (wh)
+                         << ": PC range " << cov::format_ranges (cov1)
+                         << " is not a sub-range of containing scope."
+                         << std::endl;
+
+                       wr_error (wh_parent)
+                         << ": in this context: " << cov::format_ranges (cov2)
+                         << std::endl;
                      }
 
                    coverage_free (&result);
@@ -177,19 +175,17 @@ check_range_out_of_scope::check_range_out_of_scope (dwarflint &lint)
                              && !coverage_is_covered (&cov, start, length))
                            {
                              runoff = true;
-                             std::string super_wh = where_fmt (&wh_parent);
-                             wr_error (&wh, ": attribute `%s': PC range %s "
-                                       "outside containing scope\n",
-                                       dwarf_attr_string ((*at).first),
-                                       range_fmt (start, end).c_str ());
+                             wr_error (wh)
+                               << ": attribute `"
+                               << dwarf_attr_string ((*at).first)
+                               << "': PC range " << range_fmt (start, end)
+                               << " outside containing scope." << std::endl;
                            }
                        }
                      if (runoff)
-                       {
-                         std::string rangestr = cov::format_ranges (cov);
-                         wr_error (&wh_parent, ": in this context: %s\n",
-                                   rangestr.c_str ());
-                       }
+                       wr_error (wh_parent)
+                         << ": in this context: " << cov::format_ranges (cov)
+                         << '.' << std::endl;
                    }
                }
            }
index 22506314f16b8ae0553fd8eebea5bee5a9a4f362..67c6aa62bfbd49216b8a1931efb46873f481202e 100644 (file)
@@ -66,7 +66,7 @@ namespace cov
     }
 
   public:
-    operator std::string ()
+    operator std::string () const
     {
       return _m_os.str ();
     }
@@ -94,4 +94,15 @@ namespace cov
   };
 }
 
+inline std::ostream &
+operator << (std::ostream &os, cov::format_ranges const &obj)
+{
+  return os << std::string (obj);
+}
+
+inline std::ostream &
+operator << (std::ostream &os, cov::format_holes const &obj)
+{
+  return os << std::string (obj);
+}
 #endif//DWARFLINT_COVERAGE_HH
index a106747400840e2bf809a65a0d2f799da48a521a..83e9c94fc6393223a824b9f3dc9246619c57f451 100644 (file)
@@ -6,6 +6,7 @@
 #include <sstream>
 #include <cassert>
 #include <cstdarg>
+#include <libintl.h>
 
 unsigned error_count = 0;
 
@@ -223,6 +224,42 @@ wr_message (unsigned long category, const struct where *wh,
   va_end (ap);
 }
 
+namespace
+{
+  class nostream: public std::ostream {};
+  nostream nostr;
+
+  std::ostream &get_stream ()
+  {
+    return std::cout;
+  }
+}
+
+std::ostream &
+wr_warning (where const &wh)
+{
+  ++error_count;
+  return get_stream () << gettext ("warning: ") << wh << ": ";
+}
+
+std::ostream &
+wr_error (where const &wh)
+{
+  ++error_count;
+  return get_stream () << gettext ("error: ") << wh << ": ";
+}
+
+std::ostream &
+wr_message (where const &wh, message_category category)
+{
+  if (!message_accept (&warning_criteria, category))
+    return nostr;
+  else if (message_accept (&error_criteria, category))
+    return wr_error (wh);
+  else
+    return wr_warning (wh);
+}
+
 void
 wr_format_padding_message (unsigned long category,
                           struct where *wh,
@@ -267,3 +304,9 @@ wr_message_padding_n0 (unsigned long category,
                             wh, start, end,
                             "unreferenced non-zero bytes");
 }
+
+std::ostream &
+pri::operator << (std::ostream &os, pri::pribase const &obj)
+{
+  return os << obj.m_a << obj.m_b << obj.m_c;
+}
index 7ea1ef6a41463553486f1fa9d00e095699c59cac..e920e4ffd376b8497d5e8fc9dffc42443ac96f18 100644 (file)
@@ -143,6 +143,44 @@ cat (message_category c1,
   return static_cast<message_category> (c1 | c2 | c3 | c4);
 }
 
+std::ostream &wr_warning (where const &wh);
+std::ostream &wr_error (where const &wh);
+std::ostream &wr_message (where const &wh, message_category cat);
+
+namespace pri
+{
+  class pribase
+  {
+    std::string const &m_a;
+    std::string const &m_b;
+    std::string const &m_c;
+
+  protected:
+    pribase (std::string const &a,
+            std::string const &b = "",
+            std::string const &c = "")
+      : m_a (a), m_b (b), m_c (c)
+    {}
+    friend std::ostream &operator << (std::ostream &os, pribase const &obj);
+  };
+  std::ostream &operator << (std::ostream &os, pribase const &obj);
+
+  struct not_enough
+    : public pribase
+  {
+    not_enough (std::string const &what)
+      : pribase ("not enough data for ", what)
+    {}
+  };
+
+  struct lacks_relocation
+    : public pribase
+  {
+    lacks_relocation (std::string const &what)
+      : pribase (what, " seems to lack a relocation")
+    {}
+  };
+}
 #endif
 
 #endif//DWARFLINT_MESSAGES_H
index bfa9e31575340c269a83d0bf8182d5efb3693527..0522c72b47e518347f4c3f283114f037e31d2c6a 100644 (file)
@@ -6,6 +6,7 @@
 
 #ifdef __cplusplus
 # define IF_CPLUSPLUS(X) X
+#include <iosfwd>
 extern "C"
 {
 #else
@@ -80,11 +81,21 @@ extern "C"
 #ifdef __cplusplus
 }
 
+#include <iostream>
+
 inline const char *
 where_fmt (where const &wh)
 {
   return where_fmt (&wh);
 }
+
+inline std::ostream &
+operator << (std::ostream &os, where const &wh)
+{
+  os << where_fmt (wh);
+  return os;
+}
+
 #endif
 
 #endif//DWARFLINT_WHERE_H