blob: 2d4b132b2ff75ebbf1e95b62af2ff9949f3e5392 [file] [log] [blame]
Yabin Cui9e43e9f2018-03-09 15:57:13 -08001/*
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>
Yabin Cuie32ed2b2020-07-23 15:30:14 -070020#include <stdio.h>
Yabin Cuia6a04202018-07-23 15:32:47 -070021#include <sys/mman.h>
Yabin Cui9e43e9f2018-03-09 15:57:13 -080022#include <sys/uio.h>
Yabin Cui32654f52019-12-11 16:50:24 -080023#include <sys/user.h>
Yabin Cuie32ed2b2020-07-23 15:30:14 -070024#include <unistd.h>
Yabin Cui9e43e9f2018-03-09 15:57:13 -080025
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>
Yabin Cuie32ed2b2020-07-23 15:30:14 -070033#include <android-base/stringprintf.h>
Yabin Cui9e43e9f2018-03-09 15:57:13 -080034#include <android-base/strings.h>
35
Yabin Cui18581af2022-01-20 11:03:14 -080036#include "JITDebugReader_impl.h"
Yabin Cui9e43e9f2018-03-09 15:57:13 -080037#include "dso.h"
38#include "environment.h"
Yabin Cui2a53ff32018-05-21 17:37:00 -070039#include "read_apk.h"
Yabin Cui9e43e9f2018-03-09 15:57:13 -080040#include "read_elf.h"
41#include "utils.h"
42
Yabin Cuifaa7b922021-01-11 17:35:57 -080043namespace simpleperf {
44
Yabin Cui7f94b472020-08-03 21:11:32 +000045using android::base::StartsWith;
Yabin Cuie32ed2b2020-07-23 15:30:14 -070046using android::base::StringPrintf;
47
Yabin Cui9e43e9f2018-03-09 15:57:13 -080048// If the size of a symfile is larger than EXPECTED_MAX_SYMFILE_SIZE, we don't want to read it
49// remotely.
Yabin Cuicfdc7832023-03-02 15:35:01 -080050static constexpr size_t MAX_JIT_SYMFILE_SIZE = 1 * kMegabyte;
Yabin Cui9e43e9f2018-03-09 15:57:13 -080051
Yabin Cuic8571d42018-06-06 11:20:39 -070052// It takes about 30us-130us on Pixel (depending on the cpu frequency) to check if the descriptors
53// have been updated (most time spent in process_vm_preadv). We want to know if the JIT debug info
54// changed as soon as possible, while not wasting too much time checking for updates. So use a
55// period of 100 ms.
56// In system wide profiling, we may need to check JIT debug info changes for many processes, to
57// avoid spending all time checking, wait 100 ms between any two checks.
58static constexpr size_t kUpdateJITDebugInfoIntervalInMs = 100;
59
Yabin Cui7f94b472020-08-03 21:11:32 +000060// map name used for jit zygote cache
61static const char* kJITZygoteCacheMmapPrefix = "/memfd:jit-zygote-cache";
62
Yabin Cui62fa6ee2019-10-07 15:15:12 -070063// Match the format of JITDescriptor in art/runtime/jit/debugger_interface.cc.
Yabin Cui9e43e9f2018-03-09 15:57:13 -080064template <typename ADDRT>
65struct JITDescriptor {
66 uint32_t version;
67 uint32_t action_flag;
68 ADDRT relevant_entry_addr;
69 ADDRT first_entry_addr;
70 uint8_t magic[8];
71 uint32_t flags;
72 uint32_t sizeof_descriptor;
73 uint32_t sizeof_entry;
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +020074 uint32_t action_seqlock; // incremented before and after any modification
Yabin Cui9e43e9f2018-03-09 15:57:13 -080075 uint64_t action_timestamp; // CLOCK_MONOTONIC time of last action
76
Yabin Cui62fa6ee2019-10-07 15:15:12 -070077 bool Valid() const;
78
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +020079 int AndroidVersion() const { return magic[7] - '0'; }
Yabin Cui9e43e9f2018-03-09 15:57:13 -080080};
81
Yabin Cui62fa6ee2019-10-07 15:15:12 -070082// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
83// with JITDescriptor.magic == "Android1".
Yabin Cui9e43e9f2018-03-09 15:57:13 -080084template <typename ADDRT>
85struct JITCodeEntry {
86 ADDRT next_addr;
87 ADDRT prev_addr;
88 ADDRT symfile_addr;
89 uint64_t symfile_size;
90 uint64_t register_timestamp; // CLOCK_MONOTONIC time of entry registration
91
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +020092 bool Valid() const { return symfile_addr > 0u && symfile_size > 0u; }
Yabin Cui9e43e9f2018-03-09 15:57:13 -080093};
94
Yabin Cui62fa6ee2019-10-07 15:15:12 -070095// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
96// with JITDescriptor.magic == "Android1".
Yabin Cui9e43e9f2018-03-09 15:57:13 -080097template <typename ADDRT>
98struct __attribute__((packed)) PackedJITCodeEntry {
99 ADDRT next_addr;
100 ADDRT prev_addr;
101 ADDRT symfile_addr;
102 uint64_t symfile_size;
103 uint64_t register_timestamp;
104
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200105 bool Valid() const { return symfile_addr > 0u && symfile_size > 0u; }
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800106};
107
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700108// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
109// with JITDescriptor.magic == "Android2".
110template <typename ADDRT>
111struct JITCodeEntryV2 {
112 ADDRT next_addr;
113 ADDRT prev_addr;
114 ADDRT symfile_addr;
115 uint64_t symfile_size;
116 uint64_t register_timestamp; // CLOCK_MONOTONIC time of entry registration
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200117 uint32_t seqlock; // even value if valid
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700118
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200119 bool Valid() const { return (seqlock & 1) == 0; }
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700120};
121
122// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
123// with JITDescriptor.magic == "Android2".
124template <typename ADDRT>
125struct __attribute__((packed)) PackedJITCodeEntryV2 {
126 ADDRT next_addr;
127 ADDRT prev_addr;
128 ADDRT symfile_addr;
129 uint64_t symfile_size;
130 uint64_t register_timestamp;
131 uint32_t seqlock;
132
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200133 bool Valid() const { return (seqlock & 1) == 0; }
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700134};
135
136// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
137// with JITDescriptor.magic == "Android2".
138template <typename ADDRT>
139struct __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
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200148 bool Valid() const { return (seqlock & 1) == 0; }
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700149};
150
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800151using JITDescriptor32 = JITDescriptor<uint32_t>;
152using JITDescriptor64 = JITDescriptor<uint64_t>;
153
154#if defined(__x86_64__)
155// Make sure simpleperf built for i386 and x86_64 see the correct JITCodeEntry layout of i386.
156using JITCodeEntry32 = PackedJITCodeEntry<uint32_t>;
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700157using JITCodeEntry32V2 = PackedJITCodeEntryV2<uint32_t>;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800158#else
159using JITCodeEntry32 = JITCodeEntry<uint32_t>;
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700160using JITCodeEntry32V2 = JITCodeEntryV2<uint32_t>;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800161#endif
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700162
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800163using JITCodeEntry64 = JITCodeEntry<uint64_t>;
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700164#if defined(__i386__)
165// Make sure simpleperf built for i386 and x86_64 see the correct JITCodeEntry layout of x86_64.
166using JITCodeEntry64V2 = PaddedJITCodeEntryV2<uint64_t>;
167#else
168using JITCodeEntry64V2 = JITCodeEntryV2<uint64_t>;
169#endif
170
171template <typename ADDRT>
172bool JITDescriptor<ADDRT>::Valid() const {
173 const char* magic_str = reinterpret_cast<const char*>(magic);
174 if (version != 1 ||
175 !(strncmp(magic_str, "Android1", 8) == 0 || strncmp(magic_str, "Android2", 8) == 0)) {
176 return false;
177 }
178 if (sizeof(*this) != sizeof_descriptor) {
179 return false;
180 }
181 if (sizeof(ADDRT) == 4) {
182 return sizeof_entry == (AndroidVersion() == 1) ? sizeof(JITCodeEntry32)
183 : sizeof(JITCodeEntry32V2);
184 }
185 return sizeof_entry == (AndroidVersion() == 1) ? sizeof(JITCodeEntry64)
186 : sizeof(JITCodeEntry64V2);
187}
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800188
189// We want to support both 64-bit and 32-bit simpleperf when profiling either 64-bit or 32-bit
190// apps. So using static_asserts to make sure that simpleperf on arm and aarch64 having the same
191// view of structures, and simpleperf on i386 and x86_64 having the same view of structures.
192static_assert(sizeof(JITDescriptor32) == 48, "");
193static_assert(sizeof(JITDescriptor64) == 56, "");
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700194
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800195#if defined(__i386__) or defined(__x86_64__)
196static_assert(sizeof(JITCodeEntry32) == 28, "");
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700197static_assert(sizeof(JITCodeEntry32V2) == 32, "");
198static_assert(sizeof(JITCodeEntry64) == 40, "");
199static_assert(sizeof(JITCodeEntry64V2) == 48, "");
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800200#else
201static_assert(sizeof(JITCodeEntry32) == 32, "");
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700202static_assert(sizeof(JITCodeEntry32V2) == 40, "");
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800203static_assert(sizeof(JITCodeEntry64) == 40, "");
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700204static_assert(sizeof(JITCodeEntry64V2) == 48, "");
205#endif
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800206
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700207JITDebugReader::JITDebugReader(const std::string& symfile_prefix, SymFileOption symfile_option,
208 SyncOption sync_option)
209 : symfile_prefix_(symfile_prefix), symfile_option_(symfile_option), sync_option_(sync_option) {}
210
211JITDebugReader::~JITDebugReader() {}
212
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700213bool JITDebugReader::RegisterDebugInfoCallback(IOEventLoop* loop,
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200214 const debug_info_callback_t& callback) {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700215 debug_info_callback_ = callback;
Yabin Cuic8571d42018-06-06 11:20:39 -0700216 read_event_ = loop->AddPeriodicEvent(SecondToTimeval(kUpdateJITDebugInfoIntervalInMs / 1000.0),
217 [this]() { return ReadAllProcesses(); });
218 return (read_event_ != nullptr && IOEventLoop::DisableEvent(read_event_));
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800219}
220
Yabin Cuic8571d42018-06-06 11:20:39 -0700221bool JITDebugReader::MonitorProcess(pid_t pid) {
222 if (processes_.find(pid) == processes_.end()) {
223 processes_[pid].pid = pid;
224 LOG(DEBUG) << "Start monitoring process " << pid;
225 if (processes_.size() == 1u) {
226 if (!IOEventLoop::EnableEvent(read_event_)) {
227 return false;
228 }
229 }
230 }
231 return true;
232}
233
234static bool IsArtLib(const std::string& filename) {
235 return android::base::EndsWith(filename, "libart.so") ||
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200236 android::base::EndsWith(filename, "libartd.so");
Yabin Cuic8571d42018-06-06 11:20:39 -0700237}
238
239bool JITDebugReader::UpdateRecord(const Record* record) {
240 if (record->type() == PERF_RECORD_MMAP) {
241 auto r = static_cast<const MmapRecord*>(record);
242 if (IsArtLib(r->filename)) {
243 pids_with_art_lib_.emplace(r->data->pid, false);
244 }
245 } else if (record->type() == PERF_RECORD_MMAP2) {
246 auto r = static_cast<const Mmap2Record*>(record);
247 if (IsArtLib(r->filename)) {
248 pids_with_art_lib_.emplace(r->data->pid, false);
249 }
250 } else if (record->type() == PERF_RECORD_FORK) {
251 auto r = static_cast<const ForkRecord*>(record);
252 if (r->data->pid != r->data->ppid &&
253 pids_with_art_lib_.find(r->data->ppid) != pids_with_art_lib_.end()) {
254 pids_with_art_lib_.emplace(r->data->pid, false);
255 }
256 } else if (record->type() == PERF_RECORD_SAMPLE) {
257 auto r = static_cast<const SampleRecord*>(record);
258 auto it = pids_with_art_lib_.find(r->tid_data.pid);
259 if (it != pids_with_art_lib_.end() && !it->second) {
260 it->second = true;
261 if (!MonitorProcess(r->tid_data.pid)) {
262 return false;
263 }
264 return ReadProcess(r->tid_data.pid);
265 }
266 }
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700267 return FlushDebugInfo(record->Timestamp());
268}
269
270bool JITDebugReader::FlushDebugInfo(uint64_t timestamp) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700271 if (sync_option_ == SyncOption::kSyncWithRecords) {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700272 if (!debug_info_q_.empty() && debug_info_q_.top().timestamp < timestamp) {
273 std::vector<JITDebugInfo> debug_info;
274 while (!debug_info_q_.empty() && debug_info_q_.top().timestamp < timestamp) {
275 debug_info.emplace_back(debug_info_q_.top());
276 debug_info_q_.pop();
277 }
278 return debug_info_callback_(debug_info, false);
279 }
280 }
Yabin Cuic8571d42018-06-06 11:20:39 -0700281 return true;
282}
283
284bool JITDebugReader::ReadAllProcesses() {
285 if (!IOEventLoop::DisableEvent(read_event_)) {
286 return false;
287 }
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700288 std::vector<JITDebugInfo> debug_info;
Yabin Cuic8571d42018-06-06 11:20:39 -0700289 for (auto it = processes_.begin(); it != processes_.end();) {
290 Process& process = it->second;
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700291 if (!ReadProcess(process, &debug_info)) {
292 return false;
293 }
Yabin Cuic8571d42018-06-06 11:20:39 -0700294 if (process.died) {
295 LOG(DEBUG) << "Stop monitoring process " << process.pid;
296 it = processes_.erase(it);
297 } else {
298 ++it;
299 }
300 }
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700301 if (!AddDebugInfo(debug_info, true)) {
302 return false;
Yabin Cuic8571d42018-06-06 11:20:39 -0700303 }
304 if (!processes_.empty()) {
305 return IOEventLoop::EnableEvent(read_event_);
306 }
307 return true;
308}
309
310bool JITDebugReader::ReadProcess(pid_t pid) {
311 auto it = processes_.find(pid);
312 if (it != processes_.end()) {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700313 std::vector<JITDebugInfo> debug_info;
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700314 return ReadProcess(it->second, &debug_info) && AddDebugInfo(debug_info, false);
Yabin Cuic8571d42018-06-06 11:20:39 -0700315 }
316 return true;
317}
318
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700319bool JITDebugReader::ReadProcess(Process& process, std::vector<JITDebugInfo>* debug_info) {
Yabin Cuic8571d42018-06-06 11:20:39 -0700320 if (process.died || (!process.initialized && !InitializeProcess(process))) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700321 return true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800322 }
323 // 1. Read descriptors.
324 Descriptor jit_descriptor;
325 Descriptor dex_descriptor;
Yabin Cuic8571d42018-06-06 11:20:39 -0700326 if (!ReadDescriptors(process, &jit_descriptor, &dex_descriptor)) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700327 return true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800328 }
329 // 2. Return if descriptors are not changed.
Yabin Cuic8571d42018-06-06 11:20:39 -0700330 if (jit_descriptor.action_seqlock == process.last_jit_descriptor.action_seqlock &&
331 dex_descriptor.action_seqlock == process.last_dex_descriptor.action_seqlock) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700332 return true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800333 }
334
335 // 3. Read new symfiles.
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700336 return ReadDebugInfo(process, jit_descriptor, debug_info) &&
337 ReadDebugInfo(process, dex_descriptor, debug_info);
338}
339
340bool JITDebugReader::ReadDebugInfo(Process& process, Descriptor& new_descriptor,
341 std::vector<JITDebugInfo>* debug_info) {
342 DescriptorType type = new_descriptor.type;
343 Descriptor* old_descriptor =
344 (type == DescriptorType::kJIT) ? &process.last_jit_descriptor : &process.last_dex_descriptor;
345
346 bool has_update = new_descriptor.action_seqlock != old_descriptor->action_seqlock &&
347 (new_descriptor.action_seqlock & 1) == 0;
348 LOG(DEBUG) << (type == DescriptorType::kJIT ? "JIT" : "Dex") << " symfiles of pid " << process.pid
349 << ": old seqlock " << old_descriptor->action_seqlock << ", new seqlock "
350 << new_descriptor.action_seqlock;
351 if (!has_update) {
352 return true;
353 }
354 std::vector<CodeEntry> new_entries;
355 // Adding or removing one code entry will make two increments of action_seqlock. So we should
356 // not read more than (seqlock_diff / 2) new entries.
357 uint32_t read_entry_limit = (new_descriptor.action_seqlock - old_descriptor->action_seqlock) / 2;
358 if (!ReadNewCodeEntries(process, new_descriptor, old_descriptor->action_timestamp,
359 read_entry_limit, &new_entries)) {
360 return true;
361 }
362 // If the descriptor was changed while we were reading new entries, skip reading debug info this
363 // time.
364 if (IsDescriptorChanged(process, new_descriptor)) {
365 return true;
366 }
367 LOG(DEBUG) << (type == DescriptorType::kJIT ? "JIT" : "Dex") << " symfiles of pid " << process.pid
368 << ": read " << new_entries.size() << " new entries";
369
370 if (!new_entries.empty()) {
371 if (type == DescriptorType::kJIT) {
372 if (!ReadJITCodeDebugInfo(process, new_entries, debug_info)) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800373 return false;
374 }
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800375 } else {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700376 ReadDexFileDebugInfo(process, new_entries, debug_info);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800377 }
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700378 }
379 *old_descriptor = new_descriptor;
380 return true;
381}
382
383bool JITDebugReader::IsDescriptorChanged(Process& process, Descriptor& prev_descriptor) {
384 Descriptor tmp_jit_descriptor;
385 Descriptor tmp_dex_descriptor;
386 if (!ReadDescriptors(process, &tmp_jit_descriptor, &tmp_dex_descriptor)) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800387 return true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800388 }
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700389 if (prev_descriptor.type == DescriptorType::kJIT) {
390 return prev_descriptor.action_seqlock != tmp_jit_descriptor.action_seqlock;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800391 }
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700392 return prev_descriptor.action_seqlock != tmp_dex_descriptor.action_seqlock;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800393}
394
Yabin Cuic8571d42018-06-06 11:20:39 -0700395bool JITDebugReader::InitializeProcess(Process& process) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800396 // 1. Read map file to find the location of libart.so.
397 std::vector<ThreadMmap> thread_mmaps;
Yabin Cuic8571d42018-06-06 11:20:39 -0700398 if (!GetThreadMmapsInProcess(process.pid, &thread_mmaps)) {
399 process.died = true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800400 return false;
401 }
402 std::string art_lib_path;
Yabin Cuic8571d42018-06-06 11:20:39 -0700403 uint64_t min_vaddr_in_memory;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800404 for (auto& map : thread_mmaps) {
Yabin Cui2db05b42018-07-16 14:04:49 -0700405 if ((map.prot & PROT_EXEC) && IsArtLib(map.name)) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800406 art_lib_path = map.name;
Yabin Cuic8571d42018-06-06 11:20:39 -0700407 min_vaddr_in_memory = map.start_addr;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800408 break;
409 }
410 }
411 if (art_lib_path.empty()) {
412 return false;
413 }
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800414
415 // 2. Read libart.so to find the addresses of __jit_debug_descriptor and __dex_debug_descriptor.
Yabin Cuie5defe12022-03-23 15:55:50 -0700416 const DescriptorsLocation* location = GetDescriptorsLocation(art_lib_path);
Yabin Cuic8571d42018-06-06 11:20:39 -0700417 if (location == nullptr) {
418 return false;
419 }
Yabin Cuie5defe12022-03-23 15:55:50 -0700420 process.is_64bit = location->is_64bit;
421 process.jit_descriptor_addr = location->jit_descriptor_addr + min_vaddr_in_memory;
422 process.dex_descriptor_addr = location->dex_descriptor_addr + min_vaddr_in_memory;
Yabin Cui7f94b472020-08-03 21:11:32 +0000423
424 for (auto& map : thread_mmaps) {
425 if (StartsWith(map.name, kJITZygoteCacheMmapPrefix)) {
426 process.jit_zygote_cache_ranges_.emplace_back(map.start_addr, map.start_addr + map.len);
427 }
428 }
429
Yabin Cuic8571d42018-06-06 11:20:39 -0700430 process.initialized = true;
431 return true;
432}
433
434const JITDebugReader::DescriptorsLocation* JITDebugReader::GetDescriptorsLocation(
Yabin Cuie5defe12022-03-23 15:55:50 -0700435 const std::string& art_lib_path) {
Yabin Cuic8571d42018-06-06 11:20:39 -0700436 auto it = descriptors_location_cache_.find(art_lib_path);
437 if (it != descriptors_location_cache_.end()) {
Yabin Cuie5defe12022-03-23 15:55:50 -0700438 return it->second.jit_descriptor_addr == 0u ? nullptr : &it->second;
Yabin Cuic8571d42018-06-06 11:20:39 -0700439 }
440 DescriptorsLocation& location = descriptors_location_cache_[art_lib_path];
441
442 // Read libart.so to find the addresses of __jit_debug_descriptor and __dex_debug_descriptor.
Yabin Cui90c3b302020-07-01 10:09:16 -0700443 ElfStatus status;
444 auto elf = ElfFile::Open(art_lib_path, &status);
445 if (!elf) {
446 LOG(ERROR) << "failed to read min_exec_vaddr from " << art_lib_path << ": " << status;
Yabin Cuic8571d42018-06-06 11:20:39 -0700447 return nullptr;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800448 }
Yabin Cui90c3b302020-07-01 10:09:16 -0700449 uint64_t file_offset;
450 uint64_t min_vaddr_in_file = elf->ReadMinExecutableVaddr(&file_offset);
Yabin Cui32654f52019-12-11 16:50:24 -0800451 // min_vaddr_in_file is the min vaddr of executable segments. It may not be page aligned.
452 // And dynamic linker will create map mapping to (segment.p_vaddr & PAGE_MASK).
453 uint64_t aligned_segment_vaddr = min_vaddr_in_file & PAGE_MASK;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800454 const char* jit_str = "__jit_debug_descriptor";
455 const char* dex_str = "__dex_debug_descriptor";
456 uint64_t jit_addr = 0u;
457 uint64_t dex_addr = 0u;
458
459 auto callback = [&](const ElfFileSymbol& symbol) {
460 if (symbol.name == jit_str) {
Yabin Cui32654f52019-12-11 16:50:24 -0800461 jit_addr = symbol.vaddr - aligned_segment_vaddr;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800462 } else if (symbol.name == dex_str) {
Yabin Cui32654f52019-12-11 16:50:24 -0800463 dex_addr = symbol.vaddr - aligned_segment_vaddr;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800464 }
465 };
Yabin Cui01947032020-06-30 14:36:46 -0700466 elf->ParseDynamicSymbols(callback);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800467 if (jit_addr == 0u || dex_addr == 0u) {
Yabin Cuic8571d42018-06-06 11:20:39 -0700468 return nullptr;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800469 }
Yabin Cuie5defe12022-03-23 15:55:50 -0700470 location.is_64bit = elf->Is64Bit();
471 location.jit_descriptor_addr = jit_addr;
472 location.dex_descriptor_addr = dex_addr;
Yabin Cuic8571d42018-06-06 11:20:39 -0700473 return &location;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800474}
475
Yabin Cuic8571d42018-06-06 11:20:39 -0700476bool JITDebugReader::ReadRemoteMem(Process& process, uint64_t remote_addr, uint64_t size,
477 void* data) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800478 iovec local_iov;
479 local_iov.iov_base = data;
480 local_iov.iov_len = size;
481 iovec remote_iov;
482 remote_iov.iov_base = reinterpret_cast<void*>(static_cast<uintptr_t>(remote_addr));
483 remote_iov.iov_len = size;
Yabin Cuic8571d42018-06-06 11:20:39 -0700484 ssize_t result = process_vm_readv(process.pid, &local_iov, 1, &remote_iov, 1, 0);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800485 if (static_cast<size_t>(result) != size) {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200486 PLOG(DEBUG) << "ReadRemoteMem("
487 << " pid " << process.pid << ", addr " << std::hex << remote_addr << ", size "
488 << size << ") failed";
Yabin Cuic8571d42018-06-06 11:20:39 -0700489 process.died = true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800490 return false;
491 }
492 return true;
493}
494
Yabin Cuic8571d42018-06-06 11:20:39 -0700495bool JITDebugReader::ReadDescriptors(Process& process, Descriptor* jit_descriptor,
496 Descriptor* dex_descriptor) {
Yabin Cuie5defe12022-03-23 15:55:50 -0700497 if (process.is_64bit) {
498 return ReadDescriptorsImpl<JITDescriptor64>(process, jit_descriptor, dex_descriptor);
499 }
500 return ReadDescriptorsImpl<JITDescriptor32>(process, jit_descriptor, dex_descriptor);
501}
502
503template <typename DescriptorT>
504bool JITDebugReader::ReadDescriptorsImpl(Process& process, Descriptor* jit_descriptor,
505 Descriptor* dex_descriptor) {
506 DescriptorT raw_jit_descriptor;
507 DescriptorT raw_dex_descriptor;
508 iovec local_iovs[2];
509 local_iovs[0].iov_base = &raw_jit_descriptor;
510 local_iovs[0].iov_len = sizeof(DescriptorT);
511 local_iovs[1].iov_base = &raw_dex_descriptor;
512 local_iovs[1].iov_len = sizeof(DescriptorT);
513 iovec remote_iovs[2];
514 remote_iovs[0].iov_base =
515 reinterpret_cast<void*>(static_cast<uintptr_t>(process.jit_descriptor_addr));
516 remote_iovs[0].iov_len = sizeof(DescriptorT);
517 remote_iovs[1].iov_base =
518 reinterpret_cast<void*>(static_cast<uintptr_t>(process.dex_descriptor_addr));
519 remote_iovs[1].iov_len = sizeof(DescriptorT);
520 ssize_t result = process_vm_readv(process.pid, local_iovs, 2, remote_iovs, 2, 0);
521 if (static_cast<size_t>(result) != sizeof(DescriptorT) * 2) {
522 PLOG(DEBUG) << "ReadDescriptor(pid " << process.pid << ", jit_addr " << std::hex
523 << process.jit_descriptor_addr << ", dex_addr " << process.dex_descriptor_addr
524 << ") failed";
525 process.died = true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800526 return false;
527 }
Yabin Cuie5defe12022-03-23 15:55:50 -0700528
529 if (!ParseDescriptor(raw_jit_descriptor, jit_descriptor) ||
530 !ParseDescriptor(raw_dex_descriptor, dex_descriptor)) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700531 return false;
532 }
533 jit_descriptor->type = DescriptorType::kJIT;
534 dex_descriptor->type = DescriptorType::kDEX;
535 return true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800536}
537
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700538template <typename DescriptorT>
Yabin Cuie5defe12022-03-23 15:55:50 -0700539bool JITDebugReader::ParseDescriptor(const DescriptorT& raw_descriptor, Descriptor* descriptor) {
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700540 if (!raw_descriptor.Valid()) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800541 return false;
542 }
543 descriptor->action_seqlock = raw_descriptor.action_seqlock;
544 descriptor->action_timestamp = raw_descriptor.action_timestamp;
545 descriptor->first_entry_addr = raw_descriptor.first_entry_addr;
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700546 descriptor->version = raw_descriptor.AndroidVersion();
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800547 return true;
548}
549
550// Read new code entries with timestamp > last_action_timestamp.
551// Since we don't stop the app process while reading code entries, it is possible we are reading
552// broken data. So return false once we detect that the data is broken.
Yabin Cuic8571d42018-06-06 11:20:39 -0700553bool JITDebugReader::ReadNewCodeEntries(Process& process, const Descriptor& descriptor,
554 uint64_t last_action_timestamp, uint32_t read_entry_limit,
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800555 std::vector<CodeEntry>* new_code_entries) {
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700556 if (descriptor.version == 1) {
557 if (process.is_64bit) {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200558 return ReadNewCodeEntriesImpl<JITCodeEntry64>(process, descriptor, last_action_timestamp,
559 read_entry_limit, new_code_entries);
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700560 }
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200561 return ReadNewCodeEntriesImpl<JITCodeEntry32>(process, descriptor, last_action_timestamp,
562 read_entry_limit, new_code_entries);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800563 }
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700564 if (descriptor.version == 2) {
565 if (process.is_64bit) {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200566 return ReadNewCodeEntriesImpl<JITCodeEntry64V2>(process, descriptor, last_action_timestamp,
567 read_entry_limit, new_code_entries);
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700568 }
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200569 return ReadNewCodeEntriesImpl<JITCodeEntry32V2>(process, descriptor, last_action_timestamp,
570 read_entry_limit, new_code_entries);
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700571 }
572 return false;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800573}
574
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700575template <typename CodeEntryT>
Yabin Cuic8571d42018-06-06 11:20:39 -0700576bool JITDebugReader::ReadNewCodeEntriesImpl(Process& process, const Descriptor& descriptor,
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800577 uint64_t last_action_timestamp,
Yabin Cuic8571d42018-06-06 11:20:39 -0700578 uint32_t read_entry_limit,
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800579 std::vector<CodeEntry>* new_code_entries) {
580 uint64_t current_entry_addr = descriptor.first_entry_addr;
581 uint64_t prev_entry_addr = 0u;
582 std::unordered_set<uint64_t> entry_addr_set;
Yabin Cuic8571d42018-06-06 11:20:39 -0700583 for (size_t i = 0u; i < read_entry_limit && current_entry_addr != 0u; ++i) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800584 if (entry_addr_set.find(current_entry_addr) != entry_addr_set.end()) {
585 // We enter a loop, which means a broken linked list.
586 return false;
587 }
588 CodeEntryT entry;
Yabin Cuic8571d42018-06-06 11:20:39 -0700589 if (!ReadRemoteMem(process, current_entry_addr, sizeof(entry), &entry)) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800590 return false;
591 }
592 if (entry.prev_addr != prev_entry_addr || !entry.Valid()) {
593 // A broken linked list
594 return false;
595 }
596 if (entry.register_timestamp <= last_action_timestamp) {
597 // The linked list has entries with timestamp in decreasing order. So stop searching
598 // once we hit an entry with timestamp <= last_action_timestmap.
599 break;
600 }
Yabin Cui991a3e12019-10-30 16:07:28 -0700601 if (entry.symfile_size > 0) {
602 CodeEntry code_entry;
603 code_entry.addr = current_entry_addr;
604 code_entry.symfile_addr = entry.symfile_addr;
605 code_entry.symfile_size = entry.symfile_size;
606 code_entry.timestamp = entry.register_timestamp;
607 new_code_entries->push_back(code_entry);
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700608 }
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800609 entry_addr_set.insert(current_entry_addr);
610 prev_entry_addr = current_entry_addr;
611 current_entry_addr = entry.next_addr;
612 }
613 return true;
614}
615
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700616bool JITDebugReader::ReadJITCodeDebugInfo(Process& process,
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700617 const std::vector<CodeEntry>& jit_entries,
618 std::vector<JITDebugInfo>* debug_info) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800619 std::vector<char> data;
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700620
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800621 for (auto& jit_entry : jit_entries) {
622 if (jit_entry.symfile_size > MAX_JIT_SYMFILE_SIZE) {
623 continue;
624 }
625 if (data.size() < jit_entry.symfile_size) {
626 data.resize(jit_entry.symfile_size);
627 }
Yabin Cuic8571d42018-06-06 11:20:39 -0700628 if (!ReadRemoteMem(process, jit_entry.symfile_addr, jit_entry.symfile_size, data.data())) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800629 continue;
630 }
631 if (!IsValidElfFileMagic(data.data(), jit_entry.symfile_size)) {
632 continue;
633 }
Yabin Cui7f94b472020-08-03 21:11:32 +0000634 TempSymFile* symfile = GetTempSymFile(process, jit_entry);
635 if (symfile == nullptr) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700636 return false;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800637 }
Yabin Cui7f94b472020-08-03 21:11:32 +0000638 uint64_t file_offset = symfile->GetOffset();
639 if (!symfile->WriteEntry(data.data(), jit_entry.symfile_size)) {
640 return false;
641 }
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700642
Yabin Cui39ccd9c2019-10-07 15:57:56 -0700643 auto callback = [&](const ElfFileSymbol& symbol) {
Yabin Cui991a3e12019-10-30 16:07:28 -0700644 if (symbol.len == 0) { // Some arm labels can have zero length.
645 return;
646 }
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700647 // Pass out the location of the symfile for unwinding and symbolization.
648 std::string location_in_file =
649 StringPrintf(":%" PRIu64 "-%" PRIu64, file_offset, file_offset + jit_entry.symfile_size);
Yabin Cui39ccd9c2019-10-07 15:57:56 -0700650 debug_info->emplace_back(process.pid, jit_entry.timestamp, symbol.vaddr, symbol.len,
Yabin Cui7f94b472020-08-03 21:11:32 +0000651 symfile->GetPath() + location_in_file, file_offset);
652
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200653 LOG(VERBOSE) << "JITSymbol " << symbol.name << " at [" << std::hex << symbol.vaddr << " - "
654 << (symbol.vaddr + symbol.len) << " with size " << symbol.len << " in "
655 << symfile->GetPath() << location_in_file;
Yabin Cui39ccd9c2019-10-07 15:57:56 -0700656 };
Yabin Cui01947032020-06-30 14:36:46 -0700657 ElfStatus status;
658 auto elf = ElfFile::Open(data.data(), jit_entry.symfile_size, &status);
659 if (elf) {
660 elf->ParseSymbols(callback);
661 }
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800662 }
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700663
Yabin Cui7f94b472020-08-03 21:11:32 +0000664 if (app_symfile_) {
665 app_symfile_->Flush();
666 }
667 if (zygote_symfile_) {
668 zygote_symfile_->Flush();
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700669 }
670 return true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800671}
672
Yabin Cui7f94b472020-08-03 21:11:32 +0000673TempSymFile* JITDebugReader::GetTempSymFile(Process& process, const CodeEntry& jit_entry) {
674 bool is_zygote = false;
675 for (const auto& range : process.jit_zygote_cache_ranges_) {
676 if (jit_entry.symfile_addr >= range.first && jit_entry.symfile_addr < range.second) {
677 is_zygote = true;
678 break;
679 }
680 }
681 if (is_zygote) {
682 if (!zygote_symfile_) {
Yabin Cui075dd182020-08-05 19:51:36 +0000683 std::string path = symfile_prefix_ + "_" + kJITZygoteCacheFile;
Yabin Cui7f94b472020-08-03 21:11:32 +0000684 zygote_symfile_ =
685 TempSymFile::Create(std::move(path), symfile_option_ == SymFileOption::kDropSymFiles);
686 }
687 return zygote_symfile_.get();
688 }
689 if (!app_symfile_) {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200690 std::string path = symfile_prefix_ + "_" + kJITAppCacheFile;
691 app_symfile_ =
692 TempSymFile::Create(std::move(path), symfile_option_ == SymFileOption::kDropSymFiles);
Yabin Cui7f94b472020-08-03 21:11:32 +0000693 }
694 return app_symfile_.get();
695}
696
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700697void JITDebugReader::ReadDexFileDebugInfo(Process& process,
698 const std::vector<CodeEntry>& dex_entries,
699 std::vector<JITDebugInfo>* debug_info) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800700 std::vector<ThreadMmap> thread_mmaps;
Yabin Cuic8571d42018-06-06 11:20:39 -0700701 if (!GetThreadMmapsInProcess(process.pid, &thread_mmaps)) {
702 process.died = true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800703 return;
704 }
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200705 auto comp = [](const ThreadMmap& map, uint64_t addr) { return map.start_addr <= addr; };
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800706 for (auto& dex_entry : dex_entries) {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200707 auto it =
708 std::lower_bound(thread_mmaps.begin(), thread_mmaps.end(), dex_entry.symfile_addr, comp);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800709 if (it == thread_mmaps.begin()) {
710 continue;
711 }
712 --it;
713 if (it->start_addr + it->len < dex_entry.symfile_addr + dex_entry.symfile_size) {
714 continue;
715 }
Yabin Cui2a53ff32018-05-21 17:37:00 -0700716 std::string file_path;
717 std::string zip_path;
718 std::string entry_path;
Yabin Cui400892e2019-05-31 10:39:56 -0700719 std::shared_ptr<ThreadMmap> extracted_dex_file_map;
Yabin Cui2a53ff32018-05-21 17:37:00 -0700720 if (ParseExtractedInMemoryPath(it->name, &zip_path, &entry_path)) {
721 file_path = GetUrlInApk(zip_path, entry_path);
Yabin Cui400892e2019-05-31 10:39:56 -0700722 extracted_dex_file_map = std::make_shared<ThreadMmap>(*it);
Yabin Cui2a53ff32018-05-21 17:37:00 -0700723 } else {
724 if (!IsRegularFile(it->name)) {
725 // TODO: read dex file only exist in memory?
726 continue;
727 }
728 file_path = it->name;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800729 }
730 // Offset of dex file in .vdex file or .apk file.
731 uint64_t dex_file_offset = dex_entry.symfile_addr - it->start_addr + it->pgoff;
Yabin Cui400892e2019-05-31 10:39:56 -0700732 debug_info->emplace_back(process.pid, dex_entry.timestamp, dex_file_offset, file_path,
733 extracted_dex_file_map);
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200734 LOG(VERBOSE) << "DexFile " << file_path << "+" << std::hex << dex_file_offset << " in map ["
735 << it->start_addr << " - " << (it->start_addr + it->len) << "] with size "
736 << dex_entry.symfile_size;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800737 }
738}
739
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700740bool JITDebugReader::AddDebugInfo(const std::vector<JITDebugInfo>& debug_info,
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200741 bool sync_kernel_records) {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700742 if (!debug_info.empty()) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700743 if (sync_option_ == SyncOption::kSyncWithRecords) {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700744 for (auto& info : debug_info) {
745 debug_info_q_.push(std::move(info));
746 }
747 } else {
748 return debug_info_callback_(debug_info, sync_kernel_records);
749 }
750 }
751 return true;
752}
753
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800754} // namespace simpleperf