This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG54c496dad6f2: [lldb] Allow to register frame recognizers
applied beyond the first instruction (authored by malor, committed by mib).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D108510/new/
https://reviews.llvm.org/D108510
Files:
lldb/source/Commands/CommandObjectFrame.cpp
lldb/source/Commands/Options.td
lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py
Index: lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py
===================================================================
--- lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py
+++ lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py
@@ -205,6 +205,64 @@
self.expect("frame recognizer info 0",
substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer'])
+ @skipUnlessDarwin
+ def test_frame_recognizer_not_only_first_instruction(self):
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+
+ # Clear internal & plugins recognizers that get initialized at launch.
+ self.runCmd("frame recognizer clear")
+
+ self.runCmd("command script import " + os.path.join(self.getSourceDir(), "recognizer.py"))
+
+ self.expect("frame recognizer list",
+ substrs=['no matching results found.'])
+
+ # Create a target.
+ target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "foo",
+ exe_name = exe)
+
+ # Move the PC one instruction further.
+ self.runCmd("next")
+
+ # Add a frame recognizer in that target.
+ self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar")
+
+ # It's not applied to foo(), because frame's PC is not at the first instruction of the function.
+ self.expect("frame recognizer info 0",
+ substrs=['frame 0 not recognized by any recognizer'])
+
+ # Add a frame recognizer with --first-instruction-only=true.
+ self.runCmd("frame recognizer clear")
+
+ self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar --first-instruction-only=true")
+
+ # It's not applied to foo(), because frame's PC is not at the first instruction of the function.
+ self.expect("frame recognizer info 0",
+ substrs=['frame 0 not recognized by any recognizer'])
+
+ # Now add a frame recognizer with --first-instruction-only=false.
+ self.runCmd("frame recognizer clear")
+
+ self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar --first-instruction-only=false")
+
+ # This time it should recognize the frame.
+ self.expect("frame recognizer info 0",
+ substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer'])
+
+ opts = lldb.SBVariablesOptions()
+ opts.SetIncludeRecognizedArguments(True)
+ frame = thread.GetSelectedFrame()
+ variables = frame.GetVariables(opts)
+
+ self.assertEqual(variables.GetSize(), 2)
+ self.assertEqual(variables.GetValueAtIndex(0).name, "a")
+ self.assertEqual(variables.GetValueAtIndex(0).signed, 42)
+ self.assertEqual(variables.GetValueAtIndex(0).GetValueType(), lldb.eValueTypeVariableArgument)
+ self.assertEqual(variables.GetValueAtIndex(1).name, "b")
+ self.assertEqual(variables.GetValueAtIndex(1).signed, 56)
+ self.assertEqual(variables.GetValueAtIndex(1).GetValueType(), lldb.eValueTypeVariableArgument)
+
@no_debug_info_test
def test_frame_recognizer_delete_invalid_arg(self):
self.expect("frame recognizer delete a", error=True,
@@ -226,3 +284,12 @@
substrs=["error: '-1' is not a valid frame index."])
self.expect("frame recognizer info 4294967297", error=True,
substrs=["error: '4294967297' is not a valid frame index."])
+
+ @no_debug_info_test
+ def test_frame_recognizer_add_invalid_arg(self):
+ self.expect("frame recognizer add -f", error=True,
+ substrs=["error: last option requires an argument"])
+ self.expect("frame recognizer add -f -1", error=True,
+ substrs=["error: invalid boolean value '-1' passed for -f option"])
+ self.expect("frame recognizer add -f foo", error=True,
+ substrs=["error: invalid boolean value 'foo' passed for -f option"])
Index: lldb/source/Commands/Options.td
===================================================================
--- lldb/source/Commands/Options.td
+++ lldb/source/Commands/Options.td
@@ -404,6 +404,13 @@
Desc<"Give the name of a Python class to use for this frame recognizer.">;
def frame_recognizer_regex : Option<"regex", "x">,
Desc<"Function name and module name are actually regular expressions.">;
+ def frame_recognizer_first_instruction_only : Option<"first-instruction-only", "f">, Arg<"Boolean">,
+ Desc<"If true, only apply this recognizer to frames whose PC currently points to the "
+ "first instruction of the specified function. If false, the recognizer "
+ "will always be applied, regardless of the current position within the specified function. The "
+ "implementor should keep in mind that some features, e.g. accessing function argument "
+ "values via $arg<N>, are not guaranteed to work reliably in this case, so extra care must "
+ "be taken to make the recognizer operate correctly. Defaults to true.">;
}
let Command = "history" in {
Index: lldb/source/Commands/CommandObjectFrame.cpp
===================================================================
--- lldb/source/Commands/CommandObjectFrame.cpp
+++ lldb/source/Commands/CommandObjectFrame.cpp
@@ -14,6 +14,7 @@
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionGroupVariable.h"
@@ -739,6 +740,17 @@
const int short_option = m_getopt_table[option_idx].val;
switch (short_option) {
+ case 'f': {
+ bool value, success;
+ value = OptionArgParser::ToBoolean(option_arg, true, &success);
+ if (success) {
+ m_first_instruction_only = value;
+ } else {
+ error.SetErrorStringWithFormat(
+ "invalid boolean value '%s' passed for -f option",
+ option_arg.str().c_str());
+ }
+ } break;
case 'l':
m_class_name = std::string(option_arg);
break;
@@ -763,6 +775,7 @@
m_symbols.clear();
m_class_name = "";
m_regex = false;
+ m_first_instruction_only = true;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -774,6 +787,7 @@
std::string m_module;
std::vector<std::string> m_symbols;
bool m_regex;
+ bool m_first_instruction_only;
};
CommandOptions m_options;
@@ -883,13 +897,13 @@
auto func =
RegularExpressionSP(new RegularExpression(m_options.m_symbols.front()));
GetSelectedOrDummyTarget().GetFrameRecognizerManager().AddRecognizer(
- recognizer_sp, module, func);
+ recognizer_sp, module, func, m_options.m_first_instruction_only);
} else {
auto module = ConstString(m_options.m_module);
std::vector<ConstString> symbols(m_options.m_symbols.begin(),
m_options.m_symbols.end());
GetSelectedOrDummyTarget().GetFrameRecognizerManager().AddRecognizer(
- recognizer_sp, module, symbols);
+ recognizer_sp, module, symbols, m_options.m_first_instruction_only);
}
#endif
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits