• 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 #include "JITDebugReader.h"
18 
19 #include <inttypes.h>
20 #include <sys/mman.h>
21 #include <sys/uio.h>
22 #include <sys/user.h>
23 
24 #include <algorithm>
25 #include <unordered_map>
26 #include <unordered_set>
27 #include <vector>
28 
29 #include <android-base/file.h>
30 #include <android-base/logging.h>
31 #include <android-base/strings.h>
32 
33 #include "dso.h"
34 #include "environment.h"
35 #include "read_apk.h"
36 #include "read_elf.h"
37 #include "utils.h"
38 
39 namespace simpleperf {
40 
41 // If the size of a symfile is larger than EXPECTED_MAX_SYMFILE_SIZE, we don't want to read it
42 // remotely.
43 static constexpr size_t MAX_JIT_SYMFILE_SIZE = 1024 * 1024u;
44 
45 // It takes about 30us-130us on Pixel (depending on the cpu frequency) to check if the descriptors
46 // have been updated (most time spent in process_vm_preadv). We want to know if the JIT debug info
47 // changed as soon as possible, while not wasting too much time checking for updates. So use a
48 // period of 100 ms.
49 // In system wide profiling, we may need to check JIT debug info changes for many processes, to
50 // avoid spending all time checking, wait 100 ms between any two checks.
51 static constexpr size_t kUpdateJITDebugInfoIntervalInMs = 100;
52 
53 // Match the format of JITDescriptor in art/runtime/jit/debugger_interface.cc.
54 template <typename ADDRT>
55 struct JITDescriptor {
56   uint32_t version;
57   uint32_t action_flag;
58   ADDRT relevant_entry_addr;
59   ADDRT first_entry_addr;
60   uint8_t magic[8];
61   uint32_t flags;
62   uint32_t sizeof_descriptor;
63   uint32_t sizeof_entry;
64   uint32_t action_seqlock;  // incremented before and after any modification
65   uint64_t action_timestamp;  // CLOCK_MONOTONIC time of last action
66 
67   bool Valid() const;
68 
AndroidVersionsimpleperf::JITDescriptor69   int AndroidVersion() const {
70     return magic[7] - '0';
71   }
72 };
73 
74 // Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
75 // with JITDescriptor.magic == "Android1".
76 template <typename ADDRT>
77 struct JITCodeEntry {
78   ADDRT next_addr;
79   ADDRT prev_addr;
80   ADDRT symfile_addr;
81   uint64_t symfile_size;
82   uint64_t register_timestamp;  // CLOCK_MONOTONIC time of entry registration
83 
Validsimpleperf::JITCodeEntry84   bool Valid() const {
85     return symfile_addr > 0u && symfile_size > 0u;
86   }
87 };
88 
89 // Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
90 // with JITDescriptor.magic == "Android1".
91 template <typename ADDRT>
92 struct __attribute__((packed)) PackedJITCodeEntry {
93   ADDRT next_addr;
94   ADDRT prev_addr;
95   ADDRT symfile_addr;
96   uint64_t symfile_size;
97   uint64_t register_timestamp;
98 
Validsimpleperf::PackedJITCodeEntry99   bool Valid() const {
100     return symfile_addr > 0u && symfile_size > 0u;
101   }
102 };
103 
104 // Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
105 // with JITDescriptor.magic == "Android2".
106 template <typename ADDRT>
107 struct JITCodeEntryV2 {
108   ADDRT next_addr;
109   ADDRT prev_addr;
110   ADDRT symfile_addr;
111   uint64_t symfile_size;
112   uint64_t register_timestamp;  // CLOCK_MONOTONIC time of entry registration
113   uint32_t seqlock;  // even value if valid
114 
Validsimpleperf::JITCodeEntryV2115   bool Valid() const {
116     return (seqlock & 1) == 0;
117   }
118 };
119 
120 // Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
121 // with JITDescriptor.magic == "Android2".
122 template <typename ADDRT>
123 struct __attribute__((packed)) PackedJITCodeEntryV2 {
124   ADDRT next_addr;
125   ADDRT prev_addr;
126   ADDRT symfile_addr;
127   uint64_t symfile_size;
128   uint64_t register_timestamp;
129   uint32_t seqlock;
130 
Validsimpleperf::PackedJITCodeEntryV2131   bool Valid() const {
132     return (seqlock & 1) == 0;
133   }
134 };
135 
136 // Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
137 // with JITDescriptor.magic == "Android2".
138 template <typename ADDRT>
139 struct __attribute__((packed)) PaddedJITCodeEntryV2 {
140   ADDRT next_addr;
141   ADDRT prev_addr;
142   ADDRT symfile_addr;
143   uint64_t symfile_size;
144   uint64_t register_timestamp;
145   uint32_t seqlock;
146   uint32_t pad;
147 
Validsimpleperf::PaddedJITCodeEntryV2148   bool Valid() const {
149     return (seqlock & 1) == 0;
150   }
151 };
152 
153 using JITDescriptor32 = JITDescriptor<uint32_t>;
154 using JITDescriptor64 = JITDescriptor<uint64_t>;
155 
156 #if defined(__x86_64__)
157 // Make sure simpleperf built for i386 and x86_64 see the correct JITCodeEntry layout of i386.
158 using JITCodeEntry32 = PackedJITCodeEntry<uint32_t>;
159 using JITCodeEntry32V2 = PackedJITCodeEntryV2<uint32_t>;
160 #else
161 using JITCodeEntry32 = JITCodeEntry<uint32_t>;
162 using JITCodeEntry32V2 = JITCodeEntryV2<uint32_t>;
163 #endif
164 
165 using JITCodeEntry64 = JITCodeEntry<uint64_t>;
166 #if defined(__i386__)
167 // Make sure simpleperf built for i386 and x86_64 see the correct JITCodeEntry layout of x86_64.
168 using JITCodeEntry64V2 = PaddedJITCodeEntryV2<uint64_t>;
169 #else
170 using JITCodeEntry64V2 = JITCodeEntryV2<uint64_t>;
171 #endif
172 
173 template <typename ADDRT>
Valid() const174 bool JITDescriptor<ADDRT>::Valid() const {
175   const char* magic_str = reinterpret_cast<const char*>(magic);
176   if (version != 1 ||
177       !(strncmp(magic_str, "Android1", 8) == 0 || strncmp(magic_str, "Android2", 8) == 0)) {
178     return false;
179   }
180   if (sizeof(*this) != sizeof_descriptor) {
181     return false;
182   }
183   if (sizeof(ADDRT) == 4) {
184     return sizeof_entry == (AndroidVersion() == 1) ? sizeof(JITCodeEntry32)
185                                                    : sizeof(JITCodeEntry32V2);
186   }
187   return sizeof_entry == (AndroidVersion() == 1) ? sizeof(JITCodeEntry64)
188                                                  : sizeof(JITCodeEntry64V2);
189 }
190 
191 // We want to support both 64-bit and 32-bit simpleperf when profiling either 64-bit or 32-bit
192 // apps. So using static_asserts to make sure that simpleperf on arm and aarch64 having the same
193 // view of structures, and simpleperf on i386 and x86_64 having the same view of structures.
194 static_assert(sizeof(JITDescriptor32) == 48, "");
195 static_assert(sizeof(JITDescriptor64) == 56, "");
196 
197 #if defined(__i386__) or defined(__x86_64__)
198 static_assert(sizeof(JITCodeEntry32) == 28, "");
199 static_assert(sizeof(JITCodeEntry32V2) == 32, "");
200 static_assert(sizeof(JITCodeEntry64) == 40, "");
201 static_assert(sizeof(JITCodeEntry64V2) == 48, "");
202 #else
203 static_assert(sizeof(JITCodeEntry32) == 32, "");
204 static_assert(sizeof(JITCodeEntry32V2) == 40, "");
205 static_assert(sizeof(JITCodeEntry64) == 40, "");
206 static_assert(sizeof(JITCodeEntry64V2) == 48, "");
207 #endif
208 
RegisterDebugInfoCallback(IOEventLoop * loop,const debug_info_callback_t & callback)209 bool JITDebugReader::RegisterDebugInfoCallback(IOEventLoop* loop,
210                                              const debug_info_callback_t& callback) {
211   debug_info_callback_ = callback;
212   read_event_ = loop->AddPeriodicEvent(SecondToTimeval(kUpdateJITDebugInfoIntervalInMs / 1000.0),
213                                        [this]() { return ReadAllProcesses(); });
214   return (read_event_ != nullptr && IOEventLoop::DisableEvent(read_event_));
215 }
216 
MonitorProcess(pid_t pid)217 bool JITDebugReader::MonitorProcess(pid_t pid) {
218   if (processes_.find(pid) == processes_.end()) {
219     processes_[pid].pid = pid;
220     LOG(DEBUG) << "Start monitoring process " << pid;
221     if (processes_.size() == 1u) {
222       if (!IOEventLoop::EnableEvent(read_event_)) {
223         return false;
224       }
225     }
226   }
227   return true;
228 }
229 
IsArtLib(const std::string & filename)230 static bool IsArtLib(const std::string& filename) {
231   return android::base::EndsWith(filename, "libart.so") ||
232       android::base::EndsWith(filename, "libartd.so");
233 }
234 
UpdateRecord(const Record * record)235 bool JITDebugReader::UpdateRecord(const Record* record) {
236   if (record->type() == PERF_RECORD_MMAP) {
237     auto r = static_cast<const MmapRecord*>(record);
238     if (IsArtLib(r->filename)) {
239       pids_with_art_lib_.emplace(r->data->pid, false);
240     }
241   } else if (record->type() == PERF_RECORD_MMAP2) {
242     auto r = static_cast<const Mmap2Record*>(record);
243     if (IsArtLib(r->filename)) {
244       pids_with_art_lib_.emplace(r->data->pid, false);
245     }
246   } else if (record->type() == PERF_RECORD_FORK) {
247     auto r = static_cast<const ForkRecord*>(record);
248     if (r->data->pid != r->data->ppid &&
249         pids_with_art_lib_.find(r->data->ppid) != pids_with_art_lib_.end()) {
250       pids_with_art_lib_.emplace(r->data->pid, false);
251     }
252   } else if (record->type() == PERF_RECORD_SAMPLE) {
253     auto r = static_cast<const SampleRecord*>(record);
254     auto it = pids_with_art_lib_.find(r->tid_data.pid);
255     if (it != pids_with_art_lib_.end() && !it->second) {
256       it->second = true;
257       if (!MonitorProcess(r->tid_data.pid)) {
258         return false;
259       }
260       return ReadProcess(r->tid_data.pid);
261     }
262   }
263   return FlushDebugInfo(record->Timestamp());
264 }
265 
FlushDebugInfo(uint64_t timestamp)266 bool JITDebugReader::FlushDebugInfo(uint64_t timestamp) {
267   if (sync_with_records_) {
268     if (!debug_info_q_.empty() && debug_info_q_.top().timestamp < timestamp) {
269       std::vector<JITDebugInfo> debug_info;
270       while (!debug_info_q_.empty() && debug_info_q_.top().timestamp < timestamp) {
271         debug_info.emplace_back(debug_info_q_.top());
272         debug_info_q_.pop();
273       }
274       return debug_info_callback_(debug_info, false);
275     }
276   }
277   return true;
278 }
279 
ReadAllProcesses()280 bool JITDebugReader::ReadAllProcesses() {
281   if (!IOEventLoop::DisableEvent(read_event_)) {
282     return false;
283   }
284   std::vector<JITDebugInfo> debug_info;
285   for (auto it = processes_.begin(); it != processes_.end();) {
286     Process& process = it->second;
287     ReadProcess(process, &debug_info);
288     if (process.died) {
289       LOG(DEBUG) << "Stop monitoring process " << process.pid;
290       it = processes_.erase(it);
291     } else {
292       ++it;
293     }
294   }
295   if (!AddDebugInfo(debug_info, true)) {
296     return false;
297   }
298   if (!processes_.empty()) {
299     return IOEventLoop::EnableEvent(read_event_);
300   }
301   return true;
302 }
303 
ReadProcess(pid_t pid)304 bool JITDebugReader::ReadProcess(pid_t pid) {
305   auto it = processes_.find(pid);
306   if (it != processes_.end()) {
307     std::vector<JITDebugInfo> debug_info;
308     ReadProcess(it->second, &debug_info);
309     return AddDebugInfo(debug_info, false);
310   }
311   return true;
312 }
313 
ReadProcess(Process & process,std::vector<JITDebugInfo> * debug_info)314 void JITDebugReader::ReadProcess(Process& process, std::vector<JITDebugInfo>* debug_info) {
315   if (process.died || (!process.initialized && !InitializeProcess(process))) {
316     return;
317   }
318   // 1. Read descriptors.
319   Descriptor jit_descriptor;
320   Descriptor dex_descriptor;
321   if (!ReadDescriptors(process, &jit_descriptor, &dex_descriptor)) {
322     return;
323   }
324   // 2. Return if descriptors are not changed.
325   if (jit_descriptor.action_seqlock == process.last_jit_descriptor.action_seqlock &&
326       dex_descriptor.action_seqlock == process.last_dex_descriptor.action_seqlock) {
327     return;
328   }
329 
330   // 3. Read new symfiles.
331   auto check_descriptor = [&](Descriptor& descriptor, bool is_jit) {
332       Descriptor tmp_jit_descriptor;
333       Descriptor tmp_dex_descriptor;
334       if (!ReadDescriptors(process, &tmp_jit_descriptor, &tmp_dex_descriptor)) {
335         return false;
336       }
337       if (is_jit) {
338         return descriptor.action_seqlock == tmp_jit_descriptor.action_seqlock;
339       }
340       return descriptor.action_seqlock == tmp_dex_descriptor.action_seqlock;
341   };
342 
343   auto read_debug_info = [&](Descriptor& new_descriptor, Descriptor& old_descriptor, bool is_jit) {
344     bool has_update = new_descriptor.action_seqlock != old_descriptor.action_seqlock &&
345                       (new_descriptor.action_seqlock & 1) == 0;
346     LOG(DEBUG) << (is_jit ? "JIT" : "Dex") << " symfiles of pid " << process.pid
347         << ": old seqlock " << old_descriptor.action_seqlock
348         << ", new seqlock " << new_descriptor.action_seqlock;
349     if (!has_update) {
350       return false;
351     }
352     std::vector<CodeEntry> new_entries;
353     // Adding or removing one code entry will make two increments of action_seqlock. So we should
354     // not read more than (seqlock_diff / 2) new entries.
355     uint32_t read_entry_limit = (new_descriptor.action_seqlock - old_descriptor.action_seqlock) / 2;
356     if (!ReadNewCodeEntries(process, new_descriptor, old_descriptor.action_timestamp,
357                             read_entry_limit, &new_entries)) {
358       return false;
359     }
360     // Check if the descriptor was changed while we were reading new entries.
361     if (!check_descriptor(new_descriptor, is_jit)) {
362       return false;
363     }
364     LOG(DEBUG) << (is_jit ? "JIT" : "Dex") << " symfiles of pid " << process.pid
365                << ": read " << new_entries.size() << " new entries";
366     if (new_entries.empty()) {
367       return true;
368     }
369     if (is_jit) {
370       ReadJITCodeDebugInfo(process, new_entries, debug_info);
371     } else {
372       ReadDexFileDebugInfo(process, new_entries, debug_info);
373     }
374     return true;
375   };
376   if (read_debug_info(jit_descriptor, process.last_jit_descriptor, true)) {
377     process.last_jit_descriptor = jit_descriptor;
378   }
379   if (read_debug_info(dex_descriptor, process.last_dex_descriptor, false)) {
380     process.last_dex_descriptor = dex_descriptor;
381   }
382 }
383 
InitializeProcess(Process & process)384 bool JITDebugReader::InitializeProcess(Process& process) {
385   // 1. Read map file to find the location of libart.so.
386   std::vector<ThreadMmap> thread_mmaps;
387   if (!GetThreadMmapsInProcess(process.pid, &thread_mmaps)) {
388     process.died = true;
389     return false;
390   }
391   std::string art_lib_path;
392   uint64_t min_vaddr_in_memory;
393   for (auto& map : thread_mmaps) {
394     if ((map.prot & PROT_EXEC) && IsArtLib(map.name)) {
395       art_lib_path = map.name;
396       min_vaddr_in_memory = map.start_addr;
397       break;
398     }
399   }
400   if (art_lib_path.empty()) {
401     return false;
402   }
403   process.is_64bit = art_lib_path.find("lib64") != std::string::npos;
404 
405   // 2. Read libart.so to find the addresses of __jit_debug_descriptor and __dex_debug_descriptor.
406   const DescriptorsLocation* location = GetDescriptorsLocation(art_lib_path, process.is_64bit);
407   if (location == nullptr) {
408     return false;
409   }
410   process.descriptors_addr = location->relative_addr + min_vaddr_in_memory;
411   process.descriptors_size = location->size;
412   process.jit_descriptor_offset = location->jit_descriptor_offset;
413   process.dex_descriptor_offset = location->dex_descriptor_offset;
414   process.initialized = true;
415   return true;
416 }
417 
GetDescriptorsLocation(const std::string & art_lib_path,bool is_64bit)418 const JITDebugReader::DescriptorsLocation* JITDebugReader::GetDescriptorsLocation(
419     const std::string& art_lib_path, bool is_64bit) {
420   auto it = descriptors_location_cache_.find(art_lib_path);
421   if (it != descriptors_location_cache_.end()) {
422     return it->second.relative_addr == 0u ? nullptr : &it->second;
423   }
424   DescriptorsLocation& location = descriptors_location_cache_[art_lib_path];
425 
426   // Read libart.so to find the addresses of __jit_debug_descriptor and __dex_debug_descriptor.
427   uint64_t min_vaddr_in_file;
428   uint64_t file_offset;
429   ElfStatus status = ReadMinExecutableVirtualAddressFromElfFile(art_lib_path, BuildId(),
430                                                                 &min_vaddr_in_file,
431                                                                 &file_offset);
432   if (status != ElfStatus::NO_ERROR) {
433     LOG(ERROR) << "ReadMinExecutableVirtualAddress failed, status = " << status;
434     return nullptr;
435   }
436   // min_vaddr_in_file is the min vaddr of executable segments. It may not be page aligned.
437   // And dynamic linker will create map mapping to (segment.p_vaddr & PAGE_MASK).
438   uint64_t aligned_segment_vaddr = min_vaddr_in_file & PAGE_MASK;
439   const char* jit_str = "__jit_debug_descriptor";
440   const char* dex_str = "__dex_debug_descriptor";
441   uint64_t jit_addr = 0u;
442   uint64_t dex_addr = 0u;
443 
444   auto callback = [&](const ElfFileSymbol& symbol) {
445     if (symbol.name == jit_str) {
446       jit_addr = symbol.vaddr - aligned_segment_vaddr;
447     } else if (symbol.name == dex_str) {
448       dex_addr = symbol.vaddr - aligned_segment_vaddr;
449     }
450   };
451   if (ParseDynamicSymbolsFromElfFile(art_lib_path, callback) != ElfStatus::NO_ERROR) {
452     return nullptr;
453   }
454   if (jit_addr == 0u || dex_addr == 0u) {
455     return nullptr;
456   }
457   location.relative_addr = std::min(jit_addr, dex_addr);
458   location.size = std::max(jit_addr, dex_addr) +
459       (is_64bit ? sizeof(JITDescriptor64) : sizeof(JITDescriptor32)) - location.relative_addr;
460   if (location.size >= 4096u) {
461     PLOG(WARNING) << "The descriptors_size is unexpected large: " << location.size;
462   }
463   if (descriptors_buf_.size() < location.size) {
464     descriptors_buf_.resize(location.size);
465   }
466   location.jit_descriptor_offset = jit_addr - location.relative_addr;
467   location.dex_descriptor_offset = dex_addr - location.relative_addr;
468   return &location;
469 }
470 
ReadRemoteMem(Process & process,uint64_t remote_addr,uint64_t size,void * data)471 bool JITDebugReader::ReadRemoteMem(Process& process, uint64_t remote_addr, uint64_t size,
472                                    void* data) {
473   iovec local_iov;
474   local_iov.iov_base = data;
475   local_iov.iov_len = size;
476   iovec remote_iov;
477   remote_iov.iov_base = reinterpret_cast<void*>(static_cast<uintptr_t>(remote_addr));
478   remote_iov.iov_len = size;
479   ssize_t result = process_vm_readv(process.pid, &local_iov, 1, &remote_iov, 1, 0);
480   if (static_cast<size_t>(result) != size) {
481     PLOG(DEBUG) << "ReadRemoteMem(" << " pid " << process.pid << ", addr " << std::hex
482                 << remote_addr << ", size " << size << ") failed";
483     process.died = true;
484     return false;
485   }
486   return true;
487 }
488 
ReadDescriptors(Process & process,Descriptor * jit_descriptor,Descriptor * dex_descriptor)489 bool JITDebugReader::ReadDescriptors(Process& process, Descriptor* jit_descriptor,
490                                      Descriptor* dex_descriptor) {
491   if (!ReadRemoteMem(process, process.descriptors_addr, process.descriptors_size,
492                      descriptors_buf_.data())) {
493     return false;
494   }
495   return LoadDescriptor(process.is_64bit, &descriptors_buf_[process.jit_descriptor_offset],
496                         jit_descriptor) &&
497       LoadDescriptor(process.is_64bit, &descriptors_buf_[process.dex_descriptor_offset],
498                      dex_descriptor);
499 }
500 
LoadDescriptor(bool is_64bit,const char * data,Descriptor * descriptor)501 bool JITDebugReader::LoadDescriptor(bool is_64bit, const char* data, Descriptor* descriptor) {
502   if (is_64bit) {
503     return LoadDescriptorImpl<JITDescriptor64>(data, descriptor);
504   }
505   return LoadDescriptorImpl<JITDescriptor32>(data, descriptor);
506 }
507 
508 template <typename DescriptorT>
LoadDescriptorImpl(const char * data,Descriptor * descriptor)509 bool JITDebugReader::LoadDescriptorImpl(const char* data, Descriptor* descriptor) {
510   DescriptorT raw_descriptor;
511   MoveFromBinaryFormat(raw_descriptor, data);
512   if (!raw_descriptor.Valid()) {
513     return false;
514   }
515   descriptor->action_seqlock = raw_descriptor.action_seqlock;
516   descriptor->action_timestamp = raw_descriptor.action_timestamp;
517   descriptor->first_entry_addr = raw_descriptor.first_entry_addr;
518   descriptor->version = raw_descriptor.AndroidVersion();
519   return true;
520 }
521 
522 // Read new code entries with timestamp > last_action_timestamp.
523 // Since we don't stop the app process while reading code entries, it is possible we are reading
524 // broken data. So return false once we detect that the data is broken.
ReadNewCodeEntries(Process & process,const Descriptor & descriptor,uint64_t last_action_timestamp,uint32_t read_entry_limit,std::vector<CodeEntry> * new_code_entries)525 bool JITDebugReader::ReadNewCodeEntries(Process& process, const Descriptor& descriptor,
526                                         uint64_t last_action_timestamp, uint32_t read_entry_limit,
527                                         std::vector<CodeEntry>* new_code_entries) {
528   if (descriptor.version == 1) {
529     if (process.is_64bit) {
530       return ReadNewCodeEntriesImpl<JITCodeEntry64>(
531           process, descriptor, last_action_timestamp, read_entry_limit, new_code_entries);
532     }
533     return ReadNewCodeEntriesImpl<JITCodeEntry32>(
534         process, descriptor, last_action_timestamp, read_entry_limit, new_code_entries);
535   }
536   if (descriptor.version == 2) {
537     if (process.is_64bit) {
538       return ReadNewCodeEntriesImplV2<JITCodeEntry64V2>(
539           process, descriptor, last_action_timestamp, read_entry_limit, new_code_entries);
540     }
541     return ReadNewCodeEntriesImplV2<JITCodeEntry32V2>(
542         process, descriptor, last_action_timestamp, read_entry_limit, new_code_entries);
543   }
544   return false;
545 }
546 
547 template <typename CodeEntryT>
ReadNewCodeEntriesImpl(Process & process,const Descriptor & descriptor,uint64_t last_action_timestamp,uint32_t read_entry_limit,std::vector<CodeEntry> * new_code_entries)548 bool JITDebugReader::ReadNewCodeEntriesImpl(Process& process, const Descriptor& descriptor,
549                                             uint64_t last_action_timestamp,
550                                             uint32_t read_entry_limit,
551                                             std::vector<CodeEntry>* new_code_entries) {
552   uint64_t current_entry_addr = descriptor.first_entry_addr;
553   uint64_t prev_entry_addr = 0u;
554   std::unordered_set<uint64_t> entry_addr_set;
555 
556   for (size_t i = 0u; i < read_entry_limit && current_entry_addr != 0u; ++i) {
557     if (entry_addr_set.find(current_entry_addr) != entry_addr_set.end()) {
558       // We enter a loop, which means a broken linked list.
559       return false;
560     }
561     CodeEntryT entry;
562     if (!ReadRemoteMem(process, current_entry_addr, sizeof(entry), &entry)) {
563       return false;
564     }
565     if (entry.prev_addr != prev_entry_addr || !entry.Valid()) {
566       // A broken linked list
567       return false;
568     }
569     if (entry.register_timestamp <= last_action_timestamp) {
570       // The linked list has entries with timestamp in decreasing order. So stop searching
571       // once we hit an entry with timestamp <= last_action_timestmap.
572       break;
573     }
574     if (entry.symfile_size > 0) {
575       CodeEntry code_entry;
576       code_entry.addr = current_entry_addr;
577       code_entry.symfile_addr = entry.symfile_addr;
578       code_entry.symfile_size = entry.symfile_size;
579       code_entry.timestamp = entry.register_timestamp;
580       new_code_entries->push_back(code_entry);
581     }
582     entry_addr_set.insert(current_entry_addr);
583     prev_entry_addr = current_entry_addr;
584     current_entry_addr = entry.next_addr;
585   }
586   return true;
587 }
588 
589 // Temporary work around for patch "JIT mini-debug-info: Append packed entries towards end.", which
590 // adds new entries at the end of the list and forces simpleperf to read the whole list.
591 template <typename CodeEntryT>
ReadNewCodeEntriesImplV2(Process & process,const Descriptor & descriptor,uint64_t last_action_timestamp,uint32_t,std::vector<CodeEntry> * new_code_entries)592 bool JITDebugReader::ReadNewCodeEntriesImplV2(Process& process, const Descriptor& descriptor,
593                                               uint64_t last_action_timestamp,
594                                               uint32_t /* read_entry_limit */,
595                                               std::vector<CodeEntry>* new_code_entries) {
596   uint64_t current_entry_addr = descriptor.first_entry_addr;
597   uint64_t prev_entry_addr = 0u;
598   std::unordered_set<uint64_t> entry_addr_set;
599   const size_t READ_ENTRY_LIMIT = 10000;  // to avoid endless loop
600 
601   for (size_t i = 0u; i < READ_ENTRY_LIMIT && current_entry_addr != 0u; ++i) {
602     if (entry_addr_set.find(current_entry_addr) != entry_addr_set.end()) {
603       // We enter a loop, which means a broken linked list.
604       return false;
605     }
606     CodeEntryT entry;
607     if (!ReadRemoteMem(process, current_entry_addr, sizeof(entry), &entry)) {
608       return false;
609     }
610     if (entry.prev_addr != prev_entry_addr || !entry.Valid()) {
611       // A broken linked list
612       return false;
613     }
614     if (entry.symfile_size > 0 && entry.register_timestamp > last_action_timestamp) {
615       CodeEntry code_entry;
616       code_entry.addr = current_entry_addr;
617       code_entry.symfile_addr = entry.symfile_addr;
618       code_entry.symfile_size = entry.symfile_size;
619       code_entry.timestamp = entry.register_timestamp;
620       new_code_entries->push_back(code_entry);
621     }
622     entry_addr_set.insert(current_entry_addr);
623     prev_entry_addr = current_entry_addr;
624     current_entry_addr = entry.next_addr;
625   }
626   return true;
627 }
628 
ReadJITCodeDebugInfo(Process & process,const std::vector<CodeEntry> & jit_entries,std::vector<JITDebugInfo> * debug_info)629 void JITDebugReader::ReadJITCodeDebugInfo(Process& process,
630                                           const std::vector<CodeEntry>& jit_entries,
631                                           std::vector<JITDebugInfo>* debug_info) {
632   std::vector<char> data;
633   for (auto& jit_entry : jit_entries) {
634     if (jit_entry.symfile_size > MAX_JIT_SYMFILE_SIZE) {
635       continue;
636     }
637     if (data.size() < jit_entry.symfile_size) {
638       data.resize(jit_entry.symfile_size);
639     }
640     if (!ReadRemoteMem(process, jit_entry.symfile_addr, jit_entry.symfile_size, data.data())) {
641       continue;
642     }
643     if (!IsValidElfFileMagic(data.data(), jit_entry.symfile_size)) {
644       continue;
645     }
646     std::unique_ptr<TemporaryFile> tmp_file = ScopedTempFiles::CreateTempFile(!keep_symfiles_);
647     if (tmp_file == nullptr || !android::base::WriteFully(tmp_file->fd, data.data(),
648                                                           jit_entry.symfile_size)) {
649       continue;
650     }
651     if (keep_symfiles_) {
652       tmp_file->DoNotRemove();
653     }
654     auto callback = [&](const ElfFileSymbol& symbol) {
655       if (symbol.len == 0) {  // Some arm labels can have zero length.
656         return;
657       }
658       LOG(VERBOSE) << "JITSymbol " << symbol.name << " at [" << std::hex << symbol.vaddr
659                    << " - " << (symbol.vaddr + symbol.len) << " with size " << symbol.len;
660       debug_info->emplace_back(process.pid, jit_entry.timestamp, symbol.vaddr, symbol.len,
661                                tmp_file->path);
662     };
663     ParseSymbolsFromElfFileInMemory(data.data(), jit_entry.symfile_size, callback);
664   }
665 }
666 
ReadDexFileDebugInfo(Process & process,const std::vector<CodeEntry> & dex_entries,std::vector<JITDebugInfo> * debug_info)667 void JITDebugReader::ReadDexFileDebugInfo(Process& process,
668                                           const std::vector<CodeEntry>& dex_entries,
669                                           std::vector<JITDebugInfo>* debug_info) {
670   std::vector<ThreadMmap> thread_mmaps;
671   if (!GetThreadMmapsInProcess(process.pid, &thread_mmaps)) {
672     process.died = true;
673     return;
674   }
675   auto comp = [](const ThreadMmap& map, uint64_t addr) {
676     return map.start_addr <= addr;
677   };
678   for (auto& dex_entry : dex_entries) {
679     auto it = std::lower_bound(thread_mmaps.begin(), thread_mmaps.end(),
680                                dex_entry.symfile_addr, comp);
681     if (it == thread_mmaps.begin()) {
682       continue;
683     }
684     --it;
685     if (it->start_addr + it->len < dex_entry.symfile_addr + dex_entry.symfile_size) {
686       continue;
687     }
688     std::string file_path;
689     std::string zip_path;
690     std::string entry_path;
691     std::shared_ptr<ThreadMmap> extracted_dex_file_map;
692     if (ParseExtractedInMemoryPath(it->name, &zip_path, &entry_path)) {
693       file_path = GetUrlInApk(zip_path, entry_path);
694       extracted_dex_file_map = std::make_shared<ThreadMmap>(*it);
695     } else {
696       if (!IsRegularFile(it->name)) {
697         // TODO: read dex file only exist in memory?
698         continue;
699       }
700       file_path = it->name;
701     }
702     // Offset of dex file in .vdex file or .apk file.
703     uint64_t dex_file_offset = dex_entry.symfile_addr - it->start_addr + it->pgoff;
704     debug_info->emplace_back(process.pid, dex_entry.timestamp, dex_file_offset, file_path,
705                              extracted_dex_file_map);
706     LOG(VERBOSE) << "DexFile " << file_path << "+" << std::hex << dex_file_offset
707                  << " in map [" << it->start_addr << " - " << (it->start_addr + it->len)
708                  << "] with size " << dex_entry.symfile_size;
709   }
710 }
711 
AddDebugInfo(const std::vector<JITDebugInfo> & debug_info,bool sync_kernel_records)712 bool JITDebugReader::AddDebugInfo(const std::vector<JITDebugInfo>& debug_info,
713                                     bool sync_kernel_records) {
714   if (!debug_info.empty()) {
715     if (sync_with_records_) {
716       for (auto& info : debug_info) {
717         debug_info_q_.push(std::move(info));
718       }
719     } else {
720       return debug_info_callback_(debug_info, sync_kernel_records);
721     }
722   }
723   return true;
724 }
725 
726 }  // namespace simpleperf
727