xref: /openbsd-src/gnu/llvm/lldb/source/Symbol/Function.cpp (revision dda2819751e49c83612958492e38917049128b41)
1*dda28197Spatrick //===-- Function.cpp ------------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Symbol/Function.h"
10061da546Spatrick #include "lldb/Core/Disassembler.h"
11061da546Spatrick #include "lldb/Core/Module.h"
12061da546Spatrick #include "lldb/Core/ModuleList.h"
13061da546Spatrick #include "lldb/Core/Section.h"
14061da546Spatrick #include "lldb/Host/Host.h"
15061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
16061da546Spatrick #include "lldb/Symbol/CompilerType.h"
17061da546Spatrick #include "lldb/Symbol/LineTable.h"
18061da546Spatrick #include "lldb/Symbol/SymbolFile.h"
19061da546Spatrick #include "lldb/Target/Language.h"
20061da546Spatrick #include "lldb/Target/Target.h"
21061da546Spatrick #include "lldb/Utility/Log.h"
22061da546Spatrick #include "llvm/Support/Casting.h"
23061da546Spatrick 
24061da546Spatrick using namespace lldb;
25061da546Spatrick using namespace lldb_private;
26061da546Spatrick 
27061da546Spatrick // Basic function information is contained in the FunctionInfo class. It is
28061da546Spatrick // designed to contain the name, linkage name, and declaration location.
29061da546Spatrick FunctionInfo::FunctionInfo(const char *name, const Declaration *decl_ptr)
30061da546Spatrick     : m_name(name), m_declaration(decl_ptr) {}
31061da546Spatrick 
32061da546Spatrick FunctionInfo::FunctionInfo(ConstString name, const Declaration *decl_ptr)
33061da546Spatrick     : m_name(name), m_declaration(decl_ptr) {}
34061da546Spatrick 
35061da546Spatrick FunctionInfo::~FunctionInfo() {}
36061da546Spatrick 
37061da546Spatrick void FunctionInfo::Dump(Stream *s, bool show_fullpaths) const {
38061da546Spatrick   if (m_name)
39061da546Spatrick     *s << ", name = \"" << m_name << "\"";
40061da546Spatrick   m_declaration.Dump(s, show_fullpaths);
41061da546Spatrick }
42061da546Spatrick 
43061da546Spatrick int FunctionInfo::Compare(const FunctionInfo &a, const FunctionInfo &b) {
44061da546Spatrick   int result = ConstString::Compare(a.GetName(), b.GetName());
45061da546Spatrick   if (result)
46061da546Spatrick     return result;
47061da546Spatrick 
48061da546Spatrick   return Declaration::Compare(a.m_declaration, b.m_declaration);
49061da546Spatrick }
50061da546Spatrick 
51061da546Spatrick Declaration &FunctionInfo::GetDeclaration() { return m_declaration; }
52061da546Spatrick 
53061da546Spatrick const Declaration &FunctionInfo::GetDeclaration() const {
54061da546Spatrick   return m_declaration;
55061da546Spatrick }
56061da546Spatrick 
57061da546Spatrick ConstString FunctionInfo::GetName() const { return m_name; }
58061da546Spatrick 
59061da546Spatrick size_t FunctionInfo::MemorySize() const {
60061da546Spatrick   return m_name.MemorySize() + m_declaration.MemorySize();
61061da546Spatrick }
62061da546Spatrick 
63061da546Spatrick InlineFunctionInfo::InlineFunctionInfo(const char *name,
64061da546Spatrick                                        llvm::StringRef mangled,
65061da546Spatrick                                        const Declaration *decl_ptr,
66061da546Spatrick                                        const Declaration *call_decl_ptr)
67061da546Spatrick     : FunctionInfo(name, decl_ptr), m_mangled(mangled),
68061da546Spatrick       m_call_decl(call_decl_ptr) {}
69061da546Spatrick 
70061da546Spatrick InlineFunctionInfo::InlineFunctionInfo(ConstString name,
71061da546Spatrick                                        const Mangled &mangled,
72061da546Spatrick                                        const Declaration *decl_ptr,
73061da546Spatrick                                        const Declaration *call_decl_ptr)
74061da546Spatrick     : FunctionInfo(name, decl_ptr), m_mangled(mangled),
75061da546Spatrick       m_call_decl(call_decl_ptr) {}
76061da546Spatrick 
77061da546Spatrick InlineFunctionInfo::~InlineFunctionInfo() {}
78061da546Spatrick 
79061da546Spatrick void InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const {
80061da546Spatrick   FunctionInfo::Dump(s, show_fullpaths);
81061da546Spatrick   if (m_mangled)
82061da546Spatrick     m_mangled.Dump(s);
83061da546Spatrick }
84061da546Spatrick 
85*dda28197Spatrick void InlineFunctionInfo::DumpStopContext(Stream *s) const {
86061da546Spatrick   //    s->Indent("[inlined] ");
87061da546Spatrick   s->Indent();
88061da546Spatrick   if (m_mangled)
89*dda28197Spatrick     s->PutCString(m_mangled.GetName().AsCString());
90061da546Spatrick   else
91061da546Spatrick     s->PutCString(m_name.AsCString());
92061da546Spatrick }
93061da546Spatrick 
94*dda28197Spatrick ConstString InlineFunctionInfo::GetName() const {
95061da546Spatrick   if (m_mangled)
96*dda28197Spatrick     return m_mangled.GetName();
97061da546Spatrick   return m_name;
98061da546Spatrick }
99061da546Spatrick 
100*dda28197Spatrick ConstString InlineFunctionInfo::GetDisplayName() const {
101061da546Spatrick   if (m_mangled)
102*dda28197Spatrick     return m_mangled.GetDisplayDemangledName();
103061da546Spatrick   return m_name;
104061da546Spatrick }
105061da546Spatrick 
106061da546Spatrick Declaration &InlineFunctionInfo::GetCallSite() { return m_call_decl; }
107061da546Spatrick 
108061da546Spatrick const Declaration &InlineFunctionInfo::GetCallSite() const {
109061da546Spatrick   return m_call_decl;
110061da546Spatrick }
111061da546Spatrick 
112061da546Spatrick Mangled &InlineFunctionInfo::GetMangled() { return m_mangled; }
113061da546Spatrick 
114061da546Spatrick const Mangled &InlineFunctionInfo::GetMangled() const { return m_mangled; }
115061da546Spatrick 
116061da546Spatrick size_t InlineFunctionInfo::MemorySize() const {
117061da546Spatrick   return FunctionInfo::MemorySize() + m_mangled.MemorySize();
118061da546Spatrick }
119061da546Spatrick 
120061da546Spatrick /// @name Call site related structures
121061da546Spatrick /// @{
122061da546Spatrick 
123*dda28197Spatrick lldb::addr_t CallEdge::GetLoadAddress(lldb::addr_t unresolved_pc,
124*dda28197Spatrick                                       Function &caller, Target &target) {
125*dda28197Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
126*dda28197Spatrick 
127*dda28197Spatrick   const Address &caller_start_addr = caller.GetAddressRange().GetBaseAddress();
128*dda28197Spatrick 
129*dda28197Spatrick   ModuleSP caller_module_sp = caller_start_addr.GetModule();
130*dda28197Spatrick   if (!caller_module_sp) {
131*dda28197Spatrick     LLDB_LOG(log, "GetLoadAddress: cannot get Module for caller");
132*dda28197Spatrick     return LLDB_INVALID_ADDRESS;
133*dda28197Spatrick   }
134*dda28197Spatrick 
135*dda28197Spatrick   SectionList *section_list = caller_module_sp->GetSectionList();
136*dda28197Spatrick   if (!section_list) {
137*dda28197Spatrick     LLDB_LOG(log, "GetLoadAddress: cannot get SectionList for Module");
138*dda28197Spatrick     return LLDB_INVALID_ADDRESS;
139*dda28197Spatrick   }
140*dda28197Spatrick 
141*dda28197Spatrick   Address the_addr = Address(unresolved_pc, section_list);
142*dda28197Spatrick   lldb::addr_t load_addr = the_addr.GetLoadAddress(&target);
143*dda28197Spatrick   return load_addr;
144*dda28197Spatrick }
145*dda28197Spatrick 
146061da546Spatrick lldb::addr_t CallEdge::GetReturnPCAddress(Function &caller,
147061da546Spatrick                                           Target &target) const {
148*dda28197Spatrick   return GetLoadAddress(GetUnresolvedReturnPCAddress(), caller, target);
149061da546Spatrick }
150061da546Spatrick 
151061da546Spatrick void DirectCallEdge::ParseSymbolFileAndResolve(ModuleList &images) {
152061da546Spatrick   if (resolved)
153061da546Spatrick     return;
154061da546Spatrick 
155061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
156061da546Spatrick   LLDB_LOG(log, "DirectCallEdge: Lazily parsing the call graph for {0}",
157061da546Spatrick            lazy_callee.symbol_name);
158061da546Spatrick 
159061da546Spatrick   auto resolve_lazy_callee = [&]() -> Function * {
160061da546Spatrick     ConstString callee_name{lazy_callee.symbol_name};
161061da546Spatrick     SymbolContextList sc_list;
162061da546Spatrick     images.FindFunctionSymbols(callee_name, eFunctionNameTypeAuto, sc_list);
163061da546Spatrick     size_t num_matches = sc_list.GetSize();
164061da546Spatrick     if (num_matches == 0 || !sc_list[0].symbol) {
165061da546Spatrick       LLDB_LOG(log,
166061da546Spatrick                "DirectCallEdge: Found no symbols for {0}, cannot resolve it",
167061da546Spatrick                callee_name);
168061da546Spatrick       return nullptr;
169061da546Spatrick     }
170061da546Spatrick     Address callee_addr = sc_list[0].symbol->GetAddress();
171061da546Spatrick     if (!callee_addr.IsValid()) {
172061da546Spatrick       LLDB_LOG(log, "DirectCallEdge: Invalid symbol address");
173061da546Spatrick       return nullptr;
174061da546Spatrick     }
175061da546Spatrick     Function *f = callee_addr.CalculateSymbolContextFunction();
176061da546Spatrick     if (!f) {
177061da546Spatrick       LLDB_LOG(log, "DirectCallEdge: Could not find complete function");
178061da546Spatrick       return nullptr;
179061da546Spatrick     }
180061da546Spatrick     return f;
181061da546Spatrick   };
182061da546Spatrick   lazy_callee.def = resolve_lazy_callee();
183061da546Spatrick   resolved = true;
184061da546Spatrick }
185061da546Spatrick 
186061da546Spatrick Function *DirectCallEdge::GetCallee(ModuleList &images, ExecutionContext &) {
187061da546Spatrick   ParseSymbolFileAndResolve(images);
188061da546Spatrick   assert(resolved && "Did not resolve lazy callee");
189061da546Spatrick   return lazy_callee.def;
190061da546Spatrick }
191061da546Spatrick 
192061da546Spatrick Function *IndirectCallEdge::GetCallee(ModuleList &images,
193061da546Spatrick                                       ExecutionContext &exe_ctx) {
194061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
195061da546Spatrick   Status error;
196061da546Spatrick   Value callee_addr_val;
197061da546Spatrick   if (!call_target.Evaluate(&exe_ctx, exe_ctx.GetRegisterContext(),
198061da546Spatrick                             /*loclist_base_addr=*/LLDB_INVALID_ADDRESS,
199061da546Spatrick                             /*initial_value_ptr=*/nullptr,
200061da546Spatrick                             /*object_address_ptr=*/nullptr, callee_addr_val,
201061da546Spatrick                             &error)) {
202061da546Spatrick     LLDB_LOGF(log, "IndirectCallEdge: Could not evaluate expression: %s",
203061da546Spatrick               error.AsCString());
204061da546Spatrick     return nullptr;
205061da546Spatrick   }
206061da546Spatrick 
207061da546Spatrick   addr_t raw_addr = callee_addr_val.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
208061da546Spatrick   if (raw_addr == LLDB_INVALID_ADDRESS) {
209061da546Spatrick     LLDB_LOG(log, "IndirectCallEdge: Could not extract address from scalar");
210061da546Spatrick     return nullptr;
211061da546Spatrick   }
212061da546Spatrick 
213061da546Spatrick   Address callee_addr;
214061da546Spatrick   if (!exe_ctx.GetTargetPtr()->ResolveLoadAddress(raw_addr, callee_addr)) {
215061da546Spatrick     LLDB_LOG(log, "IndirectCallEdge: Could not resolve callee's load address");
216061da546Spatrick     return nullptr;
217061da546Spatrick   }
218061da546Spatrick 
219061da546Spatrick   Function *f = callee_addr.CalculateSymbolContextFunction();
220061da546Spatrick   if (!f) {
221061da546Spatrick     LLDB_LOG(log, "IndirectCallEdge: Could not find complete function");
222061da546Spatrick     return nullptr;
223061da546Spatrick   }
224061da546Spatrick 
225061da546Spatrick   return f;
226061da546Spatrick }
227061da546Spatrick 
228061da546Spatrick /// @}
229061da546Spatrick 
230061da546Spatrick //
231061da546Spatrick Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
232061da546Spatrick                    lldb::user_id_t type_uid, const Mangled &mangled, Type *type,
233061da546Spatrick                    const AddressRange &range)
234061da546Spatrick     : UserID(func_uid), m_comp_unit(comp_unit), m_type_uid(type_uid),
235061da546Spatrick       m_type(type), m_mangled(mangled), m_block(func_uid), m_range(range),
236061da546Spatrick       m_frame_base(), m_flags(), m_prologue_byte_size(0) {
237061da546Spatrick   m_block.SetParentScope(this);
238061da546Spatrick   assert(comp_unit != nullptr);
239061da546Spatrick }
240061da546Spatrick 
241061da546Spatrick Function::~Function() {}
242061da546Spatrick 
243061da546Spatrick void Function::GetStartLineSourceInfo(FileSpec &source_file,
244061da546Spatrick                                       uint32_t &line_no) {
245061da546Spatrick   line_no = 0;
246061da546Spatrick   source_file.Clear();
247061da546Spatrick 
248061da546Spatrick   if (m_comp_unit == nullptr)
249061da546Spatrick     return;
250061da546Spatrick 
251061da546Spatrick   // Initialize m_type if it hasn't been initialized already
252061da546Spatrick   GetType();
253061da546Spatrick 
254061da546Spatrick   if (m_type != nullptr && m_type->GetDeclaration().GetLine() != 0) {
255061da546Spatrick     source_file = m_type->GetDeclaration().GetFile();
256061da546Spatrick     line_no = m_type->GetDeclaration().GetLine();
257061da546Spatrick   } else {
258061da546Spatrick     LineTable *line_table = m_comp_unit->GetLineTable();
259061da546Spatrick     if (line_table == nullptr)
260061da546Spatrick       return;
261061da546Spatrick 
262061da546Spatrick     LineEntry line_entry;
263061da546Spatrick     if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(),
264061da546Spatrick                                            line_entry, nullptr)) {
265061da546Spatrick       line_no = line_entry.line;
266061da546Spatrick       source_file = line_entry.file;
267061da546Spatrick     }
268061da546Spatrick   }
269061da546Spatrick }
270061da546Spatrick 
271061da546Spatrick void Function::GetEndLineSourceInfo(FileSpec &source_file, uint32_t &line_no) {
272061da546Spatrick   line_no = 0;
273061da546Spatrick   source_file.Clear();
274061da546Spatrick 
275061da546Spatrick   // The -1 is kind of cheesy, but I want to get the last line entry for the
276061da546Spatrick   // given function, not the first entry of the next.
277061da546Spatrick   Address scratch_addr(GetAddressRange().GetBaseAddress());
278061da546Spatrick   scratch_addr.SetOffset(scratch_addr.GetOffset() +
279061da546Spatrick                          GetAddressRange().GetByteSize() - 1);
280061da546Spatrick 
281061da546Spatrick   LineTable *line_table = m_comp_unit->GetLineTable();
282061da546Spatrick   if (line_table == nullptr)
283061da546Spatrick     return;
284061da546Spatrick 
285061da546Spatrick   LineEntry line_entry;
286061da546Spatrick   if (line_table->FindLineEntryByAddress(scratch_addr, line_entry, nullptr)) {
287061da546Spatrick     line_no = line_entry.line;
288061da546Spatrick     source_file = line_entry.file;
289061da546Spatrick   }
290061da546Spatrick }
291061da546Spatrick 
292061da546Spatrick llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetCallEdges() {
293*dda28197Spatrick   std::lock_guard<std::mutex> guard(m_call_edges_lock);
294*dda28197Spatrick 
295061da546Spatrick   if (m_call_edges_resolved)
296061da546Spatrick     return m_call_edges;
297061da546Spatrick 
298061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
299061da546Spatrick   LLDB_LOG(log, "GetCallEdges: Attempting to parse call site info for {0}",
300061da546Spatrick            GetDisplayName());
301061da546Spatrick 
302061da546Spatrick   m_call_edges_resolved = true;
303061da546Spatrick 
304061da546Spatrick   // Find the SymbolFile which provided this function's definition.
305061da546Spatrick   Block &block = GetBlock(/*can_create*/true);
306061da546Spatrick   SymbolFile *sym_file = block.GetSymbolFile();
307061da546Spatrick   if (!sym_file)
308061da546Spatrick     return llvm::None;
309061da546Spatrick 
310061da546Spatrick   // Lazily read call site information from the SymbolFile.
311061da546Spatrick   m_call_edges = sym_file->ParseCallEdgesInFunction(GetID());
312061da546Spatrick 
313061da546Spatrick   // Sort the call edges to speed up return_pc lookups.
314*dda28197Spatrick   llvm::sort(m_call_edges, [](const std::unique_ptr<CallEdge> &LHS,
315061da546Spatrick                               const std::unique_ptr<CallEdge> &RHS) {
316*dda28197Spatrick     return LHS->GetSortKey() < RHS->GetSortKey();
317061da546Spatrick   });
318061da546Spatrick 
319061da546Spatrick   return m_call_edges;
320061da546Spatrick }
321061da546Spatrick 
322061da546Spatrick llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetTailCallingEdges() {
323*dda28197Spatrick   // Tail calling edges are sorted at the end of the list. Find them by dropping
324*dda28197Spatrick   // all non-tail-calls.
325*dda28197Spatrick   return GetCallEdges().drop_until(
326*dda28197Spatrick       [](const std::unique_ptr<CallEdge> &edge) { return edge->IsTailCall(); });
327061da546Spatrick }
328061da546Spatrick 
329061da546Spatrick CallEdge *Function::GetCallEdgeForReturnAddress(addr_t return_pc,
330061da546Spatrick                                                 Target &target) {
331061da546Spatrick   auto edges = GetCallEdges();
332061da546Spatrick   auto edge_it =
333*dda28197Spatrick       llvm::partition_point(edges, [&](const std::unique_ptr<CallEdge> &edge) {
334*dda28197Spatrick         return std::make_pair(edge->IsTailCall(),
335*dda28197Spatrick                               edge->GetReturnPCAddress(*this, target)) <
336*dda28197Spatrick                std::make_pair(false, return_pc);
337061da546Spatrick       });
338061da546Spatrick   if (edge_it == edges.end() ||
339061da546Spatrick       edge_it->get()->GetReturnPCAddress(*this, target) != return_pc)
340061da546Spatrick     return nullptr;
341*dda28197Spatrick   return edge_it->get();
342061da546Spatrick }
343061da546Spatrick 
344061da546Spatrick Block &Function::GetBlock(bool can_create) {
345061da546Spatrick   if (!m_block.BlockInfoHasBeenParsed() && can_create) {
346061da546Spatrick     ModuleSP module_sp = CalculateSymbolContextModule();
347061da546Spatrick     if (module_sp) {
348061da546Spatrick       module_sp->GetSymbolFile()->ParseBlocksRecursive(*this);
349061da546Spatrick     } else {
350061da546Spatrick       Host::SystemLog(Host::eSystemLogError,
351061da546Spatrick                       "error: unable to find module "
352061da546Spatrick                       "shared pointer for function '%s' "
353061da546Spatrick                       "in %s\n",
354061da546Spatrick                       GetName().GetCString(),
355061da546Spatrick                       m_comp_unit->GetPrimaryFile().GetPath().c_str());
356061da546Spatrick     }
357061da546Spatrick     m_block.SetBlockInfoHasBeenParsed(true, true);
358061da546Spatrick   }
359061da546Spatrick   return m_block;
360061da546Spatrick }
361061da546Spatrick 
362061da546Spatrick CompileUnit *Function::GetCompileUnit() { return m_comp_unit; }
363061da546Spatrick 
364061da546Spatrick const CompileUnit *Function::GetCompileUnit() const { return m_comp_unit; }
365061da546Spatrick 
366061da546Spatrick void Function::GetDescription(Stream *s, lldb::DescriptionLevel level,
367061da546Spatrick                               Target *target) {
368061da546Spatrick   ConstString name = GetName();
369061da546Spatrick   ConstString mangled = m_mangled.GetMangledName();
370061da546Spatrick 
371061da546Spatrick   *s << "id = " << (const UserID &)*this;
372061da546Spatrick   if (name)
373*dda28197Spatrick     s->AsRawOstream() << ", name = \"" << name << '"';
374061da546Spatrick   if (mangled)
375*dda28197Spatrick     s->AsRawOstream() << ", mangled = \"" << mangled << '"';
376061da546Spatrick   *s << ", range = ";
377061da546Spatrick   Address::DumpStyle fallback_style;
378061da546Spatrick   if (level == eDescriptionLevelVerbose)
379061da546Spatrick     fallback_style = Address::DumpStyleModuleWithFileAddress;
380061da546Spatrick   else
381061da546Spatrick     fallback_style = Address::DumpStyleFileAddress;
382061da546Spatrick   GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress,
383061da546Spatrick                          fallback_style);
384061da546Spatrick }
385061da546Spatrick 
386061da546Spatrick void Function::Dump(Stream *s, bool show_context) const {
387061da546Spatrick   s->Printf("%p: ", static_cast<const void *>(this));
388061da546Spatrick   s->Indent();
389061da546Spatrick   *s << "Function" << static_cast<const UserID &>(*this);
390061da546Spatrick 
391061da546Spatrick   m_mangled.Dump(s);
392061da546Spatrick 
393061da546Spatrick   if (m_type)
394061da546Spatrick     s->Printf(", type = %p", static_cast<void *>(m_type));
395061da546Spatrick   else if (m_type_uid != LLDB_INVALID_UID)
396061da546Spatrick     s->Printf(", type_uid = 0x%8.8" PRIx64, m_type_uid);
397061da546Spatrick 
398061da546Spatrick   s->EOL();
399061da546Spatrick   // Dump the root object
400061da546Spatrick   if (m_block.BlockInfoHasBeenParsed())
401061da546Spatrick     m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX,
402061da546Spatrick                  show_context);
403061da546Spatrick }
404061da546Spatrick 
405061da546Spatrick void Function::CalculateSymbolContext(SymbolContext *sc) {
406061da546Spatrick   sc->function = this;
407061da546Spatrick   m_comp_unit->CalculateSymbolContext(sc);
408061da546Spatrick }
409061da546Spatrick 
410061da546Spatrick ModuleSP Function::CalculateSymbolContextModule() {
411061da546Spatrick   SectionSP section_sp(m_range.GetBaseAddress().GetSection());
412061da546Spatrick   if (section_sp)
413061da546Spatrick     return section_sp->GetModule();
414061da546Spatrick 
415061da546Spatrick   return this->GetCompileUnit()->GetModule();
416061da546Spatrick }
417061da546Spatrick 
418061da546Spatrick CompileUnit *Function::CalculateSymbolContextCompileUnit() {
419061da546Spatrick   return this->GetCompileUnit();
420061da546Spatrick }
421061da546Spatrick 
422061da546Spatrick Function *Function::CalculateSymbolContextFunction() { return this; }
423061da546Spatrick 
424061da546Spatrick lldb::DisassemblerSP Function::GetInstructions(const ExecutionContext &exe_ctx,
425061da546Spatrick                                                const char *flavor,
426061da546Spatrick                                                bool prefer_file_cache) {
427061da546Spatrick   ModuleSP module_sp(GetAddressRange().GetBaseAddress().GetModule());
428*dda28197Spatrick   if (module_sp && exe_ctx.HasTargetScope()) {
429061da546Spatrick     const bool prefer_file_cache = false;
430061da546Spatrick     return Disassembler::DisassembleRange(module_sp->GetArchitecture(), nullptr,
431*dda28197Spatrick                                           flavor, exe_ctx.GetTargetRef(),
432*dda28197Spatrick                                           GetAddressRange(), prefer_file_cache);
433061da546Spatrick   }
434061da546Spatrick   return lldb::DisassemblerSP();
435061da546Spatrick }
436061da546Spatrick 
437061da546Spatrick bool Function::GetDisassembly(const ExecutionContext &exe_ctx,
438061da546Spatrick                               const char *flavor, bool prefer_file_cache,
439061da546Spatrick                               Stream &strm) {
440061da546Spatrick   lldb::DisassemblerSP disassembler_sp =
441061da546Spatrick       GetInstructions(exe_ctx, flavor, prefer_file_cache);
442061da546Spatrick   if (disassembler_sp) {
443061da546Spatrick     const bool show_address = true;
444061da546Spatrick     const bool show_bytes = false;
445061da546Spatrick     disassembler_sp->GetInstructionList().Dump(&strm, show_address, show_bytes,
446061da546Spatrick                                                &exe_ctx);
447061da546Spatrick     return true;
448061da546Spatrick   }
449061da546Spatrick   return false;
450061da546Spatrick }
451061da546Spatrick 
452061da546Spatrick // Symbol *
453061da546Spatrick // Function::CalculateSymbolContextSymbol ()
454061da546Spatrick //{
455061da546Spatrick //    return // TODO: find the symbol for the function???
456061da546Spatrick //}
457061da546Spatrick 
458061da546Spatrick void Function::DumpSymbolContext(Stream *s) {
459061da546Spatrick   m_comp_unit->DumpSymbolContext(s);
460061da546Spatrick   s->Printf(", Function{0x%8.8" PRIx64 "}", GetID());
461061da546Spatrick }
462061da546Spatrick 
463061da546Spatrick size_t Function::MemorySize() const {
464061da546Spatrick   size_t mem_size = sizeof(Function) + m_block.MemorySize();
465061da546Spatrick   return mem_size;
466061da546Spatrick }
467061da546Spatrick 
468061da546Spatrick bool Function::GetIsOptimized() {
469061da546Spatrick   bool result = false;
470061da546Spatrick 
471061da546Spatrick   // Currently optimization is only indicted by the vendor extension
472061da546Spatrick   // DW_AT_APPLE_optimized which is set on a compile unit level.
473061da546Spatrick   if (m_comp_unit) {
474061da546Spatrick     result = m_comp_unit->GetIsOptimized();
475061da546Spatrick   }
476061da546Spatrick   return result;
477061da546Spatrick }
478061da546Spatrick 
479061da546Spatrick bool Function::IsTopLevelFunction() {
480061da546Spatrick   bool result = false;
481061da546Spatrick 
482061da546Spatrick   if (Language *language = Language::FindPlugin(GetLanguage()))
483061da546Spatrick     result = language->IsTopLevelFunction(*this);
484061da546Spatrick 
485061da546Spatrick   return result;
486061da546Spatrick }
487061da546Spatrick 
488061da546Spatrick ConstString Function::GetDisplayName() const {
489*dda28197Spatrick   return m_mangled.GetDisplayDemangledName();
490061da546Spatrick }
491061da546Spatrick 
492061da546Spatrick CompilerDeclContext Function::GetDeclContext() {
493061da546Spatrick   ModuleSP module_sp = CalculateSymbolContextModule();
494061da546Spatrick 
495061da546Spatrick   if (module_sp) {
496061da546Spatrick     if (SymbolFile *sym_file = module_sp->GetSymbolFile())
497061da546Spatrick       return sym_file->GetDeclContextForUID(GetID());
498061da546Spatrick   }
499061da546Spatrick   return CompilerDeclContext();
500061da546Spatrick }
501061da546Spatrick 
502061da546Spatrick Type *Function::GetType() {
503061da546Spatrick   if (m_type == nullptr) {
504061da546Spatrick     SymbolContext sc;
505061da546Spatrick 
506061da546Spatrick     CalculateSymbolContext(&sc);
507061da546Spatrick 
508061da546Spatrick     if (!sc.module_sp)
509061da546Spatrick       return nullptr;
510061da546Spatrick 
511061da546Spatrick     SymbolFile *sym_file = sc.module_sp->GetSymbolFile();
512061da546Spatrick 
513061da546Spatrick     if (sym_file == nullptr)
514061da546Spatrick       return nullptr;
515061da546Spatrick 
516061da546Spatrick     m_type = sym_file->ResolveTypeUID(m_type_uid);
517061da546Spatrick   }
518061da546Spatrick   return m_type;
519061da546Spatrick }
520061da546Spatrick 
521061da546Spatrick const Type *Function::GetType() const { return m_type; }
522061da546Spatrick 
523061da546Spatrick CompilerType Function::GetCompilerType() {
524061da546Spatrick   Type *function_type = GetType();
525061da546Spatrick   if (function_type)
526061da546Spatrick     return function_type->GetFullCompilerType();
527061da546Spatrick   return CompilerType();
528061da546Spatrick }
529061da546Spatrick 
530061da546Spatrick uint32_t Function::GetPrologueByteSize() {
531061da546Spatrick   if (m_prologue_byte_size == 0 &&
532061da546Spatrick       m_flags.IsClear(flagsCalculatedPrologueSize)) {
533061da546Spatrick     m_flags.Set(flagsCalculatedPrologueSize);
534061da546Spatrick     LineTable *line_table = m_comp_unit->GetLineTable();
535061da546Spatrick     uint32_t prologue_end_line_idx = 0;
536061da546Spatrick 
537061da546Spatrick     if (line_table) {
538061da546Spatrick       LineEntry first_line_entry;
539061da546Spatrick       uint32_t first_line_entry_idx = UINT32_MAX;
540061da546Spatrick       if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(),
541061da546Spatrick                                              first_line_entry,
542061da546Spatrick                                              &first_line_entry_idx)) {
543061da546Spatrick         // Make sure the first line entry isn't already the end of the prologue
544061da546Spatrick         addr_t prologue_end_file_addr = LLDB_INVALID_ADDRESS;
545061da546Spatrick         addr_t line_zero_end_file_addr = LLDB_INVALID_ADDRESS;
546061da546Spatrick 
547061da546Spatrick         if (first_line_entry.is_prologue_end) {
548061da546Spatrick           prologue_end_file_addr =
549061da546Spatrick               first_line_entry.range.GetBaseAddress().GetFileAddress();
550061da546Spatrick           prologue_end_line_idx = first_line_entry_idx;
551061da546Spatrick         } else {
552061da546Spatrick           // Check the first few instructions and look for one that has
553061da546Spatrick           // is_prologue_end set to true.
554061da546Spatrick           const uint32_t last_line_entry_idx = first_line_entry_idx + 6;
555061da546Spatrick           for (uint32_t idx = first_line_entry_idx + 1;
556061da546Spatrick                idx < last_line_entry_idx; ++idx) {
557061da546Spatrick             LineEntry line_entry;
558061da546Spatrick             if (line_table->GetLineEntryAtIndex(idx, line_entry)) {
559061da546Spatrick               if (line_entry.is_prologue_end) {
560061da546Spatrick                 prologue_end_file_addr =
561061da546Spatrick                     line_entry.range.GetBaseAddress().GetFileAddress();
562061da546Spatrick                 prologue_end_line_idx = idx;
563061da546Spatrick                 break;
564061da546Spatrick               }
565061da546Spatrick             }
566061da546Spatrick           }
567061da546Spatrick         }
568061da546Spatrick 
569061da546Spatrick         // If we didn't find the end of the prologue in the line tables, then
570061da546Spatrick         // just use the end address of the first line table entry
571061da546Spatrick         if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) {
572061da546Spatrick           // Check the first few instructions and look for one that has a line
573061da546Spatrick           // number that's different than the first entry.
574061da546Spatrick           uint32_t last_line_entry_idx = first_line_entry_idx + 6;
575061da546Spatrick           for (uint32_t idx = first_line_entry_idx + 1;
576061da546Spatrick                idx < last_line_entry_idx; ++idx) {
577061da546Spatrick             LineEntry line_entry;
578061da546Spatrick             if (line_table->GetLineEntryAtIndex(idx, line_entry)) {
579061da546Spatrick               if (line_entry.line != first_line_entry.line) {
580061da546Spatrick                 prologue_end_file_addr =
581061da546Spatrick                     line_entry.range.GetBaseAddress().GetFileAddress();
582061da546Spatrick                 prologue_end_line_idx = idx;
583061da546Spatrick                 break;
584061da546Spatrick               }
585061da546Spatrick             }
586061da546Spatrick           }
587061da546Spatrick 
588061da546Spatrick           if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) {
589061da546Spatrick             prologue_end_file_addr =
590061da546Spatrick                 first_line_entry.range.GetBaseAddress().GetFileAddress() +
591061da546Spatrick                 first_line_entry.range.GetByteSize();
592061da546Spatrick             prologue_end_line_idx = first_line_entry_idx;
593061da546Spatrick           }
594061da546Spatrick         }
595061da546Spatrick 
596061da546Spatrick         const addr_t func_start_file_addr =
597061da546Spatrick             m_range.GetBaseAddress().GetFileAddress();
598061da546Spatrick         const addr_t func_end_file_addr =
599061da546Spatrick             func_start_file_addr + m_range.GetByteSize();
600061da546Spatrick 
601061da546Spatrick         // Now calculate the offset to pass the subsequent line 0 entries.
602061da546Spatrick         uint32_t first_non_zero_line = prologue_end_line_idx;
603061da546Spatrick         while (true) {
604061da546Spatrick           LineEntry line_entry;
605061da546Spatrick           if (line_table->GetLineEntryAtIndex(first_non_zero_line,
606061da546Spatrick                                               line_entry)) {
607061da546Spatrick             if (line_entry.line != 0)
608061da546Spatrick               break;
609061da546Spatrick           }
610061da546Spatrick           if (line_entry.range.GetBaseAddress().GetFileAddress() >=
611061da546Spatrick               func_end_file_addr)
612061da546Spatrick             break;
613061da546Spatrick 
614061da546Spatrick           first_non_zero_line++;
615061da546Spatrick         }
616061da546Spatrick 
617061da546Spatrick         if (first_non_zero_line > prologue_end_line_idx) {
618061da546Spatrick           LineEntry first_non_zero_entry;
619061da546Spatrick           if (line_table->GetLineEntryAtIndex(first_non_zero_line,
620061da546Spatrick                                               first_non_zero_entry)) {
621061da546Spatrick             line_zero_end_file_addr =
622061da546Spatrick                 first_non_zero_entry.range.GetBaseAddress().GetFileAddress();
623061da546Spatrick           }
624061da546Spatrick         }
625061da546Spatrick 
626061da546Spatrick         // Verify that this prologue end file address in the function's address
627061da546Spatrick         // range just to be sure
628061da546Spatrick         if (func_start_file_addr < prologue_end_file_addr &&
629061da546Spatrick             prologue_end_file_addr < func_end_file_addr) {
630061da546Spatrick           m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr;
631061da546Spatrick         }
632061da546Spatrick 
633061da546Spatrick         if (prologue_end_file_addr < line_zero_end_file_addr &&
634061da546Spatrick             line_zero_end_file_addr < func_end_file_addr) {
635061da546Spatrick           m_prologue_byte_size +=
636061da546Spatrick               line_zero_end_file_addr - prologue_end_file_addr;
637061da546Spatrick         }
638061da546Spatrick       }
639061da546Spatrick     }
640061da546Spatrick   }
641061da546Spatrick 
642061da546Spatrick   return m_prologue_byte_size;
643061da546Spatrick }
644061da546Spatrick 
645061da546Spatrick lldb::LanguageType Function::GetLanguage() const {
646061da546Spatrick   lldb::LanguageType lang = m_mangled.GuessLanguage();
647061da546Spatrick   if (lang != lldb::eLanguageTypeUnknown)
648061da546Spatrick     return lang;
649061da546Spatrick 
650061da546Spatrick   if (m_comp_unit)
651061da546Spatrick     return m_comp_unit->GetLanguage();
652061da546Spatrick 
653061da546Spatrick   return lldb::eLanguageTypeUnknown;
654061da546Spatrick }
655061da546Spatrick 
656061da546Spatrick ConstString Function::GetName() const {
657*dda28197Spatrick   return m_mangled.GetName();
658061da546Spatrick }
659061da546Spatrick 
660061da546Spatrick ConstString Function::GetNameNoArguments() const {
661*dda28197Spatrick   return m_mangled.GetName(Mangled::ePreferDemangledWithoutArguments);
662061da546Spatrick }
663