comparison paraspace/dexfile.py @ 104:61cef1662035

Redirect types
author Thinker K.F. Li <thinker@codemud.net>
date Thu, 28 Jul 2011 00:06:54 +0800
parents 7fcd555d802b
children 7821c6e89622
comparison
equal deleted inserted replaced
103:8a53e6f7f517 104:61cef1662035
1029 pass 1029 pass
1030 1030
1031 1031
1032 class _DEX_TypeList(composite): 1032 class _DEX_TypeList(composite):
1033 num = uint32 1033 num = uint32
1034 typeItems = array('num', uint16) 1034 typeItems = array('num', depend_idx('DEXFile.typeIds')(uint16))
1035 1035
1036 child_names = 'num typeItems'.split() 1036 child_names = 'num typeItems'.split()
1037 pass 1037 pass
1038 1038
1039 1039
1691 return linked 1691 return linked
1692 1692
1693 ## \brief Return name string of a linked class definition item 1693 ## \brief Return name string of a linked class definition item
1694 @staticmethod 1694 @staticmethod
1695 def get_classdef_name(classdef): 1695 def get_classdef_name(classdef):
1696 return classdef.classIdx.descriptorIdx.stringDataOff.data.data 1696 return DEXFile_linked.get_typeid_name(classdef.classIdx)
1697
1698 ## \brief Return name string of a linked type ID item.
1699 @staticmethod
1700 def get_typeid_name(typeid):
1701 return typeid.descriptorIdx.stringDataOff.data.data
1702
1703 ## \brief Get index of given type ID.
1704 def get_idx_typeid(self, typeid):
1705 return self.typeIds.items.index(typeid)
1706
1707 ## \brief Find type ID item with given name.
1708 def find_typeid_name(self, name):
1709 for typeid in self.typeIds.items:
1710 typeid_name = DEXFile_linked.get_typeid_name(typeid)
1711 if typeid_name == name:
1712 return typeid
1713 pass
1714 pass
1715
1716 ## \brief Return type ID item with given index.
1717 def find_typeid_idx(self, idx):
1718 return self.typeIds.items[idx]
1697 1719
1698 def find_class_name(self, name): 1720 def find_class_name(self, name):
1699 for classdef in self.classDefs.items: 1721 for classdef in self.classDefs.items:
1700 classdef_name = DEXFile_linked.get_classdef_name(classdef) 1722 classdef_name = DEXFile_linked.get_classdef_name(classdef)
1701 if classdef_name == name: 1723 if classdef_name == name:
1702 return classdef 1724 return classdef
1703 pass 1725 pass
1704 raise ValueError, 'can not find class definition for \'%s\'' % (name) 1726 raise ValueError, 'can not find class definition for \'%s\'' % (name)
1727
1728 ## \brief Return a class definition corresponding for give type ID.
1729 def find_class_typeid(self, typeid):
1730 for classdef in self.classDefs.items:
1731 if classdef.classIdx == typeid:
1732 return classdef
1733 pass
1734 raise ValueError, \
1735 'can not find class definition for typeid %s' % (repr(typeid))
1705 1736
1706 ## \brief Update size of map items. 1737 ## \brief Update size of map items.
1707 # 1738 #
1708 # Corresponding data lists of maps may be changed, it should be updated 1739 # Corresponding data lists of maps may be changed, it should be updated
1709 # before restore dependencies and keep it consistent. 1740 # before restore dependencies and keep it consistent.
1767 wmethod_name = DEXFile_linked.get_method_name(wmethod) 1798 wmethod_name = DEXFile_linked.get_method_name(wmethod)
1768 if method_name == wmethod_name: 1799 if method_name == wmethod_name:
1769 return wmethod 1800 return wmethod
1770 pass 1801 pass
1771 pass 1802 pass
1803
1804 ## \brief Get name of given method ID.
1805 @staticmethod
1806 def get_methodid_name(methoid):
1807 return methoid.nameIdx.stringDataOff.data.data
1808
1809 ## \brief Find the method ID item of given index.
1810 def find_methodid_idx(self, idx):
1811 methodid = self.methodIds.items[idx]
1812 return methodid
1813
1814 ## \brief Find a method definition with an index to method ID.
1815 def find_method_idx(self, idx):
1816 methodid = self.find_methodid_idx(idx)
1817 method_name = DEXFile_linked.get_methoid_name(methodid)
1818 method_proto = methodid.protoIdx
1819 method_typeid = methodid.classIdx
1820 classdef = self.find_class_typeid(method_typeid)
1821
1822 method = self.find_method_name_proto(method, method_proto, classdef)
1823
1824 return method
1825
1826 ## \brief Test if prototype of two methods are compatible.
1827 @staticmethod
1828 def _proto_is_compatible(proto1, proto2):
1829 if proto1.returnTypeIdx != proto2.returnTypeIdx:
1830 return False
1831 typelist1 = proto1.parametersOffRef.value
1832 typelist2 = proto2.parametersOffRef.value
1833 if len(typelist1.typeItems.items) != len(typelist2.typeItems.items):
1834 return False
1835
1836 for typeid1, typeid2 in map(None,
1837 typelist1.typeItems.items,
1838 typelist2.typeItems.items):
1839 if typeid1 != typeid2:
1840 return False
1841 pass
1842 return True
1843
1844 def find_method_name_proto(self, method_name, proto, classdef):
1845 if not classdef.classDataOffRef.is_true:
1846 return
1847
1848 classdata = classdef.classDataOffRef.value
1849 for wmethod in classdata.directMethods.items + \
1850 classdata.virtualMethods.items:
1851 wmethod_name = DEXFile_linked.get_method_name(wmethod)
1852 if method_name != wmethod_name:
1853 continue
1854 if DEXFile_linked._proto_is_compatible(wmethod.protoIdx, proto):
1855 return wmethod
1856 pass
1857 raise ValueError, 'can not find a method for given name and prototype'
1772 pass 1858 pass
1773 1859
1774 1860
1775 if __name__ == '__main__': 1861 if __name__ == '__main__':
1776 import sys 1862 import sys