cpu_context_linux.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. // Copyright 2017 The Crashpad Authors. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "snapshot/linux/cpu_context_linux.h"
  15. #include <stddef.h>
  16. #include <string.h>
  17. #include <limits>
  18. #include "base/logging.h"
  19. namespace crashpad {
  20. namespace internal {
  21. #if defined(ARCH_CPU_X86_FAMILY)
  22. #define SET_GPRS32() \
  23. do { \
  24. context->eax = thread_context.eax; \
  25. context->ebx = thread_context.ebx; \
  26. context->ecx = thread_context.ecx; \
  27. context->edx = thread_context.edx; \
  28. context->edi = thread_context.edi; \
  29. context->esi = thread_context.esi; \
  30. context->ebp = thread_context.ebp; \
  31. context->esp = thread_context.esp; \
  32. context->eip = thread_context.eip; \
  33. context->eflags = thread_context.eflags; \
  34. context->cs = thread_context.xcs; \
  35. context->ds = thread_context.xds; \
  36. context->es = thread_context.xes; \
  37. context->fs = thread_context.xfs; \
  38. context->gs = thread_context.xgs; \
  39. context->ss = thread_context.xss; \
  40. } while (false)
  41. void InitializeCPUContextX86(const ThreadContext::t32_t& thread_context,
  42. const FloatContext::f32_t& float_context,
  43. CPUContextX86* context) {
  44. SET_GPRS32();
  45. static_assert(sizeof(context->fxsave) == sizeof(float_context.fxsave),
  46. "fxsave size mismatch");
  47. memcpy(&context->fxsave, &float_context.fxsave, sizeof(context->fxsave));
  48. // TODO(jperaza): debug registers
  49. context->dr0 = 0;
  50. context->dr1 = 0;
  51. context->dr2 = 0;
  52. context->dr3 = 0;
  53. context->dr4 = 0;
  54. context->dr5 = 0;
  55. context->dr6 = 0;
  56. context->dr7 = 0;
  57. }
  58. void InitializeCPUContextX86(const SignalThreadContext32& thread_context,
  59. const SignalFloatContext32& float_context,
  60. CPUContextX86* context) {
  61. InitializeCPUContextX86_NoFloatingPoint(thread_context, context);
  62. CPUContextX86::FsaveToFxsave(float_context.fsave, &context->fxsave);
  63. }
  64. void InitializeCPUContextX86_NoFloatingPoint(
  65. const SignalThreadContext32& thread_context,
  66. CPUContextX86* context) {
  67. SET_GPRS32();
  68. memset(&context->fxsave, 0, sizeof(context->fxsave));
  69. context->dr0 = 0;
  70. context->dr1 = 0;
  71. context->dr2 = 0;
  72. context->dr3 = 0;
  73. context->dr4 = 0;
  74. context->dr5 = 0;
  75. context->dr6 = 0;
  76. context->dr7 = 0;
  77. }
  78. #define SET_GPRS64() \
  79. do { \
  80. context->rax = thread_context.rax; \
  81. context->rbx = thread_context.rbx; \
  82. context->rcx = thread_context.rcx; \
  83. context->rdx = thread_context.rdx; \
  84. context->rdi = thread_context.rdi; \
  85. context->rsi = thread_context.rsi; \
  86. context->rbp = thread_context.rbp; \
  87. context->rsp = thread_context.rsp; \
  88. context->r8 = thread_context.r8; \
  89. context->r9 = thread_context.r9; \
  90. context->r10 = thread_context.r10; \
  91. context->r11 = thread_context.r11; \
  92. context->r12 = thread_context.r12; \
  93. context->r13 = thread_context.r13; \
  94. context->r14 = thread_context.r14; \
  95. context->r15 = thread_context.r15; \
  96. context->rip = thread_context.rip; \
  97. context->rflags = thread_context.eflags; \
  98. context->cs = thread_context.cs; \
  99. context->fs = thread_context.fs; \
  100. context->gs = thread_context.gs; \
  101. } while (false)
  102. void InitializeCPUContextX86_64(const ThreadContext::t64_t& thread_context,
  103. const FloatContext::f64_t& float_context,
  104. CPUContextX86_64* context) {
  105. SET_GPRS64();
  106. static_assert(sizeof(context->fxsave) == sizeof(float_context.fxsave),
  107. "fxsave size mismatch");
  108. memcpy(&context->fxsave, &float_context.fxsave, sizeof(context->fxsave));
  109. // TODO(jperaza): debug registers.
  110. context->dr0 = 0;
  111. context->dr1 = 0;
  112. context->dr2 = 0;
  113. context->dr3 = 0;
  114. context->dr4 = 0;
  115. context->dr5 = 0;
  116. context->dr6 = 0;
  117. context->dr7 = 0;
  118. }
  119. void InitializeCPUContextX86_64(const SignalThreadContext64& thread_context,
  120. const SignalFloatContext64& float_context,
  121. CPUContextX86_64* context) {
  122. SET_GPRS64();
  123. static_assert(
  124. std::is_same<SignalFloatContext64, CPUContextX86_64::Fxsave>::value,
  125. "signal float context has unexpected type");
  126. memcpy(&context->fxsave, &float_context, sizeof(context->fxsave));
  127. context->dr0 = 0;
  128. context->dr1 = 0;
  129. context->dr2 = 0;
  130. context->dr3 = 0;
  131. context->dr4 = 0;
  132. context->dr5 = 0;
  133. context->dr6 = 0;
  134. context->dr7 = 0;
  135. }
  136. void InitializeCPUContextX86_64_NoFloatingPoint(
  137. const SignalThreadContext64& thread_context,
  138. CPUContextX86_64* context) {
  139. SET_GPRS64();
  140. memset(&context->fxsave, 0, sizeof(context->fxsave));
  141. context->dr0 = 0;
  142. context->dr1 = 0;
  143. context->dr2 = 0;
  144. context->dr3 = 0;
  145. context->dr4 = 0;
  146. context->dr5 = 0;
  147. context->dr6 = 0;
  148. context->dr7 = 0;
  149. }
  150. #elif defined(ARCH_CPU_ARM_FAMILY)
  151. void InitializeCPUContextARM(const ThreadContext::t32_t& thread_context,
  152. const FloatContext::f32_t& float_context,
  153. CPUContextARM* context) {
  154. static_assert(sizeof(context->regs) == sizeof(thread_context.regs),
  155. "registers size mismatch");
  156. memcpy(&context->regs, &thread_context.regs, sizeof(context->regs));
  157. context->fp = thread_context.fp;
  158. context->ip = thread_context.ip;
  159. context->sp = thread_context.sp;
  160. context->lr = thread_context.lr;
  161. context->pc = thread_context.pc;
  162. context->cpsr = thread_context.cpsr;
  163. static_assert(sizeof(context->vfp_regs) == sizeof(float_context.vfp),
  164. "vfp size mismatch");
  165. context->have_vfp_regs = float_context.have_vfp;
  166. if (float_context.have_vfp) {
  167. memcpy(&context->vfp_regs, &float_context.vfp, sizeof(context->vfp_regs));
  168. }
  169. static_assert(sizeof(context->fpa_regs) == sizeof(float_context.fpregs),
  170. "fpregs size mismatch");
  171. context->have_fpa_regs = float_context.have_fpregs;
  172. if (float_context.have_fpregs) {
  173. memcpy(
  174. &context->fpa_regs, &float_context.fpregs, sizeof(context->fpa_regs));
  175. }
  176. }
  177. void InitializeCPUContextARM_NoFloatingPoint(
  178. const SignalThreadContext32& thread_context,
  179. CPUContextARM* context) {
  180. static_assert(sizeof(context->regs) == sizeof(thread_context.regs),
  181. "registers size mismatch");
  182. memcpy(&context->regs, &thread_context.regs, sizeof(context->regs));
  183. context->fp = thread_context.fp;
  184. context->ip = thread_context.ip;
  185. context->sp = thread_context.sp;
  186. context->lr = thread_context.lr;
  187. context->pc = thread_context.pc;
  188. context->cpsr = thread_context.cpsr;
  189. memset(&context->fpa_regs, 0, sizeof(context->fpa_regs));
  190. memset(&context->vfp_regs, 0, sizeof(context->vfp_regs));
  191. context->have_fpa_regs = false;
  192. context->have_vfp_regs = false;
  193. }
  194. void InitializeCPUContextARM64(const ThreadContext::t64_t& thread_context,
  195. const FloatContext::f64_t& float_context,
  196. CPUContextARM64* context) {
  197. InitializeCPUContextARM64_NoFloatingPoint(thread_context, context);
  198. static_assert(sizeof(context->fpsimd) == sizeof(float_context.vregs),
  199. "fpsimd context size mismatch");
  200. memcpy(context->fpsimd, float_context.vregs, sizeof(context->fpsimd));
  201. context->fpsr = float_context.fpsr;
  202. context->fpcr = float_context.fpcr;
  203. }
  204. void InitializeCPUContextARM64_NoFloatingPoint(
  205. const ThreadContext::t64_t& thread_context,
  206. CPUContextARM64* context) {
  207. static_assert(sizeof(context->regs) == sizeof(thread_context.regs),
  208. "gpr context size mismtach");
  209. memcpy(context->regs, thread_context.regs, sizeof(context->regs));
  210. context->sp = thread_context.sp;
  211. context->pc = thread_context.pc;
  212. // Linux seems to only be putting the SPSR register in its "pstate" field.
  213. // https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/uapi/asm/ptrace.h
  214. if (thread_context.pstate >
  215. std::numeric_limits<decltype(context->spsr)>::max()) {
  216. LOG(WARNING) << "pstate truncation: we only expect the SPSR bits to be set "
  217. "in the pstate";
  218. }
  219. context->spsr = static_cast<decltype(context->spsr)>(thread_context.pstate);
  220. memset(&context->fpsimd, 0, sizeof(context->fpsimd));
  221. context->fpsr = 0;
  222. context->fpcr = 0;
  223. }
  224. void InitializeCPUContextARM64_OnlyFPSIMD(
  225. const SignalFPSIMDContext& float_context,
  226. CPUContextARM64* context) {
  227. static_assert(sizeof(context->fpsimd) == sizeof(float_context.vregs),
  228. "fpsimd context size mismatch");
  229. memcpy(context->fpsimd, float_context.vregs, sizeof(context->fpsimd));
  230. context->fpsr = float_context.fpsr;
  231. context->fpcr = float_context.fpcr;
  232. }
  233. #elif defined(ARCH_CPU_RISCV_FAMILY)
  234. template <typename Traits>
  235. void InitializeCPUContextRISCV(
  236. const typename Traits::SignalThreadContext& thread_context,
  237. const typename Traits::SignalFloatContext& float_context,
  238. typename Traits::CPUContext* context) {
  239. static_assert(sizeof(context->regs) == sizeof(thread_context),
  240. "registers size mismatch");
  241. static_assert(sizeof(context->fpregs) == sizeof(float_context.f),
  242. "fp registers size mismatch");
  243. memcpy(&context->regs, &thread_context, sizeof(context->regs));
  244. memcpy(&context->fpregs, &float_context, sizeof(context->fpregs));
  245. context->fcsr = float_context.fcsr;
  246. }
  247. template void InitializeCPUContextRISCV<ContextTraits32>(
  248. const ContextTraits32::SignalThreadContext& thread_context,
  249. const ContextTraits32::SignalFloatContext& float_context,
  250. ContextTraits32::CPUContext* context);
  251. template void InitializeCPUContextRISCV<ContextTraits64>(
  252. const ContextTraits64::SignalThreadContext& thread_context,
  253. const ContextTraits64::SignalFloatContext& float_context,
  254. ContextTraits64::CPUContext* context);
  255. #endif // ARCH_CPU_X86_FAMILY
  256. } // namespace internal
  257. } // namespace crashpad