Mercurial > paraspace
changeset 8:59dd10bf60f2
Parse annotation items
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Tue, 24 May 2011 14:55:18 +0800 |
parents | 1d776ec496e5 |
children | 9a49826b26d4 |
files | paraspace/dexfile.py |
diffstat | 1 files changed, 212 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/paraspace/dexfile.py Tue May 24 10:28:30 2011 +0800 +++ b/paraspace/dexfile.py Tue May 24 14:55:18 2011 +0800 @@ -75,6 +75,15 @@ return v +def _to_int(data): + v = _to_uint(data) + sz = len(data) + if sz and ((1 << (sz * 8 - 1)) & v): + v = -((1 << (sz * 8)) - v) + pass + return v + + def _uleb128(data): sh = 0 v = 0 @@ -682,6 +691,183 @@ pass +## +# +# \see createAnnotationMember() in dalvik/vm/reflect/Annotation.c +# +class _DEX_AnnotationMember(object): + nameIdx = None # optional + valueType = None # 1 byte + value = None + + # + # Constants from DexFile.h + # + kDexAnnotationByte = 0x00 + kDexAnnotationShort = 0x02 + kDexAnnotationChar = 0x03 + kDexAnnotationInt = 0x04 + kDexAnnotationLong = 0x06 + kDexAnnotationFloat = 0x10 + kDexAnnotationDouble = 0x11 + kDexAnnotationString = 0x17 + kDexAnnotationType = 0x18 + kDexAnnotationField = 0x19 + kDexAnnotationMethod = 0x1a + kDexAnnotationEnum = 0x1b + kDexAnnotationArray = 0x1c + kDexAnnotationAnnotation = 0x1d + kDexAnnotationNull = 0x1e + kDexAnnotationBoolean = 0x1f + + kDexAnnotationValueTypeMask = 0x1f + kDexAnnotationValueArgShift = 5 + + data_size = None + + def parse(self, data, off): + self.nameIdx, sh = _uleb128(data[off:off + 5]) + + self.parse_noname(data, off + sh) + + self.data_size = self.data_size + sh + pass + + def parse_noname(self, data, off): + moff = man_off(off) + + valueType = _to_uint(data[moff(1):moff()]) + self.valueType = valueType + width = valueType >> self.kDexAnnotationValueArgShift + + vtype = valueType & self.kDexAnnotationValueTypeMask + + if vtype == self.kDexAnnotationByte: + self.value = _to_int(data[moff(width):moff()]) + moff(1) + pass + elif vtype == self.kDexAnnotationShort: + self.value = _to_int(data[moff(width):moff()]) + pass + elif vtype == self.kDexAnnotationChar: + self.value = _to_uint(data[moff(width):moff()]) + moff(1) + pass + elif vtype == self.kDexAnnotationInt: + self.value = _to_int(data[moff(width):moff()]) + moff(1) + pass + elif vtype == self.kDexAnnotationLong: + self.value = _to_int(data[moff(width):moff()]) + moff(1) + pass + elif vtype == self.kDexAnnotationFloat: + self.value = _to_uint(data[moff(width):moff()]) + moff(1) + pass + elif vtype == self.kDexAnnotationDouble: + self.value = _to_uint(data[moff(width):moff()]) + moff(1) + pass + elif vtype == self.kDexAnnotationBoolean: + self.value = width != 0 + pass + elif vtype == self.kDexAnnotationString: # string index + self.value = _to_uint(data[moff(width):moff()]) + moff(1) + pass + elif vtype == self.kDexAnnotationType: # TypeId index + self.value = _to_uint(data[moff(width):moff()]) + moff(1) + pass + elif vtype == self.kDexAnnotationMethod: # MethodId index + self.value = _to_uint(data[moff(width):moff()]) + moff(1) + pass + elif vtype == self.kDexAnnotationField: + self.value = _to_uint(data[moff(width):moff()]) + moff(1) + pass + elif vtype == self.kDexAnnotationEnum: # FieldId index + self.value = _to_uint(data[moff(width):moff()]) + moff(1) + pass + elif vtype == self.kDexAnnotationArray: + size, sh = _uleb128(data[moff():moff() + 5]) + moff(sh) + + def parse_array_elm(): + elm = _DEX_AnnotationMember() + elm.parse_noname(data, moff()) + moff(elm.data_size) + return elm + + self.value = [parse_array_elm() + for i in range(size)] + pass + elif vtype == self.kDexAnnotationAnnotation: + annoitem = _DEX_AnnotationItem() + annoitem.parse_novisibility(data, moff()) + moff(annoitem.data_size) + self.value = annoitem + pass + elif vtype == self.kDexAnnotationNull: + self.value = 0 + pass + else: + raise ValueError, \ + 'Bad annotation element value byte 0x02x' % (valueType) + + self.data_size = moff() - off + pass + pass + + +## \brief Annotation item +# +# \see processEncodedAnnotation() in dalvik/vm/reflect/Annotation.c +# +class _DEX_AnnotationItem(object): + visibility = None # 1 byte (optional) + typeIdx = None + members = None + + kDexVisibilityBuild = 0x00 + kDexVisibilityRuntime = 0x01 + kDexVisibilitySystem = 0x02 + + data_size = None + + def parse(self, data, off): + self.visibility = _to_uint(data[off:off + 1]) + + self.parse_novisibility(data, off + 1) + + self.data_size = self.data_size + 1 + pass + + def parse_novisibility(self, data, off): + moff = man_off(off) + + self.typeIdx, sh = _uleb128(data[moff():moff() + 5]) + moff(sh) + size, sh = _uleb128(data[moff():moff() + 5]) + moff(sh) + + def parse_AnnotationMemmber(): + member = _DEX_AnnotationMember() + member.parse(data, moff()) + moff(member.data_size) + return member + + self.members = [parse_AnnotationMemmber() + for i in range(size)] + + self.data_size = moff() - off + pass + pass + + class DEXFile(object): _data = None _header = None @@ -697,6 +883,7 @@ _codeItems = None _annotationSetItems = None _annotationsDirectoryItems = None + _annotationItems = None def __init__(self): pass @@ -958,6 +1145,25 @@ for i in range(annodir_map.size)] pass + def _parse_annotationItems(self): + data = self._data + + annoitem_map = self.find_map_item_name('kDexTypeAnnotationItem') + if annoitem_map is None: + return + + moff = man_off(annoitem_map.offset) + + def parse_annotationItem(): + item = _DEX_AnnotationItem() + item.parse(data, moff()) + moff(item.data_size) + return item + + self._annotationItems = [parse_annotationItem() + for i in range(annoitem_map.size)] + pass + def parse(self, data): self._data = data header = _DEX_header() @@ -976,6 +1182,7 @@ self._parse_codeItems() self._parse_annotationSetItems() self._parse_annotationsDirectoryItems() + self._parse_annotationItems() pass pass @@ -1044,6 +1251,11 @@ print print 'AnnotationsDirtoryItems size is %d bytes' % (bytes) + bytes = sum([annoitem.data_size + for annoitem in dex._annotationItems]) + print + print 'AnnotationItems size is %d bytes' % (bytes) + print print 'Data maps' maps = dex._maps