1 //===-- Function.cpp ------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Symbol/Function.h"
10 #include "lldb/Core/Debugger.h"
11 #include "lldb/Core/Disassembler.h"
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/ModuleList.h"
14 #include "lldb/Core/Section.h"
15 #include "lldb/Host/Host.h"
16 #include "lldb/Symbol/CompileUnit.h"
17 #include "lldb/Symbol/CompilerType.h"
18 #include "lldb/Symbol/LineTable.h"
19 #include "lldb/Symbol/SymbolFile.h"
20 #include "lldb/Target/Language.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Utility/LLDBLog.h"
23 #include "lldb/Utility/Log.h"
24 #include "llvm/Support/Casting.h"
27 using namespace lldb_private
;
29 // Basic function information is contained in the FunctionInfo class. It is
30 // designed to contain the name, linkage name, and declaration location.
31 FunctionInfo::FunctionInfo(const char *name
, const Declaration
*decl_ptr
)
32 : m_name(name
), m_declaration(decl_ptr
) {}
34 FunctionInfo::FunctionInfo(ConstString name
, const Declaration
*decl_ptr
)
35 : m_name(name
), m_declaration(decl_ptr
) {}
37 FunctionInfo::~FunctionInfo() = default;
39 void FunctionInfo::Dump(Stream
*s
, bool show_fullpaths
) const {
41 *s
<< ", name = \"" << m_name
<< "\"";
42 m_declaration
.Dump(s
, show_fullpaths
);
45 int FunctionInfo::Compare(const FunctionInfo
&a
, const FunctionInfo
&b
) {
46 int result
= ConstString::Compare(a
.GetName(), b
.GetName());
50 return Declaration::Compare(a
.m_declaration
, b
.m_declaration
);
53 Declaration
&FunctionInfo::GetDeclaration() { return m_declaration
; }
55 const Declaration
&FunctionInfo::GetDeclaration() const {
59 ConstString
FunctionInfo::GetName() const { return m_name
; }
61 size_t FunctionInfo::MemorySize() const {
62 return m_name
.MemorySize() + m_declaration
.MemorySize();
65 InlineFunctionInfo::InlineFunctionInfo(const char *name
,
66 llvm::StringRef mangled
,
67 const Declaration
*decl_ptr
,
68 const Declaration
*call_decl_ptr
)
69 : FunctionInfo(name
, decl_ptr
), m_mangled(mangled
),
70 m_call_decl(call_decl_ptr
) {}
72 InlineFunctionInfo::InlineFunctionInfo(ConstString name
,
73 const Mangled
&mangled
,
74 const Declaration
*decl_ptr
,
75 const Declaration
*call_decl_ptr
)
76 : FunctionInfo(name
, decl_ptr
), m_mangled(mangled
),
77 m_call_decl(call_decl_ptr
) {}
79 InlineFunctionInfo::~InlineFunctionInfo() = default;
81 void InlineFunctionInfo::Dump(Stream
*s
, bool show_fullpaths
) const {
82 FunctionInfo::Dump(s
, show_fullpaths
);
87 void InlineFunctionInfo::DumpStopContext(Stream
*s
) const {
88 // s->Indent("[inlined] ");
91 s
->PutCString(m_mangled
.GetName().AsCString());
93 s
->PutCString(m_name
.AsCString());
96 ConstString
InlineFunctionInfo::GetName() const {
98 return m_mangled
.GetName();
102 ConstString
InlineFunctionInfo::GetDisplayName() const {
104 return m_mangled
.GetDisplayDemangledName();
108 Declaration
&InlineFunctionInfo::GetCallSite() { return m_call_decl
; }
110 const Declaration
&InlineFunctionInfo::GetCallSite() const {
114 Mangled
&InlineFunctionInfo::GetMangled() { return m_mangled
; }
116 const Mangled
&InlineFunctionInfo::GetMangled() const { return m_mangled
; }
118 size_t InlineFunctionInfo::MemorySize() const {
119 return FunctionInfo::MemorySize() + m_mangled
.MemorySize();
122 /// @name Call site related structures
125 CallEdge::~CallEdge() = default;
127 CallEdge::CallEdge(AddrType caller_address_type
, lldb::addr_t caller_address
,
128 bool is_tail_call
, CallSiteParameterArray
&¶meters
)
129 : caller_address(caller_address
), caller_address_type(caller_address_type
),
130 is_tail_call(is_tail_call
), parameters(std::move(parameters
)) {}
132 lldb::addr_t
CallEdge::GetLoadAddress(lldb::addr_t unresolved_pc
,
133 Function
&caller
, Target
&target
) {
134 Log
*log
= GetLog(LLDBLog::Step
);
136 const Address
&caller_start_addr
= caller
.GetAddressRange().GetBaseAddress();
138 ModuleSP caller_module_sp
= caller_start_addr
.GetModule();
139 if (!caller_module_sp
) {
140 LLDB_LOG(log
, "GetLoadAddress: cannot get Module for caller");
141 return LLDB_INVALID_ADDRESS
;
144 SectionList
*section_list
= caller_module_sp
->GetSectionList();
146 LLDB_LOG(log
, "GetLoadAddress: cannot get SectionList for Module");
147 return LLDB_INVALID_ADDRESS
;
150 Address the_addr
= Address(unresolved_pc
, section_list
);
151 lldb::addr_t load_addr
= the_addr
.GetLoadAddress(&target
);
155 lldb::addr_t
CallEdge::GetReturnPCAddress(Function
&caller
,
156 Target
&target
) const {
157 return GetLoadAddress(GetUnresolvedReturnPCAddress(), caller
, target
);
160 void DirectCallEdge::ParseSymbolFileAndResolve(ModuleList
&images
) {
164 Log
*log
= GetLog(LLDBLog::Step
);
165 LLDB_LOG(log
, "DirectCallEdge: Lazily parsing the call graph for {0}",
166 lazy_callee
.symbol_name
);
168 auto resolve_lazy_callee
= [&]() -> Function
* {
169 ConstString callee_name
{lazy_callee
.symbol_name
};
170 SymbolContextList sc_list
;
171 images
.FindFunctionSymbols(callee_name
, eFunctionNameTypeAuto
, sc_list
);
172 size_t num_matches
= sc_list
.GetSize();
173 if (num_matches
== 0 || !sc_list
[0].symbol
) {
175 "DirectCallEdge: Found no symbols for {0}, cannot resolve it",
179 Address callee_addr
= sc_list
[0].symbol
->GetAddress();
180 if (!callee_addr
.IsValid()) {
181 LLDB_LOG(log
, "DirectCallEdge: Invalid symbol address");
184 Function
*f
= callee_addr
.CalculateSymbolContextFunction();
186 LLDB_LOG(log
, "DirectCallEdge: Could not find complete function");
191 lazy_callee
.def
= resolve_lazy_callee();
195 DirectCallEdge::DirectCallEdge(const char *symbol_name
,
196 AddrType caller_address_type
,
197 lldb::addr_t caller_address
, bool is_tail_call
,
198 CallSiteParameterArray
&¶meters
)
199 : CallEdge(caller_address_type
, caller_address
, is_tail_call
,
200 std::move(parameters
)) {
201 lazy_callee
.symbol_name
= symbol_name
;
204 Function
*DirectCallEdge::GetCallee(ModuleList
&images
, ExecutionContext
&) {
205 ParseSymbolFileAndResolve(images
);
206 assert(resolved
&& "Did not resolve lazy callee");
207 return lazy_callee
.def
;
210 IndirectCallEdge::IndirectCallEdge(DWARFExpressionList call_target
,
211 AddrType caller_address_type
,
212 lldb::addr_t caller_address
,
214 CallSiteParameterArray
&¶meters
)
215 : CallEdge(caller_address_type
, caller_address
, is_tail_call
,
216 std::move(parameters
)),
217 call_target(std::move(call_target
)) {}
219 Function
*IndirectCallEdge::GetCallee(ModuleList
&images
,
220 ExecutionContext
&exe_ctx
) {
221 Log
*log
= GetLog(LLDBLog::Step
);
223 Value callee_addr_val
;
224 if (!call_target
.Evaluate(
225 &exe_ctx
, exe_ctx
.GetRegisterContext(), LLDB_INVALID_ADDRESS
,
226 /*initial_value_ptr=*/nullptr,
227 /*object_address_ptr=*/nullptr, callee_addr_val
, &error
)) {
228 LLDB_LOGF(log
, "IndirectCallEdge: Could not evaluate expression: %s",
233 addr_t raw_addr
= callee_addr_val
.GetScalar().ULongLong(LLDB_INVALID_ADDRESS
);
234 if (raw_addr
== LLDB_INVALID_ADDRESS
) {
235 LLDB_LOG(log
, "IndirectCallEdge: Could not extract address from scalar");
240 if (!exe_ctx
.GetTargetPtr()->ResolveLoadAddress(raw_addr
, callee_addr
)) {
241 LLDB_LOG(log
, "IndirectCallEdge: Could not resolve callee's load address");
245 Function
*f
= callee_addr
.CalculateSymbolContextFunction();
247 LLDB_LOG(log
, "IndirectCallEdge: Could not find complete function");
257 Function::Function(CompileUnit
*comp_unit
, lldb::user_id_t func_uid
,
258 lldb::user_id_t type_uid
, const Mangled
&mangled
, Type
*type
,
259 const AddressRange
&range
)
260 : UserID(func_uid
), m_comp_unit(comp_unit
), m_type_uid(type_uid
),
261 m_type(type
), m_mangled(mangled
), m_block(func_uid
), m_range(range
),
262 m_frame_base(), m_flags(), m_prologue_byte_size(0) {
263 m_block
.SetParentScope(this);
264 assert(comp_unit
!= nullptr);
267 Function::~Function() = default;
269 void Function::GetStartLineSourceInfo(FileSpec
&source_file
,
274 if (m_comp_unit
== nullptr)
277 // Initialize m_type if it hasn't been initialized already
280 if (m_type
!= nullptr && m_type
->GetDeclaration().GetLine() != 0) {
281 source_file
= m_type
->GetDeclaration().GetFile();
282 line_no
= m_type
->GetDeclaration().GetLine();
284 LineTable
*line_table
= m_comp_unit
->GetLineTable();
285 if (line_table
== nullptr)
288 LineEntry line_entry
;
289 if (line_table
->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(),
290 line_entry
, nullptr)) {
291 line_no
= line_entry
.line
;
292 source_file
= line_entry
.file
;
297 void Function::GetEndLineSourceInfo(FileSpec
&source_file
, uint32_t &line_no
) {
301 // The -1 is kind of cheesy, but I want to get the last line entry for the
302 // given function, not the first entry of the next.
303 Address
scratch_addr(GetAddressRange().GetBaseAddress());
304 scratch_addr
.SetOffset(scratch_addr
.GetOffset() +
305 GetAddressRange().GetByteSize() - 1);
307 LineTable
*line_table
= m_comp_unit
->GetLineTable();
308 if (line_table
== nullptr)
311 LineEntry line_entry
;
312 if (line_table
->FindLineEntryByAddress(scratch_addr
, line_entry
, nullptr)) {
313 line_no
= line_entry
.line
;
314 source_file
= line_entry
.file
;
318 llvm::ArrayRef
<std::unique_ptr
<CallEdge
>> Function::GetCallEdges() {
319 std::lock_guard
<std::mutex
> guard(m_call_edges_lock
);
321 if (m_call_edges_resolved
)
324 Log
*log
= GetLog(LLDBLog::Step
);
325 LLDB_LOG(log
, "GetCallEdges: Attempting to parse call site info for {0}",
328 m_call_edges_resolved
= true;
330 // Find the SymbolFile which provided this function's definition.
331 Block
&block
= GetBlock(/*can_create*/true);
332 SymbolFile
*sym_file
= block
.GetSymbolFile();
336 // Lazily read call site information from the SymbolFile.
337 m_call_edges
= sym_file
->ParseCallEdgesInFunction(GetID());
339 // Sort the call edges to speed up return_pc lookups.
340 llvm::sort(m_call_edges
, [](const std::unique_ptr
<CallEdge
> &LHS
,
341 const std::unique_ptr
<CallEdge
> &RHS
) {
342 return LHS
->GetSortKey() < RHS
->GetSortKey();
348 llvm::ArrayRef
<std::unique_ptr
<CallEdge
>> Function::GetTailCallingEdges() {
349 // Tail calling edges are sorted at the end of the list. Find them by dropping
350 // all non-tail-calls.
351 return GetCallEdges().drop_until(
352 [](const std::unique_ptr
<CallEdge
> &edge
) { return edge
->IsTailCall(); });
355 CallEdge
*Function::GetCallEdgeForReturnAddress(addr_t return_pc
,
357 auto edges
= GetCallEdges();
359 llvm::partition_point(edges
, [&](const std::unique_ptr
<CallEdge
> &edge
) {
360 return std::make_pair(edge
->IsTailCall(),
361 edge
->GetReturnPCAddress(*this, target
)) <
362 std::make_pair(false, return_pc
);
364 if (edge_it
== edges
.end() ||
365 edge_it
->get()->GetReturnPCAddress(*this, target
) != return_pc
)
367 return edge_it
->get();
370 Block
&Function::GetBlock(bool can_create
) {
371 if (!m_block
.BlockInfoHasBeenParsed() && can_create
) {
372 ModuleSP module_sp
= CalculateSymbolContextModule();
374 module_sp
->GetSymbolFile()->ParseBlocksRecursive(*this);
376 Debugger::ReportError(llvm::formatv(
377 "unable to find module shared pointer for function '{0}' in {1}",
378 GetName().GetCString(), m_comp_unit
->GetPrimaryFile().GetPath()));
380 m_block
.SetBlockInfoHasBeenParsed(true, true);
385 CompileUnit
*Function::GetCompileUnit() { return m_comp_unit
; }
387 const CompileUnit
*Function::GetCompileUnit() const { return m_comp_unit
; }
389 void Function::GetDescription(Stream
*s
, lldb::DescriptionLevel level
,
391 ConstString name
= GetName();
392 ConstString mangled
= m_mangled
.GetMangledName();
394 *s
<< "id = " << (const UserID
&)*this;
396 s
->AsRawOstream() << ", name = \"" << name
<< '"';
398 s
->AsRawOstream() << ", mangled = \"" << mangled
<< '"';
399 if (level
== eDescriptionLevelVerbose
) {
400 *s
<< ", decl_context = {";
401 auto decl_context
= GetCompilerContext();
402 // Drop the function itself from the context chain.
403 if (decl_context
.size())
404 decl_context
.pop_back();
405 llvm::interleaveComma(decl_context
, *s
, [&](auto &ctx
) { ctx
.Dump(*s
); });
409 Address::DumpStyle fallback_style
;
410 if (level
== eDescriptionLevelVerbose
)
411 fallback_style
= Address::DumpStyleModuleWithFileAddress
;
413 fallback_style
= Address::DumpStyleFileAddress
;
414 GetAddressRange().Dump(s
, target
, Address::DumpStyleLoadAddress
,
418 void Function::Dump(Stream
*s
, bool show_context
) const {
419 s
->Printf("%p: ", static_cast<const void *>(this));
421 *s
<< "Function" << static_cast<const UserID
&>(*this);
426 s
->Printf(", type = %p", static_cast<void *>(m_type
));
427 else if (m_type_uid
!= LLDB_INVALID_UID
)
428 s
->Printf(", type_uid = 0x%8.8" PRIx64
, m_type_uid
);
431 // Dump the root object
432 if (m_block
.BlockInfoHasBeenParsed())
433 m_block
.Dump(s
, m_range
.GetBaseAddress().GetFileAddress(), INT_MAX
,
437 void Function::CalculateSymbolContext(SymbolContext
*sc
) {
439 m_comp_unit
->CalculateSymbolContext(sc
);
442 ModuleSP
Function::CalculateSymbolContextModule() {
443 SectionSP
section_sp(m_range
.GetBaseAddress().GetSection());
445 return section_sp
->GetModule();
447 return this->GetCompileUnit()->GetModule();
450 CompileUnit
*Function::CalculateSymbolContextCompileUnit() {
451 return this->GetCompileUnit();
454 Function
*Function::CalculateSymbolContextFunction() { return this; }
456 lldb::DisassemblerSP
Function::GetInstructions(const ExecutionContext
&exe_ctx
,
458 bool prefer_file_cache
) {
459 ModuleSP
module_sp(GetAddressRange().GetBaseAddress().GetModule());
460 if (module_sp
&& exe_ctx
.HasTargetScope()) {
461 return Disassembler::DisassembleRange(module_sp
->GetArchitecture(), nullptr,
462 flavor
, exe_ctx
.GetTargetRef(),
463 GetAddressRange(), !prefer_file_cache
);
465 return lldb::DisassemblerSP();
468 bool Function::GetDisassembly(const ExecutionContext
&exe_ctx
,
469 const char *flavor
, Stream
&strm
,
470 bool prefer_file_cache
) {
471 lldb::DisassemblerSP disassembler_sp
=
472 GetInstructions(exe_ctx
, flavor
, prefer_file_cache
);
473 if (disassembler_sp
) {
474 const bool show_address
= true;
475 const bool show_bytes
= false;
476 const bool show_control_flow_kind
= false;
477 disassembler_sp
->GetInstructionList().Dump(
478 &strm
, show_address
, show_bytes
, show_control_flow_kind
, &exe_ctx
);
485 // Function::CalculateSymbolContextSymbol ()
487 // return // TODO: find the symbol for the function???
490 void Function::DumpSymbolContext(Stream
*s
) {
491 m_comp_unit
->DumpSymbolContext(s
);
492 s
->Printf(", Function{0x%8.8" PRIx64
"}", GetID());
495 size_t Function::MemorySize() const {
496 size_t mem_size
= sizeof(Function
) + m_block
.MemorySize();
500 bool Function::GetIsOptimized() {
503 // Currently optimization is only indicted by the vendor extension
504 // DW_AT_APPLE_optimized which is set on a compile unit level.
506 result
= m_comp_unit
->GetIsOptimized();
511 bool Function::IsTopLevelFunction() {
514 if (Language
*language
= Language::FindPlugin(GetLanguage()))
515 result
= language
->IsTopLevelFunction(*this);
520 ConstString
Function::GetDisplayName() const {
521 return m_mangled
.GetDisplayDemangledName();
524 CompilerDeclContext
Function::GetDeclContext() {
525 if (ModuleSP module_sp
= CalculateSymbolContextModule())
526 if (SymbolFile
*sym_file
= module_sp
->GetSymbolFile())
527 return sym_file
->GetDeclContextForUID(GetID());
531 std::vector
<CompilerContext
> Function::GetCompilerContext() {
532 if (ModuleSP module_sp
= CalculateSymbolContextModule())
533 if (SymbolFile
*sym_file
= module_sp
->GetSymbolFile())
534 return sym_file
->GetCompilerContextForUID(GetID());
538 Type
*Function::GetType() {
539 if (m_type
== nullptr) {
542 CalculateSymbolContext(&sc
);
547 SymbolFile
*sym_file
= sc
.module_sp
->GetSymbolFile();
549 if (sym_file
== nullptr)
552 m_type
= sym_file
->ResolveTypeUID(m_type_uid
);
557 const Type
*Function::GetType() const { return m_type
; }
559 CompilerType
Function::GetCompilerType() {
560 Type
*function_type
= GetType();
562 return function_type
->GetFullCompilerType();
563 return CompilerType();
566 uint32_t Function::GetPrologueByteSize() {
567 if (m_prologue_byte_size
== 0 &&
568 m_flags
.IsClear(flagsCalculatedPrologueSize
)) {
569 m_flags
.Set(flagsCalculatedPrologueSize
);
570 LineTable
*line_table
= m_comp_unit
->GetLineTable();
571 uint32_t prologue_end_line_idx
= 0;
574 LineEntry first_line_entry
;
575 uint32_t first_line_entry_idx
= UINT32_MAX
;
576 if (line_table
->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(),
578 &first_line_entry_idx
)) {
579 // Make sure the first line entry isn't already the end of the prologue
580 addr_t prologue_end_file_addr
= LLDB_INVALID_ADDRESS
;
581 addr_t line_zero_end_file_addr
= LLDB_INVALID_ADDRESS
;
583 if (first_line_entry
.is_prologue_end
) {
584 prologue_end_file_addr
=
585 first_line_entry
.range
.GetBaseAddress().GetFileAddress();
586 prologue_end_line_idx
= first_line_entry_idx
;
588 // Check the first few instructions and look for one that has
589 // is_prologue_end set to true.
590 const uint32_t last_line_entry_idx
= first_line_entry_idx
+ 6;
591 for (uint32_t idx
= first_line_entry_idx
+ 1;
592 idx
< last_line_entry_idx
; ++idx
) {
593 LineEntry line_entry
;
594 if (line_table
->GetLineEntryAtIndex(idx
, line_entry
)) {
595 if (line_entry
.is_prologue_end
) {
596 prologue_end_file_addr
=
597 line_entry
.range
.GetBaseAddress().GetFileAddress();
598 prologue_end_line_idx
= idx
;
605 // If we didn't find the end of the prologue in the line tables, then
606 // just use the end address of the first line table entry
607 if (prologue_end_file_addr
== LLDB_INVALID_ADDRESS
) {
608 // Check the first few instructions and look for one that has a line
609 // number that's different than the first entry.
610 uint32_t last_line_entry_idx
= first_line_entry_idx
+ 6;
611 for (uint32_t idx
= first_line_entry_idx
+ 1;
612 idx
< last_line_entry_idx
; ++idx
) {
613 LineEntry line_entry
;
614 if (line_table
->GetLineEntryAtIndex(idx
, line_entry
)) {
615 if (line_entry
.line
!= first_line_entry
.line
) {
616 prologue_end_file_addr
=
617 line_entry
.range
.GetBaseAddress().GetFileAddress();
618 prologue_end_line_idx
= idx
;
624 if (prologue_end_file_addr
== LLDB_INVALID_ADDRESS
) {
625 prologue_end_file_addr
=
626 first_line_entry
.range
.GetBaseAddress().GetFileAddress() +
627 first_line_entry
.range
.GetByteSize();
628 prologue_end_line_idx
= first_line_entry_idx
;
632 const addr_t func_start_file_addr
=
633 m_range
.GetBaseAddress().GetFileAddress();
634 const addr_t func_end_file_addr
=
635 func_start_file_addr
+ m_range
.GetByteSize();
637 // Now calculate the offset to pass the subsequent line 0 entries.
638 uint32_t first_non_zero_line
= prologue_end_line_idx
;
640 LineEntry line_entry
;
641 if (line_table
->GetLineEntryAtIndex(first_non_zero_line
,
643 if (line_entry
.line
!= 0)
646 if (line_entry
.range
.GetBaseAddress().GetFileAddress() >=
650 first_non_zero_line
++;
653 if (first_non_zero_line
> prologue_end_line_idx
) {
654 LineEntry first_non_zero_entry
;
655 if (line_table
->GetLineEntryAtIndex(first_non_zero_line
,
656 first_non_zero_entry
)) {
657 line_zero_end_file_addr
=
658 first_non_zero_entry
.range
.GetBaseAddress().GetFileAddress();
662 // Verify that this prologue end file address in the function's address
663 // range just to be sure
664 if (func_start_file_addr
< prologue_end_file_addr
&&
665 prologue_end_file_addr
< func_end_file_addr
) {
666 m_prologue_byte_size
= prologue_end_file_addr
- func_start_file_addr
;
669 if (prologue_end_file_addr
< line_zero_end_file_addr
&&
670 line_zero_end_file_addr
< func_end_file_addr
) {
671 m_prologue_byte_size
+=
672 line_zero_end_file_addr
- prologue_end_file_addr
;
678 return m_prologue_byte_size
;
681 lldb::LanguageType
Function::GetLanguage() const {
682 lldb::LanguageType lang
= m_mangled
.GuessLanguage();
683 if (lang
!= lldb::eLanguageTypeUnknown
)
687 return m_comp_unit
->GetLanguage();
689 return lldb::eLanguageTypeUnknown
;
692 ConstString
Function::GetName() const {
693 return m_mangled
.GetName();
696 ConstString
Function::GetNameNoArguments() const {
697 return m_mangled
.GetName(Mangled::ePreferDemangledWithoutArguments
);