15ffd83dbSDimitry Andric //===-- SBInstructionList.cpp ---------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "lldb/API/SBInstructionList.h"
100b57cec5SDimitry Andric #include "lldb/API/SBAddress.h"
1104eeddc0SDimitry Andric #include "lldb/API/SBFile.h"
120b57cec5SDimitry Andric #include "lldb/API/SBInstruction.h"
130b57cec5SDimitry Andric #include "lldb/API/SBStream.h"
140b57cec5SDimitry Andric #include "lldb/Core/Disassembler.h"
150b57cec5SDimitry Andric #include "lldb/Core/Module.h"
165f757f3fSDimitry Andric #include "lldb/Host/StreamFile.h"
170b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
1804eeddc0SDimitry Andric #include "lldb/Utility/Instrumentation.h"
190b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
200b57cec5SDimitry Andric
210b57cec5SDimitry Andric using namespace lldb;
220b57cec5SDimitry Andric using namespace lldb_private;
230b57cec5SDimitry Andric
SBInstructionList()2404eeddc0SDimitry Andric SBInstructionList::SBInstructionList() { LLDB_INSTRUMENT_VA(this); }
250b57cec5SDimitry Andric
SBInstructionList(const SBInstructionList & rhs)260b57cec5SDimitry Andric SBInstructionList::SBInstructionList(const SBInstructionList &rhs)
270b57cec5SDimitry Andric : m_opaque_sp(rhs.m_opaque_sp) {
2804eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, rhs);
290b57cec5SDimitry Andric }
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric const SBInstructionList &SBInstructionList::
operator =(const SBInstructionList & rhs)320b57cec5SDimitry Andric operator=(const SBInstructionList &rhs) {
3304eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, rhs);
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric if (this != &rhs)
360b57cec5SDimitry Andric m_opaque_sp = rhs.m_opaque_sp;
3704eeddc0SDimitry Andric return *this;
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric
405ffd83dbSDimitry Andric SBInstructionList::~SBInstructionList() = default;
410b57cec5SDimitry Andric
IsValid() const420b57cec5SDimitry Andric bool SBInstructionList::IsValid() const {
4304eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this);
440b57cec5SDimitry Andric return this->operator bool();
450b57cec5SDimitry Andric }
operator bool() const460b57cec5SDimitry Andric SBInstructionList::operator bool() const {
4704eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this);
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric return m_opaque_sp.get() != nullptr;
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric
GetSize()520b57cec5SDimitry Andric size_t SBInstructionList::GetSize() {
5304eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this);
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric if (m_opaque_sp)
560b57cec5SDimitry Andric return m_opaque_sp->GetInstructionList().GetSize();
570b57cec5SDimitry Andric return 0;
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric
GetInstructionAtIndex(uint32_t idx)600b57cec5SDimitry Andric SBInstruction SBInstructionList::GetInstructionAtIndex(uint32_t idx) {
6104eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, idx);
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric SBInstruction inst;
640b57cec5SDimitry Andric if (m_opaque_sp && idx < m_opaque_sp->GetInstructionList().GetSize())
650b57cec5SDimitry Andric inst.SetOpaque(
660b57cec5SDimitry Andric m_opaque_sp,
670b57cec5SDimitry Andric m_opaque_sp->GetInstructionList().GetInstructionAtIndex(idx));
6804eeddc0SDimitry Andric return inst;
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric
GetInstructionsCount(const SBAddress & start,const SBAddress & end,bool canSetBreakpoint)710b57cec5SDimitry Andric size_t SBInstructionList::GetInstructionsCount(const SBAddress &start,
720b57cec5SDimitry Andric const SBAddress &end,
730b57cec5SDimitry Andric bool canSetBreakpoint) {
7404eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, start, end, canSetBreakpoint);
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric size_t num_instructions = GetSize();
770b57cec5SDimitry Andric size_t i = 0;
780b57cec5SDimitry Andric SBAddress addr;
790b57cec5SDimitry Andric size_t lower_index = 0;
800b57cec5SDimitry Andric size_t upper_index = 0;
810b57cec5SDimitry Andric size_t instructions_to_skip = 0;
820b57cec5SDimitry Andric for (i = 0; i < num_instructions; ++i) {
830b57cec5SDimitry Andric addr = GetInstructionAtIndex(i).GetAddress();
840b57cec5SDimitry Andric if (start == addr)
850b57cec5SDimitry Andric lower_index = i;
860b57cec5SDimitry Andric if (end == addr)
870b57cec5SDimitry Andric upper_index = i;
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric if (canSetBreakpoint)
900b57cec5SDimitry Andric for (i = lower_index; i <= upper_index; ++i) {
910b57cec5SDimitry Andric SBInstruction insn = GetInstructionAtIndex(i);
920b57cec5SDimitry Andric if (!insn.CanSetBreakpoint())
930b57cec5SDimitry Andric ++instructions_to_skip;
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric return upper_index - lower_index - instructions_to_skip;
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
Clear()980b57cec5SDimitry Andric void SBInstructionList::Clear() {
9904eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this);
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric m_opaque_sp.reset();
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric
AppendInstruction(SBInstruction insn)1040b57cec5SDimitry Andric void SBInstructionList::AppendInstruction(SBInstruction insn) {
10504eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, insn);
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric
SetDisassembler(const lldb::DisassemblerSP & opaque_sp)1080b57cec5SDimitry Andric void SBInstructionList::SetDisassembler(const lldb::DisassemblerSP &opaque_sp) {
1090b57cec5SDimitry Andric m_opaque_sp = opaque_sp;
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric
Print(FILE * out)1120b57cec5SDimitry Andric void SBInstructionList::Print(FILE *out) {
11304eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, out);
1140b57cec5SDimitry Andric if (out == nullptr)
1150b57cec5SDimitry Andric return;
1169dba64beSDimitry Andric StreamFile stream(out, false);
1179dba64beSDimitry Andric GetDescription(stream);
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric
Print(SBFile out)1209dba64beSDimitry Andric void SBInstructionList::Print(SBFile out) {
12104eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, out);
1229dba64beSDimitry Andric if (!out.IsValid())
1239dba64beSDimitry Andric return;
1249dba64beSDimitry Andric StreamFile stream(out.m_opaque_sp);
1259dba64beSDimitry Andric GetDescription(stream);
1269dba64beSDimitry Andric }
1279dba64beSDimitry Andric
Print(FileSP out_sp)1289dba64beSDimitry Andric void SBInstructionList::Print(FileSP out_sp) {
12904eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, out_sp);
1309dba64beSDimitry Andric if (!out_sp || !out_sp->IsValid())
1319dba64beSDimitry Andric return;
1329dba64beSDimitry Andric StreamFile stream(out_sp);
1339dba64beSDimitry Andric GetDescription(stream);
1349dba64beSDimitry Andric }
1359dba64beSDimitry Andric
GetDescription(lldb::SBStream & stream)1369dba64beSDimitry Andric bool SBInstructionList::GetDescription(lldb::SBStream &stream) {
13704eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, stream);
1389dba64beSDimitry Andric return GetDescription(stream.ref());
1399dba64beSDimitry Andric }
1409dba64beSDimitry Andric
GetDescription(Stream & sref)1419dba64beSDimitry Andric bool SBInstructionList::GetDescription(Stream &sref) {
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andric if (m_opaque_sp) {
1440b57cec5SDimitry Andric size_t num_instructions = GetSize();
1450b57cec5SDimitry Andric if (num_instructions) {
1460b57cec5SDimitry Andric // Call the ref() to make sure a stream is created if one deesn't exist
1470b57cec5SDimitry Andric // already inside description...
1480b57cec5SDimitry Andric const uint32_t max_opcode_byte_size =
1490b57cec5SDimitry Andric m_opaque_sp->GetInstructionList().GetMaxOpcocdeByteSize();
1500b57cec5SDimitry Andric FormatEntity::Entry format;
1510b57cec5SDimitry Andric FormatEntity::Parse("${addr}: ", format);
1520b57cec5SDimitry Andric SymbolContext sc;
1530b57cec5SDimitry Andric SymbolContext prev_sc;
1540b57cec5SDimitry Andric for (size_t i = 0; i < num_instructions; ++i) {
1550b57cec5SDimitry Andric Instruction *inst =
1560b57cec5SDimitry Andric m_opaque_sp->GetInstructionList().GetInstructionAtIndex(i).get();
1570b57cec5SDimitry Andric if (inst == nullptr)
1580b57cec5SDimitry Andric break;
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric const Address &addr = inst->GetAddress();
1610b57cec5SDimitry Andric prev_sc = sc;
1620b57cec5SDimitry Andric ModuleSP module_sp(addr.GetModule());
1630b57cec5SDimitry Andric if (module_sp) {
1640b57cec5SDimitry Andric module_sp->ResolveSymbolContextForAddress(
1650b57cec5SDimitry Andric addr, eSymbolContextEverything, sc);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
168753f127fSDimitry Andric inst->Dump(&sref, max_opcode_byte_size, true, false,
169753f127fSDimitry Andric /*show_control_flow_kind=*/false, nullptr, &sc, &prev_sc,
170753f127fSDimitry Andric &format, 0);
1710b57cec5SDimitry Andric sref.EOL();
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric return true;
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric return false;
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric
DumpEmulationForAllInstructions(const char * triple)1790b57cec5SDimitry Andric bool SBInstructionList::DumpEmulationForAllInstructions(const char *triple) {
18004eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, triple);
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric if (m_opaque_sp) {
1830b57cec5SDimitry Andric size_t len = GetSize();
1840b57cec5SDimitry Andric for (size_t i = 0; i < len; ++i) {
1850b57cec5SDimitry Andric if (!GetInstructionAtIndex((uint32_t)i).DumpEmulation(triple))
1860b57cec5SDimitry Andric return false;
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric return true;
1900b57cec5SDimitry Andric }
191