changeset 11:409e2cd76f72

Parse DebugInfoItem
author Thinker K.F. Li <thinker@codemud.net>
date Wed, 25 May 2011 01:11:43 +0800
parents 123c7a8bbf4c
children 8101024c942b
files paraspace/dexfile.py
diffstat 1 files changed, 127 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/paraspace/dexfile.py	Tue May 24 23:47:16 2011 +0800
+++ b/paraspace/dexfile.py	Wed May 25 01:11:43 2011 +0800
@@ -893,6 +893,108 @@
     pass
 
 
+class _DEX_DebugInfoItem(object):
+    start_line = None
+    parameters = None
+    opcodes = None
+    
+    DBG_END_SEQUENCE = 0x00
+    DBG_ADVANCE_PC = 0x01
+    DBG_ADVANCE_LINE = 0x02
+    DBG_START_LOCAL = 0x03
+    DBG_START_LOCAL_EXTENDED = 0x04
+    DBG_END_LOCAL = 0x05
+    DBG_RESTART_LOCAL = 0x06
+    DBG_SET_PROLOGUE_END = 0x07
+    DBG_SET_EPILOGUE_BEGIN = 0x08
+    DBG_SET_FILE = 0x09
+    DBG_FIRST_SPECIAL = 0x0a
+    DBG_LINE_BASE = -4
+    DBG_LINE_RANGE = 15
+
+    data_size = None
+
+    def parse(self, data, off):
+        moff = man_off(off)
+
+        self.start_line, sh = _uleb128(data[moff():moff() + 5])
+        moff(sh)
+        parameters_size, sh = _uleb128(data[moff():moff() + 5])
+        moff(sh)
+
+        #
+        # Parse parameters
+        #
+        def parse_parameter():
+            paramter, sh = _uleb128(data[moff():moff() + 5])
+            moff(sh)
+            return paramter
+        
+        self.parameters = [parse_parameter()
+                           for i in range(parameters_size)]
+
+        #
+        # Parse debug opcodes
+        #
+        opcodes = []
+        while True:
+            opcode = _to_uint(data[moff(1):moff()])
+
+            if opcode == self.DBG_END_SEQUENCE:
+                opcodes.append((opcode,))
+                break
+            elif opcode == self.DBG_ADVANCE_PC:
+                adv, sh = _uleb128(data[moff():moff() + 5])
+                moff(sh)
+                opcodes.append((opcode, adv))
+                pass
+            elif opcode == self.DBG_ADVANCE_LINE:
+                adv, sh = _uleb128(data[moff():moff() + 5])
+                moff(sh)
+                opcodes.append((opcode, adv))
+                pass
+            elif opcode in (self.DBG_START_LOCAL,
+                            self.DBG_START_LOCAL_EXTENDED):
+                reg, sh = _uleb128(data[moff():moff() + 5])
+                moff(sh)
+                name, sh = _uleb128(data[moff():moff() + 5])
+                moff(sh)
+                descriptor, sh = _uleb128(data[moff():moff() + 5])
+                moff(sh)
+                if opcode == self.DBG_START_LOCAL_EXTENDED:
+                    signature, sh = _uleb128(data[moff():moff() + 5])
+                    moff(sh)
+                    opcodes.append((opcode, reg, name, descriptor, signature))
+                else:
+                    opcodes.append((opcode, reg, name, descriptor))
+                    pass
+                pass
+            elif opcode == self.DBG_END_LOCAL:
+                reg, sh = _uleb128(data[moff():moff() + 5])
+                moff(sh)
+                opcodes.append((opcode, reg))
+                pass
+            elif opcode == self.DBG_RESTART_LOCAL:
+                reg, sh = _uleb128(data[moff():moff() + 5])
+                moff(sh)
+                opcodes.append((opcode, reg))
+                pass
+            elif opcode in (self.DBG_SET_PROLOGUE_END,
+                            self.DBG_SET_EPILOGUE_BEGIN,
+                            self.DBG_SET_FILE):
+                opcodes.append((opcode,))
+                pass
+            else:
+                opcodes.append((opcode,))
+                pass
+            pass
+        self.opcodes = opcodes
+        
+        self.data_size = moff() - off
+        pass
+    pass
+
+
 class DEXFile(object):
     _data = None
     _header = None
@@ -910,6 +1012,7 @@
     _annotationsDirectoryItems = None
     _annotationItems = None
     _encodedArrayItems = None
+    _debugInfoItems = None
     
     def __init__(self):
         pass
@@ -1215,6 +1318,24 @@
                                    for i in range(encodedArrayItem_map.size)]
         pass
 
+    def _parse_debugInfoItems(self):
+        data = self._data
+
+        debugInfoItem_map = \
+            self.find_map_item_name('kDexTypeDebugInfoItem')
+        
+        moff = man_off(debugInfoItem_map.offset)
+
+        def parse_debugInfoItem():
+            item = _DEX_DebugInfoItem()
+            item.parse(data, moff())
+            moff(item.data_size)
+            return item
+
+        self._debugInfoItems = [parse_debugInfoItem()
+                                for i in range(debugInfoItem_map.size)]
+        pass
+
     def parse(self, data):
         self._data = data
         self._parse_header()
@@ -1232,6 +1353,7 @@
         self._parse_annotationsDirectoryItems()
         self._parse_annotationItems()
         self._parse_encodedArrayItems()
+        self._parse_debugInfoItems()
         pass
     pass
 
@@ -1310,6 +1432,11 @@
     print
     print 'EncodedArrayItems size is %d bytes' % (bytes)
     
+    bytes = sum([debuginfoitem.data_size
+                 for debuginfoitem in dex._debugInfoItems])
+    print
+    print 'DebugInfoItems size is %d bytes' % (bytes)
+    
     print
     print 'Data maps'
     maps = dex._maps