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 "SBReproducerPrivate.h"
11 #include "lldb/API/SBProcess.h"
12 #include "lldb/API/SBStream.h"
13 #include "lldb/Core/Disassembler.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Symbol/CompileUnit.h"
16 #include "lldb/Symbol/Function.h"
17 #include "lldb/Symbol/Type.h"
18 #include "lldb/Symbol/VariableList.h"
19 #include "lldb/Target/ExecutionContext.h"
20 #include "lldb/Target/Target.h"
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 
25 SBFunction::SBFunction() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBFunction); }
26 
27 SBFunction::SBFunction(lldb_private::Function *lldb_object_ptr)
28     : m_opaque_ptr(lldb_object_ptr) {}
29 
30 SBFunction::SBFunction(const lldb::SBFunction &rhs)
31     : m_opaque_ptr(rhs.m_opaque_ptr) {
32   LLDB_RECORD_CONSTRUCTOR(SBFunction, (const lldb::SBFunction &), rhs);
33 }
34 
35 const SBFunction &SBFunction::operator=(const SBFunction &rhs) {
36   LLDB_RECORD_METHOD(const lldb::SBFunction &,
37                      SBFunction, operator=,(const lldb::SBFunction &), rhs);
38 
39   m_opaque_ptr = rhs.m_opaque_ptr;
40   return LLDB_RECORD_RESULT(*this);
41 }
42 
43 SBFunction::~SBFunction() { m_opaque_ptr = nullptr; }
44 
45 bool SBFunction::IsValid() const {
46   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFunction, IsValid);
47   return this->operator bool();
48 }
49 SBFunction::operator bool() const {
50   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFunction, operator bool);
51 
52   return m_opaque_ptr != nullptr;
53 }
54 
55 const char *SBFunction::GetName() const {
56   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBFunction, GetName);
57 
58   const char *cstr = nullptr;
59   if (m_opaque_ptr)
60     cstr = m_opaque_ptr->GetName().AsCString();
61 
62   return cstr;
63 }
64 
65 const char *SBFunction::GetDisplayName() const {
66   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBFunction, GetDisplayName);
67 
68   const char *cstr = nullptr;
69   if (m_opaque_ptr)
70     cstr = m_opaque_ptr->GetMangled().GetDisplayDemangledName().AsCString();
71 
72   return cstr;
73 }
74 
75 const char *SBFunction::GetMangledName() const {
76   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBFunction, GetMangledName);
77 
78   const char *cstr = nullptr;
79   if (m_opaque_ptr)
80     cstr = m_opaque_ptr->GetMangled().GetMangledName().AsCString();
81   return cstr;
82 }
83 
84 bool SBFunction::operator==(const SBFunction &rhs) const {
85   LLDB_RECORD_METHOD_CONST(
86       bool, SBFunction, operator==,(const lldb::SBFunction &), rhs);
87 
88   return m_opaque_ptr == rhs.m_opaque_ptr;
89 }
90 
91 bool SBFunction::operator!=(const SBFunction &rhs) const {
92   LLDB_RECORD_METHOD_CONST(
93       bool, SBFunction, operator!=,(const lldb::SBFunction &), rhs);
94 
95   return m_opaque_ptr != rhs.m_opaque_ptr;
96 }
97 
98 bool SBFunction::GetDescription(SBStream &s) {
99   LLDB_RECORD_METHOD(bool, SBFunction, GetDescription, (lldb::SBStream &), s);
100 
101   if (m_opaque_ptr) {
102     s.Printf("SBFunction: id = 0x%8.8" PRIx64 ", name = %s",
103              m_opaque_ptr->GetID(), m_opaque_ptr->GetName().AsCString());
104     Type *func_type = m_opaque_ptr->GetType();
105     if (func_type)
106       s.Printf(", type = %s", func_type->GetName().AsCString());
107     return true;
108   }
109   s.Printf("No value");
110   return false;
111 }
112 
113 SBInstructionList SBFunction::GetInstructions(SBTarget target) {
114   LLDB_RECORD_METHOD(lldb::SBInstructionList, SBFunction, GetInstructions,
115                      (lldb::SBTarget), target);
116 
117   return LLDB_RECORD_RESULT(GetInstructions(target, nullptr));
118 }
119 
120 SBInstructionList SBFunction::GetInstructions(SBTarget target,
121                                               const char *flavor) {
122   LLDB_RECORD_METHOD(lldb::SBInstructionList, SBFunction, GetInstructions,
123                      (lldb::SBTarget, const char *), target, flavor);
124 
125   SBInstructionList sb_instructions;
126   if (m_opaque_ptr) {
127     TargetSP target_sp(target.GetSP());
128     std::unique_lock<std::recursive_mutex> lock;
129     ModuleSP module_sp(
130         m_opaque_ptr->GetAddressRange().GetBaseAddress().GetModule());
131     if (target_sp && module_sp) {
132       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
133       const bool force_live_memory = true;
134       sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
135           module_sp->GetArchitecture(), nullptr, flavor, *target_sp,
136           m_opaque_ptr->GetAddressRange(), force_live_memory));
137     }
138   }
139   return LLDB_RECORD_RESULT(sb_instructions);
140 }
141 
142 lldb_private::Function *SBFunction::get() { return m_opaque_ptr; }
143 
144 void SBFunction::reset(lldb_private::Function *lldb_object_ptr) {
145   m_opaque_ptr = lldb_object_ptr;
146 }
147 
148 SBAddress SBFunction::GetStartAddress() {
149   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBAddress, SBFunction, GetStartAddress);
150 
151   SBAddress addr;
152   if (m_opaque_ptr)
153     addr.SetAddress(m_opaque_ptr->GetAddressRange().GetBaseAddress());
154   return LLDB_RECORD_RESULT(addr);
155 }
156 
157 SBAddress SBFunction::GetEndAddress() {
158   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBAddress, SBFunction, GetEndAddress);
159 
160   SBAddress addr;
161   if (m_opaque_ptr) {
162     addr_t byte_size = m_opaque_ptr->GetAddressRange().GetByteSize();
163     if (byte_size > 0) {
164       addr.SetAddress(m_opaque_ptr->GetAddressRange().GetBaseAddress());
165       addr->Slide(byte_size);
166     }
167   }
168   return LLDB_RECORD_RESULT(addr);
169 }
170 
171 const char *SBFunction::GetArgumentName(uint32_t arg_idx) {
172   LLDB_RECORD_METHOD(const char *, SBFunction, GetArgumentName, (uint32_t),
173                      arg_idx);
174 
175   if (m_opaque_ptr) {
176     Block &block = m_opaque_ptr->GetBlock(true);
177     VariableListSP variable_list_sp = block.GetBlockVariableList(true);
178     if (variable_list_sp) {
179       VariableList arguments;
180       variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,
181                                                  arguments, true);
182       lldb::VariableSP variable_sp = arguments.GetVariableAtIndex(arg_idx);
183       if (variable_sp)
184         return variable_sp->GetName().GetCString();
185     }
186   }
187   return nullptr;
188 }
189 
190 uint32_t SBFunction::GetPrologueByteSize() {
191   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBFunction, GetPrologueByteSize);
192 
193   if (m_opaque_ptr)
194     return m_opaque_ptr->GetPrologueByteSize();
195   return 0;
196 }
197 
198 SBType SBFunction::GetType() {
199   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBType, SBFunction, GetType);
200 
201   SBType sb_type;
202   if (m_opaque_ptr) {
203     Type *function_type = m_opaque_ptr->GetType();
204     if (function_type)
205       sb_type.ref().SetType(function_type->shared_from_this());
206   }
207   return LLDB_RECORD_RESULT(sb_type);
208 }
209 
210 SBBlock SBFunction::GetBlock() {
211   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBlock, SBFunction, GetBlock);
212 
213   SBBlock sb_block;
214   if (m_opaque_ptr)
215     sb_block.SetPtr(&m_opaque_ptr->GetBlock(true));
216   return LLDB_RECORD_RESULT(sb_block);
217 }
218 
219 lldb::LanguageType SBFunction::GetLanguage() {
220   LLDB_RECORD_METHOD_NO_ARGS(lldb::LanguageType, SBFunction, GetLanguage);
221 
222   if (m_opaque_ptr) {
223     if (m_opaque_ptr->GetCompileUnit())
224       return m_opaque_ptr->GetCompileUnit()->GetLanguage();
225   }
226   return lldb::eLanguageTypeUnknown;
227 }
228 
229 bool SBFunction::GetIsOptimized() {
230   LLDB_RECORD_METHOD_NO_ARGS(bool, SBFunction, GetIsOptimized);
231 
232   if (m_opaque_ptr) {
233     if (m_opaque_ptr->GetCompileUnit())
234       return m_opaque_ptr->GetCompileUnit()->GetIsOptimized();
235   }
236   return false;
237 }
238 
239 namespace lldb_private {
240 namespace repro {
241 
242 template <>
243 void RegisterMethods<SBFunction>(Registry &R) {
244   LLDB_REGISTER_CONSTRUCTOR(SBFunction, ());
245   LLDB_REGISTER_CONSTRUCTOR(SBFunction, (const lldb::SBFunction &));
246   LLDB_REGISTER_METHOD(const lldb::SBFunction &,
247                        SBFunction, operator=,(const lldb::SBFunction &));
248   LLDB_REGISTER_METHOD_CONST(bool, SBFunction, IsValid, ());
249   LLDB_REGISTER_METHOD_CONST(bool, SBFunction, operator bool, ());
250   LLDB_REGISTER_METHOD_CONST(const char *, SBFunction, GetName, ());
251   LLDB_REGISTER_METHOD_CONST(const char *, SBFunction, GetDisplayName, ());
252   LLDB_REGISTER_METHOD_CONST(const char *, SBFunction, GetMangledName, ());
253   LLDB_REGISTER_METHOD_CONST(
254       bool, SBFunction, operator==,(const lldb::SBFunction &));
255   LLDB_REGISTER_METHOD_CONST(
256       bool, SBFunction, operator!=,(const lldb::SBFunction &));
257   LLDB_REGISTER_METHOD(bool, SBFunction, GetDescription, (lldb::SBStream &));
258   LLDB_REGISTER_METHOD(lldb::SBInstructionList, SBFunction, GetInstructions,
259                        (lldb::SBTarget));
260   LLDB_REGISTER_METHOD(lldb::SBInstructionList, SBFunction, GetInstructions,
261                        (lldb::SBTarget, const char *));
262   LLDB_REGISTER_METHOD(lldb::SBAddress, SBFunction, GetStartAddress, ());
263   LLDB_REGISTER_METHOD(lldb::SBAddress, SBFunction, GetEndAddress, ());
264   LLDB_REGISTER_METHOD(const char *, SBFunction, GetArgumentName, (uint32_t));
265   LLDB_REGISTER_METHOD(uint32_t, SBFunction, GetPrologueByteSize, ());
266   LLDB_REGISTER_METHOD(lldb::SBType, SBFunction, GetType, ());
267   LLDB_REGISTER_METHOD(lldb::SBBlock, SBFunction, GetBlock, ());
268   LLDB_REGISTER_METHOD(lldb::LanguageType, SBFunction, GetLanguage, ());
269   LLDB_REGISTER_METHOD(bool, SBFunction, GetIsOptimized, ());
270 }
271 
272 }
273 }
274