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/cpu_context.h" | 15 #include "snapshot/cpu_context.h" |
16 | 16 |
17 #include <string.h> | |
18 | |
19 #include "base/logging.h" | 17 #include "base/logging.h" |
20 #include "base/macros.h" | |
21 #include "util/misc/implicit_cast.h" | 18 #include "util/misc/implicit_cast.h" |
22 | 19 |
23 namespace crashpad { | 20 namespace crashpad { |
24 | 21 |
25 namespace { | |
26 | |
27 // Sanity-check complex structures to ensure interoperability. | |
28 static_assert(sizeof(CPUContextX86::Fsave) == 108, "CPUContextX86::Fsave size"); | |
29 static_assert(sizeof(CPUContextX86::Fxsave) == 512, | |
30 "CPUContextX86::Fxsave size"); | |
31 static_assert(sizeof(CPUContextX86_64::Fxsave) == 512, | |
32 "CPUContextX86_64::Fxsave size"); | |
33 | |
34 enum { | |
35 kX87TagValid = 0, | |
36 kX87TagZero, | |
37 kX87TagSpecial, | |
38 kX87TagEmpty, | |
39 }; | |
40 | |
41 } // namespace | |
42 | |
43 // static | |
44 void CPUContextX86::FxsaveToFsave(const Fxsave& fxsave, Fsave* fsave) { | |
45 fsave->fcw = fxsave.fcw; | |
46 fsave->reserved_1 = 0; | |
47 fsave->fsw = fxsave.fsw; | |
48 fsave->reserved_2 = 0; | |
49 fsave->ftw = FxsaveToFsaveTagWord(fxsave.fsw, fxsave.ftw, fxsave.st_mm); | |
50 fsave->reserved_3 = 0; | |
51 fsave->fpu_ip = fxsave.fpu_ip; | |
52 fsave->fpu_cs = fxsave.fpu_cs; | |
53 fsave->fop = fxsave.fop; | |
54 fsave->fpu_dp = fxsave.fpu_dp; | |
55 fsave->fpu_ds = fxsave.fpu_ds; | |
56 fsave->reserved_4 = 0; | |
57 static_assert(arraysize(fsave->st) == arraysize(fxsave.st_mm), | |
58 "FPU stack registers must be equivalent"); | |
59 for (size_t index = 0; index < arraysize(fsave->st); ++index) { | |
60 memcpy(fsave->st[index], fxsave.st_mm[index].st, sizeof(fsave->st[index])); | |
61 } | |
62 } | |
63 | |
64 // static | |
65 void CPUContextX86::FsaveToFxsave(const Fsave& fsave, Fxsave* fxsave) { | |
66 fxsave->fcw = fsave.fcw; | |
67 fxsave->fsw = fsave.fsw; | |
68 fxsave->ftw = FsaveToFxsaveTagWord(fsave.ftw); | |
69 fxsave->reserved_1 = 0; | |
70 fxsave->fop = fsave.fop; | |
71 fxsave->fpu_ip = fsave.fpu_ip; | |
72 fxsave->fpu_cs = fsave.fpu_cs; | |
73 fxsave->reserved_2 = 0; | |
74 fxsave->fpu_dp = fsave.fpu_dp; | |
75 fxsave->fpu_ds = fsave.fpu_ds; | |
76 fxsave->reserved_3 = 0; | |
77 fxsave->mxcsr = 0; | |
78 fxsave->mxcsr_mask = 0; | |
79 static_assert(arraysize(fxsave->st_mm) == arraysize(fsave.st), | |
80 "FPU stack registers must be equivalent"); | |
81 for (size_t index = 0; index < arraysize(fsave.st); ++index) { | |
82 memcpy(fxsave->st_mm[index].st, fsave.st[index], sizeof(fsave.st[index])); | |
83 memset(fxsave->st_mm[index].st_reserved, | |
84 0, | |
85 sizeof(fxsave->st_mm[index].st_reserved)); | |
86 } | |
87 memset(fxsave->xmm, 0, sizeof(*fxsave) - offsetof(Fxsave, xmm)); | |
88 } | |
89 | |
90 // static | 22 // static |
91 uint16_t CPUContextX86::FxsaveToFsaveTagWord( | 23 uint16_t CPUContextX86::FxsaveToFsaveTagWord( |
92 uint16_t fsw, | 24 uint16_t fsw, |
93 uint8_t fxsave_tag, | 25 uint8_t fxsave_tag, |
94 const CPUContextX86::X87OrMMXRegister st_mm[8]) { | 26 const CPUContextX86::X87OrMMXRegister st_mm[8]) { |
| 27 enum { |
| 28 kX87TagValid = 0, |
| 29 kX87TagZero, |
| 30 kX87TagSpecial, |
| 31 kX87TagEmpty, |
| 32 }; |
| 33 |
95 // The x87 tag word (in both abridged and full form) identifies physical | 34 // The x87 tag word (in both abridged and full form) identifies physical |
96 // registers, but |st_mm| is arranged in logical stack order. In order to map | 35 // registers, but |st_mm| is arranged in logical stack order. In order to map |
97 // physical tag word bits to the logical stack registers they correspond to, | 36 // physical tag word bits to the logical stack registers they correspond to, |
98 // the “stack top” value from the x87 status word is necessary. | 37 // the “stack top” value from the x87 status word is necessary. |
99 int stack_top = (fsw >> 11) & 0x7; | 38 int stack_top = (fsw >> 11) & 0x7; |
100 | 39 |
101 uint16_t fsave_tag = 0; | 40 uint16_t fsave_tag = 0; |
102 for (int physical_index = 0; physical_index < 8; ++physical_index) { | 41 for (int physical_index = 0; physical_index < 8; ++physical_index) { |
103 bool fxsave_bit = (fxsave_tag & (1 << physical_index)) != 0; | 42 bool fxsave_bit = (fxsave_tag & (1 << physical_index)) != 0; |
104 uint8_t fsave_bits; | 43 uint8_t fsave_bits; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 } else { | 78 } else { |
140 fsave_bits = kX87TagEmpty; | 79 fsave_bits = kX87TagEmpty; |
141 } | 80 } |
142 | 81 |
143 fsave_tag |= (fsave_bits << (physical_index * 2)); | 82 fsave_tag |= (fsave_bits << (physical_index * 2)); |
144 } | 83 } |
145 | 84 |
146 return fsave_tag; | 85 return fsave_tag; |
147 } | 86 } |
148 | 87 |
149 // static | |
150 uint8_t CPUContextX86::FsaveToFxsaveTagWord(uint16_t fsave_tag) { | |
151 uint8_t fxsave_tag = 0; | |
152 for (int physical_index = 0; physical_index < 8; ++physical_index) { | |
153 const uint8_t fsave_bits = (fsave_tag >> (physical_index * 2)) & 0x3; | |
154 const bool fxsave_bit = fsave_bits != kX87TagEmpty; | |
155 fxsave_tag |= fxsave_bit << physical_index; | |
156 } | |
157 return fxsave_tag; | |
158 } | |
159 | |
160 uint64_t CPUContext::InstructionPointer() const { | 88 uint64_t CPUContext::InstructionPointer() const { |
161 switch (architecture) { | 89 switch (architecture) { |
162 case kCPUArchitectureX86: | 90 case kCPUArchitectureX86: |
163 return x86->eip; | 91 return x86->eip; |
164 case kCPUArchitectureX86_64: | 92 case kCPUArchitectureX86_64: |
165 return x86_64->rip; | 93 return x86_64->rip; |
166 default: | 94 default: |
167 NOTREACHED(); | 95 NOTREACHED(); |
168 return ~0ull; | 96 return ~0ull; |
169 } | 97 } |
170 } | 98 } |
171 | 99 |
172 } // namespace crashpad | 100 } // namespace crashpad |
OLD | NEW |