Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(920)

Side by Side Diff: snapshot/exception_snapshot_mac.cc

Issue 650303002: Add ExceptionSnapshotMac (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Address review feedback Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « snapshot/exception_snapshot_mac.h ('k') | snapshot/snapshot.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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/exception_snapshot_mac.h"
16
17 #include "base/logging.h"
18 #include "base/strings/stringprintf.h"
19 #include "snapshot/cpu_context_mac.h"
20 #include "util/mac/process_reader.h"
21 #include "util/mach/exc_server_variants.h"
22 #include "util/numeric/safe_assignment.h"
23
24 namespace crashpad {
25 namespace internal {
26
27 ExceptionSnapshotMac::ExceptionSnapshotMac()
28 : ExceptionSnapshot(),
29 context_union_(),
30 context_(),
31 codes_(),
32 thread_id_(0),
33 exception_address_(0),
34 exception_(0),
35 exception_code_0_(0),
36 initialized_() {
37 }
38
39 ExceptionSnapshotMac::~ExceptionSnapshotMac() {
40 }
41
42 bool ExceptionSnapshotMac::Initialize(ProcessReader* process_reader,
43 thread_t exception_thread,
44 exception_type_t exception,
45 const mach_exception_data_type_t* code,
46 mach_msg_type_number_t code_count,
47 thread_state_flavor_t flavor,
48 const natural_t* state,
49 mach_msg_type_number_t state_count) {
50 INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
51
52 codes_.push_back(exception);
53 for (mach_msg_type_number_t code_index = 0;
54 code_index < code_count;
55 ++code_index) {
56 codes_.push_back(code[code_index]);
57 }
58
59 exception_ = exception;
60 mach_exception_code_t exception_code_0 = code[0];
61
62 if (exception_ == EXC_CRASH) {
63 exception_ = ExcCrashRecoverOriginalException(
64 exception_code_0, &exception_code_0, NULL);
65 }
66
67 // ExceptionInfo() returns code[0] in a 32-bit field. This shouldn’t be a
68 // problem because code[0]’s values never exceed 32 bits. Only code[1] is ever
69 // expected to be that wide.
70 if (!AssignIfInRange(&exception_code_0_, exception_code_0)) {
71 LOG(WARNING)
72 << base::StringPrintf("exception_code_0 0x%llx out of range",
73 exception_code_0);
74 return false;
75 }
76
77 const ProcessReader::Thread* thread = NULL;
78 for (const ProcessReader::Thread& loop_thread : process_reader->Threads()) {
79 if (exception_thread == loop_thread.port) {
80 thread = &loop_thread;
81 break;
82 }
83 }
84
85 if (!thread) {
86 LOG(WARNING) << "exception_thread not found in task";
87 return false;
88 }
89
90 thread_id_ = thread->id;
91
92 // Normally, the exception address is present in code[1] for EXC_BAD_ACCESS
93 // exceptions, but not for other types of exceptions.
94 bool code_1_is_exception_address = exception_ == EXC_BAD_ACCESS;
95
96 #if defined(ARCH_CPU_X86_FAMILY)
97 if (process_reader->Is64Bit()) {
98 context_.architecture = kCPUArchitectureX86_64;
99 context_.x86_64 = &context_union_.x86_64;
100 InitializeCPUContextX86_64(context_.x86_64,
101 flavor,
102 state,
103 state_count,
104 &thread->thread_context.t64,
105 &thread->float_context.f64,
106 &thread->debug_context.d64);
107 } else {
108 context_.architecture = kCPUArchitectureX86;
109 context_.x86 = &context_union_.x86;
110 InitializeCPUContextX86(context_.x86,
111 flavor,
112 state,
113 state_count,
114 &thread->thread_context.t32,
115 &thread->float_context.f32,
116 &thread->debug_context.d32);
117 }
118
119 // For x86 and x86_64 EXC_BAD_ACCESS exceptions, some code[0] values indicate
120 // that code[1] does not (or may not) carry the exception address:
121 // EXC_I386_GPFLT (10.9.5 xnu-2422.115.4/osfmk/i386/trap.c user_trap() for
122 // T_GENERAL_PROTECTION) and the oddball (VM_PROT_READ | VM_PROT_EXECUTE)
123 // which collides with EXC_I386_BOUNDFLT (10.9.5
124 // xnu-2422.115.4/osfmk/i386/fpu.c fpextovrflt()). Other EXC_BAD_ACCESS
125 // exceptions come through 10.9.5 xnu-2422.115.4/osfmk/i386/trap.c
126 // user_page_fault_continue() and do contain the exception address in code[1].
127 if (exception_ == EXC_BAD_ACCESS &&
128 (exception_code_0_ == EXC_I386_GPFLT ||
129 exception_code_0_ == (VM_PROT_READ | VM_PROT_EXECUTE))) {
130 code_1_is_exception_address = false;
131 }
132 #endif
133
134 if (code_1_is_exception_address) {
135 exception_address_ = code[1];
136 } else {
137 exception_address_ = context_.InstructionPointer();
138 }
139
140 INITIALIZATION_STATE_SET_VALID(initialized_);
141 return true;
142 }
143
144 const CPUContext* ExceptionSnapshotMac::Context() const {
145 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
146 return &context_;
147 }
148
149 uint64_t ExceptionSnapshotMac::ThreadID() const {
150 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
151 return thread_id_;
152 }
153
154 uint32_t ExceptionSnapshotMac::Exception() const {
155 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
156 return exception_;
157 }
158
159 uint32_t ExceptionSnapshotMac::ExceptionInfo() const {
160 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
161 return exception_code_0_;
162 }
163
164 uint64_t ExceptionSnapshotMac::ExceptionAddress() const {
165 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
166 return exception_address_;
167 }
168
169 const std::vector<uint64_t>& ExceptionSnapshotMac::Codes() const {
170 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
171 return codes_;
172 }
173
174 } // namespace internal
175 } // namespace crashpad
OLDNEW
« no previous file with comments | « snapshot/exception_snapshot_mac.h ('k') | snapshot/snapshot.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698