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