[Lldb-commits] [lldb] r164881 - in /lldb/trunk: include/lldb/Target/ source/API/ source/Commands/ source/Plugins/DynamicLoader/Darwin-Kernel/ source/Plugins/Platform/gdb-server/ source/Plugins/Process/MacOSX-Kernel/ source/Plugins/Process/gdb-remote/ source/Target/

Jason Molenda jmolenda at apple.com
Fri Sep 28 21:02:01 PDT 2012


Author: jmolenda
Date: Fri Sep 28 23:02:01 2012
New Revision: 164881

URL: http://llvm.org/viewvc/llvm-project?rev=164881&view=rev
Log:
Add support for debugging KASLR kernels via kdp (the kernel being
loaded at a random offset).

To get the kernel's UUID and load address I need to send a kdp
packet so I had to implement the kernel relocation (and attempt to
find the kernel if none was provided to lldb already) in ProcessKDP
-- but this code really properly belongs in DynamicLoaderDarwinKernel.

I also had to add an optional Stream to ConnectRemote so
ProcessKDP::DoConnectRemote can print feedback about the remote kernel's
UUID, load address, and notify the user if we auto-loaded the kernel via
the UUID.

<rdar://problem/7714201>

Modified:
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/source/API/SBTarget.cpp
    lldb/trunk/source/Commands/CommandObjectProcess.cpp
    lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
    lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
    lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
    lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
    lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
    lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
    lldb/trunk/source/Target/Process.cpp

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=164881&r1=164880&r2=164881&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Fri Sep 28 23:02:01 2012
@@ -1673,8 +1673,22 @@
     virtual Error
     Attach (ProcessAttachInfo &attach_info);
 
+    //------------------------------------------------------------------
+    /// Attach to a remote system via a URL
+    ///
+    /// @param[in] strm
+    ///     A stream where output intended for the user
+    ///     (if the driver has a way to display that) generated during
+    ///     the connection.  This may be NULL if no output is needed.A
+    ///
+    /// @param[in] remote_url
+    ///     The URL format that we are connecting to.
+    ///
+    /// @return
+    ///     Returns an error object.
+    //------------------------------------------------------------------
     virtual Error
-    ConnectRemote (const char *remote_url);
+    ConnectRemote (Stream *strm, const char *remote_url);
 
     bool
     GetShouldDetach () const
@@ -1896,8 +1910,22 @@
         return Error(); 
     }
 
+    //------------------------------------------------------------------
+    /// Attach to a remote system via a URL
+    ///
+    /// @param[in] strm
+    ///     A stream where output intended for the user 
+    ///     (if the driver has a way to display that) generated during
+    ///     the connection.  This may be NULL if no output is needed.A
+    ///
+    /// @param[in] remote_url
+    ///     The URL format that we are connecting to.
+    ///
+    /// @return
+    ///     Returns an error object.
+    //------------------------------------------------------------------
     virtual Error
-    DoConnectRemote (const char *remote_url)
+    DoConnectRemote (Stream *strm, const char *remote_url)
     {
         Error error;
         error.SetErrorString ("remote connections are not supported");

Modified: lldb/trunk/source/API/SBTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBTarget.cpp?rev=164881&r1=164880&r2=164881&view=diff
==============================================================================
--- lldb/trunk/source/API/SBTarget.cpp (original)
+++ lldb/trunk/source/API/SBTarget.cpp Fri Sep 28 23:02:01 2012
@@ -1087,7 +1087,7 @@
         if (process_sp)
         {
             sb_process.SetSP (process_sp);
-            error.SetError (process_sp->ConnectRemote (url));
+            error.SetError (process_sp->ConnectRemote (NULL, url));
         }
         else
         {

Modified: lldb/trunk/source/Commands/CommandObjectProcess.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectProcess.cpp?rev=164881&r1=164880&r2=164881&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectProcess.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectProcess.cpp Fri Sep 28 23:02:01 2012
@@ -1041,7 +1041,7 @@
             
             if (process)
             {
-                error = process->ConnectRemote (remote_url);
+                error = process->ConnectRemote (&process->GetTarget().GetDebugger().GetOutputStream(), remote_url);
 
                 if (error.Fail())
                 {

Modified: lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp?rev=164881&r1=164880&r2=164881&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp Fri Sep 28 23:02:01 2012
@@ -342,7 +342,16 @@
     {
         m_kernel.Clear(false);
         m_kernel.module_sp = m_process->GetTarget().GetExecutableModule();
-        strncpy(m_kernel.name, "mach_kernel", sizeof(m_kernel.name));
+
+        ConstString kernel_name("mach_kernel");
+        if (m_kernel.module_sp.get() 
+            && m_kernel.module_sp->GetObjectFile()
+            && !m_kernel.module_sp->GetObjectFile()->GetFileSpec().GetFilename().IsEmpty())
+        {
+            kernel_name = m_kernel.module_sp->GetObjectFile()->GetFileSpec().GetFilename();
+        }
+        strlcpy (m_kernel.name, kernel_name.AsCString(), sizeof(m_kernel.name));
+
         if (m_kernel.address == LLDB_INVALID_ADDRESS)
         {
             m_kernel.address = m_process->GetImageInfoAddress ();
@@ -353,7 +362,25 @@
                 // the file if we have one
                 ObjectFile *kernel_object_file = m_kernel.module_sp->GetObjectFile();
                 if (kernel_object_file)
-                    m_kernel.address = kernel_object_file->GetHeaderAddress().GetFileAddress();
+                {
+                    addr_t load_address = kernel_object_file->GetHeaderAddress().GetLoadAddress(&m_process->GetTarget());
+                    addr_t file_address = kernel_object_file->GetHeaderAddress().GetFileAddress();
+                    if (load_address != LLDB_INVALID_ADDRESS && load_address != 0)
+                    {
+                        m_kernel.address = load_address;
+                        if (load_address != file_address)
+                        {
+                            // Don't accidentally relocate the kernel to the File address -- 
+                            // the Load address has already been set to its actual in-memory address.  
+                            // Mark it as IsLoaded.
+                            m_kernel.load_process_stop_id = m_process->GetStopID();
+                        }
+                    }
+                    else
+                    {
+                        m_kernel.address = file_address;
+                    }
+                }
             }
         }
         
@@ -725,7 +752,6 @@
     DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
     Clear(true);
     m_process = process;
-    m_process->GetTarget().GetSectionLoadList().Clear();
 }
 
 void

Modified: lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp?rev=164881&r1=164880&r2=164881&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp Fri Sep 28 23:02:01 2012
@@ -398,7 +398,7 @@
                                                                 GetHostname (), 
                                                                 port);
                         assert (connect_url_len < sizeof(connect_url));
-                        error = process_sp->ConnectRemote (connect_url);
+                        error = process_sp->ConnectRemote (NULL, connect_url);
                         if (error.Success())
                             error = process_sp->Attach(attach_info);
                     }

Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp?rev=164881&r1=164880&r2=164881&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Fri Sep 28 23:02:01 2012
@@ -11,6 +11,7 @@
 #include "CommunicationKDP.h"
 
 // C Includes
+#include <errno.h>
 #include <limits.h>
 #include <string.h>
 
@@ -22,6 +23,7 @@
 #include "lldb/Core/DataExtractor.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/State.h"
+#include "lldb/Core/UUID.h"
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Host/TimeValue.h"
@@ -499,6 +501,51 @@
     return m_kdp_hostinfo_cpu_subtype;
 }
 
+lldb_private::UUID
+CommunicationKDP::GetUUID ()
+{
+    UUID uuid;
+    if (GetKernelVersion() == NULL)
+        return uuid;
+
+    if (m_kernel_version.find("UUID=") == std::string::npos)
+        return uuid;
+
+    size_t p = m_kernel_version.find("UUID=") + strlen ("UUID=");
+    std::string uuid_str = m_kernel_version.substr(p, 36);
+    if (uuid_str.size() < 32)
+        return uuid;
+
+    if (uuid.SetFromCString (uuid_str.c_str()) == 0)
+    {
+        UUID invalid_uuid;
+        return invalid_uuid;
+    }
+
+    return uuid;
+}
+
+lldb::addr_t
+CommunicationKDP::GetLoadAddress ()
+{
+    if (GetKernelVersion() == NULL)
+        return LLDB_INVALID_ADDRESS;
+
+    if (m_kernel_version.find("stext=") == std::string::npos)
+        return LLDB_INVALID_ADDRESS;
+    size_t p = m_kernel_version.find("stext=") + strlen ("stext=");
+    if (m_kernel_version[p] != '0' || m_kernel_version[p + 1] != 'x')
+        return LLDB_INVALID_ADDRESS;
+
+    addr_t kernel_load_address;
+    errno = 0;
+    kernel_load_address = ::strtoul (m_kernel_version.c_str() + p, NULL, 16);
+    if (errno != 0 || kernel_load_address == 0)
+        return LLDB_INVALID_ADDRESS;
+
+    return kernel_load_address;
+}
+
 bool
 CommunicationKDP::SendRequestHostInfo ()
 {

Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h?rev=164881&r1=164880&r2=164881&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Fri Sep 28 23:02:01 2012
@@ -213,6 +213,12 @@
     uint32_t
     GetCPUSubtype ();
 
+    lldb_private::UUID 
+    GetUUID ();
+
+    lldb::addr_t
+    GetLoadAddress ();
+
     bool
     SendRequestResume ();
 

Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp?rev=164881&r1=164880&r2=164881&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Fri Sep 28 23:02:01 2012
@@ -17,8 +17,11 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/State.h"
+#include "lldb/Core/UUID.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Host/Symbols.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/RegisterContext.h"
 #include "lldb/Target/Target.h"
@@ -167,7 +170,7 @@
 }
 
 Error
-ProcessKDP::DoConnectRemote (const char *remote_url)
+ProcessKDP::DoConnectRemote (Stream *strm, const char *remote_url)
 {
     Error error;
 
@@ -214,6 +217,90 @@
                     ArchSpec kernel_arch;
                     kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
                     m_target.SetArchitecture(kernel_arch);
+
+                    /* Get the kernel's UUID and load address via kdp-kernelversion packet.  */
+                        
+                    UUID kernel_uuid = m_comm.GetUUID ();
+                    addr_t kernel_load_addr = m_comm.GetLoadAddress ();
+                    if (strm)
+                    {
+                        char uuidbuf[64];
+                        strm->Printf ("Kernel UUID: %s\n", kernel_uuid.GetAsCString (uuidbuf, sizeof (uuidbuf)));
+                        strm->Printf ("Load Address: 0x%llx\n", kernel_load_addr);
+                        strm->Flush ();
+                    }
+
+                    /* Set the kernel's LoadAddress based on the information from kdp.
+                       This would normally be handled by the DynamicLoaderDarwinKernel plugin but there's no easy
+                       way to communicate the UUID / load addr from kdp back up to that plugin so we'll set it here. */
+                    ModuleSP exe_module_sp = m_target.GetExecutableModule ();
+                    bool find_and_load_kernel = true;
+                    if (exe_module_sp.get ())
+                    {
+                        ObjectFile *exe_objfile = exe_module_sp->GetObjectFile();
+                        if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && 
+                            exe_objfile->GetStrata() == ObjectFile::eStrataKernel)
+                        {
+                            UUID exe_objfile_uuid;
+                            if (exe_objfile->GetUUID (&exe_objfile_uuid) && kernel_uuid == exe_objfile_uuid
+                                && exe_objfile->GetHeaderAddress().IsValid())
+                            {
+                                find_and_load_kernel = false;
+                                addr_t slide = kernel_load_addr - exe_objfile->GetHeaderAddress().GetFileAddress();
+                                if (slide != 0)
+                                {
+                                    bool changed = false;
+                                    exe_module_sp->SetLoadAddress (m_target, slide, changed);
+                                    if (changed)
+                                    {
+                                        ModuleList modlist;
+                                        modlist.Append (exe_module_sp);
+                                        m_target.ModulesDidLoad (modlist);
+                                    }
+                                }
+                            }
+                        }
+                    }
+
+                    // If the executable binary is not the same as the kernel being run on the remote host,
+                    // see if Symbols::DownloadObjectAndSymbolFile can find us a symbol file based on the UUID
+                    // and if so, load it at the correct address.
+                    if (find_and_load_kernel && kernel_load_addr != LLDB_INVALID_ADDRESS && kernel_uuid.IsValid())
+                    {
+                        ModuleSpec sym_spec;
+                        sym_spec.GetUUID() = kernel_uuid;
+                        if (Symbols::DownloadObjectAndSymbolFile (sym_spec) 
+                            && sym_spec.GetArchitecture().IsValid() 
+                            && sym_spec.GetSymbolFileSpec().Exists())
+                        {
+                            ModuleSP kernel_sp = m_target.GetSharedModule (sym_spec);
+                            if (kernel_sp.get())
+                            {
+                                m_target.SetExecutableModule(kernel_sp, false);
+                                if (kernel_sp->GetObjectFile() && kernel_sp->GetObjectFile()->GetHeaderAddress().IsValid())
+                                {
+                                    addr_t slide = kernel_load_addr - kernel_sp->GetObjectFile()->GetHeaderAddress().GetFileAddress();
+                                    bool changed = false;
+                                    kernel_sp->SetLoadAddress (m_target, slide, changed);
+                                    if (changed)
+                                    {
+                                        ModuleList modlist;
+                                        modlist.Append (kernel_sp);
+                                        m_target.ModulesDidLoad (modlist);
+                                    }
+                                    if (strm)
+                                    {
+                                        strm->Printf ("Loaded kernel file %s/%s\n", 
+                                                      kernel_sp->GetFileSpec().GetDirectory().AsCString(),
+                                                      kernel_sp->GetFileSpec().GetFilename().AsCString());
+                                        strm->Flush ();
+                                    }
+                                }
+                            }
+                        }
+                    }
+
+
                     // Set the thread ID
                     UpdateThreadListIfNeeded ();
                     SetID (1);

Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h?rev=164881&r1=164880&r2=164881&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h Fri Sep 28 23:02:01 2012
@@ -90,7 +90,7 @@
     WillAttachToProcessWithName (const char *process_name, bool wait_for_launch);
     
     virtual lldb_private::Error
-    DoConnectRemote (const char *remote_url);
+    DoConnectRemote (lldb_private::Stream *strm, const char *remote_url);
     
     virtual lldb_private::Error
     DoAttachToProcessWithID (lldb::pid_t pid);

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=164881&r1=164880&r2=164881&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Fri Sep 28 23:02:01 2012
@@ -414,7 +414,7 @@
 }
 
 Error
-ProcessGDBRemote::DoConnectRemote (const char *remote_url)
+ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
 {
     Error error (WillLaunchOrAttach ());
     
@@ -427,6 +427,25 @@
         return error;
     StartAsyncThread ();
 
+    const ArchSpec &gdb_remote_arch = m_gdb_comm.GetHostArchitecture();
+    if (gdb_remote_arch.IsValid() && gdb_remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)
+    {
+        Module *exe_module = GetTarget().GetExecutableModulePointer();
+        
+        ObjectFile *exe_objfile = exe_module->GetObjectFile();
+
+        // If the remote system is an Apple device and we don't have an exec file
+        // OR we have an exec file and it is a kernel, look for the kernel's load address
+        // in memory and load/relocate the kernel symbols as appropriate.
+        if (exe_objfile == NULL 
+            || (exe_objfile->GetType() == ObjectFile::eTypeExecutable && 
+                exe_objfile->GetStrata() == ObjectFile::eStrataKernel))
+        {
+        
+
+        }
+    }
+
     lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
     if (pid == LLDB_INVALID_PROCESS_ID)
     {

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=164881&r1=164880&r2=164881&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Fri Sep 28 23:02:01 2012
@@ -94,7 +94,7 @@
     WillAttachToProcessWithName (const char *process_name, bool wait_for_launch);
 
     virtual lldb_private::Error
-    DoConnectRemote (const char *remote_url);
+    DoConnectRemote (lldb_private::Stream *strm, const char *remote_url);
     
     lldb_private::Error
     WillLaunchOrAttach ();

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=164881&r1=164880&r2=164881&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Fri Sep 28 23:02:01 2012
@@ -2906,7 +2906,7 @@
 }
 
 Error
-Process::ConnectRemote (const char *remote_url)
+Process::ConnectRemote (Stream *strm, const char *remote_url)
 {
     m_abi_sp.reset();
     m_process_input_reader.reset();
@@ -2914,7 +2914,7 @@
     // Find the process and its architecture.  Make sure it matches the architecture
     // of the current Target, and if not adjust it.
     
-    Error error (DoConnectRemote (remote_url));
+    Error error (DoConnectRemote (strm, remote_url));
     if (error.Success())
     {
         if (GetID() != LLDB_INVALID_PROCESS_ID)





More information about the lldb-commits mailing list