209 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/API/SBInstructionList.h"10#include "lldb/API/SBAddress.h"11#include "lldb/API/SBExecutionContext.h"12#include "lldb/API/SBFile.h"13#include "lldb/API/SBInstruction.h"14#include "lldb/API/SBStream.h"15#include "lldb/Core/Disassembler.h"16#include "lldb/Core/Module.h"17#include "lldb/Host/StreamFile.h"18#include "lldb/Symbol/SymbolContext.h"19#include "lldb/Target/ExecutionContext.h"20#include "lldb/Utility/Instrumentation.h"21#include "lldb/Utility/Stream.h"22 23using namespace lldb;24using namespace lldb_private;25 26SBInstructionList::SBInstructionList() { LLDB_INSTRUMENT_VA(this); }27 28SBInstructionList::SBInstructionList(const SBInstructionList &rhs)29 : m_opaque_sp(rhs.m_opaque_sp) {30 LLDB_INSTRUMENT_VA(this, rhs);31}32 33const SBInstructionList &SBInstructionList::34operator=(const SBInstructionList &rhs) {35 LLDB_INSTRUMENT_VA(this, rhs);36 37 if (this != &rhs)38 m_opaque_sp = rhs.m_opaque_sp;39 return *this;40}41 42SBInstructionList::~SBInstructionList() = default;43 44bool SBInstructionList::IsValid() const {45 LLDB_INSTRUMENT_VA(this);46 return this->operator bool();47}48SBInstructionList::operator bool() const {49 LLDB_INSTRUMENT_VA(this);50 51 return m_opaque_sp.get() != nullptr;52}53 54size_t SBInstructionList::GetSize() {55 LLDB_INSTRUMENT_VA(this);56 57 if (m_opaque_sp)58 return m_opaque_sp->GetInstructionList().GetSize();59 return 0;60}61 62SBInstruction SBInstructionList::GetInstructionAtIndex(uint32_t idx) {63 LLDB_INSTRUMENT_VA(this, idx);64 65 SBInstruction inst;66 if (m_opaque_sp && idx < m_opaque_sp->GetInstructionList().GetSize())67 inst.SetOpaque(68 m_opaque_sp,69 m_opaque_sp->GetInstructionList().GetInstructionAtIndex(idx));70 return inst;71}72 73size_t SBInstructionList::GetInstructionsCount(const SBAddress &start,74 const SBAddress &end,75 bool canSetBreakpoint) {76 LLDB_INSTRUMENT_VA(this, start, end, canSetBreakpoint);77 78 size_t num_instructions = GetSize();79 size_t i = 0;80 SBAddress addr;81 size_t lower_index = 0;82 size_t upper_index = 0;83 size_t instructions_to_skip = 0;84 for (i = 0; i < num_instructions; ++i) {85 addr = GetInstructionAtIndex(i).GetAddress();86 if (start == addr)87 lower_index = i;88 if (end == addr)89 upper_index = i;90 }91 if (canSetBreakpoint)92 for (i = lower_index; i <= upper_index; ++i) {93 SBInstruction insn = GetInstructionAtIndex(i);94 if (!insn.CanSetBreakpoint())95 ++instructions_to_skip;96 }97 return upper_index - lower_index - instructions_to_skip;98}99 100void SBInstructionList::Clear() {101 LLDB_INSTRUMENT_VA(this);102 103 m_opaque_sp.reset();104}105 106void SBInstructionList::AppendInstruction(SBInstruction insn) {107 LLDB_INSTRUMENT_VA(this, insn);108}109 110void SBInstructionList::SetDisassembler(const lldb::DisassemblerSP &opaque_sp) {111 m_opaque_sp = opaque_sp;112}113 114void SBInstructionList::Print(FILE *out) {115 LLDB_INSTRUMENT_VA(this, out);116 if (out == nullptr)117 return;118 StreamFile stream(out, false);119 GetDescription(stream);120}121 122void SBInstructionList::Print(SBFile out) {123 LLDB_INSTRUMENT_VA(this, out);124 if (!out.IsValid())125 return;126 StreamFile stream(out.m_opaque_sp);127 GetDescription(stream);128}129 130void SBInstructionList::Print(FileSP out_sp) {131 LLDB_INSTRUMENT_VA(this, out_sp);132 if (!out_sp || !out_sp->IsValid())133 return;134 StreamFile stream(out_sp);135 GetDescription(stream);136}137 138bool SBInstructionList::GetDescription(lldb::SBStream &stream) {139 LLDB_INSTRUMENT_VA(this, stream);140 return GetDescription(stream.ref());141}142 143bool SBInstructionList::GetDescription(lldb::SBStream &stream,144 lldb::SBExecutionContext &exe_ctx) {145 LLDB_INSTRUMENT_VA(this, stream);146 ExecutionContext exe_ctx_wrapper(exe_ctx.get());147 return GetDescription(stream.ref(), &exe_ctx_wrapper);148}149 150bool SBInstructionList::GetDescription(151 Stream &sref, lldb_private::ExecutionContext *exe_ctx) {152 153 if (m_opaque_sp) {154 size_t num_instructions = GetSize();155 if (num_instructions) {156 // Call the ref() to make sure a stream is created if one deesn't exist157 // already inside description...158 const uint32_t max_opcode_byte_size =159 m_opaque_sp->GetInstructionList().GetMaxOpcocdeByteSize();160 FormatEntity::Entry format;161 FormatEntity::Parse("${addr-file-or-load}: ", format);162 SymbolContext sc;163 SymbolContext prev_sc;164 165 // Expected address of the next instruction. Used to print an empty line166 // for non-contiguous blocks of insns.167 std::optional<Address> next_addr;168 for (size_t i = 0; i < num_instructions; ++i) {169 Instruction *inst =170 m_opaque_sp->GetInstructionList().GetInstructionAtIndex(i).get();171 if (inst == nullptr)172 break;173 174 const Address &addr = inst->GetAddress();175 prev_sc = sc;176 ModuleSP module_sp(addr.GetModule());177 if (module_sp) {178 module_sp->ResolveSymbolContextForAddress(179 addr, eSymbolContextEverything, sc);180 }181 182 if (next_addr && *next_addr != addr)183 sref.EOL();184 inst->Dump(&sref, max_opcode_byte_size, true, false,185 /*show_control_flow_kind=*/false, exe_ctx, &sc, &prev_sc,186 &format, 0);187 sref.EOL();188 next_addr = addr;189 next_addr->Slide(inst->GetOpcode().GetByteSize());190 }191 return true;192 }193 }194 return false;195}196 197bool SBInstructionList::DumpEmulationForAllInstructions(const char *triple) {198 LLDB_INSTRUMENT_VA(this, triple);199 200 if (m_opaque_sp) {201 size_t len = GetSize();202 for (size_t i = 0; i < len; ++i) {203 if (!GetInstructionAtIndex((uint32_t)i).DumpEmulation(triple))204 return false;205 }206 }207 return true;208}209