1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/perf/regs_parsing.h"
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard Worker #include <linux/perf_event.h>
20*6dbdd20aSAndroid Build Coastguard Worker #include <stdint.h>
21*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>
22*6dbdd20aSAndroid Build Coastguard Worker
23*6dbdd20aSAndroid Build Coastguard Worker #include <cinttypes>
24*6dbdd20aSAndroid Build Coastguard Worker #include <memory>
25*6dbdd20aSAndroid Build Coastguard Worker
26*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/Elf.h>
27*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/MachineArm.h>
28*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/MachineArm64.h>
29*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/MachineRiscv64.h>
30*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/Regs.h>
31*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/RegsArm.h>
32*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/RegsArm64.h>
33*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/RegsRiscv64.h>
34*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/RegsX86.h>
35*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/RegsX86_64.h>
36*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/UserArm.h>
37*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/UserArm64.h>
38*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/UserRiscv64.h>
39*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/UserX86.h>
40*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/UserX86_64.h>
41*6dbdd20aSAndroid Build Coastguard Worker
42*6dbdd20aSAndroid Build Coastguard Worker // kernel uapi headers
43*6dbdd20aSAndroid Build Coastguard Worker #include <uapi/asm-arm/asm/perf_regs.h>
44*6dbdd20aSAndroid Build Coastguard Worker #undef PERF_REG_EXTENDED_MASK
45*6dbdd20aSAndroid Build Coastguard Worker #include <uapi/asm-x86/asm/perf_regs.h>
46*6dbdd20aSAndroid Build Coastguard Worker #undef PERF_REG_EXTENDED_MASK
47*6dbdd20aSAndroid Build Coastguard Worker #define perf_event_arm_regs perf_event_arm64_regs
48*6dbdd20aSAndroid Build Coastguard Worker #include <uapi/asm-arm64/asm/perf_regs.h>
49*6dbdd20aSAndroid Build Coastguard Worker #undef PERF_REG_EXTENDED_MASK
50*6dbdd20aSAndroid Build Coastguard Worker #undef perf_event_arm_regs
51*6dbdd20aSAndroid Build Coastguard Worker #include <uapi/asm-riscv/asm/perf_regs.h>
52*6dbdd20aSAndroid Build Coastguard Worker #undef PERF_REG_EXTENDED_MASK
53*6dbdd20aSAndroid Build Coastguard Worker
54*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
55*6dbdd20aSAndroid Build Coastguard Worker namespace profiling {
56*6dbdd20aSAndroid Build Coastguard Worker
57*6dbdd20aSAndroid Build Coastguard Worker namespace {
58*6dbdd20aSAndroid Build Coastguard Worker
constexpr_max(size_t x,size_t y)59*6dbdd20aSAndroid Build Coastguard Worker constexpr size_t constexpr_max(size_t x, size_t y) {
60*6dbdd20aSAndroid Build Coastguard Worker return x > y ? x : y;
61*6dbdd20aSAndroid Build Coastguard Worker }
62*6dbdd20aSAndroid Build Coastguard Worker
63*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
ReadValue(T * value_out,const char * ptr)64*6dbdd20aSAndroid Build Coastguard Worker const char* ReadValue(T* value_out, const char* ptr) {
65*6dbdd20aSAndroid Build Coastguard Worker memcpy(value_out, reinterpret_cast<const void*>(ptr), sizeof(T));
66*6dbdd20aSAndroid Build Coastguard Worker return ptr + sizeof(T);
67*6dbdd20aSAndroid Build Coastguard Worker }
68*6dbdd20aSAndroid Build Coastguard Worker
69*6dbdd20aSAndroid Build Coastguard Worker // Supported configurations:
70*6dbdd20aSAndroid Build Coastguard Worker // * 32 bit daemon, 32 bit userspace
71*6dbdd20aSAndroid Build Coastguard Worker // * 64 bit daemon, mixed bitness userspace
72*6dbdd20aSAndroid Build Coastguard Worker // Therefore give the kernel the mask corresponding to our build architecture.
73*6dbdd20aSAndroid Build Coastguard Worker // Register parsing handles the mixed userspace ABI cases.
74*6dbdd20aSAndroid Build Coastguard Worker // For simplicity, we ask for as many registers as we can, even if not all of
75*6dbdd20aSAndroid Build Coastguard Worker // them will be used during unwinding.
76*6dbdd20aSAndroid Build Coastguard Worker // TODO(rsavitski): cleanly detect 32 bit traced_perf builds being side-loaded
77*6dbdd20aSAndroid Build Coastguard Worker // onto a system with 64 bit userspace processes.
PerfUserRegsMask(unwindstack::ArchEnum arch)78*6dbdd20aSAndroid Build Coastguard Worker uint64_t PerfUserRegsMask(unwindstack::ArchEnum arch) {
79*6dbdd20aSAndroid Build Coastguard Worker switch (static_cast<uint8_t>(arch)) { // cast to please -Wswitch-enum
80*6dbdd20aSAndroid Build Coastguard Worker case unwindstack::ARCH_ARM64:
81*6dbdd20aSAndroid Build Coastguard Worker return (1ULL << PERF_REG_ARM64_MAX) - 1;
82*6dbdd20aSAndroid Build Coastguard Worker case unwindstack::ARCH_ARM:
83*6dbdd20aSAndroid Build Coastguard Worker return (1ULL << PERF_REG_ARM_MAX) - 1;
84*6dbdd20aSAndroid Build Coastguard Worker // perf on x86_64 doesn't allow sampling ds/es/fs/gs registers. See
85*6dbdd20aSAndroid Build Coastguard Worker // arch/x86/kernel/perf_regs.c in the kernel.
86*6dbdd20aSAndroid Build Coastguard Worker case unwindstack::ARCH_X86_64:
87*6dbdd20aSAndroid Build Coastguard Worker return (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~(1ULL << PERF_REG_X86_DS) &
88*6dbdd20aSAndroid Build Coastguard Worker ~(1ULL << PERF_REG_X86_ES) & ~(1ULL << PERF_REG_X86_FS) &
89*6dbdd20aSAndroid Build Coastguard Worker ~(1ULL << PERF_REG_X86_GS));
90*6dbdd20aSAndroid Build Coastguard Worker // Note: excluding these segment registers might not be necessary on x86,
91*6dbdd20aSAndroid Build Coastguard Worker // but they won't be used anyway (so follow x64).
92*6dbdd20aSAndroid Build Coastguard Worker case unwindstack::ARCH_X86:
93*6dbdd20aSAndroid Build Coastguard Worker return ((1ULL << PERF_REG_X86_32_MAX) - 1) & ~(1ULL << PERF_REG_X86_DS) &
94*6dbdd20aSAndroid Build Coastguard Worker ~(1ULL << PERF_REG_X86_ES) & ~(1ULL << PERF_REG_X86_FS) &
95*6dbdd20aSAndroid Build Coastguard Worker ~(1ULL << PERF_REG_X86_GS);
96*6dbdd20aSAndroid Build Coastguard Worker case unwindstack::ARCH_RISCV64:
97*6dbdd20aSAndroid Build Coastguard Worker return (1ULL << PERF_REG_RISCV_MAX) - 1;
98*6dbdd20aSAndroid Build Coastguard Worker default:
99*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_FATAL("Unsupported architecture");
100*6dbdd20aSAndroid Build Coastguard Worker }
101*6dbdd20aSAndroid Build Coastguard Worker }
102*6dbdd20aSAndroid Build Coastguard Worker
103*6dbdd20aSAndroid Build Coastguard Worker // Adjusts the given architecture enum based on the ABI (as recorded in the perf
104*6dbdd20aSAndroid Build Coastguard Worker // sample). Note: we do not support 64 bit samples on a 32 bit daemon build, so
105*6dbdd20aSAndroid Build Coastguard Worker // this only converts from 64 bit to 32 bit architectures.
106*6dbdd20aSAndroid Build Coastguard Worker // TODO(rsavitski): on riscv64, are 32 bit userspace processes posible?
ArchForAbi(unwindstack::ArchEnum arch,uint64_t abi)107*6dbdd20aSAndroid Build Coastguard Worker unwindstack::ArchEnum ArchForAbi(unwindstack::ArchEnum arch, uint64_t abi) {
108*6dbdd20aSAndroid Build Coastguard Worker if (arch == unwindstack::ARCH_ARM64 && abi == PERF_SAMPLE_REGS_ABI_32) {
109*6dbdd20aSAndroid Build Coastguard Worker return unwindstack::ARCH_ARM;
110*6dbdd20aSAndroid Build Coastguard Worker }
111*6dbdd20aSAndroid Build Coastguard Worker if (arch == unwindstack::ARCH_X86_64 && abi == PERF_SAMPLE_REGS_ABI_32) {
112*6dbdd20aSAndroid Build Coastguard Worker return unwindstack::ARCH_X86;
113*6dbdd20aSAndroid Build Coastguard Worker }
114*6dbdd20aSAndroid Build Coastguard Worker return arch;
115*6dbdd20aSAndroid Build Coastguard Worker }
116*6dbdd20aSAndroid Build Coastguard Worker
117*6dbdd20aSAndroid Build Coastguard Worker // Register values as an array, indexed using the kernel uapi perf_events.h enum
118*6dbdd20aSAndroid Build Coastguard Worker // values. Unsampled values will be left as zeroes.
119*6dbdd20aSAndroid Build Coastguard Worker struct RawRegisterData {
120*6dbdd20aSAndroid Build Coastguard Worker static constexpr uint64_t kMaxSize =
121*6dbdd20aSAndroid Build Coastguard Worker constexpr_max(constexpr_max(PERF_REG_ARM_MAX, PERF_REG_ARM64_MAX),
122*6dbdd20aSAndroid Build Coastguard Worker constexpr_max(PERF_REG_X86_64_MAX, PERF_REG_RISCV_MAX));
123*6dbdd20aSAndroid Build Coastguard Worker uint64_t regs[kMaxSize] = {};
124*6dbdd20aSAndroid Build Coastguard Worker };
125*6dbdd20aSAndroid Build Coastguard Worker
126*6dbdd20aSAndroid Build Coastguard Worker // First converts the |RawRegisterData| array to libunwindstack's "user"
127*6dbdd20aSAndroid Build Coastguard Worker // register structs (which match the ptrace/coredump format, also available at
128*6dbdd20aSAndroid Build Coastguard Worker // <sys/user.h>), then constructs the relevant unwindstack::Regs subclass out
129*6dbdd20aSAndroid Build Coastguard Worker // of the latter.
ToLibUnwindstackRegs(const RawRegisterData & raw_regs,unwindstack::ArchEnum arch)130*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<unwindstack::Regs> ToLibUnwindstackRegs(
131*6dbdd20aSAndroid Build Coastguard Worker const RawRegisterData& raw_regs,
132*6dbdd20aSAndroid Build Coastguard Worker unwindstack::ArchEnum arch) {
133*6dbdd20aSAndroid Build Coastguard Worker if (arch == unwindstack::ARCH_ARM64) {
134*6dbdd20aSAndroid Build Coastguard Worker static_assert(static_cast<int>(unwindstack::ARM64_REG_R0) ==
135*6dbdd20aSAndroid Build Coastguard Worker static_cast<int>(PERF_REG_ARM64_X0) &&
136*6dbdd20aSAndroid Build Coastguard Worker static_cast<int>(unwindstack::ARM64_REG_R0) == 0,
137*6dbdd20aSAndroid Build Coastguard Worker "register layout mismatch");
138*6dbdd20aSAndroid Build Coastguard Worker static_assert(static_cast<int>(unwindstack::ARM64_REG_R30) ==
139*6dbdd20aSAndroid Build Coastguard Worker static_cast<int>(PERF_REG_ARM64_LR),
140*6dbdd20aSAndroid Build Coastguard Worker "register layout mismatch");
141*6dbdd20aSAndroid Build Coastguard Worker // Both the perf_event register order and the "user" format are derived from
142*6dbdd20aSAndroid Build Coastguard Worker // "struct pt_regs", so we can directly memcpy the first 31 regs (up to and
143*6dbdd20aSAndroid Build Coastguard Worker // including LR).
144*6dbdd20aSAndroid Build Coastguard Worker unwindstack::arm64_user_regs arm64_user_regs = {};
145*6dbdd20aSAndroid Build Coastguard Worker memcpy(&arm64_user_regs.regs[0], &raw_regs.regs[0],
146*6dbdd20aSAndroid Build Coastguard Worker sizeof(uint64_t) * (PERF_REG_ARM64_LR + 1));
147*6dbdd20aSAndroid Build Coastguard Worker arm64_user_regs.sp = raw_regs.regs[PERF_REG_ARM64_SP];
148*6dbdd20aSAndroid Build Coastguard Worker arm64_user_regs.pc = raw_regs.regs[PERF_REG_ARM64_PC];
149*6dbdd20aSAndroid Build Coastguard Worker return std::unique_ptr<unwindstack::Regs>(
150*6dbdd20aSAndroid Build Coastguard Worker unwindstack::RegsArm64::Read(&arm64_user_regs));
151*6dbdd20aSAndroid Build Coastguard Worker }
152*6dbdd20aSAndroid Build Coastguard Worker
153*6dbdd20aSAndroid Build Coastguard Worker if (arch == unwindstack::ARCH_ARM) {
154*6dbdd20aSAndroid Build Coastguard Worker static_assert(static_cast<int>(unwindstack::ARM_REG_R0) ==
155*6dbdd20aSAndroid Build Coastguard Worker static_cast<int>(PERF_REG_ARM_R0) &&
156*6dbdd20aSAndroid Build Coastguard Worker static_cast<int>(unwindstack::ARM_REG_R0) == 0,
157*6dbdd20aSAndroid Build Coastguard Worker "register layout mismatch");
158*6dbdd20aSAndroid Build Coastguard Worker static_assert(static_cast<int>(unwindstack::ARM_REG_LAST) ==
159*6dbdd20aSAndroid Build Coastguard Worker static_cast<int>(PERF_REG_ARM_MAX),
160*6dbdd20aSAndroid Build Coastguard Worker "register layout mismatch");
161*6dbdd20aSAndroid Build Coastguard Worker // As with arm64, the layouts match, but we need to downcast to u32.
162*6dbdd20aSAndroid Build Coastguard Worker unwindstack::arm_user_regs arm_user_regs = {};
163*6dbdd20aSAndroid Build Coastguard Worker for (size_t i = 0; i < unwindstack::ARM_REG_LAST; i++) {
164*6dbdd20aSAndroid Build Coastguard Worker arm_user_regs.regs[i] = static_cast<uint32_t>(raw_regs.regs[i]);
165*6dbdd20aSAndroid Build Coastguard Worker }
166*6dbdd20aSAndroid Build Coastguard Worker return std::unique_ptr<unwindstack::Regs>(
167*6dbdd20aSAndroid Build Coastguard Worker unwindstack::RegsArm::Read(&arm_user_regs));
168*6dbdd20aSAndroid Build Coastguard Worker }
169*6dbdd20aSAndroid Build Coastguard Worker
170*6dbdd20aSAndroid Build Coastguard Worker if (arch == unwindstack::ARCH_X86_64) {
171*6dbdd20aSAndroid Build Coastguard Worker // We've sampled more registers than what libunwindstack will use. Don't
172*6dbdd20aSAndroid Build Coastguard Worker // copy over cs/ss/flags.
173*6dbdd20aSAndroid Build Coastguard Worker unwindstack::x86_64_user_regs x86_64_user_regs = {};
174*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.rax = raw_regs.regs[PERF_REG_X86_AX];
175*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.rbx = raw_regs.regs[PERF_REG_X86_BX];
176*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.rcx = raw_regs.regs[PERF_REG_X86_CX];
177*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.rdx = raw_regs.regs[PERF_REG_X86_DX];
178*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.r8 = raw_regs.regs[PERF_REG_X86_R8];
179*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.r9 = raw_regs.regs[PERF_REG_X86_R9];
180*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.r10 = raw_regs.regs[PERF_REG_X86_R10];
181*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.r11 = raw_regs.regs[PERF_REG_X86_R11];
182*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.r12 = raw_regs.regs[PERF_REG_X86_R12];
183*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.r13 = raw_regs.regs[PERF_REG_X86_R13];
184*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.r14 = raw_regs.regs[PERF_REG_X86_R14];
185*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.r15 = raw_regs.regs[PERF_REG_X86_R15];
186*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.rdi = raw_regs.regs[PERF_REG_X86_DI];
187*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.rsi = raw_regs.regs[PERF_REG_X86_SI];
188*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.rbp = raw_regs.regs[PERF_REG_X86_BP];
189*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.rsp = raw_regs.regs[PERF_REG_X86_SP];
190*6dbdd20aSAndroid Build Coastguard Worker x86_64_user_regs.rip = raw_regs.regs[PERF_REG_X86_IP];
191*6dbdd20aSAndroid Build Coastguard Worker return std::unique_ptr<unwindstack::Regs>(
192*6dbdd20aSAndroid Build Coastguard Worker unwindstack::RegsX86_64::Read(&x86_64_user_regs));
193*6dbdd20aSAndroid Build Coastguard Worker }
194*6dbdd20aSAndroid Build Coastguard Worker
195*6dbdd20aSAndroid Build Coastguard Worker if (arch == unwindstack::ARCH_X86) {
196*6dbdd20aSAndroid Build Coastguard Worker // We've sampled more registers than what libunwindstack will use. Don't
197*6dbdd20aSAndroid Build Coastguard Worker // copy over cs/ss/flags.
198*6dbdd20aSAndroid Build Coastguard Worker unwindstack::x86_user_regs x86_user_regs = {};
199*6dbdd20aSAndroid Build Coastguard Worker x86_user_regs.eax = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_AX]);
200*6dbdd20aSAndroid Build Coastguard Worker x86_user_regs.ebx = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_BX]);
201*6dbdd20aSAndroid Build Coastguard Worker x86_user_regs.ecx = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_CX]);
202*6dbdd20aSAndroid Build Coastguard Worker x86_user_regs.edx = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_DX]);
203*6dbdd20aSAndroid Build Coastguard Worker x86_user_regs.ebp = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_BP]);
204*6dbdd20aSAndroid Build Coastguard Worker x86_user_regs.edi = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_DI]);
205*6dbdd20aSAndroid Build Coastguard Worker x86_user_regs.esi = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_SI]);
206*6dbdd20aSAndroid Build Coastguard Worker x86_user_regs.esp = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_SP]);
207*6dbdd20aSAndroid Build Coastguard Worker x86_user_regs.eip = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_IP]);
208*6dbdd20aSAndroid Build Coastguard Worker return std::unique_ptr<unwindstack::Regs>(
209*6dbdd20aSAndroid Build Coastguard Worker unwindstack::RegsX86::Read(&x86_user_regs));
210*6dbdd20aSAndroid Build Coastguard Worker }
211*6dbdd20aSAndroid Build Coastguard Worker
212*6dbdd20aSAndroid Build Coastguard Worker if (arch == unwindstack::ARCH_RISCV64) {
213*6dbdd20aSAndroid Build Coastguard Worker static_assert(static_cast<int>(unwindstack::RISCV64_REG_PC) ==
214*6dbdd20aSAndroid Build Coastguard Worker static_cast<int>(PERF_REG_RISCV_PC) &&
215*6dbdd20aSAndroid Build Coastguard Worker static_cast<int>(unwindstack::RISCV64_REG_PC) == 0,
216*6dbdd20aSAndroid Build Coastguard Worker "register layout mismatch");
217*6dbdd20aSAndroid Build Coastguard Worker static_assert(static_cast<int>(unwindstack::RISCV64_REG_REAL_COUNT) ==
218*6dbdd20aSAndroid Build Coastguard Worker static_cast<int>(PERF_REG_RISCV_MAX),
219*6dbdd20aSAndroid Build Coastguard Worker "register layout mismatch");
220*6dbdd20aSAndroid Build Coastguard Worker // Register layout matches, pass the raw data to the Read call.
221*6dbdd20aSAndroid Build Coastguard Worker return std::unique_ptr<unwindstack::Regs>(
222*6dbdd20aSAndroid Build Coastguard Worker unwindstack::RegsRiscv64::Read(&raw_regs.regs[0]));
223*6dbdd20aSAndroid Build Coastguard Worker }
224*6dbdd20aSAndroid Build Coastguard Worker
225*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_FATAL("Unsupported architecture");
226*6dbdd20aSAndroid Build Coastguard Worker }
227*6dbdd20aSAndroid Build Coastguard Worker
228*6dbdd20aSAndroid Build Coastguard Worker } // namespace
229*6dbdd20aSAndroid Build Coastguard Worker
PerfUserRegsMaskForArch(unwindstack::ArchEnum arch)230*6dbdd20aSAndroid Build Coastguard Worker uint64_t PerfUserRegsMaskForArch(unwindstack::ArchEnum arch) {
231*6dbdd20aSAndroid Build Coastguard Worker return PerfUserRegsMask(arch);
232*6dbdd20aSAndroid Build Coastguard Worker }
233*6dbdd20aSAndroid Build Coastguard Worker
234*6dbdd20aSAndroid Build Coastguard Worker // Assumes that the sampling was configured with
235*6dbdd20aSAndroid Build Coastguard Worker // |PerfUserRegsMaskForArch(unwindstack::Regs::CurrentArch())|.
ReadPerfUserRegsData(const char ** data)236*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<unwindstack::Regs> ReadPerfUserRegsData(const char** data) {
237*6dbdd20aSAndroid Build Coastguard Worker unwindstack::ArchEnum requested_arch = unwindstack::Regs::CurrentArch();
238*6dbdd20aSAndroid Build Coastguard Worker
239*6dbdd20aSAndroid Build Coastguard Worker // Layout, assuming a sparse bitmask requesting r1 and r15:
240*6dbdd20aSAndroid Build Coastguard Worker // userspace thread: [u64 abi] [u64 r1] [u64 r15]
241*6dbdd20aSAndroid Build Coastguard Worker // kernel thread: [u64 abi]
242*6dbdd20aSAndroid Build Coastguard Worker const char* parse_pos = *data;
243*6dbdd20aSAndroid Build Coastguard Worker uint64_t sampled_abi;
244*6dbdd20aSAndroid Build Coastguard Worker parse_pos = ReadValue(&sampled_abi, parse_pos);
245*6dbdd20aSAndroid Build Coastguard Worker
246*6dbdd20aSAndroid Build Coastguard Worker // ABI_NONE means there were no registers, as we've sampled a kernel thread,
247*6dbdd20aSAndroid Build Coastguard Worker // which doesn't have userspace registers.
248*6dbdd20aSAndroid Build Coastguard Worker if (sampled_abi == PERF_SAMPLE_REGS_ABI_NONE) {
249*6dbdd20aSAndroid Build Coastguard Worker *data = parse_pos; // adjust caller's parsing position
250*6dbdd20aSAndroid Build Coastguard Worker return nullptr;
251*6dbdd20aSAndroid Build Coastguard Worker }
252*6dbdd20aSAndroid Build Coastguard Worker
253*6dbdd20aSAndroid Build Coastguard Worker // Unpack the densely-packed register values into |RawRegisterData|, which has
254*6dbdd20aSAndroid Build Coastguard Worker // a value for every register (unsampled registers will be left at zero).
255*6dbdd20aSAndroid Build Coastguard Worker RawRegisterData raw_regs{};
256*6dbdd20aSAndroid Build Coastguard Worker uint64_t regs_mask = PerfUserRegsMaskForArch(requested_arch);
257*6dbdd20aSAndroid Build Coastguard Worker for (size_t i = 0; regs_mask && (i < RawRegisterData::kMaxSize); i++) {
258*6dbdd20aSAndroid Build Coastguard Worker if (regs_mask & (1ULL << i)) {
259*6dbdd20aSAndroid Build Coastguard Worker parse_pos = ReadValue(&raw_regs.regs[i], parse_pos);
260*6dbdd20aSAndroid Build Coastguard Worker }
261*6dbdd20aSAndroid Build Coastguard Worker }
262*6dbdd20aSAndroid Build Coastguard Worker
263*6dbdd20aSAndroid Build Coastguard Worker // Special case: we've requested arm64 registers from a 64 bit kernel, but
264*6dbdd20aSAndroid Build Coastguard Worker // ended up sampling a 32 bit arm userspace process. The 32 bit execution
265*6dbdd20aSAndroid Build Coastguard Worker // state of the target process was saved by the exception entry in an
266*6dbdd20aSAndroid Build Coastguard Worker // ISA-specific way. The userspace R0-R14 end up saved as arm64 W0-W14, but
267*6dbdd20aSAndroid Build Coastguard Worker // the program counter (R15 on arm32) is still in PERF_REG_ARM64_PC (the 33rd
268*6dbdd20aSAndroid Build Coastguard Worker // register). So we can take the kernel-dumped 64 bit register state, reassign
269*6dbdd20aSAndroid Build Coastguard Worker // the PC into the R15 slot, and treat the resulting RawRegisterData as an
270*6dbdd20aSAndroid Build Coastguard Worker // arm32 register bank. See "Fundamentals of ARMv8-A" (ARM DOC
271*6dbdd20aSAndroid Build Coastguard Worker // 100878_0100_en), page 28.
272*6dbdd20aSAndroid Build Coastguard Worker // x86-64 doesn't need any such fixups.
273*6dbdd20aSAndroid Build Coastguard Worker if (requested_arch == unwindstack::ARCH_ARM64 &&
274*6dbdd20aSAndroid Build Coastguard Worker sampled_abi == PERF_SAMPLE_REGS_ABI_32) {
275*6dbdd20aSAndroid Build Coastguard Worker raw_regs.regs[PERF_REG_ARM_PC] = raw_regs.regs[PERF_REG_ARM64_PC];
276*6dbdd20aSAndroid Build Coastguard Worker }
277*6dbdd20aSAndroid Build Coastguard Worker
278*6dbdd20aSAndroid Build Coastguard Worker *data = parse_pos; // adjust caller's parsing position
279*6dbdd20aSAndroid Build Coastguard Worker
280*6dbdd20aSAndroid Build Coastguard Worker unwindstack::ArchEnum sampled_arch = ArchForAbi(requested_arch, sampled_abi);
281*6dbdd20aSAndroid Build Coastguard Worker return ToLibUnwindstackRegs(raw_regs, sampled_arch);
282*6dbdd20aSAndroid Build Coastguard Worker }
283*6dbdd20aSAndroid Build Coastguard Worker
284*6dbdd20aSAndroid Build Coastguard Worker } // namespace profiling
285*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
286