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