xref: /aosp_15_r20/system/extras/simpleperf/JITDebugReader.h (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker #ifndef SIMPLE_PERF_JIT_DEBUG_READER_H_
18*288bf522SAndroid Build Coastguard Worker #define SIMPLE_PERF_JIT_DEBUG_READER_H_
19*288bf522SAndroid Build Coastguard Worker 
20*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
21*288bf522SAndroid Build Coastguard Worker 
22*288bf522SAndroid Build Coastguard Worker #include <functional>
23*288bf522SAndroid Build Coastguard Worker #include <memory>
24*288bf522SAndroid Build Coastguard Worker #include <queue>
25*288bf522SAndroid Build Coastguard Worker #include <stack>
26*288bf522SAndroid Build Coastguard Worker #include <unordered_map>
27*288bf522SAndroid Build Coastguard Worker #include <unordered_set>
28*288bf522SAndroid Build Coastguard Worker #include <vector>
29*288bf522SAndroid Build Coastguard Worker 
30*288bf522SAndroid Build Coastguard Worker #include <android-base/file.h>
31*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
32*288bf522SAndroid Build Coastguard Worker 
33*288bf522SAndroid Build Coastguard Worker #include "IOEventLoop.h"
34*288bf522SAndroid Build Coastguard Worker #include "environment.h"
35*288bf522SAndroid Build Coastguard Worker #include "record.h"
36*288bf522SAndroid Build Coastguard Worker 
37*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
38*288bf522SAndroid Build Coastguard Worker 
39*288bf522SAndroid Build Coastguard Worker inline constexpr const char* kJITAppCacheFile = "jit_app_cache";
40*288bf522SAndroid Build Coastguard Worker inline constexpr const char* kJITZygoteCacheFile = "jit_zygote_cache";
41*288bf522SAndroid Build Coastguard Worker inline constexpr const char* kDexFileInMemoryPrefix = "dexfile_in_memory";
42*288bf522SAndroid Build Coastguard Worker 
43*288bf522SAndroid Build Coastguard Worker namespace JITDebugReader_impl {
44*288bf522SAndroid Build Coastguard Worker 
45*288bf522SAndroid Build Coastguard Worker enum class DescriptorType {
46*288bf522SAndroid Build Coastguard Worker   kDEX,
47*288bf522SAndroid Build Coastguard Worker   kJIT,
48*288bf522SAndroid Build Coastguard Worker };
49*288bf522SAndroid Build Coastguard Worker 
50*288bf522SAndroid Build Coastguard Worker // An arch-independent representation of JIT/dex debug descriptor.
51*288bf522SAndroid Build Coastguard Worker struct Descriptor {
52*288bf522SAndroid Build Coastguard Worker   DescriptorType type;
53*288bf522SAndroid Build Coastguard Worker   int version = 0;
54*288bf522SAndroid Build Coastguard Worker   uint32_t action_seqlock = 0;    // incremented before and after any modification
55*288bf522SAndroid Build Coastguard Worker   uint64_t action_timestamp = 0;  // CLOCK_MONOTONIC time of last action
56*288bf522SAndroid Build Coastguard Worker   uint64_t first_entry_addr = 0;
57*288bf522SAndroid Build Coastguard Worker };
58*288bf522SAndroid Build Coastguard Worker 
59*288bf522SAndroid Build Coastguard Worker // An arch-independent representation of JIT/dex code entry.
60*288bf522SAndroid Build Coastguard Worker struct CodeEntry {
61*288bf522SAndroid Build Coastguard Worker   uint64_t addr;
62*288bf522SAndroid Build Coastguard Worker   uint64_t symfile_addr;
63*288bf522SAndroid Build Coastguard Worker   uint64_t symfile_size;
64*288bf522SAndroid Build Coastguard Worker   uint64_t timestamp;  // CLOCK_MONOTONIC time of last action
65*288bf522SAndroid Build Coastguard Worker };
66*288bf522SAndroid Build Coastguard Worker 
67*288bf522SAndroid Build Coastguard Worker struct Process {
68*288bf522SAndroid Build Coastguard Worker   pid_t pid = -1;
69*288bf522SAndroid Build Coastguard Worker   bool initialized = false;
70*288bf522SAndroid Build Coastguard Worker   bool died = false;
71*288bf522SAndroid Build Coastguard Worker   bool is_64bit = false;
72*288bf522SAndroid Build Coastguard Worker   // remote addr of jit descriptor
73*288bf522SAndroid Build Coastguard Worker   uint64_t jit_descriptor_addr = 0;
74*288bf522SAndroid Build Coastguard Worker   // remote addr of dex descriptor
75*288bf522SAndroid Build Coastguard Worker   uint64_t dex_descriptor_addr = 0;
76*288bf522SAndroid Build Coastguard Worker 
77*288bf522SAndroid Build Coastguard Worker   // The state we know about the remote jit debug descriptor.
78*288bf522SAndroid Build Coastguard Worker   Descriptor last_jit_descriptor;
79*288bf522SAndroid Build Coastguard Worker   // The state we know about the remote dex debug descriptor.
80*288bf522SAndroid Build Coastguard Worker   Descriptor last_dex_descriptor;
81*288bf522SAndroid Build Coastguard Worker 
82*288bf522SAndroid Build Coastguard Worker   // memory space for /memfd:jit-zygote-cache
83*288bf522SAndroid Build Coastguard Worker   std::vector<std::pair<uint64_t, uint64_t>> jit_zygote_cache_ranges_;
84*288bf522SAndroid Build Coastguard Worker };
85*288bf522SAndroid Build Coastguard Worker 
86*288bf522SAndroid Build Coastguard Worker }  // namespace JITDebugReader_impl
87*288bf522SAndroid Build Coastguard Worker 
88*288bf522SAndroid Build Coastguard Worker // JITDebugInfo represents the debug info of a JITed Java method or a dex file.
89*288bf522SAndroid Build Coastguard Worker struct JITDebugInfo {
90*288bf522SAndroid Build Coastguard Worker   enum {
91*288bf522SAndroid Build Coastguard Worker     JIT_DEBUG_JIT_CODE,
92*288bf522SAndroid Build Coastguard Worker     JIT_DEBUG_DEX_FILE,
93*288bf522SAndroid Build Coastguard Worker   } type;
94*288bf522SAndroid Build Coastguard Worker   pid_t pid;           // Process of the debug info
95*288bf522SAndroid Build Coastguard Worker   uint64_t timestamp;  // Monotonic timestamp for the creation of the debug info
96*288bf522SAndroid Build Coastguard Worker 
97*288bf522SAndroid Build Coastguard Worker   union {
98*288bf522SAndroid Build Coastguard Worker     struct {
99*288bf522SAndroid Build Coastguard Worker       uint64_t jit_code_addr;  // The start addr of the JITed code
100*288bf522SAndroid Build Coastguard Worker       uint64_t jit_code_len;   // The end addr of the JITed code
101*288bf522SAndroid Build Coastguard Worker     };
102*288bf522SAndroid Build Coastguard Worker     uint64_t dex_file_offset;  // The offset of the dex file in the file containing it
103*288bf522SAndroid Build Coastguard Worker   };
104*288bf522SAndroid Build Coastguard Worker   // For JITed code, it is the path of a temporary ELF file storing its debug info.
105*288bf522SAndroid Build Coastguard Worker   // For dex file, it is the path of the file containing the dex file.
106*288bf522SAndroid Build Coastguard Worker   std::string file_path;
107*288bf522SAndroid Build Coastguard Worker   uint64_t file_offset;
108*288bf522SAndroid Build Coastguard Worker 
109*288bf522SAndroid Build Coastguard Worker   // dex_file_map may be a dex file extracted in memory. On Android >= Q, ART may extract dex files
110*288bf522SAndroid Build Coastguard Worker   // in apk files directly into memory, and name it using prctl(). The kernel doesn't generate a
111*288bf522SAndroid Build Coastguard Worker   // new mmap record for it. So we need to dump it manually.
112*288bf522SAndroid Build Coastguard Worker   // Or dex_file_map may be a dex file created in memory. In that case, symbols are read from the
113*288bf522SAndroid Build Coastguard Worker   // dex file.
114*288bf522SAndroid Build Coastguard Worker   std::shared_ptr<ThreadMmap> dex_file_map;
115*288bf522SAndroid Build Coastguard Worker   std::vector<Symbol> symbols;
116*288bf522SAndroid Build Coastguard Worker 
JITDebugInfoJITDebugInfo117*288bf522SAndroid Build Coastguard Worker   JITDebugInfo(pid_t pid, uint64_t timestamp, uint64_t jit_code_addr, uint64_t jit_code_len,
118*288bf522SAndroid Build Coastguard Worker                const std::string& file_path, uint64_t file_offset)
119*288bf522SAndroid Build Coastguard Worker       : type(JIT_DEBUG_JIT_CODE),
120*288bf522SAndroid Build Coastguard Worker         pid(pid),
121*288bf522SAndroid Build Coastguard Worker         timestamp(timestamp),
122*288bf522SAndroid Build Coastguard Worker         jit_code_addr(jit_code_addr),
123*288bf522SAndroid Build Coastguard Worker         jit_code_len(jit_code_len),
124*288bf522SAndroid Build Coastguard Worker         file_path(file_path),
125*288bf522SAndroid Build Coastguard Worker         file_offset(file_offset) {}
126*288bf522SAndroid Build Coastguard Worker 
JITDebugInfoJITDebugInfo127*288bf522SAndroid Build Coastguard Worker   JITDebugInfo(pid_t pid, uint64_t timestamp, uint64_t dex_file_offset,
128*288bf522SAndroid Build Coastguard Worker                const std::string& file_path, const std::shared_ptr<ThreadMmap>& dex_file_map,
129*288bf522SAndroid Build Coastguard Worker                std::vector<Symbol> symbols)
130*288bf522SAndroid Build Coastguard Worker       : type(JIT_DEBUG_DEX_FILE),
131*288bf522SAndroid Build Coastguard Worker         pid(pid),
132*288bf522SAndroid Build Coastguard Worker         timestamp(timestamp),
133*288bf522SAndroid Build Coastguard Worker         dex_file_offset(dex_file_offset),
134*288bf522SAndroid Build Coastguard Worker         file_path(file_path),
135*288bf522SAndroid Build Coastguard Worker         file_offset(0),
136*288bf522SAndroid Build Coastguard Worker         dex_file_map(dex_file_map),
137*288bf522SAndroid Build Coastguard Worker         symbols(std::move(symbols)) {}
138*288bf522SAndroid Build Coastguard Worker 
139*288bf522SAndroid Build Coastguard Worker   bool operator>(const JITDebugInfo& other) const { return timestamp > other.timestamp; }
140*288bf522SAndroid Build Coastguard Worker };
141*288bf522SAndroid Build Coastguard Worker 
142*288bf522SAndroid Build Coastguard Worker class TempSymFile;
143*288bf522SAndroid Build Coastguard Worker 
144*288bf522SAndroid Build Coastguard Worker // JITDebugReader reads debug info of JIT code and dex files of processes using ART. The
145*288bf522SAndroid Build Coastguard Worker // corresponding debug interface in ART is at art/runtime/jit/debugger_interface.cc.
146*288bf522SAndroid Build Coastguard Worker class JITDebugReader {
147*288bf522SAndroid Build Coastguard Worker  public:
148*288bf522SAndroid Build Coastguard Worker   using Descriptor = JITDebugReader_impl::Descriptor;
149*288bf522SAndroid Build Coastguard Worker   using CodeEntry = JITDebugReader_impl::CodeEntry;
150*288bf522SAndroid Build Coastguard Worker   using Process = JITDebugReader_impl::Process;
151*288bf522SAndroid Build Coastguard Worker 
152*288bf522SAndroid Build Coastguard Worker   enum class SymFileOption {
153*288bf522SAndroid Build Coastguard Worker     kDropSymFiles,  // JIT symfiles are dropped after recording.
154*288bf522SAndroid Build Coastguard Worker     kKeepSymFiles,  // JIT symfiles are kept after recording, usually for debug unwinding.
155*288bf522SAndroid Build Coastguard Worker   };
156*288bf522SAndroid Build Coastguard Worker 
157*288bf522SAndroid Build Coastguard Worker   enum class SyncOption {
158*288bf522SAndroid Build Coastguard Worker     kNoSync,           // Don't sync debug info with records.
159*288bf522SAndroid Build Coastguard Worker     kSyncWithRecords,  // Sync debug info with records based on monotonic timestamp.
160*288bf522SAndroid Build Coastguard Worker   };
161*288bf522SAndroid Build Coastguard Worker 
162*288bf522SAndroid Build Coastguard Worker   // symfile_prefix: JITDebugReader creates temporary file to store symfiles for JIT code. Add this
163*288bf522SAndroid Build Coastguard Worker   //                 prefix to avoid conflicts.
164*288bf522SAndroid Build Coastguard Worker   JITDebugReader(const std::string& symfile_prefix, SymFileOption symfile_option,
165*288bf522SAndroid Build Coastguard Worker                  SyncOption sync_option);
166*288bf522SAndroid Build Coastguard Worker 
167*288bf522SAndroid Build Coastguard Worker   ~JITDebugReader();
168*288bf522SAndroid Build Coastguard Worker 
SyncWithRecords()169*288bf522SAndroid Build Coastguard Worker   bool SyncWithRecords() const { return sync_option_ == SyncOption::kSyncWithRecords; }
170*288bf522SAndroid Build Coastguard Worker 
171*288bf522SAndroid Build Coastguard Worker   typedef std::function<bool(std::vector<JITDebugInfo>, bool)> debug_info_callback_t;
172*288bf522SAndroid Build Coastguard Worker   bool RegisterDebugInfoCallback(IOEventLoop* loop, const debug_info_callback_t& callback);
173*288bf522SAndroid Build Coastguard Worker 
174*288bf522SAndroid Build Coastguard Worker   // There are two ways to select which processes to monitor. One is using MonitorProcess(), the
175*288bf522SAndroid Build Coastguard Worker   // other is finding all processes having libart.so using records.
176*288bf522SAndroid Build Coastguard Worker   bool MonitorProcess(pid_t pid);
177*288bf522SAndroid Build Coastguard Worker   bool UpdateRecord(const Record* record);
178*288bf522SAndroid Build Coastguard Worker 
179*288bf522SAndroid Build Coastguard Worker   // Read new debug info from all monitored processes.
180*288bf522SAndroid Build Coastguard Worker   bool ReadAllProcesses();
181*288bf522SAndroid Build Coastguard Worker   // Read new debug info from one process.
182*288bf522SAndroid Build Coastguard Worker   bool ReadProcess(pid_t pid);
183*288bf522SAndroid Build Coastguard Worker 
184*288bf522SAndroid Build Coastguard Worker   // Flush all debug info registered before timestamp.
185*288bf522SAndroid Build Coastguard Worker   bool FlushDebugInfo(uint64_t timestamp);
186*288bf522SAndroid Build Coastguard Worker 
IsPathInJITSymFile(const std::string & path)187*288bf522SAndroid Build Coastguard Worker   static bool IsPathInJITSymFile(const std::string& path) {
188*288bf522SAndroid Build Coastguard Worker     return path.find(std::string("_") + kJITAppCacheFile + ":") != path.npos ||
189*288bf522SAndroid Build Coastguard Worker            path.find(std::string("_") + kJITZygoteCacheFile + ":") != path.npos;
190*288bf522SAndroid Build Coastguard Worker   }
191*288bf522SAndroid Build Coastguard Worker 
192*288bf522SAndroid Build Coastguard Worker   // exported for testing
193*288bf522SAndroid Build Coastguard Worker   void ReadDexFileDebugInfo(Process& process, const std::vector<CodeEntry>& dex_entries,
194*288bf522SAndroid Build Coastguard Worker                             std::vector<JITDebugInfo>* debug_info);
195*288bf522SAndroid Build Coastguard Worker 
196*288bf522SAndroid Build Coastguard Worker  private:
197*288bf522SAndroid Build Coastguard Worker   // The location of descriptors in libart.so.
198*288bf522SAndroid Build Coastguard Worker   struct DescriptorsLocation {
199*288bf522SAndroid Build Coastguard Worker     bool is_64bit = false;
200*288bf522SAndroid Build Coastguard Worker     uint64_t jit_descriptor_addr = 0;
201*288bf522SAndroid Build Coastguard Worker     uint64_t dex_descriptor_addr = 0;
202*288bf522SAndroid Build Coastguard Worker   };
203*288bf522SAndroid Build Coastguard Worker 
204*288bf522SAndroid Build Coastguard Worker   bool ReadProcess(Process& process, std::vector<JITDebugInfo>* debug_info);
205*288bf522SAndroid Build Coastguard Worker   bool ReadDebugInfo(Process& process, Descriptor& new_descriptor,
206*288bf522SAndroid Build Coastguard Worker                      std::vector<JITDebugInfo>* debug_info);
207*288bf522SAndroid Build Coastguard Worker   bool IsDescriptorChanged(Process& process, Descriptor& old_descriptor);
208*288bf522SAndroid Build Coastguard Worker   bool InitializeProcess(Process& process);
209*288bf522SAndroid Build Coastguard Worker   const DescriptorsLocation* GetDescriptorsLocation(const std::string& art_lib_path);
210*288bf522SAndroid Build Coastguard Worker   bool ReadRemoteMem(Process& process, uint64_t remote_addr, uint64_t size, void* data);
211*288bf522SAndroid Build Coastguard Worker   bool ReadDescriptors(Process& process, Descriptor* jit_descriptor, Descriptor* dex_descriptor);
212*288bf522SAndroid Build Coastguard Worker   template <typename DescriptorT>
213*288bf522SAndroid Build Coastguard Worker   bool ReadDescriptorsImpl(Process& process, Descriptor* jit_descriptor,
214*288bf522SAndroid Build Coastguard Worker                            Descriptor* dex_descriptor);
215*288bf522SAndroid Build Coastguard Worker   template <typename DescriptorT>
216*288bf522SAndroid Build Coastguard Worker   bool ParseDescriptor(const DescriptorT& raw_descriptor, Descriptor* descriptor);
217*288bf522SAndroid Build Coastguard Worker 
218*288bf522SAndroid Build Coastguard Worker   bool ReadNewCodeEntries(Process& process, const Descriptor& descriptor,
219*288bf522SAndroid Build Coastguard Worker                           uint64_t last_action_timestamp, uint32_t read_entry_limit,
220*288bf522SAndroid Build Coastguard Worker                           std::vector<CodeEntry>* new_code_entries);
221*288bf522SAndroid Build Coastguard Worker   template <typename CodeEntryT>
222*288bf522SAndroid Build Coastguard Worker   bool ReadNewCodeEntriesImpl(Process& process, const Descriptor& descriptor,
223*288bf522SAndroid Build Coastguard Worker                               uint64_t last_action_timestamp, uint32_t read_entry_limit,
224*288bf522SAndroid Build Coastguard Worker                               std::vector<CodeEntry>* new_code_entries);
225*288bf522SAndroid Build Coastguard Worker 
226*288bf522SAndroid Build Coastguard Worker   bool ReadJITCodeDebugInfo(Process& process, const std::vector<CodeEntry>& jit_entries,
227*288bf522SAndroid Build Coastguard Worker                             std::vector<JITDebugInfo>* debug_info);
228*288bf522SAndroid Build Coastguard Worker   TempSymFile* GetTempSymFile(Process& process, const CodeEntry& jit_entry);
229*288bf522SAndroid Build Coastguard Worker   std::vector<Symbol> ReadDexFileSymbolsInMemory(Process& process, uint64_t addr, uint64_t size);
230*288bf522SAndroid Build Coastguard Worker   bool AddDebugInfo(std::vector<JITDebugInfo> debug_info, bool sync_kernel_records);
231*288bf522SAndroid Build Coastguard Worker 
232*288bf522SAndroid Build Coastguard Worker   const std::string symfile_prefix_;
233*288bf522SAndroid Build Coastguard Worker   SymFileOption symfile_option_;
234*288bf522SAndroid Build Coastguard Worker   SyncOption sync_option_;
235*288bf522SAndroid Build Coastguard Worker   IOEventRef read_event_ = nullptr;
236*288bf522SAndroid Build Coastguard Worker   debug_info_callback_t debug_info_callback_;
237*288bf522SAndroid Build Coastguard Worker 
238*288bf522SAndroid Build Coastguard Worker   // Keys are pids of processes having libart.so, values show whether a process has been monitored.
239*288bf522SAndroid Build Coastguard Worker   std::unordered_map<pid_t, bool> pids_with_art_lib_;
240*288bf522SAndroid Build Coastguard Worker 
241*288bf522SAndroid Build Coastguard Worker   // All monitored processes
242*288bf522SAndroid Build Coastguard Worker   std::unordered_map<pid_t, Process> processes_;
243*288bf522SAndroid Build Coastguard Worker   std::unordered_map<std::string, DescriptorsLocation> descriptors_location_cache_;
244*288bf522SAndroid Build Coastguard Worker 
245*288bf522SAndroid Build Coastguard Worker   std::priority_queue<JITDebugInfo, std::vector<JITDebugInfo>, std::greater<JITDebugInfo>>
246*288bf522SAndroid Build Coastguard Worker       debug_info_q_;
247*288bf522SAndroid Build Coastguard Worker 
248*288bf522SAndroid Build Coastguard Worker   // temporary files used to store jit symfiles created by the app process and the zygote process.
249*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<TempSymFile> app_symfile_;
250*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<TempSymFile> zygote_symfile_;
251*288bf522SAndroid Build Coastguard Worker };
252*288bf522SAndroid Build Coastguard Worker 
253*288bf522SAndroid Build Coastguard Worker }  // namespace simpleperf
254*288bf522SAndroid Build Coastguard Worker 
255*288bf522SAndroid Build Coastguard Worker #endif  // SIMPLE_PERF_JIT_DEBUG_READER_H_
256