blob: 8915dd789bbf440be8a09abe9478c3a7adf2e95f [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
Johnny Chenecd4feb2011-10-14 00:42:25 +000016#include "lldb/Breakpoint/Watchpoint.h"
Greg Clayton643ee732010-08-04 01:40:35 +000017#include "lldb/Core/ArchSpec.h"
18#include "lldb/Core/StreamString.h"
19#include "lldb/Target/Process.h"
20#include "lldb/Target/RegisterContext.h"
21#include "lldb/Target/Target.h"
22#include "lldb/Target/Thread.h"
23#include "lldb/Target/ThreadPlan.h"
24#include "lldb/Target/UnixSignals.h"
25
26using namespace lldb;
27using namespace lldb_private;
28
29const char *
30StopInfoMachException::GetDescription ()
31{
32 if (m_description.empty() && m_value != 0)
33 {
Greg Clayton940b1032011-02-23 00:35:02 +000034 const llvm::Triple::ArchType cpu = m_thread.GetProcess().GetTarget().GetArchitecture().GetMachine();
Greg Clayton643ee732010-08-04 01:40:35 +000035
36 const char *exc_desc = NULL;
37 const char *code_label = "code";
38 const char *code_desc = NULL;
39 const char *subcode_label = "subcode";
40 const char *subcode_desc = NULL;
41 switch (m_value)
42 {
43 case 1: // EXC_BAD_ACCESS
44 exc_desc = "EXC_BAD_ACCESS";
45 subcode_label = "address";
46 switch (cpu)
47 {
Greg Clayton940b1032011-02-23 00:35:02 +000048 case llvm::Triple::arm:
Greg Clayton643ee732010-08-04 01:40:35 +000049 switch (m_exc_code)
50 {
51 case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
52 case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
53 }
54 break;
55
Greg Clayton940b1032011-02-23 00:35:02 +000056 case llvm::Triple::ppc:
57 case llvm::Triple::ppc64:
Greg Clayton643ee732010-08-04 01:40:35 +000058 switch (m_exc_code)
59 {
60 case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break;
61 case 0x102: code_desc = "EXC_PPC_BADSPACE"; break;
62 case 0x103: code_desc = "EXC_PPC_UNALIGNED"; break;
63 }
64 break;
65
66 default:
67 break;
68 }
69 break;
70
71 case 2: // EXC_BAD_INSTRUCTION
72 exc_desc = "EXC_BAD_INSTRUCTION";
73 switch (cpu)
74 {
Greg Clayton940b1032011-02-23 00:35:02 +000075 case llvm::Triple::x86:
76 case llvm::Triple::x86_64:
Greg Clayton643ee732010-08-04 01:40:35 +000077 if (m_exc_code == 1)
78 code_desc = "EXC_I386_INVOP";
79 break;
80
Greg Clayton940b1032011-02-23 00:35:02 +000081 case llvm::Triple::ppc:
82 case llvm::Triple::ppc64:
Greg Clayton643ee732010-08-04 01:40:35 +000083 switch (m_exc_code)
84 {
85 case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break;
86 case 2: code_desc = "EXC_PPC_UNIPL_INST"; break;
87 case 3: code_desc = "EXC_PPC_PRIVINST"; break;
88 case 4: code_desc = "EXC_PPC_PRIVREG"; break;
89 case 5: code_desc = "EXC_PPC_TRACE"; break;
90 case 6: code_desc = "EXC_PPC_PERFMON"; break;
91 }
92 break;
93
Greg Clayton940b1032011-02-23 00:35:02 +000094 case llvm::Triple::arm:
Greg Clayton643ee732010-08-04 01:40:35 +000095 if (m_exc_code == 1)
96 code_desc = "EXC_ARM_UNDEFINED";
97 break;
98
99 default:
100 break;
101 }
102 break;
103
104 case 3: // EXC_ARITHMETIC
105 exc_desc = "EXC_ARITHMETIC";
106 switch (cpu)
107 {
Greg Clayton940b1032011-02-23 00:35:02 +0000108 case llvm::Triple::x86:
109 case llvm::Triple::x86_64:
Greg Clayton643ee732010-08-04 01:40:35 +0000110 switch (m_exc_code)
111 {
112 case 1: code_desc = "EXC_I386_DIV"; break;
113 case 2: code_desc = "EXC_I386_INTO"; break;
114 case 3: code_desc = "EXC_I386_NOEXT"; break;
115 case 4: code_desc = "EXC_I386_EXTOVR"; break;
116 case 5: code_desc = "EXC_I386_EXTERR"; break;
117 case 6: code_desc = "EXC_I386_EMERR"; break;
118 case 7: code_desc = "EXC_I386_BOUND"; break;
119 case 8: code_desc = "EXC_I386_SSEEXTERR"; break;
120 }
121 break;
122
Greg Clayton940b1032011-02-23 00:35:02 +0000123 case llvm::Triple::ppc:
124 case llvm::Triple::ppc64:
Greg Clayton643ee732010-08-04 01:40:35 +0000125 switch (m_exc_code)
126 {
127 case 1: code_desc = "EXC_PPC_OVERFLOW"; break;
128 case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break;
129 case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break;
130 case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break;
131 case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break;
132 case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break;
133 case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break;
134 }
135 break;
136
137 default:
138 break;
139 }
140 break;
141
142 case 4: // EXC_EMULATION
143 exc_desc = "EXC_EMULATION";
144 break;
145
146
147 case 5: // EXC_SOFTWARE
148 exc_desc = "EXC_SOFTWARE";
149 if (m_exc_code == 0x10003)
150 {
151 subcode_desc = "EXC_SOFT_SIGNAL";
152 subcode_label = "signo";
153 }
154 break;
155
156 case 6: // EXC_BREAKPOINT
157 {
158 exc_desc = "EXC_BREAKPOINT";
159 switch (cpu)
160 {
Greg Clayton940b1032011-02-23 00:35:02 +0000161 case llvm::Triple::x86:
162 case llvm::Triple::x86_64:
Greg Clayton643ee732010-08-04 01:40:35 +0000163 switch (m_exc_code)
164 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000165 case 1: code_desc = "EXC_I386_SGL"; break;
166 case 2: code_desc = "EXC_I386_BPT"; break;
Greg Clayton643ee732010-08-04 01:40:35 +0000167 }
168 break;
169
Greg Clayton940b1032011-02-23 00:35:02 +0000170 case llvm::Triple::ppc:
171 case llvm::Triple::ppc64:
Greg Clayton643ee732010-08-04 01:40:35 +0000172 switch (m_exc_code)
173 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000174 case 1: code_desc = "EXC_PPC_BREAKPOINT"; break;
Greg Clayton643ee732010-08-04 01:40:35 +0000175 }
176 break;
177
Greg Clayton940b1032011-02-23 00:35:02 +0000178 case llvm::Triple::arm:
Greg Clayton643ee732010-08-04 01:40:35 +0000179 switch (m_exc_code)
180 {
Greg Clayton04d397c2011-05-23 18:04:09 +0000181 case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
182 case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000183 case 1: code_desc = "EXC_ARM_BREAKPOINT"; break;
Greg Clayton643ee732010-08-04 01:40:35 +0000184 }
185 break;
186
187 default:
188 break;
189 }
190 }
191 break;
192
193 case 7:
194 exc_desc = "EXC_SYSCALL";
195 break;
196
197 case 8:
198 exc_desc = "EXC_MACH_SYSCALL";
199 break;
200
201 case 9:
202 exc_desc = "EXC_RPC_ALERT";
203 break;
204
205 case 10:
206 exc_desc = "EXC_CRASH";
207 break;
208 }
209
210 StreamString strm;
211
212 if (exc_desc)
213 strm.PutCString(exc_desc);
214 else
215 strm.Printf("EXC_??? (%llu)", m_value);
216
217 if (m_exc_data_count >= 1)
218 {
219 if (code_desc)
220 strm.Printf(" (%s=%s", code_label, code_desc);
221 else
222 strm.Printf(" (%s=%llu", code_label, m_exc_code);
223 }
224
225 if (m_exc_data_count >= 2)
226 {
227 if (subcode_desc)
228 strm.Printf(", %s=%s", subcode_label, subcode_desc);
229 else
230 strm.Printf(", %s=0x%llx", subcode_label, m_exc_subcode);
231 }
232
233 if (m_exc_data_count > 0)
234 strm.PutChar(')');
235
236 m_description.swap (strm.GetString());
237 }
238 return m_description.c_str();
239}
240
241
242StopInfoSP
243StopInfoMachException::CreateStopReasonWithMachException
244(
245 Thread &thread,
246 uint32_t exc_type,
247 uint32_t exc_data_count,
248 uint64_t exc_code,
Johnny Chen36889ad2011-09-17 01:05:03 +0000249 uint64_t exc_sub_code,
250 uint64_t exc_sub_sub_code
Greg Clayton643ee732010-08-04 01:40:35 +0000251)
252{
253 if (exc_type != 0)
254 {
Greg Clayton940b1032011-02-23 00:35:02 +0000255 const llvm::Triple::ArchType cpu = thread.GetProcess().GetTarget().GetArchitecture().GetMachine();
Greg Clayton643ee732010-08-04 01:40:35 +0000256
257 switch (exc_type)
258 {
259 case 1: // EXC_BAD_ACCESS
260 break;
261
262 case 2: // EXC_BAD_INSTRUCTION
263 switch (cpu)
264 {
Greg Clayton940b1032011-02-23 00:35:02 +0000265 case llvm::Triple::ppc:
266 case llvm::Triple::ppc64:
Greg Clayton643ee732010-08-04 01:40:35 +0000267 switch (exc_code)
268 {
269 case 1: // EXC_PPC_INVALID_SYSCALL
270 case 2: // EXC_PPC_UNIPL_INST
271 case 3: // EXC_PPC_PRIVINST
272 case 4: // EXC_PPC_PRIVREG
273 break;
274 case 5: // EXC_PPC_TRACE
275 return StopInfo::CreateStopReasonToTrace (thread);
276 case 6: // EXC_PPC_PERFMON
277 break;
278 }
279 break;
280
281 default:
282 break;
283 }
284 break;
285
286 case 3: // EXC_ARITHMETIC
287 case 4: // EXC_EMULATION
288 break;
289
290 case 5: // EXC_SOFTWARE
291 if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
292 return StopInfo::CreateStopReasonWithSignal (thread, exc_sub_code);
293 break;
294
295 case 6: // EXC_BREAKPOINT
296 {
297 bool is_software_breakpoint = false;
298 switch (cpu)
299 {
Greg Clayton940b1032011-02-23 00:35:02 +0000300 case llvm::Triple::x86:
301 case llvm::Triple::x86_64:
Greg Clayton643ee732010-08-04 01:40:35 +0000302 if (exc_code == 1) // EXC_I386_SGL
303 {
Johnny Chen30e8d972011-09-08 20:52:34 +0000304 if (!exc_sub_code)
305 return StopInfo::CreateStopReasonToTrace(thread);
306
307 // It's a watchpoint, then.
Johnny Chen36889ad2011-09-17 01:05:03 +0000308 // The exc_sub_code indicates the data break address.
Johnny Chenecd4feb2011-10-14 00:42:25 +0000309 lldb::WatchpointSP wp_sp =
310 thread.GetProcess().GetTarget().GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code);
311 if (wp_sp)
Johnny Chen36889ad2011-09-17 01:05:03 +0000312 {
313 // Debugserver may piggyback the hardware index of the fired watchpoint in the exception data.
314 // Set the hardware index if that's the case.
315 if (exc_data_count >=3)
Johnny Chenecd4feb2011-10-14 00:42:25 +0000316 wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
317 return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
Johnny Chen36889ad2011-09-17 01:05:03 +0000318 }
Greg Clayton643ee732010-08-04 01:40:35 +0000319 }
320 else if (exc_code == 2) // EXC_I386_BPT
321 {
322 is_software_breakpoint = true;
323 }
324 break;
325
Greg Clayton940b1032011-02-23 00:35:02 +0000326 case llvm::Triple::ppc:
327 case llvm::Triple::ppc64:
Greg Clayton643ee732010-08-04 01:40:35 +0000328 is_software_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT
329 break;
330
Greg Clayton940b1032011-02-23 00:35:02 +0000331 case llvm::Triple::arm:
Greg Clayton04d397c2011-05-23 18:04:09 +0000332 if (exc_code == 0x102)
333 {
334 // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS
335 return StopInfo::CreateStopReasonToTrace(thread);
336 }
337 else
338 is_software_breakpoint = exc_code == 1; // EXC_ARM_BREAKPOINT
Greg Clayton643ee732010-08-04 01:40:35 +0000339 break;
340
341 default:
342 break;
343 }
344
345 if (is_software_breakpoint)
346 {
347 addr_t pc = thread.GetRegisterContext()->GetPC();
348 lldb::BreakpointSiteSP bp_site_sp = thread.GetProcess().GetBreakpointSiteList().FindByAddress(pc);
349 if (bp_site_sp)
350 {
Jim Ingham11e95852010-10-22 23:28:32 +0000351 // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
352 // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
353 // 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 +0000354 if (bp_site_sp->ValidForThisThread (&thread))
355 return StopInfo::CreateStopReasonWithBreakpointSiteID (thread, bp_site_sp->GetID());
Jim Ingham11e95852010-10-22 23:28:32 +0000356 else
357 return StopInfoSP();
Greg Clayton643ee732010-08-04 01:40:35 +0000358 }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000359 else if (cpu == llvm::Triple::arm)
360 {
361 return StopInfo::CreateStopReasonToTrace (thread);
362 }
Greg Clayton643ee732010-08-04 01:40:35 +0000363 }
364 }
365 break;
366
367 case 7: // EXC_SYSCALL
368 case 8: // EXC_MACH_SYSCALL
369 case 9: // EXC_RPC_ALERT
370 case 10: // EXC_CRASH
371 break;
372 }
373
374 return StopInfoSP(new StopInfoMachException (thread, exc_type, exc_data_count, exc_code, exc_sub_code));
375 }
376 return StopInfoSP();
377}