[Lldb-commits] [lldb] r202956 - Add support for JIT debugging on Linux using the GDB JIT interface. Patch written with Keno Fischer.

Andrew MacPherson andrew.macp at gmail.com
Wed Mar 5 02:12:44 PST 2014


Author: andrewmacp
Date: Wed Mar  5 04:12:43 2014
New Revision: 202956

URL: http://llvm.org/viewvc/llvm-project?rev=202956&view=rev
Log:
Add support for JIT debugging on Linux using the GDB JIT interface. Patch written with Keno Fischer.


Added:
    lldb/trunk/include/lldb/Target/JITLoader.h
    lldb/trunk/include/lldb/Target/JITLoaderList.h
    lldb/trunk/source/Core/JITLoader.cpp
    lldb/trunk/source/Core/JITLoaderList.cpp
    lldb/trunk/source/Plugins/JITLoader/
    lldb/trunk/source/Plugins/JITLoader/CMakeLists.txt
    lldb/trunk/source/Plugins/JITLoader/GDB/
    lldb/trunk/source/Plugins/JITLoader/GDB/CMakeLists.txt
    lldb/trunk/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
    lldb/trunk/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
    lldb/trunk/source/Plugins/JITLoader/GDB/Makefile
Modified:
    lldb/trunk/include/lldb/Core/Module.h
    lldb/trunk/include/lldb/Core/PluginManager.h
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/include/lldb/lldb-forward.h
    lldb/trunk/include/lldb/lldb-private-interfaces.h
    lldb/trunk/include/lldb/lldb-private-log.h
    lldb/trunk/lib/Makefile
    lldb/trunk/source/CMakeLists.txt
    lldb/trunk/source/Core/CMakeLists.txt
    lldb/trunk/source/Core/Module.cpp
    lldb/trunk/source/Core/PluginManager.cpp
    lldb/trunk/source/Plugins/CMakeLists.txt
    lldb/trunk/source/Plugins/Makefile
    lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
    lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
    lldb/trunk/source/Target/Process.cpp
    lldb/trunk/source/lldb-log.cpp
    lldb/trunk/source/lldb.cpp

Modified: lldb/trunk/include/lldb/Core/Module.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Module.h?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Module.h (original)
+++ lldb/trunk/include/lldb/Core/Module.h Wed Mar  5 04:12:43 2014
@@ -703,11 +703,25 @@ public:
     uint32_t
     GetVersion (uint32_t *versions, uint32_t num_versions);
 
-    // Load an object file from memory.
+    //------------------------------------------------------------------
+    /// Load an object file from memory. 
+    ///
+    /// If available, the size of the object file in memory may be 
+    /// passed to avoid additional round trips to process memory. 
+    /// If the size is not provided, a default value is used. This
+    /// value should be large enough to enable the ObjectFile plugins
+    /// to read the header of the object file without going back to the
+    /// process. 
+    ///
+    /// @return 
+    ///     The object file loaded from memory or NULL, if the operation 
+    ///     failed (see the `error` for more information in that case).
+    //------------------------------------------------------------------
     ObjectFile *
     GetMemoryObjectFile (const lldb::ProcessSP &process_sp, 
                          lldb::addr_t header_addr,
-                         Error &error);
+                         Error &error,
+                         size_t size_to_read = 512);
     //------------------------------------------------------------------
     /// Get the symbol vendor interface for the current architecture.
     ///

Modified: lldb/trunk/include/lldb/Core/PluginManager.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/PluginManager.h?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/PluginManager.h (original)
+++ lldb/trunk/include/lldb/Core/PluginManager.h Wed Mar  5 04:12:43 2014
@@ -80,6 +80,24 @@ public:
     GetDynamicLoaderCreateCallbackForPluginName (const ConstString &name);
 
     //------------------------------------------------------------------
+    // JITLoader
+    //------------------------------------------------------------------
+    static bool
+    RegisterPlugin (const ConstString &name,
+                    const char *description,
+                    JITLoaderCreateInstance create_callback,
+                    DebuggerInitializeCallback debugger_init_callback = NULL);
+
+    static bool
+    UnregisterPlugin (JITLoaderCreateInstance create_callback);
+
+    static JITLoaderCreateInstance
+    GetJITLoaderCreateCallbackAtIndex (uint32_t idx);
+
+    static JITLoaderCreateInstance
+    GetJITLoaderCreateCallbackForPluginName (const ConstString &name);
+
+    //------------------------------------------------------------------
     // EmulateInstruction
     //------------------------------------------------------------------
     static bool

Added: lldb/trunk/include/lldb/Target/JITLoader.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/JITLoader.h?rev=202956&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Target/JITLoader.h (added)
+++ lldb/trunk/include/lldb/Target/JITLoader.h Wed Mar  5 04:12:43 2014
@@ -0,0 +1,83 @@
+//===-- JITLoader.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_JITLoader_h_
+#define liblldb_JITLoader_h_
+
+#include <vector>
+
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Target/JITLoaderList.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class JITLoader JITLoader.h "lldb/Target/JITLoader.h"
+/// @brief A plug-in interface definition class for JIT loaders.
+///
+/// Plugins of this kind listen for code generated at runtime in the 
+/// target. They are very similar to dynamic loader, with the difference
+/// that they do not have information about the the target's dyld and
+/// that there may be multiple JITLoader plugins per process, while 
+/// there is at most one DynamicLoader. 
+//----------------------------------------------------------------------
+class JITLoader :
+    public PluginInterface
+{
+public:
+    //------------------------------------------------------------------
+    /// Find a JIT loader plugin for a given process.
+    ///
+    /// Scans the installed DynamicLoader plug-ins and tries to find
+    /// all applicable instances for the current process.
+    ///
+    /// @param[in] process
+    ///     The process for which to try and locate a JIT loader
+    ///     plug-in instance.
+    ///
+    //------------------------------------------------------------------
+    static void 
+    LoadPlugins (Process *process, lldb_private::JITLoaderList &list);
+
+    //------------------------------------------------------------------
+    /// Construct with a process.
+    //------------------------------------------------------------------
+    JITLoader (Process *process);
+
+    virtual 
+    ~JITLoader ();
+
+    //------------------------------------------------------------------
+    /// Called after attaching a process.
+    ///
+    /// Allow DynamicLoader plug-ins to execute some code after
+    /// attaching to a process.
+    //------------------------------------------------------------------
+    virtual void
+    DidAttach () = 0;
+
+    //------------------------------------------------------------------
+    /// Called after launching a process.
+    ///
+    /// Allow DynamicLoader plug-ins to execute some code after
+    /// the process has stopped for the first time on launch.
+    //------------------------------------------------------------------
+    virtual void
+    DidLaunch () = 0;
+
+protected:
+    //------------------------------------------------------------------
+    // Member variables.
+    //------------------------------------------------------------------
+    Process* m_process;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_JITLoader_h_

Added: lldb/trunk/include/lldb/Target/JITLoaderList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/JITLoaderList.h?rev=202956&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Target/JITLoaderList.h (added)
+++ lldb/trunk/include/lldb/Target/JITLoaderList.h Wed Mar  5 04:12:43 2014
@@ -0,0 +1,57 @@
+//===-- JITLoaderList.h -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_JITLoaderList_h_
+#define liblldb_JITLoaderList_h_
+
+#include <vector>
+
+#include "lldb/lldb-forward.h"
+#include "lldb/Host/Mutex.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class JITLoaderList JITLoaderList.h "lldb/Target/JITLoaderList.h"
+///
+/// Class used by the Process to hold a list of its JITLoaders.
+//----------------------------------------------------------------------
+class JITLoaderList
+{
+public:
+
+    JITLoaderList();
+    ~JITLoaderList();
+
+    void
+    Append (const lldb::JITLoaderSP &jit_loader_sp);
+
+    void
+    Remove (const lldb::JITLoaderSP &jit_loader_sp);
+
+    size_t
+    GetSize() const;
+
+    lldb::JITLoaderSP
+    GetLoaderAtIndex (size_t idx);
+
+    void
+    DidLaunch();
+
+    void
+    DidAttach();
+
+private:
+    std::vector<lldb::JITLoaderSP> m_jit_loaders_vec;
+    lldb_private::Mutex m_jit_loaders_mutex;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_JITLoaderList_h_

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Wed Mar  5 04:12:43 2014
@@ -42,6 +42,7 @@
 #include "lldb/Interpreter/Args.h"
 #include "lldb/Interpreter/Options.h"
 #include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/JITLoaderList.h"
 #include "lldb/Target/Memory.h"
 #include "lldb/Target/QueueList.h"
 #include "lldb/Target/ThreadList.h"
@@ -1824,6 +1825,11 @@ public:
     virtual DynamicLoader *
     GetDynamicLoader ();
 
+protected:
+    virtual JITLoaderList &
+    GetJITLoaders ();
+
+public:
     //------------------------------------------------------------------
     /// Get the system runtime plug-in for this process. 
     ///
@@ -3071,7 +3077,8 @@ public:
     
     lldb::ModuleSP
     ReadModuleFromMemory (const FileSpec& file_spec, 
-                          lldb::addr_t header_addr);
+                          lldb::addr_t header_addr,
+                          size_t size_to_read = 512);
 
     //------------------------------------------------------------------
     /// Attempt to get the attributes for a region of memory in the process.
@@ -3768,6 +3775,7 @@ protected:
     Listener                    &m_listener;
     BreakpointSiteList          m_breakpoint_site_list; ///< This is the list of breakpoint locations we intend to insert in the target.
     std::unique_ptr<DynamicLoader> m_dyld_ap;
+    std::unique_ptr<JITLoaderList> m_jit_loaders_ap;
     std::unique_ptr<DynamicCheckerFunctions> m_dynamic_checkers_ap; ///< The functions used by the expression parser to validate data that expressions use.
     std::unique_ptr<OperatingSystem> m_os_ap;
     std::unique_ptr<SystemRuntime> m_system_runtime_ap;

Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Wed Mar  5 04:12:43 2014
@@ -107,6 +107,7 @@ class   Instruction;
 class   InstructionList;
 class   IOHandler;
 class   IRExecutionUnit;
+class   JITLoader;
 class   LanguageRuntime;
 class   SystemRuntime;
 class   LineTable;
@@ -305,6 +306,7 @@ namespace lldb {
     typedef std::shared_ptr<lldb_private::InlineFunctionInfo> InlineFunctionInfoSP;
     typedef std::shared_ptr<lldb_private::Instruction> InstructionSP;
     typedef std::shared_ptr<lldb_private::IOHandler> IOHandlerSP;
+    typedef std::shared_ptr<lldb_private::JITLoader> JITLoaderSP;
     typedef std::shared_ptr<lldb_private::LanguageRuntime> LanguageRuntimeSP;
     typedef std::shared_ptr<lldb_private::SystemRuntime> SystemRuntimeSP;
     typedef std::shared_ptr<lldb_private::LineTable> LineTableSP;

Modified: lldb/trunk/include/lldb/lldb-private-interfaces.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-interfaces.h?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-private-interfaces.h (original)
+++ lldb/trunk/include/lldb/lldb-private-interfaces.h Wed Mar  5 04:12:43 2014
@@ -19,6 +19,7 @@ namespace lldb_private
     typedef lldb::ABISP (*ABICreateInstance) (const ArchSpec &arch);
     typedef Disassembler* (*DisassemblerCreateInstance) (const ArchSpec &arch, const char *flavor);
     typedef DynamicLoader* (*DynamicLoaderCreateInstance) (Process* process, bool force);
+    typedef lldb::JITLoaderSP (*JITLoaderCreateInstance) (Process *process, bool force);
     typedef ObjectContainer* (*ObjectContainerCreateInstance) (const lldb::ModuleSP &module_sp, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t offset, lldb::offset_t length);
     typedef size_t (*ObjectFileGetModuleSpecifications) (const FileSpec &file, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t length, ModuleSpecList &module_specs);
     typedef ObjectFile* (*ObjectFileCreateInstance) (const lldb::ModuleSP &module_sp, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, const FileSpec* file, lldb::offset_t file_offset, lldb::offset_t length);

Modified: lldb/trunk/include/lldb/lldb-private-log.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-log.h?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-private-log.h (original)
+++ lldb/trunk/include/lldb/lldb-private-log.h Wed Mar  5 04:12:43 2014
@@ -46,6 +46,7 @@
 #define LIBLLDB_LOG_OS                  (1u << 24)
 #define LIBLLDB_LOG_PLATFORM            (1u << 25)
 #define LIBLLDB_LOG_SYSTEM_RUNTIME      (1u << 26)
+#define LIBLLDB_LOG_JIT_LOADER          (1u << 27)
 #define LIBLLDB_LOG_ALL                 (UINT32_MAX)
 #define LIBLLDB_LOG_DEFAULT             (LIBLLDB_LOG_PROCESS              |\
                                          LIBLLDB_LOG_THREAD               |\

Modified: lldb/trunk/lib/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lib/Makefile?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/lib/Makefile (original)
+++ lldb/trunk/lib/Makefile Wed Mar  5 04:12:43 2014
@@ -105,7 +105,8 @@ ifeq ($(HOST_OS),Linux)
               lldbPluginProcessLinux.a \
               lldbPluginProcessPOSIX.a \
               lldbPluginDynamicLoaderMacOSX.a \
-              lldbPluginProcessElfCore.a
+              lldbPluginProcessElfCore.a \
+              lldbPluginJITLoaderGDB.a
 endif
 
 ifneq (,$(filter $(HOST_OS), FreeBSD GNU/kFreeBSD))

Modified: lldb/trunk/source/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/CMakeLists.txt?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/source/CMakeLists.txt (original)
+++ lldb/trunk/source/CMakeLists.txt Wed Mar  5 04:12:43 2014
@@ -103,6 +103,7 @@ if ( CMAKE_SYSTEM_NAME MATCHES "Linux" )
     lldbPluginProcessLinux
     lldbPluginProcessPOSIX
     lldbPluginProcessElfCore
+    lldbPluginJITLoaderGDB
     )
 endif ()
 

Modified: lldb/trunk/source/Core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/CMakeLists.txt?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/source/Core/CMakeLists.txt (original)
+++ lldb/trunk/source/Core/CMakeLists.txt Wed Mar  5 04:12:43 2014
@@ -29,6 +29,8 @@ add_lldb_library(lldbCore
   FileSpecList.cpp
   History.cpp
   IOHandler.cpp
+  JITLoader.cpp
+  JITLoaderList.cpp
   Language.cpp
   Listener.cpp
   Log.cpp

Added: lldb/trunk/source/Core/JITLoader.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/JITLoader.cpp?rev=202956&view=auto
==============================================================================
--- lldb/trunk/source/Core/JITLoader.cpp (added)
+++ lldb/trunk/source/Core/JITLoader.cpp Wed Mar  5 04:12:43 2014
@@ -0,0 +1,38 @@
+//===-- JITLoader.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/JITLoader.h"
+#include "lldb/Target/JITLoaderList.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+JITLoader::LoadPlugins (Process *process, JITLoaderList &list)
+{
+    JITLoaderCreateInstance create_callback = NULL;
+    for (uint32_t idx = 0; (create_callback = PluginManager::GetJITLoaderCreateCallbackAtIndex(idx)) != NULL; ++idx)
+    {
+        JITLoaderSP instance_sp(create_callback(process, false));
+        if (instance_sp)
+            list.Append(std::move(instance_sp));
+    }
+}
+
+JITLoader::JITLoader(Process *process) :
+    m_process (process)
+{
+}
+
+JITLoader::~JITLoader()
+{
+}

Added: lldb/trunk/source/Core/JITLoaderList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/JITLoaderList.cpp?rev=202956&view=auto
==============================================================================
--- lldb/trunk/source/Core/JITLoaderList.cpp (added)
+++ lldb/trunk/source/Core/JITLoaderList.cpp Wed Mar  5 04:12:43 2014
@@ -0,0 +1,69 @@
+//===-- JITLoader.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/JITLoader.h"
+#include "lldb/Target/JITLoaderList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+JITLoaderList::JITLoaderList()
+    : m_jit_loaders_vec(), m_jit_loaders_mutex(Mutex::eMutexTypeRecursive)
+{
+}
+
+JITLoaderList::~JITLoaderList()
+{
+}
+
+void
+JITLoaderList::Append (const JITLoaderSP &jit_loader_sp)
+{
+    Mutex::Locker locker(m_jit_loaders_mutex);
+    m_jit_loaders_vec.push_back(jit_loader_sp);
+}
+
+void
+JITLoaderList::Remove (const JITLoaderSP &jit_loader_sp)
+{
+    Mutex::Locker locker(m_jit_loaders_mutex);
+    m_jit_loaders_vec.erase(std::remove(m_jit_loaders_vec.begin(),
+                                        m_jit_loaders_vec.end(), jit_loader_sp),
+                            m_jit_loaders_vec.end());
+}
+
+size_t
+JITLoaderList::GetSize() const
+{
+    return m_jit_loaders_vec.size();
+}
+
+JITLoaderSP
+JITLoaderList::GetLoaderAtIndex (size_t idx)
+{
+    Mutex::Locker locker(m_jit_loaders_mutex);
+    return m_jit_loaders_vec[idx];
+}
+
+void
+JITLoaderList::DidLaunch()
+{
+    Mutex::Locker locker(m_jit_loaders_mutex);
+    for (auto const &jit_loader : m_jit_loaders_vec)
+        jit_loader->DidLaunch();
+}
+
+void
+JITLoaderList::DidAttach()
+{
+    Mutex::Locker locker(m_jit_loaders_mutex);
+    for (auto const &jit_loader : m_jit_loaders_vec)
+        jit_loader->DidAttach();
+}

Modified: lldb/trunk/source/Core/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Module.cpp?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/source/Core/Module.cpp (original)
+++ lldb/trunk/source/Core/Module.cpp Wed Mar  5 04:12:43 2014
@@ -284,7 +284,7 @@ Module::~Module()
 }
 
 ObjectFile *
-Module::GetMemoryObjectFile (const lldb::ProcessSP &process_sp, lldb::addr_t header_addr, Error &error)
+Module::GetMemoryObjectFile (const lldb::ProcessSP &process_sp, lldb::addr_t header_addr, Error &error, size_t size_to_read)
 {
     if (m_objfile_sp)
     {
@@ -296,13 +296,13 @@ Module::GetMemoryObjectFile (const lldb:
         if (process_sp)
         {
             m_did_load_objfile = true;
-            std::unique_ptr<DataBufferHeap> data_ap (new DataBufferHeap (512, 0));
+            std::unique_ptr<DataBufferHeap> data_ap (new DataBufferHeap (size_to_read, 0));
             Error readmem_error;
             const size_t bytes_read = process_sp->ReadMemory (header_addr, 
                                                               data_ap->GetBytes(), 
                                                               data_ap->GetByteSize(), 
                                                               readmem_error);
-            if (bytes_read == 512)
+            if (bytes_read == size_to_read)
             {
                 DataBufferSP data_sp(data_ap.release());
                 m_objfile_sp = ObjectFile::FindPlugin(shared_from_this(), process_sp, header_addr, data_sp);

Modified: lldb/trunk/source/Core/PluginManager.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/PluginManager.cpp?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/source/Core/PluginManager.cpp (original)
+++ lldb/trunk/source/Core/PluginManager.cpp Wed Mar  5 04:12:43 2014
@@ -544,6 +544,116 @@ PluginManager::GetDynamicLoaderCreateCal
     return NULL;
 }
 
+#pragma mark JITLoader
+
+
+struct JITLoaderInstance
+{
+    JITLoaderInstance() :
+        name(),
+        description(),
+        create_callback(NULL),
+        debugger_init_callback (NULL)
+    {
+    }
+
+    ConstString name;
+    std::string description;
+    JITLoaderCreateInstance create_callback;
+    DebuggerInitializeCallback debugger_init_callback;
+};
+
+typedef std::vector<JITLoaderInstance> JITLoaderInstances;
+
+
+static Mutex &
+GetJITLoaderMutex ()
+{
+    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
+    return g_instances_mutex;
+}
+
+static JITLoaderInstances &
+GetJITLoaderInstances ()
+{
+    static JITLoaderInstances g_instances;
+    return g_instances;
+}
+
+
+bool
+PluginManager::RegisterPlugin
+(
+    const ConstString &name,
+    const char *description,
+    JITLoaderCreateInstance create_callback,
+    DebuggerInitializeCallback debugger_init_callback
+)
+{
+    if (create_callback)
+    {
+        JITLoaderInstance instance;
+        assert ((bool)name);
+        instance.name = name;
+        if (description && description[0])
+            instance.description = description;
+        instance.create_callback = create_callback;
+        instance.debugger_init_callback = debugger_init_callback;
+        Mutex::Locker locker (GetJITLoaderMutex ());
+        GetJITLoaderInstances ().push_back (instance);
+    }
+    return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (JITLoaderCreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        Mutex::Locker locker (GetJITLoaderMutex ());
+        JITLoaderInstances &instances = GetJITLoaderInstances ();
+        
+        JITLoaderInstances::iterator pos, end = instances.end();
+        for (pos = instances.begin(); pos != end; ++ pos)
+        {
+            if (pos->create_callback == create_callback)
+            {
+                instances.erase(pos);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+JITLoaderCreateInstance
+PluginManager::GetJITLoaderCreateCallbackAtIndex (uint32_t idx)
+{
+    Mutex::Locker locker (GetJITLoaderMutex ());
+    JITLoaderInstances &instances = GetJITLoaderInstances ();
+    if (idx < instances.size())
+        return instances[idx].create_callback;
+    return NULL;
+}
+
+JITLoaderCreateInstance
+PluginManager::GetJITLoaderCreateCallbackForPluginName (const ConstString &name)
+{
+    if (name)
+    {
+        Mutex::Locker locker (GetJITLoaderMutex ());
+        JITLoaderInstances &instances = GetJITLoaderInstances ();
+        
+        JITLoaderInstances::iterator pos, end = instances.end();
+        for (pos = instances.begin(); pos != end; ++ pos)
+        {
+            if (name == pos->name)
+                return pos->create_callback;
+        }
+    }
+    return NULL;
+}
+
 #pragma mark EmulateInstruction
 
 
@@ -1941,6 +2051,19 @@ PluginManager::DebuggerInitialize (Debug
         for (pos = instances.begin(); pos != end; ++ pos)
         {
             if (pos->debugger_init_callback)
+                pos->debugger_init_callback (debugger);
+        }
+    }
+
+    // Initialize the JITLoader plugins
+    {
+        Mutex::Locker locker (GetJITLoaderMutex ());
+        JITLoaderInstances &instances = GetJITLoaderInstances ();
+    
+        JITLoaderInstances::iterator pos, end = instances.end();
+        for (pos = instances.begin(); pos != end; ++ pos)
+        {
+            if (pos->debugger_init_callback)
                 pos->debugger_init_callback (debugger);
         }
     }

Modified: lldb/trunk/source/Plugins/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/CMakeLists.txt?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/CMakeLists.txt Wed Mar  5 04:12:43 2014
@@ -2,6 +2,7 @@ add_subdirectory(ABI)
 add_subdirectory(Disassembler)
 add_subdirectory(DynamicLoader)
 add_subdirectory(Instruction)
+add_subdirectory(JITLoader)
 add_subdirectory(LanguageRuntime)
 add_subdirectory(ObjectContainer)
 add_subdirectory(ObjectFile)

Added: lldb/trunk/source/Plugins/JITLoader/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/JITLoader/CMakeLists.txt?rev=202956&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/JITLoader/CMakeLists.txt (added)
+++ lldb/trunk/source/Plugins/JITLoader/CMakeLists.txt Wed Mar  5 04:12:43 2014
@@ -0,0 +1,3 @@
+if (CMAKE_SYSTEM_NAME MATCHES "Linux")
+  add_subdirectory(GDB)
+endif()

Added: lldb/trunk/source/Plugins/JITLoader/GDB/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/JITLoader/GDB/CMakeLists.txt?rev=202956&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/JITLoader/GDB/CMakeLists.txt (added)
+++ lldb/trunk/source/Plugins/JITLoader/GDB/CMakeLists.txt Wed Mar  5 04:12:43 2014
@@ -0,0 +1,8 @@
+set(LLVM_NO_RTTI 1)
+
+include_directories(.)
+
+add_lldb_library(lldbPluginJITLoaderGDB
+  JITLoaderGDB.cpp
+  )
+

Added: lldb/trunk/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp?rev=202956&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp (added)
+++ lldb/trunk/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp Wed Mar  5 04:12:43 2014
@@ -0,0 +1,383 @@
+//===-- JITLoaderGDB.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Symbol/SymbolVendor.h"
+
+#include "JITLoaderGDB.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+// Debug Interface Structures
+//------------------------------------------------------------------
+typedef enum
+{
+    JIT_NOACTION = 0,
+    JIT_REGISTER_FN,
+    JIT_UNREGISTER_FN
+} jit_actions_t;
+
+struct jit_code_entry
+{
+    struct jit_code_entry *next_entry;
+    struct jit_code_entry *prev_entry;
+    const char *symfile_addr;
+    uint64_t symfile_size;
+};
+
+struct jit_descriptor
+{
+    uint32_t version;
+    uint32_t action_flag; // Values are jit_action_t
+    struct jit_code_entry *relevant_entry;
+    struct jit_code_entry *first_entry;
+};
+
+JITLoaderGDB::JITLoaderGDB (lldb_private::Process *process) :
+    JITLoader(process),
+    m_jit_objects(),
+    m_jit_break_id(LLDB_INVALID_BREAK_ID)
+{
+    m_notification_callbacks.baton = this;
+    m_notification_callbacks.initialize = nullptr;
+    m_notification_callbacks.process_state_changed =
+        ProcessStateChangedCallback;
+    m_process->RegisterNotificationCallbacks(m_notification_callbacks);
+}
+
+JITLoaderGDB::~JITLoaderGDB ()
+{
+    if (LLDB_BREAK_ID_IS_VALID(m_jit_break_id))
+        m_process->GetTarget().RemoveBreakpointByID (m_jit_break_id);
+    m_jit_break_id = LLDB_INVALID_BREAK_ID;
+}
+
+void JITLoaderGDB::DidAttach()
+{
+    SetJITBreakpoint();
+}
+
+void JITLoaderGDB::DidLaunch()
+{
+    SetJITBreakpoint();
+}
+
+//------------------------------------------------------------------
+// Setup the JIT Breakpoint
+//------------------------------------------------------------------
+void
+JITLoaderGDB::SetJITBreakpoint()
+{
+    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
+
+    if ( DidSetJITBreakpoint() )
+        return;
+
+    if (log)
+        log->Printf("JITLoaderGDB::%s looking for JIT register hook",
+                    __FUNCTION__);
+
+    addr_t jit_addr = GetSymbolAddress(ConstString("__jit_debug_register_code"),
+                                       eSymbolTypeAny);
+    if (jit_addr == LLDB_INVALID_ADDRESS)
+        return;
+
+    if (log)
+        log->Printf("JITLoaderGDB::%s setting JIT breakpoint",
+                    __FUNCTION__);
+
+    Breakpoint *bp =
+        m_process->GetTarget().CreateBreakpoint(jit_addr, true, false).get();
+    bp->SetCallback(JITDebugBreakpointHit, this, true);
+    bp->SetBreakpointKind("jit-debug-register");
+    m_jit_break_id = bp->GetID();
+
+    ReadJITDescriptor(true);
+}
+
+bool
+JITLoaderGDB::JITDebugBreakpointHit(void *baton,
+                                    StoppointCallbackContext *context,
+                                    user_id_t break_id, user_id_t break_loc_id)
+{
+    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
+    if (log)
+        log->Printf("JITLoaderGDB::%s hit JIT breakpoint",
+                    __FUNCTION__);
+    JITLoaderGDB *instance = static_cast<JITLoaderGDB *>(baton);
+    return instance->ReadJITDescriptor(false);
+}
+
+bool
+JITLoaderGDB::ReadJITDescriptor(bool all_entries)
+{
+    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
+    Target &target = m_process->GetTarget();
+    ModuleList &images = target.GetImages();
+
+    addr_t jit_addr = GetSymbolAddress(ConstString("__jit_debug_descriptor"),
+                                       eSymbolTypeData);
+    if (jit_addr == LLDB_INVALID_ADDRESS)
+    {
+        if (log)
+            log->Printf(
+                "JITLoaderGDB::%s failed to find JIT descriptor address",
+                __FUNCTION__);
+        return false;
+    }
+
+    jit_descriptor jit_desc;
+    const size_t jit_desc_size = sizeof(jit_desc);
+    Error error;
+    size_t bytes_read =
+        m_process->DoReadMemory(jit_addr, &jit_desc, jit_desc_size, error);
+    if (bytes_read != jit_desc_size || !error.Success())
+    {
+        if (log)
+            log->Printf("JITLoaderGDB::%s failed to read JIT descriptor",
+                        __FUNCTION__);
+        return false;
+    }
+
+    jit_actions_t jit_action = (jit_actions_t)jit_desc.action_flag;
+    addr_t jit_relevant_entry = (addr_t)jit_desc.relevant_entry;
+    if (all_entries)
+    {
+        jit_action = JIT_REGISTER_FN;
+        jit_relevant_entry = (addr_t)jit_desc.first_entry;
+    }
+
+    while (jit_relevant_entry != 0)
+    {
+        jit_code_entry jit_entry;
+        const size_t jit_entry_size = sizeof(jit_entry);
+        bytes_read = m_process->DoReadMemory(jit_relevant_entry, &jit_entry, jit_entry_size, error);
+        if (bytes_read != jit_entry_size || !error.Success())
+        {
+            if (log)
+                log->Printf(
+                    "JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64,
+                    __FUNCTION__, jit_relevant_entry);
+            return false;
+        }
+
+        const addr_t &symbolfile_addr = (addr_t)jit_entry.symfile_addr;
+        const size_t &symbolfile_size = (size_t)jit_entry.symfile_size;
+        ModuleSP module_sp;
+
+        if (jit_action == JIT_REGISTER_FN)
+        {
+            if (log)
+                log->Printf(
+                    "JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64
+                    " (%" PRIu64 " bytes)",
+                    __FUNCTION__, symbolfile_addr, symbolfile_size);
+
+            char jit_name[64];
+            snprintf(jit_name, 64, "JIT(0x%" PRIx64 ")", symbolfile_addr);
+            module_sp = m_process->ReadModuleFromMemory(
+                FileSpec(jit_name, false), symbolfile_addr, symbolfile_size);
+
+            if (module_sp && module_sp->GetObjectFile())
+            {
+                bool changed;
+                m_jit_objects.insert(
+                    std::pair<lldb::addr_t, const lldb::ModuleSP>(
+                        symbolfile_addr, module_sp));
+                module_sp->SetLoadAddress(target, 0, true, changed);
+
+                // load the symbol table right away
+                module_sp->GetObjectFile()->GetSymtab();
+
+                images.AppendIfNeeded(module_sp);
+
+                ModuleList module_list;
+                module_list.Append(module_sp);
+                target.ModulesDidLoad(module_list);
+            }
+            else
+            {
+                if (log)
+                    log->Printf("JITLoaderGDB::%s failed to load module for "
+                                "JIT entry at 0x%" PRIx64,
+                                __FUNCTION__, symbolfile_addr);
+            }
+        }
+        else if (jit_action == JIT_UNREGISTER_FN)
+        {
+            if (log)
+                log->Printf(
+                    "JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64,
+                    __FUNCTION__, symbolfile_addr);
+
+            JITObjectMap::iterator it = m_jit_objects.find(symbolfile_addr);
+            if (it != m_jit_objects.end())
+            {
+                module_sp = it->second;
+                ObjectFile *image_object_file = module_sp->GetObjectFile();
+                if (image_object_file)
+                {
+                    const SectionList *section_list = image_object_file->GetSectionList ();
+                    if (section_list)
+                    {
+                        const uint32_t num_sections = section_list->GetSize();
+                        for (uint32_t i = 0; i<num_sections; ++i)
+                        {
+                            SectionSP section_sp(section_list->GetSectionAtIndex(i));
+                            if (section_sp)
+                            {
+                                target.GetSectionLoadList().SetSectionUnloaded (section_sp);
+                            }
+                        }
+                    }
+                }
+                images.Remove(module_sp);
+                m_jit_objects.erase(it);
+            }
+        }
+        else if (jit_action == JIT_NOACTION)
+        {
+            // Nothing to do
+        }
+        else
+        {
+            assert(false && "Unknown jit action");
+        }
+
+        if (all_entries)
+            jit_relevant_entry = (addr_t)jit_entry.next_entry;
+        else
+            jit_relevant_entry = 0;
+    }
+
+    return false; // Continue Running.
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+JITLoaderGDB::GetPluginNameStatic()
+{
+    static ConstString g_name("gdb");
+    return g_name;
+}
+
+JITLoaderSP
+JITLoaderGDB::CreateInstance(Process *process, bool force)
+{
+    JITLoaderSP jit_loader_sp(new JITLoaderGDB(process));
+    return jit_loader_sp;
+}
+
+const char *
+JITLoaderGDB::GetPluginDescriptionStatic()
+{
+    return "JIT loader plug-in that watches for JIT events using the GDB interface.";
+}
+
+lldb_private::ConstString
+JITLoaderGDB::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+JITLoaderGDB::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+JITLoaderGDB::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+JITLoaderGDB::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+bool
+JITLoaderGDB::DidSetJITBreakpoint() const
+{
+    return LLDB_BREAK_ID_IS_VALID(m_jit_break_id);
+}
+
+void
+JITLoaderGDB::ProcessStateChangedCallback(void *baton,
+                                          lldb_private::Process *process,
+                                          lldb::StateType state)
+{
+    JITLoaderGDB* instance = static_cast<JITLoaderGDB*>(baton);
+
+    switch (state)
+    {
+    case eStateConnected:
+    case eStateAttaching:
+    case eStateLaunching:
+    case eStateInvalid:
+    case eStateUnloaded:
+    case eStateExited:
+    case eStateDetached:
+        // instance->Clear(false);
+        break;
+
+    case eStateRunning:
+    case eStateStopped:
+        // Keep trying to set our JIT breakpoint each time we stop until we
+        // succeed
+        if (!instance->DidSetJITBreakpoint() && process->IsAlive())
+            instance->SetJITBreakpoint();
+        break;
+
+    case eStateStepping:
+    case eStateCrashed:
+    case eStateSuspended:
+        break;
+    }
+}
+
+addr_t
+JITLoaderGDB::GetSymbolAddress(const ConstString &name, SymbolType symbol_type) const
+{
+    SymbolContextList target_symbols;
+    Target &target = m_process->GetTarget();
+    ModuleList &images = target.GetImages();
+
+    if (!images.FindSymbolsWithNameAndType(name, symbol_type, target_symbols))
+        return LLDB_INVALID_ADDRESS;
+
+    SymbolContext sym_ctx;
+    target_symbols.GetContextAtIndex(0, sym_ctx);
+
+    const Address *jit_descriptor_addr = &sym_ctx.symbol->GetAddress();
+    if (!jit_descriptor_addr || !jit_descriptor_addr->IsValid())
+        return LLDB_INVALID_ADDRESS;
+
+    const addr_t jit_addr = jit_descriptor_addr->GetLoadAddress(&target);
+    return jit_addr;
+}

Added: lldb/trunk/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/JITLoader/GDB/JITLoaderGDB.h?rev=202956&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/JITLoader/GDB/JITLoaderGDB.h (added)
+++ lldb/trunk/source/Plugins/JITLoader/GDB/JITLoaderGDB.h Wed Mar  5 04:12:43 2014
@@ -0,0 +1,100 @@
+//===-- JITLoaderGDB.h ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_JITLoaderGDB_h_
+#define liblldb_JITLoaderGDB_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <vector>
+#include <string>
+
+#include "lldb/Target/JITLoader.h"
+#include "lldb/Target/Process.h"
+
+class JITLoaderGDB : public lldb_private::JITLoader
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb::JITLoaderSP
+    CreateInstance (lldb_private::Process *process, bool force);
+
+    JITLoaderGDB (lldb_private::Process *process);
+
+    virtual
+    ~JITLoaderGDB ();
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    //------------------------------------------------------------------
+    // JITLoader interface
+    //------------------------------------------------------------------
+    virtual void
+    DidAttach ();
+
+    virtual void
+    DidLaunch ();
+
+private:
+    lldb::addr_t
+    GetSymbolAddress(const lldb_private::ConstString &name,
+                     lldb::SymbolType symbol_type) const;
+
+    void
+    SetJITBreakpoint();
+
+    bool
+    DidSetJITBreakpoint() const;
+
+    bool
+    ReadJITDescriptor(bool all_entries);
+
+    static bool
+    JITDebugBreakpointHit(void *baton,
+                          lldb_private::StoppointCallbackContext *context,
+                          lldb::user_id_t break_id,
+                          lldb::user_id_t break_loc_id);
+
+    static void
+    ProcessStateChangedCallback(void *baton,
+                                lldb_private::Process *process,
+                                lldb::StateType state);
+
+    // A collection of in-memory jitted object addresses and their corresponding modules
+    typedef std::map<lldb::addr_t, const lldb::ModuleSP> JITObjectMap;
+    JITObjectMap m_jit_objects;
+
+    lldb::user_id_t m_jit_break_id;
+    lldb_private::Process::Notifications m_notification_callbacks;
+
+};
+
+#endif

Added: lldb/trunk/source/Plugins/JITLoader/GDB/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/JITLoader/GDB/Makefile?rev=202956&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/JITLoader/GDB/Makefile (added)
+++ lldb/trunk/source/Plugins/JITLoader/GDB/Makefile Wed Mar  5 04:12:43 2014
@@ -0,0 +1,14 @@
+##===- source/Plugins/JITLoader/GDBJIT/Makefile ------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginJITLoaderGDB
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile

Modified: lldb/trunk/source/Plugins/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Makefile?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Makefile (original)
+++ lldb/trunk/source/Plugins/Makefile Wed Mar  5 04:12:43 2014
@@ -37,6 +37,7 @@ ifeq ($(HOST_OS),Linux)
 DIRS += DynamicLoader/MacOSX-DYLD
 DIRS += Process/Linux Process/POSIX
 DIRS += Process/elf-core
+DIRS += JITLoader/GDB
 endif
 
 ifneq (,$(filter $(HOST_OS), FreeBSD GNU/kFreeBSD))

Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Wed Mar  5 04:12:43 2014
@@ -72,6 +72,18 @@ public:
     static unsigned
     RelocSymbol64(const ELFRelocation &rel);
 
+    static unsigned
+    RelocOffset32(const ELFRelocation &rel);
+
+    static unsigned
+    RelocOffset64(const ELFRelocation &rel);
+
+    static unsigned
+    RelocAddend32(const ELFRelocation &rel);
+
+    static unsigned
+    RelocAddend64(const ELFRelocation &rel);
+
 private:
     typedef llvm::PointerUnion<ELFRel*, ELFRela*> RelocUnion;
 
@@ -80,9 +92,9 @@ private:
 
 ELFRelocation::ELFRelocation(unsigned type)
 { 
-    if (type == DT_REL)
+    if (type == DT_REL || type == SHT_REL)
         reloc = new ELFRel();
-    else if (type == DT_RELA)
+    else if (type == DT_RELA || type == SHT_RELA)
         reloc = new ELFRela();
     else {
         assert(false && "unexpected relocation type");
@@ -143,6 +155,42 @@ ELFRelocation::RelocSymbol64(const ELFRe
         return ELFRela::RelocSymbol64(*rel.reloc.get<ELFRela*>());
 }
 
+unsigned
+ELFRelocation::RelocOffset32(const ELFRelocation &rel)
+{
+    if (rel.reloc.is<ELFRel*>())
+        return rel.reloc.get<ELFRel*>()->r_offset;
+    else
+        return rel.reloc.get<ELFRela*>()->r_offset;
+}
+
+unsigned
+ELFRelocation::RelocOffset64(const ELFRelocation &rel)
+{
+    if (rel.reloc.is<ELFRel*>())
+        return rel.reloc.get<ELFRel*>()->r_offset;
+    else
+        return rel.reloc.get<ELFRela*>()->r_offset;
+}
+
+unsigned
+ELFRelocation::RelocAddend32(const ELFRelocation &rel)
+{
+    if (rel.reloc.is<ELFRel*>())
+        return 0;
+    else
+        return rel.reloc.get<ELFRela*>()->r_addend;
+}
+
+unsigned
+ELFRelocation::RelocAddend64(const ELFRelocation &rel)
+{
+    if (rel.reloc.is<ELFRel*>())
+        return 0;
+    else
+        return rel.reloc.get<ELFRela*>()->r_addend;
+}
+
 } // end anonymous namespace
 
 bool
@@ -261,6 +309,22 @@ ObjectFileELF::CreateMemoryInstance (con
                                      const lldb::ProcessSP &process_sp, 
                                      lldb::addr_t header_addr)
 {
+    if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT))
+    {
+        const uint8_t *magic = data_sp->GetBytes();
+        if (ELFHeader::MagicBytesMatch(magic))
+        {
+            unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
+            if (address_size == 4 || address_size == 8)
+            {
+                std::auto_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(module_sp, data_sp, process_sp, header_addr));
+                ArchSpec spec;
+                if (objfile_ap->GetArchitecture(spec) &&
+                    objfile_ap->SetModulesArchitecture(spec))
+                    return objfile_ap.release();
+            }
+        }
+    }
     return NULL;
 }
 
@@ -453,6 +517,19 @@ ObjectFileELF::ObjectFileELF (const lldb
     m_gnu_debuglink_file.clear();
 }
 
+ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,
+                              DataBufferSP& data_sp,
+                              const lldb::ProcessSP &process_sp,
+                              addr_t header_addr) :
+    ObjectFile(module_sp, process_sp, LLDB_INVALID_ADDRESS, data_sp),
+    m_header(),
+    m_program_headers(),
+    m_section_headers(),
+    m_filespec_ap()
+{
+    ::memset(&m_header, 0, sizeof(m_header));
+}
+
 ObjectFileELF::~ObjectFileELF()
 {
 }
@@ -1117,8 +1194,9 @@ ObjectFileELF::ParseSymbols (Symtab *sym
         
         const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
 
-        // No need to add symbols that have no names
-        if (symbol_name == NULL || symbol_name[0] == '\0')
+        // No need to add non-section symbols that have no names
+        if (symbol.getType() != STT_SECTION &&
+            (symbol_name == NULL || symbol_name[0] == '\0'))
             continue;
 
         //symbol.Dump (&strm, i, &strtab_data, section_list);
@@ -1228,7 +1306,7 @@ ObjectFileELF::ParseSymbols (Symtab *sym
         }
 
         uint64_t symbol_value = symbol.st_value;
-        if (symbol_section_sp)
+        if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile)
             symbol_value -= symbol_section_sp->GetFileAddress();
         bool is_global = symbol.getBinding() == STB_GLOBAL;
         uint32_t flags = symbol.st_other << 8 | symbol.st_info;
@@ -1526,6 +1604,136 @@ ObjectFileELF::ParseTrampolineSymbols(Sy
                                 strtab_data);
 }
 
+unsigned
+ObjectFileELF::RelocateSection(Symtab* symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr,
+                const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr,
+                DataExtractor &rel_data, DataExtractor &symtab_data,
+                DataExtractor &debug_data, Section* rel_section)
+{
+    ELFRelocation rel(rel_hdr->sh_type);
+    lldb::addr_t offset = 0;
+    const unsigned num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
+    typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
+    reloc_info_fn reloc_type;
+    reloc_info_fn reloc_symbol;
+
+    if (hdr->Is32Bit())
+    {
+        reloc_type = ELFRelocation::RelocType32;
+        reloc_symbol = ELFRelocation::RelocSymbol32;
+    }
+    else
+    {
+        reloc_type = ELFRelocation::RelocType64;
+        reloc_symbol = ELFRelocation::RelocSymbol64;
+    }
+
+    for (unsigned i = 0; i < num_relocations; ++i)
+    {
+        if (rel.Parse(rel_data, &offset) == false)
+            break;
+
+        Symbol* symbol = NULL;
+
+        if (hdr->Is32Bit())
+        {
+            switch (reloc_type(rel)) {
+            case R_386_32:
+            case R_386_PC32:
+            default:
+                assert(false && "unexpected relocation type");
+            }
+        } else {
+            switch (reloc_type(rel)) {
+            case R_X86_64_64:
+            {
+                symbol = symtab->FindSymbolByID(reloc_symbol(rel));
+                if (symbol)
+                {
+                    addr_t value = symbol->GetAddress().GetFileAddress();
+                    DataBufferSP& data_buffer_sp = debug_data.GetSharedDataBuffer();
+                    uint64_t* dst = reinterpret_cast<uint64_t*>(data_buffer_sp->GetBytes() + rel_section->GetFileOffset() + ELFRelocation::RelocOffset64(rel));
+                    *dst = value + ELFRelocation::RelocAddend64(rel);
+                }
+                break;
+            }
+            case R_X86_64_32:
+            case R_X86_64_32S:
+            {
+                symbol = symtab->FindSymbolByID(reloc_symbol(rel));
+                if (symbol)
+                {
+                    addr_t value = symbol->GetAddress().GetFileAddress();
+                    value += ELFRelocation::RelocAddend32(rel);
+                    assert((reloc_type(rel) == R_X86_64_32 && (value <= UINT32_MAX)) ||
+                           (reloc_type(rel) == R_X86_64_32S &&
+                            ((int64_t)value <= INT32_MAX && (int64_t)value >= INT32_MIN)));
+                    uint32_t truncated_addr = (value & 0xFFFFFFFF);
+                    DataBufferSP& data_buffer_sp = debug_data.GetSharedDataBuffer();
+                    uint32_t* dst = reinterpret_cast<uint32_t*>(data_buffer_sp->GetBytes() + rel_section->GetFileOffset() + ELFRelocation::RelocOffset32(rel));
+                    *dst = truncated_addr;
+                }
+                break;
+            }
+            case R_X86_64_PC32:
+            default:
+                assert(false && "unexpected relocation type");
+            }
+        }
+    }
+
+    return 0;
+}
+
+unsigned
+ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr, user_id_t rel_id)
+{
+    assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);
+
+    // Parse in the section list if needed.
+    SectionList *section_list = GetSectionList();
+    if (!section_list)
+        return 0;
+
+    // Section ID's are ones based.
+    user_id_t symtab_id = rel_hdr->sh_link + 1;
+    user_id_t debug_id = rel_hdr->sh_info + 1;
+
+    const ELFSectionHeader *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
+    if (!symtab_hdr)
+        return 0;
+
+    const ELFSectionHeader *debug_hdr = GetSectionHeaderByIndex(debug_id);
+    if (!debug_hdr)
+        return 0;
+
+    Section *rel = section_list->FindSectionByID(rel_id).get();
+    if (!rel)
+        return 0;
+
+    Section *symtab = section_list->FindSectionByID(symtab_id).get();
+    if (!symtab)
+        return 0;
+
+    Section *debug = section_list->FindSectionByID(debug_id).get();
+    if (!debug)
+        return 0;
+
+    DataExtractor rel_data;
+    DataExtractor symtab_data;
+    DataExtractor debug_data;
+
+    if (ReadSectionData(rel, rel_data) &&
+        ReadSectionData(symtab, symtab_data) &&
+        ReadSectionData(debug, debug_data))
+    {
+        RelocateSection(m_symtab_ap.get(), &m_header, rel_hdr, symtab_hdr, debug_hdr,
+                        rel_data, symtab_data, debug_data, debug);
+    }
+
+    return 0;
+}
+
 Symtab *
 ObjectFileELF::GetSymtab()
 {
@@ -1588,6 +1796,25 @@ ObjectFileELF::GetSymtab()
             }
         }
     }
+
+    for (SectionHeaderCollIter I = m_section_headers.begin();
+         I != m_section_headers.end(); ++I)
+    {
+        if (I->sh_type == SHT_RELA || I->sh_type == SHT_REL)
+        {
+            if (CalculateType() == eTypeObjectFile)
+            {
+                const char *section_name = I->section_name.AsCString("");
+                if (strstr(section_name, ".rela.debug") ||
+                    strstr(section_name, ".rel.debug"))
+                {
+                    const ELFSectionHeader &reloc_header = *I;
+                    user_id_t reloc_id = SectionIndex(I);
+                    RelocateDebugSections(&reloc_header, reloc_id);
+                }
+            }
+        }
+    }
     return m_symtab_ap.get();
 }
 

Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h Wed Mar  5 04:12:43 2014
@@ -191,6 +191,11 @@ private:
                   lldb::offset_t offset,
                   lldb::offset_t length);
 
+    ObjectFileELF (const lldb::ModuleSP &module_sp,
+                   lldb::DataBufferSP& data_sp,
+                   const lldb::ProcessSP &process_sp,
+                   lldb::addr_t header_addr);
+
     typedef std::vector<elf::ELFProgramHeader>  ProgramHeaderColl;
     typedef ProgramHeaderColl::iterator         ProgramHeaderCollIter;
     typedef ProgramHeaderColl::const_iterator   ProgramHeaderCollConstIter;
@@ -303,6 +308,32 @@ private:
                            const ELFSectionHeaderInfo *rela_hdr,
                            lldb::user_id_t section_id);
 
+    /// Relocates debug sections
+    unsigned
+    RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr, lldb::user_id_t rel_id);
+
+    unsigned
+    RelocateSection(lldb_private::Symtab* symtab, const elf::ELFHeader *hdr, const elf::ELFSectionHeader *rel_hdr,
+                    const elf::ELFSectionHeader *symtab_hdr, const elf::ELFSectionHeader *debug_hdr,
+                    lldb_private::DataExtractor &rel_data, lldb_private::DataExtractor &symtab_data,
+                    lldb_private::DataExtractor &debug_data, lldb_private::Section* rel_section);
+
+    /// Loads the section name string table into m_shstr_data.  Returns the
+    /// number of bytes constituting the table.
+    size_t
+    GetSectionHeaderStringTable();
+
+    /// Utility method for looking up a section given its name.  Returns the
+    /// index of the corresponding section or zero if no section with the given
+    /// name can be found (note that section indices are always 1 based, and so
+    /// section index 0 is never valid).
+    lldb::user_id_t
+    GetSectionIndexByName(const char *name);
+
+    // Returns the ID of the first section that has the given type.
+    lldb::user_id_t
+    GetSectionIndexByType(unsigned type);
+
     /// Returns the section header with the given id or NULL.
     const ELFSectionHeaderInfo *
     GetSectionHeaderByIndex(lldb::user_id_t id);

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Wed Mar  5 04:12:43 2014
@@ -30,6 +30,7 @@
 #include "lldb/Host/Terminal.h"
 #include "lldb/Target/ABI.h"
 #include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/JITLoader.h"
 #include "lldb/Target/OperatingSystem.h"
 #include "lldb/Target/LanguageRuntime.h"
 #include "lldb/Target/CPPLanguageRuntime.h"
@@ -1154,6 +1155,7 @@ Process::Finalize()
     m_os_ap.reset();
     m_system_runtime_ap.reset();
     m_dyld_ap.reset();
+    m_jit_loaders_ap.reset();
     m_thread_list_real.Destroy();
     m_thread_list.Destroy();
     m_extended_thread_list.Destroy();
@@ -2929,13 +2931,14 @@ Process::DeallocateMemory (addr_t ptr)
 
 ModuleSP
 Process::ReadModuleFromMemory (const FileSpec& file_spec, 
-                               lldb::addr_t header_addr)
+                               lldb::addr_t header_addr,
+                               size_t size_to_read)
 {
     ModuleSP module_sp (new Module (file_spec, ArchSpec()));
     if (module_sp)
     {
         Error error;
-        ObjectFile *objfile = module_sp->GetMemoryObjectFile (shared_from_this(), header_addr, error);
+        ObjectFile *objfile = module_sp->GetMemoryObjectFile (shared_from_this(), header_addr, error, size_to_read);
         if (objfile)
             return module_sp;
     }
@@ -2988,6 +2991,7 @@ Process::Launch (ProcessLaunchInfo &laun
     Error error;
     m_abi_sp.reset();
     m_dyld_ap.reset();
+    m_jit_loaders_ap.reset();
     m_system_runtime_ap.reset();
     m_os_ap.reset();
     m_process_input_reader.reset();
@@ -3064,6 +3068,8 @@ Process::Launch (ProcessLaunchInfo &laun
                         if (dyld)
                             dyld->DidLaunch();
 
+                        GetJITLoaders().DidLaunch();
+
                         SystemRuntime *system_runtime = GetSystemRuntime ();
                         if (system_runtime)
                             system_runtime->DidLaunch();
@@ -3110,6 +3116,8 @@ Process::LoadCore ()
         DynamicLoader *dyld = GetDynamicLoader ();
         if (dyld)
             dyld->DidAttach();
+
+        GetJITLoaders().DidAttach();
         
         SystemRuntime *system_runtime = GetSystemRuntime ();
         if (system_runtime)
@@ -3133,6 +3141,17 @@ Process::GetDynamicLoader ()
     return m_dyld_ap.get();
 }
 
+JITLoaderList &
+Process::GetJITLoaders ()
+{
+    if (!m_jit_loaders_ap)
+    {
+        m_jit_loaders_ap.reset(new JITLoaderList());
+        JITLoader::LoadPlugins(this, *m_jit_loaders_ap);
+    }
+    return *m_jit_loaders_ap;
+}
+
 SystemRuntime *
 Process::GetSystemRuntime ()
 {
@@ -3203,6 +3222,7 @@ Process::Attach (ProcessAttachInfo &atta
     m_abi_sp.reset();
     m_process_input_reader.reset();
     m_dyld_ap.reset();
+    m_jit_loaders_ap.reset();
     m_system_runtime_ap.reset();
     m_os_ap.reset();
     
@@ -3376,6 +3396,8 @@ Process::CompleteAttach ()
     if (dyld)
         dyld->DidAttach();
 
+    GetJITLoaders().DidAttach();
+
     SystemRuntime *system_runtime = GetSystemRuntime ();
     if (system_runtime)
         system_runtime->DidAttach();
@@ -3546,7 +3568,7 @@ Process::Halt (bool clear_thread_plans)
                     // Wait for 1 second for the process to stop.
                     TimeValue timeout_time;
                     timeout_time = TimeValue::Now();
-                    timeout_time.OffsetWithSeconds(1);
+                    timeout_time.OffsetWithSeconds(10);
                     bool got_event = halt_listener.WaitForEvent (&timeout_time, event_sp);
                     StateType state = ProcessEventData::GetStateFromEvent(event_sp.get());
                     
@@ -5957,6 +5979,7 @@ Process::DidExec ()
     m_system_runtime_ap.reset();
     m_os_ap.reset();
     m_dyld_ap.reset();
+    m_jit_loaders_ap.reset();
     m_image_tokens.clear();
     m_allocated_memory_cache.Clear();
     m_language_runtimes.clear();

Modified: lldb/trunk/source/lldb-log.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb-log.cpp?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/source/lldb-log.cpp (original)
+++ lldb/trunk/source/lldb-log.cpp Wed Mar  5 04:12:43 2014
@@ -145,6 +145,7 @@ lldb_private::DisableLog (const char **c
                 else if (0 == ::strncasecmp(arg, "module", 6))  flag_bits &= ~LIBLLDB_LOG_MODULES;
                 else if (0 == ::strncasecmp(arg, "mmap", 4))    flag_bits &= ~LIBLLDB_LOG_MMAP;
                 else if (0 == ::strcasecmp(arg, "os"))          flag_bits &= ~LIBLLDB_LOG_OS;
+                else if (0 == ::strcasecmp(arg, "jit"))         flag_bits &= ~LIBLLDB_LOG_JIT_LOADER;
                 else
                 {
                     feedback_strm->Printf ("error:  unrecognized log category '%s'\n", arg);
@@ -220,6 +221,7 @@ lldb_private::EnableLog (StreamSP &log_s
             else if (0 == ::strncasecmp(arg, "unwind", 6))  flag_bits |= LIBLLDB_LOG_UNWIND;
             else if (0 == ::strcasecmp(arg, "verbose"))     flag_bits |= LIBLLDB_LOG_VERBOSE;
             else if (0 == ::strncasecmp(arg, "watch", 5))   flag_bits |= LIBLLDB_LOG_WATCHPOINTS;
+            else if (0 == ::strcasecmp(arg, "jit"))         flag_bits |= LIBLLDB_LOG_JIT_LOADER;
             else
             {
                 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
@@ -267,5 +269,6 @@ lldb_private::ListLogCategories (Stream
                  "  types - log type system related activities\n"
                  "  unwind - log stack unwind activities\n"
                  "  verbose - enable verbose logging\n"
-                 "  watch - log watchpoint related activities\n");
+                 "  watch - log watchpoint related activities\n"
+                 "  jit - log JIT events in the target\n");
 }

Modified: lldb/trunk/source/lldb.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb.cpp?rev=202956&r1=202955&r2=202956&view=diff
==============================================================================
--- lldb/trunk/source/lldb.cpp (original)
+++ lldb/trunk/source/lldb.cpp Wed Mar  5 04:12:43 2014
@@ -72,6 +72,7 @@
 
 #if defined (__linux__)
 #include "Plugins/Process/Linux/ProcessLinux.h"
+#include "Plugins/JITLoader/GDB/JITLoaderGDB.h"
 #endif
 
 #if defined (__FreeBSD__)
@@ -149,6 +150,7 @@ lldb_private::Initialize ()
         // Linux hosted plugins
         //----------------------------------------------------------------------
         ProcessLinux::Initialize();
+        JITLoaderGDB::Initialize();
 #endif
 #if defined (__FreeBSD__)
         ProcessFreeBSD::Initialize();
@@ -231,6 +233,7 @@ lldb_private::Terminate ()
 
 #if defined (__linux__)
     ProcessLinux::Terminate();
+    JITLoaderGDB::Terminate();
 #endif
 
 #if defined (__FreeBSD__)





More information about the lldb-commits mailing list