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; 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 { +public: + virtual lldb::ValueObjectListSP GetRecognizedArguments() { + return m_arguments; + } + virtual ~RecognizedStackFrame(){}; + +protected: + lldb::ValueObjectListSP m_arguments; +}; + +class StackFrameRecognizer + : std::enable_shared_from_this { +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/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 QueueWP; typedef std::shared_ptr QueueItemSP; typedef std::shared_ptr REPLSP; +typedef std::shared_ptr + RecognizedStackFrameSP; typedef std::shared_ptr ScriptSummaryFormatSP; typedef std::shared_ptr ScriptInterpreterSP; @@ -427,6 +432,8 @@ typedef std::unique_ptr StackFrameUP; typedef std::weak_ptr StackFrameWP; typedef std::shared_ptr StackFrameListSP; +typedef std::shared_ptr + StackFrameRecognizerSP; typedef std::shared_ptr StopInfoSP; typedef std::shared_ptr StoppointLocationSP; typedef std::shared_ptr StreamSP; 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 = ""; }; 8CF02AED19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InstrumentationRuntimeStopInfo.cpp; path = source/Target/InstrumentationRuntimeStopInfo.cpp; sourceTree = ""; }; 8CF02AEE19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InstrumentationRuntimeStopInfo.h; path = include/lldb/Target/InstrumentationRuntimeStopInfo.h; sourceTree = ""; }; + 8CF46A6120522A9000423DDF /* StackFrameRecognizer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = StackFrameRecognizer.cpp; path = source/Target/StackFrameRecognizer.cpp; sourceTree = ""; }; + 8CF46A632052447D00423DDF /* AppleObjCStackFrameRecognizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleObjCStackFrameRecognizer.h; sourceTree = ""; }; + 8CF46A642052447D00423DDF /* AppleObjCStackFrameRecognizer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AppleObjCStackFrameRecognizer.cpp; sourceTree = ""; }; + 8CFDB67920467B390052B399 /* StackFrameRecognizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StackFrameRecognizer.h; path = include/lldb/Target/StackFrameRecognizer.h; sourceTree = ""; }; 94005E0313F438DF001EF42D /* python-wrapper.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-wrapper.swig"; sourceTree = ""; }; 94005E0513F45A1B001EF42D /* embedded_interpreter.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = embedded_interpreter.py; path = source/Interpreter/embedded_interpreter.py; sourceTree = ""; }; 940495781BEC497E00926025 /* NSError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSError.cpp; path = Language/ObjC/NSError.cpp; sourceTree = ""; }; @@ -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: 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: 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/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/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/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/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 +// 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 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); +}