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