summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/API/SBThread.h5
-rw-r--r--lldb/include/lldb/Core/PluginManager.h22
-rw-r--r--lldb/include/lldb/Target/InstrumentationRuntime.h47
-rw-r--r--lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h52
-rw-r--r--lldb/include/lldb/Target/Process.h2
-rw-r--r--lldb/include/lldb/Target/StopInfo.h9
-rw-r--r--lldb/include/lldb/Target/Thread.h2
-rw-r--r--lldb/include/lldb/lldb-enumerations.h8
-rw-r--r--lldb/include/lldb/lldb-forward.h2
-rw-r--r--lldb/include/lldb/lldb-private-interfaces.h2
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj34
-rw-r--r--lldb/scripts/Python/interface/SBThread.i8
-rw-r--r--lldb/source/API/SBThread.cpp22
-rw-r--r--lldb/source/Commands/CommandObjectThread.cpp17
-rw-r--r--lldb/source/Core/Debugger.cpp1
-rw-r--r--lldb/source/Core/PluginManager.cpp119
-rw-r--r--lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp300
-rw-r--r--lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h86
-rw-r--r--lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/CMakeLists.txt5
-rw-r--r--lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/Makefile14
-rw-r--r--lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt1
-rw-r--r--lldb/source/Target/CMakeLists.txt2
-rw-r--r--lldb/source/Target/InstrumentationRuntime.cpp48
-rw-r--r--lldb/source/Target/InstrumentationRuntimeStopInfo.cpp36
-rw-r--r--lldb/source/Target/Process.cpp26
-rw-r--r--lldb/source/Target/StopInfo.cpp3
-rw-r--r--lldb/source/Target/Thread.cpp22
-rw-r--r--lldb/source/lldb.cpp3
-rw-r--r--lldb/test/functionalities/asan/TestMemoryHistory.py (renamed from lldb/test/functionalities/asan/TestAsan.py)0
-rw-r--r--lldb/test/functionalities/asan/TestReportData.py92
-rw-r--r--lldb/test/functionalities/asan/main.c2
31 files changed, 971 insertions, 21 deletions
diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h
index 8d2b104ffb6..db15f651f2d 100644
--- a/lldb/include/lldb/API/SBThread.h
+++ b/lldb/include/lldb/API/SBThread.h
@@ -78,7 +78,10 @@ public:
//--------------------------------------------------------------------------
uint64_t
GetStopReasonDataAtIndex(uint32_t idx);
-
+
+ bool
+ GetStopReasonExtendedInfoAsJSON (lldb::SBStream &stream);
+
size_t
GetStopDescription (char *dst, size_t dst_len);
diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h
index f313e788641..55e6df06d84 100644
--- a/lldb/include/lldb/Core/PluginManager.h
+++ b/lldb/include/lldb/Core/PluginManager.h
@@ -361,6 +361,28 @@ public:
GetMemoryHistoryCreateCallbackForPluginName (const ConstString &name);
//------------------------------------------------------------------
+ // InstrumentationRuntime
+ //------------------------------------------------------------------
+ static bool
+ RegisterPlugin (const ConstString &name,
+ const char *description,
+ InstrumentationRuntimeCreateInstance create_callback,
+ InstrumentationRuntimeGetType get_type_callback);
+
+ static bool
+ UnregisterPlugin (InstrumentationRuntimeCreateInstance create_callback);
+
+ static InstrumentationRuntimeGetType
+ GetInstrumentationRuntimeGetTypeCallbackAtIndex (uint32_t idx);
+
+ static InstrumentationRuntimeCreateInstance
+ GetInstrumentationRuntimeCreateCallbackAtIndex (uint32_t idx);
+
+ static InstrumentationRuntimeCreateInstance
+ GetInstrumentationRuntimeCreateCallbackForPluginName (const ConstString &name);
+
+
+ //------------------------------------------------------------------
// Some plug-ins might register a DebuggerInitializeCallback
// callback when registering the plug-in. After a new Debugger
// instance is created, this DebuggerInitialize function will get
diff --git a/lldb/include/lldb/Target/InstrumentationRuntime.h b/lldb/include/lldb/Target/InstrumentationRuntime.h
new file mode 100644
index 00000000000..70aa6290840
--- /dev/null
+++ b/lldb/include/lldb/Target/InstrumentationRuntime.h
@@ -0,0 +1,47 @@
+//===-- InstrumentationRuntime.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_InstrumentationRuntime_h_
+#define liblldb_InstrumentationRuntime_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+#include <map>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/lldb-types.h"
+#include "lldb/Core/PluginInterface.h"
+
+namespace lldb_private {
+
+typedef std::map<lldb::InstrumentationRuntimeType, lldb::InstrumentationRuntimeSP> InstrumentationRuntimeCollection;
+
+class InstrumentationRuntime :
+ public std::enable_shared_from_this<InstrumentationRuntime>,
+ public PluginInterface
+{
+public:
+
+ static void
+ ModulesDidLoad(lldb_private::ModuleList &module_list, Process *process, InstrumentationRuntimeCollection &runtimes);
+
+ virtual void
+ ModulesDidLoad(lldb_private::ModuleList &module_list);
+
+ virtual bool
+ IsActive();
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_InstrumentationRuntime_h_
diff --git a/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h b/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h
new file mode 100644
index 00000000000..624267ce822
--- /dev/null
+++ b/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h
@@ -0,0 +1,52 @@
+//===-- InstrumentationRuntimeStopInfo.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_InstrumentationRuntimeStopInfo_h_
+#define liblldb_InstrumentationRuntimeStopInfo_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Core/StructuredData.h"
+
+namespace lldb_private {
+
+class InstrumentationRuntimeStopInfo : public StopInfo
+{
+public:
+
+ virtual ~InstrumentationRuntimeStopInfo()
+ {
+ }
+
+ virtual lldb::StopReason
+ GetStopReason () const
+ {
+ return lldb::eStopReasonInstrumentation;
+ }
+
+ virtual const char *
+ GetDescription ();
+
+ static lldb::StopInfoSP
+ CreateStopReasonWithInstrumentationData (Thread &thread, std::string description, StructuredData::ObjectSP additional_data);
+
+private:
+
+ InstrumentationRuntimeStopInfo(Thread &thread, std::string description, StructuredData::ObjectSP additional_data);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_InstrumentationRuntimeStopInfo_h_
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 7a9185b3122..ee71f875036 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -52,6 +52,7 @@
#include "lldb/Target/ThreadList.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/PseudoTerminal.h"
+#include "lldb/Target/InstrumentationRuntime.h"
namespace lldb_private {
@@ -3082,6 +3083,7 @@ protected:
AllocatedMemoryCache m_allocated_memory_cache;
bool m_should_detach; /// Should we detach if the process object goes away with an explicit call to Kill or Detach?
LanguageRuntimeCollection m_language_runtimes;
+ InstrumentationRuntimeCollection m_instrumentation_runtimes;
std::unique_ptr<NextEventAction> m_next_event_action_ap;
std::vector<PreResumeCallbackAndBaton> m_pre_resume_actions;
ProcessRunLock m_public_run_lock;
diff --git a/lldb/include/lldb/Target/StopInfo.h b/lldb/include/lldb/Target/StopInfo.h
index 8de40e852f4..e0d029bcc95 100644
--- a/lldb/include/lldb/Target/StopInfo.h
+++ b/lldb/include/lldb/Target/StopInfo.h
@@ -18,6 +18,7 @@
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Target/Process.h"
+#include "lldb/Core/StructuredData.h"
namespace lldb_private {
@@ -140,6 +141,12 @@ public:
return m_override_should_stop == eLazyBoolYes;
}
+ StructuredData::ObjectSP
+ GetExtendedInfo ()
+ {
+ return m_extended_info;
+ }
+
static lldb::StopInfoSP
CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id);
@@ -211,6 +218,8 @@ protected:
LazyBool m_override_should_notify;
LazyBool m_override_should_stop;
+ StructuredData::ObjectSP m_extended_info; // The extended info for this stop info
+
// This determines whether the target has run since this stop info.
// N.B. running to evaluate a user expression does not count.
bool HasTargetRunSinceMe ();
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index 87373fb8f19..64b610eaa55 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -535,7 +535,7 @@ public:
DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx);
bool
- GetDescription (Stream &s, lldb::DescriptionLevel level, bool json_output);
+ GetDescription (Stream &s, lldb::DescriptionLevel level, bool print_json_thread, bool print_json_stopinfo);
//------------------------------------------------------------------
/// Default implementation for stepping into.
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 5164326c895..b49e29cded0 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -185,7 +185,8 @@ namespace lldb {
eStopReasonException,
eStopReasonExec, // Program was re-exec'ed
eStopReasonPlanComplete,
- eStopReasonThreadExiting
+ eStopReasonThreadExiting,
+ eStopReasonInstrumentation
} StopReason;
//----------------------------------------------------------------------
@@ -387,6 +388,11 @@ namespace lldb {
eLanguageTypeDylan = 0x0020, ///< Dylan.
eNumLanguageTypes
} LanguageType;
+
+ typedef enum InstrumentationRuntimeType {
+ eInstrumentationRuntimeTypeAddressSanitizer = 0x0000,
+ eNumInstrumentationRuntimeTypes
+ } InstrumentationRuntimeType;
typedef enum DynamicValueType
{
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 97660aaad30..0f95fc9f383 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -104,6 +104,7 @@ class FunctionInfo;
class InlineFunctionInfo;
class Instruction;
class InstructionList;
+class InstrumentationRuntime;
class IOHandler;
class IOObject;
class IRExecutionUnit;
@@ -312,6 +313,7 @@ namespace lldb {
typedef std::shared_ptr<lldb_private::FuncUnwinders> FuncUnwindersSP;
typedef std::shared_ptr<lldb_private::InlineFunctionInfo> InlineFunctionInfoSP;
typedef std::shared_ptr<lldb_private::Instruction> InstructionSP;
+ typedef std::shared_ptr<lldb_private::InstrumentationRuntime> InstrumentationRuntimeSP;
typedef std::shared_ptr<lldb_private::IOHandler> IOHandlerSP;
typedef std::shared_ptr<lldb_private::IOObject> IOObjectSP;
typedef std::shared_ptr<lldb_private::JITLoader> JITLoaderSP;
diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h
index db0c84ec9e4..4d608fe10cc 100644
--- a/lldb/include/lldb/lldb-private-interfaces.h
+++ b/lldb/include/lldb/lldb-private-interfaces.h
@@ -40,6 +40,8 @@ namespace lldb_private
typedef lldb::ThreadPlanSP (*ThreadPlanStepFromHereCallback) (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton);
typedef UnwindAssembly* (*UnwindAssemblyCreateInstance) (const ArchSpec &arch);
typedef lldb::MemoryHistorySP (*MemoryHistoryCreateInstance) (const lldb::ProcessSP &process_sp);
+ typedef lldb::InstrumentationRuntimeType (*InstrumentationRuntimeGetType) ();
+ typedef lldb::InstrumentationRuntimeSP (*InstrumentationRuntimeCreateInstance) (const lldb::ProcessSP &process_sp);
typedef int (*ComparisonFunction)(const void *, const void *);
typedef void (*DebuggerInitializeCallback)(Debugger &debugger);
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj
index 3454c9f56cb..b4d59d73824 100644
--- a/lldb/lldb.xcodeproj/project.pbxproj
+++ b/lldb/lldb.xcodeproj/project.pbxproj
@@ -637,6 +637,9 @@
8CCB017E19BA28A80009FD44 /* ThreadCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CCB017A19BA283D0009FD44 /* ThreadCollection.cpp */; };
8CCB018219BA4E270009FD44 /* SBThreadCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CCB018119BA4E210009FD44 /* SBThreadCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
8CCB018319BA51BF0009FD44 /* SBThreadCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CCB017F19BA4DD00009FD44 /* SBThreadCollection.cpp */; };
+ 8CF02AE919DCC01900B14BE0 /* InstrumentationRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF02ADF19DCBF3B00B14BE0 /* InstrumentationRuntime.cpp */; };
+ 8CF02AEA19DCC02100B14BE0 /* AddressSanitizerRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF02AE519DCBF8400B14BE0 /* AddressSanitizerRuntime.cpp */; };
+ 8CF02AEF19DD16B100B14BE0 /* InstrumentationRuntimeStopInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF02AED19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.cpp */; };
94094C6B163B6F840083A547 /* ValueObjectCast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94094C69163B6CD90083A547 /* ValueObjectCast.cpp */; };
940B02F619DC96E700AD0F52 /* SBExecutionContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940B02F519DC96E700AD0F52 /* SBExecutionContext.cpp */; };
94145431175E63B500284436 /* lldb-versioning.h in Headers */ = {isa = PBXBuildFile; fileRef = 94145430175D7FDE00284436 /* lldb-versioning.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1965,6 +1968,12 @@
8CCB017F19BA4DD00009FD44 /* SBThreadCollection.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SBThreadCollection.cpp; path = source/API/SBThreadCollection.cpp; sourceTree = "<group>"; };
8CCB018119BA4E210009FD44 /* SBThreadCollection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBThreadCollection.h; path = include/lldb/API/SBThreadCollection.h; sourceTree = "<group>"; };
8CCB018419BA54930009FD44 /* SBThreadCollection.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBThreadCollection.i; sourceTree = "<group>"; };
+ 8CF02ADF19DCBF3B00B14BE0 /* InstrumentationRuntime.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InstrumentationRuntime.cpp; path = source/Target/InstrumentationRuntime.cpp; sourceTree = "<group>"; };
+ 8CF02AE019DCBF3B00B14BE0 /* InstrumentationRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InstrumentationRuntime.h; path = include/lldb/Target/InstrumentationRuntime.h; sourceTree = "<group>"; };
+ 8CF02AE519DCBF8400B14BE0 /* AddressSanitizerRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AddressSanitizerRuntime.cpp; sourceTree = "<group>"; };
+ 8CF02AE619DCBF8400B14BE0 /* AddressSanitizerRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddressSanitizerRuntime.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>"; };
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>"; };
94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PriorityPointerPair.h; path = include/lldb/Utility/PriorityPointerPair.h; sourceTree = "<group>"; };
@@ -2423,6 +2432,7 @@
260C897110F57C5600BB2B04 /* Plugins */ = {
isa = PBXGroup;
children = (
+ 8CF02ADD19DCBEC200B14BE0 /* InstrumentationRuntime */,
8C2D6A58197A1FB9006989C9 /* MemoryHistory */,
26DB3E051379E7AD0080DC73 /* ABI */,
260C897210F57C5600BB2B04 /* Disassembler */,
@@ -3746,6 +3756,10 @@
26BC7DEF10F1B80200F91463 /* Target */ = {
isa = PBXGroup;
children = (
+ 8CF02AE019DCBF3B00B14BE0 /* InstrumentationRuntime.h */,
+ 8CF02ADF19DCBF3B00B14BE0 /* InstrumentationRuntime.cpp */,
+ 8CF02AEE19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.h */,
+ 8CF02AED19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.cpp */,
3FDFD6C3199C396E009756A7 /* FileAction.h */,
3FDFDDBC199C3A06009756A7 /* FileAction.cpp */,
23EDE3311926843600F6A132 /* NativeRegisterContext.h */,
@@ -4264,6 +4278,23 @@
path = asan;
sourceTree = "<group>";
};
+ 8CF02ADD19DCBEC200B14BE0 /* InstrumentationRuntime */ = {
+ isa = PBXGroup;
+ children = (
+ 8CF02ADE19DCBEE600B14BE0 /* AddressSanitizer */,
+ );
+ path = InstrumentationRuntime;
+ sourceTree = "<group>";
+ };
+ 8CF02ADE19DCBEE600B14BE0 /* AddressSanitizer */ = {
+ isa = PBXGroup;
+ children = (
+ 8CF02AE519DCBF8400B14BE0 /* AddressSanitizerRuntime.cpp */,
+ 8CF02AE619DCBF8400B14BE0 /* AddressSanitizerRuntime.h */,
+ );
+ path = AddressSanitizer;
+ sourceTree = "<group>";
+ };
9457596415349416005A9070 /* POSIX */ = {
isa = PBXGroup;
children = (
@@ -4965,6 +4996,7 @@
2689000713353DB600698AC0 /* BreakpointSite.cpp in Sources */,
2689000913353DB600698AC0 /* BreakpointSiteList.cpp in Sources */,
26474CC918D0CB5B0073DEBA /* RegisterContextMemory.cpp in Sources */,
+ 8CF02AEA19DCC02100B14BE0 /* AddressSanitizerRuntime.cpp in Sources */,
26474CB218D0CB180073DEBA /* RegisterContextLinux_i386.cpp in Sources */,
26474CCB18D0CB5B0073DEBA /* RegisterContextPOSIX_mips64.cpp in Sources */,
2689000B13353DB600698AC0 /* Stoppoint.cpp in Sources */,
@@ -5002,6 +5034,7 @@
2689002813353DDE00698AC0 /* CommandObjectThread.cpp in Sources */,
2689002913353DDE00698AC0 /* CommandObjectVersion.cpp in Sources */,
2689002A13353E0400698AC0 /* Address.cpp in Sources */,
+ 8CF02AE919DCC01900B14BE0 /* InstrumentationRuntime.cpp in Sources */,
2689002B13353E0400698AC0 /* AddressRange.cpp in Sources */,
236124A41986B4E2004EFC37 /* IOObject.cpp in Sources */,
2689002C13353E0400698AC0 /* AddressResolver.cpp in Sources */,
@@ -5223,6 +5256,7 @@
268900FA13353E6F00698AC0 /* ThreadList.cpp in Sources */,
268900FB13353E6F00698AC0 /* ThreadPlan.cpp in Sources */,
232CB619191E00CD00EF39FC /* NativeProcessProtocol.cpp in Sources */,
+ 8CF02AEF19DD16B100B14BE0 /* InstrumentationRuntimeStopInfo.cpp in Sources */,
268900FC13353E6F00698AC0 /* ThreadPlanBase.cpp in Sources */,
268900FD13353E6F00698AC0 /* ThreadPlanCallFunction.cpp in Sources */,
268900FE13353E6F00698AC0 /* ThreadPlanCallUserExpression.cpp in Sources */,
diff --git a/lldb/scripts/Python/interface/SBThread.i b/lldb/scripts/Python/interface/SBThread.i
index dac0f9bc4a7..53848214352 100644
--- a/lldb/scripts/Python/interface/SBThread.i
+++ b/lldb/scripts/Python/interface/SBThread.i
@@ -110,6 +110,14 @@ public:
") GetStopReasonDataAtIndex;
uint64_t
GetStopReasonDataAtIndex(uint32_t idx);
+
+ %feature("autodoc", "
+ Collects a thread's stop reason extended information dictionary and prints it
+ into the SBStream in a JSON format. The format of this JSON dictionary depends
+ on the stop reason and is currently used only for instrumentation plugins.
+ ") GetStopReasonExtendedInfoAsJSON;
+ bool
+ GetStopReasonExtendedInfoAsJSON (lldb::SBStream &stream);
%feature("autodoc", "
Pass only an (int)length and expect to get a Python string describing the
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 390fa0d4b6e..036ce10fcde 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -195,6 +195,7 @@ SBThread::GetStopReasonDataCount ()
case eStopReasonExec:
case eStopReasonPlanComplete:
case eStopReasonThreadExiting:
+ case eStopReasonInstrumentation:
// There is no data for these stop reasons.
return 0;
@@ -255,6 +256,7 @@ SBThread::GetStopReasonDataAtIndex (uint32_t idx)
case eStopReasonExec:
case eStopReasonPlanComplete:
case eStopReasonThreadExiting:
+ case eStopReasonInstrumentation:
// There is no data for these stop reasons.
return 0;
@@ -306,6 +308,26 @@ SBThread::GetStopReasonDataAtIndex (uint32_t idx)
return 0;
}
+bool
+SBThread::GetStopReasonExtendedInfoAsJSON (lldb::SBStream &stream)
+{
+ Stream &strm = stream.ref();
+
+ ExecutionContext exe_ctx (m_opaque_sp.get());
+ if (! exe_ctx.HasThreadScope())
+ return false;
+
+
+ StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
+ StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
+ if (! info)
+ return false;
+
+ info->Dump(strm);
+
+ return true;
+}
+
size_t
SBThread::GetStopDescription (char *dst, size_t dst_len)
{
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index 785e8f078ee..fbb233ab1db 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -1431,7 +1431,8 @@ public:
void
OptionParsingStarting ()
{
- m_json = false;
+ m_json_thread = false;
+ m_json_stopinfo = false;
}
virtual
@@ -1448,10 +1449,14 @@ public:
switch (short_option)
{
case 'j':
- m_json = true;
+ m_json_thread = true;
+ break;
+
+ case 's':
+ m_json_stopinfo = true;
break;
- default:
+ default:
return Error("invalid short option character '%c'", short_option);
}
@@ -1464,7 +1469,8 @@ public:
return g_option_table;
}
- bool m_json;
+ bool m_json_thread;
+ bool m_json_stopinfo;
static OptionDefinition g_option_table[];
};
@@ -1486,7 +1492,7 @@ public:
HandleOneThread (Thread &thread, CommandReturnObject &result)
{
Stream &strm = result.GetOutputStream();
- if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
+ if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo))
{
result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID());
result.SetStatus (eReturnStatusFailed);
@@ -1503,6 +1509,7 @@ OptionDefinition
CommandObjectThreadInfo::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."},
+ { LLDB_OPT_SET_ALL, false, "stop-info",'s', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the extended stop info in JSON format."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 5a910a9040a..2dc9b0367cf 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -3234,6 +3234,7 @@ Debugger::HandleProcessEvent (const EventSP &event_sp)
case eStopReasonException:
case eStopReasonExec:
case eStopReasonThreadExiting:
+ case eStopReasonInstrumentation:
if (!other_thread)
other_thread = thread;
break;
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index 0cca76ee95e..95574cb2dea 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -2172,6 +2172,125 @@ PluginManager::GetMemoryHistoryCreateCallbackForPluginName (const ConstString &n
return NULL;
}
+#pragma mark InstrumentationRuntime
+
+struct InstrumentationRuntimeInstance
+{
+ InstrumentationRuntimeInstance() :
+ name(),
+ description(),
+ create_callback(NULL)
+ {
+ }
+
+ ConstString name;
+ std::string description;
+ InstrumentationRuntimeCreateInstance create_callback;
+ InstrumentationRuntimeGetType get_type_callback;
+};
+
+typedef std::vector<InstrumentationRuntimeInstance> InstrumentationRuntimeInstances;
+
+static Mutex &
+GetInstrumentationRuntimeMutex ()
+{
+ static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
+ return g_instances_mutex;
+}
+
+static InstrumentationRuntimeInstances &
+GetInstrumentationRuntimeInstances ()
+{
+ static InstrumentationRuntimeInstances g_instances;
+ return g_instances;
+}
+
+bool
+PluginManager::RegisterPlugin
+(
+ const ConstString &name,
+ const char *description,
+ InstrumentationRuntimeCreateInstance create_callback,
+ InstrumentationRuntimeGetType get_type_callback
+ )
+{
+ if (create_callback)
+ {
+ InstrumentationRuntimeInstance instance;
+ assert ((bool)name);
+ instance.name = name;
+ if (description && description[0])
+ instance.description = description;
+ instance.create_callback = create_callback;
+ instance.get_type_callback = get_type_callback;
+ Mutex::Locker locker (GetInstrumentationRuntimeMutex ());
+ GetInstrumentationRuntimeInstances ().push_back (instance);
+ }
+ return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (InstrumentationRuntimeCreateInstance create_callback)
+{
+ if (create_callback)
+ {
+ Mutex::Locker locker (GetInstrumentationRuntimeMutex ());
+ InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances ();
+
+ InstrumentationRuntimeInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (pos->create_callback == create_callback)
+ {
+ instances.erase(pos);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+InstrumentationRuntimeGetType
+PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex (uint32_t idx)
+{
+ Mutex::Locker locker (GetInstrumentationRuntimeMutex ());
+ InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances ();
+ if (idx < instances.size())
+ return instances[idx].get_type_callback;
+ return NULL;
+}
+
+InstrumentationRuntimeCreateInstance
+PluginManager::GetInstrumentationRuntimeCreateCallbackAtIndex (uint32_t idx)
+{
+ Mutex::Locker locker (GetInstrumentationRuntimeMutex ());
+ InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances ();
+ if (idx < instances.size())
+ return instances[idx].create_callback;
+ return NULL;
+}
+
+
+InstrumentationRuntimeCreateInstance
+PluginManager::GetInstrumentationRuntimeCreateCallbackForPluginName (const ConstString &name)
+{
+ if (name)
+ {
+ Mutex::Locker locker (GetInstrumentationRuntimeMutex ());
+ InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances ();
+
+ InstrumentationRuntimeInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (name == pos->name)
+ return pos->create_callback;
+ }
+ }
+ return NULL;
+}
+
+#pragma mark PluginManager
+
void
PluginManager::DebuggerInitialize (Debugger &debugger)
{
diff --git a/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
new file mode 100644
index 00000000000..26d01345b34
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
@@ -0,0 +1,300 @@
+//===-- AddressSanitizerRuntime.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AddressSanitizerRuntime.h"
+
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Target/InstrumentationRuntimeStopInfo.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+lldb::InstrumentationRuntimeSP
+AddressSanitizerRuntime::CreateInstance (const lldb::ProcessSP &process_sp)
+{
+ return InstrumentationRuntimeSP(new AddressSanitizerRuntime(process_sp));
+}
+
+void
+AddressSanitizerRuntime::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "AddressSanitizer instrumentation runtime plugin.",
+ CreateInstance,
+ GetTypeStatic);
+}
+
+void
+AddressSanitizerRuntime::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+AddressSanitizerRuntime::GetPluginNameStatic()
+{
+ return ConstString("AddressSanitizer");
+}
+
+lldb::InstrumentationRuntimeType
+AddressSanitizerRuntime::GetTypeStatic()
+{
+ return eInstrumentationRuntimeTypeAddressSanitizer;
+}
+
+AddressSanitizerRuntime::AddressSanitizerRuntime(const ProcessSP &process_sp) :
+ m_is_active(false),
+ m_runtime_module(),
+ m_process(process_sp),
+ m_breakpoint_id(0)
+{
+}
+
+AddressSanitizerRuntime::~AddressSanitizerRuntime()
+{
+ Deactivate();
+}
+
+bool ModuleContainsASanRuntime(Module * module)
+{
+ SymbolContextList sc_list;
+ const bool include_symbols = true;
+ const bool append = true;
+ const bool include_inlines = true;
+
+ size_t num_matches = module->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list);
+
+ return num_matches > 0;
+}
+
+void
+AddressSanitizerRuntime::ModulesDidLoad(lldb_private::ModuleList &module_list)
+{
+ if (IsActive())
+ return;
+
+ if (m_runtime_module) {
+ Activate();
+ return;
+ }
+
+ Mutex::Locker modules_locker(module_list.GetMutex());
+ const size_t num_modules = module_list.GetSize();
+ for (size_t i = 0; i < num_modules; ++i)
+ {
+ Module *module_pointer = module_list.GetModulePointerAtIndexUnlocked(i);
+ const FileSpec & file_spec = module_pointer->GetFileSpec();
+ if (! file_spec)
+ continue;
+
+ static RegularExpression g_asan_runtime_regex("libclang_rt.asan_(.*)_dynamic\\.dylib");
+ if (g_asan_runtime_regex.Execute (file_spec.GetFilename().GetCString()) || module_pointer->IsExecutable())
+ {
+ if (ModuleContainsASanRuntime(module_pointer))
+ {
+ m_runtime_module = module_pointer->shared_from_this();
+ Activate();
+ return;
+ }
+ }
+ }
+}
+
+bool
+AddressSanitizerRuntime::IsActive()
+{
+ return m_is_active;
+}
+
+#define RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC 2*1000*1000
+
+const char *
+address_sanitizer_retrieve_report_data_command = R"(
+ struct {
+ int present;
+ void *pc, *bp, *sp, *address;
+ int access_type;
+ size_t access_size;
+ const char *description;
+ } t;
+
+ t.present = ((int (*) ())__asan_report_present)();
+ t.pc = ((void * (*) ())__asan_get_report_pc)();
+ /* commented out because rdar://problem/18533301
+ t.bp = ((void * (*) ())__asan_get_report_bp)();
+ t.sp = ((void * (*) ())__asan_get_report_sp)();
+ */
+ t.address = ((void * (*) ())__asan_get_report_address)();
+ t.description = ((const char * (*) ())__asan_get_report_description)();
+ t.access_type = ((int (*) ())__asan_get_report_access_type)();
+ t.access_size = ((size_t (*) ())__asan_get_report_access_size)();
+
+ t;
+)";
+
+StructuredData::ObjectSP
+AddressSanitizerRuntime::RetrieveReportData()
+{
+ ThreadSP thread_sp = m_process->GetThreadList().GetSelectedThread();
+ StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+
+ if (!frame_sp)
+ return StructuredData::ObjectSP();
+
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(true);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeoutUsec(RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC);
+
+ ValueObjectSP return_value_sp;
+ if (m_process->GetTarget().EvaluateExpression(address_sanitizer_retrieve_report_data_command, frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
+ return StructuredData::ObjectSP();
+
+ int present = return_value_sp->GetValueForExpressionPath(".present")->GetValueAsUnsigned(0);
+ if (present != 1)
+ return StructuredData::ObjectSP();
+
+ addr_t pc = return_value_sp->GetValueForExpressionPath(".pc")->GetValueAsUnsigned(0);
+ addr_t bp = return_value_sp->GetValueForExpressionPath(".bp")->GetValueAsUnsigned(0);
+ addr_t sp = return_value_sp->GetValueForExpressionPath(".sp")->GetValueAsUnsigned(0);
+ addr_t address = return_value_sp->GetValueForExpressionPath(".address")->GetValueAsUnsigned(0);
+ addr_t access_type = return_value_sp->GetValueForExpressionPath(".access_type")->GetValueAsUnsigned(0);
+ addr_t access_size = return_value_sp->GetValueForExpressionPath(".access_size")->GetValueAsUnsigned(0);
+ addr_t description_ptr = return_value_sp->GetValueForExpressionPath(".description")->GetValueAsUnsigned(0);
+ std::string description;
+ Error error;
+ m_process->ReadCStringFromMemory(description_ptr, description, error);
+
+ StructuredData::Dictionary *dict = new StructuredData::Dictionary();
+ dict->AddStringItem("instrumentation_class", "AddressSanitizer");
+ dict->AddStringItem("stop_type", "fatal_error");
+ dict->AddIntegerItem("pc", pc);
+ dict->AddIntegerItem("bp", bp);
+ dict->AddIntegerItem("sp", sp);
+ dict->AddIntegerItem("address", address);
+ dict->AddIntegerItem("access_type", access_type);
+ dict->AddIntegerItem("access_size", access_size);
+ dict->AddStringItem("description", description);
+
+ return StructuredData::ObjectSP(dict);
+}
+
+std::string
+AddressSanitizerRuntime::FormatDescription(StructuredData::ObjectSP report)
+{
+ std::string description = report->GetAsDictionary()->GetValueForKey("description")->GetAsString()->GetValue();
+ if (description == "heap-use-after-free") {
+ return "Use of deallocated memory detected";
+ } else if (description == "heap-buffer-overflow") {
+ return "Heap buffer overflow detected";
+ } else if (description == "stack-buffer-underflow") {
+ return "Stack buffer underflow detected";
+ } else if (description == "initialization-order-fiasco") {
+ return "Initialization order problem detected";
+ } else if (description == "stack-buffer-overflow") {
+ return "Stack buffer overflow detected";
+ } else if (description == "stack-use-after-return") {
+ return "Use of returned stack memory detected";
+ } else if (description == "use-after-poison") {
+ return "Use of poisoned memory detected";
+ } else if (description == "container-overflow") {
+ return "Container overflow detected";
+ } else if (description == "stack-use-after-scope") {
+ return "Use of out-of-scope stack memory detected";
+ } else if (description == "global-buffer-overflow") {
+ return "Global buffer overflow detected";
+ } else if (description == "unknown-crash") {
+ return "Invalid memory access detected";
+ }
+
+ // for unknown report codes just show the code
+ return description;
+}
+
+bool
+AddressSanitizerRuntime::NotifyBreakpointHit(void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id)
+{
+ assert (baton && "null baton");
+ if (!baton)
+ return false;
+
+ AddressSanitizerRuntime *const instance = static_cast<AddressSanitizerRuntime*>(baton);
+
+ StructuredData::ObjectSP report = instance->RetrieveReportData();
+ std::string description;
+ if (report) {
+ description = instance->FormatDescription(report);
+ }
+ ThreadSP thread = context->exe_ctx_ref.GetThreadSP();
+ thread->SetStopInfo(InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(*thread, description.c_str(), report));
+
+ instance->m_runtime_module->ReportWarning("AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.\n");
+
+ // Return true to stop the target, false to just let the target run.
+ return true;
+}
+
+void
+AddressSanitizerRuntime::Activate()
+{
+ if (m_is_active)
+ return;
+
+ ConstString symbol_name ("__asan::AsanDie()");
+ const Symbol *symbol = m_runtime_module->FindFirstSymbolWithNameAndType (symbol_name, eSymbolTypeCode);
+
+ if (symbol == NULL)
+ return;
+
+ if (!symbol->GetAddress().IsValid())
+ return;
+
+ Target &target = m_process->GetTarget();
+ addr_t symbol_address = symbol->GetAddress().GetOpcodeLoadAddress(&target);
+
+ if (symbol_address == LLDB_INVALID_ADDRESS)
+ return;
+
+ bool internal = true;
+ bool hardware = false;
+ Breakpoint *breakpoint = m_process->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get();
+ breakpoint->SetCallback (AddressSanitizerRuntime::NotifyBreakpointHit, this, true);
+ breakpoint->SetBreakpointKind ("address-sanitizer-report");
+ m_breakpoint_id = breakpoint->GetID();
+
+ m_runtime_module->ReportWarning("AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.\n");
+
+ m_is_active = true;
+}
+
+void
+AddressSanitizerRuntime::Deactivate()
+{
+ if (m_breakpoint_id != LLDB_INVALID_BREAK_ID)
+ {
+ m_process->GetTarget().RemoveBreakpointByID(m_breakpoint_id);
+ m_breakpoint_id = LLDB_INVALID_BREAK_ID;
+ }
+ m_is_active = false;
+}
diff --git a/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h
new file mode 100644
index 00000000000..69c134cbeda
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h
@@ -0,0 +1,86 @@
+//===-- AddressSanitizerRuntime.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_AddressSanitizerRuntime_h_
+#define liblldb_AddressSanitizerRuntime_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/InstrumentationRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/StructuredData.h"
+
+namespace lldb_private {
+
+class AddressSanitizerRuntime : public lldb_private::InstrumentationRuntime
+{
+public:
+
+ static lldb::InstrumentationRuntimeSP
+ CreateInstance (const lldb::ProcessSP &process_sp);
+
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static lldb::InstrumentationRuntimeType
+ GetTypeStatic();
+
+ virtual
+ ~AddressSanitizerRuntime();
+
+ virtual lldb_private::ConstString
+ GetPluginName() { return GetPluginNameStatic(); }
+
+ virtual lldb::InstrumentationRuntimeType
+ GetType() { return GetTypeStatic(); }
+
+ virtual uint32_t
+ GetPluginVersion() { return 1; }
+
+ virtual void
+ ModulesDidLoad(lldb_private::ModuleList &module_list);
+
+ virtual bool
+ IsActive();
+
+private:
+
+ AddressSanitizerRuntime(const lldb::ProcessSP &process_sp);
+
+ void
+ Activate();
+
+ void
+ Deactivate();
+
+ static bool
+ NotifyBreakpointHit(void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
+
+ StructuredData::ObjectSP
+ RetrieveReportData();
+
+ std::string
+ FormatDescription(StructuredData::ObjectSP report);
+
+ bool m_is_active;
+ lldb::ModuleSP m_runtime_module;
+ lldb::ProcessSP m_process;
+ lldb::user_id_t m_breakpoint_id;
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_InstrumentationRuntime_h_
diff --git a/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/CMakeLists.txt b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/CMakeLists.txt
new file mode 100644
index 00000000000..becc0fd8604
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_NO_RTTI 1)
+
+add_lldb_library(lldbPluginInstrumentationRuntimeAddressSanitizer
+ AddressSanitizerRuntime.cpp
+ )
diff --git a/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/Makefile b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/Makefile
new file mode 100644
index 00000000000..030aec17b02
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/Makefile
@@ -0,0 +1,14 @@
+##===- source/Plugins/InstrumentationRuntime/AddressSanitizer Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginInstrumentationRuntimeAddressSanitizer
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
diff --git a/lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt b/lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt
new file mode 100644
index 00000000000..8ee303b2535
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(AddressSanitizer)
diff --git a/lldb/source/Target/CMakeLists.txt b/lldb/source/Target/CMakeLists.txt
index bfd4d47c034..f534b33bad2 100644
--- a/lldb/source/Target/CMakeLists.txt
+++ b/lldb/source/Target/CMakeLists.txt
@@ -9,6 +9,8 @@ add_lldb_library(lldbTarget
FileAction.cpp
JITLoader.cpp
JITLoaderList.cpp
+ InstrumentationRuntime.cpp
+ InstrumentationRuntimeStopInfo.cpp
LanguageRuntime.cpp
Memory.cpp
MemoryHistory.cpp
diff --git a/lldb/source/Target/InstrumentationRuntime.cpp b/lldb/source/Target/InstrumentationRuntime.cpp
new file mode 100644
index 00000000000..b3b2393b023
--- /dev/null
+++ b/lldb/source/Target/InstrumentationRuntime.cpp
@@ -0,0 +1,48 @@
+//===-- InstrumentationRuntime.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Target/InstrumentationRuntime.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+InstrumentationRuntime::ModulesDidLoad(lldb_private::ModuleList &module_list, lldb_private::Process *process, InstrumentationRuntimeCollection &runtimes)
+{
+ InstrumentationRuntimeCreateInstance create_callback = NULL;
+ InstrumentationRuntimeGetType get_type_callback;
+ for (uint32_t idx = 0; ; ++idx)
+ {
+ create_callback = PluginManager::GetInstrumentationRuntimeCreateCallbackAtIndex(idx);
+ if (create_callback == NULL)
+ break;
+ get_type_callback = PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex(idx);
+ InstrumentationRuntimeType type = get_type_callback();
+
+ InstrumentationRuntimeCollection::iterator pos;
+ pos = runtimes.find (type);
+ if (pos == runtimes.end()) {
+ runtimes[type] = create_callback(process->shared_from_this());
+ }
+ }
+}
+
+void
+InstrumentationRuntime::ModulesDidLoad(lldb_private::ModuleList &module_list)
+{
+}
+
+bool
+InstrumentationRuntime::IsActive()
+{
+ return false;
+}
diff --git a/lldb/source/Target/InstrumentationRuntimeStopInfo.cpp b/lldb/source/Target/InstrumentationRuntimeStopInfo.cpp
new file mode 100644
index 00000000000..cdbf93b5f72
--- /dev/null
+++ b/lldb/source/Target/InstrumentationRuntimeStopInfo.cpp
@@ -0,0 +1,36 @@
+//===-- InstrumentationRuntimeStopInfo.cpp ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/InstrumentationRuntimeStopInfo.h"
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/InstrumentationRuntime.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+InstrumentationRuntimeStopInfo::InstrumentationRuntimeStopInfo(Thread &thread, std::string description, StructuredData::ObjectSP additional_data) :
+ StopInfo(thread, 0)
+{
+ m_extended_info = additional_data;
+ m_description = description;
+}
+
+const char *
+InstrumentationRuntimeStopInfo::GetDescription ()
+{
+ return m_description.c_str();
+}
+
+StopInfoSP
+InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData (Thread &thread, std::string description, StructuredData::ObjectSP additionalData)
+{
+ return StopInfoSP(new InstrumentationRuntimeStopInfo(thread, description, additionalData));
+}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index dbdbbe22c90..d337d8110c8 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -48,6 +48,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanBase.h"
+#include "lldb/Target/InstrumentationRuntime.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
using namespace lldb;
@@ -843,6 +844,7 @@ Process::Finalize()
m_memory_cache.Clear();
m_allocated_memory_cache.Clear();
m_language_runtimes.clear();
+ m_instrumentation_runtimes.clear();
m_next_event_action_ap.reset();
//#ifdef LLDB_CONFIGURATION_DEBUG
// StreamFile s(stdout, false);
@@ -5983,6 +5985,7 @@ Process::DidExec ()
m_image_tokens.clear();
m_allocated_memory_cache.Clear();
m_language_runtimes.clear();
+ m_instrumentation_runtimes.clear();
m_thread_list.DiscardThreadPlans();
m_memory_cache.Clear(true);
DoDidExec();
@@ -6033,13 +6036,24 @@ Process::ResolveIndirectFunction(const Address *address, Error &error)
void
Process::ModulesDidLoad (ModuleList &module_list)
{
- SystemRuntime *sys_runtime = GetSystemRuntime();
- if (sys_runtime)
- {
- sys_runtime->ModulesDidLoad (module_list);
- }
+ SystemRuntime *sys_runtime = GetSystemRuntime();
+ if (sys_runtime)
+ {
+ sys_runtime->ModulesDidLoad (module_list);
+ }
+
+ GetJITLoaders().ModulesDidLoad (module_list);
+
+ // Give runtimes a chance to be created.
+ InstrumentationRuntime::ModulesDidLoad(module_list, this, m_instrumentation_runtimes);
+
+ // Tell runtimes about new modules.
+ for (auto pos = m_instrumentation_runtimes.begin(); pos != m_instrumentation_runtimes.end(); ++pos)
+ {
+ InstrumentationRuntimeSP runtime = pos->second;
+ runtime->ModulesDidLoad(module_list);
+ }
- GetJITLoaders().ModulesDidLoad (module_list);
}
ThreadCollectionSP
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index a37a4079ff1..b7cf11cfb7d 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -40,7 +40,8 @@ StopInfo::StopInfo (Thread &thread, uint64_t value) :
m_resume_id (thread.GetProcess()->GetResumeID()),
m_value (value),
m_override_should_notify (eLazyBoolCalculate),
- m_override_should_stop (eLazyBoolCalculate)
+ m_override_should_stop (eLazyBoolCalculate),
+ m_extended_info()
{
}
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index f4b15f5c9d2..17f06194fc1 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -2086,6 +2086,7 @@ Thread::StopReasonAsCString (lldb::StopReason reason)
case eStopReasonExec: return "exec";
case eStopReasonPlanComplete: return "plan complete";
case eStopReasonThreadExiting: return "thread exiting";
+ case eStopReasonInstrumentation: return "instrumentation break";
}
@@ -2165,17 +2166,28 @@ Thread::GetStatus (Stream &strm, uint32_t start_frame, uint32_t num_frames, uint
}
bool
-Thread::GetDescription (Stream &strm, lldb::DescriptionLevel level, bool print_json)
+Thread::GetDescription (Stream &strm, lldb::DescriptionLevel level, bool print_json_thread, bool print_json_stopinfo)
{
DumpUsingSettingsFormat (strm, 0);
strm.Printf("\n");
StructuredData::ObjectSP thread_info = GetExtendedInfo();
-
- if (thread_info && print_json)
+ StructuredData::ObjectSP stop_info = m_stop_info_sp->GetExtendedInfo();
+
+ if (print_json_thread || print_json_stopinfo)
{
- thread_info->Dump (strm);
- strm.Printf("\n");
+ if (thread_info && print_json_thread)
+ {
+ thread_info->Dump (strm);
+ strm.Printf("\n");
+ }
+
+ if (stop_info && print_json_stopinfo)
+ {
+ stop_info->Dump (strm);
+ strm.Printf("\n");
+ }
+
return true;
}
diff --git a/lldb/source/lldb.cpp b/lldb/source/lldb.cpp
index cb2af8a081d..99a54b2a4e6 100644
--- a/lldb/source/lldb.cpp
+++ b/lldb/source/lldb.cpp
@@ -93,6 +93,7 @@
#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
#include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h"
+#include "Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h"
using namespace lldb;
using namespace lldb_private;
@@ -156,6 +157,7 @@ lldb_private::Initialize ()
JITLoaderGDB::Initialize();
ProcessElfCore::Initialize();
MemoryHistoryASan::Initialize();
+ AddressSanitizerRuntime::Initialize();
#if defined (__APPLE__)
//----------------------------------------------------------------------
@@ -247,6 +249,7 @@ lldb_private::Terminate ()
JITLoaderGDB::Terminate();
ProcessElfCore::Terminate();
MemoryHistoryASan::Terminate();
+ AddressSanitizerRuntime::Terminate();
#if defined (__APPLE__)
DynamicLoaderMacOSXDYLD::Terminate();
diff --git a/lldb/test/functionalities/asan/TestAsan.py b/lldb/test/functionalities/asan/TestMemoryHistory.py
index f8a3131d235..f8a3131d235 100644
--- a/lldb/test/functionalities/asan/TestAsan.py
+++ b/lldb/test/functionalities/asan/TestMemoryHistory.py
diff --git a/lldb/test/functionalities/asan/TestReportData.py b/lldb/test/functionalities/asan/TestReportData.py
new file mode 100644
index 00000000000..7cf5a42cb44
--- /dev/null
+++ b/lldb/test/functionalities/asan/TestReportData.py
@@ -0,0 +1,92 @@
+"""
+Test the AddressSanitizer runtime support for report breakpoint and data extraction.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+import json
+
+class AsanTestReportDataCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ # The default compiler ("clang") may not support Address Sanitizer or it
+ # may not have the debugging API which was recently added, so we're calling
+ # self.useBuiltClang() to use clang from the llvm-build directory instead
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @skipIfRemote
+ @dsym_test
+ def test_with_dsym (self):
+ compiler = self.findBuiltClang ()
+ self.buildDsym (None, compiler)
+ self.asan_tests ()
+
+ @skipIfRemote
+ @dwarf_test
+ def test_with_dwarf (self):
+ compiler = self.findBuiltClang ()
+ self.buildDwarf (None, compiler)
+ self.asan_tests ()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ self.line_malloc = line_number('main.c', '// malloc line')
+ self.line_malloc2 = line_number('main.c', '// malloc2 line')
+ self.line_free = line_number('main.c', '// free line')
+ self.line_breakpoint = line_number('main.c', '// break line')
+ self.line_crash = line_number('main.c', '// BOOM line')
+
+ def asan_tests (self):
+ exe = os.path.join (os.getcwd(), "a.out")
+ self.expect("file " + exe, patterns = [ "Current executable set to .*a.out" ])
+ self.runCmd("run")
+
+ # ASan will relaunch the process to insert its library.
+ self.expect("thread list", "Process should be stopped due to exec.",
+ substrs = ['stopped', 'stop reason = exec'])
+
+ # no extended info when we have no ASan report
+ thread = self.dbg.GetSelectedTarget().process.GetSelectedThread()
+ s = lldb.SBStream()
+ self.assertFalse(thread.GetStopReasonExtendedInfoAsJSON(s))
+
+ self.runCmd("continue")
+
+ self.expect("thread list", "Process should be stopped due to ASan report",
+ substrs = ['stopped', 'stop reason = Use of deallocated memory detected'])
+
+ self.assertEqual(self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(), lldb.eStopReasonInstrumentation)
+
+ self.expect("bt", "The backtrace should show the crashing line",
+ substrs = ['main.c:%d' % self.line_crash])
+
+ self.expect("thread info -s", "The extended stop info should contain the ASan provided fields",
+ substrs = ["access_size", "access_type", "address", "pc", "description", "heap-use-after-free"])
+
+ output_lines = self.res.GetOutput().split('\n')
+ json_line = output_lines[2]
+ data = json.loads(json_line)
+ self.assertEqual(data["description"], "heap-use-after-free")
+ self.assertEqual(data["instrumentation_class"], "AddressSanitizer")
+ self.assertEqual(data["stop_type"], "fatal_error")
+
+ # now let's try the SB API
+ process = self.dbg.GetSelectedTarget().process
+ thread = process.GetSelectedThread()
+
+ s = lldb.SBStream()
+ self.assertTrue(thread.GetStopReasonExtendedInfoAsJSON(s))
+ s = s.GetData()
+ data2 = json.loads(s)
+ self.assertEqual(data, data2)
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
diff --git a/lldb/test/functionalities/asan/main.c b/lldb/test/functionalities/asan/main.c
index 4e873cca417..fab760e49f0 100644
--- a/lldb/test/functionalities/asan/main.c
+++ b/lldb/test/functionalities/asan/main.c
@@ -28,7 +28,7 @@ int main (int argc, char const *argv[])
printf("Hello world!\n"); // break line
- pointer[0] = 'A'; // BOOM
+ pointer[0] = 'A'; // BOOM line
return 0;
}
OpenPOWER on IntegriCloud