Bug Summary

File:tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
Warning:line 491, column 11
Value stored to 'is_actual_breakpoint' is never read

Annotated Source Code

1//===-- 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/Breakpoint/Watchpoint.h"
17#include "lldb/Core/ArchSpec.h"
18#include "lldb/Symbol/Symbol.h"
19#include "lldb/Target/DynamicLoader.h"
20#include "lldb/Target/ExecutionContext.h"
21#include "lldb/Target/Process.h"
22#include "lldb/Target/RegisterContext.h"
23#include "lldb/Target/Target.h"
24#include "lldb/Target/Thread.h"
25#include "lldb/Target/ThreadPlan.h"
26#include "lldb/Target/UnixSignals.h"
27#include "lldb/Utility/StreamString.h"
28
29using namespace lldb;
30using namespace lldb_private;
31
32const char *StopInfoMachException::GetDescription() {
33 if (m_description.empty() && m_value != 0) {
34 ExecutionContext exe_ctx(m_thread_wp.lock());
35 Target *target = exe_ctx.GetTargetPtr();
36 const llvm::Triple::ArchType cpu =
37 target ? target->GetArchitecture().GetMachine()
38 : llvm::Triple::UnknownArch;
39
40 const char *exc_desc = NULL__null;
41 const char *code_label = "code";
42 const char *code_desc = NULL__null;
43 const char *subcode_label = "subcode";
44 const char *subcode_desc = NULL__null;
45 switch (m_value) {
46 case 1: // EXC_BAD_ACCESS
47 exc_desc = "EXC_BAD_ACCESS";
48 subcode_label = "address";
49 switch (cpu) {
50 case llvm::Triple::x86:
51 case llvm::Triple::x86_64:
52 switch (m_exc_code) {
53 case 0xd:
54 code_desc = "EXC_I386_GPFLT";
55 m_exc_data_count = 1;
56 break;
57 }
58 break;
59 case llvm::Triple::arm:
60 case llvm::Triple::thumb:
61 switch (m_exc_code) {
62 case 0x101:
63 code_desc = "EXC_ARM_DA_ALIGN";
64 break;
65 case 0x102:
66 code_desc = "EXC_ARM_DA_DEBUG";
67 break;
68 }
69 break;
70
71 case llvm::Triple::ppc:
72 case llvm::Triple::ppc64:
73 switch (m_exc_code) {
74 case 0x101:
75 code_desc = "EXC_PPC_VM_PROT_READ";
76 break;
77 case 0x102:
78 code_desc = "EXC_PPC_BADSPACE";
79 break;
80 case 0x103:
81 code_desc = "EXC_PPC_UNALIGNED";
82 break;
83 }
84 break;
85
86 default:
87 break;
88 }
89 break;
90
91 case 2: // EXC_BAD_INSTRUCTION
92 exc_desc = "EXC_BAD_INSTRUCTION";
93 switch (cpu) {
94 case llvm::Triple::x86:
95 case llvm::Triple::x86_64:
96 if (m_exc_code == 1)
97 code_desc = "EXC_I386_INVOP";
98 break;
99
100 case llvm::Triple::ppc:
101 case llvm::Triple::ppc64:
102 switch (m_exc_code) {
103 case 1:
104 code_desc = "EXC_PPC_INVALID_SYSCALL";
105 break;
106 case 2:
107 code_desc = "EXC_PPC_UNIPL_INST";
108 break;
109 case 3:
110 code_desc = "EXC_PPC_PRIVINST";
111 break;
112 case 4:
113 code_desc = "EXC_PPC_PRIVREG";
114 break;
115 case 5:
116 code_desc = "EXC_PPC_TRACE";
117 break;
118 case 6:
119 code_desc = "EXC_PPC_PERFMON";
120 break;
121 }
122 break;
123
124 case llvm::Triple::arm:
125 case llvm::Triple::thumb:
126 if (m_exc_code == 1)
127 code_desc = "EXC_ARM_UNDEFINED";
128 break;
129
130 default:
131 break;
132 }
133 break;
134
135 case 3: // EXC_ARITHMETIC
136 exc_desc = "EXC_ARITHMETIC";
137 switch (cpu) {
138 case llvm::Triple::x86:
139 case llvm::Triple::x86_64:
140 switch (m_exc_code) {
141 case 1:
142 code_desc = "EXC_I386_DIV";
143 break;
144 case 2:
145 code_desc = "EXC_I386_INTO";
146 break;
147 case 3:
148 code_desc = "EXC_I386_NOEXT";
149 break;
150 case 4:
151 code_desc = "EXC_I386_EXTOVR";
152 break;
153 case 5:
154 code_desc = "EXC_I386_EXTERR";
155 break;
156 case 6:
157 code_desc = "EXC_I386_EMERR";
158 break;
159 case 7:
160 code_desc = "EXC_I386_BOUND";
161 break;
162 case 8:
163 code_desc = "EXC_I386_SSEEXTERR";
164 break;
165 }
166 break;
167
168 case llvm::Triple::ppc:
169 case llvm::Triple::ppc64:
170 switch (m_exc_code) {
171 case 1:
172 code_desc = "EXC_PPC_OVERFLOW";
173 break;
174 case 2:
175 code_desc = "EXC_PPC_ZERO_DIVIDE";
176 break;
177 case 3:
178 code_desc = "EXC_PPC_FLT_INEXACT";
179 break;
180 case 4:
181 code_desc = "EXC_PPC_FLT_ZERO_DIVIDE";
182 break;
183 case 5:
184 code_desc = "EXC_PPC_FLT_UNDERFLOW";
185 break;
186 case 6:
187 code_desc = "EXC_PPC_FLT_OVERFLOW";
188 break;
189 case 7:
190 code_desc = "EXC_PPC_FLT_NOT_A_NUMBER";
191 break;
192 }
193 break;
194
195 default:
196 break;
197 }
198 break;
199
200 case 4: // EXC_EMULATION
201 exc_desc = "EXC_EMULATION";
202 break;
203
204 case 5: // EXC_SOFTWARE
205 exc_desc = "EXC_SOFTWARE";
206 if (m_exc_code == 0x10003) {
207 subcode_desc = "EXC_SOFT_SIGNAL";
208 subcode_label = "signo";
209 }
210 break;
211
212 case 6: // EXC_BREAKPOINT
213 {
214 exc_desc = "EXC_BREAKPOINT";
215 switch (cpu) {
216 case llvm::Triple::x86:
217 case llvm::Triple::x86_64:
218 switch (m_exc_code) {
219 case 1:
220 code_desc = "EXC_I386_SGL";
221 break;
222 case 2:
223 code_desc = "EXC_I386_BPT";
224 break;
225 }
226 break;
227
228 case llvm::Triple::ppc:
229 case llvm::Triple::ppc64:
230 switch (m_exc_code) {
231 case 1:
232 code_desc = "EXC_PPC_BREAKPOINT";
233 break;
234 }
235 break;
236
237 case llvm::Triple::arm:
238 case llvm::Triple::thumb:
239 switch (m_exc_code) {
240 case 0x101:
241 code_desc = "EXC_ARM_DA_ALIGN";
242 break;
243 case 0x102:
244 code_desc = "EXC_ARM_DA_DEBUG";
245 break;
246 case 1:
247 code_desc = "EXC_ARM_BREAKPOINT";
248 break;
249 // FIXME temporary workaround, exc_code 0 does not really mean
250 // EXC_ARM_BREAKPOINT
251 case 0:
252 code_desc = "EXC_ARM_BREAKPOINT";
253 break;
254 }
255 break;
256
257 default:
258 break;
259 }
260 } break;
261
262 case 7:
263 exc_desc = "EXC_SYSCALL";
264 break;
265
266 case 8:
267 exc_desc = "EXC_MACH_SYSCALL";
268 break;
269
270 case 9:
271 exc_desc = "EXC_RPC_ALERT";
272 break;
273
274 case 10:
275 exc_desc = "EXC_CRASH";
276 break;
277 case 11:
278 exc_desc = "EXC_RESOURCE";
279 break;
280 case 12:
281 exc_desc = "EXC_GUARD";
282 break;
283 }
284
285 StreamString strm;
286
287 if (exc_desc)
288 strm.PutCString(exc_desc);
289 else
290 strm.Printf("EXC_??? (%" PRIu64"l" "u" ")", m_value);
291
292 if (m_exc_data_count >= 1) {
293 if (code_desc)
294 strm.Printf(" (%s=%s", code_label, code_desc);
295 else
296 strm.Printf(" (%s=%" PRIu64"l" "u", code_label, m_exc_code);
297 }
298
299 if (m_exc_data_count >= 2) {
300 if (subcode_desc)
301 strm.Printf(", %s=%s", subcode_label, subcode_desc);
302 else
303 strm.Printf(", %s=0x%" PRIx64"l" "x", subcode_label, m_exc_subcode);
304 }
305
306 if (m_exc_data_count > 0)
307 strm.PutChar(')');
308
309 m_description = strm.GetString();
310 }
311 return m_description.c_str();
312}
313
314StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
315 Thread &thread, uint32_t exc_type, uint32_t exc_data_count,
316 uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code,
317 bool pc_already_adjusted, bool adjust_pc_if_needed) {
318 if (exc_type != 0) {
319 uint32_t pc_decrement = 0;
320 ExecutionContext exe_ctx(thread.shared_from_this());
321 Target *target = exe_ctx.GetTargetPtr();
322 const llvm::Triple::ArchType cpu =
323 target ? target->GetArchitecture().GetMachine()
324 : llvm::Triple::UnknownArch;
325
326 switch (exc_type) {
327 case 1: // EXC_BAD_ACCESS
328 break;
329
330 case 2: // EXC_BAD_INSTRUCTION
331 switch (cpu) {
332 case llvm::Triple::ppc:
333 case llvm::Triple::ppc64:
334 switch (exc_code) {
335 case 1: // EXC_PPC_INVALID_SYSCALL
336 case 2: // EXC_PPC_UNIPL_INST
337 case 3: // EXC_PPC_PRIVINST
338 case 4: // EXC_PPC_PRIVREG
339 break;
340 case 5: // EXC_PPC_TRACE
341 return StopInfo::CreateStopReasonToTrace(thread);
342 case 6: // EXC_PPC_PERFMON
343 break;
344 }
345 break;
346
347 default:
348 break;
349 }
350 break;
351
352 case 3: // EXC_ARITHMETIC
353 case 4: // EXC_EMULATION
354 break;
355
356 case 5: // EXC_SOFTWARE
357 if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
358 {
359 if (exc_sub_code == 5) {
360 // On MacOSX, a SIGTRAP can signify that a process has called
361 // exec, so we should check with our dynamic loader to verify.
362 ProcessSP process_sp(thread.GetProcess());
363 if (process_sp) {
364 DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader();
365 if (dynamic_loader && dynamic_loader->ProcessDidExec()) {
366 // The program was re-exec'ed
367 return StopInfo::CreateStopReasonWithExec(thread);
368 }
369 // if (!process_did_exec)
370 // {
371 // // We have a SIGTRAP, make sure we
372 // didn't exec by checking
373 // // for the PC being at
374 // "_dyld_start"...
375 // lldb::StackFrameSP frame_sp
376 // (thread.GetStackFrameAtIndex(0));
377 // if (frame_sp)
378 // {
379 // const Symbol *symbol =
380 // frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
381 // if (symbol)
382 // {
383 // if (symbol->GetName() ==
384 // ConstString("_dyld_start"))
385 // process_did_exec = true;
386 // }
387 // }
388 // }
389 }
390 }
391 return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code);
392 }
393 break;
394
395 case 6: // EXC_BREAKPOINT
396 {
397 bool is_actual_breakpoint = false;
398 bool is_trace_if_actual_breakpoint_missing = false;
399 switch (cpu) {
400 case llvm::Triple::x86:
401 case llvm::Triple::x86_64:
402 if (exc_code == 1) // EXC_I386_SGL
403 {
404 if (!exc_sub_code) {
405 // This looks like a plain trap.
406 // Have to check if there is a breakpoint here as well. When you
407 // single-step onto a trap,
408 // the single step stops you not to trap. Since we also do that
409 // check below, let's just use
410 // that logic.
411 is_actual_breakpoint = true;
412 is_trace_if_actual_breakpoint_missing = true;
413 } else {
414
415 // It's a watchpoint, then.
416 // The exc_sub_code indicates the data break address.
417 lldb::WatchpointSP wp_sp;
418 if (target)
419 wp_sp = target->GetWatchpointList().FindByAddress(
420 (lldb::addr_t)exc_sub_code);
421 if (wp_sp && wp_sp->IsEnabled()) {
422 // Debugserver may piggyback the hardware index of the fired
423 // watchpoint in the exception data.
424 // Set the hardware index if that's the case.
425 if (exc_data_count >= 3)
426 wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
427 return StopInfo::CreateStopReasonWithWatchpointID(thread,
428 wp_sp->GetID());
429 }
430 }
431 } else if (exc_code == 2 || // EXC_I386_BPT
432 exc_code == 3) // EXC_I386_BPTFLT
433 {
434 // KDP returns EXC_I386_BPTFLT for trace breakpoints
435 if (exc_code == 3)
436 is_trace_if_actual_breakpoint_missing = true;
437
438 is_actual_breakpoint = true;
439 if (!pc_already_adjusted)
440 pc_decrement = 1;
441 }
442 break;
443
444 case llvm::Triple::ppc:
445 case llvm::Triple::ppc64:
446 is_actual_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT
447 break;
448
449 case llvm::Triple::arm:
450 case llvm::Triple::thumb:
451 if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
452 {
453 // It's a watchpoint, then, if the exc_sub_code indicates a
454 // known/enabled
455 // data break address from our watchpoint list.
456 lldb::WatchpointSP wp_sp;
457 if (target)
458 wp_sp = target->GetWatchpointList().FindByAddress(
459 (lldb::addr_t)exc_sub_code);
460 if (wp_sp && wp_sp->IsEnabled()) {
461 // Debugserver may piggyback the hardware index of the fired
462 // watchpoint in the exception data.
463 // Set the hardware index if that's the case.
464 if (exc_data_count >= 3)
465 wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
466 return StopInfo::CreateStopReasonWithWatchpointID(thread,
467 wp_sp->GetID());
468 } else {
469 is_actual_breakpoint = true;
470 is_trace_if_actual_breakpoint_missing = true;
471 }
472 } else if (exc_code == 1) // EXC_ARM_BREAKPOINT
473 {
474 is_actual_breakpoint = true;
475 is_trace_if_actual_breakpoint_missing = true;
476 } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel
477 // is currently returning this so accept it as
478 // indicating a breakpoint until the kernel is
479 // fixed
480 {
481 is_actual_breakpoint = true;
482 is_trace_if_actual_breakpoint_missing = true;
483 }
484 break;
485
486 case llvm::Triple::aarch64: {
487 if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT
488 {
489 // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0
490 // is set
491 is_actual_breakpoint = false;
Value stored to 'is_actual_breakpoint' is never read
492 is_trace_if_actual_breakpoint_missing = true;
493 }
494 if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
495 {
496 // It's a watchpoint, then, if the exc_sub_code indicates a
497 // known/enabled
498 // data break address from our watchpoint list.
499 lldb::WatchpointSP wp_sp;
500 if (target)
501 wp_sp = target->GetWatchpointList().FindByAddress(
502 (lldb::addr_t)exc_sub_code);
503 if (wp_sp && wp_sp->IsEnabled()) {
504 // Debugserver may piggyback the hardware index of the fired
505 // watchpoint in the exception data.
506 // Set the hardware index if that's the case.
507 if (exc_data_count >= 3)
508 wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
509 return StopInfo::CreateStopReasonWithWatchpointID(thread,
510 wp_sp->GetID());
511 }
512 // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as
513 // EXC_BAD_ACCESS
514 if (thread.GetTemporaryResumeState() == eStateStepping)
515 return StopInfo::CreateStopReasonToTrace(thread);
516 }
517 // It looks like exc_sub_code has the 4 bytes of the instruction that
518 // triggered the
519 // exception, i.e. our breakpoint opcode
520 is_actual_breakpoint = exc_code == 1;
521 break;
522 }
523
524 default:
525 break;
526 }
527
528 if (is_actual_breakpoint) {
529 RegisterContextSP reg_ctx_sp(thread.GetRegisterContext());
530 addr_t pc = reg_ctx_sp->GetPC() - pc_decrement;
531
532 ProcessSP process_sp(thread.CalculateProcess());
533
534 lldb::BreakpointSiteSP bp_site_sp;
535 if (process_sp)
536 bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc);
537 if (bp_site_sp && bp_site_sp->IsEnabled()) {
538 // Update the PC if we were asked to do so, but only do
539 // so if we find a breakpoint that we know about cause
540 // this could be a trap instruction in the code
541 if (pc_decrement > 0 && adjust_pc_if_needed)
542 reg_ctx_sp->SetPC(pc);
543
544 // If the breakpoint is for this thread, then we'll report the hit,
545 // but if it is for another thread,
546 // we can just report no reason. We don't need to worry about
547 // stepping over the breakpoint here, that
548 // will be taken care of when the thread resumes and notices that
549 // there's a breakpoint under the pc.
550 // If we have an operating system plug-in, we might have set a thread
551 // specific breakpoint using the
552 // operating system thread ID, so we can't make any assumptions about
553 // the thread ID so we must always
554 // report the breakpoint regardless of the thread.
555 if (bp_site_sp->ValidForThisThread(&thread) ||
556 thread.GetProcess()->GetOperatingSystem() != NULL__null)
557 return StopInfo::CreateStopReasonWithBreakpointSiteID(
558 thread, bp_site_sp->GetID());
559 else if (is_trace_if_actual_breakpoint_missing)
560 return StopInfo::CreateStopReasonToTrace(thread);
561 else
562 return StopInfoSP();
563 }
564
565 // Don't call this a trace if we weren't single stepping this thread.
566 if (is_trace_if_actual_breakpoint_missing &&
567 thread.GetTemporaryResumeState() == eStateStepping) {
568 return StopInfo::CreateStopReasonToTrace(thread);
569 }
570 }
571 } break;
572
573 case 7: // EXC_SYSCALL
574 case 8: // EXC_MACH_SYSCALL
575 case 9: // EXC_RPC_ALERT
576 case 10: // EXC_CRASH
577 break;
578 }
579
580 return StopInfoSP(new StopInfoMachException(
581 thread, exc_type, exc_data_count, exc_code, exc_sub_code));
582 }
583 return StopInfoSP();
584}