| 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 |