ruby_android 0.0.2 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.idea/.name +1 -0
  3. data/.idea/.rakeTasks +7 -0
  4. data/.idea/encodings.xml +5 -0
  5. data/.idea/misc.xml +5 -0
  6. data/.idea/modules.xml +9 -0
  7. data/.idea/ruby_apk.iml +51 -0
  8. data/.idea/scopes/scope_settings.xml +5 -0
  9. data/.idea/vcs.xml +7 -0
  10. data/.idea/workspace.xml +508 -0
  11. data/.travis.yml +4 -0
  12. data/CHANGELOG.md +51 -0
  13. data/Gemfile +3 -3
  14. data/Gemfile.lock +73 -0
  15. data/LICENSE.txt +2 -2
  16. data/Rakefile +42 -1
  17. data/VERSION +1 -0
  18. data/lib/android/apk.rb +207 -0
  19. data/lib/android/axml_parser.rb +173 -0
  20. data/lib/android/dex/access_flag.rb +74 -0
  21. data/lib/android/dex/dex_object.rb +475 -0
  22. data/lib/android/dex/info.rb +151 -0
  23. data/lib/android/dex/utils.rb +45 -0
  24. data/lib/android/dex.rb +92 -0
  25. data/lib/android/layout.rb +44 -0
  26. data/lib/android/manifest.rb +249 -0
  27. data/lib/android/resource.rb +529 -0
  28. data/lib/android/utils.rb +55 -0
  29. data/lib/ruby_apk.rb +7 -0
  30. data/ruby_android.gemspec +103 -17
  31. data/spec/apk_spec.rb +301 -0
  32. data/spec/axml_parser_spec.rb +67 -0
  33. data/spec/data/sample.apk +0 -0
  34. data/spec/data/sample_AndroidManifest.xml +0 -0
  35. data/spec/data/sample_classes.dex +0 -0
  36. data/spec/data/sample_resources.arsc +0 -0
  37. data/spec/data/sample_resources_utf16.arsc +0 -0
  38. data/spec/data/str_resources.arsc +0 -0
  39. data/spec/dex/access_flag_spec.rb +42 -0
  40. data/spec/dex/dex_object_spec.rb +118 -0
  41. data/spec/dex/info_spec.rb +121 -0
  42. data/spec/dex/utils_spec.rb +56 -0
  43. data/spec/dex_spec.rb +59 -0
  44. data/spec/layout_spec.rb +27 -0
  45. data/spec/manifest_spec.rb +221 -0
  46. data/spec/resource_spec.rb +170 -0
  47. data/spec/ruby_apk_spec.rb +4 -0
  48. data/spec/spec_helper.rb +17 -0
  49. data/spec/utils_spec.rb +90 -0
  50. metadata +112 -27
  51. data/.gitignore +0 -14
  52. data/lib/ruby_android/version.rb +0 -3
  53. data/lib/ruby_android.rb +0 -7
@@ -0,0 +1,475 @@
1
+
2
+ module Android
3
+ class Dex
4
+ # parsing dex object
5
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
6
+ class DexObject
7
+ # @return [Integer] object size
8
+ attr_reader :size
9
+
10
+ def initialize(data, offset)
11
+ @data = data
12
+ @offset = offset
13
+
14
+ @params = {}
15
+ @parsing_off = 0 # parsing offset
16
+ parse()
17
+ @size = @parsing_off
18
+ end
19
+
20
+ # returns symbol keys
21
+ # @return [Array<Symbol>] header key
22
+ def symbols
23
+ @params.keys
24
+ end
25
+
26
+ # @param [Symbol] sym should be included in #symbols
27
+ # @return [Object] dex header value which is related with sym
28
+ def [](sym)
29
+ @params[sym.to_sym]
30
+ end
31
+
32
+ # @return [String]
33
+ def inspect
34
+ str = "<#{self.class}\n"
35
+ @params.each do |key,val|
36
+ str.concat " #{key}: #{val}\n"
37
+ end
38
+ str.concat '>'
39
+ end
40
+
41
+ private
42
+ def parse
43
+ raise 'this method should be overloaded.'
44
+ end
45
+
46
+ def read_value(type)
47
+ types = {
48
+ :byte => [1, 'c'],
49
+ :ubyte => [1, 'C'],
50
+ :short => [2, 's'], #ugh!:depend on machine endian
51
+ :ushort => [2, 'v'],
52
+ :int => [4, 'i'], #ugh!:depend on machine endian
53
+ :uint => [4, 'V'],
54
+ :long => [8, 'q'],
55
+ :ulong => [8, 'Q'],
56
+ }
57
+ len, pack_str = types.fetch(type)
58
+ value = @data[@offset+@parsing_off, len].unpack(pack_str)[0]
59
+ @parsing_off += len
60
+ return value
61
+ end
62
+
63
+ # read short int from data buffer
64
+ # @return [Integer] short value
65
+ def read_sleb
66
+ value, len = Dex::sleb128(@data, @offset + @parsing_off)
67
+ @parsing_off += len
68
+ value
69
+ end
70
+ # read integer from data buffer
71
+ # @return [Integer] integer value
72
+ def read_uleb
73
+ value, len = Dex::uleb128(@data, @offset + @parsing_off)
74
+ @parsing_off += len
75
+ value
76
+ end
77
+ # read integer from data buffer and plus 1
78
+ # @return [Integer] integer value
79
+ def read_uleb128p1
80
+ value, len = Dex::uleb128p1(@data, @offset + @parsing_off)
81
+ @parsing_off += len
82
+ value
83
+ end
84
+ # read various values from data buffer as array
85
+ # @param [Symbol] type
86
+ # @param [Integer] size num of data
87
+ # @return [Array] value array
88
+ def read_value_array(type, size)
89
+ ret_array = []
90
+ size.times { ret_array << read_value(type) }
91
+ ret_array
92
+ end
93
+ # read class values from data buffer as array
94
+ # @param [Class] cls target class
95
+ # @param [Integer] size num of data
96
+ # @return [Array<cls>] object array
97
+ def read_class_array(cls, size)
98
+ ret_array = []
99
+ size.times do
100
+ item = cls.new(@data, @offset + @parsing_off)
101
+ ret_array << item
102
+ @parsing_off += item.size
103
+ end
104
+ ret_array
105
+ end
106
+
107
+ public
108
+ # header_item
109
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
110
+ class Header < DexObject
111
+ def initialize(data)
112
+ super(data, 0)
113
+ end
114
+
115
+ private
116
+ def parse
117
+ @params[:magic] = @data[0, 8]
118
+ @parsing_off += 8
119
+ @params[:checksum] = read_value(:uint)
120
+ @params[:signature] = @data[12, 20]
121
+ @parsing_off += 20
122
+ [
123
+ :file_size, :header_size, :endian_tag, :link_size, :link_off, :map_off,
124
+ :string_ids_size, :string_ids_off, :type_ids_size, :type_ids_off,
125
+ :proto_ids_size, :proto_ids_off, :field_ids_size, :field_ids_off,
126
+ :method_ids_size, :method_ids_off, :class_defs_size, :class_defs_off,
127
+ :data_size, :data_off
128
+ ].each do |key|
129
+ @params[key] = read_value(:uint)
130
+ end
131
+ end
132
+ end
133
+
134
+ # map_list
135
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
136
+ class MapList < DexObject
137
+ private
138
+ def parse
139
+ @params[:size] = read_value(:uint)
140
+ @params[:list] = read_class_array(MapItem, @params[:size])
141
+ end
142
+ end
143
+
144
+ # map_item
145
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
146
+ class MapItem < DexObject
147
+ private
148
+ def parse
149
+ @params[:type] = read_value(:short)
150
+ @params[:unused] = read_value(:short)
151
+ @params[:size] = read_value(:uint)
152
+ @params[:offset] = read_value(:uint)
153
+ end
154
+ end
155
+
156
+ # id_list
157
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
158
+ class IdsList < DexObject
159
+ attr_reader :ids_size
160
+ def initialize(data, off, ids_size)
161
+ @ids_size = ids_size
162
+ super(data, off)
163
+ end
164
+ end
165
+
166
+ # string_id_item
167
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
168
+ class StringIdItem < IdsList
169
+ private
170
+ def parse
171
+ @params[:string_data_off] = read_value_array(:uint, @ids_size)
172
+ end
173
+ end
174
+
175
+ # string_data_item
176
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
177
+ class StringDataItem < DexObject
178
+ def to_s
179
+ @params[:data]
180
+ end
181
+ private
182
+ def mutf8_to_utf8(data, off, ulen)
183
+ mi = 0 # index of mutf8 data
184
+ codepoints = []
185
+ while ulen > 0 do
186
+ b0 = data[off + mi].ord
187
+ bu = (b0 & 0xf0) # b0's upper nibble
188
+ if (b0 & 0x80) == 0 # single byte encoding (0b0xxx_xxxx)
189
+ c = b0
190
+ mi += 1
191
+ ulen -= 1
192
+ elsif bu == 0xc0 || bu == 0xd0 # two-byte encoding (0b110x_xxxx)
193
+ b1 = data[off + mi + 1].ord
194
+ c = (b0 & 0x1f) << 6 | (b1 & 0x3f)
195
+ mi += 2
196
+ ulen -= 1
197
+ elsif bu == 0xe0 # three-byte encoding (0b1110_xxxx)
198
+ b1 = data[off + mi + 1].ord
199
+ b2 = data[off + mi + 2].ord
200
+ c = (b0 & 0x0f) << 12 | (b1 & 0x3f) << 6 | (b2 & 0x3f)
201
+ mi += 3
202
+ ulen -= 1
203
+ if 0xD800 <= c && c <= 0xDBFF # this must be a surrogate pair
204
+ b4 = data[off + mi + 1].ord
205
+ b5 = data[off + mi + 2].ord
206
+ c = ((b1 & 0x0f) + 1) << 16 | (b2 & 0x3f) << 10 | (b4 & 0x0f) << 6 | (b5 & 0x3f)
207
+ mi += 3
208
+ ulen -= 1
209
+ end
210
+ else
211
+ STDERR.puts "unsupported byte: 0x#{'%02X' % b0} @#{mi}"
212
+ c = 0
213
+ mi += 1
214
+ next
215
+ end
216
+ if c != 0
217
+ codepoints << c
218
+ end
219
+ end
220
+ codepoints.pack("U*")
221
+ end
222
+ def parse
223
+ @params[:utf16_size] = read_uleb
224
+ @params[:data] = mutf8_to_utf8(@data, @offset + @parsing_off, @params[:utf16_size])
225
+ end
226
+ end
227
+
228
+ # type_id_item
229
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
230
+ class TypeIdItem < IdsList
231
+ def [](idx)
232
+ raise ArgumentError if idx >= @params[:descriptor_idx].size or idx < 0
233
+ @params[:descriptor_idx][idx]
234
+ end
235
+
236
+ private
237
+ def parse
238
+ @params[:descriptor_idx] = read_value_array(:uint, @ids_size)
239
+ end
240
+ end
241
+
242
+ # proto_id_item
243
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
244
+ class ProtoIdItem < DexObject
245
+ # return parse data size
246
+ # @return bytes
247
+ # @note this method for DexObject#read_class_array (private method)
248
+ def self.size
249
+ 4 * 3
250
+ end
251
+ private
252
+ def parse
253
+ @params[:shorty_idx] = read_value(:uint)
254
+ @params[:return_type_idx] = read_value(:uint)
255
+ @params[:parameters_off] = read_value(:uint)
256
+ end
257
+ end
258
+
259
+ # field_id_item
260
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
261
+ class FieldIdItem < DexObject
262
+ # return parse data size
263
+ # @return bytes
264
+ # @note this method for DexObject#read_class_array (private method)
265
+ def self.size
266
+ 2 * 2 + 4
267
+ end
268
+ private
269
+ def parse
270
+ @params[:class_idx] = read_value(:ushort)
271
+ @params[:type_idx] = read_value(:ushort)
272
+ @params[:name_idx] = read_value(:uint)
273
+ end
274
+ end
275
+
276
+ # method_id_item
277
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
278
+ class MethodIdItem < DexObject
279
+ # return parse data size
280
+ # @return bytes
281
+ # @note this method for DexObject#read_class_array (private method)
282
+ def self.size
283
+ 2 * 2 + 4
284
+ end
285
+ def parse
286
+ @params[:class_idx] = read_value(:ushort)
287
+ @params[:proto_idx] = read_value(:ushort)
288
+ @params[:name_idx] = read_value(:uint)
289
+ end
290
+ end
291
+
292
+ # class_def_item
293
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
294
+ # @!attribute [r] class_data_item
295
+ # @return [ClassDataItem] class_data_item of this class
296
+ class ClassDefItem < DexObject
297
+ # @return [Integer] bytes
298
+ def self.size
299
+ 4 * 8
300
+ end
301
+
302
+ def class_data_item
303
+ # description of class_data_off of class_def_item.
304
+ # offset from the start of the file to the associated class data
305
+ # for this item, or 0 if there is no class data for this class.
306
+ if @params[:class_data_off] != 0
307
+ @class_data_item ||= ClassDataItem.new(@data, @params[:class_data_off])
308
+ else
309
+ nil
310
+ end
311
+ end
312
+
313
+ private
314
+ def parse
315
+ @params[:class_idx] = read_value(:uint)
316
+ @params[:access_flags] = read_value(:uint)
317
+ @params[:superclass_idx] = read_value(:uint)
318
+ @params[:interfaces_off] = read_value(:uint)
319
+ @params[:source_file_idx] = read_value(:uint)
320
+ @params[:annotations_off] = read_value(:uint)
321
+ @params[:class_data_off] = read_value(:uint)
322
+ @params[:static_values_off] = read_value(:uint) # TODO: not implemented encoded_array_item
323
+ end
324
+ end
325
+
326
+ # class_data_item
327
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
328
+ class ClassDataItem < DexObject
329
+ private
330
+ def parse
331
+ @params[:static_fields_size] = read_uleb
332
+ @params[:instance_fields_size] = read_uleb
333
+ @params[:direct_methods_size] = read_uleb
334
+ @params[:virtual_methods_size] = read_uleb
335
+ @params[:static_fields] = read_class_array(EncodedField, @params[:static_fields_size])
336
+ @params[:instance_fields] = read_class_array(EncodedField, @params[:instance_fields_size])
337
+ @params[:direct_methods] = read_class_array(EncodedMethod, @params[:direct_methods_size])
338
+ @params[:virtual_methods] = read_class_array(EncodedMethod, @params[:virtual_methods_size])
339
+ end
340
+ end
341
+
342
+ # encoded_field
343
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
344
+ class EncodedField < DexObject
345
+ private
346
+ def parse
347
+ @params[:field_idx_diff] = read_uleb
348
+ @params[:access_flags] = read_uleb
349
+ end
350
+ end
351
+
352
+ # encoded_method
353
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
354
+ # @!attribute [r] code_item
355
+ # @return [CodeItem] code_item of the method
356
+ class EncodedMethod < DexObject
357
+ def code_item
358
+ # description of code_off in code_data_item.
359
+ # offset from the start of the file to the code structure for this method,
360
+ # or 0 if this method is either abstract or native.
361
+ unless @params[:code_off] == 0
362
+ @code_item ||= CodeItem.new(@data, @params[:code_off])
363
+ else
364
+ nil
365
+ end
366
+ end
367
+
368
+ private
369
+ def parse
370
+ @params[:method_idx_diff] = read_uleb
371
+ @params[:access_flags] = read_uleb
372
+ @params[:code_off] = read_uleb
373
+ end
374
+ end
375
+
376
+
377
+ # type_list
378
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
379
+ class TypeList < DexObject
380
+ private
381
+ def parse
382
+ @params[:size] = read_value(:uint)
383
+ @params[:list] = read_value_array(:ushort, @params[:size])
384
+ end
385
+ end
386
+
387
+ # code_item
388
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
389
+ # @!attribute [r] debug_info_item
390
+ # @return [DebugInfoItem] debug_info_item of this code
391
+ class CodeItem < DexObject
392
+ def debug_info_item
393
+ unless @params[:debug_info_off] == 0
394
+ @debug_info_item ||= DebugInfoItem.new(@data, @params[:debug_info_off])
395
+ else
396
+ nil
397
+ end
398
+ end
399
+
400
+ private
401
+ def parse
402
+ @params[:registers_size] = read_value(:ushort)
403
+ @params[:ins_size] = read_value(:ushort)
404
+ @params[:outs_size] = read_value(:ushort)
405
+ @params[:tries_size] = read_value(:ushort)
406
+ @params[:debug_info_off] = read_value(:uint)
407
+ @params[:insns_size] = read_value(:uint) # size of the instructions list
408
+ @params[:insns] = read_value_array(:ushort, @params[:insns_size])
409
+ read_value(:ushort) if ((@params[:insns_size] % 2) == 1) # for four-byte aligned
410
+ if @params[:tries_size] > 0
411
+ # This element is only present if tries_size is non-zero.
412
+ @params[:tries] = read_class_array(TryItem, @params[:tries_size])
413
+ # This element is only present if tries_size is non-zero.
414
+ @params[:handlers] = EncodedCatchHandlerList.new(@data, @offset + @parsing_off)
415
+ @parsing_off += @params[:handlers].size
416
+ end
417
+ end
418
+ end
419
+
420
+ # try_item
421
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
422
+ class TryItem < DexObject
423
+ private
424
+ def parse
425
+ @params[:start_addr] = read_value(:uint)
426
+ @params[:insn_count] = read_value(:ushort)
427
+ @params[:handler_off] = read_value(:ushort)
428
+ end
429
+ end
430
+
431
+ # encoded_catch_handler_list
432
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
433
+ class EncodedCatchHandlerList < DexObject
434
+ private
435
+ def parse
436
+ @params[:size] = read_uleb
437
+ @params[:list] = read_class_array(EncodedCatchHandler, @params[:size])
438
+ end
439
+ end
440
+
441
+ # encoded_catch_handler
442
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
443
+ class EncodedCatchHandler < DexObject
444
+ private
445
+ def parse
446
+ @params[:size] = read_sleb
447
+ @params[:list] = read_class_array(EncodedTypeAddrPair, @params[:size].abs)
448
+ @params[:catch_all_addr] = read_uleb if @params[:size] <= 0
449
+ end
450
+ end
451
+
452
+ # encoded_type_addr_pair
453
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
454
+ class EncodedTypeAddrPair < DexObject
455
+ private
456
+ def parse
457
+ @params[:type_idx] = read_uleb
458
+ @params[:addr] = read_uleb
459
+ end
460
+ end
461
+
462
+ # debug_info_item
463
+ # @see http://source.android.com/devices/tech/dalvik/dex-format.html
464
+ class DebugInfoItem < DexObject
465
+ private
466
+ def parse
467
+ @params[:line_start] = read_uleb
468
+ @params[:parameters_size] = read_uleb
469
+ @params[:parameter_names] = []
470
+ @params[:parameters_size].times { @params[:parameter_names] << read_uleb128p1 }
471
+ end
472
+ end
473
+ end
474
+ end
475
+ end
@@ -0,0 +1,151 @@
1
+ require_relative 'dex_object'
2
+
3
+ module Android
4
+ class Dex
5
+ # class information in dex
6
+ # @!attribute [r] name
7
+ # @return [String] class name
8
+ # @!attribute [r] super_class
9
+ # @return [String] super class name
10
+ class ClassInfo
11
+ # no index flag
12
+ NO_INDEX = 0xffffffff
13
+
14
+ # @return [ClassAccessFlag]
15
+ attr_reader :access_flags
16
+ # @return [Array<FieldInfo>] static fields
17
+ attr_reader :static_fields
18
+ # @return [Array<FieldInfo>] instance fields
19
+ attr_reader :instance_fields
20
+ # @return [Array<MethodInfo>] direct methods
21
+ attr_reader :direct_methods
22
+ # @return [Array<MethodInfo>] virtual methods
23
+ attr_reader :virtual_methods
24
+
25
+ # @return [DexObject::ClassDataItem]
26
+ attr_reader :class_data
27
+ # @return [DexObject::ClassDefItem]
28
+ attr_reader :class_def
29
+
30
+ def name
31
+ @dex.type_resolve(@class_def[:class_idx])
32
+ end
33
+ def super_class
34
+ if @class_def[:superclass_idx] != NO_INDEX
35
+ @super_class = @dex.type_resolve(@class_def[:superclass_idx])
36
+ else
37
+ nil
38
+ end
39
+ end
40
+ # @param [Dex::ClassDefItem] class_def
41
+ # @param [Dex] dex dex class instance
42
+ def initialize(class_def, dex)
43
+ @class_def = class_def
44
+ @dex = dex
45
+ @access_flags = ClassAccessFlag.new(@class_def[:access_flags])
46
+ @class_data = @class_def.class_data_item
47
+ @static_fields = @instance_fields = @direct_methods = @virtual_methods = []
48
+ unless @class_data.nil?
49
+ @static_fields = cls2info(@class_data[:static_fields], FieldInfo, :field_idx_diff)
50
+ @instance_fields = cls2info(@class_data[:instance_fields], FieldInfo, :field_idx_diff)
51
+ @direct_methods = cls2info(@class_data[:direct_methods], MethodInfo, :method_idx_diff)
52
+ @virtual_methods = cls2info(@class_data[:virtual_methods], MethodInfo, :method_idx_diff)
53
+ end
54
+ end
55
+
56
+ # @return [String] class difinition
57
+ def definition
58
+ ret = "#{access_flags} class #{name}"
59
+ super_class.nil? ? ret : ret + " extends #{super_class}"
60
+ end
61
+
62
+ private
63
+ def cls2info(arr, cls, idx_key)
64
+ idx = 0
65
+ ret = []
66
+ arr.each do |item|
67
+ idx += item[idx_key]
68
+ ret << cls.new(item, idx, @dex)
69
+ end
70
+ ret
71
+ end
72
+ end
73
+
74
+ # field info object
75
+ # @!attribute [r] name
76
+ # @return [String] field name
77
+ # @!attribute [r] type
78
+ # @return [String] field type
79
+ class FieldInfo
80
+ # @return [ClassAccessFlag]
81
+ attr_reader :access_flags
82
+
83
+ def name
84
+ @dex.strings[@dex.field_ids[@field_id][:name_idx]]
85
+ end
86
+ def type
87
+ @dex.type_resolve(@dex.field_ids[@field_id][:type_idx])
88
+ end
89
+ def initialize(encoded_field, field_id, dex)
90
+ @dex = dex
91
+ @encoded_field = encoded_field
92
+ @field_id = field_id
93
+ @access_flags = ClassAccessFlag.new(encoded_field[:access_flags])
94
+ end
95
+
96
+ # @return [String] field definition
97
+ def definition
98
+ "#{@access_flags.to_s} #{type} #{name}"
99
+ end
100
+ end
101
+
102
+ # method info object
103
+ # @!attribute [r] name
104
+ # @return [String] method name
105
+ # @!attribute [r] ret_type
106
+ # @return [String] return type of the method
107
+ # @!attribute [r] parameters
108
+ # @return [Array<String>] method parameters
109
+ class MethodInfo
110
+ # @return [MethodAccessFlag]
111
+ attr_reader :access_flags
112
+
113
+ def initialize(encoded_method, method_id, dex)
114
+ @encoded_method = encoded_method
115
+ @method_id = method_id
116
+ @dex = dex
117
+ @access_flags = MethodAccessFlag.new(encoded_method[:access_flags])
118
+ end
119
+ def name
120
+ @dex.strings[@dex.method_ids[@method_id][:name_idx]]
121
+ end
122
+ def ret_type
123
+ @dex.type_resolve(proto[:return_type_idx])
124
+ end
125
+ def parameters
126
+ unless proto[:parameters_off] == 0
127
+ list = DexObject::TypeList.new(@dex.data, proto[:parameters_off])
128
+ list[:list].map { |item| @dex.type_resolve(item) }
129
+ else
130
+ []
131
+ end
132
+ end
133
+
134
+ # @return [String] method definition string
135
+ def definition
136
+ "#{access_flags.to_s} #{ret_type} #{name}(#{parameters.join(', ')});"
137
+ end
138
+
139
+ # @return [DexObject::CodeItem]
140
+ def code_item
141
+ @encoded_method.code_item
142
+ end
143
+
144
+ private
145
+ def proto
146
+ @dex.proto_ids[@dex.method_ids[@method_id][:proto_idx]]
147
+ end
148
+ end
149
+
150
+ end
151
+ end
@@ -0,0 +1,45 @@
1
+ module Android
2
+ class Dex
3
+ class << self
4
+ # parse uleb128(unsigned integer) data
5
+ # @param [String] data target byte data
6
+ # @param [Integer] offset
7
+ # @return [Integer, Integer] parsed value and parsed byte length
8
+ # @see http://en.wikipedia.org/wiki/LEB128
9
+ def uleb128(data, offset=0)
10
+ result = 0
11
+ shift = 0
12
+ d = data[offset...data.size]
13
+ (0..4).each do |i|
14
+ byte = d.getbyte(i)
15
+ result |= ((byte & 0x7f) << shift)
16
+ return result, i+1 if ((byte & 0x80) == 0)
17
+ shift += 7
18
+ end
19
+ end
20
+ # parse uleb128 + 1 data
21
+ # @param [String] data target byte data
22
+ # @param [Integer] offset
23
+ # @return [Integer, Integer] parsed value and parsed byte length
24
+ def uleb128p1(data, offset=0)
25
+ ret, len = self.uleb128(data, offset)
26
+ return (ret - 1), len
27
+ end
28
+ # parse sleb128(signed integer) data
29
+ # @param [String] data target byte data
30
+ # @param [Integer] offset
31
+ # @return [Integer, Integer] parsed value and parsed byte length
32
+ def sleb128(data, offset=0)
33
+ result = 0
34
+ shift = 0
35
+ d = data[offset...data.size]
36
+ (0..4).each do |i|
37
+ byte = d.getbyte(i)
38
+ result |=((byte & 0x7F) << shift)
39
+ return (0 == (byte & 0x40) ? result : result - (1 << (shift+7))), i+1 if ((byte & 0x80) == 0)
40
+ shift += 7
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end