OLD | NEW |
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 #include "snapshot/win/cpu_context_win.h" | 15 #include "snapshot/win/cpu_context_win.h" |
16 | 16 |
17 #include <windows.h> | 17 #include <windows.h> |
18 | 18 |
| 19 #include "base/macros.h" |
19 #include "build/build_config.h" | 20 #include "build/build_config.h" |
20 #include "gtest/gtest.h" | 21 #include "gtest/gtest.h" |
| 22 #include "test/hex_string.h" |
21 #include "snapshot/cpu_context.h" | 23 #include "snapshot/cpu_context.h" |
22 | 24 |
23 namespace crashpad { | 25 namespace crashpad { |
24 namespace test { | 26 namespace test { |
25 namespace { | 27 namespace { |
26 | 28 |
| 29 template <typename T> |
| 30 void TestInitializeX86Context() { |
| 31 T context = {0}; |
| 32 context.ContextFlags = WOW64_CONTEXT_INTEGER | |
| 33 WOW64_CONTEXT_DEBUG_REGISTERS | |
| 34 WOW64_CONTEXT_EXTENDED_REGISTERS; |
| 35 context.Eax = 1; |
| 36 context.Dr0 = 3; |
| 37 context.ExtendedRegisters[4] = 2; // FTW |
| 38 |
| 39 // Test the simple case, where everything in the CPUContextX86 argument is set |
| 40 // directly from the supplied thread, float, and debug state parameters. |
| 41 { |
| 42 CPUContextX86 cpu_context_x86 = {}; |
| 43 InitializeX86Context(context, &cpu_context_x86); |
| 44 EXPECT_EQ(1u, cpu_context_x86.eax); |
| 45 EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw); |
| 46 EXPECT_EQ(3u, cpu_context_x86.dr0); |
| 47 } |
| 48 } |
| 49 |
| 50 template <typename T> |
| 51 void TestInitializeX86Context_FsaveWithoutFxsave() { |
| 52 T context = {0}; |
| 53 context.ContextFlags = WOW64_CONTEXT_INTEGER | |
| 54 WOW64_CONTEXT_FLOATING_POINT | |
| 55 WOW64_CONTEXT_DEBUG_REGISTERS; |
| 56 context.Eax = 1; |
| 57 |
| 58 // In fields that are wider than they need to be, set the high bits to ensure |
| 59 // that they’re masked off appropriately in the output. |
| 60 context.FloatSave.ControlWord = 0xffff027f; |
| 61 context.FloatSave.StatusWord = 0xffff0004; |
| 62 context.FloatSave.TagWord = 0xffffa9ff; |
| 63 context.FloatSave.ErrorOffset = 0x01234567; |
| 64 context.FloatSave.ErrorSelector = 0x0bad0003; |
| 65 context.FloatSave.DataOffset = 0x89abcdef; |
| 66 context.FloatSave.DataSelector = 0xffff0007; |
| 67 context.FloatSave.RegisterArea[77] = 0x80; |
| 68 context.FloatSave.RegisterArea[78] = 0xff; |
| 69 context.FloatSave.RegisterArea[79] = 0x7f; |
| 70 |
| 71 context.Dr0 = 3; |
| 72 |
| 73 { |
| 74 CPUContextX86 cpu_context_x86 = {}; |
| 75 InitializeX86Context(context, &cpu_context_x86); |
| 76 |
| 77 EXPECT_EQ(1u, cpu_context_x86.eax); |
| 78 |
| 79 EXPECT_EQ(0x027f, cpu_context_x86.fxsave.fcw); |
| 80 EXPECT_EQ(0x0004, cpu_context_x86.fxsave.fsw); |
| 81 EXPECT_EQ(0x00f0, cpu_context_x86.fxsave.ftw); |
| 82 EXPECT_EQ(0x0bad, cpu_context_x86.fxsave.fop); |
| 83 EXPECT_EQ(0x01234567, cpu_context_x86.fxsave.fpu_ip); |
| 84 EXPECT_EQ(0x0003, cpu_context_x86.fxsave.fpu_cs); |
| 85 EXPECT_EQ(0x89abcdef, cpu_context_x86.fxsave.fpu_dp); |
| 86 EXPECT_EQ(0x0007, cpu_context_x86.fxsave.fpu_ds); |
| 87 for (size_t st_mm = 0; st_mm < 7; ++st_mm) { |
| 88 EXPECT_EQ( |
| 89 std::string(arraysize(cpu_context_x86.fxsave.st_mm[st_mm].st) * 2, |
| 90 '0'), |
| 91 BytesToHexString(cpu_context_x86.fxsave.st_mm[st_mm].st, |
| 92 arraysize(cpu_context_x86.fxsave.st_mm[st_mm].st))) |
| 93 << "st_mm " << st_mm; |
| 94 } |
| 95 EXPECT_EQ("0000000000000080ff7f", |
| 96 BytesToHexString(cpu_context_x86.fxsave.st_mm[7].st, |
| 97 arraysize(cpu_context_x86.fxsave.st_mm[7].st))); |
| 98 |
| 99 EXPECT_EQ(3u, cpu_context_x86.dr0); |
| 100 } |
| 101 } |
| 102 |
| 103 #if defined(ARCH_CPU_X86_FAMILY) |
| 104 |
27 #if defined(ARCH_CPU_X86_64) | 105 #if defined(ARCH_CPU_X86_64) |
28 | 106 |
29 TEST(CPUContextWin, InitializeX64Context) { | 107 TEST(CPUContextWin, InitializeX64Context) { |
30 CONTEXT context = {0}; | 108 CONTEXT context = {0}; |
31 context.Rax = 10; | 109 context.Rax = 10; |
32 context.FltSave.TagWord = 11; | 110 context.FltSave.TagWord = 11; |
33 context.Dr0 = 12; | 111 context.Dr0 = 12; |
34 context.ContextFlags = | 112 context.ContextFlags = |
35 CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS; | 113 CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS; |
36 | 114 |
37 // Test the simple case, where everything in the CPUContextX86_64 argument is | 115 // Test the simple case, where everything in the CPUContextX86_64 argument is |
38 // set directly from the supplied thread, float, and debug state parameters. | 116 // set directly from the supplied thread, float, and debug state parameters. |
39 { | 117 { |
40 CPUContextX86_64 cpu_context_x86_64 = {}; | 118 CPUContextX86_64 cpu_context_x86_64 = {}; |
41 InitializeX64Context(context, &cpu_context_x86_64); | 119 InitializeX64Context(context, &cpu_context_x86_64); |
42 EXPECT_EQ(10u, cpu_context_x86_64.rax); | 120 EXPECT_EQ(10u, cpu_context_x86_64.rax); |
43 EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw); | 121 EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw); |
44 EXPECT_EQ(12u, cpu_context_x86_64.dr0); | 122 EXPECT_EQ(12u, cpu_context_x86_64.dr0); |
45 } | 123 } |
46 } | 124 } |
47 | 125 |
48 #else | |
49 | |
50 TEST(CPUContextWin, InitializeX86Context) { | |
51 CONTEXT context = {0}; | |
52 context.ContextFlags = | |
53 CONTEXT_INTEGER | CONTEXT_EXTENDED_REGISTERS | CONTEXT_DEBUG_REGISTERS; | |
54 context.Eax = 1; | |
55 context.ExtendedRegisters[4] = 2; // FTW. | |
56 context.Dr0 = 3; | |
57 | |
58 // Test the simple case, where everything in the CPUContextX86 argument is | |
59 // set directly from the supplied thread, float, and debug state parameters. | |
60 { | |
61 CPUContextX86 cpu_context_x86 = {}; | |
62 InitializeX86Context(context, &cpu_context_x86); | |
63 EXPECT_EQ(1u, cpu_context_x86.eax); | |
64 EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw); | |
65 EXPECT_EQ(3u, cpu_context_x86.dr0); | |
66 } | |
67 } | |
68 | |
69 #endif // ARCH_CPU_X86_64 | 126 #endif // ARCH_CPU_X86_64 |
70 | 127 |
| 128 TEST(CPUContextWin, InitializeX86Context) { |
| 129 #if defined(ARCH_CPU_X86) |
| 130 TestInitializeX86Context<CONTEXT>(); |
| 131 #else // ARCH_CPU_X86 |
| 132 TestInitializeX86Context<WOW64_CONTEXT>(); |
| 133 #endif // ARCH_CPU_X86 |
| 134 } |
| 135 |
| 136 TEST(CPUContextWin, InitializeX86Context_FsaveWithoutFxsave) { |
| 137 #if defined(ARCH_CPU_X86) |
| 138 TestInitializeX86Context_FsaveWithoutFxsave<CONTEXT>(); |
| 139 #else // ARCH_CPU_X86 |
| 140 TestInitializeX86Context_FsaveWithoutFxsave<WOW64_CONTEXT>(); |
| 141 #endif // ARCH_CPU_X86 |
| 142 } |
| 143 |
| 144 #endif // ARCH_CPU_X86_FAMILY |
| 145 |
71 } // namespace | 146 } // namespace |
72 } // namespace test | 147 } // namespace test |
73 } // namespace crashpad | 148 } // namespace crashpad |
OLD | NEW |