[Lldb-commits] [lldb] r123592 - in /lldb/trunk: lib/ source/ source/Plugins/ source/Plugins/DynamicLoader/Linux-DYLD/ source/Plugins/Process/Linux/

Stephen Wilson wilsons at start.ca
Sun Jan 16 11:45:39 PST 2011


Author: wilsons
Date: Sun Jan 16 13:45:39 2011
New Revision: 123592

URL: http://llvm.org/viewvc/llvm-project?rev=123592&view=rev
Log:
Initial support for a DynamicLoader plugin on Linux.

This patch is enough to have shared objects recognized by LLDB.  We can handle
position independent executables.  We can handle dynamically loaded modules
brought in via dlopen.

The DYLDRendezvous class provides an interface to a structure present in the
address space of ELF-based processes.  This structure provides the address of a
function which is called by the linker each time a shared object is loaded and
unloaded (thus a breakpoint at that address will let LLDB intercept such
events), a list of entries describing the currently loaded shared objects, plus
a few other things.

On Linux, processes are brought up with an auxiliary vector on the stack.  One
element in this vector contains the (possibly dynamic) entry address of the
process.  One does not need to walk the stack to find this information as it is
also available under /proc/<pid>/auxv.  The new AuxVector class provides a
convenient read-only view of this auxiliary vector information.  We use the
dynamic entry address and the address as specified in the object file to compute
the actual load address of the inferior image.  This strategy works for both
normal executables and PIE's.


Added:
    lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/
    lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp
    lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h
    lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp
    lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h
    lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp
    lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h
    lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile
Modified:
    lldb/trunk/lib/Makefile
    lldb/trunk/source/Plugins/Makefile
    lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
    lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h
    lldb/trunk/source/lldb.cpp

Modified: lldb/trunk/lib/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lib/Makefile?rev=123592&r1=123591&r2=123592&view=diff
==============================================================================
--- lldb/trunk/lib/Makefile (original)
+++ lldb/trunk/lib/Makefile Sun Jan 16 13:45:39 2011
@@ -67,7 +67,8 @@
 endif
 
 ifeq ($(HOST_OS),Linux)
-  USEDLIBS += lldbPluginProcessLinux.a
+  USEDLIBS += lldbPluginProcessLinux.a \
+              lldbPluginDynamicLoaderLinux.a
 endif
 
 include $(LEVEL)/Makefile.common

Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp Sun Jan 16 13:45:39 2011
@@ -0,0 +1,191 @@
+//===-- AuxVector.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 <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+
+#include "AuxVector.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static bool
+GetMaxU64(DataExtractor &data,
+          uint32_t *offset, uint64_t *value, unsigned int byte_size)
+{
+    uint32_t saved_offset = *offset;
+    *value = data.GetMaxU64(offset, byte_size);
+    return *offset != saved_offset;
+}
+
+static bool
+ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, 
+               uint32_t *offset, unsigned int byte_size)
+{
+    if (!GetMaxU64(data, offset, &entry.type, byte_size))
+        return false;
+
+    if (!GetMaxU64(data, offset, &entry.value, byte_size))
+        return false;
+
+    return true;
+}
+
+DataBufferSP
+AuxVector::GetAuxvData()
+{
+    static const size_t path_size = 128;
+    static char path[path_size];
+    DataBufferSP buf_sp;
+    int fd;
+
+    // Ideally, we would simply create a FileSpec and call ReadFileContents.
+    // However, files in procfs have zero size (since they are, in general,
+    // dynamically generated by the kernel) which is incompatible with the
+    // current ReadFileContents implementation.  Therefore we simply stream the
+    // data into a DataBuffer ourselves.
+    if (snprintf(path, path_size, "/proc/%d/auxv", m_process->GetID()) < 0)
+        return buf_sp;
+
+    if ((fd = open(path, O_RDONLY, 0)) < 0)
+        return buf_sp;
+
+    size_t bytes_read = 0;
+    std::auto_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
+    for (;;) 
+    {
+        size_t avail = buf_ap->GetByteSize() - bytes_read;
+        ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail);
+
+        if (status < 0) 
+            break;
+
+        bytes_read += status;
+
+        if (status == 0) 
+        {
+            buf_ap->SetByteSize(bytes_read);
+            buf_sp.reset(buf_ap.release());
+            break;
+        }
+
+        if (avail - status == 0)
+            buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
+    }
+
+    return buf_sp;
+}
+
+void
+AuxVector::ParseAuxv(DataExtractor &data)
+{
+    const unsigned int byte_size  = m_process->GetAddressByteSize();
+    uint32_t offset = 0;
+
+    for (;;) 
+    {
+        Entry entry;
+
+        if (!ParseAuxvEntry(data, entry, &offset, byte_size))
+            break;
+
+        if (entry.type == AT_NULL)
+            break;
+
+        if (entry.type == AT_IGNORE)
+            continue;
+
+        m_auxv.push_back(entry);
+    }
+}
+
+AuxVector::AuxVector(Process *process)
+    : m_process(process)
+{
+    DataExtractor data;
+    LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
+    data.SetData(GetAuxvData());
+    data.SetByteOrder(m_process->GetByteOrder());
+    data.SetAddressByteSize(m_process->GetAddressByteSize());
+    
+    ParseAuxv(data);
+
+    if (log)
+        DumpToLog(log);
+}
+
+AuxVector::iterator 
+AuxVector::FindEntry(EntryType type) const
+{
+    for (iterator I = begin(); I != end(); ++I)
+    {
+        if (I->type == static_cast<uint64_t>(type))
+            return I;
+    }
+
+    return end();
+}
+
+void
+AuxVector::DumpToLog(LogSP log) const
+{
+    if (!log)
+        return;
+
+    log->PutCString("AuxVector: ");
+    for (iterator I = begin(); I != end(); ++I)
+    {
+        log->Printf("   %s [%d]: %lx", GetEntryName(*I), I->type, I->value);
+    }
+}
+
+const char *
+AuxVector::GetEntryName(EntryType type)
+{
+    const char *name;
+
+#define ENTRY_NAME(_type) _type: name = #_type
+    switch (type) 
+    {
+    default:
+        name = "unkown";
+        break;
+
+    case ENTRY_NAME(AT_NULL);   break;
+    case ENTRY_NAME(AT_IGNORE); break;
+    case ENTRY_NAME(AT_EXECFD); break;
+    case ENTRY_NAME(AT_PHDR);   break;
+    case ENTRY_NAME(AT_PHENT);  break;
+    case ENTRY_NAME(AT_PHNUM);  break;
+    case ENTRY_NAME(AT_PAGESZ); break;
+    case ENTRY_NAME(AT_BASE);   break;
+    case ENTRY_NAME(AT_FLAGS);  break;
+    case ENTRY_NAME(AT_ENTRY);  break;
+    case ENTRY_NAME(AT_NOTELF); break;
+    case ENTRY_NAME(AT_UID);    break;
+    case ENTRY_NAME(AT_EUID);   break;
+    case ENTRY_NAME(AT_GID);    break;
+    case ENTRY_NAME(AT_EGID);   break;
+    case ENTRY_NAME(AT_CLKTCK); break;
+    }
+#undef ENTRY_NAME
+
+    return name;
+}
+

Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h Sun Jan 16 13:45:39 2011
@@ -0,0 +1,97 @@
+//===-- AuxVector.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_AuxVector_H_
+#define liblldb_AuxVector_H_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+#include "lldb/lldb-forward-rtti.h"
+
+namespace lldb_private {
+class DataExtractor;
+} 
+
+/// @class AuxVector
+/// @brief Represents a processes auxiliary vector.
+///
+/// When a process is loaded on Linux a vector of values is placed onto the
+/// stack communicating operating system specific information.  On construction
+/// this class locates and parses this information and provides a simple
+/// read-only interface to the entries found.
+class AuxVector {
+
+public:
+    AuxVector(lldb_private::Process *process);
+
+    struct Entry {
+        uint64_t type;
+        uint64_t value;
+
+        Entry() : type(0), value(0) { }
+    };
+
+    /// Constants describing the type of entry.
+    enum EntryType {
+        AT_NULL   = 0,          ///< End of auxv.
+        AT_IGNORE = 1,          ///< Ignore entry.
+        AT_EXECFD = 2,          ///< File descriptor of program.
+        AT_PHDR   = 3,          ///< Program headers.
+        AT_PHENT  = 4,          ///< Size of program header.
+        AT_PHNUM  = 5,          ///< Number of program headers.
+        AT_PAGESZ = 6,          ///< Page size.
+        AT_BASE   = 7,          ///< Interpreter base address.
+        AT_FLAGS  = 8,          ///< Flags.
+        AT_ENTRY  = 9,          ///< Program entry point.
+        AT_NOTELF = 10,         ///< Set if program is not an ELF.
+        AT_UID    = 11,         ///< UID.
+        AT_EUID   = 12,         ///< Effective UID.
+        AT_GID    = 13,         ///< GID.
+        AT_EGID   = 14,         ///< Effective GID.
+        AT_CLKTCK = 17          ///< Clock frequency (e.g. times(2)).
+    };
+
+private:
+    typedef std::vector<Entry> EntryVector;
+
+public:
+    typedef EntryVector::const_iterator iterator;
+
+    iterator begin() const { return m_auxv.begin(); }
+    iterator end() const { return m_auxv.end(); }
+
+    iterator 
+    FindEntry(EntryType type) const;
+
+    static const char *
+    GetEntryName(const Entry &entry) { 
+        return GetEntryName(static_cast<EntryType>(entry.type)); 
+    }
+
+    static const char *
+    GetEntryName(EntryType type);
+
+    void
+    DumpToLog(lldb::LogSP log) const;
+
+private:
+    lldb_private::Process *m_process;
+    EntryVector m_auxv;
+
+    lldb::DataBufferSP
+    GetAuxvData();
+
+    void
+    ParseAuxv(lldb_private::DataExtractor &data);
+};
+
+#endif

Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp Sun Jan 16 13:45:39 2011
@@ -0,0 +1,315 @@
+//===-- DYLDRendezvous.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
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "DYLDRendezvous.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+/// Locates the address of the rendezvous structure.  Returns the address on
+/// success and LLDB_INVALID_ADDRESS on failure.
+static addr_t
+ResolveRendezvousAddress(Process *process)
+{
+    addr_t info_location;
+    addr_t info_addr;
+    Error error;
+    size_t size;
+
+    info_location = process->GetImageInfoAddress();
+
+    if (info_location == LLDB_INVALID_ADDRESS)
+        return LLDB_INVALID_ADDRESS;
+
+    info_addr = 0;
+    size = process->DoReadMemory(info_location, &info_addr,
+                                 process->GetAddressByteSize(), error);
+    if (size != process->GetAddressByteSize() || error.Fail())
+        return LLDB_INVALID_ADDRESS;
+
+    if (info_addr == 0)
+        return LLDB_INVALID_ADDRESS;
+
+    return info_addr;
+}
+
+DYLDRendezvous::DYLDRendezvous(Process *process)
+    : m_process(process),
+      m_rendezvous_addr(LLDB_INVALID_ADDRESS),
+      m_current(),
+      m_previous(),
+      m_soentries(),
+      m_added_soentries(),
+      m_removed_soentries()
+{
+}
+
+bool
+DYLDRendezvous::Resolve()
+{
+    const size_t word_size = 4;
+    Rendezvous info;
+    size_t address_size;
+    size_t padding;
+    addr_t info_addr;
+    addr_t cursor;
+
+    address_size = m_process->GetAddressByteSize();
+    padding = address_size - word_size;
+
+    if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
+        cursor = info_addr = ResolveRendezvousAddress(m_process);
+    else
+        cursor = info_addr = m_rendezvous_addr;
+    
+    if (cursor == LLDB_INVALID_ADDRESS)
+        return false;
+
+    if (!(cursor = ReadMemory(cursor, &info.version, word_size)))
+        return false;
+
+    if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size)))
+        return false;
+
+    if (!(cursor = ReadMemory(cursor, &info.brk, address_size)))
+        return false;
+
+    if (!(cursor = ReadMemory(cursor, &info.state, word_size)))
+        return false;
+
+    if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size)))
+        return false;
+
+    // The rendezvous was successfully read.  Update our internal state.
+    m_rendezvous_addr = info_addr;
+    m_previous = m_current;
+    m_current = info;
+
+    return UpdateSOEntries();
+}
+
+bool
+DYLDRendezvous::IsValid()
+{
+    return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntries()
+{
+    SOEntry entry;
+
+    if (m_current.map_addr == 0)
+        return false;
+
+    // If we are about to add or remove a shared object clear out the current
+    // state and take a snapshot of the currently loaded images.
+    if (m_current.state == eAdd || m_current.state == eDelete)
+    {
+        assert(m_previous.state == eConsistent);
+        m_soentries.clear();
+        m_added_soentries.clear();
+        m_removed_soentries.clear();
+        return TakeSnapshot(m_soentries);
+    }
+
+    // Otherwise check the previous state to determine what to expect and update
+    // accordingly.
+    if (m_previous.state == eAdd)
+        return UpdateSOEntriesForAddition();
+    else if (m_previous.state == eDelete)
+        return UpdateSOEntriesForDeletion();
+
+    return false;
+}
+ 
+bool
+DYLDRendezvous::UpdateSOEntriesForAddition()
+{
+    SOEntry entry;
+    iterator pos;
+
+    assert(m_previous.state == eAdd);
+
+    if (m_current.map_addr == 0)
+        return false;
+
+    for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
+    {
+        if (!ReadSOEntryFromMemory(cursor, entry))
+            return false;
+
+        if (entry.path.empty())
+            continue;
+
+        pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
+        if (pos == m_soentries.end())
+        {
+            m_soentries.push_back(entry);
+            m_added_soentries.push_back(entry);
+        }
+    }
+
+    return true;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntriesForDeletion()
+{
+    SOEntryList entry_list;
+    iterator pos;
+
+    assert(m_previous.state == eDelete);
+
+    if (!TakeSnapshot(entry_list))
+        return false;
+
+    for (iterator I = begin(); I != end(); ++I)
+    {
+        pos = std::find(entry_list.begin(), entry_list.end(), *I);
+        if (pos == entry_list.end())
+            m_removed_soentries.push_back(*I);
+    }
+
+    m_soentries = entry_list;
+    return true;
+}
+
+bool
+DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
+{
+    SOEntry entry;
+
+    if (m_current.map_addr == 0)
+        return false;
+
+    for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
+    {
+        if (!ReadSOEntryFromMemory(cursor, entry))
+            return false;
+
+        if (entry.path.empty())
+            continue;
+
+        entry_list.push_back(entry);
+    }
+
+    return true;
+}
+
+addr_t
+DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size)
+{
+    size_t bytes_read;
+    Error error;
+
+    bytes_read = m_process->DoReadMemory(addr, dst, size, error);
+    if (bytes_read != size || error.Fail())
+        return 0;
+
+    return addr + bytes_read;
+}
+
+std::string
+DYLDRendezvous::ReadStringFromMemory(addr_t addr)
+{
+    std::string str;
+    Error error;
+    size_t size;
+    char c;
+
+    if (addr == LLDB_INVALID_ADDRESS)
+        return std::string();
+
+    for (;;) {
+        size = m_process->DoReadMemory(addr, &c, 1, error);
+        if (size != 1 || error.Fail())
+            return std::string();
+        if (c == 0)
+            break;
+        else {
+            str.push_back(c);
+            addr++;
+        }
+    }
+
+    return str;
+}
+
+bool
+DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
+{
+    size_t address_size = m_process->GetAddressByteSize();
+
+    entry.clear();
+    
+    if (!(addr = ReadMemory(addr, &entry.base_addr, address_size)))
+        return false;
+    
+    if (!(addr = ReadMemory(addr, &entry.path_addr, address_size)))
+        return false;
+    
+    if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size)))
+        return false;
+    
+    if (!(addr = ReadMemory(addr, &entry.next, address_size)))
+        return false;
+    
+    if (!(addr = ReadMemory(addr, &entry.prev, address_size)))
+        return false;
+    
+    entry.path = ReadStringFromMemory(entry.path_addr);
+    
+    return true;
+}
+
+void
+DYLDRendezvous::DumpToLog(LogSP log) const
+{
+    int state = GetState();
+
+    if (!log)
+        return;
+
+    log->PutCString("DYLDRendezvous:");
+    log->Printf("   Address: %lx", GetRendezvousAddress());
+    log->Printf("   Version: %d",  GetVersion());
+    log->Printf("   Link   : %lx", GetLinkMapAddress());
+    log->Printf("   Break  : %lx", GetBreakAddress());
+    log->Printf("   LDBase : %lx", GetLDBase());
+    log->Printf("   State  : %s", 
+                (state == eConsistent) ? "consistent" :
+                (state == eAdd)        ? "add"        :
+                (state == eDelete)     ? "delete"     : "unknown");
+    
+    iterator I = begin();
+    iterator E = end();
+
+    if (I != E) 
+        log->PutCString("DYLDRendezvous SOEntries:");
+    
+    for (int i = 1; I != E; ++I, ++i) 
+    {
+        log->Printf("\n   SOEntry [%d] %s", i, I->path.c_str());
+        log->Printf("      Base : %lx", I->base_addr);
+        log->Printf("      Path : %lx", I->path_addr);
+        log->Printf("      Dyn  : %lx", I->dyn_addr);
+        log->Printf("      Next : %lx", I->next);
+        log->Printf("      Prev : %lx", I->prev);
+    }
+}

Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h Sun Jan 16 13:45:39 2011
@@ -0,0 +1,227 @@
+//===-- DYLDRendezvous.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_Rendezvous_H_
+#define liblldb_Rendezvous_H_
+
+// C Includes
+// C++ Includes
+#include <list>
+#include <string>
+
+// Other libraries and framework includes
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private {
+class Process;
+}
+
+/// @class DYLDRendezvous
+/// @brief Interface to the runtime linker.
+///
+/// A structure is present in a processes memory space which is updated by the
+/// runtime liker each time a module is loaded or unloaded.  This class provides
+/// an interface to this structure and maintains a consistent snapshot of the
+/// currently loaded modules.
+class DYLDRendezvous {
+
+    // This structure is used to hold the contents of the debug rendezvous
+    // information (struct r_debug) as found in the inferiors memory.  Note that
+    // the layout of this struct is not binary compatible, it is simply large
+    // enough to hold the information on both 32 and 64 bit platforms.
+    struct Rendezvous {
+        uint64_t     version;
+        lldb::addr_t map_addr;
+        lldb::addr_t brk;
+        uint64_t     state;
+        lldb::addr_t ldbase;
+
+        Rendezvous()
+            : version(0), map_addr(0), brk(0), state(0), ldbase(0) { }
+    };
+
+public:
+    DYLDRendezvous(lldb_private::Process *process);
+
+    /// Update the internal snapshot of runtime linker rendezvous and recompute
+    /// the currently loaded modules.
+    ///
+    /// This method should be called once one start up, then once each time the
+    /// runtime linker enters the function given by GetBreakAddress().
+    ///
+    /// @returns true on success and false on failure.
+    ///
+    /// @see GetBreakAddress().
+    bool 
+    Resolve();
+
+    /// @returns true if this rendezvous has been located in the inferiors
+    /// address space and false otherwise.
+    bool 
+    IsValid();
+
+    /// @returns the address of the rendezvous structure in the inferiors
+    /// address space.
+    lldb::addr_t
+    GetRendezvousAddress() const { return m_rendezvous_addr; }
+
+    /// @returns the version of the rendezvous protocol being used.
+    int
+    GetVersion() const { return m_current.version; }
+
+    /// @returns address in the inferiors address space containing the linked
+    /// list of shared object descriptors.
+    lldb::addr_t 
+    GetLinkMapAddress() const { return m_current.map_addr; }
+
+    /// A breakpoint should be set at this address and Resolve called on each
+    /// hit.
+    ///
+    /// @returns the address of a function called by the runtime linker each
+    /// time a module is loaded/unloaded, or about to be loaded/unloaded.
+    ///
+    /// @see Resolve()
+    lldb::addr_t
+    GetBreakAddress() const { return m_current.brk; }
+
+    /// Returns the current state of the rendezvous structure.
+    int
+    GetState() const { return m_current.state; }
+
+    /// @returns the base address of the runtime linker in the inferiors address
+    /// space.
+    lldb::addr_t
+    GetLDBase() const { return m_current.ldbase; }
+
+    /// @returns true if modules have been loaded into the inferior since the
+    /// last call to Resolve().
+    bool
+    ModulesDidLoad() const { return !m_added_soentries.empty(); }
+
+    /// @returns true if modules have been unloaded from the inferior since the
+    /// last call to Resolve().
+    bool
+    ModulesDidUnload() const { return !m_removed_soentries.empty(); }
+
+    void
+    DumpToLog(lldb::LogSP log) const;
+
+    /// @brief Constants describing the state of the rendezvous.
+    ///
+    /// @see GetState().
+    enum RendezvousState {
+        eConsistent,
+        eAdd,
+        eDelete
+    };
+
+    /// @brief Structure representing the shared objects currently loaded into
+    /// the inferior process.
+    ///
+    /// This object is a rough analogue to the struct link_map object which
+    /// actually lives in the inferiors memory.
+    struct SOEntry {
+        lldb::addr_t base_addr; ///< Base address of the loaded object.
+        lldb::addr_t path_addr; ///< String naming the shared object.
+        lldb::addr_t dyn_addr;  ///< Dynamic section of shared object.
+        lldb::addr_t next;      ///< Address of next so_entry.
+        lldb::addr_t prev;      ///< Address of previous so_entry.
+        std::string  path;      ///< File name of shared object.
+
+        SOEntry() { clear(); }
+
+        bool operator ==(const SOEntry &entry) {
+            return this->path == entry.path;
+        }
+
+        void clear() {
+            base_addr = 0;
+            path_addr = 0;
+            dyn_addr  = 0;
+            next = 0;
+            prev = 0;
+            path.clear();
+        }
+    };
+
+protected:
+    typedef std::list<SOEntry> SOEntryList;
+
+public:
+    typedef SOEntryList::const_iterator iterator;
+
+    /// Iterators over all currently loaded modules.
+    iterator begin() const { return m_soentries.begin(); }
+    iterator end() const { return m_soentries.end(); }
+
+    /// Iterators over all modules loaded into the inferior since the last call
+    /// to Resolve().
+    iterator loaded_begin() const { return m_added_soentries.begin(); }
+    iterator loaded_end() const { return m_added_soentries.end(); }
+
+    /// Iterators over all modules unloaded from the inferior since the last
+    /// call to Resolve().
+    iterator unloaded_begin() const { return m_removed_soentries.begin(); }
+    iterator unloaded_end() const { return m_removed_soentries.end(); }
+    
+protected:
+    lldb_private::Process *m_process;
+
+    /// Location of the r_debug structure in the inferiors address space.
+    lldb::addr_t m_rendezvous_addr;
+
+    /// Current and previous snapshots of the rendezvous structure.
+    Rendezvous m_current;
+    Rendezvous m_previous;
+
+    /// List of SOEntry objects corresponding to the current link map state.
+    SOEntryList m_soentries;
+
+    /// List of SOEntry's added to the link map since the last call to Resolve().
+    SOEntryList m_added_soentries;
+
+    /// List of SOEntry's removed from the link map since the last call to
+    /// Resolve().
+    SOEntryList m_removed_soentries;
+
+    /// Reads @p size bytes from the inferiors address space starting at @p
+    /// addr.
+    ///
+    /// @returns addr + size if the read was successful and false otherwise.
+    lldb::addr_t
+    ReadMemory(lldb::addr_t addr, void *dst, size_t size);
+
+    /// Reads a null-terminated C string from the memory location starting at @p
+    /// addr.
+    std::string
+    ReadStringFromMemory(lldb::addr_t addr);
+
+    /// Reads an SOEntry starting at @p addr.
+    bool
+    ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
+
+    /// Updates the current set of SOEntries, the set of added entries, and the
+    /// set of removed entries.
+    bool
+    UpdateSOEntries();
+
+    bool
+    UpdateSOEntriesForAddition();
+
+    bool
+    UpdateSOEntriesForDeletion();
+
+    /// Reads the current list of shared objects according to the link map
+    /// supplied by the runtime linker.
+    bool
+    TakeSnapshot(SOEntryList &entry_list);
+};
+
+#endif

Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp Sun Jan 16 13:45:39 2011
@@ -0,0 +1,371 @@
+//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include <iostream>
+
+// Other libraries and framework includes
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "AuxVector.h"
+#include "DynamicLoaderLinuxDYLD.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+DynamicLoaderLinuxDYLD::Initialize()
+{
+    PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                  GetPluginDescriptionStatic(),
+                                  CreateInstance);
+}
+
+void
+DynamicLoaderLinuxDYLD::Terminate()
+{
+}
+
+const char *
+DynamicLoaderLinuxDYLD::GetPluginName()
+{
+    return "DynamicLoaderLinuxDYLD";
+}
+
+const char *
+DynamicLoaderLinuxDYLD::GetShortPluginName()
+{
+    return "linux-dyld";
+}
+
+const char *
+DynamicLoaderLinuxDYLD::GetPluginNameStatic()
+{
+    return "dynamic-loader.linux-dyld";
+}
+
+const char *
+DynamicLoaderLinuxDYLD::GetPluginDescriptionStatic()
+{
+    return "Dynamic loader plug-in that watches for shared library "
+           "loads/unloads in Linux processes.";
+}
+
+void
+DynamicLoaderLinuxDYLD::GetPluginCommandHelp(const char *command, Stream *strm)
+{
+}
+
+uint32_t
+DynamicLoaderLinuxDYLD::GetPluginVersion()
+{
+    return 1;
+}
+
+DynamicLoader *
+DynamicLoaderLinuxDYLD::CreateInstance(Process *process)
+{
+    return new DynamicLoaderLinuxDYLD(process);
+}
+
+DynamicLoaderLinuxDYLD::DynamicLoaderLinuxDYLD(Process *process)
+    : DynamicLoader(process),
+      m_rendezvous(process),
+      m_load_offset(LLDB_INVALID_ADDRESS),
+      m_entry_point(LLDB_INVALID_ADDRESS),
+      m_auxv(NULL)
+{
+}
+
+DynamicLoaderLinuxDYLD::~DynamicLoaderLinuxDYLD()
+{
+}
+
+void
+DynamicLoaderLinuxDYLD::DidAttach()
+{
+    ModuleSP executable;
+    addr_t load_offset;
+
+    m_auxv.reset(new AuxVector(m_process));
+
+    executable = m_process->GetTarget().GetExecutableModule();
+    load_offset = ComputeLoadOffset();
+
+    if (!executable.empty() && load_offset != LLDB_INVALID_ADDRESS)
+    {
+        ModuleList module_list;
+        module_list.Append(executable);
+        UpdateLoadedSections(executable, load_offset);
+        m_process->GetTarget().ModulesDidLoad(module_list);
+    }
+}
+
+void
+DynamicLoaderLinuxDYLD::DidLaunch()
+{
+    ModuleSP executable;
+    addr_t load_offset;
+
+    m_auxv.reset(new AuxVector(m_process));
+
+    executable = m_process->GetTarget().GetExecutableModule();
+    load_offset = ComputeLoadOffset();
+
+    if (!executable.empty() && load_offset != LLDB_INVALID_ADDRESS)
+    {
+        ModuleList module_list;
+        module_list.Append(executable);
+        UpdateLoadedSections(executable, load_offset);
+        ProbeEntry();
+        m_process->GetTarget().ModulesDidLoad(module_list);
+    }
+}
+
+Error
+DynamicLoaderLinuxDYLD::ExecutePluginCommand(Args &command, Stream *strm)
+{
+    return Error();
+}
+
+Log *
+DynamicLoaderLinuxDYLD::EnablePluginLogging(Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+Error
+DynamicLoaderLinuxDYLD::CanLoadImage()
+{
+    return Error();
+}
+
+void
+DynamicLoaderLinuxDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
+{
+    ObjectFile *obj_file = module->GetObjectFile();
+    SectionList *sections = obj_file->GetSectionList();
+    SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
+    const size_t num_sections = sections->GetSize();
+
+    for (unsigned i = 0; i < num_sections; ++i)
+    {
+        Section *section = sections->GetSectionAtIndex(i).get();
+        lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr;
+        lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section);
+
+        // If the file address of the section is zero then this is not an
+        // allocatable/loadable section (property of ELF sh_addr).  Skip it.
+        if (new_load_addr == base_addr)
+            continue;
+
+        if (old_load_addr == LLDB_INVALID_ADDRESS ||
+            old_load_addr != new_load_addr)
+            load_list.SetSectionLoadAddress(section, new_load_addr);
+    }
+}
+
+void
+DynamicLoaderLinuxDYLD::ProbeEntry()
+{
+    Breakpoint *entry_break;
+    addr_t entry;
+
+    if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
+        return;
+    
+    entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get();
+    entry_break->SetCallback(EntryBreakpointHit, this, true);
+}
+
+// The runtime linker has run and initialized the rendezvous structure once the
+// process has hit its entry point.  When we hit the corresponding breakpoint we
+// interrogate the rendezvous structure to get the load addresses of all
+// dependent modules for the process.  Similarly, we can discover the runtime
+// linker function and setup a breakpoint to notify us of any dynamically loaded
+// modules (via dlopen).
+bool
+DynamicLoaderLinuxDYLD::EntryBreakpointHit(void *baton, 
+                                           StoppointCallbackContext *context, 
+                                           user_id_t break_id, 
+                                           user_id_t break_loc_id)
+{
+    DynamicLoaderLinuxDYLD* dyld_instance;
+
+    dyld_instance = static_cast<DynamicLoaderLinuxDYLD*>(baton);
+    dyld_instance->LoadAllCurrentModules();
+    dyld_instance->SetRendezvousBreakpoint();
+    return false; // Continue running.
+}
+
+void
+DynamicLoaderLinuxDYLD::SetRendezvousBreakpoint()
+{
+    Breakpoint *dyld_break;
+    addr_t break_addr;
+
+    break_addr = m_rendezvous.GetBreakAddress();
+    dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get();
+    dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
+}
+
+bool
+DynamicLoaderLinuxDYLD::RendezvousBreakpointHit(void *baton, 
+                                                StoppointCallbackContext *context, 
+                                                user_id_t break_id, 
+                                                user_id_t break_loc_id)
+{
+    DynamicLoaderLinuxDYLD* dyld_instance;
+
+    dyld_instance = static_cast<DynamicLoaderLinuxDYLD*>(baton);
+    dyld_instance->RefreshModules();
+
+    // Return true to stop the target, false to just let the target run.
+    return dyld_instance->GetStopWhenImagesChange();
+}
+
+void
+DynamicLoaderLinuxDYLD::RefreshModules()
+{
+    if (!m_rendezvous.Resolve())
+        return;
+
+    DYLDRendezvous::iterator I;
+    DYLDRendezvous::iterator E;
+
+    ModuleList &loaded_modules = m_process->GetTarget().GetImages();
+
+    if (m_rendezvous.ModulesDidLoad()) 
+    {
+        ModuleList new_modules;
+
+        E = m_rendezvous.loaded_end();
+        for (I = m_rendezvous.loaded_begin(); I != E; ++I)
+        {
+            FileSpec file(I->path.c_str(), true);
+            ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+            if (!module_sp.empty())
+                new_modules.Append(module_sp);
+        }
+        m_process->GetTarget().ModulesDidLoad(new_modules);
+    }
+    
+    if (m_rendezvous.ModulesDidUnload())
+    {
+        ModuleList old_modules;
+
+        E = m_rendezvous.unloaded_end();
+        for (I = m_rendezvous.unloaded_begin(); I != E; ++I)
+        {
+            FileSpec file(I->path.c_str(), true);
+            ModuleSP module_sp = loaded_modules.FindFirstModuleForFileSpec(file);
+            if (!module_sp.empty())
+                old_modules.Append(module_sp);
+        }
+        m_process->GetTarget().ModulesDidUnload(old_modules);
+    }
+}
+
+ThreadPlanSP
+DynamicLoaderLinuxDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop_others)
+{
+    LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+    ThreadPlanSP thread_plan_sp;
+
+    if (log)
+        log->PutCString("DynamicLoaderLinuxDYLD: "
+                        "GetStepThroughTrampolinePlan not implemented\n");
+
+    return thread_plan_sp;
+}
+
+void
+DynamicLoaderLinuxDYLD::LoadAllCurrentModules()
+{
+    DYLDRendezvous::iterator I;
+    DYLDRendezvous::iterator E;
+    ModuleList module_list;
+    
+    if (!m_rendezvous.Resolve())
+        return;
+
+    for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
+    {
+        FileSpec file(I->path.c_str(), false);
+        ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+        if (!module_sp.empty())
+            module_list.Append(module_sp);
+    }
+
+    m_process->GetTarget().ModulesDidLoad(module_list);
+}
+
+ModuleSP
+DynamicLoaderLinuxDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr)
+{
+    Target &target = m_process->GetTarget();
+    ModuleList &modules = target.GetImages();
+    ModuleSP module_sp;
+
+    if ((module_sp = modules.FindFirstModuleForFileSpec(file))) 
+    {
+        UpdateLoadedSections(module_sp, base_addr);
+    }
+    else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture()))) 
+    {
+        UpdateLoadedSections(module_sp, base_addr);
+        modules.Append(module_sp);
+    }
+
+    return module_sp;
+}
+
+addr_t
+DynamicLoaderLinuxDYLD::ComputeLoadOffset()
+{
+    addr_t virt_entry;
+
+    if (m_load_offset != LLDB_INVALID_ADDRESS)
+        return m_load_offset;
+
+    if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
+        return LLDB_INVALID_ADDRESS;
+
+    ModuleSP module = m_process->GetTarget().GetExecutableModule();
+    ObjectFile *exe = module->GetObjectFile();
+    Address file_entry = exe->GetEntryPoint();
+
+    if (!file_entry.IsValid())
+        return LLDB_INVALID_ADDRESS;
+            
+    m_load_offset = virt_entry - file_entry.GetFileAddress();
+    return m_load_offset;
+}
+
+addr_t
+DynamicLoaderLinuxDYLD::GetEntryPoint()
+{
+    if (m_entry_point != LLDB_INVALID_ADDRESS)
+        return m_entry_point;
+
+    if (m_auxv.get() == NULL)
+        return LLDB_INVALID_ADDRESS;
+
+    AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY);
+
+    if (I == m_auxv->end())
+        return LLDB_INVALID_ADDRESS;
+
+    m_entry_point = static_cast<addr_t>(I->value);
+    return m_entry_point;
+}

Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h Sun Jan 16 13:45:39 2011
@@ -0,0 +1,165 @@
+//===-- DynamicLoaderLinux.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_DynamicLoaderLinux_H_
+#define liblldb_DynamicLoaderLinux_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Target/DynamicLoader.h"
+
+#include "DYLDRendezvous.h"
+
+class AuxVector;
+
+class DynamicLoaderLinuxDYLD : public lldb_private::DynamicLoader
+{
+public:
+
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::DynamicLoader *
+    CreateInstance(lldb_private::Process *process);
+
+    DynamicLoaderLinuxDYLD(lldb_private::Process *process);
+
+    virtual
+    ~DynamicLoaderLinuxDYLD();
+
+    //------------------------------------------------------------------
+    // DynamicLoader protocol
+    //------------------------------------------------------------------
+
+    virtual void
+    DidAttach();
+
+    virtual void
+    DidLaunch();
+
+    virtual lldb::ThreadPlanSP
+    GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
+                                 bool stop_others);
+
+    virtual lldb_private::Error
+    CanLoadImage();
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);
+
+protected:
+    /// Runtime linker rendezvous structure.
+    DYLDRendezvous m_rendezvous;
+
+    /// Virtual load address of the inferior process.
+    lldb::addr_t m_load_offset;
+
+    /// Virtual entry address of the inferior process.
+    lldb::addr_t m_entry_point;
+
+    /// Auxiliary vector of the inferior process.
+    std::auto_ptr<AuxVector> m_auxv;
+
+    /// Enables a breakpoint on a function called by the runtime
+    /// linker each time a module is loaded or unloaded.
+    void
+    SetRendezvousBreakpoint();
+
+    /// Callback routine which updates the current list of loaded modules based
+    /// on the information supplied by the runtime linker.
+    static bool
+    RendezvousBreakpointHit(void *baton, 
+                            lldb_private::StoppointCallbackContext *context, 
+                            lldb::user_id_t break_id, 
+                            lldb::user_id_t break_loc_id);
+    
+    /// Helper method for RendezvousBreakpointHit.  Updates LLDB's current set
+    /// of loaded modules.
+    void
+    RefreshModules();
+
+    /// Updates the load address of every allocatable section in @p module.
+    ///
+    /// @param module The module to traverse.
+    ///
+    /// @param base_addr The virtual base address @p module is loaded at.
+    void
+    UpdateLoadedSections(lldb::ModuleSP module, 
+                         lldb::addr_t base_addr = 0);
+
+    /// Locates or creates a module given by @p file and updates/loads the
+    /// resulting module at the virtual base address @p base_addr.
+    lldb::ModuleSP
+    LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr);
+
+    /// Resolves the entry point for the current inferior process and sets a
+    /// breakpoint at that address.
+    void
+    ProbeEntry();
+
+    /// Callback routine invoked when we hit the breakpoint on process entry.
+    ///
+    /// This routine is responsible for resolving the load addresses of all
+    /// dependent modules required by the inferior and setting up the rendezvous
+    /// breakpoint.
+    static bool
+    EntryBreakpointHit(void *baton, 
+                       lldb_private::StoppointCallbackContext *context, 
+                       lldb::user_id_t break_id, 
+                       lldb::user_id_t break_loc_id);
+
+    /// Helper for the entry breakpoint callback.  Resolves the load addresses
+    /// of all dependent modules.
+    void
+    LoadAllCurrentModules();
+
+    /// Computes a value for m_load_offset returning the computed address on
+    /// success and LLDB_INVALID_ADDRESS on failure.
+    lldb::addr_t
+    ComputeLoadOffset();
+
+    /// Computes a value for m_entry_point returning the computed address on
+    /// success and LLDB_INVALID_ADDRESS on failure.
+    lldb::addr_t
+    GetEntryPoint();
+
+private:
+    DISALLOW_COPY_AND_ASSIGN(DynamicLoaderLinuxDYLD);
+};
+
+#endif  // liblldb_DynamicLoaderLinuxDYLD_H_

Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile Sun Jan 16 13:45:39 2011
@@ -0,0 +1,14 @@
+##===- source/Plugins/DynamicLoader/Linux-DYLD/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 := lldbPluginDynamicLoaderLinux
+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=123592&r1=123591&r2=123592&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Makefile (original)
+++ lldb/trunk/source/Plugins/Makefile Sun Jan 16 13:45:39 2011
@@ -23,7 +23,7 @@
 endif
 
 ifeq ($(HOST_OS),Linux)
-DIRS += Process/Linux
+DIRS += Process/Linux DynamicLoader/Linux-DYLD
 endif
 
 include $(LLDB_LEVEL)/Makefile

Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp?rev=123592&r1=123591&r2=123592&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp Sun Jan 16 13:45:39 2011
@@ -13,6 +13,7 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/DynamicLoader.h"
 #include "lldb/Target/Target.h"
 
 #include "ProcessLinux.h"
@@ -102,6 +103,19 @@
 }
 
 Error
+ProcessLinux::WillLaunch(Module* module)
+{
+    Error error;
+
+    m_dyld_ap.reset(DynamicLoader::FindPlugin(this, "dynamic-loader.linux-dyld"));
+    if (m_dyld_ap.get() == NULL)
+        error.SetErrorString("unable to find the dynamic loader named "
+                             "'dynamic-loader.linux-dyld'");
+
+    return error;
+}
+
+Error
 ProcessLinux::DoLaunch(Module *module,
                        char const *argv[],
                        char const *envp[],
@@ -128,6 +142,13 @@
     return error;
 }
 
+void
+ProcessLinux::DidLaunch()
+{
+    if (m_dyld_ap.get() != NULL)
+        m_dyld_ap->DidLaunch();
+}
+
 Error
 ProcessLinux::DoResume()
 {
@@ -371,6 +392,12 @@
     return m_byte_order;
 }
 
+DynamicLoader *
+ProcessLinux::GetDynamicLoader()
+{
+    return m_dyld_ap.get();
+}
+
 //------------------------------------------------------------------------------
 // ProcessInterface protocol.
 

Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h?rev=123592&r1=123591&r2=123592&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h Sun Jan 16 13:45:39 2011
@@ -60,6 +60,9 @@
     CanDebug(lldb_private::Target &target);
 
     virtual lldb_private::Error
+    WillLaunch(lldb_private::Module *module);
+
+    virtual lldb_private::Error
     DoAttachToProcessWithID(lldb::pid_t pid);
 
     virtual lldb_private::Error
@@ -71,6 +74,9 @@
              const char *stdout_path,
              const char *stderr_path);
 
+    virtual void
+    DidLaunch();
+
     virtual lldb_private::Error
     DoResume();
 
@@ -131,6 +137,9 @@
     virtual lldb::addr_t
     GetImageInfoAddress();
 
+    virtual lldb_private::DynamicLoader *
+    GetDynamicLoader();
+
     //------------------------------------------------------------------
     // PluginInterface protocol
     //------------------------------------------------------------------
@@ -176,6 +185,9 @@
     lldb_private::Mutex m_message_mutex;
     std::queue<ProcessMessage> m_message_queue;
 
+    /// Dynamic loader plugin associated with this process.
+    std::auto_ptr<lldb_private::DynamicLoader> m_dyld_ap;
+
     /// Updates the loaded sections provided by the executable.
     ///
     /// FIXME:  It would probably be better to delegate this task to the

Modified: lldb/trunk/source/lldb.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb.cpp?rev=123592&r1=123591&r2=123592&view=diff
==============================================================================
--- lldb/trunk/source/lldb.cpp (original)
+++ lldb/trunk/source/lldb.cpp Sun Jan 16 13:45:39 2011
@@ -44,6 +44,7 @@
 
 #ifdef __linux__
 #include "Plugins/Process/Linux/ProcessLinux.h"
+#include "Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h"
 #endif
 
 using namespace lldb;
@@ -94,6 +95,7 @@
 #endif
 #ifdef __linux__
         ProcessLinux::Initialize();
+        DynamicLoaderLinuxDYLD::Initialize();
 #endif
     }
 }
@@ -137,6 +139,7 @@
 
 #ifdef __linux__
     ProcessLinux::Terminate();
+    DynamicLoaderLinuxDYLD::Terminate();
 #endif
 
     Log::Terminate();





More information about the lldb-commits mailing list