1 // Copyright 2014 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 
15 #include "snapshot/mac/cpu_context_mac.h"
16 
17 #include <stddef.h>
18 #include <string.h>
19 
20 #include "base/logging.h"
21 #include "base/notreached.h"
22 
23 namespace crashpad {
24 
25 #if defined(ARCH_CPU_X86_FAMILY)
26 
27 namespace {
28 
InitializeCPUContextX86Thread(CPUContextX86 * context,const x86_thread_state32_t * x86_thread_state32)29 void InitializeCPUContextX86Thread(
30     CPUContextX86* context,
31     const x86_thread_state32_t* x86_thread_state32) {
32   context->eax = x86_thread_state32->__eax;
33   context->ebx = x86_thread_state32->__ebx;
34   context->ecx = x86_thread_state32->__ecx;
35   context->edx = x86_thread_state32->__edx;
36   context->edi = x86_thread_state32->__edi;
37   context->esi = x86_thread_state32->__esi;
38   context->ebp = x86_thread_state32->__ebp;
39   context->esp = x86_thread_state32->__esp;
40   context->eip = x86_thread_state32->__eip;
41   context->eflags = x86_thread_state32->__eflags;
42   context->cs = x86_thread_state32->__cs;
43   context->ds = x86_thread_state32->__ds;
44   context->es = x86_thread_state32->__es;
45   context->fs = x86_thread_state32->__fs;
46   context->gs = x86_thread_state32->__gs;
47   context->ss = x86_thread_state32->__ss;
48 }
49 
InitializeCPUContextX86Float(CPUContextX86 * context,const x86_float_state32_t * x86_float_state32)50 void InitializeCPUContextX86Float(
51     CPUContextX86* context, const x86_float_state32_t* x86_float_state32) {
52   // This relies on both x86_float_state32_t and context->fxsave having
53   // identical (fxsave) layout.
54   static_assert(offsetof(x86_float_state32_t, __fpu_reserved1) -
55                          offsetof(x86_float_state32_t, __fpu_fcw) ==
56                      sizeof(context->fxsave),
57                 "types must be equivalent");
58 
59   memcpy(
60       &context->fxsave, &x86_float_state32->__fpu_fcw, sizeof(context->fxsave));
61 }
62 
InitializeCPUContextX86Debug(CPUContextX86 * context,const x86_debug_state32_t * x86_debug_state32)63 void InitializeCPUContextX86Debug(
64     CPUContextX86* context, const x86_debug_state32_t* x86_debug_state32) {
65   context->dr0 = x86_debug_state32->__dr0;
66   context->dr1 = x86_debug_state32->__dr1;
67   context->dr2 = x86_debug_state32->__dr2;
68   context->dr3 = x86_debug_state32->__dr3;
69   context->dr4 = x86_debug_state32->__dr4;
70   context->dr5 = x86_debug_state32->__dr5;
71   context->dr6 = x86_debug_state32->__dr6;
72   context->dr7 = x86_debug_state32->__dr7;
73 }
74 
75 // Initializes |context| from the native thread state structure |state|, which
76 // is interpreted according to |flavor|. |state_count| must be at least the
77 // expected size for |flavor|. This handles the architecture-specific
78 // x86_THREAD_STATE32, x86_FLOAT_STATE32, and x86_DEBUG_STATE32 flavors. It also
79 // handles the universal x86_THREAD_STATE, x86_FLOAT_STATE, and x86_DEBUG_STATE
80 // flavors provided that the associated structure carries 32-bit data of the
81 // corresponding state type. |flavor| may be THREAD_STATE_NONE to avoid setting
82 // any thread state in |context|. This returns the architecture-specific flavor
83 // value for the thread state that was actually set, or THREAD_STATE_NONE if no
84 // thread state was set.
InitializeCPUContextX86Flavor(CPUContextX86 * context,thread_state_flavor_t flavor,ConstThreadState state,mach_msg_type_number_t state_count)85 thread_state_flavor_t InitializeCPUContextX86Flavor(
86     CPUContextX86* context,
87     thread_state_flavor_t flavor,
88     ConstThreadState state,
89     mach_msg_type_number_t state_count) {
90   mach_msg_type_number_t expected_state_count;
91   switch (flavor) {
92     case x86_THREAD_STATE:
93       expected_state_count = x86_THREAD_STATE_COUNT;
94       break;
95     case x86_FLOAT_STATE:
96       expected_state_count = x86_FLOAT_STATE_COUNT;
97       break;
98     case x86_DEBUG_STATE:
99       expected_state_count = x86_DEBUG_STATE_COUNT;
100       break;
101     case x86_THREAD_STATE32:
102       expected_state_count = x86_THREAD_STATE32_COUNT;
103       break;
104     case x86_FLOAT_STATE32:
105       expected_state_count = x86_FLOAT_STATE32_COUNT;
106       break;
107     case x86_DEBUG_STATE32:
108       expected_state_count = x86_DEBUG_STATE32_COUNT;
109       break;
110     case THREAD_STATE_NONE:
111       expected_state_count = 0;
112       break;
113     default:
114       LOG(WARNING) << "unhandled flavor " << flavor;
115       return THREAD_STATE_NONE;
116   }
117 
118   if (state_count < expected_state_count) {
119     LOG(WARNING) << "expected state_count " << expected_state_count
120                  << " for flavor " << flavor << ", observed " << state_count;
121     return THREAD_STATE_NONE;
122   }
123 
124   switch (flavor) {
125     case x86_THREAD_STATE: {
126       const x86_thread_state_t* x86_thread_state =
127           reinterpret_cast<const x86_thread_state_t*>(state);
128       if (x86_thread_state->tsh.flavor != x86_THREAD_STATE32) {
129         LOG(WARNING) << "expected flavor x86_THREAD_STATE32, observed "
130                      << x86_thread_state->tsh.flavor;
131         return THREAD_STATE_NONE;
132       }
133       return InitializeCPUContextX86Flavor(
134           context,
135           x86_thread_state->tsh.flavor,
136           reinterpret_cast<ConstThreadState>(&x86_thread_state->uts.ts32),
137           x86_thread_state->tsh.count);
138     }
139 
140     case x86_FLOAT_STATE: {
141       const x86_float_state_t* x86_float_state =
142           reinterpret_cast<const x86_float_state_t*>(state);
143       if (x86_float_state->fsh.flavor != x86_FLOAT_STATE32) {
144         LOG(WARNING) << "expected flavor x86_FLOAT_STATE32, observed "
145                      << x86_float_state->fsh.flavor;
146         return THREAD_STATE_NONE;
147       }
148       return InitializeCPUContextX86Flavor(
149           context,
150           x86_float_state->fsh.flavor,
151           reinterpret_cast<ConstThreadState>(&x86_float_state->ufs.fs32),
152           x86_float_state->fsh.count);
153     }
154 
155     case x86_DEBUG_STATE: {
156       const x86_debug_state_t* x86_debug_state =
157           reinterpret_cast<const x86_debug_state_t*>(state);
158       if (x86_debug_state->dsh.flavor != x86_DEBUG_STATE32) {
159         LOG(WARNING) << "expected flavor x86_DEBUG_STATE32, observed "
160                      << x86_debug_state->dsh.flavor;
161         return THREAD_STATE_NONE;
162       }
163       return InitializeCPUContextX86Flavor(
164           context,
165           x86_debug_state->dsh.flavor,
166           reinterpret_cast<ConstThreadState>(&x86_debug_state->uds.ds32),
167           x86_debug_state->dsh.count);
168     }
169 
170     case x86_THREAD_STATE32: {
171       const x86_thread_state32_t* x86_thread_state32 =
172           reinterpret_cast<const x86_thread_state32_t*>(state);
173       InitializeCPUContextX86Thread(context, x86_thread_state32);
174       return flavor;
175     }
176 
177     case x86_FLOAT_STATE32: {
178       const x86_float_state32_t* x86_float_state32 =
179           reinterpret_cast<const x86_float_state32_t*>(state);
180       InitializeCPUContextX86Float(context, x86_float_state32);
181       return flavor;
182     }
183 
184     case x86_DEBUG_STATE32: {
185       const x86_debug_state32_t* x86_debug_state32 =
186           reinterpret_cast<const x86_debug_state32_t*>(state);
187       InitializeCPUContextX86Debug(context, x86_debug_state32);
188       return flavor;
189     }
190 
191     case THREAD_STATE_NONE: {
192       // This may happen without error when called without exception-style
193       // flavor data, or even from an exception handler when the exception
194       // behavior is EXCEPTION_DEFAULT.
195       return flavor;
196     }
197 
198     default: {
199       NOTREACHED();
200       return THREAD_STATE_NONE;
201     }
202   }
203 }
204 
InitializeCPUContextX86_64Thread(CPUContextX86_64 * context,const x86_thread_state64_t * x86_thread_state64)205 void InitializeCPUContextX86_64Thread(
206     CPUContextX86_64* context, const x86_thread_state64_t* x86_thread_state64) {
207   context->rax = x86_thread_state64->__rax;
208   context->rbx = x86_thread_state64->__rbx;
209   context->rcx = x86_thread_state64->__rcx;
210   context->rdx = x86_thread_state64->__rdx;
211   context->rdi = x86_thread_state64->__rdi;
212   context->rsi = x86_thread_state64->__rsi;
213   context->rbp = x86_thread_state64->__rbp;
214   context->rsp = x86_thread_state64->__rsp;
215   context->r8 = x86_thread_state64->__r8;
216   context->r9 = x86_thread_state64->__r9;
217   context->r10 = x86_thread_state64->__r10;
218   context->r11 = x86_thread_state64->__r11;
219   context->r12 = x86_thread_state64->__r12;
220   context->r13 = x86_thread_state64->__r13;
221   context->r14 = x86_thread_state64->__r14;
222   context->r15 = x86_thread_state64->__r15;
223   context->rip = x86_thread_state64->__rip;
224   context->rflags = x86_thread_state64->__rflags;
225   context->cs = x86_thread_state64->__cs;
226   context->fs = x86_thread_state64->__fs;
227   context->gs = x86_thread_state64->__gs;
228 }
229 
InitializeCPUContextX86_64Float(CPUContextX86_64 * context,const x86_float_state64_t * x86_float_state64)230 void InitializeCPUContextX86_64Float(
231     CPUContextX86_64* context, const x86_float_state64_t* x86_float_state64) {
232   // This relies on both x86_float_state64_t and context->fxsave having
233   // identical (fxsave) layout.
234   static_assert(offsetof(x86_float_state64_t, __fpu_reserved1) -
235                          offsetof(x86_float_state64_t, __fpu_fcw) ==
236                      sizeof(context->fxsave),
237                 "types must be equivalent");
238 
239   memcpy(&context->fxsave,
240          &x86_float_state64->__fpu_fcw,
241          sizeof(context->fxsave));
242 }
243 
InitializeCPUContextX86_64Debug(CPUContextX86_64 * context,const x86_debug_state64_t * x86_debug_state64)244 void InitializeCPUContextX86_64Debug(
245     CPUContextX86_64* context, const x86_debug_state64_t* x86_debug_state64) {
246   context->dr0 = x86_debug_state64->__dr0;
247   context->dr1 = x86_debug_state64->__dr1;
248   context->dr2 = x86_debug_state64->__dr2;
249   context->dr3 = x86_debug_state64->__dr3;
250   context->dr4 = x86_debug_state64->__dr4;
251   context->dr5 = x86_debug_state64->__dr5;
252   context->dr6 = x86_debug_state64->__dr6;
253   context->dr7 = x86_debug_state64->__dr7;
254 }
255 
256 // Initializes |context| from the native thread state structure |state|, which
257 // is interpreted according to |flavor|. |state_count| must be at least the
258 // expected size for |flavor|. This handles the architecture-specific
259 // x86_THREAD_STATE64, x86_FLOAT_STATE64, and x86_DEBUG_STATE64 flavors. It also
260 // handles the universal x86_THREAD_STATE, x86_FLOAT_STATE, and x86_DEBUG_STATE
261 // flavors provided that the associated structure carries 64-bit data of the
262 // corresponding state type. |flavor| may be THREAD_STATE_NONE to avoid setting
263 // any thread state in |context|. This returns the architecture-specific flavor
264 // value for the thread state that was actually set, or THREAD_STATE_NONE if no
265 // thread state was set.
InitializeCPUContextX86_64Flavor(CPUContextX86_64 * context,thread_state_flavor_t flavor,ConstThreadState state,mach_msg_type_number_t state_count)266 thread_state_flavor_t InitializeCPUContextX86_64Flavor(
267     CPUContextX86_64* context,
268     thread_state_flavor_t flavor,
269     ConstThreadState state,
270     mach_msg_type_number_t state_count) {
271   mach_msg_type_number_t expected_state_count;
272   switch (flavor) {
273     case x86_THREAD_STATE:
274       expected_state_count = x86_THREAD_STATE_COUNT;
275       break;
276     case x86_FLOAT_STATE:
277       expected_state_count = x86_FLOAT_STATE_COUNT;
278       break;
279     case x86_DEBUG_STATE:
280       expected_state_count = x86_DEBUG_STATE_COUNT;
281       break;
282     case x86_THREAD_STATE64:
283       expected_state_count = x86_THREAD_STATE64_COUNT;
284       break;
285     case x86_FLOAT_STATE64:
286       expected_state_count = x86_FLOAT_STATE64_COUNT;
287       break;
288     case x86_DEBUG_STATE64:
289       expected_state_count = x86_DEBUG_STATE64_COUNT;
290       break;
291     case THREAD_STATE_NONE:
292       expected_state_count = 0;
293       break;
294     default:
295       LOG(WARNING) << "unhandled flavor " << flavor;
296       return THREAD_STATE_NONE;
297   }
298 
299   if (state_count < expected_state_count) {
300     LOG(WARNING) << "expected state_count " << expected_state_count
301                  << " for flavor " << flavor << ", observed " << state_count;
302     return THREAD_STATE_NONE;
303   }
304 
305   switch (flavor) {
306     case x86_THREAD_STATE: {
307       const x86_thread_state_t* x86_thread_state =
308           reinterpret_cast<const x86_thread_state_t*>(state);
309       if (x86_thread_state->tsh.flavor != x86_THREAD_STATE64) {
310         LOG(WARNING) << "expected flavor x86_THREAD_STATE64, observed "
311                      << x86_thread_state->tsh.flavor;
312         return THREAD_STATE_NONE;
313       }
314       return InitializeCPUContextX86_64Flavor(
315           context,
316           x86_thread_state->tsh.flavor,
317           reinterpret_cast<ConstThreadState>(&x86_thread_state->uts.ts64),
318           x86_thread_state->tsh.count);
319     }
320 
321     case x86_FLOAT_STATE: {
322       const x86_float_state_t* x86_float_state =
323           reinterpret_cast<const x86_float_state_t*>(state);
324       if (x86_float_state->fsh.flavor != x86_FLOAT_STATE64) {
325         LOG(WARNING) << "expected flavor x86_FLOAT_STATE64, observed "
326                      << x86_float_state->fsh.flavor;
327         return THREAD_STATE_NONE;
328       }
329       return InitializeCPUContextX86_64Flavor(
330           context,
331           x86_float_state->fsh.flavor,
332           reinterpret_cast<ConstThreadState>(&x86_float_state->ufs.fs64),
333           x86_float_state->fsh.count);
334     }
335 
336     case x86_DEBUG_STATE: {
337       const x86_debug_state_t* x86_debug_state =
338           reinterpret_cast<const x86_debug_state_t*>(state);
339       if (x86_debug_state->dsh.flavor != x86_DEBUG_STATE64) {
340         LOG(WARNING) << "expected flavor x86_DEBUG_STATE64, observed "
341                      << x86_debug_state->dsh.flavor;
342         return THREAD_STATE_NONE;
343       }
344       return InitializeCPUContextX86_64Flavor(
345           context,
346           x86_debug_state->dsh.flavor,
347           reinterpret_cast<ConstThreadState>(&x86_debug_state->uds.ds64),
348           x86_debug_state->dsh.count);
349     }
350 
351     case x86_THREAD_STATE64: {
352       const x86_thread_state64_t* x86_thread_state64 =
353           reinterpret_cast<const x86_thread_state64_t*>(state);
354       InitializeCPUContextX86_64Thread(context, x86_thread_state64);
355       return flavor;
356     }
357 
358     case x86_FLOAT_STATE64: {
359       const x86_float_state64_t* x86_float_state64 =
360           reinterpret_cast<const x86_float_state64_t*>(state);
361       InitializeCPUContextX86_64Float(context, x86_float_state64);
362       return flavor;
363     }
364 
365     case x86_DEBUG_STATE64: {
366       const x86_debug_state64_t* x86_debug_state64 =
367           reinterpret_cast<const x86_debug_state64_t*>(state);
368       InitializeCPUContextX86_64Debug(context, x86_debug_state64);
369       return flavor;
370     }
371 
372     case THREAD_STATE_NONE: {
373       // This may happen without error when called without exception-style
374       // flavor data, or even from an exception handler when the exception
375       // behavior is EXCEPTION_DEFAULT.
376       return flavor;
377     }
378 
379     default: {
380       NOTREACHED();
381       return THREAD_STATE_NONE;
382     }
383   }
384 }
385 
386 }  // namespace
387 
388 namespace internal {
389 
InitializeCPUContextX86(CPUContextX86 * context,thread_state_flavor_t flavor,ConstThreadState state,mach_msg_type_number_t state_count,const x86_thread_state32_t * x86_thread_state32,const x86_float_state32_t * x86_float_state32,const x86_debug_state32_t * x86_debug_state32)390 void InitializeCPUContextX86(CPUContextX86* context,
391                              thread_state_flavor_t flavor,
392                              ConstThreadState state,
393                              mach_msg_type_number_t state_count,
394                              const x86_thread_state32_t* x86_thread_state32,
395                              const x86_float_state32_t* x86_float_state32,
396                              const x86_debug_state32_t* x86_debug_state32) {
397   thread_state_flavor_t set_flavor = THREAD_STATE_NONE;
398   if (flavor != THREAD_STATE_NONE) {
399     set_flavor =
400         InitializeCPUContextX86Flavor(context, flavor, state, state_count);
401   }
402 
403   if (set_flavor != x86_THREAD_STATE32) {
404     InitializeCPUContextX86Thread(context, x86_thread_state32);
405   }
406   if (set_flavor != x86_FLOAT_STATE32) {
407     InitializeCPUContextX86Float(context, x86_float_state32);
408   }
409   if (set_flavor != x86_DEBUG_STATE32) {
410     InitializeCPUContextX86Debug(context, x86_debug_state32);
411   }
412 }
413 
InitializeCPUContextX86_64(CPUContextX86_64 * context,thread_state_flavor_t flavor,ConstThreadState state,mach_msg_type_number_t state_count,const x86_thread_state64_t * x86_thread_state64,const x86_float_state64_t * x86_float_state64,const x86_debug_state64_t * x86_debug_state64)414 void InitializeCPUContextX86_64(CPUContextX86_64* context,
415                                 thread_state_flavor_t flavor,
416                                 ConstThreadState state,
417                                 mach_msg_type_number_t state_count,
418                                 const x86_thread_state64_t* x86_thread_state64,
419                                 const x86_float_state64_t* x86_float_state64,
420                                 const x86_debug_state64_t* x86_debug_state64) {
421   thread_state_flavor_t set_flavor = THREAD_STATE_NONE;
422   if (flavor != THREAD_STATE_NONE) {
423     set_flavor =
424         InitializeCPUContextX86_64Flavor(context, flavor, state, state_count);
425   }
426 
427   if (set_flavor != x86_THREAD_STATE64) {
428     InitializeCPUContextX86_64Thread(context, x86_thread_state64);
429   }
430   if (set_flavor != x86_FLOAT_STATE64) {
431     InitializeCPUContextX86_64Float(context, x86_float_state64);
432   }
433   if (set_flavor != x86_DEBUG_STATE64) {
434     InitializeCPUContextX86_64Debug(context, x86_debug_state64);
435   }
436 }
437 
438 }  // namespace internal
439 
440 #elif defined(ARCH_CPU_ARM64)
441 
442 namespace {
443 
444 void InitializeCPUContextARM64Thread(
445     CPUContextARM64* context,
446     const arm_thread_state64_t* arm_thread_state64) {
447   // The first 29 fields of context->regs is laid out identically to
448   // arm_thread_state64->__x.
449   memcpy(
450       context->regs, arm_thread_state64->__x, sizeof(arm_thread_state64->__x));
451 
452   context->regs[29] = arm_thread_state64_get_fp(*arm_thread_state64);
453   context->regs[30] = arm_thread_state64_get_lr(*arm_thread_state64);
454   context->sp = arm_thread_state64_get_sp(*arm_thread_state64);
455   context->pc = arm_thread_state64_get_pc(*arm_thread_state64);
456   context->spsr =
457       static_cast<decltype(context->spsr)>(arm_thread_state64->__cpsr);
458 }
459 
460 void InitializeCPUContextARM64Neon(CPUContextARM64* context,
461                                    const arm_neon_state64_t* arm_neon_state64) {
462   static_assert(sizeof(context->fpsimd) == sizeof(arm_neon_state64->__v),
463                 "fpsimd context size mismatch");
464   memcpy(context->fpsimd, arm_neon_state64->__v, sizeof(arm_neon_state64->__v));
465   context->fpsr = arm_neon_state64->__fpsr;
466   context->fpcr = arm_neon_state64->__fpcr;
467 }
468 
469 void InitializeCPUContextARM64Debug(
470     CPUContextARM64* context,
471     const arm_debug_state64_t* arm_debug_state64) {
472   // TODO(macos_arm64): Create a spot in CPUContextARM64 to keep this.
473 }
474 
475 thread_state_flavor_t InitializeCPUContextARM64Flavor(
476     CPUContextARM64* context,
477     thread_state_flavor_t flavor,
478     ConstThreadState state,
479     mach_msg_type_number_t state_count) {
480   mach_msg_type_number_t expected_state_count;
481   switch (flavor) {
482     case ARM_UNIFIED_THREAD_STATE:
483       expected_state_count = ARM_UNIFIED_THREAD_STATE_COUNT;
484       break;
485     case ARM_THREAD_STATE64:
486       expected_state_count = ARM_THREAD_STATE64_COUNT;
487       break;
488     case ARM_NEON_STATE64:
489       expected_state_count = ARM_NEON_STATE64_COUNT;
490       break;
491     case ARM_DEBUG_STATE64:
492       expected_state_count = ARM_DEBUG_STATE64_COUNT;
493       break;
494     case THREAD_STATE_NONE: {
495       // This may happen without error when called without exception-style
496       // flavor data, or even from an exception handler when the exception
497       // behavior is EXCEPTION_DEFAULT.
498       return flavor;
499     }
500     default:
501       LOG(WARNING) << "unhandled flavor " << flavor;
502       return THREAD_STATE_NONE;
503   }
504 
505   if (state_count < expected_state_count) {
506     LOG(WARNING) << "expected state_count " << expected_state_count
507                  << " for flavor " << flavor << ", observed " << state_count;
508     return THREAD_STATE_NONE;
509   }
510 
511   switch (flavor) {
512     case ARM_UNIFIED_THREAD_STATE: {
513       const arm_unified_thread_state_t* arm_thread_state =
514           reinterpret_cast<const arm_unified_thread_state_t*>(state);
515       if (arm_thread_state->ash.flavor != ARM_THREAD_STATE64) {
516         LOG(WARNING) << "expected flavor ARM_THREAD_STATE64, observed "
517                      << arm_thread_state->ash.flavor;
518         return THREAD_STATE_NONE;
519       }
520       return InitializeCPUContextARM64Flavor(
521           context,
522           arm_thread_state->ash.flavor,
523           reinterpret_cast<ConstThreadState>(&arm_thread_state->ts_64),
524           arm_thread_state->ash.count);
525     }
526 
527     case ARM_THREAD_STATE64: {
528       const arm_thread_state64_t* arm_thread_state =
529           reinterpret_cast<const arm_thread_state64_t*>(state);
530       InitializeCPUContextARM64Thread(context, arm_thread_state);
531       return ARM_THREAD_STATE64;
532     }
533 
534     case ARM_NEON_STATE64: {
535       const arm_neon_state64_t* arm_neon_state =
536           reinterpret_cast<const arm_neon_state64_t*>(state);
537       InitializeCPUContextARM64Neon(context, arm_neon_state);
538       return ARM_NEON_STATE64;
539     }
540 
541     case ARM_DEBUG_STATE64: {
542       const arm_debug_state64_t* arm_debug_state =
543           reinterpret_cast<const arm_debug_state64_t*>(state);
544       InitializeCPUContextARM64Debug(context, arm_debug_state);
545       return ARM_DEBUG_STATE64;
546     }
547 
548     case THREAD_STATE_NONE: {
549       // This may happen without error when called without exception-style
550       // flavor data, or even from an exception handler when the exception
551       // behavior is EXCEPTION_DEFAULT.
552       return flavor;
553     }
554 
555     default: {
556       NOTREACHED();
557       return THREAD_STATE_NONE;
558     }
559   }
560 }
561 
562 }  // namespace
563 
564 namespace internal {
565 
566 void InitializeCPUContextARM64(CPUContextARM64* context,
567                                thread_state_flavor_t flavor,
568                                ConstThreadState state,
569                                mach_msg_type_number_t state_count,
570                                const arm_thread_state64_t* arm_thread_state64,
571                                const arm_neon_state64_t* arm_neon_state64,
572                                const arm_debug_state64_t* arm_debug_state64) {
573   thread_state_flavor_t set_flavor = THREAD_STATE_NONE;
574   if (flavor != THREAD_STATE_NONE) {
575     set_flavor =
576         InitializeCPUContextARM64Flavor(context, flavor, state, state_count);
577   }
578 
579   if (set_flavor != ARM_THREAD_STATE64) {
580     InitializeCPUContextARM64Thread(context, arm_thread_state64);
581   }
582   if (set_flavor != ARM_NEON_STATE64) {
583     InitializeCPUContextARM64Neon(context, arm_neon_state64);
584   }
585   if (set_flavor != ARM_DEBUG_STATE64) {
586     InitializeCPUContextARM64Debug(context, arm_debug_state64);
587   }
588 }
589 
590 }  // namespace internal
591 
592 #endif
593 
594 }  // namespace crashpad
595