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:
parent
2dc4a3e91b
commit
1aa0ed4e0d
|
@ -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
|
|
@ -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.")
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#include "foo.h"
|
||||
|
||||
int call_foo1() { return foo1(); }
|
|
@ -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();
|
|
@ -0,0 +1,9 @@
|
|||
#include "foo.h"
|
||||
|
||||
int call_foo2() { return foo2(); }
|
||||
|
||||
int
|
||||
main() // !BR_main
|
||||
{
|
||||
return call_foo1() + call_foo2();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue