Bug Summary

File:src/gnu/usr.bin/clang/liblldbPluginProcess/../../../llvm/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
Warning:line 452, column 9
Value stored to 'is_actual_breakpoint' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name StopInfoMachException.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/liblldbPluginProcess/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/../include -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/obj -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/../../../llvm/lldb/include -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/../../../llvm/lldb/source -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/../../../llvm/clang/include -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/obj/../include/lldb/Plugins -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/liblldbPluginProcess/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/../../../llvm/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
1//===-- StopInfoMachException.cpp -----------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "StopInfoMachException.h"
10
11#include "lldb/lldb-forward.h"
12
13#if defined(__APPLE__)
14// Needed for the EXC_RESOURCE interpretation macros
15#include <kern/exc_resource.h>
16#endif
17
18#include "lldb/Breakpoint/Watchpoint.h"
19#include "lldb/Symbol/Symbol.h"
20#include "lldb/Target/DynamicLoader.h"
21#include "lldb/Target/ExecutionContext.h"
22#include "lldb/Target/Process.h"
23#include "lldb/Target/RegisterContext.h"
24#include "lldb/Target/Target.h"
25#include "lldb/Target/Thread.h"
26#include "lldb/Target/ThreadPlan.h"
27#include "lldb/Target/UnixSignals.h"
28#include "lldb/Utility/StreamString.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
33const char *StopInfoMachException::GetDescription() {
34 if (!m_description.empty())
35 return m_description.c_str();
36 if (GetValue() == eStopReasonInvalid)
37 return "invalid stop reason!";
38
39 ExecutionContext exe_ctx(m_thread_wp.lock());
40 Target *target = exe_ctx.GetTargetPtr();
41 const llvm::Triple::ArchType cpu =
42 target ? target->GetArchitecture().GetMachine()
43 : llvm::Triple::UnknownArch;
44
45 const char *exc_desc = nullptr;
46 const char *code_label = "code";
47 const char *code_desc = nullptr;
48 const char *subcode_label = "subcode";
49 const char *subcode_desc = nullptr;
50
51#if defined(__APPLE__)
52 char code_desc_buf[32];
53 char subcode_desc_buf[32];
54#endif
55
56 switch (m_value) {
57 case 1: // EXC_BAD_ACCESS
58 exc_desc = "EXC_BAD_ACCESS";
59 subcode_label = "address";
60 switch (cpu) {
61 case llvm::Triple::x86:
62 case llvm::Triple::x86_64:
63 switch (m_exc_code) {
64 case 0xd:
65 code_desc = "EXC_I386_GPFLT";
66 m_exc_data_count = 1;
67 break;
68 }
69 break;
70 case llvm::Triple::arm:
71 case llvm::Triple::thumb:
72 switch (m_exc_code) {
73 case 0x101:
74 code_desc = "EXC_ARM_DA_ALIGN";
75 break;
76 case 0x102:
77 code_desc = "EXC_ARM_DA_DEBUG";
78 break;
79 }
80 break;
81
82 default:
83 break;
84 }
85 break;
86
87 case 2: // EXC_BAD_INSTRUCTION
88 exc_desc = "EXC_BAD_INSTRUCTION";
89 switch (cpu) {
90 case llvm::Triple::x86:
91 case llvm::Triple::x86_64:
92 if (m_exc_code == 1)
93 code_desc = "EXC_I386_INVOP";
94 break;
95
96 case llvm::Triple::arm:
97 case llvm::Triple::thumb:
98 if (m_exc_code == 1)
99 code_desc = "EXC_ARM_UNDEFINED";
100 break;
101
102 default:
103 break;
104 }
105 break;
106
107 case 3: // EXC_ARITHMETIC
108 exc_desc = "EXC_ARITHMETIC";
109 switch (cpu) {
110 case llvm::Triple::x86:
111 case llvm::Triple::x86_64:
112 switch (m_exc_code) {
113 case 1:
114 code_desc = "EXC_I386_DIV";
115 break;
116 case 2:
117 code_desc = "EXC_I386_INTO";
118 break;
119 case 3:
120 code_desc = "EXC_I386_NOEXT";
121 break;
122 case 4:
123 code_desc = "EXC_I386_EXTOVR";
124 break;
125 case 5:
126 code_desc = "EXC_I386_EXTERR";
127 break;
128 case 6:
129 code_desc = "EXC_I386_EMERR";
130 break;
131 case 7:
132 code_desc = "EXC_I386_BOUND";
133 break;
134 case 8:
135 code_desc = "EXC_I386_SSEEXTERR";
136 break;
137 }
138 break;
139
140 default:
141 break;
142 }
143 break;
144
145 case 4: // EXC_EMULATION
146 exc_desc = "EXC_EMULATION";
147 break;
148
149 case 5: // EXC_SOFTWARE
150 exc_desc = "EXC_SOFTWARE";
151 if (m_exc_code == 0x10003) {
152 subcode_desc = "EXC_SOFT_SIGNAL";
153 subcode_label = "signo";
154 }
155 break;
156
157 case 6: // EXC_BREAKPOINT
158 {
159 exc_desc = "EXC_BREAKPOINT";
160 switch (cpu) {
161 case llvm::Triple::x86:
162 case llvm::Triple::x86_64:
163 switch (m_exc_code) {
164 case 1:
165 code_desc = "EXC_I386_SGL";
166 break;
167 case 2:
168 code_desc = "EXC_I386_BPT";
169 break;
170 }
171 break;
172
173 case llvm::Triple::arm:
174 case llvm::Triple::thumb:
175 switch (m_exc_code) {
176 case 0x101:
177 code_desc = "EXC_ARM_DA_ALIGN";
178 break;
179 case 0x102:
180 code_desc = "EXC_ARM_DA_DEBUG";
181 break;
182 case 1:
183 code_desc = "EXC_ARM_BREAKPOINT";
184 break;
185 // FIXME temporary workaround, exc_code 0 does not really mean
186 // EXC_ARM_BREAKPOINT
187 case 0:
188 code_desc = "EXC_ARM_BREAKPOINT";
189 break;
190 }
191 break;
192
193 default:
194 break;
195 }
196 } break;
197
198 case 7:
199 exc_desc = "EXC_SYSCALL";
200 break;
201
202 case 8:
203 exc_desc = "EXC_MACH_SYSCALL";
204 break;
205
206 case 9:
207 exc_desc = "EXC_RPC_ALERT";
208 break;
209
210 case 10:
211 exc_desc = "EXC_CRASH";
212 break;
213 case 11:
214 exc_desc = "EXC_RESOURCE";
215#if defined(__APPLE__)
216 {
217 int resource_type = EXC_RESOURCE_DECODE_RESOURCE_TYPE(m_exc_code);
218
219 code_label = "limit";
220 code_desc = code_desc_buf;
221 subcode_label = "observed";
222 subcode_desc = subcode_desc_buf;
223
224 switch (resource_type) {
225 case RESOURCE_TYPE_CPU:
226 exc_desc = "EXC_RESOURCE RESOURCE_TYPE_CPU";
227 snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%",
228 (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code));
229 snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%",
230 (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE_OBSERVED(
231 m_exc_subcode));
232 break;
233 case RESOURCE_TYPE_WAKEUPS:
234 exc_desc = "EXC_RESOURCE RESOURCE_TYPE_WAKEUPS";
235 snprintf(
236 code_desc_buf, sizeof(code_desc_buf), "%d w/s",
237 (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_PERMITTED(m_exc_code));
238 snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d w/s",
239 (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_OBSERVED(
240 m_exc_subcode));
241 break;
242 case RESOURCE_TYPE_MEMORY:
243 exc_desc = "EXC_RESOURCE RESOURCE_TYPE_MEMORY";
244 snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB",
245 (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code));
246 subcode_desc = nullptr;
247 subcode_label = "unused";
248 break;
249#if defined(RESOURCE_TYPE_IO)
250 // RESOURCE_TYPE_IO is introduced in macOS SDK 10.12.
251 case RESOURCE_TYPE_IO:
252 exc_desc = "EXC_RESOURCE RESOURCE_TYPE_IO";
253 snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB",
254 (int)EXC_RESOURCE_IO_DECODE_LIMIT(m_exc_code));
255 snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d MB",
256 (int)EXC_RESOURCE_IO_OBSERVED(m_exc_subcode));
257 ;
258 break;
259#endif
260 }
261 }
262#endif
263 break;
264 case 12:
265 exc_desc = "EXC_GUARD";
266 break;
267 }
268
269 StreamString strm;
270
271 if (exc_desc)
272 strm.PutCString(exc_desc);
273 else
274 strm.Printf("EXC_??? (%" PRIu64"llu" ")", m_value);
275
276 if (m_exc_data_count >= 1) {
277 if (code_desc)
278 strm.Printf(" (%s=%s", code_label, code_desc);
279 else
280 strm.Printf(" (%s=%" PRIu64"llu", code_label, m_exc_code);
281 }
282
283 if (m_exc_data_count >= 2) {
284 if (subcode_desc)
285 strm.Printf(", %s=%s", subcode_label, subcode_desc);
286 else
287 strm.Printf(", %s=0x%" PRIx64"llx", subcode_label, m_exc_subcode);
288 }
289
290 if (m_exc_data_count > 0)
291 strm.PutChar(')');
292
293 m_description = std::string(strm.GetString());
294 return m_description.c_str();
295}
296
297static StopInfoSP GetStopInfoForHardwareBP(Thread &thread, Target *target,
298 uint32_t exc_data_count,
299 uint64_t exc_sub_code,
300 uint64_t exc_sub_sub_code) {
301 // Try hardware watchpoint.
302 if (target) {
303 // The exc_sub_code indicates the data break address.
304 lldb::WatchpointSP wp_sp =
305 target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code);
306 if (wp_sp && wp_sp->IsEnabled()) {
307 // Debugserver may piggyback the hardware index of the fired watchpoint
308 // in the exception data. Set the hardware index if that's the case.
309 if (exc_data_count >= 3)
310 wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
311 return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
312 }
313 }
314
315 // Try hardware breakpoint.
316 ProcessSP process_sp(thread.GetProcess());
317 if (process_sp) {
318 // The exc_sub_code indicates the data break address.
319 lldb::BreakpointSiteSP bp_sp =
320 process_sp->GetBreakpointSiteList().FindByAddress(
321 (lldb::addr_t)exc_sub_code);
322 if (bp_sp && bp_sp->IsEnabled()) {
323 // Debugserver may piggyback the hardware index of the fired breakpoint
324 // in the exception data. Set the hardware index if that's the case.
325 if (exc_data_count >= 3)
326 bp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
327 return StopInfo::CreateStopReasonWithBreakpointSiteID(thread,
328 bp_sp->GetID());
329 }
330 }
331
332 return nullptr;
333}
334
335StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
336 Thread &thread, uint32_t exc_type, uint32_t exc_data_count,
337 uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code,
338 bool pc_already_adjusted, bool adjust_pc_if_needed) {
339 if (exc_type == 0)
340 return StopInfoSP();
341
342 uint32_t pc_decrement = 0;
343 ExecutionContext exe_ctx(thread.shared_from_this());
344 Target *target = exe_ctx.GetTargetPtr();
345 const llvm::Triple::ArchType cpu =
346 target ? target->GetArchitecture().GetMachine()
347 : llvm::Triple::UnknownArch;
348
349 switch (exc_type) {
350 case 1: // EXC_BAD_ACCESS
351 case 2: // EXC_BAD_INSTRUCTION
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 exec,
361 // 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 }
370 }
371 return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code);
372 }
373 break;
374
375 case 6: // EXC_BREAKPOINT
376 {
377 bool is_actual_breakpoint = false;
378 bool is_trace_if_actual_breakpoint_missing = false;
379 switch (cpu) {
380 case llvm::Triple::x86:
381 case llvm::Triple::x86_64:
382 if (exc_code == 1) // EXC_I386_SGL
383 {
384 if (!exc_sub_code) {
385 // This looks like a plain trap.
386 // Have to check if there is a breakpoint here as well. When you
387 // single-step onto a trap, the single step stops you not to trap.
388 // Since we also do that check below, let's just use that logic.
389 is_actual_breakpoint = true;
390 is_trace_if_actual_breakpoint_missing = true;
391 } else {
392 if (StopInfoSP stop_info =
393 GetStopInfoForHardwareBP(thread, target, exc_data_count,
394 exc_sub_code, exc_sub_sub_code))
395 return stop_info;
396 }
397 } else if (exc_code == 2 || // EXC_I386_BPT
398 exc_code == 3) // EXC_I386_BPTFLT
399 {
400 // KDP returns EXC_I386_BPTFLT for trace breakpoints
401 if (exc_code == 3)
402 is_trace_if_actual_breakpoint_missing = true;
403
404 is_actual_breakpoint = true;
405 if (!pc_already_adjusted)
406 pc_decrement = 1;
407 }
408 break;
409
410 case llvm::Triple::arm:
411 case llvm::Triple::thumb:
412 if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
413 {
414 // It's a watchpoint, then, if the exc_sub_code indicates a
415 // known/enabled data break address from our watchpoint list.
416 lldb::WatchpointSP wp_sp;
417 if (target)
418 wp_sp = target->GetWatchpointList().FindByAddress(
419 (lldb::addr_t)exc_sub_code);
420 if (wp_sp && wp_sp->IsEnabled()) {
421 // Debugserver may piggyback the hardware index of the fired
422 // watchpoint in the exception data. Set the hardware index if
423 // that's the case.
424 if (exc_data_count >= 3)
425 wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
426 return StopInfo::CreateStopReasonWithWatchpointID(thread,
427 wp_sp->GetID());
428 } else {
429 is_actual_breakpoint = true;
430 is_trace_if_actual_breakpoint_missing = true;
431 }
432 } else if (exc_code == 1) // EXC_ARM_BREAKPOINT
433 {
434 is_actual_breakpoint = true;
435 is_trace_if_actual_breakpoint_missing = true;
436 } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel
437 // is currently returning this so accept it
438 // as indicating a breakpoint until the
439 // kernel is fixed
440 {
441 is_actual_breakpoint = true;
442 is_trace_if_actual_breakpoint_missing = true;
443 }
444 break;
445
446 case llvm::Triple::aarch64_32:
447 case llvm::Triple::aarch64: {
448 if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT
449 {
450 // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0
451 // is set
452 is_actual_breakpoint = false;
Value stored to 'is_actual_breakpoint' is never read
453 is_trace_if_actual_breakpoint_missing = true;
454 }
455 if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
456 {
457 // It's a watchpoint, then, if the exc_sub_code indicates a
458 // known/enabled data break address from our watchpoint list.
459 lldb::WatchpointSP wp_sp;
460 if (target)
461 wp_sp = target->GetWatchpointList().FindByAddress(
462 (lldb::addr_t)exc_sub_code);
463 if (wp_sp && wp_sp->IsEnabled()) {
464 // Debugserver may piggyback the hardware index of the fired
465 // watchpoint in the exception data. Set the hardware index if
466 // that's the case.
467 if (exc_data_count >= 3)
468 wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
469 return StopInfo::CreateStopReasonWithWatchpointID(thread,
470 wp_sp->GetID());
471 }
472 // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as
473 // EXC_BAD_ACCESS
474 if (thread.GetTemporaryResumeState() == eStateStepping)
475 return StopInfo::CreateStopReasonToTrace(thread);
476 }
477 // It looks like exc_sub_code has the 4 bytes of the instruction that
478 // triggered the exception, i.e. our breakpoint opcode
479 is_actual_breakpoint = exc_code == 1;
480 break;
481 }
482
483 default:
484 break;
485 }
486
487 if (is_actual_breakpoint) {
488 RegisterContextSP reg_ctx_sp(thread.GetRegisterContext());
489 addr_t pc = reg_ctx_sp->GetPC() - pc_decrement;
490
491 ProcessSP process_sp(thread.CalculateProcess());
492
493 lldb::BreakpointSiteSP bp_site_sp;
494 if (process_sp)
495 bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc);
496 if (bp_site_sp && bp_site_sp->IsEnabled()) {
497 // Update the PC if we were asked to do so, but only do so if we find
498 // a breakpoint that we know about cause this could be a trap
499 // instruction in the code
500 if (pc_decrement > 0 && adjust_pc_if_needed)
501 reg_ctx_sp->SetPC(pc);
502
503 // If the breakpoint is for this thread, then we'll report the hit,
504 // but if it is for another thread, we can just report no reason. We
505 // don't need to worry about stepping over the breakpoint here, that
506 // will be taken care of when the thread resumes and notices that
507 // there's a breakpoint under the pc. If we have an operating system
508 // plug-in, we might have set a thread specific breakpoint using the
509 // operating system thread ID, so we can't make any assumptions about
510 // the thread ID so we must always report the breakpoint regardless
511 // of the thread.
512 if (bp_site_sp->ValidForThisThread(thread) ||
513 thread.GetProcess()->GetOperatingSystem() != nullptr)
514 return StopInfo::CreateStopReasonWithBreakpointSiteID(
515 thread, bp_site_sp->GetID());
516 else if (is_trace_if_actual_breakpoint_missing)
517 return StopInfo::CreateStopReasonToTrace(thread);
518 else
519 return StopInfoSP();
520 }
521
522 // Don't call this a trace if we weren't single stepping this thread.
523 if (is_trace_if_actual_breakpoint_missing &&
524 thread.GetTemporaryResumeState() == eStateStepping) {
525 return StopInfo::CreateStopReasonToTrace(thread);
526 }
527 }
528 } break;
529
530 case 7: // EXC_SYSCALL
531 case 8: // EXC_MACH_SYSCALL
532 case 9: // EXC_RPC_ALERT
533 case 10: // EXC_CRASH
534 break;
535 }
536
537 return StopInfoSP(new StopInfoMachException(thread, exc_type, exc_data_count,
538 exc_code, exc_sub_code));
539}