Path: blob/main/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp
39654 views
//===-- ReportRetriever.cpp -----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "ReportRetriever.h"910#include "lldb/Breakpoint/StoppointCallbackContext.h"11#include "lldb/Core/Debugger.h"12#include "lldb/Core/Module.h"13#include "lldb/Core/ValueObject.h"14#include "lldb/Expression/UserExpression.h"15#include "lldb/Target/InstrumentationRuntimeStopInfo.h"1617using namespace lldb;18using namespace lldb_private;1920const char *address_sanitizer_retrieve_report_data_prefix = R"(21extern "C"22{23int __asan_report_present();24void *__asan_get_report_pc();25void *__asan_get_report_bp();26void *__asan_get_report_sp();27void *__asan_get_report_address();28const char *__asan_get_report_description();29int __asan_get_report_access_type();30size_t __asan_get_report_access_size();31}32)";3334const char *address_sanitizer_retrieve_report_data_command = R"(35struct {36int present;37int access_type;38void *pc;39void *bp;40void *sp;41void *address;42size_t access_size;43const char *description;44} t;4546t.present = __asan_report_present();47t.access_type = __asan_get_report_access_type();48t.pc = __asan_get_report_pc();49t.bp = __asan_get_report_bp();50t.sp = __asan_get_report_sp();51t.address = __asan_get_report_address();52t.access_size = __asan_get_report_access_size();53t.description = __asan_get_report_description();54t55)";5657StructuredData::ObjectSP58ReportRetriever::RetrieveReportData(const ProcessSP process_sp) {59if (!process_sp)60return StructuredData::ObjectSP();6162ThreadSP thread_sp =63process_sp->GetThreadList().GetExpressionExecutionThread();6465if (!thread_sp)66return StructuredData::ObjectSP();6768StackFrameSP frame_sp =69thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);7071if (!frame_sp)72return StructuredData::ObjectSP();7374EvaluateExpressionOptions options;75options.SetUnwindOnError(true);76options.SetTryAllThreads(true);77options.SetStopOthers(true);78options.SetIgnoreBreakpoints(true);79options.SetTimeout(process_sp->GetUtilityExpressionTimeout());80options.SetPrefix(address_sanitizer_retrieve_report_data_prefix);81options.SetAutoApplyFixIts(false);82options.SetLanguage(eLanguageTypeObjC_plus_plus);8384ValueObjectSP return_value_sp;85ExecutionContext exe_ctx;86Status eval_error;87frame_sp->CalculateExecutionContext(exe_ctx);88ExpressionResults result = UserExpression::Evaluate(89exe_ctx, options, address_sanitizer_retrieve_report_data_command, "",90return_value_sp, eval_error);91if (result != eExpressionCompleted) {92StreamString ss;93ss << "cannot evaluate AddressSanitizer expression:\n";94ss << eval_error.AsCString();95Debugger::ReportWarning(ss.GetString().str(),96process_sp->GetTarget().GetDebugger().GetID());97return StructuredData::ObjectSP();98}99100int present = return_value_sp->GetValueForExpressionPath(".present")101->GetValueAsUnsigned(0);102if (present != 1)103return StructuredData::ObjectSP();104105addr_t pc =106return_value_sp->GetValueForExpressionPath(".pc")->GetValueAsUnsigned(0);107addr_t bp =108return_value_sp->GetValueForExpressionPath(".bp")->GetValueAsUnsigned(0);109addr_t sp =110return_value_sp->GetValueForExpressionPath(".sp")->GetValueAsUnsigned(0);111addr_t address = return_value_sp->GetValueForExpressionPath(".address")112->GetValueAsUnsigned(0);113addr_t access_type =114return_value_sp->GetValueForExpressionPath(".access_type")115->GetValueAsUnsigned(0);116addr_t access_size =117return_value_sp->GetValueForExpressionPath(".access_size")118->GetValueAsUnsigned(0);119addr_t description_ptr =120return_value_sp->GetValueForExpressionPath(".description")121->GetValueAsUnsigned(0);122std::string description;123Status error;124process_sp->ReadCStringFromMemory(description_ptr, description, error);125126auto dict = std::make_shared<StructuredData::Dictionary>();127if (!dict)128return StructuredData::ObjectSP();129130dict->AddStringItem("instrumentation_class", "AddressSanitizer");131dict->AddStringItem("stop_type", "fatal_error");132dict->AddIntegerItem("pc", pc);133dict->AddIntegerItem("bp", bp);134dict->AddIntegerItem("sp", sp);135dict->AddIntegerItem("address", address);136dict->AddIntegerItem("access_type", access_type);137dict->AddIntegerItem("access_size", access_size);138dict->AddStringItem("description", description);139140return StructuredData::ObjectSP(dict);141}142143std::string144ReportRetriever::FormatDescription(StructuredData::ObjectSP report) {145std::string description = std::string(report->GetAsDictionary()146->GetValueForKey("description")147->GetAsString()148->GetValue());149return llvm::StringSwitch<std::string>(description)150.Case("heap-use-after-free", "Use of deallocated memory")151.Case("heap-buffer-overflow", "Heap buffer overflow")152.Case("stack-buffer-underflow", "Stack buffer underflow")153.Case("initialization-order-fiasco", "Initialization order problem")154.Case("stack-buffer-overflow", "Stack buffer overflow")155.Case("stack-use-after-return", "Use of stack memory after return")156.Case("use-after-poison", "Use of poisoned memory")157.Case("container-overflow", "Container overflow")158.Case("stack-use-after-scope", "Use of out-of-scope stack memory")159.Case("global-buffer-overflow", "Global buffer overflow")160.Case("unknown-crash", "Invalid memory access")161.Case("stack-overflow", "Stack space exhausted")162.Case("null-deref", "Dereference of null pointer")163.Case("wild-jump", "Jump to non-executable address")164.Case("wild-addr-write", "Write through wild pointer")165.Case("wild-addr-read", "Read from wild pointer")166.Case("wild-addr", "Access through wild pointer")167.Case("signal", "Deadly signal")168.Case("double-free", "Deallocation of freed memory")169.Case("new-delete-type-mismatch",170"Deallocation size different from allocation size")171.Case("bad-free", "Deallocation of non-allocated memory")172.Case("alloc-dealloc-mismatch",173"Mismatch between allocation and deallocation APIs")174.Case("bad-malloc_usable_size", "Invalid argument to malloc_usable_size")175.Case("bad-__sanitizer_get_allocated_size",176"Invalid argument to __sanitizer_get_allocated_size")177.Case("param-overlap",178"Call to function disallowing overlapping memory ranges")179.Case("negative-size-param", "Negative size used when accessing memory")180.Case("bad-__sanitizer_annotate_contiguous_container",181"Invalid argument to __sanitizer_annotate_contiguous_container")182.Case("odr-violation", "Symbol defined in multiple translation units")183.Case(184"invalid-pointer-pair",185"Comparison or arithmetic on pointers from different memory regions")186// for unknown report codes just show the code187.Default("AddressSanitizer detected: " + description);188}189190bool ReportRetriever::NotifyBreakpointHit(ProcessSP process_sp,191StoppointCallbackContext *context,192user_id_t break_id,193user_id_t break_loc_id) {194// Make sure this is the right process195if (!process_sp || process_sp != context->exe_ctx_ref.GetProcessSP())196return false;197198if (process_sp->GetModIDRef().IsLastResumeForUserExpression())199return false;200201StructuredData::ObjectSP report = RetrieveReportData(process_sp);202if (!report || report->GetType() != lldb::eStructuredDataTypeDictionary)203return false;204205std::string description = FormatDescription(report);206207if (ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP())208thread_sp->SetStopInfo(209InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(210*thread_sp, description, report));211212if (StreamFileSP stream_sp = StreamFileSP(213process_sp->GetTarget().GetDebugger().GetOutputStreamSP()))214stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread "215"info -s' to get extended information about the "216"report.\n");217218return true; // Return true to stop the target219}220221// FIXME: Setup the breakpoint using a less fragile SPI. rdar://124399066222Breakpoint *ReportRetriever::SetupBreakpoint(ModuleSP module_sp,223ProcessSP process_sp,224ConstString symbol_name) {225if (!module_sp || !process_sp)226return nullptr;227228const Symbol *symbol =229module_sp->FindFirstSymbolWithNameAndType(symbol_name, eSymbolTypeCode);230231if (symbol == nullptr)232return nullptr;233234if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid())235return nullptr;236237Target &target = process_sp->GetTarget();238addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target);239240if (symbol_address == LLDB_INVALID_ADDRESS)241return nullptr;242243const bool internal = true;244const bool hardware = false;245246Breakpoint *breakpoint =247process_sp->GetTarget()248.CreateBreakpoint(symbol_address, internal, hardware)249.get();250251return breakpoint;252}253254255