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());
             }