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