1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
18 #define ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
19
20 #include "dex_file.h"
21
22 #include "base/casts.h"
23 #include "base/iteration_range.h"
24 #include "base/leb128.h"
25 #include "base/utils.h"
26 #include "class_iterator.h"
27 #include "compact_dex_file.h"
28 #include "dex_instruction_iterator.h"
29 #include "invoke_type.h"
30 #include "signature.h"
31 #include "standard_dex_file.h"
32
33 namespace art {
34
CompareDescriptors(std::string_view lhs,std::string_view rhs)35 inline int DexFile::CompareDescriptors(std::string_view lhs, std::string_view rhs) {
36 // Note: `std::string_view::compare()` uses lexicographical comparison and treats the `char`
37 // as unsigned; for Modified-UTF-8 without embedded nulls this is consistent with the
38 // `CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues()` ordering.
39 return lhs.compare(rhs);
40 }
41
CompareMemberNames(std::string_view lhs,std::string_view rhs)42 inline int DexFile::CompareMemberNames(std::string_view lhs, std::string_view rhs) {
43 // Note: `std::string_view::compare()` uses lexicographical comparison and treats the `char`
44 // as unsigned; for Modified-UTF-8 without embedded nulls this is consistent with the
45 // `CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues()` ordering.
46 return lhs.compare(rhs);
47 }
48
StringViewFromUtf16Length(const char * utf8_data,size_t utf16_length)49 inline std::string_view DexFile::StringViewFromUtf16Length(const char* utf8_data,
50 size_t utf16_length) {
51 size_t utf8_length = LIKELY(utf8_data[utf16_length] == 0) // Is ASCII?
52 ? utf16_length
53 : utf16_length + strlen(utf8_data + utf16_length);
54 return std::string_view(utf8_data, utf8_length);
55 }
56
57 ALWAYS_INLINE
GetStringDataAndUtf16Length(const dex::StringId & string_id,uint32_t * utf16_length)58 inline const char* DexFile::GetStringDataAndUtf16Length(const dex::StringId& string_id,
59 uint32_t* utf16_length) const {
60 DCHECK(utf16_length != nullptr) << GetLocation();
61 const uint8_t* ptr = DataBegin() + string_id.string_data_off_;
62 *utf16_length = DecodeUnsignedLeb128(&ptr);
63 return reinterpret_cast<const char*>(ptr);
64 }
65
66 ALWAYS_INLINE
GetStringDataAndUtf16Length(const dex::StringIndex string_idx,uint32_t * utf16_length)67 inline const char* DexFile::GetStringDataAndUtf16Length(const dex::StringIndex string_idx,
68 uint32_t* utf16_length) const {
69 return GetStringDataAndUtf16Length(GetStringId(string_idx), utf16_length);
70 }
71
72 ALWAYS_INLINE
GetStringUtf16Length(const dex::StringId & string_id)73 inline uint32_t DexFile::GetStringUtf16Length(const dex::StringId& string_id) const {
74 uint32_t utf16_length;
75 GetStringDataAndUtf16Length(string_id, &utf16_length);
76 return utf16_length;
77 }
78
79 ALWAYS_INLINE
GetStringData(const dex::StringId & string_id)80 inline const char* DexFile::GetStringData(const dex::StringId& string_id) const {
81 uint32_t ignored;
82 return GetStringDataAndUtf16Length(string_id, &ignored);
83 }
84
85 ALWAYS_INLINE
GetStringData(dex::StringIndex string_idx)86 inline const char* DexFile::GetStringData(dex::StringIndex string_idx) const {
87 return GetStringData(GetStringId(string_idx));
88 }
89
90 ALWAYS_INLINE
GetStringView(const dex::StringId & string_id)91 inline std::string_view DexFile::GetStringView(const dex::StringId& string_id) const {
92 uint32_t utf16_length;
93 const char* data = GetStringDataAndUtf16Length(string_id, &utf16_length);
94 return StringViewFromUtf16Length(data, utf16_length);
95 }
96
97 ALWAYS_INLINE
GetStringView(dex::StringIndex string_idx)98 inline std::string_view DexFile::GetStringView(dex::StringIndex string_idx) const {
99 return GetStringView(GetStringId(string_idx));
100 }
101
GetTypeDescriptor(const dex::TypeId & type_id)102 inline const char* DexFile::GetTypeDescriptor(const dex::TypeId& type_id) const {
103 return GetStringData(type_id.descriptor_idx_);
104 }
105
GetTypeDescriptor(dex::TypeIndex type_idx)106 inline const char* DexFile::GetTypeDescriptor(dex::TypeIndex type_idx) const {
107 return GetTypeDescriptor(GetTypeId(type_idx));
108 }
109
GetTypeDescriptorView(const dex::TypeId & type_id)110 inline std::string_view DexFile::GetTypeDescriptorView(const dex::TypeId& type_id) const {
111 return GetStringView(type_id.descriptor_idx_);
112 }
113
GetTypeDescriptorView(dex::TypeIndex type_idx)114 inline std::string_view DexFile::GetTypeDescriptorView(dex::TypeIndex type_idx) const {
115 return GetTypeDescriptorView(GetTypeId(type_idx));
116 }
117
GetFieldDeclaringClassDescriptor(const dex::FieldId & field_id)118 inline const char* DexFile::GetFieldDeclaringClassDescriptor(const dex::FieldId& field_id) const {
119 return GetTypeDescriptor(field_id.class_idx_);
120 }
121
GetFieldDeclaringClassDescriptor(uint32_t field_idx)122 inline const char* DexFile::GetFieldDeclaringClassDescriptor(uint32_t field_idx) const {
123 return GetFieldDeclaringClassDescriptor(GetFieldId(field_idx));
124 }
125
GetFieldDeclaringClassDescriptorView(const dex::FieldId & field_id)126 inline std::string_view DexFile::GetFieldDeclaringClassDescriptorView(
127 const dex::FieldId& field_id) const {
128 return GetTypeDescriptorView(field_id.class_idx_);
129 }
130
GetFieldDeclaringClassDescriptorView(uint32_t field_idx)131 inline std::string_view DexFile::GetFieldDeclaringClassDescriptorView(uint32_t field_idx) const {
132 return GetFieldDeclaringClassDescriptorView(GetFieldId(field_idx));
133 }
134
GetFieldTypeDescriptor(const dex::FieldId & field_id)135 inline const char* DexFile::GetFieldTypeDescriptor(const dex::FieldId& field_id) const {
136 return GetTypeDescriptor(field_id.type_idx_);
137 }
138
GetFieldTypeDescriptor(uint32_t field_idx)139 inline const char* DexFile::GetFieldTypeDescriptor(uint32_t field_idx) const {
140 return GetFieldTypeDescriptor(GetFieldId(field_idx));
141 }
142
GetFieldTypeDescriptorView(const dex::FieldId & field_id)143 inline std::string_view DexFile::GetFieldTypeDescriptorView(const dex::FieldId& field_id) const {
144 return GetTypeDescriptorView(field_id.type_idx_);
145 }
146
GetFieldTypeDescriptorView(uint32_t field_idx)147 inline std::string_view DexFile::GetFieldTypeDescriptorView(uint32_t field_idx) const {
148 return GetFieldTypeDescriptorView(GetFieldId(field_idx));
149 }
150
GetFieldName(const dex::FieldId & field_id)151 inline const char* DexFile::GetFieldName(const dex::FieldId& field_id) const {
152 return GetStringData(field_id.name_idx_);
153 }
154
GetFieldName(uint32_t field_idx)155 inline const char* DexFile::GetFieldName(uint32_t field_idx) const {
156 return GetFieldName(GetFieldId(field_idx));
157 }
158
GetFieldNameView(const dex::FieldId & field_id)159 inline std::string_view DexFile::GetFieldNameView(const dex::FieldId& field_id) const {
160 return GetStringView(field_id.name_idx_);
161 }
162
GetFieldNameView(uint32_t field_idx)163 inline std::string_view DexFile::GetFieldNameView(uint32_t field_idx) const {
164 return GetFieldNameView(GetFieldId(field_idx));
165 }
166
GetMethodDeclaringClassDescriptor(const dex::MethodId & method_id)167 inline const char* DexFile::GetMethodDeclaringClassDescriptor(
168 const dex::MethodId& method_id) const {
169 return GetTypeDescriptor(method_id.class_idx_);
170 }
171
GetMethodDeclaringClassDescriptor(uint32_t method_idx)172 inline const char* DexFile::GetMethodDeclaringClassDescriptor(uint32_t method_idx) const {
173 return GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
174 }
175
GetMethodDeclaringClassDescriptorView(const dex::MethodId & method_id)176 inline std::string_view DexFile::GetMethodDeclaringClassDescriptorView(
177 const dex::MethodId& method_id) const {
178 return GetTypeDescriptorView(method_id.class_idx_);
179 }
180
GetMethodDeclaringClassDescriptorView(uint32_t method_idx)181 inline std::string_view DexFile::GetMethodDeclaringClassDescriptorView(uint32_t method_idx) const {
182 return GetMethodDeclaringClassDescriptorView(GetMethodId(method_idx));
183 }
184
GetMethodSignature(const dex::MethodId & method_id)185 inline const Signature DexFile::GetMethodSignature(const dex::MethodId& method_id) const {
186 return Signature(this, GetProtoId(method_id.proto_idx_));
187 }
188
GetProtoSignature(const dex::ProtoId & proto_id)189 inline const Signature DexFile::GetProtoSignature(const dex::ProtoId& proto_id) const {
190 return Signature(this, proto_id);
191 }
192
GetMethodName(const dex::MethodId & method_id)193 inline const char* DexFile::GetMethodName(const dex::MethodId& method_id) const {
194 return GetStringData(method_id.name_idx_);
195 }
196
GetMethodName(const dex::MethodId & method_id,uint32_t * utf_length)197 inline const char* DexFile::GetMethodName(const dex::MethodId& method_id, uint32_t* utf_length)
198 const {
199 return GetStringDataAndUtf16Length(method_id.name_idx_, utf_length);
200 }
201
GetMethodName(uint32_t method_idx)202 inline const char* DexFile::GetMethodName(uint32_t method_idx) const {
203 return GetStringData(GetMethodId(method_idx).name_idx_);
204 }
205
GetMethodName(uint32_t idx,uint32_t * utf_length)206 inline const char* DexFile::GetMethodName(uint32_t idx, uint32_t* utf_length) const {
207 return GetStringDataAndUtf16Length(GetMethodId(idx).name_idx_, utf_length);
208 }
209
210 ALWAYS_INLINE
GetMethodNameView(const dex::MethodId & method_id)211 inline std::string_view DexFile::GetMethodNameView(const dex::MethodId& method_id) const {
212 return GetStringView(method_id.name_idx_);
213 }
214
215 ALWAYS_INLINE
GetMethodNameView(uint32_t method_idx)216 inline std::string_view DexFile::GetMethodNameView(uint32_t method_idx) const {
217 return GetMethodNameView(GetMethodId(method_idx));
218 }
219
GetMethodShorty(uint32_t idx)220 inline const char* DexFile::GetMethodShorty(uint32_t idx) const {
221 return GetMethodShorty(GetMethodId(idx));
222 }
223
GetMethodShortyView(uint32_t idx)224 inline std::string_view DexFile::GetMethodShortyView(uint32_t idx) const {
225 return GetMethodShortyView(GetMethodId(idx));
226 }
227
GetMethodShorty(const dex::MethodId & method_id)228 inline const char* DexFile::GetMethodShorty(const dex::MethodId& method_id) const {
229 return GetStringData(GetProtoId(method_id.proto_idx_).shorty_idx_);
230 }
231
GetMethodShorty(const dex::MethodId & method_id,uint32_t * length)232 inline const char* DexFile::GetMethodShorty(const dex::MethodId& method_id, uint32_t* length)
233 const {
234 // Using the UTF16 length is safe here as shorties are guaranteed to be ASCII characters.
235 return GetStringDataAndUtf16Length(GetProtoId(method_id.proto_idx_).shorty_idx_, length);
236 }
237
GetMethodShortyView(const dex::MethodId & method_id)238 inline std::string_view DexFile::GetMethodShortyView(const dex::MethodId& method_id) const {
239 return GetShortyView(method_id.proto_idx_);
240 }
241
GetClassDescriptor(const dex::ClassDef & class_def)242 inline const char* DexFile::GetClassDescriptor(const dex::ClassDef& class_def) const {
243 return GetTypeDescriptor(class_def.class_idx_);
244 }
245
GetReturnTypeDescriptor(const dex::ProtoId & proto_id)246 inline const char* DexFile::GetReturnTypeDescriptor(const dex::ProtoId& proto_id) const {
247 return GetTypeDescriptor(proto_id.return_type_idx_);
248 }
249
GetShorty(dex::ProtoIndex proto_idx)250 inline const char* DexFile::GetShorty(dex::ProtoIndex proto_idx) const {
251 const dex::ProtoId& proto_id = GetProtoId(proto_idx);
252 return GetStringData(proto_id.shorty_idx_);
253 }
254
255 ALWAYS_INLINE
GetShortyView(dex::ProtoIndex proto_idx)256 inline std::string_view DexFile::GetShortyView(dex::ProtoIndex proto_idx) const {
257 return GetShortyView(GetProtoId(proto_idx));
258 }
259
260 ALWAYS_INLINE
GetShortyView(const dex::ProtoId & proto_id)261 inline std::string_view DexFile::GetShortyView(const dex::ProtoId& proto_id) const {
262 uint32_t shorty_len;
263 const char* shorty_data = GetStringDataAndUtf16Length(proto_id.shorty_idx_, &shorty_len);
264 DCHECK_EQ(shorty_data[shorty_len], '\0'); // For a shorty utf16 length == mutf8 length.
265 return std::string_view(shorty_data, shorty_len);
266 }
267
GetTryItems(const DexInstructionIterator & code_item_end,uint32_t offset)268 inline const dex::TryItem* DexFile::GetTryItems(const DexInstructionIterator& code_item_end,
269 uint32_t offset) {
270 return reinterpret_cast<const dex::TryItem*>
271 (RoundUp(reinterpret_cast<uintptr_t>(&code_item_end.Inst()), dex::TryItem::kAlignment)) +
272 offset;
273 }
274
StringEquals(const DexFile * df1,dex::StringIndex sidx1,const DexFile * df2,dex::StringIndex sidx2)275 inline bool DexFile::StringEquals(const DexFile* df1, dex::StringIndex sidx1,
276 const DexFile* df2, dex::StringIndex sidx2) {
277 uint32_t s1_len; // Note: utf16 length != mutf8 length.
278 const char* s1_data = df1->GetStringDataAndUtf16Length(sidx1, &s1_len);
279 uint32_t s2_len;
280 const char* s2_data = df2->GetStringDataAndUtf16Length(sidx2, &s2_len);
281 return (s1_len == s2_len) && (strcmp(s1_data, s2_data) == 0);
282 }
283
284 template<typename NewLocalCallback, typename IndexToStringData, typename TypeIndexToStringData>
DecodeDebugLocalInfo(const uint8_t * stream,const std::string & location,const char * declaring_class_descriptor,const std::vector<const char * > & arg_descriptors,const std::string & method_name,bool is_static,uint16_t registers_size,uint16_t ins_size,uint16_t insns_size_in_code_units,const IndexToStringData & index_to_string_data,const TypeIndexToStringData & type_index_to_string_data,const NewLocalCallback & new_local_callback)285 bool DexFile::DecodeDebugLocalInfo(const uint8_t* stream,
286 const std::string& location,
287 const char* declaring_class_descriptor,
288 const std::vector<const char*>& arg_descriptors,
289 const std::string& method_name,
290 bool is_static,
291 uint16_t registers_size,
292 uint16_t ins_size,
293 uint16_t insns_size_in_code_units,
294 const IndexToStringData& index_to_string_data,
295 const TypeIndexToStringData& type_index_to_string_data,
296 const NewLocalCallback& new_local_callback) {
297 if (stream == nullptr) {
298 return false;
299 }
300 std::vector<LocalInfo> local_in_reg(registers_size);
301
302 uint16_t arg_reg = registers_size - ins_size;
303 if (!is_static) {
304 const char* descriptor = declaring_class_descriptor;
305 local_in_reg[arg_reg].name_ = "this";
306 local_in_reg[arg_reg].descriptor_ = descriptor;
307 local_in_reg[arg_reg].signature_ = nullptr;
308 local_in_reg[arg_reg].start_address_ = 0;
309 local_in_reg[arg_reg].reg_ = arg_reg;
310 local_in_reg[arg_reg].is_live_ = true;
311 arg_reg++;
312 }
313
314 DecodeUnsignedLeb128(&stream); // Line.
315 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
316 uint32_t i;
317 if (parameters_size != arg_descriptors.size()) {
318 LOG(ERROR) << "invalid stream - problem with parameter iterator in " << location
319 << " for method " << method_name;
320 return false;
321 }
322 for (i = 0; i < parameters_size && i < arg_descriptors.size(); ++i) {
323 if (arg_reg >= registers_size) {
324 LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
325 << " >= " << registers_size << ") in " << location;
326 return false;
327 }
328 uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
329 const char* descriptor = arg_descriptors[i];
330 local_in_reg[arg_reg].name_ = index_to_string_data(name_idx);
331 local_in_reg[arg_reg].descriptor_ = descriptor;
332 local_in_reg[arg_reg].signature_ = nullptr;
333 local_in_reg[arg_reg].start_address_ = 0;
334 local_in_reg[arg_reg].reg_ = arg_reg;
335 local_in_reg[arg_reg].is_live_ = true;
336 switch (*descriptor) {
337 case 'D':
338 case 'J':
339 arg_reg += 2;
340 break;
341 default:
342 arg_reg += 1;
343 break;
344 }
345 }
346
347 uint32_t address = 0;
348 for (;;) {
349 uint8_t opcode = *stream++;
350 switch (opcode) {
351 case DBG_END_SEQUENCE:
352 // Emit all variables which are still alive at the end of the method.
353 for (uint16_t reg = 0; reg < registers_size; reg++) {
354 if (local_in_reg[reg].is_live_) {
355 local_in_reg[reg].end_address_ = insns_size_in_code_units;
356 new_local_callback(local_in_reg[reg]);
357 }
358 }
359 return true;
360 case DBG_ADVANCE_PC:
361 address += DecodeUnsignedLeb128(&stream);
362 break;
363 case DBG_ADVANCE_LINE:
364 DecodeSignedLeb128(&stream); // Line.
365 break;
366 case DBG_START_LOCAL:
367 case DBG_START_LOCAL_EXTENDED: {
368 uint16_t reg = DecodeUnsignedLeb128(&stream);
369 if (reg >= registers_size) {
370 LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
371 << registers_size << ") in " << location;
372 return false;
373 }
374
375 uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
376 uint16_t descriptor_idx = DecodeUnsignedLeb128P1(&stream);
377 uint32_t signature_idx = dex::kDexNoIndex;
378 if (opcode == DBG_START_LOCAL_EXTENDED) {
379 signature_idx = DecodeUnsignedLeb128P1(&stream);
380 }
381
382 // Emit what was previously there, if anything
383 if (local_in_reg[reg].is_live_) {
384 local_in_reg[reg].end_address_ = address;
385 // Parameters with generic types cannot be encoded in the debug_info_item header. So d8
386 // encodes it as null in the header with start and end address as 0. There will be a
387 // START_LOCAL_EXTENDED that will declare the parameter with correct signature
388 // Debuggers get confused when they see empty ranges. So don't emit them.
389 // See b/297843934 for more details.
390 if (local_in_reg[reg].end_address_ != 0) {
391 new_local_callback(local_in_reg[reg]);
392 }
393 }
394
395 local_in_reg[reg].name_ = index_to_string_data(name_idx);
396 local_in_reg[reg].descriptor_ = type_index_to_string_data(descriptor_idx);
397 local_in_reg[reg].signature_ = index_to_string_data(signature_idx);
398 local_in_reg[reg].start_address_ = address;
399 local_in_reg[reg].reg_ = reg;
400 local_in_reg[reg].is_live_ = true;
401 break;
402 }
403 case DBG_END_LOCAL: {
404 uint16_t reg = DecodeUnsignedLeb128(&stream);
405 if (reg >= registers_size) {
406 LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
407 << registers_size << ") in " << location;
408 return false;
409 }
410 // If the register is live, close it properly. Otherwise, closing an already
411 // closed register is sloppy, but harmless if no further action is taken.
412 if (local_in_reg[reg].is_live_) {
413 local_in_reg[reg].end_address_ = address;
414 new_local_callback(local_in_reg[reg]);
415 local_in_reg[reg].is_live_ = false;
416 }
417 break;
418 }
419 case DBG_RESTART_LOCAL: {
420 uint16_t reg = DecodeUnsignedLeb128(&stream);
421 if (reg >= registers_size) {
422 LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
423 << registers_size << ") in " << location;
424 return false;
425 }
426 // If the register is live, the "restart" is superfluous,
427 // and we don't want to mess with the existing start address.
428 if (!local_in_reg[reg].is_live_) {
429 local_in_reg[reg].start_address_ = address;
430 local_in_reg[reg].is_live_ = true;
431 }
432 break;
433 }
434 case DBG_SET_PROLOGUE_END:
435 case DBG_SET_EPILOGUE_BEGIN:
436 break;
437 case DBG_SET_FILE:
438 DecodeUnsignedLeb128P1(&stream); // name.
439 break;
440 default:
441 address += (opcode - DBG_FIRST_SPECIAL) / DBG_LINE_RANGE;
442 break;
443 }
444 }
445 }
446
447 template<typename NewLocalCallback>
DecodeDebugLocalInfo(uint32_t registers_size,uint32_t ins_size,uint32_t insns_size_in_code_units,uint32_t debug_info_offset,bool is_static,uint32_t method_idx,const NewLocalCallback & new_local_callback)448 bool DexFile::DecodeDebugLocalInfo(uint32_t registers_size,
449 uint32_t ins_size,
450 uint32_t insns_size_in_code_units,
451 uint32_t debug_info_offset,
452 bool is_static,
453 uint32_t method_idx,
454 const NewLocalCallback& new_local_callback) const {
455 const uint8_t* const stream = GetDebugInfoStream(debug_info_offset);
456 if (stream == nullptr) {
457 return false;
458 }
459 std::vector<const char*> arg_descriptors;
460 DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
461 for (; it.HasNext(); it.Next()) {
462 arg_descriptors.push_back(it.GetDescriptor());
463 }
464 return DecodeDebugLocalInfo(stream,
465 GetLocation(),
466 GetMethodDeclaringClassDescriptor(GetMethodId(method_idx)),
467 arg_descriptors,
468 this->PrettyMethod(method_idx),
469 is_static,
470 registers_size,
471 ins_size,
472 insns_size_in_code_units,
473 [this](uint32_t idx) {
474 dex::StringIndex string_idx(idx);
475 return string_idx.IsValid() ? GetStringData(string_idx) : nullptr;
476 },
477 [this](uint16_t idx) {
478 dex::TypeIndex type_idx(idx);
479 return type_idx.IsValid() ? GetTypeDescriptor(type_idx) : nullptr;
480 },
481 new_local_callback);
482 }
483
484 template<typename DexDebugNewPosition, typename IndexToStringData>
DecodeDebugPositionInfo(const uint8_t * stream,IndexToStringData && index_to_string_data,DexDebugNewPosition && position_functor)485 bool DexFile::DecodeDebugPositionInfo(const uint8_t* stream,
486 IndexToStringData&& index_to_string_data,
487 DexDebugNewPosition&& position_functor) {
488 if (stream == nullptr) {
489 return false;
490 }
491
492 PositionInfo entry;
493 entry.line_ = DecodeDebugInfoParameterNames(&stream, VoidFunctor());
494
495 for (;;) {
496 uint8_t opcode = *stream++;
497 switch (opcode) {
498 case DBG_END_SEQUENCE:
499 return true; // end of stream.
500 case DBG_ADVANCE_PC:
501 entry.address_ += DecodeUnsignedLeb128(&stream);
502 break;
503 case DBG_ADVANCE_LINE:
504 entry.line_ += DecodeSignedLeb128(&stream);
505 break;
506 case DBG_START_LOCAL:
507 DecodeUnsignedLeb128(&stream); // reg.
508 DecodeUnsignedLeb128P1(&stream); // name.
509 DecodeUnsignedLeb128P1(&stream); // descriptor.
510 break;
511 case DBG_START_LOCAL_EXTENDED:
512 DecodeUnsignedLeb128(&stream); // reg.
513 DecodeUnsignedLeb128P1(&stream); // name.
514 DecodeUnsignedLeb128P1(&stream); // descriptor.
515 DecodeUnsignedLeb128P1(&stream); // signature.
516 break;
517 case DBG_END_LOCAL:
518 case DBG_RESTART_LOCAL:
519 DecodeUnsignedLeb128(&stream); // reg.
520 break;
521 case DBG_SET_PROLOGUE_END:
522 entry.prologue_end_ = true;
523 break;
524 case DBG_SET_EPILOGUE_BEGIN:
525 entry.epilogue_begin_ = true;
526 break;
527 case DBG_SET_FILE: {
528 uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
529 entry.source_file_ = index_to_string_data(name_idx);
530 break;
531 }
532 default: {
533 int adjopcode = opcode - DBG_FIRST_SPECIAL;
534 entry.address_ += adjopcode / DBG_LINE_RANGE;
535 entry.line_ += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
536 if (position_functor(entry)) {
537 return true; // early exit.
538 }
539 entry.prologue_end_ = false;
540 entry.epilogue_begin_ = false;
541 break;
542 }
543 }
544 }
545 }
546
AsCompactDexFile()547 inline const CompactDexFile* DexFile::AsCompactDexFile() const {
548 DCHECK(IsCompactDexFile());
549 return down_cast<const CompactDexFile*>(this);
550 }
551
AsStandardDexFile()552 inline const StandardDexFile* DexFile::AsStandardDexFile() const {
553 DCHECK(IsStandardDexFile());
554 return down_cast<const StandardDexFile*>(this);
555 }
556
557 // Get the base of the encoded data for the given DexCode.
GetCatchHandlerData(const DexInstructionIterator & code_item_end,uint32_t tries_size,uint32_t offset)558 inline const uint8_t* DexFile::GetCatchHandlerData(const DexInstructionIterator& code_item_end,
559 uint32_t tries_size,
560 uint32_t offset) {
561 const uint8_t* handler_data =
562 reinterpret_cast<const uint8_t*>(GetTryItems(code_item_end, tries_size));
563 return handler_data + offset;
564 }
565
GetClasses()566 inline IterationRange<ClassIterator> DexFile::GetClasses() const {
567 return { ClassIterator(*this, 0u), ClassIterator(*this, NumClassDefs()) };
568 }
569
570 // Returns the line number
571 template <typename Visitor>
DecodeDebugInfoParameterNames(const uint8_t ** debug_info,Visitor && visitor)572 inline uint32_t DexFile::DecodeDebugInfoParameterNames(const uint8_t** debug_info,
573 Visitor&& visitor) {
574 uint32_t line = DecodeUnsignedLeb128(debug_info);
575 const uint32_t parameters_size = DecodeUnsignedLeb128(debug_info);
576 for (uint32_t i = 0; i < parameters_size; ++i) {
577 visitor(dex::StringIndex(DecodeUnsignedLeb128P1(debug_info)));
578 }
579 return line;
580 }
581
582 } // namespace art
583
584 #endif // ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
585