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