blob: b62c0c340b2e7ef13b1252a24b85c1c5796f5cb6 [file] [log] [blame]
Greg Clayton643ee732010-08-04 01:40:35 +00001//===-- StopInfoMachException.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "StopInfoMachException.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/ArchSpec.h"
17#include "lldb/Core/StreamString.h"
18#include "lldb/Target/Process.h"
19#include "lldb/Target/RegisterContext.h"
20#include "lldb/Target/Target.h"
21#include "lldb/Target/Thread.h"
22#include "lldb/Target/ThreadPlan.h"
23#include "lldb/Target/UnixSignals.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28const char *
29StopInfoMachException::GetDescription ()
30{
31 if (m_description.empty() && m_value != 0)
32 {
Greg Clayton940b1032011-02-23 00:35:02 +000033 const llvm::Triple::ArchType cpu = m_thread.GetProcess().GetTarget().GetArchitecture().GetMachine();
Greg Clayton643ee732010-08-04 01:40:35 +000034
35 const char *exc_desc = NULL;
36 const char *code_label = "code";
37 const char *code_desc = NULL;
38 const char *subcode_label = "subcode";
39 const char *subcode_desc = NULL;
40 switch (m_value)
41 {
42 case 1: // EXC_BAD_ACCESS
43 exc_desc = "EXC_BAD_ACCESS";
44 subcode_label = "address";
45 switch (cpu)
46 {
Greg Clayton940b1032011-02-23 00:35:02 +000047 case llvm::Triple::arm:
Greg Clayton643ee732010-08-04 01:40:35 +000048 switch (m_exc_code)
49 {
50 case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
51 case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
52 }
53 break;
54
Greg Clayton940b1032011-02-23 00:35:02 +000055 case llvm::Triple::ppc:
56 case llvm::Triple::ppc64:
Greg Clayton643ee732010-08-04 01:40:35 +000057 switch (m_exc_code)
58 {
59 case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break;
60 case 0x102: code_desc = "EXC_PPC_BADSPACE"; break;
61 case 0x103: code_desc = "EXC_PPC_UNALIGNED"; break;
62 }
63 break;
64
65 default:
66 break;
67 }
68 break;
69
70 case 2: // EXC_BAD_INSTRUCTION
71 exc_desc = "EXC_BAD_INSTRUCTION";
72 switch (cpu)
73 {
Greg Clayton940b1032011-02-23 00:35:02 +000074 case llvm::Triple::x86:
75 case llvm::Triple::x86_64:
Greg Clayton643ee732010-08-04 01:40:35 +000076 if (m_exc_code == 1)
77 code_desc = "EXC_I386_INVOP";
78 break;
79
Greg Clayton940b1032011-02-23 00:35:02 +000080 case llvm::Triple::ppc:
81 case llvm::Triple::ppc64:
Greg Clayton643ee732010-08-04 01:40:35 +000082 switch (m_exc_code)
83 {
84 case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break;
85 case 2: code_desc = "EXC_PPC_UNIPL_INST"; break;
86 case 3: code_desc = "EXC_PPC_PRIVINST"; break;
87 case 4: code_desc = "EXC_PPC_PRIVREG"; break;
88 case 5: code_desc = "EXC_PPC_TRACE"; break;
89 case 6: code_desc = "EXC_PPC_PERFMON"; break;
90 }
91 break;
92
Greg Clayton940b1032011-02-23 00:35:02 +000093 case llvm::Triple::arm:
Greg Clayton643ee732010-08-04 01:40:35 +000094 if (m_exc_code == 1)
95 code_desc = "EXC_ARM_UNDEFINED";
96 break;
97
98 default:
99 break;
100 }
101 break;
102
103 case 3: // EXC_ARITHMETIC
104 exc_desc = "EXC_ARITHMETIC";
105 switch (cpu)
106 {
Greg Clayton940b1032011-02-23 00:35:02 +0000107 case llvm::Triple::x86:
108 case llvm::Triple::x86_64:
Greg Clayton643ee732010-08-04 01:40:35 +0000109 switch (m_exc_code)
110 {
111 case 1: code_desc = "EXC_I386_DIV"; break;
112 case 2: code_desc = "EXC_I386_INTO"; break;
113 case 3: code_desc = "EXC_I386_NOEXT"; break;
114 case 4: code_desc = "EXC_I386_EXTOVR"; break;
115 case 5: code_desc = "EXC_I386_EXTERR"; break;
116 case 6: code_desc = "EXC_I386_EMERR"; break;
117 case 7: code_desc = "EXC_I386_BOUND"; break;
118 case 8: code_desc = "EXC_I386_SSEEXTERR"; break;
119 }
120 break;
121
Greg Clayton940b1032011-02-23 00:35:02 +0000122 case llvm::Triple::ppc:
123 case llvm::Triple::ppc64:
Greg Clayton643ee732010-08-04 01:40:35 +0000124 switch (m_exc_code)
125 {
126 case 1: code_desc = "EXC_PPC_OVERFLOW"; break;
127 case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break;
128 case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break;
129 case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break;
130 case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break;
131 case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break;
132 case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break;
133 }
134 break;
135
136 default:
137 break;
138 }
139 break;
140
141 case 4: // EXC_EMULATION
142 exc_desc = "EXC_EMULATION";
143 break;
144
145
146 case 5: // EXC_SOFTWARE
147 exc_desc = "EXC_SOFTWARE";
148 if (m_exc_code == 0x10003)
149 {
150 subcode_desc = "EXC_SOFT_SIGNAL";
151 subcode_label = "signo";
152 }
153 break;
154
155 case 6: // EXC_BREAKPOINT
156 {
157 exc_desc = "EXC_BREAKPOINT";
158 switch (cpu)
159 {
Greg Clayton940b1032011-02-23 00:35:02 +0000160 case llvm::Triple::x86:
161 case llvm::Triple::x86_64:
Greg Clayton643ee732010-08-04 01:40:35 +0000162 switch (m_exc_code)
163 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000164 case 1: code_desc = "EXC_I386_SGL"; break;
165 case 2: code_desc = "EXC_I386_BPT"; break;
Greg Clayton643ee732010-08-04 01:40:35 +0000166 }
167 break;
168
Greg Clayton940b1032011-02-23 00:35:02 +0000169 case llvm::Triple::ppc:
170 case llvm::Triple::ppc64:
Greg Clayton643ee732010-08-04 01:40:35 +0000171 switch (m_exc_code)
172 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000173 case 1: code_desc = "EXC_PPC_BREAKPOINT"; break;
Greg Clayton643ee732010-08-04 01:40:35 +0000174 }
175 break;
176
Greg Clayton940b1032011-02-23 00:35:02 +0000177 case llvm::Triple::arm:
Greg Clayton643ee732010-08-04 01:40:35 +0000178 switch (m_exc_code)
179 {
Greg Clayton04d397c2011-05-23 18:04:09 +0000180 case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
181 case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000182 case 1: code_desc = "EXC_ARM_BREAKPOINT"; break;
Greg Clayton643ee732010-08-04 01:40:35 +0000183 }
184 break;
185
186 default:
187 break;
188 }
189 }
190 break;
191
192 case 7:
193 exc_desc = "EXC_SYSCALL";
194 break;
195
196 case 8:
197 exc_desc = "EXC_MACH_SYSCALL";
198 break;
199
200 case 9:
201 exc_desc = "EXC_RPC_ALERT";
202 break;
203
204 case 10:
205 exc_desc = "EXC_CRASH";
206 break;
207 }
208
209 StreamString strm;
210
211 if (exc_desc)
212 strm.PutCString(exc_desc);
213 else
214 strm.Printf("EXC_??? (%llu)", m_value);
215
216 if (m_exc_data_count >= 1)
217 {
218 if (code_desc)
219 strm.Printf(" (%s=%s", code_label, code_desc);
220 else
221 strm.Printf(" (%s=%llu", code_label, m_exc_code);
222 }
223
224 if (m_exc_data_count >= 2)
225 {
226 if (subcode_desc)
227 strm.Printf(", %s=%s", subcode_label, subcode_desc);
228 else
229 strm.Printf(", %s=0x%llx", subcode_label, m_exc_subcode);
230 }
231
232 if (m_exc_data_count > 0)
233 strm.PutChar(')');
234
235 m_description.swap (strm.GetString());
236 }
237 return m_description.c_str();
238}
239
240
241StopInfoSP
242StopInfoMachException::CreateStopReasonWithMachException
243(
244 Thread &thread,
245 uint32_t exc_type,
246 uint32_t exc_data_count,
247 uint64_t exc_code,
Johnny Chen36889ad2011-09-17 01:05:03 +0000248 uint64_t exc_sub_code,
249 uint64_t exc_sub_sub_code
Greg Clayton643ee732010-08-04 01:40:35 +0000250)
251{
252 if (exc_type != 0)
253 {
Greg Clayton940b1032011-02-23 00:35:02 +0000254 const llvm::Triple::ArchType cpu = thread.GetProcess().GetTarget().GetArchitecture().GetMachine();
Greg Clayton643ee732010-08-04 01:40:35 +0000255
256 switch (exc_type)
257 {
258 case 1: // EXC_BAD_ACCESS
259 break;
260
261 case 2: // EXC_BAD_INSTRUCTION
262 switch (cpu)
263 {
Greg Clayton940b1032011-02-23 00:35:02 +0000264 case llvm::Triple::ppc:
265 case llvm::Triple::ppc64:
Greg Clayton643ee732010-08-04 01:40:35 +0000266 switch (exc_code)
267 {
268 case 1: // EXC_PPC_INVALID_SYSCALL
269 case 2: // EXC_PPC_UNIPL_INST
270 case 3: // EXC_PPC_PRIVINST
271 case 4: // EXC_PPC_PRIVREG
272 break;
273 case 5: // EXC_PPC_TRACE
274 return StopInfo::CreateStopReasonToTrace (thread);
275 case 6: // EXC_PPC_PERFMON
276 break;
277 }
278 break;
279
280 default:
281 break;
282 }
283 break;
284
285 case 3: // EXC_ARITHMETIC
286 case 4: // EXC_EMULATION
287 break;
288
289 case 5: // EXC_SOFTWARE
290 if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
291 return StopInfo::CreateStopReasonWithSignal (thread, exc_sub_code);
292 break;
293
294 case 6: // EXC_BREAKPOINT
295 {
296 bool is_software_breakpoint = false;
297 switch (cpu)
298 {
Greg Clayton940b1032011-02-23 00:35:02 +0000299 case llvm::Triple::x86:
300 case llvm::Triple::x86_64:
Greg Clayton643ee732010-08-04 01:40:35 +0000301 if (exc_code == 1) // EXC_I386_SGL
302 {
Johnny Chen30e8d972011-09-08 20:52:34 +0000303 if (!exc_sub_code)
304 return StopInfo::CreateStopReasonToTrace(thread);
305
306 // It's a watchpoint, then.
Johnny Chen36889ad2011-09-17 01:05:03 +0000307 // The exc_sub_code indicates the data break address.
Johnny Chen30e8d972011-09-08 20:52:34 +0000308 lldb::WatchpointLocationSP wp_loc_sp =
309 thread.GetProcess().GetTarget().GetWatchpointLocationList().FindByAddress((lldb::addr_t)exc_sub_code);
310 if (wp_loc_sp)
Johnny Chen36889ad2011-09-17 01:05:03 +0000311 {
312 // Debugserver may piggyback the hardware index of the fired watchpoint in the exception data.
313 // Set the hardware index if that's the case.
314 if (exc_data_count >=3)
315 wp_loc_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
Johnny Chen30e8d972011-09-08 20:52:34 +0000316 return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_loc_sp->GetID());
Johnny Chen36889ad2011-09-17 01:05:03 +0000317 }
Greg Clayton643ee732010-08-04 01:40:35 +0000318 }
319 else if (exc_code == 2) // EXC_I386_BPT
320 {
321 is_software_breakpoint = true;
322 }
323 break;
324
Greg Clayton940b1032011-02-23 00:35:02 +0000325 case llvm::Triple::ppc:
326 case llvm::Triple::ppc64:
Greg Clayton643ee732010-08-04 01:40:35 +0000327 is_software_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT
328 break;
329
Greg Clayton940b1032011-02-23 00:35:02 +0000330 case llvm::Triple::arm:
Greg Clayton04d397c2011-05-23 18:04:09 +0000331 if (exc_code == 0x102)
332 {
333 // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS
334 return StopInfo::CreateStopReasonToTrace(thread);
335 }
336 else
337 is_software_breakpoint = exc_code == 1; // EXC_ARM_BREAKPOINT
Greg Clayton643ee732010-08-04 01:40:35 +0000338 break;
339
340 default:
341 break;
342 }
343
344 if (is_software_breakpoint)
345 {
346 addr_t pc = thread.GetRegisterContext()->GetPC();
347 lldb::BreakpointSiteSP bp_site_sp = thread.GetProcess().GetBreakpointSiteList().FindByAddress(pc);
348 if (bp_site_sp)
349 {
Jim Ingham11e95852010-10-22 23:28:32 +0000350 // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
351 // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
352 // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
Greg Clayton643ee732010-08-04 01:40:35 +0000353 if (bp_site_sp->ValidForThisThread (&thread))
354 return StopInfo::CreateStopReasonWithBreakpointSiteID (thread, bp_site_sp->GetID());
Jim Ingham11e95852010-10-22 23:28:32 +0000355 else
356 return StopInfoSP();
Greg Clayton643ee732010-08-04 01:40:35 +0000357 }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000358 else if (cpu == llvm::Triple::arm)
359 {
360 return StopInfo::CreateStopReasonToTrace (thread);
361 }
Greg Clayton643ee732010-08-04 01:40:35 +0000362 }
363 }
364 break;
365
366 case 7: // EXC_SYSCALL
367 case 8: // EXC_MACH_SYSCALL
368 case 9: // EXC_RPC_ALERT
369 case 10: // EXC_CRASH
370 break;
371 }
372
373 return StopInfoSP(new StopInfoMachException (thread, exc_type, exc_data_count, exc_code, exc_sub_code));
374 }
375 return StopInfoSP();
376}