blob: b5430c70c0c1edc325c1e2566a66dc63a9811251 [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 Cui8b8ed0f2023-10-24 16:18:38 -070040#include "read_dex_file.h"
Yabin Cui9e43e9f2018-03-09 15:57:13 -080041#include "read_elf.h"
42#include "utils.h"
43
Yabin Cuifaa7b922021-01-11 17:35:57 -080044namespace simpleperf {
45
Yabin Cui42eb3d22023-10-25 11:59:09 -070046using namespace JITDebugReader_impl;
Yabin Cui7f94b472020-08-03 21:11:32 +000047using android::base::StartsWith;
Yabin Cuie32ed2b2020-07-23 15:30:14 -070048using android::base::StringPrintf;
49
Yabin Cui9e43e9f2018-03-09 15:57:13 -080050// If the size of a symfile is larger than EXPECTED_MAX_SYMFILE_SIZE, we don't want to read it
51// remotely.
Yabin Cuicfdc7832023-03-02 15:35:01 -080052static constexpr size_t MAX_JIT_SYMFILE_SIZE = 1 * kMegabyte;
Yabin Cui9e43e9f2018-03-09 15:57:13 -080053
Yabin Cuic8571d42018-06-06 11:20:39 -070054// It takes about 30us-130us on Pixel (depending on the cpu frequency) to check if the descriptors
55// have been updated (most time spent in process_vm_preadv). We want to know if the JIT debug info
56// changed as soon as possible, while not wasting too much time checking for updates. So use a
57// period of 100 ms.
58// In system wide profiling, we may need to check JIT debug info changes for many processes, to
59// avoid spending all time checking, wait 100 ms between any two checks.
60static constexpr size_t kUpdateJITDebugInfoIntervalInMs = 100;
61
Yabin Cui7f94b472020-08-03 21:11:32 +000062// map name used for jit zygote cache
63static const char* kJITZygoteCacheMmapPrefix = "/memfd:jit-zygote-cache";
64
Yabin Cui62fa6ee2019-10-07 15:15:12 -070065// Match the format of JITDescriptor in art/runtime/jit/debugger_interface.cc.
Yabin Cui9e43e9f2018-03-09 15:57:13 -080066template <typename ADDRT>
67struct JITDescriptor {
68 uint32_t version;
69 uint32_t action_flag;
70 ADDRT relevant_entry_addr;
71 ADDRT first_entry_addr;
72 uint8_t magic[8];
73 uint32_t flags;
74 uint32_t sizeof_descriptor;
75 uint32_t sizeof_entry;
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +020076 uint32_t action_seqlock; // incremented before and after any modification
Yabin Cui9e43e9f2018-03-09 15:57:13 -080077 uint64_t action_timestamp; // CLOCK_MONOTONIC time of last action
78
Yabin Cui62fa6ee2019-10-07 15:15:12 -070079 bool Valid() const;
80
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +020081 int AndroidVersion() const { return magic[7] - '0'; }
Yabin Cui9e43e9f2018-03-09 15:57:13 -080082};
83
Yabin Cui62fa6ee2019-10-07 15:15:12 -070084// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
85// with JITDescriptor.magic == "Android1".
Yabin Cui9e43e9f2018-03-09 15:57:13 -080086template <typename ADDRT>
87struct JITCodeEntry {
88 ADDRT next_addr;
89 ADDRT prev_addr;
90 ADDRT symfile_addr;
91 uint64_t symfile_size;
92 uint64_t register_timestamp; // CLOCK_MONOTONIC time of entry registration
93
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +020094 bool Valid() const { return symfile_addr > 0u && symfile_size > 0u; }
Yabin Cui9e43e9f2018-03-09 15:57:13 -080095};
96
Yabin Cui62fa6ee2019-10-07 15:15:12 -070097// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
98// with JITDescriptor.magic == "Android1".
Yabin Cui9e43e9f2018-03-09 15:57:13 -080099template <typename ADDRT>
100struct __attribute__((packed)) PackedJITCodeEntry {
101 ADDRT next_addr;
102 ADDRT prev_addr;
103 ADDRT symfile_addr;
104 uint64_t symfile_size;
105 uint64_t register_timestamp;
106
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200107 bool Valid() const { return symfile_addr > 0u && symfile_size > 0u; }
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800108};
109
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700110// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
111// with JITDescriptor.magic == "Android2".
112template <typename ADDRT>
113struct JITCodeEntryV2 {
114 ADDRT next_addr;
115 ADDRT prev_addr;
116 ADDRT symfile_addr;
117 uint64_t symfile_size;
118 uint64_t register_timestamp; // CLOCK_MONOTONIC time of entry registration
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200119 uint32_t seqlock; // even value if valid
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700120
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200121 bool Valid() const { return (seqlock & 1) == 0; }
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700122};
123
124// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
125// with JITDescriptor.magic == "Android2".
126template <typename ADDRT>
127struct __attribute__((packed)) PackedJITCodeEntryV2 {
128 ADDRT next_addr;
129 ADDRT prev_addr;
130 ADDRT symfile_addr;
131 uint64_t symfile_size;
132 uint64_t register_timestamp;
133 uint32_t seqlock;
134
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200135 bool Valid() const { return (seqlock & 1) == 0; }
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700136};
137
138// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
139// with JITDescriptor.magic == "Android2".
140template <typename ADDRT>
141struct __attribute__((packed)) PaddedJITCodeEntryV2 {
142 ADDRT next_addr;
143 ADDRT prev_addr;
144 ADDRT symfile_addr;
145 uint64_t symfile_size;
146 uint64_t register_timestamp;
147 uint32_t seqlock;
148 uint32_t pad;
149
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200150 bool Valid() const { return (seqlock & 1) == 0; }
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700151};
152
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800153using JITDescriptor32 = JITDescriptor<uint32_t>;
154using 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.
158using JITCodeEntry32 = PackedJITCodeEntry<uint32_t>;
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700159using JITCodeEntry32V2 = PackedJITCodeEntryV2<uint32_t>;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800160#else
161using JITCodeEntry32 = JITCodeEntry<uint32_t>;
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700162using JITCodeEntry32V2 = JITCodeEntryV2<uint32_t>;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800163#endif
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700164
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800165using JITCodeEntry64 = JITCodeEntry<uint64_t>;
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700166#if defined(__i386__)
167// Make sure simpleperf built for i386 and x86_64 see the correct JITCodeEntry layout of x86_64.
168using JITCodeEntry64V2 = PaddedJITCodeEntryV2<uint64_t>;
169#else
170using JITCodeEntry64V2 = JITCodeEntryV2<uint64_t>;
171#endif
172
173template <typename ADDRT>
174bool 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}
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800190
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.
194static_assert(sizeof(JITDescriptor32) == 48, "");
195static_assert(sizeof(JITDescriptor64) == 56, "");
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700196
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800197#if defined(__i386__) or defined(__x86_64__)
198static_assert(sizeof(JITCodeEntry32) == 28, "");
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700199static_assert(sizeof(JITCodeEntry32V2) == 32, "");
200static_assert(sizeof(JITCodeEntry64) == 40, "");
201static_assert(sizeof(JITCodeEntry64V2) == 48, "");
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800202#else
203static_assert(sizeof(JITCodeEntry32) == 32, "");
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700204static_assert(sizeof(JITCodeEntry32V2) == 40, "");
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800205static_assert(sizeof(JITCodeEntry64) == 40, "");
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700206static_assert(sizeof(JITCodeEntry64V2) == 48, "");
207#endif
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800208
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700209JITDebugReader::JITDebugReader(const std::string& symfile_prefix, SymFileOption symfile_option,
210 SyncOption sync_option)
211 : symfile_prefix_(symfile_prefix), symfile_option_(symfile_option), sync_option_(sync_option) {}
212
213JITDebugReader::~JITDebugReader() {}
214
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700215bool JITDebugReader::RegisterDebugInfoCallback(IOEventLoop* loop,
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200216 const debug_info_callback_t& callback) {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700217 debug_info_callback_ = callback;
Yabin Cuic8571d42018-06-06 11:20:39 -0700218 read_event_ = loop->AddPeriodicEvent(SecondToTimeval(kUpdateJITDebugInfoIntervalInMs / 1000.0),
219 [this]() { return ReadAllProcesses(); });
220 return (read_event_ != nullptr && IOEventLoop::DisableEvent(read_event_));
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800221}
222
Yabin Cuic8571d42018-06-06 11:20:39 -0700223bool JITDebugReader::MonitorProcess(pid_t pid) {
224 if (processes_.find(pid) == processes_.end()) {
225 processes_[pid].pid = pid;
226 LOG(DEBUG) << "Start monitoring process " << pid;
227 if (processes_.size() == 1u) {
228 if (!IOEventLoop::EnableEvent(read_event_)) {
229 return false;
230 }
231 }
232 }
233 return true;
234}
235
236static bool IsArtLib(const std::string& filename) {
237 return android::base::EndsWith(filename, "libart.so") ||
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200238 android::base::EndsWith(filename, "libartd.so");
Yabin Cuic8571d42018-06-06 11:20:39 -0700239}
240
241bool JITDebugReader::UpdateRecord(const Record* record) {
242 if (record->type() == PERF_RECORD_MMAP) {
243 auto r = static_cast<const MmapRecord*>(record);
244 if (IsArtLib(r->filename)) {
245 pids_with_art_lib_.emplace(r->data->pid, false);
246 }
247 } else if (record->type() == PERF_RECORD_MMAP2) {
248 auto r = static_cast<const Mmap2Record*>(record);
249 if (IsArtLib(r->filename)) {
250 pids_with_art_lib_.emplace(r->data->pid, false);
251 }
252 } else if (record->type() == PERF_RECORD_FORK) {
253 auto r = static_cast<const ForkRecord*>(record);
254 if (r->data->pid != r->data->ppid &&
255 pids_with_art_lib_.find(r->data->ppid) != pids_with_art_lib_.end()) {
256 pids_with_art_lib_.emplace(r->data->pid, false);
257 }
258 } else if (record->type() == PERF_RECORD_SAMPLE) {
259 auto r = static_cast<const SampleRecord*>(record);
260 auto it = pids_with_art_lib_.find(r->tid_data.pid);
261 if (it != pids_with_art_lib_.end() && !it->second) {
262 it->second = true;
263 if (!MonitorProcess(r->tid_data.pid)) {
264 return false;
265 }
266 return ReadProcess(r->tid_data.pid);
267 }
268 }
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700269 return FlushDebugInfo(record->Timestamp());
270}
271
272bool JITDebugReader::FlushDebugInfo(uint64_t timestamp) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700273 if (sync_option_ == SyncOption::kSyncWithRecords) {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700274 if (!debug_info_q_.empty() && debug_info_q_.top().timestamp < timestamp) {
275 std::vector<JITDebugInfo> debug_info;
276 while (!debug_info_q_.empty() && debug_info_q_.top().timestamp < timestamp) {
277 debug_info.emplace_back(debug_info_q_.top());
278 debug_info_q_.pop();
279 }
280 return debug_info_callback_(debug_info, false);
281 }
282 }
Yabin Cuic8571d42018-06-06 11:20:39 -0700283 return true;
284}
285
286bool JITDebugReader::ReadAllProcesses() {
287 if (!IOEventLoop::DisableEvent(read_event_)) {
288 return false;
289 }
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700290 std::vector<JITDebugInfo> debug_info;
Yabin Cuic8571d42018-06-06 11:20:39 -0700291 for (auto it = processes_.begin(); it != processes_.end();) {
292 Process& process = it->second;
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700293 if (!ReadProcess(process, &debug_info)) {
294 return false;
295 }
Yabin Cuic8571d42018-06-06 11:20:39 -0700296 if (process.died) {
297 LOG(DEBUG) << "Stop monitoring process " << process.pid;
298 it = processes_.erase(it);
299 } else {
300 ++it;
301 }
302 }
Yabin Cui8b8ed0f2023-10-24 16:18:38 -0700303 if (!AddDebugInfo(std::move(debug_info), true)) {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700304 return false;
Yabin Cuic8571d42018-06-06 11:20:39 -0700305 }
306 if (!processes_.empty()) {
307 return IOEventLoop::EnableEvent(read_event_);
308 }
309 return true;
310}
311
312bool JITDebugReader::ReadProcess(pid_t pid) {
313 auto it = processes_.find(pid);
314 if (it != processes_.end()) {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700315 std::vector<JITDebugInfo> debug_info;
Yabin Cui8b8ed0f2023-10-24 16:18:38 -0700316 return ReadProcess(it->second, &debug_info) && AddDebugInfo(std::move(debug_info), false);
Yabin Cuic8571d42018-06-06 11:20:39 -0700317 }
318 return true;
319}
320
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700321bool JITDebugReader::ReadProcess(Process& process, std::vector<JITDebugInfo>* debug_info) {
Yabin Cuic8571d42018-06-06 11:20:39 -0700322 if (process.died || (!process.initialized && !InitializeProcess(process))) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700323 return true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800324 }
325 // 1. Read descriptors.
326 Descriptor jit_descriptor;
327 Descriptor dex_descriptor;
Yabin Cuic8571d42018-06-06 11:20:39 -0700328 if (!ReadDescriptors(process, &jit_descriptor, &dex_descriptor)) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700329 return true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800330 }
331 // 2. Return if descriptors are not changed.
Yabin Cuic8571d42018-06-06 11:20:39 -0700332 if (jit_descriptor.action_seqlock == process.last_jit_descriptor.action_seqlock &&
333 dex_descriptor.action_seqlock == process.last_dex_descriptor.action_seqlock) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700334 return true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800335 }
336
337 // 3. Read new symfiles.
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700338 return ReadDebugInfo(process, jit_descriptor, debug_info) &&
339 ReadDebugInfo(process, dex_descriptor, debug_info);
340}
341
342bool JITDebugReader::ReadDebugInfo(Process& process, Descriptor& new_descriptor,
343 std::vector<JITDebugInfo>* debug_info) {
344 DescriptorType type = new_descriptor.type;
345 Descriptor* old_descriptor =
346 (type == DescriptorType::kJIT) ? &process.last_jit_descriptor : &process.last_dex_descriptor;
347
348 bool has_update = new_descriptor.action_seqlock != old_descriptor->action_seqlock &&
349 (new_descriptor.action_seqlock & 1) == 0;
350 LOG(DEBUG) << (type == DescriptorType::kJIT ? "JIT" : "Dex") << " symfiles of pid " << process.pid
351 << ": old seqlock " << old_descriptor->action_seqlock << ", new seqlock "
352 << new_descriptor.action_seqlock;
353 if (!has_update) {
354 return true;
355 }
356 std::vector<CodeEntry> new_entries;
357 // Adding or removing one code entry will make two increments of action_seqlock. So we should
358 // not read more than (seqlock_diff / 2) new entries.
359 uint32_t read_entry_limit = (new_descriptor.action_seqlock - old_descriptor->action_seqlock) / 2;
360 if (!ReadNewCodeEntries(process, new_descriptor, old_descriptor->action_timestamp,
361 read_entry_limit, &new_entries)) {
362 return true;
363 }
364 // If the descriptor was changed while we were reading new entries, skip reading debug info this
365 // time.
366 if (IsDescriptorChanged(process, new_descriptor)) {
367 return true;
368 }
369 LOG(DEBUG) << (type == DescriptorType::kJIT ? "JIT" : "Dex") << " symfiles of pid " << process.pid
370 << ": read " << new_entries.size() << " new entries";
371
372 if (!new_entries.empty()) {
373 if (type == DescriptorType::kJIT) {
374 if (!ReadJITCodeDebugInfo(process, new_entries, debug_info)) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800375 return false;
376 }
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800377 } else {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700378 ReadDexFileDebugInfo(process, new_entries, debug_info);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800379 }
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700380 }
381 *old_descriptor = new_descriptor;
382 return true;
383}
384
385bool JITDebugReader::IsDescriptorChanged(Process& process, Descriptor& prev_descriptor) {
386 Descriptor tmp_jit_descriptor;
387 Descriptor tmp_dex_descriptor;
388 if (!ReadDescriptors(process, &tmp_jit_descriptor, &tmp_dex_descriptor)) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800389 return true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800390 }
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700391 if (prev_descriptor.type == DescriptorType::kJIT) {
392 return prev_descriptor.action_seqlock != tmp_jit_descriptor.action_seqlock;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800393 }
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700394 return prev_descriptor.action_seqlock != tmp_dex_descriptor.action_seqlock;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800395}
396
Yabin Cuic8571d42018-06-06 11:20:39 -0700397bool JITDebugReader::InitializeProcess(Process& process) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800398 // 1. Read map file to find the location of libart.so.
399 std::vector<ThreadMmap> thread_mmaps;
Yabin Cuic8571d42018-06-06 11:20:39 -0700400 if (!GetThreadMmapsInProcess(process.pid, &thread_mmaps)) {
401 process.died = true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800402 return false;
403 }
404 std::string art_lib_path;
Yabin Cuic8571d42018-06-06 11:20:39 -0700405 uint64_t min_vaddr_in_memory;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800406 for (auto& map : thread_mmaps) {
Yabin Cui2db05b42018-07-16 14:04:49 -0700407 if ((map.prot & PROT_EXEC) && IsArtLib(map.name)) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800408 art_lib_path = map.name;
Yabin Cuic8571d42018-06-06 11:20:39 -0700409 min_vaddr_in_memory = map.start_addr;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800410 break;
411 }
412 }
413 if (art_lib_path.empty()) {
414 return false;
415 }
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800416
417 // 2. Read libart.so to find the addresses of __jit_debug_descriptor and __dex_debug_descriptor.
Yabin Cuie5defe12022-03-23 15:55:50 -0700418 const DescriptorsLocation* location = GetDescriptorsLocation(art_lib_path);
Yabin Cuic8571d42018-06-06 11:20:39 -0700419 if (location == nullptr) {
420 return false;
421 }
Yabin Cuie5defe12022-03-23 15:55:50 -0700422 process.is_64bit = location->is_64bit;
423 process.jit_descriptor_addr = location->jit_descriptor_addr + min_vaddr_in_memory;
424 process.dex_descriptor_addr = location->dex_descriptor_addr + min_vaddr_in_memory;
Yabin Cui7f94b472020-08-03 21:11:32 +0000425
426 for (auto& map : thread_mmaps) {
427 if (StartsWith(map.name, kJITZygoteCacheMmapPrefix)) {
428 process.jit_zygote_cache_ranges_.emplace_back(map.start_addr, map.start_addr + map.len);
429 }
430 }
431
Yabin Cuic8571d42018-06-06 11:20:39 -0700432 process.initialized = true;
433 return true;
434}
435
436const JITDebugReader::DescriptorsLocation* JITDebugReader::GetDescriptorsLocation(
Yabin Cuie5defe12022-03-23 15:55:50 -0700437 const std::string& art_lib_path) {
Yabin Cuic8571d42018-06-06 11:20:39 -0700438 auto it = descriptors_location_cache_.find(art_lib_path);
439 if (it != descriptors_location_cache_.end()) {
Yabin Cuie5defe12022-03-23 15:55:50 -0700440 return it->second.jit_descriptor_addr == 0u ? nullptr : &it->second;
Yabin Cuic8571d42018-06-06 11:20:39 -0700441 }
442 DescriptorsLocation& location = descriptors_location_cache_[art_lib_path];
443
444 // Read libart.so to find the addresses of __jit_debug_descriptor and __dex_debug_descriptor.
Yabin Cui90c3b302020-07-01 10:09:16 -0700445 ElfStatus status;
446 auto elf = ElfFile::Open(art_lib_path, &status);
447 if (!elf) {
448 LOG(ERROR) << "failed to read min_exec_vaddr from " << art_lib_path << ": " << status;
Yabin Cuic8571d42018-06-06 11:20:39 -0700449 return nullptr;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800450 }
Juan Yescas48e2d9c2023-08-18 05:37:24 +0000451
452 const size_t kPageSize = getpagesize();
453 const size_t kPageMask = ~(kPageSize - 1);
Yabin Cui90c3b302020-07-01 10:09:16 -0700454 uint64_t file_offset;
455 uint64_t min_vaddr_in_file = elf->ReadMinExecutableVaddr(&file_offset);
Yabin Cui32654f52019-12-11 16:50:24 -0800456 // min_vaddr_in_file is the min vaddr of executable segments. It may not be page aligned.
Juan Yescas48e2d9c2023-08-18 05:37:24 +0000457 // And dynamic linker will create map mapping to (segment.p_vaddr & kPageMask).
458 uint64_t aligned_segment_vaddr = min_vaddr_in_file & kPageMask;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800459 const char* jit_str = "__jit_debug_descriptor";
460 const char* dex_str = "__dex_debug_descriptor";
461 uint64_t jit_addr = 0u;
462 uint64_t dex_addr = 0u;
463
464 auto callback = [&](const ElfFileSymbol& symbol) {
465 if (symbol.name == jit_str) {
Yabin Cui32654f52019-12-11 16:50:24 -0800466 jit_addr = symbol.vaddr - aligned_segment_vaddr;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800467 } else if (symbol.name == dex_str) {
Yabin Cui32654f52019-12-11 16:50:24 -0800468 dex_addr = symbol.vaddr - aligned_segment_vaddr;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800469 }
470 };
Yabin Cui01947032020-06-30 14:36:46 -0700471 elf->ParseDynamicSymbols(callback);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800472 if (jit_addr == 0u || dex_addr == 0u) {
Yabin Cuic8571d42018-06-06 11:20:39 -0700473 return nullptr;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800474 }
Yabin Cuie5defe12022-03-23 15:55:50 -0700475 location.is_64bit = elf->Is64Bit();
476 location.jit_descriptor_addr = jit_addr;
477 location.dex_descriptor_addr = dex_addr;
Yabin Cuic8571d42018-06-06 11:20:39 -0700478 return &location;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800479}
480
Yabin Cuic8571d42018-06-06 11:20:39 -0700481bool JITDebugReader::ReadRemoteMem(Process& process, uint64_t remote_addr, uint64_t size,
482 void* data) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800483 iovec local_iov;
484 local_iov.iov_base = data;
485 local_iov.iov_len = size;
486 iovec remote_iov;
487 remote_iov.iov_base = reinterpret_cast<void*>(static_cast<uintptr_t>(remote_addr));
488 remote_iov.iov_len = size;
Yabin Cuic8571d42018-06-06 11:20:39 -0700489 ssize_t result = process_vm_readv(process.pid, &local_iov, 1, &remote_iov, 1, 0);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800490 if (static_cast<size_t>(result) != size) {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200491 PLOG(DEBUG) << "ReadRemoteMem("
492 << " pid " << process.pid << ", addr " << std::hex << remote_addr << ", size "
493 << size << ") failed";
Yabin Cuic8571d42018-06-06 11:20:39 -0700494 process.died = true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800495 return false;
496 }
497 return true;
498}
499
Yabin Cuic8571d42018-06-06 11:20:39 -0700500bool JITDebugReader::ReadDescriptors(Process& process, Descriptor* jit_descriptor,
501 Descriptor* dex_descriptor) {
Yabin Cuie5defe12022-03-23 15:55:50 -0700502 if (process.is_64bit) {
503 return ReadDescriptorsImpl<JITDescriptor64>(process, jit_descriptor, dex_descriptor);
504 }
505 return ReadDescriptorsImpl<JITDescriptor32>(process, jit_descriptor, dex_descriptor);
506}
507
508template <typename DescriptorT>
509bool JITDebugReader::ReadDescriptorsImpl(Process& process, Descriptor* jit_descriptor,
510 Descriptor* dex_descriptor) {
511 DescriptorT raw_jit_descriptor;
512 DescriptorT raw_dex_descriptor;
513 iovec local_iovs[2];
514 local_iovs[0].iov_base = &raw_jit_descriptor;
515 local_iovs[0].iov_len = sizeof(DescriptorT);
516 local_iovs[1].iov_base = &raw_dex_descriptor;
517 local_iovs[1].iov_len = sizeof(DescriptorT);
518 iovec remote_iovs[2];
519 remote_iovs[0].iov_base =
520 reinterpret_cast<void*>(static_cast<uintptr_t>(process.jit_descriptor_addr));
521 remote_iovs[0].iov_len = sizeof(DescriptorT);
522 remote_iovs[1].iov_base =
523 reinterpret_cast<void*>(static_cast<uintptr_t>(process.dex_descriptor_addr));
524 remote_iovs[1].iov_len = sizeof(DescriptorT);
525 ssize_t result = process_vm_readv(process.pid, local_iovs, 2, remote_iovs, 2, 0);
526 if (static_cast<size_t>(result) != sizeof(DescriptorT) * 2) {
527 PLOG(DEBUG) << "ReadDescriptor(pid " << process.pid << ", jit_addr " << std::hex
528 << process.jit_descriptor_addr << ", dex_addr " << process.dex_descriptor_addr
529 << ") failed";
530 process.died = true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800531 return false;
532 }
Yabin Cuie5defe12022-03-23 15:55:50 -0700533
534 if (!ParseDescriptor(raw_jit_descriptor, jit_descriptor) ||
535 !ParseDescriptor(raw_dex_descriptor, dex_descriptor)) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700536 return false;
537 }
538 jit_descriptor->type = DescriptorType::kJIT;
539 dex_descriptor->type = DescriptorType::kDEX;
540 return true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800541}
542
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700543template <typename DescriptorT>
Yabin Cuie5defe12022-03-23 15:55:50 -0700544bool JITDebugReader::ParseDescriptor(const DescriptorT& raw_descriptor, Descriptor* descriptor) {
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700545 if (!raw_descriptor.Valid()) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800546 return false;
547 }
548 descriptor->action_seqlock = raw_descriptor.action_seqlock;
549 descriptor->action_timestamp = raw_descriptor.action_timestamp;
550 descriptor->first_entry_addr = raw_descriptor.first_entry_addr;
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700551 descriptor->version = raw_descriptor.AndroidVersion();
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800552 return true;
553}
554
555// Read new code entries with timestamp > last_action_timestamp.
556// Since we don't stop the app process while reading code entries, it is possible we are reading
557// broken data. So return false once we detect that the data is broken.
Yabin Cuic8571d42018-06-06 11:20:39 -0700558bool JITDebugReader::ReadNewCodeEntries(Process& process, const Descriptor& descriptor,
559 uint64_t last_action_timestamp, uint32_t read_entry_limit,
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800560 std::vector<CodeEntry>* new_code_entries) {
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700561 if (descriptor.version == 1) {
562 if (process.is_64bit) {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200563 return ReadNewCodeEntriesImpl<JITCodeEntry64>(process, descriptor, last_action_timestamp,
564 read_entry_limit, new_code_entries);
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700565 }
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200566 return ReadNewCodeEntriesImpl<JITCodeEntry32>(process, descriptor, last_action_timestamp,
567 read_entry_limit, new_code_entries);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800568 }
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700569 if (descriptor.version == 2) {
570 if (process.is_64bit) {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200571 return ReadNewCodeEntriesImpl<JITCodeEntry64V2>(process, descriptor, last_action_timestamp,
572 read_entry_limit, new_code_entries);
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700573 }
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200574 return ReadNewCodeEntriesImpl<JITCodeEntry32V2>(process, descriptor, last_action_timestamp,
575 read_entry_limit, new_code_entries);
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700576 }
577 return false;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800578}
579
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700580template <typename CodeEntryT>
Yabin Cuic8571d42018-06-06 11:20:39 -0700581bool JITDebugReader::ReadNewCodeEntriesImpl(Process& process, const Descriptor& descriptor,
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800582 uint64_t last_action_timestamp,
Yabin Cuic8571d42018-06-06 11:20:39 -0700583 uint32_t read_entry_limit,
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800584 std::vector<CodeEntry>* new_code_entries) {
585 uint64_t current_entry_addr = descriptor.first_entry_addr;
586 uint64_t prev_entry_addr = 0u;
587 std::unordered_set<uint64_t> entry_addr_set;
Yabin Cuic8571d42018-06-06 11:20:39 -0700588 for (size_t i = 0u; i < read_entry_limit && current_entry_addr != 0u; ++i) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800589 if (entry_addr_set.find(current_entry_addr) != entry_addr_set.end()) {
590 // We enter a loop, which means a broken linked list.
591 return false;
592 }
593 CodeEntryT entry;
Yabin Cuic8571d42018-06-06 11:20:39 -0700594 if (!ReadRemoteMem(process, current_entry_addr, sizeof(entry), &entry)) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800595 return false;
596 }
597 if (entry.prev_addr != prev_entry_addr || !entry.Valid()) {
598 // A broken linked list
599 return false;
600 }
601 if (entry.register_timestamp <= last_action_timestamp) {
602 // The linked list has entries with timestamp in decreasing order. So stop searching
603 // once we hit an entry with timestamp <= last_action_timestmap.
604 break;
605 }
Yabin Cui991a3e12019-10-30 16:07:28 -0700606 if (entry.symfile_size > 0) {
607 CodeEntry code_entry;
608 code_entry.addr = current_entry_addr;
609 code_entry.symfile_addr = entry.symfile_addr;
610 code_entry.symfile_size = entry.symfile_size;
611 code_entry.timestamp = entry.register_timestamp;
612 new_code_entries->push_back(code_entry);
Yabin Cui62fa6ee2019-10-07 15:15:12 -0700613 }
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800614 entry_addr_set.insert(current_entry_addr);
615 prev_entry_addr = current_entry_addr;
616 current_entry_addr = entry.next_addr;
617 }
618 return true;
619}
620
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700621bool JITDebugReader::ReadJITCodeDebugInfo(Process& process,
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700622 const std::vector<CodeEntry>& jit_entries,
623 std::vector<JITDebugInfo>* debug_info) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800624 std::vector<char> data;
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700625
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800626 for (auto& jit_entry : jit_entries) {
627 if (jit_entry.symfile_size > MAX_JIT_SYMFILE_SIZE) {
628 continue;
629 }
630 if (data.size() < jit_entry.symfile_size) {
631 data.resize(jit_entry.symfile_size);
632 }
Yabin Cuic8571d42018-06-06 11:20:39 -0700633 if (!ReadRemoteMem(process, jit_entry.symfile_addr, jit_entry.symfile_size, data.data())) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800634 continue;
635 }
636 if (!IsValidElfFileMagic(data.data(), jit_entry.symfile_size)) {
637 continue;
638 }
Yabin Cui7f94b472020-08-03 21:11:32 +0000639 TempSymFile* symfile = GetTempSymFile(process, jit_entry);
640 if (symfile == nullptr) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700641 return false;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800642 }
Yabin Cui7f94b472020-08-03 21:11:32 +0000643 uint64_t file_offset = symfile->GetOffset();
644 if (!symfile->WriteEntry(data.data(), jit_entry.symfile_size)) {
645 return false;
646 }
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700647
Yabin Cui39ccd9c2019-10-07 15:57:56 -0700648 auto callback = [&](const ElfFileSymbol& symbol) {
Yabin Cui991a3e12019-10-30 16:07:28 -0700649 if (symbol.len == 0) { // Some arm labels can have zero length.
650 return;
651 }
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700652 // Pass out the location of the symfile for unwinding and symbolization.
653 std::string location_in_file =
654 StringPrintf(":%" PRIu64 "-%" PRIu64, file_offset, file_offset + jit_entry.symfile_size);
Yabin Cui39ccd9c2019-10-07 15:57:56 -0700655 debug_info->emplace_back(process.pid, jit_entry.timestamp, symbol.vaddr, symbol.len,
Yabin Cui7f94b472020-08-03 21:11:32 +0000656 symfile->GetPath() + location_in_file, file_offset);
657
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200658 LOG(VERBOSE) << "JITSymbol " << symbol.name << " at [" << std::hex << symbol.vaddr << " - "
659 << (symbol.vaddr + symbol.len) << " with size " << symbol.len << " in "
660 << symfile->GetPath() << location_in_file;
Yabin Cui39ccd9c2019-10-07 15:57:56 -0700661 };
Yabin Cui01947032020-06-30 14:36:46 -0700662 ElfStatus status;
663 auto elf = ElfFile::Open(data.data(), jit_entry.symfile_size, &status);
664 if (elf) {
665 elf->ParseSymbols(callback);
666 }
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800667 }
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700668
Yabin Cui7f94b472020-08-03 21:11:32 +0000669 if (app_symfile_) {
670 app_symfile_->Flush();
671 }
672 if (zygote_symfile_) {
673 zygote_symfile_->Flush();
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700674 }
675 return true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800676}
677
Yabin Cui7f94b472020-08-03 21:11:32 +0000678TempSymFile* JITDebugReader::GetTempSymFile(Process& process, const CodeEntry& jit_entry) {
679 bool is_zygote = false;
680 for (const auto& range : process.jit_zygote_cache_ranges_) {
681 if (jit_entry.symfile_addr >= range.first && jit_entry.symfile_addr < range.second) {
682 is_zygote = true;
683 break;
684 }
685 }
686 if (is_zygote) {
687 if (!zygote_symfile_) {
Yabin Cui075dd182020-08-05 19:51:36 +0000688 std::string path = symfile_prefix_ + "_" + kJITZygoteCacheFile;
Yabin Cui7f94b472020-08-03 21:11:32 +0000689 zygote_symfile_ =
690 TempSymFile::Create(std::move(path), symfile_option_ == SymFileOption::kDropSymFiles);
691 }
692 return zygote_symfile_.get();
693 }
694 if (!app_symfile_) {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200695 std::string path = symfile_prefix_ + "_" + kJITAppCacheFile;
696 app_symfile_ =
697 TempSymFile::Create(std::move(path), symfile_option_ == SymFileOption::kDropSymFiles);
Yabin Cui7f94b472020-08-03 21:11:32 +0000698 }
699 return app_symfile_.get();
700}
701
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700702void JITDebugReader::ReadDexFileDebugInfo(Process& process,
703 const std::vector<CodeEntry>& dex_entries,
704 std::vector<JITDebugInfo>* debug_info) {
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800705 std::vector<ThreadMmap> thread_mmaps;
Yabin Cuic8571d42018-06-06 11:20:39 -0700706 if (!GetThreadMmapsInProcess(process.pid, &thread_mmaps)) {
707 process.died = true;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800708 return;
709 }
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200710 auto comp = [](const ThreadMmap& map, uint64_t addr) { return map.start_addr <= addr; };
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800711 for (auto& dex_entry : dex_entries) {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200712 auto it =
713 std::lower_bound(thread_mmaps.begin(), thread_mmaps.end(), dex_entry.symfile_addr, comp);
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800714 if (it == thread_mmaps.begin()) {
715 continue;
716 }
717 --it;
718 if (it->start_addr + it->len < dex_entry.symfile_addr + dex_entry.symfile_size) {
719 continue;
720 }
Yabin Cui2a53ff32018-05-21 17:37:00 -0700721 std::string file_path;
722 std::string zip_path;
723 std::string entry_path;
Yabin Cui8b8ed0f2023-10-24 16:18:38 -0700724 std::shared_ptr<ThreadMmap> dex_file_map;
725 std::vector<Symbol> symbols;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800726 // Offset of dex file in .vdex file or .apk file.
727 uint64_t dex_file_offset = dex_entry.symfile_addr - it->start_addr + it->pgoff;
Yabin Cui8b8ed0f2023-10-24 16:18:38 -0700728 if (ParseExtractedInMemoryPath(it->name, &zip_path, &entry_path)) {
729 file_path = GetUrlInApk(zip_path, entry_path);
730 dex_file_map = std::make_shared<ThreadMmap>(*it);
731 } else if (IsRegularFile(it->name)) {
732 file_path = it->name;
733 } else {
734 // Read a dex file only existing in memory.
735 file_path = StringPrintf("%s_pid_%d_addr_0x%" PRIx64 "-0x%" PRIx64 "", kDexFileInMemoryPrefix,
736 process.pid, dex_entry.symfile_addr,
737 dex_entry.symfile_addr + dex_entry.symfile_size);
738 dex_file_map.reset(new ThreadMmap(dex_entry.symfile_addr, dex_entry.symfile_size, 0,
739 file_path.c_str(), PROT_READ));
740 symbols = ReadDexFileSymbolsInMemory(process, dex_entry.symfile_addr, dex_entry.symfile_size);
741 dex_file_offset = 0;
742 }
743
Yabin Cui400892e2019-05-31 10:39:56 -0700744 debug_info->emplace_back(process.pid, dex_entry.timestamp, dex_file_offset, file_path,
Yabin Cui8b8ed0f2023-10-24 16:18:38 -0700745 dex_file_map, std::move(symbols));
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200746 LOG(VERBOSE) << "DexFile " << file_path << "+" << std::hex << dex_file_offset << " in map ["
747 << it->start_addr << " - " << (it->start_addr + it->len) << "] with size "
748 << dex_entry.symfile_size;
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800749 }
750}
751
Yabin Cui8b8ed0f2023-10-24 16:18:38 -0700752std::vector<Symbol> JITDebugReader::ReadDexFileSymbolsInMemory(Process& process, uint64_t addr,
753 uint64_t size) {
754 std::vector<Symbol> symbols;
755 std::vector<uint8_t> data(size, 0);
756 if (!ReadRemoteMem(process, addr, size, data.data())) {
757 LOG(DEBUG) << "failed to read dex file in memory for process " << process.pid << ", addr "
758 << std::hex << addr << "-" << (addr + size);
759 return symbols;
760 }
761
762 auto process_symbol = [&](DexFileSymbol* symbol) {
763 symbols.emplace_back(symbol->name, symbol->addr, symbol->size);
764 };
765 if (!ReadSymbolsFromDexFileInMemory(data.data(), data.size(), "dex_file_in_memory", {0},
766 process_symbol)) {
767 LOG(DEBUG) << "failed to parse dex file in memory for process " << process.pid << ", addr "
768 << std::hex << addr << "-" << (addr + size);
769 return symbols;
770 }
771 std::sort(symbols.begin(), symbols.end(), Symbol::CompareValueByAddr);
772 return symbols;
773}
774
775bool JITDebugReader::AddDebugInfo(std::vector<JITDebugInfo> debug_info, bool sync_kernel_records) {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700776 if (!debug_info.empty()) {
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700777 if (sync_option_ == SyncOption::kSyncWithRecords) {
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700778 for (auto& info : debug_info) {
779 debug_info_q_.push(std::move(info));
780 }
781 } else {
Yabin Cui8b8ed0f2023-10-24 16:18:38 -0700782 return debug_info_callback_(std::move(debug_info), sync_kernel_records);
Yabin Cui5d5c01a2018-08-27 10:30:20 -0700783 }
784 }
785 return true;
786}
787
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800788} // namespace simpleperf