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 "environment.h" 34 #include "IOEventLoop.h" 35 #include "record.h" 36 37 namespace simpleperf { 38 39 // JITDebugInfo represents the debug info of a JITed Java method or a dex file. 40 struct JITDebugInfo { 41 enum { 42 JIT_DEBUG_JIT_CODE, 43 JIT_DEBUG_DEX_FILE, 44 } type; 45 pid_t pid; // Process of the debug info 46 uint64_t timestamp; // Monotonic timestamp for the creation of the debug info 47 union { 48 struct { 49 uint64_t jit_code_addr; // The start addr of the JITed code 50 uint64_t jit_code_len; // The end addr of the JITed code 51 }; 52 uint64_t dex_file_offset; // The offset of the dex file in the file containing it 53 }; 54 // For JITed code, it is the path of a temporary ELF file storing its debug info. 55 // For dex file, it is the path of the file containing the dex file. 56 std::string file_path; 57 58 // The map for dex file extracted in memory. On Android Q, ART extracts dex files in apk files 59 // directly into memory, and names it using prctl(). The kernel doesn't generate a new mmap 60 // record for it. So we need to dump it manually. 61 std::shared_ptr<ThreadMmap> extracted_dex_file_map; 62 JITDebugInfoJITDebugInfo63 JITDebugInfo(pid_t pid, uint64_t timestamp, uint64_t jit_code_addr, uint64_t jit_code_len, 64 const std::string& file_path) 65 : type(JIT_DEBUG_JIT_CODE), pid(pid), timestamp(timestamp), jit_code_addr(jit_code_addr), 66 jit_code_len(jit_code_len), file_path(file_path) {} 67 JITDebugInfoJITDebugInfo68 JITDebugInfo(pid_t pid, uint64_t timestamp, uint64_t dex_file_offset, 69 const std::string& file_path, 70 const std::shared_ptr<ThreadMmap>& extracted_dex_file_map) 71 : type(JIT_DEBUG_DEX_FILE), pid(pid), timestamp(timestamp), dex_file_offset(dex_file_offset), 72 file_path(file_path), extracted_dex_file_map(extracted_dex_file_map) {} 73 74 bool operator>(const JITDebugInfo& other) const { 75 return timestamp > other.timestamp; 76 } 77 }; 78 79 // JITDebugReader reads debug info of JIT code and dex files of processes using ART. The 80 // corresponding debug interface in ART is at art/runtime/jit/debugger_interface.cc. 81 class JITDebugReader { 82 public: 83 // keep_symfiles: whether to keep dumped JIT debug info files after recording. Usually they 84 // are only kept for debug unwinding. 85 // sync_with_records: If true, sync debug info with records based on monotonic timestamp. 86 // Otherwise, save debug info whenever they are added. JITDebugReader(bool keep_symfiles,bool sync_with_records)87 JITDebugReader(bool keep_symfiles, bool sync_with_records) 88 : keep_symfiles_(keep_symfiles), sync_with_records_(sync_with_records) {} 89 SyncWithRecords()90 bool SyncWithRecords() const { 91 return sync_with_records_; 92 } 93 94 typedef std::function<bool(const std::vector<JITDebugInfo>&, bool)> debug_info_callback_t; 95 bool RegisterDebugInfoCallback(IOEventLoop* loop, const debug_info_callback_t& callback); 96 97 // There are two ways to select which processes to monitor. One is using MonitorProcess(), the 98 // other is finding all processes having libart.so using records. 99 bool MonitorProcess(pid_t pid); 100 bool UpdateRecord(const Record* record); 101 102 // Read new debug info from all monitored processes. 103 bool ReadAllProcesses(); 104 // Read new debug info from one process. 105 bool ReadProcess(pid_t pid); 106 107 // Flush all debug info registered before timestamp. 108 bool FlushDebugInfo(uint64_t timestamp); 109 110 private: 111 112 // An arch-independent representation of JIT/dex debug descriptor. 113 struct Descriptor { 114 int version = 0; 115 uint32_t action_seqlock = 0; // incremented before and after any modification 116 uint64_t action_timestamp = 0; // CLOCK_MONOTONIC time of last action 117 uint64_t first_entry_addr = 0; 118 }; 119 120 // An arch-independent representation of JIT/dex code entry. 121 struct CodeEntry { 122 uint64_t addr; 123 uint64_t symfile_addr; 124 uint64_t symfile_size; 125 uint64_t timestamp; // CLOCK_MONOTONIC time of last action 126 }; 127 128 struct Process { 129 pid_t pid = -1; 130 bool initialized = false; 131 bool died = false; 132 bool is_64bit = false; 133 // The jit descriptor and dex descriptor can be read in one process_vm_readv() call. 134 uint64_t descriptors_addr = 0; 135 uint64_t descriptors_size = 0; 136 // offset relative to descriptors_addr 137 uint64_t jit_descriptor_offset = 0; 138 // offset relative to descriptors_addr 139 uint64_t dex_descriptor_offset = 0; 140 141 // The state we know about the remote jit debug descriptor. 142 Descriptor last_jit_descriptor; 143 // The state we know about the remote dex debug descriptor. 144 Descriptor last_dex_descriptor; 145 }; 146 147 // The location of descriptors in libart.so. 148 struct DescriptorsLocation { 149 uint64_t relative_addr = 0; 150 uint64_t size = 0; 151 uint64_t jit_descriptor_offset = 0; 152 uint64_t dex_descriptor_offset = 0; 153 }; 154 155 void ReadProcess(Process& process, std::vector<JITDebugInfo>* debug_info); 156 bool InitializeProcess(Process& process); 157 const DescriptorsLocation* GetDescriptorsLocation(const std::string& art_lib_path, 158 bool is_64bit); 159 bool ReadRemoteMem(Process& process, uint64_t remote_addr, uint64_t size, void* data); 160 bool ReadDescriptors(Process& process, Descriptor* jit_descriptor, Descriptor* dex_descriptor); 161 bool LoadDescriptor(bool is_64bit, const char* data, Descriptor* descriptor); 162 template <typename DescriptorT> 163 bool LoadDescriptorImpl(const char* data, Descriptor* descriptor); 164 165 bool ReadNewCodeEntries(Process& process, const Descriptor& descriptor, 166 uint64_t last_action_timestamp, uint32_t read_entry_limit, 167 std::vector<CodeEntry>* new_code_entries); 168 template <typename CodeEntryT> 169 bool ReadNewCodeEntriesImpl(Process& process, const Descriptor& descriptor, 170 uint64_t last_action_timestamp, uint32_t read_entry_limit, 171 std::vector<CodeEntry>* new_code_entries); 172 template <typename CodeEntryT> 173 bool ReadNewCodeEntriesImplV2(Process& process, const Descriptor& descriptor, 174 uint64_t last_action_timestamp, uint32_t read_entry_limit, 175 std::vector<CodeEntry>* new_code_entries); 176 177 void ReadJITCodeDebugInfo(Process& process, const std::vector<CodeEntry>& jit_entries, 178 std::vector<JITDebugInfo>* debug_info); 179 void ReadDexFileDebugInfo(Process& process, const std::vector<CodeEntry>& dex_entries, 180 std::vector<JITDebugInfo>* debug_info); 181 bool AddDebugInfo(const std::vector<JITDebugInfo>& debug_info, bool sync_kernel_records); 182 183 bool keep_symfiles_ = false; 184 bool sync_with_records_ = false; 185 IOEventRef read_event_ = nullptr; 186 debug_info_callback_t debug_info_callback_; 187 188 // Keys are pids of processes having libart.so, values show whether a process has been monitored. 189 std::unordered_map<pid_t, bool> pids_with_art_lib_; 190 191 // All monitored processes 192 std::unordered_map<pid_t, Process> processes_; 193 std::unordered_map<std::string, DescriptorsLocation> descriptors_location_cache_; 194 std::vector<char> descriptors_buf_; 195 196 std::priority_queue<JITDebugInfo, std::vector<JITDebugInfo>, std::greater<JITDebugInfo>> 197 debug_info_q_; 198 }; 199 200 } //namespace simpleperf 201 202 #endif // SIMPLE_PERF_JIT_DEBUG_READER_H_ 203