blob: 7e075ce3527935bda27909d6e1454fa7b8c72c16 [file] [log] [blame]
Vladimir Marko606adb32018-04-05 14:49:24 +01001/*
2 * Copyright (C) 2018 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 <sstream>
18
19#include "debug_print.h"
20
21#include "class_linker.h"
22#include "class_table.h"
23#include "class_loader_utils.h"
24#include "dex/utf.h"
25#include "gc/heap.h"
26#include "gc/space/space-inl.h"
27#include "mirror/class.h"
28#include "mirror/class_loader.h"
29#include "runtime.h"
30#include "scoped_thread_state_change-inl.h"
31#include "thread-current-inl.h"
32#include "well_known_classes.h"
33
34namespace art {
35
36std::string DescribeSpace(ObjPtr<mirror::Class> klass) {
37 std::ostringstream oss;
38 gc::Heap* heap = Runtime::Current()->GetHeap();
39 gc::space::ContinuousSpace* cs =
40 heap->FindContinuousSpaceFromObject(klass.Ptr(), /* fail_ok */ true);
41 if (cs != nullptr) {
42 if (cs->IsImageSpace()) {
43 oss << "image;" << cs->GetName() << ";" << cs->AsImageSpace()->GetImageFilename();
44 } else {
45 oss << "continuous;" << cs->GetName();
46 }
47 } else {
48 gc::space::DiscontinuousSpace* ds =
49 heap->FindDiscontinuousSpaceFromObject(klass, /* fail_ok */ true);
50 if (ds != nullptr) {
51 oss << "discontinuous;" << ds->GetName();
52 } else {
53 oss << "invalid";
54 }
55 }
56 return oss.str();
57}
58
59std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* class_descriptor) {
60 std::ostringstream oss;
61 uint32_t hash = ComputeModifiedUtf8Hash(class_descriptor);
62 ObjPtr<mirror::Class> path_class_loader =
63 WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_PathClassLoader);
64 ObjPtr<mirror::Class> dex_class_loader =
65 WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_DexClassLoader);
66 ObjPtr<mirror::Class> delegate_last_class_loader =
67 WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_DelegateLastClassLoader);
68
69 // Print the class loader chain.
70 bool found_class = false;
71 const char* loader_separator = "";
72 if (loader == nullptr) {
73 oss << "BootClassLoader"; // This would be unexpected.
74 }
75 for (; loader != nullptr; loader = loader->GetParent()) {
Vladimir Marko957e7082018-04-11 17:25:42 +010076 ClassTable* table = Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(loader);
77 oss << loader_separator << loader->GetClass()->PrettyDescriptor()
78 << "/" << static_cast<const void*>(table);
Vladimir Marko606adb32018-04-05 14:49:24 +010079 loader_separator = ";";
80 // If we didn't find the class yet, try to find it in the current class loader.
81 if (!found_class) {
Vladimir Marko606adb32018-04-05 14:49:24 +010082 ObjPtr<mirror::Class> klass =
83 (table != nullptr) ? table->Lookup(class_descriptor, hash) : nullptr;
84 if (klass != nullptr) {
85 found_class = true;
86 oss << "[hit:" << DescribeSpace(klass) << "]";
87 }
88 }
89
90 // For PathClassLoader, DexClassLoader or DelegateLastClassLoader
91 // also dump the dex file locations.
92 if (loader->GetClass() == path_class_loader ||
93 loader->GetClass() == dex_class_loader ||
94 loader->GetClass() == delegate_last_class_loader) {
95 oss << "(";
96 ScopedObjectAccessUnchecked soa(Thread::Current());
97 StackHandleScope<1> hs(soa.Self());
98 Handle<mirror::ClassLoader> handle(hs.NewHandle(loader));
99 const char* path_separator = "";
Vladimir Marko811da572018-04-16 15:14:08 +0100100 const DexFile* base_dex_file = nullptr;
101 VisitClassLoaderDexFiles(
102 soa,
103 handle,
104 [&](const DexFile* dex_file) {
105 oss << path_separator;
106 path_separator = ":";
107 if (base_dex_file != nullptr &&
108 dex_file->GetLocation().length() > base_dex_file->GetLocation().length() &&
109 dex_file->GetLocation().compare(0u,
110 base_dex_file->GetLocation().length(),
111 base_dex_file->GetLocation()) == 0) {
112 // Replace the base location with "+" to shorten the output.
113 oss << "+" << dex_file->GetLocation().substr(base_dex_file->GetLocation().length());
114 } else {
115 oss << dex_file->GetLocation();
116 base_dex_file = dex_file;
117 }
118 oss << "/" << static_cast<const void*>(dex_file);
119 return true; // Continue with the next DexFile.
120 });
Vladimir Marko606adb32018-04-05 14:49:24 +0100121 oss << ")";
122 }
123 }
124
125 return oss.str();
126}
127
Vladimir Markof5c537e2018-04-09 18:33:55 +0100128void DumpB77342775DebugData(ObjPtr<mirror::Class> target_class, ObjPtr<mirror::Class> src_class) {
129 std::string target_descriptor_storage;
130 const char* target_descriptor = target_class->GetDescriptor(&target_descriptor_storage);
131 const char kCheckedPrefix[] = "Lorg/apache/http/";
132 // Avoid spam for other packages. (That spam would break some ART run-tests for example.)
133 if (strncmp(target_descriptor, kCheckedPrefix, sizeof(kCheckedPrefix) - 1) != 0) {
134 return;
135 }
136 auto matcher = [target_descriptor, target_class](ObjPtr<mirror::Class> klass)
137 REQUIRES_SHARED(Locks::mutator_lock_) {
138 if (klass->DescriptorEquals(target_descriptor)) {
139 LOG(ERROR) << " descriptor match in "
140 << DescribeLoaders(klass->GetClassLoader(), target_descriptor)
141 << " match? " << std::boolalpha << (klass == target_class);
142 }
143 };
144
145 std::string source_descriptor_storage;
146 const char* source_descriptor = src_class->GetDescriptor(&source_descriptor_storage);
147
Vladimir Marko811da572018-04-16 15:14:08 +0100148 LOG(ERROR) << "Maybe bug 77342775, looking for " << target_descriptor
149 << " with loader " << DescribeLoaders(target_class->GetClassLoader(), target_descriptor);
Vladimir Markof5c537e2018-04-09 18:33:55 +0100150 if (target_class->IsInterface()) {
151 ObjPtr<mirror::IfTable> iftable = src_class->GetIfTable();
152 CHECK(iftable != nullptr);
153 size_t ifcount = iftable->Count();
Vladimir Marko811da572018-04-16 15:14:08 +0100154 LOG(ERROR) << " in interface table for " << source_descriptor << " ifcount=" << ifcount
Vladimir Marko957e7082018-04-11 17:25:42 +0100155 << " with loader " << DescribeLoaders(src_class->GetClassLoader(), source_descriptor);
Vladimir Markof5c537e2018-04-09 18:33:55 +0100156 for (size_t i = 0; i != ifcount; ++i) {
157 ObjPtr<mirror::Class> iface = iftable->GetInterface(i);
158 CHECK(iface != nullptr);
159 LOG(ERROR) << " iface #" << i << ": " << iface->PrettyDescriptor();
160 matcher(iface);
161 }
162 } else {
Vladimir Marko811da572018-04-16 15:14:08 +0100163 LOG(ERROR) << " in superclass chain for " << source_descriptor
Vladimir Marko957e7082018-04-11 17:25:42 +0100164 << " with loader " << DescribeLoaders(src_class->GetClassLoader(), source_descriptor);
Vladimir Markof5c537e2018-04-09 18:33:55 +0100165 for (ObjPtr<mirror::Class> klass = src_class;
166 klass != nullptr;
167 klass = klass->GetSuperClass()) {
168 LOG(ERROR) << " - " << klass->PrettyDescriptor();
169 matcher(klass);
170 }
171 }
172}
173
Vladimir Marko606adb32018-04-05 14:49:24 +0100174} // namespace art