1 //===-- SBInstruction.cpp ---------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/API/SBInstruction.h" 11 12 #include "lldb/API/SBAddress.h" 13 #include "lldb/API/SBFrame.h" 14 #include "lldb/API/SBInstruction.h" 15 #include "lldb/API/SBStream.h" 16 #include "lldb/API/SBTarget.h" 17 18 #include "lldb/Core/ArchSpec.h" 19 #include "lldb/Core/DataBufferHeap.h" 20 #include "lldb/Core/DataExtractor.h" 21 #include "lldb/Core/Disassembler.h" 22 #include "lldb/Core/EmulateInstruction.h" 23 #include "lldb/Core/Module.h" 24 #include "lldb/Core/StreamFile.h" 25 #include "lldb/Target/ExecutionContext.h" 26 #include "lldb/Target/StackFrame.h" 27 #include "lldb/Target/Target.h" 28 29 //---------------------------------------------------------------------- 30 // We recently fixed a leak in one of the Instruction subclasses where 31 // the instruction will only hold a weak reference to the disassembler 32 // to avoid a cycle that was keeping both objects alive (leak) and we 33 // need the InstructionImpl class to make sure our public API behaves 34 // as users would expect. Calls in our public API allow clients to do 35 // things like: 36 // 37 // 1 lldb::SBInstruction inst; 38 // 2 inst = target.ReadInstructions(pc, 1).GetInstructionAtIndex(0) 39 // 3 if (inst.DoesBranch()) 40 // 4 ... 41 // 42 // There was a temporary lldb::DisassemblerSP object created in the 43 // SBInstructionList that was returned by lldb.target.ReadInstructions() 44 // that will go away after line 2 but the "inst" object should be able 45 // to still answer questions about itself. So we make sure that any 46 // SBInstruction objects that are given out have a strong reference to 47 // the disassembler and the instruction so that the object can live and 48 // successfully respond to all queries. 49 //---------------------------------------------------------------------- 50 class InstructionImpl { 51 public: 52 InstructionImpl(const lldb::DisassemblerSP &disasm_sp, 53 const lldb::InstructionSP &inst_sp) 54 : m_disasm_sp(disasm_sp), m_inst_sp(inst_sp) {} 55 56 lldb::InstructionSP GetSP() const { return m_inst_sp; } 57 58 bool IsValid() const { return (bool)m_inst_sp; } 59 60 protected: 61 lldb::DisassemblerSP m_disasm_sp; // Can be empty/invalid 62 lldb::InstructionSP m_inst_sp; 63 }; 64 65 using namespace lldb; 66 using namespace lldb_private; 67 68 SBInstruction::SBInstruction() : m_opaque_sp() {} 69 70 SBInstruction::SBInstruction(const lldb::DisassemblerSP &disasm_sp, 71 const lldb::InstructionSP &inst_sp) 72 : m_opaque_sp(new InstructionImpl(disasm_sp, inst_sp)) {} 73 74 SBInstruction::SBInstruction(const SBInstruction &rhs) 75 : m_opaque_sp(rhs.m_opaque_sp) {} 76 77 const SBInstruction &SBInstruction::operator=(const SBInstruction &rhs) { 78 if (this != &rhs) 79 m_opaque_sp = rhs.m_opaque_sp; 80 return *this; 81 } 82 83 SBInstruction::~SBInstruction() {} 84 85 bool SBInstruction::IsValid() { return m_opaque_sp && m_opaque_sp->IsValid(); } 86 87 SBAddress SBInstruction::GetAddress() { 88 SBAddress sb_addr; 89 lldb::InstructionSP inst_sp(GetOpaque()); 90 if (inst_sp && inst_sp->GetAddress().IsValid()) 91 sb_addr.SetAddress(&inst_sp->GetAddress()); 92 return sb_addr; 93 } 94 95 const char *SBInstruction::GetMnemonic(SBTarget target) { 96 lldb::InstructionSP inst_sp(GetOpaque()); 97 if (inst_sp) { 98 ExecutionContext exe_ctx; 99 TargetSP target_sp(target.GetSP()); 100 std::unique_lock<std::recursive_mutex> lock; 101 if (target_sp) { 102 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 103 104 target_sp->CalculateExecutionContext(exe_ctx); 105 exe_ctx.SetProcessSP(target_sp->GetProcessSP()); 106 } 107 return inst_sp->GetMnemonic(&exe_ctx); 108 } 109 return NULL; 110 } 111 112 const char *SBInstruction::GetOperands(SBTarget target) { 113 lldb::InstructionSP inst_sp(GetOpaque()); 114 if (inst_sp) { 115 ExecutionContext exe_ctx; 116 TargetSP target_sp(target.GetSP()); 117 std::unique_lock<std::recursive_mutex> lock; 118 if (target_sp) { 119 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 120 121 target_sp->CalculateExecutionContext(exe_ctx); 122 exe_ctx.SetProcessSP(target_sp->GetProcessSP()); 123 } 124 return inst_sp->GetOperands(&exe_ctx); 125 } 126 return NULL; 127 } 128 129 const char *SBInstruction::GetComment(SBTarget target) { 130 lldb::InstructionSP inst_sp(GetOpaque()); 131 if (inst_sp) { 132 ExecutionContext exe_ctx; 133 TargetSP target_sp(target.GetSP()); 134 std::unique_lock<std::recursive_mutex> lock; 135 if (target_sp) { 136 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 137 138 target_sp->CalculateExecutionContext(exe_ctx); 139 exe_ctx.SetProcessSP(target_sp->GetProcessSP()); 140 } 141 return inst_sp->GetComment(&exe_ctx); 142 } 143 return NULL; 144 } 145 146 size_t SBInstruction::GetByteSize() { 147 lldb::InstructionSP inst_sp(GetOpaque()); 148 if (inst_sp) 149 return inst_sp->GetOpcode().GetByteSize(); 150 return 0; 151 } 152 153 SBData SBInstruction::GetData(SBTarget target) { 154 lldb::SBData sb_data; 155 lldb::InstructionSP inst_sp(GetOpaque()); 156 if (inst_sp) { 157 DataExtractorSP data_extractor_sp(new DataExtractor()); 158 if (inst_sp->GetData(*data_extractor_sp)) { 159 sb_data.SetOpaque(data_extractor_sp); 160 } 161 } 162 return sb_data; 163 } 164 165 bool SBInstruction::DoesBranch() { 166 lldb::InstructionSP inst_sp(GetOpaque()); 167 if (inst_sp) 168 return inst_sp->DoesBranch(); 169 return false; 170 } 171 172 bool SBInstruction::HasDelaySlot() { 173 lldb::InstructionSP inst_sp(GetOpaque()); 174 if (inst_sp) 175 return inst_sp->HasDelaySlot(); 176 return false; 177 } 178 179 lldb::InstructionSP SBInstruction::GetOpaque() { 180 if (m_opaque_sp) 181 return m_opaque_sp->GetSP(); 182 else 183 return lldb::InstructionSP(); 184 } 185 186 void SBInstruction::SetOpaque(const lldb::DisassemblerSP &disasm_sp, 187 const lldb::InstructionSP &inst_sp) { 188 m_opaque_sp.reset(new InstructionImpl(disasm_sp, inst_sp)); 189 } 190 191 bool SBInstruction::GetDescription(lldb::SBStream &s) { 192 lldb::InstructionSP inst_sp(GetOpaque()); 193 if (inst_sp) { 194 SymbolContext sc; 195 const Address &addr = inst_sp->GetAddress(); 196 ModuleSP module_sp(addr.GetModule()); 197 if (module_sp) 198 module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, 199 sc); 200 // Use the "ref()" instead of the "get()" accessor in case the SBStream 201 // didn't have a stream already created, one will get created... 202 FormatEntity::Entry format; 203 FormatEntity::Parse("${addr}: ", format); 204 inst_sp->Dump(&s.ref(), 0, true, false, NULL, &sc, NULL, &format, 0); 205 return true; 206 } 207 return false; 208 } 209 210 void SBInstruction::Print(FILE *out) { 211 if (out == NULL) 212 return; 213 214 lldb::InstructionSP inst_sp(GetOpaque()); 215 if (inst_sp) { 216 SymbolContext sc; 217 const Address &addr = inst_sp->GetAddress(); 218 ModuleSP module_sp(addr.GetModule()); 219 if (module_sp) 220 module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, 221 sc); 222 StreamFile out_stream(out, false); 223 FormatEntity::Entry format; 224 FormatEntity::Parse("${addr}: ", format); 225 inst_sp->Dump(&out_stream, 0, true, false, NULL, &sc, NULL, &format, 0); 226 } 227 } 228 229 bool SBInstruction::EmulateWithFrame(lldb::SBFrame &frame, 230 uint32_t evaluate_options) { 231 lldb::InstructionSP inst_sp(GetOpaque()); 232 if (inst_sp) { 233 lldb::StackFrameSP frame_sp(frame.GetFrameSP()); 234 235 if (frame_sp) { 236 lldb_private::ExecutionContext exe_ctx; 237 frame_sp->CalculateExecutionContext(exe_ctx); 238 lldb_private::Target *target = exe_ctx.GetTargetPtr(); 239 lldb_private::ArchSpec arch = target->GetArchitecture(); 240 241 return inst_sp->Emulate( 242 arch, evaluate_options, (void *)frame_sp.get(), 243 &lldb_private::EmulateInstruction::ReadMemoryFrame, 244 &lldb_private::EmulateInstruction::WriteMemoryFrame, 245 &lldb_private::EmulateInstruction::ReadRegisterFrame, 246 &lldb_private::EmulateInstruction::WriteRegisterFrame); 247 } 248 } 249 return false; 250 } 251 252 bool SBInstruction::DumpEmulation(const char *triple) { 253 lldb::InstructionSP inst_sp(GetOpaque()); 254 if (inst_sp && triple) { 255 lldb_private::ArchSpec arch(triple, NULL); 256 return inst_sp->DumpEmulation(arch); 257 } 258 return false; 259 } 260 261 bool SBInstruction::TestEmulation(lldb::SBStream &output_stream, 262 const char *test_file) { 263 if (!m_opaque_sp) 264 SetOpaque(lldb::DisassemblerSP(), 265 lldb::InstructionSP(new PseudoInstruction())); 266 267 lldb::InstructionSP inst_sp(GetOpaque()); 268 if (inst_sp) 269 return inst_sp->TestEmulation(output_stream.get(), test_file); 270 return false; 271 } 272 273 lldb::AddressClass SBInstruction::GetAddressClass() { 274 lldb::InstructionSP inst_sp(GetOpaque()); 275 if (inst_sp) 276 return inst_sp->GetAddressClass(); 277 return eAddressClassInvalid; 278 } 279