Stop objects from keeping a strong reference to the process when they should have a weak reference.

llvm-svn: 246488
This commit is contained in:
Greg Clayton 2015-08-31 21:25:45 +00:00
parent b38affa474
commit 915272ff54
6 changed files with 165 additions and 123 deletions
lldb/source/Plugins

View File

@ -66,9 +66,11 @@ AddressSanitizerRuntime::GetTypeStatic()
AddressSanitizerRuntime::AddressSanitizerRuntime(const ProcessSP &process_sp) :
m_is_active(false),
m_runtime_module(),
m_process(process_sp),
m_process_wp(),
m_breakpoint_id(0)
{
if (process_sp)
m_process_wp = process_sp;
}
AddressSanitizerRuntime::~AddressSanitizerRuntime()
@ -161,7 +163,11 @@ t
StructuredData::ObjectSP
AddressSanitizerRuntime::RetrieveReportData()
{
ThreadSP thread_sp = m_process->GetThreadList().GetSelectedThread();
ProcessSP process_sp = GetProcessSP();
if (!process_sp)
return StructuredData::ObjectSP();
ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread();
StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
if (!frame_sp)
@ -175,7 +181,7 @@ AddressSanitizerRuntime::RetrieveReportData()
options.SetTimeoutUsec(RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC);
ValueObjectSP return_value_sp;
if (m_process->GetTarget().EvaluateExpression(address_sanitizer_retrieve_report_data_command, frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
if (process_sp->GetTarget().EvaluateExpression(address_sanitizer_retrieve_report_data_command, frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
return StructuredData::ObjectSP();
int present = return_value_sp->GetValueForExpressionPath(".present")->GetValueAsUnsigned(0);
@ -193,7 +199,7 @@ AddressSanitizerRuntime::RetrieveReportData()
addr_t description_ptr = return_value_sp->GetValueForExpressionPath(".description")->GetValueAsUnsigned(0);
std::string description;
Error error;
m_process->ReadCStringFromMemory(description_ptr, description, error);
process_sp->ReadCStringFromMemory(description_ptr, description, error);
StructuredData::Dictionary *dict = new StructuredData::Dictionary();
dict->AddStringItem("instrumentation_class", "AddressSanitizer");
@ -249,27 +255,31 @@ AddressSanitizerRuntime::NotifyBreakpointHit(void *baton, StoppointCallbackConte
assert (baton && "null baton");
if (!baton)
return false;
AddressSanitizerRuntime *const instance = static_cast<AddressSanitizerRuntime*>(baton);
StructuredData::ObjectSP report = instance->RetrieveReportData();
std::string description;
if (report) {
description = instance->FormatDescription(report);
}
ThreadSP thread = context->exe_ctx_ref.GetThreadSP();
thread->SetStopInfo(InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(*thread, description.c_str(), report));
if (instance->m_process)
ProcessSP process_sp = instance->GetProcessSP();
// Make sure this is the right process
if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP())
{
StreamFileSP stream_sp (instance->m_process->GetTarget().GetDebugger().GetOutputFile());
ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
if (thread_sp)
thread_sp->SetStopInfo(InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(*thread_sp, description.c_str(), report));
StreamFileSP stream_sp (process_sp->GetTarget().GetDebugger().GetOutputFile());
if (stream_sp)
{
stream_sp->Printf ("AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.\n");
}
return true; // Return true to stop the target
}
// Return true to stop the target, false to just let the target run.
return true;
else
return false; // Let target run
}
void
@ -278,6 +288,10 @@ AddressSanitizerRuntime::Activate()
if (m_is_active)
return;
ProcessSP process_sp = GetProcessSP();
if (!process_sp)
return;
ConstString symbol_name ("__asan::AsanDie()");
const Symbol *symbol = m_runtime_module->FindFirstSymbolWithNameAndType (symbol_name, eSymbolTypeCode);
@ -287,7 +301,7 @@ AddressSanitizerRuntime::Activate()
if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid())
return;
Target &target = m_process->GetTarget();
Target &target = process_sp->GetTarget();
addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target);
if (symbol_address == LLDB_INVALID_ADDRESS)
@ -295,18 +309,15 @@ AddressSanitizerRuntime::Activate()
bool internal = true;
bool hardware = false;
Breakpoint *breakpoint = m_process->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get();
Breakpoint *breakpoint = process_sp->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get();
breakpoint->SetCallback (AddressSanitizerRuntime::NotifyBreakpointHit, this, true);
breakpoint->SetBreakpointKind ("address-sanitizer-report");
m_breakpoint_id = breakpoint->GetID();
if (m_process)
StreamFileSP stream_sp (process_sp->GetTarget().GetDebugger().GetOutputFile());
if (stream_sp)
{
StreamFileSP stream_sp (m_process->GetTarget().GetDebugger().GetOutputFile());
if (stream_sp)
{
stream_sp->Printf ("AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.\n");
}
stream_sp->Printf ("AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.\n");
}
m_is_active = true;
@ -317,8 +328,12 @@ AddressSanitizerRuntime::Deactivate()
{
if (m_breakpoint_id != LLDB_INVALID_BREAK_ID)
{
m_process->GetTarget().RemoveBreakpointByID(m_breakpoint_id);
m_breakpoint_id = LLDB_INVALID_BREAK_ID;
ProcessSP process_sp = GetProcessSP();
if (process_sp)
{
process_sp->GetTarget().RemoveBreakpointByID(m_breakpoint_id);
m_breakpoint_id = LLDB_INVALID_BREAK_ID;
}
}
m_is_active = false;
}

View File

@ -56,7 +56,13 @@ public:
IsActive();
private:
lldb::ProcessSP
GetProcessSP ()
{
return m_process_wp.lock();
}
AddressSanitizerRuntime(const lldb::ProcessSP &process_sp);
void
@ -76,7 +82,7 @@ private:
bool m_is_active;
lldb::ModuleSP m_runtime_module;
lldb::ProcessSP m_process;
lldb::ProcessWP m_process_wp;
lldb::user_id_t m_breakpoint_id;
};

View File

@ -294,13 +294,15 @@ AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion()
// First read in the header:
char memory_buffer[16];
Process *process = m_owner->GetProcess();
ProcessSP process_sp = m_owner->GetProcessSP();
if (!process_sp)
return;
DataExtractor data(memory_buffer, sizeof(memory_buffer),
process->GetByteOrder(),
process->GetAddressByteSize());
size_t actual_size = 8 + process->GetAddressByteSize();
process_sp->GetByteOrder(),
process_sp->GetAddressByteSize());
size_t actual_size = 8 + process_sp->GetAddressByteSize();
Error error;
size_t bytes_read = process->ReadMemory (m_header_addr, memory_buffer, actual_size, error);
size_t bytes_read = process_sp->ReadMemory (m_header_addr, memory_buffer, actual_size, error);
if (bytes_read != actual_size)
{
m_valid = false;
@ -340,9 +342,9 @@ AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion()
uint8_t* dst = (uint8_t*)data_sp->GetBytes();
DataExtractor desc_extractor (dst, desc_array_size,
process->GetByteOrder(),
process->GetAddressByteSize());
bytes_read = process->ReadMemory(desc_ptr, dst, desc_array_size, error);
process_sp->GetByteOrder(),
process_sp->GetAddressByteSize());
bytes_read = process_sp->ReadMemory(desc_ptr, dst, desc_array_size, error);
if (bytes_read != desc_array_size)
{
m_valid = false;
@ -428,79 +430,88 @@ AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::Dump (Stream &s)
AppleObjCTrampolineHandler::AppleObjCVTables::AppleObjCVTables (const ProcessSP &process_sp,
const ModuleSP &objc_module_sp) :
m_process_sp (process_sp),
m_process_wp (),
m_trampoline_header (LLDB_INVALID_ADDRESS),
m_trampolines_changed_bp_id (LLDB_INVALID_BREAK_ID),
m_objc_module_sp (objc_module_sp)
{
if (process_sp)
m_process_wp = process_sp;
}
AppleObjCTrampolineHandler::AppleObjCVTables::~AppleObjCVTables()
{
if (m_trampolines_changed_bp_id != LLDB_INVALID_BREAK_ID)
m_process_sp->GetTarget().RemoveBreakpointByID (m_trampolines_changed_bp_id);
ProcessSP process_sp = GetProcessSP ();
if (process_sp)
{
if (m_trampolines_changed_bp_id != LLDB_INVALID_BREAK_ID)
process_sp->GetTarget().RemoveBreakpointByID (m_trampolines_changed_bp_id);
}
}
bool
AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols ()
{
if (m_trampoline_header != LLDB_INVALID_ADDRESS)
return true;
Target &target = m_process_sp->GetTarget();
const ModuleList &target_modules = target.GetImages();
Mutex::Locker modules_locker(target_modules.GetMutex());
size_t num_modules = target_modules.GetSize();
if (!m_objc_module_sp)
ProcessSP process_sp = GetProcessSP ();
if (process_sp)
{
for (size_t i = 0; i < num_modules; i++)
Target &target = process_sp->GetTarget();
const ModuleList &target_modules = target.GetImages();
Mutex::Locker modules_locker(target_modules.GetMutex());
size_t num_modules = target_modules.GetSize();
if (!m_objc_module_sp)
{
if (m_process_sp->GetObjCLanguageRuntime()->IsModuleObjCLibrary (target_modules.GetModuleAtIndexUnlocked(i)))
for (size_t i = 0; i < num_modules; i++)
{
m_objc_module_sp = target_modules.GetModuleAtIndexUnlocked(i);
break;
if (process_sp->GetObjCLanguageRuntime()->IsModuleObjCLibrary (target_modules.GetModuleAtIndexUnlocked(i)))
{
m_objc_module_sp = target_modules.GetModuleAtIndexUnlocked(i);
break;
}
}
}
}
if (m_objc_module_sp)
{
ConstString trampoline_name ("gdb_objc_trampolines");
const Symbol *trampoline_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (trampoline_name,
eSymbolTypeData);
if (trampoline_symbol != NULL)
if (m_objc_module_sp)
{
m_trampoline_header = trampoline_symbol->GetLoadAddress(&target);
if (m_trampoline_header == LLDB_INVALID_ADDRESS)
return false;
// Next look up the "changed" symbol and set a breakpoint on that...
ConstString changed_name ("gdb_objc_trampolines_changed");
const Symbol *changed_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (changed_name,
eSymbolTypeCode);
if (changed_symbol != NULL)
ConstString trampoline_name ("gdb_objc_trampolines");
const Symbol *trampoline_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (trampoline_name,
eSymbolTypeData);
if (trampoline_symbol != NULL)
{
const Address changed_symbol_addr = changed_symbol->GetAddress();
if (!changed_symbol_addr.IsValid())
m_trampoline_header = trampoline_symbol->GetLoadAddress(&target);
if (m_trampoline_header == LLDB_INVALID_ADDRESS)
return false;
lldb::addr_t changed_addr = changed_symbol_addr.GetOpcodeLoadAddress (&target);
if (changed_addr != LLDB_INVALID_ADDRESS)
// Next look up the "changed" symbol and set a breakpoint on that...
ConstString changed_name ("gdb_objc_trampolines_changed");
const Symbol *changed_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (changed_name,
eSymbolTypeCode);
if (changed_symbol != NULL)
{
BreakpointSP trampolines_changed_bp_sp = target.CreateBreakpoint (changed_addr, true, false);
if (trampolines_changed_bp_sp)
const Address changed_symbol_addr = changed_symbol->GetAddress();
if (!changed_symbol_addr.IsValid())
return false;
lldb::addr_t changed_addr = changed_symbol_addr.GetOpcodeLoadAddress (&target);
if (changed_addr != LLDB_INVALID_ADDRESS)
{
m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID();
trampolines_changed_bp_sp->SetCallback (RefreshTrampolines, this, true);
trampolines_changed_bp_sp->SetBreakpointKind ("objc-trampolines-changed");
return true;
BreakpointSP trampolines_changed_bp_sp = target.CreateBreakpoint (changed_addr, true, false);
if (trampolines_changed_bp_sp)
{
m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID();
trampolines_changed_bp_sp->SetCallback (RefreshTrampolines, this, true);
trampolines_changed_bp_sp->SetBreakpointKind ("objc-trampolines-changed");
return true;
}
}
}
}
}
}
return false;
}
@ -559,16 +570,21 @@ AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions ()
if (!InitializeVTableSymbols())
return false;
Error error;
lldb::addr_t region_addr = m_process_sp->ReadPointerFromMemory (m_trampoline_header, error);
if (error.Success())
return ReadRegions (region_addr);
ProcessSP process_sp = GetProcessSP ();
if (process_sp)
{
lldb::addr_t region_addr = process_sp->ReadPointerFromMemory (m_trampoline_header, error);
if (error.Success())
return ReadRegions (region_addr);
}
return false;
}
bool
AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions (lldb::addr_t region_addr)
{
if (!m_process_sp)
ProcessSP process_sp = GetProcessSP ();
if (!process_sp)
return false;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
@ -639,12 +655,14 @@ AppleObjCTrampolineHandler::g_dispatch_functions[] =
AppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process_sp,
const ModuleSP &objc_module_sp) :
m_process_sp (process_sp),
m_process_wp (),
m_objc_module_sp (objc_module_sp),
m_impl_fn_addr (LLDB_INVALID_ADDRESS),
m_impl_stret_fn_addr (LLDB_INVALID_ADDRESS),
m_msg_forward_addr (LLDB_INVALID_ADDRESS)
{
if (process_sp)
m_process_wp = process_sp;
// Look up the known resolution functions:
ConstString get_impl_name("class_getMethodImplementation");
@ -652,7 +670,7 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process
ConstString msg_forward_name("_objc_msgForward");
ConstString msg_forward_stret_name("_objc_msgForward_stret");
Target *target = m_process_sp ? &m_process_sp->GetTarget() : NULL;
Target *target = process_sp ? &process_sp->GetTarget() : NULL;
const Symbol *class_getMethodImplementation = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_name, eSymbolTypeCode);
const Symbol *class_getMethodImplementation_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_stret_name, eSymbolTypeCode);
const Symbol *msg_forward = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_name, eSymbolTypeCode);
@ -1041,7 +1059,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan (Thread &thread, bool sto
log->Printf("Resolving call for class - 0x%" PRIx64 " and selector - 0x%" PRIx64,
isa_addr, sel_addr);
}
ObjCLanguageRuntime *objc_runtime = m_process_sp->GetObjCLanguageRuntime ();
ObjCLanguageRuntime *objc_runtime = thread.GetProcess()->GetObjCLanguageRuntime ();
assert(objc_runtime != NULL);
impl_addr = objc_runtime->LookupInMethodCache (isa_addr, sel_addr);

View File

@ -176,13 +176,14 @@ private:
bool
IsAddressInVTables (lldb::addr_t addr, uint32_t &flags);
Process *GetProcess ()
lldb::ProcessSP
GetProcessSP ()
{
return m_process_sp.get();
return m_process_wp.lock();
}
private:
lldb::ProcessSP m_process_sp;
lldb::ProcessWP m_process_wp;
typedef std::vector<VTableRegion> region_collection;
lldb::addr_t m_trampoline_header;
lldb::break_id_t m_trampolines_changed_bp_id;
@ -195,7 +196,7 @@ private:
typedef std::map<lldb::addr_t, int> MsgsendMap; // This table maps an dispatch fn address to the index in g_dispatch_functions
MsgsendMap m_msgSend_map;
lldb::ProcessSP m_process_sp;
lldb::ProcessWP m_process_wp;
lldb::ModuleSP m_objc_module_sp;
std::unique_ptr<ClangFunction> m_impl_function;
std::unique_ptr<ClangUtilityFunction> m_impl_code;

View File

@ -75,7 +75,8 @@ MemoryHistoryASan::GetPluginNameStatic()
MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp)
{
this->m_process_sp = process_sp;
if (process_sp)
m_process_wp = process_sp;
}
const char *
@ -133,40 +134,41 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObject
HistoryThreads
MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address)
{
ProcessSP process_sp = m_process_sp;
ThreadSP thread_sp = m_process_sp->GetThreadList().GetSelectedThread();
StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
if (!frame_sp)
{
return HistoryThreads();
}
ExecutionContext exe_ctx (frame_sp);
ValueObjectSP return_value_sp;
StreamString expr;
expr.Printf(memory_history_asan_command_format, address, address);
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetTryAllThreads(true);
options.SetStopOthers(true);
options.SetIgnoreBreakpoints(true);
options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC);
if (m_process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
{
return HistoryThreads();
}
if (!return_value_sp)
{
return HistoryThreads();
}
HistoryThreads result;
CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated at", result);
CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated at", result);
ProcessSP process_sp = m_process_wp.lock();
if (process_sp)
{
ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread();
if (thread_sp)
{
StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
if (frame_sp)
{
ExecutionContext exe_ctx (frame_sp);
ValueObjectSP return_value_sp;
StreamString expr;
expr.Printf(memory_history_asan_command_format, address, address);
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetTryAllThreads(true);
options.SetStopOthers(true);
options.SetIgnoreBreakpoints(true);
options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC);
if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) == eExpressionCompleted)
{
if (return_value_sp)
{
CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated at", result);
CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated at", result);
}
}
}
}
}
return result;
}

View File

@ -53,7 +53,7 @@ private:
MemoryHistoryASan(const lldb::ProcessSP &process_sp);
lldb::ProcessSP m_process_sp;
lldb::ProcessWP m_process_wp;
};