xref: /aosp_15_r20/art/libdexfile/dex/dex_file.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "dex_file.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <limits.h>
20*795d594fSAndroid Build Coastguard Worker #include <stdio.h>
21*795d594fSAndroid Build Coastguard Worker #include <stdlib.h>
22*795d594fSAndroid Build Coastguard Worker #include <string.h>
23*795d594fSAndroid Build Coastguard Worker #include <zlib.h>
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker #include <memory>
26*795d594fSAndroid Build Coastguard Worker #include <optional>
27*795d594fSAndroid Build Coastguard Worker #include <ostream>
28*795d594fSAndroid Build Coastguard Worker #include <sstream>
29*795d594fSAndroid Build Coastguard Worker #include <type_traits>
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/hiddenapi_domain.h"
33*795d594fSAndroid Build Coastguard Worker #include "base/leb128.h"
34*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
35*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
36*795d594fSAndroid Build Coastguard Worker #include "class_accessor-inl.h"
37*795d594fSAndroid Build Coastguard Worker #include "compact_dex_file.h"
38*795d594fSAndroid Build Coastguard Worker #include "descriptors_names.h"
39*795d594fSAndroid Build Coastguard Worker #include "dex_file-inl.h"
40*795d594fSAndroid Build Coastguard Worker #include "standard_dex_file.h"
41*795d594fSAndroid Build Coastguard Worker #include "utf-inl.h"
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker namespace art {
44*795d594fSAndroid Build Coastguard Worker 
45*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
46*795d594fSAndroid Build Coastguard Worker 
47*795d594fSAndroid Build Coastguard Worker using dex::CallSiteIdItem;
48*795d594fSAndroid Build Coastguard Worker using dex::ClassDef;
49*795d594fSAndroid Build Coastguard Worker using dex::FieldId;
50*795d594fSAndroid Build Coastguard Worker using dex::MapList;
51*795d594fSAndroid Build Coastguard Worker using dex::MapItem;
52*795d594fSAndroid Build Coastguard Worker using dex::MethodHandleItem;
53*795d594fSAndroid Build Coastguard Worker using dex::MethodId;
54*795d594fSAndroid Build Coastguard Worker using dex::ProtoId;
55*795d594fSAndroid Build Coastguard Worker using dex::StringId;
56*795d594fSAndroid Build Coastguard Worker using dex::TryItem;
57*795d594fSAndroid Build Coastguard Worker using dex::TypeId;
58*795d594fSAndroid Build Coastguard Worker using dex::TypeList;
59*795d594fSAndroid Build Coastguard Worker 
60*795d594fSAndroid Build Coastguard Worker static_assert(sizeof(dex::StringIndex) == sizeof(uint32_t), "StringIndex size is wrong");
61*795d594fSAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<dex::StringIndex>::value, "StringIndex not trivial");
62*795d594fSAndroid Build Coastguard Worker static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong");
63*795d594fSAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial");
64*795d594fSAndroid Build Coastguard Worker 
65*795d594fSAndroid Build Coastguard Worker // Print the SHA1 as 20-byte hexadecimal string.
ToString() const66*795d594fSAndroid Build Coastguard Worker std::string DexFile::Sha1::ToString() const {
67*795d594fSAndroid Build Coastguard Worker   auto data = this->data();
68*795d594fSAndroid Build Coastguard Worker   auto part = [d = data](int i) { return d[i] << 24 | d[i + 1] << 16 | d[i + 2] << 8 | d[i + 3]; };
69*795d594fSAndroid Build Coastguard Worker   return StringPrintf("%08x%08x%08x%08x%08x", part(0), part(4), part(8), part(12), part(16));
70*795d594fSAndroid Build Coastguard Worker }
71*795d594fSAndroid Build Coastguard Worker 
CalculateChecksum() const72*795d594fSAndroid Build Coastguard Worker uint32_t DexFile::CalculateChecksum() const {
73*795d594fSAndroid Build Coastguard Worker   return CalculateChecksum(Begin(), Size());
74*795d594fSAndroid Build Coastguard Worker }
75*795d594fSAndroid Build Coastguard Worker 
CalculateChecksum(const uint8_t * begin,size_t size)76*795d594fSAndroid Build Coastguard Worker uint32_t DexFile::CalculateChecksum(const uint8_t* begin, size_t size) {
77*795d594fSAndroid Build Coastguard Worker   const uint32_t non_sum_bytes = OFFSETOF_MEMBER(DexFile::Header, signature_);
78*795d594fSAndroid Build Coastguard Worker   return ChecksumMemoryRange(begin + non_sum_bytes, size - non_sum_bytes);
79*795d594fSAndroid Build Coastguard Worker }
80*795d594fSAndroid Build Coastguard Worker 
ChecksumMemoryRange(const uint8_t * begin,size_t size)81*795d594fSAndroid Build Coastguard Worker uint32_t DexFile::ChecksumMemoryRange(const uint8_t* begin, size_t size) {
82*795d594fSAndroid Build Coastguard Worker   return adler32(adler32(0L, Z_NULL, 0), begin, size);
83*795d594fSAndroid Build Coastguard Worker }
84*795d594fSAndroid Build Coastguard Worker 
IsReadOnly() const85*795d594fSAndroid Build Coastguard Worker bool DexFile::IsReadOnly() const {
86*795d594fSAndroid Build Coastguard Worker   CHECK(container_.get() != nullptr);
87*795d594fSAndroid Build Coastguard Worker   return container_->IsReadOnly();
88*795d594fSAndroid Build Coastguard Worker }
89*795d594fSAndroid Build Coastguard Worker 
EnableWrite() const90*795d594fSAndroid Build Coastguard Worker bool DexFile::EnableWrite() const {
91*795d594fSAndroid Build Coastguard Worker   CHECK(container_.get() != nullptr);
92*795d594fSAndroid Build Coastguard Worker   return container_->EnableWrite();
93*795d594fSAndroid Build Coastguard Worker }
94*795d594fSAndroid Build Coastguard Worker 
DisableWrite() const95*795d594fSAndroid Build Coastguard Worker bool DexFile::DisableWrite() const {
96*795d594fSAndroid Build Coastguard Worker   CHECK(container_.get() != nullptr);
97*795d594fSAndroid Build Coastguard Worker   return container_->DisableWrite();
98*795d594fSAndroid Build Coastguard Worker }
99*795d594fSAndroid Build Coastguard Worker 
GetExpectedHeaderSize() const100*795d594fSAndroid Build Coastguard Worker uint32_t DexFile::Header::GetExpectedHeaderSize() const {
101*795d594fSAndroid Build Coastguard Worker   uint32_t version = GetVersion();
102*795d594fSAndroid Build Coastguard Worker   return version == 0 ? 0 : version < 41 ? sizeof(Header) : sizeof(HeaderV41);
103*795d594fSAndroid Build Coastguard Worker }
104*795d594fSAndroid Build Coastguard Worker 
HasDexContainer() const105*795d594fSAndroid Build Coastguard Worker bool DexFile::Header::HasDexContainer() const {
106*795d594fSAndroid Build Coastguard Worker   if (CompactDexFile::IsMagicValid(magic_.data())) {
107*795d594fSAndroid Build Coastguard Worker     return false;
108*795d594fSAndroid Build Coastguard Worker   }
109*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(header_size_, GetExpectedHeaderSize());
110*795d594fSAndroid Build Coastguard Worker   return header_size_ >= sizeof(HeaderV41);
111*795d594fSAndroid Build Coastguard Worker }
112*795d594fSAndroid Build Coastguard Worker 
HeaderOffset() const113*795d594fSAndroid Build Coastguard Worker uint32_t DexFile::Header::HeaderOffset() const {
114*795d594fSAndroid Build Coastguard Worker   return HasDexContainer() ? reinterpret_cast<const HeaderV41*>(this)->header_offset_ : 0;
115*795d594fSAndroid Build Coastguard Worker }
116*795d594fSAndroid Build Coastguard Worker 
ContainerSize() const117*795d594fSAndroid Build Coastguard Worker uint32_t DexFile::Header::ContainerSize() const {
118*795d594fSAndroid Build Coastguard Worker   return HasDexContainer() ? reinterpret_cast<const HeaderV41*>(this)->container_size_ : file_size_;
119*795d594fSAndroid Build Coastguard Worker }
120*795d594fSAndroid Build Coastguard Worker 
SetDexContainer(size_t header_offset,size_t container_size)121*795d594fSAndroid Build Coastguard Worker void DexFile::Header::SetDexContainer(size_t header_offset, size_t container_size) {
122*795d594fSAndroid Build Coastguard Worker   if (HasDexContainer()) {
123*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(header_offset, container_size);
124*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(file_size_, container_size - header_offset);
125*795d594fSAndroid Build Coastguard Worker     data_off_ = 0;
126*795d594fSAndroid Build Coastguard Worker     data_size_ = 0;
127*795d594fSAndroid Build Coastguard Worker     auto* headerV41 = reinterpret_cast<HeaderV41*>(this);
128*795d594fSAndroid Build Coastguard Worker     DCHECK_GE(header_size_, sizeof(*headerV41));
129*795d594fSAndroid Build Coastguard Worker     headerV41->header_offset_ = header_offset;
130*795d594fSAndroid Build Coastguard Worker     headerV41->container_size_ = container_size;
131*795d594fSAndroid Build Coastguard Worker   } else {
132*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(header_offset, 0u);
133*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(container_size, file_size_);
134*795d594fSAndroid Build Coastguard Worker   }
135*795d594fSAndroid Build Coastguard Worker }
136*795d594fSAndroid Build Coastguard Worker 
137*795d594fSAndroid Build Coastguard Worker template <typename T>
GetSection(const uint32_t * offset,DexFileContainer * container)138*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE const T* DexFile::GetSection(const uint32_t* offset, DexFileContainer* container) {
139*795d594fSAndroid Build Coastguard Worker   size_t size = container->End() - begin_;
140*795d594fSAndroid Build Coastguard Worker   if (size < sizeof(Header)) {
141*795d594fSAndroid Build Coastguard Worker     return nullptr;  // Invalid dex file.
142*795d594fSAndroid Build Coastguard Worker   }
143*795d594fSAndroid Build Coastguard Worker   // Compact dex is inconsistent: section offsets are relative to the
144*795d594fSAndroid Build Coastguard Worker   // header as opposed to the data section like all other its offsets.
145*795d594fSAndroid Build Coastguard Worker   if (CompactDexFile::IsMagicValid(begin_)) {
146*795d594fSAndroid Build Coastguard Worker     const uint8_t* data = reinterpret_cast<const uint8_t*>(header_);
147*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<const T*>(data + *offset);
148*795d594fSAndroid Build Coastguard Worker   }
149*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<const T*>(data_.data() + *offset);
150*795d594fSAndroid Build Coastguard Worker }
151*795d594fSAndroid Build Coastguard Worker 
DexFile(const uint8_t * base,const std::string & location,uint32_t location_checksum,const OatDexFile * oat_dex_file,std::shared_ptr<DexFileContainer> container,bool is_compact_dex)152*795d594fSAndroid Build Coastguard Worker DexFile::DexFile(const uint8_t* base,
153*795d594fSAndroid Build Coastguard Worker                  const std::string& location,
154*795d594fSAndroid Build Coastguard Worker                  uint32_t location_checksum,
155*795d594fSAndroid Build Coastguard Worker                  const OatDexFile* oat_dex_file,
156*795d594fSAndroid Build Coastguard Worker                  std::shared_ptr<DexFileContainer> container,
157*795d594fSAndroid Build Coastguard Worker                  bool is_compact_dex)
158*795d594fSAndroid Build Coastguard Worker     : begin_(base),
159*795d594fSAndroid Build Coastguard Worker       data_(GetDataRange(base, container.get())),
160*795d594fSAndroid Build Coastguard Worker       location_(location),
161*795d594fSAndroid Build Coastguard Worker       location_checksum_(location_checksum),
162*795d594fSAndroid Build Coastguard Worker       header_(reinterpret_cast<const Header*>(base)),
163*795d594fSAndroid Build Coastguard Worker       string_ids_(GetSection<StringId>(&header_->string_ids_off_, container.get())),
164*795d594fSAndroid Build Coastguard Worker       type_ids_(GetSection<TypeId>(&header_->type_ids_off_, container.get())),
165*795d594fSAndroid Build Coastguard Worker       field_ids_(GetSection<FieldId>(&header_->field_ids_off_, container.get())),
166*795d594fSAndroid Build Coastguard Worker       method_ids_(GetSection<MethodId>(&header_->method_ids_off_, container.get())),
167*795d594fSAndroid Build Coastguard Worker       proto_ids_(GetSection<ProtoId>(&header_->proto_ids_off_, container.get())),
168*795d594fSAndroid Build Coastguard Worker       class_defs_(GetSection<ClassDef>(&header_->class_defs_off_, container.get())),
169*795d594fSAndroid Build Coastguard Worker       method_handles_(nullptr),
170*795d594fSAndroid Build Coastguard Worker       num_method_handles_(0),
171*795d594fSAndroid Build Coastguard Worker       call_site_ids_(nullptr),
172*795d594fSAndroid Build Coastguard Worker       num_call_site_ids_(0),
173*795d594fSAndroid Build Coastguard Worker       hiddenapi_class_data_(nullptr),
174*795d594fSAndroid Build Coastguard Worker       oat_dex_file_(oat_dex_file),
175*795d594fSAndroid Build Coastguard Worker       container_(std::move(container)),
176*795d594fSAndroid Build Coastguard Worker       is_compact_dex_(is_compact_dex),
177*795d594fSAndroid Build Coastguard Worker       hiddenapi_domain_(hiddenapi::Domain::kApplication) {
178*795d594fSAndroid Build Coastguard Worker   CHECK(begin_ != nullptr) << GetLocation();
179*795d594fSAndroid Build Coastguard Worker   // Check base (=header) alignment.
180*795d594fSAndroid Build Coastguard Worker   // Must be 4-byte aligned to avoid undefined behavior when accessing
181*795d594fSAndroid Build Coastguard Worker   // any of the sections via a pointer.
182*795d594fSAndroid Build Coastguard Worker   CHECK_ALIGNED(begin_, alignof(Header));
183*795d594fSAndroid Build Coastguard Worker 
184*795d594fSAndroid Build Coastguard Worker   if (DataSize() < sizeof(Header)) {
185*795d594fSAndroid Build Coastguard Worker     // Don't go further if the data doesn't even contain a header.
186*795d594fSAndroid Build Coastguard Worker     return;
187*795d594fSAndroid Build Coastguard Worker   }
188*795d594fSAndroid Build Coastguard Worker 
189*795d594fSAndroid Build Coastguard Worker   InitializeSectionsFromMapList();
190*795d594fSAndroid Build Coastguard Worker }
191*795d594fSAndroid Build Coastguard Worker 
~DexFile()192*795d594fSAndroid Build Coastguard Worker DexFile::~DexFile() {
193*795d594fSAndroid Build Coastguard Worker   // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and
194*795d594fSAndroid Build Coastguard Worker   // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could
195*795d594fSAndroid Build Coastguard Worker   // re-attach, but cleaning up these global references is not obviously useful. It's not as if
196*795d594fSAndroid Build Coastguard Worker   // the global reference table is otherwise empty!
197*795d594fSAndroid Build Coastguard Worker }
198*795d594fSAndroid Build Coastguard Worker 
Init(std::string * error_msg)199*795d594fSAndroid Build Coastguard Worker bool DexFile::Init(std::string* error_msg) {
200*795d594fSAndroid Build Coastguard Worker   CHECK_GE(container_->End(), reinterpret_cast<const uint8_t*>(header_));
201*795d594fSAndroid Build Coastguard Worker   size_t container_size = container_->End() - reinterpret_cast<const uint8_t*>(header_);
202*795d594fSAndroid Build Coastguard Worker   if (container_size < sizeof(Header)) {
203*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Unable to open '%s' : File size is too small to fit dex header",
204*795d594fSAndroid Build Coastguard Worker                               location_.c_str());
205*795d594fSAndroid Build Coastguard Worker     return false;
206*795d594fSAndroid Build Coastguard Worker   }
207*795d594fSAndroid Build Coastguard Worker   if (!CheckMagicAndVersion(error_msg)) {
208*795d594fSAndroid Build Coastguard Worker     return false;
209*795d594fSAndroid Build Coastguard Worker   }
210*795d594fSAndroid Build Coastguard Worker   if (!IsCompactDexFile()) {
211*795d594fSAndroid Build Coastguard Worker     uint32_t expected_header_size = header_->GetExpectedHeaderSize();
212*795d594fSAndroid Build Coastguard Worker     if (header_->header_size_ != expected_header_size) {
213*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Unable to open '%s' : Header size is %u but %u was expected",
214*795d594fSAndroid Build Coastguard Worker                                 location_.c_str(),
215*795d594fSAndroid Build Coastguard Worker                                 header_->header_size_,
216*795d594fSAndroid Build Coastguard Worker                                 expected_header_size);
217*795d594fSAndroid Build Coastguard Worker       return false;
218*795d594fSAndroid Build Coastguard Worker     }
219*795d594fSAndroid Build Coastguard Worker   }
220*795d594fSAndroid Build Coastguard Worker   if (container_size < header_->file_size_) {
221*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Unable to open '%s' : File size is %zu but the header expects %u",
222*795d594fSAndroid Build Coastguard Worker                               location_.c_str(),
223*795d594fSAndroid Build Coastguard Worker                               container_size,
224*795d594fSAndroid Build Coastguard Worker                               header_->file_size_);
225*795d594fSAndroid Build Coastguard Worker     return false;
226*795d594fSAndroid Build Coastguard Worker   }
227*795d594fSAndroid Build Coastguard Worker   return true;
228*795d594fSAndroid Build Coastguard Worker }
229*795d594fSAndroid Build Coastguard Worker 
CheckMagicAndVersion(std::string * error_msg) const230*795d594fSAndroid Build Coastguard Worker bool DexFile::CheckMagicAndVersion(std::string* error_msg) const {
231*795d594fSAndroid Build Coastguard Worker   if (!IsMagicValid()) {
232*795d594fSAndroid Build Coastguard Worker     std::ostringstream oss;
233*795d594fSAndroid Build Coastguard Worker     oss << "Unrecognized magic number in "  << GetLocation() << ":"
234*795d594fSAndroid Build Coastguard Worker             << " " << header_->magic_[0]
235*795d594fSAndroid Build Coastguard Worker             << " " << header_->magic_[1]
236*795d594fSAndroid Build Coastguard Worker             << " " << header_->magic_[2]
237*795d594fSAndroid Build Coastguard Worker             << " " << header_->magic_[3];
238*795d594fSAndroid Build Coastguard Worker     *error_msg = oss.str();
239*795d594fSAndroid Build Coastguard Worker     return false;
240*795d594fSAndroid Build Coastguard Worker   }
241*795d594fSAndroid Build Coastguard Worker   if (!IsVersionValid()) {
242*795d594fSAndroid Build Coastguard Worker     std::ostringstream oss;
243*795d594fSAndroid Build Coastguard Worker     oss << "Unrecognized version number in "  << GetLocation() << ":"
244*795d594fSAndroid Build Coastguard Worker             << " " << header_->magic_[4]
245*795d594fSAndroid Build Coastguard Worker             << " " << header_->magic_[5]
246*795d594fSAndroid Build Coastguard Worker             << " " << header_->magic_[6]
247*795d594fSAndroid Build Coastguard Worker             << " " << header_->magic_[7];
248*795d594fSAndroid Build Coastguard Worker     *error_msg = oss.str();
249*795d594fSAndroid Build Coastguard Worker     return false;
250*795d594fSAndroid Build Coastguard Worker   }
251*795d594fSAndroid Build Coastguard Worker   return true;
252*795d594fSAndroid Build Coastguard Worker }
253*795d594fSAndroid Build Coastguard Worker 
GetDataRange(const uint8_t * data,DexFileContainer * container)254*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint8_t> DexFile::GetDataRange(const uint8_t* data, DexFileContainer* container) {
255*795d594fSAndroid Build Coastguard Worker   // NB: This function must survive random data to pass fuzzing and testing.
256*795d594fSAndroid Build Coastguard Worker   CHECK(container != nullptr);
257*795d594fSAndroid Build Coastguard Worker   CHECK_GE(data, container->Begin());
258*795d594fSAndroid Build Coastguard Worker   CHECK_LE(data, container->End());
259*795d594fSAndroid Build Coastguard Worker   size_t size = container->End() - data;
260*795d594fSAndroid Build Coastguard Worker   if (size >= sizeof(StandardDexFile::Header) && StandardDexFile::IsMagicValid(data)) {
261*795d594fSAndroid Build Coastguard Worker     auto header = reinterpret_cast<const DexFile::Header*>(data);
262*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(container->Data().size(), 0u) << "Unsupported for standard dex";
263*795d594fSAndroid Build Coastguard Worker     if (size >= sizeof(HeaderV41) && header->header_size_ >= sizeof(HeaderV41)) {
264*795d594fSAndroid Build Coastguard Worker       auto headerV41 = reinterpret_cast<const DexFile::HeaderV41*>(data);
265*795d594fSAndroid Build Coastguard Worker       data -= headerV41->header_offset_;  // Allow underflow and later overflow.
266*795d594fSAndroid Build Coastguard Worker       size = headerV41->container_size_;
267*795d594fSAndroid Build Coastguard Worker     } else {
268*795d594fSAndroid Build Coastguard Worker       size = header->file_size_;
269*795d594fSAndroid Build Coastguard Worker     }
270*795d594fSAndroid Build Coastguard Worker   } else if (size >= sizeof(CompactDexFile::Header) && CompactDexFile::IsMagicValid(data)) {
271*795d594fSAndroid Build Coastguard Worker     auto header = reinterpret_cast<const CompactDexFile::Header*>(data);
272*795d594fSAndroid Build Coastguard Worker     // TODO: Remove. This is a hack. See comment of the Data method.
273*795d594fSAndroid Build Coastguard Worker     ArrayRef<const uint8_t> separate_data = container->Data();
274*795d594fSAndroid Build Coastguard Worker     if (separate_data.size() > 0) {
275*795d594fSAndroid Build Coastguard Worker       return separate_data;
276*795d594fSAndroid Build Coastguard Worker     }
277*795d594fSAndroid Build Coastguard Worker     // Shared compact dex data is located at the end after all dex files.
278*795d594fSAndroid Build Coastguard Worker     data += std::min<size_t>(header->data_off_, size);
279*795d594fSAndroid Build Coastguard Worker     size = header->data_size_;
280*795d594fSAndroid Build Coastguard Worker   }
281*795d594fSAndroid Build Coastguard Worker   // The returned range is guaranteed to be in bounds of the container memory.
282*795d594fSAndroid Build Coastguard Worker   return {data, std::min<size_t>(size, container->End() - data)};
283*795d594fSAndroid Build Coastguard Worker }
284*795d594fSAndroid Build Coastguard Worker 
InitializeSectionsFromMapList()285*795d594fSAndroid Build Coastguard Worker void DexFile::InitializeSectionsFromMapList() {
286*795d594fSAndroid Build Coastguard Worker   // NB: This function must survive random data to pass fuzzing and testing.
287*795d594fSAndroid Build Coastguard Worker   static_assert(sizeof(MapList) <= sizeof(Header));
288*795d594fSAndroid Build Coastguard Worker   DCHECK_GE(DataSize(), sizeof(MapList));
289*795d594fSAndroid Build Coastguard Worker   if (header_->map_off_ == 0 || header_->map_off_ > DataSize() - sizeof(MapList)) {
290*795d594fSAndroid Build Coastguard Worker     // Bad offset. The dex file verifier runs after this method and will reject the file.
291*795d594fSAndroid Build Coastguard Worker     return;
292*795d594fSAndroid Build Coastguard Worker   }
293*795d594fSAndroid Build Coastguard Worker   const uint8_t* map_list_raw = DataBegin() + header_->map_off_;
294*795d594fSAndroid Build Coastguard Worker   if (map_list_raw < Begin()) {
295*795d594fSAndroid Build Coastguard Worker     return;
296*795d594fSAndroid Build Coastguard Worker   }
297*795d594fSAndroid Build Coastguard Worker   const MapList* map_list = reinterpret_cast<const MapList*>(map_list_raw);
298*795d594fSAndroid Build Coastguard Worker   const size_t count = map_list->size_;
299*795d594fSAndroid Build Coastguard Worker 
300*795d594fSAndroid Build Coastguard Worker   size_t map_limit =
301*795d594fSAndroid Build Coastguard Worker       (DataSize() - OFFSETOF_MEMBER(MapList, list_) - header_->map_off_) / sizeof(MapItem);
302*795d594fSAndroid Build Coastguard Worker   if (count > map_limit) {
303*795d594fSAndroid Build Coastguard Worker     // Too many items. The dex file verifier runs after
304*795d594fSAndroid Build Coastguard Worker     // this method and will reject the file as it is malformed.
305*795d594fSAndroid Build Coastguard Worker     return;
306*795d594fSAndroid Build Coastguard Worker   }
307*795d594fSAndroid Build Coastguard Worker 
308*795d594fSAndroid Build Coastguard Worker   // Construct pointers to certain arrays without any checks. If they are outside the
309*795d594fSAndroid Build Coastguard Worker   // data, the dex file verification should fail and these pointers should not be used.
310*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < count; ++i) {
311*795d594fSAndroid Build Coastguard Worker     const MapItem& map_item = map_list->list_[i];
312*795d594fSAndroid Build Coastguard Worker     if (map_item.type_ == kDexTypeMethodHandleItem) {
313*795d594fSAndroid Build Coastguard Worker       method_handles_ = GetSection<MethodHandleItem>(&map_item.offset_, container_.get());
314*795d594fSAndroid Build Coastguard Worker       num_method_handles_ = map_item.size_;
315*795d594fSAndroid Build Coastguard Worker     } else if (map_item.type_ == kDexTypeCallSiteIdItem) {
316*795d594fSAndroid Build Coastguard Worker       call_site_ids_ = GetSection<CallSiteIdItem>(&map_item.offset_, container_.get());
317*795d594fSAndroid Build Coastguard Worker       num_call_site_ids_ = map_item.size_;
318*795d594fSAndroid Build Coastguard Worker     } else if (map_item.type_ == kDexTypeHiddenapiClassData) {
319*795d594fSAndroid Build Coastguard Worker       hiddenapi_class_data_ =
320*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<const dex::HiddenapiClassData*>(DataBegin() + map_item.offset_);
321*795d594fSAndroid Build Coastguard Worker     } else {
322*795d594fSAndroid Build Coastguard Worker       // Pointers to other sections are not necessary to retain in the DexFile struct.
323*795d594fSAndroid Build Coastguard Worker       // Other items have pointers directly into their data.
324*795d594fSAndroid Build Coastguard Worker     }
325*795d594fSAndroid Build Coastguard Worker   }
326*795d594fSAndroid Build Coastguard Worker }
327*795d594fSAndroid Build Coastguard Worker 
GetVersion() const328*795d594fSAndroid Build Coastguard Worker uint32_t DexFile::Header::GetVersion() const {
329*795d594fSAndroid Build Coastguard Worker   const char* version = reinterpret_cast<const char*>(&magic_[kDexMagicSize]);
330*795d594fSAndroid Build Coastguard Worker   return atoi(version);
331*795d594fSAndroid Build Coastguard Worker }
332*795d594fSAndroid Build Coastguard Worker 
FindClassDef(dex::TypeIndex type_idx) const333*795d594fSAndroid Build Coastguard Worker const ClassDef* DexFile::FindClassDef(dex::TypeIndex type_idx) const {
334*795d594fSAndroid Build Coastguard Worker   size_t num_class_defs = NumClassDefs();
335*795d594fSAndroid Build Coastguard Worker   // Fast path for rare no class defs case.
336*795d594fSAndroid Build Coastguard Worker   if (num_class_defs == 0) {
337*795d594fSAndroid Build Coastguard Worker     return nullptr;
338*795d594fSAndroid Build Coastguard Worker   }
339*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < num_class_defs; ++i) {
340*795d594fSAndroid Build Coastguard Worker     const ClassDef& class_def = GetClassDef(i);
341*795d594fSAndroid Build Coastguard Worker     if (class_def.class_idx_ == type_idx) {
342*795d594fSAndroid Build Coastguard Worker       return &class_def;
343*795d594fSAndroid Build Coastguard Worker     }
344*795d594fSAndroid Build Coastguard Worker   }
345*795d594fSAndroid Build Coastguard Worker   return nullptr;
346*795d594fSAndroid Build Coastguard Worker }
347*795d594fSAndroid Build Coastguard Worker 
GetCodeItemOffset(const ClassDef & class_def,uint32_t method_idx) const348*795d594fSAndroid Build Coastguard Worker std::optional<uint32_t> DexFile::GetCodeItemOffset(const ClassDef &class_def,
349*795d594fSAndroid Build Coastguard Worker                                                    uint32_t method_idx) const {
350*795d594fSAndroid Build Coastguard Worker   ClassAccessor accessor(*this, class_def);
351*795d594fSAndroid Build Coastguard Worker   CHECK(accessor.HasClassData());
352*795d594fSAndroid Build Coastguard Worker   for (const ClassAccessor::Method &method : accessor.GetMethods()) {
353*795d594fSAndroid Build Coastguard Worker     if (method.GetIndex() == method_idx) {
354*795d594fSAndroid Build Coastguard Worker       return method.GetCodeItemOffset();
355*795d594fSAndroid Build Coastguard Worker     }
356*795d594fSAndroid Build Coastguard Worker   }
357*795d594fSAndroid Build Coastguard Worker   return std::nullopt;
358*795d594fSAndroid Build Coastguard Worker }
359*795d594fSAndroid Build Coastguard Worker 
FindCodeItemOffset(const dex::ClassDef & class_def,uint32_t dex_method_idx) const360*795d594fSAndroid Build Coastguard Worker uint32_t DexFile::FindCodeItemOffset(const dex::ClassDef &class_def,
361*795d594fSAndroid Build Coastguard Worker                                      uint32_t dex_method_idx) const {
362*795d594fSAndroid Build Coastguard Worker   std::optional<uint32_t> val = GetCodeItemOffset(class_def, dex_method_idx);
363*795d594fSAndroid Build Coastguard Worker   CHECK(val.has_value()) << "Unable to find method " << dex_method_idx;
364*795d594fSAndroid Build Coastguard Worker   return *val;
365*795d594fSAndroid Build Coastguard Worker }
366*795d594fSAndroid Build Coastguard Worker 
FindFieldId(const TypeId & declaring_klass,const StringId & name,const TypeId & type) const367*795d594fSAndroid Build Coastguard Worker const FieldId* DexFile::FindFieldId(const TypeId& declaring_klass,
368*795d594fSAndroid Build Coastguard Worker                                     const StringId& name,
369*795d594fSAndroid Build Coastguard Worker                                     const TypeId& type) const {
370*795d594fSAndroid Build Coastguard Worker   // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
371*795d594fSAndroid Build Coastguard Worker   const dex::TypeIndex class_idx = GetIndexForTypeId(declaring_klass);
372*795d594fSAndroid Build Coastguard Worker   const dex::StringIndex name_idx = GetIndexForStringId(name);
373*795d594fSAndroid Build Coastguard Worker   const dex::TypeIndex type_idx = GetIndexForTypeId(type);
374*795d594fSAndroid Build Coastguard Worker   int32_t lo = 0;
375*795d594fSAndroid Build Coastguard Worker   int32_t hi = NumFieldIds() - 1;
376*795d594fSAndroid Build Coastguard Worker   while (hi >= lo) {
377*795d594fSAndroid Build Coastguard Worker     int32_t mid = (hi + lo) / 2;
378*795d594fSAndroid Build Coastguard Worker     const FieldId& field = GetFieldId(mid);
379*795d594fSAndroid Build Coastguard Worker     if (class_idx > field.class_idx_) {
380*795d594fSAndroid Build Coastguard Worker       lo = mid + 1;
381*795d594fSAndroid Build Coastguard Worker     } else if (class_idx < field.class_idx_) {
382*795d594fSAndroid Build Coastguard Worker       hi = mid - 1;
383*795d594fSAndroid Build Coastguard Worker     } else {
384*795d594fSAndroid Build Coastguard Worker       if (name_idx > field.name_idx_) {
385*795d594fSAndroid Build Coastguard Worker         lo = mid + 1;
386*795d594fSAndroid Build Coastguard Worker       } else if (name_idx < field.name_idx_) {
387*795d594fSAndroid Build Coastguard Worker         hi = mid - 1;
388*795d594fSAndroid Build Coastguard Worker       } else {
389*795d594fSAndroid Build Coastguard Worker         if (type_idx > field.type_idx_) {
390*795d594fSAndroid Build Coastguard Worker           lo = mid + 1;
391*795d594fSAndroid Build Coastguard Worker         } else if (type_idx < field.type_idx_) {
392*795d594fSAndroid Build Coastguard Worker           hi = mid - 1;
393*795d594fSAndroid Build Coastguard Worker         } else {
394*795d594fSAndroid Build Coastguard Worker           return &field;
395*795d594fSAndroid Build Coastguard Worker         }
396*795d594fSAndroid Build Coastguard Worker       }
397*795d594fSAndroid Build Coastguard Worker     }
398*795d594fSAndroid Build Coastguard Worker   }
399*795d594fSAndroid Build Coastguard Worker   return nullptr;
400*795d594fSAndroid Build Coastguard Worker }
401*795d594fSAndroid Build Coastguard Worker 
FindMethodId(const TypeId & declaring_klass,const StringId & name,const ProtoId & signature) const402*795d594fSAndroid Build Coastguard Worker const MethodId* DexFile::FindMethodId(const TypeId& declaring_klass,
403*795d594fSAndroid Build Coastguard Worker                                       const StringId& name,
404*795d594fSAndroid Build Coastguard Worker                                       const ProtoId& signature) const {
405*795d594fSAndroid Build Coastguard Worker   // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
406*795d594fSAndroid Build Coastguard Worker   const dex::TypeIndex class_idx = GetIndexForTypeId(declaring_klass);
407*795d594fSAndroid Build Coastguard Worker   const dex::StringIndex name_idx = GetIndexForStringId(name);
408*795d594fSAndroid Build Coastguard Worker   const dex::ProtoIndex proto_idx = GetIndexForProtoId(signature);
409*795d594fSAndroid Build Coastguard Worker   return FindMethodIdByIndex(class_idx, name_idx, proto_idx);
410*795d594fSAndroid Build Coastguard Worker }
411*795d594fSAndroid Build Coastguard Worker 
FindMethodIdByIndex(dex::TypeIndex class_idx,dex::StringIndex name_idx,dex::ProtoIndex proto_idx) const412*795d594fSAndroid Build Coastguard Worker const MethodId* DexFile::FindMethodIdByIndex(dex::TypeIndex class_idx,
413*795d594fSAndroid Build Coastguard Worker                                              dex::StringIndex name_idx,
414*795d594fSAndroid Build Coastguard Worker                                              dex::ProtoIndex proto_idx) const {
415*795d594fSAndroid Build Coastguard Worker   // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
416*795d594fSAndroid Build Coastguard Worker   int32_t lo = 0;
417*795d594fSAndroid Build Coastguard Worker   int32_t hi = NumMethodIds() - 1;
418*795d594fSAndroid Build Coastguard Worker   while (hi >= lo) {
419*795d594fSAndroid Build Coastguard Worker     int32_t mid = (hi + lo) / 2;
420*795d594fSAndroid Build Coastguard Worker     const MethodId& method = GetMethodId(mid);
421*795d594fSAndroid Build Coastguard Worker     if (class_idx > method.class_idx_) {
422*795d594fSAndroid Build Coastguard Worker       lo = mid + 1;
423*795d594fSAndroid Build Coastguard Worker     } else if (class_idx < method.class_idx_) {
424*795d594fSAndroid Build Coastguard Worker       hi = mid - 1;
425*795d594fSAndroid Build Coastguard Worker     } else {
426*795d594fSAndroid Build Coastguard Worker       if (name_idx > method.name_idx_) {
427*795d594fSAndroid Build Coastguard Worker         lo = mid + 1;
428*795d594fSAndroid Build Coastguard Worker       } else if (name_idx < method.name_idx_) {
429*795d594fSAndroid Build Coastguard Worker         hi = mid - 1;
430*795d594fSAndroid Build Coastguard Worker       } else {
431*795d594fSAndroid Build Coastguard Worker         if (proto_idx > method.proto_idx_) {
432*795d594fSAndroid Build Coastguard Worker           lo = mid + 1;
433*795d594fSAndroid Build Coastguard Worker         } else if (proto_idx < method.proto_idx_) {
434*795d594fSAndroid Build Coastguard Worker           hi = mid - 1;
435*795d594fSAndroid Build Coastguard Worker         } else {
436*795d594fSAndroid Build Coastguard Worker           DCHECK_EQ(class_idx, method.class_idx_);
437*795d594fSAndroid Build Coastguard Worker           DCHECK_EQ(proto_idx, method.proto_idx_);
438*795d594fSAndroid Build Coastguard Worker           DCHECK_EQ(name_idx, method.name_idx_);
439*795d594fSAndroid Build Coastguard Worker           return &method;
440*795d594fSAndroid Build Coastguard Worker         }
441*795d594fSAndroid Build Coastguard Worker       }
442*795d594fSAndroid Build Coastguard Worker     }
443*795d594fSAndroid Build Coastguard Worker   }
444*795d594fSAndroid Build Coastguard Worker   return nullptr;
445*795d594fSAndroid Build Coastguard Worker }
446*795d594fSAndroid Build Coastguard Worker 
FindStringId(const char * string) const447*795d594fSAndroid Build Coastguard Worker const StringId* DexFile::FindStringId(const char* string) const {
448*795d594fSAndroid Build Coastguard Worker   int32_t lo = 0;
449*795d594fSAndroid Build Coastguard Worker   int32_t hi = NumStringIds() - 1;
450*795d594fSAndroid Build Coastguard Worker   while (hi >= lo) {
451*795d594fSAndroid Build Coastguard Worker     int32_t mid = (hi + lo) / 2;
452*795d594fSAndroid Build Coastguard Worker     const StringId& str_id = GetStringId(dex::StringIndex(mid));
453*795d594fSAndroid Build Coastguard Worker     const char* str = GetStringData(str_id);
454*795d594fSAndroid Build Coastguard Worker     int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string, str);
455*795d594fSAndroid Build Coastguard Worker     if (compare > 0) {
456*795d594fSAndroid Build Coastguard Worker       lo = mid + 1;
457*795d594fSAndroid Build Coastguard Worker     } else if (compare < 0) {
458*795d594fSAndroid Build Coastguard Worker       hi = mid - 1;
459*795d594fSAndroid Build Coastguard Worker     } else {
460*795d594fSAndroid Build Coastguard Worker       return &str_id;
461*795d594fSAndroid Build Coastguard Worker     }
462*795d594fSAndroid Build Coastguard Worker   }
463*795d594fSAndroid Build Coastguard Worker   return nullptr;
464*795d594fSAndroid Build Coastguard Worker }
465*795d594fSAndroid Build Coastguard Worker 
FindTypeId(std::string_view descriptor) const466*795d594fSAndroid Build Coastguard Worker const TypeId* DexFile::FindTypeId(std::string_view descriptor) const {
467*795d594fSAndroid Build Coastguard Worker   int32_t lo = 0;
468*795d594fSAndroid Build Coastguard Worker   int32_t hi = NumTypeIds() - 1;
469*795d594fSAndroid Build Coastguard Worker   while (hi >= lo) {
470*795d594fSAndroid Build Coastguard Worker     int32_t mid = (hi + lo) / 2;
471*795d594fSAndroid Build Coastguard Worker     const TypeId& type_id = GetTypeId(dex::TypeIndex(mid));
472*795d594fSAndroid Build Coastguard Worker     std::string_view mid_descriptor = GetTypeDescriptorView(type_id);
473*795d594fSAndroid Build Coastguard Worker     int compare = CompareDescriptors(descriptor, mid_descriptor);
474*795d594fSAndroid Build Coastguard Worker     if (compare > 0) {
475*795d594fSAndroid Build Coastguard Worker       lo = mid + 1;
476*795d594fSAndroid Build Coastguard Worker     } else if (compare < 0) {
477*795d594fSAndroid Build Coastguard Worker       hi = mid - 1;
478*795d594fSAndroid Build Coastguard Worker     } else {
479*795d594fSAndroid Build Coastguard Worker       return &type_id;
480*795d594fSAndroid Build Coastguard Worker     }
481*795d594fSAndroid Build Coastguard Worker   }
482*795d594fSAndroid Build Coastguard Worker   return nullptr;
483*795d594fSAndroid Build Coastguard Worker }
484*795d594fSAndroid Build Coastguard Worker 
FindTypeId(dex::StringIndex string_idx) const485*795d594fSAndroid Build Coastguard Worker const TypeId* DexFile::FindTypeId(dex::StringIndex string_idx) const {
486*795d594fSAndroid Build Coastguard Worker   int32_t lo = 0;
487*795d594fSAndroid Build Coastguard Worker   int32_t hi = NumTypeIds() - 1;
488*795d594fSAndroid Build Coastguard Worker   while (hi >= lo) {
489*795d594fSAndroid Build Coastguard Worker     int32_t mid = (hi + lo) / 2;
490*795d594fSAndroid Build Coastguard Worker     const TypeId& type_id = GetTypeId(dex::TypeIndex(mid));
491*795d594fSAndroid Build Coastguard Worker     if (string_idx > type_id.descriptor_idx_) {
492*795d594fSAndroid Build Coastguard Worker       lo = mid + 1;
493*795d594fSAndroid Build Coastguard Worker     } else if (string_idx < type_id.descriptor_idx_) {
494*795d594fSAndroid Build Coastguard Worker       hi = mid - 1;
495*795d594fSAndroid Build Coastguard Worker     } else {
496*795d594fSAndroid Build Coastguard Worker       return &type_id;
497*795d594fSAndroid Build Coastguard Worker     }
498*795d594fSAndroid Build Coastguard Worker   }
499*795d594fSAndroid Build Coastguard Worker   return nullptr;
500*795d594fSAndroid Build Coastguard Worker }
501*795d594fSAndroid Build Coastguard Worker 
FindProtoId(dex::TypeIndex return_type_idx,const dex::TypeIndex * signature_type_idxs,uint32_t signature_length) const502*795d594fSAndroid Build Coastguard Worker const ProtoId* DexFile::FindProtoId(dex::TypeIndex return_type_idx,
503*795d594fSAndroid Build Coastguard Worker                                     const dex::TypeIndex* signature_type_idxs,
504*795d594fSAndroid Build Coastguard Worker                                     uint32_t signature_length) const {
505*795d594fSAndroid Build Coastguard Worker   int32_t lo = 0;
506*795d594fSAndroid Build Coastguard Worker   int32_t hi = NumProtoIds() - 1;
507*795d594fSAndroid Build Coastguard Worker   while (hi >= lo) {
508*795d594fSAndroid Build Coastguard Worker     int32_t mid = (hi + lo) / 2;
509*795d594fSAndroid Build Coastguard Worker     const dex::ProtoIndex proto_idx = static_cast<dex::ProtoIndex>(mid);
510*795d594fSAndroid Build Coastguard Worker     const ProtoId& proto = GetProtoId(proto_idx);
511*795d594fSAndroid Build Coastguard Worker     int compare = return_type_idx.index_ - proto.return_type_idx_.index_;
512*795d594fSAndroid Build Coastguard Worker     if (compare == 0) {
513*795d594fSAndroid Build Coastguard Worker       DexFileParameterIterator it(*this, proto);
514*795d594fSAndroid Build Coastguard Worker       size_t i = 0;
515*795d594fSAndroid Build Coastguard Worker       while (it.HasNext() && i < signature_length && compare == 0) {
516*795d594fSAndroid Build Coastguard Worker         compare = signature_type_idxs[i].index_ - it.GetTypeIdx().index_;
517*795d594fSAndroid Build Coastguard Worker         it.Next();
518*795d594fSAndroid Build Coastguard Worker         i++;
519*795d594fSAndroid Build Coastguard Worker       }
520*795d594fSAndroid Build Coastguard Worker       if (compare == 0) {
521*795d594fSAndroid Build Coastguard Worker         if (it.HasNext()) {
522*795d594fSAndroid Build Coastguard Worker           compare = -1;
523*795d594fSAndroid Build Coastguard Worker         } else if (i < signature_length) {
524*795d594fSAndroid Build Coastguard Worker           compare = 1;
525*795d594fSAndroid Build Coastguard Worker         }
526*795d594fSAndroid Build Coastguard Worker       }
527*795d594fSAndroid Build Coastguard Worker     }
528*795d594fSAndroid Build Coastguard Worker     if (compare > 0) {
529*795d594fSAndroid Build Coastguard Worker       lo = mid + 1;
530*795d594fSAndroid Build Coastguard Worker     } else if (compare < 0) {
531*795d594fSAndroid Build Coastguard Worker       hi = mid - 1;
532*795d594fSAndroid Build Coastguard Worker     } else {
533*795d594fSAndroid Build Coastguard Worker       return &proto;
534*795d594fSAndroid Build Coastguard Worker     }
535*795d594fSAndroid Build Coastguard Worker   }
536*795d594fSAndroid Build Coastguard Worker   return nullptr;
537*795d594fSAndroid Build Coastguard Worker }
538*795d594fSAndroid Build Coastguard Worker 
539*795d594fSAndroid Build Coastguard Worker // Given a signature place the type ids into the given vector
CreateTypeList(std::string_view signature,dex::TypeIndex * return_type_idx,std::vector<dex::TypeIndex> * param_type_idxs) const540*795d594fSAndroid Build Coastguard Worker bool DexFile::CreateTypeList(std::string_view signature,
541*795d594fSAndroid Build Coastguard Worker                              dex::TypeIndex* return_type_idx,
542*795d594fSAndroid Build Coastguard Worker                              std::vector<dex::TypeIndex>* param_type_idxs) const {
543*795d594fSAndroid Build Coastguard Worker   if (signature[0] != '(') {
544*795d594fSAndroid Build Coastguard Worker     return false;
545*795d594fSAndroid Build Coastguard Worker   }
546*795d594fSAndroid Build Coastguard Worker   size_t offset = 1;
547*795d594fSAndroid Build Coastguard Worker   size_t end = signature.size();
548*795d594fSAndroid Build Coastguard Worker   bool process_return = false;
549*795d594fSAndroid Build Coastguard Worker   while (offset < end) {
550*795d594fSAndroid Build Coastguard Worker     size_t start_offset = offset;
551*795d594fSAndroid Build Coastguard Worker     char c = signature[offset];
552*795d594fSAndroid Build Coastguard Worker     offset++;
553*795d594fSAndroid Build Coastguard Worker     if (c == ')') {
554*795d594fSAndroid Build Coastguard Worker       process_return = true;
555*795d594fSAndroid Build Coastguard Worker       continue;
556*795d594fSAndroid Build Coastguard Worker     }
557*795d594fSAndroid Build Coastguard Worker     while (c == '[') {  // process array prefix
558*795d594fSAndroid Build Coastguard Worker       if (offset >= end) {  // expect some descriptor following [
559*795d594fSAndroid Build Coastguard Worker         return false;
560*795d594fSAndroid Build Coastguard Worker       }
561*795d594fSAndroid Build Coastguard Worker       c = signature[offset];
562*795d594fSAndroid Build Coastguard Worker       offset++;
563*795d594fSAndroid Build Coastguard Worker     }
564*795d594fSAndroid Build Coastguard Worker     if (c == 'L') {  // process type descriptors
565*795d594fSAndroid Build Coastguard Worker       do {
566*795d594fSAndroid Build Coastguard Worker         if (offset >= end) {  // unexpected early termination of descriptor
567*795d594fSAndroid Build Coastguard Worker           return false;
568*795d594fSAndroid Build Coastguard Worker         }
569*795d594fSAndroid Build Coastguard Worker         c = signature[offset];
570*795d594fSAndroid Build Coastguard Worker         offset++;
571*795d594fSAndroid Build Coastguard Worker       } while (c != ';');
572*795d594fSAndroid Build Coastguard Worker     }
573*795d594fSAndroid Build Coastguard Worker     std::string_view descriptor(signature.data() + start_offset, offset - start_offset);
574*795d594fSAndroid Build Coastguard Worker     const TypeId* type_id = FindTypeId(descriptor);
575*795d594fSAndroid Build Coastguard Worker     if (type_id == nullptr) {
576*795d594fSAndroid Build Coastguard Worker       return false;
577*795d594fSAndroid Build Coastguard Worker     }
578*795d594fSAndroid Build Coastguard Worker     dex::TypeIndex type_idx = GetIndexForTypeId(*type_id);
579*795d594fSAndroid Build Coastguard Worker     if (!process_return) {
580*795d594fSAndroid Build Coastguard Worker       param_type_idxs->push_back(type_idx);
581*795d594fSAndroid Build Coastguard Worker     } else {
582*795d594fSAndroid Build Coastguard Worker       *return_type_idx = type_idx;
583*795d594fSAndroid Build Coastguard Worker       return offset == end;  // return true if the signature had reached a sensible end
584*795d594fSAndroid Build Coastguard Worker     }
585*795d594fSAndroid Build Coastguard Worker   }
586*795d594fSAndroid Build Coastguard Worker   return false;  // failed to correctly parse return type
587*795d594fSAndroid Build Coastguard Worker }
588*795d594fSAndroid Build Coastguard Worker 
FindTryItem(const TryItem * try_items,uint32_t tries_size,uint32_t address)589*795d594fSAndroid Build Coastguard Worker int32_t DexFile::FindTryItem(const TryItem* try_items, uint32_t tries_size, uint32_t address) {
590*795d594fSAndroid Build Coastguard Worker   uint32_t min = 0;
591*795d594fSAndroid Build Coastguard Worker   uint32_t max = tries_size;
592*795d594fSAndroid Build Coastguard Worker   while (min < max) {
593*795d594fSAndroid Build Coastguard Worker     const uint32_t mid = (min + max) / 2;
594*795d594fSAndroid Build Coastguard Worker 
595*795d594fSAndroid Build Coastguard Worker     const TryItem& ti = try_items[mid];
596*795d594fSAndroid Build Coastguard Worker     const uint32_t start = ti.start_addr_;
597*795d594fSAndroid Build Coastguard Worker     const uint32_t end = start + ti.insn_count_;
598*795d594fSAndroid Build Coastguard Worker 
599*795d594fSAndroid Build Coastguard Worker     if (address < start) {
600*795d594fSAndroid Build Coastguard Worker       max = mid;
601*795d594fSAndroid Build Coastguard Worker     } else if (address >= end) {
602*795d594fSAndroid Build Coastguard Worker       min = mid + 1;
603*795d594fSAndroid Build Coastguard Worker     } else {  // We have a winner!
604*795d594fSAndroid Build Coastguard Worker       return mid;
605*795d594fSAndroid Build Coastguard Worker     }
606*795d594fSAndroid Build Coastguard Worker   }
607*795d594fSAndroid Build Coastguard Worker   // No match.
608*795d594fSAndroid Build Coastguard Worker   return -1;
609*795d594fSAndroid Build Coastguard Worker }
610*795d594fSAndroid Build Coastguard Worker 
611*795d594fSAndroid Build Coastguard Worker // Read a signed integer.  "zwidth" is the zero-based byte count.
ReadSignedInt(const uint8_t * ptr,int zwidth)612*795d594fSAndroid Build Coastguard Worker int32_t DexFile::ReadSignedInt(const uint8_t* ptr, int zwidth) {
613*795d594fSAndroid Build Coastguard Worker   int32_t val = 0;
614*795d594fSAndroid Build Coastguard Worker   for (int i = zwidth; i >= 0; --i) {
615*795d594fSAndroid Build Coastguard Worker     val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
616*795d594fSAndroid Build Coastguard Worker   }
617*795d594fSAndroid Build Coastguard Worker   val >>= (3 - zwidth) * 8;
618*795d594fSAndroid Build Coastguard Worker   return val;
619*795d594fSAndroid Build Coastguard Worker }
620*795d594fSAndroid Build Coastguard Worker 
621*795d594fSAndroid Build Coastguard Worker // Read an unsigned integer.  "zwidth" is the zero-based byte count,
622*795d594fSAndroid Build Coastguard Worker // "fill_on_right" indicates which side we want to zero-fill from.
ReadUnsignedInt(const uint8_t * ptr,int zwidth,bool fill_on_right)623*795d594fSAndroid Build Coastguard Worker uint32_t DexFile::ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right) {
624*795d594fSAndroid Build Coastguard Worker   uint32_t val = 0;
625*795d594fSAndroid Build Coastguard Worker   for (int i = zwidth; i >= 0; --i) {
626*795d594fSAndroid Build Coastguard Worker     val = (val >> 8) | (((uint32_t)*ptr++) << 24);
627*795d594fSAndroid Build Coastguard Worker   }
628*795d594fSAndroid Build Coastguard Worker   if (!fill_on_right) {
629*795d594fSAndroid Build Coastguard Worker     val >>= (3 - zwidth) * 8;
630*795d594fSAndroid Build Coastguard Worker   }
631*795d594fSAndroid Build Coastguard Worker   return val;
632*795d594fSAndroid Build Coastguard Worker }
633*795d594fSAndroid Build Coastguard Worker 
634*795d594fSAndroid Build Coastguard Worker // Read a signed long.  "zwidth" is the zero-based byte count.
ReadSignedLong(const uint8_t * ptr,int zwidth)635*795d594fSAndroid Build Coastguard Worker int64_t DexFile::ReadSignedLong(const uint8_t* ptr, int zwidth) {
636*795d594fSAndroid Build Coastguard Worker   int64_t val = 0;
637*795d594fSAndroid Build Coastguard Worker   for (int i = zwidth; i >= 0; --i) {
638*795d594fSAndroid Build Coastguard Worker     val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
639*795d594fSAndroid Build Coastguard Worker   }
640*795d594fSAndroid Build Coastguard Worker   val >>= (7 - zwidth) * 8;
641*795d594fSAndroid Build Coastguard Worker   return val;
642*795d594fSAndroid Build Coastguard Worker }
643*795d594fSAndroid Build Coastguard Worker 
644*795d594fSAndroid Build Coastguard Worker // Read an unsigned long.  "zwidth" is the zero-based byte count,
645*795d594fSAndroid Build Coastguard Worker // "fill_on_right" indicates which side we want to zero-fill from.
ReadUnsignedLong(const uint8_t * ptr,int zwidth,bool fill_on_right)646*795d594fSAndroid Build Coastguard Worker uint64_t DexFile::ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right) {
647*795d594fSAndroid Build Coastguard Worker   uint64_t val = 0;
648*795d594fSAndroid Build Coastguard Worker   for (int i = zwidth; i >= 0; --i) {
649*795d594fSAndroid Build Coastguard Worker     val = (val >> 8) | (((uint64_t)*ptr++) << 56);
650*795d594fSAndroid Build Coastguard Worker   }
651*795d594fSAndroid Build Coastguard Worker   if (!fill_on_right) {
652*795d594fSAndroid Build Coastguard Worker     val >>= (7 - zwidth) * 8;
653*795d594fSAndroid Build Coastguard Worker   }
654*795d594fSAndroid Build Coastguard Worker   return val;
655*795d594fSAndroid Build Coastguard Worker }
656*795d594fSAndroid Build Coastguard Worker 
AppendPrettyMethod(uint32_t method_idx,bool with_signature,std::string * const result) const657*795d594fSAndroid Build Coastguard Worker void DexFile::AppendPrettyMethod(uint32_t method_idx,
658*795d594fSAndroid Build Coastguard Worker                                  bool with_signature,
659*795d594fSAndroid Build Coastguard Worker                                  std::string* const result) const {
660*795d594fSAndroid Build Coastguard Worker   if (method_idx >= NumMethodIds()) {
661*795d594fSAndroid Build Coastguard Worker     android::base::StringAppendF(result, "<<invalid-method-idx-%d>>", method_idx);
662*795d594fSAndroid Build Coastguard Worker     return;
663*795d594fSAndroid Build Coastguard Worker   }
664*795d594fSAndroid Build Coastguard Worker   const MethodId& method_id = GetMethodId(method_idx);
665*795d594fSAndroid Build Coastguard Worker   const ProtoId* proto_id = with_signature ? &GetProtoId(method_id.proto_idx_) : nullptr;
666*795d594fSAndroid Build Coastguard Worker   if (with_signature) {
667*795d594fSAndroid Build Coastguard Worker     AppendPrettyDescriptor(GetTypeDescriptor(proto_id->return_type_idx_), result);
668*795d594fSAndroid Build Coastguard Worker     result->push_back(' ');
669*795d594fSAndroid Build Coastguard Worker   }
670*795d594fSAndroid Build Coastguard Worker   AppendPrettyDescriptor(GetMethodDeclaringClassDescriptor(method_id), result);
671*795d594fSAndroid Build Coastguard Worker   result->push_back('.');
672*795d594fSAndroid Build Coastguard Worker   result->append(GetMethodName(method_id));
673*795d594fSAndroid Build Coastguard Worker   if (with_signature) {
674*795d594fSAndroid Build Coastguard Worker     result->push_back('(');
675*795d594fSAndroid Build Coastguard Worker     const TypeList* params = GetProtoParameters(*proto_id);
676*795d594fSAndroid Build Coastguard Worker     if (params != nullptr) {
677*795d594fSAndroid Build Coastguard Worker       const char* separator = "";
678*795d594fSAndroid Build Coastguard Worker       for (uint32_t i = 0u, size = params->Size(); i != size; ++i) {
679*795d594fSAndroid Build Coastguard Worker         result->append(separator);
680*795d594fSAndroid Build Coastguard Worker         separator = ", ";
681*795d594fSAndroid Build Coastguard Worker         AppendPrettyDescriptor(GetTypeDescriptor(params->GetTypeItem(i).type_idx_), result);
682*795d594fSAndroid Build Coastguard Worker       }
683*795d594fSAndroid Build Coastguard Worker     }
684*795d594fSAndroid Build Coastguard Worker     result->push_back(')');
685*795d594fSAndroid Build Coastguard Worker   }
686*795d594fSAndroid Build Coastguard Worker }
687*795d594fSAndroid Build Coastguard Worker 
PrettyField(uint32_t field_idx,bool with_type) const688*795d594fSAndroid Build Coastguard Worker std::string DexFile::PrettyField(uint32_t field_idx, bool with_type) const {
689*795d594fSAndroid Build Coastguard Worker   if (field_idx >= NumFieldIds()) {
690*795d594fSAndroid Build Coastguard Worker     return StringPrintf("<<invalid-field-idx-%d>>", field_idx);
691*795d594fSAndroid Build Coastguard Worker   }
692*795d594fSAndroid Build Coastguard Worker   const FieldId& field_id = GetFieldId(field_idx);
693*795d594fSAndroid Build Coastguard Worker   std::string result;
694*795d594fSAndroid Build Coastguard Worker   if (with_type) {
695*795d594fSAndroid Build Coastguard Worker     AppendPrettyDescriptor(GetFieldTypeDescriptor(field_id), &result);
696*795d594fSAndroid Build Coastguard Worker     result += ' ';
697*795d594fSAndroid Build Coastguard Worker   }
698*795d594fSAndroid Build Coastguard Worker   AppendPrettyDescriptor(GetFieldDeclaringClassDescriptor(field_id), &result);
699*795d594fSAndroid Build Coastguard Worker   result += '.';
700*795d594fSAndroid Build Coastguard Worker   result += GetFieldName(field_id);
701*795d594fSAndroid Build Coastguard Worker   return result;
702*795d594fSAndroid Build Coastguard Worker }
703*795d594fSAndroid Build Coastguard Worker 
PrettyType(dex::TypeIndex type_idx) const704*795d594fSAndroid Build Coastguard Worker std::string DexFile::PrettyType(dex::TypeIndex type_idx) const {
705*795d594fSAndroid Build Coastguard Worker   if (type_idx.index_ >= NumTypeIds()) {
706*795d594fSAndroid Build Coastguard Worker     return StringPrintf("<<invalid-type-idx-%d>>", type_idx.index_);
707*795d594fSAndroid Build Coastguard Worker   }
708*795d594fSAndroid Build Coastguard Worker   const TypeId& type_id = GetTypeId(type_idx);
709*795d594fSAndroid Build Coastguard Worker   return PrettyDescriptor(GetTypeDescriptor(type_id));
710*795d594fSAndroid Build Coastguard Worker }
711*795d594fSAndroid Build Coastguard Worker 
GetProtoIndexForCallSite(uint32_t call_site_idx) const712*795d594fSAndroid Build Coastguard Worker dex::ProtoIndex DexFile::GetProtoIndexForCallSite(uint32_t call_site_idx) const {
713*795d594fSAndroid Build Coastguard Worker   const CallSiteIdItem& csi = GetCallSiteId(call_site_idx);
714*795d594fSAndroid Build Coastguard Worker   CallSiteArrayValueIterator it(*this, csi);
715*795d594fSAndroid Build Coastguard Worker   it.Next();
716*795d594fSAndroid Build Coastguard Worker   it.Next();
717*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(EncodedArrayValueIterator::ValueType::kMethodType, it.GetValueType());
718*795d594fSAndroid Build Coastguard Worker   return dex::ProtoIndex(it.GetJavaValue().i);
719*795d594fSAndroid Build Coastguard Worker }
720*795d594fSAndroid Build Coastguard Worker 
721*795d594fSAndroid Build Coastguard Worker // Checks that visibility is as expected. Includes special behavior for M and
722*795d594fSAndroid Build Coastguard Worker // before to allow runtime and build visibility when expecting runtime.
operator <<(std::ostream & os,const DexFile & dex_file)723*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const DexFile& dex_file) {
724*795d594fSAndroid Build Coastguard Worker   os << StringPrintf("[DexFile: %s dex-checksum=%08x location-checksum=%08x %p-%p]",
725*795d594fSAndroid Build Coastguard Worker                      dex_file.GetLocation().c_str(),
726*795d594fSAndroid Build Coastguard Worker                      dex_file.GetHeader().checksum_, dex_file.GetLocationChecksum(),
727*795d594fSAndroid Build Coastguard Worker                      dex_file.Begin(), dex_file.Begin() + dex_file.Size());
728*795d594fSAndroid Build Coastguard Worker   return os;
729*795d594fSAndroid Build Coastguard Worker }
730*795d594fSAndroid Build Coastguard Worker 
EncodedArrayValueIterator(const DexFile & dex_file,const uint8_t * array_data)731*795d594fSAndroid Build Coastguard Worker EncodedArrayValueIterator::EncodedArrayValueIterator(const DexFile& dex_file,
732*795d594fSAndroid Build Coastguard Worker                                                      const uint8_t* array_data)
733*795d594fSAndroid Build Coastguard Worker     : dex_file_(dex_file),
734*795d594fSAndroid Build Coastguard Worker       array_size_(),
735*795d594fSAndroid Build Coastguard Worker       pos_(-1),
736*795d594fSAndroid Build Coastguard Worker       ptr_(array_data),
737*795d594fSAndroid Build Coastguard Worker       type_(kByte) {
738*795d594fSAndroid Build Coastguard Worker   array_size_ = (ptr_ != nullptr) ? DecodeUnsignedLeb128(&ptr_) : 0;
739*795d594fSAndroid Build Coastguard Worker   if (array_size_ > 0) {
740*795d594fSAndroid Build Coastguard Worker     bool ok [[maybe_unused]] = MaybeNext();
741*795d594fSAndroid Build Coastguard Worker   }
742*795d594fSAndroid Build Coastguard Worker }
743*795d594fSAndroid Build Coastguard Worker 
MaybeNext()744*795d594fSAndroid Build Coastguard Worker bool EncodedArrayValueIterator::MaybeNext() {
745*795d594fSAndroid Build Coastguard Worker   pos_++;
746*795d594fSAndroid Build Coastguard Worker   if (pos_ >= array_size_) {
747*795d594fSAndroid Build Coastguard Worker     type_ = kEndOfInput;
748*795d594fSAndroid Build Coastguard Worker     return true;
749*795d594fSAndroid Build Coastguard Worker   }
750*795d594fSAndroid Build Coastguard Worker   uint8_t value_type = *ptr_++;
751*795d594fSAndroid Build Coastguard Worker   uint8_t value_arg = value_type >> kEncodedValueArgShift;
752*795d594fSAndroid Build Coastguard Worker   size_t width = value_arg + 1;  // assume and correct later
753*795d594fSAndroid Build Coastguard Worker   type_ = static_cast<ValueType>(value_type & kEncodedValueTypeMask);
754*795d594fSAndroid Build Coastguard Worker   switch (type_) {
755*795d594fSAndroid Build Coastguard Worker   case kBoolean:
756*795d594fSAndroid Build Coastguard Worker     jval_.i = (value_arg != 0) ? 1 : 0;
757*795d594fSAndroid Build Coastguard Worker     width = 0;
758*795d594fSAndroid Build Coastguard Worker     break;
759*795d594fSAndroid Build Coastguard Worker   case kByte:
760*795d594fSAndroid Build Coastguard Worker     jval_.i = DexFile::ReadSignedInt(ptr_, value_arg);
761*795d594fSAndroid Build Coastguard Worker     CHECK(IsInt<8>(jval_.i));
762*795d594fSAndroid Build Coastguard Worker     break;
763*795d594fSAndroid Build Coastguard Worker   case kShort:
764*795d594fSAndroid Build Coastguard Worker     jval_.i = DexFile::ReadSignedInt(ptr_, value_arg);
765*795d594fSAndroid Build Coastguard Worker     CHECK(IsInt<16>(jval_.i));
766*795d594fSAndroid Build Coastguard Worker     break;
767*795d594fSAndroid Build Coastguard Worker   case kChar:
768*795d594fSAndroid Build Coastguard Worker     jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false);
769*795d594fSAndroid Build Coastguard Worker     CHECK(IsUint<16>(jval_.i));
770*795d594fSAndroid Build Coastguard Worker     break;
771*795d594fSAndroid Build Coastguard Worker   case kInt:
772*795d594fSAndroid Build Coastguard Worker     jval_.i = DexFile::ReadSignedInt(ptr_, value_arg);
773*795d594fSAndroid Build Coastguard Worker     break;
774*795d594fSAndroid Build Coastguard Worker   case kLong:
775*795d594fSAndroid Build Coastguard Worker     jval_.j = DexFile::ReadSignedLong(ptr_, value_arg);
776*795d594fSAndroid Build Coastguard Worker     break;
777*795d594fSAndroid Build Coastguard Worker   case kFloat:
778*795d594fSAndroid Build Coastguard Worker     jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, true);
779*795d594fSAndroid Build Coastguard Worker     break;
780*795d594fSAndroid Build Coastguard Worker   case kDouble:
781*795d594fSAndroid Build Coastguard Worker     jval_.j = DexFile::ReadUnsignedLong(ptr_, value_arg, true);
782*795d594fSAndroid Build Coastguard Worker     break;
783*795d594fSAndroid Build Coastguard Worker   case kString:
784*795d594fSAndroid Build Coastguard Worker   case kType:
785*795d594fSAndroid Build Coastguard Worker   case kMethodType:
786*795d594fSAndroid Build Coastguard Worker   case kMethodHandle:
787*795d594fSAndroid Build Coastguard Worker     jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false);
788*795d594fSAndroid Build Coastguard Worker     break;
789*795d594fSAndroid Build Coastguard Worker   case kField:
790*795d594fSAndroid Build Coastguard Worker   case kMethod:
791*795d594fSAndroid Build Coastguard Worker   case kEnum:
792*795d594fSAndroid Build Coastguard Worker   case kArray:
793*795d594fSAndroid Build Coastguard Worker   case kAnnotation:
794*795d594fSAndroid Build Coastguard Worker     return false;
795*795d594fSAndroid Build Coastguard Worker   case kNull:
796*795d594fSAndroid Build Coastguard Worker     jval_.l = nullptr;
797*795d594fSAndroid Build Coastguard Worker     width = 0;
798*795d594fSAndroid Build Coastguard Worker     break;
799*795d594fSAndroid Build Coastguard Worker   default:
800*795d594fSAndroid Build Coastguard Worker     return false;
801*795d594fSAndroid Build Coastguard Worker   }
802*795d594fSAndroid Build Coastguard Worker   ptr_ += width;
803*795d594fSAndroid Build Coastguard Worker   return true;
804*795d594fSAndroid Build Coastguard Worker }
805*795d594fSAndroid Build Coastguard Worker 
806*795d594fSAndroid Build Coastguard Worker namespace dex {
807*795d594fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,const ProtoIndex & index)808*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const ProtoIndex& index) {
809*795d594fSAndroid Build Coastguard Worker   os << "ProtoIndex[" << index.index_ << "]";
810*795d594fSAndroid Build Coastguard Worker   return os;
811*795d594fSAndroid Build Coastguard Worker }
812*795d594fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,const StringIndex & index)813*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const StringIndex& index) {
814*795d594fSAndroid Build Coastguard Worker   os << "StringIndex[" << index.index_ << "]";
815*795d594fSAndroid Build Coastguard Worker   return os;
816*795d594fSAndroid Build Coastguard Worker }
817*795d594fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,const TypeIndex & index)818*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const TypeIndex& index) {
819*795d594fSAndroid Build Coastguard Worker   os << "TypeIndex[" << index.index_ << "]";
820*795d594fSAndroid Build Coastguard Worker   return os;
821*795d594fSAndroid Build Coastguard Worker }
822*795d594fSAndroid Build Coastguard Worker 
823*795d594fSAndroid Build Coastguard Worker }  // namespace dex
824*795d594fSAndroid Build Coastguard Worker 
825*795d594fSAndroid Build Coastguard Worker }  // namespace art
826