* completed implementation of abbrevtable
authoreliben <devnull@localhost>
Wed, 21 Sep 2011 09:09:53 +0000 (12:09 +0300)
committereliben <devnull@localhost>
Wed, 21 Sep 2011 09:09:53 +0000 (12:09 +0300)
* started implementing DIE
* added code to CompileUnit to tie them all together

DIEs start showing signs of life

elftools/common/ordereddict.py [new file with mode: 0644]
elftools/dwarf/abbrevtable.py
elftools/dwarf/compileunit.py
elftools/dwarf/die.py [new file with mode: 0644]
elftools/dwarf/dwarfinfo.py
elftools/dwarf/enums.py
elftools/dwarf/structs.py
z.py
zd.py

diff --git a/elftools/common/ordereddict.py b/elftools/common/ordereddict.py
new file mode 100644 (file)
index 0000000..aabeafc
--- /dev/null
@@ -0,0 +1,282 @@
+# http://code.activestate.com/recipes/576693/ (r9)\r
+#      Created by Raymond Hettinger on Wed, 18 Mar 2009 (MIT) \r
+#\r
+# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 \r
+# and pypy.\r
+# Passes Python2.7's test suite and incorporates all the latest updates.\r
+#\r
+\r
+try:\r
+    from thread import get_ident as _get_ident\r
+except ImportError:\r
+    from dummy_thread import get_ident as _get_ident\r
+\r
+try:\r
+    from _abcoll import KeysView, ValuesView, ItemsView\r
+except ImportError:\r
+    pass\r
+\r
+\r
+class OrderedDict(dict):\r
+    'Dictionary that remembers insertion order'\r
+    # An inherited dict maps keys to values.\r
+    # The inherited dict provides __getitem__, __len__, __contains__, and get.\r
+    # The remaining methods are order-aware.\r
+    # Big-O running times for all methods are the same as for regular dictionaries.\r
+\r
+    # The internal self.__map dictionary maps keys to links in a doubly linked list.\r
+    # The circular doubly linked list starts and ends with a sentinel element.\r
+    # The sentinel element never gets deleted (this simplifies the algorithm).\r
+    # Each link is stored as a list of length three:  [PREV, NEXT, KEY].\r
+\r
+    def __init__(self, *args, **kwds):\r
+        '''Initialize an ordered dictionary.  Signature is the same as for\r
+        regular dictionaries, but keyword arguments are not recommended\r
+        because their insertion order is arbitrary.\r
+\r
+        '''\r
+        if len(args) > 1:\r
+            raise TypeError('expected at most 1 arguments, got %d' % len(args))\r
+        try:\r
+            self.__root\r
+        except AttributeError:\r
+            self.__root = root = []                     # sentinel node\r
+            root[:] = [root, root, None]\r
+            self.__map = {}\r
+        self.__update(*args, **kwds)\r
+\r
+    def __setitem__(self, key, value, dict_setitem=dict.__setitem__):\r
+        'od.__setitem__(i, y) <==> od[i]=y'\r
+        # Setting a new item creates a new link which goes at the end of the linked\r
+        # list, and the inherited dictionary is updated with the new key/value pair.\r
+        if key not in self:\r
+            root = self.__root\r
+            last = root[0]\r
+            last[1] = root[0] = self.__map[key] = [last, root, key]\r
+        dict_setitem(self, key, value)\r
+\r
+    def __delitem__(self, key, dict_delitem=dict.__delitem__):\r
+        'od.__delitem__(y) <==> del od[y]'\r
+        # Deleting an existing item uses self.__map to find the link which is\r
+        # then removed by updating the links in the predecessor and successor nodes.\r
+        dict_delitem(self, key)\r
+        link_prev, link_next, key = self.__map.pop(key)\r
+        link_prev[1] = link_next\r
+        link_next[0] = link_prev\r
+\r
+    def __iter__(self):\r
+        'od.__iter__() <==> iter(od)'\r
+        root = self.__root\r
+        curr = root[1]\r
+        while curr is not root:\r
+            yield curr[2]\r
+            curr = curr[1]\r
+\r
+    def __reversed__(self):\r
+        'od.__reversed__() <==> reversed(od)'\r
+        root = self.__root\r
+        curr = root[0]\r
+        while curr is not root:\r
+            yield curr[2]\r
+            curr = curr[0]\r
+\r
+    def clear(self):\r
+        'od.clear() -> None.  Remove all items from od.'\r
+        try:\r
+            for node in self.__map.itervalues():\r
+                del node[:]\r
+            root = self.__root\r
+            root[:] = [root, root, None]\r
+            self.__map.clear()\r
+        except AttributeError:\r
+            pass\r
+        dict.clear(self)\r
+\r
+    def popitem(self, last=True):\r
+        '''od.popitem() -> (k, v), return and remove a (key, value) pair.\r
+        Pairs are returned in LIFO order if last is true or FIFO order if false.\r
+\r
+        '''\r
+        if not self:\r
+            raise KeyError('dictionary is empty')\r
+        root = self.__root\r
+        if last:\r
+            link = root[0]\r
+            link_prev = link[0]\r
+            link_prev[1] = root\r
+            root[0] = link_prev\r
+        else:\r
+            link = root[1]\r
+            link_next = link[1]\r
+            root[1] = link_next\r
+            link_next[0] = root\r
+        key = link[2]\r
+        del self.__map[key]\r
+        value = dict.pop(self, key)\r
+        return key, value\r
+\r
+    # -- the following methods do not depend on the internal structure --\r
+\r
+    def keys(self):\r
+        'od.keys() -> list of keys in od'\r
+        return list(self)\r
+\r
+    def values(self):\r
+        'od.values() -> list of values in od'\r
+        return [self[key] for key in self]\r
+\r
+    def items(self):\r
+        'od.items() -> list of (key, value) pairs in od'\r
+        return [(key, self[key]) for key in self]\r
+\r
+    def iterkeys(self):\r
+        'od.iterkeys() -> an iterator over the keys in od'\r
+        return iter(self)\r
+\r
+    def itervalues(self):\r
+        'od.itervalues -> an iterator over the values in od'\r
+        for k in self:\r
+            yield self[k]\r
+\r
+    def iteritems(self):\r
+        'od.iteritems -> an iterator over the (key, value) items in od'\r
+        for k in self:\r
+            yield (k, self[k])\r
+\r
+    def update(*args, **kwds):\r
+        '''od.update(E, **F) -> None.  Update od from dict/iterable E and F.\r
+\r
+        If E is a dict instance, does:           for k in E: od[k] = E[k]\r
+        If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]\r
+        Or if E is an iterable of items, does:   for k, v in E: od[k] = v\r
+        In either case, this is followed by:     for k, v in F.items(): od[k] = v\r
+\r
+        '''\r
+        if len(args) > 2:\r
+            raise TypeError('update() takes at most 2 positional '\r
+                            'arguments (%d given)' % (len(args),))\r
+        elif not args:\r
+            raise TypeError('update() takes at least 1 argument (0 given)')\r
+        self = args[0]\r
+        # Make progressively weaker assumptions about "other"\r
+        other = ()\r
+        if len(args) == 2:\r
+            other = args[1]\r
+        if isinstance(other, dict):\r
+            for key in other:\r
+                self[key] = other[key]\r
+        elif hasattr(other, 'keys'):\r
+            for key in other.keys():\r
+                self[key] = other[key]\r
+        else:\r
+            for key, value in other:\r
+                self[key] = value\r
+        for key, value in kwds.items():\r
+            self[key] = value\r
+\r
+    __update = update  # let subclasses override update without breaking __init__\r
+\r
+    __marker = object()\r
+\r
+    def pop(self, key, default=__marker):\r
+        '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.\r
+        If key is not found, d is returned if given, otherwise KeyError is raised.\r
+\r
+        '''\r
+        if key in self:\r
+            result = self[key]\r
+            del self[key]\r
+            return result\r
+        if default is self.__marker:\r
+            raise KeyError(key)\r
+        return default\r
+\r
+    def setdefault(self, key, default=None):\r
+        'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'\r
+        if key in self:\r
+            return self[key]\r
+        self[key] = default\r
+        return default\r
+\r
+    def __repr__(self, _repr_running={}):\r
+        'od.__repr__() <==> repr(od)'\r
+        call_key = id(self), _get_ident()\r
+        if call_key in _repr_running:\r
+            return '...'\r
+        _repr_running[call_key] = 1\r
+        try:\r
+            if not self:\r
+                return '%s()' % (self.__class__.__name__,)\r
+            return '%s(%r)' % (self.__class__.__name__, self.items())\r
+        finally:\r
+            del _repr_running[call_key]\r
+\r
+    def __reduce__(self):\r
+        'Return state information for pickling'\r
+        items = [[k, self[k]] for k in self]\r
+        inst_dict = vars(self).copy()\r
+        for k in vars(OrderedDict()):\r
+            inst_dict.pop(k, None)\r
+        if inst_dict:\r
+            return (self.__class__, (items,), inst_dict)\r
+        return self.__class__, (items,)\r
+\r
+    def copy(self):\r
+        'od.copy() -> a shallow copy of od'\r
+        return self.__class__(self)\r
+\r
+    @classmethod\r
+    def fromkeys(cls, iterable, value=None):\r
+        '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S\r
+        and values equal to v (which defaults to None).\r
+\r
+        '''\r
+        d = cls()\r
+        for key in iterable:\r
+            d[key] = value\r
+        return d\r
+\r
+    def __eq__(self, other):\r
+        '''od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive\r
+        while comparison to a regular mapping is order-insensitive.\r
+\r
+        '''\r
+        if isinstance(other, OrderedDict):\r
+            return len(self)==len(other) and self.items() == other.items()\r
+        return dict.__eq__(self, other)\r
+\r
+    def __ne__(self, other):\r
+        return not self == other\r
+\r
+    # -- the following methods are only used in Python 2.7 --\r
+\r
+    def viewkeys(self):\r
+        "od.viewkeys() -> a set-like object providing a view on od's keys"\r
+        return KeysView(self)\r
+\r
+    def viewvalues(self):\r
+        "od.viewvalues() -> an object providing a view on od's values"\r
+        return ValuesView(self)\r
+\r
+    def viewitems(self):\r
+        "od.viewitems() -> a set-like object providing a view on od's items"\r
+        return ItemsView(self)\r
+\r
+\r
+\r
+\r
+#-------------------------------------------------------------------------------\r
+if __name__ == "__main__":\r
+    od = OrderedDict()\r
+    d = dict()\r
+    \r
+    for key in ['joe', 'more', 'tem', 'opsdf', 'dsf']:\r
+        od[key] = d[key] = key + '1'\r
+    \r
+    for k in d:\r
+        print k, d[k]\r
+    \r
+    print '-------- ordered ----------'\r
+    \r
+    for k in od:\r
+        print k, od[k]\r
index 14f88f59814b946e623a97d6d9aa28beb463650c..328f49a86da327acbe2628f0c7dde9efbfc2cc9b 100644 (file)
@@ -58,17 +58,28 @@ class AbbrevTable(object):
 class AbbrevDecl(object):
     """ Wraps a parsed abbreviation declaration, exposing its fields with 
         dict-like access, and adding some convenience methods.
+        
+        The abbreviation declaration represents an "entry" that points to it.
     """
     def __init__(self, code, decl):
         self.code = code
         self.decl = decl
     
     def has_children(self):
+        """ Does the entry have children?
+        """
         return self['children_flag'] == 'DW_CHILDREN_yes'
-    
+
+    def iter_attr_specs(self):
+        """ Iterate over the attribute specifications for the entry. Yield
+            (name, form) pairs.
+        """
+        for attr_spec in self['attr_spec']:
+            # Ignore the terminating 'null' spec
+            if attr_spec.name == 'DW_AT_null':
+                break
+            yield attr_spec.name, attr_spec.form
+            
     def __getitem__(self, entry):
         return self.decl[entry]
 
-
-
-
index 92198e44d6848b827a0bbb0ff58dc3dc57740f47..8852fac0a7bfe06e953b1dc26c04b9f3c9d53a2b 100644 (file)
@@ -6,10 +6,11 @@
 # Eli Bendersky (eliben@gmail.com)
 # This code is in the public domain
 #-------------------------------------------------------------------------------
+from .die import DIE
 
 
 class CompileUnit(object):
-    def __init__(self, header, dwarfinfo, structs):
+    def __init__(self, header, dwarfinfo, structs, cu_die_offset):
         """ header:
                 CU header for this compile unit
             
@@ -18,16 +19,39 @@ class CompileUnit(object):
                         
             structs:
                 A DWARFStructs instance suitable for this compile unit
+            
+            cu_die_offset:
+                Offset in the stream of the top DIE of this CU
         """
         self.dwarfinfo = dwarfinfo
         self.header = header
         self.structs = structs
-    
+        self.cu_die_offset = cu_die_offset
+        
+        # The abbreviation table for this CU. Filled lazily when DIEs are 
+        # requested.
+        self._abbrev_table = None
+        
+    def get_abbrev_table(self):
+        """ Get the abbreviation table (AbbrevTable object) for this CU
+        """
+        if self._abbrev_table is None:
+            self._abbrev_table = self.dwarfinfo.get_abbrev_table(
+                self['debug_abbrev_offset'])
+        return self._abbrev_table
+
+    def get_top_DIE(self):
+        """ Get the top DIE (which is either a DW_TAG_compile_unit or 
+            DW_TAG_partial_unit) of this CU
+        """
+        return DIE(
+            cu=self,
+            stream=self.dwarfinfo.stream,
+            offset=self.cu_die_offset)
+
     def __getitem__(self, name):
         """ Implement dict-like access to header entries
         """
         return self.header[name]
 
-
-
-
+    
\ No newline at end of file
diff --git a/elftools/dwarf/die.py b/elftools/dwarf/die.py
new file mode 100644 (file)
index 0000000..4a034fb
--- /dev/null
@@ -0,0 +1,63 @@
+#-------------------------------------------------------------------------------
+# elftools: dwarf/die.py
+#
+# DWARF Debugging Information Entry
+#
+# Eli Bendersky (eliben@gmail.com)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+from collections import namedtuple
+
+from ..common.ordereddict import OrderedDict
+from ..common.utils import struct_parse
+
+
+# Describes an attribute value in the DIE: form and actual value
+#
+AttributeValue = namedtuple('AttributeValue', 'form value')
+
+
+class DIE(object):
+    """ A DWARF debugging information entry. On creation, parses itself from
+        the stream. Each DIE is held by a CU.
+        
+        Accessible attributes:
+        
+            tag:
+                The DIE tag
+        
+            length:
+                The size this DIE occupies in the section
+            
+            attributes:
+                An ordered dictionary mapping attribute names to values
+    """
+    def __init__(self, cu, stream, offset):
+        """ cu:
+                CompileUnit object this DIE belongs to. Used to obtain context
+                information (structs, abbrev table, etc.)
+            
+            stream, offset:
+                The stream and offset into it where this DIE's data is located
+        """
+        self.cu = cu
+        self.stream = stream
+        self.offset = offset
+        self._parse_DIE()
+    
+    def _parse_DIE(self):
+        """ Parses the DIE info from the section, based on the abbreviation
+            table of the CU
+        """
+        saved_offset = self.offset
+        structs = self.cu.structs
+        
+        # The DIE begins with the abbreviation code. Read it and use it to 
+        # obtain the abbrev declaration for this DIE
+        #
+        abbrev_code = struct_parse(structs.Dwarf_uleb128(''), self.stream)
+        abbrev = self.cu.get_abbrev_table().get_abbrev(abbrev_code)
+        
+        print abbrev_code, abbrev, abbrev.decl
+
+
index 6e96f14fb3518a584e07c2c6a0edca2d282fe0e0..343b5767d10fd1385ba6f65acea50baca374e748 100644 (file)
@@ -59,6 +59,22 @@ class DWARFInfo(object):
         # Cache for abbrev tables: a dict keyed by offset
         self._abbrevtable_cache = {}
     
+    def num_CUs(self):
+        """ Number of compile units in the debug info
+        """
+        return len(self._CU)
+    
+    def get_CU(self, n):
+        """ Get the compile unit (CompileUnit object) at index #n
+        """
+        return self._CU[n]
+    
+    def iter_CUs(self):
+        """ Yield all the compile units (CompileUnit objects) in the debug info
+        """
+        for i in range(self.num_CUs()):
+            yield self.get_CU(i)
+    
     def get_abbrev_table(self, offset):
         """ Get an AbbrevTable from the given offset in the debug_abbrev
             section.
@@ -81,6 +97,16 @@ class DWARFInfo(object):
                 offset=offset + self.debug_abbrev_loc.offset)
         return self._abbrevtable_cache[offset]
     
+    def info_offset2absolute(self, offset):
+        """ Given an offset into the debug_info section, translate it to an 
+            absolute offset into the stream. Raise an exception if the offset
+            exceeds the section bounds.
+        """
+        dwarf_assert(
+            offset < self.debug_info_loc.size,
+            "Offset '0x%x' to debug_info out of section bounds" % offset)
+        return offset + self.debug_info_loc.offset
+    
     def _parse_CUs(self):
         """ Parse CU entries from debug_info.
         """
@@ -106,13 +132,15 @@ class DWARFInfo(object):
             
             cu_header = struct_parse(
                 cu_structs.Dwarf_CU_header, self.stream, offset)
+            cu_die_offset = self.stream.tell()
             dwarf_assert(
                 self._is_supported_version(cu_header['version']),
                 "Expected supported DWARF version. Got '%s'" % cu_header['version'])
             CUlist.append(CompileUnit(
                 header=cu_header,
                 dwarfinfo=self,
-                structs=cu_structs))
+                structs=cu_structs,
+                cu_die_offset=cu_die_offset))
             # Compute the offset of the next CU in the section. The unit_length
             # field of the CU header contains its size not including the length
             # field itself.
index 8655e48792976f763b4269a7d097dce0cd6f9316..479733ef49ccbe48367bb4a2472f3edef8e9da1c 100644 (file)
@@ -216,10 +216,6 @@ ENUM_DW_FORM = dict(
     DW_FORM_ref8            = 0x14,
     DW_FORM_ref_udata       = 0x15,
     DW_FORM_indirect        = 0x16,
-    DW_FORM_sec_offset      = 0x17,
-    DW_FORM_exprloc         = 0x18,
-    DW_FORM_flag_present    = 0x19,
-    DW_FORM_ref_sig8        = 0x20,
 
     _default_               = Pass,
 )
index e77f98e3b7d7e3e8a2e3864f623f61fc6bd31815..536132b3bf80128f539beb4bdce270818108539c 100644 (file)
@@ -11,6 +11,7 @@ from ..construct import (
     UBInt8, UBInt16, UBInt32, UBInt64,
     ULInt8, ULInt16, ULInt32, ULInt64,
     Adapter, Struct, ConstructError, If, RepeatUntil, Field, Rename, Enum,
+    PrefixedArray, CString,
     )
 
 from .enums import *
@@ -42,6 +43,11 @@ class DWARFStructs(object):
             Dwarf_abbrev_declaration:
                 Abbreviation table declaration - doesn't include the initial
                 code, only the contents.
+            
+            Dwarf_dw_form:
+                A dictionary mapping 'DW_FORM_*' keys into construct Structs
+                that parse such forms. These Structs have already been given
+                dummy names.
         
         See also the documentation of public methods.
     """
@@ -68,12 +74,13 @@ class DWARFStructs(object):
             self.Dwarf_uint16 = UBInt16
             self.Dwarf_uint32 = UBInt32
             self.Dwarf_uint64 = UBInt64
-            self.Dwarf_offest = UBInt32 if self.dwarf_format == 32 else UBInt64
+            self.Dwarf_offset = UBInt32 if self.dwarf_format == 32 else UBInt64
 
         self._create_initial_length()
         self._create_leb128()
         self._create_cu_header()
         self._create_abbrev_declaration()
+        self._create_dw_form()
 
     def _create_initial_length(self):
         def _InitialLength(name):
@@ -107,10 +114,48 @@ class DWARFStructs(object):
             RepeatUntil(
                 lambda obj, ctx: 
                     obj.name == 'DW_AT_null' and obj.form == 'DW_FORM_null',
-                Struct('spec',
+                Struct('attr_spec',
                     Enum(self.Dwarf_uleb128('name'), **ENUM_DW_AT),
                     Enum(self.Dwarf_uleb128('form'), **ENUM_DW_FORM))))
 
+    def _create_dw_form(self):
+        self.Dwarf_dw_form = dict(
+            DW_FORM_addr=self.Dwarf_offset(''),
+            
+            DW_FORM_block1=self._make_block_struct(self.Dwarf_uint8),
+            DW_FORM_block2=self._make_block_struct(self.Dwarf_uint16),
+            DW_FORM_block4=self._make_block_struct(self.Dwarf_uint32),
+            DW_FORM_block=self._make_block_struct(self.Dwarf_uleb128),
+            
+            # All DW_FORM_data<n> forms are assumed to be unsigned
+            DW_FORM_data1=self.Dwarf_uint8(''),
+            DW_FORM_data2=self.Dwarf_uint16(''),
+            DW_FORM_data4=self.Dwarf_uint32(''),
+            DW_FORM_data8=self.Dwarf_uint64(''),
+            DW_FORM_sdata=self.Dwarf_sleb128(''),
+            DW_FORM_udata=self.Dwarf_uleb128(''),
+            
+            DW_FORM_string=CString(''),
+            DW_FORM_strp=self.Dwarf_offset(''),
+            DW_FORM_flag=self.Dwarf_uint8(''),
+            
+            DW_FORM_ref1=self.Dwarf_uint8(''),
+            DW_FORM_ref2=self.Dwarf_uint16(''),
+            DW_FORM_ref4=self.Dwarf_uint32(''),
+            DW_FORM_ref8=self.Dwarf_uint64(''),
+            DW_FORM_ref_udata=self.Dwarf_uleb128(''),
+            DW_FORM_ref_addr=self.Dwarf_offset(''),
+            
+            DW_FORM_indirect=self.Dwarf_uleb128(''),
+        )
+
+    def _make_block_struct(self, length_field):
+        """ Create a struct for DW_FORM_block<size> 
+        """
+        return PrefixedArray(
+                    subcon=self.Dwarf_uint8('elem'),
+                    length_field=length_field(''))
+
 
 class _InitialLengthAdapter(Adapter):
     """ A standard Construct adapter that expects a sub-construct
@@ -171,3 +216,4 @@ def _SLEB128(name):
     """
     return Rename(name, _SLEB128Adapter(_LEB128_reader()))
 
+
diff --git a/z.py b/z.py
index 648145895b2dc5db21f6275a8d4769290e658a70..013a7c7297937813bd1895360f4ab25493d4fbd4 100644 (file)
--- a/z.py
+++ b/z.py
@@ -21,14 +21,21 @@ print efile.has_dwarf_info()
 
 dwarfinfo = efile.get_dwarf_info()
 
+cu = dwarfinfo.get_CU(1)
+print cu.get_top_DIE()
+
 #~ print dwarfinfo.structs.Dwarf_abbrev_entry.parse('\x13\x01\x01\x03\x50\x04\x00\x00')
 
-print id(dwarfinfo.get_abbrev_table(0))
-print id(dwarfinfo.get_abbrev_table(0))
-pprint.pprint(dwarfinfo.get_abbrev_table(0)._abbrev_map)
+#~ abbrevtable = dwarfinfo.get_abbrev_table(95)
+#~ print id(abbrevtable)
+#~ pprint.pprint(abbrevtable._abbrev_map)
+
+#~ ab1 = abbrevtable.get_abbrev(2)
+#~ print ab1.has_children()
+#~ for name, form in ab1.iter_attr_specs():
+    #~ print name, form
 
-print dwarfinfo.get_abbrev_table(0).get_abbrev(1).decl
-print dwarfinfo.get_abbrev_table(0).get_abbrev(1).has_children()
+#~ print dwarfinfo.get_abbrev_table(0).get_abbrev(1).has_children()
 
 #~ for cu in dwarfinfo._CU:
     #~ print cu, cu.header
diff --git a/zd.py b/zd.py
index 54af0f79d4cd36af3c2fbe58ec53a3cc57ffb110..e5a4503460c0a3615a1659a54ce4fee3fde1841b 100644 (file)
--- a/zd.py
+++ b/zd.py
@@ -6,11 +6,16 @@ from elftools.dwarf.structs import DWARFStructs
 from elftools.dwarf.dwarfinfo import DWARFInfo\r
 \r
 \r
-ds = DWARFStructs(little_endian=True,\r
-    dwarfclass=32)\r
+ds = DWARFStructs(little_endian=True, dwarf_format=32)\r
 \r
-print ds.Dwarf_xword('x').parse('\x04\x01\x00\x00')\r
+print ds.Dwarf_offset('x').parse('\x04\x01\x00\x00')\r
 print ds.Dwarf_initial_length('joe').parse('\xff\xff\xff\xff\x32\x00\x00\x00\x00\x00\x00\x00')\r
 \r
 \r
 print ds.Dwarf_sleb128('kwa').parse('\x81\x7f')\r
+\r
+s = ds.Dwarf_dw_form['DW_FORM_block']\r
+#~ s = ds.Dwarf_dw_form['DW_FORM_addr']\r
+\r
+print s.parse('\x04\x12\x13\x13\x16')\r
+#~ print s.parse('\x04\x00\x12\x13')\r