diff options
author | 2018-04-05 14:49:24 +0100 | |
---|---|---|
committer | 2018-04-05 16:34:11 +0100 | |
commit | 606adb3a515b31e6d4b02becb36f732918fe7713 (patch) | |
tree | eea60acb136237fdff195ab264b5513dae3b0ce7 | |
parent | 30a2d9c61da75359dee4ce90236d19fc6341b07a (diff) |
Fix and extend debugging output for bug 74410240.
Test: Manually break in the resolution trampoline and
force printing the message.
Bug: 74410240
Change-Id: I5f3fea53a7ec2170b644fb13bca84bae099243c8
-rw-r--r-- | runtime/Android.bp | 1 | ||||
-rw-r--r-- | runtime/class_linker.cc | 78 | ||||
-rw-r--r-- | runtime/debug_print.cc | 113 | ||||
-rw-r--r-- | runtime/debug_print.h | 34 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 22 |
5 files changed, 169 insertions, 79 deletions
diff --git a/runtime/Android.bp b/runtime/Android.bp index c0f1c366b8..08025824c3 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -46,6 +46,7 @@ cc_defaults { "class_table.cc", "common_throws.cc", "compiler_filter.cc", + "debug_print.cc", "debugger.cc", "dex/art_dex_file_loader.cc", "dex/dex_file_annotations.cc", diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 3025818ab7..b5af08f2e8 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -53,6 +53,7 @@ #include "class_loader_utils.h" #include "class_table-inl.h" #include "compiler_callbacks.h" +#include "debug_print.h" #include "debugger.h" #include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" @@ -7844,83 +7845,6 @@ ObjPtr<mirror::Class> ClassLinker::DoResolveType(dex::TypeIndex type_idx, return resolved; } -std::string DescribeSpace(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) { - std::ostringstream oss; - gc::Heap* heap = Runtime::Current()->GetHeap(); - gc::space::ContinuousSpace* cs = heap->FindContinuousSpaceFromAddress(klass.Ptr()); - if (cs != nullptr) { - if (cs->IsImageSpace()) { - oss << "image;" << cs->GetName() << ";" << cs->AsImageSpace()->GetImageFilename(); - } else { - oss << "continuous;" << cs->GetName(); - } - } else { - gc::space::DiscontinuousSpace* ds = - heap->FindDiscontinuousSpaceFromObject(klass, /* fail_ok */ true); - if (ds != nullptr) { - oss << "discontinuous;" << ds->GetName(); - } else { - oss << "invalid"; - } - } - return oss.str(); -} - -std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* class_descriptor) - REQUIRES_SHARED(Locks::mutator_lock_) { - std::ostringstream oss; - uint32_t hash = ComputeModifiedUtf8Hash(class_descriptor); - ObjPtr<mirror::Class> path_class_loader = - WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_PathClassLoader); - ObjPtr<mirror::Class> dex_class_loader = - WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_DexClassLoader); - ObjPtr<mirror::Class> delegate_last_class_loader = - WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_DelegateLastClassLoader); - - // Print the class loader chain. - bool found_class = false; - const char* loader_separator = ""; - if (loader == nullptr) { - oss << "BootClassLoader"; // This would be unexpected. - } - for (; loader != nullptr; loader = loader->GetParent()) { - oss << loader_separator << loader->GetClass()->PrettyDescriptor(); - loader_separator = ";"; - // If we didn't find the interface yet, try to find it in the current class loader. - if (!found_class) { - ClassTable* table = Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(loader); - ObjPtr<mirror::Class> klass = - (table != nullptr) ? table->Lookup(class_descriptor, hash) : nullptr; - if (klass != nullptr) { - found_class = true; - oss << "[hit:" << DescribeSpace(klass) << "]"; - } - } - - // For PathClassLoader, DexClassLoader or DelegateLastClassLoader - // also dump the dex file locations. - if (loader->GetClass() == path_class_loader || - loader->GetClass() == dex_class_loader || - loader->GetClass() == delegate_last_class_loader) { - oss << "("; - ScopedObjectAccessUnchecked soa(Thread::Current()); - StackHandleScope<1> hs(soa.Self()); - Handle<mirror::ClassLoader> handle(hs.NewHandle(loader)); - const char* path_separator = ""; - VisitClassLoaderDexFiles(soa, - handle, - [&](const DexFile* dex_file) { - oss << path_separator << dex_file->GetLocation(); - path_separator = ":"; - return true; // Continue with the next DexFile. - }); - oss << ")"; - } - } - - return oss.str(); -} - ArtMethod* ClassLinker::FindResolvedMethod(ObjPtr<mirror::Class> klass, ObjPtr<mirror::DexCache> dex_cache, ObjPtr<mirror::ClassLoader> class_loader, diff --git a/runtime/debug_print.cc b/runtime/debug_print.cc new file mode 100644 index 0000000000..44a183669d --- /dev/null +++ b/runtime/debug_print.cc @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <sstream> + +#include "debug_print.h" + +#include "class_linker.h" +#include "class_table.h" +#include "class_loader_utils.h" +#include "dex/utf.h" +#include "gc/heap.h" +#include "gc/space/space-inl.h" +#include "mirror/class.h" +#include "mirror/class_loader.h" +#include "runtime.h" +#include "scoped_thread_state_change-inl.h" +#include "thread-current-inl.h" +#include "well_known_classes.h" + +namespace art { + +std::string DescribeSpace(ObjPtr<mirror::Class> klass) { + std::ostringstream oss; + gc::Heap* heap = Runtime::Current()->GetHeap(); + gc::space::ContinuousSpace* cs = + heap->FindContinuousSpaceFromObject(klass.Ptr(), /* fail_ok */ true); + if (cs != nullptr) { + if (cs->IsImageSpace()) { + oss << "image;" << cs->GetName() << ";" << cs->AsImageSpace()->GetImageFilename(); + } else { + oss << "continuous;" << cs->GetName(); + } + } else { + gc::space::DiscontinuousSpace* ds = + heap->FindDiscontinuousSpaceFromObject(klass, /* fail_ok */ true); + if (ds != nullptr) { + oss << "discontinuous;" << ds->GetName(); + } else { + oss << "invalid"; + } + } + return oss.str(); +} + +std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* class_descriptor) { + std::ostringstream oss; + uint32_t hash = ComputeModifiedUtf8Hash(class_descriptor); + ObjPtr<mirror::Class> path_class_loader = + WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_PathClassLoader); + ObjPtr<mirror::Class> dex_class_loader = + WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_DexClassLoader); + ObjPtr<mirror::Class> delegate_last_class_loader = + WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_DelegateLastClassLoader); + + // Print the class loader chain. + bool found_class = false; + const char* loader_separator = ""; + if (loader == nullptr) { + oss << "BootClassLoader"; // This would be unexpected. + } + for (; loader != nullptr; loader = loader->GetParent()) { + oss << loader_separator << loader->GetClass()->PrettyDescriptor(); + loader_separator = ";"; + // If we didn't find the class yet, try to find it in the current class loader. + if (!found_class) { + ClassTable* table = Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(loader); + ObjPtr<mirror::Class> klass = + (table != nullptr) ? table->Lookup(class_descriptor, hash) : nullptr; + if (klass != nullptr) { + found_class = true; + oss << "[hit:" << DescribeSpace(klass) << "]"; + } + } + + // For PathClassLoader, DexClassLoader or DelegateLastClassLoader + // also dump the dex file locations. + if (loader->GetClass() == path_class_loader || + loader->GetClass() == dex_class_loader || + loader->GetClass() == delegate_last_class_loader) { + oss << "("; + ScopedObjectAccessUnchecked soa(Thread::Current()); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::ClassLoader> handle(hs.NewHandle(loader)); + const char* path_separator = ""; + VisitClassLoaderDexFiles(soa, + handle, + [&](const DexFile* dex_file) { + oss << path_separator << dex_file->GetLocation(); + path_separator = ":"; + return true; // Continue with the next DexFile. + }); + oss << ")"; + } + } + + return oss.str(); +} + +} // namespace art diff --git a/runtime/debug_print.h b/runtime/debug_print.h new file mode 100644 index 0000000000..479c36a02f --- /dev/null +++ b/runtime/debug_print.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_DEBUG_PRINT_H_ +#define ART_RUNTIME_DEBUG_PRINT_H_ + +#include "base/mutex.h" +#include "mirror/object.h" + +// Helper functions for printing extra information for certain hard to diagnose bugs. + +namespace art { + +std::string DescribeSpace(ObjPtr<mirror::Class> klass) + REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; +std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* class_descriptor) + REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; + +} // namespace art + +#endif // ART_RUNTIME_DEBUG_PRINT_H_ diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 2284100564..39429c5b41 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -19,6 +19,7 @@ #include "base/enums.h" #include "callee_save_frame.h" #include "common_throws.h" +#include "debug_print.h" #include "debugger.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_types.h" @@ -1187,9 +1188,24 @@ static std::string DumpInstruction(ArtMethod* method, uint32_t dex_pc) } } +static void DumpB74410240ClassData(ObjPtr<mirror::Class> klass) + REQUIRES_SHARED(Locks::mutator_lock_) { + std::string storage; + const char* descriptor = klass->GetDescriptor(&storage); + LOG(FATAL_WITHOUT_ABORT) << " " << DescribeLoaders(klass->GetClassLoader(), descriptor); + const OatDexFile* oat_dex_file = klass->GetDexFile().GetOatDexFile(); + if (oat_dex_file != nullptr) { + const OatFile* oat_file = oat_dex_file->GetOatFile(); + const char* dex2oat_cmdline = + oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kDex2OatCmdLineKey); + LOG(FATAL_WITHOUT_ABORT) << " OatFile: " << oat_file->GetLocation() + << "; " << (dex2oat_cmdline != nullptr ? dex2oat_cmdline : "<not recorded>"); + } +} + static void DumpB74410240DebugData(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) { // Mimick the search for the caller and dump some data while doing so. - LOG(FATAL_WITHOUT_ABORT) << "Dumping debugging data for b/74410240."; + LOG(FATAL_WITHOUT_ABORT) << "Dumping debugging data, please attach a bugreport to b/74410240."; constexpr CalleeSaveType type = CalleeSaveType::kSaveRefsAndArgs; CHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(type)); @@ -1227,6 +1243,7 @@ static void DumpB74410240DebugData(ArtMethod** sp) REQUIRES_SHARED(Locks::mutato << " dex pc: " << dex_pc << " dex file: " << outer_method->GetDexFile()->GetLocation() << " class table: " << class_linker->ClassTableForClassLoader(outer_method->GetClassLoader()); + DumpB74410240ClassData(outer_method->GetDeclaringClass()); LOG(FATAL_WITHOUT_ABORT) << " instruction: " << DumpInstruction(outer_method, dex_pc); ArtMethod* caller = outer_method; @@ -1260,7 +1277,8 @@ static void DumpB74410240DebugData(ArtMethod** sp) REQUIRES_SHARED(Locks::mutato << " dex pc: " << dex_pc << " dex file: " << caller->GetDexFile()->GetLocation() << " class table: " - << class_linker->ClassTableForClassLoader(outer_method->GetClassLoader()); + << class_linker->ClassTableForClassLoader(caller->GetClassLoader()); + DumpB74410240ClassData(caller->GetDeclaringClass()); LOG(FATAL_WITHOUT_ABORT) << " instruction: " << DumpInstruction(caller, dex_pc); } } |