Skip to content

Commit

Permalink
Get jar / apk / dexfile location for classes.
Browse files Browse the repository at this point in the history
We need this information for deobfuscation.

This is a cherry-pick of 29e62c3

Bug: 150546312

Merged-In: Ie44c79437644641a8a72b876fa83a3f498602dbe
Change-Id: Ie44c79437644641a8a72b876fa83a3f498602dbe
  • Loading branch information
fmayer authored and TreeHugger Robot committed Mar 24, 2020
1 parent cbef173 commit 4b7a6bf
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
1 change: 1 addition & 0 deletions perfetto_hprof/Android.bp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ cc_defaults {
shared_libs: [
"libbase",
"liblog",
"libdexfile",
],
static_libs: [
"libperfetto_client_experimental",
Expand Down
55 changes: 46 additions & 9 deletions perfetto_hprof/perfetto_hprof.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -347,6 +348,15 @@ perfetto::protos::pbzero::HeapGraphRoot::Type ToProtoType(art::RootType art_type
}
}

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;
Expand Down Expand Up @@ -416,7 +426,7 @@ void DumpPerfetto(art::Thread* self) {
// 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);
Expand All @@ -441,14 +451,41 @@ void DumpPerfetto(art::Thread* self) {
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*>>
Expand All @@ -475,14 +512,14 @@ void DumpPerfetto(art::Thread* self) {
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());
}

Expand Down

0 comments on commit 4b7a6bf

Please sign in to comment.