summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2010-10-12 00:34:56 +0200
committerPetr Machata <pmachata@redhat.com>2010-10-12 00:34:56 +0200
commitc3150260380eecc9cb686700eb46605bd35fd19d (patch)
tree432da4c40beefa2e94d3d153ba622eda945d573c
parent75dfc809260802688613b806a1ea22fd3d3e20b5 (diff)
parentf4c226a35942ec8e9e9b28e5c02b757143c38381 (diff)
downloadelfutils-c3150260380eecc9cb686700eb46605bd35fd19d.tar.gz
Merge branch 'pmachata/dwarflint-smartforms' into dwarf
-rw-r--r--dwarflint/Makefile.am23
-rw-r--r--dwarflint/TODO50
-rw-r--r--dwarflint/check_debug_abbrev.cc194
-rw-r--r--dwarflint/check_debug_abbrev.hh11
-rw-r--r--dwarflint/check_debug_info.cc391
-rw-r--r--dwarflint/check_debug_info.ii2
-rw-r--r--dwarflint/check_debug_loc_range.cc156
-rw-r--r--dwarflint/check_debug_loc_range.hh4
-rw-r--r--dwarflint/checked_read.cc93
-rw-r--r--dwarflint/checked_read.hh42
-rw-r--r--dwarflint/dwarf_2.cc177
-rw-r--r--dwarflint/dwarf_2.hh33
-rw-r--r--dwarflint/dwarf_3.cc150
-rw-r--r--dwarflint/dwarf_3.hh37
-rw-r--r--dwarflint/dwarf_4.cc103
-rw-r--r--dwarflint/dwarf_4.hh37
-rw-r--r--dwarflint/dwarf_mips.cc96
-rw-r--r--dwarflint/dwarf_mips.hh33
-rw-r--r--dwarflint/dwarf_version-imp.cc77
-rw-r--r--dwarflint/dwarf_version-imp.hh121
-rw-r--r--dwarflint/dwarf_version.cc259
-rw-r--r--dwarflint/dwarf_version.hh227
-rw-r--r--dwarflint/dwarf_version.ii3
-rw-r--r--dwarflint/misc.hh28
-rw-r--r--dwarflint/tables.cc724
-rw-r--r--dwarflint/tables.hh83
26 files changed, 1795 insertions, 1359 deletions
diff --git a/dwarflint/Makefile.am b/dwarflint/Makefile.am
index 7d61ff98..f4160884 100644
--- a/dwarflint/Makefile.am
+++ b/dwarflint/Makefile.am
@@ -46,6 +46,12 @@ dwarflint_SOURCES = \
checks.cc checks.hh checks.ii \
coverage.cc coverage.hh \
cu_coverage.cc cu_coverage.hh cu_coverage.ii \
+ dwarf_2.cc dwarf_2.hh \
+ dwarf_3.cc dwarf_3.hh \
+ dwarf_4.cc dwarf_4.hh \
+ dwarf_mips.cc dwarf_mips.hh \
+ dwarf_version-imp.cc dwarf_version-imp.hh \
+ dwarf_version.cc dwarf_version.hh dwarf_version.ii \
dwarflint.cc dwarflint.hh dwarflint.ii \
elf_file.hh elf_file.ii \
expected-at.cc expected.hh \
@@ -59,23 +65,24 @@ dwarflint_SOURCES = \
reloc.cc reloc.hh \
section_id.cc section_id.hh \
sections.cc sections.hh sections.ii \
- tables.cc tables.hh \
where.c where.h \
wrap.cc wrap.hh \
+ \
check_debug_abbrev.cc check_debug_abbrev.hh check_debug_abbrev.ii \
+ check_debug_aranges.cc check_debug_aranges.hh check_debug_aranges.ii \
check_debug_info.cc check_debug_info.hh check_debug_info.ii \
check_debug_line.cc check_debug_line.hh check_debug_line.ii \
- check_debug_pub.cc check_debug_pub.hh \
check_debug_loc_range.cc check_debug_loc_range.hh check_debug_loc_range.ii \
- check_debug_aranges.cc check_debug_aranges.hh check_debug_aranges.ii \
- lowlevel_checks.cc lowlevel_checks.hh \
- check_matching_ranges.cc \
- check_range_out_of_scope.cc \
- check_expected_trees.cc \
- check_dups_abstract_origin.cc \
+ check_debug_pub.cc check_debug_pub.hh \
check_duplicate_DW_tag_variable.cc \
+ check_dups_abstract_origin.cc \
+ check_expected_trees.cc \
+ check_matching_ranges.cc \
check_nodebug.cc \
+ check_range_out_of_scope.cc \
locstats.cc \
+ lowlevel_checks.cc lowlevel_checks.hh \
+ \
../src/dwarfstrings.c
TESTS = tests/run-debug_abbrev-duplicate-attribute.sh \
diff --git a/dwarflint/TODO b/dwarflint/TODO
index 872e6b2c..17a3c3ca 100644
--- a/dwarflint/TODO
+++ b/dwarflint/TODO
@@ -1,12 +1,21 @@
-*-org-*-
-* DWARF 4 support
- This TODO item is actually to go through the DWARF 4 standard and
- add TODO items for individual tasks.
-
- Roland: i.e., block* forms can be constant-block or location in
- DWARF<=3, but only exprloc is a location in DWARF>=4; data* forms
- can be either constant or *ptr in DWARF<=3 but only sec_offset is
- *ptr in DWARF>=4.
+* Generic DWARF support
+ We now have dwarf_version, form and attribute classes. These can be
+ (and are) set up to support DWARF 2, 3 and 4 separately, as well as
+ the MIPS extension (in a kinda-sorta way, since I've got no binaries
+ to check this).
+
+ But there's still some code around that depends on per-form/per-attr
+ switches, namely check_debug_info.cc::reloc_target and the
+ reference-checking code in the same file. Maybe the way to do this
+ is to merge all the cl_*ptr into one class cl_pointer and have
+ dwarflint know that the attribute determines what it points to.
+ (Except that some forms determine the target themselves.) Then
+ declare at relevant attributes the pointer target (a section_id), if
+ any. I.e. type the forms more richly.
+
+ So that's about the FORMs and ATs. But there's more, e.g. DW_OP_
+ support.
* high-level checks
@@ -17,8 +26,8 @@
http://www.mail-archive.com/elfutils-devel@lists.fedorahosted.org/msg00816.html
** dwarflint --stats
-*** the mutable/immutable part is not implemented yet
- http://www.mail-archive.com/elfutils-devel@lists.fedorahosted.org/msg00849.html
+*** mutability probably needs to take into account DW_OP_call*
+ https://fedorahosted.org/pipermail/elfutils-devel/2010-October/001628.html
** expected trees/attributes
This is about the check_expected_trees check. All attributes are
@@ -30,7 +39,7 @@
in DWARF revisions and doesn't tackle the expected children case at
all. It seems that what we need is some sort of XPath-like
approach to matching sub-graphs. Each time one of the queries
- triggered, a check would be done for expected "neighborhood" of the
+ triggers, a check would be done for expected "neighborhood" of the
node. Such a query might reach far from the original node,
spanning layers of parent/child or die/neighbor relationship.
@@ -83,9 +92,10 @@
** streams vs fmtstring
We now use C++ streams in most places (there are remnants of C
- printfs in places). But we would like to be able to localize it
- all, and I'm afraid that means moving back to some sort of
- formatting strings.
+ printfs in places). But streams suck for localization. Personally
+ I'm not too enthusiastic about non-English bugreports, but rest of
+ elfutils is localized, and dwarflint should be too. I'm afraid
+ that means moving back to some sort of formatting strings.
** filtering
@@ -111,12 +121,16 @@
there to be frequent additions to this "quirks table", so it should
be fairly easy to extend this.
+ (Maybe quirk is simply a dwarf_version. After loading the CU DIE,
+ dwarflint would consult the quirk table and construct new
+ dwarf_version with appropriate exceptions.)
+
The current option --tolerant will go away when this is implemented.
I don't think it even works anyway.
* multi-file mode
- While dwarflint manages checking several files (meaning you can put
- several file names to a command line), it treats each of them in
- isolation. In theory these files can link to each other and form
- graphs, and dwarflint should be able to handle this.
+ While dwarflint can check several files (meaning you can put several
+ file names to a command line), it treats each of them in isolation.
+ In theory these files can link to each other and form graphs, and
+ dwarflint should be able to check the whole graph.
diff --git a/dwarflint/check_debug_abbrev.cc b/dwarflint/check_debug_abbrev.cc
index e62445d2..fac1f468 100644
--- a/dwarflint/check_debug_abbrev.cc
+++ b/dwarflint/check_debug_abbrev.cc
@@ -30,7 +30,7 @@
#include "check_debug_info.hh"
#include "check_debug_abbrev.hh"
#include "pri.hh"
-#include "tables.hh"
+#include "dwarf_version.hh"
#include "sections.hh"
#include "checked_read.hh"
#include "messages.hh"
@@ -111,13 +111,14 @@ namespace
};
void
- complain_invalid_form (where const &where, int name, int form,
- std::string const &specification = "")
+ complain (where const *where,
+ attribute const *attribute, form const *form,
+ bool indirect, char const *qualifier)
{
- wr_error (where)
- << specification << (" "[specification.length () == 0])
- << pri::attr (name) << " with invalid form "
- << pri::form (form) << '.' << std::endl;
+ wr_error (*where)
+ << "attribute " << *attribute << " with " << qualifier
+ << (indirect ? " indirect" : "") << " form"
+ << *form << '.' << std::endl;
}
bool
@@ -358,117 +359,69 @@ namespace
"attribute form"))
throw check_base::failed ();
- null_attrib = attrib_name == 0 && attrib_form == 0;
-
/* Now if both are zero, this was the last attribute. */
- if (!null_attrib)
- {
- /* Otherwise validate name and form. */
- if (attrib_name > DW_AT_hi_user)
- {
- wr_error (where)
- << "invalid name " << pri::hex (attrib_name)
- << '.' << std::endl;
- failed = true;
- continue;
- }
-
- if (!ver->form_allowed (attrib_form))
- {
- wr_error (where)
- << "invalid form " << pri::hex (attrib_form)
- << '.' << std::endl;
- failed = true;
- continue;
- }
-
- std::pair<std::map<unsigned, uint64_t>::iterator, bool> inserted
- = seen.insert (std::make_pair (attrib_name, attr_off));
- if (!inserted.second)
- {
- wr_error (where)
- << "duplicate attribute " << pri::attr (attrib_name)
- << " (first was at " << pri::hex (inserted.first->second)
- << ")." << std::endl;
- // I think we may allow such files for high-level
- // consumption, so don't fail the check...
- if (attrib_name == DW_AT_sibling)
- // ... unless it's DW_AT_sibling.
- failed = true;
- }
- }
+ null_attrib = attrib_name == 0 && attrib_form == 0;
+ attribute const *attribute = NULL;
REALLOC (cur, attribs);
struct abbrev_attrib *acur = cur->attribs + cur->size++;
WIPE (*acur);
+ acur->name = attrib_name;
+ acur->form = attrib_form;
+ acur->where = where;
- /* We do structural checking of sibling attribute, so make
- sure our assumptions in actual DIE-loading code are
- right. We expect form from reference class, but only
- CU-local, not DW_FORM_ref_addr. */
- if (attrib_name == DW_AT_sibling)
- {
- if (!cur->has_children)
- wr_message (where,
- cat (mc_die_rel, mc_acc_bloat, mc_impact_1))
- << "excessive DW_AT_sibling attribute at childless abbrev."
- << std::endl;
-
- switch (ver->check_sibling_form (attrib_form))
- {
- case -1:
- wr_message (where, cat (mc_die_rel, mc_impact_2))
- << "DW_AT_sibling attribute with form DW_FORM_ref_addr."
- << std::endl;
- break;
+ if (null_attrib)
+ break;
- case -2:
- wr_error (where)
- << "DW_AT_sibling attribute with non-reference form "
- << pri::form (attrib_form) << '.' << std::endl;
- };
+ /* Otherwise validate name and form. */
+ attribute = ver->get_attribute (attrib_name);
+ if (attribute == NULL)
+ {
+ wr_error (where)
+ << "invalid name " << pri::hex (attrib_name)
+ << '.' << std::endl;
+ failed = true;
+ continue;
}
- /* Similar for DW_AT_location and friends. */
- else if (is_location_attrib (attrib_name))
+ std::pair<std::map<unsigned, uint64_t>::iterator, bool> inserted
+ = seen.insert (std::make_pair (attrib_name, attr_off));
+ if (!inserted.second)
{
- if (!ver->form_allowed (attrib_name, attrib_form))
- complain_invalid_form (where, attrib_name, attrib_form,
- "location attribute");
+ wr_error (where)
+ << "duplicate attribute " << pri::attr (attrib_name)
+ << " (first was at " << pri::hex (inserted.first->second)
+ << ")." << std::endl;
+ // I think we may allow such files for high-level
+ // consumption, so don't fail the check...
+ if (attrib_name == DW_AT_sibling)
+ // ... unless it's DW_AT_sibling.
+ failed = true;
}
- /* Similar for DW_AT_ranges. */
- else if (attrib_name == DW_AT_ranges
- || attrib_name == DW_AT_stmt_list)
+ form const *form = check_debug_abbrev::check_form
+ (ver, attrib_form, attribute, &where, false);
+ if (form == NULL)
{
- if (attrib_form != DW_FORM_data4
- && attrib_form != DW_FORM_data8
- && attrib_form != DW_FORM_sec_offset
- && attrib_form != DW_FORM_indirect)
- complain_invalid_form (where, attrib_name, attrib_form);
- if (attrib_name == DW_AT_ranges)
- ranges = true;
+ failed = true;
+ continue;
}
- /* Similar for DW_AT_{low,high}_pc, plus also make sure we
- don't see high_pc without low_pc. */
- else if (attrib_name == DW_AT_low_pc
- || attrib_name == DW_AT_high_pc)
+ if (attrib_name == DW_AT_sibling)
{
- if (attrib_form != DW_FORM_addr
- && attrib_form != DW_FORM_ref_addr)
- complain_invalid_form (where, attrib_name, attrib_form);
-
- if (attrib_name == DW_AT_low_pc)
- low_pc = true;
- else if (attrib_name == DW_AT_high_pc)
- high_pc = true;
+ if (!cur->has_children)
+ wr_message (where,
+ cat (mc_die_rel, mc_acc_bloat, mc_impact_1))
+ << "excessive DW_AT_sibling attribute at childless abbrev."
+ << std::endl;
}
-
- acur->name = attrib_name;
- acur->form = attrib_form;
- acur->where = where;
+ if (attrib_name == DW_AT_ranges)
+ ranges = true;
+ else if (attrib_name == DW_AT_low_pc)
+ low_pc = true;
+ else if (attrib_name == DW_AT_high_pc)
+ high_pc = true;
}
while (!null_attrib);
@@ -510,6 +463,32 @@ check_debug_abbrev::check_debug_abbrev (checkstack &stack, dwarflint &lint)
{
}
+form const *
+check_debug_abbrev::check_form (dwarf_version const *ver, int form_name,
+ attribute const *attribute, where const *where,
+ bool indirect)
+{
+ form const *form = ver->get_form (form_name);
+ if (form == NULL)
+ {
+ wr_error (*where)
+ << "invalid form " << pri::hex (form_name)
+ << '.' << std::endl;
+ return NULL;
+ }
+
+ if (!ver->form_allowed (attribute->name (), form_name))
+ {
+ complain (where, attribute, form, indirect, "invalid");
+ return NULL;
+ }
+ else if (attribute->name () == DW_AT_sibling
+ && sibling_form_suitable (ver, form_name) == sfs_long)
+ complain (where, attribute, form, indirect, "unsuitable");
+
+ return form;
+}
+
check_debug_abbrev::~check_debug_abbrev ()
{
// xxx So using new[]/delete[] would be nicer (delete ignores
@@ -525,18 +504,3 @@ check_debug_abbrev::~check_debug_abbrev ()
free (it->second.abbr);
}
}
-
-bool
-is_location_attrib (uint64_t name)
-{
- switch (name)
- {
- case DW_AT_location:
- case DW_AT_frame_base:
- case DW_AT_data_location:
- case DW_AT_data_member_location:
- return true;
- default:
- return false;
- }
-}
diff --git a/dwarflint/check_debug_abbrev.hh b/dwarflint/check_debug_abbrev.hh
index f905bd24..bdc7f8c6 100644
--- a/dwarflint/check_debug_abbrev.hh
+++ b/dwarflint/check_debug_abbrev.hh
@@ -29,6 +29,7 @@
#include "checks.hh"
#include "sections.ii"
#include "check_debug_info.ii"
+#include "dwarf_version.ii"
struct abbrev_attrib
{
@@ -83,11 +84,13 @@ public:
abbrev_map const abbrevs;
check_debug_abbrev (checkstack &stack, dwarflint &lint);
+ static form const *check_form (dwarf_version const *ver,
+ int form_name,
+ attribute const *attribute,
+ where const *where,
+ bool indirect);
+
~check_debug_abbrev ();
};
-// xxx When dwarf version objects are properly implemented, that's
-// where this should end up in.
-bool is_location_attrib (uint64_t name);
-
#endif//DWARFLINT_CHECK_DEBUG_ABBREV_HH
diff --git a/dwarflint/check_debug_info.cc b/dwarflint/check_debug_info.cc
index 87b81c88..91296bf6 100644
--- a/dwarflint/check_debug_info.cc
+++ b/dwarflint/check_debug_info.cc
@@ -33,7 +33,7 @@
#include "../libdw/dwarf.h"
#include "messages.hh"
-#include "tables.hh"
+#include "dwarf_version.hh"
#include "pri.hh"
#include "option.hh"
#include "sections.hh"
@@ -298,16 +298,16 @@ namespace
}
section_id
- reloc_target (uint8_t form, struct abbrev_attrib *at)
+ reloc_target (form const *form, attribute const *attribute)
{
- switch (form)
+ switch (form->name ())
{
case DW_FORM_strp:
return sec_str;
case DW_FORM_addr:
- switch (at->name)
+ switch (attribute->name ())
{
case DW_AT_low_pc:
case DW_AT_high_pc:
@@ -335,7 +335,7 @@ namespace
case DW_FORM_data4:
case DW_FORM_data8:
- switch (at->name)
+ switch (attribute->name ())
{
case DW_AT_stmt_list:
return sec_line;
@@ -381,8 +381,8 @@ namespace
assert (!"Should be handled specially!");
};
- std::cout << "XXX don't know how to handle form=" << pri::form (form)
- << ", at=" << pri::attr (at->name) << std::endl;
+ std::cout << "XXX don't know how to handle form=" << *form
+ << ", at=" << *attribute << std::endl;
return rel_value;
}
@@ -622,39 +622,26 @@ namespace
{
where.ref = &it->where;
- uint8_t form = it->form;
- bool indirect = form == DW_FORM_indirect;
- if (indirect)
+ attribute const *attribute = ver->get_attribute (it->name);
+ int form_name = it->form;
+ form const *form = ver->get_form (form_name);
+ if (ver->form_class (form, attribute) == cl_indirect)
{
uint64_t value;
- if (!checked_read_uleb128 (ctx, &value, &where,
- "indirect attribute form"))
+ if (!read_sc_value (&value, form->width (cu), ctx, &where))
return -1;
+ form_name = value;
+ form = check_debug_abbrev::check_form
+ (ver, form_name, attribute, &where, true);
+ if (form == NULL)
+ return -1;
+ }
- if (!ver->form_allowed (form))
- {
- wr_error (where)
- << "invalid indirect form " << pri::hex (value)
- << '.' << std::endl;
- return -1;
- }
- form = value;
-
- if (it->name == DW_AT_sibling)
- switch (ver->check_sibling_form (form))
- {
- case -1:
- wr_message (where, cat (mc_die_rel, mc_impact_2))
- << "DW_AT_sibling attribute with (indirect) form "
- "DW_FORM_ref_addr." << std::endl;
- break;
-
- case -2:
- wr_error (where)
- << "DW_AT_sibling attribute with non-reference "
- "(indirect) form \"" << pri::form (value)
- << "\"." << std::endl;
- };
+ dw_class cls = ver->form_class (form, attribute);
+ if (cls == cl_indirect)
+ {
+ wr_error (&where, ": indirect form is again indirect.\n");
+ return -1;
}
value_check_cb_t value_check_cb = NULL;
@@ -666,9 +653,6 @@ namespace
uint64_t ctx_offset = read_ctx_get_offset (ctx) + cu->head->offset;
bool type_is_rel = file.ehdr.e_type == ET_REL;
- /* Attribute value. */
- uint64_t value = 0;
-
/* Whether the value should be relocated first. Note that
relocations are really required only in REL files, so
missing relocations are not warned on even with
@@ -679,7 +663,6 @@ namespace
rel_require, // require a relocation
rel_nonzero, // require a relocation if value != 0
} relocate = rel_no;
- size_t width = 0;
/* Point to variable that you want to copy relocated value
to. */
@@ -693,259 +676,129 @@ namespace
relocation was made against. */
GElf_Sym **symbolp = NULL;
- /* Setup locptr checking. */
- if (is_location_attrib (it->name))
+ assert (form);
+ assert (attribute);
+
+ static dw_class_set ref_classes
+ (cl_reference, cl_loclistptr, cl_lineptr, cl_macptr,
+ cl_rangelistptr);
+
+ if (ref_classes.test (cls))
+ if (form->width (cu) == fw_8
+ && cu->head->offset_size == 4)
+ wr_error (where)
+ << "reference attribute with form \""
+ << pri::form (form_name) << "\" in 32-bit CU."
+ << std::endl;
+
+ /* Setup pointer checking. */
+ switch (cls)
{
- switch (form)
- {
- case DW_FORM_data8:
- if (cu->head->offset_size == 4)
- wr_error (where)
- << "location attribute with form \""
- << pri::form (form) << "\" in 32-bit CU." << std::endl;
- /* fall-through */
-
- case DW_FORM_data4:
- case DW_FORM_sec_offset:
- value_check_cb = check_locptr;
- extra_mc = mc_loc;
- check_someptr = true;
- break;
-
- case DW_FORM_block1:
- case DW_FORM_block2:
- case DW_FORM_block4:
- case DW_FORM_block:
- break;
-
- default:
- /* Only print error if it's indirect. Otherwise we
- gave diagnostic during abbrev loading. */
- if (indirect)
- wr_error (where)
- << "location attribute with invalid (indirect) form \""
- << pri::form (form) << "\"." << std::endl;
- };
+ case cl_loclistptr:
+ check_someptr = true;
+ value_check_cb = check_locptr;
+ extra_mc = mc_loc;
+ break;
+
+ case cl_rangelistptr:
+ check_someptr = true;
+ value_check_cb = check_rangeptr;
+ extra_mc = mc_ranges;
+ break;
+
+ case cl_lineptr:
+ check_someptr = true;
+ value_check_cb = check_lineptr;
+ extra_mc = mc_line;
+ break;
+
+ default:
+ ;
+ };
+
+ /* Setup low_pc / high_pc checking. */
+ switch (it->name)
+ {
+ case DW_AT_low_pc:
+ relocatedp = &low_pc_relocated;
+ symbolp = &low_pc_symbol;
+ valuep = &low_pc;
+ break;
+
+ case DW_AT_high_pc:
+ relocatedp = &high_pc_relocated;
+ symbolp = &high_pc_symbol;
+ valuep = &high_pc;
+ break;
+
+ case DW_AT_decl_file:
+ value_check_cb = check_decl_file;
+ break;
}
- /* Setup rangeptr or lineptr checking. */
- else
- switch (it->name)
- {
- case DW_AT_ranges:
- case DW_AT_stmt_list:
- {
- switch (form)
- {
- case DW_FORM_data8:
- if (cu->head->offset_size == 4)
- // xxx could now also be checked during abbrev loading
- wr_error (where)
- << pri::attr (it->name)
- << " with form DW_FORM_data8 in 32-bit CU."
- << std::endl;
- /* fall-through */
-
- case DW_FORM_data4:
- case DW_FORM_sec_offset:
- check_someptr = true;
- if (it->name == DW_AT_ranges)
- {
- value_check_cb = check_rangeptr;
- extra_mc = mc_ranges;
- }
- else
- {
- assert (it->name == DW_AT_stmt_list);
- value_check_cb = check_lineptr;
- extra_mc = mc_line;
- }
- break;
-
- default:
- /* Only print error if it's indirect. Otherwise we
- gave diagnostic during abbrev loading. */
- if (indirect)
- wr_error (where)
- << pri::attr (it->name)
- << " with invalid (indirect) form \""
- << pri::form (form) << "\"." << std::endl;
- }
- break;
-
- case DW_AT_low_pc:
- relocatedp = &low_pc_relocated;
- symbolp = &low_pc_symbol;
- valuep = &low_pc;
- break;
-
- case DW_AT_high_pc:
- relocatedp = &high_pc_relocated;
- symbolp = &high_pc_symbol;
- valuep = &high_pc;
- break;
-
- case DW_AT_decl_file:
- value_check_cb = check_decl_file;
- break;
- }
- }
- /* Load attribute value and setup per-form checking. */
- switch (form)
+ /* Setup per-form checking & relocation. */
+ switch (form_name)
{
case DW_FORM_strp:
value_check_cb = check_strp;
case DW_FORM_sec_offset:
- if (!read_ctx_read_offset (ctx, cu->head->offset_size == 8,
- &value))
- {
- cant_read:
- wr_error (where)
- << "can't read value of attribute "
- << pri::attr (it->name) << '.' << std::endl;
- return -1;
- }
-
relocate = rel_require;
- width = cu->head->offset_size;
- break;
-
- case DW_FORM_string:
- if (!read_ctx_read_str (ctx))
- goto cant_read;
break;
case DW_FORM_ref_addr:
value_check_cb = check_die_ref_global;
- width = cu->head->offset_size;
-
- if (cu->head->version == 2)
- case DW_FORM_addr:
- width = cu->head->address_size;
-
- if (!read_ctx_read_offset (ctx, width == 8, &value))
- goto cant_read;
-
+ case DW_FORM_addr:
/* In non-rel files, neither addr, nor ref_addr /need/
a relocation. */
relocate = rel_nonzero;
break;
case DW_FORM_ref_udata:
- value_check_cb = check_die_ref_local;
- case DW_FORM_udata:
- if (!checked_read_uleb128 (ctx, &value, &where,
- "attribute value"))
- return -1;
- break;
-
- case DW_FORM_flag_present:
- value = 1;
- break;
-
case DW_FORM_ref1:
- value_check_cb = check_die_ref_local;
- case DW_FORM_flag:
- case DW_FORM_data1:
- if (!read_ctx_read_var (ctx, 1, &value))
- goto cant_read;
- break;
-
case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref8:
value_check_cb = check_die_ref_local;
- case DW_FORM_data2:
- if (!read_ctx_read_var (ctx, 2, &value))
- goto cant_read;
break;
case DW_FORM_data4:
- if (check_someptr)
- {
- relocate = rel_require;
- width = 4;
- }
- if (false)
- case DW_FORM_ref4:
- value_check_cb = check_die_ref_local;
- if (!read_ctx_read_var (ctx, 4, &value))
- goto cant_read;
- break;
-
case DW_FORM_data8:
if (check_someptr)
- {
- relocate = rel_require;
- width = 8;
- }
- if (false)
- case DW_FORM_ref8:
- value_check_cb = check_die_ref_local;
- if (!read_ctx_read_8ubyte (ctx, &value))
- goto cant_read;
+ relocate = rel_require;
break;
+ }
- case DW_FORM_sdata:
- {
- int64_t value64;
- if (!checked_read_sleb128 (ctx, &value64, &where,
- "attribute value"))
- return -1;
- value = (uint64_t) value64;
- break;
- }
-
- case DW_FORM_block:
- {
- uint64_t length;
-
- if (false)
- case DW_FORM_block1:
- width = 1;
-
- if (false)
- case DW_FORM_block2:
- width = 2;
-
- if (false)
- case DW_FORM_block4:
- width = 4;
-
- if (width == 0)
- {
- if (!checked_read_uleb128 (ctx, &length, &where,
- "attribute value"))
- return -1;
- }
- else if (!read_ctx_read_var (ctx, width, &length))
- goto cant_read;
-
- if (is_location_attrib (it->name))
- {
- uint64_t expr_start
- = cu->head->offset + read_ctx_get_offset (ctx);
- if (!check_location_expression (file, ctx, cu, expr_start,
- reloc, length, &where))
- return -1;
- }
- else
- /* xxx really skip_mismatched? We just don't know
- how to process these... */
- relocation_skip (reloc,
- read_ctx_get_offset (ctx) + length,
- &where, skip_mismatched);
-
- if (!read_ctx_skip (ctx, length))
- goto cant_read;
- break;
- }
-
- case DW_FORM_indirect:
- wr_error (&where, ": indirect form is again indirect.\n");
- return -1;
+ /* Attribute value. */
+ uint64_t value;
+ read_ctx block;
- default:
- wr_error (&where,
- ": internal error: unhandled form 0x%x.\n", form);
+ storage_class_t storclass = form->storage_class ();
+ if (!read_generic_value (ctx, form->width (cu), storclass,
+ &where, &value, &block))
+ {
+ // Note that for fw_uleb and fw_sleb we report the
+ // error the second time now.
+ wr_error (where)
+ << "can't read value of attribute "
+ << *attribute << '.' << std::endl;
+ return -1;
+ }
+ if (storclass == sc_block)
+ {
+ if (cls == cl_exprloc)
+ {
+ uint64_t expr_start
+ = cu->head->offset + read_ctx_get_offset (ctx) - value;
+ // xxx should we disallow relocation of length
+ // field? See check_debug_loc_range::op_read_form
+ if (!check_location_expression
+ (ver, file, &block, cu,
+ expr_start, reloc, value, &where))
+ return -1;
+ }
+ else
+ relocation_skip (reloc, read_ctx_get_offset (ctx),
+ &where, skip_mismatched);
}
/* Relocate the value if appropriate. */
@@ -956,11 +809,12 @@ namespace
if (relocate == rel_no)
wr_message (where, cat (mc_impact_4, mc_die_other,
mc_reloc, extra_mc))
- << "unexpected relocation of " << pri::form (form) << '.'
- << std::endl;
+ << "unexpected relocation of " << pri::form (form_name)
+ << '.' << std::endl;
+ form_width_t width = form->width (cu);
relocate_one (&file, reloc, rel, width, &value, &where,
- reloc_target (form, it), symbolp);
+ reloc_target (form, attribute), symbolp);
if (relocatedp != NULL)
*relocatedp = true;
@@ -975,7 +829,8 @@ namespace
&& value != 0)))
wr_message (where, cat (mc_impact_2, mc_die_other,
mc_reloc, extra_mc))
- << pri::lacks_relocation (pri::form (form)) << std::endl;
+ << pri::lacks_relocation (pri::form (form_name))
+ << std::endl;
}
/* Dispatch value checking. */
diff --git a/dwarflint/check_debug_info.ii b/dwarflint/check_debug_info.ii
index 70c4cbae..ea388e39 100644
--- a/dwarflint/check_debug_info.ii
+++ b/dwarflint/check_debug_info.ii
@@ -1,3 +1,5 @@
+struct cu_head;
+struct cu;
class read_cu_headers;
class check_debug_info;
class check_debug_info_refs;
diff --git a/dwarflint/check_debug_loc_range.cc b/dwarflint/check_debug_loc_range.cc
index 7bbca1d6..24ddc8c9 100644
--- a/dwarflint/check_debug_loc_range.cc
+++ b/dwarflint/check_debug_loc_range.cc
@@ -381,7 +381,8 @@ namespace
}
bool
- check_loc_or_range_ref (struct elf_file *file,
+ check_loc_or_range_ref (dwarf_version const *ver,
+ struct elf_file *file,
const struct read_ctx *parent_ctx,
struct cu *cu,
struct sec *sec,
@@ -551,8 +552,8 @@ namespace
/* location expression itself */
uint64_t expr_start = read_ctx_get_offset (&ctx);
- if (!check_location_expression (*file, &ctx, cu, expr_start,
- &sec->rel, len, &where))
+ if (!check_location_expression
+ (ver, *file, &ctx, cu, expr_start, &sec->rel, len, &where))
return false;
uint64_t expr_end = read_ctx_get_offset (&ctx);
if (!overlap
@@ -629,11 +630,11 @@ namespace
enum message_category cat = sec->id == sec_loc ? mc_loc : mc_ranges;
+ {
/* Relocation checking in the followings assumes that all the
references are organized in monotonously increasing order. That
doesn't have to be the case. So merge all the references into
one sorted array. */
- {
typedef std::vector<ref_cu> ref_cu_vect;
ref_cu_vect refs;
for (struct cu *cu = cu_chain; cu != NULL; cu = cu->next)
@@ -661,10 +662,18 @@ namespace
relocation_skip (&sec->rel, off, &wh, skip_unref);
}
+ // xxx right now this is just so that we can ver->get_form
+ // down the road, which is just a result of the way
+ // dwarf-opcodes encode operator operand types. But in the
+ // future, we'd like versions to support also queries for
+ // operators and their operands, so keep it.
+ dwarf_version const *ver
+ = dwarf_version::get (it->cu->head->version);
+
/* XXX We pass cu_coverage down for all ranges. That means all
ranges get recorded, not only those belonging to CUs.
Perhaps that's undesirable. */
- if (!check_loc_or_range_ref (file, &ctx, it->cu, sec,
+ if (!check_loc_or_range_ref (ver, file, &ctx, it->cu, sec,
&coverage, coverage_map, pc_coverage,
off, &it->ref.who, cat))
retval = false;
@@ -742,12 +751,16 @@ namespace
*/
bool
- get_location_opcode_operands (uint8_t opcode, uint8_t *op1, uint8_t *op2)
+ get_location_opcode_operands (dwarf_version const *ver,
+ uint8_t opcode,
+ form const **f1p,
+ form const **f2p)
{
+ int op1, op2;
switch (opcode)
{
#define DW_OP_2(OPCODE, OP1, OP2) \
- case OPCODE: *op1 = OP1; *op2 = OP2; return true;
+ case OPCODE: op1 = OP1; op2 = OP2; break;
#define DW_OP_1(OPCODE, OP1) DW_OP_2(OPCODE, OP1, 0)
#define DW_OP_0(OPCODE) DW_OP_2(OPCODE, 0, 0)
@@ -759,92 +772,22 @@ namespace
default:
return false;
};
- }
-
- /* The value passed back in uint64_t VALUEP may actually be
- type-casted signed quantity. WHAT and WHERE describe error
- message and context for LEB128 loading.
-
- If IS_BLOCKP is non-NULL, block values are accepted, and
- *IS_BLOCKP is initialized depending on whether FORM is a block
- form. For block forms, the value passed back in VALUEP is block
- length. */
- bool
- read_ctx_read_form (struct read_ctx *ctx, struct cu *cu,
- uint8_t form, uint64_t *valuep, struct where *where,
- const char *what, bool *is_blockp)
- {
- if (is_blockp != NULL)
- *is_blockp = false;
- switch (form)
- {
- case DW_FORM_addr:
- return read_ctx_read_offset (ctx, cu->head->address_size == 8, valuep);
- case DW_FORM_ref_addr:
- return read_ctx_read_offset (ctx, (cu->head->version >= 3
- ? cu->head->offset_size
- : cu->head->address_size) == 8,
- valuep);
- case DW_FORM_udata:
- return checked_read_uleb128 (ctx, valuep, where, what);
- case DW_FORM_sdata:
- return checked_read_sleb128 (ctx, (int64_t *)valuep, where, what);
- case DW_FORM_data1:
- {
- uint8_t v;
- if (!read_ctx_read_ubyte (ctx, &v))
- return false;
- if (valuep != NULL)
- *valuep = v;
- return true;
- }
- case DW_FORM_data2:
- {
- uint16_t v;
- if (!read_ctx_read_2ubyte (ctx, &v))
- return false;
- if (valuep != NULL)
- *valuep = v;
- return true;
- }
- case DW_FORM_data4:
- {
- uint32_t v;
- if (!read_ctx_read_4ubyte (ctx, &v))
- return false;
- if (valuep != NULL)
- *valuep = v;
- return true;
- }
- case DW_FORM_data8:
- return read_ctx_read_8ubyte (ctx, valuep);
- };
- if (is_blockp != NULL)
- {
- int dform;
- switch (form)
- {
-#define HANDLE(BFORM, DFORM) \
- case BFORM: \
- dform = DFORM; \
- break
- HANDLE (DW_FORM_block, DW_FORM_udata);
- HANDLE (DW_FORM_block1, DW_FORM_data1);
- HANDLE (DW_FORM_block2, DW_FORM_data2);
- HANDLE (DW_FORM_block4, DW_FORM_data4);
-#undef HANDLE
- default:
- return false;
- }
-
- *is_blockp = true;
- return read_ctx_read_form (ctx, cu, dform,
- valuep, where, what, NULL)
- && read_ctx_skip (ctx, *valuep);
- }
-
- return false;
+#define RETV(OP,P) \
+ if (OP != 0) \
+ { \
+ form const *f = NULL; \
+ f = ver->get_form (OP); \
+ if (f == NULL) \
+ return false; \
+ *P = f; \
+ } \
+ else \
+ *P = NULL;
+
+ RETV (op1, f1p);
+ RETV (op2, f2p);
+ return true;
}
static enum section_id
@@ -876,24 +819,25 @@ namespace
uint64_t init_off,
struct relocation_data *reloc,
int opcode,
- int form,
+ form const *form,
uint64_t *valuep,
char const *str,
struct where *where)
{
- if (form == 0)
+ if (form == NULL)
return true;
- bool isblock;
uint64_t off = read_ctx_get_offset (ctx) + init_off;
- if (!read_ctx_read_form (ctx, cu, form,
- valuep, where, str, &isblock))
+ storage_class_t storclass = form->storage_class ();
+ assert (storclass != sc_string);
+ if (!read_generic_value (ctx, form->width (cu), storclass,
+ where, valuep, NULL))
{
wr_error (*where)
<< "opcode \"" << pri::locexpr_opcode (opcode)
<< "\": can't read " << str << " (form \""
- << pri::form (form) << "\")." << std::endl;
+ << *form << "\")." << std::endl;
return false;
}
@@ -905,14 +849,14 @@ namespace
if ((rel = relocation_next (reloc, off,
where, skip_mismatched)))
{
- if (!isblock)
+ if (storclass != sc_block)
relocate_one (&file, reloc, rel,
cu->head->address_size, valuep, where,
reloc_target_loc (opcode), NULL);
else
wr_error (where, ": relocation relocates a length field.\n");
}
- if (isblock)
+ 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);
@@ -923,7 +867,8 @@ namespace
}
bool
-check_location_expression (elf_file const &file,
+check_location_expression (dwarf_version const *ver,
+ elf_file const &file,
struct read_ctx *parent_ctx,
struct cu *cu,
uint64_t init_off,
@@ -959,8 +904,9 @@ check_location_expression (elf_file const &file,
break;
}
- uint8_t op1, op2;
- if (!get_location_opcode_operands (opcode, &op1, &op2))
+ form const *form1 = NULL;
+ form const *form2 = NULL;
+ if (!get_location_opcode_operands (ver, opcode, &form1, &form2))
{
wr_error (where)
<< "can't decode opcode \""
@@ -970,9 +916,9 @@ check_location_expression (elf_file const &file,
uint64_t value1, value2;
if (!op_read_form (file, &ctx, cu, init_off, reloc,
- opcode, op1, &value1, "1st operand", &where)
+ opcode, form1, &value1, "1st operand", &where)
|| !op_read_form (file, &ctx, cu, init_off, reloc,
- opcode, op2, &value2, "2st operand", &where))
+ opcode, form2, &value2, "2st operand", &where))
goto out;
switch (opcode)
diff --git a/dwarflint/check_debug_loc_range.hh b/dwarflint/check_debug_loc_range.hh
index 4f5ac452..21319692 100644
--- a/dwarflint/check_debug_loc_range.hh
+++ b/dwarflint/check_debug_loc_range.hh
@@ -28,6 +28,7 @@
#include "check_debug_info.ii"
#include "messages.hh"
#include "coverage.hh"
+#include "dwarf_version.ii"
struct section_coverage
{
@@ -85,7 +86,8 @@ struct hole_info
DATA->data has to point at d_buf of section in question. */
bool found_hole (uint64_t start, uint64_t length, void *data);
-bool check_location_expression (elf_file const &file,
+bool check_location_expression (dwarf_version const *ver,
+ elf_file const &file,
struct read_ctx *parent_ctx,
struct cu *cu,
uint64_t init_off,
diff --git a/dwarflint/checked_read.cc b/dwarflint/checked_read.cc
index ced62bea..c6a71445 100644
--- a/dwarflint/checked_read.cc
+++ b/dwarflint/checked_read.cc
@@ -31,8 +31,11 @@
#endif
#include <dwarf.h>
+#include <cassert>
+
#include "checked_read.hh"
#include "messages.hh"
+#include "misc.hh"
bool
read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep,
@@ -96,8 +99,8 @@ read_address_size (struct read_ctx *ctx,
}
bool
-checked_read_uleb128 (struct read_ctx *ctx, uint64_t *ret,
- struct where *where, const char *what)
+checked_read_uleb128 (read_ctx *ctx, uint64_t *ret,
+ where const *where, const char *what)
{
const unsigned char *ptr = ctx->ptr;
int st = read_ctx_read_uleb128 (ctx, ret);
@@ -113,8 +116,8 @@ checked_read_uleb128 (struct read_ctx *ctx, uint64_t *ret,
}
bool
-checked_read_sleb128 (struct read_ctx *ctx, int64_t *ret,
- struct where *where, const char *what)
+checked_read_sleb128 (read_ctx *ctx, int64_t *ret,
+ where const *where, const char *what)
{
const unsigned char *ptr = ctx->ptr;
int st = read_ctx_read_sleb128 (ctx, ret);
@@ -129,3 +132,85 @@ checked_read_sleb128 (struct read_ctx *ctx, int64_t *ret,
}
return st >= 0;
}
+
+bool
+checked_read_leb128 (read_ctx *ctx, form_width_t width, uint64_t *ret,
+ where const *where, 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))
+ return false;
+ *ret = (uint64_t) svalue;
+ return true;
+ }
+ else
+ return checked_read_uleb128 (ctx, ret, where, what);
+}
+
+bool
+read_sc_value (uint64_t *valuep, form_width_t width,
+ read_ctx *ctx, where const *where)
+{
+ switch (width)
+ {
+ case fw_0:
+ *valuep = 1;
+ return true;
+
+ case fw_1:
+ case fw_2:
+ case fw_4:
+ case fw_8:
+ return read_ctx_read_var (ctx, width, valuep);
+
+ case fw_uleb:
+ case fw_sleb:
+ return checked_read_leb128 (ctx, width, valuep,
+ where, "attribute value");
+
+ case fw_unknown:
+ ;
+ }
+ UNREACHABLE;
+}
+
+bool
+read_generic_value (read_ctx *ctx,
+ form_width_t width, storage_class_t storclass,
+ where const *where, uint64_t *valuep, read_ctx *blockp)
+{
+ uint64_t value;
+ if (storclass == sc_value
+ || storclass == sc_block)
+ {
+ if (!read_sc_value (&value, width, ctx, where))
+ return false;
+ if (valuep != NULL)
+ *valuep = value;
+ if (storclass == sc_value)
+ return true;
+ }
+
+ unsigned char const *start = ctx->ptr;
+ if (storclass == sc_string)
+ {
+ if (!read_ctx_read_str (ctx))
+ return false;
+ }
+ else if (storclass == sc_block)
+ {
+ if (!read_ctx_skip (ctx, value))
+ return false;
+ }
+
+ if (blockp != NULL)
+ {
+ if (!read_ctx_init_sub (blockp, ctx, start, ctx->ptr))
+ return false;
+ }
+
+ return true;
+}
diff --git a/dwarflint/checked_read.hh b/dwarflint/checked_read.hh
index caeba92d..0843aaf1 100644
--- a/dwarflint/checked_read.hh
+++ b/dwarflint/checked_read.hh
@@ -27,28 +27,38 @@
#define DWARFLINT_CHECKED_READ_HH
#include "readctx.h"
+#include "where.h"
+#include "dwarf_version.hh"
-#ifdef __cplusplus
-extern "C"
-{
-#endif
+bool read_size_extra (read_ctx *ctx, uint32_t size32, uint64_t *sizep,
+ int *offset_sizep, where *where);
-bool read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep,
- int *offset_sizep, struct where *where);
-
-bool read_address_size (struct read_ctx *ctx,
+bool read_address_size (read_ctx *ctx,
bool addr_64,
int *address_sizep,
- struct where const *where);
+ where const *where);
+
+bool checked_read_uleb128 (read_ctx *ctx, uint64_t *ret,
+ where const *where, const char *what);
+
+bool checked_read_sleb128 (read_ctx *ctx, int64_t *ret,
+ where const *where, const char *what);
-bool checked_read_uleb128 (struct read_ctx *ctx, uint64_t *ret,
- struct where *where, const char *what);
+bool checked_read_leb128 (read_ctx *ctx, form_width_t width, uint64_t *ret,
+ where const *where, const char *what);
-bool checked_read_sleb128 (struct read_ctx *ctx, int64_t *ret,
- struct where *where, 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);
-#ifdef __cplusplus
-}
-#endif
+/// Read value depending on the form width and storage class.
+/// Value is returned via VALUEP, if that is non-NULL; for block
+/// forms, the value is block length. Block context is returned via
+/// BLOCKP, in non-NULL; for string class, the block is the string
+/// itself.
+bool read_generic_value (read_ctx *ctx,
+ form_width_t width, storage_class_t storclass,
+ where const *where, uint64_t *valuep,
+ read_ctx *blockp);
#endif//DWARFLINT_CHECKED_READ_HH
diff --git a/dwarflint/dwarf_2.cc b/dwarflint/dwarf_2.cc
new file mode 100644
index 00000000..69c45953
--- /dev/null
+++ b/dwarflint/dwarf_2.cc
@@ -0,0 +1,177 @@
+/* Pedantic checking of DWARF files
+ Copyright (C) 2010 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 "dwarf_version-imp.hh"
+#include "dwarf_2.hh"
+#include "../libdw/dwarf.h"
+
+namespace
+{
+ typedef preset_attribute<cl_reference, cl_constant> const_or_ref_attribute;
+
+ struct dwarf_2_attributes
+ : public attribute_table
+ {
+ dwarf_2_attributes ()
+ {
+ // Note about location descriptions in DWARF 2 (and 3). In
+ // DWARF 2, location expressions can have classes of cl_constant
+ // or cl_block. But we need to tell those block expressions
+ // from any old block attribute to validate the expression, and
+ // those constants from any old number to validate the
+ // reference. So we retrofit all the DW_FORM_block* forms and
+ // appropriate attributes with cl_exprloc form DWARF 4 and
+ // cl_loclistptr (even though in DWARF 4 it's actually only
+ // DW_FORM_exprloc that has this class).
+ //
+ // Similarly with cl_lineptr and cl_macptr. cl_rangelistptr
+ // wasn't introduced until DWARF 3.
+
+ add (ref_attribute (DW_AT_sibling));
+ add (location_attribute (DW_AT_location));
+ add (string_attribute (DW_AT_name));
+ add (const_attribute (DW_AT_ordering));
+ add (const_attribute (DW_AT_byte_size));
+ add (const_attribute (DW_AT_bit_offset));
+ add (const_attribute (DW_AT_bit_size));
+ add (attribute (DW_AT_stmt_list, cl_lineptr));
+ add (addr_attribute (DW_AT_low_pc));
+ add (addr_attribute (DW_AT_high_pc));
+ add (const_attribute (DW_AT_language));
+ add (ref_attribute (DW_AT_discr));
+ add (const_attribute (DW_AT_discr_value));
+ add (const_attribute (DW_AT_visibility));
+ add (ref_attribute (DW_AT_import));
+ add (location_attribute (DW_AT_string_length));
+ add (ref_attribute (DW_AT_common_reference));
+ add (string_attribute (DW_AT_comp_dir));
+ add (attribute (DW_AT_const_value,
+ dw_class_set (cl_string, cl_constant, cl_block)));
+ add (ref_attribute (DW_AT_containing_type));
+ add (ref_attribute (DW_AT_default_value));
+ add (const_attribute (DW_AT_inline));
+ add (flag_attribute (DW_AT_is_optional));
+ add (const_or_ref_attribute (DW_AT_lower_bound));
+ add (string_attribute (DW_AT_producer));
+ add (flag_attribute (DW_AT_prototyped));
+ add (location_attribute (DW_AT_return_addr));
+ add (const_attribute (DW_AT_start_scope));
+ add (const_attribute (DW_AT_bit_stride));
+ add (const_or_ref_attribute (DW_AT_upper_bound));
+ add (ref_attribute (DW_AT_abstract_origin));
+ add (const_attribute (DW_AT_accessibility));
+ add (const_attribute (DW_AT_address_class));
+ add (flag_attribute (DW_AT_artificial));
+ add (ref_attribute (DW_AT_base_types));
+ add (const_attribute (DW_AT_calling_convention));
+ add (const_or_ref_attribute (DW_AT_count));
+ add (static_location_attribute (DW_AT_data_member_location));
+ add (const_attribute (DW_AT_decl_column));
+ add (const_attribute (DW_AT_decl_file));
+ add (const_attribute (DW_AT_decl_line));
+ add (flag_attribute (DW_AT_declaration));
+ add (block_attribute (DW_AT_discr_list));
+ add (const_attribute (DW_AT_encoding));
+ add (flag_attribute (DW_AT_external));
+ add (location_attribute (DW_AT_frame_base));
+ add (ref_attribute (DW_AT_friend));
+ add (const_attribute (DW_AT_identifier_case));
+ add (attribute (DW_AT_macro_info, cl_macptr));
+ add (block_attribute (DW_AT_namelist_item));
+ add (ref_attribute (DW_AT_priority));
+ add (location_attribute (DW_AT_segment));
+ add (ref_attribute (DW_AT_specification));
+ add (location_attribute (DW_AT_static_link));
+ add (ref_attribute (DW_AT_type));
+ add (location_attribute (DW_AT_use_location));
+ add (flag_attribute (DW_AT_variable_parameter));
+ add (const_attribute (DW_AT_virtuality));
+ add (static_location_attribute (DW_AT_vtable_elem_location));
+ }
+ };
+
+ struct exprloc_form
+ : public preset_form<sc_block, cl_exprloc, cl_block>
+ {
+ exprloc_form (int a_name, form_width_t a_width)
+ : preset_form<sc_block, cl_exprloc, cl_block> (a_name, a_width)
+ {}
+ };
+
+ typedef preset_form<sc_value,
+ cl_constant, cl_lineptr, cl_loclistptr,
+ cl_macptr> dw2_data_form;
+
+ struct dwarf_2_forms
+ : public form_table
+ {
+ dwarf_2_forms ()
+ {
+ add (exprloc_form (DW_FORM_block, fw_uleb));
+ add (exprloc_form (DW_FORM_block1, fw_1));
+ add (exprloc_form (DW_FORM_block2, fw_2));
+ add (exprloc_form (DW_FORM_block4, fw_4));
+
+ // These constant forms can in theory, in legal DWARF 2,
+ // represent various pointers.
+ add (dw2_data_form (DW_FORM_data1, fw_1));
+ add (dw2_data_form (DW_FORM_data2, fw_2));
+ add (dw2_data_form (DW_FORM_data4, fw_4));
+ add (dw2_data_form (DW_FORM_data8, fw_8));
+ add (dw2_data_form (DW_FORM_sdata, fw_sleb));
+ add (dw2_data_form (DW_FORM_udata, fw_uleb));
+
+ add (flag_form (DW_FORM_flag, fw_1));
+
+ add (ref_form (DW_FORM_ref1, fw_1));
+ add (ref_form (DW_FORM_ref2, fw_2));
+ add (ref_form (DW_FORM_ref4, fw_4));
+ add (ref_form (DW_FORM_ref8, fw_8));
+ add (ref_form (DW_FORM_ref_udata, fw_uleb));
+
+ add (string_form (DW_FORM_string));
+ add (offset_form (DW_FORM_strp, cl_string));
+ add (address_form (DW_FORM_addr, cl_address));
+ add (address_form (DW_FORM_ref_addr, cl_reference));
+
+ add (form (DW_FORM_indirect, cl_indirect, fw_uleb, sc_value));
+ }
+ };
+
+ struct dwarf_2_t
+ : public std_dwarf
+ {
+ dwarf_2_t ()
+ : std_dwarf (dwarf_2_attributes (), dwarf_2_forms ())
+ {}
+ };
+}
+
+dwarf_version const *
+dwarf_2 ()
+{
+ static dwarf_2_t dw;
+ return &dw;
+}
diff --git a/dwarflint/dwarf_2.hh b/dwarflint/dwarf_2.hh
new file mode 100644
index 00000000..ec524960
--- /dev/null
+++ b/dwarflint/dwarf_2.hh
@@ -0,0 +1,33 @@
+/* Pedantic checking of DWARF files
+ Copyright (C) 2010 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_DWARF_2_HH
+#define DWARFLINT_DWARF_2_HH
+
+#include "dwarf_version.ii"
+
+dwarf_version const *dwarf_2 ();
+
+#endif//DWARFLINT_DWARF_2_HH
diff --git a/dwarflint/dwarf_3.cc b/dwarflint/dwarf_3.cc
new file mode 100644
index 00000000..cf2b753a
--- /dev/null
+++ b/dwarflint/dwarf_3.cc
@@ -0,0 +1,150 @@
+/* Pedantic checking of DWARF files
+ Copyright (C) 2010 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 "dwarf_version-imp.hh"
+#include "dwarf_2.hh"
+#include "dwarf_3.hh"
+#include "../libdw/dwarf.h"
+#include <cassert>
+
+namespace
+{
+ struct dwarf_3_attributes
+ : public attribute_table
+ {
+ dwarf_3_attributes ()
+ {
+ add (location_attribute (DW_AT_location));
+ add (dynval_attribute (DW_AT_byte_size));
+ add (dynval_attribute (DW_AT_bit_offset));
+ add (dynval_attribute (DW_AT_bit_size));
+ add (location_attribute (DW_AT_string_length));
+ add (dynval_attribute (DW_AT_lower_bound));
+ add (location_attribute (DW_AT_return_addr));
+
+ // Note, DWARF 3 claims only a const class for DW_AT_bit_stride,
+ // but from 2.19 it's clear that this is an omission.
+ add (dynval_attribute (DW_AT_bit_stride));
+
+ add (dynval_attribute (DW_AT_upper_bound));
+ add (dynval_attribute (DW_AT_count));
+ add (attribute (DW_AT_data_member_location,
+ dw_class_set (cl_exprloc, cl_constant, cl_loclistptr)));
+ add (location_attribute (DW_AT_frame_base));
+ add (location_attribute (DW_AT_segment));
+ add (location_attribute (DW_AT_static_link));
+ add (location_attribute (DW_AT_use_location));
+ add (location_attribute (DW_AT_vtable_elem_location));
+ add (dynval_attribute (DW_AT_allocated));
+ add (dynval_attribute (DW_AT_associated));
+ add (attribute (DW_AT_data_location, cl_exprloc));
+ add (dynval_attribute (DW_AT_byte_stride));
+ add (addr_attribute (DW_AT_entry_pc));
+ add (flag_attribute (DW_AT_use_UTF8));
+ add (ref_attribute (DW_AT_extension));
+ add (attribute (DW_AT_ranges, cl_rangelistptr));
+ add (attribute (DW_AT_trampoline,
+ dw_class_set (cl_address, cl_flag,
+ cl_reference, cl_string)));
+ add (const_attribute (DW_AT_call_column));
+ add (const_attribute (DW_AT_call_file));
+ add (const_attribute (DW_AT_call_line));
+ add (string_attribute (DW_AT_description));
+ add (const_attribute (DW_AT_binary_scale));
+ add (const_attribute (DW_AT_decimal_scale));
+ add (ref_attribute (DW_AT_small));
+ add (const_attribute (DW_AT_decimal_sign));
+ add (const_attribute (DW_AT_digit_count));
+ add (string_attribute (DW_AT_picture_string));
+ add (flag_attribute (DW_AT_mutable));
+ add (flag_attribute (DW_AT_threads_scaled));
+ add (flag_attribute (DW_AT_explicit));
+ add (ref_attribute (DW_AT_object_pointer));
+ add (const_attribute (DW_AT_endianity));
+ add (flag_attribute (DW_AT_elemental));
+ add (flag_attribute (DW_AT_pure));
+ add (flag_attribute (DW_AT_recursive));
+ }
+ };
+
+ typedef preset_form<sc_value,
+ cl_constant, cl_lineptr, cl_loclistptr,
+ cl_macptr, cl_rangelistptr> dw3_data_form;
+ typedef preset_form<sc_block, cl_block, cl_exprloc> locexpr_form;
+
+ struct dwarf_3_forms
+ : public form_table
+ {
+ dwarf_3_forms ()
+ {
+ add (offset_form (DW_FORM_ref_addr, cl_reference));
+
+ // In DWARF 2 we made all the const forms into various cl_*ptr,
+ // since that's how the standard was worded: it allowed
+ // DW_AT_location to have any constant form. In DWARF 3, only
+ // data4 and data8 are like this. In addition, these two can
+ // also be cl_rangelistptr.
+ add (const_form (DW_FORM_data1, fw_1));
+ add (const_form (DW_FORM_data2, fw_2));
+ add (dw3_data_form (DW_FORM_data4, fw_4));
+ add (dw3_data_form (DW_FORM_data8, fw_8));
+ add (const_form (DW_FORM_sdata, fw_sleb));
+ add (const_form (DW_FORM_udata, fw_uleb));
+ }
+ };
+
+ struct dwarf_3_ext_t
+ : public std_dwarf
+ {
+ dwarf_3_ext_t ()
+ : std_dwarf (dwarf_3_attributes (), dwarf_3_forms ())
+ {}
+
+ dw_class
+ ambiguous_class (__attribute__ ((unused)) form const *form,
+ attribute const *attribute,
+ dw_class_set const &candidates) const
+ {
+ assert (attribute->name () == DW_AT_data_member_location);
+ assert (candidates == dw_class_set (cl_constant, cl_loclistptr));
+ return cl_loclistptr;
+ }
+ };
+}
+
+dwarf_version const *
+dwarf_3_ext ()
+{
+ static dwarf_3_ext_t dw;
+ return &dw;
+}
+
+dwarf_version const *
+dwarf_3 ()
+{
+ static dwarf_version const *dw =
+ dwarf_version::extend (dwarf_2 (), dwarf_3_ext ());
+ return dw;
+}
diff --git a/dwarflint/dwarf_3.hh b/dwarflint/dwarf_3.hh
new file mode 100644
index 00000000..e9edfbea
--- /dev/null
+++ b/dwarflint/dwarf_3.hh
@@ -0,0 +1,37 @@
+/* Pedantic checking of DWARF files
+ Copyright (C) 2010 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_DWARF_3_HH
+#define DWARFLINT_DWARF_3_HH
+
+#include "dwarf_version.ii"
+
+/// Pure DWARF 3 extension.
+dwarf_version const *dwarf_3_ext ();
+
+/// DWARF 3 and below.
+dwarf_version const *dwarf_3 ();
+
+#endif//DWARFLINT_DWARF_3_HH
diff --git a/dwarflint/dwarf_4.cc b/dwarflint/dwarf_4.cc
new file mode 100644
index 00000000..3894c499
--- /dev/null
+++ b/dwarflint/dwarf_4.cc
@@ -0,0 +1,103 @@
+/* Pedantic checking of DWARF files
+ Copyright (C) 2010 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 "dwarf_version-imp.hh"
+#include "dwarf_3.hh"
+#include "dwarf_4.hh"
+#include "../libdw/dwarf.h"
+
+namespace
+{
+ struct dwarf_4_attributes
+ : public attribute_table
+ {
+ dwarf_4_attributes ()
+ {
+ add (attribute (DW_AT_high_pc, dw_class_set (cl_address, cl_constant)));
+ add (ref_attribute (DW_AT_namelist_item));
+ add (ref_attribute (DW_AT_signature));
+ add (flag_attribute (DW_AT_main_subprogram));
+ add (const_attribute (DW_AT_data_bit_offset));
+ add (flag_attribute (DW_AT_const_expr));
+ add (flag_attribute (DW_AT_enum_class));
+ add (string_attribute (DW_AT_linkage_name));
+ }
+ };
+
+ struct exprloc_form
+ : public preset_form<sc_block, cl_exprloc>
+ {
+ exprloc_form (int a_name)
+ : preset_form<sc_block, cl_exprloc> (a_name, fw_uleb)
+ {}
+ };
+
+ struct dwarf_4_forms
+ : public form_table
+ {
+ dwarf_4_forms ()
+ {
+ add (const_form (DW_FORM_data4, fw_4));
+ add (const_form (DW_FORM_data8, fw_8));
+ add (offset_form (DW_FORM_sec_offset,
+ dw_class_set (cl_lineptr, cl_loclistptr,
+ cl_macptr, cl_rangelistptr)));
+ add (exprloc_form (DW_FORM_exprloc));
+ add (flag_form (DW_FORM_flag_present, fw_0));
+ add (ref_form (DW_FORM_ref_sig8, fw_8));
+
+ // In DWARF 2 we claim that blocks are exprloc forms (see
+ // comment there). Revert back to pure blocks now that we have
+ // proper support for cl_exprloc.
+ add (block_form (DW_FORM_block, fw_uleb));
+ add (block_form (DW_FORM_block1, fw_1));
+ add (block_form (DW_FORM_block2, fw_2));
+ add (block_form (DW_FORM_block4, fw_4));
+ }
+ };
+
+ struct dwarf_4_ext_t
+ : public std_dwarf
+ {
+ dwarf_4_ext_t ()
+ : std_dwarf (dwarf_4_attributes (), dwarf_4_forms ())
+ {}
+ };
+}
+
+dwarf_version const *
+dwarf_4_ext ()
+{
+ static dwarf_4_ext_t dw;
+ return &dw;
+}
+
+dwarf_version const *
+dwarf_4 ()
+{
+ static dwarf_version const *dw =
+ dwarf_version::extend (dwarf_3 (), dwarf_4_ext ());
+ return dw;
+}
diff --git a/dwarflint/dwarf_4.hh b/dwarflint/dwarf_4.hh
new file mode 100644
index 00000000..846c86c9
--- /dev/null
+++ b/dwarflint/dwarf_4.hh
@@ -0,0 +1,37 @@
+/* Pedantic checking of DWARF files
+ Copyright (C) 2010 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_DWARF_4_HH
+#define DWARFLINT_DWARF_4_HH
+
+#include "dwarf_version.ii"
+
+/// Pure DWARF 4 extension.
+dwarf_version const *dwarf_4_ext ();
+
+/// DWARF 4 and below.
+dwarf_version const *dwarf_4 ();
+
+#endif//DWARFLINT_DWARF_4_HH
diff --git a/dwarflint/dwarf_mips.cc b/dwarflint/dwarf_mips.cc
new file mode 100644
index 00000000..1349a733
--- /dev/null
+++ b/dwarflint/dwarf_mips.cc
@@ -0,0 +1,96 @@
+/* Pedantic checking of DWARF files
+ Copyright (C) 2010 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 "dwarf_version-imp.hh"
+#include "../libdw/dwarf.h"
+
+namespace
+{
+ struct dwarf_mips_attributes
+ : public attribute_table
+ {
+ void unused (__attribute__ ((unused)) attribute const &attrib) const {}
+ dwarf_mips_attributes ()
+ {
+ // Most of these are really just sketched, since we don't emit
+ // them anyway. For those in need, the documentation is in
+ // mips_extensions.pdf that's installed by libdwarf-devel in
+ // Fedora. According to that document, some forms were never
+ // even emitted. Those are marked as unused and not added.
+ // Their class is arbitrarily chosen as cl_constant.
+
+ add (const_attribute (DW_AT_MIPS_fde));
+ unused (const_attribute (DW_AT_MIPS_loop_begin));
+ unused (const_attribute (DW_AT_MIPS_tail_loop_begin));
+ unused (const_attribute (DW_AT_MIPS_epilog_begin));
+ unused (const_attribute (DW_AT_MIPS_loop_unroll_factor));
+ unused (const_attribute (DW_AT_MIPS_software_pipeline_depth));
+ add (string_attribute (DW_AT_MIPS_linkage_name));
+
+ // [section 8.10] If DW_AT_MIPS_stride is present, the attribute
+ // contains a reference to a DIE which describes the location
+ // holding the stride, and the DW_AT_stride_size field of
+ // DW_TAG_array_type is ignored if present. The value of the
+ // stride is the number of 4 byte words between elements along
+ // that axis.
+ add (ref_attribute (DW_AT_MIPS_stride));
+
+ add (string_attribute (DW_AT_MIPS_abstract_name));
+
+ // xxx in addition, this is supposed to be CU-local reference,
+ // similarly to the DW_AT_sibling. An opportunity to generalize
+ // sibling_form_suitable.
+ add (ref_attribute (DW_AT_MIPS_clone_origin));
+
+ add (flag_attribute (DW_AT_MIPS_has_inlines));
+
+ // The documentation is unclear on what form these should take.
+ // I'm making them the same as DW_AT_byte_stride in DWARF2, in
+ // hopes that that's what they are supposed to be.
+ add (const_attribute (DW_AT_MIPS_stride_byte));
+ add (const_attribute (DW_AT_MIPS_stride_elem));
+
+ add (ref_attribute (DW_AT_MIPS_ptr_dopetype));
+ add (ref_attribute (DW_AT_MIPS_allocatable_dopetype));
+ add (ref_attribute (DW_AT_MIPS_assumed_shape_dopetype));
+ add (flag_attribute (DW_AT_MIPS_assumed_size));
+ }
+ };
+
+ struct dwarf_mips_ext_t
+ : public std_dwarf
+ {
+ dwarf_mips_ext_t ()
+ : std_dwarf (dwarf_mips_attributes (), form_table ())
+ {}
+ };
+}
+
+dwarf_version const *
+dwarf_mips_ext ()
+{
+ static dwarf_mips_ext_t dw;
+ return &dw;
+}
diff --git a/dwarflint/dwarf_mips.hh b/dwarflint/dwarf_mips.hh
new file mode 100644
index 00000000..994c4dbc
--- /dev/null
+++ b/dwarflint/dwarf_mips.hh
@@ -0,0 +1,33 @@
+/* Pedantic checking of DWARF files
+ Copyright (C) 2010 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_DWARF_MIPS_HH
+#define DWARFLINT_DWARF_MIPS_HH
+
+#include "dwarf_version.ii"
+
+dwarf_version const *dwarf_mips_ext ();
+
+#endif//DWARFLINT_DWARF_MIPS_HH
diff --git a/dwarflint/dwarf_version-imp.cc b/dwarflint/dwarf_version-imp.cc
new file mode 100644
index 00000000..9fd0449a
--- /dev/null
+++ b/dwarflint/dwarf_version-imp.cc
@@ -0,0 +1,77 @@
+/* Pedantic checking of DWARF files
+ Copyright (C) 2010 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 "dwarf_version-imp.hh"
+
+template <class T>
+void
+dwver_index_table<T>::add (T const &emt)
+{
+ _m_table.insert (std::make_pair (emt.name (), emt));
+}
+
+template <class T>
+T const *
+dwver_index_table<T>::get (int f) const
+{
+ typename _table_t::const_iterator it = _m_table.find (f);
+ if (it != _m_table.end ())
+ return &it->second;
+ else
+ return NULL;
+}
+
+template class dwver_index_table<form>;
+template class dwver_index_table<attribute>;
+
+offset_form::offset_form (int a_name, dw_class_set a_classes)
+ : form (a_name, a_classes, fw_offset, sc_value)
+{}
+
+address_form::address_form (int a_name, dw_class_set a_classes)
+ : form (a_name, a_classes, fw_address, sc_value)
+{}
+
+string_form::string_form (int a_name)
+ : preset_form<sc_string, cl_string> (a_name, fw_unknown)
+{}
+
+std_dwarf::std_dwarf (attribute_table const &attrtab,
+ form_table const &formtab)
+ : _m_attrtab (attrtab)
+ , _m_formtab (formtab)
+{}
+
+form const *
+std_dwarf::get_form (int form_name) const
+{
+ return _m_formtab.get (form_name);
+}
+
+attribute const *
+std_dwarf::get_attribute (int attribute_name) const
+{
+ return _m_attrtab.get (attribute_name);
+}
diff --git a/dwarflint/dwarf_version-imp.hh b/dwarflint/dwarf_version-imp.hh
new file mode 100644
index 00000000..4f00c7c8
--- /dev/null
+++ b/dwarflint/dwarf_version-imp.hh
@@ -0,0 +1,121 @@
+/* Pedantic checking of DWARF files
+ Copyright (C) 2010 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_DWARF_VERSION_IMP_HH
+#define DWARFLINT_DWARF_VERSION_IMP_HH
+
+#include "dwarf_version.hh"
+#include <map>
+
+template <class T>
+class dwver_index_table
+{
+ typedef std::map<int, T> _table_t;
+ _table_t _m_table;
+
+protected:
+ void add (T const &emt);
+
+public:
+ T const *get (int name) const;
+};
+
+typedef dwver_index_table<form> form_table;
+typedef dwver_index_table<attribute> attribute_table;
+
+template<storage_class_t StorClass, dw_class... Classes>
+struct preset_form
+ : public form
+{
+ preset_form (int a_name, form_width_t a_width)
+ : form (a_name, dw_class_set (Classes...), a_width, StorClass)
+ {}
+};
+
+template<dw_class... Classes>
+struct preset_attribute
+ : public attribute
+{
+ preset_attribute (int a_name)
+ : attribute (a_name, dw_class_set (Classes...))
+ {}
+};
+
+
+struct offset_form
+ : public form
+{
+ offset_form (int a_name, dw_class_set a_classes);
+};
+
+struct address_form
+ : public form
+{
+ address_form (int a_name, dw_class_set a_classes);
+};
+
+struct string_form
+ : public preset_form<sc_string, cl_string>
+{
+ string_form (int a_name);
+};
+
+typedef preset_form<sc_block, cl_block> block_form;
+typedef preset_form<sc_value, cl_constant> const_form;
+typedef preset_form<sc_value, cl_reference> ref_form;
+typedef preset_form<sc_value, cl_flag> flag_form;
+
+typedef preset_attribute<cl_constant> const_attribute;
+typedef preset_attribute<cl_reference> ref_attribute;
+typedef preset_attribute<cl_address> addr_attribute;
+typedef preset_attribute<cl_string> string_attribute;
+typedef preset_attribute<cl_flag> flag_attribute;
+typedef preset_attribute<cl_block> block_attribute;
+
+// [DWARF 3, DWARF 4, section 2.19]: attributes that [...] specify a
+// property [...] that is an integer value, where the value may be
+// known during compilation or may be computed dynamically during
+// execution.
+typedef preset_attribute<cl_constant, cl_exprloc,
+ cl_reference> dynval_attribute;
+
+typedef preset_attribute<cl_exprloc, cl_loclistptr> location_attribute;
+typedef preset_attribute<cl_exprloc, cl_reference> static_location_attribute;
+
+class std_dwarf
+ : public dwarf_version
+{
+ attribute_table const _m_attrtab;
+ form_table const _m_formtab;
+
+public:
+ std_dwarf (attribute_table const &attrtab,
+ form_table const &formtab);
+
+ form const *get_form (int form_name) const;
+ attribute const *get_attribute (int attribute_name) const;
+};
+
+#endif//DWARFLINT_DWARF_VERSION_IMP_HH
diff --git a/dwarflint/dwarf_version.cc b/dwarflint/dwarf_version.cc
new file mode 100644
index 00000000..669a5f8a
--- /dev/null
+++ b/dwarflint/dwarf_version.cc
@@ -0,0 +1,259 @@
+/* Pedantic checking of DWARF files
+ Copyright (C) 2009,2010 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>. */
+
+// The tables here capture attribute/allowed forms depending on DWARF
+// version. Apart from standardized DWARF formats, e.g. DWARF3+GNU is
+// a version of its own.
+
+#include "dwarf_version.hh"
+#include "dwarf_2.hh"
+#include "dwarf_3.hh"
+#include "dwarf_4.hh"
+#include "dwarf_mips.hh"
+#include "check_debug_info.hh"
+#include "pri.hh"
+
+#include "../libdw/dwarf.h"
+#include <map>
+#include <cassert>
+#include <string.h>
+
+dw_class_set::dw_class_set (dw_class a, dw_class b, dw_class c,
+ dw_class d, dw_class e)
+{
+#define ADD(V) if (V != max_dw_class) (*this)[V] = true
+ ADD (a);
+ ADD (b);
+ ADD (c);
+ ADD (d);
+ ADD (e);
+#undef ADD
+}
+
+form::form (int a_name, dw_class_set a_classes,
+ form_width_t a_width, storage_class_t a_storclass)
+ : _m_name (a_name)
+ , _m_classes (a_classes)
+ , _m_width (a_width)
+ , _m_storclass (a_storclass)
+{}
+
+form::form (int a_name, dw_class_set a_classes,
+ form_width_special_t a_width, storage_class_t a_storclass)
+ : _m_name (a_name)
+ , _m_classes (a_classes)
+ , _m_width (a_width)
+ , _m_storclass (a_storclass)
+{}
+
+dw_class
+dwarf_version::form_class (form const *form, attribute const *attribute) const
+{
+ assert (form != NULL);
+ assert (attribute != NULL);
+ dw_class_set result = form->classes ();
+ result &= attribute->classes ();
+ assert (result.any ());
+ if (result.count () > 1)
+ {
+ dw_class ret = this->ambiguous_class (form, attribute, result);
+ assert (ret < max_dw_class);
+ assert (result[ret]);
+ return ret;
+ }
+ else
+ return static_cast<dw_class> (ffsl (result.to_ulong ()) - 1);
+}
+
+form_width_t
+form::width (cu const *cu) const
+{
+ if (_m_width == fw_offset)
+ return static_cast<form_width_t> (cu->head->offset_size);
+ else if (_m_width == fw_address)
+ return static_cast<form_width_t> (cu->head->address_size);
+ else
+ return static_cast<form_width_t> (_m_width);
+}
+
+std::ostream &
+operator << (std::ostream &os, form const &obj)
+{
+ return os << pri::form (obj.name ());
+}
+
+namespace
+{
+ dw_class_set
+ include_indirect (dw_class_set a_classes)
+ {
+ a_classes.set (cl_indirect);
+ return a_classes;
+ }
+}
+
+attribute::attribute (int a_name, dw_class_set const &a_classes)
+ : _m_name (a_name)
+ , _m_classes (include_indirect (a_classes))
+{}
+
+std::ostream &
+operator << (std::ostream &os, attribute const &obj)
+{
+ return os << pri::attr (obj.name ());
+}
+
+
+bool
+dwarf_version::form_allowed (int form) const
+{
+ return get_form (form) != NULL;
+}
+
+bool
+dwarf_version::form_allowed (int attribute_name, int form_name) const
+{
+ attribute const *attribute = this->get_attribute (attribute_name);
+ assert (attribute != NULL);
+ dw_class_set const &attr_classes = attribute->classes ();
+
+ form const *form = this->get_form (form_name);
+ assert (form != NULL);
+ dw_class_set const &form_classes = form->classes ();
+
+ return (attr_classes & form_classes).any ();
+}
+
+sibling_form_suitable_t
+sibling_form_suitable (dwarf_version const *ver, int form)
+{
+ if (!ver->form_allowed (DW_AT_sibling, form))
+ return sfs_invalid;
+ else if (form == DW_FORM_ref_addr)
+ return sfs_long;
+ else
+ return sfs_ok;
+}
+
+namespace
+{
+ class dwarf_version_union
+ : public dwarf_version
+ {
+ dwarf_version const *_m_source;
+ dwarf_version const *_m_extension;
+
+ public:
+ dwarf_version_union (dwarf_version const *source,
+ dwarf_version const *extension)
+ : _m_source (source)
+ , _m_extension (extension)
+ {
+ }
+
+ template<class T>
+ T const *
+ lookfor (int name, T const*(dwarf_version::*getter) (int) const) const
+ {
+ if (T const *emt = (_m_extension->*getter) (name))
+ return emt;
+ else
+ return (_m_source->*getter) (name);
+ }
+
+ form const *
+ get_form (int form_name) const
+ {
+ return lookfor (form_name, &dwarf_version::get_form);
+ }
+
+ attribute const *
+ get_attribute (int attribute_name) const
+ {
+ return lookfor (attribute_name, &dwarf_version::get_attribute);
+ }
+
+ dw_class
+ ambiguous_class (form const *form,
+ attribute const *attribute,
+ dw_class_set const &candidates) const
+ {
+ dw_class ret = _m_extension->ambiguous_class (form, attribute, candidates);
+ if (ret == max_dw_class)
+ ret = _m_source->ambiguous_class (form, attribute, candidates);
+ return ret;
+ }
+ };
+}
+
+dwarf_version const *
+dwarf_version::extend (dwarf_version const *source,
+ dwarf_version const *extension)
+{
+ assert (source != NULL);
+ assert (extension != NULL);
+ // this leaks, but we don't really care. These objects have to live
+ // the whole execution time anyway.
+ return new dwarf_version_union (source, extension);
+}
+
+dwarf_version const *
+dwarf_version::get (unsigned version)
+{
+ // xxx The GNU toolchain commonly uses DW_AT_MIPS_linkage_name,
+ // which is part of the MIPS extensions. So that's what we return.
+ // I wonder how to solve this "right". We cannot simply request
+ // DW_AT_producer/DW_AT_language values here, since we need the
+ // version to know how to read these attributes in the first place.
+
+ switch (version)
+ {
+ case 2:
+ {
+ static dwarf_version const *dw = extend (dwarf_2 (), dwarf_mips_ext ());
+ return dw;
+ }
+
+ case 3:
+ {
+ static dwarf_version const *dw = extend (dwarf_3 (), dwarf_mips_ext ());
+ return dw;
+ }
+
+ case 4:
+ {
+ static dwarf_version const *dw = extend (dwarf_4 (), dwarf_mips_ext ());
+ return dw;
+ }
+
+ default: return NULL;
+ };
+}
+
+dwarf_version const *
+dwarf_version::get_latest ()
+{
+ return get (4);
+}
diff --git a/dwarflint/dwarf_version.hh b/dwarflint/dwarf_version.hh
new file mode 100644
index 00000000..f3bee10b
--- /dev/null
+++ b/dwarflint/dwarf_version.hh
@@ -0,0 +1,227 @@
+/* Dwarf version tables.
+
+ Copyright (C) 2009, 2010 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_DWARF_VERSION_HH
+#define DWARFLINT_DWARF_VERSION_HH
+
+#include <bitset>
+#include <iosfwd>
+#include "check_debug_info.ii"
+#include "dwarf_version.ii"
+
+enum dw_class
+ {
+ cl_indirect,
+ cl_address,
+ cl_block,
+ cl_constant,
+ cl_exprloc,
+ cl_flag,
+ cl_reference,
+ cl_string,
+ cl_loclistptr,
+ cl_lineptr,
+ cl_macptr,
+ cl_rangelistptr,
+ max_dw_class
+ };
+
+class dw_class_set
+ : public std::bitset<max_dw_class>
+{
+public:
+ dw_class_set (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 e = max_dw_class);
+};
+
+enum form_width_t
+ {
+ fw_0 = 0,
+ fw_1 = 1,
+ fw_2 = 2,
+ fw_4 = 4,
+ fw_8 = 8,
+ fw_sleb,
+ fw_uleb,
+ fw_unknown,
+ };
+
+/// Special forms for use in DWARF tables. These never leak out to
+/// the user of dwarf_version.
+enum form_width_special_t
+ {
+ fw_offset = fw_unknown + 1,
+ fw_address,
+ };
+
+enum storage_class_t
+ {
+ sc_value,
+ sc_block,
+ sc_string,
+ };
+
+class form
+{
+ int const _m_name;
+ dw_class_set const _m_classes;
+ int const _m_width;
+ storage_class_t const _m_storclass;
+
+public:
+ form (int a_name, dw_class_set a_classes,
+ form_width_t a_width, storage_class_t a_storclass);
+
+ form (int a_name, dw_class_set a_classes,
+ form_width_special_t a_width, storage_class_t a_storclass);
+
+ int
+ name () const
+ {
+ return _m_name;
+ }
+
+ /// Answer set of DWARF classes that this form can have.
+ dw_class_set const &
+ classes () const
+ {
+ return _m_classes;
+ }
+
+ /// Return width of data stored with given form. CU may be NULL if
+ /// you are sure that the form size doesn't depend on bitness of
+ /// address_size or offset_size.
+ ///
+ /// Forms for which width makes no sense (namely those in the
+ /// storage class of sc_string) get fw_unknown. Unknown forms get
+ /// an assert.
+ ///
+ /// Return value is never fw_offset or fw_address. These get
+ /// resolved to fw_4 or fw_8 depending on corresponding value in
+ /// CU->head.
+ form_width_t width (cu const *cu) const;
+
+ /// Return storage class of given form. Closely related to width.
+ storage_class_t
+ storage_class () const
+ {
+ return _m_storclass;
+ }
+};
+std::ostream &operator << (std::ostream &os, form const &obj);
+
+
+class attribute
+{
+ int const _m_name;
+ dw_class_set const _m_classes;
+
+public:
+ /// NB this ctor automatically adds cl_indirect to a_classes.
+ attribute (int a_name, dw_class_set const &a_classes);
+
+ int
+ name () const
+ {
+ return _m_name;
+ }
+
+ /// Answer set of DWARF classes that this form can have.
+ dw_class_set const &
+ classes () const
+ {
+ return _m_classes;
+ }
+};
+std::ostream &operator << (std::ostream &os, attribute const &obj);
+
+class dwarf_version
+{
+public:
+ /// Return form object for given form name. Return NULL for unknown
+ /// forms.
+ virtual form const *get_form (int form_name) const = 0;
+
+ /// Return attribute object for given attribute name. Return NULL
+ /// for unknown attributes;
+ virtual attribute const *get_attribute (int attribute_name) const = 0;
+
+ /// If more than one class ends up as a candidate after the request
+ /// to form_class, this function is called to resolve the ambiguity.
+ virtual dw_class
+ ambiguous_class (__attribute__ ((unused)) form const *form,
+ __attribute__ ((unused)) attribute const *attribute,
+ __attribute__ ((unused)) dw_class_set const &candidates)
+ const
+ {
+ return max_dw_class; // = we don't know. This will assert back in caller.
+ }
+
+ /// Shortcut for get_form (form_name) != NULL.
+ bool form_allowed (int form_name) const;
+
+ /// Figure out whether, in given DWARF version, given attribute is
+ /// allowed to have given form.
+ bool form_allowed (int attribute_name, int form_name) const;
+
+ /// Answer a class of FORM given ATTRIBUTE as a context. If there's
+ /// exactly one candidate class, that's the one answered. If
+ /// there's more, ambiguous_class is called to resolve the
+ /// ambiguity. If there's no candidate, then the request is
+ /// invalid, you must validate the form via form_allowed before
+ /// calling this.
+ dw_class form_class (form const *form, attribute const *attribute) const;
+
+
+ /// Return dwarf_version object for given DWARF version.
+ static dwarf_version const *get (unsigned version)
+ __attribute__ ((pure));
+
+ /// Return dwarf_version object for latest supported DWARF version.
+ static dwarf_version const *get_latest ()
+ __attribute__ ((pure));
+
+ /// Return dwarf_version that represents SOURCE extended with
+ /// EXTENSION. Currently this probably has no use, but one obvious
+ /// candidate usage is representing GNU extensions over core DWARF.
+ /// Extension can contain overrides of the source dwarf_version
+ /// object, and these overrides take precedence.
+ static dwarf_version const *extend (dwarf_version const *source,
+ dwarf_version const *extension);
+};
+
+/// Check that the form is suitable for the DW_AT_sibling attribute.
+enum sibling_form_suitable_t
+ {
+ sfs_ok, ///< This form is OK for DW_AT_sibling
+ sfs_long, ///< Global reference form, unnecessary for DW_AT_sibling
+ sfs_invalid, ///< This form isn't allowed at DW_AT_sibling
+ };
+sibling_form_suitable_t sibling_form_suitable (dwarf_version const *ver,
+ int form);
+
+#endif//DWARFLINT_DWARF_VERSION_HH
diff --git a/dwarflint/dwarf_version.ii b/dwarflint/dwarf_version.ii
new file mode 100644
index 00000000..b1a54b5b
--- /dev/null
+++ b/dwarflint/dwarf_version.ii
@@ -0,0 +1,3 @@
+class form;
+class attribute;
+class dwarf_version;
diff --git a/dwarflint/misc.hh b/dwarflint/misc.hh
index 79b60147..fac9526d 100644
--- a/dwarflint/misc.hh
+++ b/dwarflint/misc.hh
@@ -34,19 +34,19 @@ extern "C"
#include "../lib/system.h"
}
-#define REALLOC(A, BUF) \
- do { \
- typeof ((A)) _a = (A); \
- if (_a->size == _a->alloc) \
- { \
- if (_a->alloc == 0) \
- _a->alloc = 8; \
- else \
- _a->alloc *= 2; \
- _a->BUF = (typeof (_a->BUF)) \
- xrealloc (_a->BUF, \
- sizeof (*_a->BUF) * _a->alloc); \
- } \
+#define REALLOC(A, BUF) \
+ do { \
+ typeof ((A)) _a = (A); \
+ if (_a->size == _a->alloc) \
+ { \
+ if (_a->alloc == 0) \
+ _a->alloc = 8; \
+ else \
+ _a->alloc *= 2; \
+ _a->BUF = (typeof (_a->BUF)) \
+ xrealloc (_a->BUF, \
+ sizeof (*_a->BUF) * _a->alloc); \
+ } \
} while (0)
#define WIPE(OBJ) memset (&OBJ, 0, sizeof (OBJ))
@@ -58,5 +58,7 @@ bool necessary_alignment (uint64_t start, uint64_t length,
bool supported_version (unsigned version,
size_t num_supported, struct where *where, ...);
+#define UNREACHABLE assert (!"unreachable")
+
#endif//DWARFLINT_MISC_HH
diff --git a/dwarflint/tables.cc b/dwarflint/tables.cc
deleted file mode 100644
index a44f2a61..00000000
--- a/dwarflint/tables.cc
+++ /dev/null
@@ -1,724 +0,0 @@
-/* Pedantic checking of DWARF files
- Copyright (C) 2009,2010 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>. */
-
-// 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 "../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,
- cl_loclistptr,
- cl_lineptr,
- cl_macptr,
- cl_rangelistptr,
- 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 e = 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);
- ADD (e);
-#undef ADD
- return s;
- }
-
- struct dwarf_row {
- int val;
- dw_class_set classes;
- };
-
- class form_table
- {
- typedef std::set <form> _form_set_t;
- typedef std::map <dw_class, _form_set_t > _form_map_t;
-
- static _form_map_t init_class_forms (dwarf_row const forms[],
- form_table const *parent)
- {
- _form_map_t class_forms;
-
- if (parent != NULL)
- {
- std::set <form> overriden_forms;
- for (size_t i = 0; forms[i].val != 0; ++i)
- overriden_forms.insert (forms[i].val);
-
- for (_form_map_t::const_iterator it = parent->m_class_forms.begin ();
- it != parent->m_class_forms.end (); ++it)
- {
- std::set <form> new_forms = it->second;
- for (_form_set_t::const_iterator ot = overriden_forms.begin ();
- ot != overriden_forms.end (); ++ot)
- new_forms.erase (*ot);
- class_forms.insert (std::make_pair (it->first, new_forms));
- }
- }
-
- for (size_t i = 0; forms[i].val != 0; ++i)
- for (unsigned c = 0; c < forms[i].classes.size (); ++c)
- class_forms[static_cast<dw_class> (c)].insert (forms[i].val);
-
- return class_forms;
- }
-
- static _form_set_t init_all_forms (_form_map_t const &class_forms)
- {
- _form_set_t all_forms;
- for (_form_map_t::const_iterator it = class_forms.begin ();
- it != class_forms.end (); ++it)
- all_forms.insert (it->second.begin (), it->second.end ());
- return all_forms;
- }
-
- _form_map_t const m_class_forms;
- _form_set_t const m_all_forms;
-
- public:
- form_table (dwarf_row const forms[], form_table const *parent = NULL)
- : m_class_forms (init_class_forms (forms, parent))
- , m_all_forms (init_all_forms (m_class_forms))
- {}
-
- std::set <form> const &get (dw_class c) const
- {
- _form_map_t::const_iterator it = m_class_forms.find (c);
- assert (it != m_class_forms.end ());
- return it->second;
- }
-
- std::set <form> const &get_all () const
- {
- return m_all_forms;
- }
- };
-
- dwarf_row const 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_row const dwarf_2_form_table_rows[] = {
- {DW_FORM_addr, dw_classes (cl_address)},
- {DW_FORM_block2, dw_classes (cl_block)},
- {DW_FORM_block4, dw_classes (cl_block)},
- {DW_FORM_data2, dw_classes (cl_constant)},
- {DW_FORM_data4, dw_classes (cl_constant)},
- {DW_FORM_data8, dw_classes (cl_constant)},
- {DW_FORM_string, dw_classes (cl_string)},
- {DW_FORM_block, dw_classes (cl_block)},
- {DW_FORM_block1, dw_classes (cl_block)},
- {DW_FORM_data1, dw_classes (cl_constant)},
- {DW_FORM_flag, dw_classes (cl_flag)},
- {DW_FORM_sdata, dw_classes (cl_constant)},
- {DW_FORM_strp, dw_classes (cl_string)},
- {DW_FORM_udata, dw_classes (cl_constant)},
- {DW_FORM_ref_addr, dw_classes (cl_reference)},
- {DW_FORM_ref1, dw_classes (cl_reference)},
- {DW_FORM_ref2, dw_classes (cl_reference)},
- {DW_FORM_ref4, dw_classes (cl_reference)},
- {DW_FORM_ref8, dw_classes (cl_reference)},
- {DW_FORM_ref_udata, dw_classes (cl_reference)},
- {0, dw_classes ()}
- };
- form_table const dwarf_2_form_table (dwarf_2_form_table_rows);
-
- /* Changes from dwarf_2_*_table: */
- dwarf_row const dwarf_3_at_table[] = {
- {DW_AT_location, dw_classes (cl_block, cl_loclistptr)},
- {DW_AT_byte_size, dw_classes (cl_block, cl_constant, cl_reference)},
- {DW_AT_bit_offset, dw_classes (cl_block, cl_constant, cl_reference)},
- {DW_AT_bit_size, dw_classes (cl_block, cl_constant, cl_reference)},
- {DW_AT_stmt_list, dw_classes (cl_lineptr)},
- {DW_AT_string_length, dw_classes (cl_block, cl_loclistptr)},
- {DW_AT_const_value, dw_classes (cl_block, cl_constant, cl_string)},
- {DW_AT_lower_bound, dw_classes (cl_block, cl_constant, cl_reference)},
- {DW_AT_return_addr, dw_classes (cl_block, cl_loclistptr)},
- {DW_AT_bit_stride, dw_classes (cl_constant)},
- {DW_AT_upper_bound, dw_classes (cl_block, cl_constant, cl_reference)},
- {DW_AT_count, dw_classes (cl_block, cl_constant, cl_reference)},
- {DW_AT_data_member_location, dw_classes (cl_block, cl_constant,
- cl_loclistptr)},
- {DW_AT_frame_base, dw_classes (cl_block, cl_loclistptr)},
- {DW_AT_macro_info, dw_classes (cl_macptr)},
- {DW_AT_segment, dw_classes (cl_block, cl_loclistptr)},
- {DW_AT_static_link, dw_classes (cl_block, cl_loclistptr)},
- {DW_AT_use_location, dw_classes (cl_block, cl_loclistptr)},
- {DW_AT_vtable_elem_location, dw_classes (cl_block, cl_loclistptr)},
- {DW_AT_associated, dw_classes (cl_block, cl_constant, cl_reference)},
- {DW_AT_data_location, dw_classes (cl_block)},
- {DW_AT_byte_stride, dw_classes (cl_block, cl_constant, cl_reference)},
- {DW_AT_entry_pc, dw_classes (cl_address)},
- {DW_AT_use_UTF8, dw_classes (cl_flag)},
- {DW_AT_extension, dw_classes (cl_reference)},
- {DW_AT_ranges, dw_classes (cl_rangelistptr)},
- {DW_AT_trampoline, dw_classes (cl_address, cl_flag, cl_reference,
- cl_string)},
- {DW_AT_call_column, dw_classes (cl_constant)},
- {DW_AT_call_file, dw_classes (cl_constant)},
- {DW_AT_call_line, dw_classes (cl_constant)},
- {DW_AT_description, dw_classes (cl_string)},
- {DW_AT_binary_scale, dw_classes (cl_constant)},
- {DW_AT_decimal_scale, dw_classes (cl_constant)},
- {DW_AT_small, dw_classes (cl_reference)},
- {DW_AT_decimal_sign, dw_classes (cl_constant)},
- {DW_AT_digit_count, dw_classes (cl_constant)},
- {DW_AT_picture_string, dw_classes (cl_string)},
- {DW_AT_mutable, dw_classes (cl_flag)},
- {DW_AT_threads_scaled, dw_classes (cl_flag)},
- {DW_AT_explicit, dw_classes (cl_flag)},
- {DW_AT_object_pointer, dw_classes (cl_reference)},
- {DW_AT_endianity, dw_classes (cl_constant)},
- {DW_AT_elemental, dw_classes (cl_flag)},
- {DW_AT_pure, dw_classes (cl_flag)},
- {DW_AT_recursive, dw_classes (cl_flag)},
- {0, dw_classes ()}
- };
-
- dwarf_row const dwarf_3_form_table_rows[] = {
- {DW_FORM_data4, dw_classes (cl_constant, cl_lineptr, cl_loclistptr,
- cl_macptr, cl_rangelistptr)},
- {DW_FORM_data8, dw_classes (cl_constant, cl_lineptr, cl_loclistptr,
- cl_macptr, cl_rangelistptr)},
- {0, dw_classes ()}
- };
- form_table const dwarf_3_form_table (dwarf_3_form_table_rows, &dwarf_2_form_table);
-
- /* Changes from dwarf_3_*_table: */
- dwarf_row const dwarf_4_at_table[] = {
- {DW_AT_location, dw_classes (cl_exprloc, cl_loclistptr)},
- {DW_AT_bit_offset, dw_classes (cl_constant, cl_exprloc, cl_reference)},
- {DW_AT_bit_size, dw_classes (cl_constant, cl_exprloc, cl_reference)},
- {DW_AT_high_pc, dw_classes (cl_address, cl_constant)},
- {DW_AT_string_length, dw_classes (cl_exprloc, cl_loclistptr)},
- {DW_AT_const_value, dw_classes (cl_block, cl_constant, cl_string)},
- {DW_AT_lower_bound, dw_classes (cl_constant, cl_exprloc, cl_reference)},
- {DW_AT_return_addr, dw_classes (cl_exprloc, cl_loclistptr)},
- {DW_AT_bit_stride, dw_classes (cl_constant, cl_exprloc, cl_reference)},
- {DW_AT_upper_bound, dw_classes (cl_constant, cl_exprloc, cl_reference)},
- {DW_AT_count, dw_classes (cl_constant, cl_exprloc, cl_reference)},
- {DW_AT_data_member_location, dw_classes (cl_constant, cl_exprloc,
- cl_loclistptr)},
- {DW_AT_frame_base, dw_classes (cl_exprloc, cl_loclistptr)},
- {DW_AT_namelist_item, dw_classes (cl_reference)},
- {DW_AT_segment, dw_classes (cl_exprloc, cl_loclistptr)},
- {DW_AT_static_link, dw_classes (cl_exprloc, cl_loclistptr)},
- {DW_AT_use_location, dw_classes (cl_exprloc, cl_loclistptr)},
- {DW_AT_vtable_elem_location, dw_classes (cl_exprloc, cl_loclistptr)},
- {DW_AT_allocated, dw_classes (cl_constant, cl_exprloc, cl_reference)},
- {DW_AT_associated, dw_classes (cl_constant, cl_exprloc, cl_reference)},
- {DW_AT_data_location, dw_classes (cl_exprloc)},
- {DW_AT_byte_stride, dw_classes (cl_constant, cl_exprloc, cl_reference)},
- {DW_AT_signature, dw_classes (cl_reference)},
- {DW_AT_main_subprogram, dw_classes (cl_flag)},
- {DW_AT_data_bit_offset, dw_classes (cl_constant)},
- {DW_AT_const_expr, dw_classes (cl_flag)},
- {0, dw_classes ()}
- };
-
- dwarf_row const dwarf_4_form_table_rows[] = {
- {DW_FORM_data4, dw_classes (cl_constant)},
- {DW_FORM_data8, dw_classes (cl_constant)},
- {DW_FORM_sec_offset, dw_classes (cl_lineptr, cl_loclistptr,
- cl_macptr, cl_rangelistptr)},
- {DW_FORM_exprloc, dw_classes (cl_exprloc)},
- {DW_FORM_flag_present, dw_classes (cl_flag)},
- {DW_FORM_ref_sig8, dw_classes (cl_reference)},
- {0, dw_classes ()}
- };
- form_table const dwarf_4_form_table (dwarf_4_form_table_rows, &dwarf_3_form_table);
-
- class std_dwarf
- : public dwarf_version
- {
- typedef std::map <attr, form_set_t> _forms_t;
- _forms_t m_forms;
- dwarf_version const *m_parent;
- form_table const &m_formtab;
-
- public:
- std_dwarf (dwarf_row const attrtab[], form_table const &formtab,
- dwarf_version const *parent = NULL)
- : m_parent (parent)
- , m_formtab (formtab)
- {
- for (unsigned i = 0; attrtab[i].val != 0; ++i)
- for (unsigned c = 0; c < attrtab[i].classes.size (); ++c)
- if (attrtab[i].classes[c])
- m_forms[attrtab[i].val]
- = formtab.get (static_cast <dw_class> (c));
-
- /*
- 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 m_formtab.get_all ();
- }
-
- form_set_t const &allowed_forms (attr at) const
- {
- _forms_t::const_iterator it = m_forms.find (at);
- assert (it != m_forms.end () || m_parent != NULL);
- if (it != m_forms.end ())
- return it->second;
- else
- return m_parent->allowed_forms (at);
- }
-
- // 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_3_at_table, dwarf_3_form_table, &dwarf2);
- std_dwarf dwarf4 (dwarf_4_at_table, dwarf_4_form_table, &dwarf3);
-}
-
-dwarf_version const *
-dwarf_version::get (unsigned version)
-{
- switch (version)
- {
- case 2: return &dwarf2;
- case 3: return &dwarf3;
- case 4: return &dwarf4;
- default: return NULL;
- };
-}
-
-dwarf_version const *
-dwarf_version::get_latest ()
-{
- return get (4);
-}
-
-int
-dwarf_version::check_sibling_form (int form) const
-{
- if (!form_allowed (DW_AT_sibling, form))
- return -2;
- else if (form == DW_FORM_ref_addr)
- return -1;
- else
- return 0;
-}
-
-#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/dwarflint/tables.hh b/dwarflint/tables.hh
deleted file mode 100644
index 6208b893..00000000
--- a/dwarflint/tables.hh
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Dwarf version tables.
-
- Copyright (C) 2009, 2010 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);
- }
-
- int check_sibling_form (int form) const;
-
- static dwarf_version const *get (unsigned version)
- __attribute__ ((pure));
-
- static dwarf_version const *get_latest ()
- __attribute__ ((pure));
-};
-
-#endif//DWARFLINT_TABLES_HH