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