[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