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 llvm::Expected
<Value
> callee_addr_val
= call_target
.Evaluate(
224 &exe_ctx
, exe_ctx
.GetRegisterContext(), LLDB_INVALID_ADDRESS
,
225 /*initial_value_ptr=*/nullptr,
226 /*object_address_ptr=*/nullptr);
227 if (!callee_addr_val
) {
228 LLDB_LOG_ERROR(log
, callee_addr_val
.takeError(),
229 "IndirectCallEdge: Could not evaluate expression: {0}");
234 callee_addr_val
->GetScalar().ULongLong(LLDB_INVALID_ADDRESS
);
235 if (raw_addr
== LLDB_INVALID_ADDRESS
) {
236 LLDB_LOG(log
, "IndirectCallEdge: Could not extract address from scalar");
241 if (!exe_ctx
.GetTargetPtr()->ResolveLoadAddress(raw_addr
, callee_addr
)) {
242 LLDB_LOG(log
, "IndirectCallEdge: Could not resolve callee's load address");
246 Function
*f
= callee_addr
.CalculateSymbolContextFunction();
248 LLDB_LOG(log
, "IndirectCallEdge: Could not find complete function");
257 AddressRange
CollapseRanges(llvm::ArrayRef
<AddressRange
> ranges
) {
259 return AddressRange();
260 if (ranges
.size() == 1)
263 Address lowest_addr
= ranges
[0].GetBaseAddress();
264 addr_t highest_addr
= lowest_addr
.GetFileAddress() + ranges
[0].GetByteSize();
265 for (const AddressRange
&range
: ranges
.drop_front()) {
266 Address range_begin
= range
.GetBaseAddress();
267 addr_t range_end
= range_begin
.GetFileAddress() + range
.GetByteSize();
268 if (range_begin
.GetFileAddress() < lowest_addr
.GetFileAddress())
269 lowest_addr
= range_begin
;
270 if (range_end
> highest_addr
)
271 highest_addr
= range_end
;
273 return AddressRange(lowest_addr
, highest_addr
- lowest_addr
.GetFileAddress());
277 Function::Function(CompileUnit
*comp_unit
, lldb::user_id_t func_uid
,
278 lldb::user_id_t type_uid
, const Mangled
&mangled
, Type
*type
,
279 AddressRanges ranges
)
280 : UserID(func_uid
), m_comp_unit(comp_unit
), m_type_uid(type_uid
),
281 m_type(type
), m_mangled(mangled
), m_block(func_uid
),
282 m_ranges(std::move(ranges
)), m_range(CollapseRanges(m_ranges
)),
283 m_frame_base(), m_flags(), m_prologue_byte_size(0) {
284 m_block
.SetParentScope(this);
285 assert(comp_unit
!= nullptr);
288 Function::~Function() = default;
290 void Function::GetStartLineSourceInfo(SupportFileSP
&source_file_sp
,
293 source_file_sp
.reset();
295 if (m_comp_unit
== nullptr)
298 // Initialize m_type if it hasn't been initialized already
301 if (m_type
!= nullptr && m_type
->GetDeclaration().GetLine() != 0) {
303 std::make_shared
<SupportFile
>(m_type
->GetDeclaration().GetFile());
304 line_no
= m_type
->GetDeclaration().GetLine();
306 LineTable
*line_table
= m_comp_unit
->GetLineTable();
307 if (line_table
== nullptr)
310 LineEntry line_entry
;
311 if (line_table
->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(),
312 line_entry
, nullptr)) {
313 line_no
= line_entry
.line
;
314 source_file_sp
= line_entry
.file_sp
;
319 void Function::GetEndLineSourceInfo(FileSpec
&source_file
, uint32_t &line_no
) {
323 // The -1 is kind of cheesy, but I want to get the last line entry for the
324 // given function, not the first entry of the next.
325 Address
scratch_addr(GetAddressRange().GetBaseAddress());
326 scratch_addr
.SetOffset(scratch_addr
.GetOffset() +
327 GetAddressRange().GetByteSize() - 1);
329 LineTable
*line_table
= m_comp_unit
->GetLineTable();
330 if (line_table
== nullptr)
333 LineEntry line_entry
;
334 if (line_table
->FindLineEntryByAddress(scratch_addr
, line_entry
, nullptr)) {
335 line_no
= line_entry
.line
;
336 source_file
= line_entry
.GetFile();
340 llvm::ArrayRef
<std::unique_ptr
<CallEdge
>> Function::GetCallEdges() {
341 std::lock_guard
<std::mutex
> guard(m_call_edges_lock
);
343 if (m_call_edges_resolved
)
346 Log
*log
= GetLog(LLDBLog::Step
);
347 LLDB_LOG(log
, "GetCallEdges: Attempting to parse call site info for {0}",
350 m_call_edges_resolved
= true;
352 // Find the SymbolFile which provided this function's definition.
353 Block
&block
= GetBlock(/*can_create*/true);
354 SymbolFile
*sym_file
= block
.GetSymbolFile();
358 // Lazily read call site information from the SymbolFile.
359 m_call_edges
= sym_file
->ParseCallEdgesInFunction(GetID());
361 // Sort the call edges to speed up return_pc lookups.
362 llvm::sort(m_call_edges
, [](const std::unique_ptr
<CallEdge
> &LHS
,
363 const std::unique_ptr
<CallEdge
> &RHS
) {
364 return LHS
->GetSortKey() < RHS
->GetSortKey();
370 llvm::ArrayRef
<std::unique_ptr
<CallEdge
>> Function::GetTailCallingEdges() {
371 // Tail calling edges are sorted at the end of the list. Find them by dropping
372 // all non-tail-calls.
373 return GetCallEdges().drop_until(
374 [](const std::unique_ptr
<CallEdge
> &edge
) { return edge
->IsTailCall(); });
377 CallEdge
*Function::GetCallEdgeForReturnAddress(addr_t return_pc
,
379 auto edges
= GetCallEdges();
381 llvm::partition_point(edges
, [&](const std::unique_ptr
<CallEdge
> &edge
) {
382 return std::make_pair(edge
->IsTailCall(),
383 edge
->GetReturnPCAddress(*this, target
)) <
384 std::make_pair(false, return_pc
);
386 if (edge_it
== edges
.end() ||
387 edge_it
->get()->GetReturnPCAddress(*this, target
) != return_pc
)
389 return edge_it
->get();
392 Block
&Function::GetBlock(bool can_create
) {
393 if (!m_block
.BlockInfoHasBeenParsed() && can_create
) {
394 ModuleSP module_sp
= CalculateSymbolContextModule();
396 module_sp
->GetSymbolFile()->ParseBlocksRecursive(*this);
398 Debugger::ReportError(llvm::formatv(
399 "unable to find module shared pointer for function '{0}' in {1}",
400 GetName().GetCString(), m_comp_unit
->GetPrimaryFile().GetPath()));
402 m_block
.SetBlockInfoHasBeenParsed(true, true);
407 CompileUnit
*Function::GetCompileUnit() { return m_comp_unit
; }
409 const CompileUnit
*Function::GetCompileUnit() const { return m_comp_unit
; }
411 void Function::GetDescription(Stream
*s
, lldb::DescriptionLevel level
,
413 ConstString name
= GetName();
414 ConstString mangled
= m_mangled
.GetMangledName();
416 *s
<< "id = " << (const UserID
&)*this;
418 s
->AsRawOstream() << ", name = \"" << name
<< '"';
420 s
->AsRawOstream() << ", mangled = \"" << mangled
<< '"';
421 if (level
== eDescriptionLevelVerbose
) {
422 *s
<< ", decl_context = {";
423 auto decl_context
= GetCompilerContext();
424 // Drop the function itself from the context chain.
425 if (decl_context
.size())
426 decl_context
.pop_back();
427 llvm::interleaveComma(decl_context
, *s
, [&](auto &ctx
) { ctx
.Dump(*s
); });
430 *s
<< ", range" << (m_ranges
.size() > 1 ? "s" : "") << " = ";
431 Address::DumpStyle fallback_style
=
432 level
== eDescriptionLevelVerbose
433 ? Address::DumpStyleModuleWithFileAddress
434 : Address::DumpStyleFileAddress
;
435 for (const AddressRange
&range
: m_ranges
)
436 range
.Dump(s
, target
, Address::DumpStyleLoadAddress
, fallback_style
);
439 void Function::Dump(Stream
*s
, bool show_context
) const {
440 s
->Printf("%p: ", static_cast<const void *>(this));
442 *s
<< "Function" << static_cast<const UserID
&>(*this);
447 s
->Printf(", type = %p", static_cast<void *>(m_type
));
448 else if (m_type_uid
!= LLDB_INVALID_UID
)
449 s
->Printf(", type_uid = 0x%8.8" PRIx64
, m_type_uid
);
452 // Dump the root object
453 if (m_block
.BlockInfoHasBeenParsed())
454 m_block
.Dump(s
, m_range
.GetBaseAddress().GetFileAddress(), INT_MAX
,
458 void Function::CalculateSymbolContext(SymbolContext
*sc
) {
460 m_comp_unit
->CalculateSymbolContext(sc
);
463 ModuleSP
Function::CalculateSymbolContextModule() {
464 SectionSP
section_sp(m_range
.GetBaseAddress().GetSection());
466 return section_sp
->GetModule();
468 return this->GetCompileUnit()->GetModule();
471 CompileUnit
*Function::CalculateSymbolContextCompileUnit() {
472 return this->GetCompileUnit();
475 Function
*Function::CalculateSymbolContextFunction() { return this; }
477 lldb::DisassemblerSP
Function::GetInstructions(const ExecutionContext
&exe_ctx
,
479 bool prefer_file_cache
) {
480 ModuleSP
module_sp(GetAddressRange().GetBaseAddress().GetModule());
481 if (module_sp
&& exe_ctx
.HasTargetScope()) {
482 return Disassembler::DisassembleRange(
483 module_sp
->GetArchitecture(), nullptr, nullptr, nullptr, flavor
,
484 exe_ctx
.GetTargetRef(), GetAddressRange(), !prefer_file_cache
);
486 return lldb::DisassemblerSP();
489 bool Function::GetDisassembly(const ExecutionContext
&exe_ctx
,
490 const char *flavor
, Stream
&strm
,
491 bool prefer_file_cache
) {
492 lldb::DisassemblerSP disassembler_sp
=
493 GetInstructions(exe_ctx
, flavor
, prefer_file_cache
);
494 if (disassembler_sp
) {
495 const bool show_address
= true;
496 const bool show_bytes
= false;
497 const bool show_control_flow_kind
= false;
498 disassembler_sp
->GetInstructionList().Dump(
499 &strm
, show_address
, show_bytes
, show_control_flow_kind
, &exe_ctx
);
506 // Function::CalculateSymbolContextSymbol ()
508 // return // TODO: find the symbol for the function???
511 void Function::DumpSymbolContext(Stream
*s
) {
512 m_comp_unit
->DumpSymbolContext(s
);
513 s
->Printf(", Function{0x%8.8" PRIx64
"}", GetID());
516 size_t Function::MemorySize() const {
517 size_t mem_size
= sizeof(Function
) + m_block
.MemorySize();
521 bool Function::GetIsOptimized() {
524 // Currently optimization is only indicted by the vendor extension
525 // DW_AT_APPLE_optimized which is set on a compile unit level.
527 result
= m_comp_unit
->GetIsOptimized();
532 bool Function::IsTopLevelFunction() {
535 if (Language
*language
= Language::FindPlugin(GetLanguage()))
536 result
= language
->IsTopLevelFunction(*this);
541 ConstString
Function::GetDisplayName() const {
542 return m_mangled
.GetDisplayDemangledName();
545 CompilerDeclContext
Function::GetDeclContext() {
546 if (ModuleSP module_sp
= CalculateSymbolContextModule())
547 if (SymbolFile
*sym_file
= module_sp
->GetSymbolFile())
548 return sym_file
->GetDeclContextForUID(GetID());
552 std::vector
<CompilerContext
> Function::GetCompilerContext() {
553 if (ModuleSP module_sp
= CalculateSymbolContextModule())
554 if (SymbolFile
*sym_file
= module_sp
->GetSymbolFile())
555 return sym_file
->GetCompilerContextForUID(GetID());
559 Type
*Function::GetType() {
560 if (m_type
== nullptr) {
563 CalculateSymbolContext(&sc
);
568 SymbolFile
*sym_file
= sc
.module_sp
->GetSymbolFile();
570 if (sym_file
== nullptr)
573 m_type
= sym_file
->ResolveTypeUID(m_type_uid
);
578 const Type
*Function::GetType() const { return m_type
; }
580 CompilerType
Function::GetCompilerType() {
581 Type
*function_type
= GetType();
583 return function_type
->GetFullCompilerType();
584 return CompilerType();
587 uint32_t Function::GetPrologueByteSize() {
588 if (m_prologue_byte_size
== 0 &&
589 m_flags
.IsClear(flagsCalculatedPrologueSize
)) {
590 m_flags
.Set(flagsCalculatedPrologueSize
);
591 LineTable
*line_table
= m_comp_unit
->GetLineTable();
592 uint32_t prologue_end_line_idx
= 0;
595 LineEntry first_line_entry
;
596 uint32_t first_line_entry_idx
= UINT32_MAX
;
597 if (line_table
->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(),
599 &first_line_entry_idx
)) {
600 // Make sure the first line entry isn't already the end of the prologue
601 addr_t prologue_end_file_addr
= LLDB_INVALID_ADDRESS
;
602 addr_t line_zero_end_file_addr
= LLDB_INVALID_ADDRESS
;
604 if (first_line_entry
.is_prologue_end
) {
605 prologue_end_file_addr
=
606 first_line_entry
.range
.GetBaseAddress().GetFileAddress();
607 prologue_end_line_idx
= first_line_entry_idx
;
609 // Check the first few instructions and look for one that has
610 // is_prologue_end set to true.
611 const uint32_t last_line_entry_idx
= first_line_entry_idx
+ 6;
612 for (uint32_t idx
= first_line_entry_idx
+ 1;
613 idx
< last_line_entry_idx
; ++idx
) {
614 LineEntry line_entry
;
615 if (line_table
->GetLineEntryAtIndex(idx
, line_entry
)) {
616 if (line_entry
.is_prologue_end
) {
617 prologue_end_file_addr
=
618 line_entry
.range
.GetBaseAddress().GetFileAddress();
619 prologue_end_line_idx
= idx
;
626 // If we didn't find the end of the prologue in the line tables, then
627 // just use the end address of the first line table entry
628 if (prologue_end_file_addr
== LLDB_INVALID_ADDRESS
) {
629 // Check the first few instructions and look for one that has a line
630 // number that's different than the first entry.
631 uint32_t last_line_entry_idx
= first_line_entry_idx
+ 6;
632 for (uint32_t idx
= first_line_entry_idx
+ 1;
633 idx
< last_line_entry_idx
; ++idx
) {
634 LineEntry line_entry
;
635 if (line_table
->GetLineEntryAtIndex(idx
, line_entry
)) {
636 if (line_entry
.line
!= first_line_entry
.line
) {
637 prologue_end_file_addr
=
638 line_entry
.range
.GetBaseAddress().GetFileAddress();
639 prologue_end_line_idx
= idx
;
645 if (prologue_end_file_addr
== LLDB_INVALID_ADDRESS
) {
646 prologue_end_file_addr
=
647 first_line_entry
.range
.GetBaseAddress().GetFileAddress() +
648 first_line_entry
.range
.GetByteSize();
649 prologue_end_line_idx
= first_line_entry_idx
;
653 const addr_t func_start_file_addr
=
654 m_range
.GetBaseAddress().GetFileAddress();
655 const addr_t func_end_file_addr
=
656 func_start_file_addr
+ m_range
.GetByteSize();
658 // Now calculate the offset to pass the subsequent line 0 entries.
659 uint32_t first_non_zero_line
= prologue_end_line_idx
;
661 LineEntry line_entry
;
662 if (line_table
->GetLineEntryAtIndex(first_non_zero_line
,
664 if (line_entry
.line
!= 0)
667 if (line_entry
.range
.GetBaseAddress().GetFileAddress() >=
671 first_non_zero_line
++;
674 if (first_non_zero_line
> prologue_end_line_idx
) {
675 LineEntry first_non_zero_entry
;
676 if (line_table
->GetLineEntryAtIndex(first_non_zero_line
,
677 first_non_zero_entry
)) {
678 line_zero_end_file_addr
=
679 first_non_zero_entry
.range
.GetBaseAddress().GetFileAddress();
683 // Verify that this prologue end file address in the function's address
684 // range just to be sure
685 if (func_start_file_addr
< prologue_end_file_addr
&&
686 prologue_end_file_addr
< func_end_file_addr
) {
687 m_prologue_byte_size
= prologue_end_file_addr
- func_start_file_addr
;
690 if (prologue_end_file_addr
< line_zero_end_file_addr
&&
691 line_zero_end_file_addr
< func_end_file_addr
) {
692 m_prologue_byte_size
+=
693 line_zero_end_file_addr
- prologue_end_file_addr
;
699 return m_prologue_byte_size
;
702 lldb::LanguageType
Function::GetLanguage() const {
703 lldb::LanguageType lang
= m_mangled
.GuessLanguage();
704 if (lang
!= lldb::eLanguageTypeUnknown
)
708 return m_comp_unit
->GetLanguage();
710 return lldb::eLanguageTypeUnknown
;
713 ConstString
Function::GetName() const {
714 return m_mangled
.GetName();
717 ConstString
Function::GetNameNoArguments() const {
718 return m_mangled
.GetName(Mangled::ePreferDemangledWithoutArguments
);