summaryrefslogtreecommitdiff
path: root/simpleperf/report_lib_interface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'simpleperf/report_lib_interface.cpp')
-rw-r--r--simpleperf/report_lib_interface.cpp178
1 files changed, 74 insertions, 104 deletions
diff --git a/simpleperf/report_lib_interface.cpp b/simpleperf/report_lib_interface.cpp
index 70a274f4..d6a4bc09 100644
--- a/simpleperf/report_lib_interface.cpp
+++ b/simpleperf/report_lib_interface.cpp
@@ -17,24 +17,22 @@
#include <memory>
#include <utility>
-#include <android-base/logging.h>
#include <android-base/file.h>
+#include <android-base/logging.h>
#include <android-base/strings.h>
+#include "JITDebugReader.h"
#include "dso.h"
#include "event_attr.h"
#include "event_type.h"
#include "record_file.h"
+#include "report_utils.h"
#include "thread_tree.h"
#include "tracing.h"
#include "utils.h"
-class ReportLib;
-
extern "C" {
-#define EXPORT __attribute__((visibility("default")))
-
struct Sample {
uint64_t ip;
uint32_t pid;
@@ -52,6 +50,7 @@ struct TracingFieldFormat {
uint32_t elem_size;
uint32_t elem_count;
uint32_t is_signed;
+ uint32_t is_dynamic;
};
struct TracingDataFormat {
@@ -95,30 +94,9 @@ struct FeatureSection {
uint32_t data_size;
};
-// Create a new instance,
-// pass the instance to the other functions below.
-ReportLib* CreateReportLib() EXPORT;
-void DestroyReportLib(ReportLib* report_lib) EXPORT;
+} // extern "C"
-// Set log severity, different levels are:
-// verbose, debug, info, warning, error, fatal.
-bool SetLogSeverity(ReportLib* report_lib, const char* log_level) EXPORT;
-bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) EXPORT;
-bool SetRecordFile(ReportLib* report_lib, const char* record_file) EXPORT;
-bool SetKallsymsFile(ReportLib* report_lib, const char* kallsyms_file) EXPORT;
-void ShowIpForUnknownSymbol(ReportLib* report_lib) EXPORT;
-void ShowArtFrames(ReportLib* report_lib, bool show) EXPORT;
-void MergeJavaMethods(ReportLib* report_lib, bool merge) EXPORT;
-
-Sample* GetNextSample(ReportLib* report_lib) EXPORT;
-Event* GetEventOfCurrentSample(ReportLib* report_lib) EXPORT;
-SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) EXPORT;
-CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) EXPORT;
-const char* GetTracingDataOfCurrentSample(ReportLib* report_lib) EXPORT;
-
-const char* GetBuildIdForPath(ReportLib* report_lib, const char* path) EXPORT;
-FeatureSection* GetFeatureSection(ReportLib* report_lib, const char* feature_name) EXPORT;
-}
+namespace simpleperf {
struct EventInfo {
perf_event_attr attr;
@@ -134,13 +112,11 @@ struct EventInfo {
class ReportLib {
public:
ReportLib()
- : log_severity_(
- new android::base::ScopedLogSeverity(android::base::INFO)),
+ : log_severity_(new android::base::ScopedLogSeverity(android::base::INFO)),
record_filename_("perf.data"),
current_thread_(nullptr),
trace_offcpu_(false),
- show_art_frames_(false) {
- }
+ callchain_report_builder_(thread_tree_) {}
bool SetLogSeverity(const char* log_level);
@@ -154,8 +130,14 @@ class ReportLib {
bool SetKallsymsFile(const char* kallsyms_file);
void ShowIpForUnknownSymbol() { thread_tree_.ShowIpForUnknownSymbol(); }
- void ShowArtFrames(bool show) { show_art_frames_ = show; }
- void MergeJavaMethods(bool merge) { merge_java_methods_ = merge; }
+ void ShowArtFrames(bool show) {
+ bool remove_art_frame = !show;
+ callchain_report_builder_.SetRemoveArtFrame(remove_art_frame);
+ }
+ void MergeJavaMethods(bool merge) { callchain_report_builder_.SetConvertJITFrame(merge); }
+ bool AddProguardMappingFile(const char* mapping_file) {
+ return callchain_report_builder_.AddProguardMappingFile(mapping_file);
+ }
Sample* GetNextSample();
Event* GetEventOfCurrentSample() { return &current_event_; }
@@ -193,10 +175,7 @@ class ReportLib {
std::unordered_map<pid_t, std::unique_ptr<SampleRecord>> next_sample_cache_;
FeatureSection feature_section_;
std::vector<char> feature_section_data_;
- bool show_art_frames_;
- bool merge_java_methods_ = true;
- // Map from a java method name to it's dex file, start_addr and len.
- std::unordered_map<std::string, std::tuple<Dso*, uint64_t, uint64_t>> java_methods_;
+ CallChainReportBuilder callchain_report_builder_;
std::unique_ptr<Tracing> tracing_;
};
@@ -232,15 +211,6 @@ bool ReportLib::OpenRecordFileIfNecessary() {
if (auto it = meta_info.find("trace_offcpu"); it != meta_info.end()) {
trace_offcpu_ = it->second == "true";
}
- if (merge_java_methods_) {
- for (Dso* dso : thread_tree_.GetAllDsos()) {
- if (dso->type() == DSO_DEX_FILE) {
- for (auto& symbol : dso->GetSymbols()) {
- java_methods_[symbol.Name()] = std::make_tuple(dso, symbol.addr, symbol.len);
- }
- }
- }
- }
}
return true;
}
@@ -295,8 +265,8 @@ void ReportLib::SetCurrentSample() {
current_sample_.in_kernel = r.InKernel();
current_sample_.cpu = r.cpu_data.cpu;
if (trace_offcpu_) {
- uint64_t next_time = std::max(next_sample_cache_[r.tid_data.tid]->time_data.time,
- r.time_data.time + 1);
+ uint64_t next_time =
+ std::max(next_sample_cache_[r.tid_data.tid]->time_data.time, r.time_data.time + 1);
current_sample_.period = next_time - r.time_data.time;
} else {
current_sample_.period = r.period_data.period;
@@ -304,62 +274,23 @@ void ReportLib::SetCurrentSample() {
size_t kernel_ip_count;
std::vector<uint64_t> ips = r.GetCallChain(&kernel_ip_count);
- std::vector<std::pair<uint64_t, const MapEntry*>> ip_maps;
- bool near_java_method = false;
- auto is_map_for_interpreter = [](const MapEntry* map) {
- return android::base::EndsWith(map->dso->Path(), "/libart.so") ||
- android::base::EndsWith(map->dso->Path(), "/libartd.so");
- };
- for (size_t i = 0; i < ips.size(); ++i) {
- const MapEntry* map = thread_tree_.FindMap(current_thread_, ips[i], i < kernel_ip_count);
- if (!show_art_frames_) {
- // Remove interpreter frames both before and after the Java frame.
- if (map->dso->IsForJavaMethod()) {
- near_java_method = true;
- while (!ip_maps.empty() && is_map_for_interpreter(ip_maps.back().second)) {
- ip_maps.pop_back();
- }
- } else if (is_map_for_interpreter(map)){
- if (near_java_method) {
- continue;
- }
- } else {
- near_java_method = false;
- }
- }
- ip_maps.push_back(std::make_pair(ips[i], map));
- }
- for (auto& pair : ip_maps) {
- uint64_t ip = pair.first;
- const MapEntry* map = pair.second;
- uint64_t vaddr_in_file;
- const Symbol* symbol = thread_tree_.FindSymbol(map, ip, &vaddr_in_file);
- CallChainEntry entry;
- entry.ip = ip;
- entry.symbol.dso_name = map->dso->Path().c_str();
- entry.symbol.vaddr_in_file = vaddr_in_file;
- entry.symbol.symbol_name = symbol->DemangledName();
- entry.symbol.symbol_addr = symbol->addr;
- entry.symbol.symbol_len = symbol->len;
- entry.symbol.mapping = AddMapping(*map);
-
- if (merge_java_methods_ && map->dso->type() == DSO_ELF_FILE && map->dso->IsForJavaMethod()) {
- // This is a jitted java method, merge it with the interpreted java method having the same
- // name if possible. Otherwise, merge it with other jitted java methods having the same name
- // by assigning a common dso_name.
- if (auto it = java_methods_.find(entry.symbol.symbol_name); it != java_methods_.end()) {
- entry.symbol.dso_name = std::get<0>(it->second)->Path().c_str();
- entry.symbol.symbol_addr = std::get<1>(it->second);
- entry.symbol.symbol_len = std::get<2>(it->second);
- // Not enough info to map an offset in a jitted method to an offset in a dex file. So just
- // use the symbol_addr.
- entry.symbol.vaddr_in_file = entry.symbol.symbol_addr;
- } else {
- entry.symbol.dso_name = "[JIT cache]";
- }
+ std::vector<CallChainReportEntry> report_entries =
+ callchain_report_builder_.Build(current_thread_, ips, kernel_ip_count);
+
+ for (const auto& report_entry : report_entries) {
+ callchain_entries_.resize(callchain_entries_.size() + 1);
+ CallChainEntry& entry = callchain_entries_.back();
+ entry.ip = report_entry.ip;
+ if (report_entry.dso_name != nullptr) {
+ entry.symbol.dso_name = report_entry.dso_name;
+ } else {
+ entry.symbol.dso_name = report_entry.dso->GetReportPath().data();
}
-
- callchain_entries_.push_back(entry);
+ entry.symbol.vaddr_in_file = report_entry.vaddr_in_file;
+ entry.symbol.symbol_name = report_entry.symbol->DemangledName();
+ entry.symbol.symbol_addr = report_entry.symbol->addr;
+ entry.symbol.symbol_len = report_entry.symbol->len;
+ entry.symbol.mapping = AddMapping(*report_entry.map);
}
current_sample_.ip = callchain_entries_[0].ip;
current_symbol_ = &(callchain_entries_[0].symbol);
@@ -409,6 +340,7 @@ void ReportLib::CreateEvents() {
field.elem_size = format.fields[i].elem_size;
field.elem_count = format.fields[i].elem_count;
field.is_signed = format.fields[i].is_signed;
+ field.is_dynamic = format.fields[i].is_dynamic;
}
if (tracing_info.fields.empty()) {
tracing_info.data_format.size = 0;
@@ -462,6 +394,40 @@ FeatureSection* ReportLib::GetFeatureSection(const char* feature_name) {
return &feature_section_;
}
+} // namespace simpleperf
+
+using ReportLib = simpleperf::ReportLib;
+
+extern "C" {
+
+#define EXPORT __attribute__((visibility("default")))
+
+// Create a new instance,
+// pass the instance to the other functions below.
+ReportLib* CreateReportLib() EXPORT;
+void DestroyReportLib(ReportLib* report_lib) EXPORT;
+
+// Set log severity, different levels are:
+// verbose, debug, info, warning, error, fatal.
+bool SetLogSeverity(ReportLib* report_lib, const char* log_level) EXPORT;
+bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) EXPORT;
+bool SetRecordFile(ReportLib* report_lib, const char* record_file) EXPORT;
+bool SetKallsymsFile(ReportLib* report_lib, const char* kallsyms_file) EXPORT;
+void ShowIpForUnknownSymbol(ReportLib* report_lib) EXPORT;
+void ShowArtFrames(ReportLib* report_lib, bool show) EXPORT;
+void MergeJavaMethods(ReportLib* report_lib, bool merge) EXPORT;
+bool AddProguardMappingFile(ReportLib* report_lib, const char* mapping_file) EXPORT;
+
+Sample* GetNextSample(ReportLib* report_lib) EXPORT;
+Event* GetEventOfCurrentSample(ReportLib* report_lib) EXPORT;
+SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) EXPORT;
+CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) EXPORT;
+const char* GetTracingDataOfCurrentSample(ReportLib* report_lib) EXPORT;
+
+const char* GetBuildIdForPath(ReportLib* report_lib, const char* path) EXPORT;
+FeatureSection* GetFeatureSection(ReportLib* report_lib, const char* feature_name) EXPORT;
+}
+
// Exported methods working with a client created instance
ReportLib* CreateReportLib() {
return new ReportLib();
@@ -499,6 +465,10 @@ bool SetKallsymsFile(ReportLib* report_lib, const char* kallsyms_file) {
return report_lib->SetKallsymsFile(kallsyms_file);
}
+bool AddProguardMappingFile(ReportLib* report_lib, const char* mapping_file) {
+ return report_lib->AddProguardMappingFile(mapping_file);
+}
+
Sample* GetNextSample(ReportLib* report_lib) {
return report_lib->GetNextSample();
}