1 //===-- SBFunction.cpp ------------------------------------------*- C++ -*-===//
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() : m_opaque_ptr(NULL) {
26   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBFunction);
27 }
28 
29 SBFunction::SBFunction(lldb_private::Function *lldb_object_ptr)
30     : m_opaque_ptr(lldb_object_ptr) {}
31 
32 SBFunction::SBFunction(const lldb::SBFunction &rhs)
33     : m_opaque_ptr(rhs.m_opaque_ptr) {
34   LLDB_RECORD_CONSTRUCTOR(SBFunction, (const lldb::SBFunction &), rhs);
35 }
36 
37 const SBFunction &SBFunction::operator=(const SBFunction &rhs) {
38   LLDB_RECORD_METHOD(const lldb::SBFunction &,
39                      SBFunction, operator=,(const lldb::SBFunction &), rhs);
40 
41   m_opaque_ptr = rhs.m_opaque_ptr;
42   return *this;
43 }
44 
45 SBFunction::~SBFunction() { m_opaque_ptr = NULL; }
46 
47 bool SBFunction::IsValid() const {
48   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFunction, IsValid);
49 
50   return m_opaque_ptr != NULL;
51 }
52 
53 const char *SBFunction::GetName() const {
54   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBFunction, GetName);
55 
56   const char *cstr = NULL;
57   if (m_opaque_ptr)
58     cstr = m_opaque_ptr->GetName().AsCString();
59 
60   return cstr;
61 }
62 
63 const char *SBFunction::GetDisplayName() const {
64   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBFunction, GetDisplayName);
65 
66   const char *cstr = NULL;
67   if (m_opaque_ptr)
68     cstr = m_opaque_ptr->GetMangled()
69                .GetDisplayDemangledName(m_opaque_ptr->GetLanguage())
70                .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 = NULL;
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, NULL));
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     ExecutionContext exe_ctx;
128     TargetSP target_sp(target.GetSP());
129     std::unique_lock<std::recursive_mutex> lock;
130     if (target_sp) {
131       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
132       target_sp->CalculateExecutionContext(exe_ctx);
133       exe_ctx.SetProcessSP(target_sp->GetProcessSP());
134     }
135     ModuleSP module_sp(
136         m_opaque_ptr->GetAddressRange().GetBaseAddress().GetModule());
137     if (module_sp) {
138       const bool prefer_file_cache = false;
139       sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
140           module_sp->GetArchitecture(), NULL, flavor, exe_ctx,
141           m_opaque_ptr->GetAddressRange(), prefer_file_cache));
142     }
143   }
144   return LLDB_RECORD_RESULT(sb_instructions);
145 }
146 
147 lldb_private::Function *SBFunction::get() { return m_opaque_ptr; }
148 
149 void SBFunction::reset(lldb_private::Function *lldb_object_ptr) {
150   m_opaque_ptr = lldb_object_ptr;
151 }
152 
153 SBAddress SBFunction::GetStartAddress() {
154   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBAddress, SBFunction, GetStartAddress);
155 
156   SBAddress addr;
157   if (m_opaque_ptr)
158     addr.SetAddress(&m_opaque_ptr->GetAddressRange().GetBaseAddress());
159   return LLDB_RECORD_RESULT(addr);
160 }
161 
162 SBAddress SBFunction::GetEndAddress() {
163   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBAddress, SBFunction, GetEndAddress);
164 
165   SBAddress addr;
166   if (m_opaque_ptr) {
167     addr_t byte_size = m_opaque_ptr->GetAddressRange().GetByteSize();
168     if (byte_size > 0) {
169       addr.SetAddress(&m_opaque_ptr->GetAddressRange().GetBaseAddress());
170       addr->Slide(byte_size);
171     }
172   }
173   return LLDB_RECORD_RESULT(addr);
174 }
175 
176 const char *SBFunction::GetArgumentName(uint32_t arg_idx) {
177   LLDB_RECORD_METHOD(const char *, SBFunction, GetArgumentName, (uint32_t),
178                      arg_idx);
179 
180   if (m_opaque_ptr) {
181     Block &block = m_opaque_ptr->GetBlock(true);
182     VariableListSP variable_list_sp = block.GetBlockVariableList(true);
183     if (variable_list_sp) {
184       VariableList arguments;
185       variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,
186                                                  arguments, true);
187       lldb::VariableSP variable_sp = arguments.GetVariableAtIndex(arg_idx);
188       if (variable_sp)
189         return variable_sp->GetName().GetCString();
190     }
191   }
192   return nullptr;
193 }
194 
195 uint32_t SBFunction::GetPrologueByteSize() {
196   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBFunction, GetPrologueByteSize);
197 
198   if (m_opaque_ptr)
199     return m_opaque_ptr->GetPrologueByteSize();
200   return 0;
201 }
202 
203 SBType SBFunction::GetType() {
204   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBType, SBFunction, GetType);
205 
206   SBType sb_type;
207   if (m_opaque_ptr) {
208     Type *function_type = m_opaque_ptr->GetType();
209     if (function_type)
210       sb_type.ref().SetType(function_type->shared_from_this());
211   }
212   return LLDB_RECORD_RESULT(sb_type);
213 }
214 
215 SBBlock SBFunction::GetBlock() {
216   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBlock, SBFunction, GetBlock);
217 
218   SBBlock sb_block;
219   if (m_opaque_ptr)
220     sb_block.SetPtr(&m_opaque_ptr->GetBlock(true));
221   return LLDB_RECORD_RESULT(sb_block);
222 }
223 
224 lldb::LanguageType SBFunction::GetLanguage() {
225   LLDB_RECORD_METHOD_NO_ARGS(lldb::LanguageType, SBFunction, GetLanguage);
226 
227   if (m_opaque_ptr) {
228     if (m_opaque_ptr->GetCompileUnit())
229       return m_opaque_ptr->GetCompileUnit()->GetLanguage();
230   }
231   return lldb::eLanguageTypeUnknown;
232 }
233 
234 bool SBFunction::GetIsOptimized() {
235   LLDB_RECORD_METHOD_NO_ARGS(bool, SBFunction, GetIsOptimized);
236 
237   if (m_opaque_ptr) {
238     if (m_opaque_ptr->GetCompileUnit())
239       return m_opaque_ptr->GetCompileUnit()->GetIsOptimized();
240   }
241   return false;
242 }
243