1//===-- SBFunction.cpp ----------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/API/SBFunction.h"
10#include "lldb/API/SBProcess.h"
11#include "lldb/API/SBStream.h"
12#include "lldb/Core/Disassembler.h"
13#include "lldb/Core/Module.h"
14#include "lldb/Symbol/CompileUnit.h"
15#include "lldb/Symbol/Function.h"
16#include "lldb/Symbol/Type.h"
17#include "lldb/Symbol/VariableList.h"
18#include "lldb/Target/ExecutionContext.h"
19#include "lldb/Target/Target.h"
20#include "lldb/Utility/Instrumentation.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
25SBFunction::SBFunction() { LLDB_INSTRUMENT_VA(this); }
26
27SBFunction::SBFunction(lldb_private::Function *lldb_object_ptr)
28    : m_opaque_ptr(lldb_object_ptr) {}
29
30SBFunction::SBFunction(const lldb::SBFunction &rhs)
31    : m_opaque_ptr(rhs.m_opaque_ptr) {
32  LLDB_INSTRUMENT_VA(this, rhs);
33}
34
35const SBFunction &SBFunction::operator=(const SBFunction &rhs) {
36  LLDB_INSTRUMENT_VA(this, rhs);
37
38  m_opaque_ptr = rhs.m_opaque_ptr;
39  return *this;
40}
41
42SBFunction::~SBFunction() { m_opaque_ptr = nullptr; }
43
44bool SBFunction::IsValid() const {
45  LLDB_INSTRUMENT_VA(this);
46  return this->operator bool();
47}
48SBFunction::operator bool() const {
49  LLDB_INSTRUMENT_VA(this);
50
51  return m_opaque_ptr != nullptr;
52}
53
54const char *SBFunction::GetName() const {
55  LLDB_INSTRUMENT_VA(this);
56
57  if (m_opaque_ptr)
58    return m_opaque_ptr->GetName().AsCString();
59
60  return nullptr;
61}
62
63const char *SBFunction::GetDisplayName() const {
64  LLDB_INSTRUMENT_VA(this);
65
66  if (m_opaque_ptr)
67    return m_opaque_ptr->GetMangled().GetDisplayDemangledName().AsCString();
68
69  return nullptr;
70}
71
72const char *SBFunction::GetMangledName() const {
73  LLDB_INSTRUMENT_VA(this);
74
75  if (m_opaque_ptr)
76    return m_opaque_ptr->GetMangled().GetMangledName().AsCString();
77  return nullptr;
78}
79
80bool SBFunction::operator==(const SBFunction &rhs) const {
81  LLDB_INSTRUMENT_VA(this, rhs);
82
83  return m_opaque_ptr == rhs.m_opaque_ptr;
84}
85
86bool SBFunction::operator!=(const SBFunction &rhs) const {
87  LLDB_INSTRUMENT_VA(this, rhs);
88
89  return m_opaque_ptr != rhs.m_opaque_ptr;
90}
91
92bool SBFunction::GetDescription(SBStream &s) {
93  LLDB_INSTRUMENT_VA(this, s);
94
95  if (m_opaque_ptr) {
96    s.Printf("SBFunction: id = 0x%8.8" PRIx64 ", name = %s",
97             m_opaque_ptr->GetID(), m_opaque_ptr->GetName().AsCString());
98    Type *func_type = m_opaque_ptr->GetType();
99    if (func_type)
100      s.Printf(", type = %s", func_type->GetName().AsCString());
101    return true;
102  }
103  s.Printf("No value");
104  return false;
105}
106
107SBInstructionList SBFunction::GetInstructions(SBTarget target) {
108  LLDB_INSTRUMENT_VA(this, target);
109
110  return GetInstructions(target, nullptr);
111}
112
113SBInstructionList SBFunction::GetInstructions(SBTarget target,
114                                              const char *flavor) {
115  LLDB_INSTRUMENT_VA(this, target, flavor);
116
117  SBInstructionList sb_instructions;
118  if (m_opaque_ptr) {
119    TargetSP target_sp(target.GetSP());
120    std::unique_lock<std::recursive_mutex> lock;
121    ModuleSP module_sp(
122        m_opaque_ptr->GetAddressRange().GetBaseAddress().GetModule());
123    if (target_sp && module_sp) {
124      lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
125      const bool force_live_memory = true;
126      sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
127          module_sp->GetArchitecture(), nullptr, flavor, *target_sp,
128          m_opaque_ptr->GetAddressRange(), force_live_memory));
129    }
130  }
131  return sb_instructions;
132}
133
134lldb_private::Function *SBFunction::get() { return m_opaque_ptr; }
135
136void SBFunction::reset(lldb_private::Function *lldb_object_ptr) {
137  m_opaque_ptr = lldb_object_ptr;
138}
139
140SBAddress SBFunction::GetStartAddress() {
141  LLDB_INSTRUMENT_VA(this);
142
143  SBAddress addr;
144  if (m_opaque_ptr)
145    addr.SetAddress(m_opaque_ptr->GetAddressRange().GetBaseAddress());
146  return addr;
147}
148
149SBAddress SBFunction::GetEndAddress() {
150  LLDB_INSTRUMENT_VA(this);
151
152  SBAddress addr;
153  if (m_opaque_ptr) {
154    addr_t byte_size = m_opaque_ptr->GetAddressRange().GetByteSize();
155    if (byte_size > 0) {
156      addr.SetAddress(m_opaque_ptr->GetAddressRange().GetBaseAddress());
157      addr->Slide(byte_size);
158    }
159  }
160  return addr;
161}
162
163const char *SBFunction::GetArgumentName(uint32_t arg_idx) {
164  LLDB_INSTRUMENT_VA(this, arg_idx);
165
166  if (!m_opaque_ptr)
167    return nullptr;
168
169  Block &block = m_opaque_ptr->GetBlock(true);
170  VariableListSP variable_list_sp = block.GetBlockVariableList(true);
171  if (!variable_list_sp)
172    return nullptr;
173
174  VariableList arguments;
175  variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,
176                                             arguments, true);
177  lldb::VariableSP variable_sp = arguments.GetVariableAtIndex(arg_idx);
178  if (!variable_sp)
179    return nullptr;
180
181  return variable_sp->GetName().GetCString();
182}
183
184uint32_t SBFunction::GetPrologueByteSize() {
185  LLDB_INSTRUMENT_VA(this);
186
187  if (m_opaque_ptr)
188    return m_opaque_ptr->GetPrologueByteSize();
189  return 0;
190}
191
192SBType SBFunction::GetType() {
193  LLDB_INSTRUMENT_VA(this);
194
195  SBType sb_type;
196  if (m_opaque_ptr) {
197    Type *function_type = m_opaque_ptr->GetType();
198    if (function_type)
199      sb_type.ref().SetType(function_type->shared_from_this());
200  }
201  return sb_type;
202}
203
204SBBlock SBFunction::GetBlock() {
205  LLDB_INSTRUMENT_VA(this);
206
207  SBBlock sb_block;
208  if (m_opaque_ptr)
209    sb_block.SetPtr(&m_opaque_ptr->GetBlock(true));
210  return sb_block;
211}
212
213lldb::LanguageType SBFunction::GetLanguage() {
214  LLDB_INSTRUMENT_VA(this);
215
216  if (m_opaque_ptr) {
217    if (m_opaque_ptr->GetCompileUnit())
218      return m_opaque_ptr->GetCompileUnit()->GetLanguage();
219  }
220  return lldb::eLanguageTypeUnknown;
221}
222
223bool SBFunction::GetIsOptimized() {
224  LLDB_INSTRUMENT_VA(this);
225
226  if (m_opaque_ptr) {
227    if (m_opaque_ptr->GetCompileUnit())
228      return m_opaque_ptr->GetCompileUnit()->GetIsOptimized();
229  }
230  return false;
231}
232