brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.3 KiB · 206a471 Raw
202 lines · cpp
1//===-- MemoryHistoryASan.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "MemoryHistoryASan.h"10 11#include "lldb/Symbol/SymbolContext.h"12#include "lldb/Target/MemoryHistory.h"13 14#include "Plugins/InstrumentationRuntime/Utility/Utility.h"15#include "Plugins/Process/Utility/HistoryThread.h"16#include "lldb/Core/Debugger.h"17#include "lldb/Core/Module.h"18#include "lldb/Core/PluginInterface.h"19#include "lldb/Core/PluginManager.h"20#include "lldb/Expression/UserExpression.h"21#include "lldb/Target/ExecutionContext.h"22#include "lldb/Target/Target.h"23#include "lldb/Target/Thread.h"24#include "lldb/Target/ThreadList.h"25#include "lldb/ValueObject/ValueObject.h"26#include "lldb/lldb-private.h"27 28#include <sstream>29 30using namespace lldb;31using namespace lldb_private;32 33LLDB_PLUGIN_DEFINE(MemoryHistoryASan)34 35MemoryHistorySP MemoryHistoryASan::CreateInstance(const ProcessSP &process_sp) {36  if (!process_sp.get())37    return nullptr;38 39  Target &target = process_sp->GetTarget();40 41  for (ModuleSP module_sp : target.GetImages().Modules()) {42    const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(43        ConstString("__asan_get_alloc_stack"), lldb::eSymbolTypeAny);44 45    if (symbol != nullptr)46      return MemoryHistorySP(new MemoryHistoryASan(process_sp));47  }48 49  return MemoryHistorySP();50}51 52void MemoryHistoryASan::Initialize() {53  PluginManager::RegisterPlugin(54      GetPluginNameStatic(), "ASan memory history provider.", CreateInstance);55}56 57void MemoryHistoryASan::Terminate() {58  PluginManager::UnregisterPlugin(CreateInstance);59}60 61MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp) {62  if (process_sp)63    m_process_wp = process_sp;64}65 66const char *memory_history_asan_command_prefix = R"(67    extern "C"68    {69        size_t __asan_get_alloc_stack(void *addr, void **trace, size_t size, int *thread_id);70        size_t __asan_get_free_stack(void *addr, void **trace, size_t size, int *thread_id);71    }72)";73 74const char *memory_history_asan_command_format =75    R"(76    struct {77        void *alloc_trace[256];78        size_t alloc_count;79        int alloc_tid;80 81        void *free_trace[256];82        size_t free_count;83        int free_tid;84    } t;85 86    t.alloc_count = __asan_get_alloc_stack((void *)0x%)" PRIx6487    R"(, t.alloc_trace, 256, &t.alloc_tid);88    t.free_count = __asan_get_free_stack((void *)0x%)" PRIx6489    R"(, t.free_trace, 256, &t.free_tid);90 91    t;92)";93 94static void CreateHistoryThreadFromValueObject(95    ProcessSP process_sp, ValueObjectSP return_value_sp, HistoryPCType pc_type,96    const char *type, const char *thread_name, HistoryThreads &result) {97  std::string count_path = "." + std::string(type) + "_count";98  std::string tid_path = "." + std::string(type) + "_tid";99  std::string trace_path = "." + std::string(type) + "_trace";100 101  ValueObjectSP count_sp =102      return_value_sp->GetValueForExpressionPath(count_path.c_str());103  ValueObjectSP tid_sp =104      return_value_sp->GetValueForExpressionPath(tid_path.c_str());105 106  if (!count_sp || !tid_sp)107    return;108 109  int count = count_sp->GetValueAsUnsigned(0);110  lldb::tid_t tid = tid_sp->GetValueAsUnsigned(0) + 1;111 112  if (count <= 0)113    return;114 115  ValueObjectSP trace_sp =116      return_value_sp->GetValueForExpressionPath(trace_path.c_str());117 118  if (!trace_sp)119    return;120 121  std::vector<lldb::addr_t> pcs;122  for (int i = 0; i < count; i++) {123    addr_t pc = trace_sp->GetChildAtIndex(i)->GetValueAsUnsigned(0);124    if (pc == 0 || pc == 1 || pc == LLDB_INVALID_ADDRESS)125      continue;126    pcs.push_back(pc);127  }128 129  HistoryThread *history_thread =130      new HistoryThread(*process_sp, tid, pcs, pc_type);131  ThreadSP new_thread_sp(history_thread);132  std::ostringstream thread_name_with_number;133  thread_name_with_number << thread_name << " Thread " << tid;134  history_thread->SetThreadName(thread_name_with_number.str().c_str());135  // Save this in the Process' ExtendedThreadList so a strong pointer retains136  // the object137  process_sp->GetExtendedThreadList().AddThread(new_thread_sp);138  result.push_back(new_thread_sp);139}140 141HistoryThreads MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address) {142  HistoryThreads result;143 144  ProcessSP process_sp = m_process_wp.lock();145  if (!process_sp)146    return result;147 148  ThreadSP thread_sp =149      process_sp->GetThreadList().GetExpressionExecutionThread();150  if (!thread_sp)151    return result;152 153  StackFrameSP frame_sp =154      thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);155  if (!frame_sp)156    return result;157 158  ExecutionContext exe_ctx(frame_sp);159  ValueObjectSP return_value_sp;160  StreamString expr;161  expr.Printf(memory_history_asan_command_format, address, address);162 163  EvaluateExpressionOptions options;164  options.SetUnwindOnError(true);165  options.SetTryAllThreads(true);166  options.SetStopOthers(true);167  options.SetIgnoreBreakpoints(true);168  options.SetTimeout(process_sp->GetUtilityExpressionTimeout());169  options.SetPrefix(memory_history_asan_command_prefix);170  options.SetAutoApplyFixIts(false);171  options.SetLanguage(eLanguageTypeObjC_plus_plus);172 173  auto [m, pc_type] = GetPreferredAsanModule(process_sp->GetTarget());174  if (m) {175    SymbolContextList sc_list;176    sc_list.Append(SymbolContext(std::move(m)));177    options.SetPreferredSymbolContexts(std::move(sc_list));178  }179 180  ExpressionResults expr_result = UserExpression::Evaluate(181      exe_ctx, options, expr.GetString(), "", return_value_sp);182  if (expr_result != eExpressionCompleted) {183    StreamString ss;184    ss << "cannot evaluate AddressSanitizer expression:\n";185    if (return_value_sp)186      ss << return_value_sp->GetError().AsCString();187    Debugger::ReportWarning(ss.GetString().str(),188                            process_sp->GetTarget().GetDebugger().GetID());189    return result;190  }191 192  if (!return_value_sp)193    return result;194 195  CreateHistoryThreadFromValueObject(process_sp, return_value_sp, pc_type,196                                     "free", "Memory deallocated by", result);197  CreateHistoryThreadFromValueObject(process_sp, return_value_sp, pc_type,198                                     "alloc", "Memory allocated by", result);199 200  return result;201}202