comparison paraspace/dexfile.py @ 1:05346b632adb

Parse records mentioned in file header
author Thinker K.F. Li <thinker@codemud.net>
date Sun, 22 May 2011 02:16:20 +0800
parents 31050a971b52
children add64d56b0e2
comparison
equal deleted inserted replaced
0:31050a971b52 1:05346b632adb
44 pass 44 pass
45 45
46 46
47 def _to_uint(data): 47 def _to_uint(data):
48 v = 0 48 v = 0
49 sh = 0
49 for c in data: 50 for c in data:
50 v = (v << 8) + ord(c) 51 v = v + (ord(c) << sh)
52 sh = sh + 8
51 pass 53 pass
52 return v 54 return v
55
56
57 def _uleb128(data):
58 sh = 0
59 v = 0
60 for c in data:
61 cv = ord(c)
62 v = v + ((cv & 0x7f) << sh)
63 sh = sh + 7
64
65 if cv <= 0x7f:
66 break
67 pass
68
69 nbytes = sh / 7
70 return v, nbytes
53 71
54 72
55 class _DEX_MapItem(object): 73 class _DEX_MapItem(object):
56 type = None # 2 bytes 74 type = None # 2 bytes
57 unused = None # 2 bytes 75 unused = None # 2 bytes
65 self.size = _to_uint(data[4:8]) 83 self.size = _to_uint(data[4:8])
66 self.offset = _to_uint(data[8:12]) 84 self.offset = _to_uint(data[8:12])
67 pass 85 pass
68 pass 86 pass
69 87
88
70 class _DEX_TypeId(object): 89 class _DEX_TypeId(object):
71 descriptorIdx = None # 4 bytes 90 descriptorIdx = None # 4 bytes
72 91
73 data_size = 4 92 data_size = 4
74 93
92 pass 111 pass
93 pass 112 pass
94 113
95 114
96 class _DEX_FieldId(object): 115 class _DEX_FieldId(object):
97 classIdx # 2 bytes 116 classIdx = None # 2 bytes
98 typeIdx # 2 bytes 117 typeIdx = None # 2 bytes
99 nameIdx # 4 bytes 118 nameIdx = None # 4 bytes
100 119
101 data_size = 8 120 data_size = 8
102 121
103 def parse(self, data): 122 def parse(self, data):
104 self.classIdx = _to_uint(data[:2]) 123 self.classIdx = _to_uint(data[:2])
107 pass 126 pass
108 pass 127 pass
109 128
110 129
111 class _DEX_MethodId(object): 130 class _DEX_MethodId(object):
112 classIdx # 2 bytes 131 classIdx = None # 2 bytes
113 protoIdx # 2 bytes 132 protoIdx = None # 2 bytes
114 nameIdx # 4 bytes 133 nameIdx = None # 4 bytes
115 134
116 data_size = 8 135 data_size = 8
117 136
118 def parse(self, data): 137 def parse(self, data):
119 self.classIdx = _to_uint(data[:2]) 138 self.classIdx = _to_uint(data[:2])
120 self.protoIdx = _to_uint(data[2:4]) 139 self.protoIdx = _to_uint(data[2:4])
121 self.nameIdx = _to_uint(data[4:8]) 140 self.nameIdx = _to_uint(data[4:8])
122 pass 141 pass
123 pass 142 pass
143
124 144
125 class _DEX_ClassDef(object): 145 class _DEX_ClassDef(object):
126 classIdx = None # 0x00 146 classIdx = None # 0x00
127 accessFlags = None # 0x04 147 accessFlags = None # 0x04
128 superclassIdx = None # 0x08 148 superclassIdx = None # 0x08
148 168
149 169
150 class DEXFile(object): 170 class DEXFile(object):
151 _data = None 171 _data = None
152 _header = None 172 _header = None
173 _maps = None
153 _strings = None 174 _strings = None
175 _typeIds = None
176 _protoIds = None
177 _fieldIds = None
178 _methodIds = None
179 _classDefs = None
154 180
155 def __init__(self): 181 def __init__(self):
156 pass 182 pass
157 183
158 def open(self, filename): 184 def open(self, filename):
159 fo = file(filename) 185 fo = file(filename, 'r')
160 data = fo.read() 186 data = fo.read()
161 187
162 self.parse(data) 188 self.parse(data)
189 pass
190
191 def _parse_maps(self):
192 data = self._data
193 header = self._header
194 off = header.mapOff
195
196 num = _to_uint(data[off:off + 4])
197 off = off + 4
198
199 maps = []
200 for i in range(num):
201 item_data = data[off:off + _DEX_MapItem.data_size]
202 item = _DEX_MapItem()
203 item.parse(item_data)
204 maps.append(item)
205 off = off + _DEX_MapItem.data_size
206 pass
207
208 self._maps = map
209 pass
210
211 def _parse_strings(self):
212 data = self._data
213 header = self._header
214 strings = []
215
216 num = header.stringIdsSize
217 off = header.stringIdsOff
218 for i in range(num):
219 str_start_off = _to_uint(data[off:off + 4])
220 str_stop_off = data.index('\x00', str_start_off)
221 string = data[str_start_off:str_stop_off]
222
223 sz, sh = _uleb128(string)
224 string = string[sh:]
225 strings.append(string)
226 off = off + 4
227 pass
228
229 self._strings = strings
230 pass
231
232 def _parse_typeIds(self):
233 data = self._data
234 header = self._header
235
236 num = header.typeIdsSize
237 off = header.typeIdsOff
238
239 def parse(item_data):
240 type_id = _DEX_TypeId()
241 type_id.parse(item_data)
242 return type_id
243
244 item_size = _DEX_TypeId.data_size
245 item_offs = range(off, off + item_size * num, item_size)
246 item_datas = [data[item_off:item_off + item_size]
247 for item_off in item_offs]
248 typeIds = [parse(item_data) for item_data in item_datas]
249
250 self._typeIds = typeIds
251 pass
252
253 def _parse_protoIds(self):
254 data = self._data
255 header = self._header
256
257 num = header.protoIdsSize
258 off = header.protoIdsOff
259
260 def parse(item_data):
261 proto_id = _DEX_ProtoId()
262 proto_id.parse(item_data)
263 return proto_id
264
265 item_size = _DEX_ProtoId.data_size
266 item_offs = range(off, off + item_size * num, item_size)
267 item_datas = [data[item_off:item_off + item_size]
268 for item_off in item_offs]
269 protoIds = [parse(item_data) for item_data in item_datas]
270
271 self._protoIds = protoIds
272 pass
273
274 def _parse_fieldIds(self):
275 data = self._data
276 header = self._header
277
278 num = header.fieldIdsSize
279 off = header.fieldIdsOff
280
281 def parse(item_data):
282 field_id = _DEX_FieldId()
283 field_id.parse(item_data)
284 return field_id
285
286 item_size = _DEX_FieldId.data_size
287 item_offs = range(off, off + item_size * num, item_size)
288 item_datas = [data[item_off:item_off + item_size]
289 for item_off in item_offs]
290 fieldIds = [parse(item_data) for item_data in item_datas]
291
292 self._fieldIds = fieldIds
293 pass
294
295 def _parse_methodIds(self):
296 data = self._data
297 header = self._header
298
299 num = header.methodIdsSize
300 off = header.methodIdsOff
301
302 def parse(item_data):
303 method_id = _DEX_MethodId()
304 method_id.parse(item_data)
305 return method_id
306
307 item_size = _DEX_MethodId.data_size
308 item_offs = range(off, off + item_size * num, item_size)
309 item_datas = [data[item_off:item_off + item_size]
310 for item_off in item_offs]
311 methodIds = [parse(item_data) for item_data in item_datas]
312
313 self._methodIds = methodIds
314 pass
315
316 def _parse_classDefs(self):
317 data = self._data
318 header = self._header
319
320 num = header.classDefsSize
321 off = header.classDefsOff
322
323 def parse(item_data):
324 class_def = _DEX_ClassDef()
325 class_def.parse(item_data)
326 return class_def
327
328 item_size = _DEX_ClassDef.data_size
329 item_offs = range(off, off + item_size * num, item_size)
330 item_datas = [data[item_off:item_off + item_size]
331 for item_off in item_offs]
332 classDefs = [parse(item_data) for item_data in item_datas]
333
334 self._classDefs = classDefs
163 pass 335 pass
164 336
165 def parse(self, data): 337 def parse(self, data):
166 self._data = data 338 self._data = data
167 header = _DEX_header() 339 header = _DEX_header()
168 header.parse(data) 340 header.parse(data)
169 self._header = header 341 self._header = header
170 pass 342
171 pass 343 self._parse_maps()
344 self._parse_strings()
345 self._parse_typeIds()
346 self._parse_protoIds()
347 self._parse_fieldIds()
348 self._parse_methodIds()
349 self._parse_classDefs()
350 pass
351 pass
352
353 if __name__ == '__main__':
354 dex = DEXFile()
355 dex.open('test.dex')
356
357 h = dex._header
358 for attr in h.__dict__.keys():
359 print '%s: %s' % (attr, repr(h.__dict__[attr]))
360 pass
361
362 print
363 print 'Define Classes'
364 strings = dex._strings
365 classDefs = dex._classDefs
366 typeIds = dex._typeIds
367 for classDef in classDefs:
368 typeId = typeIds[classDef.classIdx]
369 descriptor = strings[typeId.descriptorIdx]
370 print descriptor
371 pass
372
373 print
374 print 'Reference Classes'
375 for typeId in typeIds:
376 descriptor = strings[typeId.descriptorIdx]
377 print descriptor
378 pass
379 pass