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