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

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: 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 "snapshot/cpu_context_mac.h"
19 #include "util/mac/process_reader.h"
20
21 namespace crashpad {
22 namespace internal {
23
24 ExceptionSnapshotMac::ExceptionSnapshotMac()
25 : ExceptionSnapshot(),
26 context_union_(),
27 context_(),
28 codes_(),
29 thread_id_(0),
30 exception_address_(0),
31 exception_(0),
32 exception_code_0_(0),
33 initialized_() {
34 }
35
36 ExceptionSnapshotMac::~ExceptionSnapshotMac() {
37 }
38
39 bool ExceptionSnapshotMac::Initialize(ProcessReader* process_reader,
40 thread_t exception_thread,
41 exception_type_t exception,
42 const mach_exception_data_type_t* code,
43 mach_msg_type_number_t code_count,
44 thread_state_flavor_t flavor,
45 const natural_t* state,
46 mach_msg_type_number_t state_count) {
47 INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
48
49 codes_.push_back(exception);
50 for (mach_msg_type_number_t code_index = 0;
51 code_index < code_count;
52 ++code_index) {
53 codes_.push_back(code[code_index]);
54 }
55
56 exception_ = exception;
57 exception_code_0_ = code[0];
58
59 if (exception == EXC_CRASH) {
60 // Recover the original exception and the original code[0] from code[0]. See
61 // 10.9.5 xnu-2422.115.4/bsd/kern/kern_exit.c proc_prepareexit().
62 //
63 // This is only done if the EXC_CRASH exception originated from a previous
64 // exception. This is not the case for certain software-triggered
65 // terminations, such as exiting on a signal that causes termination. This
66 // happens by default for SIGABRT, for example, so abort() calls will
67 // ordinarily lead to EXC_CRASH showing up in Exception().
68 //
69 // Note: the signal number is stored at (code[0] >> 24) & 0xff.
70 exception_type_t original_exception = (code[0] >> 20) & 0xf;
Robert Sesek 2014/10/13 21:04:54 This is ExcCrashRecoverOriginalException() right?
71 if (original_exception > 0) {
72 exception_ = original_exception;
73 exception_code_0_ = code[0] & 0xfffff;
74 }
75 }
76
77 const std::vector<ProcessReader::Thread>& threads = process_reader->Threads();
78 const ProcessReader::Thread* thread = NULL;
79 for (std::vector<ProcessReader::Thread>::const_iterator thread_iterator =
Robert Sesek 2014/10/13 21:04:54 C++11 loop ?
80 threads.begin();
81 thread_iterator != threads.end();
82 ++thread_iterator) {
83 if (exception_thread == thread_iterator->port) {
84 thread = &*thread_iterator;
85 break;
86 }
87 }
88
89 if (!thread) {
90 LOG(WARNING) << "exception_thread not found in task";
91 return false;
92 }
93
94 thread_id_ = thread->id;
95
96 // Normally, the exception address is present in code[1] for EXC_BAD_ACCESS
97 // exceptions, but not for other types of exceptions.
98 bool code_1_is_exception_address = exception_ == EXC_BAD_ACCESS;
99
100 #if defined(ARCH_CPU_X86_FAMILY)
101 if (process_reader->Is64Bit()) {
102 context_.architecture = kCPUArchitectureX86_64;
103 context_.x86_64 = &context_union_.x86_64;
104 InitializeCPUContextX86_64(context_.x86_64,
105 flavor,
106 state,
107 state_count,
108 &thread->thread_context.t64,
109 &thread->float_context.f64,
110 &thread->debug_context.d64);
111 } else {
112 context_.architecture = kCPUArchitectureX86;
113 context_.x86 = &context_union_.x86;
114 InitializeCPUContextX86(context_.x86,
115 flavor,
116 state,
117 state_count,
118 &thread->thread_context.t32,
119 &thread->float_context.f32,
120 &thread->debug_context.d32);
121 }
122
123 // For x86 and x86_64 EXC_BAD_ACCESS exceptions, some code[0] values indicate
124 // that code[1] does not (or may not) carry the exception address:
125 // EXC_I386_GPFLT (10.9.5 xnu-2422.115.4/osfmk/i386/trap.c user_trap() for
126 // T_GENERAL_PROTECTION) and the oddball (VM_PROT_READ | VM_PROT_EXECUTE)
127 // which collides with EXC_I386_BOUNDFLT (10.9.5
128 // xnu-2422.115.4/osfmk/i386/fpu.c fpextovrflt()). Other EXC_BAD_ACCESS
129 // exceptions come through 10.9.5 xnu-2422.115.4/osfmk/i386/trap.c
130 // user_page_fault_continue() and do contain the exception address in code[1].
131 if (exception_ == EXC_BAD_ACCESS &&
132 (exception_code_0_ == EXC_I386_GPFLT ||
133 exception_code_0_ == (VM_PROT_READ | VM_PROT_EXECUTE))) {
134 code_1_is_exception_address = false;
135 }
136 #endif
137
138 if (code_1_is_exception_address) {
139 exception_address_ = code[1];
140 } else {
141 exception_address_ = context_.InstructionPointer();
142 }
143
144 INITIALIZATION_STATE_SET_VALID(initialized_);
145 return true;
146 }
147
148 const CPUContext* ExceptionSnapshotMac::Context() const {
149 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
150 return &context_;
151 }
152
153 uint64_t ExceptionSnapshotMac::ThreadID() const {
154 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
155 return thread_id_;
156 }
157
158 uint32_t ExceptionSnapshotMac::Exception() const {
159 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
160 return exception_;
161 }
162
163 uint32_t ExceptionSnapshotMac::ExceptionInfo() const {
164 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
165 return exception_code_0_;
166 }
167
168 uint64_t ExceptionSnapshotMac::ExceptionAddress() const {
169 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
170 return exception_address_;
171 }
172
173 const std::vector<uint64_t>& ExceptionSnapshotMac::Codes() const {
174 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
175 return codes_;
176 }
177
178 } // namespace internal
179 } // 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