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 21using namespace lldb; 22using namespace lldb_private; 23 24SBInstructionList::SBInstructionList() { LLDB_INSTRUMENT_VA(this); } 25 26SBInstructionList::SBInstructionList(const SBInstructionList &rhs) 27 : m_opaque_sp(rhs.m_opaque_sp) { 28 LLDB_INSTRUMENT_VA(this, rhs); 29} 30 31const SBInstructionList &SBInstructionList:: 32operator=(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 40SBInstructionList::~SBInstructionList() = default; 41 42bool SBInstructionList::IsValid() const { 43 LLDB_INSTRUMENT_VA(this); 44 return this->operator bool(); 45} 46SBInstructionList::operator bool() const { 47 LLDB_INSTRUMENT_VA(this); 48 49 return m_opaque_sp.get() != nullptr; 50} 51 52size_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 60SBInstruction 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 71size_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 98void SBInstructionList::Clear() { 99 LLDB_INSTRUMENT_VA(this); 100 101 m_opaque_sp.reset(); 102} 103 104void SBInstructionList::AppendInstruction(SBInstruction insn) { 105 LLDB_INSTRUMENT_VA(this, insn); 106} 107 108void SBInstructionList::SetDisassembler(const lldb::DisassemblerSP &opaque_sp) { 109 m_opaque_sp = opaque_sp; 110} 111 112void 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 120void 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 128void 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 136bool SBInstructionList::GetDescription(lldb::SBStream &stream) { 137 LLDB_INSTRUMENT_VA(this, stream); 138 return GetDescription(stream.ref()); 139} 140 141bool 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 179bool 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