Skip to content

Commit 77edd9b

Browse files
authored
[lldb] Refactor InstrumentationRuntimeAsan and add a new plugin (#69388)
[lldb] Refactor InstrumentationRuntimeAsan and add a new plugin InstrumentationRuntimeLibsanitizers. 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. The commit also adds InstrumentationRuntimeASanLibsanitizers, 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
1 parent c2b64df commit 77edd9b

File tree

11 files changed

+498
-237
lines changed

11 files changed

+498
-237
lines changed

lldb/include/lldb/lldb-enumerations.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ enum InstrumentationRuntimeType {
527527
eInstrumentationRuntimeTypeUndefinedBehaviorSanitizer = 0x0002,
528528
eInstrumentationRuntimeTypeMainThreadChecker = 0x0003,
529529
eInstrumentationRuntimeTypeSwiftRuntimeReporting = 0x0004,
530+
eInstrumentationRuntimeTypeLibsanitizersAsan = 0x0005,
530531
eNumInstrumentationRuntimeTypes
531532
};
532533

lldb/source/Plugins/InstrumentationRuntime/ASan/CMakeLists.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ add_lldb_library(lldbPluginInstrumentationRuntimeASan PLUGIN
44
LINK_LIBS
55
lldbBreakpoint
66
lldbCore
7-
lldbExpression
8-
lldbInterpreter
97
lldbSymbol
108
lldbTarget
11-
LINK_COMPONENTS
12-
Support
9+
lldbPluginInstrumentationRuntimeUtility
1310
)

lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp

Lines changed: 16 additions & 226 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,14 @@
99
#include "InstrumentationRuntimeASan.h"
1010

1111
#include "lldb/Breakpoint/StoppointCallbackContext.h"
12-
#include "lldb/Core/Debugger.h"
1312
#include "lldb/Core/Module.h"
1413
#include "lldb/Core/PluginInterface.h"
1514
#include "lldb/Core/PluginManager.h"
16-
#include "lldb/Core/ValueObject.h"
17-
#include "lldb/Expression/UserExpression.h"
18-
#include "lldb/Host/StreamFile.h"
19-
#include "lldb/Interpreter/CommandReturnObject.h"
2015
#include "lldb/Symbol/Symbol.h"
21-
#include "lldb/Target/InstrumentationRuntimeStopInfo.h"
22-
#include "lldb/Target/StopInfo.h"
23-
#include "lldb/Target/Target.h"
24-
#include "lldb/Target/Thread.h"
16+
#include "lldb/Target/Process.h"
2517
#include "lldb/Utility/RegularExpression.h"
26-
#include "lldb/Utility/Stream.h"
2718

28-
#include "llvm/ADT/StringSwitch.h"
19+
#include "Plugins/InstrumentationRuntime/Utility/ReportRetriever.h"
2920

3021
using namespace lldb;
3122
using namespace lldb_private;
@@ -69,169 +60,6 @@ bool InstrumentationRuntimeASan::CheckIfRuntimeIsValid(
6960
return symbol != nullptr;
7061
}
7162

72-
const char *address_sanitizer_retrieve_report_data_prefix = R"(
73-
extern "C"
74-
{
75-
int __asan_report_present();
76-
void *__asan_get_report_pc();
77-
void *__asan_get_report_bp();
78-
void *__asan_get_report_sp();
79-
void *__asan_get_report_address();
80-
const char *__asan_get_report_description();
81-
int __asan_get_report_access_type();
82-
size_t __asan_get_report_access_size();
83-
}
84-
)";
85-
86-
const char *address_sanitizer_retrieve_report_data_command = R"(
87-
struct {
88-
int present;
89-
int access_type;
90-
void *pc;
91-
void *bp;
92-
void *sp;
93-
void *address;
94-
size_t access_size;
95-
const char *description;
96-
} t;
97-
98-
t.present = __asan_report_present();
99-
t.access_type = __asan_get_report_access_type();
100-
t.pc = __asan_get_report_pc();
101-
t.bp = __asan_get_report_bp();
102-
t.sp = __asan_get_report_sp();
103-
t.address = __asan_get_report_address();
104-
t.access_size = __asan_get_report_access_size();
105-
t.description = __asan_get_report_description();
106-
t
107-
)";
108-
109-
StructuredData::ObjectSP InstrumentationRuntimeASan::RetrieveReportData() {
110-
ProcessSP process_sp = GetProcessSP();
111-
if (!process_sp)
112-
return StructuredData::ObjectSP();
113-
114-
ThreadSP thread_sp =
115-
process_sp->GetThreadList().GetExpressionExecutionThread();
116-
StackFrameSP frame_sp =
117-
thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);
118-
119-
if (!frame_sp)
120-
return StructuredData::ObjectSP();
121-
122-
EvaluateExpressionOptions options;
123-
options.SetUnwindOnError(true);
124-
options.SetTryAllThreads(true);
125-
options.SetStopOthers(true);
126-
options.SetIgnoreBreakpoints(true);
127-
options.SetTimeout(process_sp->GetUtilityExpressionTimeout());
128-
options.SetPrefix(address_sanitizer_retrieve_report_data_prefix);
129-
options.SetAutoApplyFixIts(false);
130-
options.SetLanguage(eLanguageTypeObjC_plus_plus);
131-
132-
ValueObjectSP return_value_sp;
133-
ExecutionContext exe_ctx;
134-
Status eval_error;
135-
frame_sp->CalculateExecutionContext(exe_ctx);
136-
ExpressionResults result = UserExpression::Evaluate(
137-
exe_ctx, options, address_sanitizer_retrieve_report_data_command, "",
138-
return_value_sp, eval_error);
139-
if (result != eExpressionCompleted) {
140-
StreamString ss;
141-
ss << "cannot evaluate AddressSanitizer expression:\n";
142-
ss << eval_error.AsCString();
143-
Debugger::ReportWarning(ss.GetString().str(),
144-
process_sp->GetTarget().GetDebugger().GetID());
145-
return StructuredData::ObjectSP();
146-
}
147-
148-
int present = return_value_sp->GetValueForExpressionPath(".present")
149-
->GetValueAsUnsigned(0);
150-
if (present != 1)
151-
return StructuredData::ObjectSP();
152-
153-
addr_t pc =
154-
return_value_sp->GetValueForExpressionPath(".pc")->GetValueAsUnsigned(0);
155-
addr_t bp =
156-
return_value_sp->GetValueForExpressionPath(".bp")->GetValueAsUnsigned(0);
157-
addr_t sp =
158-
return_value_sp->GetValueForExpressionPath(".sp")->GetValueAsUnsigned(0);
159-
addr_t address = return_value_sp->GetValueForExpressionPath(".address")
160-
->GetValueAsUnsigned(0);
161-
addr_t access_type =
162-
return_value_sp->GetValueForExpressionPath(".access_type")
163-
->GetValueAsUnsigned(0);
164-
addr_t access_size =
165-
return_value_sp->GetValueForExpressionPath(".access_size")
166-
->GetValueAsUnsigned(0);
167-
addr_t description_ptr =
168-
return_value_sp->GetValueForExpressionPath(".description")
169-
->GetValueAsUnsigned(0);
170-
std::string description;
171-
Status error;
172-
process_sp->ReadCStringFromMemory(description_ptr, description, error);
173-
174-
StructuredData::Dictionary *dict = new StructuredData::Dictionary();
175-
dict->AddStringItem("instrumentation_class", "AddressSanitizer");
176-
dict->AddStringItem("stop_type", "fatal_error");
177-
dict->AddIntegerItem("pc", pc);
178-
dict->AddIntegerItem("bp", bp);
179-
dict->AddIntegerItem("sp", sp);
180-
dict->AddIntegerItem("address", address);
181-
dict->AddIntegerItem("access_type", access_type);
182-
dict->AddIntegerItem("access_size", access_size);
183-
dict->AddStringItem("description", description);
184-
185-
return StructuredData::ObjectSP(dict);
186-
}
187-
188-
std::string
189-
InstrumentationRuntimeASan::FormatDescription(StructuredData::ObjectSP report) {
190-
std::string description = std::string(report->GetAsDictionary()
191-
->GetValueForKey("description")
192-
->GetAsString()
193-
->GetValue());
194-
return llvm::StringSwitch<std::string>(description)
195-
.Case("heap-use-after-free", "Use of deallocated memory")
196-
.Case("heap-buffer-overflow", "Heap buffer overflow")
197-
.Case("stack-buffer-underflow", "Stack buffer underflow")
198-
.Case("initialization-order-fiasco", "Initialization order problem")
199-
.Case("stack-buffer-overflow", "Stack buffer overflow")
200-
.Case("stack-use-after-return", "Use of stack memory after return")
201-
.Case("use-after-poison", "Use of poisoned memory")
202-
.Case("container-overflow", "Container overflow")
203-
.Case("stack-use-after-scope", "Use of out-of-scope stack memory")
204-
.Case("global-buffer-overflow", "Global buffer overflow")
205-
.Case("unknown-crash", "Invalid memory access")
206-
.Case("stack-overflow", "Stack space exhausted")
207-
.Case("null-deref", "Dereference of null pointer")
208-
.Case("wild-jump", "Jump to non-executable address")
209-
.Case("wild-addr-write", "Write through wild pointer")
210-
.Case("wild-addr-read", "Read from wild pointer")
211-
.Case("wild-addr", "Access through wild pointer")
212-
.Case("signal", "Deadly signal")
213-
.Case("double-free", "Deallocation of freed memory")
214-
.Case("new-delete-type-mismatch",
215-
"Deallocation size different from allocation size")
216-
.Case("bad-free", "Deallocation of non-allocated memory")
217-
.Case("alloc-dealloc-mismatch",
218-
"Mismatch between allocation and deallocation APIs")
219-
.Case("bad-malloc_usable_size", "Invalid argument to malloc_usable_size")
220-
.Case("bad-__sanitizer_get_allocated_size",
221-
"Invalid argument to __sanitizer_get_allocated_size")
222-
.Case("param-overlap",
223-
"Call to function disallowing overlapping memory ranges")
224-
.Case("negative-size-param", "Negative size used when accessing memory")
225-
.Case("bad-__sanitizer_annotate_contiguous_container",
226-
"Invalid argument to __sanitizer_annotate_contiguous_container")
227-
.Case("odr-violation", "Symbol defined in multiple translation units")
228-
.Case(
229-
"invalid-pointer-pair",
230-
"Comparison or arithmetic on pointers from different memory regions")
231-
// for unknown report codes just show the code
232-
.Default("AddressSanitizer detected: " + description);
233-
}
234-
23563
bool InstrumentationRuntimeASan::NotifyBreakpointHit(
23664
void *baton, StoppointCallbackContext *context, user_id_t break_id,
23765
user_id_t break_loc_id) {
@@ -244,32 +72,8 @@ bool InstrumentationRuntimeASan::NotifyBreakpointHit(
24472

24573
ProcessSP process_sp = instance->GetProcessSP();
24674

247-
if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
248-
return false;
249-
250-
StructuredData::ObjectSP report = instance->RetrieveReportData();
251-
std::string description;
252-
if (report) {
253-
description = instance->FormatDescription(report);
254-
}
255-
// Make sure this is the right process
256-
if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) {
257-
ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
258-
if (thread_sp)
259-
thread_sp->SetStopInfo(InstrumentationRuntimeStopInfo::
260-
CreateStopReasonWithInstrumentationData(
261-
*thread_sp, description, report));
262-
263-
StreamFileSP stream_sp(
264-
process_sp->GetTarget().GetDebugger().GetOutputStreamSP());
265-
if (stream_sp) {
266-
stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread "
267-
"info -s' to get extended information about the "
268-
"report.\n");
269-
}
270-
return true; // Return true to stop the target
271-
} else
272-
return false; // Let target run
75+
return ReportRetriever::NotifyBreakpointHit(process_sp, context, break_id,
76+
break_loc_id);
27377
}
27478

27579
void InstrumentationRuntimeASan::Activate() {
@@ -280,29 +84,14 @@ void InstrumentationRuntimeASan::Activate() {
28084
if (!process_sp)
28185
return;
28286

283-
ConstString symbol_name("_ZN6__asanL7AsanDieEv");
284-
const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType(
285-
symbol_name, eSymbolTypeCode);
286-
287-
if (symbol == nullptr)
288-
return;
87+
Breakpoint *breakpoint = ReportRetriever::SetupBreakpoint(
88+
GetRuntimeModuleSP(), process_sp, ConstString("_ZN6__asanL7AsanDieEv"));
28989

290-
if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid())
90+
if (!breakpoint)
29191
return;
29292

293-
Target &target = process_sp->GetTarget();
294-
addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target);
295-
296-
if (symbol_address == LLDB_INVALID_ADDRESS)
297-
return;
298-
299-
const bool internal = true;
300-
const bool hardware = false;
30193
const bool sync = false;
302-
Breakpoint *breakpoint =
303-
process_sp->GetTarget()
304-
.CreateBreakpoint(symbol_address, internal, hardware)
305-
.get();
94+
30695
breakpoint->SetCallback(InstrumentationRuntimeASan::NotifyBreakpointHit, this,
30796
sync);
30897
breakpoint->SetBreakpointKind("address-sanitizer-report");
@@ -312,12 +101,13 @@ void InstrumentationRuntimeASan::Activate() {
312101
}
313102

314103
void InstrumentationRuntimeASan::Deactivate() {
315-
if (GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
316-
ProcessSP process_sp = GetProcessSP();
317-
if (process_sp) {
318-
process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID());
319-
SetBreakpointID(LLDB_INVALID_BREAK_ID);
320-
}
321-
}
322104
SetActive(false);
105+
106+
if (GetBreakpointID() == LLDB_INVALID_BREAK_ID)
107+
return;
108+
109+
if (ProcessSP process_sp = GetProcessSP()) {
110+
process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID());
111+
SetBreakpointID(LLDB_INVALID_BREAK_ID);
112+
}
323113
}

lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
#define LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_ASAN_INSTRUMENTATIONRUNTIMEASAN_H
1111

1212
#include "lldb/Target/InstrumentationRuntime.h"
13-
#include "lldb/Target/Process.h"
14-
#include "lldb/Utility/StructuredData.h"
15-
#include "lldb/lldb-private.h"
1613

1714
namespace lldb_private {
1815

@@ -51,10 +48,6 @@ class InstrumentationRuntimeASan : public lldb_private::InstrumentationRuntime {
5148
StoppointCallbackContext *context,
5249
lldb::user_id_t break_id,
5350
lldb::user_id_t break_loc_id);
54-
55-
StructuredData::ObjectSP RetrieveReportData();
56-
57-
std::string FormatDescription(StructuredData::ObjectSP report);
5851
};
5952

6053
} // namespace lldb_private
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
add_lldb_library(lldbPluginInstrumentationRuntimeASanLibsanitizers PLUGIN
2+
InstrumentationRuntimeASanLibsanitizers.cpp
3+
4+
LINK_LIBS
5+
lldbBreakpoint
6+
lldbCore
7+
lldbSymbol
8+
lldbTarget
9+
lldbPluginInstrumentationRuntimeUtility
10+
)

0 commit comments

Comments
 (0)