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 { 52 public: 53 InstructionImpl (const lldb::DisassemblerSP &disasm_sp, const lldb::InstructionSP& inst_sp) : 54 m_disasm_sp(disasm_sp), 55 m_inst_sp(inst_sp) 56 { 57 } 58 59 lldb::InstructionSP 60 GetSP() const 61 { 62 return m_inst_sp; 63 } 64 65 bool 66 IsValid() const 67 { 68 return (bool)m_inst_sp; 69 } 70 71 protected: 72 lldb::DisassemblerSP m_disasm_sp; // Can be empty/invalid 73 lldb::InstructionSP m_inst_sp; 74 }; 75 76 using namespace lldb; 77 using namespace lldb_private; 78 79 SBInstruction::SBInstruction() : 80 m_opaque_sp() 81 { 82 } 83 84 SBInstruction::SBInstruction(const lldb::DisassemblerSP &disasm_sp, const lldb::InstructionSP& inst_sp) : 85 m_opaque_sp(new InstructionImpl(disasm_sp, inst_sp)) 86 { 87 } 88 89 SBInstruction::SBInstruction(const SBInstruction &rhs) : 90 m_opaque_sp (rhs.m_opaque_sp) 91 { 92 } 93 94 const SBInstruction & 95 SBInstruction::operator = (const SBInstruction &rhs) 96 { 97 if (this != &rhs) 98 m_opaque_sp = rhs.m_opaque_sp; 99 return *this; 100 } 101 102 SBInstruction::~SBInstruction () 103 { 104 } 105 106 bool 107 SBInstruction::IsValid() 108 { 109 return m_opaque_sp && m_opaque_sp->IsValid(); 110 } 111 112 SBAddress 113 SBInstruction::GetAddress() 114 { 115 SBAddress sb_addr; 116 lldb::InstructionSP inst_sp(GetOpaque()); 117 if (inst_sp && inst_sp->GetAddress().IsValid()) 118 sb_addr.SetAddress(&inst_sp->GetAddress()); 119 return sb_addr; 120 } 121 122 const char * 123 SBInstruction::GetMnemonic(SBTarget target) 124 { 125 lldb::InstructionSP inst_sp(GetOpaque()); 126 if (inst_sp) 127 { 128 ExecutionContext exe_ctx; 129 TargetSP target_sp (target.GetSP()); 130 std::unique_lock<std::recursive_mutex> lock; 131 if (target_sp) 132 { 133 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 134 135 target_sp->CalculateExecutionContext (exe_ctx); 136 exe_ctx.SetProcessSP(target_sp->GetProcessSP()); 137 } 138 return inst_sp->GetMnemonic(&exe_ctx); 139 } 140 return NULL; 141 } 142 143 const char * 144 SBInstruction::GetOperands(SBTarget target) 145 { 146 lldb::InstructionSP inst_sp(GetOpaque()); 147 if (inst_sp) 148 { 149 ExecutionContext exe_ctx; 150 TargetSP target_sp (target.GetSP()); 151 std::unique_lock<std::recursive_mutex> lock; 152 if (target_sp) 153 { 154 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 155 156 target_sp->CalculateExecutionContext (exe_ctx); 157 exe_ctx.SetProcessSP(target_sp->GetProcessSP()); 158 } 159 return inst_sp->GetOperands(&exe_ctx); 160 } 161 return NULL; 162 } 163 164 const char * 165 SBInstruction::GetComment(SBTarget target) 166 { 167 lldb::InstructionSP inst_sp(GetOpaque()); 168 if (inst_sp) 169 { 170 ExecutionContext exe_ctx; 171 TargetSP target_sp (target.GetSP()); 172 std::unique_lock<std::recursive_mutex> lock; 173 if (target_sp) 174 { 175 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 176 177 target_sp->CalculateExecutionContext (exe_ctx); 178 exe_ctx.SetProcessSP(target_sp->GetProcessSP()); 179 } 180 return inst_sp->GetComment(&exe_ctx); 181 } 182 return NULL; 183 } 184 185 size_t 186 SBInstruction::GetByteSize () 187 { 188 lldb::InstructionSP inst_sp(GetOpaque()); 189 if (inst_sp) 190 return inst_sp->GetOpcode().GetByteSize(); 191 return 0; 192 } 193 194 SBData 195 SBInstruction::GetData (SBTarget target) 196 { 197 lldb::SBData sb_data; 198 lldb::InstructionSP inst_sp(GetOpaque()); 199 if (inst_sp) 200 { 201 DataExtractorSP data_extractor_sp (new DataExtractor()); 202 if (inst_sp->GetData (*data_extractor_sp)) 203 { 204 sb_data.SetOpaque (data_extractor_sp); 205 } 206 } 207 return sb_data; 208 } 209 210 211 212 bool 213 SBInstruction::DoesBranch () 214 { 215 lldb::InstructionSP inst_sp(GetOpaque()); 216 if (inst_sp) 217 return inst_sp->DoesBranch (); 218 return false; 219 } 220 221 bool 222 SBInstruction::HasDelaySlot () 223 { 224 lldb::InstructionSP inst_sp(GetOpaque()); 225 if (inst_sp) 226 return inst_sp->HasDelaySlot (); 227 return false; 228 } 229 230 lldb::InstructionSP 231 SBInstruction::GetOpaque () 232 { 233 if (m_opaque_sp) 234 return m_opaque_sp->GetSP(); 235 else 236 return lldb::InstructionSP(); 237 } 238 239 void 240 SBInstruction::SetOpaque (const lldb::DisassemblerSP &disasm_sp, const lldb::InstructionSP& inst_sp) 241 { 242 m_opaque_sp.reset(new InstructionImpl(disasm_sp, inst_sp)); 243 } 244 245 bool 246 SBInstruction::GetDescription (lldb::SBStream &s) 247 { 248 lldb::InstructionSP inst_sp(GetOpaque()); 249 if (inst_sp) 250 { 251 SymbolContext sc; 252 const Address &addr = inst_sp->GetAddress(); 253 ModuleSP module_sp (addr.GetModule()); 254 if (module_sp) 255 module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); 256 // Use the "ref()" instead of the "get()" accessor in case the SBStream 257 // didn't have a stream already created, one will get created... 258 FormatEntity::Entry format; 259 FormatEntity::Parse("${addr}: ", format); 260 inst_sp->Dump (&s.ref(), 0, true, false, NULL, &sc, NULL, &format, 0); 261 return true; 262 } 263 return false; 264 } 265 266 void 267 SBInstruction::Print (FILE *out) 268 { 269 if (out == NULL) 270 return; 271 272 lldb::InstructionSP inst_sp(GetOpaque()); 273 if (inst_sp) 274 { 275 SymbolContext sc; 276 const Address &addr = inst_sp->GetAddress(); 277 ModuleSP module_sp (addr.GetModule()); 278 if (module_sp) 279 module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); 280 StreamFile out_stream (out, false); 281 FormatEntity::Entry format; 282 FormatEntity::Parse("${addr}: ", format); 283 inst_sp->Dump (&out_stream, 0, true, false, NULL, &sc, NULL, &format, 0); 284 } 285 } 286 287 bool 288 SBInstruction::EmulateWithFrame (lldb::SBFrame &frame, uint32_t evaluate_options) 289 { 290 lldb::InstructionSP inst_sp(GetOpaque()); 291 if (inst_sp) 292 { 293 lldb::StackFrameSP frame_sp (frame.GetFrameSP()); 294 295 if (frame_sp) 296 { 297 lldb_private::ExecutionContext exe_ctx; 298 frame_sp->CalculateExecutionContext (exe_ctx); 299 lldb_private::Target *target = exe_ctx.GetTargetPtr(); 300 lldb_private::ArchSpec arch = target->GetArchitecture(); 301 302 return inst_sp->Emulate(arch, 303 evaluate_options, 304 (void *) frame_sp.get(), 305 &lldb_private::EmulateInstruction::ReadMemoryFrame, 306 &lldb_private::EmulateInstruction::WriteMemoryFrame, 307 &lldb_private::EmulateInstruction::ReadRegisterFrame, 308 &lldb_private::EmulateInstruction::WriteRegisterFrame); 309 } 310 } 311 return false; 312 } 313 314 bool 315 SBInstruction::DumpEmulation (const char *triple) 316 { 317 lldb::InstructionSP inst_sp(GetOpaque()); 318 if (inst_sp && triple) 319 { 320 lldb_private::ArchSpec arch (triple, NULL); 321 return inst_sp->DumpEmulation (arch); 322 } 323 return false; 324 } 325 326 bool 327 SBInstruction::TestEmulation (lldb::SBStream &output_stream, const char *test_file) 328 { 329 if (!m_opaque_sp) 330 SetOpaque(lldb::DisassemblerSP(), lldb::InstructionSP(new PseudoInstruction())); 331 332 lldb::InstructionSP inst_sp(GetOpaque()); 333 if (inst_sp) 334 return inst_sp->TestEmulation (output_stream.get(), test_file); 335 return false; 336 } 337 338 lldb::AddressClass 339 SBInstruction::GetAddressClass () 340 { 341 lldb::InstructionSP inst_sp(GetOpaque()); 342 if (inst_sp) 343 return inst_sp->GetAddressClass(); 344 return eAddressClassInvalid; 345 } 346