15f757f3fSDimitry Andric //===-- InstrumentationRuntimeASanLibsanitizers.cpp -----------------------===//
25f757f3fSDimitry Andric //
35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f757f3fSDimitry Andric //
75f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
85f757f3fSDimitry Andric 
95f757f3fSDimitry Andric #include "InstrumentationRuntimeASanLibsanitizers.h"
105f757f3fSDimitry Andric 
115f757f3fSDimitry Andric #include "lldb/Breakpoint/StoppointCallbackContext.h"
125f757f3fSDimitry Andric #include "lldb/Core/Module.h"
135f757f3fSDimitry Andric #include "lldb/Core/PluginInterface.h"
145f757f3fSDimitry Andric #include "lldb/Core/PluginManager.h"
155f757f3fSDimitry Andric #include "lldb/Symbol/Symbol.h"
165f757f3fSDimitry Andric #include "lldb/Target/Process.h"
175f757f3fSDimitry Andric #include "lldb/Utility/RegularExpression.h"
185f757f3fSDimitry Andric 
195f757f3fSDimitry Andric #include "Plugins/InstrumentationRuntime/Utility/ReportRetriever.h"
205f757f3fSDimitry Andric 
215f757f3fSDimitry Andric using namespace lldb;
225f757f3fSDimitry Andric using namespace lldb_private;
235f757f3fSDimitry Andric 
245f757f3fSDimitry Andric LLDB_PLUGIN_DEFINE(InstrumentationRuntimeASanLibsanitizers)
255f757f3fSDimitry Andric 
265f757f3fSDimitry Andric lldb::InstrumentationRuntimeSP
275f757f3fSDimitry Andric InstrumentationRuntimeASanLibsanitizers::CreateInstance(
285f757f3fSDimitry Andric     const lldb::ProcessSP &process_sp) {
295f757f3fSDimitry Andric   return InstrumentationRuntimeSP(
305f757f3fSDimitry Andric       new InstrumentationRuntimeASanLibsanitizers(process_sp));
315f757f3fSDimitry Andric }
325f757f3fSDimitry Andric 
335f757f3fSDimitry Andric void InstrumentationRuntimeASanLibsanitizers::Initialize() {
345f757f3fSDimitry Andric   PluginManager::RegisterPlugin(
355f757f3fSDimitry Andric       GetPluginNameStatic(),
365f757f3fSDimitry Andric       "AddressSanitizer instrumentation runtime plugin for Libsanitizers.",
375f757f3fSDimitry Andric       CreateInstance, GetTypeStatic);
385f757f3fSDimitry Andric }
395f757f3fSDimitry Andric 
405f757f3fSDimitry Andric void InstrumentationRuntimeASanLibsanitizers::Terminate() {
415f757f3fSDimitry Andric   PluginManager::UnregisterPlugin(CreateInstance);
425f757f3fSDimitry Andric }
435f757f3fSDimitry Andric 
445f757f3fSDimitry Andric lldb::InstrumentationRuntimeType
455f757f3fSDimitry Andric InstrumentationRuntimeASanLibsanitizers::GetTypeStatic() {
465f757f3fSDimitry Andric   return eInstrumentationRuntimeTypeLibsanitizersAsan;
475f757f3fSDimitry Andric }
485f757f3fSDimitry Andric 
495f757f3fSDimitry Andric InstrumentationRuntimeASanLibsanitizers::
505f757f3fSDimitry Andric     ~InstrumentationRuntimeASanLibsanitizers() {
515f757f3fSDimitry Andric   Deactivate();
525f757f3fSDimitry Andric }
535f757f3fSDimitry Andric 
545f757f3fSDimitry Andric const RegularExpression &
555f757f3fSDimitry Andric InstrumentationRuntimeASanLibsanitizers::GetPatternForRuntimeLibrary() {
565f757f3fSDimitry Andric   static RegularExpression regex(
575f757f3fSDimitry Andric       llvm::StringRef("libsystem_sanitizers\\.dylib"));
585f757f3fSDimitry Andric   return regex;
595f757f3fSDimitry Andric }
605f757f3fSDimitry Andric 
615f757f3fSDimitry Andric bool InstrumentationRuntimeASanLibsanitizers::CheckIfRuntimeIsValid(
625f757f3fSDimitry Andric     const lldb::ModuleSP module_sp) {
635f757f3fSDimitry Andric   const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(
645f757f3fSDimitry Andric       ConstString("__asan_abi_init"), lldb::eSymbolTypeAny);
655f757f3fSDimitry Andric 
665f757f3fSDimitry Andric   return symbol != nullptr;
675f757f3fSDimitry Andric }
685f757f3fSDimitry Andric 
695f757f3fSDimitry Andric bool InstrumentationRuntimeASanLibsanitizers::NotifyBreakpointHit(
705f757f3fSDimitry Andric     void *baton, StoppointCallbackContext *context, user_id_t break_id,
715f757f3fSDimitry Andric     user_id_t break_loc_id) {
725f757f3fSDimitry Andric   assert(baton && "null baton");
735f757f3fSDimitry Andric   if (!baton)
745f757f3fSDimitry Andric     return false;
755f757f3fSDimitry Andric 
765f757f3fSDimitry Andric   InstrumentationRuntimeASanLibsanitizers *const instance =
775f757f3fSDimitry Andric       static_cast<InstrumentationRuntimeASanLibsanitizers *>(baton);
785f757f3fSDimitry Andric 
795f757f3fSDimitry Andric   ProcessSP process_sp = instance->GetProcessSP();
805f757f3fSDimitry Andric 
815f757f3fSDimitry Andric   return ReportRetriever::NotifyBreakpointHit(process_sp, context, break_id,
825f757f3fSDimitry Andric                                               break_loc_id);
835f757f3fSDimitry Andric }
845f757f3fSDimitry Andric 
855f757f3fSDimitry Andric void InstrumentationRuntimeASanLibsanitizers::Activate() {
865f757f3fSDimitry Andric   if (IsActive())
875f757f3fSDimitry Andric     return;
885f757f3fSDimitry Andric 
895f757f3fSDimitry Andric   ProcessSP process_sp = GetProcessSP();
905f757f3fSDimitry Andric   if (!process_sp)
915f757f3fSDimitry Andric     return;
925f757f3fSDimitry Andric 
93*0fca6ea1SDimitry Andric   lldb::ModuleSP module_sp = GetRuntimeModuleSP();
94*0fca6ea1SDimitry Andric 
955f757f3fSDimitry Andric   Breakpoint *breakpoint = ReportRetriever::SetupBreakpoint(
96*0fca6ea1SDimitry Andric       module_sp, process_sp, ConstString("sanitizers_address_on_report"));
97*0fca6ea1SDimitry Andric 
98*0fca6ea1SDimitry Andric   if (!breakpoint) {
99*0fca6ea1SDimitry Andric     breakpoint = ReportRetriever::SetupBreakpoint(
100*0fca6ea1SDimitry Andric         module_sp, process_sp,
1015f757f3fSDimitry Andric         ConstString("_Z22raise_sanitizers_error23sanitizer_error_context"));
102*0fca6ea1SDimitry Andric   }
1035f757f3fSDimitry Andric 
1045f757f3fSDimitry Andric   if (!breakpoint)
1055f757f3fSDimitry Andric     return;
1065f757f3fSDimitry Andric 
1075f757f3fSDimitry Andric   const bool sync = false;
1085f757f3fSDimitry Andric 
1095f757f3fSDimitry Andric   breakpoint->SetCallback(
1105f757f3fSDimitry Andric       InstrumentationRuntimeASanLibsanitizers::NotifyBreakpointHit, this, sync);
1115f757f3fSDimitry Andric   breakpoint->SetBreakpointKind("address-sanitizer-report");
1125f757f3fSDimitry Andric   SetBreakpointID(breakpoint->GetID());
1135f757f3fSDimitry Andric 
1145f757f3fSDimitry Andric   SetActive(true);
1155f757f3fSDimitry Andric }
1165f757f3fSDimitry Andric 
1175f757f3fSDimitry Andric void InstrumentationRuntimeASanLibsanitizers::Deactivate() {
1185f757f3fSDimitry Andric   SetActive(false);
1195f757f3fSDimitry Andric 
1205f757f3fSDimitry Andric   if (GetBreakpointID() == LLDB_INVALID_BREAK_ID)
1215f757f3fSDimitry Andric     return;
1225f757f3fSDimitry Andric 
1235f757f3fSDimitry Andric   if (ProcessSP process_sp = GetProcessSP()) {
1245f757f3fSDimitry Andric     process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID());
1255f757f3fSDimitry Andric     SetBreakpointID(LLDB_INVALID_BREAK_ID);
1265f757f3fSDimitry Andric   }
1275f757f3fSDimitry Andric }
128