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