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