diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 12589adf227d0..5746bf3eb7cbd 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -789,7 +789,12 @@ ResolveFunctionCallLabel(FunctionCallLabel &label, sc_list.Append(*sc_or_err); LoadAddressResolver resolver(*sc.target_sp, symbol_was_missing_weak); - return resolver.Resolve(sc_list).value_or(LLDB_INVALID_ADDRESS); + lldb::addr_t resolved_addr = + resolver.Resolve(sc_list).value_or(LLDB_INVALID_ADDRESS); + if (resolved_addr == LLDB_INVALID_ADDRESS) + return llvm::createStringError("couldn't resolve address for function"); + + return resolved_addr; } lldb::addr_t diff --git a/lldb/test/API/lang/cpp/function-call-from-object-file/Makefile b/lldb/test/API/lang/cpp/function-call-from-object-file/Makefile new file mode 100644 index 0000000000000..285bbfbbca4fe --- /dev/null +++ b/lldb/test/API/lang/cpp/function-call-from-object-file/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp lib1.cpp lib2.cpp + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/function-call-from-object-file/TestFunctionCallFromObjectFile.py b/lldb/test/API/lang/cpp/function-call-from-object-file/TestFunctionCallFromObjectFile.py new file mode 100644 index 0000000000000..f0a7aef182a67 --- /dev/null +++ b/lldb/test/API/lang/cpp/function-call-from-object-file/TestFunctionCallFromObjectFile.py @@ -0,0 +1,29 @@ +""" +Tests that we can call functions that have definitions in multiple +CUs in the debug-info (which is the case for functions defined in headers). +The linker will most likely de-duplicate the functiond definitions when linking +the final executable. On Darwin, this will create a debug-map that LLDB will use +to fix up object file addresses to addresses in the linked executable. However, +if we parsed the DIE from the object file whose functiond definition got stripped +by the linker, LLDB needs to ensure it can still resolve the function symbol it +got for it. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestFunctionCallFromObjectFile(TestBase): + def test_lib1(self): + self.build() + lldbutil.run_to_name_breakpoint(self, "lib1_func") + + self.expect_expr("Foo{}.foo()", result_type="int", result_value="15") + + def test_lib2(self): + self.build() + lldbutil.run_to_name_breakpoint(self, "lib2_func") + + self.expect_expr("Foo{}.foo()", result_type="int", result_value="15") diff --git a/lldb/test/API/lang/cpp/function-call-from-object-file/common.h b/lldb/test/API/lang/cpp/function-call-from-object-file/common.h new file mode 100644 index 0000000000000..76e23be6b97a6 --- /dev/null +++ b/lldb/test/API/lang/cpp/function-call-from-object-file/common.h @@ -0,0 +1,8 @@ +#ifndef COMMON_H_IN +#define COMMON_H_IN + +struct Foo { + int foo() { return 15; } +}; + +#endif // COMMON_H_IN diff --git a/lldb/test/API/lang/cpp/function-call-from-object-file/lib1.cpp b/lldb/test/API/lang/cpp/function-call-from-object-file/lib1.cpp new file mode 100644 index 0000000000000..b97bcc1b712b6 --- /dev/null +++ b/lldb/test/API/lang/cpp/function-call-from-object-file/lib1.cpp @@ -0,0 +1,8 @@ +#include "common.h" + +// Parameter "Foo*" forces LLDB to parse "Foo" from the object +// file that it is stopped in. +void lib1_func(Foo *) { + // Force definition into lib1.o debug-info. + Foo{}.foo(); +} diff --git a/lldb/test/API/lang/cpp/function-call-from-object-file/lib2.cpp b/lldb/test/API/lang/cpp/function-call-from-object-file/lib2.cpp new file mode 100644 index 0000000000000..2f9d81a8bdf4c --- /dev/null +++ b/lldb/test/API/lang/cpp/function-call-from-object-file/lib2.cpp @@ -0,0 +1,6 @@ +#include "common.h" + +void lib2_func(Foo *) { + // Force definition into lib2.o debug-info. + Foo{}.foo(); +} diff --git a/lldb/test/API/lang/cpp/function-call-from-object-file/main.cpp b/lldb/test/API/lang/cpp/function-call-from-object-file/main.cpp new file mode 100644 index 0000000000000..61ca798daf1df --- /dev/null +++ b/lldb/test/API/lang/cpp/function-call-from-object-file/main.cpp @@ -0,0 +1,10 @@ +struct Foo; + +extern void lib1_func(Foo *); +extern void lib2_func(Foo *); + +int main() { + lib1_func(nullptr); + lib2_func(nullptr); + return 0; +}