[Lldb-commits] [lldb] r238886 - Fix LLDB so that it can correctly track down dependent shared libraries that use @rpath.

Greg Clayton gclayton at apple.com
Tue Jun 2 15:43:30 PDT 2015


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





More information about the lldb-commits mailing list