1 //===-- StackFrameRecognizer.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/Target/StackFrameRecognizer.h"
10 #include "lldb/Core/Module.h"
11 #include "lldb/Interpreter/ScriptInterpreter.h"
12 #include "lldb/Symbol/Symbol.h"
13 #include "lldb/Target/StackFrame.h"
14 #include "lldb/Utility/RegularExpression.h"
17 using namespace lldb_private
;
19 class ScriptedRecognizedStackFrame
: public RecognizedStackFrame
{
21 ScriptedRecognizedStackFrame(ValueObjectListSP args
) {
26 ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer(
27 ScriptInterpreter
*interpreter
, const char *pclass
)
28 : m_interpreter(interpreter
), m_python_class(pclass
) {
30 m_interpreter
->CreateFrameRecognizer(m_python_class
.c_str());
33 RecognizedStackFrameSP
34 ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame
) {
35 if (!m_python_object_sp
|| !m_interpreter
)
36 return RecognizedStackFrameSP();
38 ValueObjectListSP args
=
39 m_interpreter
->GetRecognizedArguments(m_python_object_sp
, frame
);
40 auto args_synthesized
= ValueObjectListSP(new ValueObjectList());
41 for (const auto &o
: args
->GetObjects()) {
42 args_synthesized
->Append(ValueObjectRecognizerSynthesizedValue::Create(
43 *o
, eValueTypeVariableArgument
));
46 return RecognizedStackFrameSP(
47 new ScriptedRecognizedStackFrame(args_synthesized
));
50 void StackFrameRecognizerManager::AddRecognizer(
51 StackFrameRecognizerSP recognizer
, ConstString module
,
52 llvm::ArrayRef
<ConstString
> symbols
, bool first_instruction_only
) {
53 m_recognizers
.push_front({(uint32_t)m_recognizers
.size(), recognizer
, false,
54 module
, RegularExpressionSP(), symbols
,
55 RegularExpressionSP(), first_instruction_only
});
58 void StackFrameRecognizerManager::AddRecognizer(
59 StackFrameRecognizerSP recognizer
, RegularExpressionSP module
,
60 RegularExpressionSP symbol
, bool first_instruction_only
) {
61 m_recognizers
.push_front({(uint32_t)m_recognizers
.size(), recognizer
, true,
62 ConstString(), module
, std::vector
<ConstString
>(),
63 symbol
, first_instruction_only
});
66 void StackFrameRecognizerManager::ForEach(
67 const std::function
<void(uint32_t, std::string
, std::string
,
68 llvm::ArrayRef
<ConstString
>, bool)> &callback
) {
69 for (auto entry
: m_recognizers
) {
70 if (entry
.is_regexp
) {
71 std::string module_name
;
72 std::string symbol_name
;
74 if (entry
.module_regexp
)
75 module_name
= entry
.module_regexp
->GetText().str();
76 if (entry
.symbol_regexp
)
77 symbol_name
= entry
.symbol_regexp
->GetText().str();
79 callback(entry
.recognizer_id
, entry
.recognizer
->GetName(), module_name
,
80 llvm::makeArrayRef(ConstString(symbol_name
)), true);
83 callback(entry
.recognizer_id
, entry
.recognizer
->GetName(),
84 entry
.module
.GetCString(), entry
.symbols
, false);
89 bool StackFrameRecognizerManager::RemoveRecognizerWithID(
90 uint32_t recognizer_id
) {
91 if (recognizer_id
>= m_recognizers
.size())
94 llvm::find_if(m_recognizers
, [recognizer_id
](const RegisteredEntry
&e
) {
95 return e
.recognizer_id
== recognizer_id
;
97 if (found
== m_recognizers
.end())
99 m_recognizers
.erase(found
);
103 void StackFrameRecognizerManager::RemoveAllRecognizers() {
104 m_recognizers
.clear();
107 StackFrameRecognizerSP
108 StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame
) {
109 const SymbolContext
&symctx
= frame
->GetSymbolContext(
110 eSymbolContextModule
| eSymbolContextFunction
| eSymbolContextSymbol
);
111 ConstString function_name
= symctx
.GetFunctionName();
112 ModuleSP module_sp
= symctx
.module_sp
;
114 return StackFrameRecognizerSP();
115 ConstString module_name
= module_sp
->GetFileSpec().GetFilename();
116 Symbol
*symbol
= symctx
.symbol
;
118 return StackFrameRecognizerSP();
119 Address start_addr
= symbol
->GetAddress();
120 Address current_addr
= frame
->GetFrameCodeAddress();
122 for (auto entry
: m_recognizers
) {
124 if (entry
.module
!= module_name
)
127 if (entry
.module_regexp
)
128 if (!entry
.module_regexp
->Execute(module_name
.GetStringRef()))
131 if (!entry
.symbols
.empty())
132 if (!llvm::is_contained(entry
.symbols
, function_name
))
135 if (entry
.symbol_regexp
)
136 if (!entry
.symbol_regexp
->Execute(function_name
.GetStringRef()))
139 if (entry
.first_instruction_only
)
140 if (start_addr
!= current_addr
)
143 return entry
.recognizer
;
145 return StackFrameRecognizerSP();
148 RecognizedStackFrameSP
149 StackFrameRecognizerManager::RecognizeFrame(StackFrameSP frame
) {
150 auto recognizer
= GetRecognizerForFrame(frame
);
152 return RecognizedStackFrameSP();
153 return recognizer
->RecognizeFrame(frame
);