blob: 4483ddf0b4947b9ac94abea8ca39c38addd1c40f [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";
Yabin Cui8b8ed0f2023-10-24 16:18:38 -070041inline constexpr const char* kDexFileInMemoryPrefix = "dexfile_in_memory";
Yabin Cui075dd182020-08-05 19:51:36 +000042
Yabin Cui42eb3d22023-10-25 11:59:09 -070043namespace JITDebugReader_impl {
44
45enum class DescriptorType {
46 kDEX,
47 kJIT,
48};
49
50// An arch-independent representation of JIT/dex debug descriptor.
51struct Descriptor {
52 DescriptorType type;
53 int version = 0;
54 uint32_t action_seqlock = 0; // incremented before and after any modification
55 uint64_t action_timestamp = 0; // CLOCK_MONOTONIC time of last action
56 uint64_t first_entry_addr = 0;
57};
58
59// An arch-independent representation of JIT/dex code entry.
60struct CodeEntry {
61 uint64_t addr;
62 uint64_t symfile_addr;
63 uint64_t symfile_size;
64 uint64_t timestamp; // CLOCK_MONOTONIC time of last action
65};
66
67struct Process {
68 pid_t pid = -1;
69 bool initialized = false;
70 bool died = false;
71 bool is_64bit = false;
72 // remote addr of jit descriptor
73 uint64_t jit_descriptor_addr = 0;
74 // remote addr of dex descriptor
75 uint64_t dex_descriptor_addr = 0;
76
77 // The state we know about the remote jit debug descriptor.
78 Descriptor last_jit_descriptor;
79 // The state we know about the remote dex debug descriptor.
80 Descriptor last_dex_descriptor;
81
82 // memory space for /memfd:jit-zygote-cache
83 std::vector<std::pair<uint64_t, uint64_t>> jit_zygote_cache_ranges_;
84};
85
86} // namespace JITDebugReader_impl
87
Yabin Cui5d5c01a2018-08-27 10:30:20 -070088// JITDebugInfo represents the debug info of a JITed Java method or a dex file.
89struct JITDebugInfo {
90 enum {
91 JIT_DEBUG_JIT_CODE,
92 JIT_DEBUG_DEX_FILE,
93 } type;
94 pid_t pid; // Process of the debug info
95 uint64_t timestamp; // Monotonic timestamp for the creation of the debug info
Yabin Cui8b8ed0f2023-10-24 16:18:38 -070096
Yabin Cui5d5c01a2018-08-27 10:30:20 -070097 union {
98 struct {
99 uint64_t jit_code_addr; // The start addr of the JITed code
100 uint64_t jit_code_len; // The end addr of the JITed code
101 };
102 uint64_t dex_file_offset; // The offset of the dex file in the file containing it
103 };
104 // For JITed code, it is the path of a temporary ELF file storing its debug info.
105 // For dex file, it is the path of the file containing the dex file.
106 std::string file_path;
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700107 uint64_t file_offset;
Yabin Cuic8571d42018-06-06 11:20:39 -0700108
Yabin Cui8b8ed0f2023-10-24 16:18:38 -0700109 // dex_file_map may be a dex file extracted in memory. On Android >= Q, ART may extract dex files
110 // in apk files directly into memory, and name it using prctl(). The kernel doesn't generate a
111 // new mmap record for it. So we need to dump it manually.
112 // Or dex_file_map may be a dex file created in memory. In that case, symbols are read from the
113 // dex file.
114 std::shared_ptr<ThreadMmap> dex_file_map;
115 std::vector<Symbol> symbols;
Yabin Cui400892e2019-05-31 10:39:56 -0700116
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700117 JITDebugInfo(pid_t pid, uint64_t timestamp, uint64_t jit_code_addr, uint64_t jit_code_len,
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700118 const std::string& file_path, uint64_t file_offset)
119 : type(JIT_DEBUG_JIT_CODE),
120 pid(pid),
121 timestamp(timestamp),
122 jit_code_addr(jit_code_addr),
123 jit_code_len(jit_code_len),
124 file_path(file_path),
125 file_offset(file_offset) {}
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800126
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700127 JITDebugInfo(pid_t pid, uint64_t timestamp, uint64_t dex_file_offset,
Yabin Cui8b8ed0f2023-10-24 16:18:38 -0700128 const std::string& file_path, const std::shared_ptr<ThreadMmap>& dex_file_map,
129 std::vector<Symbol> symbols)
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700130 : type(JIT_DEBUG_DEX_FILE),
131 pid(pid),
132 timestamp(timestamp),
133 dex_file_offset(dex_file_offset),
134 file_path(file_path),
135 file_offset(0),
Yabin Cui8b8ed0f2023-10-24 16:18:38 -0700136 dex_file_map(dex_file_map),
137 symbols(std::move(symbols)) {}
Yabin Cui2a53ff32018-05-21 17:37:00 -0700138
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200139 bool operator>(const JITDebugInfo& other) const { return timestamp > other.timestamp; }
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800140};
141
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700142class TempSymFile;
143
Yabin Cuic8571d42018-06-06 11:20:39 -0700144// JITDebugReader reads debug info of JIT code and dex files of processes using ART. The
145// corresponding debug interface in ART is at art/runtime/jit/debugger_interface.cc.
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800146class JITDebugReader {
147 public:
Yabin Cui42eb3d22023-10-25 11:59:09 -0700148 using Descriptor = JITDebugReader_impl::Descriptor;
149 using CodeEntry = JITDebugReader_impl::CodeEntry;
150 using Process = JITDebugReader_impl::Process;
151
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700152 enum class SymFileOption {
153 kDropSymFiles, // JIT symfiles are dropped after recording.
154 kKeepSymFiles, // JIT symfiles are kept after recording, usually for debug unwinding.
155 };
156
157 enum class SyncOption {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200158 kNoSync, // Don't sync debug info with records.
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700159 kSyncWithRecords, // Sync debug info with records based on monotonic timestamp.
160 };
161
162 // symfile_prefix: JITDebugReader creates temporary file to store symfiles for JIT code. Add this
163 // prefix to avoid conflicts.
164 JITDebugReader(const std::string& symfile_prefix, SymFileOption symfile_option,
165 SyncOption sync_option);
166
167 ~JITDebugReader();
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800168
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200169 bool SyncWithRecords() const { return sync_option_ == SyncOption::kSyncWithRecords; }
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700170
Yabin Cui8b8ed0f2023-10-24 16:18:38 -0700171 typedef std::function<bool(std::vector<JITDebugInfo>, bool)> debug_info_callback_t;
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700172 bool RegisterDebugInfoCallback(IOEventLoop* loop, const debug_info_callback_t& callback);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800173
Yabin Cuic8571d42018-06-06 11:20:39 -0700174 // There are two ways to select which processes to monitor. One is using MonitorProcess(), the
175 // other is finding all processes having libart.so using records.
176 bool MonitorProcess(pid_t pid);
177 bool UpdateRecord(const Record* record);
178
179 // Read new debug info from all monitored processes.
180 bool ReadAllProcesses();
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700181 // Read new debug info from one process.
182 bool ReadProcess(pid_t pid);
183
184 // Flush all debug info registered before timestamp.
185 bool FlushDebugInfo(uint64_t timestamp);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800186
Yabin Cui9ba4d942020-09-08 16:12:46 -0700187 static bool IsPathInJITSymFile(const std::string& path) {
188 return path.find(std::string("_") + kJITAppCacheFile + ":") != path.npos ||
189 path.find(std::string("_") + kJITZygoteCacheFile + ":") != path.npos;
190 }
191
Yabin Cui42eb3d22023-10-25 11:59:09 -0700192 // exported for testing
193 void ReadDexFileDebugInfo(Process& process, const std::vector<CodeEntry>& dex_entries,
194 std::vector<JITDebugInfo>* debug_info);
195
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800196 private:
Yabin Cuic8571d42018-06-06 11:20:39 -0700197 // The location of descriptors in libart.so.
198 struct DescriptorsLocation {
Yabin Cuie5defe12022-03-23 15:55:50 -0700199 bool is_64bit = false;
200 uint64_t jit_descriptor_addr = 0;
201 uint64_t dex_descriptor_addr = 0;
Yabin Cuic8571d42018-06-06 11:20:39 -0700202 };
203
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700204 bool ReadProcess(Process& process, std::vector<JITDebugInfo>* debug_info);
205 bool ReadDebugInfo(Process& process, Descriptor& new_descriptor,
206 std::vector<JITDebugInfo>* debug_info);
207 bool IsDescriptorChanged(Process& process, Descriptor& old_descriptor);
Yabin Cuic8571d42018-06-06 11:20:39 -0700208 bool InitializeProcess(Process& process);
Yabin Cuie5defe12022-03-23 15:55:50 -0700209 const DescriptorsLocation* GetDescriptorsLocation(const std::string& art_lib_path);
Yabin Cuic8571d42018-06-06 11:20:39 -0700210 bool ReadRemoteMem(Process& process, uint64_t remote_addr, uint64_t size, void* data);
211 bool ReadDescriptors(Process& process, Descriptor* jit_descriptor, Descriptor* dex_descriptor);
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700212 template <typename DescriptorT>
Yabin Cuie5defe12022-03-23 15:55:50 -0700213 bool ReadDescriptorsImpl(Process& process, Descriptor* jit_descriptor,
214 Descriptor* dex_descriptor);
215 template <typename DescriptorT>
216 bool ParseDescriptor(const DescriptorT& raw_descriptor, Descriptor* descriptor);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800217
Yabin Cuic8571d42018-06-06 11:20:39 -0700218 bool ReadNewCodeEntries(Process& process, const Descriptor& descriptor,
219 uint64_t last_action_timestamp, uint32_t read_entry_limit,
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800220 std::vector<CodeEntry>* new_code_entries);
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700221 template <typename CodeEntryT>
Yabin Cuic8571d42018-06-06 11:20:39 -0700222 bool ReadNewCodeEntriesImpl(Process& process, const Descriptor& descriptor,
223 uint64_t last_action_timestamp, uint32_t read_entry_limit,
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800224 std::vector<CodeEntry>* new_code_entries);
225
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700226 bool ReadJITCodeDebugInfo(Process& process, const std::vector<CodeEntry>& jit_entries,
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200227 std::vector<JITDebugInfo>* debug_info);
Yabin Cui7f94b472020-08-03 21:11:32 +0000228 TempSymFile* GetTempSymFile(Process& process, const CodeEntry& jit_entry);
Yabin Cui8b8ed0f2023-10-24 16:18:38 -0700229 std::vector<Symbol> ReadDexFileSymbolsInMemory(Process& process, uint64_t addr, uint64_t size);
230 bool AddDebugInfo(std::vector<JITDebugInfo> debug_info, bool sync_kernel_records);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800231
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700232 const std::string symfile_prefix_;
233 SymFileOption symfile_option_;
234 SyncOption sync_option_;
Yabin Cuic8571d42018-06-06 11:20:39 -0700235 IOEventRef read_event_ = nullptr;
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700236 debug_info_callback_t debug_info_callback_;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800237
Yabin Cuic8571d42018-06-06 11:20:39 -0700238 // Keys are pids of processes having libart.so, values show whether a process has been monitored.
239 std::unordered_map<pid_t, bool> pids_with_art_lib_;
240
241 // All monitored processes
242 std::unordered_map<pid_t, Process> processes_;
243 std::unordered_map<std::string, DescriptorsLocation> descriptors_location_cache_;
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700244
245 std::priority_queue<JITDebugInfo, std::vector<JITDebugInfo>, std::greater<JITDebugInfo>>
246 debug_info_q_;
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700247
248 // temporary files used to store jit symfiles created by the app process and the zygote process.
249 std::unique_ptr<TempSymFile> app_symfile_;
Yabin Cui7f94b472020-08-03 21:11:32 +0000250 std::unique_ptr<TempSymFile> zygote_symfile_;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800251};
252
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200253} // namespace simpleperf
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800254
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200255#endif // SIMPLE_PERF_JIT_DEBUG_READER_H_