180814287SRaphael Isemann //===-- SBInstructionList.cpp ---------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
930fdc8d8SChris Lattner #include "lldb/API/SBInstructionList.h"
10dd125943SNitesh Jain #include "lldb/API/SBAddress.h"
111755f5b1SJonas Devlieghere #include "lldb/API/SBFile.h"
12baf5664fSJonas Devlieghere #include "lldb/API/SBInstruction.h"
131d273166SGreg Clayton #include "lldb/API/SBStream.h"
141d273166SGreg Clayton #include "lldb/Core/Disassembler.h"
15aff1b357SJason Molenda #include "lldb/Core/Module.h"
16e7a91156SLawrence D'Anna #include "lldb/Core/StreamFile.h"
17aff1b357SJason Molenda #include "lldb/Symbol/SymbolContext.h"
181755f5b1SJonas Devlieghere #include "lldb/Utility/Instrumentation.h"
19bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
2030fdc8d8SChris Lattner 
2130fdc8d8SChris Lattner using namespace lldb;
221d273166SGreg Clayton using namespace lldb_private;
2330fdc8d8SChris Lattner 
SBInstructionList()241755f5b1SJonas Devlieghere SBInstructionList::SBInstructionList() { LLDB_INSTRUMENT_VA(this); }
2530fdc8d8SChris Lattner 
SBInstructionList(const SBInstructionList & rhs)26b9c1b51eSKate Stone SBInstructionList::SBInstructionList(const SBInstructionList &rhs)
27baf5664fSJonas Devlieghere     : m_opaque_sp(rhs.m_opaque_sp) {
281755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this, rhs);
29baf5664fSJonas Devlieghere }
3030fdc8d8SChris Lattner 
31b9c1b51eSKate Stone const SBInstructionList &SBInstructionList::
operator =(const SBInstructionList & rhs)32b9c1b51eSKate Stone operator=(const SBInstructionList &rhs) {
331755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this, rhs);
34baf5664fSJonas Devlieghere 
35efabb123SGreg Clayton   if (this != &rhs)
36efabb123SGreg Clayton     m_opaque_sp = rhs.m_opaque_sp;
37d232abc3SJonas Devlieghere   return *this;
38efabb123SGreg Clayton }
39efabb123SGreg Clayton 
40866b7a65SJonas Devlieghere SBInstructionList::~SBInstructionList() = default;
41efabb123SGreg Clayton 
IsValid() const42baf5664fSJonas Devlieghere bool SBInstructionList::IsValid() const {
431755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this);
447f5237bcSPavel Labath   return this->operator bool();
457f5237bcSPavel Labath }
operator bool() const467f5237bcSPavel Labath SBInstructionList::operator bool() const {
471755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this);
48baf5664fSJonas Devlieghere 
49248a1305SKonrad Kleine   return m_opaque_sp.get() != nullptr;
50baf5664fSJonas Devlieghere }
5130fdc8d8SChris Lattner 
GetSize()52b9c1b51eSKate Stone size_t SBInstructionList::GetSize() {
531755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this);
54baf5664fSJonas Devlieghere 
551d273166SGreg Clayton   if (m_opaque_sp)
561d273166SGreg Clayton     return m_opaque_sp->GetInstructionList().GetSize();
5730fdc8d8SChris Lattner   return 0;
5830fdc8d8SChris Lattner }
5930fdc8d8SChris Lattner 
GetInstructionAtIndex(uint32_t idx)60b9c1b51eSKate Stone SBInstruction SBInstructionList::GetInstructionAtIndex(uint32_t idx) {
611755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this, idx);
62baf5664fSJonas Devlieghere 
6330fdc8d8SChris Lattner   SBInstruction inst;
641d273166SGreg Clayton   if (m_opaque_sp && idx < m_opaque_sp->GetInstructionList().GetSize())
65b9c1b51eSKate Stone     inst.SetOpaque(
66b9c1b51eSKate Stone         m_opaque_sp,
67b9c1b51eSKate Stone         m_opaque_sp->GetInstructionList().GetInstructionAtIndex(idx));
68d232abc3SJonas Devlieghere   return inst;
6930fdc8d8SChris Lattner }
7030fdc8d8SChris Lattner 
GetInstructionsCount(const SBAddress & start,const SBAddress & end,bool canSetBreakpoint)71dd125943SNitesh Jain size_t SBInstructionList::GetInstructionsCount(const SBAddress &start,
72dd125943SNitesh Jain                                                const SBAddress &end,
73dd125943SNitesh Jain                                                bool canSetBreakpoint) {
741755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this, start, end, canSetBreakpoint);
75baf5664fSJonas Devlieghere 
76dd125943SNitesh Jain   size_t num_instructions = GetSize();
77dd125943SNitesh Jain   size_t i = 0;
78dd125943SNitesh Jain   SBAddress addr;
79dd125943SNitesh Jain   size_t lower_index = 0;
80dd125943SNitesh Jain   size_t upper_index = 0;
81dd125943SNitesh Jain   size_t instructions_to_skip = 0;
82dd125943SNitesh Jain   for (i = 0; i < num_instructions; ++i) {
83dd125943SNitesh Jain     addr = GetInstructionAtIndex(i).GetAddress();
84dd125943SNitesh Jain     if (start == addr)
85dd125943SNitesh Jain       lower_index = i;
86dd125943SNitesh Jain     if (end == addr)
87dd125943SNitesh Jain       upper_index = i;
88dd125943SNitesh Jain   }
89dd125943SNitesh Jain   if (canSetBreakpoint)
90dd125943SNitesh Jain     for (i = lower_index; i <= upper_index; ++i) {
91dd125943SNitesh Jain       SBInstruction insn = GetInstructionAtIndex(i);
92dd125943SNitesh Jain       if (!insn.CanSetBreakpoint())
93dd125943SNitesh Jain         ++instructions_to_skip;
94dd125943SNitesh Jain     }
95dd125943SNitesh Jain   return upper_index - lower_index - instructions_to_skip;
96dd125943SNitesh Jain }
97dd125943SNitesh Jain 
Clear()98baf5664fSJonas Devlieghere void SBInstructionList::Clear() {
991755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this);
10030fdc8d8SChris Lattner 
101baf5664fSJonas Devlieghere   m_opaque_sp.reset();
102baf5664fSJonas Devlieghere }
103baf5664fSJonas Devlieghere 
AppendInstruction(SBInstruction insn)104baf5664fSJonas Devlieghere void SBInstructionList::AppendInstruction(SBInstruction insn) {
1051755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this, insn);
106baf5664fSJonas Devlieghere }
10730fdc8d8SChris Lattner 
SetDisassembler(const lldb::DisassemblerSP & opaque_sp)108b9c1b51eSKate Stone void SBInstructionList::SetDisassembler(const lldb::DisassemblerSP &opaque_sp) {
1091d273166SGreg Clayton   m_opaque_sp = opaque_sp;
1101d273166SGreg Clayton }
1111d273166SGreg Clayton 
Print(FILE * out)112b9c1b51eSKate Stone void SBInstructionList::Print(FILE *out) {
1131755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this, out);
114248a1305SKonrad Kleine   if (out == nullptr)
11530fdc8d8SChris Lattner     return;
116e7a91156SLawrence D'Anna   StreamFile stream(out, false);
117e7a91156SLawrence D'Anna   GetDescription(stream);
11830fdc8d8SChris Lattner }
11930fdc8d8SChris Lattner 
Print(SBFile out)120e7a91156SLawrence D'Anna void SBInstructionList::Print(SBFile out) {
1211755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this, out);
122e7a91156SLawrence D'Anna   if (!out.IsValid())
123e7a91156SLawrence D'Anna     return;
1249efbc564SLawrence D'Anna   StreamFile stream(out.m_opaque_sp);
125e7a91156SLawrence D'Anna   GetDescription(stream);
126e7a91156SLawrence D'Anna }
127e7a91156SLawrence D'Anna 
Print(FileSP out_sp)128e7a91156SLawrence D'Anna void SBInstructionList::Print(FileSP out_sp) {
1291755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this, out_sp);
130e7a91156SLawrence D'Anna   if (!out_sp || !out_sp->IsValid())
131e7a91156SLawrence D'Anna     return;
132e7a91156SLawrence D'Anna   StreamFile stream(out_sp);
133e7a91156SLawrence D'Anna   GetDescription(stream);
134e7a91156SLawrence D'Anna }
135e7a91156SLawrence D'Anna 
GetDescription(lldb::SBStream & stream)136e7a91156SLawrence D'Anna bool SBInstructionList::GetDescription(lldb::SBStream &stream) {
1371755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this, stream);
138e7a91156SLawrence D'Anna   return GetDescription(stream.ref());
139e7a91156SLawrence D'Anna }
140e7a91156SLawrence D'Anna 
GetDescription(Stream & sref)141e7a91156SLawrence D'Anna bool SBInstructionList::GetDescription(Stream &sref) {
142baf5664fSJonas Devlieghere 
143b9c1b51eSKate Stone   if (m_opaque_sp) {
1441d273166SGreg Clayton     size_t num_instructions = GetSize();
145b9c1b51eSKate Stone     if (num_instructions) {
14605097246SAdrian Prantl       // Call the ref() to make sure a stream is created if one deesn't exist
14705097246SAdrian Prantl       // already inside description...
148b9c1b51eSKate Stone       const uint32_t max_opcode_byte_size =
149b9c1b51eSKate Stone           m_opaque_sp->GetInstructionList().GetMaxOpcocdeByteSize();
150554f68d3SGreg Clayton       FormatEntity::Entry format;
151554f68d3SGreg Clayton       FormatEntity::Parse("${addr}: ", format);
152aff1b357SJason Molenda       SymbolContext sc;
153aff1b357SJason Molenda       SymbolContext prev_sc;
154b9c1b51eSKate Stone       for (size_t i = 0; i < num_instructions; ++i) {
155b9c1b51eSKate Stone         Instruction *inst =
156b9c1b51eSKate Stone             m_opaque_sp->GetInstructionList().GetInstructionAtIndex(i).get();
157248a1305SKonrad Kleine         if (inst == nullptr)
1581d273166SGreg Clayton           break;
159aff1b357SJason Molenda 
160aff1b357SJason Molenda         const Address &addr = inst->GetAddress();
161aff1b357SJason Molenda         prev_sc = sc;
162aff1b357SJason Molenda         ModuleSP module_sp(addr.GetModule());
163b9c1b51eSKate Stone         if (module_sp) {
164b9c1b51eSKate Stone           module_sp->ResolveSymbolContextForAddress(
165b9c1b51eSKate Stone               addr, eSymbolContextEverything, sc);
166aff1b357SJason Molenda         }
167aff1b357SJason Molenda 
168*ad7bcda9SWalter Erquinigo         inst->Dump(&sref, max_opcode_byte_size, true, false,
169*ad7bcda9SWalter Erquinigo                    /*show_control_flow_kind=*/false, nullptr, &sc, &prev_sc,
170*ad7bcda9SWalter Erquinigo                    &format, 0);
1711d273166SGreg Clayton         sref.EOL();
1721d273166SGreg Clayton       }
1731d273166SGreg Clayton       return true;
1741d273166SGreg Clayton     }
1751d273166SGreg Clayton   }
1761d273166SGreg Clayton   return false;
1771d273166SGreg Clayton }
1781d273166SGreg Clayton 
DumpEmulationForAllInstructions(const char * triple)179b9c1b51eSKate Stone bool SBInstructionList::DumpEmulationForAllInstructions(const char *triple) {
1801755f5b1SJonas Devlieghere   LLDB_INSTRUMENT_VA(this, triple);
181baf5664fSJonas Devlieghere 
182b9c1b51eSKate Stone   if (m_opaque_sp) {
1837c9dd3ceSCaroline Tice     size_t len = GetSize();
184b9c1b51eSKate Stone     for (size_t i = 0; i < len; ++i) {
1857c9dd3ceSCaroline Tice       if (!GetInstructionAtIndex((uint32_t)i).DumpEmulation(triple))
1867c9dd3ceSCaroline Tice         return false;
1877c9dd3ceSCaroline Tice     }
1887c9dd3ceSCaroline Tice   }
1897c9dd3ceSCaroline Tice   return true;
1907c9dd3ceSCaroline Tice }
191