Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Breakpoint/BreakpointOptions.cpp
39587 views
1
//===-- BreakpointOptions.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 "lldb/Breakpoint/BreakpointOptions.h"
10
11
#include "lldb/Breakpoint/StoppointCallbackContext.h"
12
#include "lldb/Core/Value.h"
13
#include "lldb/Interpreter/CommandInterpreter.h"
14
#include "lldb/Interpreter/CommandReturnObject.h"
15
#include "lldb/Target/Process.h"
16
#include "lldb/Target/Target.h"
17
#include "lldb/Target/ThreadSpec.h"
18
#include "lldb/Utility/Stream.h"
19
#include "lldb/Utility/StringList.h"
20
21
#include "llvm/ADT/STLExtras.h"
22
23
using namespace lldb;
24
using namespace lldb_private;
25
26
const char
27
*BreakpointOptions::CommandData::g_option_names[static_cast<uint32_t>(
28
BreakpointOptions::CommandData::OptionNames::LastOptionName)]{
29
"UserSource", "ScriptSource", "StopOnError"};
30
31
StructuredData::ObjectSP
32
BreakpointOptions::CommandData::SerializeToStructuredData() {
33
size_t num_strings = user_source.GetSize();
34
if (num_strings == 0 && script_source.empty()) {
35
// We shouldn't serialize commands if there aren't any, return an empty sp
36
// to indicate this.
37
return StructuredData::ObjectSP();
38
}
39
40
StructuredData::DictionarySP options_dict_sp(
41
new StructuredData::Dictionary());
42
options_dict_sp->AddBooleanItem(GetKey(OptionNames::StopOnError),
43
stop_on_error);
44
45
StructuredData::ArraySP user_source_sp(new StructuredData::Array());
46
for (size_t i = 0; i < num_strings; i++) {
47
StructuredData::StringSP item_sp(
48
new StructuredData::String(user_source[i]));
49
user_source_sp->AddItem(item_sp);
50
options_dict_sp->AddItem(GetKey(OptionNames::UserSource), user_source_sp);
51
}
52
53
options_dict_sp->AddStringItem(
54
GetKey(OptionNames::Interpreter),
55
ScriptInterpreter::LanguageToString(interpreter));
56
return options_dict_sp;
57
}
58
59
std::unique_ptr<BreakpointOptions::CommandData>
60
BreakpointOptions::CommandData::CreateFromStructuredData(
61
const StructuredData::Dictionary &options_dict, Status &error) {
62
std::unique_ptr<CommandData> data_up(new CommandData());
63
64
bool success = options_dict.GetValueForKeyAsBoolean(
65
GetKey(OptionNames::StopOnError), data_up->stop_on_error);
66
67
llvm::StringRef interpreter_str;
68
ScriptLanguage interp_language;
69
success = options_dict.GetValueForKeyAsString(
70
GetKey(OptionNames::Interpreter), interpreter_str);
71
72
if (!success) {
73
error.SetErrorString("Missing command language value.");
74
return data_up;
75
}
76
77
interp_language = ScriptInterpreter::StringToLanguage(interpreter_str);
78
if (interp_language == eScriptLanguageUnknown) {
79
error.SetErrorStringWithFormatv("Unknown breakpoint command language: {0}.",
80
interpreter_str);
81
return data_up;
82
}
83
data_up->interpreter = interp_language;
84
85
StructuredData::Array *user_source;
86
success = options_dict.GetValueForKeyAsArray(GetKey(OptionNames::UserSource),
87
user_source);
88
if (success) {
89
size_t num_elems = user_source->GetSize();
90
for (size_t i = 0; i < num_elems; i++) {
91
if (std::optional<llvm::StringRef> maybe_elem_string =
92
user_source->GetItemAtIndexAsString(i))
93
data_up->user_source.AppendString(*maybe_elem_string);
94
}
95
}
96
97
return data_up;
98
}
99
100
const char *BreakpointOptions::g_option_names[(
101
size_t)BreakpointOptions::OptionNames::LastOptionName]{
102
"ConditionText", "IgnoreCount",
103
"EnabledState", "OneShotState", "AutoContinue"};
104
105
// BreakpointOptions constructor
106
BreakpointOptions::BreakpointOptions(bool all_flags_set)
107
: m_callback(nullptr), m_baton_is_command_baton(false),
108
m_callback_is_synchronous(false), m_enabled(true), m_one_shot(false),
109
m_ignore_count(0), m_condition_text_hash(0), m_inject_condition(false),
110
m_auto_continue(false), m_set_flags(0) {
111
if (all_flags_set)
112
m_set_flags.Set(~((Flags::ValueType)0));
113
}
114
115
BreakpointOptions::BreakpointOptions(const char *condition, bool enabled,
116
int32_t ignore, bool one_shot,
117
bool auto_continue)
118
: m_callback(nullptr), m_baton_is_command_baton(false),
119
m_callback_is_synchronous(false), m_enabled(enabled),
120
m_one_shot(one_shot), m_ignore_count(ignore), m_condition_text_hash(0),
121
m_inject_condition(false), m_auto_continue(auto_continue) {
122
m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot | eAutoContinue);
123
if (condition && *condition != '\0') {
124
SetCondition(condition);
125
}
126
}
127
128
// BreakpointOptions copy constructor
129
BreakpointOptions::BreakpointOptions(const BreakpointOptions &rhs)
130
: m_callback(rhs.m_callback), m_callback_baton_sp(rhs.m_callback_baton_sp),
131
m_baton_is_command_baton(rhs.m_baton_is_command_baton),
132
m_callback_is_synchronous(rhs.m_callback_is_synchronous),
133
m_enabled(rhs.m_enabled), m_one_shot(rhs.m_one_shot),
134
m_ignore_count(rhs.m_ignore_count), m_inject_condition(false),
135
m_auto_continue(rhs.m_auto_continue), m_set_flags(rhs.m_set_flags) {
136
if (rhs.m_thread_spec_up != nullptr)
137
m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);
138
m_condition_text = rhs.m_condition_text;
139
m_condition_text_hash = rhs.m_condition_text_hash;
140
}
141
142
// BreakpointOptions assignment operator
143
const BreakpointOptions &BreakpointOptions::
144
operator=(const BreakpointOptions &rhs) {
145
m_callback = rhs.m_callback;
146
m_callback_baton_sp = rhs.m_callback_baton_sp;
147
m_baton_is_command_baton = rhs.m_baton_is_command_baton;
148
m_callback_is_synchronous = rhs.m_callback_is_synchronous;
149
m_enabled = rhs.m_enabled;
150
m_one_shot = rhs.m_one_shot;
151
m_ignore_count = rhs.m_ignore_count;
152
if (rhs.m_thread_spec_up != nullptr)
153
m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);
154
m_condition_text = rhs.m_condition_text;
155
m_condition_text_hash = rhs.m_condition_text_hash;
156
m_inject_condition = rhs.m_inject_condition;
157
m_auto_continue = rhs.m_auto_continue;
158
m_set_flags = rhs.m_set_flags;
159
return *this;
160
}
161
162
void BreakpointOptions::CopyOverSetOptions(const BreakpointOptions &incoming)
163
{
164
if (incoming.m_set_flags.Test(eEnabled))
165
{
166
m_enabled = incoming.m_enabled;
167
m_set_flags.Set(eEnabled);
168
}
169
if (incoming.m_set_flags.Test(eOneShot))
170
{
171
m_one_shot = incoming.m_one_shot;
172
m_set_flags.Set(eOneShot);
173
}
174
if (incoming.m_set_flags.Test(eCallback))
175
{
176
m_callback = incoming.m_callback;
177
m_callback_baton_sp = incoming.m_callback_baton_sp;
178
m_callback_is_synchronous = incoming.m_callback_is_synchronous;
179
m_baton_is_command_baton = incoming.m_baton_is_command_baton;
180
m_set_flags.Set(eCallback);
181
}
182
if (incoming.m_set_flags.Test(eIgnoreCount))
183
{
184
m_ignore_count = incoming.m_ignore_count;
185
m_set_flags.Set(eIgnoreCount);
186
}
187
if (incoming.m_set_flags.Test(eCondition))
188
{
189
// If we're copying over an empty condition, mark it as unset.
190
if (incoming.m_condition_text.empty()) {
191
m_condition_text.clear();
192
m_condition_text_hash = 0;
193
m_set_flags.Clear(eCondition);
194
} else {
195
m_condition_text = incoming.m_condition_text;
196
m_condition_text_hash = incoming.m_condition_text_hash;
197
m_set_flags.Set(eCondition);
198
}
199
}
200
if (incoming.m_set_flags.Test(eAutoContinue))
201
{
202
m_auto_continue = incoming.m_auto_continue;
203
m_set_flags.Set(eAutoContinue);
204
}
205
if (incoming.m_set_flags.Test(eThreadSpec) && incoming.m_thread_spec_up) {
206
if (!m_thread_spec_up)
207
m_thread_spec_up =
208
std::make_unique<ThreadSpec>(*incoming.m_thread_spec_up);
209
else
210
*m_thread_spec_up = *incoming.m_thread_spec_up;
211
m_set_flags.Set(eThreadSpec);
212
}
213
}
214
215
// Destructor
216
BreakpointOptions::~BreakpointOptions() = default;
217
218
std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
219
Target &target, const StructuredData::Dictionary &options_dict,
220
Status &error) {
221
bool enabled = true;
222
bool one_shot = false;
223
bool auto_continue = false;
224
uint32_t ignore_count = 0;
225
llvm::StringRef condition_ref("");
226
Flags set_options;
227
228
const char *key = GetKey(OptionNames::EnabledState);
229
bool success;
230
if (key && options_dict.HasKey(key)) {
231
success = options_dict.GetValueForKeyAsBoolean(key, enabled);
232
if (!success) {
233
error.SetErrorStringWithFormat("%s key is not a boolean.", key);
234
return nullptr;
235
}
236
set_options.Set(eEnabled);
237
}
238
239
key = GetKey(OptionNames::OneShotState);
240
if (key && options_dict.HasKey(key)) {
241
success = options_dict.GetValueForKeyAsBoolean(key, one_shot);
242
if (!success) {
243
error.SetErrorStringWithFormat("%s key is not a boolean.", key);
244
return nullptr;
245
}
246
set_options.Set(eOneShot);
247
}
248
249
key = GetKey(OptionNames::AutoContinue);
250
if (key && options_dict.HasKey(key)) {
251
success = options_dict.GetValueForKeyAsBoolean(key, auto_continue);
252
if (!success) {
253
error.SetErrorStringWithFormat("%s key is not a boolean.", key);
254
return nullptr;
255
}
256
set_options.Set(eAutoContinue);
257
}
258
259
key = GetKey(OptionNames::IgnoreCount);
260
if (key && options_dict.HasKey(key)) {
261
success = options_dict.GetValueForKeyAsInteger(key, ignore_count);
262
if (!success) {
263
error.SetErrorStringWithFormat("%s key is not an integer.", key);
264
return nullptr;
265
}
266
set_options.Set(eIgnoreCount);
267
}
268
269
key = GetKey(OptionNames::ConditionText);
270
if (key && options_dict.HasKey(key)) {
271
success = options_dict.GetValueForKeyAsString(key, condition_ref);
272
if (!success) {
273
error.SetErrorStringWithFormat("%s key is not an string.", key);
274
return nullptr;
275
}
276
set_options.Set(eCondition);
277
}
278
279
std::unique_ptr<CommandData> cmd_data_up;
280
StructuredData::Dictionary *cmds_dict;
281
success = options_dict.GetValueForKeyAsDictionary(
282
CommandData::GetSerializationKey(), cmds_dict);
283
if (success && cmds_dict) {
284
Status cmds_error;
285
cmd_data_up = CommandData::CreateFromStructuredData(*cmds_dict, cmds_error);
286
if (cmds_error.Fail()) {
287
error.SetErrorStringWithFormat(
288
"Failed to deserialize breakpoint command options: %s.",
289
cmds_error.AsCString());
290
return nullptr;
291
}
292
}
293
294
auto bp_options = std::make_unique<BreakpointOptions>(
295
condition_ref.str().c_str(), enabled,
296
ignore_count, one_shot, auto_continue);
297
if (cmd_data_up) {
298
if (cmd_data_up->interpreter == eScriptLanguageNone)
299
bp_options->SetCommandDataCallback(cmd_data_up);
300
else {
301
ScriptInterpreter *interp = target.GetDebugger().GetScriptInterpreter();
302
if (!interp) {
303
error.SetErrorString(
304
"Can't set script commands - no script interpreter");
305
return nullptr;
306
}
307
if (interp->GetLanguage() != cmd_data_up->interpreter) {
308
error.SetErrorStringWithFormat(
309
"Current script language doesn't match breakpoint's language: %s",
310
ScriptInterpreter::LanguageToString(cmd_data_up->interpreter)
311
.c_str());
312
return nullptr;
313
}
314
Status script_error;
315
script_error =
316
interp->SetBreakpointCommandCallback(*bp_options, cmd_data_up);
317
if (script_error.Fail()) {
318
error.SetErrorStringWithFormat("Error generating script callback: %s.",
319
error.AsCString());
320
return nullptr;
321
}
322
}
323
}
324
325
StructuredData::Dictionary *thread_spec_dict;
326
success = options_dict.GetValueForKeyAsDictionary(
327
ThreadSpec::GetSerializationKey(), thread_spec_dict);
328
if (success) {
329
Status thread_spec_error;
330
std::unique_ptr<ThreadSpec> thread_spec_up =
331
ThreadSpec::CreateFromStructuredData(*thread_spec_dict,
332
thread_spec_error);
333
if (thread_spec_error.Fail()) {
334
error.SetErrorStringWithFormat(
335
"Failed to deserialize breakpoint thread spec options: %s.",
336
thread_spec_error.AsCString());
337
return nullptr;
338
}
339
bp_options->SetThreadSpec(thread_spec_up);
340
}
341
return bp_options;
342
}
343
344
StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() {
345
StructuredData::DictionarySP options_dict_sp(
346
new StructuredData::Dictionary());
347
if (m_set_flags.Test(eEnabled))
348
options_dict_sp->AddBooleanItem(GetKey(OptionNames::EnabledState),
349
m_enabled);
350
if (m_set_flags.Test(eOneShot))
351
options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState),
352
m_one_shot);
353
if (m_set_flags.Test(eAutoContinue))
354
options_dict_sp->AddBooleanItem(GetKey(OptionNames::AutoContinue),
355
m_auto_continue);
356
if (m_set_flags.Test(eIgnoreCount))
357
options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
358
m_ignore_count);
359
if (m_set_flags.Test(eCondition))
360
options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText),
361
m_condition_text);
362
363
if (m_set_flags.Test(eCallback) && m_baton_is_command_baton) {
364
auto cmd_baton =
365
std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
366
StructuredData::ObjectSP commands_sp =
367
cmd_baton->getItem()->SerializeToStructuredData();
368
if (commands_sp) {
369
options_dict_sp->AddItem(
370
BreakpointOptions::CommandData::GetSerializationKey(), commands_sp);
371
}
372
}
373
if (m_set_flags.Test(eThreadSpec) && m_thread_spec_up) {
374
StructuredData::ObjectSP thread_spec_sp =
375
m_thread_spec_up->SerializeToStructuredData();
376
options_dict_sp->AddItem(ThreadSpec::GetSerializationKey(), thread_spec_sp);
377
}
378
379
return options_dict_sp;
380
}
381
382
// Callbacks
383
void BreakpointOptions::SetCallback(BreakpointHitCallback callback,
384
const lldb::BatonSP &callback_baton_sp,
385
bool callback_is_synchronous) {
386
// FIXME: This seems unsafe. If BatonSP actually *is* a CommandBaton, but
387
// in a shared_ptr<Baton> instead of a shared_ptr<CommandBaton>, then we will
388
// set m_baton_is_command_baton to false, which is incorrect. One possible
389
// solution is to make the base Baton class provide a method such as:
390
// virtual StringRef getBatonId() const { return ""; }
391
// and have CommandBaton override this to return something unique, and then
392
// check for it here. Another option might be to make Baton using the llvm
393
// casting infrastructure, so that we could write something like:
394
// if (llvm::isa<CommandBaton>(callback_baton_sp))
395
// at relevant callsites instead of storing a boolean.
396
m_callback_is_synchronous = callback_is_synchronous;
397
m_callback = callback;
398
m_callback_baton_sp = callback_baton_sp;
399
m_baton_is_command_baton = false;
400
m_set_flags.Set(eCallback);
401
}
402
403
void BreakpointOptions::SetCallback(
404
BreakpointHitCallback callback,
405
const BreakpointOptions::CommandBatonSP &callback_baton_sp,
406
bool callback_is_synchronous) {
407
m_callback_is_synchronous = callback_is_synchronous;
408
m_callback = callback;
409
m_callback_baton_sp = callback_baton_sp;
410
m_baton_is_command_baton = true;
411
m_set_flags.Set(eCallback);
412
}
413
414
void BreakpointOptions::ClearCallback() {
415
m_callback = nullptr;
416
m_callback_is_synchronous = false;
417
m_callback_baton_sp.reset();
418
m_baton_is_command_baton = false;
419
m_set_flags.Clear(eCallback);
420
}
421
422
Baton *BreakpointOptions::GetBaton() { return m_callback_baton_sp.get(); }
423
424
const Baton *BreakpointOptions::GetBaton() const {
425
return m_callback_baton_sp.get();
426
}
427
428
bool BreakpointOptions::InvokeCallback(StoppointCallbackContext *context,
429
lldb::user_id_t break_id,
430
lldb::user_id_t break_loc_id) {
431
if (m_callback) {
432
if (context->is_synchronous == IsCallbackSynchronous()) {
433
return m_callback(m_callback_baton_sp ? m_callback_baton_sp->data()
434
: nullptr,
435
context, break_id, break_loc_id);
436
} else if (IsCallbackSynchronous()) {
437
return false;
438
}
439
}
440
return true;
441
}
442
443
bool BreakpointOptions::HasCallback() const {
444
return static_cast<bool>(m_callback);
445
}
446
447
bool BreakpointOptions::GetCommandLineCallbacks(StringList &command_list) {
448
if (!HasCallback())
449
return false;
450
if (!m_baton_is_command_baton)
451
return false;
452
453
auto cmd_baton = std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
454
CommandData *data = cmd_baton->getItem();
455
if (!data)
456
return false;
457
command_list = data->user_source;
458
return true;
459
}
460
461
void BreakpointOptions::SetCondition(const char *condition) {
462
if (!condition || condition[0] == '\0') {
463
condition = "";
464
m_set_flags.Clear(eCondition);
465
}
466
else
467
m_set_flags.Set(eCondition);
468
469
m_condition_text.assign(condition);
470
std::hash<std::string> hasher;
471
m_condition_text_hash = hasher(m_condition_text);
472
}
473
474
const char *BreakpointOptions::GetConditionText(size_t *hash) const {
475
if (!m_condition_text.empty()) {
476
if (hash)
477
*hash = m_condition_text_hash;
478
479
return m_condition_text.c_str();
480
} else {
481
return nullptr;
482
}
483
}
484
485
const ThreadSpec *BreakpointOptions::GetThreadSpecNoCreate() const {
486
return m_thread_spec_up.get();
487
}
488
489
ThreadSpec *BreakpointOptions::GetThreadSpec() {
490
if (m_thread_spec_up == nullptr) {
491
m_set_flags.Set(eThreadSpec);
492
m_thread_spec_up = std::make_unique<ThreadSpec>();
493
}
494
495
return m_thread_spec_up.get();
496
}
497
498
void BreakpointOptions::SetThreadID(lldb::tid_t thread_id) {
499
GetThreadSpec()->SetTID(thread_id);
500
m_set_flags.Set(eThreadSpec);
501
}
502
503
void BreakpointOptions::SetThreadSpec(
504
std::unique_ptr<ThreadSpec> &thread_spec_up) {
505
m_thread_spec_up = std::move(thread_spec_up);
506
m_set_flags.Set(eThreadSpec);
507
}
508
509
void BreakpointOptions::GetDescription(Stream *s,
510
lldb::DescriptionLevel level) const {
511
// Figure out if there are any options not at their default value, and only
512
// print anything if there are:
513
514
if (m_ignore_count != 0 || !m_enabled || m_one_shot || m_auto_continue ||
515
(GetThreadSpecNoCreate() != nullptr &&
516
GetThreadSpecNoCreate()->HasSpecification())) {
517
if (level == lldb::eDescriptionLevelVerbose) {
518
s->EOL();
519
s->IndentMore();
520
s->Indent();
521
s->PutCString("Breakpoint Options:\n");
522
s->IndentMore();
523
s->Indent();
524
} else
525
s->PutCString(" Options: ");
526
527
if (m_ignore_count > 0)
528
s->Printf("ignore: %d ", m_ignore_count);
529
s->Printf("%sabled ", m_enabled ? "en" : "dis");
530
531
if (m_one_shot)
532
s->Printf("one-shot ");
533
534
if (m_auto_continue)
535
s->Printf("auto-continue ");
536
537
if (m_thread_spec_up)
538
m_thread_spec_up->GetDescription(s, level);
539
540
if (level == lldb::eDescriptionLevelFull) {
541
s->IndentLess();
542
s->IndentMore();
543
}
544
}
545
546
if (m_callback_baton_sp.get()) {
547
if (level != eDescriptionLevelBrief) {
548
s->EOL();
549
m_callback_baton_sp->GetDescription(s->AsRawOstream(), level,
550
s->GetIndentLevel());
551
}
552
}
553
if (!m_condition_text.empty()) {
554
if (level != eDescriptionLevelBrief) {
555
s->EOL();
556
s->Printf("Condition: %s\n", m_condition_text.c_str());
557
}
558
}
559
}
560
561
void BreakpointOptions::CommandBaton::GetDescription(
562
llvm::raw_ostream &s, lldb::DescriptionLevel level,
563
unsigned indentation) const {
564
const CommandData *data = getItem();
565
566
if (level == eDescriptionLevelBrief) {
567
s << ", commands = "
568
<< ((data && data->user_source.GetSize() > 0) ? "yes" : "no");
569
return;
570
}
571
572
indentation += 2;
573
s.indent(indentation);
574
s << "Breakpoint commands";
575
if (data->interpreter != eScriptLanguageNone)
576
s << llvm::formatv(" ({0}):\n",
577
ScriptInterpreter::LanguageToString(data->interpreter));
578
else
579
s << ":\n";
580
581
indentation += 2;
582
if (data && data->user_source.GetSize() > 0) {
583
for (llvm::StringRef str : data->user_source) {
584
s.indent(indentation);
585
s << str << "\n";
586
}
587
} else
588
s << "No commands.\n";
589
}
590
591
void BreakpointOptions::SetCommandDataCallback(
592
std::unique_ptr<CommandData> &cmd_data) {
593
cmd_data->interpreter = eScriptLanguageNone;
594
auto baton_sp = std::make_shared<CommandBaton>(std::move(cmd_data));
595
SetCallback(BreakpointOptions::BreakpointOptionsCallbackFunction, baton_sp);
596
m_set_flags.Set(eCallback);
597
}
598
599
bool BreakpointOptions::BreakpointOptionsCallbackFunction(
600
void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
601
lldb::user_id_t break_loc_id) {
602
bool ret_value = true;
603
if (baton == nullptr)
604
return true;
605
606
CommandData *data = (CommandData *)baton;
607
StringList &commands = data->user_source;
608
609
if (commands.GetSize() > 0) {
610
ExecutionContext exe_ctx(context->exe_ctx_ref);
611
Target *target = exe_ctx.GetTargetPtr();
612
if (target) {
613
Debugger &debugger = target->GetDebugger();
614
CommandReturnObject result(debugger.GetUseColor());
615
616
// Rig up the results secondary output stream to the debugger's, so the
617
// output will come out synchronously if the debugger is set up that way.
618
StreamSP output_stream(debugger.GetAsyncOutputStream());
619
StreamSP error_stream(debugger.GetAsyncErrorStream());
620
result.SetImmediateOutputStream(output_stream);
621
result.SetImmediateErrorStream(error_stream);
622
623
CommandInterpreterRunOptions options;
624
options.SetStopOnContinue(true);
625
options.SetStopOnError(data->stop_on_error);
626
options.SetEchoCommands(true);
627
options.SetPrintResults(true);
628
options.SetPrintErrors(true);
629
options.SetAddToHistory(false);
630
631
debugger.GetCommandInterpreter().HandleCommands(commands, exe_ctx,
632
options, result);
633
result.GetImmediateOutputStream()->Flush();
634
result.GetImmediateErrorStream()->Flush();
635
}
636
}
637
return ret_value;
638
}
639
640
void BreakpointOptions::Clear()
641
{
642
m_set_flags.Clear();
643
m_thread_spec_up.release();
644
m_one_shot = false;
645
m_ignore_count = 0;
646
m_auto_continue = false;
647
m_callback = nullptr;
648
m_callback_baton_sp.reset();
649
m_baton_is_command_baton = false;
650
m_callback_is_synchronous = false;
651
m_enabled = false;
652
m_condition_text.clear();
653
}
654
655