diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -859,6 +859,8 @@ /// Update the ArchSpec to a more specific variant. bool MergeArchitecture(const ArchSpec &arch_spec); + bool HaveSectionAtAddressZero(); + /// \class LookupInfo Module.h "lldb/Core/Module.h" /// A class that encapsulates name lookup information. /// @@ -977,6 +979,7 @@ std::atomic m_did_load_objfile{false}; std::atomic m_did_load_symfile{false}; std::atomic m_did_set_uuid{false}; + bool m_have_section_at_address_zero{false}; mutable bool m_file_has_changed : 1, m_first_file_changed_log : 1; /// See if the module was modified after it /// was initially opened. diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -1256,10 +1256,21 @@ ObjectFile *obj_file = GetObjectFile(); if (obj_file != nullptr) obj_file->CreateSections(*GetUnifiedSectionList()); + for (const auto &Section : *m_sections_up) { + if (Section->GetFileOffset() == 0) { + m_have_section_at_address_zero = true; + break; + } + } } return m_sections_up.get(); } +bool Module::HaveSectionAtAddressZero() { + GetSectionList(); + return m_have_section_at_address_zero; +} + void Module::SectionFileAddressesChanged() { ObjectFile *obj_file = GetObjectFile(); if (obj_file) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2355,6 +2355,9 @@ std::vector dies; m_index->GetFunctions(name, *this, *parent_decl_ctx, name_type_mask, dies); for (const DWARFDIE &die : dies) { + if (die.GetAttributeValueAsAddress(DW_AT_low_pc, /*fail_value=*/1) == 0 && + !GetObjectFile()->GetModule()->HaveSectionAtAddressZero()) + continue; if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); } diff --git a/lldb/test/Shell/Expr/Inputs/function-address-lib.cpp b/lldb/test/Shell/Expr/Inputs/function-address-lib.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Expr/Inputs/function-address-lib.cpp @@ -0,0 +1,4 @@ +#include "function-address-shared.h" +void (*ErrorHandler)(); +void LLVMErrorHandler() { TinyVector().clear(); } +void SetErrorHandler() { ErrorHandler = LLVMErrorHandler; } diff --git a/lldb/test/Shell/Expr/Inputs/function-address-main.cpp b/lldb/test/Shell/Expr/Inputs/function-address-main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Expr/Inputs/function-address-main.cpp @@ -0,0 +1,4 @@ +#include "function-address-shared.h" +int main() { + TinyVector argv(true); +} diff --git a/lldb/test/Shell/Expr/Inputs/function-address-shared.h b/lldb/test/Shell/Expr/Inputs/function-address-shared.h new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Expr/Inputs/function-address-shared.h @@ -0,0 +1,23 @@ +#ifndef function_address_shared_h +#define function_address_shared_h +namespace llvm_namespace { +struct TinyVectorBase { + int SomeInlineInitializedMember = 0; +}; +struct TinyVector : TinyVectorBase { + TinyVector *Self; + + TinyVector() : Self(getFirstEl()) {} + TinyVector(bool) : TinyVector() { nop(four()); } + int four() const { return 4; } + TinyVector *getFirstEl() { return this; } + char *begin() { return nullptr; } + char *end() { return begin() + four(); } + void clear() { nop(begin()), nop(end()); } + + void nop(void *) {} + void nop(int) {} +}; +} // end namespace llvm_namespace +using llvm_namespace::TinyVector; +#endif // function_address_shared_h diff --git a/lldb/test/Shell/Expr/TestFunctionAddress.lldb b/lldb/test/Shell/Expr/TestFunctionAddress.lldb new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Expr/TestFunctionAddress.lldb @@ -0,0 +1,9 @@ +# RUN: %clangxx_host %p/Inputs/function-address-main.cpp %p/Inputs/function-address-lib.cpp -g -fuse-ld=lld -o %t +# RUN: %lldb %t -s %s 2>&1 | FileCheck %s +b main +run +next +expr argv.four() +# CHECK: expr argv.four() +# CHECK-NEXT: (int) $0 = 4 +# CHECK-NOT: SIGSEGV