summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2015-06-02 22:43:29 +0000
committerGreg Clayton <gclayton@apple.com>2015-06-02 22:43:29 +0000
commit5a27195b1a93fccc63129509d43cd8f943bf9ddc (patch)
tree40ef8bf349e2c20101c4ac2451479e99ff7fb4c1
parent677324e0b56aef7f43af3da612363f0471833f8d (diff)
downloadbcm5719-llvm-5a27195b1a93fccc63129509d43cd8f943bf9ddc.tar.gz
bcm5719-llvm-5a27195b1a93fccc63129509d43cd8f943bf9ddc.zip
Fix LLDB so that it can correctly track down dependent shared libraries that use @rpath.
<rdar://problem/8371885> llvm-svn: 238886
-rw-r--r--lldb/include/lldb/Host/FileSpec.h7
-rw-r--r--lldb/source/Host/common/FileSpec.cpp8
-rw-r--r--lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp69
3 files changed, 77 insertions, 7 deletions
diff --git a/lldb/include/lldb/Host/FileSpec.h b/lldb/include/lldb/Host/FileSpec.h
index 7918dd943ac..c5359669c3a 100644
--- a/lldb/include/lldb/Host/FileSpec.h
+++ b/lldb/include/lldb/Host/FileSpec.h
@@ -639,6 +639,13 @@ public:
ReadFileContentsAsCString(Error *error_ptr = NULL);
//------------------------------------------------------------------
+ /// Normalize a pathname by collapsing redundant separators and
+ /// up-level references.
+ //------------------------------------------------------------------
+ void
+ NormalizePath ();
+
+ //------------------------------------------------------------------
/// Run through the input string, replaying the effect of any ".." and produce
/// the resultant path. The input path is not required to be in the host file system
/// format, but it is required to be normalized to that system.
diff --git a/lldb/source/Host/common/FileSpec.cpp b/lldb/source/Host/common/FileSpec.cpp
index 0e8f71acb37..1b5ec3339a6 100644
--- a/lldb/source/Host/common/FileSpec.cpp
+++ b/lldb/source/Host/common/FileSpec.cpp
@@ -546,6 +546,14 @@ FileSpec::Equal (const FileSpec& a, const FileSpec& b, bool full, bool remove_ba
}
void
+FileSpec::NormalizePath ()
+{
+ ConstString normalized_directory;
+ FileSpec::RemoveBackupDots(m_directory, normalized_directory);
+ m_directory = normalized_directory;
+}
+
+void
FileSpec::RemoveBackupDots (const ConstString &input_const_str, ConstString &result_const_str)
{
const char *input = input_const_str.GetCString();
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 9cfa8b09302..7c78246bb0c 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -4788,6 +4788,8 @@ ObjectFileMachO::GetDependentModules (FileSpecList& files)
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
struct load_command load_cmd;
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ std::vector<std::string> rpath_paths;
+ std::vector<std::string> rpath_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;
for (i=0; i<m_header.ncmds; ++i)
@@ -4798,6 +4800,7 @@ ObjectFileMachO::GetDependentModules (FileSpecList& files)
switch (load_cmd.cmd)
{
+ case LC_RPATH:
case LC_LOAD_DYLIB:
case LC_LOAD_WEAK_DYLIB:
case LC_REEXPORT_DYLIB:
@@ -4807,14 +4810,24 @@ ObjectFileMachO::GetDependentModules (FileSpecList& files)
{
uint32_t name_offset = cmd_offset + m_data.GetU32(&offset);
const char *path = m_data.PeekCStr(name_offset);
- // Skip any path that starts with '@' since these are usually:
- // @executable_path/.../file
- // @rpath/.../file
- if (path && path[0] != '@')
+ if (path)
{
- FileSpec file_spec(path, resolve_path);
- if (files.AppendIfUnique(file_spec))
- count++;
+ if (load_cmd.cmd == LC_RPATH)
+ rpath_paths.push_back(path);
+ else
+ {
+ if (path[0] == '@')
+ {
+ if (strncmp(path, "@rpath", strlen("@rpath")) == 0)
+ rpath_relative_paths.push_back(path + strlen("@rpath"));
+ }
+ else
+ {
+ FileSpec file_spec(path, resolve_path);
+ if (files.AppendIfUnique(file_spec))
+ count++;
+ }
+ }
}
}
break;
@@ -4824,6 +4837,48 @@ ObjectFileMachO::GetDependentModules (FileSpecList& files)
}
offset = cmd_offset + load_cmd.cmdsize;
}
+
+ 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)
+ {
+ if (rpath.find(loader_path) == 0)
+ {
+ rpath.erase(0, loader_path.size());
+ rpath.insert(0, this_file_spec.GetDirectory().GetCString());
+ }
+ else if (rpath.find(executable_path) == 0)
+ {
+ rpath.erase(0, executable_path.size());
+ rpath.insert(0, this_file_spec.GetDirectory().GetCString());
+ }
+ }
+
+ for (const auto &rpath_relative_path : rpath_relative_paths)
+ {
+ for (const auto &rpath : rpath_paths)
+ {
+ std::string path = rpath;
+ path += rpath_relative_path;
+ // It is OK to resolve this path because we must find a file on
+ // disk for us to accept it anyway if it is rpath relative.
+ FileSpec file_spec(path, true);
+ // Remove any redundant parts of the path (like "../foo") since
+ // LC_RPATH values often contain "..".
+ file_spec.NormalizePath ();
+ if (file_spec.Exists() && files.AppendIfUnique(file_spec))
+ {
+ count++;
+ break;
+ }
+ }
+ }
+ }
}
return count;
}
OpenPOWER on IntegriCloud