Get jar / apk / dexfile location for classes.
We need this information for deobfuscation.
Change-Id: Ie44c79437644641a8a72b876fa83a3f498602dbe
diff --git a/perfetto_hprof/Android.bp b/perfetto_hprof/Android.bp
index 7627bcd..45acdfb 100644
--- a/perfetto_hprof/Android.bp
+++ b/perfetto_hprof/Android.bp
@@ -47,6 +47,7 @@
shared_libs: [
"libbase",
"liblog",
+ "libdexfile",
],
static_libs: [
"libperfetto_client_experimental",
diff --git a/perfetto_hprof/perfetto_hprof.cc b/perfetto_hprof/perfetto_hprof.cc
index efd105b..b04d413 100644
--- a/perfetto_hprof/perfetto_hprof.cc
+++ b/perfetto_hprof/perfetto_hprof.cc
@@ -46,6 +46,7 @@
#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
#include "well_known_classes.h"
+#include "dex/descriptors_names.h"
// There are three threads involved in this:
// * listener thread: this is idle in the background when this plugin gets loaded, and waits
@@ -366,6 +367,15 @@
}
}
+std::string PrettyType(art::mirror::Class* klass) NO_THREAD_SAFETY_ANALYSIS {
+ if (klass == nullptr) {
+ return "(raw)";
+ }
+ std::string temp;
+ std::string result(art::PrettyDescriptor(klass->GetDescriptor(&temp)));
+ return result;
+}
+
void DumpPerfetto(art::Thread* self) {
pid_t parent_pid = getpid();
LOG(INFO) << "preparing to dump heap for " << parent_pid;
@@ -435,7 +445,7 @@
// Make sure that intern ID 0 (default proto value for a uint64_t) always maps to ""
// (default proto value for a string).
std::map<std::string, uint64_t> interned_fields{{"", 0}};
- std::map<std::string, uint64_t> interned_types{{"", 0}};
+ std::map<std::string, uint64_t> interned_locations{{"", 0}};
std::map<art::RootType, std::vector<art::mirror::Object*>> root_objects;
RootFinder rcf(&root_objects);
@@ -467,14 +477,41 @@
new protozero::PackedVarInt);
art::Runtime::Current()->GetHeap()->VisitObjectsPaused(
- [&writer, &interned_types, &interned_fields,
+ [&writer, &interned_fields, &interned_locations,
&reference_field_ids, &reference_object_ids](
art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ if (obj->IsClass()) {
+ art::mirror::Class* klass = obj->AsClass().Ptr();
+ perfetto::protos::pbzero::HeapGraphType* type_proto =
+ writer.GetHeapGraph()->add_types();
+ type_proto->set_id(reinterpret_cast<uintptr_t>(klass));
+ type_proto->set_class_name(PrettyType(klass));
+ type_proto->set_location_id(FindOrAppend(&interned_locations,
+ klass->GetLocation()));
+ }
+
+ art::mirror::Class* klass = obj->GetClass();
+ uintptr_t class_id = reinterpret_cast<uintptr_t>(klass);
+ // We need to synethesize a new type for Class<Foo>, which does not exist
+ // in the runtime. Otherwise, all the static members of all classes would be
+ // attributed to java.lang.Class.
+ if (klass->IsClassClass()) {
+ CHECK(obj->IsClass());
+ perfetto::protos::pbzero::HeapGraphType* type_proto =
+ writer.GetHeapGraph()->add_types();
+ // All pointers are at least multiples of two, so this way we can make sure
+ // we are not colliding with a real class.
+ class_id = reinterpret_cast<uintptr_t>(obj) | 1;
+ type_proto->set_id(class_id);
+ type_proto->set_class_name(obj->PrettyTypeOf());
+ type_proto->set_location_id(FindOrAppend(&interned_locations,
+ obj->AsClass()->GetLocation()));
+ }
+
perfetto::protos::pbzero::HeapGraphObject* object_proto =
writer.GetHeapGraph()->add_objects();
object_proto->set_id(reinterpret_cast<uintptr_t>(obj));
- object_proto->set_type_id(
- FindOrAppend(&interned_types, obj->PrettyTypeOf()));
+ object_proto->set_type_id(class_id);
object_proto->set_self_size(obj->SizeOf());
std::vector<std::pair<std::string, art::mirror::Object*>>
@@ -501,14 +538,14 @@
field_proto->set_str(
reinterpret_cast<const uint8_t*>(str.c_str()), str.size());
}
- for (const auto& p : interned_types) {
+ for (const auto& p : interned_locations) {
const std::string& str = p.first;
uint64_t id = p.second;
- perfetto::protos::pbzero::InternedString* type_proto =
- writer.GetHeapGraph()->add_type_names();
- type_proto->set_iid(id);
- type_proto->set_str(reinterpret_cast<const uint8_t*>(str.c_str()),
+ perfetto::protos::pbzero::InternedString* location_proto =
+ writer.GetHeapGraph()->add_location_names();
+ location_proto->set_iid(id);
+ location_proto->set_str(reinterpret_cast<const uint8_t*>(str.c_str()),
str.size());
}