Home | History | Annotate | Download | only in runtime
      1 /*
      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 
     34 namespace art {
     35 
     36 std::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       gc::space::ImageSpace* ispace = cs->AsImageSpace();
     44       oss << "image;" << ispace->GetName() << ";"
     45           // If the file name is the same as the name, output "+" instead to shorten the output.
     46           << (ispace->GetImageFilename() == cs->GetName() ? "+" : ispace->GetImageFilename())
     47           << ";" << static_cast<const void*>(ispace->Begin());
     48     } else {
     49       oss << "continuous;" << cs->GetName();
     50     }
     51   } else {
     52     gc::space::DiscontinuousSpace* ds =
     53         heap->FindDiscontinuousSpaceFromObject(klass, /* fail_ok */ true);
     54     if (ds != nullptr) {
     55       oss << "discontinuous;" << ds->GetName();
     56     } else {
     57       oss << "invalid";
     58     }
     59   }
     60   return oss.str();
     61 }
     62 
     63 std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* class_descriptor) {
     64   std::ostringstream oss;
     65   uint32_t hash = ComputeModifiedUtf8Hash(class_descriptor);
     66   ObjPtr<mirror::Class> path_class_loader =
     67       WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_PathClassLoader);
     68   ObjPtr<mirror::Class> dex_class_loader =
     69       WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_DexClassLoader);
     70   ObjPtr<mirror::Class> delegate_last_class_loader =
     71       WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_DelegateLastClassLoader);
     72 
     73   // Print the class loader chain.
     74   bool found_class = false;
     75   const char* loader_separator = "";
     76   if (loader == nullptr) {
     77     oss << "BootClassLoader";  // This would be unexpected.
     78   }
     79   for (; loader != nullptr; loader = loader->GetParent()) {
     80     ClassTable* table = Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(loader);
     81     oss << loader_separator << loader->GetClass()->PrettyDescriptor()
     82         << "/" << static_cast<const void*>(table);
     83     loader_separator = ";";
     84     // If we didn't find the class yet, try to find it in the current class loader.
     85     if (!found_class) {
     86       ObjPtr<mirror::Class> klass =
     87           (table != nullptr) ? table->Lookup(class_descriptor, hash) : nullptr;
     88       if (klass != nullptr) {
     89         found_class = true;
     90         oss << "[hit:" << DescribeSpace(klass) << "]";
     91       }
     92     }
     93 
     94     // For PathClassLoader, DexClassLoader or DelegateLastClassLoader
     95     // also dump the dex file locations.
     96     if (loader->GetClass() == path_class_loader ||
     97         loader->GetClass() == dex_class_loader ||
     98         loader->GetClass() == delegate_last_class_loader) {
     99       oss << "(";
    100       ScopedObjectAccessUnchecked soa(Thread::Current());
    101       StackHandleScope<1> hs(soa.Self());
    102       Handle<mirror::ClassLoader> handle(hs.NewHandle(loader));
    103       const char* path_separator = "";
    104       const DexFile* base_dex_file = nullptr;
    105       VisitClassLoaderDexFiles(
    106           soa,
    107           handle,
    108           [&](const DexFile* dex_file) {
    109               oss << path_separator;
    110               path_separator = ":";
    111               if (base_dex_file != nullptr &&
    112                   dex_file->GetLocation().length() > base_dex_file->GetLocation().length() &&
    113                   dex_file->GetLocation().compare(0u,
    114                                                   base_dex_file->GetLocation().length(),
    115                                                   base_dex_file->GetLocation()) == 0) {
    116                 // Replace the base location with "+" to shorten the output.
    117                 oss << "+" << dex_file->GetLocation().substr(base_dex_file->GetLocation().length());
    118               } else {
    119                 oss << dex_file->GetLocation();
    120                 base_dex_file = dex_file;
    121               }
    122               oss << "/" << static_cast<const void*>(dex_file);
    123               return true;  // Continue with the next DexFile.
    124           });
    125       oss << ")";
    126     }
    127   }
    128 
    129   return oss.str();
    130 }
    131 
    132 void DumpB77342775DebugData(ObjPtr<mirror::Class> target_class, ObjPtr<mirror::Class> src_class) {
    133   std::string target_descriptor_storage;
    134   const char* target_descriptor = target_class->GetDescriptor(&target_descriptor_storage);
    135   const char kCheckedPrefix[] = "Lorg/apache/http/";
    136   // Avoid spam for other packages. (That spam would break some ART run-tests for example.)
    137   if (strncmp(target_descriptor, kCheckedPrefix, sizeof(kCheckedPrefix) - 1) != 0) {
    138     return;
    139   }
    140   auto matcher = [target_descriptor, target_class](ObjPtr<mirror::Class> klass)
    141       REQUIRES_SHARED(Locks::mutator_lock_) {
    142     if (klass->DescriptorEquals(target_descriptor)) {
    143       LOG(ERROR) << "    descriptor match in "
    144           << DescribeLoaders(klass->GetClassLoader(), target_descriptor)
    145           << " match? " << std::boolalpha << (klass == target_class);
    146     }
    147   };
    148 
    149   std::string source_descriptor_storage;
    150   const char* source_descriptor = src_class->GetDescriptor(&source_descriptor_storage);
    151 
    152   LOG(ERROR) << "Maybe bug 77342775, looking for " << target_descriptor
    153       << " " << target_class.Ptr() << "[" << DescribeSpace(target_class) << "]"
    154       << " defined in " << target_class->GetDexFile().GetLocation()
    155       << "/" << static_cast<const void*>(&target_class->GetDexFile())
    156       << "\n  with loader: " << DescribeLoaders(target_class->GetClassLoader(), target_descriptor);
    157   if (target_class->IsInterface()) {
    158     ObjPtr<mirror::IfTable> iftable = src_class->GetIfTable();
    159     CHECK(iftable != nullptr);
    160     size_t ifcount = iftable->Count();
    161     LOG(ERROR) << "  in interface table for " << source_descriptor
    162         << " " << src_class.Ptr() << "[" << DescribeSpace(src_class) << "]"
    163         << " defined in " << src_class->GetDexFile().GetLocation()
    164         << "/" << static_cast<const void*>(&src_class->GetDexFile())
    165         << " ifcount=" << ifcount
    166         << "\n  with loader " << DescribeLoaders(src_class->GetClassLoader(), source_descriptor);
    167     for (size_t i = 0; i != ifcount; ++i) {
    168       ObjPtr<mirror::Class> iface = iftable->GetInterface(i);
    169       CHECK(iface != nullptr);
    170       LOG(ERROR) << "  iface #" << i << ": " << iface->PrettyDescriptor();
    171       matcher(iface);
    172     }
    173   } else {
    174     LOG(ERROR) << "  in superclass chain for " << source_descriptor
    175         << " " << src_class.Ptr() << "[" << DescribeSpace(src_class) << "]"
    176         << " defined in " << src_class->GetDexFile().GetLocation()
    177         << "/" << static_cast<const void*>(&src_class->GetDexFile())
    178         << "\n  with loader " << DescribeLoaders(src_class->GetClassLoader(), source_descriptor);
    179     for (ObjPtr<mirror::Class> klass = src_class;
    180          klass != nullptr;
    181          klass = klass->GetSuperClass()) {
    182       LOG(ERROR) << "  - " << klass->PrettyDescriptor();
    183       matcher(klass);
    184     }
    185   }
    186 }
    187 
    188 }  // namespace art
    189