177edd9b7SUsama Hameed //===-- ReportRetriever.cpp -----------------------------------------------===// 277edd9b7SUsama Hameed // 377edd9b7SUsama Hameed // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 477edd9b7SUsama Hameed // See https://llvm.org/LICENSE.txt for license information. 577edd9b7SUsama Hameed // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 677edd9b7SUsama Hameed // 777edd9b7SUsama Hameed //===----------------------------------------------------------------------===// 877edd9b7SUsama Hameed 977edd9b7SUsama Hameed #include "ReportRetriever.h" 1077edd9b7SUsama Hameed 1177edd9b7SUsama Hameed #include "lldb/Breakpoint/StoppointCallbackContext.h" 1277edd9b7SUsama Hameed #include "lldb/Core/Debugger.h" 1377edd9b7SUsama Hameed #include "lldb/Core/Module.h" 1477edd9b7SUsama Hameed #include "lldb/Expression/UserExpression.h" 1577edd9b7SUsama Hameed #include "lldb/Target/InstrumentationRuntimeStopInfo.h" 16b852fb1eSJonas Devlieghere #include "lldb/ValueObject/ValueObject.h" 1777edd9b7SUsama Hameed 1877edd9b7SUsama Hameed using namespace lldb; 1977edd9b7SUsama Hameed using namespace lldb_private; 2077edd9b7SUsama Hameed 2177edd9b7SUsama Hameed const char *address_sanitizer_retrieve_report_data_prefix = R"( 2277edd9b7SUsama Hameed extern "C" 2377edd9b7SUsama Hameed { 2477edd9b7SUsama Hameed int __asan_report_present(); 2577edd9b7SUsama Hameed void *__asan_get_report_pc(); 2677edd9b7SUsama Hameed void *__asan_get_report_bp(); 2777edd9b7SUsama Hameed void *__asan_get_report_sp(); 2877edd9b7SUsama Hameed void *__asan_get_report_address(); 2977edd9b7SUsama Hameed const char *__asan_get_report_description(); 3077edd9b7SUsama Hameed int __asan_get_report_access_type(); 3177edd9b7SUsama Hameed size_t __asan_get_report_access_size(); 3277edd9b7SUsama Hameed } 3377edd9b7SUsama Hameed )"; 3477edd9b7SUsama Hameed 3577edd9b7SUsama Hameed const char *address_sanitizer_retrieve_report_data_command = R"( 3677edd9b7SUsama Hameed struct { 3777edd9b7SUsama Hameed int present; 3877edd9b7SUsama Hameed int access_type; 3977edd9b7SUsama Hameed void *pc; 4077edd9b7SUsama Hameed void *bp; 4177edd9b7SUsama Hameed void *sp; 4277edd9b7SUsama Hameed void *address; 4377edd9b7SUsama Hameed size_t access_size; 4477edd9b7SUsama Hameed const char *description; 4577edd9b7SUsama Hameed } t; 4677edd9b7SUsama Hameed 4777edd9b7SUsama Hameed t.present = __asan_report_present(); 4877edd9b7SUsama Hameed t.access_type = __asan_get_report_access_type(); 4977edd9b7SUsama Hameed t.pc = __asan_get_report_pc(); 5077edd9b7SUsama Hameed t.bp = __asan_get_report_bp(); 5177edd9b7SUsama Hameed t.sp = __asan_get_report_sp(); 5277edd9b7SUsama Hameed t.address = __asan_get_report_address(); 5377edd9b7SUsama Hameed t.access_size = __asan_get_report_access_size(); 5477edd9b7SUsama Hameed t.description = __asan_get_report_description(); 5577edd9b7SUsama Hameed t 5677edd9b7SUsama Hameed )"; 5777edd9b7SUsama Hameed 5877edd9b7SUsama Hameed StructuredData::ObjectSP 5977edd9b7SUsama Hameed ReportRetriever::RetrieveReportData(const ProcessSP process_sp) { 6077edd9b7SUsama Hameed if (!process_sp) 6177edd9b7SUsama Hameed return StructuredData::ObjectSP(); 6277edd9b7SUsama Hameed 6377edd9b7SUsama Hameed ThreadSP thread_sp = 6477edd9b7SUsama Hameed process_sp->GetThreadList().GetExpressionExecutionThread(); 6577edd9b7SUsama Hameed 6677edd9b7SUsama Hameed if (!thread_sp) 6777edd9b7SUsama Hameed return StructuredData::ObjectSP(); 6877edd9b7SUsama Hameed 6977edd9b7SUsama Hameed StackFrameSP frame_sp = 7077edd9b7SUsama Hameed thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame); 7177edd9b7SUsama Hameed 7277edd9b7SUsama Hameed if (!frame_sp) 7377edd9b7SUsama Hameed return StructuredData::ObjectSP(); 7477edd9b7SUsama Hameed 7577edd9b7SUsama Hameed EvaluateExpressionOptions options; 7677edd9b7SUsama Hameed options.SetUnwindOnError(true); 7777edd9b7SUsama Hameed options.SetTryAllThreads(true); 7877edd9b7SUsama Hameed options.SetStopOthers(true); 7977edd9b7SUsama Hameed options.SetIgnoreBreakpoints(true); 8077edd9b7SUsama Hameed options.SetTimeout(process_sp->GetUtilityExpressionTimeout()); 8177edd9b7SUsama Hameed options.SetPrefix(address_sanitizer_retrieve_report_data_prefix); 8277edd9b7SUsama Hameed options.SetAutoApplyFixIts(false); 8377edd9b7SUsama Hameed options.SetLanguage(eLanguageTypeObjC_plus_plus); 8477edd9b7SUsama Hameed 8577edd9b7SUsama Hameed ValueObjectSP return_value_sp; 8677edd9b7SUsama Hameed ExecutionContext exe_ctx; 8777edd9b7SUsama Hameed frame_sp->CalculateExecutionContext(exe_ctx); 8877edd9b7SUsama Hameed ExpressionResults result = UserExpression::Evaluate( 8977edd9b7SUsama Hameed exe_ctx, options, address_sanitizer_retrieve_report_data_command, "", 906a8a4d51SAdrian Prantl return_value_sp); 9177edd9b7SUsama Hameed if (result != eExpressionCompleted) { 9277edd9b7SUsama Hameed StreamString ss; 9377edd9b7SUsama Hameed ss << "cannot evaluate AddressSanitizer expression:\n"; 946a8a4d51SAdrian Prantl if (return_value_sp) 956a8a4d51SAdrian Prantl ss << return_value_sp->GetError().AsCString(); 9677edd9b7SUsama Hameed Debugger::ReportWarning(ss.GetString().str(), 9777edd9b7SUsama Hameed process_sp->GetTarget().GetDebugger().GetID()); 9877edd9b7SUsama Hameed return StructuredData::ObjectSP(); 9977edd9b7SUsama Hameed } 10077edd9b7SUsama Hameed 10177edd9b7SUsama Hameed int present = return_value_sp->GetValueForExpressionPath(".present") 10277edd9b7SUsama Hameed ->GetValueAsUnsigned(0); 10377edd9b7SUsama Hameed if (present != 1) 10477edd9b7SUsama Hameed return StructuredData::ObjectSP(); 10577edd9b7SUsama Hameed 10677edd9b7SUsama Hameed addr_t pc = 10777edd9b7SUsama Hameed return_value_sp->GetValueForExpressionPath(".pc")->GetValueAsUnsigned(0); 10877edd9b7SUsama Hameed addr_t bp = 10977edd9b7SUsama Hameed return_value_sp->GetValueForExpressionPath(".bp")->GetValueAsUnsigned(0); 11077edd9b7SUsama Hameed addr_t sp = 11177edd9b7SUsama Hameed return_value_sp->GetValueForExpressionPath(".sp")->GetValueAsUnsigned(0); 11277edd9b7SUsama Hameed addr_t address = return_value_sp->GetValueForExpressionPath(".address") 11377edd9b7SUsama Hameed ->GetValueAsUnsigned(0); 11477edd9b7SUsama Hameed addr_t access_type = 11577edd9b7SUsama Hameed return_value_sp->GetValueForExpressionPath(".access_type") 11677edd9b7SUsama Hameed ->GetValueAsUnsigned(0); 11777edd9b7SUsama Hameed addr_t access_size = 11877edd9b7SUsama Hameed return_value_sp->GetValueForExpressionPath(".access_size") 11977edd9b7SUsama Hameed ->GetValueAsUnsigned(0); 12077edd9b7SUsama Hameed addr_t description_ptr = 12177edd9b7SUsama Hameed return_value_sp->GetValueForExpressionPath(".description") 12277edd9b7SUsama Hameed ->GetValueAsUnsigned(0); 12377edd9b7SUsama Hameed std::string description; 12477edd9b7SUsama Hameed Status error; 12577edd9b7SUsama Hameed process_sp->ReadCStringFromMemory(description_ptr, description, error); 12677edd9b7SUsama Hameed 12777edd9b7SUsama Hameed auto dict = std::make_shared<StructuredData::Dictionary>(); 12877edd9b7SUsama Hameed if (!dict) 12977edd9b7SUsama Hameed return StructuredData::ObjectSP(); 13077edd9b7SUsama Hameed 13177edd9b7SUsama Hameed dict->AddStringItem("instrumentation_class", "AddressSanitizer"); 13277edd9b7SUsama Hameed dict->AddStringItem("stop_type", "fatal_error"); 13377edd9b7SUsama Hameed dict->AddIntegerItem("pc", pc); 13477edd9b7SUsama Hameed dict->AddIntegerItem("bp", bp); 13577edd9b7SUsama Hameed dict->AddIntegerItem("sp", sp); 13677edd9b7SUsama Hameed dict->AddIntegerItem("address", address); 13777edd9b7SUsama Hameed dict->AddIntegerItem("access_type", access_type); 13877edd9b7SUsama Hameed dict->AddIntegerItem("access_size", access_size); 13977edd9b7SUsama Hameed dict->AddStringItem("description", description); 14077edd9b7SUsama Hameed 14177edd9b7SUsama Hameed return StructuredData::ObjectSP(dict); 14277edd9b7SUsama Hameed } 14377edd9b7SUsama Hameed 14477edd9b7SUsama Hameed std::string 14577edd9b7SUsama Hameed ReportRetriever::FormatDescription(StructuredData::ObjectSP report) { 14677edd9b7SUsama Hameed std::string description = std::string(report->GetAsDictionary() 14777edd9b7SUsama Hameed ->GetValueForKey("description") 14877edd9b7SUsama Hameed ->GetAsString() 14977edd9b7SUsama Hameed ->GetValue()); 15077edd9b7SUsama Hameed return llvm::StringSwitch<std::string>(description) 15177edd9b7SUsama Hameed .Case("heap-use-after-free", "Use of deallocated memory") 15277edd9b7SUsama Hameed .Case("heap-buffer-overflow", "Heap buffer overflow") 15377edd9b7SUsama Hameed .Case("stack-buffer-underflow", "Stack buffer underflow") 15477edd9b7SUsama Hameed .Case("initialization-order-fiasco", "Initialization order problem") 15577edd9b7SUsama Hameed .Case("stack-buffer-overflow", "Stack buffer overflow") 15677edd9b7SUsama Hameed .Case("stack-use-after-return", "Use of stack memory after return") 15777edd9b7SUsama Hameed .Case("use-after-poison", "Use of poisoned memory") 15877edd9b7SUsama Hameed .Case("container-overflow", "Container overflow") 15977edd9b7SUsama Hameed .Case("stack-use-after-scope", "Use of out-of-scope stack memory") 16077edd9b7SUsama Hameed .Case("global-buffer-overflow", "Global buffer overflow") 16177edd9b7SUsama Hameed .Case("unknown-crash", "Invalid memory access") 16277edd9b7SUsama Hameed .Case("stack-overflow", "Stack space exhausted") 16377edd9b7SUsama Hameed .Case("null-deref", "Dereference of null pointer") 16477edd9b7SUsama Hameed .Case("wild-jump", "Jump to non-executable address") 16577edd9b7SUsama Hameed .Case("wild-addr-write", "Write through wild pointer") 16677edd9b7SUsama Hameed .Case("wild-addr-read", "Read from wild pointer") 16777edd9b7SUsama Hameed .Case("wild-addr", "Access through wild pointer") 16877edd9b7SUsama Hameed .Case("signal", "Deadly signal") 16977edd9b7SUsama Hameed .Case("double-free", "Deallocation of freed memory") 17077edd9b7SUsama Hameed .Case("new-delete-type-mismatch", 17177edd9b7SUsama Hameed "Deallocation size different from allocation size") 17277edd9b7SUsama Hameed .Case("bad-free", "Deallocation of non-allocated memory") 17377edd9b7SUsama Hameed .Case("alloc-dealloc-mismatch", 17477edd9b7SUsama Hameed "Mismatch between allocation and deallocation APIs") 17577edd9b7SUsama Hameed .Case("bad-malloc_usable_size", "Invalid argument to malloc_usable_size") 17677edd9b7SUsama Hameed .Case("bad-__sanitizer_get_allocated_size", 17777edd9b7SUsama Hameed "Invalid argument to __sanitizer_get_allocated_size") 17877edd9b7SUsama Hameed .Case("param-overlap", 17977edd9b7SUsama Hameed "Call to function disallowing overlapping memory ranges") 18077edd9b7SUsama Hameed .Case("negative-size-param", "Negative size used when accessing memory") 18177edd9b7SUsama Hameed .Case("bad-__sanitizer_annotate_contiguous_container", 18277edd9b7SUsama Hameed "Invalid argument to __sanitizer_annotate_contiguous_container") 18377edd9b7SUsama Hameed .Case("odr-violation", "Symbol defined in multiple translation units") 18477edd9b7SUsama Hameed .Case( 18577edd9b7SUsama Hameed "invalid-pointer-pair", 18677edd9b7SUsama Hameed "Comparison or arithmetic on pointers from different memory regions") 18777edd9b7SUsama Hameed // for unknown report codes just show the code 18877edd9b7SUsama Hameed .Default("AddressSanitizer detected: " + description); 18977edd9b7SUsama Hameed } 19077edd9b7SUsama Hameed 19177edd9b7SUsama Hameed bool ReportRetriever::NotifyBreakpointHit(ProcessSP process_sp, 19277edd9b7SUsama Hameed StoppointCallbackContext *context, 19377edd9b7SUsama Hameed user_id_t break_id, 19477edd9b7SUsama Hameed user_id_t break_loc_id) { 19577edd9b7SUsama Hameed // Make sure this is the right process 19677edd9b7SUsama Hameed if (!process_sp || process_sp != context->exe_ctx_ref.GetProcessSP()) 19777edd9b7SUsama Hameed return false; 19877edd9b7SUsama Hameed 19977edd9b7SUsama Hameed if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) 20077edd9b7SUsama Hameed return false; 20177edd9b7SUsama Hameed 20277edd9b7SUsama Hameed StructuredData::ObjectSP report = RetrieveReportData(process_sp); 20377edd9b7SUsama Hameed if (!report || report->GetType() != lldb::eStructuredDataTypeDictionary) 20477edd9b7SUsama Hameed return false; 20577edd9b7SUsama Hameed 20677edd9b7SUsama Hameed std::string description = FormatDescription(report); 20777edd9b7SUsama Hameed 20877edd9b7SUsama Hameed if (ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP()) 20977edd9b7SUsama Hameed thread_sp->SetStopInfo( 21077edd9b7SUsama Hameed InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData( 21177edd9b7SUsama Hameed *thread_sp, description, report)); 21277edd9b7SUsama Hameed 21377edd9b7SUsama Hameed if (StreamFileSP stream_sp = StreamFileSP( 21477edd9b7SUsama Hameed process_sp->GetTarget().GetDebugger().GetOutputStreamSP())) 21577edd9b7SUsama Hameed stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread " 21677edd9b7SUsama Hameed "info -s' to get extended information about the " 21777edd9b7SUsama Hameed "report.\n"); 21877edd9b7SUsama Hameed 21977edd9b7SUsama Hameed return true; // Return true to stop the target 22077edd9b7SUsama Hameed } 22177edd9b7SUsama Hameed 22277edd9b7SUsama Hameed Breakpoint *ReportRetriever::SetupBreakpoint(ModuleSP module_sp, 22377edd9b7SUsama Hameed ProcessSP process_sp, 22477edd9b7SUsama Hameed ConstString symbol_name) { 22577edd9b7SUsama Hameed if (!module_sp || !process_sp) 22677edd9b7SUsama Hameed return nullptr; 22777edd9b7SUsama Hameed 22877edd9b7SUsama Hameed const Symbol *symbol = 22977edd9b7SUsama Hameed module_sp->FindFirstSymbolWithNameAndType(symbol_name, eSymbolTypeCode); 23077edd9b7SUsama Hameed 23177edd9b7SUsama Hameed if (symbol == nullptr) 23277edd9b7SUsama Hameed return nullptr; 23377edd9b7SUsama Hameed 23477edd9b7SUsama Hameed if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) 23577edd9b7SUsama Hameed return nullptr; 23677edd9b7SUsama Hameed 237*01e980e7SJulian Lettner const Address &address = symbol->GetAddressRef(); 23877edd9b7SUsama Hameed const bool internal = true; 23977edd9b7SUsama Hameed const bool hardware = false; 24077edd9b7SUsama Hameed 241*01e980e7SJulian Lettner Breakpoint *breakpoint = process_sp->GetTarget() 242*01e980e7SJulian Lettner .CreateBreakpoint(address, internal, hardware) 24377edd9b7SUsama Hameed .get(); 24477edd9b7SUsama Hameed 24577edd9b7SUsama Hameed return breakpoint; 24677edd9b7SUsama Hameed } 247