1 /*
2  * Copyright (C) 2017 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 #include "verification.h"
18 
19 #include <iomanip>
20 #include <sstream>
21 
22 #include "art_field-inl.h"
23 #include "mirror/class-inl.h"
24 
25 namespace art {
26 namespace gc {
27 
DumpObjectInfo(const void * addr,const char * tag) const28 std::string Verification::DumpObjectInfo(const void* addr, const char* tag) const {
29   std::ostringstream oss;
30   oss << tag << "=" << addr;
31   if (IsValidHeapObjectAddress(addr)) {
32     mirror::Object* obj = reinterpret_cast<mirror::Object*>(const_cast<void*>(addr));
33     mirror::Class* klass = obj->GetClass<kVerifyNone, kWithoutReadBarrier>();
34     oss << " klass=" << klass;
35     if (IsValidClass(klass)) {
36       oss << "(" << klass->PrettyClass() << ")";
37       if (klass->IsArrayClass<kVerifyNone, kWithoutReadBarrier>()) {
38         oss << " length=" << obj->AsArray<kVerifyNone, kWithoutReadBarrier>()->GetLength();
39       }
40     } else {
41       oss << " <invalid address>";
42     }
43     space::Space* const space = heap_->FindSpaceFromAddress(addr);
44     if (space != nullptr) {
45       oss << " space=" << *space;
46     }
47     accounting::CardTable* card_table = heap_->GetCardTable();
48     if (card_table->AddrIsInCardTable(addr)) {
49       oss << " card=" << static_cast<size_t>(
50           card_table->GetCard(reinterpret_cast<const mirror::Object*>(addr)));
51     }
52     // Dump adjacent RAM.
53     const uintptr_t uint_addr = reinterpret_cast<uintptr_t>(addr);
54     static constexpr size_t kBytesBeforeAfter = 2 * kObjectAlignment;
55     const uintptr_t dump_start = uint_addr - kBytesBeforeAfter;
56     const uintptr_t dump_end = uint_addr + kBytesBeforeAfter;
57     if (dump_start < dump_end &&
58         IsValidHeapObjectAddress(reinterpret_cast<const void*>(dump_start)) &&
59         IsValidHeapObjectAddress(reinterpret_cast<const void*>(dump_end - kObjectAlignment))) {
60       oss << " adjacent_ram=";
61       for (uintptr_t p = dump_start; p < dump_end; ++p) {
62         if (p == uint_addr) {
63           // Marker of where the object is.
64           oss << "|";
65         }
66         uint8_t* ptr = reinterpret_cast<uint8_t*>(p);
67         oss << std::hex << std::setfill('0') << std::setw(2) << static_cast<uintptr_t>(*ptr);
68       }
69     }
70   } else {
71     oss << " <invalid address>";
72   }
73   return oss.str();
74 }
75 
LogHeapCorruption(ObjPtr<mirror::Object> holder,MemberOffset offset,mirror::Object * ref,bool fatal) const76 void Verification::LogHeapCorruption(ObjPtr<mirror::Object> holder,
77                                      MemberOffset offset,
78                                      mirror::Object* ref,
79                                      bool fatal) const {
80   // Lowest priority logging first:
81   PrintFileToLog("/proc/self/maps", LogSeverity::FATAL_WITHOUT_ABORT);
82   MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), true);
83   // Buffer the output in the string stream since it is more important than the stack traces
84   // and we want it to have log priority. The stack traces are printed from Runtime::Abort
85   // which is called from LOG(FATAL) but before the abort message.
86   std::ostringstream oss;
87   oss << "GC tried to mark invalid reference " << ref << std::endl;
88   oss << DumpObjectInfo(ref, "ref") << "\n";
89   oss << DumpObjectInfo(holder.Ptr(), "holder");
90   if (holder != nullptr) {
91     mirror::Class* holder_klass = holder->GetClass<kVerifyNone, kWithoutReadBarrier>();
92     if (IsValidClass(holder_klass)) {
93       oss << "field_offset=" << offset.Uint32Value();
94       ArtField* field = holder->FindFieldByOffset(offset);
95       if (field != nullptr) {
96         oss << " name=" << field->GetName();
97       }
98     }
99   }
100 
101   if (fatal) {
102     LOG(FATAL) << oss.str();
103   } else {
104     LOG(FATAL_WITHOUT_ABORT) << oss.str();
105   }
106 }
107 
IsValidHeapObjectAddress(const void * addr,space::Space ** out_space) const108 bool Verification::IsValidHeapObjectAddress(const void* addr, space::Space** out_space) const {
109   if (!IsAligned<kObjectAlignment>(addr)) {
110     return false;
111   }
112   space::Space* const space = heap_->FindSpaceFromAddress(addr);
113   if (space != nullptr) {
114     if (out_space != nullptr) {
115       *out_space = space;
116     }
117     return true;
118   }
119   return false;
120 }
121 
IsValidClass(const void * addr) const122 bool Verification::IsValidClass(const void* addr) const {
123   if (!IsValidHeapObjectAddress(addr)) {
124     return false;
125   }
126   mirror::Class* klass = reinterpret_cast<mirror::Class*>(const_cast<void*>(addr));
127   mirror::Class* k1 = klass->GetClass<kVerifyNone, kWithoutReadBarrier>();
128   if (!IsValidHeapObjectAddress(k1)) {
129     return false;
130   }
131   // k should be class class, take the class again to verify.
132   // Note that this check may not be valid for the no image space since the class class might move
133   // around from moving GC.
134   mirror::Class* k2 = k1->GetClass<kVerifyNone, kWithoutReadBarrier>();
135   if (!IsValidHeapObjectAddress(k2)) {
136     return false;
137   }
138   return k1 == k2;
139 }
140 
141 }  // namespace gc
142 }  // namespace art
143