1 //===-- BreakpointLocation.cpp --------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Breakpoint/BreakpointLocation.h"
10 #include "lldb/Breakpoint/BreakpointID.h"
11 #include "lldb/Breakpoint/StoppointCallbackContext.h"
12 #include "lldb/Core/Debugger.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Expression/DiagnosticManager.h"
15 #include "lldb/Expression/ExpressionVariable.h"
16 #include "lldb/Expression/UserExpression.h"
17 #include "lldb/Symbol/CompileUnit.h"
18 #include "lldb/Symbol/Symbol.h"
19 #include "lldb/Symbol/TypeSystem.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Target/Thread.h"
23 #include "lldb/Target/ThreadSpec.h"
24 #include "lldb/Utility/LLDBLog.h"
25 #include "lldb/Utility/Log.h"
26 #include "lldb/Utility/StreamString.h"
27 #include "lldb/ValueObject/ValueObject.h"
30 using namespace lldb_private
;
32 BreakpointLocation::BreakpointLocation(break_id_t loc_id
, Breakpoint
&owner
,
33 const Address
&addr
, lldb::tid_t tid
,
34 bool hardware
, bool check_for_resolver
)
35 : m_should_resolve_indirect_functions(false), m_is_reexported(false),
36 m_is_indirect(false), m_address(addr
), m_owner(owner
),
37 m_condition_hash(0), m_loc_id(loc_id
), m_hit_counter() {
38 if (check_for_resolver
) {
39 Symbol
*symbol
= m_address
.CalculateSymbolContextSymbol();
40 if (symbol
&& symbol
->IsIndirect()) {
41 SetShouldResolveIndirectFunctions(true);
45 SetThreadIDInternal(tid
);
48 BreakpointLocation::~BreakpointLocation() { ClearBreakpointSite(); }
50 lldb::addr_t
BreakpointLocation::GetLoadAddress() const {
51 return m_address
.GetOpcodeLoadAddress(&m_owner
.GetTarget());
54 const BreakpointOptions
&BreakpointLocation::GetOptionsSpecifyingKind(
55 BreakpointOptions::OptionKind kind
) const {
56 if (m_options_up
&& m_options_up
->IsOptionSet(kind
))
59 return m_owner
.GetOptions();
62 Address
&BreakpointLocation::GetAddress() { return m_address
; }
64 Breakpoint
&BreakpointLocation::GetBreakpoint() { return m_owner
; }
66 Target
&BreakpointLocation::GetTarget() { return m_owner
.GetTarget(); }
68 bool BreakpointLocation::IsEnabled() const {
69 if (!m_owner
.IsEnabled())
71 else if (m_options_up
!= nullptr)
72 return m_options_up
->IsEnabled();
77 void BreakpointLocation::SetEnabled(bool enabled
) {
78 GetLocationOptions().SetEnabled(enabled
);
80 ResolveBreakpointSite();
82 ClearBreakpointSite();
84 SendBreakpointLocationChangedEvent(enabled
? eBreakpointEventTypeEnabled
85 : eBreakpointEventTypeDisabled
);
88 bool BreakpointLocation::IsAutoContinue() const {
90 m_options_up
->IsOptionSet(BreakpointOptions::eAutoContinue
))
91 return m_options_up
->IsAutoContinue();
93 return m_owner
.IsAutoContinue();
96 void BreakpointLocation::SetAutoContinue(bool auto_continue
) {
97 GetLocationOptions().SetAutoContinue(auto_continue
);
98 SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged
);
101 void BreakpointLocation::SetThreadID(lldb::tid_t thread_id
) {
102 SetThreadIDInternal(thread_id
);
103 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged
);
106 lldb::tid_t
BreakpointLocation::GetThreadID() {
107 const ThreadSpec
*thread_spec
=
108 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec
)
109 .GetThreadSpecNoCreate();
111 return thread_spec
->GetTID();
113 return LLDB_INVALID_THREAD_ID
;
116 void BreakpointLocation::SetThreadIndex(uint32_t index
) {
118 GetLocationOptions().GetThreadSpec()->SetIndex(index
);
120 // If we're resetting this to an invalid thread id, then don't make an
121 // options pointer just to do that.
122 if (m_options_up
!= nullptr)
123 m_options_up
->GetThreadSpec()->SetIndex(index
);
125 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged
);
128 uint32_t BreakpointLocation::GetThreadIndex() const {
129 const ThreadSpec
*thread_spec
=
130 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec
)
131 .GetThreadSpecNoCreate();
133 return thread_spec
->GetIndex();
138 void BreakpointLocation::SetThreadName(const char *thread_name
) {
139 if (thread_name
!= nullptr)
140 GetLocationOptions().GetThreadSpec()->SetName(thread_name
);
142 // If we're resetting this to an invalid thread id, then don't make an
143 // options pointer just to do that.
144 if (m_options_up
!= nullptr)
145 m_options_up
->GetThreadSpec()->SetName(thread_name
);
147 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged
);
150 const char *BreakpointLocation::GetThreadName() const {
151 const ThreadSpec
*thread_spec
=
152 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec
)
153 .GetThreadSpecNoCreate();
155 return thread_spec
->GetName();
160 void BreakpointLocation::SetQueueName(const char *queue_name
) {
161 if (queue_name
!= nullptr)
162 GetLocationOptions().GetThreadSpec()->SetQueueName(queue_name
);
164 // If we're resetting this to an invalid thread id, then don't make an
165 // options pointer just to do that.
166 if (m_options_up
!= nullptr)
167 m_options_up
->GetThreadSpec()->SetQueueName(queue_name
);
169 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged
);
172 const char *BreakpointLocation::GetQueueName() const {
173 const ThreadSpec
*thread_spec
=
174 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec
)
175 .GetThreadSpecNoCreate();
177 return thread_spec
->GetQueueName();
182 bool BreakpointLocation::InvokeCallback(StoppointCallbackContext
*context
) {
183 if (m_options_up
!= nullptr && m_options_up
->HasCallback())
184 return m_options_up
->InvokeCallback(context
, m_owner
.GetID(), GetID());
186 return m_owner
.InvokeCallback(context
, GetID());
189 bool BreakpointLocation::IsCallbackSynchronous() {
190 if (m_options_up
!= nullptr && m_options_up
->HasCallback())
191 return m_options_up
->IsCallbackSynchronous();
193 return m_owner
.GetOptions().IsCallbackSynchronous();
196 void BreakpointLocation::SetCallback(BreakpointHitCallback callback
,
197 void *baton
, bool is_synchronous
) {
198 // The default "Baton" class will keep a copy of "baton" and won't free or
199 // delete it when it goes out of scope.
200 GetLocationOptions().SetCallback(
201 callback
, std::make_shared
<UntypedBaton
>(baton
), is_synchronous
);
202 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged
);
205 void BreakpointLocation::SetCallback(BreakpointHitCallback callback
,
206 const BatonSP
&baton_sp
,
207 bool is_synchronous
) {
208 GetLocationOptions().SetCallback(callback
, baton_sp
, is_synchronous
);
209 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged
);
212 void BreakpointLocation::ClearCallback() {
213 GetLocationOptions().ClearCallback();
216 void BreakpointLocation::SetCondition(const char *condition
) {
217 GetLocationOptions().SetCondition(condition
);
218 SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged
);
221 const char *BreakpointLocation::GetConditionText(size_t *hash
) const {
222 return GetOptionsSpecifyingKind(BreakpointOptions::eCondition
)
223 .GetConditionText(hash
);
226 bool BreakpointLocation::ConditionSaysStop(ExecutionContext
&exe_ctx
,
228 Log
*log
= GetLog(LLDBLog::Breakpoints
);
230 std::lock_guard
<std::mutex
> guard(m_condition_mutex
);
232 size_t condition_hash
;
233 const char *condition_text
= GetConditionText(&condition_hash
);
235 if (!condition_text
) {
236 m_user_expression_sp
.reset();
242 DiagnosticManager diagnostics
;
244 if (condition_hash
!= m_condition_hash
|| !m_user_expression_sp
||
245 !m_user_expression_sp
->IsParseCacheable() ||
246 !m_user_expression_sp
->MatchesContext(exe_ctx
)) {
247 LanguageType language
= eLanguageTypeUnknown
;
248 // See if we can figure out the language from the frame, otherwise use the
250 CompileUnit
*comp_unit
= m_address
.CalculateSymbolContextCompileUnit();
252 language
= comp_unit
->GetLanguage();
254 m_user_expression_sp
.reset(GetTarget().GetUserExpressionForLanguage(
255 condition_text
, llvm::StringRef(), language
, Expression::eResultTypeAny
,
256 EvaluateExpressionOptions(), nullptr, error
));
258 LLDB_LOGF(log
, "Error getting condition expression: %s.",
260 m_user_expression_sp
.reset();
264 if (!m_user_expression_sp
->Parse(diagnostics
, exe_ctx
,
265 eExecutionPolicyOnlyWhenNeeded
, true,
267 error
= Status::FromError(
268 diagnostics
.GetAsError(lldb::eExpressionParseError
,
269 "Couldn't parse conditional expression:"));
271 m_user_expression_sp
.reset();
275 m_condition_hash
= condition_hash
;
278 // We need to make sure the user sees any parse errors in their condition, so
279 // we'll hook the constructor errors up to the debugger's Async I/O.
281 ValueObjectSP result_value_sp
;
283 EvaluateExpressionOptions options
;
284 options
.SetUnwindOnError(true);
285 options
.SetIgnoreBreakpoints(true);
286 options
.SetTryAllThreads(true);
287 options
.SetSuppressPersistentResult(
288 true); // Don't generate a user variable for condition expressions.
294 ExpressionVariableSP result_variable_sp
;
296 ExpressionResults result_code
= m_user_expression_sp
->Execute(
297 diagnostics
, exe_ctx
, options
, m_user_expression_sp
, result_variable_sp
);
301 if (result_code
== eExpressionCompleted
) {
302 if (!result_variable_sp
) {
303 error
= Status::FromErrorString("Expression did not return a result");
307 result_value_sp
= result_variable_sp
->GetValueObject();
309 if (result_value_sp
) {
310 ret
= result_value_sp
->IsLogicalTrue(error
);
312 if (error
.Success()) {
313 LLDB_LOGF(log
, "Condition successfully evaluated, result is %s.\n",
314 ret
? "true" : "false");
316 error
= Status::FromErrorString(
317 "Failed to get an integer result from the expression");
323 error
= Status::FromErrorString(
324 "Failed to get any result from the expression");
328 error
= Status::FromError(diagnostics
.GetAsError(
329 lldb::eExpressionParseError
, "Couldn't execute expression:"));
335 uint32_t BreakpointLocation::GetIgnoreCount() const {
336 return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount
)
340 void BreakpointLocation::SetIgnoreCount(uint32_t n
) {
341 GetLocationOptions().SetIgnoreCount(n
);
342 SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged
);
345 void BreakpointLocation::DecrementIgnoreCount() {
346 if (m_options_up
!= nullptr) {
347 uint32_t loc_ignore
= m_options_up
->GetIgnoreCount();
349 m_options_up
->SetIgnoreCount(loc_ignore
- 1);
353 bool BreakpointLocation::IgnoreCountShouldStop() {
354 uint32_t owner_ignore
= GetBreakpoint().GetIgnoreCount();
355 uint32_t loc_ignore
= 0;
356 if (m_options_up
!= nullptr)
357 loc_ignore
= m_options_up
->GetIgnoreCount();
359 if (loc_ignore
!= 0 || owner_ignore
!= 0) {
360 m_owner
.DecrementIgnoreCount();
361 DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
362 // since it won't get a chance to.
368 BreakpointOptions
&BreakpointLocation::GetLocationOptions() {
369 // If we make the copy we don't copy the callbacks because that is
370 // potentially expensive and we don't want to do that for the simple case
371 // where someone is just disabling the location.
372 if (m_options_up
== nullptr)
373 m_options_up
= std::make_unique
<BreakpointOptions
>(false);
375 return *m_options_up
;
378 bool BreakpointLocation::ValidForThisThread(Thread
&thread
) {
379 return thread
.MatchesSpec(
380 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec
)
381 .GetThreadSpecNoCreate());
384 // RETURNS - true if we should stop at this breakpoint, false if we
385 // should continue. Note, we don't check the thread spec for the breakpoint
386 // here, since if the breakpoint is not for this thread, then the event won't
387 // even get reported, so the check is redundant.
389 bool BreakpointLocation::ShouldStop(StoppointCallbackContext
*context
) {
390 bool should_stop
= true;
391 Log
*log
= GetLog(LLDBLog::Breakpoints
);
393 // Do this first, if a location is disabled, it shouldn't increment its hit
398 // We only run synchronous callbacks in ShouldStop:
399 context
->is_synchronous
= true;
400 should_stop
= InvokeCallback(context
);
404 GetDescription(&s
, lldb::eDescriptionLevelVerbose
);
405 LLDB_LOGF(log
, "Hit breakpoint location: %s, %s.\n", s
.GetData(),
406 should_stop
? "stopping" : "continuing");
412 void BreakpointLocation::BumpHitCount() {
414 // Step our hit count, and also step the hit count of the owner.
415 m_hit_counter
.Increment();
416 m_owner
.m_hit_counter
.Increment();
420 void BreakpointLocation::UndoBumpHitCount() {
422 // Step our hit count, and also step the hit count of the owner.
423 m_hit_counter
.Decrement();
424 m_owner
.m_hit_counter
.Decrement();
428 bool BreakpointLocation::IsResolved() const {
429 return m_bp_site_sp
.get() != nullptr;
432 lldb::BreakpointSiteSP
BreakpointLocation::GetBreakpointSite() const {
436 bool BreakpointLocation::ResolveBreakpointSite() {
440 Process
*process
= m_owner
.GetTarget().GetProcessSP().get();
441 if (process
== nullptr)
444 lldb::break_id_t new_id
=
445 process
->CreateBreakpointSite(shared_from_this(), m_owner
.IsHardware());
447 if (new_id
== LLDB_INVALID_BREAK_ID
) {
448 Log
*log
= GetLog(LLDBLog::Breakpoints
);
450 log
->Warning("Failed to add breakpoint site at 0x%" PRIx64
,
451 m_address
.GetOpcodeLoadAddress(&m_owner
.GetTarget()));
457 bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP
&bp_site_sp
) {
458 m_bp_site_sp
= bp_site_sp
;
459 SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved
);
463 bool BreakpointLocation::ClearBreakpointSite() {
464 if (m_bp_site_sp
.get()) {
465 ProcessSP
process_sp(m_owner
.GetTarget().GetProcessSP());
466 // If the process exists, get it to remove the owner, it will remove the
467 // physical implementation of the breakpoint as well if there are no more
468 // owners. Otherwise just remove this owner.
470 process_sp
->RemoveConstituentFromBreakpointSite(GetBreakpoint().GetID(),
471 GetID(), m_bp_site_sp
);
473 m_bp_site_sp
->RemoveConstituent(GetBreakpoint().GetID(), GetID());
475 m_bp_site_sp
.reset();
481 void BreakpointLocation::GetDescription(Stream
*s
,
482 lldb::DescriptionLevel level
) {
485 // If the description level is "initial" then the breakpoint is printing out
486 // our initial state, and we should let it decide how it wants to print our
488 if (level
!= eDescriptionLevelInitial
) {
490 BreakpointID::GetCanonicalReference(s
, m_owner
.GetID(), GetID());
493 if (level
== lldb::eDescriptionLevelBrief
)
496 if (level
!= eDescriptionLevelInitial
)
499 if (level
== lldb::eDescriptionLevelVerbose
)
502 if (m_address
.IsSectionOffset()) {
503 m_address
.CalculateSymbolContext(&sc
);
505 if (level
== lldb::eDescriptionLevelFull
||
506 level
== eDescriptionLevelInitial
) {
508 s
->PutCString("re-exported target = ");
510 s
->PutCString("where = ");
512 // If there's a preferred line entry for printing, use that.
513 bool show_function_info
= true;
514 if (auto preferred
= GetPreferredLineEntry()) {
515 sc
.line_entry
= *preferred
;
516 // FIXME: We're going to get the function name wrong when the preferred
517 // line entry is not the lowest one. For now, just leave the function
518 // out in this case, but we really should also figure out how to easily
519 // fake the function name here.
520 show_function_info
= false;
522 sc
.DumpStopContext(s
, m_owner
.GetTarget().GetProcessSP().get(), m_address
,
523 false, true, false, show_function_info
,
524 show_function_info
, show_function_info
);
528 s
->Indent("module = ");
529 sc
.module_sp
->GetFileSpec().Dump(s
->AsRawOstream());
532 if (sc
.comp_unit
!= nullptr) {
534 s
->Indent("compile unit = ");
535 sc
.comp_unit
->GetPrimaryFile().GetFilename().Dump(s
);
537 if (sc
.function
!= nullptr) {
539 s
->Indent("function = ");
540 s
->PutCString(sc
.function
->GetName().AsCString("<unknown>"));
541 if (ConstString mangled_name
=
542 sc
.function
->GetMangled().GetMangledName()) {
544 s
->Indent("mangled function = ");
545 s
->PutCString(mangled_name
.AsCString());
549 if (sc
.line_entry
.line
> 0) {
551 s
->Indent("location = ");
552 if (auto preferred
= GetPreferredLineEntry())
553 preferred
->DumpStopContext(s
, true);
555 sc
.line_entry
.DumpStopContext(s
, true);
559 // If we don't have a comp unit, see if we have a symbol we can print.
563 s
->Indent("re-exported target = ");
565 s
->Indent("symbol = ");
566 s
->PutCString(sc
.symbol
->GetName().AsCString("<unknown>"));
572 if (level
== lldb::eDescriptionLevelVerbose
) {
577 if (m_address
.IsSectionOffset() &&
578 (level
== eDescriptionLevelFull
|| level
== eDescriptionLevelInitial
))
580 s
->Printf("address = ");
582 ExecutionContextScope
*exe_scope
= nullptr;
583 Target
*target
= &m_owner
.GetTarget();
585 exe_scope
= target
->GetProcessSP().get();
586 if (exe_scope
== nullptr)
589 if (level
== eDescriptionLevelInitial
)
590 m_address
.Dump(s
, exe_scope
, Address::DumpStyleLoadAddress
,
591 Address::DumpStyleFileAddress
);
593 m_address
.Dump(s
, exe_scope
, Address::DumpStyleLoadAddress
,
594 Address::DumpStyleModuleWithFileAddress
);
596 if (IsIndirect() && m_bp_site_sp
) {
597 Address resolved_address
;
598 resolved_address
.SetLoadAddress(m_bp_site_sp
->GetLoadAddress(), target
);
599 Symbol
*resolved_symbol
= resolved_address
.CalculateSymbolContextSymbol();
600 if (resolved_symbol
) {
601 if (level
== eDescriptionLevelFull
|| level
== eDescriptionLevelInitial
)
603 else if (level
== lldb::eDescriptionLevelVerbose
) {
607 s
->Printf("indirect target = %s",
608 resolved_symbol
->GetName().GetCString());
612 bool is_resolved
= IsResolved();
613 bool is_hardware
= is_resolved
&& m_bp_site_sp
->IsHardware();
615 if (level
== lldb::eDescriptionLevelVerbose
) {
618 s
->Printf("resolved = %s\n", is_resolved
? "true" : "false");
620 s
->Printf("hardware = %s\n", is_hardware
? "true" : "false");
622 s
->Printf("hit count = %-4u\n", GetHitCount());
626 m_options_up
->GetDescription(s
, level
);
630 } else if (level
!= eDescriptionLevelInitial
) {
631 s
->Printf(", %sresolved, %shit count = %u ", (is_resolved
? "" : "un"),
632 (is_hardware
? "hardware, " : ""), GetHitCount());
634 m_options_up
->GetDescription(s
, level
);
639 void BreakpointLocation::Dump(Stream
*s
) const {
643 bool is_resolved
= IsResolved();
644 bool is_hardware
= is_resolved
&& m_bp_site_sp
->IsHardware();
646 lldb::tid_t tid
= GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec
)
647 .GetThreadSpecNoCreate()
649 s
->Printf("BreakpointLocation %u: tid = %4.4" PRIx64
650 " load addr = 0x%8.8" PRIx64
" state = %s type = %s breakpoint "
651 "hit_count = %-4u ignore_count = %-4u",
653 (uint64_t)m_address
.GetOpcodeLoadAddress(&m_owner
.GetTarget()),
654 (m_options_up
? m_options_up
->IsEnabled() : m_owner
.IsEnabled())
657 is_hardware
? "hardware" : "software", GetHitCount(),
658 GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount
)
662 void BreakpointLocation::SendBreakpointLocationChangedEvent(
663 lldb::BreakpointEventType eventKind
) {
664 if (!m_owner
.IsInternal() && m_owner
.GetTarget().EventTypeHasListeners(
665 Target::eBroadcastBitBreakpointChanged
)) {
666 auto data_sp
= std::make_shared
<Breakpoint::BreakpointEventData
>(
667 eventKind
, m_owner
.shared_from_this());
668 data_sp
->GetBreakpointLocationCollection().Add(shared_from_this());
669 m_owner
.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged
,
674 std::optional
<uint32_t> BreakpointLocation::GetSuggestedStackFrameIndex() {
675 auto preferred_opt
= GetPreferredLineEntry();
678 LineEntry preferred
= *preferred_opt
;
680 if (!m_address
.CalculateSymbolContext(&sc
))
682 // Don't return anything special if frame 0 is the preferred line entry.
683 // We not really telling the stack frame list to do anything special in that
685 if (!LineEntry::Compare(sc
.line_entry
, preferred
))
691 // Blocks have their line info in Declaration form, so make one here:
692 Declaration
preferred_decl(preferred
.GetFile(), preferred
.line
,
696 Block
*inlined_block
= sc
.block
->GetContainingInlinedBlock();
697 while (inlined_block
) {
698 // If we've moved to a block that this isn't the start of, that's not
699 // our inlining info or call site, so we can stop here.
700 Address start_address
;
701 if (!inlined_block
->GetStartAddress(start_address
) ||
702 start_address
!= m_address
)
705 const InlineFunctionInfo
*info
= inlined_block
->GetInlinedFunctionInfo();
707 if (preferred_decl
== info
->GetDeclaration())
709 if (preferred_decl
== info
->GetCallSite())
712 inlined_block
= inlined_block
->GetInlinedParent();
718 void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from
) {
719 m_address
= swap_from
->m_address
;
720 m_should_resolve_indirect_functions
=
721 swap_from
->m_should_resolve_indirect_functions
;
722 m_is_reexported
= swap_from
->m_is_reexported
;
723 m_is_indirect
= swap_from
->m_is_indirect
;
724 m_user_expression_sp
.reset();
727 void BreakpointLocation::SetThreadIDInternal(lldb::tid_t thread_id
) {
728 if (thread_id
!= LLDB_INVALID_THREAD_ID
)
729 GetLocationOptions().SetThreadID(thread_id
);
731 // If we're resetting this to an invalid thread id, then don't make an
732 // options pointer just to do that.
733 if (m_options_up
!= nullptr)
734 m_options_up
->SetThreadID(thread_id
);