• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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