1 /* 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> 24 #include <queue> 25 #include <stack> 26 #include <unordered_map> 27 #include <unordered_set> 28 #include <vector> 29 30 #include <android-base/file.h> 31 #include <android-base/logging.h> 32 33 #include "IOEventLoop.h" 34 #include "environment.h" 35 #include "record.h" 36 37 namespace simpleperf { 38 39 inline constexpr const char* kJITAppCacheFile = "jit_app_cache"; 40 inline constexpr const char* kJITZygoteCacheFile = "jit_zygote_cache"; 41 42 // JITDebugInfo represents the debug info of a JITed Java method or a dex file. 43 struct 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; 60 uint64_t file_offset; 61 62 // 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 JITDebugInfoJITDebugInfo67 JITDebugInfo(pid_t pid, uint64_t timestamp, uint64_t jit_code_addr, uint64_t jit_code_len, 68 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) {} 76 JITDebugInfoJITDebugInfo77 JITDebugInfo(pid_t pid, uint64_t timestamp, uint64_t dex_file_offset, 78 const std::string& file_path, 79 const std::shared_ptr<ThreadMmap>& extracted_dex_file_map) 80 : 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) {} 87 88 bool operator>(const JITDebugInfo& other) const { return timestamp > other.timestamp; } 89 }; 90 91 class TempSymFile; 92 93 // 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. 95 class JITDebugReader { 96 public: 97 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 { 103 kNoSync, // Don't sync debug info with records. 104 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(); 113 SyncWithRecords()114 bool SyncWithRecords() const { return sync_option_ == SyncOption::kSyncWithRecords; } 115 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); 118 119 // 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(); 126 // 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); 131 IsPathInJITSymFile(const std::string & path)132 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 137 private: 138 enum class DescriptorType { 139 kDEX, 140 kJIT, 141 }; 142 143 // An arch-independent representation of JIT/dex debug descriptor. 144 struct Descriptor { 145 DescriptorType type; 146 int version = 0; 147 uint32_t action_seqlock = 0; // incremented before and after any modification 148 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 160 struct Process { 161 pid_t pid = -1; 162 bool initialized = false; 163 bool died = false; 164 bool is_64bit = false; 165 // 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; 169 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; 174 175 // memory space for /memfd:jit-zygote-cache 176 std::vector<std::pair<uint64_t, uint64_t>> jit_zygote_cache_ranges_; 177 }; 178 179 // The location of descriptors in libart.so. 180 struct DescriptorsLocation { 181 bool is_64bit = false; 182 uint64_t jit_descriptor_addr = 0; 183 uint64_t dex_descriptor_addr = 0; 184 }; 185 186 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); 190 bool InitializeProcess(Process& process); 191 const DescriptorsLocation* GetDescriptorsLocation(const std::string& art_lib_path); 192 bool ReadRemoteMem(Process& process, uint64_t remote_addr, uint64_t size, void* data); 193 bool ReadDescriptors(Process& process, Descriptor* jit_descriptor, Descriptor* dex_descriptor); 194 template <typename DescriptorT> 195 bool ReadDescriptorsImpl(Process& process, Descriptor* jit_descriptor, 196 Descriptor* dex_descriptor); 197 template <typename DescriptorT> 198 bool ParseDescriptor(const DescriptorT& raw_descriptor, Descriptor* descriptor); 199 200 bool ReadNewCodeEntries(Process& process, const Descriptor& descriptor, 201 uint64_t last_action_timestamp, uint32_t read_entry_limit, 202 std::vector<CodeEntry>* new_code_entries); 203 template <typename CodeEntryT> 204 bool ReadNewCodeEntriesImpl(Process& process, const Descriptor& descriptor, 205 uint64_t last_action_timestamp, uint32_t read_entry_limit, 206 std::vector<CodeEntry>* new_code_entries); 207 208 bool ReadJITCodeDebugInfo(Process& process, const std::vector<CodeEntry>& jit_entries, 209 std::vector<JITDebugInfo>* debug_info); 210 TempSymFile* GetTempSymFile(Process& process, const CodeEntry& jit_entry); 211 void ReadDexFileDebugInfo(Process& process, const std::vector<CodeEntry>& dex_entries, 212 std::vector<JITDebugInfo>* debug_info); 213 bool AddDebugInfo(const std::vector<JITDebugInfo>& debug_info, bool sync_kernel_records); 214 215 const std::string symfile_prefix_; 216 SymFileOption symfile_option_; 217 SyncOption sync_option_; 218 IOEventRef read_event_ = nullptr; 219 debug_info_callback_t debug_info_callback_; 220 221 // 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_; 227 228 std::priority_queue<JITDebugInfo, std::vector<JITDebugInfo>, std::greater<JITDebugInfo>> 229 debug_info_q_; 230 231 // temporary files used to store jit symfiles created by the app process and the zygote process. 232 std::unique_ptr<TempSymFile> app_symfile_; 233 std::unique_ptr<TempSymFile> zygote_symfile_; 234 }; 235 236 } // namespace simpleperf 237 238 #endif // SIMPLE_PERF_JIT_DEBUG_READER_H_ 239