diff options
Diffstat (limited to 'lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer')
-rw-r--r-- | lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp | 433 | ||||
-rw-r--r-- | lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h | 105 |
2 files changed, 260 insertions, 278 deletions
diff --git a/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp index 4e28840acc8..7b905878a0e 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp @@ -12,9 +12,9 @@ #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" -#include "lldb/Core/RegularExpression.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/RegularExpression.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" @@ -30,63 +30,47 @@ using namespace lldb; using namespace lldb_private; lldb::InstrumentationRuntimeSP -AddressSanitizerRuntime::CreateInstance (const lldb::ProcessSP &process_sp) -{ - return InstrumentationRuntimeSP(new AddressSanitizerRuntime(process_sp)); +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::Initialize() { + PluginManager::RegisterPlugin( + GetPluginNameStatic(), "AddressSanitizer instrumentation runtime plugin.", + CreateInstance, GetTypeStatic); } -void -AddressSanitizerRuntime::Terminate() -{ - PluginManager::UnregisterPlugin (CreateInstance); +void AddressSanitizerRuntime::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); } -lldb_private::ConstString -AddressSanitizerRuntime::GetPluginNameStatic() -{ - return ConstString("AddressSanitizer"); +lldb_private::ConstString AddressSanitizerRuntime::GetPluginNameStatic() { + return ConstString("AddressSanitizer"); } -lldb::InstrumentationRuntimeType -AddressSanitizerRuntime::GetTypeStatic() -{ - return eInstrumentationRuntimeTypeAddressSanitizer; +lldb::InstrumentationRuntimeType AddressSanitizerRuntime::GetTypeStatic() { + return eInstrumentationRuntimeTypeAddressSanitizer; } -AddressSanitizerRuntime::~AddressSanitizerRuntime() -{ - Deactivate(); -} +AddressSanitizerRuntime::~AddressSanitizerRuntime() { Deactivate(); } const RegularExpression & -AddressSanitizerRuntime::GetPatternForRuntimeLibrary() -{ - // FIXME: This shouldn't include the "dylib" suffix. - static RegularExpression regex("libclang_rt.asan_(.*)_dynamic\\.dylib"); - return regex; +AddressSanitizerRuntime::GetPatternForRuntimeLibrary() { + // FIXME: This shouldn't include the "dylib" suffix. + static RegularExpression regex("libclang_rt.asan_(.*)_dynamic\\.dylib"); + return regex; } -bool -AddressSanitizerRuntime::CheckIfRuntimeIsValid(const lldb::ModuleSP module_sp) -{ - const Symbol *symbol = - module_sp->FindFirstSymbolWithNameAndType(ConstString("__asan_get_alloc_stack"), lldb::eSymbolTypeAny); +bool AddressSanitizerRuntime::CheckIfRuntimeIsValid( + const lldb::ModuleSP module_sp) { + const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType( + ConstString("__asan_get_alloc_stack"), lldb::eSymbolTypeAny); - return symbol != nullptr; + return symbol != nullptr; } -#define RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC 2*1000*1000 -const char * -address_sanitizer_retrieve_report_data_prefix = R"( +#define RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC 2 * 1000 * 1000 +const char *address_sanitizer_retrieve_report_data_prefix = R"( extern "C" { int __asan_report_present(); @@ -100,8 +84,7 @@ size_t __asan_get_report_access_size(); } )"; -const char * -address_sanitizer_retrieve_report_data_command = R"( +const char *address_sanitizer_retrieve_report_data_command = R"( struct { int present; int access_type; @@ -124,194 +107,208 @@ t.description = __asan_get_report_description(); t )"; -StructuredData::ObjectSP -AddressSanitizerRuntime::RetrieveReportData() -{ - ProcessSP process_sp = GetProcessSP(); - if (!process_sp) - return StructuredData::ObjectSP(); - - ThreadSP thread_sp = process_sp->GetThreadList().GetExpressionExecutionThread(); - 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); - options.SetPrefix(address_sanitizer_retrieve_report_data_prefix); - options.SetAutoApplyFixIts(false); - options.SetLanguage(eLanguageTypeObjC_plus_plus); - - ValueObjectSP return_value_sp; - ExecutionContext exe_ctx; - Error 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) { - process_sp->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf("Warning: Cannot evaluate AddressSanitizer expression:\n%s\n", eval_error.AsCString()); - 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); - /* commented out because rdar://problem/18533301 - 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; - 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); - /* commented out because rdar://problem/18533301 - 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); +StructuredData::ObjectSP AddressSanitizerRuntime::RetrieveReportData() { + ProcessSP process_sp = GetProcessSP(); + if (!process_sp) + return StructuredData::ObjectSP(); + + ThreadSP thread_sp = + process_sp->GetThreadList().GetExpressionExecutionThread(); + 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); + options.SetPrefix(address_sanitizer_retrieve_report_data_prefix); + options.SetAutoApplyFixIts(false); + options.SetLanguage(eLanguageTypeObjC_plus_plus); + + ValueObjectSP return_value_sp; + ExecutionContext exe_ctx; + Error 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) { + process_sp->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf( + "Warning: Cannot evaluate AddressSanitizer expression:\n%s\n", + eval_error.AsCString()); + 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); + /* commented out because rdar://problem/18533301 + 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; + 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); + /* commented out because rdar://problem/18533301 + 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; +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; +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); + AddressSanitizerRuntime *const instance = + static_cast<AddressSanitizerRuntime *>(baton); - StructuredData::ObjectSP report = instance->RetrieveReportData(); - std::string description; - if (report) { - description = instance->FormatDescription(report); - } - ProcessSP process_sp = instance->GetProcessSP(); - // 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.c_str(), report)); - - StreamFileSP stream_sp (process_sp->GetTarget().GetDebugger().GetOutputFile()); - 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 + StructuredData::ObjectSP report = instance->RetrieveReportData(); + std::string description; + if (report) { + description = instance->FormatDescription(report); + } + ProcessSP process_sp = instance->GetProcessSP(); + // 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.c_str(), report)); + + StreamFileSP stream_sp( + process_sp->GetTarget().GetDebugger().GetOutputFile()); + if (stream_sp) { + stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread " + "info -s' to get extended information about the " + "report.\n"); } - else - return false; // Let target run + return true; // Return true to stop the target + } else + return false; // Let target run } -void -AddressSanitizerRuntime::Activate() -{ - if (IsActive()) - return; +void AddressSanitizerRuntime::Activate() { + if (IsActive()) + return; - ProcessSP process_sp = GetProcessSP(); - if (!process_sp) - return; - - ConstString symbol_name ("__asan::AsanDie()"); - const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType (symbol_name, eSymbolTypeCode); - - if (symbol == NULL) - return; - - if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) - return; - - Target &target = process_sp->GetTarget(); - addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target); - - if (symbol_address == LLDB_INVALID_ADDRESS) - return; - - bool internal = true; - bool hardware = false; - Breakpoint *breakpoint = process_sp->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get(); - breakpoint->SetCallback (AddressSanitizerRuntime::NotifyBreakpointHit, this, true); - breakpoint->SetBreakpointKind ("address-sanitizer-report"); - SetBreakpointID(breakpoint->GetID()); - - StreamFileSP stream_sp (process_sp->GetTarget().GetDebugger().GetOutputFile()); - if (stream_sp) - { - stream_sp->Printf ("AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.\n"); - } + ProcessSP process_sp = GetProcessSP(); + if (!process_sp) + return; + + ConstString symbol_name("__asan::AsanDie()"); + const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType( + symbol_name, eSymbolTypeCode); + + if (symbol == NULL) + return; + + if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) + return; + + Target &target = process_sp->GetTarget(); + addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target); - SetActive(true); + if (symbol_address == LLDB_INVALID_ADDRESS) + return; + + bool internal = true; + bool hardware = false; + Breakpoint *breakpoint = + process_sp->GetTarget() + .CreateBreakpoint(symbol_address, internal, hardware) + .get(); + breakpoint->SetCallback(AddressSanitizerRuntime::NotifyBreakpointHit, this, + true); + breakpoint->SetBreakpointKind("address-sanitizer-report"); + SetBreakpointID(breakpoint->GetID()); + + StreamFileSP stream_sp(process_sp->GetTarget().GetDebugger().GetOutputFile()); + if (stream_sp) { + stream_sp->Printf("AddressSanitizer debugger support is active. Memory " + "error breakpoint has been installed and you can now use " + "the 'memory history' command.\n"); + } + + SetActive(true); } -void -AddressSanitizerRuntime::Deactivate() -{ - if (GetBreakpointID() != LLDB_INVALID_BREAK_ID) - { - ProcessSP process_sp = GetProcessSP(); - if (process_sp) - { - process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID()); - SetBreakpointID(LLDB_INVALID_BREAK_ID); - } +void AddressSanitizerRuntime::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); + } + SetActive(false); } diff --git a/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h index 06aa5a0b9aa..9fd21c06f30 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h +++ b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h @@ -14,73 +14,58 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" +#include "lldb/Core/StructuredData.h" #include "lldb/Target/InstrumentationRuntime.h" #include "lldb/Target/Process.h" -#include "lldb/Core/StructuredData.h" +#include "lldb/lldb-private.h" namespace lldb_private { - -class AddressSanitizerRuntime : public lldb_private::InstrumentationRuntime -{ + +class AddressSanitizerRuntime : public lldb_private::InstrumentationRuntime { public: - ~AddressSanitizerRuntime() override; - - static lldb::InstrumentationRuntimeSP - CreateInstance (const lldb::ProcessSP &process_sp); - - static void - Initialize(); - - static void - Terminate(); - - static lldb_private::ConstString - GetPluginNameStatic(); - - static lldb::InstrumentationRuntimeType - GetTypeStatic(); - - lldb_private::ConstString - GetPluginName() override - { - return GetPluginNameStatic(); - } - - virtual lldb::InstrumentationRuntimeType - GetType() { return GetTypeStatic(); } - - uint32_t - GetPluginVersion() override - { - return 1; - } - + ~AddressSanitizerRuntime() override; + + static lldb::InstrumentationRuntimeSP + CreateInstance(const lldb::ProcessSP &process_sp); + + static void Initialize(); + + static void Terminate(); + + static lldb_private::ConstString GetPluginNameStatic(); + + static lldb::InstrumentationRuntimeType GetTypeStatic(); + + lldb_private::ConstString GetPluginName() override { + return GetPluginNameStatic(); + } + + virtual lldb::InstrumentationRuntimeType GetType() { return GetTypeStatic(); } + + uint32_t GetPluginVersion() override { return 1; } + private: - AddressSanitizerRuntime(const lldb::ProcessSP &process_sp) : lldb_private::InstrumentationRuntime(process_sp) {} - - const RegularExpression & - GetPatternForRuntimeLibrary() override; - - bool - CheckIfRuntimeIsValid(const lldb::ModuleSP module_sp) override; - - void - Activate() override; - - 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); + AddressSanitizerRuntime(const lldb::ProcessSP &process_sp) + : lldb_private::InstrumentationRuntime(process_sp) {} + + const RegularExpression &GetPatternForRuntimeLibrary() override; + + bool CheckIfRuntimeIsValid(const lldb::ModuleSP module_sp) override; + + void Activate() override; + + 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); }; - + } // namespace lldb_private #endif // liblldb_AddressSanitizerRuntime_h_ |