13
13
// limitations under the License.
14
14
use std:: collections:: HashSet ;
15
15
// use std::fmt;
16
+ use std:: ops:: Deref ;
16
17
use std:: str;
17
18
18
19
use strings:: * ;
@@ -21,7 +22,7 @@ use dalvik::{DalvikInstruction, parse_bytecode};
21
22
22
23
const NO_INDEX : u32 = 0xFFFFFFFF ;
23
24
24
- fn type_list < ' a > ( dex : & ' a DexFile < ' a > , off : u32 , parse_cls_desc : bool ) -> Vec < & ' a bstr > {
25
+ fn type_list < ' a > ( dex : & DexFileNoProtos < ' a > , off : u32 , parse_cls_desc : bool ) -> Vec < & ' a bstr > {
25
26
if off == 0 { return Vec :: new ( ) ; }
26
27
27
28
let mut st = dex. stream ( off) ;
@@ -89,7 +90,7 @@ pub struct FieldId<'a> {
89
90
pub desc : & ' a bstr ,
90
91
}
91
92
impl < ' a > FieldId < ' a > {
92
- fn new ( dex : & ' a DexFile < ' a > , field_idx : u32 ) -> FieldId < ' a > {
93
+ fn new ( dex : & DexFile < ' a > , field_idx : u32 ) -> FieldId < ' a > {
93
94
let mut st = dex. stream ( dex. field_ids . off + field_idx* 8 ) ;
94
95
FieldId {
95
96
cname : dex. cls_type ( st. u16 ( ) as u32 ) ,
@@ -191,15 +192,30 @@ impl<'a> CodeItem<'a> {
191
192
}
192
193
}
193
194
195
+ fn parse_prototype < ' a > ( dex : & DexFileNoProtos < ' a > , proto_idx : u32 ) -> ( BString , Vec < & ' a bstr > , & ' a bstr ) {
196
+ let mut st = dex. stream ( dex. proto_ids . off + proto_idx * 12 ) ;
197
+ st. u32 ( ) ;
198
+ let return_type = dex. raw_type ( st. u32 ( ) ) ;
199
+ let param_types = type_list ( dex, st. u32 ( ) , false ) ;
200
+
201
+ let mut desc = vec ! [ b'(' ] ;
202
+ for part in & param_types {
203
+ desc. extend_from_slice ( part) ;
204
+ }
205
+ desc. push ( b')' ) ;
206
+ desc. extend_from_slice ( return_type) ;
207
+ ( desc, param_types, return_type)
208
+ }
209
+
194
210
pub struct MethodId < ' a > {
195
211
pub cname : & ' a bstr ,
196
212
pub name : & ' a bstr ,
197
- pub desc : BString ,
213
+ pub desc : & ' a bstr ,
198
214
pub return_type : & ' a bstr ,
199
215
pub method_idx : u32 ,
200
216
217
+ proto_idx : u32 ,
201
218
cdesc : & ' a bstr ,
202
- param_types : Vec < & ' a bstr > ,
203
219
}
204
220
impl < ' a > MethodId < ' a > {
205
221
fn new ( dex : & ' a DexFile < ' a > , method_idx : u32 ) -> MethodId < ' a > {
@@ -209,35 +225,24 @@ impl<'a> MethodId<'a> {
209
225
let proto_idx = st. u16 ( ) as u32 ;
210
226
let name = dex. string ( st. u32 ( ) ) ;
211
227
212
- st = dex. stream ( dex. proto_ids . off + proto_idx * 12 ) ;
213
- st. u32 ( ) ;
214
- let return_type = dex. raw_type ( st. u32 ( ) ) ;
215
- let param_types = type_list ( dex, st. u32 ( ) , false ) ;
216
-
217
- let mut desc = vec ! [ b'(' ] ;
218
- for part in & param_types {
219
- desc. extend_from_slice ( part) ;
220
- }
221
- desc. push ( b')' ) ;
222
- desc. extend_from_slice ( return_type) ;
223
-
224
228
MethodId {
225
229
cname : cname,
226
230
name : name,
227
- desc : desc ,
228
- return_type : return_type ,
231
+ desc : & dex . proto ( proto_idx ) . 0 ,
232
+ return_type : dex . proto ( proto_idx ) . 2 ,
229
233
method_idx : method_idx,
234
+ proto_idx : proto_idx,
230
235
231
236
cdesc : dex. raw_type ( cname_idx) ,
232
- param_types : param_types,
233
237
}
234
238
}
235
239
236
- pub fn spaced_param_types ( & self , isstatic : bool ) -> Vec < Option < & ' a bstr > > {
237
- let mut res = Vec :: with_capacity ( self . param_types . len ( ) + 1 ) ;
240
+ pub fn spaced_param_types ( & self , dex : & DexFile < ' a > , isstatic : bool ) -> Vec < Option < & ' a bstr > > {
241
+ let param_types = & dex. proto ( self . proto_idx ) . 1 ;
242
+ let mut res = Vec :: with_capacity ( param_types. len ( ) + 1 ) ;
238
243
if !isstatic { res. push ( Some ( self . cdesc ) ) ; }
239
244
240
- for param in & self . param_types {
245
+ for param in param_types {
241
246
res. push ( Some ( param) ) ;
242
247
if param[ 0 ] == b'J' || param[ 0 ] == b'D' { res. push ( None ) ; }
243
248
}
@@ -350,19 +355,17 @@ impl SizeOff {
350
355
}
351
356
}
352
357
353
- #[ allow( dead_code) ] //data is not used
354
- pub struct DexFile < ' a > {
358
+ pub struct DexFileNoProtos < ' a > {
355
359
raw : & ' a bstr ,
356
360
string_ids : SizeOff ,
357
361
type_ids : SizeOff ,
358
362
proto_ids : SizeOff ,
359
363
field_ids : SizeOff ,
360
364
method_ids : SizeOff ,
361
365
class_defs : SizeOff ,
362
- data : SizeOff ,
363
366
}
364
- impl < ' a > DexFile < ' a > {
365
- pub fn new ( data : & bstr ) -> DexFile {
367
+ impl < ' a > DexFileNoProtos < ' a > {
368
+ pub fn new ( data : & bstr ) -> DexFileNoProtos {
366
369
let mut stream = Reader ( data) ;
367
370
stream. read ( 36 ) ;
368
371
if stream. u32 ( ) != 0x70 {
@@ -375,24 +378,17 @@ impl<'a> DexFile<'a> {
375
378
SizeOff :: new ( & mut stream) ;
376
379
stream. u32 ( ) ;
377
380
378
- DexFile {
381
+ DexFileNoProtos {
379
382
raw : data,
380
383
string_ids : SizeOff :: new ( & mut stream) ,
381
384
type_ids : SizeOff :: new ( & mut stream) ,
382
385
proto_ids : SizeOff :: new ( & mut stream) ,
383
386
field_ids : SizeOff :: new ( & mut stream) ,
384
387
method_ids : SizeOff :: new ( & mut stream) ,
385
388
class_defs : SizeOff :: new ( & mut stream) ,
386
- data : SizeOff :: new ( & mut stream) ,
389
+ // data: SizeOff::new(&mut stream),
387
390
}
388
391
}
389
- pub fn parse_classes ( & ' a self ) -> Vec < DexClass < ' a > > {
390
- let mut classes = Vec :: with_capacity ( self . class_defs . size as usize ) ;
391
- for i in 0 ..self . class_defs . size {
392
- classes. push ( DexClass :: new ( & self , self . class_defs . off , i) ) ;
393
- }
394
- classes
395
- }
396
392
397
393
fn stream ( & self , offset : u32 ) -> Reader < ' a > {
398
394
Reader ( self . raw . split_at ( offset as usize ) . 1 )
@@ -401,29 +397,58 @@ impl<'a> DexFile<'a> {
401
397
self . stream ( i) . u32 ( )
402
398
}
403
399
404
- pub fn string ( & self , i : u32 ) -> & bstr {
400
+ pub fn string ( & self , i : u32 ) -> & ' a bstr {
405
401
let data_off = self . u32 ( self . string_ids . off + i* 4 ) ;
406
402
let mut stream = self . stream ( data_off) ;
407
403
stream. uleb128 ( ) ; // Ignore decoded length
408
404
stream. cstr ( )
409
405
}
410
406
411
- pub fn raw_type ( & self , i : u32 ) -> & bstr {
407
+ pub fn raw_type ( & self , i : u32 ) -> & ' a bstr {
412
408
assert ! ( i < self . type_ids. size) ;
413
409
self . string ( self . u32 ( self . type_ids . off + i* 4 ) )
414
410
}
415
411
416
- pub fn cls_type ( & self , i : u32 ) -> & bstr {
412
+ pub fn cls_type ( & self , i : u32 ) -> & ' a bstr {
417
413
let data = self . raw_type ( i) ;
418
414
if data[ 0 ] == b'L' {
419
415
& data[ 1 ..data. len ( ) -1 ]
420
416
} else { data }
421
417
}
422
418
423
- fn cls_type_opt ( & self , i : u32 ) -> Option < & bstr > {
419
+ fn cls_type_opt ( & self , i : u32 ) -> Option < & ' a bstr > {
424
420
if i == NO_INDEX { None } else { Some ( self . cls_type ( i) ) }
425
421
}
422
+ }
423
+
424
+ pub struct DexFile < ' a > {
425
+ dex : DexFileNoProtos < ' a > ,
426
+ protos : Vec < ( BString , Vec < & ' a bstr > , & ' a bstr ) > ,
427
+ }
428
+ impl < ' a > Deref for DexFile < ' a > {
429
+ type Target = DexFileNoProtos < ' a > ;
430
+ fn deref ( & self ) -> & Self :: Target { & self . dex }
431
+ }
432
+ impl < ' a > DexFile < ' a > {
433
+ pub fn new ( data : & bstr ) -> DexFile {
434
+ let dex = DexFileNoProtos :: new ( data) ;
435
+ let n = dex. proto_ids . size ;
436
+ let mut protos = Vec :: with_capacity ( n as usize ) ;
437
+ for i in 0 ..n {
438
+ protos. push ( parse_prototype ( & dex, i) ) ;
439
+ }
440
+ DexFile { dex : dex, protos : protos}
441
+ }
442
+
443
+ pub fn parse_classes ( & ' a self ) -> Vec < DexClass < ' a > > {
444
+ let mut classes = Vec :: with_capacity ( self . class_defs . size as usize ) ;
445
+ for i in 0 ..self . class_defs . size {
446
+ classes. push ( DexClass :: new ( & self , self . class_defs . off , i) ) ;
447
+ }
448
+ classes
449
+ }
426
450
427
451
pub fn field_id ( & self , i : u32 ) -> FieldId { FieldId :: new ( self , i) }
428
452
pub fn method_id ( & self , i : u32 ) -> MethodId { MethodId :: new ( self , i) }
429
- }
453
+ fn proto ( & self , i : u32 ) -> & ( BString , Vec < & ' a bstr > , & ' a bstr ) { & self . protos [ i as usize ] }
454
+ }
0 commit comments