OLD | NEW |
| (Empty) |
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/cpu_context_mac.h" | |
16 | |
17 #include <mach/mach.h> | |
18 | |
19 #include "gtest/gtest.h" | |
20 | |
21 namespace crashpad { | |
22 namespace test { | |
23 namespace { | |
24 | |
25 #if defined(ARCH_CPU_X86_FAMILY) | |
26 | |
27 TEST(CPUContextMac, InitializeContextX86) { | |
28 x86_thread_state32_t x86_thread_state32 = {}; | |
29 x86_float_state32_t x86_float_state32 = {}; | |
30 x86_debug_state32_t x86_debug_state32 = {}; | |
31 x86_thread_state32.__eax = 1; | |
32 x86_float_state32.__fpu_ftw = 2; | |
33 x86_debug_state32.__dr0 = 3; | |
34 | |
35 // Test the simple case, where everything in the CPUContextX86 argument is set | |
36 // directly from the supplied thread, float, and debug state parameters. | |
37 { | |
38 CPUContextX86 cpu_context_x86 = {}; | |
39 internal::InitializeCPUContextX86(&cpu_context_x86, | |
40 THREAD_STATE_NONE, | |
41 nullptr, | |
42 0, | |
43 &x86_thread_state32, | |
44 &x86_float_state32, | |
45 &x86_debug_state32); | |
46 EXPECT_EQ(1u, cpu_context_x86.eax); | |
47 EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw); | |
48 EXPECT_EQ(3u, cpu_context_x86.dr0); | |
49 } | |
50 | |
51 // Supply context in a CPU-specific “flavor” parameter expected to be used | |
52 // instead of the supplied thread, float, or debug state parameters. Do this | |
53 // once for each of the three valid flavors. This simulates how | |
54 // InitializeCPUContextX86() might be used to initialize the context in an | |
55 // exception handler, where the exception handler may have received the | |
56 // “flavor” parameter and this context should be used to initialize the | |
57 // CPUContextX86. | |
58 | |
59 { | |
60 x86_thread_state32_t alt_x86_thread_state32 = {}; | |
61 alt_x86_thread_state32.__eax = 4; | |
62 | |
63 CPUContextX86 cpu_context_x86 = {}; | |
64 internal::InitializeCPUContextX86( | |
65 &cpu_context_x86, | |
66 x86_THREAD_STATE32, | |
67 reinterpret_cast<natural_t*>(&alt_x86_thread_state32), | |
68 x86_THREAD_STATE32_COUNT, | |
69 &x86_thread_state32, | |
70 &x86_float_state32, | |
71 &x86_debug_state32); | |
72 EXPECT_EQ(4u, cpu_context_x86.eax); | |
73 EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw); | |
74 EXPECT_EQ(3u, cpu_context_x86.dr0); | |
75 } | |
76 | |
77 { | |
78 x86_float_state32_t alt_x86_float_state32 = {}; | |
79 alt_x86_float_state32.__fpu_ftw = 5; | |
80 | |
81 CPUContextX86 cpu_context_x86 = {}; | |
82 internal::InitializeCPUContextX86( | |
83 &cpu_context_x86, | |
84 x86_FLOAT_STATE32, | |
85 reinterpret_cast<natural_t*>(&alt_x86_float_state32), | |
86 x86_FLOAT_STATE32_COUNT, | |
87 &x86_thread_state32, | |
88 &x86_float_state32, | |
89 &x86_debug_state32); | |
90 EXPECT_EQ(1u, cpu_context_x86.eax); | |
91 EXPECT_EQ(5u, cpu_context_x86.fxsave.ftw); | |
92 EXPECT_EQ(3u, cpu_context_x86.dr0); | |
93 } | |
94 | |
95 { | |
96 x86_debug_state32_t alt_x86_debug_state32 = {}; | |
97 alt_x86_debug_state32.__dr0 = 6; | |
98 | |
99 CPUContextX86 cpu_context_x86 = {}; | |
100 internal::InitializeCPUContextX86( | |
101 &cpu_context_x86, | |
102 x86_DEBUG_STATE32, | |
103 reinterpret_cast<natural_t*>(&alt_x86_debug_state32), | |
104 x86_DEBUG_STATE32_COUNT, | |
105 &x86_thread_state32, | |
106 &x86_float_state32, | |
107 &x86_debug_state32); | |
108 EXPECT_EQ(1u, cpu_context_x86.eax); | |
109 EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw); | |
110 EXPECT_EQ(6u, cpu_context_x86.dr0); | |
111 } | |
112 | |
113 // Supply context in a universal “flavor” parameter expected to be used | |
114 // instead of the supplied thread, float, or debug state parameters. The | |
115 // universal format allows an exception handler to be registered to receive | |
116 // thread, float, or debug state without having to know in advance whether it | |
117 // will be receiving the state from a 32-bit or 64-bit process. For | |
118 // CPUContextX86, only the 32-bit form is supported. | |
119 | |
120 { | |
121 x86_thread_state x86_thread_state_3264 = {}; | |
122 x86_thread_state_3264.tsh.flavor = x86_THREAD_STATE32; | |
123 x86_thread_state_3264.tsh.count = x86_THREAD_STATE32_COUNT; | |
124 x86_thread_state_3264.uts.ts32.__eax = 7; | |
125 | |
126 CPUContextX86 cpu_context_x86 = {}; | |
127 internal::InitializeCPUContextX86( | |
128 &cpu_context_x86, | |
129 x86_THREAD_STATE, | |
130 reinterpret_cast<natural_t*>(&x86_thread_state_3264), | |
131 x86_THREAD_STATE_COUNT, | |
132 &x86_thread_state32, | |
133 &x86_float_state32, | |
134 &x86_debug_state32); | |
135 EXPECT_EQ(7u, cpu_context_x86.eax); | |
136 EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw); | |
137 EXPECT_EQ(3u, cpu_context_x86.dr0); | |
138 } | |
139 | |
140 { | |
141 x86_float_state x86_float_state_3264 = {}; | |
142 x86_float_state_3264.fsh.flavor = x86_FLOAT_STATE32; | |
143 x86_float_state_3264.fsh.count = x86_FLOAT_STATE32_COUNT; | |
144 x86_float_state_3264.ufs.fs32.__fpu_ftw = 8; | |
145 | |
146 CPUContextX86 cpu_context_x86 = {}; | |
147 internal::InitializeCPUContextX86( | |
148 &cpu_context_x86, | |
149 x86_FLOAT_STATE, | |
150 reinterpret_cast<natural_t*>(&x86_float_state_3264), | |
151 x86_FLOAT_STATE_COUNT, | |
152 &x86_thread_state32, | |
153 &x86_float_state32, | |
154 &x86_debug_state32); | |
155 EXPECT_EQ(1u, cpu_context_x86.eax); | |
156 EXPECT_EQ(8u, cpu_context_x86.fxsave.ftw); | |
157 EXPECT_EQ(3u, cpu_context_x86.dr0); | |
158 } | |
159 | |
160 { | |
161 x86_debug_state x86_debug_state_3264 = {}; | |
162 x86_debug_state_3264.dsh.flavor = x86_DEBUG_STATE32; | |
163 x86_debug_state_3264.dsh.count = x86_DEBUG_STATE32_COUNT; | |
164 x86_debug_state_3264.uds.ds32.__dr0 = 9; | |
165 | |
166 CPUContextX86 cpu_context_x86 = {}; | |
167 internal::InitializeCPUContextX86( | |
168 &cpu_context_x86, | |
169 x86_DEBUG_STATE, | |
170 reinterpret_cast<natural_t*>(&x86_debug_state_3264), | |
171 x86_DEBUG_STATE_COUNT, | |
172 &x86_thread_state32, | |
173 &x86_float_state32, | |
174 &x86_debug_state32); | |
175 EXPECT_EQ(1u, cpu_context_x86.eax); | |
176 EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw); | |
177 EXPECT_EQ(9u, cpu_context_x86.dr0); | |
178 } | |
179 | |
180 // Supply inappropriate “flavor” contexts to test that | |
181 // InitializeCPUContextX86() detects the problem and refuses to use the | |
182 // supplied “flavor” context, falling back to the thread, float, and debug | |
183 // states. | |
184 | |
185 { | |
186 x86_thread_state64_t x86_thread_state64 = {}; | |
187 | |
188 CPUContextX86 cpu_context_x86 = {}; | |
189 internal::InitializeCPUContextX86( | |
190 &cpu_context_x86, | |
191 x86_THREAD_STATE64, | |
192 reinterpret_cast<natural_t*>(&x86_thread_state64), | |
193 x86_THREAD_STATE64_COUNT, | |
194 &x86_thread_state32, | |
195 &x86_float_state32, | |
196 &x86_debug_state32); | |
197 EXPECT_EQ(1u, cpu_context_x86.eax); | |
198 EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw); | |
199 EXPECT_EQ(3u, cpu_context_x86.dr0); | |
200 } | |
201 | |
202 { | |
203 x86_thread_state x86_thread_state_3264 = {}; | |
204 x86_thread_state_3264.tsh.flavor = x86_THREAD_STATE64; | |
205 x86_thread_state_3264.tsh.count = x86_THREAD_STATE64_COUNT; | |
206 | |
207 CPUContextX86 cpu_context_x86 = {}; | |
208 internal::InitializeCPUContextX86( | |
209 &cpu_context_x86, | |
210 x86_THREAD_STATE, | |
211 reinterpret_cast<natural_t*>(&x86_thread_state_3264), | |
212 x86_THREAD_STATE_COUNT, | |
213 &x86_thread_state32, | |
214 &x86_float_state32, | |
215 &x86_debug_state32); | |
216 EXPECT_EQ(1u, cpu_context_x86.eax); | |
217 EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw); | |
218 EXPECT_EQ(3u, cpu_context_x86.dr0); | |
219 } | |
220 } | |
221 | |
222 TEST(CPUContextMac, InitializeContextX86_64) { | |
223 x86_thread_state64_t x86_thread_state64 = {}; | |
224 x86_float_state64_t x86_float_state64 = {}; | |
225 x86_debug_state64_t x86_debug_state64 = {}; | |
226 x86_thread_state64.__rax = 10; | |
227 x86_float_state64.__fpu_ftw = 11; | |
228 x86_debug_state64.__dr0 = 12; | |
229 | |
230 // Test the simple case, where everything in the CPUContextX86_64 argument is | |
231 // set directly from the supplied thread, float, and debug state parameters. | |
232 { | |
233 CPUContextX86_64 cpu_context_x86_64 = {}; | |
234 internal::InitializeCPUContextX86_64(&cpu_context_x86_64, | |
235 THREAD_STATE_NONE, | |
236 nullptr, | |
237 0, | |
238 &x86_thread_state64, | |
239 &x86_float_state64, | |
240 &x86_debug_state64); | |
241 EXPECT_EQ(10u, cpu_context_x86_64.rax); | |
242 EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw); | |
243 EXPECT_EQ(12u, cpu_context_x86_64.dr0); | |
244 } | |
245 | |
246 // Supply context in a CPU-specific “flavor” parameter expected to be used | |
247 // instead of the supplied thread, float, or debug state parameters. Do this | |
248 // once for each of the three valid flavors. This simulates how | |
249 // InitializeCPUContextX86_64() might be used to initialize the context in an | |
250 // exception handler, where the exception handler may have received the | |
251 // “flavor” parameter and this context should be used to initialize the | |
252 // CPUContextX86_64. | |
253 | |
254 { | |
255 x86_thread_state64_t alt_x86_thread_state64 = {}; | |
256 alt_x86_thread_state64.__rax = 13; | |
257 | |
258 CPUContextX86_64 cpu_context_x86_64 = {}; | |
259 internal::InitializeCPUContextX86_64( | |
260 &cpu_context_x86_64, | |
261 x86_THREAD_STATE64, | |
262 reinterpret_cast<natural_t*>(&alt_x86_thread_state64), | |
263 x86_THREAD_STATE64_COUNT, | |
264 &x86_thread_state64, | |
265 &x86_float_state64, | |
266 &x86_debug_state64); | |
267 EXPECT_EQ(13u, cpu_context_x86_64.rax); | |
268 EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw); | |
269 EXPECT_EQ(12u, cpu_context_x86_64.dr0); | |
270 } | |
271 | |
272 { | |
273 x86_float_state64_t alt_x86_float_state64 = {}; | |
274 alt_x86_float_state64.__fpu_ftw = 14; | |
275 | |
276 CPUContextX86_64 cpu_context_x86_64 = {}; | |
277 internal::InitializeCPUContextX86_64( | |
278 &cpu_context_x86_64, | |
279 x86_FLOAT_STATE64, | |
280 reinterpret_cast<natural_t*>(&alt_x86_float_state64), | |
281 x86_FLOAT_STATE64_COUNT, | |
282 &x86_thread_state64, | |
283 &x86_float_state64, | |
284 &x86_debug_state64); | |
285 EXPECT_EQ(10u, cpu_context_x86_64.rax); | |
286 EXPECT_EQ(14u, cpu_context_x86_64.fxsave.ftw); | |
287 EXPECT_EQ(12u, cpu_context_x86_64.dr0); | |
288 } | |
289 | |
290 { | |
291 x86_debug_state64_t alt_x86_debug_state64 = {}; | |
292 alt_x86_debug_state64.__dr0 = 15; | |
293 | |
294 CPUContextX86_64 cpu_context_x86_64 = {}; | |
295 internal::InitializeCPUContextX86_64( | |
296 &cpu_context_x86_64, | |
297 x86_DEBUG_STATE64, | |
298 reinterpret_cast<natural_t*>(&alt_x86_debug_state64), | |
299 x86_DEBUG_STATE64_COUNT, | |
300 &x86_thread_state64, | |
301 &x86_float_state64, | |
302 &x86_debug_state64); | |
303 EXPECT_EQ(10u, cpu_context_x86_64.rax); | |
304 EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw); | |
305 EXPECT_EQ(15u, cpu_context_x86_64.dr0); | |
306 } | |
307 | |
308 // Supply context in a universal “flavor” parameter expected to be used | |
309 // instead of the supplied thread, float, or debug state parameters. The | |
310 // universal format allows an exception handler to be registered to receive | |
311 // thread, float, or debug state without having to know in advance whether it | |
312 // will be receiving the state from a 32-bit or 64-bit process. For | |
313 // CPUContextX86_64, only the 64-bit form is supported. | |
314 | |
315 { | |
316 x86_thread_state x86_thread_state_3264 = {}; | |
317 x86_thread_state_3264.tsh.flavor = x86_THREAD_STATE64; | |
318 x86_thread_state_3264.tsh.count = x86_THREAD_STATE64_COUNT; | |
319 x86_thread_state_3264.uts.ts64.__rax = 16; | |
320 | |
321 CPUContextX86_64 cpu_context_x86_64 = {}; | |
322 internal::InitializeCPUContextX86_64( | |
323 &cpu_context_x86_64, | |
324 x86_THREAD_STATE, | |
325 reinterpret_cast<natural_t*>(&x86_thread_state_3264), | |
326 x86_THREAD_STATE_COUNT, | |
327 &x86_thread_state64, | |
328 &x86_float_state64, | |
329 &x86_debug_state64); | |
330 EXPECT_EQ(16u, cpu_context_x86_64.rax); | |
331 EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw); | |
332 EXPECT_EQ(12u, cpu_context_x86_64.dr0); | |
333 } | |
334 | |
335 { | |
336 x86_float_state x86_float_state_3264 = {}; | |
337 x86_float_state_3264.fsh.flavor = x86_FLOAT_STATE64; | |
338 x86_float_state_3264.fsh.count = x86_FLOAT_STATE64_COUNT; | |
339 x86_float_state_3264.ufs.fs64.__fpu_ftw = 17; | |
340 | |
341 CPUContextX86_64 cpu_context_x86_64 = {}; | |
342 internal::InitializeCPUContextX86_64( | |
343 &cpu_context_x86_64, | |
344 x86_FLOAT_STATE, | |
345 reinterpret_cast<natural_t*>(&x86_float_state_3264), | |
346 x86_FLOAT_STATE_COUNT, | |
347 &x86_thread_state64, | |
348 &x86_float_state64, | |
349 &x86_debug_state64); | |
350 EXPECT_EQ(10u, cpu_context_x86_64.rax); | |
351 EXPECT_EQ(17u, cpu_context_x86_64.fxsave.ftw); | |
352 EXPECT_EQ(12u, cpu_context_x86_64.dr0); | |
353 } | |
354 | |
355 { | |
356 x86_debug_state x86_debug_state_3264 = {}; | |
357 x86_debug_state_3264.dsh.flavor = x86_DEBUG_STATE64; | |
358 x86_debug_state_3264.dsh.count = x86_DEBUG_STATE64_COUNT; | |
359 x86_debug_state_3264.uds.ds64.__dr0 = 18; | |
360 | |
361 CPUContextX86_64 cpu_context_x86_64 = {}; | |
362 internal::InitializeCPUContextX86_64( | |
363 &cpu_context_x86_64, | |
364 x86_DEBUG_STATE, | |
365 reinterpret_cast<natural_t*>(&x86_debug_state_3264), | |
366 x86_DEBUG_STATE_COUNT, | |
367 &x86_thread_state64, | |
368 &x86_float_state64, | |
369 &x86_debug_state64); | |
370 EXPECT_EQ(10u, cpu_context_x86_64.rax); | |
371 EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw); | |
372 EXPECT_EQ(18u, cpu_context_x86_64.dr0); | |
373 } | |
374 | |
375 // Supply inappropriate “flavor” contexts to test that | |
376 // InitializeCPUContextX86() detects the problem and refuses to use the | |
377 // supplied “flavor” context, falling back to the thread, float, and debug | |
378 // states. | |
379 | |
380 { | |
381 x86_thread_state32_t x86_thread_state32 = {}; | |
382 | |
383 CPUContextX86_64 cpu_context_x86_64 = {}; | |
384 internal::InitializeCPUContextX86_64( | |
385 &cpu_context_x86_64, | |
386 x86_THREAD_STATE32, | |
387 reinterpret_cast<natural_t*>(&x86_thread_state32), | |
388 x86_THREAD_STATE32_COUNT, | |
389 &x86_thread_state64, | |
390 &x86_float_state64, | |
391 &x86_debug_state64); | |
392 EXPECT_EQ(10u, cpu_context_x86_64.rax); | |
393 EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw); | |
394 EXPECT_EQ(12u, cpu_context_x86_64.dr0); | |
395 } | |
396 | |
397 { | |
398 x86_thread_state x86_thread_state_3264 = {}; | |
399 x86_thread_state_3264.tsh.flavor = x86_THREAD_STATE32; | |
400 x86_thread_state_3264.tsh.count = x86_THREAD_STATE32_COUNT; | |
401 | |
402 CPUContextX86_64 cpu_context_x86_64 = {}; | |
403 internal::InitializeCPUContextX86_64( | |
404 &cpu_context_x86_64, | |
405 x86_THREAD_STATE, | |
406 reinterpret_cast<natural_t*>(&x86_thread_state_3264), | |
407 x86_THREAD_STATE_COUNT, | |
408 &x86_thread_state64, | |
409 &x86_float_state64, | |
410 &x86_debug_state64); | |
411 EXPECT_EQ(10u, cpu_context_x86_64.rax); | |
412 EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw); | |
413 EXPECT_EQ(12u, cpu_context_x86_64.dr0); | |
414 } | |
415 } | |
416 | |
417 #endif | |
418 | |
419 } // namespace | |
420 } // namespace test | |
421 } // namespace crashpad | |
OLD | NEW |