Merge "simpleperf: Split jit_app_cache and jit_zygote_cache."
diff --git a/simpleperf/JITDebugReader.cpp b/simpleperf/JITDebugReader.cpp
index 08064cd..efc4fae 100644
--- a/simpleperf/JITDebugReader.cpp
+++ b/simpleperf/JITDebugReader.cpp
@@ -39,6 +39,7 @@
#include "read_elf.h"
#include "utils.h"
+using android::base::StartsWith;
using android::base::StringPrintf;
namespace simpleperf {
@@ -55,6 +56,9 @@
// avoid spending all time checking, wait 100 ms between any two checks.
static constexpr size_t kUpdateJITDebugInfoIntervalInMs = 100;
+// map name used for jit zygote cache
+static const char* kJITZygoteCacheMmapPrefix = "/memfd:jit-zygote-cache";
+
// Match the format of JITDescriptor in art/runtime/jit/debugger_interface.cc.
template <typename ADDRT>
struct JITDescriptor {
@@ -231,13 +235,17 @@
return false;
}
file_offset_ += size;
+ need_flush_ = true;
return true;
}
bool Flush() {
- if (fflush(fp_.get()) != 0) {
- PLOG(ERROR) << "failed to flush " << path_;
- return false;
+ if (need_flush_) {
+ if (fflush(fp_.get()) != 0) {
+ PLOG(ERROR) << "failed to flush " << path_;
+ return false;
+ }
+ need_flush_ = false;
}
return true;
}
@@ -252,6 +260,7 @@
const std::string path_;
std::unique_ptr<FILE, decltype(&fclose)> fp_;
uint64_t file_offset_ = 0;
+ bool need_flush_ = false;
};
JITDebugReader::JITDebugReader(const std::string& symfile_prefix, SymFileOption symfile_option,
@@ -472,6 +481,13 @@
process.descriptors_size = location->size;
process.jit_descriptor_offset = location->jit_descriptor_offset;
process.dex_descriptor_offset = location->dex_descriptor_offset;
+
+ for (auto& map : thread_mmaps) {
+ if (StartsWith(map.name, kJITZygoteCacheMmapPrefix)) {
+ process.jit_zygote_cache_ranges_.emplace_back(map.start_addr, map.start_addr + map.len);
+ }
+ }
+
process.initialized = true;
return true;
}
@@ -653,7 +669,6 @@
const std::vector<CodeEntry>& jit_entries,
std::vector<JITDebugInfo>* debug_info) {
std::vector<char> data;
- bool need_flush_app_symfile = false;
for (auto& jit_entry : jit_entries) {
if (jit_entry.symfile_size > MAX_JIT_SYMFILE_SIZE) {
@@ -668,32 +683,28 @@
if (!IsValidElfFileMagic(data.data(), jit_entry.symfile_size)) {
continue;
}
- if (!app_symfile_) {
- std::string path = symfile_prefix_ + "_jit_app_cache";
- app_symfile_ =
- TempSymFile::Create(std::move(path), symfile_option_ == SymFileOption::kDropSymFiles);
- if (!app_symfile_) {
- return false;
- }
- }
- uint64_t file_offset = app_symfile_->GetOffset();
- if (!app_symfile_->WriteEntry(data.data(), jit_entry.symfile_size)) {
+ TempSymFile* symfile = GetTempSymFile(process, jit_entry);
+ if (symfile == nullptr) {
return false;
}
- need_flush_app_symfile = true;
+ uint64_t file_offset = symfile->GetOffset();
+ if (!symfile->WriteEntry(data.data(), jit_entry.symfile_size)) {
+ return false;
+ }
auto callback = [&](const ElfFileSymbol& symbol) {
if (symbol.len == 0) { // Some arm labels can have zero length.
return;
}
- LOG(VERBOSE) << "JITSymbol " << symbol.name << " at [" << std::hex << symbol.vaddr
- << " - " << (symbol.vaddr + symbol.len) << " with size " << symbol.len;
-
// Pass out the location of the symfile for unwinding and symbolization.
std::string location_in_file =
StringPrintf(":%" PRIu64 "-%" PRIu64, file_offset, file_offset + jit_entry.symfile_size);
debug_info->emplace_back(process.pid, jit_entry.timestamp, symbol.vaddr, symbol.len,
- app_symfile_->GetPath() + location_in_file, file_offset);
+ symfile->GetPath() + location_in_file, file_offset);
+
+ LOG(VERBOSE) << "JITSymbol " << symbol.name << " at [" << std::hex << symbol.vaddr
+ << " - " << (symbol.vaddr + symbol.len) << " with size " << symbol.len
+ << " in " << symfile->GetPath() << location_in_file;
};
ElfStatus status;
auto elf = ElfFile::Open(data.data(), jit_entry.symfile_size, &status);
@@ -702,14 +713,39 @@
}
}
- if (need_flush_app_symfile) {
- if (!app_symfile_->Flush()) {
- return false;
- }
+ if (app_symfile_) {
+ app_symfile_->Flush();
+ }
+ if (zygote_symfile_) {
+ zygote_symfile_->Flush();
}
return true;
}
+TempSymFile* JITDebugReader::GetTempSymFile(Process& process, const CodeEntry& jit_entry) {
+ bool is_zygote = false;
+ for (const auto& range : process.jit_zygote_cache_ranges_) {
+ if (jit_entry.symfile_addr >= range.first && jit_entry.symfile_addr < range.second) {
+ is_zygote = true;
+ break;
+ }
+ }
+ if (is_zygote) {
+ if (!zygote_symfile_) {
+ std::string path = symfile_prefix_ + "_jit_zygote_cache";
+ zygote_symfile_ =
+ TempSymFile::Create(std::move(path), symfile_option_ == SymFileOption::kDropSymFiles);
+ }
+ return zygote_symfile_.get();
+ }
+ if (!app_symfile_) {
+ std::string path = symfile_prefix_ + "_jit_app_cache";
+ app_symfile_ =
+ TempSymFile::Create(std::move(path), symfile_option_ == SymFileOption::kDropSymFiles);
+ }
+ return app_symfile_.get();
+}
+
void JITDebugReader::ReadDexFileDebugInfo(Process& process,
const std::vector<CodeEntry>& dex_entries,
std::vector<JITDebugInfo>* debug_info) {
diff --git a/simpleperf/JITDebugReader.h b/simpleperf/JITDebugReader.h
index 31741a5..167b0e9 100644
--- a/simpleperf/JITDebugReader.h
+++ b/simpleperf/JITDebugReader.h
@@ -170,6 +170,9 @@
Descriptor last_jit_descriptor;
// The state we know about the remote dex debug descriptor.
Descriptor last_dex_descriptor;
+
+ // memory space for /memfd:jit-zygote-cache
+ std::vector<std::pair<uint64_t, uint64_t>> jit_zygote_cache_ranges_;
};
// The location of descriptors in libart.so.
@@ -203,6 +206,7 @@
bool ReadJITCodeDebugInfo(Process& process, const std::vector<CodeEntry>& jit_entries,
std::vector<JITDebugInfo>* debug_info);
+ TempSymFile* GetTempSymFile(Process& process, const CodeEntry& jit_entry);
void ReadDexFileDebugInfo(Process& process, const std::vector<CodeEntry>& dex_entries,
std::vector<JITDebugInfo>* debug_info);
bool AddDebugInfo(const std::vector<JITDebugInfo>& debug_info, bool sync_kernel_records);
@@ -226,6 +230,7 @@
// temporary files used to store jit symfiles created by the app process and the zygote process.
std::unique_ptr<TempSymFile> app_symfile_;
+ std::unique_ptr<TempSymFile> zygote_symfile_;
};
} //namespace simpleperf