summaryrefslogtreecommitdiff
path: root/simpleperf/JITDebugReader.h
diff options
context:
space:
mode:
Diffstat (limited to 'simpleperf/JITDebugReader.h')
-rw-r--r--simpleperf/JITDebugReader.h121
1 files changed, 69 insertions, 52 deletions
diff --git a/simpleperf/JITDebugReader.h b/simpleperf/JITDebugReader.h
index b9e984d5..4483ddf0 100644
--- a/simpleperf/JITDebugReader.h
+++ b/simpleperf/JITDebugReader.h
@@ -38,6 +38,52 @@ namespace simpleperf {
inline constexpr const char* kJITAppCacheFile = "jit_app_cache";
inline constexpr const char* kJITZygoteCacheFile = "jit_zygote_cache";
+inline constexpr const char* kDexFileInMemoryPrefix = "dexfile_in_memory";
+
+namespace JITDebugReader_impl {
+
+enum class DescriptorType {
+ kDEX,
+ kJIT,
+};
+
+// An arch-independent representation of JIT/dex debug descriptor.
+struct Descriptor {
+ DescriptorType type;
+ int version = 0;
+ uint32_t action_seqlock = 0; // incremented before and after any modification
+ uint64_t action_timestamp = 0; // CLOCK_MONOTONIC time of last action
+ uint64_t first_entry_addr = 0;
+};
+
+// An arch-independent representation of JIT/dex code entry.
+struct CodeEntry {
+ uint64_t addr;
+ uint64_t symfile_addr;
+ uint64_t symfile_size;
+ uint64_t timestamp; // CLOCK_MONOTONIC time of last action
+};
+
+struct Process {
+ pid_t pid = -1;
+ bool initialized = false;
+ bool died = false;
+ bool is_64bit = false;
+ // remote addr of jit descriptor
+ uint64_t jit_descriptor_addr = 0;
+ // remote addr of dex descriptor
+ uint64_t dex_descriptor_addr = 0;
+
+ // The state we know about the remote jit debug descriptor.
+ 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_;
+};
+
+} // namespace JITDebugReader_impl
// JITDebugInfo represents the debug info of a JITed Java method or a dex file.
struct JITDebugInfo {
@@ -47,6 +93,7 @@ struct JITDebugInfo {
} type;
pid_t pid; // Process of the debug info
uint64_t timestamp; // Monotonic timestamp for the creation of the debug info
+
union {
struct {
uint64_t jit_code_addr; // The start addr of the JITed code
@@ -59,10 +106,13 @@ struct JITDebugInfo {
std::string file_path;
uint64_t file_offset;
- // The map for dex file extracted in memory. On Android Q, ART extracts dex files in apk files
- // directly into memory, and names it using prctl(). The kernel doesn't generate a new mmap
- // record for it. So we need to dump it manually.
- std::shared_ptr<ThreadMmap> extracted_dex_file_map;
+ // dex_file_map may be a dex file extracted in memory. On Android >= Q, ART may extract dex files
+ // in apk files directly into memory, and name it using prctl(). The kernel doesn't generate a
+ // new mmap record for it. So we need to dump it manually.
+ // Or dex_file_map may be a dex file created in memory. In that case, symbols are read from the
+ // dex file.
+ std::shared_ptr<ThreadMmap> dex_file_map;
+ std::vector<Symbol> symbols;
JITDebugInfo(pid_t pid, uint64_t timestamp, uint64_t jit_code_addr, uint64_t jit_code_len,
const std::string& file_path, uint64_t file_offset)
@@ -75,15 +125,16 @@ struct JITDebugInfo {
file_offset(file_offset) {}
JITDebugInfo(pid_t pid, uint64_t timestamp, uint64_t dex_file_offset,
- const std::string& file_path,
- const std::shared_ptr<ThreadMmap>& extracted_dex_file_map)
+ const std::string& file_path, const std::shared_ptr<ThreadMmap>& dex_file_map,
+ std::vector<Symbol> symbols)
: type(JIT_DEBUG_DEX_FILE),
pid(pid),
timestamp(timestamp),
dex_file_offset(dex_file_offset),
file_path(file_path),
file_offset(0),
- extracted_dex_file_map(extracted_dex_file_map) {}
+ dex_file_map(dex_file_map),
+ symbols(std::move(symbols)) {}
bool operator>(const JITDebugInfo& other) const { return timestamp > other.timestamp; }
};
@@ -94,6 +145,10 @@ class TempSymFile;
// corresponding debug interface in ART is at art/runtime/jit/debugger_interface.cc.
class JITDebugReader {
public:
+ using Descriptor = JITDebugReader_impl::Descriptor;
+ using CodeEntry = JITDebugReader_impl::CodeEntry;
+ using Process = JITDebugReader_impl::Process;
+
enum class SymFileOption {
kDropSymFiles, // JIT symfiles are dropped after recording.
kKeepSymFiles, // JIT symfiles are kept after recording, usually for debug unwinding.
@@ -113,7 +168,7 @@ class JITDebugReader {
bool SyncWithRecords() const { return sync_option_ == SyncOption::kSyncWithRecords; }
- typedef std::function<bool(const std::vector<JITDebugInfo>&, bool)> debug_info_callback_t;
+ typedef std::function<bool(std::vector<JITDebugInfo>, bool)> debug_info_callback_t;
bool RegisterDebugInfoCallback(IOEventLoop* loop, const debug_info_callback_t& callback);
// There are two ways to select which processes to monitor. One is using MonitorProcess(), the
@@ -134,48 +189,11 @@ class JITDebugReader {
path.find(std::string("_") + kJITZygoteCacheFile + ":") != path.npos;
}
- private:
- enum class DescriptorType {
- kDEX,
- kJIT,
- };
-
- // An arch-independent representation of JIT/dex debug descriptor.
- struct Descriptor {
- DescriptorType type;
- int version = 0;
- uint32_t action_seqlock = 0; // incremented before and after any modification
- uint64_t action_timestamp = 0; // CLOCK_MONOTONIC time of last action
- uint64_t first_entry_addr = 0;
- };
-
- // An arch-independent representation of JIT/dex code entry.
- struct CodeEntry {
- uint64_t addr;
- uint64_t symfile_addr;
- uint64_t symfile_size;
- uint64_t timestamp; // CLOCK_MONOTONIC time of last action
- };
-
- struct Process {
- pid_t pid = -1;
- bool initialized = false;
- bool died = false;
- bool is_64bit = false;
- // remote addr of jit descriptor
- uint64_t jit_descriptor_addr = 0;
- // remote addr of dex descriptor
- uint64_t dex_descriptor_addr = 0;
-
- // The state we know about the remote jit debug descriptor.
- 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_;
- };
+ // exported for testing
+ void ReadDexFileDebugInfo(Process& process, const std::vector<CodeEntry>& dex_entries,
+ std::vector<JITDebugInfo>* debug_info);
+ private:
// The location of descriptors in libart.so.
struct DescriptorsLocation {
bool is_64bit = false;
@@ -208,9 +226,8 @@ class JITDebugReader {
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);
+ std::vector<Symbol> ReadDexFileSymbolsInMemory(Process& process, uint64_t addr, uint64_t size);
+ bool AddDebugInfo(std::vector<JITDebugInfo> debug_info, bool sync_kernel_records);
const std::string symfile_prefix_;
SymFileOption symfile_option_;