diff options
Diffstat (limited to 'source/API/SBInstruction.cpp')
-rw-r--r-- | source/API/SBInstruction.cpp | 180 |
1 files changed, 127 insertions, 53 deletions
diff --git a/source/API/SBInstruction.cpp b/source/API/SBInstruction.cpp index a17f3f8dbd5d..ccf561edb90f 100644 --- a/source/API/SBInstruction.cpp +++ b/source/API/SBInstruction.cpp @@ -26,15 +26,63 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" +//---------------------------------------------------------------------- +// We recently fixed a leak in one of the Instruction subclasses where +// the instruction will only hold a weak reference to the disassembler +// to avoid a cycle that was keeping both objects alive (leak) and we +// need the InstructionImpl class to make sure our public API behaves +// as users would expect. Calls in our public API allow clients to do +// things like: +// +// 1 lldb::SBInstruction inst; +// 2 inst = target.ReadInstructions(pc, 1).GetInstructionAtIndex(0) +// 3 if (inst.DoesBranch()) +// 4 ... +// +// There was a temporary lldb::DisassemblerSP object created in the +// SBInstructionList that was returned by lldb.target.ReadInstructions() +// that will go away after line 2 but the "inst" object should be able +// to still answer questions about itself. So we make sure that any +// SBInstruction objects that are given out have a strong reference to +// the disassembler and the instruction so that the object can live and +// successfully respond to all queries. +//---------------------------------------------------------------------- +class InstructionImpl +{ +public: + InstructionImpl (const lldb::DisassemblerSP &disasm_sp, const lldb::InstructionSP& inst_sp) : + m_disasm_sp(disasm_sp), + m_inst_sp(inst_sp) + { + } + + lldb::InstructionSP + GetSP() const + { + return m_inst_sp; + } + + bool + IsValid() const + { + return (bool)m_inst_sp; + } + +protected: + lldb::DisassemblerSP m_disasm_sp; // Can be empty/invalid + lldb::InstructionSP m_inst_sp; +}; + using namespace lldb; using namespace lldb_private; -SBInstruction::SBInstruction () +SBInstruction::SBInstruction() : + m_opaque_sp() { } -SBInstruction::SBInstruction (const lldb::InstructionSP& inst_sp) : - m_opaque_sp (inst_sp) +SBInstruction::SBInstruction(const lldb::DisassemblerSP &disasm_sp, const lldb::InstructionSP& inst_sp) : + m_opaque_sp(new InstructionImpl(disasm_sp, inst_sp)) { } @@ -58,33 +106,36 @@ SBInstruction::~SBInstruction () bool SBInstruction::IsValid() { - return (m_opaque_sp.get() != NULL); + return m_opaque_sp && m_opaque_sp->IsValid(); } SBAddress SBInstruction::GetAddress() { SBAddress sb_addr; - if (m_opaque_sp && m_opaque_sp->GetAddress().IsValid()) - sb_addr.SetAddress(&m_opaque_sp->GetAddress()); + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp && inst_sp->GetAddress().IsValid()) + sb_addr.SetAddress(&inst_sp->GetAddress()); return sb_addr; } const char * SBInstruction::GetMnemonic(SBTarget target) { - if (m_opaque_sp) + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) { - Mutex::Locker api_locker; ExecutionContext exe_ctx; TargetSP target_sp (target.GetSP()); + std::unique_lock<std::recursive_mutex> lock; if (target_sp) { - api_locker.Lock (target_sp->GetAPIMutex()); + lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); + target_sp->CalculateExecutionContext (exe_ctx); exe_ctx.SetProcessSP(target_sp->GetProcessSP()); } - return m_opaque_sp->GetMnemonic(&exe_ctx); + return inst_sp->GetMnemonic(&exe_ctx); } return NULL; } @@ -92,18 +143,20 @@ SBInstruction::GetMnemonic(SBTarget target) const char * SBInstruction::GetOperands(SBTarget target) { - if (m_opaque_sp) + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) { - Mutex::Locker api_locker; ExecutionContext exe_ctx; TargetSP target_sp (target.GetSP()); + std::unique_lock<std::recursive_mutex> lock; if (target_sp) { - api_locker.Lock (target_sp->GetAPIMutex()); + lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); + target_sp->CalculateExecutionContext (exe_ctx); exe_ctx.SetProcessSP(target_sp->GetProcessSP()); } - return m_opaque_sp->GetOperands(&exe_ctx); + return inst_sp->GetOperands(&exe_ctx); } return NULL; } @@ -111,18 +164,20 @@ SBInstruction::GetOperands(SBTarget target) const char * SBInstruction::GetComment(SBTarget target) { - if (m_opaque_sp) + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) { - Mutex::Locker api_locker; ExecutionContext exe_ctx; TargetSP target_sp (target.GetSP()); + std::unique_lock<std::recursive_mutex> lock; if (target_sp) { - api_locker.Lock (target_sp->GetAPIMutex()); + lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); + target_sp->CalculateExecutionContext (exe_ctx); exe_ctx.SetProcessSP(target_sp->GetProcessSP()); } - return m_opaque_sp->GetComment(&exe_ctx); + return inst_sp->GetComment(&exe_ctx); } return NULL; } @@ -130,8 +185,9 @@ SBInstruction::GetComment(SBTarget target) size_t SBInstruction::GetByteSize () { - if (m_opaque_sp) - return m_opaque_sp->GetOpcode().GetByteSize(); + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) + return inst_sp->GetOpcode().GetByteSize(); return 0; } @@ -139,10 +195,11 @@ SBData SBInstruction::GetData (SBTarget target) { lldb::SBData sb_data; - if (m_opaque_sp) + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) { DataExtractorSP data_extractor_sp (new DataExtractor()); - if (m_opaque_sp->GetData (*data_extractor_sp)) + if (inst_sp->GetData (*data_extractor_sp)) { sb_data.SetOpaque (data_extractor_sp); } @@ -155,32 +212,44 @@ SBInstruction::GetData (SBTarget target) bool SBInstruction::DoesBranch () { - if (m_opaque_sp) - return m_opaque_sp->DoesBranch (); + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) + return inst_sp->DoesBranch (); return false; } bool SBInstruction::HasDelaySlot () { - if (m_opaque_sp) - return m_opaque_sp->HasDelaySlot (); + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) + return inst_sp->HasDelaySlot (); return false; } +lldb::InstructionSP +SBInstruction::GetOpaque () +{ + if (m_opaque_sp) + return m_opaque_sp->GetSP(); + else + return lldb::InstructionSP(); +} + void -SBInstruction::SetOpaque (const lldb::InstructionSP &inst_sp) +SBInstruction::SetOpaque (const lldb::DisassemblerSP &disasm_sp, const lldb::InstructionSP& inst_sp) { - m_opaque_sp = inst_sp; + m_opaque_sp.reset(new InstructionImpl(disasm_sp, inst_sp)); } bool SBInstruction::GetDescription (lldb::SBStream &s) { - if (m_opaque_sp) + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) { SymbolContext sc; - const Address &addr = m_opaque_sp->GetAddress(); + const Address &addr = inst_sp->GetAddress(); ModuleSP module_sp (addr.GetModule()); if (module_sp) module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); @@ -188,7 +257,7 @@ SBInstruction::GetDescription (lldb::SBStream &s) // didn't have a stream already created, one will get created... FormatEntity::Entry format; FormatEntity::Parse("${addr}: ", format); - m_opaque_sp->Dump (&s.ref(), 0, true, false, NULL, &sc, NULL, &format, 0); + inst_sp->Dump (&s.ref(), 0, true, false, NULL, &sc, NULL, &format, 0); return true; } return false; @@ -200,24 +269,26 @@ SBInstruction::Print (FILE *out) if (out == NULL) return; - if (m_opaque_sp) + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) { SymbolContext sc; - const Address &addr = m_opaque_sp->GetAddress(); + const Address &addr = inst_sp->GetAddress(); ModuleSP module_sp (addr.GetModule()); if (module_sp) module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); StreamFile out_stream (out, false); FormatEntity::Entry format; FormatEntity::Parse("${addr}: ", format); - m_opaque_sp->Dump (&out_stream, 0, true, false, NULL, &sc, NULL, &format, 0); + inst_sp->Dump (&out_stream, 0, true, false, NULL, &sc, NULL, &format, 0); } } bool SBInstruction::EmulateWithFrame (lldb::SBFrame &frame, uint32_t evaluate_options) { - if (m_opaque_sp) + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) { lldb::StackFrameSP frame_sp (frame.GetFrameSP()); @@ -228,13 +299,13 @@ SBInstruction::EmulateWithFrame (lldb::SBFrame &frame, uint32_t evaluate_options lldb_private::Target *target = exe_ctx.GetTargetPtr(); lldb_private::ArchSpec arch = target->GetArchitecture(); - return m_opaque_sp->Emulate (arch, - evaluate_options, - (void *) frame_sp.get(), - &lldb_private::EmulateInstruction::ReadMemoryFrame, - &lldb_private::EmulateInstruction::WriteMemoryFrame, - &lldb_private::EmulateInstruction::ReadRegisterFrame, - &lldb_private::EmulateInstruction::WriteRegisterFrame); + return inst_sp->Emulate(arch, + evaluate_options, + (void *) frame_sp.get(), + &lldb_private::EmulateInstruction::ReadMemoryFrame, + &lldb_private::EmulateInstruction::WriteMemoryFrame, + &lldb_private::EmulateInstruction::ReadRegisterFrame, + &lldb_private::EmulateInstruction::WriteRegisterFrame); } } return false; @@ -243,29 +314,32 @@ SBInstruction::EmulateWithFrame (lldb::SBFrame &frame, uint32_t evaluate_options bool SBInstruction::DumpEmulation (const char *triple) { - if (m_opaque_sp && triple) + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp && triple) { lldb_private::ArchSpec arch (triple, NULL); - - return m_opaque_sp->DumpEmulation (arch); - + return inst_sp->DumpEmulation (arch); } return false; } bool -SBInstruction::TestEmulation (lldb::SBStream &output_stream, const char *test_file) +SBInstruction::TestEmulation (lldb::SBStream &output_stream, const char *test_file) { - if (!m_opaque_sp.get()) - m_opaque_sp.reset (new PseudoInstruction()); - - return m_opaque_sp->TestEmulation (output_stream.get(), test_file); + if (!m_opaque_sp) + SetOpaque(lldb::DisassemblerSP(), lldb::InstructionSP(new PseudoInstruction())); + + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) + return inst_sp->TestEmulation (output_stream.get(), test_file); + return false; } lldb::AddressClass SBInstruction::GetAddressClass () { - if (m_opaque_sp.get()) - return m_opaque_sp->GetAddressClass(); + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) + return inst_sp->GetAddressClass(); return eAddressClassInvalid; } |