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 using namespace lldb; 30 using namespace lldb_private; 31 32 SBInstruction::SBInstruction () 33 { 34 } 35 36 SBInstruction::SBInstruction (const lldb::InstructionSP& inst_sp) : 37 m_opaque_sp (inst_sp) 38 { 39 } 40 41 SBInstruction::SBInstruction(const SBInstruction &rhs) : 42 m_opaque_sp (rhs.m_opaque_sp) 43 { 44 } 45 46 const SBInstruction & 47 SBInstruction::operator = (const SBInstruction &rhs) 48 { 49 if (this != &rhs) 50 m_opaque_sp = rhs.m_opaque_sp; 51 return *this; 52 } 53 54 SBInstruction::~SBInstruction () 55 { 56 } 57 58 bool 59 SBInstruction::IsValid() 60 { 61 return (m_opaque_sp.get() != NULL); 62 } 63 64 SBAddress 65 SBInstruction::GetAddress() 66 { 67 SBAddress sb_addr; 68 if (m_opaque_sp && m_opaque_sp->GetAddress().IsValid()) 69 sb_addr.SetAddress(&m_opaque_sp->GetAddress()); 70 return sb_addr; 71 } 72 73 const char * 74 SBInstruction::GetMnemonic(SBTarget target) 75 { 76 if (m_opaque_sp) 77 { 78 ExecutionContext exe_ctx; 79 TargetSP target_sp (target.GetSP()); 80 std::unique_lock<std::recursive_mutex> lock; 81 if (target_sp) 82 { 83 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 84 85 target_sp->CalculateExecutionContext (exe_ctx); 86 exe_ctx.SetProcessSP(target_sp->GetProcessSP()); 87 } 88 return m_opaque_sp->GetMnemonic(&exe_ctx); 89 } 90 return NULL; 91 } 92 93 const char * 94 SBInstruction::GetOperands(SBTarget target) 95 { 96 if (m_opaque_sp) 97 { 98 ExecutionContext exe_ctx; 99 TargetSP target_sp (target.GetSP()); 100 std::unique_lock<std::recursive_mutex> lock; 101 if (target_sp) 102 { 103 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 104 105 target_sp->CalculateExecutionContext (exe_ctx); 106 exe_ctx.SetProcessSP(target_sp->GetProcessSP()); 107 } 108 return m_opaque_sp->GetOperands(&exe_ctx); 109 } 110 return NULL; 111 } 112 113 const char * 114 SBInstruction::GetComment(SBTarget target) 115 { 116 if (m_opaque_sp) 117 { 118 ExecutionContext exe_ctx; 119 TargetSP target_sp (target.GetSP()); 120 std::unique_lock<std::recursive_mutex> lock; 121 if (target_sp) 122 { 123 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 124 125 target_sp->CalculateExecutionContext (exe_ctx); 126 exe_ctx.SetProcessSP(target_sp->GetProcessSP()); 127 } 128 return m_opaque_sp->GetComment(&exe_ctx); 129 } 130 return NULL; 131 } 132 133 size_t 134 SBInstruction::GetByteSize () 135 { 136 if (m_opaque_sp) 137 return m_opaque_sp->GetOpcode().GetByteSize(); 138 return 0; 139 } 140 141 SBData 142 SBInstruction::GetData (SBTarget target) 143 { 144 lldb::SBData sb_data; 145 if (m_opaque_sp) 146 { 147 DataExtractorSP data_extractor_sp (new DataExtractor()); 148 if (m_opaque_sp->GetData (*data_extractor_sp)) 149 { 150 sb_data.SetOpaque (data_extractor_sp); 151 } 152 } 153 return sb_data; 154 } 155 156 157 158 bool 159 SBInstruction::DoesBranch () 160 { 161 if (m_opaque_sp) 162 return m_opaque_sp->DoesBranch (); 163 return false; 164 } 165 166 bool 167 SBInstruction::HasDelaySlot () 168 { 169 if (m_opaque_sp) 170 return m_opaque_sp->HasDelaySlot (); 171 return false; 172 } 173 174 void 175 SBInstruction::SetOpaque (const lldb::InstructionSP &inst_sp) 176 { 177 m_opaque_sp = inst_sp; 178 } 179 180 bool 181 SBInstruction::GetDescription (lldb::SBStream &s) 182 { 183 if (m_opaque_sp) 184 { 185 SymbolContext sc; 186 const Address &addr = m_opaque_sp->GetAddress(); 187 ModuleSP module_sp (addr.GetModule()); 188 if (module_sp) 189 module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); 190 // Use the "ref()" instead of the "get()" accessor in case the SBStream 191 // didn't have a stream already created, one will get created... 192 FormatEntity::Entry format; 193 FormatEntity::Parse("${addr}: ", format); 194 m_opaque_sp->Dump (&s.ref(), 0, true, false, NULL, &sc, NULL, &format, 0); 195 return true; 196 } 197 return false; 198 } 199 200 void 201 SBInstruction::Print (FILE *out) 202 { 203 if (out == NULL) 204 return; 205 206 if (m_opaque_sp) 207 { 208 SymbolContext sc; 209 const Address &addr = m_opaque_sp->GetAddress(); 210 ModuleSP module_sp (addr.GetModule()); 211 if (module_sp) 212 module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); 213 StreamFile out_stream (out, false); 214 FormatEntity::Entry format; 215 FormatEntity::Parse("${addr}: ", format); 216 m_opaque_sp->Dump (&out_stream, 0, true, false, NULL, &sc, NULL, &format, 0); 217 } 218 } 219 220 bool 221 SBInstruction::EmulateWithFrame (lldb::SBFrame &frame, uint32_t evaluate_options) 222 { 223 if (m_opaque_sp) 224 { 225 lldb::StackFrameSP frame_sp (frame.GetFrameSP()); 226 227 if (frame_sp) 228 { 229 lldb_private::ExecutionContext exe_ctx; 230 frame_sp->CalculateExecutionContext (exe_ctx); 231 lldb_private::Target *target = exe_ctx.GetTargetPtr(); 232 lldb_private::ArchSpec arch = target->GetArchitecture(); 233 234 return m_opaque_sp->Emulate (arch, 235 evaluate_options, 236 (void *) frame_sp.get(), 237 &lldb_private::EmulateInstruction::ReadMemoryFrame, 238 &lldb_private::EmulateInstruction::WriteMemoryFrame, 239 &lldb_private::EmulateInstruction::ReadRegisterFrame, 240 &lldb_private::EmulateInstruction::WriteRegisterFrame); 241 } 242 } 243 return false; 244 } 245 246 bool 247 SBInstruction::DumpEmulation (const char *triple) 248 { 249 if (m_opaque_sp && triple) 250 { 251 lldb_private::ArchSpec arch (triple, NULL); 252 253 return m_opaque_sp->DumpEmulation (arch); 254 255 } 256 return false; 257 } 258 259 bool 260 SBInstruction::TestEmulation (lldb::SBStream &output_stream, const char *test_file) 261 { 262 if (!m_opaque_sp.get()) 263 m_opaque_sp.reset (new PseudoInstruction()); 264 265 return m_opaque_sp->TestEmulation (output_stream.get(), test_file); 266 } 267 268 lldb::AddressClass 269 SBInstruction::GetAddressClass () 270 { 271 if (m_opaque_sp.get()) 272 return m_opaque_sp->GetAddressClass(); 273 return eAddressClassInvalid; 274 } 275