[Lldb-commits] [lldb] [lldb] Refactor InstrumentationRuntimeAsan and add a new plugin (PR #69388)
Usama Hameed via lldb-commits
lldb-commits at lists.llvm.org
Thu Oct 19 11:48:21 PDT 2023
https://github.com/usama54321 updated https://github.com/llvm/llvm-project/pull/69388
>From bafeea33e1aea4a9e947220a78801ef241106eac Mon Sep 17 00:00:00 2001
From: usama <u_hameed at apple.com>
Date: Wed, 18 Oct 2023 17:16:50 -0700
Subject: [PATCH 1/2] [lldb] Refactor InstrumentationRuntimeAsan
This commit refactors InstrumentationRuntimeASan by pulling out reusable
code into a separate ReportRetriever class. The purpose of the
refactoring is to allow reuse of the ReportRetriever class in another
plugin.
rdar://112491689
---
lldb/include/lldb/lldb-enumerations.h | 1 +
.../ASan/CMakeLists.txt | 5 +-
.../ASan/InstrumentationRuntimeASan.cpp | 242 ++---------------
.../ASan/InstrumentationRuntimeASan.h | 7 -
.../InstrumentationRuntime/CMakeLists.txt | 1 +
.../Utility/CMakeLists.txt | 10 +
.../Utility/ReportRetriever.cpp | 252 ++++++++++++++++++
.../Utility/ReportRetriever.h | 34 +++
8 files changed, 315 insertions(+), 237 deletions(-)
create mode 100644 lldb/source/Plugins/InstrumentationRuntime/Utility/CMakeLists.txt
create mode 100644 lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp
create mode 100644 lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.h
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 36f3030c5226d60..206ff4ed7e6ad05 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -527,6 +527,7 @@ enum InstrumentationRuntimeType {
eInstrumentationRuntimeTypeUndefinedBehaviorSanitizer = 0x0002,
eInstrumentationRuntimeTypeMainThreadChecker = 0x0003,
eInstrumentationRuntimeTypeSwiftRuntimeReporting = 0x0004,
+ eInstrumentationRuntimeTypeLibsanitizersAsan = 0x0005,
eNumInstrumentationRuntimeTypes
};
diff --git a/lldb/source/Plugins/InstrumentationRuntime/ASan/CMakeLists.txt b/lldb/source/Plugins/InstrumentationRuntime/ASan/CMakeLists.txt
index 0b29027018463fe..b746a16b31f7789 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/ASan/CMakeLists.txt
+++ b/lldb/source/Plugins/InstrumentationRuntime/ASan/CMakeLists.txt
@@ -4,10 +4,7 @@ add_lldb_library(lldbPluginInstrumentationRuntimeASan PLUGIN
LINK_LIBS
lldbBreakpoint
lldbCore
- lldbExpression
- lldbInterpreter
lldbSymbol
lldbTarget
- LINK_COMPONENTS
- Support
+ lldbPluginInstrumentationRuntimeUtility
)
diff --git a/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp b/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp
index 5fcdc808bbb154c..a09c89103b0e3dd 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp
@@ -9,23 +9,14 @@
#include "InstrumentationRuntimeASan.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
-#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/ValueObject.h"
-#include "lldb/Expression/UserExpression.h"
-#include "lldb/Host/StreamFile.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/Symbol.h"
-#include "lldb/Target/InstrumentationRuntimeStopInfo.h"
-#include "lldb/Target/StopInfo.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
+#include "lldb/Target/Process.h"
#include "lldb/Utility/RegularExpression.h"
-#include "lldb/Utility/Stream.h"
-#include "llvm/ADT/StringSwitch.h"
+#include "Plugins/InstrumentationRuntime/Utility/ReportRetriever.h"
using namespace lldb;
using namespace lldb_private;
@@ -69,169 +60,6 @@ bool InstrumentationRuntimeASan::CheckIfRuntimeIsValid(
return symbol != nullptr;
}
-const char *address_sanitizer_retrieve_report_data_prefix = R"(
-extern "C"
-{
-int __asan_report_present();
-void *__asan_get_report_pc();
-void *__asan_get_report_bp();
-void *__asan_get_report_sp();
-void *__asan_get_report_address();
-const char *__asan_get_report_description();
-int __asan_get_report_access_type();
-size_t __asan_get_report_access_size();
-}
-)";
-
-const char *address_sanitizer_retrieve_report_data_command = R"(
-struct {
- int present;
- int access_type;
- void *pc;
- void *bp;
- void *sp;
- void *address;
- size_t access_size;
- const char *description;
-} t;
-
-t.present = __asan_report_present();
-t.access_type = __asan_get_report_access_type();
-t.pc = __asan_get_report_pc();
-t.bp = __asan_get_report_bp();
-t.sp = __asan_get_report_sp();
-t.address = __asan_get_report_address();
-t.access_size = __asan_get_report_access_size();
-t.description = __asan_get_report_description();
-t
-)";
-
-StructuredData::ObjectSP InstrumentationRuntimeASan::RetrieveReportData() {
- ProcessSP process_sp = GetProcessSP();
- if (!process_sp)
- return StructuredData::ObjectSP();
-
- ThreadSP thread_sp =
- process_sp->GetThreadList().GetExpressionExecutionThread();
- StackFrameSP frame_sp =
- thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);
-
- if (!frame_sp)
- return StructuredData::ObjectSP();
-
- EvaluateExpressionOptions options;
- options.SetUnwindOnError(true);
- options.SetTryAllThreads(true);
- options.SetStopOthers(true);
- options.SetIgnoreBreakpoints(true);
- options.SetTimeout(process_sp->GetUtilityExpressionTimeout());
- options.SetPrefix(address_sanitizer_retrieve_report_data_prefix);
- options.SetAutoApplyFixIts(false);
- options.SetLanguage(eLanguageTypeObjC_plus_plus);
-
- ValueObjectSP return_value_sp;
- ExecutionContext exe_ctx;
- Status eval_error;
- frame_sp->CalculateExecutionContext(exe_ctx);
- ExpressionResults result = UserExpression::Evaluate(
- exe_ctx, options, address_sanitizer_retrieve_report_data_command, "",
- return_value_sp, eval_error);
- if (result != eExpressionCompleted) {
- StreamString ss;
- ss << "cannot evaluate AddressSanitizer expression:\n";
- ss << eval_error.AsCString();
- Debugger::ReportWarning(ss.GetString().str(),
- process_sp->GetTarget().GetDebugger().GetID());
- 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;
- Status error;
- process_sp->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
-InstrumentationRuntimeASan::FormatDescription(StructuredData::ObjectSP report) {
- std::string description = std::string(report->GetAsDictionary()
- ->GetValueForKey("description")
- ->GetAsString()
- ->GetValue());
- return llvm::StringSwitch<std::string>(description)
- .Case("heap-use-after-free", "Use of deallocated memory")
- .Case("heap-buffer-overflow", "Heap buffer overflow")
- .Case("stack-buffer-underflow", "Stack buffer underflow")
- .Case("initialization-order-fiasco", "Initialization order problem")
- .Case("stack-buffer-overflow", "Stack buffer overflow")
- .Case("stack-use-after-return", "Use of stack memory after return")
- .Case("use-after-poison", "Use of poisoned memory")
- .Case("container-overflow", "Container overflow")
- .Case("stack-use-after-scope", "Use of out-of-scope stack memory")
- .Case("global-buffer-overflow", "Global buffer overflow")
- .Case("unknown-crash", "Invalid memory access")
- .Case("stack-overflow", "Stack space exhausted")
- .Case("null-deref", "Dereference of null pointer")
- .Case("wild-jump", "Jump to non-executable address")
- .Case("wild-addr-write", "Write through wild pointer")
- .Case("wild-addr-read", "Read from wild pointer")
- .Case("wild-addr", "Access through wild pointer")
- .Case("signal", "Deadly signal")
- .Case("double-free", "Deallocation of freed memory")
- .Case("new-delete-type-mismatch",
- "Deallocation size different from allocation size")
- .Case("bad-free", "Deallocation of non-allocated memory")
- .Case("alloc-dealloc-mismatch",
- "Mismatch between allocation and deallocation APIs")
- .Case("bad-malloc_usable_size", "Invalid argument to malloc_usable_size")
- .Case("bad-__sanitizer_get_allocated_size",
- "Invalid argument to __sanitizer_get_allocated_size")
- .Case("param-overlap",
- "Call to function disallowing overlapping memory ranges")
- .Case("negative-size-param", "Negative size used when accessing memory")
- .Case("bad-__sanitizer_annotate_contiguous_container",
- "Invalid argument to __sanitizer_annotate_contiguous_container")
- .Case("odr-violation", "Symbol defined in multiple translation units")
- .Case(
- "invalid-pointer-pair",
- "Comparison or arithmetic on pointers from different memory regions")
- // for unknown report codes just show the code
- .Default("AddressSanitizer detected: " + description);
-}
-
bool InstrumentationRuntimeASan::NotifyBreakpointHit(
void *baton, StoppointCallbackContext *context, user_id_t break_id,
user_id_t break_loc_id) {
@@ -244,32 +72,8 @@ bool InstrumentationRuntimeASan::NotifyBreakpointHit(
ProcessSP process_sp = instance->GetProcessSP();
- if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
- return false;
-
- StructuredData::ObjectSP report = instance->RetrieveReportData();
- std::string description;
- if (report) {
- description = instance->FormatDescription(report);
- }
- // Make sure this is the right process
- if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) {
- ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
- if (thread_sp)
- thread_sp->SetStopInfo(InstrumentationRuntimeStopInfo::
- CreateStopReasonWithInstrumentationData(
- *thread_sp, description, report));
-
- StreamFileSP stream_sp(
- process_sp->GetTarget().GetDebugger().GetOutputStreamSP());
- if (stream_sp) {
- stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread "
- "info -s' to get extended information about the "
- "report.\n");
- }
- return true; // Return true to stop the target
- } else
- return false; // Let target run
+ return ReportRetriever::NotifyBreakpointHit(process_sp, context, break_id,
+ break_loc_id);
}
void InstrumentationRuntimeASan::Activate() {
@@ -280,29 +84,14 @@ void InstrumentationRuntimeASan::Activate() {
if (!process_sp)
return;
- ConstString symbol_name("_ZN6__asanL7AsanDieEv");
- const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType(
- symbol_name, eSymbolTypeCode);
-
- if (symbol == nullptr)
- return;
+ Breakpoint *breakpoint = ReportRetriever::SetupBreakpoint(
+ GetRuntimeModuleSP(), process_sp, ConstString("_ZN6__asanL7AsanDieEv"));
- if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid())
+ if (!breakpoint)
return;
- Target &target = process_sp->GetTarget();
- addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target);
-
- if (symbol_address == LLDB_INVALID_ADDRESS)
- return;
-
- const bool internal = true;
- const bool hardware = false;
const bool sync = false;
- Breakpoint *breakpoint =
- process_sp->GetTarget()
- .CreateBreakpoint(symbol_address, internal, hardware)
- .get();
+
breakpoint->SetCallback(InstrumentationRuntimeASan::NotifyBreakpointHit, this,
sync);
breakpoint->SetBreakpointKind("address-sanitizer-report");
@@ -312,12 +101,13 @@ void InstrumentationRuntimeASan::Activate() {
}
void InstrumentationRuntimeASan::Deactivate() {
- if (GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
- ProcessSP process_sp = GetProcessSP();
- if (process_sp) {
- process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID());
- SetBreakpointID(LLDB_INVALID_BREAK_ID);
- }
- }
SetActive(false);
+
+ if (GetBreakpointID() == LLDB_INVALID_BREAK_ID)
+ return;
+
+ if (ProcessSP process_sp = GetProcessSP()) {
+ process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID());
+ SetBreakpointID(LLDB_INVALID_BREAK_ID);
+ }
}
diff --git a/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.h b/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.h
index 83a88cf7f89fadf..177959d7126be9e 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.h
+++ b/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.h
@@ -10,9 +10,6 @@
#define LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_ASAN_INSTRUMENTATIONRUNTIMEASAN_H
#include "lldb/Target/InstrumentationRuntime.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Utility/StructuredData.h"
-#include "lldb/lldb-private.h"
namespace lldb_private {
@@ -51,10 +48,6 @@ class InstrumentationRuntimeASan : public lldb_private::InstrumentationRuntime {
StoppointCallbackContext *context,
lldb::user_id_t break_id,
lldb::user_id_t break_loc_id);
-
- StructuredData::ObjectSP RetrieveReportData();
-
- std::string FormatDescription(StructuredData::ObjectSP report);
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt b/lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt
index 55e8752e74242ae..72ccce2dca45a94 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt
+++ b/lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt
@@ -2,3 +2,4 @@ add_subdirectory(ASan)
add_subdirectory(MainThreadChecker)
add_subdirectory(TSan)
add_subdirectory(UBSan)
+add_subdirectory(Utility)
diff --git a/lldb/source/Plugins/InstrumentationRuntime/Utility/CMakeLists.txt b/lldb/source/Plugins/InstrumentationRuntime/Utility/CMakeLists.txt
new file mode 100644
index 000000000000000..05f05c81392276c
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_lldb_library(lldbPluginInstrumentationRuntimeUtility
+ ReportRetriever.cpp
+
+ LINK_LIBS
+ lldbBreakpoint
+ lldbCore
+ lldbExpression
+ lldbSymbol
+ lldbTarget
+ )
diff --git a/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp b/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp
new file mode 100644
index 000000000000000..ff58c4cababae32
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp
@@ -0,0 +1,252 @@
+//===-- ReportRetriever.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReportRetriever.h"
+
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Expression/UserExpression.h"
+#include "lldb/Target/InstrumentationRuntimeStopInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const char *address_sanitizer_retrieve_report_data_prefix = R"(
+extern "C"
+{
+int __asan_report_present();
+void *__asan_get_report_pc();
+void *__asan_get_report_bp();
+void *__asan_get_report_sp();
+void *__asan_get_report_address();
+const char *__asan_get_report_description();
+int __asan_get_report_access_type();
+size_t __asan_get_report_access_size();
+}
+)";
+
+const char *address_sanitizer_retrieve_report_data_command = R"(
+struct {
+ int present;
+ int access_type;
+ void *pc;
+ void *bp;
+ void *sp;
+ void *address;
+ size_t access_size;
+ const char *description;
+} t;
+
+t.present = __asan_report_present();
+t.access_type = __asan_get_report_access_type();
+t.pc = __asan_get_report_pc();
+t.bp = __asan_get_report_bp();
+t.sp = __asan_get_report_sp();
+t.address = __asan_get_report_address();
+t.access_size = __asan_get_report_access_size();
+t.description = __asan_get_report_description();
+t
+)";
+
+StructuredData::ObjectSP
+ReportRetriever::RetrieveReportData(const ProcessSP process_sp) {
+ if (!process_sp)
+ return StructuredData::ObjectSP();
+
+ ThreadSP thread_sp =
+ process_sp->GetThreadList().GetExpressionExecutionThread();
+
+ if (!thread_sp)
+ return StructuredData::ObjectSP();
+
+ StackFrameSP frame_sp =
+ thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);
+
+ if (!frame_sp)
+ return StructuredData::ObjectSP();
+
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(true);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeout(process_sp->GetUtilityExpressionTimeout());
+ options.SetPrefix(address_sanitizer_retrieve_report_data_prefix);
+ options.SetAutoApplyFixIts(false);
+ options.SetLanguage(eLanguageTypeObjC_plus_plus);
+
+ ValueObjectSP return_value_sp;
+ ExecutionContext exe_ctx;
+ Status eval_error;
+ frame_sp->CalculateExecutionContext(exe_ctx);
+ ExpressionResults result = UserExpression::Evaluate(
+ exe_ctx, options, address_sanitizer_retrieve_report_data_command, "",
+ return_value_sp, eval_error);
+ if (result != eExpressionCompleted) {
+ StreamString ss;
+ ss << "cannot evaluate AddressSanitizer expression:\n";
+ ss << eval_error.AsCString();
+ Debugger::ReportWarning(ss.GetString().str(),
+ process_sp->GetTarget().GetDebugger().GetID());
+ 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;
+ Status error;
+ process_sp->ReadCStringFromMemory(description_ptr, description, error);
+
+ auto dict = std::make_shared<StructuredData::Dictionary>();
+ if (!dict)
+ return StructuredData::ObjectSP();
+
+ 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
+ReportRetriever::FormatDescription(StructuredData::ObjectSP report) {
+ std::string description = std::string(report->GetAsDictionary()
+ ->GetValueForKey("description")
+ ->GetAsString()
+ ->GetValue());
+ return llvm::StringSwitch<std::string>(description)
+ .Case("heap-use-after-free", "Use of deallocated memory")
+ .Case("heap-buffer-overflow", "Heap buffer overflow")
+ .Case("stack-buffer-underflow", "Stack buffer underflow")
+ .Case("initialization-order-fiasco", "Initialization order problem")
+ .Case("stack-buffer-overflow", "Stack buffer overflow")
+ .Case("stack-use-after-return", "Use of stack memory after return")
+ .Case("use-after-poison", "Use of poisoned memory")
+ .Case("container-overflow", "Container overflow")
+ .Case("stack-use-after-scope", "Use of out-of-scope stack memory")
+ .Case("global-buffer-overflow", "Global buffer overflow")
+ .Case("unknown-crash", "Invalid memory access")
+ .Case("stack-overflow", "Stack space exhausted")
+ .Case("null-deref", "Dereference of null pointer")
+ .Case("wild-jump", "Jump to non-executable address")
+ .Case("wild-addr-write", "Write through wild pointer")
+ .Case("wild-addr-read", "Read from wild pointer")
+ .Case("wild-addr", "Access through wild pointer")
+ .Case("signal", "Deadly signal")
+ .Case("double-free", "Deallocation of freed memory")
+ .Case("new-delete-type-mismatch",
+ "Deallocation size different from allocation size")
+ .Case("bad-free", "Deallocation of non-allocated memory")
+ .Case("alloc-dealloc-mismatch",
+ "Mismatch between allocation and deallocation APIs")
+ .Case("bad-malloc_usable_size", "Invalid argument to malloc_usable_size")
+ .Case("bad-__sanitizer_get_allocated_size",
+ "Invalid argument to __sanitizer_get_allocated_size")
+ .Case("param-overlap",
+ "Call to function disallowing overlapping memory ranges")
+ .Case("negative-size-param", "Negative size used when accessing memory")
+ .Case("bad-__sanitizer_annotate_contiguous_container",
+ "Invalid argument to __sanitizer_annotate_contiguous_container")
+ .Case("odr-violation", "Symbol defined in multiple translation units")
+ .Case(
+ "invalid-pointer-pair",
+ "Comparison or arithmetic on pointers from different memory regions")
+ // for unknown report codes just show the code
+ .Default("AddressSanitizer detected: " + description);
+}
+
+bool ReportRetriever::NotifyBreakpointHit(ProcessSP process_sp,
+ StoppointCallbackContext *context,
+ user_id_t break_id,
+ user_id_t break_loc_id) {
+ // Make sure this is the right process
+ if (!process_sp || process_sp != context->exe_ctx_ref.GetProcessSP())
+ return false;
+
+ if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
+ return false;
+
+ StructuredData::ObjectSP report = RetrieveReportData(process_sp);
+ if (!report || report->GetType() != lldb::eStructuredDataTypeDictionary)
+ return false;
+
+ std::string description = FormatDescription(report);
+
+ if (ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP())
+ thread_sp->SetStopInfo(
+ InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(
+ *thread_sp, description, report));
+
+ if (StreamFileSP stream_sp = StreamFileSP(
+ process_sp->GetTarget().GetDebugger().GetOutputStreamSP()))
+ stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread "
+ "info -s' to get extended information about the "
+ "report.\n");
+
+ return true; // Return true to stop the target
+}
+
+Breakpoint *ReportRetriever::SetupBreakpoint(ModuleSP module_sp,
+ ProcessSP process_sp,
+ ConstString symbol_name) {
+ if (!module_sp || !process_sp)
+ return nullptr;
+
+ const Symbol *symbol =
+ module_sp->FindFirstSymbolWithNameAndType(symbol_name, eSymbolTypeCode);
+
+ if (symbol == nullptr)
+ return nullptr;
+
+ if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid())
+ return nullptr;
+
+ Target &target = process_sp->GetTarget();
+ addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target);
+
+ if (symbol_address == LLDB_INVALID_ADDRESS)
+ return nullptr;
+
+ const bool internal = true;
+ const bool hardware = false;
+
+ Breakpoint *breakpoint =
+ process_sp->GetTarget()
+ .CreateBreakpoint(symbol_address, internal, hardware)
+ .get();
+
+ return breakpoint;
+}
diff --git a/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.h b/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.h
new file mode 100644
index 000000000000000..a45339a5809c01c
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.h
@@ -0,0 +1,34 @@
+//===-- ReportRetriever.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/Process.h"
+
+#ifndef LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_REPORTRETRIEVER_H
+#define LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_REPORTRETRIEVER_H
+
+namespace lldb_private {
+
+class ReportRetriever {
+private:
+ static StructuredData::ObjectSP
+ RetrieveReportData(const lldb::ProcessSP process_sp);
+
+ static std::string FormatDescription(StructuredData::ObjectSP report);
+
+public:
+ static bool NotifyBreakpointHit(lldb::ProcessSP process_sp,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ static Breakpoint *SetupBreakpoint(lldb::ModuleSP, lldb::ProcessSP,
+ ConstString);
+};
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_REPORTRETRIEVER_H
>From 3586c7d4e6c4e041fc78fafd848827f0f4048744 Mon Sep 17 00:00:00 2001
From: usama <u_hameed at apple.com>
Date: Thu, 19 Oct 2023 11:20:43 -0700
Subject: [PATCH 2/2] [lldb] Add a new plugin ASanLibsanitizers
This commit adds ASanLibsanitizers, a new runtime plugin for ASan. The
plugin provides the same functionality as InstrumentationRuntimeASan,
but provides a different set of symbols/library names to search for
while activating the plugin.
rdar://112491689
---
.../ASanLibsanitizers/CMakeLists.txt | 10 ++
.../InstrumentationRuntimeASan.cpp | 120 ++++++++++++++++++
.../InstrumentationRuntimeASan.h | 52 ++++++++
.../InstrumentationRuntime/CMakeLists.txt | 1 +
4 files changed, 183 insertions(+)
create mode 100644 lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/CMakeLists.txt
create mode 100644 lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASan.cpp
create mode 100644 lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASan.h
diff --git a/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/CMakeLists.txt b/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/CMakeLists.txt
new file mode 100644
index 000000000000000..fe96fdcc83fa28f
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_lldb_library(lldbPluginInstrumentationRuntimeASanLibsanitizers PLUGIN
+ InstrumentationRuntimeASan.cpp
+
+ LINK_LIBS
+ lldbBreakpoint
+ lldbCore
+ lldbSymbol
+ lldbTarget
+ lldbPluginInstrumentationRuntimeUtility
+ )
diff --git a/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASan.cpp b/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASan.cpp
new file mode 100644
index 000000000000000..b407b1eb828633c
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASan.cpp
@@ -0,0 +1,120 @@
+//===-- InstrumentationRuntimeASan.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "InstrumentationRuntimeASan.h"
+
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/RegularExpression.h"
+
+#include "Plugins/InstrumentationRuntime/Utility/ReportRetriever.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(InstrumentationRuntimeASanLibsanitizers)
+
+lldb::InstrumentationRuntimeSP
+InstrumentationRuntimeASanLibsanitizers::CreateInstance(
+ const lldb::ProcessSP &process_sp) {
+ return InstrumentationRuntimeSP(
+ new InstrumentationRuntimeASanLibsanitizers(process_sp));
+}
+
+void InstrumentationRuntimeASanLibsanitizers::Initialize() {
+ PluginManager::RegisterPlugin(
+ GetPluginNameStatic(),
+ "AddressSanitizer instrumentation runtime plugin for Libsanitizers.",
+ CreateInstance, GetTypeStatic);
+}
+
+void InstrumentationRuntimeASanLibsanitizers::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+lldb::InstrumentationRuntimeType
+InstrumentationRuntimeASanLibsanitizers::GetTypeStatic() {
+ return eInstrumentationRuntimeTypeLibsanitizersAsan;
+}
+
+InstrumentationRuntimeASanLibsanitizers::
+ ~InstrumentationRuntimeASanLibsanitizers() {
+ Deactivate();
+}
+
+const RegularExpression &
+InstrumentationRuntimeASanLibsanitizers::GetPatternForRuntimeLibrary() {
+ static RegularExpression regex(
+ llvm::StringRef("libsystem_sanitizers\\.dylib"));
+ return regex;
+}
+
+bool InstrumentationRuntimeASanLibsanitizers::CheckIfRuntimeIsValid(
+ const lldb::ModuleSP module_sp) {
+ const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(
+ ConstString("__asan_abi_init"), lldb::eSymbolTypeAny);
+
+ return symbol != nullptr;
+}
+
+bool InstrumentationRuntimeASanLibsanitizers::NotifyBreakpointHit(
+ void *baton, StoppointCallbackContext *context, user_id_t break_id,
+ user_id_t break_loc_id) {
+ assert(baton && "null baton");
+ if (!baton)
+ return false;
+
+ InstrumentationRuntimeASanLibsanitizers *const instance =
+ static_cast<InstrumentationRuntimeASanLibsanitizers *>(baton);
+
+ ProcessSP process_sp = instance->GetProcessSP();
+
+ return ReportRetriever::NotifyBreakpointHit(process_sp, context, break_id,
+ break_loc_id);
+}
+
+void InstrumentationRuntimeASanLibsanitizers::Activate() {
+ if (IsActive())
+ return;
+
+ ProcessSP process_sp = GetProcessSP();
+ if (!process_sp)
+ return;
+
+ Breakpoint *breakpoint = ReportRetriever::SetupBreakpoint(
+ GetRuntimeModuleSP(), process_sp,
+ ConstString("_Z22raise_sanitizers_error23sanitizer_error_context"));
+
+ if (!breakpoint)
+ return;
+
+ const bool sync = false;
+
+ breakpoint->SetCallback(
+ InstrumentationRuntimeASanLibsanitizers::NotifyBreakpointHit, this, sync);
+ breakpoint->SetBreakpointKind("address-sanitizer-report");
+ SetBreakpointID(breakpoint->GetID());
+
+ SetActive(true);
+}
+
+void InstrumentationRuntimeASanLibsanitizers::Deactivate() {
+ SetActive(false);
+
+ if (GetBreakpointID() == LLDB_INVALID_BREAK_ID)
+ return;
+
+ if (ProcessSP process_sp = GetProcessSP()) {
+ process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID());
+ SetBreakpointID(LLDB_INVALID_BREAK_ID);
+ }
+}
diff --git a/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASan.h b/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASan.h
new file mode 100644
index 000000000000000..962935ddc68f02e
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASan.h
@@ -0,0 +1,52 @@
+//===-- InstrumentationRuntimeASan.h ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_ASANLIBSANITIZERS_INSTRUMENTATIONRUNTIMEASAN_H
+#define LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_ASANLIBSANITIZERS_INSTRUMENTATIONRUNTIMEASAN_H
+
+#include "lldb/Target/InstrumentationRuntime.h"
+
+class InstrumentationRuntimeASanLibsanitizers
+ : public lldb_private::InstrumentationRuntime {
+public:
+ ~InstrumentationRuntimeASanLibsanitizers() override;
+
+ static lldb::InstrumentationRuntimeSP
+ CreateInstance(const lldb::ProcessSP &process_sp);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static llvm::StringRef GetPluginNameStatic() { return "Libsanitizers-ASan"; }
+
+ static lldb::InstrumentationRuntimeType GetTypeStatic();
+
+ llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+
+ virtual lldb::InstrumentationRuntimeType GetType() { return GetTypeStatic(); }
+
+private:
+ InstrumentationRuntimeASanLibsanitizers(const lldb::ProcessSP &process_sp)
+ : lldb_private::InstrumentationRuntime(process_sp) {}
+
+ const lldb_private::RegularExpression &GetPatternForRuntimeLibrary() override;
+
+ bool CheckIfRuntimeIsValid(const lldb::ModuleSP module_sp) override;
+
+ void Activate() override;
+
+ void Deactivate();
+
+ static bool
+ NotifyBreakpointHit(void *baton,
+ lldb_private::StoppointCallbackContext *context,
+ lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
+};
+
+#endif // LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_ASANLIBSANITIZERS_INSTRUMENTATIONRUNTIMEASAN_H
diff --git a/lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt b/lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt
index 72ccce2dca45a94..7f301bca14a8375 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt
+++ b/lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt
@@ -1,4 +1,5 @@
add_subdirectory(ASan)
+add_subdirectory(ASanLibsanitizers)
add_subdirectory(MainThreadChecker)
add_subdirectory(TSan)
add_subdirectory(UBSan)
More information about the lldb-commits
mailing list