[lldb/DWARF] Don't create lldb_private::Functions for gc'ed DW_TAG_subprograms

Front-load the first_valid_code_address check, so that we avoid creating
the function object (instead of simply refusing to use it in queries).

Differential Revision: https://reviews.llvm.org/D112310
This commit is contained in:
Pavel Labath
2021-10-22 14:19:27 +02:00
parent 477551fd09
commit c1055f0919
5 changed files with 109 additions and 87 deletions

View File

@@ -32,7 +32,8 @@ public:
virtual lldb_private::Function *
ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit,
const DWARFDIE &die) = 0;
const DWARFDIE &die,
const lldb_private::AddressRange &range) = 0;
virtual bool
CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type,

View File

@@ -2342,8 +2342,11 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
return enumerators_added;
}
Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
const DWARFDIE &die) {
Function *
DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
const DWARFDIE &die,
const AddressRange &func_range) {
assert(func_range.GetBaseAddress().IsValid());
DWARFRangeList func_ranges;
const char *name = nullptr;
const char *mangled = nullptr;
@@ -2363,94 +2366,75 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line,
decl_column, call_file, call_line, call_column,
&frame_base)) {
Mangled func_name;
if (mangled)
func_name.SetValue(ConstString(mangled), true);
else if ((die.GetParent().Tag() == DW_TAG_compile_unit ||
die.GetParent().Tag() == DW_TAG_partial_unit) &&
Language::LanguageIsCPlusPlus(
SymbolFileDWARF::GetLanguage(*die.GetCU())) &&
!Language::LanguageIsObjC(
SymbolFileDWARF::GetLanguage(*die.GetCU())) &&
name && strcmp(name, "main") != 0) {
// If the mangled name is not present in the DWARF, generate the
// demangled name using the decl context. We skip if the function is
// "main" as its name is never mangled.
bool is_static = false;
bool is_variadic = false;
bool has_template_params = false;
unsigned type_quals = 0;
std::vector<CompilerType> param_types;
std::vector<clang::ParmVarDecl *> param_decls;
StreamString sstr;
// Union of all ranges in the function DIE (if the function is
// discontiguous)
AddressRange func_range;
lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0);
lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0);
if (lowest_func_addr != LLDB_INVALID_ADDRESS &&
lowest_func_addr <= highest_func_addr) {
ModuleSP module_sp(die.GetModule());
func_range.GetBaseAddress().ResolveAddressUsingFileSections(
lowest_func_addr, module_sp->GetSectionList());
if (func_range.GetBaseAddress().IsValid())
func_range.SetByteSize(highest_func_addr - lowest_func_addr);
}
DWARFDeclContext decl_ctx = SymbolFileDWARF::GetDWARFDeclContext(die);
sstr << decl_ctx.GetQualifiedName();
if (func_range.GetBaseAddress().IsValid()) {
Mangled func_name;
if (mangled)
func_name.SetValue(ConstString(mangled), true);
else if ((die.GetParent().Tag() == DW_TAG_compile_unit ||
die.GetParent().Tag() == DW_TAG_partial_unit) &&
Language::LanguageIsCPlusPlus(
SymbolFileDWARF::GetLanguage(*die.GetCU())) &&
!Language::LanguageIsObjC(
SymbolFileDWARF::GetLanguage(*die.GetCU())) &&
name && strcmp(name, "main") != 0) {
// If the mangled name is not present in the DWARF, generate the
// demangled name using the decl context. We skip if the function is
// "main" as its name is never mangled.
bool is_static = false;
bool is_variadic = false;
bool has_template_params = false;
unsigned type_quals = 0;
std::vector<CompilerType> param_types;
std::vector<clang::ParmVarDecl *> param_decls;
StreamString sstr;
clang::DeclContext *containing_decl_ctx =
GetClangDeclContextContainingDIE(die, nullptr);
ParseChildParameters(containing_decl_ctx, die, true, is_static,
is_variadic, has_template_params, param_types,
param_decls, type_quals);
sstr << "(";
for (size_t i = 0; i < param_types.size(); i++) {
if (i > 0)
sstr << ", ";
sstr << param_types[i].GetTypeName();
}
if (is_variadic)
sstr << ", ...";
sstr << ")";
if (type_quals & clang::Qualifiers::Const)
sstr << " const";
DWARFDeclContext decl_ctx = SymbolFileDWARF::GetDWARFDeclContext(die);
sstr << decl_ctx.GetQualifiedName();
func_name.SetValue(ConstString(sstr.GetString()), false);
} else
func_name.SetValue(ConstString(name), false);
clang::DeclContext *containing_decl_ctx =
GetClangDeclContextContainingDIE(die, nullptr);
ParseChildParameters(containing_decl_ctx, die, true, is_static,
is_variadic, has_template_params, param_types,
param_decls, type_quals);
sstr << "(";
for (size_t i = 0; i < param_types.size(); i++) {
if (i > 0)
sstr << ", ";
sstr << param_types[i].GetTypeName();
}
if (is_variadic)
sstr << ", ...";
sstr << ")";
if (type_quals & clang::Qualifiers::Const)
sstr << " const";
FunctionSP func_sp;
std::unique_ptr<Declaration> decl_up;
if (decl_file != 0 || decl_line != 0 || decl_column != 0)
decl_up = std::make_unique<Declaration>(die.GetCU()->GetFile(decl_file),
decl_line, decl_column);
func_name.SetValue(ConstString(sstr.GetString()), false);
} else
func_name.SetValue(ConstString(name), false);
SymbolFileDWARF *dwarf = die.GetDWARF();
// Supply the type _only_ if it has already been parsed
Type *func_type = dwarf->GetDIEToType().lookup(die.GetDIE());
FunctionSP func_sp;
std::unique_ptr<Declaration> decl_up;
if (decl_file != 0 || decl_line != 0 || decl_column != 0)
decl_up = std::make_unique<Declaration>(die.GetCU()->GetFile(decl_file),
decl_line, decl_column);
assert(func_type == nullptr || func_type != DIE_IS_BEING_PARSED);
SymbolFileDWARF *dwarf = die.GetDWARF();
// Supply the type _only_ if it has already been parsed
Type *func_type = dwarf->GetDIEToType().lookup(die.GetDIE());
assert(func_type == nullptr || func_type != DIE_IS_BEING_PARSED);
if (dwarf->FixupAddress(func_range.GetBaseAddress())) {
const user_id_t func_user_id = die.GetID();
func_sp =
std::make_shared<Function>(&comp_unit,
const user_id_t func_user_id = die.GetID();
func_sp =
std::make_shared<Function>(&comp_unit,
func_user_id, // UserID is the DIE offset
func_user_id, func_name, func_type,
func_range); // first address range
func_range); // first address range
if (func_sp.get() != nullptr) {
if (frame_base.IsValid())
func_sp->GetFrameBaseExpression() = frame_base;
comp_unit.AddFunction(func_sp);
return func_sp.get();
}
}
if (func_sp.get() != nullptr) {
if (frame_base.IsValid())
func_sp->GetFrameBaseExpression() = frame_base;
comp_unit.AddFunction(func_sp);
return func_sp.get();
}
}
return nullptr;

View File

@@ -47,7 +47,8 @@ public:
lldb_private::Function *
ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit,
const DWARFDIE &die) override;
const DWARFDIE &die,
const lldb_private::AddressRange &func_range) override;
bool
CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type,

View File

@@ -856,7 +856,32 @@ Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit,
if (!dwarf_ast)
return nullptr;
return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die);
DWARFRangeList ranges;
if (die.GetDIE()->GetAttributeAddressRanges(die.GetCU(), ranges,
/*check_hi_lo_pc=*/true) == 0)
return nullptr;
// Union of all ranges in the function DIE (if the function is
// discontiguous)
AddressRange func_range;
lldb::addr_t lowest_func_addr = ranges.GetMinRangeBase(0);
lldb::addr_t highest_func_addr = ranges.GetMaxRangeEnd(0);
if (lowest_func_addr == LLDB_INVALID_ADDRESS ||
lowest_func_addr >= highest_func_addr ||
lowest_func_addr < m_first_code_address)
return nullptr;
ModuleSP module_sp(die.GetModule());
func_range.GetBaseAddress().ResolveAddressUsingFileSections(
lowest_func_addr, module_sp->GetSectionList());
if (!func_range.GetBaseAddress().IsValid())
return nullptr;
func_range.SetByteSize(highest_func_addr - lowest_func_addr);
if (!FixupAddress(func_range.GetBaseAddress()))
return nullptr;
return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die, func_range);
}
lldb::addr_t SymbolFileDWARF::FixupAddress(lldb::addr_t file_addr) {
@@ -2263,10 +2288,8 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
addr = sc.function->GetAddressRange().GetBaseAddress();
}
if (addr.IsValid() && addr.GetFileAddress() >= m_first_code_address) {
sc_list.Append(sc);
return true;
}
sc_list.Append(sc);
return true;
}
return false;

View File

@@ -1,6 +1,16 @@
# RUN: yaml2obj %s > %t
# RUN: lldb-test symbols %t | FileCheck %s --check-prefix=TEST
# RUN: %lldb %t -o "image dump line-table a.c" -o "image lookup -n _start" -o "image lookup -n f" -o exit | FileCheck %s
# TEST: Compile units:
# TEST-NEXT: CompileUnit{0x00000000}, language = "c", file = 'a.c'
# TEST-NEXT: Function{0x00000043}, demangled = _start, type_uid = 0x00000043
# TEST-NEXT: Block{0x00000043}, ranges = [0x00000080-0x00000086)
# TEST-EMPTY:
# TEST-EMPTY:
# TEST-NEXT: Symtab
# CHECK-LABEL: image dump line-table a.c
# CHECK-NEXT: Line table for a.c
# CHECK-NEXT: 0x0000000000000080: a.c:1
@@ -59,6 +69,8 @@ DWARF:
Attributes:
- Attribute: DW_AT_producer
Form: DW_FORM_string
- Attribute: DW_AT_language
Form: DW_FORM_data1
- Attribute: DW_AT_name
Form: DW_FORM_string
- Attribute: DW_AT_stmt_list
@@ -86,6 +98,7 @@ DWARF:
- AbbrCode: 0x00000001
Values:
- CStr: Hand-written DWARF
- Value: 2
- CStr: a.c
- Value: 0x0000000000000000
- Value: 0x0000000000000000