diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h --- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h +++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h @@ -63,6 +63,8 @@ return lldb::eLanguageTypeUnknown; } + lldb::FunctionSP GetOrCreateFunction(CompileUnit &comp_unit); + size_t ParseFunctions(CompileUnit &comp_unit) override; bool ParseLineTable(CompileUnit &comp_unit) override; diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp --- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -219,9 +219,45 @@ return cu_sp; } +FunctionSP SymbolFileBreakpad::GetOrCreateFunction(CompileUnit &comp_unit) { + user_id_t id = comp_unit.GetID(); + if (FunctionSP func_sp = comp_unit.FindFunctionByUID(id)) + return func_sp; + + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); + FunctionSP func_sp; + addr_t base = GetBaseFileAddress(); + if (base == LLDB_INVALID_ADDRESS) { + LLDB_LOG(log, "Unable to fetch the base address of object file. Skipping " + "symtab population."); + return func_sp; + } + + const SectionList *list = comp_unit.GetModule()->GetSectionList(); + CompUnitData &data = m_cu_data->GetEntryRef(id).data; + LineIterator It(*m_objfile_sp, Record::Func, data.bookmark); + assert(Record::classify(*It) == Record::Func); + + if (auto record = FuncRecord::parse(*It)) { + Mangled func_name; + func_name.SetValue(ConstString(record->Name), false); + addr_t address = record->Address + base; + SectionSP section_sp = list->FindSectionContainingFileAddress(address); + if (section_sp) { + AddressRange func_range( + section_sp, address - section_sp->GetFileAddress(), record->Size); + // Use the CU's id because every CU has only one function inside. + func_sp = std::make_shared(&comp_unit, id, 0, func_name, + nullptr, func_range); + comp_unit.AddFunction(func_sp); + } + } + return func_sp; +} + size_t SymbolFileBreakpad::ParseFunctions(CompileUnit &comp_unit) { - // TODO - return 0; + std::lock_guard guard(GetModuleMutex()); + return GetOrCreateFunction(comp_unit) ? 1 : 0; } bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) { @@ -251,7 +287,8 @@ SymbolContextItem resolve_scope, SymbolContext &sc) { std::lock_guard guard(GetModuleMutex()); - if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry))) + if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry | + eSymbolContextFunction))) return 0; ParseCUData(); @@ -268,6 +305,13 @@ result |= eSymbolContextLineEntry; } } + if (resolve_scope & eSymbolContextFunction) { + FunctionSP func_sp = GetOrCreateFunction(*sc.comp_unit); + if (func_sp) { + sc.function = func_sp.get(); + result |= eSymbolContextFunction; + } + } return result; } @@ -291,7 +335,20 @@ ConstString name, const CompilerDeclContext &parent_decl_ctx, FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) { - // TODO + std::lock_guard guard(GetModuleMutex()); + // TODO: Implement this with supported FunctionNameType. + + for (uint32_t i = 0; i < GetNumCompileUnits(); ++i) { + CompUnitSP cu_sp = GetCompileUnitAtIndex(i); + FunctionSP func_sp = GetOrCreateFunction(*cu_sp); + if (func_sp && name == func_sp->GetNameNoArguments()) { + SymbolContext sc; + sc.comp_unit = cu_sp.get(); + sc.function = func_sp.get(); + sc.module_sp = func_sp->CalculateSymbolContextModule(); + sc_list.Append(sc); + } + } } void SymbolFileBreakpad::FindFunctions(const RegularExpression ®ex, @@ -346,11 +403,6 @@ size.hasValue(), /*contains_linker_annotations*/ false, /*flags*/ 0); }; - for (llvm::StringRef line : lines(Record::Func)) { - if (auto record = FuncRecord::parse(line)) - add_symbol(record->Address, record->Size, record->Name); - } - for (llvm::StringRef line : lines(Record::Public)) { if (auto record = PublicRecord::parse(line)) add_symbol(record->Address, llvm::None, record->Name); diff --git a/lldb/test/Shell/Minidump/Inputs/linux-x86_64.syms b/lldb/test/Shell/Minidump/Inputs/linux-x86_64.syms --- a/lldb/test/Shell/Minidump/Inputs/linux-x86_64.syms +++ b/lldb/test/Shell/Minidump/Inputs/linux-x86_64.syms @@ -1,4 +1,4 @@ MODULE Linux x86_64 3B285CE327C387C262DB788BF5A4078B0 linux-x86_64 INFO CODE_ID E35C283BC327C28762DB788BF5A4078BE2351448 -FUNC 3d0 18 0 crash() -FUNC 3f0 10 0 _start +PUBLIC 3d0 0 crash() +PUBLIC 3f0 0 _start diff --git a/lldb/test/Shell/Minidump/breakpad-symbols.test b/lldb/test/Shell/Minidump/breakpad-symbols.test --- a/lldb/test/Shell/Minidump/breakpad-symbols.test +++ b/lldb/test/Shell/Minidump/breakpad-symbols.test @@ -15,8 +15,8 @@ image dump symtab /tmp/test/linux-x86_64 # CHECK-LABEL: image dump symtab /tmp/test/linux-x86_64 # CHECK: Symtab, file = /tmp/test/linux-x86_64, num_symbols = 2: -# CHECK: [ 0] 0 X Code 0x00000000004003d0 0x00000000004003d0 0x0000000000000018 0x00000000 crash() -# CHECK: [ 1] 0 X Code 0x00000000004003f0 0x00000000004003f0 0x0000000000000010 0x00000000 _start +# CHECK: [ 0] 0 X Code 0x00000000004003d0 0x00000000004003d0 0x0000000000000020 0x00000000 crash() +# CHECK: [ 1] 0 X Code 0x00000000004003f0 0x00000000004003f0 0x0000000000000c10 0x00000000 _start image lookup -a 0x4003f3 # CHECK-LABEL: image lookup -a 0x4003f3 diff --git a/lldb/test/Shell/SymbolFile/Breakpad/line-table.test b/lldb/test/Shell/SymbolFile/Breakpad/line-table.test --- a/lldb/test/Shell/SymbolFile/Breakpad/line-table.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/line-table.test @@ -39,7 +39,16 @@ image lookup -a 0x4000b2 -v # CHECK-LABEL: image lookup -a 0x4000b2 -v # CHECK: Summary: line-table.out`func + 2 +# CHECK: Function: id = {0x00000000}, name = "func", range = [0x00000000004000b0-0x00000000004000c0) + +image dump symfile +# CHECK-LABEL: Compile units: +# CHECK-NEXT: CompileUnit{0x00000000}, language = "", file = '/tmp/a.c' +# CHECK-NEXT: Function{0x00000000}, demangled = func, type_uid = 0x00000000 +# CHECK: CompileUnit{0x00000001}, language = "", file = '/tmp/c.c' +# CHECK-NEXT: CompileUnit{0x00000002}, language = "", file = '/tmp/d.c' +# CHECK-NEXT: CompileUnit{0x00000003}, language = "", file = '/tmp/d.c' breakpoint set -f c.c -l 2 # CHECK-LABEL: breakpoint set -f c.c -l 2 -# CHECK: Breakpoint 1: where = line-table.out`func + 2, address = 0x00000000004000b2 +# CHECK: Breakpoint 1: where = line-table.out`func + 2 at c.c:2, address = 0x00000000004000b2 diff --git a/lldb/test/Shell/SymbolFile/Breakpad/symtab.test b/lldb/test/Shell/SymbolFile/Breakpad/symtab.test --- a/lldb/test/Shell/SymbolFile/Breakpad/symtab.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/symtab.test @@ -3,17 +3,17 @@ # RUN: -s %s | FileCheck %s # CHECK-LABEL: (lldb) image dump symtab symtab.out -# CHECK: Symtab, file = {{.*}}symtab.out, num_symbols = 5: +# CHECK: Symtab, file = {{.*}}symtab.out, num_symbols = 4: # CHECK: Index UserID DSX Type File Address/Value Load Address Size Flags Name # CHECK: [ 0] 0 SX Code 0x0000000000400000 0x00000000000000b0 0x00000000 ___lldb_unnamed_symbol{{[0-9]*}} -# CHECK: [ 1] 0 X Code 0x00000000004000b0 0x000000000000000c 0x00000000 f1_func -# CHECK: [ 2] 0 X Code 0x00000000004000a0 0x000000000000000d 0x00000000 func_only -# CHECK: [ 3] 0 X Code 0x00000000004000c0 0x0000000000000010 0x00000000 f2 -# CHECK: [ 4] 0 X Code 0x00000000004000d0 0x0000000000000022 0x00000000 _start +# CHECK: [ 1] 0 X Code 0x00000000004000b0 0x0000000000000010 0x00000000 f1 +# CHECK: [ 2] 0 X Code 0x00000000004000c0 0x0000000000000010 0x00000000 f2 +# CHECK: [ 3] 0 X Code 0x00000000004000d0 0x0000000000000022 0x00000000 _start # CHECK-LABEL: (lldb) image lookup -a 0x4000b0 -v # CHECK: Address: symtab.out[0x00000000004000b0] (symtab.out.PT_LOAD[0]..text2 + 0) -# CHECK: Symbol: id = {0x00000000}, range = [0x00000000004000b0-0x00000000004000bc), name="f1_func" +# CHECK: Function: id = {0x00000001}, name = "f1_func", range = [0x00000000004000b0-0x00000000004000bc) +# CHECK: Symbol: id = {0x00000000}, range = [0x00000000004000b0-0x00000000004000c0), name="f1" # CHECK-LABEL: (lldb) image lookup -n f2 -v # CHECK: Address: symtab.out[0x00000000004000c0] (symtab.out.PT_LOAD[0]..text2 + 16)