Index: lldb/trunk/lit/SymbolFile/PDB/Inputs/FunctionNestedBlockTest.cpp =================================================================== --- lldb/trunk/lit/SymbolFile/PDB/Inputs/FunctionNestedBlockTest.cpp +++ lldb/trunk/lit/SymbolFile/PDB/Inputs/FunctionNestedBlockTest.cpp @@ -0,0 +1,8 @@ +int main() { + auto r = 0; + for (auto i = 1; i <= 10; i++) { + r += i & 1 + (i - 1) & 1 - 1; + } + + return r; +} Index: lldb/trunk/lit/SymbolFile/PDB/function-nested-block.test =================================================================== --- lldb/trunk/lit/SymbolFile/PDB/function-nested-block.test +++ lldb/trunk/lit/SymbolFile/PDB/function-nested-block.test @@ -0,0 +1,7 @@ +REQUIRES: windows, lld +RUN: clang-cl /c /Zi %S/Inputs/FunctionNestedBlockTest.cpp /o %t.obj +RUN: lld-link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe +RUN: lldb-test symbols -find=function -file FunctionNestedBlockTest.cpp -line 4 %t.exe | FileCheck %s + +CHECK: Found 1 functions: +CHECK: name = "{{.*}}", mangled = "_main" Index: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -347,6 +347,11 @@ FileSpec spec(file->getFileName(), false, FileSpec::Style::windows); support_files.AppendIfUnique(spec); } + + // LLDB uses the DWARF-like file numeration (one based), + // the zeroth file is the compile unit itself + support_files.Insert(0, *sc.comp_unit); + return true; } @@ -596,12 +601,6 @@ resolve_scope & eSymbolContextFunction || resolve_scope & eSymbolContextBlock || resolve_scope & eSymbolContextLineEntry) { - addr_t file_vm_addr = so_addr.GetFileAddress(); - auto symbol_up = - m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::None); - if (!symbol_up) - return 0; - auto cu_sp = GetCompileUnitContainsAddress(so_addr); if (!cu_sp) { if (resolved_flags | eSymbolContextVariable) { @@ -612,39 +611,39 @@ sc.comp_unit = cu_sp.get(); resolved_flags |= eSymbolContextCompUnit; lldbassert(sc.module_sp == cu_sp->GetModule()); + } - switch (symbol_up->getSymTag()) { - case PDB_SymType::Function: - if (resolve_scope & eSymbolContextFunction) { - auto *pdb_func = llvm::dyn_cast(symbol_up.get()); - assert(pdb_func); - auto func_uid = pdb_func->getSymIndexId(); - sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get(); - if (sc.function == nullptr) - sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc); - if (sc.function) { - resolved_flags |= eSymbolContextFunction; - if (resolve_scope & eSymbolContextBlock) { - Block &block = sc.function->GetBlock(true); - sc.block = block.FindBlockByID(sc.function->GetID()); - if (sc.block) - resolved_flags |= eSymbolContextBlock; - } + if (resolve_scope & eSymbolContextFunction) { + addr_t file_vm_addr = so_addr.GetFileAddress(); + auto symbol_up = + m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::Function); + if (symbol_up) { + auto *pdb_func = llvm::dyn_cast(symbol_up.get()); + assert(pdb_func); + auto func_uid = pdb_func->getSymIndexId(); + sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get(); + if (sc.function == nullptr) + sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc); + if (sc.function) { + resolved_flags |= eSymbolContextFunction; + if (resolve_scope & eSymbolContextBlock) { + Block &block = sc.function->GetBlock(true); + sc.block = block.FindBlockByID(sc.function->GetID()); + if (sc.block) + resolved_flags |= eSymbolContextBlock; } } - break; - default: - break; } + } - if (resolve_scope & eSymbolContextLineEntry) { - if (auto *line_table = sc.comp_unit->GetLineTable()) { - Address addr(so_addr); - if (line_table->FindLineEntryByAddress(addr, sc.line_entry)) - resolved_flags |= eSymbolContextLineEntry; - } + if (resolve_scope & eSymbolContextLineEntry) { + if (auto *line_table = sc.comp_unit->GetLineTable()) { + Address addr(so_addr); + if (line_table->FindLineEntryByAddress(addr, sc.line_entry)) + resolved_flags |= eSymbolContextLineEntry; } } + return resolved_flags; } @@ -1631,7 +1630,9 @@ auto source_files = m_session_up->getSourceFilesForCompiland(compiland); if (!source_files) return; - int index = 0; + + // LLDB uses the DWARF-like file numeration (one based) + int index = 1; while (auto file = source_files->getNext()) { uint32_t source_id = file->getUniqueId(); Index: lldb/trunk/tools/lldb-test/lldb-test.cpp =================================================================== --- lldb/trunk/tools/lldb-test/lldb-test.cpp +++ lldb/trunk/tools/lldb-test/lldb-test.cpp @@ -35,8 +35,8 @@ #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" @@ -108,8 +108,7 @@ static cl::opt Find( "find", cl::desc("Choose search type:"), cl::values( - clEnumValN(FindType::None, "none", - "No search, just dump the module."), + clEnumValN(FindType::None, "none", "No search, just dump the module."), clEnumValN(FindType::Function, "function", "Find functions."), clEnumValN(FindType::Namespace, "namespace", "Find namespaces."), clEnumValN(FindType::Type, "type", "Find types."), @@ -151,6 +150,8 @@ static cl::opt File("file", cl::desc("File (compile unit) to search."), cl::sub(SymbolsSubcommand)); +static cl::opt Line("line", cl::desc("Line to search."), + cl::sub(SymbolsSubcommand)); static Expected getDeclContext(SymbolVendor &Vendor); @@ -163,7 +164,7 @@ static Expected getAction(); static int dumpSymbols(Debugger &Dbg); -} +} // namespace symbols namespace irmemorymap { static cl::opt Target(cl::Positional, cl::desc(""), @@ -179,7 +180,7 @@ using AllocationT = std::pair; using AddrIntervalMap = - IntervalMap>; + IntervalMap>; struct IRMemoryMapTestState { TargetSP Target; @@ -334,7 +335,32 @@ Error opts::symbols::findFunctions(lldb_private::Module &Module) { SymbolVendor &Vendor = *Module.GetSymbolVendor(); SymbolContextList List; - if (Regex) { + if (!File.empty()) { + assert(Line != 0); + + FileSpec src_file(File, false); + size_t cu_count = Module.GetNumCompileUnits(); + for (size_t i = 0; i < cu_count; i++) { + lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i); + if (!cu_sp) + continue; + + LineEntry le; + cu_sp->FindLineEntry(0, Line, &src_file, false, &le); + if (!le.IsValid()) + continue; + + auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress(); + if (!addr.IsValid()) + continue; + + SymbolContext sc; + uint32_t resolved = + addr.CalculateSymbolContext(&sc, eSymbolContextFunction); + if (resolved & eSymbolContextFunction) + List.Append(sc); + } + } else if (Regex) { RegularExpression RE(Name); assert(RE.IsValid()); Vendor.FindFunctions(RE, true, false, List); @@ -346,7 +372,7 @@ ContextOr->IsValid() ? &*ContextOr : nullptr; Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(), - true, false, List); + true, false, List); } outs() << formatv("Found {0} functions:\n", List.GetSize()); StreamString Stream; @@ -386,7 +412,7 @@ DenseSet SearchedFiles; TypeMap Map; Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX, - SearchedFiles, Map); + SearchedFiles, Map); outs() << formatv("Found {0} types:\n", Map.GetSize()); StreamString Stream; @@ -458,8 +484,8 @@ if (!comp_unit) return make_string_error("Connot parse compile unit {0}.", i); - outs() << "Processing '" << comp_unit->GetFilename().AsCString() << - "' compile unit.\n"; + outs() << "Processing '" << comp_unit->GetFilename().AsCString() + << "' compile unit.\n"; LineTable *lt = comp_unit->GetLineTable(); if (!lt) @@ -478,7 +504,7 @@ for (uint32_t i = 1; i < count; i++) { lldb::addr_t curr_end = - le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize(); + le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize(); if (!lt->GetLineEntryAtIndex(i, le)) return make_string_error("Can't get a line entry of a compile unit"); @@ -499,9 +525,11 @@ if (Find != FindType::None) return make_string_error( "Cannot both search and verify symbol information."); - if (Regex || !Context.empty() || !Name.empty() || !File.empty()) - return make_string_error("-regex, -context, -name and -file options are not " - "applicable for symbol verification."); + if (Regex || !Context.empty() || !Name.empty() || !File.empty() || + Line != 0) + return make_string_error( + "-regex, -context, -name, -file and -line options are not " + "applicable for symbol verification."); return verify; } @@ -520,32 +548,38 @@ switch (Find) { case FindType::None: - if (!Context.empty() || !Name.empty() || !File.empty()) + if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0) return make_string_error( "Specify search type (-find) to use search options."); return dumpModule; case FindType::Function: - if (!File.empty()) - return make_string_error("Cannot search for functions by file name."); - if (Regex && getFunctionNameFlags() != 0) - return make_string_error("Cannot search for functions using both regular " - "expressions and function-flags."); + if (!File.empty() + (Line != 0) == 1) + return make_string_error("Both file name and line number must be " + "specified when searching a function " + "by file position."); + if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2) + return make_string_error("Only one of regular expression, function-flags " + "and file position may be used simultaneously " + "when searching a function."); return findFunctions; case FindType::Namespace: - if (Regex || !File.empty()) + if (Regex || !File.empty() || Line != 0) return make_string_error("Cannot search for namespaces using regular " - "expressions or file names."); + "expressions, file names or line numbers."); return findNamespaces; case FindType::Type: - if (Regex || !File.empty()) + if (Regex || !File.empty() || Line != 0) return make_string_error("Cannot search for types using regular " - "expressions or file names."); + "expressions, file names or line numbers."); return findTypes; case FindType::Variable: + if (Line != 0) + return make_string_error("Cannot search for variables " + "using line numbers."); return findVariables; } }