[Lldb-commits] [lldb] [lldb] Refactor InstrumentationRuntimeAsan and add a new plugin (PR #69388)
Alex Langford via lldb-commits
lldb-commits at lists.llvm.org
Wed Oct 18 08:56:49 PDT 2023
================
@@ -0,0 +1,241 @@
+//===-- ReportRetriever.cpp ----------------------------*- 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 "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();
+ 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
+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) {
+
+ if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
----------------
bulbazord wrote:
On line 196 you check that `process_sp` is valid before using it, but you use it before checking validity up here. Let's hoist that check higher up.
https://github.com/llvm/llvm-project/pull/69388
More information about the lldb-commits
mailing list