Index: lit/SymbolFile/PDB/Inputs/FunctionNestedBlockTest.cpp =================================================================== --- /dev/null +++ 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: lit/SymbolFile/PDB/function-nested-block.test =================================================================== --- /dev/null +++ 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: source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp =================================================================== --- source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ 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: tools/lldb-test/lldb-test.cpp =================================================================== --- tools/lldb-test/lldb-test.cpp +++ tools/lldb-test/lldb-test.cpp @@ -148,6 +148,11 @@ static cl::opt Verify("verify", cl::desc("Verify symbol information."), cl::sub(SymbolsSubcommand)); +static cl::opt File("file", cl::desc("Function search source file."), + cl::sub(SymbolsSubcommand)); +static cl::opt Line("line", cl::desc("Function search line number."), + cl::sub(SymbolsSubcommand)); + static Expected getDeclContext(SymbolVendor &Vendor); static Error findFunctions(lldb_private::Module &Module); @@ -326,7 +331,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; + uint32_t le_idx = 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); @@ -507,6 +537,24 @@ << "` is not a valid regular expression.\n"; return 1; } + if (!File.empty() && Line == 0 || File.empty() && Line != 0) + { + WithColor::error() << "Both the file and the line must be specified when " + "functions are searched with a source location.\n"; + return 1; + } + if (!File.empty() && Find != FindType::Function) + { + WithColor::error() << "Only functions can be searched " + "with a source location.\n"; + return 1; + } + if (!File.empty() && !Name.empty()) + { + WithColor::error() << "Cannot search for functions using both " + "a source location and a name.\n"; + return 1; + } Error (*Action)(lldb_private::Module &); if (!Verify) {