kubamracek created this revision. kubamracek added reviewers: jingham, jasonmolenda. Herald added a subscriber: mgorny.
This is following on the discussion and goals of https://reviews.llvm.org/D43886. The patch introduces a concept of "frame recognizer" and "recognized frame". This should be an extensible mechanism that retrieves information about special frames based on ABI, arguments or other special properties of that frame, even without source code. A few examples where that could be useful could be 1) objc_exception_throw, where we'd like to get the current exception, 2) terminate_with_reason and extracting the current terminate string This should address the comments from Jim from https://reviews.llvm.org/D43886: The results from the recognizer should be generic (we now return a ValueObjectList that represent recognized arguments), and the frame recognizers are extensible and we could create a Python interface for those and register Python-based recognizers via StackFrameRecognizerManager. https://reviews.llvm.org/D44603 Files: include/lldb/Target/StackFrame.h include/lldb/Target/StackFrameRecognizer.h include/lldb/lldb-forward.h lldb.xcodeproj/project.pbxproj source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCStackFrameRecognizer.cpp source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCStackFrameRecognizer.h source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt source/Target/CMakeLists.txt source/Target/StackFrame.cpp source/Target/StackFrameRecognizer.cpp
Index: source/Target/StackFrameRecognizer.cpp =================================================================== --- /dev/null +++ source/Target/StackFrameRecognizer.cpp @@ -0,0 +1,111 @@ +//===-- StackFrameRecognizer.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +#include <vector> +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Module.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/StackFrameRecognizer.h" +#include "lldb/Utility/RegularExpression.h" + +using namespace lldb; +using namespace lldb_private; + +class StackFrameRecognizerManagerImpl { +public: + void AddRecognizer(StackFrameRecognizerSP recognizer, ConstString &module, + ConstString &symbol, bool first_instruction_only) { + m_recognizers.push_back({recognizer, module, RegularExpressionSP(), symbol, + RegularExpressionSP(), first_instruction_only}); + } + + void AddRecognizer(StackFrameRecognizerSP recognizer, + RegularExpressionSP module, RegularExpressionSP symbol, + bool first_instruction_only) { + m_recognizers.push_back({recognizer, ConstString(), module, ConstString(), + symbol, first_instruction_only}); + } + + RecognizedStackFrameSP RecognizeFrame(StackFrameSP frame) { + const SymbolContext &symctx = + frame->GetSymbolContext(eSymbolContextModule | eSymbolContextFunction); + ConstString function_name = symctx.GetFunctionName(); + ConstString module_name = symctx.module_sp->GetFileSpec().GetFilename(); + Address start_addr = symctx.symbol->GetAddress(); + Address current_addr = frame->GetFrameCodeAddress(); + + for (auto entry : m_recognizers) { + if (entry.module) + if (entry.module != module_name) + continue; + + if (entry.module_regexp) + if (!entry.module_regexp->Execute(module_name.GetStringRef())) + continue; + + if (entry.symbol) + if (entry.symbol != function_name) + continue; + + if (entry.symbol_regexp) + if (!entry.symbol_regexp->Execute(function_name.GetStringRef())) + continue; + + if (entry.first_instruction_only) + if (start_addr != current_addr) + continue; + + auto recognized_frame = entry.recognizer->RecognizeFrame(frame); + if (recognized_frame) + return recognized_frame; + } + return RecognizedStackFrameSP(); + } + +private: + struct RegisteredEntry { + StackFrameRecognizerSP recognizer; + ConstString module; + RegularExpressionSP module_regexp; + ConstString symbol; + RegularExpressionSP symbol_regexp; + bool first_instruction_only; + }; + + std::vector<RegisteredEntry> m_recognizers; +}; + +StackFrameRecognizerManagerImpl &GetStackFrameRecognizerManagerImpl() { + static StackFrameRecognizerManagerImpl instance = + StackFrameRecognizerManagerImpl(); + return instance; +} + +void StackFrameRecognizerManager::AddRecognizer( + StackFrameRecognizerSP recognizer, ConstString &module, ConstString &symbol, + bool first_instruction_only) { + GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol, + first_instruction_only); +} + +void StackFrameRecognizerManager::AddRecognizer( + StackFrameRecognizerSP recognizer, RegularExpressionSP module, + RegularExpressionSP symbol, bool first_instruction_only) { + GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol, + first_instruction_only); +} + +RecognizedStackFrameSP +StackFrameRecognizerManager::RecognizeFrame(StackFrameSP frame) { + return GetStackFrameRecognizerManagerImpl().RecognizeFrame(frame); +} Index: source/Target/StackFrame.cpp =================================================================== --- source/Target/StackFrame.cpp +++ source/Target/StackFrame.cpp @@ -32,6 +32,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrameRecognizer.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" @@ -1918,3 +1919,12 @@ } return true; } + +RecognizedStackFrameSP StackFrame::GetRecognizedFrame() { + if (!m_recognized) { + m_recognized_frame = + StackFrameRecognizerManager::RecognizeFrame(CalculateStackFrame()); + m_recognized = true; + } + return m_recognized_frame; +} Index: source/Target/CMakeLists.txt =================================================================== --- source/Target/CMakeLists.txt +++ source/Target/CMakeLists.txt @@ -30,6 +30,7 @@ SectionLoadList.cpp StackFrame.cpp StackFrameList.cpp + StackFrameRecognizer.cpp StackID.cpp StopInfo.cpp StructuredDataPlugin.cpp Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt @@ -2,6 +2,7 @@ AppleObjCRuntime.cpp AppleObjCRuntimeV1.cpp AppleObjCRuntimeV2.cpp + AppleObjCStackFrameRecognizer.cpp AppleObjCTrampolineHandler.cpp AppleObjCDeclVendor.cpp AppleThreadPlanStepThroughObjCTrampoline.cpp Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCStackFrameRecognizer.h =================================================================== --- /dev/null +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCStackFrameRecognizer.h @@ -0,0 +1,28 @@ +//===-- AppleObjCStackFrameRecognizer.h -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_AppleObjCStackFrameRecognizer_h_ +#define lldb_AppleObjCStackFrameRecognizer_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/StackFrameRecognizer.h" + +namespace lldb_private { + +class AppleObjCStackFrameRecognizer : public StackFrameRecognizer { + public: + static void Initialize(); +}; + +} // namespace lldb_private + +#endif // lldb_AppleObjCStackFrameRecognizer_h_ Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCStackFrameRecognizer.cpp =================================================================== --- /dev/null +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCStackFrameRecognizer.cpp @@ -0,0 +1,75 @@ +//===-- AppleObjCStackFrameRecognizer.cpp ------------------------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "AppleObjCStackFrameRecognizer.h" +#include "lldb/Core/Module.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/ABI.h" +#include "lldb/Target/StackFrameRecognizer.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +class DarwinObjCExceptionRecognizedStackFrame : public RecognizedStackFrame { + public: + DarwinObjCExceptionRecognizedStackFrame(StackFrameSP frame_sp) { + ThreadSP thread_sp = frame_sp->GetThread(); + ProcessSP process_sp = thread_sp->GetProcess(); + + const lldb::ABISP &abi = process_sp->GetABI(); + if (!abi) return; + + CompilerType voidstar = process_sp->GetTarget() + .GetScratchClangASTContext() + ->GetBasicType(lldb::eBasicTypeVoid) + .GetPointerType(); + + ValueList args; + Value input_value; + input_value.SetCompilerType(voidstar); + args.PushValue(input_value); + + if (!abi->GetArgumentValues(*thread_sp, args)) return; + + addr_t exception_addr = args.GetValueAtIndex(0)->GetScalar().ULongLong(); + + lldb_private::formatters::InferiorSizedWord exception_isw(exception_addr, + *process_sp); + + m_arguments = ValueObjectListSP(new ValueObjectList()); + auto exception = ValueObject::CreateValueObjectFromData( + "exception", exception_isw.GetAsData(process_sp->GetByteOrder()), + *frame_sp, voidstar); + exception = exception->GetDynamicValue(eDynamicDontRunTarget); + m_arguments->Append(exception); + } +}; + +class DarwinFrameRecognizer : public StackFrameRecognizer { + RecognizedStackFrameSP RecognizeFrame(StackFrameSP frame) { + return RecognizedStackFrameSP( + new DarwinObjCExceptionRecognizedStackFrame(frame)); + } +}; + +void AppleObjCStackFrameRecognizer::Initialize() { + static llvm::once_flag g_once_flag; + llvm::call_once(g_once_flag, []() { + static ConstString libobjc("libobjc.A.dylib"); + static ConstString objc_exception_throw("objc_exception_throw"); + StackFrameRecognizerManager::AddRecognizer(StackFrameRecognizerSP( + new DarwinFrameRecognizer()), libobjc, objc_exception_throw); + }); +} Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -59,6 +59,7 @@ #include "AppleObjCClassDescriptorV2.h" #include "AppleObjCDeclVendor.h" #include "AppleObjCRuntimeV2.h" +#include "AppleObjCStackFrameRecognizer.h" #include "AppleObjCTrampolineHandler.h" #include "AppleObjCTypeEncodingParser.h" @@ -776,6 +777,8 @@ [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP { return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter)); }); + + AppleObjCStackFrameRecognizer::Initialize(); } void AppleObjCRuntimeV2::Terminate() { Index: lldb.xcodeproj/project.pbxproj =================================================================== --- lldb.xcodeproj/project.pbxproj +++ lldb.xcodeproj/project.pbxproj @@ -785,6 +785,8 @@ 8CF02AE919DCC01900B14BE0 /* InstrumentationRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF02ADF19DCBF3B00B14BE0 /* InstrumentationRuntime.cpp */; }; 8CF02AEA19DCC02100B14BE0 /* ASanRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF02AE519DCBF8400B14BE0 /* ASanRuntime.cpp */; }; 8CF02AEF19DD16B100B14BE0 /* InstrumentationRuntimeStopInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF02AED19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.cpp */; }; + 8CF46A6220522A9800423DDF /* StackFrameRecognizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF46A6120522A9000423DDF /* StackFrameRecognizer.cpp */; }; + 8CF46A652052451800423DDF /* AppleObjCStackFrameRecognizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF46A642052447D00423DDF /* AppleObjCStackFrameRecognizer.cpp */; }; 9404957A1BEC497E00926025 /* NSError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940495781BEC497E00926025 /* NSError.cpp */; }; 9404957B1BEC497E00926025 /* NSException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940495791BEC497E00926025 /* NSException.cpp */; }; 94094C6B163B6F840083A547 /* ValueObjectCast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94094C69163B6CD90083A547 /* ValueObjectCast.cpp */; }; @@ -2700,6 +2702,10 @@ 8CF02AE619DCBF8400B14BE0 /* ASanRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASanRuntime.h; sourceTree = "<group>"; }; 8CF02AED19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InstrumentationRuntimeStopInfo.cpp; path = source/Target/InstrumentationRuntimeStopInfo.cpp; sourceTree = "<group>"; }; 8CF02AEE19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InstrumentationRuntimeStopInfo.h; path = include/lldb/Target/InstrumentationRuntimeStopInfo.h; sourceTree = "<group>"; }; + 8CF46A6120522A9000423DDF /* StackFrameRecognizer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = StackFrameRecognizer.cpp; path = source/Target/StackFrameRecognizer.cpp; sourceTree = "<group>"; }; + 8CF46A632052447D00423DDF /* AppleObjCStackFrameRecognizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleObjCStackFrameRecognizer.h; sourceTree = "<group>"; }; + 8CF46A642052447D00423DDF /* AppleObjCStackFrameRecognizer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AppleObjCStackFrameRecognizer.cpp; sourceTree = "<group>"; }; + 8CFDB67920467B390052B399 /* StackFrameRecognizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StackFrameRecognizer.h; path = include/lldb/Target/StackFrameRecognizer.h; sourceTree = "<group>"; }; 94005E0313F438DF001EF42D /* python-wrapper.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-wrapper.swig"; sourceTree = "<group>"; }; 94005E0513F45A1B001EF42D /* embedded_interpreter.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = embedded_interpreter.py; path = source/Interpreter/embedded_interpreter.py; sourceTree = "<group>"; }; 940495781BEC497E00926025 /* NSError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSError.cpp; path = Language/ObjC/NSError.cpp; sourceTree = "<group>"; }; @@ -5413,6 +5419,8 @@ 26BC7DF210F1B81A00F91463 /* ExecutionContext.h */, 26BC7F3510F1B90C00F91463 /* ExecutionContext.cpp */, 26DAFD9711529BC7005A394E /* ExecutionContextScope.h */, + 8CFDB67920467B390052B399 /* StackFrameRecognizer.h */, + 8CF46A6120522A9000423DDF /* StackFrameRecognizer.cpp */, 26BC179B18C7F2CB00D2196D /* JITLoader.h */, 26BC179718C7F2B300D2196D /* JITLoader.cpp */, 26BC179C18C7F2CB00D2196D /* JITLoaderList.h */, @@ -6020,6 +6028,8 @@ 4CCA644513B40B82003BDF98 /* AppleObjCRuntimeV1.h */, 4CCA644613B40B82003BDF98 /* AppleObjCRuntimeV2.cpp */, 4CCA644713B40B82003BDF98 /* AppleObjCRuntimeV2.h */, + 8CF46A642052447D00423DDF /* AppleObjCStackFrameRecognizer.cpp */, + 8CF46A632052447D00423DDF /* AppleObjCStackFrameRecognizer.h */, 4CCA644813B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp */, 4CCA644913B40B82003BDF98 /* AppleObjCTrampolineHandler.h */, 94CD7D0A19A3FBC300908B7C /* AppleObjCTypeEncodingParser.h */, @@ -7431,6 +7441,7 @@ files = ( 33E5E8471A674FB60024ED68 /* StringConvert.cpp in Sources */, 2689FFDA13353D9D00698AC0 /* lldb.cpp in Sources */, + 8CF46A652052451800423DDF /* AppleObjCStackFrameRecognizer.cpp in Sources */, 4C0083401B9F9BA900D5CF24 /* UtilityFunction.cpp in Sources */, AF415AE71D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp in Sources */, 26474CCD18D0CB5B0073DEBA /* RegisterContextPOSIX_x86.cpp in Sources */, @@ -7687,6 +7698,7 @@ 2689009813353E4200698AC0 /* ELFHeader.cpp in Sources */, 2689009913353E4200698AC0 /* ObjectFileELF.cpp in Sources */, 2689009A13353E4200698AC0 /* ObjectFileMachO.cpp in Sources */, + 8CF46A6220522A9800423DDF /* StackFrameRecognizer.cpp in Sources */, 2689009B13353E4200698AC0 /* PlatformMacOSX.cpp in Sources */, 2689009C13353E4200698AC0 /* PlatformRemoteiOS.cpp in Sources */, 2689009D13353E4200698AC0 /* GDBRemoteCommunication.cpp in Sources */, Index: include/lldb/lldb-forward.h =================================================================== --- include/lldb/lldb-forward.h +++ include/lldb/lldb-forward.h @@ -183,6 +183,7 @@ class ProcessLaunchInfo; class Property; struct PropertyDefinition; +class RecognizedStackFrame; class RegisterCheckpoint; class RegisterContext; class RegisterLocation; @@ -206,6 +207,8 @@ class StackFrame; class StackFrameImpl; class StackFrameList; +class StackFrameRecognizer; +class StackFrameRecognizerManager; class StackID; class StopInfo; class Stoppoint; @@ -412,6 +415,8 @@ typedef std::weak_ptr<lldb_private::Queue> QueueWP; typedef std::shared_ptr<lldb_private::QueueItem> QueueItemSP; typedef std::shared_ptr<lldb_private::REPL> REPLSP; +typedef std::shared_ptr<lldb_private::RecognizedStackFrame> + RecognizedStackFrameSP; typedef std::shared_ptr<lldb_private::ScriptSummaryFormat> ScriptSummaryFormatSP; typedef std::shared_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterSP; @@ -427,6 +432,8 @@ typedef std::unique_ptr<lldb_private::StackFrame> StackFrameUP; typedef std::weak_ptr<lldb_private::StackFrame> StackFrameWP; typedef std::shared_ptr<lldb_private::StackFrameList> StackFrameListSP; +typedef std::shared_ptr<lldb_private::StackFrameRecognizer> + StackFrameRecognizerSP; typedef std::shared_ptr<lldb_private::StopInfo> StopInfoSP; typedef std::shared_ptr<lldb_private::StoppointLocation> StoppointLocationSP; typedef std::shared_ptr<lldb_private::Stream> StreamSP; Index: include/lldb/Target/StackFrameRecognizer.h =================================================================== --- /dev/null +++ include/lldb/Target/StackFrameRecognizer.h @@ -0,0 +1,63 @@ +//===-- FrameRecognizer.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_FrameRecognizer_h_ +#define liblldb_FrameRecognizer_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/lldb-private-forward.h" +#include "lldb/lldb-public.h" + +namespace lldb_private { + +class RecognizedStackFrame + : std::enable_shared_from_this<RecognizedStackFrame> { +public: + virtual lldb::ValueObjectListSP GetRecognizedArguments() { + return m_arguments; + } + virtual ~RecognizedStackFrame(){}; + +protected: + lldb::ValueObjectListSP m_arguments; +}; + +class StackFrameRecognizer + : std::enable_shared_from_this<StackFrameRecognizer> { +public: + virtual lldb::RecognizedStackFrameSP + RecognizeFrame(lldb::StackFrameSP frame) { + return lldb::RecognizedStackFrameSP(); + }; + + virtual ~StackFrameRecognizer(){}; +}; + +class StackFrameRecognizerManager { +public: + static void AddRecognizer(lldb::StackFrameRecognizerSP recognizer, + ConstString &module, ConstString &symbol, + bool first_instruction_only = true); + + static void AddRecognizer(lldb::StackFrameRecognizerSP recognizer, + lldb::RegularExpressionSP module, + lldb::RegularExpressionSP symbol, + bool first_instruction_only = true); + + static lldb::RecognizedStackFrameSP RecognizeFrame(lldb::StackFrameSP frame); +}; + +} // namespace lldb_private + +#endif // liblldb_FrameRecognizer_h_ Index: include/lldb/Target/StackFrame.h =================================================================== --- include/lldb/Target/StackFrame.h +++ include/lldb/Target/StackFrame.h @@ -516,6 +516,8 @@ void CalculateExecutionContext(ExecutionContext &exe_ctx) override; + lldb::RecognizedStackFrameSP GetRecognizedFrame(); + protected: friend class StackFrameList; @@ -553,6 +555,8 @@ ValueObjectList m_variable_list_value_objects; // Value objects for each // variable in // m_variable_list_sp + bool m_recognized; + lldb::RecognizedStackFrameSP m_recognized_frame; StreamString m_disassembly; std::recursive_mutex m_mutex;
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits