1*dda28197Spatrick //===-- 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" 10061da546Spatrick #include "lldb/Core/Disassembler.h" 11061da546Spatrick #include "lldb/Core/Module.h" 12061da546Spatrick #include "lldb/Core/ModuleList.h" 13061da546Spatrick #include "lldb/Core/Section.h" 14061da546Spatrick #include "lldb/Host/Host.h" 15061da546Spatrick #include "lldb/Symbol/CompileUnit.h" 16061da546Spatrick #include "lldb/Symbol/CompilerType.h" 17061da546Spatrick #include "lldb/Symbol/LineTable.h" 18061da546Spatrick #include "lldb/Symbol/SymbolFile.h" 19061da546Spatrick #include "lldb/Target/Language.h" 20061da546Spatrick #include "lldb/Target/Target.h" 21061da546Spatrick #include "lldb/Utility/Log.h" 22061da546Spatrick #include "llvm/Support/Casting.h" 23061da546Spatrick 24061da546Spatrick using namespace lldb; 25061da546Spatrick using namespace lldb_private; 26061da546Spatrick 27061da546Spatrick // Basic function information is contained in the FunctionInfo class. It is 28061da546Spatrick // designed to contain the name, linkage name, and declaration location. 29061da546Spatrick FunctionInfo::FunctionInfo(const char *name, const Declaration *decl_ptr) 30061da546Spatrick : m_name(name), m_declaration(decl_ptr) {} 31061da546Spatrick 32061da546Spatrick FunctionInfo::FunctionInfo(ConstString name, const Declaration *decl_ptr) 33061da546Spatrick : m_name(name), m_declaration(decl_ptr) {} 34061da546Spatrick 35061da546Spatrick FunctionInfo::~FunctionInfo() {} 36061da546Spatrick 37061da546Spatrick void FunctionInfo::Dump(Stream *s, bool show_fullpaths) const { 38061da546Spatrick if (m_name) 39061da546Spatrick *s << ", name = \"" << m_name << "\""; 40061da546Spatrick m_declaration.Dump(s, show_fullpaths); 41061da546Spatrick } 42061da546Spatrick 43061da546Spatrick int FunctionInfo::Compare(const FunctionInfo &a, const FunctionInfo &b) { 44061da546Spatrick int result = ConstString::Compare(a.GetName(), b.GetName()); 45061da546Spatrick if (result) 46061da546Spatrick return result; 47061da546Spatrick 48061da546Spatrick return Declaration::Compare(a.m_declaration, b.m_declaration); 49061da546Spatrick } 50061da546Spatrick 51061da546Spatrick Declaration &FunctionInfo::GetDeclaration() { return m_declaration; } 52061da546Spatrick 53061da546Spatrick const Declaration &FunctionInfo::GetDeclaration() const { 54061da546Spatrick return m_declaration; 55061da546Spatrick } 56061da546Spatrick 57061da546Spatrick ConstString FunctionInfo::GetName() const { return m_name; } 58061da546Spatrick 59061da546Spatrick size_t FunctionInfo::MemorySize() const { 60061da546Spatrick return m_name.MemorySize() + m_declaration.MemorySize(); 61061da546Spatrick } 62061da546Spatrick 63061da546Spatrick InlineFunctionInfo::InlineFunctionInfo(const char *name, 64061da546Spatrick llvm::StringRef mangled, 65061da546Spatrick const Declaration *decl_ptr, 66061da546Spatrick const Declaration *call_decl_ptr) 67061da546Spatrick : FunctionInfo(name, decl_ptr), m_mangled(mangled), 68061da546Spatrick m_call_decl(call_decl_ptr) {} 69061da546Spatrick 70061da546Spatrick InlineFunctionInfo::InlineFunctionInfo(ConstString name, 71061da546Spatrick const Mangled &mangled, 72061da546Spatrick const Declaration *decl_ptr, 73061da546Spatrick const Declaration *call_decl_ptr) 74061da546Spatrick : FunctionInfo(name, decl_ptr), m_mangled(mangled), 75061da546Spatrick m_call_decl(call_decl_ptr) {} 76061da546Spatrick 77061da546Spatrick InlineFunctionInfo::~InlineFunctionInfo() {} 78061da546Spatrick 79061da546Spatrick void InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const { 80061da546Spatrick FunctionInfo::Dump(s, show_fullpaths); 81061da546Spatrick if (m_mangled) 82061da546Spatrick m_mangled.Dump(s); 83061da546Spatrick } 84061da546Spatrick 85*dda28197Spatrick void InlineFunctionInfo::DumpStopContext(Stream *s) const { 86061da546Spatrick // s->Indent("[inlined] "); 87061da546Spatrick s->Indent(); 88061da546Spatrick if (m_mangled) 89*dda28197Spatrick s->PutCString(m_mangled.GetName().AsCString()); 90061da546Spatrick else 91061da546Spatrick s->PutCString(m_name.AsCString()); 92061da546Spatrick } 93061da546Spatrick 94*dda28197Spatrick ConstString InlineFunctionInfo::GetName() const { 95061da546Spatrick if (m_mangled) 96*dda28197Spatrick return m_mangled.GetName(); 97061da546Spatrick return m_name; 98061da546Spatrick } 99061da546Spatrick 100*dda28197Spatrick ConstString InlineFunctionInfo::GetDisplayName() const { 101061da546Spatrick if (m_mangled) 102*dda28197Spatrick return m_mangled.GetDisplayDemangledName(); 103061da546Spatrick return m_name; 104061da546Spatrick } 105061da546Spatrick 106061da546Spatrick Declaration &InlineFunctionInfo::GetCallSite() { return m_call_decl; } 107061da546Spatrick 108061da546Spatrick const Declaration &InlineFunctionInfo::GetCallSite() const { 109061da546Spatrick return m_call_decl; 110061da546Spatrick } 111061da546Spatrick 112061da546Spatrick Mangled &InlineFunctionInfo::GetMangled() { return m_mangled; } 113061da546Spatrick 114061da546Spatrick const Mangled &InlineFunctionInfo::GetMangled() const { return m_mangled; } 115061da546Spatrick 116061da546Spatrick size_t InlineFunctionInfo::MemorySize() const { 117061da546Spatrick return FunctionInfo::MemorySize() + m_mangled.MemorySize(); 118061da546Spatrick } 119061da546Spatrick 120061da546Spatrick /// @name Call site related structures 121061da546Spatrick /// @{ 122061da546Spatrick 123*dda28197Spatrick lldb::addr_t CallEdge::GetLoadAddress(lldb::addr_t unresolved_pc, 124*dda28197Spatrick Function &caller, Target &target) { 125*dda28197Spatrick Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 126*dda28197Spatrick 127*dda28197Spatrick const Address &caller_start_addr = caller.GetAddressRange().GetBaseAddress(); 128*dda28197Spatrick 129*dda28197Spatrick ModuleSP caller_module_sp = caller_start_addr.GetModule(); 130*dda28197Spatrick if (!caller_module_sp) { 131*dda28197Spatrick LLDB_LOG(log, "GetLoadAddress: cannot get Module for caller"); 132*dda28197Spatrick return LLDB_INVALID_ADDRESS; 133*dda28197Spatrick } 134*dda28197Spatrick 135*dda28197Spatrick SectionList *section_list = caller_module_sp->GetSectionList(); 136*dda28197Spatrick if (!section_list) { 137*dda28197Spatrick LLDB_LOG(log, "GetLoadAddress: cannot get SectionList for Module"); 138*dda28197Spatrick return LLDB_INVALID_ADDRESS; 139*dda28197Spatrick } 140*dda28197Spatrick 141*dda28197Spatrick Address the_addr = Address(unresolved_pc, section_list); 142*dda28197Spatrick lldb::addr_t load_addr = the_addr.GetLoadAddress(&target); 143*dda28197Spatrick return load_addr; 144*dda28197Spatrick } 145*dda28197Spatrick 146061da546Spatrick lldb::addr_t CallEdge::GetReturnPCAddress(Function &caller, 147061da546Spatrick Target &target) const { 148*dda28197Spatrick return GetLoadAddress(GetUnresolvedReturnPCAddress(), caller, target); 149061da546Spatrick } 150061da546Spatrick 151061da546Spatrick void DirectCallEdge::ParseSymbolFileAndResolve(ModuleList &images) { 152061da546Spatrick if (resolved) 153061da546Spatrick return; 154061da546Spatrick 155061da546Spatrick Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 156061da546Spatrick LLDB_LOG(log, "DirectCallEdge: Lazily parsing the call graph for {0}", 157061da546Spatrick lazy_callee.symbol_name); 158061da546Spatrick 159061da546Spatrick auto resolve_lazy_callee = [&]() -> Function * { 160061da546Spatrick ConstString callee_name{lazy_callee.symbol_name}; 161061da546Spatrick SymbolContextList sc_list; 162061da546Spatrick images.FindFunctionSymbols(callee_name, eFunctionNameTypeAuto, sc_list); 163061da546Spatrick size_t num_matches = sc_list.GetSize(); 164061da546Spatrick if (num_matches == 0 || !sc_list[0].symbol) { 165061da546Spatrick LLDB_LOG(log, 166061da546Spatrick "DirectCallEdge: Found no symbols for {0}, cannot resolve it", 167061da546Spatrick callee_name); 168061da546Spatrick return nullptr; 169061da546Spatrick } 170061da546Spatrick Address callee_addr = sc_list[0].symbol->GetAddress(); 171061da546Spatrick if (!callee_addr.IsValid()) { 172061da546Spatrick LLDB_LOG(log, "DirectCallEdge: Invalid symbol address"); 173061da546Spatrick return nullptr; 174061da546Spatrick } 175061da546Spatrick Function *f = callee_addr.CalculateSymbolContextFunction(); 176061da546Spatrick if (!f) { 177061da546Spatrick LLDB_LOG(log, "DirectCallEdge: Could not find complete function"); 178061da546Spatrick return nullptr; 179061da546Spatrick } 180061da546Spatrick return f; 181061da546Spatrick }; 182061da546Spatrick lazy_callee.def = resolve_lazy_callee(); 183061da546Spatrick resolved = true; 184061da546Spatrick } 185061da546Spatrick 186061da546Spatrick Function *DirectCallEdge::GetCallee(ModuleList &images, ExecutionContext &) { 187061da546Spatrick ParseSymbolFileAndResolve(images); 188061da546Spatrick assert(resolved && "Did not resolve lazy callee"); 189061da546Spatrick return lazy_callee.def; 190061da546Spatrick } 191061da546Spatrick 192061da546Spatrick Function *IndirectCallEdge::GetCallee(ModuleList &images, 193061da546Spatrick ExecutionContext &exe_ctx) { 194061da546Spatrick Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 195061da546Spatrick Status error; 196061da546Spatrick Value callee_addr_val; 197061da546Spatrick if (!call_target.Evaluate(&exe_ctx, exe_ctx.GetRegisterContext(), 198061da546Spatrick /*loclist_base_addr=*/LLDB_INVALID_ADDRESS, 199061da546Spatrick /*initial_value_ptr=*/nullptr, 200061da546Spatrick /*object_address_ptr=*/nullptr, callee_addr_val, 201061da546Spatrick &error)) { 202061da546Spatrick LLDB_LOGF(log, "IndirectCallEdge: Could not evaluate expression: %s", 203061da546Spatrick error.AsCString()); 204061da546Spatrick return nullptr; 205061da546Spatrick } 206061da546Spatrick 207061da546Spatrick addr_t raw_addr = callee_addr_val.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); 208061da546Spatrick if (raw_addr == LLDB_INVALID_ADDRESS) { 209061da546Spatrick LLDB_LOG(log, "IndirectCallEdge: Could not extract address from scalar"); 210061da546Spatrick return nullptr; 211061da546Spatrick } 212061da546Spatrick 213061da546Spatrick Address callee_addr; 214061da546Spatrick if (!exe_ctx.GetTargetPtr()->ResolveLoadAddress(raw_addr, callee_addr)) { 215061da546Spatrick LLDB_LOG(log, "IndirectCallEdge: Could not resolve callee's load address"); 216061da546Spatrick return nullptr; 217061da546Spatrick } 218061da546Spatrick 219061da546Spatrick Function *f = callee_addr.CalculateSymbolContextFunction(); 220061da546Spatrick if (!f) { 221061da546Spatrick LLDB_LOG(log, "IndirectCallEdge: Could not find complete function"); 222061da546Spatrick return nullptr; 223061da546Spatrick } 224061da546Spatrick 225061da546Spatrick return f; 226061da546Spatrick } 227061da546Spatrick 228061da546Spatrick /// @} 229061da546Spatrick 230061da546Spatrick // 231061da546Spatrick Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid, 232061da546Spatrick lldb::user_id_t type_uid, const Mangled &mangled, Type *type, 233061da546Spatrick const AddressRange &range) 234061da546Spatrick : UserID(func_uid), m_comp_unit(comp_unit), m_type_uid(type_uid), 235061da546Spatrick m_type(type), m_mangled(mangled), m_block(func_uid), m_range(range), 236061da546Spatrick m_frame_base(), m_flags(), m_prologue_byte_size(0) { 237061da546Spatrick m_block.SetParentScope(this); 238061da546Spatrick assert(comp_unit != nullptr); 239061da546Spatrick } 240061da546Spatrick 241061da546Spatrick Function::~Function() {} 242061da546Spatrick 243061da546Spatrick void Function::GetStartLineSourceInfo(FileSpec &source_file, 244061da546Spatrick uint32_t &line_no) { 245061da546Spatrick line_no = 0; 246061da546Spatrick source_file.Clear(); 247061da546Spatrick 248061da546Spatrick if (m_comp_unit == nullptr) 249061da546Spatrick return; 250061da546Spatrick 251061da546Spatrick // Initialize m_type if it hasn't been initialized already 252061da546Spatrick GetType(); 253061da546Spatrick 254061da546Spatrick if (m_type != nullptr && m_type->GetDeclaration().GetLine() != 0) { 255061da546Spatrick source_file = m_type->GetDeclaration().GetFile(); 256061da546Spatrick line_no = m_type->GetDeclaration().GetLine(); 257061da546Spatrick } else { 258061da546Spatrick LineTable *line_table = m_comp_unit->GetLineTable(); 259061da546Spatrick if (line_table == nullptr) 260061da546Spatrick return; 261061da546Spatrick 262061da546Spatrick LineEntry line_entry; 263061da546Spatrick if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), 264061da546Spatrick line_entry, nullptr)) { 265061da546Spatrick line_no = line_entry.line; 266061da546Spatrick source_file = line_entry.file; 267061da546Spatrick } 268061da546Spatrick } 269061da546Spatrick } 270061da546Spatrick 271061da546Spatrick void Function::GetEndLineSourceInfo(FileSpec &source_file, uint32_t &line_no) { 272061da546Spatrick line_no = 0; 273061da546Spatrick source_file.Clear(); 274061da546Spatrick 275061da546Spatrick // The -1 is kind of cheesy, but I want to get the last line entry for the 276061da546Spatrick // given function, not the first entry of the next. 277061da546Spatrick Address scratch_addr(GetAddressRange().GetBaseAddress()); 278061da546Spatrick scratch_addr.SetOffset(scratch_addr.GetOffset() + 279061da546Spatrick GetAddressRange().GetByteSize() - 1); 280061da546Spatrick 281061da546Spatrick LineTable *line_table = m_comp_unit->GetLineTable(); 282061da546Spatrick if (line_table == nullptr) 283061da546Spatrick return; 284061da546Spatrick 285061da546Spatrick LineEntry line_entry; 286061da546Spatrick if (line_table->FindLineEntryByAddress(scratch_addr, line_entry, nullptr)) { 287061da546Spatrick line_no = line_entry.line; 288061da546Spatrick source_file = line_entry.file; 289061da546Spatrick } 290061da546Spatrick } 291061da546Spatrick 292061da546Spatrick llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetCallEdges() { 293*dda28197Spatrick std::lock_guard<std::mutex> guard(m_call_edges_lock); 294*dda28197Spatrick 295061da546Spatrick if (m_call_edges_resolved) 296061da546Spatrick return m_call_edges; 297061da546Spatrick 298061da546Spatrick Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 299061da546Spatrick LLDB_LOG(log, "GetCallEdges: Attempting to parse call site info for {0}", 300061da546Spatrick GetDisplayName()); 301061da546Spatrick 302061da546Spatrick m_call_edges_resolved = true; 303061da546Spatrick 304061da546Spatrick // Find the SymbolFile which provided this function's definition. 305061da546Spatrick Block &block = GetBlock(/*can_create*/true); 306061da546Spatrick SymbolFile *sym_file = block.GetSymbolFile(); 307061da546Spatrick if (!sym_file) 308061da546Spatrick return llvm::None; 309061da546Spatrick 310061da546Spatrick // Lazily read call site information from the SymbolFile. 311061da546Spatrick m_call_edges = sym_file->ParseCallEdgesInFunction(GetID()); 312061da546Spatrick 313061da546Spatrick // Sort the call edges to speed up return_pc lookups. 314*dda28197Spatrick llvm::sort(m_call_edges, [](const std::unique_ptr<CallEdge> &LHS, 315061da546Spatrick const std::unique_ptr<CallEdge> &RHS) { 316*dda28197Spatrick return LHS->GetSortKey() < RHS->GetSortKey(); 317061da546Spatrick }); 318061da546Spatrick 319061da546Spatrick return m_call_edges; 320061da546Spatrick } 321061da546Spatrick 322061da546Spatrick llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetTailCallingEdges() { 323*dda28197Spatrick // Tail calling edges are sorted at the end of the list. Find them by dropping 324*dda28197Spatrick // all non-tail-calls. 325*dda28197Spatrick return GetCallEdges().drop_until( 326*dda28197Spatrick [](const std::unique_ptr<CallEdge> &edge) { return edge->IsTailCall(); }); 327061da546Spatrick } 328061da546Spatrick 329061da546Spatrick CallEdge *Function::GetCallEdgeForReturnAddress(addr_t return_pc, 330061da546Spatrick Target &target) { 331061da546Spatrick auto edges = GetCallEdges(); 332061da546Spatrick auto edge_it = 333*dda28197Spatrick llvm::partition_point(edges, [&](const std::unique_ptr<CallEdge> &edge) { 334*dda28197Spatrick return std::make_pair(edge->IsTailCall(), 335*dda28197Spatrick edge->GetReturnPCAddress(*this, target)) < 336*dda28197Spatrick std::make_pair(false, return_pc); 337061da546Spatrick }); 338061da546Spatrick if (edge_it == edges.end() || 339061da546Spatrick edge_it->get()->GetReturnPCAddress(*this, target) != return_pc) 340061da546Spatrick return nullptr; 341*dda28197Spatrick return edge_it->get(); 342061da546Spatrick } 343061da546Spatrick 344061da546Spatrick Block &Function::GetBlock(bool can_create) { 345061da546Spatrick if (!m_block.BlockInfoHasBeenParsed() && can_create) { 346061da546Spatrick ModuleSP module_sp = CalculateSymbolContextModule(); 347061da546Spatrick if (module_sp) { 348061da546Spatrick module_sp->GetSymbolFile()->ParseBlocksRecursive(*this); 349061da546Spatrick } else { 350061da546Spatrick Host::SystemLog(Host::eSystemLogError, 351061da546Spatrick "error: unable to find module " 352061da546Spatrick "shared pointer for function '%s' " 353061da546Spatrick "in %s\n", 354061da546Spatrick GetName().GetCString(), 355061da546Spatrick m_comp_unit->GetPrimaryFile().GetPath().c_str()); 356061da546Spatrick } 357061da546Spatrick m_block.SetBlockInfoHasBeenParsed(true, true); 358061da546Spatrick } 359061da546Spatrick return m_block; 360061da546Spatrick } 361061da546Spatrick 362061da546Spatrick CompileUnit *Function::GetCompileUnit() { return m_comp_unit; } 363061da546Spatrick 364061da546Spatrick const CompileUnit *Function::GetCompileUnit() const { return m_comp_unit; } 365061da546Spatrick 366061da546Spatrick void Function::GetDescription(Stream *s, lldb::DescriptionLevel level, 367061da546Spatrick Target *target) { 368061da546Spatrick ConstString name = GetName(); 369061da546Spatrick ConstString mangled = m_mangled.GetMangledName(); 370061da546Spatrick 371061da546Spatrick *s << "id = " << (const UserID &)*this; 372061da546Spatrick if (name) 373*dda28197Spatrick s->AsRawOstream() << ", name = \"" << name << '"'; 374061da546Spatrick if (mangled) 375*dda28197Spatrick s->AsRawOstream() << ", mangled = \"" << mangled << '"'; 376061da546Spatrick *s << ", range = "; 377061da546Spatrick Address::DumpStyle fallback_style; 378061da546Spatrick if (level == eDescriptionLevelVerbose) 379061da546Spatrick fallback_style = Address::DumpStyleModuleWithFileAddress; 380061da546Spatrick else 381061da546Spatrick fallback_style = Address::DumpStyleFileAddress; 382061da546Spatrick GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, 383061da546Spatrick fallback_style); 384061da546Spatrick } 385061da546Spatrick 386061da546Spatrick void Function::Dump(Stream *s, bool show_context) const { 387061da546Spatrick s->Printf("%p: ", static_cast<const void *>(this)); 388061da546Spatrick s->Indent(); 389061da546Spatrick *s << "Function" << static_cast<const UserID &>(*this); 390061da546Spatrick 391061da546Spatrick m_mangled.Dump(s); 392061da546Spatrick 393061da546Spatrick if (m_type) 394061da546Spatrick s->Printf(", type = %p", static_cast<void *>(m_type)); 395061da546Spatrick else if (m_type_uid != LLDB_INVALID_UID) 396061da546Spatrick s->Printf(", type_uid = 0x%8.8" PRIx64, m_type_uid); 397061da546Spatrick 398061da546Spatrick s->EOL(); 399061da546Spatrick // Dump the root object 400061da546Spatrick if (m_block.BlockInfoHasBeenParsed()) 401061da546Spatrick m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, 402061da546Spatrick show_context); 403061da546Spatrick } 404061da546Spatrick 405061da546Spatrick void Function::CalculateSymbolContext(SymbolContext *sc) { 406061da546Spatrick sc->function = this; 407061da546Spatrick m_comp_unit->CalculateSymbolContext(sc); 408061da546Spatrick } 409061da546Spatrick 410061da546Spatrick ModuleSP Function::CalculateSymbolContextModule() { 411061da546Spatrick SectionSP section_sp(m_range.GetBaseAddress().GetSection()); 412061da546Spatrick if (section_sp) 413061da546Spatrick return section_sp->GetModule(); 414061da546Spatrick 415061da546Spatrick return this->GetCompileUnit()->GetModule(); 416061da546Spatrick } 417061da546Spatrick 418061da546Spatrick CompileUnit *Function::CalculateSymbolContextCompileUnit() { 419061da546Spatrick return this->GetCompileUnit(); 420061da546Spatrick } 421061da546Spatrick 422061da546Spatrick Function *Function::CalculateSymbolContextFunction() { return this; } 423061da546Spatrick 424061da546Spatrick lldb::DisassemblerSP Function::GetInstructions(const ExecutionContext &exe_ctx, 425061da546Spatrick const char *flavor, 426061da546Spatrick bool prefer_file_cache) { 427061da546Spatrick ModuleSP module_sp(GetAddressRange().GetBaseAddress().GetModule()); 428*dda28197Spatrick if (module_sp && exe_ctx.HasTargetScope()) { 429061da546Spatrick const bool prefer_file_cache = false; 430061da546Spatrick return Disassembler::DisassembleRange(module_sp->GetArchitecture(), nullptr, 431*dda28197Spatrick flavor, exe_ctx.GetTargetRef(), 432*dda28197Spatrick GetAddressRange(), prefer_file_cache); 433061da546Spatrick } 434061da546Spatrick return lldb::DisassemblerSP(); 435061da546Spatrick } 436061da546Spatrick 437061da546Spatrick bool Function::GetDisassembly(const ExecutionContext &exe_ctx, 438061da546Spatrick const char *flavor, bool prefer_file_cache, 439061da546Spatrick Stream &strm) { 440061da546Spatrick lldb::DisassemblerSP disassembler_sp = 441061da546Spatrick GetInstructions(exe_ctx, flavor, prefer_file_cache); 442061da546Spatrick if (disassembler_sp) { 443061da546Spatrick const bool show_address = true; 444061da546Spatrick const bool show_bytes = false; 445061da546Spatrick disassembler_sp->GetInstructionList().Dump(&strm, show_address, show_bytes, 446061da546Spatrick &exe_ctx); 447061da546Spatrick return true; 448061da546Spatrick } 449061da546Spatrick return false; 450061da546Spatrick } 451061da546Spatrick 452061da546Spatrick // Symbol * 453061da546Spatrick // Function::CalculateSymbolContextSymbol () 454061da546Spatrick //{ 455061da546Spatrick // return // TODO: find the symbol for the function??? 456061da546Spatrick //} 457061da546Spatrick 458061da546Spatrick void Function::DumpSymbolContext(Stream *s) { 459061da546Spatrick m_comp_unit->DumpSymbolContext(s); 460061da546Spatrick s->Printf(", Function{0x%8.8" PRIx64 "}", GetID()); 461061da546Spatrick } 462061da546Spatrick 463061da546Spatrick size_t Function::MemorySize() const { 464061da546Spatrick size_t mem_size = sizeof(Function) + m_block.MemorySize(); 465061da546Spatrick return mem_size; 466061da546Spatrick } 467061da546Spatrick 468061da546Spatrick bool Function::GetIsOptimized() { 469061da546Spatrick bool result = false; 470061da546Spatrick 471061da546Spatrick // Currently optimization is only indicted by the vendor extension 472061da546Spatrick // DW_AT_APPLE_optimized which is set on a compile unit level. 473061da546Spatrick if (m_comp_unit) { 474061da546Spatrick result = m_comp_unit->GetIsOptimized(); 475061da546Spatrick } 476061da546Spatrick return result; 477061da546Spatrick } 478061da546Spatrick 479061da546Spatrick bool Function::IsTopLevelFunction() { 480061da546Spatrick bool result = false; 481061da546Spatrick 482061da546Spatrick if (Language *language = Language::FindPlugin(GetLanguage())) 483061da546Spatrick result = language->IsTopLevelFunction(*this); 484061da546Spatrick 485061da546Spatrick return result; 486061da546Spatrick } 487061da546Spatrick 488061da546Spatrick ConstString Function::GetDisplayName() const { 489*dda28197Spatrick return m_mangled.GetDisplayDemangledName(); 490061da546Spatrick } 491061da546Spatrick 492061da546Spatrick CompilerDeclContext Function::GetDeclContext() { 493061da546Spatrick ModuleSP module_sp = CalculateSymbolContextModule(); 494061da546Spatrick 495061da546Spatrick if (module_sp) { 496061da546Spatrick if (SymbolFile *sym_file = module_sp->GetSymbolFile()) 497061da546Spatrick return sym_file->GetDeclContextForUID(GetID()); 498061da546Spatrick } 499061da546Spatrick return CompilerDeclContext(); 500061da546Spatrick } 501061da546Spatrick 502061da546Spatrick Type *Function::GetType() { 503061da546Spatrick if (m_type == nullptr) { 504061da546Spatrick SymbolContext sc; 505061da546Spatrick 506061da546Spatrick CalculateSymbolContext(&sc); 507061da546Spatrick 508061da546Spatrick if (!sc.module_sp) 509061da546Spatrick return nullptr; 510061da546Spatrick 511061da546Spatrick SymbolFile *sym_file = sc.module_sp->GetSymbolFile(); 512061da546Spatrick 513061da546Spatrick if (sym_file == nullptr) 514061da546Spatrick return nullptr; 515061da546Spatrick 516061da546Spatrick m_type = sym_file->ResolveTypeUID(m_type_uid); 517061da546Spatrick } 518061da546Spatrick return m_type; 519061da546Spatrick } 520061da546Spatrick 521061da546Spatrick const Type *Function::GetType() const { return m_type; } 522061da546Spatrick 523061da546Spatrick CompilerType Function::GetCompilerType() { 524061da546Spatrick Type *function_type = GetType(); 525061da546Spatrick if (function_type) 526061da546Spatrick return function_type->GetFullCompilerType(); 527061da546Spatrick return CompilerType(); 528061da546Spatrick } 529061da546Spatrick 530061da546Spatrick uint32_t Function::GetPrologueByteSize() { 531061da546Spatrick if (m_prologue_byte_size == 0 && 532061da546Spatrick m_flags.IsClear(flagsCalculatedPrologueSize)) { 533061da546Spatrick m_flags.Set(flagsCalculatedPrologueSize); 534061da546Spatrick LineTable *line_table = m_comp_unit->GetLineTable(); 535061da546Spatrick uint32_t prologue_end_line_idx = 0; 536061da546Spatrick 537061da546Spatrick if (line_table) { 538061da546Spatrick LineEntry first_line_entry; 539061da546Spatrick uint32_t first_line_entry_idx = UINT32_MAX; 540061da546Spatrick if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), 541061da546Spatrick first_line_entry, 542061da546Spatrick &first_line_entry_idx)) { 543061da546Spatrick // Make sure the first line entry isn't already the end of the prologue 544061da546Spatrick addr_t prologue_end_file_addr = LLDB_INVALID_ADDRESS; 545061da546Spatrick addr_t line_zero_end_file_addr = LLDB_INVALID_ADDRESS; 546061da546Spatrick 547061da546Spatrick if (first_line_entry.is_prologue_end) { 548061da546Spatrick prologue_end_file_addr = 549061da546Spatrick first_line_entry.range.GetBaseAddress().GetFileAddress(); 550061da546Spatrick prologue_end_line_idx = first_line_entry_idx; 551061da546Spatrick } else { 552061da546Spatrick // Check the first few instructions and look for one that has 553061da546Spatrick // is_prologue_end set to true. 554061da546Spatrick const uint32_t last_line_entry_idx = first_line_entry_idx + 6; 555061da546Spatrick for (uint32_t idx = first_line_entry_idx + 1; 556061da546Spatrick idx < last_line_entry_idx; ++idx) { 557061da546Spatrick LineEntry line_entry; 558061da546Spatrick if (line_table->GetLineEntryAtIndex(idx, line_entry)) { 559061da546Spatrick if (line_entry.is_prologue_end) { 560061da546Spatrick prologue_end_file_addr = 561061da546Spatrick line_entry.range.GetBaseAddress().GetFileAddress(); 562061da546Spatrick prologue_end_line_idx = idx; 563061da546Spatrick break; 564061da546Spatrick } 565061da546Spatrick } 566061da546Spatrick } 567061da546Spatrick } 568061da546Spatrick 569061da546Spatrick // If we didn't find the end of the prologue in the line tables, then 570061da546Spatrick // just use the end address of the first line table entry 571061da546Spatrick if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) { 572061da546Spatrick // Check the first few instructions and look for one that has a line 573061da546Spatrick // number that's different than the first entry. 574061da546Spatrick uint32_t last_line_entry_idx = first_line_entry_idx + 6; 575061da546Spatrick for (uint32_t idx = first_line_entry_idx + 1; 576061da546Spatrick idx < last_line_entry_idx; ++idx) { 577061da546Spatrick LineEntry line_entry; 578061da546Spatrick if (line_table->GetLineEntryAtIndex(idx, line_entry)) { 579061da546Spatrick if (line_entry.line != first_line_entry.line) { 580061da546Spatrick prologue_end_file_addr = 581061da546Spatrick line_entry.range.GetBaseAddress().GetFileAddress(); 582061da546Spatrick prologue_end_line_idx = idx; 583061da546Spatrick break; 584061da546Spatrick } 585061da546Spatrick } 586061da546Spatrick } 587061da546Spatrick 588061da546Spatrick if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) { 589061da546Spatrick prologue_end_file_addr = 590061da546Spatrick first_line_entry.range.GetBaseAddress().GetFileAddress() + 591061da546Spatrick first_line_entry.range.GetByteSize(); 592061da546Spatrick prologue_end_line_idx = first_line_entry_idx; 593061da546Spatrick } 594061da546Spatrick } 595061da546Spatrick 596061da546Spatrick const addr_t func_start_file_addr = 597061da546Spatrick m_range.GetBaseAddress().GetFileAddress(); 598061da546Spatrick const addr_t func_end_file_addr = 599061da546Spatrick func_start_file_addr + m_range.GetByteSize(); 600061da546Spatrick 601061da546Spatrick // Now calculate the offset to pass the subsequent line 0 entries. 602061da546Spatrick uint32_t first_non_zero_line = prologue_end_line_idx; 603061da546Spatrick while (true) { 604061da546Spatrick LineEntry line_entry; 605061da546Spatrick if (line_table->GetLineEntryAtIndex(first_non_zero_line, 606061da546Spatrick line_entry)) { 607061da546Spatrick if (line_entry.line != 0) 608061da546Spatrick break; 609061da546Spatrick } 610061da546Spatrick if (line_entry.range.GetBaseAddress().GetFileAddress() >= 611061da546Spatrick func_end_file_addr) 612061da546Spatrick break; 613061da546Spatrick 614061da546Spatrick first_non_zero_line++; 615061da546Spatrick } 616061da546Spatrick 617061da546Spatrick if (first_non_zero_line > prologue_end_line_idx) { 618061da546Spatrick LineEntry first_non_zero_entry; 619061da546Spatrick if (line_table->GetLineEntryAtIndex(first_non_zero_line, 620061da546Spatrick first_non_zero_entry)) { 621061da546Spatrick line_zero_end_file_addr = 622061da546Spatrick first_non_zero_entry.range.GetBaseAddress().GetFileAddress(); 623061da546Spatrick } 624061da546Spatrick } 625061da546Spatrick 626061da546Spatrick // Verify that this prologue end file address in the function's address 627061da546Spatrick // range just to be sure 628061da546Spatrick if (func_start_file_addr < prologue_end_file_addr && 629061da546Spatrick prologue_end_file_addr < func_end_file_addr) { 630061da546Spatrick m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr; 631061da546Spatrick } 632061da546Spatrick 633061da546Spatrick if (prologue_end_file_addr < line_zero_end_file_addr && 634061da546Spatrick line_zero_end_file_addr < func_end_file_addr) { 635061da546Spatrick m_prologue_byte_size += 636061da546Spatrick line_zero_end_file_addr - prologue_end_file_addr; 637061da546Spatrick } 638061da546Spatrick } 639061da546Spatrick } 640061da546Spatrick } 641061da546Spatrick 642061da546Spatrick return m_prologue_byte_size; 643061da546Spatrick } 644061da546Spatrick 645061da546Spatrick lldb::LanguageType Function::GetLanguage() const { 646061da546Spatrick lldb::LanguageType lang = m_mangled.GuessLanguage(); 647061da546Spatrick if (lang != lldb::eLanguageTypeUnknown) 648061da546Spatrick return lang; 649061da546Spatrick 650061da546Spatrick if (m_comp_unit) 651061da546Spatrick return m_comp_unit->GetLanguage(); 652061da546Spatrick 653061da546Spatrick return lldb::eLanguageTypeUnknown; 654061da546Spatrick } 655061da546Spatrick 656061da546Spatrick ConstString Function::GetName() const { 657*dda28197Spatrick return m_mangled.GetName(); 658061da546Spatrick } 659061da546Spatrick 660061da546Spatrick ConstString Function::GetNameNoArguments() const { 661*dda28197Spatrick return m_mangled.GetName(Mangled::ePreferDemangledWithoutArguments); 662061da546Spatrick } 663