1*5f757f3fSDimitry Andric //===-- InstrumentationRuntimeASanLibsanitizers.cpp -----------------------===//
2*5f757f3fSDimitry Andric //
3*5f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5f757f3fSDimitry Andric //
7*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
8*5f757f3fSDimitry Andric 
9*5f757f3fSDimitry Andric #include "InstrumentationRuntimeASanLibsanitizers.h"
10*5f757f3fSDimitry Andric 
11*5f757f3fSDimitry Andric #include "lldb/Breakpoint/StoppointCallbackContext.h"
12*5f757f3fSDimitry Andric #include "lldb/Core/Module.h"
13*5f757f3fSDimitry Andric #include "lldb/Core/PluginInterface.h"
14*5f757f3fSDimitry Andric #include "lldb/Core/PluginManager.h"
15*5f757f3fSDimitry Andric #include "lldb/Symbol/Symbol.h"
16*5f757f3fSDimitry Andric #include "lldb/Target/Process.h"
17*5f757f3fSDimitry Andric #include "lldb/Utility/RegularExpression.h"
18*5f757f3fSDimitry Andric 
19*5f757f3fSDimitry Andric #include "Plugins/InstrumentationRuntime/Utility/ReportRetriever.h"
20*5f757f3fSDimitry Andric 
21*5f757f3fSDimitry Andric using namespace lldb;
22*5f757f3fSDimitry Andric using namespace lldb_private;
23*5f757f3fSDimitry Andric 
24*5f757f3fSDimitry Andric LLDB_PLUGIN_DEFINE(InstrumentationRuntimeASanLibsanitizers)
25*5f757f3fSDimitry Andric 
26*5f757f3fSDimitry Andric lldb::InstrumentationRuntimeSP
27*5f757f3fSDimitry Andric InstrumentationRuntimeASanLibsanitizers::CreateInstance(
28*5f757f3fSDimitry Andric     const lldb::ProcessSP &process_sp) {
29*5f757f3fSDimitry Andric   return InstrumentationRuntimeSP(
30*5f757f3fSDimitry Andric       new InstrumentationRuntimeASanLibsanitizers(process_sp));
31*5f757f3fSDimitry Andric }
32*5f757f3fSDimitry Andric 
33*5f757f3fSDimitry Andric void InstrumentationRuntimeASanLibsanitizers::Initialize() {
34*5f757f3fSDimitry Andric   PluginManager::RegisterPlugin(
35*5f757f3fSDimitry Andric       GetPluginNameStatic(),
36*5f757f3fSDimitry Andric       "AddressSanitizer instrumentation runtime plugin for Libsanitizers.",
37*5f757f3fSDimitry Andric       CreateInstance, GetTypeStatic);
38*5f757f3fSDimitry Andric }
39*5f757f3fSDimitry Andric 
40*5f757f3fSDimitry Andric void InstrumentationRuntimeASanLibsanitizers::Terminate() {
41*5f757f3fSDimitry Andric   PluginManager::UnregisterPlugin(CreateInstance);
42*5f757f3fSDimitry Andric }
43*5f757f3fSDimitry Andric 
44*5f757f3fSDimitry Andric lldb::InstrumentationRuntimeType
45*5f757f3fSDimitry Andric InstrumentationRuntimeASanLibsanitizers::GetTypeStatic() {
46*5f757f3fSDimitry Andric   return eInstrumentationRuntimeTypeLibsanitizersAsan;
47*5f757f3fSDimitry Andric }
48*5f757f3fSDimitry Andric 
49*5f757f3fSDimitry Andric InstrumentationRuntimeASanLibsanitizers::
50*5f757f3fSDimitry Andric     ~InstrumentationRuntimeASanLibsanitizers() {
51*5f757f3fSDimitry Andric   Deactivate();
52*5f757f3fSDimitry Andric }
53*5f757f3fSDimitry Andric 
54*5f757f3fSDimitry Andric const RegularExpression &
55*5f757f3fSDimitry Andric InstrumentationRuntimeASanLibsanitizers::GetPatternForRuntimeLibrary() {
56*5f757f3fSDimitry Andric   static RegularExpression regex(
57*5f757f3fSDimitry Andric       llvm::StringRef("libsystem_sanitizers\\.dylib"));
58*5f757f3fSDimitry Andric   return regex;
59*5f757f3fSDimitry Andric }
60*5f757f3fSDimitry Andric 
61*5f757f3fSDimitry Andric bool InstrumentationRuntimeASanLibsanitizers::CheckIfRuntimeIsValid(
62*5f757f3fSDimitry Andric     const lldb::ModuleSP module_sp) {
63*5f757f3fSDimitry Andric   const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(
64*5f757f3fSDimitry Andric       ConstString("__asan_abi_init"), lldb::eSymbolTypeAny);
65*5f757f3fSDimitry Andric 
66*5f757f3fSDimitry Andric   return symbol != nullptr;
67*5f757f3fSDimitry Andric }
68*5f757f3fSDimitry Andric 
69*5f757f3fSDimitry Andric bool InstrumentationRuntimeASanLibsanitizers::NotifyBreakpointHit(
70*5f757f3fSDimitry Andric     void *baton, StoppointCallbackContext *context, user_id_t break_id,
71*5f757f3fSDimitry Andric     user_id_t break_loc_id) {
72*5f757f3fSDimitry Andric   assert(baton && "null baton");
73*5f757f3fSDimitry Andric   if (!baton)
74*5f757f3fSDimitry Andric     return false;
75*5f757f3fSDimitry Andric 
76*5f757f3fSDimitry Andric   InstrumentationRuntimeASanLibsanitizers *const instance =
77*5f757f3fSDimitry Andric       static_cast<InstrumentationRuntimeASanLibsanitizers *>(baton);
78*5f757f3fSDimitry Andric 
79*5f757f3fSDimitry Andric   ProcessSP process_sp = instance->GetProcessSP();
80*5f757f3fSDimitry Andric 
81*5f757f3fSDimitry Andric   return ReportRetriever::NotifyBreakpointHit(process_sp, context, break_id,
82*5f757f3fSDimitry Andric                                               break_loc_id);
83*5f757f3fSDimitry Andric }
84*5f757f3fSDimitry Andric 
85*5f757f3fSDimitry Andric void InstrumentationRuntimeASanLibsanitizers::Activate() {
86*5f757f3fSDimitry Andric   if (IsActive())
87*5f757f3fSDimitry Andric     return;
88*5f757f3fSDimitry Andric 
89*5f757f3fSDimitry Andric   ProcessSP process_sp = GetProcessSP();
90*5f757f3fSDimitry Andric   if (!process_sp)
91*5f757f3fSDimitry Andric     return;
92*5f757f3fSDimitry Andric 
93*5f757f3fSDimitry Andric   Breakpoint *breakpoint = ReportRetriever::SetupBreakpoint(
94*5f757f3fSDimitry Andric       GetRuntimeModuleSP(), process_sp,
95*5f757f3fSDimitry Andric       ConstString("_Z22raise_sanitizers_error23sanitizer_error_context"));
96*5f757f3fSDimitry Andric 
97*5f757f3fSDimitry Andric   if (!breakpoint)
98*5f757f3fSDimitry Andric     return;
99*5f757f3fSDimitry Andric 
100*5f757f3fSDimitry Andric   const bool sync = false;
101*5f757f3fSDimitry Andric 
102*5f757f3fSDimitry Andric   breakpoint->SetCallback(
103*5f757f3fSDimitry Andric       InstrumentationRuntimeASanLibsanitizers::NotifyBreakpointHit, this, sync);
104*5f757f3fSDimitry Andric   breakpoint->SetBreakpointKind("address-sanitizer-report");
105*5f757f3fSDimitry Andric   SetBreakpointID(breakpoint->GetID());
106*5f757f3fSDimitry Andric 
107*5f757f3fSDimitry Andric   SetActive(true);
108*5f757f3fSDimitry Andric }
109*5f757f3fSDimitry Andric 
110*5f757f3fSDimitry Andric void InstrumentationRuntimeASanLibsanitizers::Deactivate() {
111*5f757f3fSDimitry Andric   SetActive(false);
112*5f757f3fSDimitry Andric 
113*5f757f3fSDimitry Andric   if (GetBreakpointID() == LLDB_INVALID_BREAK_ID)
114*5f757f3fSDimitry Andric     return;
115*5f757f3fSDimitry Andric 
116*5f757f3fSDimitry Andric   if (ProcessSP process_sp = GetProcessSP()) {
117*5f757f3fSDimitry Andric     process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID());
118*5f757f3fSDimitry Andric     SetBreakpointID(LLDB_INVALID_BREAK_ID);
119*5f757f3fSDimitry Andric   }
120*5f757f3fSDimitry Andric }
121