xref: /src/contrib/llvm-project/lldb/source/API/SBInstructionList.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1cfca06d7SDimitry Andric //===-- SBInstructionList.cpp ---------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "lldb/API/SBInstructionList.h"
108b4000f1SDimitry Andric #include "lldb/API/SBAddress.h"
116f8fc217SDimitry Andric #include "lldb/API/SBFile.h"
125f29bb8aSDimitry Andric #include "lldb/API/SBInstruction.h"
13f034231aSEd Maste #include "lldb/API/SBStream.h"
14f034231aSEd Maste #include "lldb/Core/Disassembler.h"
15205afe67SEd Maste #include "lldb/Core/Module.h"
16b1c73532SDimitry Andric #include "lldb/Host/StreamFile.h"
17205afe67SEd Maste #include "lldb/Symbol/SymbolContext.h"
186f8fc217SDimitry Andric #include "lldb/Utility/Instrumentation.h"
1974a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
20f034231aSEd Maste 
21f034231aSEd Maste using namespace lldb;
22f034231aSEd Maste using namespace lldb_private;
23f034231aSEd Maste 
SBInstructionList()246f8fc217SDimitry Andric SBInstructionList::SBInstructionList() { LLDB_INSTRUMENT_VA(this); }
25f034231aSEd Maste 
SBInstructionList(const SBInstructionList & rhs)2614f1b3e8SDimitry Andric SBInstructionList::SBInstructionList(const SBInstructionList &rhs)
275f29bb8aSDimitry Andric     : m_opaque_sp(rhs.m_opaque_sp) {
286f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, rhs);
295f29bb8aSDimitry Andric }
30f034231aSEd Maste 
3114f1b3e8SDimitry Andric const SBInstructionList &SBInstructionList::
operator =(const SBInstructionList & rhs)3214f1b3e8SDimitry Andric operator=(const SBInstructionList &rhs) {
336f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, rhs);
345f29bb8aSDimitry Andric 
35f034231aSEd Maste   if (this != &rhs)
36f034231aSEd Maste     m_opaque_sp = rhs.m_opaque_sp;
376f8fc217SDimitry Andric   return *this;
38f034231aSEd Maste }
39f034231aSEd Maste 
40cfca06d7SDimitry Andric SBInstructionList::~SBInstructionList() = default;
41f034231aSEd Maste 
IsValid() const425f29bb8aSDimitry Andric bool SBInstructionList::IsValid() const {
436f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this);
445f29bb8aSDimitry Andric   return this->operator bool();
455f29bb8aSDimitry Andric }
operator bool() const465f29bb8aSDimitry Andric SBInstructionList::operator bool() const {
476f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this);
485f29bb8aSDimitry Andric 
495f29bb8aSDimitry Andric   return m_opaque_sp.get() != nullptr;
505f29bb8aSDimitry Andric }
51f034231aSEd Maste 
GetSize()5214f1b3e8SDimitry Andric size_t SBInstructionList::GetSize() {
536f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this);
545f29bb8aSDimitry Andric 
55f034231aSEd Maste   if (m_opaque_sp)
56f034231aSEd Maste     return m_opaque_sp->GetInstructionList().GetSize();
57f034231aSEd Maste   return 0;
58f034231aSEd Maste }
59f034231aSEd Maste 
GetInstructionAtIndex(uint32_t idx)6014f1b3e8SDimitry Andric SBInstruction SBInstructionList::GetInstructionAtIndex(uint32_t idx) {
616f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, idx);
625f29bb8aSDimitry Andric 
63f034231aSEd Maste   SBInstruction inst;
64f034231aSEd Maste   if (m_opaque_sp && idx < m_opaque_sp->GetInstructionList().GetSize())
6514f1b3e8SDimitry Andric     inst.SetOpaque(
6614f1b3e8SDimitry Andric         m_opaque_sp,
6714f1b3e8SDimitry Andric         m_opaque_sp->GetInstructionList().GetInstructionAtIndex(idx));
686f8fc217SDimitry Andric   return inst;
69f034231aSEd Maste }
70f034231aSEd Maste 
GetInstructionsCount(const SBAddress & start,const SBAddress & end,bool canSetBreakpoint)718b4000f1SDimitry Andric size_t SBInstructionList::GetInstructionsCount(const SBAddress &start,
728b4000f1SDimitry Andric                                                const SBAddress &end,
738b4000f1SDimitry Andric                                                bool canSetBreakpoint) {
746f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, start, end, canSetBreakpoint);
755f29bb8aSDimitry Andric 
768b4000f1SDimitry Andric   size_t num_instructions = GetSize();
778b4000f1SDimitry Andric   size_t i = 0;
788b4000f1SDimitry Andric   SBAddress addr;
798b4000f1SDimitry Andric   size_t lower_index = 0;
808b4000f1SDimitry Andric   size_t upper_index = 0;
818b4000f1SDimitry Andric   size_t instructions_to_skip = 0;
828b4000f1SDimitry Andric   for (i = 0; i < num_instructions; ++i) {
838b4000f1SDimitry Andric     addr = GetInstructionAtIndex(i).GetAddress();
848b4000f1SDimitry Andric     if (start == addr)
858b4000f1SDimitry Andric       lower_index = i;
868b4000f1SDimitry Andric     if (end == addr)
878b4000f1SDimitry Andric       upper_index = i;
888b4000f1SDimitry Andric   }
898b4000f1SDimitry Andric   if (canSetBreakpoint)
908b4000f1SDimitry Andric     for (i = lower_index; i <= upper_index; ++i) {
918b4000f1SDimitry Andric       SBInstruction insn = GetInstructionAtIndex(i);
928b4000f1SDimitry Andric       if (!insn.CanSetBreakpoint())
938b4000f1SDimitry Andric         ++instructions_to_skip;
948b4000f1SDimitry Andric     }
958b4000f1SDimitry Andric   return upper_index - lower_index - instructions_to_skip;
968b4000f1SDimitry Andric }
978b4000f1SDimitry Andric 
Clear()985f29bb8aSDimitry Andric void SBInstructionList::Clear() {
996f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this);
100f034231aSEd Maste 
1015f29bb8aSDimitry Andric   m_opaque_sp.reset();
1025f29bb8aSDimitry Andric }
1035f29bb8aSDimitry Andric 
AppendInstruction(SBInstruction insn)1045f29bb8aSDimitry Andric void SBInstructionList::AppendInstruction(SBInstruction insn) {
1056f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, insn);
1065f29bb8aSDimitry Andric }
107f034231aSEd Maste 
SetDisassembler(const lldb::DisassemblerSP & opaque_sp)10814f1b3e8SDimitry Andric void SBInstructionList::SetDisassembler(const lldb::DisassemblerSP &opaque_sp) {
109f034231aSEd Maste   m_opaque_sp = opaque_sp;
110f034231aSEd Maste }
111f034231aSEd Maste 
Print(FILE * out)11214f1b3e8SDimitry Andric void SBInstructionList::Print(FILE *out) {
1136f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, out);
1145f29bb8aSDimitry Andric   if (out == nullptr)
115f034231aSEd Maste     return;
116ead24645SDimitry Andric   StreamFile stream(out, false);
117ead24645SDimitry Andric   GetDescription(stream);
118f034231aSEd Maste }
119f034231aSEd Maste 
Print(SBFile out)120ead24645SDimitry Andric void SBInstructionList::Print(SBFile out) {
1216f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, out);
122ead24645SDimitry Andric   if (!out.IsValid())
123ead24645SDimitry Andric     return;
124ead24645SDimitry Andric   StreamFile stream(out.m_opaque_sp);
125ead24645SDimitry Andric   GetDescription(stream);
126ead24645SDimitry Andric }
127ead24645SDimitry Andric 
Print(FileSP out_sp)128ead24645SDimitry Andric void SBInstructionList::Print(FileSP out_sp) {
1296f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, out_sp);
130ead24645SDimitry Andric   if (!out_sp || !out_sp->IsValid())
131ead24645SDimitry Andric     return;
132ead24645SDimitry Andric   StreamFile stream(out_sp);
133ead24645SDimitry Andric   GetDescription(stream);
134ead24645SDimitry Andric }
135ead24645SDimitry Andric 
GetDescription(lldb::SBStream & stream)136ead24645SDimitry Andric bool SBInstructionList::GetDescription(lldb::SBStream &stream) {
1376f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, stream);
138ead24645SDimitry Andric   return GetDescription(stream.ref());
139ead24645SDimitry Andric }
140ead24645SDimitry Andric 
GetDescription(Stream & sref)141ead24645SDimitry Andric bool SBInstructionList::GetDescription(Stream &sref) {
1425f29bb8aSDimitry Andric 
14314f1b3e8SDimitry Andric   if (m_opaque_sp) {
144f034231aSEd Maste     size_t num_instructions = GetSize();
14514f1b3e8SDimitry Andric     if (num_instructions) {
146f73363f1SDimitry Andric       // Call the ref() to make sure a stream is created if one deesn't exist
147f73363f1SDimitry Andric       // already inside description...
14814f1b3e8SDimitry Andric       const uint32_t max_opcode_byte_size =
14914f1b3e8SDimitry Andric           m_opaque_sp->GetInstructionList().GetMaxOpcocdeByteSize();
15012bd4897SEd Maste       FormatEntity::Entry format;
15112bd4897SEd Maste       FormatEntity::Parse("${addr}: ", format);
152205afe67SEd Maste       SymbolContext sc;
153205afe67SEd Maste       SymbolContext prev_sc;
15414f1b3e8SDimitry Andric       for (size_t i = 0; i < num_instructions; ++i) {
15514f1b3e8SDimitry Andric         Instruction *inst =
15614f1b3e8SDimitry Andric             m_opaque_sp->GetInstructionList().GetInstructionAtIndex(i).get();
1575f29bb8aSDimitry Andric         if (inst == nullptr)
158f034231aSEd Maste           break;
159205afe67SEd Maste 
160205afe67SEd Maste         const Address &addr = inst->GetAddress();
161205afe67SEd Maste         prev_sc = sc;
162205afe67SEd Maste         ModuleSP module_sp(addr.GetModule());
16314f1b3e8SDimitry Andric         if (module_sp) {
16414f1b3e8SDimitry Andric           module_sp->ResolveSymbolContextForAddress(
16514f1b3e8SDimitry Andric               addr, eSymbolContextEverything, sc);
166205afe67SEd Maste         }
167205afe67SEd Maste 
1681f917f69SDimitry Andric         inst->Dump(&sref, max_opcode_byte_size, true, false,
1691f917f69SDimitry Andric                    /*show_control_flow_kind=*/false, nullptr, &sc, &prev_sc,
1701f917f69SDimitry Andric                    &format, 0);
171f034231aSEd Maste         sref.EOL();
172f034231aSEd Maste       }
173f034231aSEd Maste       return true;
174f034231aSEd Maste     }
175f034231aSEd Maste   }
176f034231aSEd Maste   return false;
177f034231aSEd Maste }
178f034231aSEd Maste 
DumpEmulationForAllInstructions(const char * triple)17914f1b3e8SDimitry Andric bool SBInstructionList::DumpEmulationForAllInstructions(const char *triple) {
1806f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, triple);
1815f29bb8aSDimitry Andric 
18214f1b3e8SDimitry Andric   if (m_opaque_sp) {
183f034231aSEd Maste     size_t len = GetSize();
18414f1b3e8SDimitry Andric     for (size_t i = 0; i < len; ++i) {
185f034231aSEd Maste       if (!GetInstructionAtIndex((uint32_t)i).DumpEmulation(triple))
186f034231aSEd Maste         return false;
187f034231aSEd Maste     }
188f034231aSEd Maste   }
189f034231aSEd Maste   return true;
190f034231aSEd Maste }
191