android_parser 2.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +54 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +45 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +92 -0
- data/LICENSE.txt +22 -0
- data/README.md +158 -0
- data/Rakefile +44 -0
- data/android_parser.gemspec +64 -0
- data/lib/android/apk.rb +220 -0
- data/lib/android/axml_parser.rb +239 -0
- data/lib/android/axml_writer.rb +49 -0
- data/lib/android/dex/access_flag.rb +74 -0
- data/lib/android/dex/dex_object.rb +475 -0
- data/lib/android/dex/info.rb +151 -0
- data/lib/android/dex/utils.rb +45 -0
- data/lib/android/dex.rb +92 -0
- data/lib/android/layout.rb +44 -0
- data/lib/android/manifest.rb +350 -0
- data/lib/android/resource.rb +621 -0
- data/lib/android/utils.rb +55 -0
- data/lib/ruby_apk.rb +8 -0
- metadata +193 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module Android
|
5
|
+
class AXMLWriter < AXMLParser
|
6
|
+
# @param [String] axml binary xml data
|
7
|
+
def initialize(axml)
|
8
|
+
@io = StringIO.new(axml, "r+b")
|
9
|
+
@strings = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def modify_metadata!(name, new_value)
|
13
|
+
parse if @doc.nil?
|
14
|
+
|
15
|
+
entry = @metadata.find { |meta| meta['android:name'][:value] == name }
|
16
|
+
raise "Metadata #{name} could not be found and modified" if entry.nil?
|
17
|
+
|
18
|
+
pos = if entry['android:value'][:is_string]
|
19
|
+
new_string_id = add_string!(new_value)
|
20
|
+
new_value = new_string_id
|
21
|
+
entry['android:value'][:val_str_id]
|
22
|
+
else
|
23
|
+
entry['android:value'][:position]
|
24
|
+
end
|
25
|
+
|
26
|
+
@io.pos = pos
|
27
|
+
@io.write([new_value].pack('V'))
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_string!(str)
|
31
|
+
new_string_id, bytes_added = Resource::ResStringPool.new(@io.string, 8).add_string(str)
|
32
|
+
|
33
|
+
# Update XML size and positions of metadata attributes.
|
34
|
+
@io.pos = 4
|
35
|
+
xml_size = @io.read(4).unpack1('V')
|
36
|
+
@io.pos = 4
|
37
|
+
@io.write([xml_size + bytes_added].pack('V'))
|
38
|
+
|
39
|
+
@metadata = @metadata.map do |metadata|
|
40
|
+
metadata.transform_values do |attribute|
|
41
|
+
attribute[:position] += bytes_added
|
42
|
+
attribute[:val_str_id] += bytes_added
|
43
|
+
attribute
|
44
|
+
end
|
45
|
+
end
|
46
|
+
new_string_id
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
|
2
|
+
module Android
|
3
|
+
class Dex
|
4
|
+
# access flag object
|
5
|
+
class AccessFlag
|
6
|
+
# @return [Integer] flag value
|
7
|
+
attr_reader :flag
|
8
|
+
def initialize(flag)
|
9
|
+
@flag = flag
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# access flag object for class in dex
|
14
|
+
class ClassAccessFlag < AccessFlag
|
15
|
+
ACCESSORS = [
|
16
|
+
{value:0x1, name:'public'},
|
17
|
+
{value:0x2, name:'private'},
|
18
|
+
{value:0x4, name:'protected'},
|
19
|
+
{value:0x8, name:'static'},
|
20
|
+
{value:0x10, name:'final'},
|
21
|
+
{value:0x20, name:'synchronized'},
|
22
|
+
{value:0x40, name:'volatile'},
|
23
|
+
{value:0x80, name:'transient'},
|
24
|
+
{value:0x100, name:'native'},
|
25
|
+
{value:0x200, name:'interface'},
|
26
|
+
{value:0x400, name:'abstract'},
|
27
|
+
{value:0x800, name:'strict'},
|
28
|
+
{value:0x1000, name:'synthetic'},
|
29
|
+
{value:0x2000, name:'annotation'},
|
30
|
+
{value:0x4000, name:'enum'},
|
31
|
+
#{value:0x8000, name:'unused'},
|
32
|
+
{value:0x10000, name:'constructor'},
|
33
|
+
{value:0x20000, name:'declared-synchronized'},
|
34
|
+
]
|
35
|
+
|
36
|
+
# convert access flag to string
|
37
|
+
# @return [String]
|
38
|
+
def to_s
|
39
|
+
ACCESSORS.select{|e| ((e[:value] & @flag) != 0) }.map{|e| e[:name] }.join(' ')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# access flag object for method in dex
|
44
|
+
class MethodAccessFlag < AccessFlag
|
45
|
+
ACCESSORS = [
|
46
|
+
{value: 0x1, name:'public'},
|
47
|
+
{value: 0x2, name:'private'},
|
48
|
+
{value: 0x4, name:'protected'},
|
49
|
+
{value: 0x8, name:'static'},
|
50
|
+
{value: 0x10, name:'final'},
|
51
|
+
{value: 0x20, name:'synchronized'},
|
52
|
+
{value: 0x40, name:'bridge'},
|
53
|
+
{value: 0x80, name:'varargs'},
|
54
|
+
{value: 0x100, name:'native'},
|
55
|
+
{value: 0x200, name:'interface'},
|
56
|
+
{value: 0x400, name:'abstract'},
|
57
|
+
{value: 0x800, name:'strict'},
|
58
|
+
{value: 0x1000, name:'synthetic'},
|
59
|
+
{value: 0x2000, name:'annotation'},
|
60
|
+
{value: 0x4000, name:'enum'},
|
61
|
+
#{value: 0x8000, name:'unused'},
|
62
|
+
{value: 0x10000, name:'constructor'},
|
63
|
+
{value: 0x20000, name:'declared-synchronized'},
|
64
|
+
]
|
65
|
+
# convert access flag to string
|
66
|
+
# @return [String]
|
67
|
+
def to_s
|
68
|
+
ACCESSORS.select{|e| ((e[:value] & @flag) != 0) }.map{|e| e[:name] }.join(' ')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
@@ -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
|