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 |
17 #include "base/logging.h" | 19 #include "base/logging.h" |
| 20 #include "base/macros.h" |
18 #include "util/misc/implicit_cast.h" | 21 #include "util/misc/implicit_cast.h" |
19 | 22 |
20 namespace crashpad { | 23 namespace crashpad { |
21 | 24 |
| 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 |
22 // static | 90 // static |
23 uint16_t CPUContextX86::FxsaveToFsaveTagWord( | 91 uint16_t CPUContextX86::FxsaveToFsaveTagWord( |
24 uint16_t fsw, | 92 uint16_t fsw, |
25 uint8_t fxsave_tag, | 93 uint8_t fxsave_tag, |
26 const CPUContextX86::X87OrMMXRegister st_mm[8]) { | 94 const CPUContextX86::X87OrMMXRegister st_mm[8]) { |
27 enum { | |
28 kX87TagValid = 0, | |
29 kX87TagZero, | |
30 kX87TagSpecial, | |
31 kX87TagEmpty, | |
32 }; | |
33 | |
34 // The x87 tag word (in both abridged and full form) identifies physical | 95 // The x87 tag word (in both abridged and full form) identifies physical |
35 // registers, but |st_mm| is arranged in logical stack order. In order to map | 96 // registers, but |st_mm| is arranged in logical stack order. In order to map |
36 // physical tag word bits to the logical stack registers they correspond to, | 97 // physical tag word bits to the logical stack registers they correspond to, |
37 // the “stack top” value from the x87 status word is necessary. | 98 // the “stack top” value from the x87 status word is necessary. |
38 int stack_top = (fsw >> 11) & 0x7; | 99 int stack_top = (fsw >> 11) & 0x7; |
39 | 100 |
40 uint16_t fsave_tag = 0; | 101 uint16_t fsave_tag = 0; |
41 for (int physical_index = 0; physical_index < 8; ++physical_index) { | 102 for (int physical_index = 0; physical_index < 8; ++physical_index) { |
42 bool fxsave_bit = (fxsave_tag & (1 << physical_index)) != 0; | 103 bool fxsave_bit = (fxsave_tag & (1 << physical_index)) != 0; |
43 uint8_t fsave_bits; | 104 uint8_t fsave_bits; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 } else { | 139 } else { |
79 fsave_bits = kX87TagEmpty; | 140 fsave_bits = kX87TagEmpty; |
80 } | 141 } |
81 | 142 |
82 fsave_tag |= (fsave_bits << (physical_index * 2)); | 143 fsave_tag |= (fsave_bits << (physical_index * 2)); |
83 } | 144 } |
84 | 145 |
85 return fsave_tag; | 146 return fsave_tag; |
86 } | 147 } |
87 | 148 |
| 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 |
88 uint64_t CPUContext::InstructionPointer() const { | 160 uint64_t CPUContext::InstructionPointer() const { |
89 switch (architecture) { | 161 switch (architecture) { |
90 case kCPUArchitectureX86: | 162 case kCPUArchitectureX86: |
91 return x86->eip; | 163 return x86->eip; |
92 case kCPUArchitectureX86_64: | 164 case kCPUArchitectureX86_64: |
93 return x86_64->rip; | 165 return x86_64->rip; |
94 default: | 166 default: |
95 NOTREACHED(); | 167 NOTREACHED(); |
96 return ~0ull; | 168 return ~0ull; |
97 } | 169 } |
98 } | 170 } |
99 | 171 |
100 } // namespace crashpad | 172 } // namespace crashpad |
OLD | NEW |