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 Workeruintptr_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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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 Workerinline 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