]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: Work on support of multiple versions
authorPetr Machata <pmachata@redhat.com>
Fri, 13 Nov 2009 18:43:23 +0000 (19:43 +0100)
committerPetr Machata <pmachata@redhat.com>
Wed, 18 Aug 2010 12:55:13 +0000 (14:55 +0200)
src/Makefile.am
src/dwarflint/check_debug_abbrev.cc
src/dwarflint/low.c
src/dwarflint/low.h
src/dwarflint/tables.cc [new file with mode: 0644]
src/dwarflint/tables.h [new file with mode: 0644]
src/dwarflint/tables.hh [new file with mode: 0644]

index 0de9cef563ea815e1759f2798a32b66867715152..3f498e30e96e7e01aab1193be06653d37b0975cc 100644 (file)
@@ -85,7 +85,7 @@ dwarflint_SOURCES = dwarfstrings.c \
                    dwarflint/expected-at.cc dwarflint/expected.hh \
                    dwarflint/coverage.cc dwarflint/coverage.h \
                    dwarflint/readctx.c  dwarflint/readctx.h \
-                   dwarflint/pri.cc dwarflint/pri.h \
+                   dwarflint/pri.cc dwarflint/pri.hh \
                    dwarflint/messages.cc dwarflint/messages.h \
                    dwarflint/where.c dwarflint/where.h \
                    dwarflint/config.cc dwarflint/config.h \
@@ -93,6 +93,7 @@ dwarflint_SOURCES = dwarfstrings.c \
                    dwarflint/checks-low.cc dwarflint/checks-low.hh \
                    dwarflint/addr-record.cc dwarflint/addr-record.h \
                    dwarflint/reloc.cc dwarflint/reloc.h \
+                   dwarflint/tables.cc dwarflint/tables.hh dwarflint/tables.h \
                    dwarflint/all-dies-it.hh \
                    dwarflint/checks-high.hh \
                    dwarflint/check_debug_abbrev.cc \
index d2256b861e4e4a52d9d5f3eaaee9f3c22d9ba036..cf61ea1c850094f020c0ee293428b1461dbaa263 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "checks-low.hh"
 #include "pri.hh"
+#include "tables.hh"
 
 #include <dwarf.h>
 #include <sstream>
@@ -134,6 +135,13 @@ namespace
 check_debug_abbrev::check_debug_abbrev (dwarflint &lint)
   : _m_sec_abbr (lint.check (_m_sec_abbr))
 {
+  // xxx Hmm, we need to know a dwarf version to consider which
+  // attributes are legal for DW_AT_sibling.  But there's no way to
+  // get it, we need to parse abbrevs first to parse info.  We could
+  // peek to info to get CU version/table offset mapping though, but
+  // for the time being, just take version 2.
+  dwarf_version_h ver = get_dwarf_version (2);
+
   read_ctx ctx;
   read_ctx_init (&ctx, _m_sec_abbr->sect.data,
                 _m_sec_abbr->file.other_byte_order);
@@ -312,7 +320,7 @@ check_debug_abbrev::check_debug_abbrev (dwarflint &lint)
                  throw check_base::failed ();
                }
 
-             if (!attrib_form_valid (attrib_form))
+             if (!ver->form_allowed (attrib_form))
                {
                  wr_error (where)
                    << "invalid form " << pri::hex (attrib_form)
@@ -350,7 +358,7 @@ check_debug_abbrev::check_debug_abbrev (dwarflint &lint)
                      << std::endl;
                }
 
-             switch (check_sibling_form (attrib_form))
+             switch (check_sibling_form (ver, attrib_form))
                {
                case -1:
                  wr_message (where, cat (mc_die_rel, mc_impact_2))
@@ -425,3 +433,4 @@ check_debug_abbrev::check_debug_abbrev (dwarflint &lint)
       last = &it->second;
     }
 }
+
index a9907018f12c641f09781a3b1e97797a646fbb66..2eea902db0ee6e467f7cd8269ef490e9ccd8360b 100644 (file)
@@ -48,6 +48,7 @@
 #include "readctx.h"
 #include "config.h"
 #include "dwarf-opcodes.h"
+#include "tables.h"
 
 /* True if coverage analysis of .debug_ranges vs. ELF sections should
    be done.  */
@@ -169,33 +170,15 @@ read_ctx_read_form (struct read_ctx *ctx, struct cu *cu, uint8_t form,
   return false;
 }
 
-bool
-attrib_form_valid (uint64_t form)
-{
-  return form > 0 && form <= DW_FORM_ref_sig8;
-}
-
 int
-check_sibling_form (uint64_t form)
+check_sibling_form (dwarf_version_h ver, uint64_t form)
 {
-  switch (form)
-    {
-    case DW_FORM_indirect:
-      /* Tolerate this in abbrev loading, even during the DIE loading.
-        We check that dereferenced indirect form yields valid form.  */
-    case DW_FORM_ref1:
-    case DW_FORM_ref2:
-    case DW_FORM_ref4:
-    case DW_FORM_ref8:
-    case DW_FORM_ref_udata:
-      return 0;
-
-    case DW_FORM_ref_addr:
-      return -1;
-
-    default:
-      return -2;
-    };
+  if (!dwver_form_allowed (ver, DW_AT_sibling, form))
+    return -2;
+  else if (form == DW_FORM_ref_addr)
+    return -1;
+  else
+    return 0;
 }
 
 bool
@@ -769,7 +752,8 @@ check_range_relocations (enum message_category cat,
     +1 in case some dies were actually loaded
  */
 static int
-read_die_chain (struct elf_file *file,
+read_die_chain (dwarf_version_h ver,
+               struct elf_file *file,
                struct read_ctx *ctx,
                struct cu *cu,
                struct abbrev_table *abbrevs,
@@ -885,7 +869,7 @@ read_die_chain (struct elf_file *file,
                                         "indirect attribute form"))
                return -1;
 
-             if (!attrib_form_valid (value))
+             if (!dwver_form_valid (ver, form))
                {
                  wr_error (&where,
                            ": invalid indirect form 0x%" PRIx64 ".\n", value);
@@ -894,7 +878,7 @@ read_die_chain (struct elf_file *file,
              form = value;
 
              if (it->name == DW_AT_sibling)
-               switch (check_sibling_form (form))
+               switch (check_sibling_form (ver, form))
                  {
                  case -1:
                    wr_message (mc_die_rel | mc_impact_2, &where,
@@ -1335,7 +1319,7 @@ read_die_chain (struct elf_file *file,
 
       if (abbrev->has_children)
        {
-         int st = read_die_chain (file, ctx, cu, abbrevs, strings,
+         int st = read_die_chain (ver, file, ctx, cu, abbrevs, strings,
                                   local_die_refs,
                                   strings_coverage, reloc,
                                   cu_coverage);
@@ -1409,9 +1393,10 @@ check_cu_structural (struct elf_file *file,
       wr_error (&cu->where, ": can't read version.\n");
       return false;
     }
-  if (!supported_version (version, 2, &cu->where, 2, 3))
+  dwarf_version_h ver = get_dwarf_version (version);
+  if (ver == NULL)
     return false;
-  if (version == 2 && cu->offset_size == 8)
+  if (version == 2 && cu->offset_size == 8) // xxx?
     /* Keep going.  It's a standard violation, but we may still be
        able to read the unit under consideration and do high-level
        checks.  */
@@ -1465,7 +1450,7 @@ check_cu_structural (struct elf_file *file,
   WIPE (local_die_refs);
 
   cu->cudie_offset = read_ctx_get_offset (ctx) + cu->offset;
-  if (read_die_chain (file, ctx, cu, abbrevs, strings,
+  if (read_die_chain (ver, file, ctx, cu, abbrevs, strings,
                      &local_die_refs, strings_coverage,
                      (reloc != NULL && reloc->size > 0) ? reloc : NULL,
                      cu_coverage) < 0)
index 9b8299c2c7b40c9df957580ce509503b8aba66be..35f7a3a9942800ea3787a8d5aa06e56a9aa3bd54 100644 (file)
@@ -33,6 +33,7 @@
 #include "readctx.h"
 #include "addr-record.h"
 #include "reloc.h"
+#include "tables.h"
 
 #ifdef __cplusplus
 extern "C"
@@ -161,8 +162,7 @@ extern "C"
                                     struct addr_record *line_tables);
   extern void cu_free (struct cu *cu_chain);
 
-  extern bool attrib_form_valid (uint64_t form);
-  extern int check_sibling_form (uint64_t form);
+  extern int check_sibling_form (dwarf_version_h ver, uint64_t form);
   extern bool is_location_attrib (uint64_t name);
 
   struct hole_info
diff --git a/src/dwarflint/tables.cc b/src/dwarflint/tables.cc
new file mode 100644 (file)
index 0000000..67143f3
--- /dev/null
@@ -0,0 +1,523 @@
+// The tables here capture attribute/allowed forms depending on DWARF
+// version.  Apart from standardized DWARF formats, e.g. DWARF3+GNU is
+// a version in its own.
+
+#include "tables.hh"
+#include "tables.h"
+#include "../libdw/dwarf.h"
+
+#include <map>
+#include <bitset>
+#include <cassert>
+
+namespace
+{
+  enum dw_class {
+    cl_address,
+    cl_block,
+    cl_constant,
+    cl_exprloc,
+    cl_flag,
+    cl_reference,
+    cl_string,
+    max_dw_class
+  };
+
+  typedef std::bitset <max_dw_class> dw_class_set;
+
+  dw_class_set dw_classes (dw_class a = max_dw_class, dw_class b = max_dw_class,
+                          dw_class c = max_dw_class, dw_class d = max_dw_class)
+  {
+    dw_class_set s;
+#define ADD(V) if (V != max_dw_class) s[V] = true
+    ADD (a);
+    ADD (b);
+    ADD (c);
+    ADD (d);
+#undef ADD
+    return s;
+  }
+
+  struct dwarf_at_row {
+    attr at;
+    dw_class_set classes;
+  };
+
+
+
+  struct dwarf_form_row {
+    form f;
+    dw_class cls;
+  };
+
+  dwarf_at_row dwarf_2_at_table[] = {
+    {DW_AT_sibling,            dw_classes (cl_reference)},
+    {DW_AT_location,           dw_classes (cl_block, cl_constant)},
+    {DW_AT_name,                       dw_classes (cl_string)},
+    {DW_AT_ordering,           dw_classes (cl_constant)},
+    {DW_AT_byte_size,          dw_classes (cl_constant)},
+    {DW_AT_bit_offset,         dw_classes (cl_constant)},
+    {DW_AT_bit_size,           dw_classes (cl_constant)},
+    {DW_AT_stmt_list,          dw_classes (cl_constant)},
+    {DW_AT_low_pc,             dw_classes (cl_address)},
+    {DW_AT_high_pc,            dw_classes (cl_address)},
+    {DW_AT_language,           dw_classes (cl_constant)},
+    {DW_AT_discr,                      dw_classes (cl_reference)},
+    {DW_AT_discr_value,                dw_classes (cl_constant)},
+    {DW_AT_visibility,         dw_classes (cl_constant)},
+    {DW_AT_import,             dw_classes (cl_reference)},
+    {DW_AT_string_length,              dw_classes (cl_block, cl_constant)},
+    {DW_AT_common_reference,   dw_classes (cl_reference)},
+    {DW_AT_comp_dir,           dw_classes (cl_string)},
+    {DW_AT_const_value,                dw_classes (cl_string, cl_constant, cl_block)},
+    {DW_AT_containing_type,    dw_classes (cl_reference)},
+    {DW_AT_default_value,              dw_classes (cl_reference)},
+    {DW_AT_inline,             dw_classes (cl_constant)},
+    {DW_AT_is_optional,                dw_classes (cl_flag)},
+    {DW_AT_lower_bound,                dw_classes (cl_constant, cl_reference)},
+    {DW_AT_producer,           dw_classes (cl_string)},
+    {DW_AT_prototyped,         dw_classes (cl_flag)},
+    {DW_AT_return_addr,                dw_classes (cl_block, cl_constant)},
+    {DW_AT_start_scope,                dw_classes (cl_constant)},
+    {DW_AT_bit_stride,         dw_classes (cl_constant)},
+    {DW_AT_upper_bound,                dw_classes (cl_constant, cl_reference)},
+    {DW_AT_abstract_origin,    dw_classes (cl_constant)},
+    {DW_AT_accessibility,              dw_classes (cl_reference)},
+    {DW_AT_address_class,              dw_classes (cl_constant)},
+    {DW_AT_artificial,         dw_classes (cl_flag)},
+    {DW_AT_base_types,         dw_classes (cl_reference)},
+    {DW_AT_calling_convention, dw_classes (cl_constant)},
+    {DW_AT_count,                      dw_classes (cl_constant, cl_reference)},
+    {DW_AT_data_member_location,       dw_classes (cl_block, cl_reference)},
+    {DW_AT_decl_column,                dw_classes (cl_constant)},
+    {DW_AT_decl_file,          dw_classes (cl_constant)},
+    {DW_AT_decl_line,          dw_classes (cl_constant)},
+    {DW_AT_declaration,                dw_classes (cl_flag)},
+    {DW_AT_discr_list,         dw_classes (cl_block)},
+    {DW_AT_encoding,           dw_classes (cl_constant)},
+    {DW_AT_external,           dw_classes (cl_flag)},
+    {DW_AT_frame_base,         dw_classes (cl_block, cl_constant)},
+    {DW_AT_friend,             dw_classes (cl_reference)},
+    {DW_AT_identifier_case,    dw_classes (cl_constant)},
+    {DW_AT_macro_info,         dw_classes (cl_constant)},
+    {DW_AT_namelist_item,              dw_classes (cl_block)},
+    {DW_AT_priority,           dw_classes (cl_reference)},
+    {DW_AT_segment,            dw_classes (cl_block, cl_constant)},
+    {DW_AT_specification,              dw_classes (cl_reference)},
+    {DW_AT_static_link,                dw_classes (cl_block, cl_constant)},
+    {DW_AT_type,                       dw_classes (cl_reference)},
+    {DW_AT_use_location,               dw_classes (cl_block, cl_constant)},
+    {DW_AT_variable_parameter, dw_classes (cl_flag)},
+    {DW_AT_virtuality,         dw_classes (cl_constant)},
+    {DW_AT_vtable_elem_location,       dw_classes (cl_block, cl_reference)},
+    {0, dw_classes ()}
+  };
+
+  dwarf_form_row dwarf_2_form_table[] = {
+    {DW_FORM_addr,     cl_address},
+    {DW_FORM_block2,   cl_block},
+    {DW_FORM_block4,   cl_block},
+    {DW_FORM_data2,    cl_constant},
+    {DW_FORM_data4,    cl_constant},
+    {DW_FORM_data8,    cl_constant},
+    {DW_FORM_string,   cl_string},
+    {DW_FORM_block,    cl_block},
+    {DW_FORM_block1,   cl_block},
+    {DW_FORM_data1,    cl_constant},
+    {DW_FORM_flag,     cl_flag},
+    {DW_FORM_sdata,    cl_constant},
+    {DW_FORM_strp,     cl_string},
+    {DW_FORM_udata,    cl_constant},
+    {DW_FORM_ref_addr, cl_reference},
+    {DW_FORM_ref1,     cl_reference},
+    {DW_FORM_ref2,     cl_reference},
+    {DW_FORM_ref4,     cl_reference},
+    {DW_FORM_ref8,     cl_reference},
+    {DW_FORM_ref_udata,        cl_reference},
+    {0, max_dw_class}
+  };
+
+  class std_dwarf
+    : public dwarf_version
+  {
+    typedef std::map <attr, form_set_t> _forms_t;
+    _forms_t _forms;
+    form_set_t all_forms;
+
+  public:
+    std_dwarf (dwarf_at_row attrtab[], dwarf_form_row formtab[])
+    {
+      for (unsigned i = 0; attrtab[i].at != 0; ++i)
+       for (unsigned c = 0; c < attrtab[i].classes.size (); ++c)
+         if (attrtab[i].classes[c])
+           for (unsigned j = 0; formtab[j].f != 0; ++j)
+             if (formtab[j].cls == static_cast <dw_class> (c))
+               _forms[attrtab[i].at].insert (formtab[j].f);
+
+      for (unsigned j = 0; formtab[j].f != 0; ++j)
+       all_forms.insert (formtab[j].f);
+
+      /*
+       std::cout << pri::attr (attrtab[i].at) << " {";
+       for (std::set <int>::const_iterator it = forms.begin ();
+       it != forms.end (); ++it)
+       std::cout << (it == forms.begin () ? "" : ", ") << pri::form (*it);
+       std::cout << "}" << std::endl;
+      */
+    }
+
+    form_set_t const &allowed_forms () const { return all_forms; }
+
+    form_set_t const &allowed_forms (attr at) const
+    {
+      _forms_t::const_iterator it = _forms.find (at);
+      assert (it != _forms.end ());
+      return it->second;
+    }
+
+    // Answer forms allowed at DIE with that tag.
+    form_set_t const &allowed_forms (attr at,
+                                    __attribute__ ((unused)) die_tag tag) const
+    {
+      return allowed_forms (at);
+    }
+  };
+
+  std_dwarf dwarf2 (dwarf_2_at_table, dwarf_2_form_table);
+  std_dwarf dwarf3 (dwarf_2_at_table, dwarf_2_form_table); // xxx for now till we get real dw3 table
+}
+
+dwarf_version_h
+get_dwarf_version (unsigned version)
+{
+  switch (version)
+    {
+    case 2: return &dwarf2;
+    case 3: return &dwarf3;
+    default: return NULL;
+    };
+}
+
+bool
+dwver_form_valid (dwarf_version const *ver, int form)
+{
+  return ver->form_allowed (form);
+}
+
+bool
+dwver_form_allowed (dwarf_version const *ver, int attr, int form)
+{
+  return ver->form_allowed (attr, form);
+}
+
+bool
+dwver_form_allowed_in (dwarf_version const *ver, int attr, int form, int tag)
+{
+  return ver->form_allowed (attr, form, tag);
+}
+
+#if 0
+
+.at (DW_AT_abstract_origin)
+.version (dwarf_2, dwarf_3, dwarf_4).classes (reference)
+
+.ad (DW_AT_accessibility)
+.version (dwarf_2, dwarf_3, dwarf_4).classes (constant)
+
+.at (DW_AT_allocated)
+.version (dwarf_3).classes (constant, block, reference)
+.version (dwarf_4).classes (constant, exprloc, reference)
+
+;
+
+
+{DW_AT_abstract_origin,                0x31    2,3,4   reference
+
+DW_AT_accessibility            0x32    2,3,4   constant
+
+DW_AT_address_class            0x33    2,3,4   constant
+
+
+// compositions of dwarf_version:
+//  - extend (A, B): allow union of A and B
+//  - strict (A, B): allow intersection of A and B
+
+// AT->class
+DW_AT_abstract_origin          0x31    /*2,3,4*/reference
+
+DW_AT_accessibility            0x32    /*2,3,4*/constant
+
+DW_AT_address_class            0x33    /*2,3,4*/constant
+
+DW_AT_allocated                        0x4e    /*3*/constant,block,reference
+DW_AT_allocated                        0x4e    /*4*/constant,exprloc,reference
+
+DW_AT_artificial               0x34    /*2,3,4*/flag
+
+DW_AT_associated               0x4f    /*3*/block,constant,reference
+DW_AT_associated               0x4f    /*4*/constant,exprloc,reference
+
+DW_AT_base_types               0x35    /*2,3,4*/reference
+
+DW_AT_binary_scale             0x5b    /*3,4*/constant
+
+DW_AT_bit_offset               0x0c    /*2*/constant
+DW_AT_bit_offset               0x0c    /*3*/block,constant,reference
+DW_AT_bit_offset               0x0c    /*4*/constant,exprloc,reference
+
+DW_AT_bit_size                 0x0d    /*2*/constant
+DW_AT_bit_size                 0x0d    /*3*/block,constant,reference
+DW_AT_bit_size                 0x0d    /*4*/constant,exprloc,reference
+
+DW_AT_bit_stride               0x2e    /*3*/constant
+DW_AT_bit_stride               0x2e    /*4*/constant,exprloc,reference
+
+DW_AT_byte_size                        0x0b    /*2*/constant
+DW_AT_byte_size                        0x0b    /*3*/block,constant,reference
+DW_AT_byte_size                        0x0b    /*4*/constant,exprloc,reference
+
+DW_AT_byte_stride              0x51    /*3*/block,constant,reference
+DW_AT_byte_stride              0x51    /*4*/constant,exprloc,reference
+
+DW_AT_call_column              0x57    /*3,4*/constant
+
+DW_AT_call_file                        0x58    /*3,4*/constant
+
+DW_AT_call_line                        0x59    /*3,4*/constant
+
+DW_AT_calling_convention       0x36    /*2,3,4*/constant
+
+DW_AT_common_reference         0x1a    /*2,3,4*/reference
+
+DW_AT_comp_dir                 0x1b    /*2,3,4*/string
+
+DW_AT_const_expr               0x6c    /*4*/flag
+
+DW_AT_const_value              0x1c    /*2*/string,constant,block
+DW_AT_const_value              0x1c    /*3*/block,constant,string
+DW_AT_const_value              0x1c    /*4*/block,constant,string
+
+DW_AT_containing_type          0x1d    /*2,3,4*/reference
+
+DW_AT_count                    0x37    /*2*/constant,reference
+DW_AT_count                    0x37    /*3*/block,constant,reference
+DW_AT_count                    0x37    /*4*/constant,exprloc,reference
+
+DW_AT_data_bit_offset          0x6b    /*4*/constant
+
+DW_AT_data_location            0x50    /*3*/block
+DW_AT_data_location            0x50    /*4*/exprloc
+
+DW_AT_data_member_location     0x38    /*2*/block,reference
+DW_AT_data_member_location     0x38    /*3*/block,constant,loclistptr
+DW_AT_data_member_location     0x38    /*4*/constant,exprloc,loclistptr
+
+DW_AT_decimal_scale            0x5c    /*3,4*/constant
+
+DW_AT_decimal_sign             0x5e    /*3,4*/constant
+
+DW_AT_decl_column              0x39    /*2,3,4*/constant
+
+DW_AT_decl_file                        0x3a    /*2,3,4*/constant
+
+DW_AT_decl_line                        0x3b    /*2,3,4*/constant
+
+DW_AT_declaration              0x3c    /*2,3,4*/flag
+
+DW_AT_default_value            0x1e    /*2,3,4*/reference
+
+DW_AT_description              0x5a    /*3,4*/string
+
+DW_AT_digit_count              0x5f    /*3,4*/constant
+
+DW_AT_discr                    0x15    /*2,3,4*/reference
+
+DW_AT_discr_list               0x3d    /*2,3,4*/block
+
+DW_AT_discr_value              0x16    /*2,3,4*/constant
+
+DW_AT_elemental                        0x66    /*3,4*/flag
+
+DW_AT_encoding                 0x3e    /*2,3,4*/constant
+
+DW_AT_endianity                        0x65    /*3,4*/constant
+
+DW_AT_entry_pc                 0x52    /*3,4*/address
+
+DW_AT_explicit                 0x63    /*3,4*/flag
+
+DW_AT_extension                        0x54    /*3,4*/reference
+
+DW_AT_external                 0x3f    /*2,3,4*/flag
+
+DW_AT_frame_base               0x40    /*2*/block,constant
+DW_AT_frame_base               0x40    /*3*/block,loclistptr
+DW_AT_frame_base               0x40    /*4*/exprloc,loclistptr
+
+DW_AT_friend                   0x41    /*2,3,4*/reference
+
+DW_AT_high_pc                  0x12    /*2,3*/address
+DW_AT_high_pc                  0x12    /*4*/address,constant
+
+DW_AT_identifier_case          0x42    /*2,3,4*/constant
+
+DW_AT_import                   0x18    /*2,3,4*/reference
+
+DW_AT_inline                   0x20    /*2,3,4*/constant
+
+DW_AT_is_optional              0x21    /*2,3,4*/flag
+
+DW_AT_language                 0x13    /*2,3,4*/constant
+
+DW_AT_location                 0x02    /*2*/block,constant
+DW_AT_location                 0x02    /*3*/block,loclistptr
+DW_AT_location                 0x02    /*4*/exprloc,loclistptr
+
+DW_AT_low_pc                   0x11    /*2,3,4*/address
+
+DW_AT_lower_bound              0x22    /*2*/constant,reference
+DW_AT_lower_bound              0x22    /*3*/block,constant,reference
+DW_AT_lower_bound              0x22    /*4*/constant,exprloc,reference
+
+DW_AT_macro_info               0x43    /*2*/constant
+DW_AT_macro_info               0x43    /*3,4*/macptr
+
+DW_AT_main_subprogram          0x6a    /*4*/flag
+
+DW_AT_mutable                  0x61    /*3,4*/flag
+
+DW_AT_name                     0x03    /*2,3,4*/string
+
+DW_AT_namelist_item            0x44    /*2,3*/block
+DW_AT_namelist_item            0x44    /*4*/reference
+
+DW_AT_object_pointer           0x64    /*3,4*/reference
+
+DW_AT_ordering                 0x09    /*2,3,4*/constant
+
+DW_AT_picture_string           0x60    /*3,4*/string
+
+DW_AT_priority                 0x45    /*2,3,4*/reference
+
+DW_AT_producer                 0x25    /*2,3,4*/string
+
+DW_AT_prototyped               0x27    /*2,3,4*/flag
+
+DW_AT_pure                     0x67    /*3,4*/flag
+
+DW_AT_ranges                   0x55    /*3,4*/rangelistptr
+
+DW_AT_recursive                        0x68    /*3,4*/flag
+
+DW_AT_return_addr              0x2a    /*2*/block,constant
+DW_AT_return_addr              0x2a    /*3*/block,loclistptr
+DW_AT_return_addr              0x2a    /*4*/exprloc,loclistptr
+
+DW_AT_segment                  0x46    /*2*/block,constant
+DW_AT_segment                  0x46    /*3*/block,loclistptr
+DW_AT_segment                  0x46    /*4*/exprloc,loclistptr
+
+DW_AT_sibling                  0x01    /*2,3,4*/reference
+
+DW_AT_signature                        0x69    /*4*/reference
+
+DW_AT_small                    0x5d    /*3,4*/reference
+
+DW_AT_specification            0x47    /*2,3,4*/reference
+
+DW_AT_start_scope              0x2c    /*2,3,4*/constant
+
+DW_AT_static_link              0x48    /*2*/block,constant
+DW_AT_static_link              0x48    /*3*/block,loclistptr
+DW_AT_static_link              0x48    /*4*/exprloc,loclistptr
+
+DW_AT_stmt_list                        0x10    /*2*/constant
+DW_AT_stmt_list                        0x10    /*3,4*/lineptr
+
+DW_AT_stride_size              0x2e    /*2*/constant
+
+DW_AT_string_length            0x19    /*2*/block,constant
+DW_AT_string_length            0x19    /*3*/block,loclistptr
+DW_AT_string_length            0x19    /*4*/exprloc,loclistptr
+
+DW_AT_threads_scaled           0x62    /*3,4*/flag
+
+DW_AT_trampoline               0x56    /*3,4*/address,flag,reference,string
+
+DW_AT_type                     0x49    /*2,3,4*/reference
+
+DW_AT_upper_bound              0x2f    /*2*/constant
+DW_AT_upper_bound              0x2f    /*3*/block,constant,reference
+DW_AT_upper_bound              0x2f    /*4*/constant,exprloc,reference
+
+DW_AT_use_UTF8                 0x53    /*3,4*/flag
+
+DW_AT_use_location             0x4a    /*2*/block,constant
+DW_AT_use_location             0x4a    /*3*/block,loclistptr
+DW_AT_use_location             0x4a    /*4*/exprloc,loclistptr
+
+DW_AT_variable_parameter       0x4b    /*2,3,4*/flag
+
+DW_AT_virtuality               0x4c    /*2,3,4*/constant
+
+DW_AT_visibility               0x17    /*2,3,4*/constant
+
+DW_AT_vtable_elem_location     0x4d    /*2*/block,reference
+DW_AT_vtable_elem_location     0x4d    /*3*/block,loclistptr
+DW_AT_vtable_elem_location     0x4d    /*4*/exprloc,loclistptr
+
+
+// FORM->class
+DW_FORM_addr           0x01    /*2,3,4*/address
+
+DW_FORM_block          0x09    /*2,3,4*/block
+
+DW_FORM_block1         0x0a    /*2,3,4*/block
+
+DW_FORM_block2         0x03    /*2,3,4*/block
+
+DW_FORM_block4         0x04    /*2,3,4*/block
+
+DW_FORM_data1          0x0b    /*2,3,4*/constant
+
+DW_FORM_data2          0x05    /*2,3,4*/constant
+
+DW_FORM_data4          0x06    /*2,4*/constant
+DW_FORM_data4          0x06    /*3*/constant, lineptr, loclistptr, macptr, rangelistptr
+
+DW_FORM_data8          0x07    /*2,4*/constant
+DW_FORM_data8          0x07    /*3*/constant, lineptr, loclistptr, macptr, rangelistptr
+
+DW_FORM_exprloc                0x18    /*4*/exprloc
+
+DW_FORM_flag           0x0c    /*2,3,4*/flag
+
+DW_FORM_flag_present   0x19    /*4*/flag
+
+DW_FORM_indirect       0x16    /*2,3,4*/-
+
+DW_FORM_ref1           0x11    /*2,3,4*/reference
+
+DW_FORM_ref2           0x12    /*2,3,4*/reference
+
+DW_FORM_ref4           0x13    /*2,3,4*/reference
+
+DW_FORM_ref8           0x14    /*2,3,4*/reference
+
+DW_FORM_ref_addr       0x10    /*2,3,4*/reference
+
+DW_FORM_ref_sig8       0x20    /*4*/reference
+
+DW_FORM_ref_udata      0x15    /*2,3,4*/reference
+
+DW_FORM_sdata          0x0d    /*2,3,4*/constant
+
+DW_FORM_sec_offset     0x17    /*4*/lineptr, loclistptr, macptr, rangelistptr
+
+DW_FORM_string         0x08    /*2,3,4*/string
+
+DW_FORM_strp           0x0e    /*2,3,4*/string
+
+DW_FORM_udata          0x0f    /*2,3,4*/constant
+
+#endif
diff --git a/src/dwarflint/tables.h b/src/dwarflint/tables.h
new file mode 100644 (file)
index 0000000..f5f36bf
--- /dev/null
@@ -0,0 +1,53 @@
+/* Dwarf version tables, C binding.
+
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifndef DWARFLINT_TABLES_H
+#define DWARFLINT_TABLES_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#else
+# include <stdbool.h>
+#endif
+
+  struct dwarf_version;
+  typedef struct dwarf_version const *dwarf_version_h;
+
+  dwarf_version_h get_dwarf_version (unsigned version)
+    __attribute__ ((pure));
+
+  bool dwver_form_valid (dwarf_version_h ver, int form);
+
+  bool dwver_form_allowed (dwarf_version_h ver, int attr, int form);
+
+  bool dwver_form_allowed_in (dwarf_version_h ver, int attr,int form, int tag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif//DWARFLINT_TABLES_H
diff --git a/src/dwarflint/tables.hh b/src/dwarflint/tables.hh
new file mode 100644 (file)
index 0000000..16ee24d
--- /dev/null
@@ -0,0 +1,75 @@
+/* Dwarf version tables.
+
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifndef DWARFLINT_TABLES_HH
+#define DWARFLINT_TABLES_HH
+
+#include <set>
+
+typedef int form;
+typedef int attr;
+typedef int die_tag;
+class locexpr_op {};
+
+class dwarf_version
+{
+protected:
+  typedef std::set <form> form_set_t;
+
+private:
+  inline static bool find_form (form_set_t const &s, int f)
+  {
+    return s.find (f) != s.end ();
+  }
+
+public:
+  // Answer all known forms.
+  virtual form_set_t const &allowed_forms () const = 0;
+
+  // Answer all forms allowed in theory for this attribute.
+  virtual form_set_t const &allowed_forms (attr at) const = 0;
+
+  // Answer forms allowed for this attribute at DIE with that tag.
+  virtual form_set_t const &allowed_forms (attr at, die_tag tag) const = 0;
+
+public:
+  bool form_allowed (form f) const
+  {
+    return find_form (allowed_forms (), f);
+  }
+
+  bool form_allowed (attr at, form f) const
+  {
+    return find_form (allowed_forms (at), f);
+  }
+
+  bool form_allowed (attr at, form f, die_tag tag) const
+  {
+    return find_form (allowed_forms (at, tag), f);
+  }
+};
+
+#endif//DWARFLINT_TABLES_HH