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