blob: b9e984d59f73abb6801a7e423c81468dc8ca2733 [file] [log] [blame]
Yabin Cui9e43e9f2018-03-09 15:57:13 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SIMPLE_PERF_JIT_DEBUG_READER_H_
18#define SIMPLE_PERF_JIT_DEBUG_READER_H_
19
20#include <unistd.h>
21
22#include <functional>
23#include <memory>
Yabin Cui5d5c01a2018-08-27 10:30:20 -070024#include <queue>
Yabin Cui9e43e9f2018-03-09 15:57:13 -080025#include <stack>
Yabin Cuic8571d42018-06-06 11:20:39 -070026#include <unordered_map>
Yabin Cui9e43e9f2018-03-09 15:57:13 -080027#include <unordered_set>
28#include <vector>
29
Mark Salyzyn499a0172018-11-12 12:58:06 -080030#include <android-base/file.h>
Yabin Cui9e43e9f2018-03-09 15:57:13 -080031#include <android-base/logging.h>
Yabin Cui9e43e9f2018-03-09 15:57:13 -080032
Yabin Cuic8571d42018-06-06 11:20:39 -070033#include "IOEventLoop.h"
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +020034#include "environment.h"
Yabin Cuic8571d42018-06-06 11:20:39 -070035#include "record.h"
36
Yabin Cui9e43e9f2018-03-09 15:57:13 -080037namespace simpleperf {
38
Yabin Cui075dd182020-08-05 19:51:36 +000039inline constexpr const char* kJITAppCacheFile = "jit_app_cache";
40inline constexpr const char* kJITZygoteCacheFile = "jit_zygote_cache";
41
Yabin Cui5d5c01a2018-08-27 10:30:20 -070042// JITDebugInfo represents the debug info of a JITed Java method or a dex file.
43struct JITDebugInfo {
44 enum {
45 JIT_DEBUG_JIT_CODE,
46 JIT_DEBUG_DEX_FILE,
47 } type;
48 pid_t pid; // Process of the debug info
49 uint64_t timestamp; // Monotonic timestamp for the creation of the debug info
50 union {
51 struct {
52 uint64_t jit_code_addr; // The start addr of the JITed code
53 uint64_t jit_code_len; // The end addr of the JITed code
54 };
55 uint64_t dex_file_offset; // The offset of the dex file in the file containing it
56 };
57 // For JITed code, it is the path of a temporary ELF file storing its debug info.
58 // For dex file, it is the path of the file containing the dex file.
59 std::string file_path;
Yabin Cuie32ed2b2020-07-23 15:30:14 -070060 uint64_t file_offset;
Yabin Cuic8571d42018-06-06 11:20:39 -070061
Yabin Cui400892e2019-05-31 10:39:56 -070062 // The map for dex file extracted in memory. On Android Q, ART extracts dex files in apk files
63 // directly into memory, and names it using prctl(). The kernel doesn't generate a new mmap
64 // record for it. So we need to dump it manually.
65 std::shared_ptr<ThreadMmap> extracted_dex_file_map;
66
Yabin Cui5d5c01a2018-08-27 10:30:20 -070067 JITDebugInfo(pid_t pid, uint64_t timestamp, uint64_t jit_code_addr, uint64_t jit_code_len,
Yabin Cuie32ed2b2020-07-23 15:30:14 -070068 const std::string& file_path, uint64_t file_offset)
69 : type(JIT_DEBUG_JIT_CODE),
70 pid(pid),
71 timestamp(timestamp),
72 jit_code_addr(jit_code_addr),
73 jit_code_len(jit_code_len),
74 file_path(file_path),
75 file_offset(file_offset) {}
Yabin Cui9e43e9f2018-03-09 15:57:13 -080076
Yabin Cui5d5c01a2018-08-27 10:30:20 -070077 JITDebugInfo(pid_t pid, uint64_t timestamp, uint64_t dex_file_offset,
Yabin Cui400892e2019-05-31 10:39:56 -070078 const std::string& file_path,
79 const std::shared_ptr<ThreadMmap>& extracted_dex_file_map)
Yabin Cuie32ed2b2020-07-23 15:30:14 -070080 : type(JIT_DEBUG_DEX_FILE),
81 pid(pid),
82 timestamp(timestamp),
83 dex_file_offset(dex_file_offset),
84 file_path(file_path),
85 file_offset(0),
86 extracted_dex_file_map(extracted_dex_file_map) {}
Yabin Cui2a53ff32018-05-21 17:37:00 -070087
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +020088 bool operator>(const JITDebugInfo& other) const { return timestamp > other.timestamp; }
Yabin Cui9e43e9f2018-03-09 15:57:13 -080089};
90
Yabin Cuie32ed2b2020-07-23 15:30:14 -070091class TempSymFile;
92
Yabin Cuic8571d42018-06-06 11:20:39 -070093// JITDebugReader reads debug info of JIT code and dex files of processes using ART. The
94// corresponding debug interface in ART is at art/runtime/jit/debugger_interface.cc.
Yabin Cui9e43e9f2018-03-09 15:57:13 -080095class JITDebugReader {
96 public:
Yabin Cuie32ed2b2020-07-23 15:30:14 -070097 enum class SymFileOption {
98 kDropSymFiles, // JIT symfiles are dropped after recording.
99 kKeepSymFiles, // JIT symfiles are kept after recording, usually for debug unwinding.
100 };
101
102 enum class SyncOption {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200103 kNoSync, // Don't sync debug info with records.
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700104 kSyncWithRecords, // Sync debug info with records based on monotonic timestamp.
105 };
106
107 // symfile_prefix: JITDebugReader creates temporary file to store symfiles for JIT code. Add this
108 // prefix to avoid conflicts.
109 JITDebugReader(const std::string& symfile_prefix, SymFileOption symfile_option,
110 SyncOption sync_option);
111
112 ~JITDebugReader();
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800113
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200114 bool SyncWithRecords() const { return sync_option_ == SyncOption::kSyncWithRecords; }
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700115
116 typedef std::function<bool(const std::vector<JITDebugInfo>&, bool)> debug_info_callback_t;
117 bool RegisterDebugInfoCallback(IOEventLoop* loop, const debug_info_callback_t& callback);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800118
Yabin Cuic8571d42018-06-06 11:20:39 -0700119 // There are two ways to select which processes to monitor. One is using MonitorProcess(), the
120 // other is finding all processes having libart.so using records.
121 bool MonitorProcess(pid_t pid);
122 bool UpdateRecord(const Record* record);
123
124 // Read new debug info from all monitored processes.
125 bool ReadAllProcesses();
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700126 // Read new debug info from one process.
127 bool ReadProcess(pid_t pid);
128
129 // Flush all debug info registered before timestamp.
130 bool FlushDebugInfo(uint64_t timestamp);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800131
Yabin Cui9ba4d942020-09-08 16:12:46 -0700132 static bool IsPathInJITSymFile(const std::string& path) {
133 return path.find(std::string("_") + kJITAppCacheFile + ":") != path.npos ||
134 path.find(std::string("_") + kJITZygoteCacheFile + ":") != path.npos;
135 }
136
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800137 private:
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700138 enum class DescriptorType {
139 kDEX,
140 kJIT,
141 };
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800142
143 // An arch-independent representation of JIT/dex debug descriptor.
144 struct Descriptor {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700145 DescriptorType type;
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700146 int version = 0;
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200147 uint32_t action_seqlock = 0; // incremented before and after any modification
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800148 uint64_t action_timestamp = 0; // CLOCK_MONOTONIC time of last action
149 uint64_t first_entry_addr = 0;
150 };
151
152 // An arch-independent representation of JIT/dex code entry.
153 struct CodeEntry {
154 uint64_t addr;
155 uint64_t symfile_addr;
156 uint64_t symfile_size;
157 uint64_t timestamp; // CLOCK_MONOTONIC time of last action
158 };
159
Yabin Cuic8571d42018-06-06 11:20:39 -0700160 struct Process {
161 pid_t pid = -1;
162 bool initialized = false;
163 bool died = false;
164 bool is_64bit = false;
Yabin Cuie5defe12022-03-23 15:55:50 -0700165 // remote addr of jit descriptor
166 uint64_t jit_descriptor_addr = 0;
167 // remote addr of dex descriptor
168 uint64_t dex_descriptor_addr = 0;
Yabin Cuic8571d42018-06-06 11:20:39 -0700169
170 // The state we know about the remote jit debug descriptor.
171 Descriptor last_jit_descriptor;
172 // The state we know about the remote dex debug descriptor.
173 Descriptor last_dex_descriptor;
Yabin Cui7f94b472020-08-03 21:11:32 +0000174
175 // memory space for /memfd:jit-zygote-cache
176 std::vector<std::pair<uint64_t, uint64_t>> jit_zygote_cache_ranges_;
Yabin Cuic8571d42018-06-06 11:20:39 -0700177 };
178
179 // The location of descriptors in libart.so.
180 struct DescriptorsLocation {
Yabin Cuie5defe12022-03-23 15:55:50 -0700181 bool is_64bit = false;
182 uint64_t jit_descriptor_addr = 0;
183 uint64_t dex_descriptor_addr = 0;
Yabin Cuic8571d42018-06-06 11:20:39 -0700184 };
185
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700186 bool ReadProcess(Process& process, std::vector<JITDebugInfo>* debug_info);
187 bool ReadDebugInfo(Process& process, Descriptor& new_descriptor,
188 std::vector<JITDebugInfo>* debug_info);
189 bool IsDescriptorChanged(Process& process, Descriptor& old_descriptor);
Yabin Cuic8571d42018-06-06 11:20:39 -0700190 bool InitializeProcess(Process& process);
Yabin Cuie5defe12022-03-23 15:55:50 -0700191 const DescriptorsLocation* GetDescriptorsLocation(const std::string& art_lib_path);
Yabin Cuic8571d42018-06-06 11:20:39 -0700192 bool ReadRemoteMem(Process& process, uint64_t remote_addr, uint64_t size, void* data);
193 bool ReadDescriptors(Process& process, Descriptor* jit_descriptor, Descriptor* dex_descriptor);
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700194 template <typename DescriptorT>
Yabin Cuie5defe12022-03-23 15:55:50 -0700195 bool ReadDescriptorsImpl(Process& process, Descriptor* jit_descriptor,
196 Descriptor* dex_descriptor);
197 template <typename DescriptorT>
198 bool ParseDescriptor(const DescriptorT& raw_descriptor, Descriptor* descriptor);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800199
Yabin Cuic8571d42018-06-06 11:20:39 -0700200 bool ReadNewCodeEntries(Process& process, const Descriptor& descriptor,
201 uint64_t last_action_timestamp, uint32_t read_entry_limit,
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800202 std::vector<CodeEntry>* new_code_entries);
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700203 template <typename CodeEntryT>
Yabin Cuic8571d42018-06-06 11:20:39 -0700204 bool ReadNewCodeEntriesImpl(Process& process, const Descriptor& descriptor,
205 uint64_t last_action_timestamp, uint32_t read_entry_limit,
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800206 std::vector<CodeEntry>* new_code_entries);
207
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700208 bool ReadJITCodeDebugInfo(Process& process, const std::vector<CodeEntry>& jit_entries,
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200209 std::vector<JITDebugInfo>* debug_info);
Yabin Cui7f94b472020-08-03 21:11:32 +0000210 TempSymFile* GetTempSymFile(Process& process, const CodeEntry& jit_entry);
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700211 void ReadDexFileDebugInfo(Process& process, const std::vector<CodeEntry>& dex_entries,
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200212 std::vector<JITDebugInfo>* debug_info);
Yabin Cui400892e2019-05-31 10:39:56 -0700213 bool AddDebugInfo(const std::vector<JITDebugInfo>& debug_info, bool sync_kernel_records);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800214
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700215 const std::string symfile_prefix_;
216 SymFileOption symfile_option_;
217 SyncOption sync_option_;
Yabin Cuic8571d42018-06-06 11:20:39 -0700218 IOEventRef read_event_ = nullptr;
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700219 debug_info_callback_t debug_info_callback_;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800220
Yabin Cuic8571d42018-06-06 11:20:39 -0700221 // Keys are pids of processes having libart.so, values show whether a process has been monitored.
222 std::unordered_map<pid_t, bool> pids_with_art_lib_;
223
224 // All monitored processes
225 std::unordered_map<pid_t, Process> processes_;
226 std::unordered_map<std::string, DescriptorsLocation> descriptors_location_cache_;
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700227
228 std::priority_queue<JITDebugInfo, std::vector<JITDebugInfo>, std::greater<JITDebugInfo>>
229 debug_info_q_;
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700230
231 // temporary files used to store jit symfiles created by the app process and the zygote process.
232 std::unique_ptr<TempSymFile> app_symfile_;
Yabin Cui7f94b472020-08-03 21:11:32 +0000233 std::unique_ptr<TempSymFile> zygote_symfile_;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800234};
235
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200236} // namespace simpleperf
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800237
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200238#endif // SIMPLE_PERF_JIT_DEBUG_READER_H_