Skip to content

Commit 53b3f15

Browse files
committed
[lldb] Add support for specifying language when setting watchpoint by expression
This is useful in contexts where you have multiple languages in play: You may be stopped in a frame for language A, but want to set a watchpoint with an expression using language B. The current way to do this is to use the setting `target.language` while setting the watchpoint and unset it after the watchpoint is set, but that's kind of clunky and somewhat error-prone. This should add a better way to do this. rdar://108202559 Differential Revision: https://reviews.llvm.org/D149111 (cherry picked from commit c997acb)
1 parent c2ef45f commit 53b3f15

File tree

5 files changed

+61
-3
lines changed

5 files changed

+61
-3
lines changed

lldb/include/lldb/Interpreter/OptionGroupWatchpoint.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class OptionGroupWatchpoint : public OptionGroup {
4343
WatchType watch_type;
4444
uint32_t watch_size;
4545
bool watch_type_specified;
46+
lldb::LanguageType language_type;
4647

4748
private:
4849
OptionGroupWatchpoint(const OptionGroupWatchpoint &) = delete;

lldb/source/Commands/CommandObjectWatchpoint.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -835,8 +835,7 @@ corresponding to the byte size of the data type.");
835835
m_arguments.push_back(arg);
836836

837837
// Absorb the '-w' and '-s' options into our option group.
838-
m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
839-
LLDB_OPT_SET_1);
838+
m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_1, LLDB_OPT_SET_1);
840839
m_option_group.Finalize();
841840
}
842841

@@ -990,6 +989,7 @@ class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
990989
: CommandObjectRaw(
991990
interpreter, "watchpoint set expression",
992991
"Set a watchpoint on an address by supplying an expression. "
992+
"Use the '-l' option to specify the language of the expression. "
993993
"Use the '-w' option to specify the type of watchpoint and "
994994
"the '-s' option to specify the byte size to watch for. "
995995
"If no '-w' option is specified, it defaults to write. "
@@ -1083,6 +1083,8 @@ class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
10831083
options.SetKeepInMemory(false);
10841084
options.SetTryAllThreads(true);
10851085
options.SetTimeout(llvm::None);
1086+
if (m_option_watchpoint.language_type != eLanguageTypeUnknown)
1087+
options.SetLanguage(m_option_watchpoint.language_type);
10861088

10871089
ExpressionResults expr_result =
10881090
target->EvaluateExpression(expr, frame, valobj_sp, options);

lldb/source/Interpreter/OptionGroupWatchpoint.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "lldb/Host/OptionParser.h"
1212
#include "lldb/Interpreter/OptionArgParser.h"
13+
#include "lldb/Target/Language.h"
1314
#include "lldb/lldb-enumerations.h"
1415

1516
using namespace lldb;
@@ -62,7 +63,17 @@ static constexpr OptionDefinition g_option_table[] = {
6263
"Specify the type of watching to perform."},
6364
{LLDB_OPT_SET_1, false, "size", 's', OptionParser::eRequiredArgument,
6465
nullptr, OptionEnumValues(g_watch_size), 0, eArgTypeByteSize,
65-
"Number of bytes to use to watch a region."}};
66+
"Number of bytes to use to watch a region."},
67+
{LLDB_OPT_SET_2,
68+
false,
69+
"language",
70+
'l',
71+
OptionParser::eRequiredArgument,
72+
nullptr,
73+
{},
74+
0,
75+
eArgTypeLanguage,
76+
"Language of expression to run"}};
6677

6778
bool OptionGroupWatchpoint::IsWatchSizeSupported(uint32_t watch_size) {
6879
for (const auto& size : g_watch_size) {
@@ -81,6 +92,18 @@ OptionGroupWatchpoint::SetOptionValue(uint32_t option_idx,
8192
Status error;
8293
const int short_option = g_option_table[option_idx].short_option;
8394
switch (short_option) {
95+
case 'l': {
96+
language_type = Language::GetLanguageTypeFromString(option_arg);
97+
if (language_type == eLanguageTypeUnknown) {
98+
StreamString sstr;
99+
sstr.Printf("Unknown language type: '%s' for expression. List of "
100+
"supported languages:\n",
101+
option_arg.str().c_str());
102+
Language::PrintSupportedLanguagesForExpressions(sstr, " ", "\n");
103+
error.SetErrorString(sstr.GetString());
104+
}
105+
break;
106+
}
84107
case 'w': {
85108
WatchType tmp_watch_type;
86109
tmp_watch_type = (WatchType)OptionArgParser::ToOptionEnum(
@@ -108,6 +131,7 @@ void OptionGroupWatchpoint::OptionParsingStarting(
108131
watch_type_specified = false;
109132
watch_type = eWatchInvalid;
110133
watch_size = 0;
134+
language_type = eLanguageTypeUnknown;
111135
}
112136

113137
llvm::ArrayRef<OptionDefinition> OptionGroupWatchpoint::GetDefinitions() {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# RUN: %clangxx_host %p/Inputs/languages.cpp -g -o %t.out
2+
# RUN: %lldb -b -o 'settings set interpreter.stop-command-source-on-error false' -s %s %t.out 2>&1 | FileCheck %s
3+
4+
settings show interpreter.stop-command-source-on-error
5+
# CHECK: interpreter.stop-command-source-on-error (boolean) = false
6+
7+
b main
8+
run
9+
# CHECK: stopped
10+
# CHECK-NEXT: stop reason = breakpoint
11+
12+
watchpoint set expression -- &g_foo
13+
# CHECK: Watchpoint created:
14+
15+
watchpoint set expression -l c++ -- &g_bar
16+
# CHECK: Watchpoint created:
17+
18+
watchpoint set expression -l fake -- &g_baz
19+
# CHECK: Unknown language type: 'fake' for expression. List of supported languages:
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <cstdint>
2+
#include <iostream>
3+
4+
uint64_t g_foo = 5;
5+
uint64_t g_bar = 6;
6+
uint64_t g_baz = 7;
7+
8+
int main() {
9+
int val = 8;
10+
printf("Hello world! %d\n", val);
11+
return 0;
12+
}

0 commit comments

Comments
 (0)