[LLDB][Breakpad] Create a function for each compilation unit.

Since every FUNC record (in breakpad) is a compilation unit, creating the
function for the CU allows `ResolveSymbolContext` to resolve
`eSymbolContextFunction`.

Differential Revision: https://reviews.llvm.org/D113163
This commit is contained in:
Zequan Wu 2021-11-03 19:19:55 -07:00
parent 360d901bf0
commit fbf665a008
6 changed files with 83 additions and 20 deletions

View File

@ -219,9 +219,45 @@ CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) {
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<Function>(&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<std::recursive_mutex> guard(GetModuleMutex());
return GetOrCreateFunction(comp_unit) ? 1 : 0;
}
bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) {
@ -251,7 +287,8 @@ SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr,
SymbolContextItem resolve_scope,
SymbolContext &sc) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry)))
if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry |
eSymbolContextFunction)))
return 0;
ParseCUData();
@ -268,6 +305,13 @@ SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr,
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 @@ void SymbolFileBreakpad::FindFunctions(
ConstString name, const CompilerDeclContext &parent_decl_ctx,
FunctionNameType name_type_mask, bool include_inlines,
SymbolContextList &sc_list) {
// TODO
std::lock_guard<std::recursive_mutex> 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 &regex,
@ -346,11 +403,6 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {
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);

View File

@ -63,6 +63,8 @@ public:
return lldb::eLanguageTypeUnknown;
}
lldb::FunctionSP GetOrCreateFunction(CompileUnit &comp_unit);
size_t ParseFunctions(CompileUnit &comp_unit) override;
bool ParseLineTable(CompileUnit &comp_unit) override;

View File

@ -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

View File

@ -15,8 +15,8 @@ image list
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

View File

@ -39,7 +39,16 @@ image dump line-table d.c
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 = "<not loaded>", file = '/tmp/a.c'
# CHECK-NEXT: Function{0x00000000}, demangled = func, type_uid = 0x00000000
# CHECK: CompileUnit{0x00000001}, language = "<not loaded>", file = '/tmp/c.c'
# CHECK-NEXT: CompileUnit{0x00000002}, language = "<not loaded>", file = '/tmp/d.c'
# CHECK-NEXT: CompileUnit{0x00000003}, language = "<not loaded>", 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

View File

@ -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)