]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Getting there on dwarf_output value sets.
authorRoland McGrath <roland@redhat.com>
Mon, 6 Jul 2009 11:34:46 +0000 (04:34 -0700)
committerRoland McGrath <roland@redhat.com>
Mon, 6 Jul 2009 11:34:46 +0000 (04:34 -0700)
libdw/c++/dwarf_data
libdw/c++/dwarf_output
libdw/c++/output-values.cc
libdw/c++/subr.hh

index 19457d91dc586caff3b8a52f10bc4da8408877bf..91d4e663d967244c7ffacecd2789188098403f55 100644 (file)
@@ -516,18 +516,6 @@ namespace elfutils
       typedef std::pair<directory_table, line_table> _base;
 
     public:
-      struct hasher
-       : public std::unary_function<line_info_table, size_t>
-      {
-       size_t operator () (const line_info_table &v) const
-       {
-         size_t hash = 0;
-         subr::hash_combine (hash, v.first);
-         subr::hash_combine (hash, v.second);
-         return hash;
-       }
-      };
-
       inline line_info_table () : _base () {}
 
       template<typename table>
@@ -591,7 +579,7 @@ namespace elfutils
       {
        size_t operator () (const dwarf_enum &v) const
        {
-         return v.first;
+         return subr::hash_this<_base> (v);
        }
       };
 
@@ -781,7 +769,7 @@ namespace elfutils
     };
 
   public:
-    template<typename impl>
+    template<typename impl, bool alloc_values = true>
     struct value
     {
       struct value_dispatch
@@ -789,15 +777,22 @@ namespace elfutils
        virtual ~value_dispatch () {}
       };
 
+      typedef value_dispatch value_cell_type;
+
+      static const bool delete_value = alloc_values;
+
       template<typename flavor, typename input, typename arg_type>
       static inline value_dispatch *
       make (flavor *&result, const input &x, arg_type &arg)
       {
+       assert (alloc_values);
        return result = new flavor (x, arg);
       }
 
       struct value_string : public value_dispatch, public std::string
       {
+       typedef subr::hash<std::string> hasher;
+
        inline value_string () {}
 
        template<typename string, typename arg_type>
@@ -805,6 +800,11 @@ namespace elfutils
          : std::string (s)
        {}
 
+       template<typename string>
+       inline value_string (const string &s)
+         : std::string (s)
+       {}
+
        std::string to_string () const
        {
          std::string result ("\"");
@@ -822,6 +822,11 @@ namespace elfutils
        inline value_identifier (const id &s, arg_type &arg)
          : value_string (s, arg)
        {}
+
+       template<typename id>
+       inline value_identifier (const id &s)
+         : value_string (s)
+       {}
       };
 
       struct value_reference : public value_dispatch
@@ -854,8 +859,8 @@ namespace elfutils
       {
        bool flag;
 
-       inline value_flag ()
-         : flag (true)
+       inline value_flag (bool t = true)
+         : flag (t)
        {}
 
        template<typename arg_type>
@@ -869,14 +874,32 @@ namespace elfutils
        // XXX dwfl, reloc
        ::Dwarf_Addr addr;
 
-       inline value_address ()
-         : addr (0)
+       inline value_address (::Dwarf_Addr x = 0)
+         : addr (x)
        {}
 
        template<typename arg_type>
        inline value_address (::Dwarf_Addr x, arg_type &)
          : addr (x)
        {}
+
+       struct hasher : public std::unary_function<value_address, size_t>
+       {
+         inline size_t operator () (const value_address &c) const
+         {
+           return c.addr;
+         }
+       };
+
+       inline operator ::Dwarf_Addr () const
+       {
+         return addr;
+       }
+
+       inline bool operator== (::Dwarf_Addr x) const
+       {
+         return addr == x;
+       }
       };
 
       struct value_rangelistptr : public value_dispatch, public range_list
@@ -887,6 +910,11 @@ namespace elfutils
        inline value_rangelistptr (const list &other, arg_type &)
          : range_list (other)
        {}
+
+       template<typename list>
+       inline value_rangelistptr (const list &other)
+         : range_list (other)
+       {}
       };
 
       struct value_lineptr : public value_dispatch, public impl::line_info_table
@@ -907,31 +935,61 @@ namespace elfutils
          ::Dwarf_Sword sword;
        };
 
-       inline value_constant ()
-         : word (0)
+       inline value_constant (::Dwarf_Word value = 0)
+         : word (value)
        {}
 
        template<typename arg_type>
        inline value_constant (::Dwarf_Word x, arg_type &)
          : word (x)
        {}
+
+       struct hasher : public std::unary_function<value_constant, size_t>
+       {
+         inline size_t operator () (const value_constant &c) const
+         {
+           return c.word;
+         }
+       };
+
+       inline operator ::Dwarf_Word () const
+       {
+         return word;
+       }
+
+       inline bool operator== (::Dwarf_Word x) const
+       {
+         return word == x;
+       }
       };
 
       struct value_constant_block : public value_dispatch,
                                    public std::vector<uint8_t>
       {
+       typedef subr::hash<std::vector<uint8_t> > hasher;
+
        inline value_constant_block () {}
 
        template<typename block, typename arg_type>
        inline value_constant_block (const block &b, arg_type &)
          : std::vector<uint8_t> (b.begin (), b.end ())
        {}
+
+       template<typename block>
+       inline value_constant_block (const block &b)
+         : std::vector<uint8_t> (b.begin (), b.end ())
+       {}
       };
 
       struct value_dwarf_constant : public value_dispatch, public dwarf_enum
       {
        inline value_dwarf_constant () {}
 
+       template<typename constant>
+       inline value_dwarf_constant (const constant &other)
+         : dwarf_enum (other)
+       {}
+
        template<typename constant, typename arg_type>
        inline value_dwarf_constant (const constant &other, arg_type &)
          : dwarf_enum (other)
@@ -946,22 +1004,48 @@ namespace elfutils
        inline value_source_file (const file &other, arg_type &)
          : source_file (other)
        {}
+
+       template<typename file>
+       inline value_source_file (const file &other)
+         : source_file (other)
+       {}
       };
 
       struct value_source_line : public value_dispatch
       {
        unsigned int n;
 
-       inline value_source_line ()
-         : n (0)
+       inline value_source_line (unsigned int x = 0)
+         : n (x)
        {}
 
        template<typename arg_type>
        inline value_source_line (unsigned int m, arg_type &)
          : n (m)
        {}
+
+       struct hasher : public std::unary_function<value_source_line, size_t>
+       {
+         inline size_t operator () (const value_source_line &c) const
+         {
+           return c.n;
+         }
+       };
+
+       inline operator unsigned int () const
+       {
+         return n;
+       }
+
+       inline bool operator== (unsigned int x) const
+       {
+         return n == x;
+       }
+      };
+
+      class value_source_column : public value_source_line
+      {
       };
-      typedef value_source_line value_source_column;
 
       struct value_macptr : public value_dispatch {};
 
@@ -985,7 +1069,7 @@ namespace elfutils
       friend class attributes_type<impl, vw>;
 
     private:
-      typename vw::value_dispatch *_m_value;
+      typename vw::value_cell_type *_m_value;
       typedef typename impl::debug_info_entry::pointer die_ptr;
 
       template<typename value, typename arg_type = const subr::nothing>
@@ -1058,9 +1142,9 @@ namespace elfutils
       }
 
       template<typename flavor>
-      inline flavor &variant () const
+      inline const flavor &variant () const
       {
-       return const_variant<flavor> ();
+       return const_variant<const flavor> ();
       }
 
       template<typename flavor>
@@ -1092,7 +1176,7 @@ namespace elfutils
 
       ~attr_value ()
       {
-       if (_m_value != NULL)
+       if (vw::delete_value && _m_value != NULL)
          delete _m_value;
       }
 
@@ -1121,7 +1205,7 @@ namespace elfutils
       dwarf::value_space what_space () const;
       inline std::string to_string () const;
 
-      inline bool &flag () const
+      inline const bool &flag () const
       {
        return variant<typename vw::value_flag> ().flag;
       }
@@ -1132,7 +1216,7 @@ namespace elfutils
       }
 
       // XXX dwfl, reloc
-      inline ::Dwarf_Addr &address () const
+      inline const ::Dwarf_Addr &address () const
       {
        return variant<typename vw::value_address> ().addr;
       }
@@ -1143,7 +1227,7 @@ namespace elfutils
        return variant<typename vw::value_address> ().addr;
       }
 
-      inline die_ptr &reference () const
+      inline const die_ptr &reference () const
       {
        return variant<typename vw::value_reference> ().ref;
       }
@@ -1153,9 +1237,9 @@ namespace elfutils
        return variant<typename vw::value_reference> ().ref;
       }
 
-      inline location_attr &location () const
+      inline const location_attr &location () const
       {
-       return static_cast<location_attr &>
+       return static_cast<const location_attr &>
          (variant<typename vw::value_location> ());
       }
 
@@ -1191,7 +1275,7 @@ namespace elfutils
 
       inline const typename impl::source_file &source_file () const
       {
-       return static_cast<typename impl::source_file &>
+       return static_cast<const typename impl::source_file &>
          (variant<typename vw::value_source_file> ());
       }
 
@@ -1243,7 +1327,7 @@ namespace elfutils
 
       inline const std::vector<uint8_t> &constant_block () const
       {
-       return static_cast<std::vector<uint8_t> &>
+       return static_cast<const std::vector<uint8_t> &>
          (variant<typename vw::value_constant_block> ());
       }
 
@@ -1265,13 +1349,14 @@ namespace elfutils
 
       inline bool constant_is_integer () const
       {
-       return dynamic_cast<typename vw::value_constant *> (_m_value) != NULL;
+       return (dynamic_cast<const typename vw::value_constant *> (_m_value)
+               != NULL);
       }
 
       inline const typename impl::range_list &ranges () const
       {
-       return static_cast<range_list &>
-         (variant<typename vw::value_rangelistptr> ());
+       return static_cast<const range_list &>
+         (variant<const typename vw::value_rangelistptr> ());
       }
 
       inline typename impl::range_list &ranges ()
@@ -1282,8 +1367,8 @@ namespace elfutils
 
       inline const typename impl::line_info_table &line_info () const
       {
-       return static_cast<typename impl::line_info_table &>
-         (variant<typename vw::value_lineptr> ());
+       return static_cast<const typename impl::line_info_table &>
+         (variant<const typename vw::value_lineptr> ());
       }
 
       inline typename impl::line_info_table &line_info ()
index efd29859d1f8499bee4e257de531f3f0dacec1f4..bd9b63b7d7b98fbf539083057ea51e0a12342c15 100644 (file)
@@ -272,6 +272,8 @@ namespace elfutils
 
   class dwarf_output
   {
+    friend class dwarf_output_collector;
+
   public:
     typedef dwarf_data::source_file source_file;
     typedef dwarf_data::directory_table directory_table;
@@ -289,10 +291,6 @@ namespace elfutils
   protected:
     template<typename input> class copier; // Below.
 
-    template<typename input>
-    static inline const std::string &
-    collect_string (dwarf_output_collector &c, const input &);
-
     /* An iterator adapter for use in iterator-based constructors.
        collectify (iterator) yields an iterator on input where *i
        constructs output::value_type (input::value_type v, collector).  */
@@ -305,31 +303,12 @@ namespace elfutils
       return subr::argifier<input, output, dwarf_output_collector &> (c) (in);
     }
 
-    struct value_wrapper
-      : public dwarf_data::value<dwarf_output>
+    struct value
+      : public dwarf_data::value<dwarf_output, false>
     {
-      struct value_string : public value_dispatch
-      {
-       const std::string &_m_str;
+      typedef const value_dispatch value_cell_type;
 
-       template<typename string, typename input>
-       inline value_string (const string &s, dwarf_output::copier<input> &c)
-         : _m_str (collect_string (c, s))
-       {}
-
-       inline operator const std::string & () const
-       {
-         return _m_str;
-       }
-
-       std::string to_string () const
-       {
-         std::string result ("\"");
-         result += _m_str;
-         result += "\"";
-         return result;
-       }
-      };
+      typedef dwarf_data::value<dwarf_output> data;
 
       template<typename flavor, typename input>
       static inline value_dispatch *
@@ -338,33 +317,116 @@ namespace elfutils
        throw std::logic_error ("dwarf_output cannot be default-constructed");
       }
 
-      template<typename flavor, typename input, typename arg_type>
+      // XXX temporary
+      template<typename flavor, typename input, typename input_dw>
       static inline value_dispatch *
-      make (flavor *&result, const input &x, arg_type &arg)
+      make (flavor *&result, const input &x, copier<input_dw> &c)
       {
-       return result = new flavor (x, arg);
+       return result = new flavor (x, c);
       }
 
-      template<typename input>
-      static inline value_dispatch *
-      make (value_string *&result, const input &x, dwarf_output_collector &c)
+      template<typename input, typename input_dw>
+      static inline const value_dispatch *
+      make (value_string *&, const input &x, copier<input_dw> &c)
+      {
+       return c.add_string (x);
+      }
+
+      template<typename input, typename input_dw>
+      static inline const value_dispatch *
+      make (value_identifier *&, const input &x, copier<input_dw> &c)
+      {
+       return c.add_identifier (x);
+      }
+
+      // XXX reference
+
+      template<typename input, typename input_dw>
+      static inline const value_dispatch *
+      make (value_flag *&, const input &x, copier<input_dw> &c)
+      {
+       return c.add_flag (x);
+      }
+
+      template<typename input, typename input_dw>
+      static inline const value_dispatch *
+      make (value_address *&, const input &x, copier<input_dw> &c)
+      {
+       return c.add_address (x);
+      }
+
+      template<typename input, typename input_dw>
+      static inline const value_dispatch *
+      make (value_rangelistptr *&, const input &x, copier<input_dw> &c)
+      {
+       return c.add_ranges (x);
+      }
+
+      /* XXX lineptr
+      template<typename input, typename input_dw>
+      static inline const value_dispatch *
+      make (value_lineptr *&, const input &x, copier<input_dw> &c)
+      {
+       return c.add_line_info (x);
+      }
+      */
+
+      template<typename input, typename input_dw>
+      static inline const value_dispatch *
+      make (value_constant *&, const input &x, copier<input_dw> &c)
+      {
+       return c.add_constant (x);
+      }
+
+      template<typename input, typename input_dw>
+      static inline const value_dispatch *
+      make (value_constant_block *&, const input &x, copier<input_dw> &c)
+      {
+       return c.add_constant_block (x);
+      }
+
+      template<typename input, typename input_dw>
+      static inline const value_dispatch *
+      make (value_dwarf_constant *&, const input &x, copier<input_dw> &c)
       {
-       return result = new value_string (x, c);
+       return c.add_dwarf_constant (x);
       }
 
+      template<typename input, typename input_dw>
+      static inline const value_dispatch *
+      make (value_source_file *&, const input &x, copier<input_dw> &c)
+      {
+       return c.add_source_file (x);
+      }
+
+      template<typename input, typename input_dw>
+      static inline const value_dispatch *
+      make (value_source_line *&, const input &x, copier<input_dw> &c)
+      {
+       return c.add_source_line (x);
+      }
+
+      template<typename input, typename input_dw>
+      static inline const value_dispatch *
+      make (value_source_column *&, const input &x, copier<input_dw> &c)
+      {
+       return c.add_source_column (x);
+      }
+
+      // XXX macptr
+      // XXX location
     };
 
   public:
 
-    typedef dwarf_data::attr_value<dwarf_output, value_wrapper> attr_value;
+    typedef dwarf_data::attr_value<dwarf_output, value> attr_value;
 
     class debug_info_entry
     {
       friend class subr::create_container;
 
     public:
-      typedef dwarf_data::attributes_type<dwarf_output,
-                                         value_wrapper> attributes_type;
+      typedef dwarf_data::attributes_type<dwarf_output, value> attributes_type;
 
       class children_type : public std::list<debug_info_entry>
       {
@@ -580,16 +642,28 @@ namespace elfutils
     friend class dwarf_output;
 
   private:
-    subr::value_set<std::string> _m_strings;
-    subr::value_set<dwarf_output::range_list> _m_ranges;
-
-  public:
-
+    subr::value_set<dwarf_output::value::value_string> _m_strings;
+    subr::value_set<dwarf_output::value::value_identifier> _m_identifiers;
+    subr::value_set<dwarf_output::value::value_address> _m_address;
+    subr::value_set<dwarf_output::value::value_rangelistptr> _m_ranges;
+    subr::value_set<dwarf_output::value::value_constant> _m_constants;
+    subr::value_set<dwarf_output::value::value_constant_block> _m_const_block;
+    subr::value_set<dwarf_output::value::value_dwarf_constant> _m_dwarf_const;
+    subr::value_set<dwarf_output::value::value_source_file> _m_source_file;
+    subr::value_set<dwarf_output::value::value_source_line> _m_source_line;
+    subr::value_set<dwarf_output::value::value_source_column> _m_source_column;
+
+    static const dwarf_output::value::value_flag flag_true;
+    static const dwarf_output::value::value_flag flag_false;
+    static inline const dwarf_output::value::value_flag *flag (bool flag)
+    {
+      return flag ? &flag_true : &flag_false;
+    }
   };
 
-  template<class input>
+  template<class dw>
   class dwarf_output::copier
-    : public dwarf_ref_maker<dwarf_output, input> // XXX temporary
+    : public dwarf_ref_maker<dwarf_output, dw> // XXX temporary
   {
     friend class dwarf_output;
   private:
@@ -609,6 +683,74 @@ namespace elfutils
     {
       return *_m_collector;
     }
+
+    template<typename input>
+    inline const value::value_string *add_string (const input &x)
+    {
+      return _m_collector->_m_strings.add (x);
+    }
+
+    template<typename input>
+    inline const value::value_string *add_identifier (const input &x)
+    {
+      return _m_collector->_m_identifiers.add (x);
+    }
+
+    template<typename input>
+    inline const value::value_flag *add_flag (const input &x)
+    {
+      return dwarf_output_collector::flag (x);
+    }
+
+    template<typename input>
+    inline const value::value_address *add_address (const input &x)
+    {
+      return _m_collector->_m_address.add (x);
+    }
+
+    template<typename input>
+    inline const value::value_rangelistptr *add_ranges (const input &x)
+    {
+      return _m_collector->_m_ranges.add (x);
+    }
+
+    template<typename input>
+    inline const value::value_constant *add_constant (const input &x)
+    {
+      return _m_collector->_m_constants.add (x);
+    }
+
+    template<typename input>
+    inline const value::value_constant_block *
+    add_constant_block (const input &x)
+    {
+      return _m_collector->_m_const_block.add (x);
+    }
+
+    template<typename input>
+    inline const value::value_dwarf_constant *
+    add_dwarf_constant (const input &x)
+    {
+      return _m_collector->_m_dwarf_const.add (x);
+    }
+
+    template<typename input>
+    inline const value::value_source_file *add_source_file (const input &x)
+    {
+      return _m_collector->_m_source_file.add (x);
+    }
+
+    template<typename input>
+    inline const value::value_source_line *add_source_line (const input &x)
+    {
+      return _m_collector->_m_source_line.add (x);
+    }
+
+    template<typename input>
+    inline const value::value_source_column *add_source_column (const input &x)
+    {
+      return _m_collector->_m_source_column.add (x);
+    }
   };
 
   // Copy construction instantiates a copier derived from the collector.
@@ -618,14 +760,6 @@ namespace elfutils
                                     copier<input> maker)
     : _m_units (dw.compile_units (), maker (c))
   {}
-
-  template<typename input>
-  inline const std::string &
-  dwarf_output::collect_string (dwarf_output_collector &c, const input &s)
-  {
-    return c._m_strings.add (s);
-  }
-
 };
 
 #endif // <elfutils/dwarf_output>
index 05e9b740407a3655afb17e6170a12d23f04b2250..aa45180ceeace41fc0825b948c5ec55b134fdd74 100644 (file)
@@ -67,3 +67,6 @@ to_string<dwarf_output::attribute> (const dwarf_output::attribute &attr)
   result += attr.second.to_string ();
   return result;
 }
+
+const dwarf_output::value::value_flag dwarf_output_collector::flag_true (1);
+const dwarf_output::value::value_flag dwarf_output_collector::flag_false (0);
index 02d95b3811db5822ff44d8dcad988c94d1e39556..694b9b21502e82a7f9b13bf7948274e8250c904c 100644 (file)
@@ -53,7 +53,23 @@ namespace elfutils
     template<>
     struct hash<int> : public integer_hash<int> {};
     template<>
+    struct hash<unsigned int> : public integer_hash<unsigned int> {};
+    template<>
     struct hash<uint64_t> : public integer_hash<uint64_t> {};
+    template<>
+    struct hash<uint8_t> : public integer_hash<uint8_t> {};
+
+    template<typename T1, typename T2>
+    struct hash<std::pair<T1, T2> >
+      : public std::unary_function<std::pair<T1, T2>, size_t>
+    {
+      inline size_t operator () (const std::pair<T1, T2> &x) const
+      {
+       size_t h = 0;
+       subr::hash_combine (h, x);
+       return h;
+      }
+    };
 
     template<typename T>
     struct container_hasher : public std::unary_function<T, size_t>
@@ -76,8 +92,15 @@ namespace elfutils
       }
     };
 
+    template<typename T>
+    struct hash<std::vector<T> >
+      : public container_hasher<std::vector<T> >
+    {
+    };
+
     template<>
     struct hash<std::string>
+      : public container_hasher<std::string>
     {
     private:
       struct hasher : public container_hasher<std::string>::hasher
@@ -399,7 +422,7 @@ namespace elfutils
                                      struct hashed_value_type::hasher> _base;
 
     public:
-      const value_type &add (const value_type &v)
+      const value_type *add (const value_type &v)
       {
        std::pair<class _base::iterator, bool> p
          = _base::insert (hashed_value_type (v));
@@ -407,11 +430,11 @@ namespace elfutils
          {
            // XXX hook for collection: abbrev building, etc.
          }
-       return p.first->second;
+       return &p.first->second;
       };
 
       template<typename input>
-      const value_type &add (const input &v)
+      const value_type *add (const input &v)
       {
        return add (value_type (v));
       }