Author: gclayton Date: Tue Jun 2 17:43:29 2015 New Revision: 238886 URL: http://llvm.org/viewvc/llvm-project?rev=238886&view=rev Log: Fix LLDB so that it can correctly track down dependent shared libraries that use @rpath.
<rdar://problem/8371885> Modified: lldb/trunk/include/lldb/Host/FileSpec.h lldb/trunk/source/Host/common/FileSpec.cpp lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Modified: lldb/trunk/include/lldb/Host/FileSpec.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/FileSpec.h?rev=238886&r1=238885&r2=238886&view=diff ============================================================================== --- lldb/trunk/include/lldb/Host/FileSpec.h (original) +++ lldb/trunk/include/lldb/Host/FileSpec.h Tue Jun 2 17:43:29 2015 @@ -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. Modified: lldb/trunk/source/Host/common/FileSpec.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/FileSpec.cpp?rev=238886&r1=238885&r2=238886&view=diff ============================================================================== --- lldb/trunk/source/Host/common/FileSpec.cpp (original) +++ lldb/trunk/source/Host/common/FileSpec.cpp Tue Jun 2 17:43:29 2015 @@ -546,6 +546,14 @@ FileSpec::Equal (const FileSpec& a, cons } 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(); Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=238886&r1=238885&r2=238886&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original) +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Tue Jun 2 17:43:29 2015 @@ -4788,6 +4788,8 @@ ObjectFileMachO::GetDependentModules (Fi 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 (Fi 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 (Fi { 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 (Fi } 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; } _______________________________________________ lldb-commits mailing list lldb-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits