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/Disassembler.h"
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/ModuleList.h"
13 #include "lldb/Core/Section.h"
14 #include "lldb/Host/Host.h"
15 #include "lldb/Symbol/CompileUnit.h"
16 #include "lldb/Symbol/CompilerType.h"
17 #include "lldb/Symbol/LineTable.h"
18 #include "lldb/Symbol/SymbolFile.h"
19 #include "lldb/Target/Language.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Utility/Log.h"
22 #include "llvm/Support/Casting.h"
25 using namespace lldb_private
;
27 // Basic function information is contained in the FunctionInfo class. It is
28 // designed to contain the name, linkage name, and declaration location.
29 FunctionInfo::FunctionInfo(const char *name
, const Declaration
*decl_ptr
)
30 : m_name(name
), m_declaration(decl_ptr
) {}
32 FunctionInfo::FunctionInfo(ConstString name
, const Declaration
*decl_ptr
)
33 : m_name(name
), m_declaration(decl_ptr
) {}
35 FunctionInfo::~FunctionInfo() = default;
37 void FunctionInfo::Dump(Stream
*s
, bool show_fullpaths
) const {
39 *s
<< ", name = \"" << m_name
<< "\"";
40 m_declaration
.Dump(s
, show_fullpaths
);
43 int FunctionInfo::Compare(const FunctionInfo
&a
, const FunctionInfo
&b
) {
44 int result
= ConstString::Compare(a
.GetName(), b
.GetName());
48 return Declaration::Compare(a
.m_declaration
, b
.m_declaration
);
51 Declaration
&FunctionInfo::GetDeclaration() { return m_declaration
; }
53 const Declaration
&FunctionInfo::GetDeclaration() const {
57 ConstString
FunctionInfo::GetName() const { return m_name
; }
59 size_t FunctionInfo::MemorySize() const {
60 return m_name
.MemorySize() + m_declaration
.MemorySize();
63 InlineFunctionInfo::InlineFunctionInfo(const char *name
,
64 llvm::StringRef mangled
,
65 const Declaration
*decl_ptr
,
66 const Declaration
*call_decl_ptr
)
67 : FunctionInfo(name
, decl_ptr
), m_mangled(mangled
),
68 m_call_decl(call_decl_ptr
) {}
70 InlineFunctionInfo::InlineFunctionInfo(ConstString name
,
71 const Mangled
&mangled
,
72 const Declaration
*decl_ptr
,
73 const Declaration
*call_decl_ptr
)
74 : FunctionInfo(name
, decl_ptr
), m_mangled(mangled
),
75 m_call_decl(call_decl_ptr
) {}
77 InlineFunctionInfo::~InlineFunctionInfo() = default;
79 void InlineFunctionInfo::Dump(Stream
*s
, bool show_fullpaths
) const {
80 FunctionInfo::Dump(s
, show_fullpaths
);
85 void InlineFunctionInfo::DumpStopContext(Stream
*s
) const {
86 // s->Indent("[inlined] ");
89 s
->PutCString(m_mangled
.GetName().AsCString());
91 s
->PutCString(m_name
.AsCString());
94 ConstString
InlineFunctionInfo::GetName() const {
96 return m_mangled
.GetName();
100 ConstString
InlineFunctionInfo::GetDisplayName() const {
102 return m_mangled
.GetDisplayDemangledName();
106 Declaration
&InlineFunctionInfo::GetCallSite() { return m_call_decl
; }
108 const Declaration
&InlineFunctionInfo::GetCallSite() const {
112 Mangled
&InlineFunctionInfo::GetMangled() { return m_mangled
; }
114 const Mangled
&InlineFunctionInfo::GetMangled() const { return m_mangled
; }
116 size_t InlineFunctionInfo::MemorySize() const {
117 return FunctionInfo::MemorySize() + m_mangled
.MemorySize();
120 /// @name Call site related structures
123 lldb::addr_t
CallEdge::GetLoadAddress(lldb::addr_t unresolved_pc
,
124 Function
&caller
, Target
&target
) {
125 Log
*log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP
));
127 const Address
&caller_start_addr
= caller
.GetAddressRange().GetBaseAddress();
129 ModuleSP caller_module_sp
= caller_start_addr
.GetModule();
130 if (!caller_module_sp
) {
131 LLDB_LOG(log
, "GetLoadAddress: cannot get Module for caller");
132 return LLDB_INVALID_ADDRESS
;
135 SectionList
*section_list
= caller_module_sp
->GetSectionList();
137 LLDB_LOG(log
, "GetLoadAddress: cannot get SectionList for Module");
138 return LLDB_INVALID_ADDRESS
;
141 Address the_addr
= Address(unresolved_pc
, section_list
);
142 lldb::addr_t load_addr
= the_addr
.GetLoadAddress(&target
);
146 lldb::addr_t
CallEdge::GetReturnPCAddress(Function
&caller
,
147 Target
&target
) const {
148 return GetLoadAddress(GetUnresolvedReturnPCAddress(), caller
, target
);
151 void DirectCallEdge::ParseSymbolFileAndResolve(ModuleList
&images
) {
155 Log
*log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP
));
156 LLDB_LOG(log
, "DirectCallEdge: Lazily parsing the call graph for {0}",
157 lazy_callee
.symbol_name
);
159 auto resolve_lazy_callee
= [&]() -> Function
* {
160 ConstString callee_name
{lazy_callee
.symbol_name
};
161 SymbolContextList sc_list
;
162 images
.FindFunctionSymbols(callee_name
, eFunctionNameTypeAuto
, sc_list
);
163 size_t num_matches
= sc_list
.GetSize();
164 if (num_matches
== 0 || !sc_list
[0].symbol
) {
166 "DirectCallEdge: Found no symbols for {0}, cannot resolve it",
170 Address callee_addr
= sc_list
[0].symbol
->GetAddress();
171 if (!callee_addr
.IsValid()) {
172 LLDB_LOG(log
, "DirectCallEdge: Invalid symbol address");
175 Function
*f
= callee_addr
.CalculateSymbolContextFunction();
177 LLDB_LOG(log
, "DirectCallEdge: Could not find complete function");
182 lazy_callee
.def
= resolve_lazy_callee();
186 Function
*DirectCallEdge::GetCallee(ModuleList
&images
, ExecutionContext
&) {
187 ParseSymbolFileAndResolve(images
);
188 assert(resolved
&& "Did not resolve lazy callee");
189 return lazy_callee
.def
;
192 Function
*IndirectCallEdge::GetCallee(ModuleList
&images
,
193 ExecutionContext
&exe_ctx
) {
194 Log
*log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP
));
196 Value callee_addr_val
;
197 if (!call_target
.Evaluate(&exe_ctx
, exe_ctx
.GetRegisterContext(),
198 /*loclist_base_load_addr=*/LLDB_INVALID_ADDRESS
,
199 /*initial_value_ptr=*/nullptr,
200 /*object_address_ptr=*/nullptr, callee_addr_val
,
202 LLDB_LOGF(log
, "IndirectCallEdge: Could not evaluate expression: %s",
207 addr_t raw_addr
= callee_addr_val
.GetScalar().ULongLong(LLDB_INVALID_ADDRESS
);
208 if (raw_addr
== LLDB_INVALID_ADDRESS
) {
209 LLDB_LOG(log
, "IndirectCallEdge: Could not extract address from scalar");
214 if (!exe_ctx
.GetTargetPtr()->ResolveLoadAddress(raw_addr
, callee_addr
)) {
215 LLDB_LOG(log
, "IndirectCallEdge: Could not resolve callee's load address");
219 Function
*f
= callee_addr
.CalculateSymbolContextFunction();
221 LLDB_LOG(log
, "IndirectCallEdge: Could not find complete function");
231 Function::Function(CompileUnit
*comp_unit
, lldb::user_id_t func_uid
,
232 lldb::user_id_t type_uid
, const Mangled
&mangled
, Type
*type
,
233 const AddressRange
&range
)
234 : UserID(func_uid
), m_comp_unit(comp_unit
), m_type_uid(type_uid
),
235 m_type(type
), m_mangled(mangled
), m_block(func_uid
), m_range(range
),
236 m_frame_base(), m_flags(), m_prologue_byte_size(0) {
237 m_block
.SetParentScope(this);
238 assert(comp_unit
!= nullptr);
241 Function::~Function() = default;
243 void Function::GetStartLineSourceInfo(FileSpec
&source_file
,
248 if (m_comp_unit
== nullptr)
251 // Initialize m_type if it hasn't been initialized already
254 if (m_type
!= nullptr && m_type
->GetDeclaration().GetLine() != 0) {
255 source_file
= m_type
->GetDeclaration().GetFile();
256 line_no
= m_type
->GetDeclaration().GetLine();
258 LineTable
*line_table
= m_comp_unit
->GetLineTable();
259 if (line_table
== nullptr)
262 LineEntry line_entry
;
263 if (line_table
->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(),
264 line_entry
, nullptr)) {
265 line_no
= line_entry
.line
;
266 source_file
= line_entry
.file
;
271 void Function::GetEndLineSourceInfo(FileSpec
&source_file
, uint32_t &line_no
) {
275 // The -1 is kind of cheesy, but I want to get the last line entry for the
276 // given function, not the first entry of the next.
277 Address
scratch_addr(GetAddressRange().GetBaseAddress());
278 scratch_addr
.SetOffset(scratch_addr
.GetOffset() +
279 GetAddressRange().GetByteSize() - 1);
281 LineTable
*line_table
= m_comp_unit
->GetLineTable();
282 if (line_table
== nullptr)
285 LineEntry line_entry
;
286 if (line_table
->FindLineEntryByAddress(scratch_addr
, line_entry
, nullptr)) {
287 line_no
= line_entry
.line
;
288 source_file
= line_entry
.file
;
292 llvm::ArrayRef
<std::unique_ptr
<CallEdge
>> Function::GetCallEdges() {
293 std::lock_guard
<std::mutex
> guard(m_call_edges_lock
);
295 if (m_call_edges_resolved
)
298 Log
*log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP
));
299 LLDB_LOG(log
, "GetCallEdges: Attempting to parse call site info for {0}",
302 m_call_edges_resolved
= true;
304 // Find the SymbolFile which provided this function's definition.
305 Block
&block
= GetBlock(/*can_create*/true);
306 SymbolFile
*sym_file
= block
.GetSymbolFile();
310 // Lazily read call site information from the SymbolFile.
311 m_call_edges
= sym_file
->ParseCallEdgesInFunction(GetID());
313 // Sort the call edges to speed up return_pc lookups.
314 llvm::sort(m_call_edges
, [](const std::unique_ptr
<CallEdge
> &LHS
,
315 const std::unique_ptr
<CallEdge
> &RHS
) {
316 return LHS
->GetSortKey() < RHS
->GetSortKey();
322 llvm::ArrayRef
<std::unique_ptr
<CallEdge
>> Function::GetTailCallingEdges() {
323 // Tail calling edges are sorted at the end of the list. Find them by dropping
324 // all non-tail-calls.
325 return GetCallEdges().drop_until(
326 [](const std::unique_ptr
<CallEdge
> &edge
) { return edge
->IsTailCall(); });
329 CallEdge
*Function::GetCallEdgeForReturnAddress(addr_t return_pc
,
331 auto edges
= GetCallEdges();
333 llvm::partition_point(edges
, [&](const std::unique_ptr
<CallEdge
> &edge
) {
334 return std::make_pair(edge
->IsTailCall(),
335 edge
->GetReturnPCAddress(*this, target
)) <
336 std::make_pair(false, return_pc
);
338 if (edge_it
== edges
.end() ||
339 edge_it
->get()->GetReturnPCAddress(*this, target
) != return_pc
)
341 return edge_it
->get();
344 Block
&Function::GetBlock(bool can_create
) {
345 if (!m_block
.BlockInfoHasBeenParsed() && can_create
) {
346 ModuleSP module_sp
= CalculateSymbolContextModule();
348 module_sp
->GetSymbolFile()->ParseBlocksRecursive(*this);
350 Host::SystemLog(Host::eSystemLogError
,
351 "error: unable to find module "
352 "shared pointer for function '%s' "
354 GetName().GetCString(),
355 m_comp_unit
->GetPrimaryFile().GetPath().c_str());
357 m_block
.SetBlockInfoHasBeenParsed(true, true);
362 CompileUnit
*Function::GetCompileUnit() { return m_comp_unit
; }
364 const CompileUnit
*Function::GetCompileUnit() const { return m_comp_unit
; }
366 void Function::GetDescription(Stream
*s
, lldb::DescriptionLevel level
,
368 ConstString name
= GetName();
369 ConstString mangled
= m_mangled
.GetMangledName();
371 *s
<< "id = " << (const UserID
&)*this;
373 s
->AsRawOstream() << ", name = \"" << name
<< '"';
375 s
->AsRawOstream() << ", mangled = \"" << mangled
<< '"';
377 Address::DumpStyle fallback_style
;
378 if (level
== eDescriptionLevelVerbose
)
379 fallback_style
= Address::DumpStyleModuleWithFileAddress
;
381 fallback_style
= Address::DumpStyleFileAddress
;
382 GetAddressRange().Dump(s
, target
, Address::DumpStyleLoadAddress
,
386 void Function::Dump(Stream
*s
, bool show_context
) const {
387 s
->Printf("%p: ", static_cast<const void *>(this));
389 *s
<< "Function" << static_cast<const UserID
&>(*this);
394 s
->Printf(", type = %p", static_cast<void *>(m_type
));
395 else if (m_type_uid
!= LLDB_INVALID_UID
)
396 s
->Printf(", type_uid = 0x%8.8" PRIx64
, m_type_uid
);
399 // Dump the root object
400 if (m_block
.BlockInfoHasBeenParsed())
401 m_block
.Dump(s
, m_range
.GetBaseAddress().GetFileAddress(), INT_MAX
,
405 void Function::CalculateSymbolContext(SymbolContext
*sc
) {
407 m_comp_unit
->CalculateSymbolContext(sc
);
410 ModuleSP
Function::CalculateSymbolContextModule() {
411 SectionSP
section_sp(m_range
.GetBaseAddress().GetSection());
413 return section_sp
->GetModule();
415 return this->GetCompileUnit()->GetModule();
418 CompileUnit
*Function::CalculateSymbolContextCompileUnit() {
419 return this->GetCompileUnit();
422 Function
*Function::CalculateSymbolContextFunction() { return this; }
424 lldb::DisassemblerSP
Function::GetInstructions(const ExecutionContext
&exe_ctx
,
426 bool prefer_file_cache
) {
427 ModuleSP
module_sp(GetAddressRange().GetBaseAddress().GetModule());
428 if (module_sp
&& exe_ctx
.HasTargetScope()) {
429 return Disassembler::DisassembleRange(module_sp
->GetArchitecture(), nullptr,
430 flavor
, exe_ctx
.GetTargetRef(),
431 GetAddressRange(), !prefer_file_cache
);
433 return lldb::DisassemblerSP();
436 bool Function::GetDisassembly(const ExecutionContext
&exe_ctx
,
437 const char *flavor
, Stream
&strm
,
438 bool prefer_file_cache
) {
439 lldb::DisassemblerSP disassembler_sp
=
440 GetInstructions(exe_ctx
, flavor
, prefer_file_cache
);
441 if (disassembler_sp
) {
442 const bool show_address
= true;
443 const bool show_bytes
= false;
444 disassembler_sp
->GetInstructionList().Dump(&strm
, show_address
, show_bytes
,
452 // Function::CalculateSymbolContextSymbol ()
454 // return // TODO: find the symbol for the function???
457 void Function::DumpSymbolContext(Stream
*s
) {
458 m_comp_unit
->DumpSymbolContext(s
);
459 s
->Printf(", Function{0x%8.8" PRIx64
"}", GetID());
462 size_t Function::MemorySize() const {
463 size_t mem_size
= sizeof(Function
) + m_block
.MemorySize();
467 bool Function::GetIsOptimized() {
470 // Currently optimization is only indicted by the vendor extension
471 // DW_AT_APPLE_optimized which is set on a compile unit level.
473 result
= m_comp_unit
->GetIsOptimized();
478 bool Function::IsTopLevelFunction() {
481 if (Language
*language
= Language::FindPlugin(GetLanguage()))
482 result
= language
->IsTopLevelFunction(*this);
487 ConstString
Function::GetDisplayName() const {
488 return m_mangled
.GetDisplayDemangledName();
491 CompilerDeclContext
Function::GetDeclContext() {
492 ModuleSP module_sp
= CalculateSymbolContextModule();
495 if (SymbolFile
*sym_file
= module_sp
->GetSymbolFile())
496 return sym_file
->GetDeclContextForUID(GetID());
498 return CompilerDeclContext();
501 Type
*Function::GetType() {
502 if (m_type
== nullptr) {
505 CalculateSymbolContext(&sc
);
510 SymbolFile
*sym_file
= sc
.module_sp
->GetSymbolFile();
512 if (sym_file
== nullptr)
515 m_type
= sym_file
->ResolveTypeUID(m_type_uid
);
520 const Type
*Function::GetType() const { return m_type
; }
522 CompilerType
Function::GetCompilerType() {
523 Type
*function_type
= GetType();
525 return function_type
->GetFullCompilerType();
526 return CompilerType();
529 uint32_t Function::GetPrologueByteSize() {
530 if (m_prologue_byte_size
== 0 &&
531 m_flags
.IsClear(flagsCalculatedPrologueSize
)) {
532 m_flags
.Set(flagsCalculatedPrologueSize
);
533 LineTable
*line_table
= m_comp_unit
->GetLineTable();
534 uint32_t prologue_end_line_idx
= 0;
537 LineEntry first_line_entry
;
538 uint32_t first_line_entry_idx
= UINT32_MAX
;
539 if (line_table
->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(),
541 &first_line_entry_idx
)) {
542 // Make sure the first line entry isn't already the end of the prologue
543 addr_t prologue_end_file_addr
= LLDB_INVALID_ADDRESS
;
544 addr_t line_zero_end_file_addr
= LLDB_INVALID_ADDRESS
;
546 if (first_line_entry
.is_prologue_end
) {
547 prologue_end_file_addr
=
548 first_line_entry
.range
.GetBaseAddress().GetFileAddress();
549 prologue_end_line_idx
= first_line_entry_idx
;
551 // Check the first few instructions and look for one that has
552 // is_prologue_end set to true.
553 const uint32_t last_line_entry_idx
= first_line_entry_idx
+ 6;
554 for (uint32_t idx
= first_line_entry_idx
+ 1;
555 idx
< last_line_entry_idx
; ++idx
) {
556 LineEntry line_entry
;
557 if (line_table
->GetLineEntryAtIndex(idx
, line_entry
)) {
558 if (line_entry
.is_prologue_end
) {
559 prologue_end_file_addr
=
560 line_entry
.range
.GetBaseAddress().GetFileAddress();
561 prologue_end_line_idx
= idx
;
568 // If we didn't find the end of the prologue in the line tables, then
569 // just use the end address of the first line table entry
570 if (prologue_end_file_addr
== LLDB_INVALID_ADDRESS
) {
571 // Check the first few instructions and look for one that has a line
572 // number that's different than the first entry.
573 uint32_t last_line_entry_idx
= first_line_entry_idx
+ 6;
574 for (uint32_t idx
= first_line_entry_idx
+ 1;
575 idx
< last_line_entry_idx
; ++idx
) {
576 LineEntry line_entry
;
577 if (line_table
->GetLineEntryAtIndex(idx
, line_entry
)) {
578 if (line_entry
.line
!= first_line_entry
.line
) {
579 prologue_end_file_addr
=
580 line_entry
.range
.GetBaseAddress().GetFileAddress();
581 prologue_end_line_idx
= idx
;
587 if (prologue_end_file_addr
== LLDB_INVALID_ADDRESS
) {
588 prologue_end_file_addr
=
589 first_line_entry
.range
.GetBaseAddress().GetFileAddress() +
590 first_line_entry
.range
.GetByteSize();
591 prologue_end_line_idx
= first_line_entry_idx
;
595 const addr_t func_start_file_addr
=
596 m_range
.GetBaseAddress().GetFileAddress();
597 const addr_t func_end_file_addr
=
598 func_start_file_addr
+ m_range
.GetByteSize();
600 // Now calculate the offset to pass the subsequent line 0 entries.
601 uint32_t first_non_zero_line
= prologue_end_line_idx
;
603 LineEntry line_entry
;
604 if (line_table
->GetLineEntryAtIndex(first_non_zero_line
,
606 if (line_entry
.line
!= 0)
609 if (line_entry
.range
.GetBaseAddress().GetFileAddress() >=
613 first_non_zero_line
++;
616 if (first_non_zero_line
> prologue_end_line_idx
) {
617 LineEntry first_non_zero_entry
;
618 if (line_table
->GetLineEntryAtIndex(first_non_zero_line
,
619 first_non_zero_entry
)) {
620 line_zero_end_file_addr
=
621 first_non_zero_entry
.range
.GetBaseAddress().GetFileAddress();
625 // Verify that this prologue end file address in the function's address
626 // range just to be sure
627 if (func_start_file_addr
< prologue_end_file_addr
&&
628 prologue_end_file_addr
< func_end_file_addr
) {
629 m_prologue_byte_size
= prologue_end_file_addr
- func_start_file_addr
;
632 if (prologue_end_file_addr
< line_zero_end_file_addr
&&
633 line_zero_end_file_addr
< func_end_file_addr
) {
634 m_prologue_byte_size
+=
635 line_zero_end_file_addr
- prologue_end_file_addr
;
641 return m_prologue_byte_size
;
644 lldb::LanguageType
Function::GetLanguage() const {
645 lldb::LanguageType lang
= m_mangled
.GuessLanguage();
646 if (lang
!= lldb::eLanguageTypeUnknown
)
650 return m_comp_unit
->GetLanguage();
652 return lldb::eLanguageTypeUnknown
;
655 ConstString
Function::GetName() const {
656 return m_mangled
.GetName();
659 ConstString
Function::GetNameNoArguments() const {
660 return m_mangled
.GetName(Mangled::ePreferDemangledWithoutArguments
);