1 //===-- Function.cpp --------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Symbol/Function.h"
11 #include "lldb/Core/Disassembler.h"
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/Section.h"
14 #include "lldb/Host/Host.h"
15 #include "lldb/Symbol/CompilerType.h"
16 #include "lldb/Symbol/CompileUnit.h"
17 #include "lldb/Symbol/LineTable.h"
18 #include "lldb/Symbol/SymbolFile.h"
19 #include "lldb/Symbol/SymbolVendor.h"
20 #include "lldb/Target/Language.h"
21 #include "llvm/Support/Casting.h"
24 using namespace lldb_private;
26 //----------------------------------------------------------------------
27 // Basic function information is contained in the FunctionInfo class.
28 // It is designed to contain the name, linkage name, and declaration
30 //----------------------------------------------------------------------
31 FunctionInfo::FunctionInfo (const char *name, const Declaration *decl_ptr) :
33 m_declaration(decl_ptr)
38 FunctionInfo::FunctionInfo (const ConstString& name, const Declaration *decl_ptr) :
40 m_declaration(decl_ptr)
45 FunctionInfo::~FunctionInfo()
50 FunctionInfo::Dump(Stream *s, bool show_fullpaths) const
53 *s << ", name = \"" << m_name << "\"";
54 m_declaration.Dump(s, show_fullpaths);
59 FunctionInfo::Compare(const FunctionInfo& a, const FunctionInfo& b)
61 int result = ConstString::Compare(a.GetName(), b.GetName());
65 return Declaration::Compare(a.m_declaration, b.m_declaration);
70 FunctionInfo::GetDeclaration()
76 FunctionInfo::GetDeclaration() const
82 FunctionInfo::GetName() const
88 FunctionInfo::MemorySize() const
90 return m_name.MemorySize() + m_declaration.MemorySize();
94 InlineFunctionInfo::InlineFunctionInfo
98 const Declaration *decl_ptr,
99 const Declaration *call_decl_ptr
101 FunctionInfo(name, decl_ptr),
102 m_mangled(ConstString(mangled), true),
103 m_call_decl (call_decl_ptr)
107 InlineFunctionInfo::InlineFunctionInfo
109 const ConstString& name,
110 const Mangled &mangled,
111 const Declaration *decl_ptr,
112 const Declaration *call_decl_ptr
114 FunctionInfo(name, decl_ptr),
116 m_call_decl (call_decl_ptr)
120 InlineFunctionInfo::~InlineFunctionInfo()
125 InlineFunctionInfo::Compare(const InlineFunctionInfo& a, const InlineFunctionInfo& b)
128 int result = FunctionInfo::Compare(a, b);
131 // only compare the mangled names if both have them
132 return Mangled::Compare(a.m_mangled, a.m_mangled);
136 InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const
138 FunctionInfo::Dump(s, show_fullpaths);
144 InlineFunctionInfo::DumpStopContext (Stream *s, LanguageType language) const
146 // s->Indent("[inlined] ");
149 s->PutCString (m_mangled.GetName(language).AsCString());
151 s->PutCString (m_name.AsCString());
156 InlineFunctionInfo::GetName (LanguageType language) const
159 return m_mangled.GetName(language);
164 InlineFunctionInfo::GetDisplayName (LanguageType language) const
167 return m_mangled.GetDisplayDemangledName(language);
172 InlineFunctionInfo::GetCallSite ()
178 InlineFunctionInfo::GetCallSite () const
185 InlineFunctionInfo::GetMangled()
191 InlineFunctionInfo::GetMangled() const
197 InlineFunctionInfo::MemorySize() const
199 return FunctionInfo::MemorySize() + m_mangled.MemorySize();
202 //----------------------------------------------------------------------
204 //----------------------------------------------------------------------
207 CompileUnit *comp_unit,
208 lldb::user_id_t func_uid,
209 lldb::user_id_t type_uid,
210 const Mangled &mangled,
212 const AddressRange& range
215 m_comp_unit (comp_unit),
216 m_type_uid (type_uid),
221 m_frame_base (nullptr),
223 m_prologue_byte_size (0)
225 m_block.SetParentScope(this);
226 assert(comp_unit != nullptr);
231 CompileUnit *comp_unit,
232 lldb::user_id_t func_uid,
233 lldb::user_id_t type_uid,
236 const AddressRange &range
239 m_comp_unit (comp_unit),
240 m_type_uid (type_uid),
242 m_mangled (ConstString(mangled), true),
245 m_frame_base (nullptr),
247 m_prologue_byte_size (0)
249 m_block.SetParentScope(this);
250 assert(comp_unit != nullptr);
254 Function::~Function()
259 Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
264 if (m_comp_unit == nullptr)
267 if (m_type != nullptr && m_type->GetDeclaration().GetLine() != 0)
269 source_file = m_type->GetDeclaration().GetFile();
270 line_no = m_type->GetDeclaration().GetLine();
274 LineTable *line_table = m_comp_unit->GetLineTable();
275 if (line_table == nullptr)
278 LineEntry line_entry;
279 if (line_table->FindLineEntryByAddress (GetAddressRange().GetBaseAddress(), line_entry, nullptr))
281 line_no = line_entry.line;
282 source_file = line_entry.file;
288 Function::GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
293 // The -1 is kind of cheesy, but I want to get the last line entry for the given function, not the
294 // first entry of the next.
295 Address scratch_addr(GetAddressRange().GetBaseAddress());
296 scratch_addr.SetOffset (scratch_addr.GetOffset() + GetAddressRange().GetByteSize() - 1);
298 LineTable *line_table = m_comp_unit->GetLineTable();
299 if (line_table == nullptr)
302 LineEntry line_entry;
303 if (line_table->FindLineEntryByAddress (scratch_addr, line_entry, nullptr))
305 line_no = line_entry.line;
306 source_file = line_entry.file;
311 Function::GetBlock (bool can_create)
313 if (!m_block.BlockInfoHasBeenParsed() && can_create)
316 CalculateSymbolContext(&sc);
319 sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc);
323 Host::SystemLog (Host::eSystemLogError,
324 "error: unable to find module shared pointer for function '%s' in %s\n",
325 GetName().GetCString(),
326 m_comp_unit->GetPath().c_str());
328 m_block.SetBlockInfoHasBeenParsed (true, true);
334 Function::GetCompileUnit()
340 Function::GetCompileUnit() const
347 Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target)
349 Type* func_type = GetType();
350 const char *name = func_type ? func_type->GetName().AsCString() : "<unknown>";
352 *s << "id = " << (const UserID&)*this << ", name = \"" << name << "\", range = ";
354 Address::DumpStyle fallback_style;
355 if (level == eDescriptionLevelVerbose)
356 fallback_style = Address::DumpStyleModuleWithFileAddress;
358 fallback_style = Address::DumpStyleFileAddress;
359 GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, fallback_style);
363 Function::Dump(Stream *s, bool show_context) const
365 s->Printf("%p: ", static_cast<const void*>(this));
367 *s << "Function" << static_cast<const UserID&>(*this);
372 s->Printf(", type = %p", static_cast<void*>(m_type));
373 else if (m_type_uid != LLDB_INVALID_UID)
374 s->Printf(", type_uid = 0x%8.8" PRIx64, m_type_uid);
377 // Dump the root object
378 if (m_block.BlockInfoHasBeenParsed ())
379 m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, show_context);
384 Function::CalculateSymbolContext(SymbolContext* sc)
387 m_comp_unit->CalculateSymbolContext(sc);
391 Function::CalculateSymbolContextModule ()
393 SectionSP section_sp (m_range.GetBaseAddress().GetSection());
395 return section_sp->GetModule();
397 return this->GetCompileUnit()->GetModule();
401 Function::CalculateSymbolContextCompileUnit ()
403 return this->GetCompileUnit();
407 Function::CalculateSymbolContextFunction ()
413 Function::GetInstructions (const ExecutionContext &exe_ctx,
415 bool prefer_file_cache)
417 ModuleSP module_sp (GetAddressRange().GetBaseAddress().GetModule());
420 const bool prefer_file_cache = false;
421 return Disassembler::DisassembleRange (module_sp->GetArchitecture(),
428 return lldb::DisassemblerSP();
432 Function::GetDisassembly (const ExecutionContext &exe_ctx,
434 bool prefer_file_cache,
437 lldb::DisassemblerSP disassembler_sp = GetInstructions (exe_ctx, flavor, prefer_file_cache);
440 const bool show_address = true;
441 const bool show_bytes = false;
442 disassembler_sp->GetInstructionList().Dump (&strm, show_address, show_bytes, &exe_ctx);
450 //Function::CalculateSymbolContextSymbol ()
452 // return // TODO: find the symbol for the function???
457 Function::DumpSymbolContext(Stream *s)
459 m_comp_unit->DumpSymbolContext(s);
460 s->Printf(", Function{0x%8.8" PRIx64 "}", GetID());
464 Function::MemorySize () const
466 size_t mem_size = sizeof(Function) + m_block.MemorySize();
471 Function::GetIsOptimized ()
475 // Currently optimization is only indicted by the
476 // vendor extension DW_AT_APPLE_optimized which
477 // is set on a compile unit level.
480 result = m_comp_unit->GetIsOptimized();
486 Function::IsTopLevelFunction ()
490 if (Language* language = Language::FindPlugin(GetLanguage()))
491 result = language->IsTopLevelFunction(*this);
497 Function::GetDisplayName () const
500 return ConstString();
501 return m_mangled.GetDisplayDemangledName(GetLanguage());
505 Function::GetDeclContext()
507 ModuleSP module_sp = CalculateSymbolContextModule ();
511 SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
515 SymbolFile *sym_file = sym_vendor->GetSymbolFile();
518 return sym_file->GetDeclContextForUID (GetID());
521 return CompilerDeclContext();
527 if (m_type == nullptr)
531 CalculateSymbolContext (&sc);
536 SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
538 if (sym_vendor == nullptr)
541 SymbolFile *sym_file = sym_vendor->GetSymbolFile();
543 if (sym_file == nullptr)
546 m_type = sym_file->ResolveTypeUID(m_type_uid);
552 Function::GetType() const
558 Function::GetCompilerType()
560 Type *function_type = GetType();
562 return function_type->GetFullCompilerType ();
563 return CompilerType();
567 Function::GetPrologueByteSize ()
569 if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize))
571 m_flags.Set(flagsCalculatedPrologueSize);
572 LineTable* line_table = m_comp_unit->GetLineTable ();
573 uint32_t prologue_end_line_idx = 0;
577 LineEntry first_line_entry;
578 uint32_t first_line_entry_idx = UINT32_MAX;
579 if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), first_line_entry, &first_line_entry_idx))
581 // Make sure the first line entry isn't already the end of the prologue
582 addr_t prologue_end_file_addr = LLDB_INVALID_ADDRESS;
583 addr_t line_zero_end_file_addr = LLDB_INVALID_ADDRESS;
585 if (first_line_entry.is_prologue_end)
587 prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress();
588 prologue_end_line_idx = first_line_entry_idx;
592 // Check the first few instructions and look for one that has
593 // is_prologue_end set to true.
594 const uint32_t last_line_entry_idx = first_line_entry_idx + 6;
595 for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx)
597 LineEntry line_entry;
598 if (line_table->GetLineEntryAtIndex (idx, line_entry))
600 if (line_entry.is_prologue_end)
602 prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress();
603 prologue_end_line_idx = idx;
610 // If we didn't find the end of the prologue in the line tables,
611 // then just use the end address of the first line table entry
612 if (prologue_end_file_addr == LLDB_INVALID_ADDRESS)
614 // Check the first few instructions and look for one that has
615 // a line number that's different than the first entry.
616 uint32_t last_line_entry_idx = first_line_entry_idx + 6;
617 for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx)
619 LineEntry line_entry;
620 if (line_table->GetLineEntryAtIndex (idx, line_entry))
622 if (line_entry.line != first_line_entry.line)
624 prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress();
625 prologue_end_line_idx = idx;
631 if (prologue_end_file_addr == LLDB_INVALID_ADDRESS)
633 prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress() + first_line_entry.range.GetByteSize();
634 prologue_end_line_idx = first_line_entry_idx;
638 const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress();
639 const addr_t func_end_file_addr = func_start_file_addr + m_range.GetByteSize();
641 // Now calculate the offset to pass the subsequent line 0 entries.
642 uint32_t first_non_zero_line = prologue_end_line_idx;
645 LineEntry line_entry;
646 if (line_table->GetLineEntryAtIndex(first_non_zero_line, line_entry))
648 if (line_entry.line != 0)
651 if (line_entry.range.GetBaseAddress().GetFileAddress() >= func_end_file_addr)
654 first_non_zero_line++;
657 if (first_non_zero_line > prologue_end_line_idx)
659 LineEntry first_non_zero_entry;
660 if (line_table->GetLineEntryAtIndex(first_non_zero_line, first_non_zero_entry))
662 line_zero_end_file_addr = first_non_zero_entry.range.GetBaseAddress().GetFileAddress();
666 // Verify that this prologue end file address in the function's
667 // address range just to be sure
668 if (func_start_file_addr < prologue_end_file_addr && prologue_end_file_addr < func_end_file_addr)
670 m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr;
673 if (prologue_end_file_addr < line_zero_end_file_addr && line_zero_end_file_addr < func_end_file_addr)
675 m_prologue_byte_size += line_zero_end_file_addr - prologue_end_file_addr;
681 return m_prologue_byte_size;
685 Function::GetLanguage() const
688 return m_comp_unit->GetLanguage();
690 return lldb::eLanguageTypeUnknown;
694 Function::GetName() const
696 LanguageType language = lldb::eLanguageTypeUnknown;
698 language = m_comp_unit->GetLanguage();
699 return m_mangled.GetName(language);
703 Function::GetNameNoArguments() const
705 LanguageType language = lldb::eLanguageTypeUnknown;
707 language = m_comp_unit->GetLanguage();
708 return m_mangled.GetName(language, Mangled::ePreferDemangledWithoutArguments);