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