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
This commit is contained in:
Jim Ingham 2017-03-20 19:21:31 +00:00
parent 2dc4a3e91b
commit 1aa0ed4e0d
6 changed files with 89 additions and 2 deletions

View File

@ -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

View File

@ -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.")

View File

@ -0,0 +1,3 @@
#include "foo.h"
int call_foo1() { return foo1(); }

View File

@ -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();

View File

@ -0,0 +1,9 @@
#include "foo.h"
int call_foo2() { return foo2(); }
int
main() // !BR_main
{
return call_foo1() + call_foo2();
}

View File

@ -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;
}