diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -830,6 +830,9 @@ if (load_address != LLDB_INVALID_ADDRESS) { if (is_external) { + // Keep looking for a function entry with a symbol. + if (candidate_sc.function && !candidate_sc.symbol) + continue; return true; } else if (best_internal_load_address == LLDB_INVALID_ADDRESS) { best_internal_load_address = load_address; @@ -844,8 +847,8 @@ load_address = 0; return true; } - - return false; + + return load_address != LLDB_INVALID_ADDRESS; }; if (sc.module_sp) { 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