1 //===-- SBInstructionList.cpp ---------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/API/SBInstructionList.h" 10 #include "lldb/API/SBAddress.h" 11 #include "lldb/API/SBFile.h" 12 #include "lldb/API/SBInstruction.h" 13 #include "lldb/API/SBStream.h" 14 #include "lldb/Core/Disassembler.h" 15 #include "lldb/Core/Module.h" 16 #include "lldb/Host/StreamFile.h" 17 #include "lldb/Symbol/SymbolContext.h" 18 #include "lldb/Utility/Instrumentation.h" 19 #include "lldb/Utility/Stream.h" 20 21 using namespace lldb; 22 using namespace lldb_private; 23 24 SBInstructionList::SBInstructionList() { LLDB_INSTRUMENT_VA(this); } 25 26 SBInstructionList::SBInstructionList(const SBInstructionList &rhs) 27 : m_opaque_sp(rhs.m_opaque_sp) { 28 LLDB_INSTRUMENT_VA(this, rhs); 29 } 30 31 const SBInstructionList &SBInstructionList:: 32 operator=(const SBInstructionList &rhs) { 33 LLDB_INSTRUMENT_VA(this, rhs); 34 35 if (this != &rhs) 36 m_opaque_sp = rhs.m_opaque_sp; 37 return *this; 38 } 39 40 SBInstructionList::~SBInstructionList() = default; 41 42 bool SBInstructionList::IsValid() const { 43 LLDB_INSTRUMENT_VA(this); 44 return this->operator bool(); 45 } 46 SBInstructionList::operator bool() const { 47 LLDB_INSTRUMENT_VA(this); 48 49 return m_opaque_sp.get() != nullptr; 50 } 51 52 size_t SBInstructionList::GetSize() { 53 LLDB_INSTRUMENT_VA(this); 54 55 if (m_opaque_sp) 56 return m_opaque_sp->GetInstructionList().GetSize(); 57 return 0; 58 } 59 60 SBInstruction SBInstructionList::GetInstructionAtIndex(uint32_t idx) { 61 LLDB_INSTRUMENT_VA(this, idx); 62 63 SBInstruction inst; 64 if (m_opaque_sp && idx < m_opaque_sp->GetInstructionList().GetSize()) 65 inst.SetOpaque( 66 m_opaque_sp, 67 m_opaque_sp->GetInstructionList().GetInstructionAtIndex(idx)); 68 return inst; 69 } 70 71 size_t SBInstructionList::GetInstructionsCount(const SBAddress &start, 72 const SBAddress &end, 73 bool canSetBreakpoint) { 74 LLDB_INSTRUMENT_VA(this, start, end, canSetBreakpoint); 75 76 size_t num_instructions = GetSize(); 77 size_t i = 0; 78 SBAddress addr; 79 size_t lower_index = 0; 80 size_t upper_index = 0; 81 size_t instructions_to_skip = 0; 82 for (i = 0; i < num_instructions; ++i) { 83 addr = GetInstructionAtIndex(i).GetAddress(); 84 if (start == addr) 85 lower_index = i; 86 if (end == addr) 87 upper_index = i; 88 } 89 if (canSetBreakpoint) 90 for (i = lower_index; i <= upper_index; ++i) { 91 SBInstruction insn = GetInstructionAtIndex(i); 92 if (!insn.CanSetBreakpoint()) 93 ++instructions_to_skip; 94 } 95 return upper_index - lower_index - instructions_to_skip; 96 } 97 98 void SBInstructionList::Clear() { 99 LLDB_INSTRUMENT_VA(this); 100 101 m_opaque_sp.reset(); 102 } 103 104 void SBInstructionList::AppendInstruction(SBInstruction insn) { 105 LLDB_INSTRUMENT_VA(this, insn); 106 } 107 108 void SBInstructionList::SetDisassembler(const lldb::DisassemblerSP &opaque_sp) { 109 m_opaque_sp = opaque_sp; 110 } 111 112 void SBInstructionList::Print(FILE *out) { 113 LLDB_INSTRUMENT_VA(this, out); 114 if (out == nullptr) 115 return; 116 StreamFile stream(out, false); 117 GetDescription(stream); 118 } 119 120 void SBInstructionList::Print(SBFile out) { 121 LLDB_INSTRUMENT_VA(this, out); 122 if (!out.IsValid()) 123 return; 124 StreamFile stream(out.m_opaque_sp); 125 GetDescription(stream); 126 } 127 128 void SBInstructionList::Print(FileSP out_sp) { 129 LLDB_INSTRUMENT_VA(this, out_sp); 130 if (!out_sp || !out_sp->IsValid()) 131 return; 132 StreamFile stream(out_sp); 133 GetDescription(stream); 134 } 135 136 bool SBInstructionList::GetDescription(lldb::SBStream &stream) { 137 LLDB_INSTRUMENT_VA(this, stream); 138 return GetDescription(stream.ref()); 139 } 140 141 bool SBInstructionList::GetDescription(Stream &sref) { 142 143 if (m_opaque_sp) { 144 size_t num_instructions = GetSize(); 145 if (num_instructions) { 146 // Call the ref() to make sure a stream is created if one deesn't exist 147 // already inside description... 148 const uint32_t max_opcode_byte_size = 149 m_opaque_sp->GetInstructionList().GetMaxOpcocdeByteSize(); 150 FormatEntity::Entry format; 151 FormatEntity::Parse("${addr}: ", format); 152 SymbolContext sc; 153 SymbolContext prev_sc; 154 for (size_t i = 0; i < num_instructions; ++i) { 155 Instruction *inst = 156 m_opaque_sp->GetInstructionList().GetInstructionAtIndex(i).get(); 157 if (inst == nullptr) 158 break; 159 160 const Address &addr = inst->GetAddress(); 161 prev_sc = sc; 162 ModuleSP module_sp(addr.GetModule()); 163 if (module_sp) { 164 module_sp->ResolveSymbolContextForAddress( 165 addr, eSymbolContextEverything, sc); 166 } 167 168 inst->Dump(&sref, max_opcode_byte_size, true, false, 169 /*show_control_flow_kind=*/false, nullptr, &sc, &prev_sc, 170 &format, 0); 171 sref.EOL(); 172 } 173 return true; 174 } 175 } 176 return false; 177 } 178 179 bool SBInstructionList::DumpEmulationForAllInstructions(const char *triple) { 180 LLDB_INSTRUMENT_VA(this, triple); 181 182 if (m_opaque_sp) { 183 size_t len = GetSize(); 184 for (size_t i = 0; i < len; ++i) { 185 if (!GetInstructionAtIndex((uint32_t)i).DumpEmulation(triple)) 186 return false; 187 } 188 } 189 return true; 190 } 191