From b281480203663a1add8248f400947b8d23db9509 Mon Sep 17 00:00:00 2001 From: Sean Callanan Date: Fri, 12 Feb 2016 21:11:25 +0000 Subject: [PATCH] Centralized symbol lookup in IRExecutionUnit, and fixed the code model. I'm preparing to remove symbol lookup from IRForTarget, where it constitutes a dreadful hack working around no-longer-existing JIT bugs. Thanks to our contributors, IRForTarget has a lot of smarts that IRExecutionUnit doesn't have, so I've cleaned them up a bit and moved them over to IRExecutionUnit. Also for historical reasons, IRExecutionUnit used the "Small" code model on non- ELF platforms (namely, OS X). That's no longer necessary, and we can use the same code model as everyone else on OS X. I've fixed that. llvm-svn: 260734 --- lldb/include/lldb/Expression/IRExecutionUnit.h | 15 +- lldb/source/Expression/IRExecutionUnit.cpp | 391 +++++++++++++++++---- .../Clang/ClangExpressionParser.cpp | 12 + 3 files changed, 348 insertions(+), 70 deletions(-) diff --git a/lldb/include/lldb/Expression/IRExecutionUnit.h b/lldb/include/lldb/Expression/IRExecutionUnit.h index 86744b7..c043bc1 100644 --- a/lldb/include/lldb/Expression/IRExecutionUnit.h +++ b/lldb/include/lldb/Expression/IRExecutionUnit.h @@ -28,6 +28,7 @@ #include "lldb/Expression/IRMemoryMap.h" #include "lldb/Host/Mutex.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" namespace llvm { @@ -71,6 +72,7 @@ public: std::unique_ptr &module_ap, ConstString &name, const lldb::TargetSP &target_sp, + const SymbolContext &sym_ctx, std::vector &cpu_features); //------------------------------------------------------------------ @@ -131,7 +133,16 @@ public: lldb::ModuleSP GetJITModule (); + + static lldb::addr_t + FindSymbol(const ConstString &name, + const SymbolContext &sc); + lldb::addr_t + FindSymbol(const ConstString &name) + { + return FindSymbol(name, m_sym_ctx); + } private: //------------------------------------------------------------------ /// Look up the object in m_address_map that contains a given address, @@ -275,9 +286,6 @@ private: void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override { } - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ uint64_t getSymbolAddress(const std::string &Name) override; void *getPointerToNamedFunction(const std::string &Name, @@ -387,6 +395,7 @@ private: std::vector m_cpu_features; llvm::SmallVector m_jitted_functions; ///< A vector of all functions that have been JITted into machine code const ConstString m_name; + SymbolContext m_sym_ctx; ///< Used for symbol lookups std::vector m_failed_lookups; std::atomic m_did_jit; diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 3f19c50..e962f2e 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -20,18 +20,24 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" +#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/../../source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" + using namespace lldb_private; IRExecutionUnit::IRExecutionUnit (std::unique_ptr &context_ap, std::unique_ptr &module_ap, ConstString &name, const lldb::TargetSP &target_sp, + const SymbolContext &sym_ctx, std::vector &cpu_features) : IRMemoryMap(target_sp), m_context_ap(context_ap.release()), @@ -39,6 +45,7 @@ IRExecutionUnit::IRExecutionUnit (std::unique_ptr &context_ap m_module(m_module_ap.get()), m_cpu_features(cpu_features), m_name(name), + m_sym_ctx(sym_ctx), m_did_jit(false), m_function_load_addr(LLDB_INVALID_ADDRESS), m_function_end_load_addr(LLDB_INVALID_ADDRESS) @@ -285,14 +292,14 @@ IRExecutionUnit::GetRunnableInfo(Error &error, if (triple.isOSBinFormatELF()) { relocModel = llvm::Reloc::Static; - // This will be small for 32-bit and large for 64-bit. - codeModel = llvm::CodeModel::JITDefault; } else { relocModel = llvm::Reloc::PIC_; - codeModel = llvm::CodeModel::Small; } + + // This will be small for 32-bit and large for 64-bit. + codeModel = llvm::CodeModel::JITDefault; m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error); @@ -637,94 +644,344 @@ IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size, return return_value; } -uint64_t -IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) +static void +FindCodeSymbolInContext(const ConstString &name, + const SymbolContext &sym_ctx, + uint32_t name_type_mask, + SymbolContextList &sc_list) { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - SymbolContextList sc_list; - - ExecutionContextScope *exe_scope = m_parent.GetBestExecutionContextScope(); - - lldb::TargetSP target_sp = exe_scope->CalculateTarget(); - - const char *name = Name.c_str(); + sc_list.Clear(); + SymbolContextList temp_sc_list; + if (sym_ctx.module_sp) + sym_ctx.module_sp->FindFunctions(name, + NULL, + name_type_mask, + true, // include_symbols + false, // include_inlines + true, // append + temp_sc_list); + if (temp_sc_list.GetSize() == 0) + { + if (sym_ctx.target_sp) + sym_ctx.target_sp->GetImages().FindFunctions(name, + name_type_mask, + true, // include_symbols + false, // include_inlines + true, // append + temp_sc_list); + } + + SymbolContextList internal_symbol_sc_list; + unsigned temp_sc_list_size = temp_sc_list.GetSize(); + for (unsigned i = 0; i < temp_sc_list_size; i++) + { + SymbolContext sc; + temp_sc_list.GetContextAtIndex(i, sc); + if (sc.function) + { + sc_list.Append(sc); + } + else if (sc.symbol) + { + if (sc.symbol->IsExternal()) + { + sc_list.Append(sc); + } + else + { + internal_symbol_sc_list.Append(sc); + } + } + } + + // If we had internal symbols and we didn't find any external symbols or + // functions in debug info, then fallback to the internal symbols + if (sc_list.GetSize() == 0 && internal_symbol_sc_list.GetSize()) + { + sc_list = internal_symbol_sc_list; + } +} + +static ConstString +FindBestAlternateMangledName(const ConstString &demangled, + const lldb::LanguageType &lang_type, + const SymbolContext &sym_ctx) +{ + CPlusPlusLanguage::MethodName cpp_name(demangled); + std::string scope_qualified_name = cpp_name.GetScopeQualifiedName(); + + if (!scope_qualified_name.size()) + return ConstString(); + + if (!sym_ctx.module_sp) + return ConstString(); + + SymbolVendor *sym_vendor = sym_ctx.module_sp->GetSymbolVendor(); + if (!sym_vendor) + return ConstString(); + + lldb_private::SymbolFile *sym_file = sym_vendor->GetSymbolFile(); + if (!sym_file) + return ConstString(); + + std::vector alternates; + sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates); + + std::vector param_and_qual_matches; + std::vector param_matches; + for (size_t i = 0; i < alternates.size(); i++) + { + ConstString alternate_mangled_name = alternates[i]; + Mangled mangled(alternate_mangled_name, true); + ConstString demangled = mangled.GetDemangledName(lang_type); + + CPlusPlusLanguage::MethodName alternate_cpp_name(demangled); + if (!cpp_name.IsValid()) + continue; + + if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments()) + { + if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers()) + param_and_qual_matches.push_back(alternate_mangled_name); + else + param_matches.push_back(alternate_mangled_name); + } + } + + if (param_and_qual_matches.size()) + return param_and_qual_matches[0]; // It is assumed that there will be only one! + else if (param_matches.size()) + return param_matches[0]; // Return one of them as a best match + else + return ConstString(); +} + +struct SearchSpec +{ + ConstString name; + uint32_t mask; + + SearchSpec(ConstString n, uint32_t m = lldb::eFunctionNameTypeAuto) : + name(n), + mask(m) + { + } +}; + +static void +CollectCandidateCNames(std::vector &C_specs, const ConstString &name) +{ + C_specs.push_back(SearchSpec(name)); + if (name.AsCString()[0] == '_') + C_specs.push_back(ConstString(&name.AsCString()[1])); +} + +static void +CollectCandidateCPlusPlusNames(std::vector &CPP_specs, const std::vector &C_specs, const SymbolContext &sc) +{ + for (const SearchSpec &C_spec : C_specs) + { + const ConstString &name = C_spec.name; + + if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) + { + Mangled mangled(name, true); + ConstString demangled = mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus); + + if (demangled) + { + ConstString best_alternate_mangled_name = FindBestAlternateMangledName(demangled, lldb::eLanguageTypeC_plus_plus, sc); + + if (best_alternate_mangled_name) + { + CPP_specs.push_back(best_alternate_mangled_name); + } + + CPP_specs.push_back(SearchSpec(demangled, lldb::eFunctionNameTypeFull)); + } + } + + // Maybe we're looking for a const symbol but the debug info told us it was const... + if (!strncmp(name.GetCString(), "_ZN", 3) && + strncmp(name.GetCString(), "_ZNK", 4)) + { + std::string fixed_scratch("_ZNK"); + fixed_scratch.append(name.GetCString() + 3); + CPP_specs.push_back(ConstString(fixed_scratch.c_str())); + } + + // Maybe we're looking for a static symbol but we thought it was global... + if (!strncmp(name.GetCString(), "_Z", 2) && + strncmp(name.GetCString(), "_ZL", 3)) + { + std::string fixed_scratch("_ZL"); + fixed_scratch.append(name.GetCString() + 2); + CPP_specs.push_back(ConstString(fixed_scratch.c_str())); + } + + } +} + +static lldb::addr_t +FindInSymbols(const std::vector &specs, const lldb_private::SymbolContext &sc) +{ + for (const SearchSpec &spec : specs) + { + SymbolContextList sc_list; + + if (sc.module_sp) + { + sc.module_sp->FindFunctions(spec.name, + NULL, + spec.mask, + true, // include_symbols + false, // include_inlines + true, // append + sc_list); + } - ConstString bare_name_cs(name); - ConstString name_cs; + if (sc_list.GetSize() == 0 && sc.target_sp) + { + sc.target_sp->GetImages().FindFunctions(spec.name, + spec.mask, + true, // include_symbols + false, // include_inlines + true, // append + sc_list); + } + + if (sc_list.GetSize() == 0 && sc.target_sp) + { + sc.target_sp->GetImages().FindSymbolsWithNameAndType(spec.name, lldb::eSymbolTypeAny, sc_list); + } + + lldb::addr_t best_internal_load_address = LLDB_INVALID_ADDRESS; + + for (size_t si = 0, se = sc_list.GetSize(); si < se; ++si) + { + bool is_external = false; + + SymbolContext candidate_sc; + + sc_list.GetContextAtIndex(si, candidate_sc); + if (candidate_sc.function) + { + is_external = true; + } + else if (sc.symbol) + { + if (sc.symbol->IsExternal()) + { + is_external = true; + } + } + + lldb::addr_t load_address = candidate_sc.symbol->ResolveCallableAddress(*sc.target_sp); + + if (load_address == LLDB_INVALID_ADDRESS) + load_address = candidate_sc.symbol->GetAddress().GetLoadAddress(sc.target_sp.get()); + + if (load_address != LLDB_INVALID_ADDRESS) + { + if (is_external) + { + return load_address; + } + else + { + best_internal_load_address = load_address; + } + } + } + if (best_internal_load_address != LLDB_INVALID_ADDRESS) + { + return best_internal_load_address; + } + } - if (name[0] == '_') - name_cs = ConstString(name + 1); + return LLDB_INVALID_ADDRESS; +} + +static lldb::addr_t +FindInRuntimes(const std::vector &specs, const lldb_private::SymbolContext &sc) +{ + lldb::TargetSP target_sp = sc.target_sp; if (!target_sp) { - if (log) - log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = ", - Name.c_str()); - - m_parent.ReportSymbolLookupError(name_cs); - - return 0xbad0bad0; + return LLDB_INVALID_ADDRESS; } - uint32_t num_matches = 0; - lldb::ProcessSP process_sp = exe_scope->CalculateProcess(); + lldb::ProcessSP process_sp = sc.target_sp->GetProcessSP(); - if (!name_cs.IsEmpty()) + if (!process_sp) { - target_sp->GetImages().FindSymbolsWithNameAndType(name_cs, lldb::eSymbolTypeAny, sc_list); - num_matches = sc_list.GetSize(); + return LLDB_INVALID_ADDRESS; } - - if (!num_matches) + + ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime(); + + if (runtime) { - target_sp->GetImages().FindSymbolsWithNameAndType(bare_name_cs, lldb::eSymbolTypeAny, sc_list); - num_matches = sc_list.GetSize(); + for (const SearchSpec &spec : specs) + { + lldb::addr_t symbol_load_addr = runtime->LookupRuntimeSymbol(spec.name); + + if (symbol_load_addr != LLDB_INVALID_ADDRESS) + return symbol_load_addr; + } } - - lldb::addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; - for (uint32_t i=0; iResolveCallableAddress(*target_sp); + return LLDB_INVALID_ADDRESS; +} - if (symbol_load_addr == LLDB_INVALID_ADDRESS) - symbol_load_addr = sym_ctx.symbol->GetAddress().GetLoadAddress(target_sp.get()); - } +lldb::addr_t +IRExecutionUnit::FindSymbol(const lldb_private::ConstString &name, const lldb_private::SymbolContext &sc) +{ + std::vector candidate_C_names; + std::vector candidate_CPlusPlus_names; - if (symbol_load_addr == LLDB_INVALID_ADDRESS && process_sp && name_cs) + CollectCandidateCNames(candidate_C_names, name); + + lldb::addr_t ret = FindInSymbols(candidate_C_names, sc); + if (ret == LLDB_INVALID_ADDRESS) + ret = FindInRuntimes(candidate_C_names, sc); + + if (ret == LLDB_INVALID_ADDRESS) { - // Try the Objective-C language runtime. - - ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime(); - - if (runtime) - symbol_load_addr = runtime->LookupRuntimeSymbol(name_cs); + CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names, sc); + ret = FindInSymbols(candidate_CPlusPlus_names, sc); } - if (symbol_load_addr == LLDB_INVALID_ADDRESS) + return ret; +} + +uint64_t +IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + ConstString name_cs(Name.c_str()); + + lldb::addr_t ret = m_parent.FindSymbol(name_cs); + + if (ret == LLDB_INVALID_ADDRESS) { if (log) log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = ", - name); - - m_parent.ReportSymbolLookupError(bare_name_cs); - + Name.c_str()); + + m_parent.ReportSymbolLookupError(name_cs); return 0xbad0bad0; } - - if (log) - log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64, - name, - symbol_load_addr); - - if (symbol_load_addr == 0) - return 0xbad00add; - - return symbol_load_addr; + else + { + if (log) + log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64, + Name.c_str(), + ret); + return ret; + } } void * diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 01a155a..db75126 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -612,11 +612,23 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, if (log) log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); } + + SymbolContext sc; + + if (lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP()) + { + sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything); + } + else if (lldb::TargetSP target_sp = exe_ctx.GetTargetSP()) + { + sc.target_sp = target_sp; + } execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here llvm_module_ap, // handed off here function_name, exe_ctx.GetTargetSP(), + sc, m_compiler->getTargetOpts().Features)); ClangExpressionHelper *type_system_helper = dyn_cast(m_expr.GetTypeSystemHelper()); -- 2.7.4