LLDB  mainline
InstrumentationRuntimeASan.cpp
Go to the documentation of this file.
1 //===-- InstrumentationRuntimeASan.cpp ------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
12 #include "lldb/Core/Debugger.h"
13 #include "lldb/Core/Module.h"
16 #include "lldb/Core/StreamFile.h"
17 #include "lldb/Core/ValueObject.h"
20 #include "lldb/Symbol/Symbol.h"
22 #include "lldb/Target/StopInfo.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/Thread.h"
26 #include "lldb/Utility/Stream.h"
27 
28 #include "llvm/ADT/StringSwitch.h"
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
34 
35 lldb::InstrumentationRuntimeSP
36 InstrumentationRuntimeASan::CreateInstance(const lldb::ProcessSP &process_sp) {
37  return InstrumentationRuntimeSP(new InstrumentationRuntimeASan(process_sp));
38 }
39 
40 void InstrumentationRuntimeASan::Initialize() {
41  PluginManager::RegisterPlugin(
42  GetPluginNameStatic(), "AddressSanitizer instrumentation runtime plugin.",
43  CreateInstance, GetTypeStatic);
44 }
45 
46 void InstrumentationRuntimeASan::Terminate() {
47  PluginManager::UnregisterPlugin(CreateInstance);
48 }
49 
50 lldb::InstrumentationRuntimeType InstrumentationRuntimeASan::GetTypeStatic() {
52 }
53 
54 InstrumentationRuntimeASan::~InstrumentationRuntimeASan() { Deactivate(); }
55 
56 const RegularExpression &
57 InstrumentationRuntimeASan::GetPatternForRuntimeLibrary() {
58  // FIXME: This shouldn't include the "dylib" suffix.
59  static RegularExpression regex(
60  llvm::StringRef("libclang_rt.asan_(.*)_dynamic\\.dylib"));
61  return regex;
62 }
63 
64 bool InstrumentationRuntimeASan::CheckIfRuntimeIsValid(
65  const lldb::ModuleSP module_sp) {
66  const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(
67  ConstString("__asan_get_alloc_stack"), lldb::eSymbolTypeAny);
68 
69  return symbol != nullptr;
70 }
71 
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 
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 = thread_sp->GetSelectedFrame();
117 
118  if (!frame_sp)
119  return StructuredData::ObjectSP();
120 
122  options.SetUnwindOnError(true);
123  options.SetTryAllThreads(true);
124  options.SetStopOthers(true);
125  options.SetIgnoreBreakpoints(true);
126  options.SetTimeout(process_sp->GetUtilityExpressionTimeout());
128  options.SetAutoApplyFixIts(false);
130 
131  ValueObjectSP return_value_sp;
132  ExecutionContext exe_ctx;
133  Status eval_error;
134  frame_sp->CalculateExecutionContext(exe_ctx);
135  ExpressionResults result = UserExpression::Evaluate(
137  return_value_sp, eval_error);
138  if (result != eExpressionCompleted) {
139  StreamString ss;
140  ss << "cannot evaluate AddressSanitizer expression:\n";
141  ss << eval_error.AsCString();
142  Debugger::ReportWarning(ss.GetString().str(),
143  process_sp->GetTarget().GetDebugger().GetID());
144  return StructuredData::ObjectSP();
145  }
146 
147  int present = return_value_sp->GetValueForExpressionPath(".present")
148  ->GetValueAsUnsigned(0);
149  if (present != 1)
150  return StructuredData::ObjectSP();
151 
152  addr_t pc =
153  return_value_sp->GetValueForExpressionPath(".pc")->GetValueAsUnsigned(0);
154  /* commented out because rdar://problem/18533301
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  */
160  addr_t address = return_value_sp->GetValueForExpressionPath(".address")
161  ->GetValueAsUnsigned(0);
162  addr_t access_type =
163  return_value_sp->GetValueForExpressionPath(".access_type")
164  ->GetValueAsUnsigned(0);
165  addr_t access_size =
166  return_value_sp->GetValueForExpressionPath(".access_size")
167  ->GetValueAsUnsigned(0);
168  addr_t description_ptr =
169  return_value_sp->GetValueForExpressionPath(".description")
170  ->GetValueAsUnsigned(0);
171  std::string description;
172  Status error;
173  process_sp->ReadCStringFromMemory(description_ptr, description, error);
174 
176  dict->AddStringItem("instrumentation_class", "AddressSanitizer");
177  dict->AddStringItem("stop_type", "fatal_error");
178  dict->AddIntegerItem("pc", pc);
179  /* commented out because rdar://problem/18533301
180  dict->AddIntegerItem("bp", bp);
181  dict->AddIntegerItem("sp", sp);
182  */
183  dict->AddIntegerItem("address", address);
184  dict->AddIntegerItem("access_type", access_type);
185  dict->AddIntegerItem("access_size", access_size);
186  dict->AddStringItem("description", description);
187 
188  return StructuredData::ObjectSP(dict);
189 }
190 
192 InstrumentationRuntimeASan::FormatDescription(StructuredData::ObjectSP report) {
193  std::string description = std::string(report->GetAsDictionary()
194  ->GetValueForKey("description")
195  ->GetAsString()
196  ->GetValue());
197  return llvm::StringSwitch<std::string>(description)
198  .Case("heap-use-after-free", "Use of deallocated memory")
199  .Case("heap-buffer-overflow", "Heap buffer overflow")
200  .Case("stack-buffer-underflow", "Stack buffer underflow")
201  .Case("initialization-order-fiasco", "Initialization order problem")
202  .Case("stack-buffer-overflow", "Stack buffer overflow")
203  .Case("stack-use-after-return", "Use of stack memory after return")
204  .Case("use-after-poison", "Use of poisoned memory")
205  .Case("container-overflow", "Container overflow")
206  .Case("stack-use-after-scope", "Use of out-of-scope stack memory")
207  .Case("global-buffer-overflow", "Global buffer overflow")
208  .Case("unknown-crash", "Invalid memory access")
209  .Case("stack-overflow", "Stack space exhausted")
210  .Case("null-deref", "Dereference of null pointer")
211  .Case("wild-jump", "Jump to non-executable address")
212  .Case("wild-addr-write", "Write through wild pointer")
213  .Case("wild-addr-read", "Read from wild pointer")
214  .Case("wild-addr", "Access through wild pointer")
215  .Case("signal", "Deadly signal")
216  .Case("double-free", "Deallocation of freed memory")
217  .Case("new-delete-type-mismatch",
218  "Deallocation size different from allocation size")
219  .Case("bad-free", "Deallocation of non-allocated memory")
220  .Case("alloc-dealloc-mismatch",
221  "Mismatch between allocation and deallocation APIs")
222  .Case("bad-malloc_usable_size", "Invalid argument to malloc_usable_size")
223  .Case("bad-__sanitizer_get_allocated_size",
224  "Invalid argument to __sanitizer_get_allocated_size")
225  .Case("param-overlap",
226  "Call to function disallowing overlapping memory ranges")
227  .Case("negative-size-param", "Negative size used when accessing memory")
228  .Case("bad-__sanitizer_annotate_contiguous_container",
229  "Invalid argument to __sanitizer_annotate_contiguous_container")
230  .Case("odr-violation", "Symbol defined in multiple translation units")
231  .Case(
232  "invalid-pointer-pair",
233  "Comparison or arithmetic on pointers from different memory regions")
234  // for unknown report codes just show the code
235  .Default("AddressSanitizer detected: " + description);
236 }
237 
238 bool InstrumentationRuntimeASan::NotifyBreakpointHit(
239  void *baton, StoppointCallbackContext *context, user_id_t break_id,
240  user_id_t break_loc_id) {
241  assert(baton && "null baton");
242  if (!baton)
243  return false;
244 
245  InstrumentationRuntimeASan *const instance =
246  static_cast<InstrumentationRuntimeASan *>(baton);
247 
248  ProcessSP process_sp = instance->GetProcessSP();
249 
250  if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
251  return false;
252 
253  StructuredData::ObjectSP report = instance->RetrieveReportData();
254  std::string description;
255  if (report) {
256  description = instance->FormatDescription(report);
257  }
258  // Make sure this is the right process
259  if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) {
260  ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
261  if (thread_sp)
262  thread_sp->SetStopInfo(InstrumentationRuntimeStopInfo::
263  CreateStopReasonWithInstrumentationData(
264  *thread_sp, description, report));
265 
266  StreamFileSP stream_sp(
267  process_sp->GetTarget().GetDebugger().GetOutputStreamSP());
268  if (stream_sp) {
269  stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread "
270  "info -s' to get extended information about the "
271  "report.\n");
272  }
273  return true; // Return true to stop the target
274  } else
275  return false; // Let target run
276 }
277 
278 void InstrumentationRuntimeASan::Activate() {
279  if (IsActive())
280  return;
281 
282  ProcessSP process_sp = GetProcessSP();
283  if (!process_sp)
284  return;
285 
286  ConstString symbol_name("_ZN6__asanL7AsanDieEv");
287  const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType(
288  symbol_name, eSymbolTypeCode);
289 
290  if (symbol == nullptr)
291  return;
292 
293  if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid())
294  return;
295 
296  Target &target = process_sp->GetTarget();
297  addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target);
298 
299  if (symbol_address == LLDB_INVALID_ADDRESS)
300  return;
301 
302  const bool internal = true;
303  const bool hardware = false;
304  const bool sync = false;
305  Breakpoint *breakpoint =
306  process_sp->GetTarget()
307  .CreateBreakpoint(symbol_address, internal, hardware)
308  .get();
309  breakpoint->SetCallback(InstrumentationRuntimeASan::NotifyBreakpointHit, this,
310  sync);
311  breakpoint->SetBreakpointKind("address-sanitizer-report");
312  SetBreakpointID(breakpoint->GetID());
313 
314  SetActive(true);
315 }
316 
317 void InstrumentationRuntimeASan::Deactivate() {
318  if (GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
319  ProcessSP process_sp = GetProcessSP();
320  if (process_sp) {
321  process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID());
322  SetBreakpointID(LLDB_INVALID_BREAK_ID);
323  }
324  }
325  SetActive(false);
326 }
RegularExpression.h
lldb_private::ExecutionContext
Definition: ExecutionContext.h:292
lldb_private::StructuredData::Dictionary
Definition: StructuredData.h:368
lldb_private::RegularExpression
Definition: RegularExpression.h:18
lldb_private::InstrumentationRuntimeStopInfo
Definition: InstrumentationRuntimeStopInfo.h:19
lldb_private::StoppointCallbackContext
General Outline: When we hit a breakpoint we need to package up whatever information is needed to eva...
Definition: StoppointCallbackContext.h:26
lldb_private::Stoppoint::GetID
lldb::break_id_t GetID() const
Definition: Stoppoint.cpp:22
lldb_private::Address::IsValid
bool IsValid() const
Check if the object state is valid.
Definition: Address.h:345
lldb_private::InstrumentationRuntimeASan
Definition: InstrumentationRuntimeASan.h:19
lldb::eSymbolTypeCode
@ eSymbolTypeCode
Definition: lldb-enumerations.h:623
lldb_private::EvaluateExpressionOptions::SetTimeout
void SetTimeout(const Timeout< std::micro > &timeout)
Definition: Target.h:345
lldb_private::EvaluateExpressionOptions::SetLanguage
void SetLanguage(lldb::LanguageType language)
Definition: Target.h:305
lldb_private::Symbol
Definition: Symbol.h:20
lldb_private::Symbol::ValueIsAddress
bool ValueIsAddress() const
Definition: Symbol.cpp:117
lldb_private::ExecutionContextRef::GetThreadSP
lldb::ThreadSP GetThreadSP() const
Get accessor that creates a strong reference from the weak thread reference contained in this object.
Definition: ExecutionContext.cpp:574
lldb_private::Breakpoint::SetBreakpointKind
void SetBreakpointKind(const char *kind)
Set the "kind" description for a breakpoint.
Definition: Breakpoint.h:453
lldb::ExpressionResults
ExpressionResults
The results of expression evaluation.
Definition: lldb-enumerations.h:271
Module.h
lldb_private::StoppointCallbackContext::exe_ctx_ref
ExecutionContextRef exe_ctx_ref
Definition: StoppointCallbackContext.h:43
lldb_private::EvaluateExpressionOptions
Definition: Target.h:277
StoppointCallbackContext.h
lldb_private::InstrumentationRuntimeASan::FormatDescription
std::string FormatDescription(StructuredData::ObjectSP report)
Definition: InstrumentationRuntimeASan.cpp:192
UserExpression.h
lldb_private::Target::CreateBreakpoint
lldb::BreakpointSP CreateBreakpoint(const FileSpecList *containingModules, const FileSpec &file, uint32_t line_no, uint32_t column, lldb::addr_t offset, LazyBool check_inlines, LazyBool skip_prologue, bool internal, bool request_hardware, LazyBool move_to_nearest_code)
Definition: Target.cpp:353
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
pc
@ pc
Definition: CompactUnwindInfo.cpp:1251
CommandReturnObject.h
Debugger.h
lldb_private::Target
Definition: Target.h:469
lldb_private::Address::GetOpcodeLoadAddress
lldb::addr_t GetOpcodeLoadAddress(Target *target, AddressClass addr_class=AddressClass::eInvalid) const
Get the load address as an opcode load address.
Definition: Address.cpp:368
lldb_private::StreamString::GetString
llvm::StringRef GetString() const
Definition: StreamString.cpp:51
address_sanitizer_retrieve_report_data_command
const char * address_sanitizer_retrieve_report_data_command
Definition: InstrumentationRuntimeASan.cpp:86
Target.h
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb::eSymbolTypeAny
@ eSymbolTypeAny
Definition: lldb-enumerations.h:620
InstrumentationRuntimeStopInfo.h
lldb_private::StructuredData::ObjectSP
std::shared_ptr< Object > ObjectSP
Definition: StructuredData.h:59
lldb::eExpressionCompleted
@ eExpressionCompleted
Definition: lldb-enumerations.h:272
lldb_private::Symbol::GetAddressRef
Address & GetAddressRef()
Definition: Symbol.h:57
lldb_private::ConstString
Definition: ConstString.h:39
lldb_private::StreamString
Definition: StreamString.h:23
lldb_private::EvaluateExpressionOptions::SetTryAllThreads
void SetTryAllThreads(bool try_others=true)
Definition: Target.h:357
PluginInterface.h
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
lldb_private::EvaluateExpressionOptions::SetUnwindOnError
void SetUnwindOnError(bool unwind=false)
Definition: Target.h:324
Thread.h
ValueObject.h
LLDB_INVALID_BREAK_ID
#define LLDB_INVALID_BREAK_ID
Definition: lldb-defines.h:37
lldb_private::EvaluateExpressionOptions::SetIgnoreBreakpoints
void SetIgnoreBreakpoints(bool ignore=false)
Definition: Target.h:328
Symbol.h
StreamFile.h
lldb_private::Status
Definition: Status.h:44
address_sanitizer_retrieve_report_data_prefix
const char * address_sanitizer_retrieve_report_data_prefix
Definition: InstrumentationRuntimeASan.cpp:72
lldb_private::Breakpoint::SetCallback
void SetCallback(BreakpointHitCallback callback, void *baton, bool is_synchronous=false)
Set the callback action invoked when the breakpoint is hit.
Definition: Breakpoint.cpp:418
StopInfo.h
PluginManager.h
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
lldb_private::StructuredData::Dictionary::AddStringItem
void AddStringItem(llvm::StringRef key, llvm::StringRef value)
Definition: StructuredData.h:533
lldb::eInstrumentationRuntimeTypeAddressSanitizer
@ eInstrumentationRuntimeTypeAddressSanitizer
Definition: lldb-enumerations.h:487
lldb::user_id_t
uint64_t user_id_t
Definition: lldb-types.h:84
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::StructuredData::Dictionary::AddIntegerItem
void AddIntegerItem(llvm::StringRef key, uint64_t value)
Definition: StructuredData.h:525
lldb_private::Breakpoint::GetTarget
Target & GetTarget()
Accessor for the breakpoint Target.
Definition: Breakpoint.h:464
lldb_private::InstrumentationRuntime::GetProcessSP
lldb::ProcessSP GetProcessSP()
Definition: InstrumentationRuntime.h:50
Stream.h
LLDB_PLUGIN_DEFINE
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
lldb_private::EvaluateExpressionOptions::SetStopOthers
void SetStopOthers(bool stop_others=true)
Definition: Target.h:361
lldb_private::ExecutionContextRef::GetProcessSP
lldb::ProcessSP GetProcessSP() const
Get accessor that creates a strong reference from the weak process reference contained in this object...
Definition: ExecutionContext.cpp:567
lldb::eLanguageTypeObjC_plus_plus
@ eLanguageTypeObjC_plus_plus
Objective-C++.
Definition: lldb-enumerations.h:455
lldb_private::EvaluateExpressionOptions::SetPrefix
void SetPrefix(const char *prefix)
Definition: Target.h:313
lldb
Definition: SBAddress.h:15
InstrumentationRuntimeASan.h
lldb_private::Breakpoint
General Outline: A breakpoint has four main parts, a filter, a resolver, the list of breakpoint locat...
Definition: Breakpoint.h:80
lldb_private::InstrumentationRuntimeASan::RetrieveReportData
StructuredData::ObjectSP RetrieveReportData()
Definition: InstrumentationRuntimeASan.cpp:109
lldb::InstrumentationRuntimeType
InstrumentationRuntimeType
Definition: lldb-enumerations.h:486
lldb_private::Status::AsCString
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:130
lldb_private::EvaluateExpressionOptions::SetAutoApplyFixIts
void SetAutoApplyFixIts(bool b)
Definition: Target.h:420