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