diff options
| author | Jim Ingham <jingham@apple.com> | 2017-03-20 19:21:31 +0000 |
|---|---|---|
| committer | Jim Ingham <jingham@apple.com> | 2017-03-20 19:21:31 +0000 |
| commit | 1aa0ed4e0d202fde2c7225aaae513b228cb9a2b3 (patch) | |
| tree | 056809d44acb64eddd452f939cde96b9a97ff07d | |
| parent | 2dc4a3e91b2b448a5fd30b605802faf55308232a (diff) | |
| download | bcm5719-llvm-1aa0ed4e0d202fde2c7225aaae513b228cb9a2b3.tar.gz bcm5719-llvm-1aa0ed4e0d202fde2c7225aaae513b228cb9a2b3.zip | |
Get ObjectFileMachO to handle @executable_path
Only do this when we are debugging an executable, since we
don't have a good way to trace from an ObjectFile back to its
containing executable. Detecting pre-run libs before running
is "best effort" in lldb, but this one is pretty easy.
llvm-svn: 298290
6 files changed, 89 insertions, 2 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/Makefile new file mode 100644 index 00000000000..c4855ca9b12 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../make + +DYLIB_NAME := unlikely_name +DYLIB_CXX_SOURCES := foo.cpp +CXX_SOURCES := main.cpp +CFLAGS_EXTRAS += -fPIC + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/TestPreRunDylibs.py b/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/TestPreRunDylibs.py new file mode 100644 index 00000000000..258c3d3fbb9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/TestPreRunDylibs.py @@ -0,0 +1,38 @@ +from __future__ import print_function + +import unittest2 +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * + +class TestPreRunLibraries(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + @skipIf(oslist=no_match(['darwin','macos'])) + def test(self): + """Test that we find directly linked dylib pre-run.""" + + self.build() + target = self.dbg.CreateTarget("a.out") + self.assertTrue(target, VALID_TARGET) + + # I don't know what the name of a shared library + # extension is in general, so instead of using FindModule, + # I'll iterate through the module and do a basename match. + found_it = False + for module in target.modules: + file_name = module.GetFileSpec().GetFilename() + if file_name.find("unlikely_name") != -1: + found_it = True + break + + self.assertTrue(found_it, "Couldn't find unlikely_to_occur_name in loaded libraries.") + + diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/foo.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/foo.cpp new file mode 100644 index 00000000000..8dad0a23f36 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/foo.cpp @@ -0,0 +1,3 @@ +#include "foo.h" + +int call_foo1() { return foo1(); } diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/foo.h b/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/foo.h new file mode 100644 index 00000000000..060b91f5a5e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/foo.h @@ -0,0 +1,6 @@ +LLDB_TEST_API inline int foo1() { return 1; } // !BR1 + +LLDB_TEST_API inline int foo2() { return 2; } // !BR2 + +LLDB_TEST_API extern int call_foo1(); +LLDB_TEST_API extern int call_foo2(); diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/main.cpp new file mode 100644 index 00000000000..c9295a5c7d3 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/pre_run_dylibs/main.cpp @@ -0,0 +1,9 @@ +#include "foo.h" + +int call_foo2() { return foo2(); } + +int +main() // !BR_main +{ + return call_foo1() + call_foo2(); +} diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index a6d5a85e2d4..716cd404c73 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -5052,6 +5052,7 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) { lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); std::vector<std::string> rpath_paths; std::vector<std::string> rpath_relative_paths; + std::vector<std::string> at_exec_relative_paths; const bool resolve_path = false; // Don't resolve the dependent file paths // since they may not reside on this system uint32_t i; @@ -5077,6 +5078,10 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) { if (path[0] == '@') { if (strncmp(path, "@rpath", strlen("@rpath")) == 0) rpath_relative_paths.push_back(path + strlen("@rpath")); + else if (strncmp(path, "@executable_path", + strlen("@executable_path")) == 0) + at_exec_relative_paths.push_back(path + + strlen("@executable_path")); } else { FileSpec file_spec(path, resolve_path); if (files.AppendIfUnique(file_spec)) @@ -5092,10 +5097,11 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) { offset = cmd_offset + load_cmd.cmdsize; } + FileSpec this_file_spec(m_file); + this_file_spec.ResolvePath(); + if (!rpath_paths.empty()) { // Fixup all LC_RPATH values to be absolute paths - FileSpec this_file_spec(m_file); - this_file_spec.ResolvePath(); std::string loader_path("@loader_path"); std::string executable_path("@executable_path"); for (auto &rpath : rpath_paths) { @@ -5125,6 +5131,23 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) { } } } + + // We may have @executable_paths but no RPATHS. Figure those out here. + // Only do this if this object file is the executable. We have no way to + // get back to the actual executable otherwise, so we won't get the right + // path. + if (!at_exec_relative_paths.empty() && CalculateType() == eTypeExecutable) { + FileSpec exec_dir = this_file_spec.CopyByRemovingLastPathComponent(); + for (const auto &at_exec_relative_path : at_exec_relative_paths) { + FileSpec file_spec = + exec_dir.CopyByAppendingPathComponent(at_exec_relative_path); + file_spec = file_spec.GetNormalizedPath(); + if (file_spec.Exists() && files.AppendIfUnique(file_spec)) { + count++; + break; + } + } + } } return count; } |

