xref: /aosp_15_r20/external/cronet/base/profiler/register_context.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2019 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker //
5*6777b538SAndroid Build Coastguard Worker // This file provides the RegisterContext cross-platform typedef that represents
6*6777b538SAndroid Build Coastguard Worker // the native register context for the platform, plus functions that provide
7*6777b538SAndroid Build Coastguard Worker // access to key registers in the context.
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #ifndef BASE_PROFILER_REGISTER_CONTEXT_H_
10*6777b538SAndroid Build Coastguard Worker #define BASE_PROFILER_REGISTER_CONTEXT_H_
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include <cstdint>
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
17*6777b538SAndroid Build Coastguard Worker #include <windows.h>
18*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_APPLE)
19*6777b538SAndroid Build Coastguard Worker #include <mach/machine/thread_status.h>
20*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
21*6777b538SAndroid Build Coastguard Worker #include <sys/ucontext.h>
22*6777b538SAndroid Build Coastguard Worker #endif
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker namespace base {
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker // Helper function to account for the fact that platform-specific register state
27*6777b538SAndroid Build Coastguard Worker // types may be of the same size as uintptr_t, but not of the same type or
28*6777b538SAndroid Build Coastguard Worker // signedness -- e.g. unsigned int vs. unsigned long on 32-bit Windows, unsigned
29*6777b538SAndroid Build Coastguard Worker // long vs. unsigned long long on Mac, long long vs. unsigned long long on
30*6777b538SAndroid Build Coastguard Worker // Linux.
31*6777b538SAndroid Build Coastguard Worker template <typename T>
AsUintPtr(T * value)32*6777b538SAndroid Build Coastguard Worker uintptr_t& AsUintPtr(T* value) {
33*6777b538SAndroid Build Coastguard Worker   static_assert(sizeof(T) == sizeof(uintptr_t),
34*6777b538SAndroid Build Coastguard Worker                 "register state type must be of equivalent size to uintptr_t");
35*6777b538SAndroid Build Coastguard Worker   return *reinterpret_cast<uintptr_t*>(value);
36*6777b538SAndroid Build Coastguard Worker }
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker using RegisterContext = ::CONTEXT;
41*6777b538SAndroid Build Coastguard Worker 
RegisterContextStackPointer(::CONTEXT * context)42*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextStackPointer(::CONTEXT* context) {
43*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_64)
44*6777b538SAndroid Build Coastguard Worker   return context->Rsp;
45*6777b538SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_ARM64)
46*6777b538SAndroid Build Coastguard Worker   return context->Sp;
47*6777b538SAndroid Build Coastguard Worker #else
48*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->Esp);
49*6777b538SAndroid Build Coastguard Worker #endif
50*6777b538SAndroid Build Coastguard Worker }
51*6777b538SAndroid Build Coastguard Worker 
RegisterContextFramePointer(::CONTEXT * context)52*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextFramePointer(::CONTEXT* context) {
53*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_64)
54*6777b538SAndroid Build Coastguard Worker   return context->Rbp;
55*6777b538SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_ARM64)
56*6777b538SAndroid Build Coastguard Worker   return context->Fp;
57*6777b538SAndroid Build Coastguard Worker #else
58*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->Ebp);
59*6777b538SAndroid Build Coastguard Worker #endif
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker 
RegisterContextInstructionPointer(::CONTEXT * context)62*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextInstructionPointer(::CONTEXT* context) {
63*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_64)
64*6777b538SAndroid Build Coastguard Worker   return context->Rip;
65*6777b538SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_ARM64)
66*6777b538SAndroid Build Coastguard Worker   return context->Pc;
67*6777b538SAndroid Build Coastguard Worker #else
68*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->Eip);
69*6777b538SAndroid Build Coastguard Worker #endif
70*6777b538SAndroid Build Coastguard Worker }
71*6777b538SAndroid Build Coastguard Worker 
72*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_MAC) || BUILDFLAG(IS_IOS)
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_64)
75*6777b538SAndroid Build Coastguard Worker using RegisterContext = x86_thread_state64_t;
76*6777b538SAndroid Build Coastguard Worker 
RegisterContextStackPointer(x86_thread_state64_t * context)77*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextStackPointer(x86_thread_state64_t* context) {
78*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->__rsp);
79*6777b538SAndroid Build Coastguard Worker }
80*6777b538SAndroid Build Coastguard Worker 
RegisterContextFramePointer(x86_thread_state64_t * context)81*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextFramePointer(x86_thread_state64_t* context) {
82*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->__rbp);
83*6777b538SAndroid Build Coastguard Worker }
84*6777b538SAndroid Build Coastguard Worker 
RegisterContextInstructionPointer(x86_thread_state64_t * context)85*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextInstructionPointer(
86*6777b538SAndroid Build Coastguard Worker     x86_thread_state64_t* context) {
87*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->__rip);
88*6777b538SAndroid Build Coastguard Worker }
89*6777b538SAndroid Build Coastguard Worker 
90*6777b538SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_ARM64)  // defined(ARCH_CPU_X86_64)
91*6777b538SAndroid Build Coastguard Worker using RegisterContext = arm_thread_state64_t;
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker // TODO(thakis): Have getter/setter functions instead of returning a ref to
94*6777b538SAndroid Build Coastguard Worker // prepare for arm64e. See __DARWIN_OPAQUE_ARM_THREAD_STATE6 in
95*6777b538SAndroid Build Coastguard Worker // mach/arm/_structs.h
RegisterContextStackPointer(arm_thread_state64_t * context)96*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextStackPointer(arm_thread_state64_t* context) {
97*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->__sp);
98*6777b538SAndroid Build Coastguard Worker }
99*6777b538SAndroid Build Coastguard Worker 
RegisterContextFramePointer(arm_thread_state64_t * context)100*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextFramePointer(arm_thread_state64_t* context) {
101*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->__fp);
102*6777b538SAndroid Build Coastguard Worker }
103*6777b538SAndroid Build Coastguard Worker 
RegisterContextInstructionPointer(arm_thread_state64_t * context)104*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextInstructionPointer(
105*6777b538SAndroid Build Coastguard Worker     arm_thread_state64_t* context) {
106*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->__pc);
107*6777b538SAndroid Build Coastguard Worker }
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker #else  // defined(ARCH_CPU_ARM64)
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker // Placeholders for other cpus.
112*6777b538SAndroid Build Coastguard Worker struct RegisterContext {
113*6777b538SAndroid Build Coastguard Worker   uintptr_t stack_pointer;
114*6777b538SAndroid Build Coastguard Worker   uintptr_t frame_pointer;
115*6777b538SAndroid Build Coastguard Worker   uintptr_t instruction_pointer;
116*6777b538SAndroid Build Coastguard Worker };
117*6777b538SAndroid Build Coastguard Worker 
RegisterContextStackPointer(RegisterContext * context)118*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextStackPointer(RegisterContext* context) {
119*6777b538SAndroid Build Coastguard Worker   return context->stack_pointer;
120*6777b538SAndroid Build Coastguard Worker }
121*6777b538SAndroid Build Coastguard Worker 
RegisterContextFramePointer(RegisterContext * context)122*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextFramePointer(RegisterContext* context) {
123*6777b538SAndroid Build Coastguard Worker   return context->frame_pointer;
124*6777b538SAndroid Build Coastguard Worker }
125*6777b538SAndroid Build Coastguard Worker 
RegisterContextInstructionPointer(RegisterContext * context)126*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextInstructionPointer(RegisterContext* context) {
127*6777b538SAndroid Build Coastguard Worker   return context->instruction_pointer;
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker 
130*6777b538SAndroid Build Coastguard Worker #endif
131*6777b538SAndroid Build Coastguard Worker 
132*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
133*6777b538SAndroid Build Coastguard Worker 
134*6777b538SAndroid Build Coastguard Worker using RegisterContext = mcontext_t;
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
137*6777b538SAndroid Build Coastguard Worker 
RegisterContextStackPointer(mcontext_t * context)138*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextStackPointer(mcontext_t* context) {
139*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->arm_sp);
140*6777b538SAndroid Build Coastguard Worker }
141*6777b538SAndroid Build Coastguard Worker 
RegisterContextFramePointer(mcontext_t * context)142*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextFramePointer(mcontext_t* context) {
143*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->arm_fp);
144*6777b538SAndroid Build Coastguard Worker }
145*6777b538SAndroid Build Coastguard Worker 
RegisterContextInstructionPointer(mcontext_t * context)146*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextInstructionPointer(mcontext_t* context) {
147*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->arm_pc);
148*6777b538SAndroid Build Coastguard Worker }
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
151*6777b538SAndroid Build Coastguard Worker 
RegisterContextStackPointer(mcontext_t * context)152*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextStackPointer(mcontext_t* context) {
153*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->sp);
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker 
RegisterContextFramePointer(mcontext_t * context)156*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextFramePointer(mcontext_t* context) {
157*6777b538SAndroid Build Coastguard Worker   // r29 is the FP register on 64-bit ARM per the Procedure Call Standard,
158*6777b538SAndroid Build Coastguard Worker   // section 5.1.1.
159*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->regs[29]);
160*6777b538SAndroid Build Coastguard Worker }
161*6777b538SAndroid Build Coastguard Worker 
RegisterContextInstructionPointer(mcontext_t * context)162*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextInstructionPointer(mcontext_t* context) {
163*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->pc);
164*6777b538SAndroid Build Coastguard Worker }
165*6777b538SAndroid Build Coastguard Worker 
166*6777b538SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_X86_FAMILY) && defined(ARCH_CPU_32_BITS)
167*6777b538SAndroid Build Coastguard Worker 
RegisterContextStackPointer(mcontext_t * context)168*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextStackPointer(mcontext_t* context) {
169*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->gregs[REG_ESP]);
170*6777b538SAndroid Build Coastguard Worker }
171*6777b538SAndroid Build Coastguard Worker 
RegisterContextFramePointer(mcontext_t * context)172*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextFramePointer(mcontext_t* context) {
173*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->gregs[REG_EBP]);
174*6777b538SAndroid Build Coastguard Worker }
175*6777b538SAndroid Build Coastguard Worker 
RegisterContextInstructionPointer(mcontext_t * context)176*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextInstructionPointer(mcontext_t* context) {
177*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->gregs[REG_EIP]);
178*6777b538SAndroid Build Coastguard Worker }
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_X86_FAMILY) && defined(ARCH_CPU_64_BITS)
181*6777b538SAndroid Build Coastguard Worker 
RegisterContextStackPointer(mcontext_t * context)182*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextStackPointer(mcontext_t* context) {
183*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->gregs[REG_RSP]);
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker 
RegisterContextFramePointer(mcontext_t * context)186*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextFramePointer(mcontext_t* context) {
187*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->gregs[REG_RBP]);
188*6777b538SAndroid Build Coastguard Worker }
189*6777b538SAndroid Build Coastguard Worker 
RegisterContextInstructionPointer(mcontext_t * context)190*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextInstructionPointer(mcontext_t* context) {
191*6777b538SAndroid Build Coastguard Worker   return AsUintPtr(&context->gregs[REG_RIP]);
192*6777b538SAndroid Build Coastguard Worker }
193*6777b538SAndroid Build Coastguard Worker 
194*6777b538SAndroid Build Coastguard Worker #else  // defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
195*6777b538SAndroid Build Coastguard Worker 
196*6777b538SAndroid Build Coastguard Worker // Placeholders for other POSIX platforms that just return the first
197*6777b538SAndroid Build Coastguard Worker // three register slots in the context.
RegisterContextStackPointer(mcontext_t * context)198*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextStackPointer(mcontext_t* context) {
199*6777b538SAndroid Build Coastguard Worker   return *reinterpret_cast<uintptr_t*>(context);
200*6777b538SAndroid Build Coastguard Worker }
201*6777b538SAndroid Build Coastguard Worker 
RegisterContextFramePointer(mcontext_t * context)202*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextFramePointer(mcontext_t* context) {
203*6777b538SAndroid Build Coastguard Worker   return *(reinterpret_cast<uintptr_t*>(context) + 1);
204*6777b538SAndroid Build Coastguard Worker }
205*6777b538SAndroid Build Coastguard Worker 
RegisterContextInstructionPointer(mcontext_t * context)206*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextInstructionPointer(mcontext_t* context) {
207*6777b538SAndroid Build Coastguard Worker   return *(reinterpret_cast<uintptr_t*>(context) + 2);
208*6777b538SAndroid Build Coastguard Worker }
209*6777b538SAndroid Build Coastguard Worker 
210*6777b538SAndroid Build Coastguard Worker #endif  // defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
211*6777b538SAndroid Build Coastguard Worker 
212*6777b538SAndroid Build Coastguard Worker #else  // BUILDFLAG(IS_WIN)
213*6777b538SAndroid Build Coastguard Worker 
214*6777b538SAndroid Build Coastguard Worker // Placeholders for other platforms.
215*6777b538SAndroid Build Coastguard Worker struct RegisterContext {
216*6777b538SAndroid Build Coastguard Worker   uintptr_t stack_pointer;
217*6777b538SAndroid Build Coastguard Worker   uintptr_t frame_pointer;
218*6777b538SAndroid Build Coastguard Worker   uintptr_t instruction_pointer;
219*6777b538SAndroid Build Coastguard Worker };
220*6777b538SAndroid Build Coastguard Worker 
RegisterContextStackPointer(RegisterContext * context)221*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextStackPointer(RegisterContext* context) {
222*6777b538SAndroid Build Coastguard Worker   return context->stack_pointer;
223*6777b538SAndroid Build Coastguard Worker }
224*6777b538SAndroid Build Coastguard Worker 
RegisterContextFramePointer(RegisterContext * context)225*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextFramePointer(RegisterContext* context) {
226*6777b538SAndroid Build Coastguard Worker   return context->frame_pointer;
227*6777b538SAndroid Build Coastguard Worker }
228*6777b538SAndroid Build Coastguard Worker 
RegisterContextInstructionPointer(RegisterContext * context)229*6777b538SAndroid Build Coastguard Worker inline uintptr_t& RegisterContextInstructionPointer(RegisterContext* context) {
230*6777b538SAndroid Build Coastguard Worker   return context->instruction_pointer;
231*6777b538SAndroid Build Coastguard Worker }
232*6777b538SAndroid Build Coastguard Worker 
233*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_WIN)
234*6777b538SAndroid Build Coastguard Worker 
235*6777b538SAndroid Build Coastguard Worker }  // namespace base
236*6777b538SAndroid Build Coastguard Worker 
237*6777b538SAndroid Build Coastguard Worker #endif  // BASE_PROFILER_REGISTER_CONTEXT_H_
238