Mercurial > paraspace
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 |