<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Hi Mark and Charles,<div><br></div><div>Let me know if there are still issues left.</div><div>Thanks.<br><div><br><div>Begin forwarded message:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px;"><span style="font-family:'Helvetica'; font-size:medium; color:rgba(0, 0, 0, 1.0);"><b>From: </b></span><span style="font-family:'Helvetica'; font-size:medium;">Johnny Chen <<a href="mailto:johnny.chen@apple.com">johnny.chen@apple.com</a>><br></span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px;"><span style="font-family:'Helvetica'; font-size:medium; color:rgba(0, 0, 0, 1.0);"><b>Subject: </b></span><span style="font-family:'Helvetica'; font-size:medium;"><b>[Lldb-commits] [lldb] r147613 - in /lldb/trunk/source/Plugins: DynamicLoader/Linux-DYLD/ DynamicLoader/POSIX-DYLD/ Process/FreeBSD/ Process/Linux/ Process/POSIX/</b><br></span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px;"><span style="font-family:'Helvetica'; font-size:medium; color:rgba(0, 0, 0, 1.0);"><b>Date: </b></span><span style="font-family:'Helvetica'; font-size:medium;">January 5, 2012 1:48:16 PM PST<br></span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px;"><span style="font-family:'Helvetica'; font-size:medium; color:rgba(0, 0, 0, 1.0);"><b>To: </b></span><span style="font-family:'Helvetica'; font-size:medium;"><a href="mailto:lldb-commits@cs.uiuc.edu">lldb-commits@cs.uiuc.edu</a><br></span></div><br><div>Author: johnny<br>Date: Thu Jan  5 15:48:15 2012<br>New Revision: 147613<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=147613&view=rev">http://llvm.org/viewvc/llvm-project?rev=147613&view=rev</a><br>Log:<br>Fix incomplete commit of <a href="http://llvm.org/viewvc/llvm-project?rev=147609&view=rev:">http://llvm.org/viewvc/llvm-project?rev=147609&view=rev:</a><br><br>This patch combines common code from Linux and FreeBSD into<br>a new POSIX platform.  It also contains fixes for 64bit FreeBSD.<br><br>The patch is based on changes by Mark Peek <<a href="mailto:mp@FreeBSD.org">mp@FreeBSD.org</a>> and<br>"K. Macy" <<a href="mailto:kmacy@freebsd.org">kmacy@freebsd.org</a>> in their github repo located at<br><a href="https://github.com/fbsd/lldb">https://github.com/fbsd/lldb</a>.<br><br>Added:<br>    lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/<br>    lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp<br>    lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h<br>    lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp<br>    lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h<br>    lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp<br>    lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h<br>    lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile<br>    lldb/trunk/source/Plugins/Process/FreeBSD/<br>    lldb/trunk/source/Plugins/Process/FreeBSD/Makefile<br>    lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp<br>    lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h<br>    lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp<br>    lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h<br>    lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h<br>    lldb/trunk/source/Plugins/Process/POSIX/<br>    lldb/trunk/source/Plugins/Process/POSIX/Makefile<br>    lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.cpp<br>    lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.h<br>    lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp<br>    lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h<br>    lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.cpp<br>    lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.h<br>    lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp<br>    lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h<br>    lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp<br>    lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.h<br>    lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h<br>    lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.cpp<br>    lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.h<br>    lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp<br>    lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h<br>Removed:<br>    lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/<br>    lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp<br>    lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h<br>    lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp<br>    lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h<br>    lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp<br>    lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h<br>    lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp<br>    lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h<br>    lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h<br>    lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp<br>    lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h<br>    lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp<br>    lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h<br><br>Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (added)<br>+++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,153 @@<br>+//===-- AuxVector.cpp -------------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+// C Includes<br>+#include <fcntl.h><br>+#include <sys/stat.h><br>+#include <sys/types.h><br>+<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+#include "lldb/Core/DataBufferHeap.h"<br>+#include "lldb/Core/DataExtractor.h"<br>+#include "lldb/Core/Log.h"<br>+#include "lldb/Target/Process.h"<br>+<br>+#include "AuxVector.h"<br>+<br>+using namespace lldb;<br>+using namespace lldb_private;<br>+<br>+static bool<br>+GetMaxU64(DataExtractor &data,<br>+          uint32_t *offset, uint64_t *value, unsigned int byte_size)<br>+{<br>+    uint32_t saved_offset = *offset;<br>+    *value = data.GetMaxU64(offset, byte_size);<br>+    return *offset != saved_offset;<br>+}<br>+<br>+static bool<br>+ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, <br>+               uint32_t *offset, unsigned int byte_size)<br>+{<br>+    if (!GetMaxU64(data, offset, &entry.type, byte_size))<br>+        return false;<br>+<br>+    if (!GetMaxU64(data, offset, &entry.value, byte_size))<br>+        return false;<br>+<br>+    return true;<br>+}<br>+<br>+DataBufferSP<br>+AuxVector::GetAuxvData()<br>+{<br>+<br>+    return lldb_private::Host::GetAuxvData(m_process);<br>+}<br>+<br>+void<br>+AuxVector::ParseAuxv(DataExtractor &data)<br>+{<br>+    const unsigned int byte_size  = m_process->GetAddressByteSize();<br>+    uint32_t offset = 0;<br>+<br>+    for (;;) <br>+    {<br>+        Entry entry;<br>+<br>+        if (!ParseAuxvEntry(data, entry, &offset, byte_size))<br>+            break;<br>+<br>+        if (entry.type == AT_NULL)<br>+            break;<br>+<br>+        if (entry.type == AT_IGNORE)<br>+            continue;<br>+<br>+        m_auxv.push_back(entry);<br>+    }<br>+}<br>+<br>+AuxVector::AuxVector(Process *process)<br>+    : m_process(process)<br>+{<br>+    DataExtractor data;<br>+    LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));<br>+<br>+    data.SetData(GetAuxvData());<br>+    data.SetByteOrder(m_process->GetByteOrder());<br>+    data.SetAddressByteSize(m_process->GetAddressByteSize());<br>+    <br>+    ParseAuxv(data);<br>+<br>+    if (log)<br>+        DumpToLog(log);<br>+}<br>+<br>+AuxVector::iterator <br>+AuxVector::FindEntry(EntryType type) const<br>+{<br>+    for (iterator I = begin(); I != end(); ++I)<br>+    {<br>+        if (I->type == static_cast<uint64_t>(type))<br>+            return I;<br>+    }<br>+<br>+    return end();<br>+}<br>+<br>+void<br>+AuxVector::DumpToLog(LogSP log) const<br>+{<br>+    if (!log)<br>+        return;<br>+<br>+    log->PutCString("AuxVector: ");<br>+    for (iterator I = begin(); I != end(); ++I)<br>+    {<br>+        log->Printf("   %s [%d]: %lx", GetEntryName(*I), I->type, I->value);<br>+    }<br>+}<br>+<br>+const char *<br>+AuxVector::GetEntryName(EntryType type)<br>+{<br>+    const char *name;<br>+<br>+#define ENTRY_NAME(_type) _type: name = #_type<br>+    switch (type) <br>+    {<br>+    default:<br>+        name = "unkown";<br>+        break;<br>+<br>+    case ENTRY_NAME(AT_NULL);   break;<br>+    case ENTRY_NAME(AT_IGNORE); break;<br>+    case ENTRY_NAME(AT_EXECFD); break;<br>+    case ENTRY_NAME(AT_PHDR);   break;<br>+    case ENTRY_NAME(AT_PHENT);  break;<br>+    case ENTRY_NAME(AT_PHNUM);  break;<br>+    case ENTRY_NAME(AT_PAGESZ); break;<br>+    case ENTRY_NAME(AT_BASE);   break;<br>+    case ENTRY_NAME(AT_FLAGS);  break;<br>+    case ENTRY_NAME(AT_ENTRY);  break;<br>+    case ENTRY_NAME(AT_NOTELF); break;<br>+    case ENTRY_NAME(AT_UID);    break;<br>+    case ENTRY_NAME(AT_EUID);   break;<br>+    case ENTRY_NAME(AT_GID);    break;<br>+    case ENTRY_NAME(AT_EGID);   break;<br>+    case ENTRY_NAME(AT_CLKTCK); break;<br>+    }<br>+#undef ENTRY_NAME<br>+<br>+    return name;<br>+}<br>+<br><br>Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (added)<br>+++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,97 @@<br>+//===-- AuxVector.h ---------------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_AuxVector_H_<br>+#define liblldb_AuxVector_H_<br>+<br>+// C Includes<br>+// C++ Includes<br>+#include <vector><br>+<br>+// Other libraries and framework includes<br>+#include "lldb/lldb-forward-rtti.h"<br>+<br>+namespace lldb_private {<br>+class DataExtractor;<br>+} <br>+<br>+/// @class AuxVector<br>+/// @brief Represents a processes auxiliary vector.<br>+///<br>+/// When a process is loaded on Linux a vector of values is placed onto the<br>+/// stack communicating operating system specific information.  On construction<br>+/// this class locates and parses this information and provides a simple<br>+/// read-only interface to the entries found.<br>+class AuxVector {<br>+<br>+public:<br>+    AuxVector(lldb_private::Process *process);<br>+<br>+    struct Entry {<br>+        uint64_t type;<br>+        uint64_t value;<br>+<br>+        Entry() : type(0), value(0) { }<br>+    };<br>+<br>+    /// Constants describing the type of entry.<br>+    enum EntryType {<br>+        AT_NULL   = 0,          ///< End of auxv.<br>+        AT_IGNORE = 1,          ///< Ignore entry.<br>+        AT_EXECFD = 2,          ///< File descriptor of program.<br>+        AT_PHDR   = 3,          ///< Program headers.<br>+        AT_PHENT  = 4,          ///< Size of program header.<br>+        AT_PHNUM  = 5,          ///< Number of program headers.<br>+        AT_PAGESZ = 6,          ///< Page size.<br>+        AT_BASE   = 7,          ///< Interpreter base address.<br>+        AT_FLAGS  = 8,          ///< Flags.<br>+        AT_ENTRY  = 9,          ///< Program entry point.<br>+        AT_NOTELF = 10,         ///< Set if program is not an ELF.<br>+        AT_UID    = 11,         ///< UID.<br>+        AT_EUID   = 12,         ///< Effective UID.<br>+        AT_GID    = 13,         ///< GID.<br>+        AT_EGID   = 14,         ///< Effective GID.<br>+        AT_CLKTCK = 17          ///< Clock frequency (e.g. times(2)).<br>+    };<br>+<br>+private:<br>+    typedef std::vector<Entry> EntryVector;<br>+<br>+public:<br>+    typedef EntryVector::const_iterator iterator;<br>+<br>+    iterator begin() const { return m_auxv.begin(); }<br>+    iterator end() const { return m_auxv.end(); }<br>+<br>+    iterator <br>+    FindEntry(EntryType type) const;<br>+<br>+    static const char *<br>+    GetEntryName(const Entry &entry) { <br>+        return GetEntryName(static_cast<EntryType>(entry.type)); <br>+    }<br>+<br>+    static const char *<br>+    GetEntryName(EntryType type);<br>+<br>+    void<br>+    DumpToLog(lldb::LogSP log) const;<br>+<br>+private:<br>+    lldb_private::Process *m_process;<br>+    EntryVector m_auxv;<br>+<br>+    lldb::DataBufferSP<br>+    GetAuxvData();<br>+<br>+    void<br>+    ParseAuxv(lldb_private::DataExtractor &data);<br>+};<br>+<br>+#endif<br><br>Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (added)<br>+++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,330 @@<br>+//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+// C Includes<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+#include "lldb/Core/ArchSpec.h"<br>+#include "lldb/Core/Error.h"<br>+#include "lldb/Core/Log.h"<br>+#include "lldb/Target/Process.h"<br>+#include "lldb/Target/Target.h"<br>+<br>+#include "DYLDRendezvous.h"<br>+<br>+using namespace lldb;<br>+using namespace lldb_private;<br>+<br>+/// Locates the address of the rendezvous structure.  Returns the address on<br>+/// success and LLDB_INVALID_ADDRESS on failure.<br>+static addr_t<br>+ResolveRendezvousAddress(Process *process)<br>+{<br>+    addr_t info_location;<br>+    addr_t info_addr;<br>+    Error error;<br>+    size_t size;<br>+<br>+    info_location = process->GetImageInfoAddress();<br>+<br>+    if (info_location == LLDB_INVALID_ADDRESS)<br>+        return LLDB_INVALID_ADDRESS;<br>+<br>+    info_addr = 0;<br>+    size = process->DoReadMemory(info_location, &info_addr,<br>+                                 process->GetAddressByteSize(), error);<br>+    if (size != process->GetAddressByteSize() || error.Fail())<br>+        return LLDB_INVALID_ADDRESS;<br>+<br>+    if (info_addr == 0)<br>+        return LLDB_INVALID_ADDRESS;<br>+<br>+    return info_addr;<br>+}<br>+<br>+DYLDRendezvous::DYLDRendezvous(Process *process)<br>+    : m_process(process),<br>+      m_rendezvous_addr(LLDB_INVALID_ADDRESS),<br>+      m_current(),<br>+      m_previous(),<br>+      m_soentries(),<br>+      m_added_soentries(),<br>+      m_removed_soentries()<br>+{<br>+    // Cache a copy of the executable path<br>+    m_process->GetTarget().GetExecutableModule().get()->GetFileSpec().GetPath(m_exe_path, PATH_MAX);<br>+}<br>+<br>+bool<br>+DYLDRendezvous::Resolve()<br>+{<br>+    const size_t word_size = 4;<br>+    Rendezvous info;<br>+    size_t address_size;<br>+    size_t padding;<br>+    addr_t info_addr;<br>+    addr_t cursor;<br>+<br>+    address_size = m_process->GetAddressByteSize();<br>+    padding = address_size - word_size;<br>+<br>+    if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)<br>+        cursor = info_addr = ResolveRendezvousAddress(m_process);<br>+    else<br>+        cursor = info_addr = m_rendezvous_addr;<br>+    <br>+    if (cursor == LLDB_INVALID_ADDRESS)<br>+        return false;<br>+<br>+    if (!(cursor = ReadMemory(cursor, &info.version, word_size)))<br>+        return false;<br>+<br>+    if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size)))<br>+        return false;<br>+<br>+    if (!(cursor = ReadMemory(cursor, &info.brk, address_size)))<br>+        return false;<br>+<br>+    if (!(cursor = ReadMemory(cursor, &info.state, word_size)))<br>+        return false;<br>+<br>+    if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size)))<br>+        return false;<br>+<br>+    // The rendezvous was successfully read.  Update our internal state.<br>+    m_rendezvous_addr = info_addr;<br>+    m_previous = m_current;<br>+    m_current = info;<br>+<br>+    return UpdateSOEntries();<br>+}<br>+<br>+bool<br>+DYLDRendezvous::IsValid()<br>+{<br>+    return m_rendezvous_addr != LLDB_INVALID_ADDRESS;<br>+}<br>+<br>+bool<br>+DYLDRendezvous::UpdateSOEntries()<br>+{<br>+    SOEntry entry;<br>+<br>+    if (m_current.map_addr == 0)<br>+        return false;<br>+<br>+    // When the previous and current states are consistent this is the first<br>+    // time we have been asked to update.  Just take a snapshot of the currently<br>+    // loaded modules.<br>+    if (m_previous.state == eConsistent && m_current.state == eConsistent) <br>+        return TakeSnapshot(m_soentries);<br>+<br>+    // If we are about to add or remove a shared object clear out the current<br>+    // state and take a snapshot of the currently loaded images.<br>+    if (m_current.state == eAdd || m_current.state == eDelete)<br>+    {<br>+        assert(m_previous.state == eConsistent);<br>+        m_soentries.clear();<br>+        m_added_soentries.clear();<br>+        m_removed_soentries.clear();<br>+        return TakeSnapshot(m_soentries);<br>+    }<br>+    assert(m_current.state == eConsistent);<br>+<br>+    // Otherwise check the previous state to determine what to expect and update<br>+    // accordingly.<br>+    if (m_previous.state == eAdd)<br>+        return UpdateSOEntriesForAddition();<br>+    else if (m_previous.state == eDelete)<br>+        return UpdateSOEntriesForDeletion();<br>+<br>+    return false;<br>+}<br>+ <br>+bool<br>+DYLDRendezvous::UpdateSOEntriesForAddition()<br>+{<br>+    SOEntry entry;<br>+    iterator pos;<br>+<br>+    assert(m_previous.state == eAdd);<br>+<br>+    if (m_current.map_addr == 0)<br>+        return false;<br>+<br>+    for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)<br>+    {<br>+        if (!ReadSOEntryFromMemory(cursor, entry))<br>+            return false;<br>+<br>+        // Only add shared libraries and not the executable.<br>+        // On Linux this is indicated by an empty path in the entry.<br>+        // On FreeBSD it is the name of the executable.<br>+        if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)<br>+            continue;<br>+<br>+        pos = std::find(m_soentries.begin(), m_soentries.end(), entry);<br>+        if (pos == m_soentries.end())<br>+        {<br>+            m_soentries.push_back(entry);<br>+            m_added_soentries.push_back(entry);<br>+        }<br>+    }<br>+<br>+    return true;<br>+}<br>+<br>+bool<br>+DYLDRendezvous::UpdateSOEntriesForDeletion()<br>+{<br>+    SOEntryList entry_list;<br>+    iterator pos;<br>+<br>+    assert(m_previous.state == eDelete);<br>+<br>+    if (!TakeSnapshot(entry_list))<br>+        return false;<br>+<br>+    for (iterator I = begin(); I != end(); ++I)<br>+    {<br>+        pos = std::find(entry_list.begin(), entry_list.end(), *I);<br>+        if (pos == entry_list.end())<br>+            m_removed_soentries.push_back(*I);<br>+    }<br>+<br>+    m_soentries = entry_list;<br>+    return true;<br>+}<br>+<br>+bool<br>+DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)<br>+{<br>+    SOEntry entry;<br>+<br>+    if (m_current.map_addr == 0)<br>+        return false;<br>+<br>+    for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)<br>+    {<br>+        if (!ReadSOEntryFromMemory(cursor, entry))<br>+            return false;<br>+<br>+        // Only add shared libraries and not the executable.<br>+        // On Linux this is indicated by an empty path in the entry.<br>+        // On FreeBSD it is the name of the executable.<br>+        if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)<br>+            continue;<br>+<br>+        entry_list.push_back(entry);<br>+    }<br>+<br>+    return true;<br>+}<br>+<br>+addr_t<br>+DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size)<br>+{<br>+    size_t bytes_read;<br>+    Error error;<br>+<br>+    bytes_read = m_process->DoReadMemory(addr, dst, size, error);<br>+    if (bytes_read != size || error.Fail())<br>+        return 0;<br>+<br>+    return addr + bytes_read;<br>+}<br>+<br>+std::string<br>+DYLDRendezvous::ReadStringFromMemory(addr_t addr)<br>+{<br>+    std::string str;<br>+    Error error;<br>+    size_t size;<br>+    char c;<br>+<br>+    if (addr == LLDB_INVALID_ADDRESS)<br>+        return std::string();<br>+<br>+    for (;;) {<br>+        size = m_process->DoReadMemory(addr, &c, 1, error);<br>+        if (size != 1 || error.Fail())<br>+            return std::string();<br>+        if (c == 0)<br>+            break;<br>+        else {<br>+            str.push_back(c);<br>+            addr++;<br>+        }<br>+    }<br>+<br>+    return str;<br>+}<br>+<br>+bool<br>+DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)<br>+{<br>+    size_t address_size = m_process->GetAddressByteSize();<br>+<br>+    entry.clear();<br>+    <br>+    if (!(addr = ReadMemory(addr, &entry.base_addr, address_size)))<br>+        return false;<br>+    <br>+    if (!(addr = ReadMemory(addr, &entry.path_addr, address_size)))<br>+        return false;<br>+    <br>+    if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size)))<br>+        return false;<br>+    <br>+    if (!(addr = ReadMemory(addr, &entry.next, address_size)))<br>+        return false;<br>+    <br>+    if (!(addr = ReadMemory(addr, &entry.prev, address_size)))<br>+        return false;<br>+    <br>+    entry.path = ReadStringFromMemory(entry.path_addr);<br>+    <br>+    return true;<br>+}<br>+<br>+void<br>+DYLDRendezvous::DumpToLog(LogSP log) const<br>+{<br>+    int state = GetState();<br>+<br>+    if (!log)<br>+        return;<br>+<br>+    log->PutCString("DYLDRendezvous:");<br>+    log->Printf("   Address: %lx", GetRendezvousAddress());<br>+    log->Printf("   Version: %d",  GetVersion());<br>+    log->Printf("   Link   : %lx", GetLinkMapAddress());<br>+    log->Printf("   Break  : %lx", GetBreakAddress());<br>+    log->Printf("   LDBase : %lx", GetLDBase());<br>+    log->Printf("   State  : %s", <br>+                (state == eConsistent) ? "consistent" :<br>+                (state == eAdd)        ? "add"        :<br>+                (state == eDelete)     ? "delete"     : "unknown");<br>+    <br>+    iterator I = begin();<br>+    iterator E = end();<br>+<br>+    if (I != E) <br>+        log->PutCString("DYLDRendezvous SOEntries:");<br>+    <br>+    for (int i = 1; I != E; ++I, ++i) <br>+    {<br>+        log->Printf("\n   SOEntry [%d] %s", i, I->path.c_str());<br>+        log->Printf("      Base : %lx", I->base_addr);<br>+        log->Printf("      Path : %lx", I->path_addr);<br>+        log->Printf("      Dyn  : %lx", I->dyn_addr);<br>+        log->Printf("      Next : %lx", I->next);<br>+        log->Printf("      Prev : %lx", I->prev);<br>+    }<br>+}<br><br>Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (added)<br>+++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,230 @@<br>+//===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_Rendezvous_H_<br>+#define liblldb_Rendezvous_H_<br>+<br>+// C Includes<br>+// C++ Includes<br>+#include <list><br>+#include <string><br>+<br>+// Other libraries and framework includes<br>+#include "lldb/lldb-defines.h"<br>+#include "lldb/lldb-types.h"<br>+<br>+namespace lldb_private {<br>+class Process;<br>+}<br>+<br>+/// @class DYLDRendezvous<br>+/// @brief Interface to the runtime linker.<br>+///<br>+/// A structure is present in a processes memory space which is updated by the<br>+/// runtime liker each time a module is loaded or unloaded.  This class provides<br>+/// an interface to this structure and maintains a consistent snapshot of the<br>+/// currently loaded modules.<br>+class DYLDRendezvous {<br>+<br>+    // This structure is used to hold the contents of the debug rendezvous<br>+    // information (struct r_debug) as found in the inferiors memory.  Note that<br>+    // the layout of this struct is not binary compatible, it is simply large<br>+    // enough to hold the information on both 32 and 64 bit platforms.<br>+    struct Rendezvous {<br>+        uint64_t     version;<br>+        lldb::addr_t map_addr;<br>+        lldb::addr_t brk;<br>+        uint64_t     state;<br>+        lldb::addr_t ldbase;<br>+<br>+        Rendezvous()<br>+            : version(0), map_addr(0), brk(0), state(0), ldbase(0) { }<br>+    };<br>+<br>+public:<br>+    DYLDRendezvous(lldb_private::Process *process);<br>+<br>+    /// Update the internal snapshot of runtime linker rendezvous and recompute<br>+    /// the currently loaded modules.<br>+    ///<br>+    /// This method should be called once one start up, then once each time the<br>+    /// runtime linker enters the function given by GetBreakAddress().<br>+    ///<br>+    /// @returns true on success and false on failure.<br>+    ///<br>+    /// @see GetBreakAddress().<br>+    bool <br>+    Resolve();<br>+<br>+    /// @returns true if this rendezvous has been located in the inferiors<br>+    /// address space and false otherwise.<br>+    bool <br>+    IsValid();<br>+<br>+    /// @returns the address of the rendezvous structure in the inferiors<br>+    /// address space.<br>+    lldb::addr_t<br>+    GetRendezvousAddress() const { return m_rendezvous_addr; }<br>+<br>+    /// @returns the version of the rendezvous protocol being used.<br>+    int<br>+    GetVersion() const { return m_current.version; }<br>+<br>+    /// @returns address in the inferiors address space containing the linked<br>+    /// list of shared object descriptors.<br>+    lldb::addr_t <br>+    GetLinkMapAddress() const { return m_current.map_addr; }<br>+<br>+    /// A breakpoint should be set at this address and Resolve called on each<br>+    /// hit.<br>+    ///<br>+    /// @returns the address of a function called by the runtime linker each<br>+    /// time a module is loaded/unloaded, or about to be loaded/unloaded.<br>+    ///<br>+    /// @see Resolve()<br>+    lldb::addr_t<br>+    GetBreakAddress() const { return m_current.brk; }<br>+<br>+    /// Returns the current state of the rendezvous structure.<br>+    int<br>+    GetState() const { return m_current.state; }<br>+<br>+    /// @returns the base address of the runtime linker in the inferiors address<br>+    /// space.<br>+    lldb::addr_t<br>+    GetLDBase() const { return m_current.ldbase; }<br>+<br>+    /// @returns true if modules have been loaded into the inferior since the<br>+    /// last call to Resolve().<br>+    bool<br>+    ModulesDidLoad() const { return !m_added_soentries.empty(); }<br>+<br>+    /// @returns true if modules have been unloaded from the inferior since the<br>+    /// last call to Resolve().<br>+    bool<br>+    ModulesDidUnload() const { return !m_removed_soentries.empty(); }<br>+<br>+    void<br>+    DumpToLog(lldb::LogSP log) const;<br>+<br>+    /// @brief Constants describing the state of the rendezvous.<br>+    ///<br>+    /// @see GetState().<br>+    enum RendezvousState {<br>+        eConsistent,<br>+        eAdd,<br>+        eDelete<br>+    };<br>+<br>+    /// @brief Structure representing the shared objects currently loaded into<br>+    /// the inferior process.<br>+    ///<br>+    /// This object is a rough analogue to the struct link_map object which<br>+    /// actually lives in the inferiors memory.<br>+    struct SOEntry {<br>+        lldb::addr_t base_addr; ///< Base address of the loaded object.<br>+        lldb::addr_t path_addr; ///< String naming the shared object.<br>+        lldb::addr_t dyn_addr;  ///< Dynamic section of shared object.<br>+        lldb::addr_t next;      ///< Address of next so_entry.<br>+        lldb::addr_t prev;      ///< Address of previous so_entry.<br>+        std::string  path;      ///< File name of shared object.<br>+<br>+        SOEntry() { clear(); }<br>+<br>+        bool operator ==(const SOEntry &entry) {<br>+            return this->path == entry.path;<br>+        }<br>+<br>+        void clear() {<br>+            base_addr = 0;<br>+            path_addr = 0;<br>+            dyn_addr  = 0;<br>+            next = 0;<br>+            prev = 0;<br>+            path.clear();<br>+        }<br>+    };<br>+<br>+protected:<br>+    typedef std::list<SOEntry> SOEntryList;<br>+<br>+public:<br>+    typedef SOEntryList::const_iterator iterator;<br>+<br>+    /// Iterators over all currently loaded modules.<br>+    iterator begin() const { return m_soentries.begin(); }<br>+    iterator end() const { return m_soentries.end(); }<br>+<br>+    /// Iterators over all modules loaded into the inferior since the last call<br>+    /// to Resolve().<br>+    iterator loaded_begin() const { return m_added_soentries.begin(); }<br>+    iterator loaded_end() const { return m_added_soentries.end(); }<br>+<br>+    /// Iterators over all modules unloaded from the inferior since the last<br>+    /// call to Resolve().<br>+    iterator unloaded_begin() const { return m_removed_soentries.begin(); }<br>+    iterator unloaded_end() const { return m_removed_soentries.end(); }<br>+    <br>+protected:<br>+    lldb_private::Process *m_process;<br>+<br>+    // Cached copy of executable pathname<br>+    char m_exe_path[PATH_MAX];<br>+<br>+    /// Location of the r_debug structure in the inferiors address space.<br>+    lldb::addr_t m_rendezvous_addr;<br>+<br>+    /// Current and previous snapshots of the rendezvous structure.<br>+    Rendezvous m_current;<br>+    Rendezvous m_previous;<br>+<br>+    /// List of SOEntry objects corresponding to the current link map state.<br>+    SOEntryList m_soentries;<br>+<br>+    /// List of SOEntry's added to the link map since the last call to Resolve().<br>+    SOEntryList m_added_soentries;<br>+<br>+    /// List of SOEntry's removed from the link map since the last call to<br>+    /// Resolve().<br>+    SOEntryList m_removed_soentries;<br>+<br>+    /// Reads @p size bytes from the inferiors address space starting at @p<br>+    /// addr.<br>+    ///<br>+    /// @returns addr + size if the read was successful and false otherwise.<br>+    lldb::addr_t<br>+    ReadMemory(lldb::addr_t addr, void *dst, size_t size);<br>+<br>+    /// Reads a null-terminated C string from the memory location starting at @p<br>+    /// addr.<br>+    std::string<br>+    ReadStringFromMemory(lldb::addr_t addr);<br>+<br>+    /// Reads an SOEntry starting at @p addr.<br>+    bool<br>+    ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);<br>+<br>+    /// Updates the current set of SOEntries, the set of added entries, and the<br>+    /// set of removed entries.<br>+    bool<br>+    UpdateSOEntries();<br>+<br>+    bool<br>+    UpdateSOEntriesForAddition();<br>+<br>+    bool<br>+    UpdateSOEntriesForDeletion();<br>+<br>+    /// Reads the current list of shared objects according to the link map<br>+    /// supplied by the runtime linker.<br>+    bool<br>+    TakeSnapshot(SOEntryList &entry_list);<br>+};<br>+<br>+#endif<br><br>Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (added)<br>+++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,425 @@<br>+//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+// C Includes<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+#include "lldb/Core/PluginManager.h"<br>+#include "lldb/Core/Log.h"<br>+#include "lldb/Target/Process.h"<br>+#include "lldb/Target/Target.h"<br>+#include "lldb/Target/Thread.h"<br>+#include "lldb/Target/ThreadPlanRunToAddress.h"<br>+<br>+#include "AuxVector.h"<br>+#include "DynamicLoaderPOSIXDYLD.h"<br>+<br>+using namespace lldb;<br>+using namespace lldb_private;<br>+<br>+void<br>+DynamicLoaderPOSIXDYLD::Initialize()<br>+{<br>+    PluginManager::RegisterPlugin(GetPluginNameStatic(),<br>+                                  GetPluginDescriptionStatic(),<br>+                                  CreateInstance);<br>+}<br>+<br>+void<br>+DynamicLoaderPOSIXDYLD::Terminate()<br>+{<br>+}<br>+<br>+const char *<br>+DynamicLoaderPOSIXDYLD::GetPluginName()<br>+{<br>+    return "DynamicLoaderPOSIXDYLD";<br>+}<br>+<br>+const char *<br>+DynamicLoaderPOSIXDYLD::GetShortPluginName()<br>+{<br>+    return "linux-dyld";<br>+}<br>+<br>+const char *<br>+DynamicLoaderPOSIXDYLD::GetPluginNameStatic()<br>+{<br>+    return "dynamic-loader.linux-dyld";<br>+}<br>+<br>+const char *<br>+DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic()<br>+{<br>+    return "Dynamic loader plug-in that watches for shared library "<br>+           "loads/unloads in POSIX processes.";<br>+}<br>+<br>+void<br>+DynamicLoaderPOSIXDYLD::GetPluginCommandHelp(const char *command, Stream *strm)<br>+{<br>+}<br>+<br>+uint32_t<br>+DynamicLoaderPOSIXDYLD::GetPluginVersion()<br>+{<br>+    return 1;<br>+}<br>+<br>+DynamicLoader *<br>+DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, bool force)<br>+{<br>+    bool create = force;<br>+    if (!create)<br>+    {<br>+        const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();<br>+        if (triple_ref.getOS() == llvm::Triple::Linux ||<br>+            triple_ref.getOS() == llvm::Triple::FreeBSD)<br>+            create = true;<br>+    }<br>+    <br>+    if (create)<br>+        return new DynamicLoaderPOSIXDYLD (process);<br>+    return NULL;<br>+}<br>+<br>+DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process)<br>+    : DynamicLoader(process),<br>+      m_rendezvous(process),<br>+      m_load_offset(LLDB_INVALID_ADDRESS),<br>+      m_entry_point(LLDB_INVALID_ADDRESS),<br>+      m_auxv(NULL)<br>+{<br>+}<br>+<br>+DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD()<br>+{<br>+}<br>+<br>+void<br>+DynamicLoaderPOSIXDYLD::DidAttach()<br>+{<br>+    ModuleSP executable;<br>+    addr_t load_offset;<br>+<br>+    m_auxv.reset(new AuxVector(m_process));<br>+<br>+    executable = m_process->GetTarget().GetExecutableModule();<br>+    load_offset = ComputeLoadOffset();<br>+<br>+    if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)<br>+    {<br>+        ModuleList module_list;<br>+        module_list.Append(executable);<br>+        UpdateLoadedSections(executable, load_offset);<br>+        LoadAllCurrentModules();<br>+        m_process->GetTarget().ModulesDidLoad(module_list);<br>+    }<br>+}<br>+<br>+void<br>+DynamicLoaderPOSIXDYLD::DidLaunch()<br>+{<br>+    ModuleSP executable;<br>+    addr_t load_offset;<br>+<br>+    m_auxv.reset(new AuxVector(m_process));<br>+<br>+    executable = m_process->GetTarget().GetExecutableModule();<br>+    load_offset = ComputeLoadOffset();<br>+<br>+    if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)<br>+    {<br>+        ModuleList module_list;<br>+        module_list.Append(executable);<br>+        UpdateLoadedSections(executable, load_offset);<br>+        ProbeEntry();<br>+        m_process->GetTarget().ModulesDidLoad(module_list);<br>+    }<br>+}<br>+<br>+Error<br>+DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm)<br>+{<br>+    return Error();<br>+}<br>+<br>+Log *<br>+DynamicLoaderPOSIXDYLD::EnablePluginLogging(Stream *strm, Args &command)<br>+{<br>+    return NULL;<br>+}<br>+<br>+Error<br>+DynamicLoaderPOSIXDYLD::CanLoadImage()<br>+{<br>+    return Error();<br>+}<br>+<br>+void<br>+DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)<br>+{<br>+    ObjectFile *obj_file = module->GetObjectFile();<br>+    SectionList *sections = obj_file->GetSectionList();<br>+    SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();<br>+    const size_t num_sections = sections->GetSize();<br>+<br>+    for (unsigned i = 0; i < num_sections; ++i)<br>+    {<br>+        Section *section = sections->GetSectionAtIndex(i).get();<br>+        lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr;<br>+        lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section);<br>+<br>+        // If the file address of the section is zero then this is not an<br>+        // allocatable/loadable section (property of ELF sh_addr).  Skip it.<br>+        if (new_load_addr == base_addr)<br>+            continue;<br>+<br>+        if (old_load_addr == LLDB_INVALID_ADDRESS ||<br>+            old_load_addr != new_load_addr)<br>+            load_list.SetSectionLoadAddress(section, new_load_addr);<br>+    }<br>+}<br>+<br>+void<br>+DynamicLoaderPOSIXDYLD::ProbeEntry()<br>+{<br>+    Breakpoint *entry_break;<br>+    addr_t entry;<br>+<br>+    if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)<br>+        return;<br>+    <br>+    entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get();<br>+    entry_break->SetCallback(EntryBreakpointHit, this, true);<br>+}<br>+<br>+// The runtime linker has run and initialized the rendezvous structure once the<br>+// process has hit its entry point.  When we hit the corresponding breakpoint we<br>+// interrogate the rendezvous structure to get the load addresses of all<br>+// dependent modules for the process.  Similarly, we can discover the runtime<br>+// linker function and setup a breakpoint to notify us of any dynamically loaded<br>+// modules (via dlopen).<br>+bool<br>+DynamicLoaderPOSIXDYLD::EntryBreakpointHit(void *baton, <br>+                                           StoppointCallbackContext *context, <br>+                                           user_id_t break_id, <br>+                                           user_id_t break_loc_id)<br>+{<br>+    DynamicLoaderPOSIXDYLD* dyld_instance;<br>+<br>+    dyld_instance = static_cast<DynamicLoaderPOSIXDYLD*>(baton);<br>+    dyld_instance->LoadAllCurrentModules();<br>+    dyld_instance->SetRendezvousBreakpoint();<br>+    return false; // Continue running.<br>+}<br>+<br>+void<br>+DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint()<br>+{<br>+    Breakpoint *dyld_break;<br>+    addr_t break_addr;<br>+<br>+    break_addr = m_rendezvous.GetBreakAddress();<br>+    dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get();<br>+    dyld_break->SetCallback(RendezvousBreakpointHit, this, true);<br>+}<br>+<br>+bool<br>+DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(void *baton, <br>+                                                StoppointCallbackContext *context, <br>+                                                user_id_t break_id, <br>+                                                user_id_t break_loc_id)<br>+{<br>+    DynamicLoaderPOSIXDYLD* dyld_instance;<br>+<br>+    dyld_instance = static_cast<DynamicLoaderPOSIXDYLD*>(baton);<br>+    dyld_instance->RefreshModules();<br>+<br>+    // Return true to stop the target, false to just let the target run.<br>+    return dyld_instance->GetStopWhenImagesChange();<br>+}<br>+<br>+void<br>+DynamicLoaderPOSIXDYLD::RefreshModules()<br>+{<br>+    if (!m_rendezvous.Resolve())<br>+        return;<br>+<br>+    DYLDRendezvous::iterator I;<br>+    DYLDRendezvous::iterator E;<br>+<br>+    ModuleList &loaded_modules = m_process->GetTarget().GetImages();<br>+<br>+    if (m_rendezvous.ModulesDidLoad()) <br>+    {<br>+        ModuleList new_modules;<br>+<br>+        E = m_rendezvous.loaded_end();<br>+        for (I = m_rendezvous.loaded_begin(); I != E; ++I)<br>+        {<br>+            FileSpec file(I->path.c_str(), true);<br>+            ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);<br>+            if (module_sp.get())<br>+                new_modules.Append(module_sp);<br>+        }<br>+        m_process->GetTarget().ModulesDidLoad(new_modules);<br>+    }<br>+    <br>+    if (m_rendezvous.ModulesDidUnload())<br>+    {<br>+        ModuleList old_modules;<br>+<br>+        E = m_rendezvous.unloaded_end();<br>+        for (I = m_rendezvous.unloaded_begin(); I != E; ++I)<br>+        {<br>+            FileSpec file(I->path.c_str(), true);<br>+            ModuleSP module_sp = <br>+                loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL);<br>+            if (module_sp.get())<br>+                old_modules.Append(module_sp);<br>+        }<br>+        m_process->GetTarget().ModulesDidUnload(old_modules);<br>+    }<br>+}<br>+<br>+ThreadPlanSP<br>+DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop)<br>+{<br>+    LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));<br>+    ThreadPlanSP thread_plan_sp;<br>+<br>+    StackFrame *frame = thread.GetStackFrameAtIndex(0).get();<br>+    const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol);<br>+    Symbol *sym = context.symbol;<br>+<br>+    if (sym == NULL || !sym->IsTrampoline())<br>+        return thread_plan_sp;<br>+<br>+    const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);<br>+    if (!sym_name)<br>+        return thread_plan_sp;<br>+<br>+    SymbolContextList target_symbols;<br>+    Target &target = thread.GetProcess().GetTarget();<br>+    ModuleList &images = target.GetImages();<br>+<br>+    images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols);<br>+    size_t num_targets = target_symbols.GetSize();<br>+    if (!num_targets)<br>+        return thread_plan_sp;<br>+<br>+    typedef std::vector<lldb::addr_t> AddressVector;<br>+    AddressVector addrs;<br>+    for (size_t i = 0; i < num_targets; ++i)<br>+    {<br>+        SymbolContext context;<br>+        AddressRange range;<br>+        if (target_symbols.GetContextAtIndex(i, context))<br>+        {<br>+            context.GetAddressRange(eSymbolContextEverything, 0, false, range);<br>+            lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target);<br>+            if (addr != LLDB_INVALID_ADDRESS)<br>+                addrs.push_back(addr);<br>+        }<br>+    }<br>+<br>+    if (addrs.size() > 0) <br>+    {<br>+        AddressVector::iterator start = addrs.begin();<br>+        AddressVector::iterator end = addrs.end();<br>+<br>+        std::sort(start, end);<br>+        addrs.erase(std::unique(start, end), end);<br>+        thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop));<br>+    }<br>+<br>+    return thread_plan_sp;<br>+}<br>+<br>+void<br>+DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()<br>+{<br>+    DYLDRendezvous::iterator I;<br>+    DYLDRendezvous::iterator E;<br>+    ModuleList module_list;<br>+    <br>+    if (!m_rendezvous.Resolve())<br>+        return;<br>+<br>+    for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)<br>+    {<br>+        FileSpec file(I->path.c_str(), false);<br>+        ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);<br>+        if (module_sp.get())<br>+            module_list.Append(module_sp);<br>+    }<br>+<br>+    m_process->GetTarget().ModulesDidLoad(module_list);<br>+}<br>+<br>+ModuleSP<br>+DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr)<br>+{<br>+    Target &target = m_process->GetTarget();<br>+    ModuleList &modules = target.GetImages();<br>+    ModuleSP module_sp;<br>+<br>+    if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL))) <br>+    {<br>+        UpdateLoadedSections(module_sp, base_addr);<br>+    }<br>+    else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture()))) <br>+    {<br>+        UpdateLoadedSections(module_sp, base_addr);<br>+        modules.Append(module_sp);<br>+    }<br>+<br>+    return module_sp;<br>+}<br>+<br>+addr_t<br>+DynamicLoaderPOSIXDYLD::ComputeLoadOffset()<br>+{<br>+    addr_t virt_entry;<br>+<br>+    if (m_load_offset != LLDB_INVALID_ADDRESS)<br>+        return m_load_offset;<br>+<br>+    if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)<br>+        return LLDB_INVALID_ADDRESS;<br>+<br>+    ModuleSP module = m_process->GetTarget().GetExecutableModule();<br>+    ObjectFile *exe = module->GetObjectFile();<br>+    Address file_entry = exe->GetEntryPointAddress();<br>+<br>+    if (!file_entry.IsValid())<br>+        return LLDB_INVALID_ADDRESS;<br>+            <br>+    m_load_offset = virt_entry - file_entry.GetFileAddress();<br>+    return m_load_offset;<br>+}<br>+<br>+addr_t<br>+DynamicLoaderPOSIXDYLD::GetEntryPoint()<br>+{<br>+    if (m_entry_point != LLDB_INVALID_ADDRESS)<br>+        return m_entry_point;<br>+<br>+    if (m_auxv.get() == NULL)<br>+        return LLDB_INVALID_ADDRESS;<br>+<br>+    AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY);<br>+<br>+    if (I == m_auxv->end())<br>+        return LLDB_INVALID_ADDRESS;<br>+<br>+    m_entry_point = static_cast<addr_t>(I->value);<br>+    return m_entry_point;<br>+}<br><br>Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (added)<br>+++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,165 @@<br>+//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_DynamicLoaderPOSIX_H_<br>+#define liblldb_DynamicLoaderPOSIX_H_<br>+<br>+// C Includes<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+#include "lldb/Breakpoint/StoppointCallbackContext.h"<br>+#include "lldb/Target/DynamicLoader.h"<br>+<br>+#include "DYLDRendezvous.h"<br>+<br>+class AuxVector;<br>+<br>+class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader<br>+{<br>+public:<br>+<br>+    static void<br>+    Initialize();<br>+<br>+    static void<br>+    Terminate();<br>+<br>+    static const char *<br>+    GetPluginNameStatic();<br>+<br>+    static const char *<br>+    GetPluginDescriptionStatic();<br>+<br>+    static lldb_private::DynamicLoader *<br>+    CreateInstance(lldb_private::Process *process, bool force);<br>+<br>+    DynamicLoaderPOSIXDYLD(lldb_private::Process *process);<br>+<br>+    virtual<br>+    ~DynamicLoaderPOSIXDYLD();<br>+<br>+    //------------------------------------------------------------------<br>+    // DynamicLoader protocol<br>+    //------------------------------------------------------------------<br>+<br>+    virtual void<br>+    DidAttach();<br>+<br>+    virtual void<br>+    DidLaunch();<br>+<br>+    virtual lldb::ThreadPlanSP<br>+    GetStepThroughTrampolinePlan(lldb_private::Thread &thread,<br>+                                 bool stop_others);<br>+<br>+    virtual lldb_private::Error<br>+    CanLoadImage();<br>+<br>+    //------------------------------------------------------------------<br>+    // PluginInterface protocol<br>+    //------------------------------------------------------------------<br>+    virtual const char *<br>+    GetPluginName();<br>+<br>+    virtual const char *<br>+    GetShortPluginName();<br>+<br>+    virtual uint32_t<br>+    GetPluginVersion();<br>+<br>+    virtual void<br>+    GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);<br>+<br>+    virtual lldb_private::Error<br>+    ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);<br>+<br>+    virtual lldb_private::Log *<br>+    EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);<br>+<br>+protected:<br>+    /// Runtime linker rendezvous structure.<br>+    DYLDRendezvous m_rendezvous;<br>+<br>+    /// Virtual load address of the inferior process.<br>+    lldb::addr_t m_load_offset;<br>+<br>+    /// Virtual entry address of the inferior process.<br>+    lldb::addr_t m_entry_point;<br>+<br>+    /// Auxiliary vector of the inferior process.<br>+    std::auto_ptr<AuxVector> m_auxv;<br>+<br>+    /// Enables a breakpoint on a function called by the runtime<br>+    /// linker each time a module is loaded or unloaded.<br>+    void<br>+    SetRendezvousBreakpoint();<br>+<br>+    /// Callback routine which updates the current list of loaded modules based<br>+    /// on the information supplied by the runtime linker.<br>+    static bool<br>+    RendezvousBreakpointHit(void *baton, <br>+                            lldb_private::StoppointCallbackContext *context, <br>+                            lldb::user_id_t break_id, <br>+                            lldb::user_id_t break_loc_id);<br>+    <br>+    /// Helper method for RendezvousBreakpointHit.  Updates LLDB's current set<br>+    /// of loaded modules.<br>+    void<br>+    RefreshModules();<br>+<br>+    /// Updates the load address of every allocatable section in @p module.<br>+    ///<br>+    /// @param module The module to traverse.<br>+    ///<br>+    /// @param base_addr The virtual base address @p module is loaded at.<br>+    void<br>+    UpdateLoadedSections(lldb::ModuleSP module, <br>+                         lldb::addr_t base_addr = 0);<br>+<br>+    /// Locates or creates a module given by @p file and updates/loads the<br>+    /// resulting module at the virtual base address @p base_addr.<br>+    lldb::ModuleSP<br>+    LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr);<br>+<br>+    /// Resolves the entry point for the current inferior process and sets a<br>+    /// breakpoint at that address.<br>+    void<br>+    ProbeEntry();<br>+<br>+    /// Callback routine invoked when we hit the breakpoint on process entry.<br>+    ///<br>+    /// This routine is responsible for resolving the load addresses of all<br>+    /// dependent modules required by the inferior and setting up the rendezvous<br>+    /// breakpoint.<br>+    static bool<br>+    EntryBreakpointHit(void *baton, <br>+                       lldb_private::StoppointCallbackContext *context, <br>+                       lldb::user_id_t break_id, <br>+                       lldb::user_id_t break_loc_id);<br>+<br>+    /// Helper for the entry breakpoint callback.  Resolves the load addresses<br>+    /// of all dependent modules.<br>+    void<br>+    LoadAllCurrentModules();<br>+<br>+    /// Computes a value for m_load_offset returning the computed address on<br>+    /// success and LLDB_INVALID_ADDRESS on failure.<br>+    lldb::addr_t<br>+    ComputeLoadOffset();<br>+<br>+    /// Computes a value for m_entry_point returning the computed address on<br>+    /// success and LLDB_INVALID_ADDRESS on failure.<br>+    lldb::addr_t<br>+    GetEntryPoint();<br>+<br>+private:<br>+    DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);<br>+};<br>+<br>+#endif  // liblldb_DynamicLoaderPOSIXDYLD_H_<br><br>Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile (added)<br>+++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,14 @@<br>+##===- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile ----*- Makefile -*-===##<br>+# <br>+#                     The LLVM Compiler Infrastructure<br>+#<br>+# This file is distributed under the University of Illinois Open Source<br>+# License. See LICENSE.TXT for details.<br>+# <br>+##===----------------------------------------------------------------------===##<br>+<br>+LLDB_LEVEL := ../../../..<br>+LIBRARYNAME := lldbPluginDynamicLoaderPOSIX<br>+BUILD_ARCHIVE = 1<br>+<br>+include $(LLDB_LEVEL)/Makefile<br><br>Added: lldb/trunk/source/Plugins/Process/FreeBSD/Makefile<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/Makefile?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/Makefile?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/FreeBSD/Makefile (added)<br>+++ lldb/trunk/source/Plugins/Process/FreeBSD/Makefile Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,17 @@<br>+##===- source/Plugins/Process/FreeBSD/Makefile ---------------*- Makefile -*-===##<br>+# <br>+#                     The LLVM Compiler Infrastructure<br>+#<br>+# This file is distributed under the University of Illinois Open Source<br>+# License. See LICENSE.TXT for details.<br>+# <br>+##===----------------------------------------------------------------------===##<br>+<br>+LLDB_LEVEL := ../../../..<br>+LIBRARYNAME := lldbPluginProcessFreeBSD<br>+BUILD_ARCHIVE = 1<br>+<br>+# Extend the include path so we may locate UnwindLLDB.h<br>+CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility<br>+<br>+include $(LLDB_LEVEL)/Makefile<br><br>Added: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (added)<br>+++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,136 @@<br>+//===-- ProcessFreeBSD.cpp ----------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+// C Includes<br>+#include <errno.h><br>+<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+#include "lldb/Core/PluginManager.h"<br>+#include "lldb/Core/State.h"<br>+#include "lldb/Host/Host.h"<br>+#include "lldb/Symbol/ObjectFile.h"<br>+#include "lldb/Target/DynamicLoader.h"<br>+#include "lldb/Target/Target.h"<br>+<br>+#include "ProcessFreeBSD.h"<br>+#include "ProcessPOSIXLog.h"<br>+#include "Plugins/Process/Utility/InferiorCallPOSIX.h"<br>+#include "ProcessMonitor.h"<br>+#include "POSIXThread.h"<br>+<br>+using namespace lldb;<br>+using namespace lldb_private;<br>+<br>+//------------------------------------------------------------------------------<br>+// Static functions.<br>+<br>+Process*<br>+ProcessFreeBSD::CreateInstance(Target& target, Listener &listener)<br>+{<br>+    return new ProcessFreeBSD(target, listener);<br>+}<br>+<br>+void<br>+ProcessFreeBSD::Initialize()<br>+{<br>+    static bool g_initialized = false;<br>+<br>+    if (!g_initialized)<br>+    {<br>+        PluginManager::RegisterPlugin(GetPluginNameStatic(),<br>+                                      GetPluginDescriptionStatic(),<br>+                                      CreateInstance);<br>+        Log::Callbacks log_callbacks = {<br>+            ProcessPOSIXLog::DisableLog,<br>+            ProcessPOSIXLog::EnableLog,<br>+            ProcessPOSIXLog::ListLogCategories<br>+        };<br>+<br>+        Log::RegisterLogChannel (ProcessFreeBSD::GetPluginNameStatic(), log_callbacks);<br>+        ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic());<br>+        g_initialized = true;<br>+    }<br>+}<br>+<br>+const char *<br>+ProcessFreeBSD::GetPluginNameStatic()<br>+{<br>+    return "freebsd";<br>+}<br>+<br>+const char *<br>+ProcessFreeBSD::GetPluginDescriptionStatic()<br>+{<br>+    return "Process plugin for FreeBSD";<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+// ProcessInterface protocol.<br>+<br>+const char *<br>+ProcessFreeBSD::GetPluginName()<br>+{<br>+    return "process.freebsd";<br>+}<br>+<br>+const char *<br>+ProcessFreeBSD::GetShortPluginName()<br>+{<br>+    return "process.freebsd";<br>+}<br>+<br>+uint32_t<br>+ProcessFreeBSD::GetPluginVersion()<br>+{<br>+    return 1;<br>+}<br>+<br>+void<br>+ProcessFreeBSD::GetPluginCommandHelp(const char *command, Stream *strm)<br>+{<br>+}<br>+<br>+Error<br>+ProcessFreeBSD::ExecutePluginCommand(Args &command, Stream *strm)<br>+{<br>+    return Error(1, eErrorTypeGeneric);<br>+}<br>+<br>+Log *<br>+ProcessFreeBSD::EnablePluginLogging(Stream *strm, Args &command)<br>+{<br>+    return NULL;<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+// Constructors and destructors.<br>+<br>+ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener)<br>+    : ProcessPOSIX(target, listener)<br>+{<br>+    // FIXME: Putting this code in the ctor and saving the byte order in a<br>+    // member variable is a hack to avoid const qual issues in GetByteOrder.<br>+    ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();<br>+    m_byte_order = obj_file->GetByteOrder();<br>+}<br>+<br>+void<br>+ProcessFreeBSD::Terminate()<br>+{<br>+}<br>+<br>+uint32_t<br>+ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)<br>+{<br>+    // XXX haxx<br>+    new_thread_list = old_thread_list;<br>+  <br>+    return 0;<br>+}<br><br>Added: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (added)<br>+++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,84 @@<br>+//===-- ProcessFreeBSD.h ------------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_ProcessFreeBSD_H_<br>+#define liblldb_ProcessFreeBSD_H_<br>+<br>+// C Includes<br>+<br>+// C++ Includes<br>+#include <queue><br>+<br>+// Other libraries and framework includes<br>+#include "lldb/Target/Process.h"<br>+#include "lldb/Target/ThreadList.h"<br>+#include "ProcessMessage.h"<br>+#include "ProcessPOSIX.h"<br>+<br>+class ProcessMonitor;<br>+<br>+class ProcessFreeBSD :<br>+    public ProcessPOSIX<br>+{<br>+<br>+public:<br>+    //------------------------------------------------------------------<br>+    // Static functions.<br>+    //------------------------------------------------------------------<br>+    static Process*<br>+    CreateInstance(lldb_private::Target& target,<br>+                   lldb_private::Listener &listener);<br>+<br>+    static void<br>+    Initialize();<br>+<br>+    static void<br>+    Terminate();<br>+<br>+    static const char *<br>+    GetPluginNameStatic();<br>+<br>+    static const char *<br>+    GetPluginDescriptionStatic();<br>+<br>+    //------------------------------------------------------------------<br>+    // Constructors and destructors<br>+    //------------------------------------------------------------------<br>+    ProcessFreeBSD(lldb_private::Target& target,<br>+                 lldb_private::Listener &listener);<br>+<br>+    virtual uint32_t<br>+    UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list);<br>+<br>+    //------------------------------------------------------------------<br>+    // PluginInterface protocol<br>+    //------------------------------------------------------------------<br>+    virtual const char *<br>+    GetPluginName();<br>+<br>+    virtual const char *<br>+    GetShortPluginName();<br>+<br>+    virtual uint32_t<br>+    GetPluginVersion();<br>+<br>+    virtual void<br>+    GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);<br>+<br>+    virtual lldb_private::Error<br>+    ExecutePluginCommand(lldb_private::Args &command,<br>+                         lldb_private::Stream *strm);<br>+<br>+    virtual lldb_private::Log *<br>+    EnablePluginLogging(lldb_private::Stream *strm,<br>+                        lldb_private::Args &command);<br>+<br>+};<br>+<br>+#endif  // liblldb_MacOSXProcess_H_<br><br>Added: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (added)<br>+++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,1558 @@<br>+//===-- ProcessMonitor.cpp ------------------------------------ -*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+// C Includes<br>+#include <errno.h><br>+#include <poll.h><br>+#include <string.h><br>+#include <unistd.h><br>+#include <signal.h><br>+#include <sys/ptrace.h><br>+#include <sys/socket.h><br>+#include <sys/types.h><br>+#include <sys/wait.h><br>+<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+#include "lldb/Core/Error.h"<br>+#include "lldb/Core/RegisterValue.h"<br>+#include "lldb/Core/Scalar.h"<br>+#include "lldb/Host/Host.h"<br>+#include "lldb/Target/Thread.h"<br>+#include "lldb/Target/RegisterContext.h"<br>+#include "lldb/Utility/PseudoTerminal.h"<br>+<br>+<br>+#include "POSIXThread.h"<br>+#include "ProcessFreeBSD.h"<br>+#include "ProcessPOSIXLog.h"<br>+#include "ProcessMonitor.h"<br>+<br>+extern "C" {<br>+      extern char ** environ;<br>+ }<br>+<br>+using namespace lldb;<br>+using namespace lldb_private;<br>+<br>+// We disable the tracing of ptrace calls for integration builds to<br>+// avoid the additional indirection and checks.<br>+#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION<br>+// Wrapper for ptrace to catch errors and log calls.<br>+<br>+const char *<br>+Get_PT_IO_OP(int op)<br>+{<br>+    switch (op) {<br>+        case PIOD_READ_D:  return "READ_D";<br>+        case PIOD_WRITE_D: return "WRITE_D";<br>+        case PIOD_READ_I:  return "READ_I";<br>+        case PIOD_WRITE_I: return "WRITE_I";<br>+        default:           return "Unknown op";<br>+    }<br>+}<br>+<br>+extern long<br>+PtraceWrapper(int req, ::pid_t pid, void *addr, int data,<br>+              const char* reqName, const char* file, int line)<br>+{<br>+    long int result;<br>+<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));<br>+<br>+    if (log) {<br>+        log->Printf("ptrace(%s, %u, %p, %x) called from file %s line %d",<br>+                    reqName, pid, addr, data, file, line);<br>+        if (req == PT_IO) {<br>+            struct ptrace_io_desc *pi = (struct ptrace_io_desc *) addr;<br>+            <br>+            log->Printf("PT_IO: op=%s offs=%zx size=%ld",<br>+                     Get_PT_IO_OP(pi->piod_op),  pi->piod_offs, pi->piod_len);<br>+        }<br>+    }<br>+<br>+    //PtraceDisplayBytes(req, data);<br>+<br>+    errno = 0;<br>+    result = ptrace(req, pid, (caddr_t) addr, data);<br>+<br>+    //PtraceDisplayBytes(req, data);<br>+<br>+    if (log && (result == -1 || errno != 0))<br>+    {<br>+        const char* str;<br>+        switch (errno)<br>+        {<br>+        case ESRCH:  str = "ESRCH"; break;<br>+        case EINVAL: str = "EINVAL"; break;<br>+        case EBUSY:  str = "EBUSY"; break;<br>+        case EPERM:  str = "EPERM"; break;<br>+        default:     str = "<unknown>";<br>+        }<br>+        log->Printf("ptrace() failed; errno=%d (%s)", errno, str);<br>+    }<br>+<br>+    if (log) {<br>+        if (req == PT_GETREGS) {<br>+            struct reg *r = (struct reg *) addr;<br>+<br>+            log->Printf("PT_GETREGS: ip=0x%lx", r->r_rip);<br>+            log->Printf("PT_GETREGS: sp=0x%lx", r->r_rsp);<br>+            log->Printf("PT_GETREGS: bp=0x%lx", r->r_rbp);<br>+            log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax);<br>+        }<br>+    }<br>+     <br>+    return result;<br>+}<br>+<br>+#define PTRACE(req, pid, addr, data) \<br>+    PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__)<br>+#else<br>+#define PTRACE ptrace<br>+#endif<br>+<br>+//------------------------------------------------------------------------------<br>+// Static implementations of ProcessMonitor::ReadMemory and<br>+// ProcessMonitor::WriteMemory.  This enables mutual recursion between these<br>+// functions without needed to go thru the thread funnel.<br>+<br>+static size_t<br>+DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf, size_t size, <br>+             Error &error)<br>+{<br>+    struct ptrace_io_desc pi_desc;<br>+<br>+    pi_desc.piod_op = PIOD_READ_D;<br>+    pi_desc.piod_offs = (void *)vm_addr;<br>+    pi_desc.piod_addr = buf;<br>+    pi_desc.piod_len = size;<br>+<br>+    if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0)<br>+        error.SetErrorToErrno();<br>+    return pi_desc.piod_len;<br>+}<br>+<br>+static size_t<br>+DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, const void *buf, <br>+              size_t size, Error &error)<br>+{<br>+    struct ptrace_io_desc pi_desc;<br>+<br>+    pi_desc.piod_op = PIOD_WRITE_D;<br>+    pi_desc.piod_offs = (void *)vm_addr;<br>+    pi_desc.piod_addr = (void *)buf;<br>+    pi_desc.piod_len = size;<br>+<br>+    if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0)<br>+        error.SetErrorToErrno();<br>+    return pi_desc.piod_len;<br>+}<br>+<br>+// Simple helper function to ensure flags are enabled on the given file<br>+// descriptor.<br>+static bool<br>+EnsureFDFlags(int fd, int flags, Error &error)<br>+{<br>+    int status;<br>+<br>+    if ((status = fcntl(fd, F_GETFL)) == -1)<br>+    {<br>+        error.SetErrorToErrno();<br>+        return false;<br>+    }<br>+<br>+    if (fcntl(fd, F_SETFL, status | flags) == -1)<br>+    {<br>+        error.SetErrorToErrno();<br>+        return false;<br>+    }<br>+<br>+    return true;<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class Operation<br>+/// @brief Represents a ProcessMonitor operation.<br>+///<br>+/// Under FreeBSD, it is not possible to ptrace() from any other thread but the<br>+/// one that spawned or attached to the process from the start.  Therefore, when<br>+/// a ProcessMonitor is asked to deliver or change the state of an inferior<br>+/// process the operation must be "funneled" to a specific thread to perform the<br>+/// task.  The Operation class provides an abstract base for all services the<br>+/// ProcessMonitor must perform via the single virtual function Execute, thus<br>+/// encapsulating the code that needs to run in the privileged context.<br>+class Operation<br>+{<br>+public:<br>+    virtual void Execute(ProcessMonitor *monitor) = 0;<br>+};<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class ReadOperation<br>+/// @brief Implements ProcessMonitor::ReadMemory.<br>+class ReadOperation : public Operation<br>+{<br>+public:<br>+    ReadOperation(lldb::addr_t addr, void *buff, size_t size,<br>+                  Error &error, size_t &result)<br>+        : m_addr(addr), m_buff(buff), m_size(size),<br>+          m_error(error), m_result(result)<br>+        { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    lldb::addr_t m_addr;<br>+    void *m_buff;<br>+    size_t m_size;<br>+    Error &m_error;<br>+    size_t &m_result;<br>+};<br>+<br>+void<br>+ReadOperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    lldb::pid_t pid = monitor->GetPID();<br>+<br>+    m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error);<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class ReadOperation<br>+/// @brief Implements ProcessMonitor::WriteMemory.<br>+class WriteOperation : public Operation<br>+{<br>+public:<br>+    WriteOperation(lldb::addr_t addr, const void *buff, size_t size,<br>+                   Error &error, size_t &result)<br>+        : m_addr(addr), m_buff(buff), m_size(size),<br>+          m_error(error), m_result(result)<br>+        { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    lldb::addr_t m_addr;<br>+    const void *m_buff;<br>+    size_t m_size;<br>+    Error &m_error;<br>+    size_t &m_result;<br>+};<br>+<br>+void<br>+WriteOperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    lldb::pid_t pid = monitor->GetPID();<br>+<br>+    m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error);<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class ReadRegOperation<br>+/// @brief Implements ProcessMonitor::ReadRegisterValue.<br>+class ReadRegOperation : public Operation<br>+{<br>+public:<br>+    ReadRegOperation(unsigned offset, unsigned size, RegisterValue &value, bool &result)<br>+      : m_offset(offset), m_size(size), m_value(value), m_result(result)<br>+        { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    unsigned m_offset;<br>+    unsigned m_size;<br>+    RegisterValue &m_value;<br>+    bool &m_result;<br>+};<br>+<br>+void<br>+ReadRegOperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    lldb::pid_t pid = monitor->GetPID();<br>+    struct reg regs;<br>+    int rc;<br>+<br>+    if ((rc = PTRACE(PT_GETREGS, pid, (caddr_t)&regs, 0)) < 0) {<br>+        m_result = false;<br>+    } else {<br>+        if (m_size == sizeof(uintptr_t))<br>+            m_value = *(uintptr_t *)(((caddr_t)&regs) + m_offset);<br>+        else <br>+            memcpy(&m_value, (((caddr_t)&regs) + m_offset), m_size);<br>+        m_result = true;<br>+    }<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class WriteRegOperation<br>+/// @brief Implements ProcessMonitor::WriteRegisterValue.<br>+class WriteRegOperation : public Operation<br>+{<br>+public:<br>+    WriteRegOperation(unsigned offset, const RegisterValue &value, bool &result)<br>+        : m_offset(offset), m_value(value), m_result(result)<br>+        { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    unsigned m_offset;<br>+    const RegisterValue &m_value;<br>+    bool &m_result;<br>+};<br>+<br>+void<br>+WriteRegOperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    lldb::pid_t pid = monitor->GetPID();<br>+    struct reg regs;<br>+<br>+    if (PTRACE(PT_GETREGS, pid, (caddr_t)&regs, 0) < 0) {<br>+        m_result = false;<br>+        return;<br>+    }<br>+    *(uintptr_t *)(((caddr_t)&regs) + m_offset) = (uintptr_t)m_value.GetAsUInt64();<br>+    if (PTRACE(PT_SETREGS, pid, (caddr_t)&regs, 0) < 0)<br>+        m_result = false;<br>+    else<br>+        m_result = true;<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class ReadGPROperation<br>+/// @brief Implements ProcessMonitor::ReadGPR.<br>+class ReadGPROperation : public Operation<br>+{<br>+public:<br>+    ReadGPROperation(void *buf, bool &result)<br>+        : m_buf(buf), m_result(result)<br>+        { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    void *m_buf;<br>+    bool &m_result;<br>+};<br>+<br>+void<br>+ReadGPROperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    int rc;<br>+<br>+    errno = 0;<br>+    rc = PTRACE(PT_GETREGS, monitor->GetPID(), (caddr_t)m_buf, 0);<br>+    if (errno != 0)<br>+        m_result = false;<br>+    else<br>+        m_result = true;<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class ReadFPROperation<br>+/// @brief Implements ProcessMonitor::ReadFPR.<br>+class ReadFPROperation : public Operation<br>+{<br>+public:<br>+    ReadFPROperation(void *buf, bool &result)<br>+        : m_buf(buf), m_result(result)<br>+        { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    void *m_buf;<br>+    bool &m_result;<br>+};<br>+<br>+void<br>+ReadFPROperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    if (PTRACE(PT_GETFPREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0)<br>+        m_result = false;<br>+    else<br>+        m_result = true;<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class WriteGPROperation<br>+/// @brief Implements ProcessMonitor::WriteGPR.<br>+class WriteGPROperation : public Operation<br>+{<br>+public:<br>+    WriteGPROperation(void *buf, bool &result)<br>+        : m_buf(buf), m_result(result)<br>+        { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    void *m_buf;<br>+    bool &m_result;<br>+};<br>+<br>+void<br>+WriteGPROperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    if (PTRACE(PT_SETREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0)<br>+        m_result = false;<br>+    else<br>+        m_result = true;<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class WriteFPROperation<br>+/// @brief Implements ProcessMonitor::WriteFPR.<br>+class WriteFPROperation : public Operation<br>+{<br>+public:<br>+    WriteFPROperation(void *buf, bool &result)<br>+        : m_buf(buf), m_result(result)<br>+        { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    void *m_buf;<br>+    bool &m_result;<br>+};<br>+<br>+void<br>+WriteFPROperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    if (PTRACE(PT_SETFPREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0)<br>+        m_result = false;<br>+    else<br>+        m_result = true;<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class ResumeOperation<br>+/// @brief Implements ProcessMonitor::Resume.<br>+class ResumeOperation : public Operation<br>+{<br>+public:<br>+    ResumeOperation(lldb::tid_t tid, uint32_t signo, bool &result) :<br>+        m_tid(tid), m_signo(signo), m_result(result) { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    lldb::tid_t m_tid;<br>+    uint32_t m_signo;<br>+    bool &m_result;<br>+};<br>+<br>+void<br>+ResumeOperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    int data = 0;<br>+<br>+    if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)<br>+        data = m_signo;<br>+<br>+    if (PTRACE(PT_CONTINUE, m_tid, (caddr_t)1, data))<br>+        m_result = false;<br>+    else<br>+        m_result = true;<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class ResumeOperation<br>+/// @brief Implements ProcessMonitor::SingleStep.<br>+class SingleStepOperation : public Operation<br>+{<br>+public:<br>+    SingleStepOperation(lldb::tid_t tid, uint32_t signo, bool &result)<br>+        : m_tid(tid), m_signo(signo), m_result(result) { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    lldb::tid_t m_tid;<br>+    uint32_t m_signo;<br>+    bool &m_result;<br>+};<br>+<br>+void<br>+SingleStepOperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    int data = 0;<br>+<br>+    if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)<br>+        data = m_signo;<br>+<br>+    if (PTRACE(PT_STEP, m_tid, NULL, data))<br>+        m_result = false;<br>+    else<br>+        m_result = true;<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class SiginfoOperation<br>+/// @brief Implements ProcessMonitor::GetSignalInfo.<br>+class SiginfoOperation : public Operation<br>+{<br>+public:<br>+    SiginfoOperation(lldb::tid_t tid, void *info, bool &result)<br>+        : m_tid(tid), m_info(info), m_result(result) { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    lldb::tid_t m_tid;<br>+    void *m_info;<br>+    bool &m_result;<br>+};<br>+<br>+void<br>+SiginfoOperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    struct ptrace_lwpinfo plwp;<br>+<br>+    if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp)))<br>+        m_result = false;<br>+    else {<br>+        memcpy(m_info, &plwp.pl_siginfo, sizeof(siginfo_t));<br>+        m_result = true;<br>+    }<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class EventMessageOperation<br>+/// @brief Implements ProcessMonitor::GetEventMessage.<br>+class EventMessageOperation : public Operation<br>+{<br>+public:<br>+    EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result)<br>+        : m_tid(tid), m_message(message), m_result(result) { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    lldb::tid_t m_tid;<br>+    unsigned long *m_message;<br>+    bool &m_result;<br>+};<br>+<br>+void<br>+EventMessageOperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    struct ptrace_lwpinfo plwp;<br>+<br>+    if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp)))<br>+        m_result = false;<br>+    else {<br>+        if (plwp.pl_flags & PL_FLAG_FORKED) {<br>+            m_message = (unsigned long *)plwp.pl_child_pid;<br>+            m_result = true;<br>+        } else<br>+            m_result = false;<br>+    }<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class KillOperation<br>+/// @brief Implements ProcessMonitor::BringProcessIntoLimbo.<br>+class KillOperation : public Operation<br>+{<br>+public:<br>+    KillOperation(bool &result) : m_result(result) { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    bool &m_result;<br>+};<br>+<br>+void<br>+KillOperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    lldb::pid_t pid = monitor->GetPID();<br>+<br>+    if (PTRACE(PT_KILL, pid, NULL, 0))<br>+        m_result = false;<br>+    else<br>+        m_result = true;<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class KillOperation<br>+/// @brief Implements ProcessMonitor::BringProcessIntoLimbo.<br>+class DetachOperation : public Operation<br>+{<br>+public:<br>+    DetachOperation(Error &result) : m_error(result) { }<br>+<br>+    void Execute(ProcessMonitor *monitor);<br>+<br>+private:<br>+    Error &m_error;<br>+};<br>+<br>+void<br>+DetachOperation::Execute(ProcessMonitor *monitor)<br>+{<br>+    lldb::pid_t pid = monitor->GetPID();<br>+<br>+    if (PTRACE(PT_DETACH, pid, NULL, 0) < 0)<br>+        m_error.SetErrorToErrno();<br>+  <br>+}<br>+<br>+ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor)<br>+    : m_monitor(monitor)<br>+{<br>+    sem_init(&m_semaphore, 0, 0);<br>+}<br>+<br>+ProcessMonitor::OperationArgs::~OperationArgs()<br>+{<br>+    sem_destroy(&m_semaphore);<br>+}<br>+<br>+ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,<br>+                                       lldb_private::Module *module,<br>+                                       char const **argv,<br>+                                       char const **envp,<br>+                                       const char *stdin_path,<br>+                                       const char *stdout_path,<br>+                                       const char *stderr_path)<br>+    : OperationArgs(monitor),<br>+      m_module(module),<br>+      m_argv(argv),<br>+      m_envp(envp),<br>+      m_stdin_path(stdin_path),<br>+      m_stdout_path(stdout_path),<br>+      m_stderr_path(stderr_path) { }<br>+<br>+ProcessMonitor::LaunchArgs::~LaunchArgs()<br>+{ }<br>+<br>+ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor,<br>+                                       lldb::pid_t pid)<br>+    : OperationArgs(monitor), m_pid(pid) { }<br>+<br>+ProcessMonitor::AttachArgs::~AttachArgs()<br>+{ }<br>+<br>+//------------------------------------------------------------------------------<br>+/// The basic design of the ProcessMonitor is built around two threads.<br>+///<br>+/// One thread (@see SignalThread) simply blocks on a call to waitpid() looking<br>+/// for changes in the debugee state.  When a change is detected a<br>+/// ProcessMessage is sent to the associated ProcessFreeBSD instance.  This thread<br>+/// "drives" state changes in the debugger.<br>+///<br>+/// The second thread (@see OperationThread) is responsible for two things 1)<br>+/// launching or attaching to the inferior process, and then 2) servicing<br>+/// operations such as register reads/writes, stepping, etc.  See the comments<br>+/// on the Operation class for more info as to why this is needed.<br>+ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,<br>+                               Module *module,<br>+                               const char *argv[],<br>+                               const char *envp[],<br>+                               const char *stdin_path,<br>+                               const char *stdout_path,<br>+                               const char *stderr_path,<br>+                               lldb_private::Error &error)<br>+    : m_process(static_cast<ProcessFreeBSD *>(process)),<br>+      m_operation_thread(LLDB_INVALID_HOST_THREAD),<br>+      m_monitor_thread(LLDB_INVALID_HOST_THREAD),<br>+      m_pid(LLDB_INVALID_PROCESS_ID),<br>+      m_server_mutex(Mutex::eMutexTypeRecursive),<br>+      m_terminal_fd(-1),<br>+      m_client_fd(-1),<br>+      m_server_fd(-1)<br>+{<br>+    std::auto_ptr<LaunchArgs> args;<br>+<br>+    args.reset(new LaunchArgs(this, module, argv, envp,<br>+                              stdin_path, stdout_path, stderr_path));<br>+    <br>+<br>+    // Server/client descriptors.<br>+    if (!EnableIPC())<br>+    {<br>+        error.SetErrorToGenericError();<br>+        error.SetErrorString("Monitor failed to initialize.");<br>+    }<br>+<br>+    StartLaunchOpThread(args.get(), error);<br>+    if (!error.Success())<br>+        return;<br>+<br>+WAIT_AGAIN:<br>+    // Wait for the operation thread to initialize.<br>+    if (sem_wait(&args->m_semaphore))<br>+    {<br>+        if (errno == EINTR)<br>+            goto WAIT_AGAIN;<br>+        else<br>+        {<br>+            error.SetErrorToErrno();<br>+            return;<br>+        }<br>+    }<br>+<br>+    // Check that the launch was a success.<br>+    if (!args->m_error.Success())<br>+    {<br>+        StopLaunchOpThread();<br>+        error = args->m_error;<br>+        return;<br>+    }<br>+<br>+    // Finally, start monitoring the child process for change in state.<br>+    m_monitor_thread = Host::StartMonitoringChildProcess(<br>+        ProcessMonitor::MonitorCallback, this, GetPID(), true);<br>+    if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))<br>+    {<br>+        error.SetErrorToGenericError();<br>+        error.SetErrorString("Process launch failed.");<br>+        return;<br>+    }<br>+}<br>+<br>+ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,<br>+                               lldb::pid_t pid,<br>+                               lldb_private::Error &error)<br>+    : m_process(static_cast<ProcessFreeBSD *>(process)),<br>+      m_operation_thread(LLDB_INVALID_HOST_THREAD),<br>+      m_monitor_thread(LLDB_INVALID_HOST_THREAD),<br>+      m_pid(pid),<br>+      m_server_mutex(Mutex::eMutexTypeRecursive),<br>+      m_terminal_fd(-1),<br>+      m_client_fd(-1),<br>+      m_server_fd(-1)<br>+{<br>+    std::auto_ptr<AttachArgs> args;<br>+<br>+    args.reset(new AttachArgs(this, pid));<br>+<br>+    // Server/client descriptors.<br>+    if (!EnableIPC())<br>+    {<br>+        error.SetErrorToGenericError();<br>+        error.SetErrorString("Monitor failed to initialize.");<br>+    }<br>+<br>+    StartAttachOpThread(args.get(), error);<br>+    if (!error.Success())<br>+        return;<br>+<br>+WAIT_AGAIN:<br>+    // Wait for the operation thread to initialize.<br>+    if (sem_wait(&args->m_semaphore))<br>+    {<br>+        if (errno == EINTR)<br>+            goto WAIT_AGAIN;<br>+        else<br>+        {<br>+            error.SetErrorToErrno();<br>+            return;<br>+        }<br>+    }<br>+<br>+    // Check that the launch was a success.<br>+    if (!args->m_error.Success())<br>+    {<br>+        StopAttachOpThread();<br>+        error = args->m_error;<br>+        return;<br>+    }<br>+<br>+    // Finally, start monitoring the child process for change in state.<br>+    m_monitor_thread = Host::StartMonitoringChildProcess(<br>+        ProcessMonitor::MonitorCallback, this, GetPID(), true);<br>+    if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))<br>+    {<br>+        error.SetErrorToGenericError();<br>+        error.SetErrorString("Process attach failed.");<br>+        return;<br>+    }<br>+}<br>+<br>+ProcessMonitor::~ProcessMonitor()<br>+{<br>+    StopMonitor();<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+// Thread setup and tear down.<br>+void<br>+ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error)<br>+{<br>+    static const char *g_thread_name = "lldb.process.freebsd.operation";<br>+<br>+    if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread))<br>+        return;<br>+<br>+    m_operation_thread =<br>+        Host::ThreadCreate(g_thread_name, LaunchOpThread, args, &error);<br>+}<br>+<br>+void<br>+ProcessMonitor::StopLaunchOpThread()<br>+{<br>+    lldb::thread_result_t result;<br>+<br>+    if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread))<br>+        return;<br>+<br>+    Host::ThreadCancel(m_operation_thread, NULL);<br>+    Host::ThreadJoin(m_operation_thread, &result, NULL);<br>+}<br>+<br>+void *<br>+ProcessMonitor::LaunchOpThread(void *arg)<br>+{<br>+    LaunchArgs *args = static_cast<LaunchArgs*>(arg);<br>+<br>+    if (!Launch(args)) {<br>+        sem_post(&args->m_semaphore);<br>+        return NULL;<br>+    }<br>+<br>+    ServeOperation(args);<br>+    return NULL;<br>+}<br>+<br>+bool<br>+ProcessMonitor::Launch(LaunchArgs *args)<br>+{<br>+    ProcessMonitor *monitor = args->m_monitor;<br>+    ProcessFreeBSD &process = monitor->GetProcess();<br>+    const char **argv = args->m_argv;<br>+    const char **envp = args->m_envp;<br>+    const char *stdin_path = args->m_stdin_path;<br>+    const char *stdout_path = args->m_stdout_path;<br>+    const char *stderr_path = args->m_stderr_path;<br>+    lldb::pid_t pid;<br>+<br>+    lldb::ThreadSP inferior;<br>+<br>+    // Propagate the environment if one is not supplied.<br>+    if (envp == NULL || envp[0] == NULL)<br>+        envp = const_cast<const char **>(environ);<br>+<br>+    // Recognized child exit status codes.<br>+    enum {<br>+        ePtraceFailed = 1,<br>+        eDupStdinFailed,<br>+        eDupStdoutFailed,<br>+        eDupStderrFailed,<br>+        eExecFailed<br>+    };<br>+<br>+    pid = fork();<br>+<br>+    // Child process.<br>+    if (pid == 0)<br>+    {<br>+        // Trace this process.<br>+        if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0)<br>+            exit(ePtraceFailed);<br>+<br>+        // Do not inherit setgid powers.<br>+        setgid(getgid());<br>+<br>+        // Let us have our own process group.<br>+        setpgid(0, 0);<br>+<br>+        // Dup file descriptors if needed.<br>+        //<br>+        // FIXME: If two or more of the paths are the same we needlessly open<br>+        // the same file multiple times.<br>+        if (stdin_path != NULL && stdin_path[0])<br>+            if (!DupDescriptor(stdin_path, STDIN_FILENO, O_RDONLY))<br>+                exit(eDupStdinFailed);<br>+<br>+        if (stdout_path != NULL && stdout_path[0])<br>+            if (!DupDescriptor(stdout_path, STDOUT_FILENO, O_WRONLY | O_CREAT))<br>+                exit(eDupStdoutFailed);<br>+<br>+        if (stderr_path != NULL && stderr_path[0])<br>+            if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT))<br>+                exit(eDupStderrFailed);<br>+<br>+        // Execute.  We should never return.<br>+        execve(argv[0],<br>+               const_cast<char *const *>(argv),<br>+               const_cast<char *const *>(envp));<br>+        exit(eExecFailed);<br>+    }<br>+<br>+    // Wait for the child process to to trap on its call to execve.<br>+    ::pid_t wpid;<br>+    int status;<br>+    if ((wpid = waitpid(pid, &status, 0)) < 0)<br>+    {<br>+        args->m_error.SetErrorToErrno();<br>+        goto FINISH;<br>+    }<br>+    else if (WIFEXITED(status))<br>+    {<br>+        // open, dup or execve likely failed for some reason.<br>+        args->m_error.SetErrorToGenericError();<br>+        switch (WEXITSTATUS(status))<br>+        {<br>+            case ePtraceFailed: <br>+                args->m_error.SetErrorString("Child ptrace failed.");<br>+                break;<br>+            case eDupStdinFailed: <br>+                args->m_error.SetErrorString("Child open stdin failed.");<br>+                break;<br>+            case eDupStdoutFailed: <br>+                args->m_error.SetErrorString("Child open stdout failed.");<br>+                break;<br>+            case eDupStderrFailed: <br>+                args->m_error.SetErrorString("Child open stderr failed.");<br>+                break;<br>+            case eExecFailed: <br>+                args->m_error.SetErrorString("Child exec failed.");<br>+                break;<br>+            default: <br>+                args->m_error.SetErrorString("Child returned unknown exit status.");<br>+                break;<br>+        }<br>+        goto FINISH;<br>+    }<br>+    assert(WIFSTOPPED(status) && wpid == pid &&<br>+           "Could not sync with inferior process.");<br>+<br>+#ifdef notyet<br>+    // Have the child raise an event on exit.  This is used to keep the child in<br>+    // limbo until it is destroyed.<br>+    if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEEXIT) < 0)<br>+    {<br>+        args->m_error.SetErrorToErrno();<br>+        goto FINISH;<br>+    }<br>+#endif<br>+    // XXX - Release the master terminal descriptor and pass it off to the<br>+    // XXX - ProcessMonitor instance.  Similarly stash the inferior pid.<br>+    // For now just use stdin fd<br>+    monitor->m_terminal_fd = STDIN_FILENO;<br>+    monitor->m_pid = pid;<br>+<br>+    // Set the terminal fd to be in non blocking mode (it simplifies the<br>+    // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking<br>+    // descriptor to read from).<br>+    if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error))<br>+        goto FINISH;<br>+<br>+    // Update the process thread list with this new thread.<br>+    inferior.reset(new POSIXThread(process, pid));<br>+    process.GetThreadList().AddThread(inferior);<br>+<br>+    // Let our process instance know the thread has stopped.<br>+    process.SendMessage(ProcessMessage::Trace(pid));<br>+<br>+FINISH:<br>+    return args->m_error.Success();<br>+}<br>+<br>+bool<br>+ProcessMonitor::EnableIPC()<br>+{<br>+    int fd[2];<br>+<br>+    if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd))<br>+        return false;<br>+<br>+    m_client_fd = fd[0];<br>+    m_server_fd = fd[1];<br>+    return true;<br>+}<br>+<br>+void<br>+ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error)<br>+{<br>+    static const char *g_thread_name = "lldb.process.freebsd.operation";<br>+<br>+    if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread))<br>+        return;<br>+<br>+    m_operation_thread =<br>+        Host::ThreadCreate(g_thread_name, AttachOpThread, args, &error);<br>+}<br>+<br>+void<br>+ProcessMonitor::StopAttachOpThread()<br>+{<br>+    assert(!"Not implemented yet!!!");<br>+}<br>+<br>+void *<br>+ProcessMonitor::AttachOpThread(void *arg)<br>+{<br>+    AttachArgs *args = static_cast<AttachArgs*>(arg);<br>+<br>+    if (!Attach(args))<br>+        return NULL;<br>+<br>+    ServeOperation(args);<br>+    return NULL;<br>+}<br>+<br>+bool<br>+ProcessMonitor::Attach(AttachArgs *args)<br>+{<br>+    lldb::pid_t pid = args->m_pid;<br>+<br>+    ProcessMonitor *monitor = args->m_monitor;<br>+    ProcessFreeBSD &process = monitor->GetProcess();<br>+    ThreadList &tl = process.GetThreadList();<br>+    lldb::ThreadSP inferior;<br>+<br>+    if (pid <= 1)<br>+    {<br>+        args->m_error.SetErrorToGenericError();<br>+        args->m_error.SetErrorString("Attaching to process 1 is not allowed.");<br>+        goto FINISH;<br>+    }<br>+<br>+    // Attach to the requested process.<br>+    if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0)<br>+    {<br>+        args->m_error.SetErrorToErrno();<br>+        goto FINISH;<br>+    }<br>+<br>+    int status;<br>+    if ((status = waitpid(pid, NULL, 0)) < 0)<br>+    {<br>+        args->m_error.SetErrorToErrno();<br>+        goto FINISH;<br>+    }<br>+<br>+    // Update the process thread list with the attached thread.<br>+    inferior.reset(new POSIXThread(process, pid));<br>+    tl.AddThread(inferior);<br>+<br>+    // Let our process instance know the thread has stopped.<br>+    process.SendMessage(ProcessMessage::Trace(pid));<br>+<br>+ FINISH:<br>+    return args->m_error.Success();<br>+}<br>+<br>+bool<br>+ProcessMonitor::MonitorCallback(void *callback_baton,<br>+                                lldb::pid_t pid,<br>+                                bool exited,<br>+                                int signal,<br>+                                int status)<br>+{<br>+    ProcessMessage message;<br>+    ProcessMonitor *monitor = static_cast<ProcessMonitor*>(callback_baton);<br>+    ProcessFreeBSD *process = monitor->m_process;<br>+    bool stop_monitoring;<br>+    siginfo_t info;<br>+<br>+    if (!monitor->GetSignalInfo(pid, &info))<br>+        stop_monitoring = true; // pid is gone.  Bail.<br>+    else {<br>+        switch (info.si_signo)<br>+        {<br>+        case SIGTRAP:<br>+            message = MonitorSIGTRAP(monitor, &info, pid);<br>+            break;<br>+            <br>+        default:<br>+            message = MonitorSignal(monitor, &info, pid);<br>+            break;<br>+        }<br>+<br>+        process->SendMessage(message);<br>+        stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage;<br>+    }<br>+<br>+    return stop_monitoring;<br>+}<br>+<br>+ProcessMessage<br>+ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,<br>+                               const siginfo_t *info, lldb::pid_t pid)<br>+{<br>+    ProcessMessage message;<br>+<br>+    assert(info->si_signo == SIGTRAP && "Unexpected child signal!");<br>+<br>+    switch (info->si_code)<br>+    {<br>+    default:<br>+        assert(false && "Unexpected SIGTRAP code!");<br>+        break;<br>+<br>+    case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */):<br>+    {<br>+        // The inferior process is about to exit.  Maintain the process in a<br>+        // state of "limbo" until we are explicitly commanded to detach,<br>+        // destroy, resume, etc.<br>+        unsigned long data = 0;<br>+        if (!monitor->GetEventMessage(pid, &data))<br>+            data = -1;<br>+        message = ProcessMessage::Limbo(pid, (data >> 8));<br>+        break;<br>+    }<br>+<br>+    case 0:<br>+    case TRAP_TRACE:<br>+        message = ProcessMessage::Trace(pid);<br>+        break;<br>+<br>+    case SI_KERNEL:<br>+    case TRAP_BRKPT:<br>+        message = ProcessMessage::Break(pid);<br>+        break;<br>+    }<br>+<br>+    return message;<br>+}<br>+<br>+ProcessMessage<br>+ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,<br>+                              const siginfo_t *info, lldb::pid_t pid)<br>+{<br>+    ProcessMessage message;<br>+    int signo = info->si_signo;<br>+<br>+    // POSIX says that process behaviour is undefined after it ignores a SIGFPE,<br>+    // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a<br>+    // kill(2) or raise(3).  Similarly for tgkill(2) on FreeBSD.<br>+    //<br>+    // IOW, user generated signals never generate what we consider to be a<br>+    // "crash".<br>+    //<br>+    // Similarly, ACK signals generated by this monitor.<br>+    if (info->si_code == SI_USER)<br>+    {<br>+        if (info->si_pid == getpid())<br>+            return ProcessMessage::SignalDelivered(pid, signo);<br>+        else<br>+            return ProcessMessage::Signal(pid, signo);<br>+    }<br>+<br>+    if (signo == SIGSEGV) {<br>+        lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);<br>+        ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info);<br>+        return ProcessMessage::Crash(pid, reason, signo, fault_addr);<br>+    }<br>+<br>+    if (signo == SIGILL) {<br>+        lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);<br>+        ProcessMessage::CrashReason reason = GetCrashReasonForSIGILL(info);<br>+        return ProcessMessage::Crash(pid, reason, signo, fault_addr);<br>+    }<br>+<br>+    if (signo == SIGFPE) {<br>+        lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);<br>+        ProcessMessage::CrashReason reason = GetCrashReasonForSIGFPE(info);<br>+        return ProcessMessage::Crash(pid, reason, signo, fault_addr);<br>+    }<br>+<br>+    if (signo == SIGBUS) {<br>+        lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);<br>+        ProcessMessage::CrashReason reason = GetCrashReasonForSIGBUS(info);<br>+        return ProcessMessage::Crash(pid, reason, signo, fault_addr);<br>+    }<br>+<br>+    // Everything else is "normal" and does not require any special action on<br>+    // our part.<br>+    return ProcessMessage::Signal(pid, signo);<br>+}<br>+<br>+ProcessMessage::CrashReason<br>+ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info)<br>+{<br>+    ProcessMessage::CrashReason reason;<br>+    assert(info->si_signo == SIGSEGV);<br>+<br>+    reason = ProcessMessage::eInvalidCrashReason;<br>+<br>+    switch (info->si_code) <br>+    {<br>+    default:<br>+        assert(false && "unexpected si_code for SIGSEGV");<br>+        break;<br>+    case SEGV_MAPERR:<br>+        reason = ProcessMessage::eInvalidAddress;<br>+        break;<br>+    case SEGV_ACCERR:<br>+        reason = ProcessMessage::ePrivilegedAddress;<br>+        break;<br>+    }<br>+        <br>+    return reason;<br>+}<br>+<br>+ProcessMessage::CrashReason<br>+ProcessMonitor::GetCrashReasonForSIGILL(const siginfo_t *info)<br>+{<br>+    ProcessMessage::CrashReason reason;<br>+    assert(info->si_signo == SIGILL);<br>+<br>+    reason = ProcessMessage::eInvalidCrashReason;<br>+<br>+    switch (info->si_code)<br>+    {<br>+    default:<br>+        assert(false && "unexpected si_code for SIGILL");<br>+        break;<br>+    case ILL_ILLOPC:<br>+        reason = ProcessMessage::eIllegalOpcode;<br>+        break;<br>+    case ILL_ILLOPN:<br>+        reason = ProcessMessage::eIllegalOperand;<br>+        break;<br>+    case ILL_ILLADR:<br>+        reason = ProcessMessage::eIllegalAddressingMode;<br>+        break;<br>+    case ILL_ILLTRP:<br>+        reason = ProcessMessage::eIllegalTrap;<br>+        break;<br>+    case ILL_PRVOPC:<br>+        reason = ProcessMessage::ePrivilegedOpcode;<br>+        break;<br>+    case ILL_PRVREG:<br>+        reason = ProcessMessage::ePrivilegedRegister;<br>+        break;<br>+    case ILL_COPROC:<br>+        reason = ProcessMessage::eCoprocessorError;<br>+        break;<br>+    case ILL_BADSTK:<br>+        reason = ProcessMessage::eInternalStackError;<br>+        break;<br>+    }<br>+<br>+    return reason;<br>+}<br>+<br>+ProcessMessage::CrashReason<br>+ProcessMonitor::GetCrashReasonForSIGFPE(const siginfo_t *info)<br>+{<br>+    ProcessMessage::CrashReason reason;<br>+    assert(info->si_signo == SIGFPE);<br>+<br>+    reason = ProcessMessage::eInvalidCrashReason;<br>+<br>+    switch (info->si_code)<br>+    {<br>+    default:<br>+        assert(false && "unexpected si_code for SIGFPE");<br>+        break;<br>+    case FPE_INTDIV:<br>+        reason = ProcessMessage::eIntegerDivideByZero;<br>+        break;<br>+    case FPE_INTOVF:<br>+        reason = ProcessMessage::eIntegerOverflow;<br>+        break;<br>+    case FPE_FLTDIV:<br>+        reason = ProcessMessage::eFloatDivideByZero;<br>+        break;<br>+    case FPE_FLTOVF:<br>+        reason = ProcessMessage::eFloatOverflow;<br>+        break;<br>+    case FPE_FLTUND:<br>+        reason = ProcessMessage::eFloatUnderflow;<br>+        break;<br>+    case FPE_FLTRES:<br>+        reason = ProcessMessage::eFloatInexactResult;<br>+        break;<br>+    case FPE_FLTINV:<br>+        reason = ProcessMessage::eFloatInvalidOperation;<br>+        break;<br>+    case FPE_FLTSUB:<br>+        reason = ProcessMessage::eFloatSubscriptRange;<br>+        break;<br>+    }<br>+<br>+    return reason;<br>+}<br>+<br>+ProcessMessage::CrashReason<br>+ProcessMonitor::GetCrashReasonForSIGBUS(const siginfo_t *info)<br>+{<br>+    ProcessMessage::CrashReason reason;<br>+    assert(info->si_signo == SIGBUS);<br>+<br>+    reason = ProcessMessage::eInvalidCrashReason;<br>+<br>+    switch (info->si_code)<br>+    {<br>+    default:<br>+        assert(false && "unexpected si_code for SIGBUS");<br>+        break;<br>+    case BUS_ADRALN:<br>+        reason = ProcessMessage::eIllegalAlignment;<br>+        break;<br>+    case BUS_ADRERR:<br>+        reason = ProcessMessage::eIllegalAddress;<br>+        break;<br>+    case BUS_OBJERR:<br>+        reason = ProcessMessage::eHardwareError;<br>+        break;<br>+    }<br>+<br>+    return reason;<br>+}<br>+<br>+void<br>+ProcessMonitor::ServeOperation(OperationArgs *args)<br>+{<br>+    int status;<br>+    pollfd fdset;<br>+<br>+    ProcessMonitor *monitor = args->m_monitor;<br>+<br>+    fdset.fd = monitor->m_server_fd;<br>+    fdset.events = POLLIN | POLLPRI;<br>+    fdset.revents = 0;<br>+<br>+    // We are finised with the arguments and are ready to go.  Sync with the<br>+    // parent thread and start serving operations on the inferior.<br>+    sem_post(&args->m_semaphore);<br>+<br>+    for (;;)<br>+    {<br>+        if ((status = poll(&fdset, 1, -1)) < 0)<br>+        {<br>+            switch (errno)<br>+            {<br>+            default:<br>+                assert(false && "Unexpected poll() failure!");<br>+                continue;<br>+<br>+            case EINTR: continue; // Just poll again.<br>+            case EBADF: return;   // Connection terminated.<br>+            }<br>+        }<br>+<br>+        assert(status == 1 && "Too many descriptors!");<br>+<br>+        if (fdset.revents & POLLIN)<br>+        {<br>+            Operation *op = NULL;<br>+<br>+        READ_AGAIN:<br>+            if ((status = read(fdset.fd, &op, sizeof(op))) < 0)<br>+            {<br>+                // There is only one acceptable failure.<br>+                assert(errno == EINTR);<br>+                goto READ_AGAIN;<br>+            }<br>+<br>+            assert(status == sizeof(op));<br>+            op->Execute(monitor);<br>+            write(fdset.fd, &op, sizeof(op));<br>+        }<br>+    }<br>+}<br>+<br>+void<br>+ProcessMonitor::DoOperation(Operation *op)<br>+{<br>+    int status;<br>+    Operation *ack = NULL;<br>+    Mutex::Locker lock(m_server_mutex);<br>+<br>+    // FIXME: Do proper error checking here.<br>+    write(m_client_fd, &op, sizeof(op));<br>+<br>+READ_AGAIN:<br>+    if ((status = read(m_client_fd, &ack, sizeof(ack))) < 0)<br>+    {<br>+        // If interrupted by a signal handler try again.  Otherwise the monitor<br>+        // thread probably died and we have a stale file descriptor -- abort the<br>+        // operation.<br>+        if (errno == EINTR)<br>+            goto READ_AGAIN;<br>+        return;<br>+    }<br>+<br>+    assert(status == sizeof(ack));<br>+    assert(ack == op && "Invalid monitor thread response!");<br>+}<br>+<br>+size_t<br>+ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,<br>+                           Error &error)<br>+{<br>+    size_t result;<br>+    ReadOperation op(vm_addr, buf, size, error, result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+size_t<br>+ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,<br>+                            lldb_private::Error &error)<br>+{<br>+    size_t result;<br>+    WriteOperation op(vm_addr, buf, size, error, result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+bool<br>+ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value)<br>+{<br>+    bool result;<br>+    ReadRegOperation op(offset, size, value, result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+bool<br>+ProcessMonitor::WriteRegisterValue(unsigned offset, const RegisterValue &value)<br>+{<br>+    bool result;<br>+    WriteRegOperation op(offset, value, result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+bool<br>+ProcessMonitor::ReadGPR(void *buf)<br>+{<br>+    bool result;<br>+    ReadGPROperation op(buf, result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+bool<br>+ProcessMonitor::ReadFPR(void *buf)<br>+{<br>+    bool result;<br>+    ReadFPROperation op(buf, result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+bool<br>+ProcessMonitor::WriteGPR(void *buf)<br>+{<br>+    bool result;<br>+    WriteGPROperation op(buf, result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+bool<br>+ProcessMonitor::WriteFPR(void *buf)<br>+{<br>+    bool result;<br>+    WriteFPROperation op(buf, result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+bool<br>+ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo)<br>+{<br>+    bool result;<br>+    ResumeOperation op(tid, signo, result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+bool<br>+ProcessMonitor::SingleStep(lldb::tid_t tid, uint32_t signo)<br>+{<br>+    bool result;<br>+    SingleStepOperation op(tid, signo, result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+bool<br>+ProcessMonitor::BringProcessIntoLimbo()<br>+{<br>+    bool result;<br>+    KillOperation op(result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+bool<br>+ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo)<br>+{<br>+    bool result;<br>+    SiginfoOperation op(tid, siginfo, result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+bool<br>+ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message)<br>+{<br>+    bool result;<br>+    EventMessageOperation op(tid, message, result);<br>+    DoOperation(&op);<br>+    return result;<br>+}<br>+<br>+Error<br>+ProcessMonitor::Detach()<br>+{<br>+    Error result;<br>+    DetachOperation op(result);<br>+    DoOperation(&op);<br>+    StopMonitor();<br>+    return result;<br>+}    <br>+<br>+bool<br>+ProcessMonitor::DupDescriptor(const char *path, int fd, int flags)<br>+{<br>+    int target_fd = open(path, flags, 0666);<br>+<br>+    if (target_fd == -1)<br>+        return false;<br>+<br>+    return (dup2(target_fd, fd) == -1) ? false : true;<br>+}<br>+<br>+void<br>+ProcessMonitor::StopMonitoringChildProcess()<br>+{<br>+    lldb::thread_result_t thread_result;<br>+<br>+    if (IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))<br>+    {<br>+        Host::ThreadCancel(m_monitor_thread, NULL);<br>+        Host::ThreadJoin(m_monitor_thread, &thread_result, NULL);<br>+        m_monitor_thread = LLDB_INVALID_HOST_THREAD;<br>+    }<br>+}<br>+<br>+void<br>+ProcessMonitor::StopMonitor()<br>+{<br>+    StopMonitoringChildProcess();<br>+    StopLaunchOpThread();<br>+    CloseFD(m_terminal_fd);<br>+    CloseFD(m_client_fd);<br>+    CloseFD(m_server_fd);<br>+}<br>+<br>+void<br>+ProcessMonitor::CloseFD(int &fd)<br>+{<br>+    if (fd != -1)<br>+    {<br>+        close(fd);<br>+        fd = -1;<br>+    }<br>+}<br><br>Added: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h (added)<br>+++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,292 @@<br>+//===-- ProcessMonitor.h -------------------------------------- -*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_ProcessMonitor_H_<br>+#define liblldb_ProcessMonitor_H_<br>+<br>+// C Includes<br>+#include <semaphore.h><br>+#include <signal.h><br>+<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+#include "lldb/lldb-types.h"<br>+#include "lldb/Host/Mutex.h"<br>+<br>+namespace lldb_private<br>+{<br>+class Error;<br>+class Module;<br>+class Scalar;<br>+} // End lldb_private namespace.<br>+<br>+class ProcessFreeBSD;<br>+class Operation;<br>+<br>+/// @class ProcessMonitor<br>+/// @brief Manages communication with the inferior (debugee) process.<br>+///<br>+/// Upon construction, this class prepares and launches an inferior process for<br>+/// debugging.<br>+///<br>+/// Changes in the inferior process state are propagated to the associated<br>+/// ProcessFreeBSD instance by calling ProcessFreeBSD::SendMessage with the<br>+/// appropriate ProcessMessage events.<br>+///<br>+/// A purposely minimal set of operations are provided to interrogate and change<br>+/// the inferior process state.<br>+class ProcessMonitor<br>+{<br>+public:<br>+<br>+    /// Launches an inferior process ready for debugging.  Forms the<br>+    /// implementation of Process::DoLaunch.<br>+    ProcessMonitor(ProcessPOSIX *process,<br>+                   lldb_private::Module *module,<br>+                   char const *argv[],<br>+                   char const *envp[],<br>+                   const char *stdin_path,<br>+                   const char *stdout_path,<br>+                   const char *stderr_path,<br>+                   lldb_private::Error &error);<br>+<br>+    ProcessMonitor(ProcessPOSIX *process,<br>+                   lldb::pid_t pid,<br>+                   lldb_private::Error &error);<br>+<br>+    ~ProcessMonitor();<br>+<br>+    /// Provides the process number of debugee.<br>+    lldb::pid_t<br>+    GetPID() const { return m_pid; }<br>+<br>+    /// Returns the process associated with this ProcessMonitor.<br>+    ProcessFreeBSD &<br>+    GetProcess() { return *m_process; }<br>+<br>+    /// Returns a file descriptor to the controlling terminal of the inferior<br>+    /// process.<br>+    ///<br>+    /// Reads from this file descriptor yield both the standard output and<br>+    /// standard error of this debugee.  Even if stderr and stdout were<br>+    /// redirected on launch it may still happen that data is available on this<br>+    /// descriptor (if the inferior process opens /dev/tty, for example).<br>+    ///<br>+    /// If this monitor was attached to an existing process this method returns<br>+    /// -1.<br>+    int<br>+    GetTerminalFD() const { return m_terminal_fd; }<br>+<br>+    /// Reads @p size bytes from address @vm_adder in the inferior process<br>+    /// address space.<br>+    ///<br>+    /// This method is provided to implement Process::DoReadMemory.<br>+    size_t<br>+    ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,<br>+               lldb_private::Error &error);<br>+<br>+    /// Writes @p size bytes from address @p vm_adder in the inferior process<br>+    /// address space.<br>+    ///<br>+    /// This method is provided to implement Process::DoWriteMemory.<br>+    size_t<br>+    WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,<br>+                lldb_private::Error &error);<br>+<br>+    /// Reads the contents from the register identified by the given (architecture<br>+    /// dependent) offset.<br>+    ///<br>+    /// This method is provided for use by RegisterContextFreeBSD derivatives.<br>+    bool<br>+    ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value);<br>+<br>+    /// Writes the given value to the register identified by the given<br>+    /// (architecture dependent) offset.<br>+    ///<br>+    /// This method is provided for use by RegisterContextFreeBSD derivatives.<br>+    bool<br>+    WriteRegisterValue(unsigned offset, const lldb_private::RegisterValue &value);<br>+<br>+    /// Reads all general purpose registers into the specified buffer.<br>+    bool<br>+    ReadGPR(void *buf);<br>+<br>+    /// Reads all floating point registers into the specified buffer.<br>+    bool<br>+    ReadFPR(void *buf);<br>+<br>+    /// Writes all general purpose registers into the specified buffer.<br>+    bool<br>+    WriteGPR(void *buf);<br>+<br>+    /// Writes all floating point registers into the specified buffer.<br>+    bool<br>+    WriteFPR(void *buf);<br>+<br>+    /// Writes a siginfo_t structure corresponding to the given thread ID to the<br>+    /// memory region pointed to by @p siginfo.<br>+    bool<br>+    GetSignalInfo(lldb::tid_t tid, void *siginfo);<br>+<br>+    /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)<br>+    /// corresponding to the given thread IDto the memory pointed to by @p<br>+    /// message.<br>+    bool<br>+    GetEventMessage(lldb::tid_t tid, unsigned long *message);<br>+<br>+    /// Resumes the given thread.  If @p signo is anything but<br>+    /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.<br>+    bool<br>+    Resume(lldb::tid_t tid, uint32_t signo);<br>+<br>+    /// Single steps the given thread.  If @p signo is anything but<br>+    /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.<br>+    bool<br>+    SingleStep(lldb::tid_t tid, uint32_t signo);<br>+<br>+    /// Sends the inferior process a PTRACE_KILL signal.  The inferior will<br>+    /// still exists and can be interrogated.  Once resumed it will exit as<br>+    /// though it received a SIGKILL.<br>+    bool<br>+    BringProcessIntoLimbo();<br>+<br>+    lldb_private::Error<br>+    Detach();<br>+<br>+<br>+private:<br>+    ProcessFreeBSD *m_process;<br>+<br>+    lldb::thread_t m_operation_thread;<br>+    lldb::thread_t m_monitor_thread;<br>+    lldb::pid_t m_pid;<br>+<br>+<br>+    lldb_private::Mutex m_server_mutex;<br>+    int m_terminal_fd;<br>+    int m_client_fd;<br>+    int m_server_fd;<br>+<br>+    struct OperationArgs<br>+    {<br>+        OperationArgs(ProcessMonitor *monitor);<br>+<br>+        ~OperationArgs();<br>+<br>+        ProcessMonitor *m_monitor;      // The monitor performing the attach.<br>+        sem_t m_semaphore;              // Posted to once operation complete.<br>+        lldb_private::Error m_error;    // Set if process operation failed.<br>+    };<br>+<br>+    /// @class LauchArgs<br>+    ///<br>+    /// @brief Simple structure to pass data to the thread responsible for<br>+    /// launching a child process.<br>+    struct LaunchArgs : OperationArgs<br>+    {<br>+        LaunchArgs(ProcessMonitor *monitor,<br>+                   lldb_private::Module *module,<br>+                   char const **argv,<br>+                   char const **envp,<br>+                   const char *stdin_path,<br>+                   const char *stdout_path,<br>+                   const char *stderr_path);<br>+<br>+        ~LaunchArgs();<br>+<br>+        lldb_private::Module *m_module; // The executable image to launch.<br>+        char const **m_argv;            // Process arguments.<br>+        char const **m_envp;            // Process environment.<br>+        const char *m_stdin_path;       // Redirect stdin or NULL.<br>+        const char *m_stdout_path;      // Redirect stdout or NULL.<br>+        const char *m_stderr_path;      // Redirect stderr or NULL.<br>+    };<br>+<br>+    void<br>+    StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error);<br>+<br>+    void<br>+    StopLaunchOpThread();<br>+<br>+    static void *<br>+    LaunchOpThread(void *arg);<br>+<br>+    static bool<br>+    Launch(LaunchArgs *args);<br>+<br>+    bool<br>+    EnableIPC();<br>+<br>+    struct AttachArgs : OperationArgs<br>+    {<br>+        AttachArgs(ProcessMonitor *monitor,<br>+                   lldb::pid_t pid);<br>+<br>+        ~AttachArgs();<br>+<br>+        lldb::pid_t m_pid;              // pid of the process to be attached.<br>+    };<br>+<br>+    void<br>+    StartAttachOpThread(AttachArgs *args, lldb_private::Error &error);<br>+<br>+    void<br>+    StopAttachOpThread();<br>+<br>+    static void *<br>+    AttachOpThread(void *args);<br>+<br>+    static bool<br>+    Attach(AttachArgs *args);<br>+<br>+    static void<br>+    ServeOperation(OperationArgs *args);<br>+<br>+    static bool<br>+    DupDescriptor(const char *path, int fd, int flags);<br>+<br>+    static bool<br>+    MonitorCallback(void *callback_baton,<br>+                    lldb::pid_t pid, bool exited, int signal, int status);<br>+<br>+    static ProcessMessage<br>+    MonitorSIGTRAP(ProcessMonitor *monitor,<br>+                   const siginfo_t *info, lldb::pid_t pid);<br>+<br>+    static ProcessMessage<br>+    MonitorSignal(ProcessMonitor *monitor, <br>+                  const siginfo_t *info, lldb::pid_t pid);<br>+<br>+    static ProcessMessage::CrashReason<br>+    GetCrashReasonForSIGSEGV(const siginfo_t *info);<br>+<br>+    static ProcessMessage::CrashReason<br>+    GetCrashReasonForSIGILL(const siginfo_t *info);<br>+<br>+    static ProcessMessage::CrashReason<br>+    GetCrashReasonForSIGFPE(const siginfo_t *info);<br>+<br>+    static ProcessMessage::CrashReason<br>+    GetCrashReasonForSIGBUS(const siginfo_t *info);<br>+<br>+    void<br>+    DoOperation(Operation *op);<br>+<br>+    /// Stops the child monitor thread.<br>+    void<br>+    StopMonitoringChildProcess();<br>+<br>+    void <br>+    StopMonitor();<br>+<br>+    void<br>+    CloseFD(int &fd);<br>+};<br>+<br>+#endif // #ifndef liblldb_ProcessMonitor_H_<br><br>Added: lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (added)<br>+++ lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,43 @@<br>+//===-- RegisterContextFreeBSD_x86_64.h ---------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_<br>+#define liblldb_RegisterContextFreeBSD_x86_64_H_<br>+<br>+    typedef struct _GPR<br>+    {<br>+        uint64_t r15;<br>+        uint64_t r14;<br>+        uint64_t r13;<br>+        uint64_t r12;<br>+        uint64_t r11;<br>+        uint64_t r10;<br>+        uint64_t r9;<br>+        uint64_t r8;<br>+        uint64_t rdi;<br>+        uint64_t rsi;<br>+        uint64_t rbp;<br>+        uint64_t rbx;<br>+        uint64_t rdx;<br>+        uint64_t rcx;<br>+        uint64_t rax;<br>+        uint32_t trapno;<br>+        uint16_t fs;<br>+        uint16_t gs;<br>+        uint32_t err;<br>+        uint16_t es;<br>+        uint16_t ds;<br>+        uint64_t rip;<br>+        uint64_t cs;<br>+        uint64_t rflags;<br>+        uint64_t rsp;<br>+        uint64_t ss;<br>+    } GPR;<br>+<br>+#endif<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp?rev=147612&view=auto</a><br>==============================================================================<br>    (empty)<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h?rev=147612&view=auto</a><br>==============================================================================<br>    (empty)<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp?rev=147612&view=auto</a><br>==============================================================================<br>    (empty)<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h?rev=147612&view=auto</a><br>==============================================================================<br>    (empty)<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp?rev=147612&view=auto</a><br>==============================================================================<br>    (empty)<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h?rev=147612&view=auto</a><br>==============================================================================<br>    (empty)<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp?rev=147612&view=auto</a><br>==============================================================================<br>    (empty)<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h?rev=147612&view=auto</a><br>==============================================================================<br>    (empty)<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h?rev=147612&view=auto</a><br>==============================================================================<br>    (empty)<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp?rev=147612&view=auto</a><br>==============================================================================<br>    (empty)<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h?rev=147612&view=auto</a><br>==============================================================================<br>    (empty)<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp?rev=147612&view=auto</a><br>==============================================================================<br>    (empty)<br><br>Removed: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h?rev=147612&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h?rev=147612&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (original)<br>+++ lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (removed)<br>@@ -1,44 +0,0 @@<br>-//===-- RegisterContextLinux_x86_64.h ---------------------------*- C++ -*-===//<br>-//<br>-//                     The LLVM Compiler Infrastructure<br>-//<br>-// This file is distributed under the University of Illinois Open Source<br>-// License. See LICENSE.TXT for details.<br>-//<br>-//===----------------------------------------------------------------------===//<br>-<br>-#ifndef liblldb_RegisterContextLinux_x86_64_H_<br>-#define liblldb_RegisterContextLinux_x86_64_H_<br>-<br>-    typedef struct _GPR<br>-    {<br>-        uint64_t r15;<br>-        uint64_t r14;<br>-        uint64_t r13;<br>-        uint64_t r12;<br>-        uint64_t rbp;<br>-        uint64_t rbx;<br>-        uint64_t r11;<br>-        uint64_t r10;<br>-        uint64_t r9;<br>-        uint64_t r8;<br>-        uint64_t rax;<br>-        uint64_t rcx;<br>-        uint64_t rdx;<br>-        uint64_t rsi;<br>-        uint64_t rdi;<br>-        uint64_t orig_ax;<br>-        uint64_t rip;<br>-        uint64_t cs;<br>-        uint64_t rflags;<br>-        uint64_t rsp;<br>-        uint64_t ss;<br>-        uint64_t fs_base;<br>-        uint64_t gs_base;<br>-        uint64_t ds;<br>-        uint64_t es;<br>-        uint64_t fs;<br>-        uint64_t gs;<br>-    } GPR;<br>-<br>-#endif<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/Makefile<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/Makefile?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/Makefile?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/Makefile (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/Makefile Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,28 @@<br>+##===- source/Plugins/Process/POSIX/Makefile ---------------*- Makefile -*-===##<br>+# <br>+#                     The LLVM Compiler Infrastructure<br>+#<br>+# This file is distributed under the University of Illinois Open Source<br>+# License. See LICENSE.TXT for details.<br>+# <br>+##===----------------------------------------------------------------------===##<br>+<br>+LLDB_LEVEL := ../../../..<br>+LIBRARYNAME := lldbPluginProcessPOSIX<br>+BUILD_ARCHIVE = 1<br>+<br>+include $(LLDB_LEVEL)/../../Makefile.config<br>+<br>+# Extend the include path so we may locate UnwindLLDB.h<br>+CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility<br>+<br>+ifeq ($(HOST_OS),Linux)<br>+CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Linux<br>+endif<br>+<br>+ifeq ($(HOST_OS),FreeBSD)<br>+# Extend the include path so we may locate ProcessMonitor<br>+CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/FreeBSD<br>+endif<br>+<br>+include $(LLDB_LEVEL)/Makefile<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.cpp?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.cpp?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.cpp (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.cpp Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,60 @@<br>+//===-- POSIXStopInfo.cpp ---------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#include "POSIXStopInfo.h"<br>+<br>+using namespace lldb;<br>+using namespace lldb_private;<br>+<br>+<br>+//===----------------------------------------------------------------------===//<br>+// POSIXLimboStopInfo<br>+<br>+POSIXLimboStopInfo::~POSIXLimboStopInfo() { }<br>+<br>+lldb::StopReason<br>+POSIXLimboStopInfo::GetStopReason() const<br>+{<br>+    return lldb::eStopReasonTrace;<br>+}<br>+<br>+const char *<br>+POSIXLimboStopInfo::GetDescription()<br>+{<br>+    return "thread exiting";<br>+}<br>+<br>+bool<br>+POSIXLimboStopInfo::ShouldStop(Event *event_ptr)<br>+{<br>+    return true;<br>+}<br>+<br>+bool<br>+POSIXLimboStopInfo::ShouldNotify(Event *event_ptr)<br>+{<br>+    return true;<br>+}<br>+<br>+//===----------------------------------------------------------------------===//<br>+// POSIXCrashStopInfo<br>+<br>+POSIXCrashStopInfo::~POSIXCrashStopInfo() { }<br>+<br>+lldb::StopReason<br>+POSIXCrashStopInfo::GetStopReason() const<br>+{<br>+    return lldb::eStopReasonException;<br>+}<br>+<br>+const char *<br>+POSIXCrashStopInfo::GetDescription()<br>+{<br>+    return ProcessMessage::GetCrashReasonString(m_crash_reason);<br>+}<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.h (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,92 @@<br>+//===-- POSIXStopInfo.h -----------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_POSIXStopInfo_H_<br>+#define liblldb_POSIXStopInfo_H_<br>+<br>+// C Includes<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+// Project includes<br>+#include "lldb/Target/StopInfo.h"<br>+<br>+#include "POSIXThread.h"<br>+#include "ProcessMessage.h"<br>+<br>+//===----------------------------------------------------------------------===//<br>+/// @class POSIXStopInfo<br>+/// @brief Simple base class for all POSIX-specific StopInfo objects.<br>+///<br>+class POSIXStopInfo<br>+    : public lldb_private::StopInfo<br>+{<br>+public:<br>+    POSIXStopInfo(lldb_private::Thread &thread, uint32_t status)<br>+        : StopInfo(thread, status)<br>+        { }<br>+};<br>+<br>+//===----------------------------------------------------------------------===//<br>+/// @class POSIXLimboStopInfo<br>+/// @brief Represents the stop state of a process ready to exit.<br>+///<br>+class POSIXLimboStopInfo<br>+    : public POSIXStopInfo<br>+{<br>+public:<br>+    POSIXLimboStopInfo(POSIXThread &thread)<br>+        : POSIXStopInfo(thread, 0)<br>+        { }<br>+<br>+    ~POSIXLimboStopInfo();<br>+<br>+    lldb::StopReason<br>+    GetStopReason() const;<br>+<br>+    const char *<br>+    GetDescription();<br>+<br>+    bool<br>+    ShouldStop(lldb_private::Event *event_ptr);<br>+<br>+    bool<br>+    ShouldNotify(lldb_private::Event *event_ptr);<br>+};<br>+<br>+<br>+//===----------------------------------------------------------------------===//<br>+/// @class POSIXCrashStopInfo<br>+/// @brief Represents the stop state of process that is ready to crash.<br>+///<br>+class POSIXCrashStopInfo<br>+    : public POSIXStopInfo<br>+{<br>+public:<br>+    POSIXCrashStopInfo(POSIXThread &thread, uint32_t status, <br>+                  ProcessMessage::CrashReason reason)<br>+        : POSIXStopInfo(thread, status),<br>+          m_crash_reason(reason)<br>+        { }<br>+<br>+    ~POSIXCrashStopInfo();<br>+<br>+    lldb::StopReason<br>+    GetStopReason() const;<br>+<br>+    const char *<br>+    GetDescription();<br>+<br>+    ProcessMessage::CrashReason<br>+    GetCrashReason() const;<br>+<br>+private:<br>+    ProcessMessage::CrashReason m_crash_reason;<br>+};    <br>+<br>+#endif<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,352 @@<br>+//===-- POSIXThread.cpp -----------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+// C Includes<br>+#include <errno.h><br>+<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+// Project includes<br>+#include "lldb/Core/Debugger.h"<br>+#include "lldb/Host/Host.h"<br>+#include "lldb/Target/Process.h"<br>+#include "lldb/Target/StopInfo.h"<br>+#include "lldb/Target/Target.h"<br>+#include "POSIXStopInfo.h"<br>+#include "POSIXThread.h"<br>+#include "ProcessPOSIX.h"<br>+#include "ProcessPOSIXLog.h"<br>+#include "ProcessMonitor.h"<br>+#include "RegisterContext_i386.h"<br>+#include "RegisterContext_x86_64.h"<br>+#include "RegisterContextPOSIX.h"<br>+<br>+#include "UnwindLLDB.h"<br>+<br>+using namespace lldb_private;<br>+<br>+<br>+POSIXThread::POSIXThread(Process &process, lldb::tid_t tid)<br>+    : Thread(process, tid),<br>+      m_frame_ap(0)<br>+{<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));<br>+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))<br>+        log->Printf ("POSIXThread::%s (tid = %i)", __FUNCTION__, tid);<br>+}<br>+<br>+POSIXThread::~POSIXThread()<br>+{<br>+    DestroyThread();<br>+}<br>+<br>+ProcessMonitor &<br>+POSIXThread::GetMonitor()<br>+{<br>+    ProcessPOSIX &process = static_cast<ProcessPOSIX&>(GetProcess());<br>+    return process.GetMonitor();<br>+}<br>+<br>+void<br>+POSIXThread::RefreshStateAfterStop()<br>+{<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));<br>+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))<br>+        log->Printf ("POSIXThread::%s ()", __FUNCTION__);<br>+<br>+    // Let all threads recover from stopping and do any clean up based<br>+    // on the previous thread state (if any).<br>+    ProcessPOSIX &process = static_cast<ProcessPOSIX&>(GetProcess());<br>+    process.GetThreadList().RefreshStateAfterStop();<br>+}<br>+<br>+const char *<br>+POSIXThread::GetInfo()<br>+{<br>+    return NULL;<br>+}<br>+<br>+lldb::RegisterContextSP<br>+POSIXThread::GetRegisterContext()<br>+{<br>+    if (!m_reg_context_sp)<br>+    {<br>+        ArchSpec arch = Host::GetArchitecture();<br>+<br>+        switch (arch.GetCore())<br>+        {<br>+        default:<br>+            assert(false && "CPU type not supported!");<br>+            break;<br>+<br>+        case ArchSpec::eCore_x86_32_i386:<br>+        case ArchSpec::eCore_x86_32_i486:<br>+        case ArchSpec::eCore_x86_32_i486sx:<br>+            m_reg_context_sp.reset(new RegisterContext_i386(*this, 0));<br>+            break;<br>+<br>+        case ArchSpec::eCore_x86_64_x86_64:<br>+            m_reg_context_sp.reset(new RegisterContext_x86_64(*this, 0));<br>+            break;<br>+        }<br>+    }<br>+    return m_reg_context_sp;<br>+}<br>+<br>+lldb::RegisterContextSP<br>+POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)<br>+{<br>+    lldb::RegisterContextSP reg_ctx_sp;<br>+    uint32_t concrete_frame_idx = 0;<br>+<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));<br>+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))<br>+        log->Printf ("POSIXThread::%s ()", __FUNCTION__);<br>+<br>+    if (frame)<br>+        concrete_frame_idx = frame->GetConcreteFrameIndex();<br>+<br>+    if (concrete_frame_idx == 0)<br>+        reg_ctx_sp = GetRegisterContext();<br>+    else<br>+    {<br>+        assert(GetUnwinder());<br>+        reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);<br>+    }<br>+<br>+    return reg_ctx_sp;<br>+}<br>+<br>+lldb::StopInfoSP<br>+POSIXThread::GetPrivateStopReason()<br>+{<br>+    return m_stop_info;<br>+}<br>+<br>+Unwind *<br>+POSIXThread::GetUnwinder()<br>+{<br>+    if (m_unwinder_ap.get() == NULL)<br>+        m_unwinder_ap.reset(new UnwindLLDB(*this));<br>+<br>+    return m_unwinder_ap.get();<br>+}<br>+<br>+bool<br>+POSIXThread::WillResume(lldb::StateType resume_state)<br>+{<br>+    SetResumeState(resume_state);<br>+<br>+    ClearStackFrames();<br>+    if (m_unwinder_ap.get())<br>+        m_unwinder_ap->Clear();<br>+<br>+    return Thread::WillResume(resume_state);<br>+}<br>+<br>+bool<br>+POSIXThread::Resume()<br>+{<br>+    lldb::StateType resume_state = GetResumeState();<br>+    ProcessMonitor &monitor = GetMonitor();<br>+    bool status;<br>+<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));<br>+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))<br>+        log->Printf ("POSIXThread::%s ()", __FUNCTION__);<br>+<br>+    switch (resume_state)<br>+    {<br>+    default:<br>+        assert(false && "Unexpected state for resume!");<br>+        status = false;<br>+        break;<br>+<br>+    case lldb::eStateRunning:<br>+        SetState(resume_state);<br>+        status = monitor.Resume(GetID(), GetResumeSignal());<br>+        break;<br>+<br>+    case lldb::eStateStepping:<br>+        SetState(resume_state);<br>+        status = monitor.SingleStep(GetID(), GetResumeSignal());<br>+        break;<br>+    }<br>+<br>+    return status;<br>+}<br>+<br>+void<br>+POSIXThread::Notify(const ProcessMessage &message)<br>+{<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));<br>+    if (log)<br>+        log->Printf ("POSIXThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind());<br>+<br>+    switch (message.GetKind())<br>+    {<br>+    default:<br>+        assert(false && "Unexpected message kind!");<br>+        break;<br>+<br>+    case ProcessMessage::eLimboMessage:<br>+        LimboNotify(message);<br>+        break;<br>+        <br>+    case ProcessMessage::eSignalMessage:<br>+        SignalNotify(message);<br>+        break;<br>+<br>+    case ProcessMessage::eSignalDeliveredMessage:<br>+        SignalDeliveredNotify(message);<br>+        break;<br>+<br>+    case ProcessMessage::eTraceMessage:<br>+        TraceNotify(message);<br>+        break;<br>+<br>+    case ProcessMessage::eBreakpointMessage:<br>+        BreakNotify(message);<br>+        break;<br>+<br>+    case ProcessMessage::eCrashMessage:<br>+        CrashNotify(message);<br>+        break;<br>+    }<br>+}<br>+<br>+void<br>+POSIXThread::BreakNotify(const ProcessMessage &message)<br>+{<br>+    bool status;<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));<br>+<br>+    assert(GetRegisterContext());<br>+    status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint();<br>+    assert(status && "Breakpoint update failed!");<br>+<br>+    // With our register state restored, resolve the breakpoint object<br>+    // corresponding to our current PC.<br>+    assert(GetRegisterContext());<br>+    lldb::addr_t pc = GetRegisterContext()->GetPC();<br>+    if (log)<br>+        log->Printf ("POSIXThread::%s () PC=0x%8.8llx", __FUNCTION__, pc);<br>+    lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc));<br>+    assert(bp_site);<br>+    lldb::break_id_t bp_id = bp_site->GetID();<br>+    assert(bp_site && bp_site->ValidForThisThread(this));<br>+<br>+    <br>+    m_breakpoint = bp_site;<br>+    m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);<br>+}<br>+<br>+void<br>+POSIXThread::TraceNotify(const ProcessMessage &message)<br>+{<br>+    m_stop_info = StopInfo::CreateStopReasonToTrace(*this);<br>+}<br>+<br>+void<br>+POSIXThread::LimboNotify(const ProcessMessage &message)<br>+{<br>+    m_stop_info = lldb::StopInfoSP(new POSIXLimboStopInfo(*this));<br>+}<br>+<br>+void<br>+POSIXThread::SignalNotify(const ProcessMessage &message)<br>+{<br>+    int signo = message.GetSignal();<br>+<br>+    m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);<br>+    SetResumeSignal(signo);<br>+}<br>+<br>+void<br>+POSIXThread::SignalDeliveredNotify(const ProcessMessage &message)<br>+{<br>+    int signo = message.GetSignal();<br>+<br>+    // Just treat debugger generated signal events like breakpoints for now.<br>+    m_stop_info = StopInfo::CreateStopReasonToTrace(*this);<br>+    SetResumeSignal(signo);<br>+}<br>+<br>+void<br>+POSIXThread::CrashNotify(const ProcessMessage &message)<br>+{<br>+    int signo = message.GetSignal();<br>+<br>+    assert(message.GetKind() == ProcessMessage::eCrashMessage);<br>+<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));<br>+    if (log)<br>+        log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason());<br>+<br>+    m_stop_info = lldb::StopInfoSP(new POSIXCrashStopInfo(<br>+                                       *this, signo, message.GetCrashReason()));<br>+    SetResumeSignal(signo);<br>+}<br>+<br>+unsigned<br>+POSIXThread::GetRegisterIndexFromOffset(unsigned offset)<br>+{<br>+    unsigned reg;<br>+    ArchSpec arch = Host::GetArchitecture();<br>+<br>+    switch (arch.GetCore())<br>+    {<br>+    default:<br>+        assert(false && "CPU type not supported!");<br>+        break;<br>+<br>+    case ArchSpec::eCore_x86_32_i386:<br>+    case ArchSpec::eCore_x86_32_i486:<br>+    case ArchSpec::eCore_x86_32_i486sx:<br>+        reg = RegisterContext_i386::GetRegisterIndexFromOffset(offset);<br>+        break;<br>+<br>+    case ArchSpec::eCore_x86_64_x86_64:<br>+        reg = RegisterContext_x86_64::GetRegisterIndexFromOffset(offset);<br>+        break;<br>+    }<br>+    return reg;<br>+}<br>+<br>+const char *<br>+POSIXThread::GetRegisterName(unsigned reg)<br>+{<br>+    const char * name;<br>+    ArchSpec arch = Host::GetArchitecture();<br>+<br>+    switch (arch.GetCore())<br>+    {<br>+    default:<br>+        assert(false && "CPU type not supported!");<br>+        break;<br>+<br>+    case ArchSpec::eCore_x86_32_i386:<br>+    case ArchSpec::eCore_x86_32_i486:<br>+    case ArchSpec::eCore_x86_32_i486sx:<br>+        name = RegisterContext_i386::GetRegisterName(reg);<br>+        break;<br>+<br>+    case ArchSpec::eCore_x86_64_x86_64:<br>+        name = RegisterContext_x86_64::GetRegisterName(reg);<br>+        break;<br>+    }<br>+    return name;<br>+}<br>+<br>+const char *<br>+POSIXThread::GetRegisterNameFromOffset(unsigned offset)<br>+{<br>+    return GetRegisterName(GetRegisterIndexFromOffset(offset));<br>+}<br>+<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,106 @@<br>+//===-- POSIXThread.h -------------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_POSIXThread_H_<br>+#define liblldb_POSIXThread_H_<br>+<br>+// C Includes<br>+// C++ Includes<br>+#include <memory><br>+<br>+// Other libraries and framework includes<br>+#include "lldb/Target/Thread.h"<br>+#include "RegisterContextPOSIX.h"<br>+<br>+class ProcessMessage;<br>+class ProcessMonitor;<br>+class RegisterContextPOSIX;<br>+<br>+//------------------------------------------------------------------------------<br>+// @class POSIXThread<br>+// @brief Abstraction of a linux process (thread).<br>+class POSIXThread<br>+    : public lldb_private::Thread<br>+{<br>+public:<br>+    POSIXThread(lldb_private::Process &process, lldb::tid_t tid);<br>+<br>+    virtual ~POSIXThread();<br>+<br>+    void<br>+    RefreshStateAfterStop();<br>+<br>+    bool<br>+    WillResume(lldb::StateType resume_state);<br>+<br>+    const char *<br>+    GetInfo();<br>+<br>+    virtual lldb::RegisterContextSP<br>+    GetRegisterContext();<br>+<br>+    virtual lldb::RegisterContextSP<br>+    CreateRegisterContextForFrame (lldb_private::StackFrame *frame);<br>+<br>+    //--------------------------------------------------------------------------<br>+    // These static functions provide a mapping from the register offset<br>+    // back to the register index or name for use in debugging or log<br>+    // output.<br>+<br>+    static unsigned<br>+    GetRegisterIndexFromOffset(unsigned offset);<br>+<br>+    static const char *<br>+    GetRegisterName(unsigned reg);<br>+<br>+    static const char *<br>+    GetRegisterNameFromOffset(unsigned offset);<br>+<br>+    //--------------------------------------------------------------------------<br>+    // These methods form a specialized interface to linux threads.<br>+    //<br>+    bool Resume();<br>+<br>+    void Notify(const ProcessMessage &message);<br>+<br>+private:<br>+    RegisterContextPOSIX *<br>+    GetRegisterContextPOSIX ()<br>+    {<br>+        if (!m_reg_context_sp)<br>+            m_reg_context_sp = GetRegisterContext();<br>+#if 0<br>+        return dynamic_cast<RegisterContextPOSIX*>(m_reg_context_sp.get());<br>+#endif<br>+        return (RegisterContextPOSIX *)m_reg_context_sp.get();<br>+    }<br>+    <br>+    std::auto_ptr<lldb_private::StackFrame> m_frame_ap;<br>+<br>+    lldb::BreakpointSiteSP m_breakpoint;<br>+    lldb::StopInfoSP m_stop_info;<br>+<br>+    ProcessMonitor &<br>+    GetMonitor();<br>+<br>+    lldb::StopInfoSP<br>+    GetPrivateStopReason();<br>+<br>+    void BreakNotify(const ProcessMessage &message);<br>+    void TraceNotify(const ProcessMessage &message);<br>+    void LimboNotify(const ProcessMessage &message);<br>+    void SignalNotify(const ProcessMessage &message);<br>+    void SignalDeliveredNotify(const ProcessMessage &message);<br>+    void CrashNotify(const ProcessMessage &message);<br>+<br>+    lldb_private::Unwind *<br>+    GetUnwinder();<br>+};<br>+<br>+#endif // #ifndef liblldb_POSIXThread_H_<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.cpp?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.cpp?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.cpp (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.cpp Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,245 @@<br>+//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#include "ProcessMessage.h"<br>+<br>+using namespace lldb_private;<br>+<br>+const char *<br>+ProcessMessage::GetCrashReasonString(CrashReason reason)<br>+{<br>+    const char *str = NULL;<br>+<br>+    switch (reason)<br>+    {<br>+    default:<br>+        assert(false && "invalid CrashReason");<br>+        break;<br>+<br>+    case eInvalidAddress:<br>+        str = "invalid address";<br>+        break;<br>+    case ePrivilegedAddress:<br>+        str = "address access protected";<br>+        break;<br>+    case eIllegalOpcode:<br>+        str = "illegal instruction";<br>+        break;<br>+    case eIllegalOperand:<br>+        str = "illegal instruction operand";<br>+        break;<br>+    case eIllegalAddressingMode:<br>+        str = "illegal addressing mode";<br>+        break;<br>+    case eIllegalTrap:<br>+        str = "illegal trap";<br>+        break;<br>+    case ePrivilegedOpcode:<br>+        str = "privileged instruction";<br>+        break;<br>+    case ePrivilegedRegister:<br>+        str = "privileged register";<br>+        break;<br>+    case eCoprocessorError:<br>+        str = "coprocessor error";<br>+        break;<br>+    case eInternalStackError:<br>+        str = "internal stack error";<br>+        break;<br>+    case eIllegalAlignment:<br>+        str = "illegal alignment";<br>+        break;<br>+    case eIllegalAddress:<br>+        str = "illegal address";<br>+        break;<br>+    case eHardwareError:<br>+        str = "hardware error";<br>+        break;<br>+    case eIntegerDivideByZero:<br>+        str = "integer divide by zero";<br>+        break;<br>+    case eIntegerOverflow:<br>+        str = "integer overflow";<br>+        break;<br>+    case eFloatDivideByZero:<br>+        str = "floating point divide by zero";<br>+        break;<br>+    case eFloatOverflow:<br>+        str = "floating point overflow";<br>+        break;<br>+    case eFloatUnderflow:<br>+        str = "floating point underflow";<br>+        break;<br>+    case eFloatInexactResult:<br>+        str = "inexact floating point result";<br>+        break;<br>+    case eFloatInvalidOperation:<br>+        str = "invalid floating point operation";<br>+        break;<br>+    case eFloatSubscriptRange:<br>+        str = "invalid floating point subscript range";<br>+        break;<br>+    }<br>+<br>+    return str;<br>+}<br>+<br>+const char *<br>+ProcessMessage::PrintCrashReason(CrashReason reason)<br>+{<br>+#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION<br>+    // Just return the code in asci for integration builds.<br>+    chcar str[8];<br>+    sprintf(str, "%d", reason);<br>+#else<br>+    const char *str = NULL;<br>+<br>+    switch (reason)<br>+    {<br>+    default:<br>+        assert(false && "invalid CrashReason");<br>+        break;<br>+<br>+        case eInvalidCrashReason:<br>+            str = "eInvalidCrashReason";<br>+            break;<br>+<br>+        // SIGSEGV crash reasons.<br>+        case eInvalidAddress:<br>+            str = "eInvalidAddress";<br>+            break;<br>+        case ePrivilegedAddress:<br>+            str = "ePrivilegedAddress";<br>+            break;<br>+<br>+        // SIGILL crash reasons.<br>+        case eIllegalOpcode:<br>+            str = "eIllegalOpcode";<br>+            break;<br>+        case eIllegalOperand:<br>+            str = "eIllegalOperand";<br>+            break;<br>+        case eIllegalAddressingMode:<br>+            str = "eIllegalAddressingMode";<br>+            break;<br>+        case eIllegalTrap:<br>+            str = "eIllegalTrap";<br>+            break;<br>+        case ePrivilegedOpcode:<br>+            str = "ePrivilegedOpcode";<br>+            break;<br>+        case ePrivilegedRegister:<br>+            str = "ePrivilegedRegister";<br>+            break;<br>+        case eCoprocessorError:<br>+            str = "eCoprocessorError";<br>+            break;<br>+        case eInternalStackError:<br>+            str = "eInternalStackError";<br>+            break;<br>+<br>+        // SIGBUS crash reasons:<br>+        case eIllegalAlignment:<br>+            str = "eIllegalAlignment";<br>+            break;<br>+        case eIllegalAddress:<br>+            str = "eIllegalAddress";<br>+            break;<br>+        case eHardwareError:<br>+            str = "eHardwareError";<br>+            break;<br>+<br>+        // SIGFPE crash reasons:<br>+        case eIntegerDivideByZero:<br>+            str = "eIntegerDivideByZero";<br>+            break;<br>+        case eIntegerOverflow:<br>+            str = "eIntegerOverflow";<br>+            break;<br>+        case eFloatDivideByZero:<br>+            str = "eFloatDivideByZero";<br>+            break;<br>+        case eFloatOverflow:<br>+            str = "eFloatOverflow";<br>+            break;<br>+        case eFloatUnderflow:<br>+            str = "eFloatUnderflow";<br>+            break;<br>+        case eFloatInexactResult:<br>+            str = "eFloatInexactResult";<br>+            break;<br>+        case eFloatInvalidOperation:<br>+            str = "eFloatInvalidOperation";<br>+            break;<br>+        case eFloatSubscriptRange:<br>+            str = "eFloatSubscriptRange";<br>+            break;<br>+    }<br>+#endif<br>+<br>+    return str;<br>+}<br>+<br>+const char *<br>+ProcessMessage::PrintCrashReason() const<br>+{<br>+    return PrintCrashReason(m_crash_reason);<br>+}<br>+<br>+const char *<br>+ProcessMessage::PrintKind(Kind kind)<br>+{<br>+#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION<br>+    // Just return the code in asci for integration builds.<br>+    chcar str[8];<br>+    sprintf(str, "%d", reason);<br>+#else<br>+    const char *str = NULL;<br>+<br>+    switch (kind)<br>+    {<br>+    default:<br>+        assert(false && "invalid Kind");<br>+        break;<br>+<br>+    case eInvalidMessage:<br>+        str = "eInvalidMessage";<br>+        break;<br>+    case eExitMessage:<br>+        str = "eExitMessage";<br>+        break;<br>+    case eLimboMessage:<br>+        str = "eLimboMessage";<br>+        break;<br>+    case eSignalMessage:<br>+        str = "eSignalMessage";<br>+        break;<br>+    case eSignalDeliveredMessage:<br>+        str = "eSignalDeliveredMessage";<br>+        break;<br>+    case eTraceMessage:<br>+        str = "eTraceMessage";<br>+        break;<br>+    case eBreakpointMessage:<br>+        str = "eBreakpointMessage";<br>+        break;<br>+    case eCrashMessage:<br>+        str = "eCrashMessage";<br>+        break;<br>+    }<br>+#endif<br>+<br>+    return str;<br>+}<br>+<br>+const char *<br>+ProcessMessage::PrintKind() const<br>+{<br>+    return PrintKind(m_kind);<br>+}<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.h (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,171 @@<br>+//===-- ProcessMessage.h ----------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_ProcessMessage_H_<br>+#define liblldb_ProcessMessage_H_<br>+<br>+#include <cassert><br>+<br>+#include "lldb/lldb-defines.h"<br>+#include "lldb/lldb-types.h"<br>+<br>+class ProcessMessage<br>+{<br>+public:<br>+<br>+    /// The type of signal this message can correspond to.<br>+    enum Kind<br>+    {<br>+        eInvalidMessage,<br>+        eExitMessage,<br>+        eLimboMessage,<br>+        eSignalMessage,<br>+        eSignalDeliveredMessage,<br>+        eTraceMessage,<br>+        eBreakpointMessage,<br>+        eCrashMessage<br>+    };<br>+<br>+    enum CrashReason<br>+    {<br>+        eInvalidCrashReason,<br>+<br>+        // SIGSEGV crash reasons.<br>+        eInvalidAddress,<br>+        ePrivilegedAddress,<br>+<br>+        // SIGILL crash reasons.<br>+        eIllegalOpcode,<br>+        eIllegalOperand,<br>+        eIllegalAddressingMode,<br>+        eIllegalTrap,<br>+        ePrivilegedOpcode,<br>+        ePrivilegedRegister,<br>+        eCoprocessorError,<br>+        eInternalStackError,<br>+<br>+        // SIGBUS crash reasons,<br>+        eIllegalAlignment,<br>+        eIllegalAddress,<br>+        eHardwareError,<br>+<br>+        // SIGFPE crash reasons,<br>+        eIntegerDivideByZero,<br>+        eIntegerOverflow,<br>+        eFloatDivideByZero,<br>+        eFloatOverflow,<br>+        eFloatUnderflow,<br>+        eFloatInexactResult,<br>+        eFloatInvalidOperation,<br>+        eFloatSubscriptRange<br>+    };<br>+<br>+    ProcessMessage()<br>+        : m_tid(LLDB_INVALID_PROCESS_ID),<br>+          m_kind(eInvalidMessage),<br>+          m_crash_reason(eInvalidCrashReason),<br>+          m_status(0),<br>+          m_addr(0) { }<br>+<br>+    Kind GetKind() const { return m_kind; }<br>+<br>+    lldb::tid_t GetTID() const { return m_tid; }<br>+<br>+    /// Indicates that the thread @p tid is about to exit with status @p status.<br>+    static ProcessMessage Limbo(lldb::tid_t tid, int status) {<br>+        return ProcessMessage(tid, eLimboMessage, status);<br>+    }<br>+<br>+    /// Indicates that the thread @p tid had the signal @p signum delivered.<br>+    static ProcessMessage Signal(lldb::tid_t tid, int signum) {<br>+        return ProcessMessage(tid, eSignalMessage, signum);<br>+    }<br>+<br>+    /// Indicates that a signal @p signum generated by the debugging process was<br>+    /// delivered to the thread @p tid.<br>+    static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) {<br>+        return ProcessMessage(tid, eSignalDeliveredMessage, signum);<br>+    }<br>+<br>+    /// Indicates that the thread @p tid encountered a trace point.<br>+    static ProcessMessage Trace(lldb::tid_t tid) {<br>+        return ProcessMessage(tid, eTraceMessage);<br>+    }<br>+<br>+    /// Indicates that the thread @p tid encountered a break point.<br>+    static ProcessMessage Break(lldb::tid_t tid) {<br>+        return ProcessMessage(tid, eBreakpointMessage);<br>+    }<br>+<br>+    /// Indicates that the thread @p tid crashed.<br>+    static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason,<br>+                                int signo, lldb::addr_t fault_addr) {<br>+        ProcessMessage message(pid, eCrashMessage, signo, fault_addr);<br>+        message.m_crash_reason = reason;<br>+        return message;<br>+    }<br>+<br>+    int GetExitStatus() const {<br>+        assert(GetKind() == eExitMessage || GetKind() == eLimboMessage);<br>+        return m_status;<br>+    }<br>+<br>+    int GetSignal() const {<br>+        assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage ||<br>+               GetKind() == eSignalDeliveredMessage);<br>+        return m_status;<br>+    }<br>+<br>+    int GetStopStatus() const {<br>+        assert(GetKind() == eSignalMessage);<br>+        return m_status;<br>+    }<br>+<br>+    CrashReason GetCrashReason() const {<br>+        assert(GetKind() == eCrashMessage);<br>+        return m_crash_reason;<br>+    }<br>+<br>+    lldb::addr_t GetFaultAddress() const {<br>+        assert(GetKind() == eCrashMessage);<br>+        return m_addr;<br>+    }<br>+<br>+    static const char *<br>+    GetCrashReasonString(CrashReason reason);<br>+<br>+    const char *<br>+    PrintCrashReason() const;<br>+<br>+    static const char *<br>+    PrintCrashReason(CrashReason reason);<br>+<br>+    const char *<br>+    PrintKind() const;<br>+<br>+    static const char *<br>+    PrintKind(Kind);<br>+<br>+private:<br>+    ProcessMessage(lldb::tid_t tid, Kind kind, <br>+                   int status = 0, lldb::addr_t addr = 0)<br>+        : m_tid(tid),<br>+          m_kind(kind),<br>+          m_crash_reason(eInvalidCrashReason),<br>+          m_status(status),<br>+          m_addr(addr) { }<br>+<br>+    lldb::tid_t m_tid;<br>+    Kind        m_kind         : 8;<br>+    CrashReason m_crash_reason : 8;<br>+    int m_status;<br>+    lldb::addr_t m_addr;<br>+};<br>+<br>+#endif // #ifndef liblldb_ProcessMessage_H_<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,594 @@<br>+//===-- ProcessPOSIX.cpp ----------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+// C Includes<br>+#include <errno.h><br>+<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+#include "lldb/Core/PluginManager.h"<br>+#include "lldb/Core/State.h"<br>+#include "lldb/Host/Host.h"<br>+#include "lldb/Symbol/ObjectFile.h"<br>+#include "lldb/Target/DynamicLoader.h"<br>+#include "lldb/Target/Target.h"<br>+<br>+#include "ProcessPOSIX.h"<br>+#include "ProcessPOSIXLog.h"<br>+#include "Plugins/Process/Utility/InferiorCallPOSIX.h"<br>+#include "ProcessMonitor.h"<br>+#include "POSIXThread.h"<br>+<br>+using namespace lldb;<br>+using namespace lldb_private;<br>+<br>+//------------------------------------------------------------------------------<br>+// Static functions.<br>+#if 0<br>+Process*<br>+ProcessPOSIX::CreateInstance(Target& target, Listener &listener)<br>+{<br>+    return new ProcessPOSIX(target, listener);<br>+}<br>+<br>+<br>+void<br>+ProcessPOSIX::Initialize()<br>+{<br>+    static bool g_initialized = false;<br>+<br>+    if (!g_initialized)<br>+    {<br>+        g_initialized = true;<br>+        PluginManager::RegisterPlugin(GetPluginNameStatic(),<br>+                                      GetPluginDescriptionStatic(),<br>+                                      CreateInstance);<br>+<br>+        Log::Callbacks log_callbacks = {<br>+            ProcessPOSIXLog::DisableLog,<br>+            ProcessPOSIXLog::EnableLog,<br>+            ProcessPOSIXLog::ListLogCategories<br>+        };<br>+        <br>+        Log::RegisterLogChannel (ProcessPOSIX::GetPluginNameStatic(), log_callbacks);<br>+    }<br>+}<br>+#endif<br>+<br>+//------------------------------------------------------------------------------<br>+// Constructors and destructors.<br>+<br>+ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener)<br>+    : Process(target, listener),<br>+      m_monitor(NULL),<br>+      m_module(NULL),<br>+      m_in_limbo(false),<br>+      m_exit_now(false)<br>+{<br>+    // FIXME: Putting this code in the ctor and saving the byte order in a<br>+    // member variable is a hack to avoid const qual issues in GetByteOrder.<br>+    ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();<br>+    m_byte_order = obj_file->GetByteOrder();<br>+}<br>+<br>+ProcessPOSIX::~ProcessPOSIX()<br>+{<br>+    delete m_monitor;<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+// Process protocol.<br>+<br>+bool<br>+ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name)<br>+{<br>+    // For now we are just making sure the file exists for a given module<br>+    ModuleSP exe_module_sp(target.GetExecutableModule());<br>+    if (exe_module_sp.get())<br>+        return exe_module_sp->GetFileSpec().Exists();<br>+    return false;<br>+}<br>+<br>+Error<br>+ProcessPOSIX::DoAttachToProcessWithID(lldb::pid_t pid)<br>+{<br>+    Error error;<br>+    assert(m_monitor == NULL);<br>+<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));<br>+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))<br>+        log->Printf ("ProcessPOSIX::%s(pid = %i)", __FUNCTION__, GetID());<br>+<br>+    m_monitor = new ProcessMonitor(this, pid, error);<br>+<br>+    if (!error.Success())<br>+        return error;<br>+<br>+    SetID(pid);<br>+    return error;<br>+}<br>+<br>+Error<br>+ProcessPOSIX::WillLaunch(Module* module)<br>+{<br>+    Error error;<br>+    return error;<br>+}<br>+<br>+const char *<br>+ProcessPOSIX::GetFilePath(<br>+    const lldb_private::ProcessLaunchInfo::FileAction *file_action,<br>+    const char *default_path)<br>+{<br>+    const char *pts_name = "/dev/pts/";<br>+    const char *path = NULL;<br>+<br>+    if (file_action)<br>+    {<br>+        if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)<br>+            path = file_action->GetPath();<br>+            // By default the stdio paths passed in will be pseudo-terminal<br>+            // (/dev/pts). If so, convert to using a different default path<br>+            // instead to redirect I/O to the debugger console. This should<br>+            //  also handle user overrides to /dev/null or a different file.<br>+            if (::strncmp(path, pts_name, ::strlen(pts_name)) == 0)<br>+                path = default_path;<br>+    }<br>+<br>+    return path;<br>+}<br>+<br>+Error<br>+ProcessPOSIX::DoLaunch (Module *module,<br>+                       const ProcessLaunchInfo &launch_info)<br>+{<br>+    Error error;<br>+    assert(m_monitor == NULL);<br>+<br>+    SetPrivateState(eStateLaunching);<br>+<br>+    const lldb_private::ProcessLaunchInfo::FileAction *file_action;<br>+<br>+    // Default of NULL will mean to use existing open file descriptors<br>+    const char *stdin_path = NULL;<br>+    const char *stdout_path = NULL;<br>+    const char *stderr_path = NULL;<br>+    <br>+    file_action = launch_info.GetFileActionForFD (STDIN_FILENO);<br>+    stdin_path = GetFilePath(file_action, stdin_path);<br>+<br>+    file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);<br>+    stdout_path = GetFilePath(file_action, stdout_path);<br>+<br>+    file_action = launch_info.GetFileActionForFD (STDERR_FILENO);<br>+    stderr_path = GetFilePath(file_action, stderr_path);<br>+<br>+    m_monitor = new ProcessMonitor (this, <br>+                                    module,<br>+                                    launch_info.GetArguments().GetConstArgumentVector(), <br>+                                    launch_info.GetEnvironmentEntries().GetConstArgumentVector(),<br>+                                    stdin_path, <br>+                                    stdout_path, <br>+                                    stderr_path,<br>+                                    error);<br>+<br>+    m_module = module;<br>+<br>+    if (!error.Success())<br>+        return error;<br>+<br>+    SetID(m_monitor->GetPID());<br>+    return error;<br>+}<br>+<br>+void<br>+ProcessPOSIX::DidLaunch()<br>+{<br>+}<br>+<br>+Error<br>+ProcessPOSIX::DoResume()<br>+{<br>+    StateType state = GetPrivateState();<br>+<br>+    assert(state == eStateStopped || state == eStateCrashed);<br>+<br>+    // We are about to resume a thread that will cause the process to exit so<br>+    // set our exit status now.  Do not change our state if the inferior<br>+    // crashed.<br>+    if (state == eStateStopped) <br>+    {<br>+        if (m_in_limbo)<br>+            SetExitStatus(m_exit_status, NULL);<br>+        else<br>+            SetPrivateState(eStateRunning);<br>+    }<br>+<br>+    bool did_resume = false;<br>+    uint32_t thread_count = m_thread_list.GetSize(false);<br>+    for (uint32_t i = 0; i < thread_count; ++i)<br>+    {<br>+        POSIXThread *thread = static_cast<POSIXThread*>(<br>+            m_thread_list.GetThreadAtIndex(i, false).get());<br>+        did_resume = thread->Resume() || did_resume;<br>+    }<br>+    assert(did_resume && "Process resume failed!");<br>+<br>+    return Error();<br>+}<br>+<br>+addr_t<br>+ProcessPOSIX::GetImageInfoAddress()<br>+{<br>+    Target *target = &GetTarget();<br>+    ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();<br>+    Address addr = obj_file->GetImageInfoAddress();<br>+<br>+    if (addr.IsValid()) <br>+        return addr.GetLoadAddress(target);<br>+    else<br>+        return LLDB_INVALID_ADDRESS;<br>+}<br>+<br>+Error<br>+ProcessPOSIX::DoHalt(bool &caused_stop)<br>+{<br>+    Error error;<br>+<br>+    if (IsStopped())<br>+    {<br>+        caused_stop = false;<br>+    }<br>+    else if (kill(GetID(), SIGSTOP))<br>+    {<br>+        caused_stop = false;<br>+        error.SetErrorToErrno();<br>+    }<br>+    else<br>+    {<br>+        caused_stop = true;<br>+    }<br>+<br>+    return error;<br>+}<br>+<br>+Error<br>+ProcessPOSIX::DoDetach()<br>+{<br>+    Error error;<br>+<br>+    error = m_monitor->Detach();<br>+    if (error.Success())<br>+        SetPrivateState(eStateDetached);<br>+<br>+    return error;<br>+}<br>+<br>+Error<br>+ProcessPOSIX::DoSignal(int signal)<br>+{<br>+    Error error;<br>+<br>+    if (kill(GetID(), signal))<br>+        error.SetErrorToErrno();<br>+<br>+    return error;<br>+}<br>+<br>+Error<br>+ProcessPOSIX::DoDestroy()<br>+{<br>+    Error error;<br>+<br>+    if (!HasExited())<br>+    {<br>+        // Drive the exit event to completion (do not keep the inferior in<br>+        // limbo).<br>+        m_exit_now = true;<br>+<br>+        if (kill(m_monitor->GetPID(), SIGKILL) && error.Success())<br>+        {<br>+            error.SetErrorToErrno();<br>+            return error;<br>+        }<br>+<br>+        SetPrivateState(eStateExited);<br>+    }<br>+<br>+    return error;<br>+}<br>+<br>+void<br>+ProcessPOSIX::SendMessage(const ProcessMessage &message)<br>+{<br>+    Mutex::Locker lock(m_message_mutex);<br>+<br>+    switch (message.GetKind())<br>+    {<br>+    default:<br>+        assert(false && "Unexpected process message!");<br>+        break;<br>+<br>+    case ProcessMessage::eInvalidMessage:<br>+        return;<br>+<br>+    case ProcessMessage::eLimboMessage:<br>+        m_in_limbo = true;<br>+        m_exit_status = message.GetExitStatus();<br>+        if (m_exit_now)<br>+        {<br>+            SetPrivateState(eStateExited);<br>+            m_monitor->Detach();<br>+        }<br>+        else<br>+            SetPrivateState(eStateStopped);<br>+        break;<br>+<br>+    case ProcessMessage::eExitMessage:<br>+        m_exit_status = message.GetExitStatus();<br>+        SetExitStatus(m_exit_status, NULL);<br>+        break;<br>+<br>+    case ProcessMessage::eTraceMessage:<br>+    case ProcessMessage::eBreakpointMessage:<br>+        SetPrivateState(eStateStopped);<br>+        break;<br>+<br>+    case ProcessMessage::eSignalMessage:<br>+    case ProcessMessage::eSignalDeliveredMessage:<br>+        SetPrivateState(eStateStopped);<br>+        break;<br>+<br>+    case ProcessMessage::eCrashMessage:<br>+        SetPrivateState(eStateCrashed);<br>+        break;<br>+    }<br>+<br>+    m_message_queue.push(message);<br>+}<br>+<br>+void<br>+ProcessPOSIX::RefreshStateAfterStop()<br>+{<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));<br>+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))<br>+        log->Printf ("ProcessPOSIX::%s()", __FUNCTION__);<br>+<br>+    Mutex::Locker lock(m_message_mutex);<br>+    if (m_message_queue.empty())<br>+        return;<br>+<br>+    ProcessMessage &message = m_message_queue.front();<br>+<br>+    // Resolve the thread this message corresponds to and pass it along.<br>+    // FIXME: we're really dealing with the pid here.  This should get<br>+    // fixed when this code is fixed to handle multiple threads.<br>+    lldb::tid_t tid = message.GetTID();<br>+    if (log)<br>+        log->Printf ("ProcessPOSIX::%s() pid = %i", __FUNCTION__, tid);<br>+    POSIXThread *thread = static_cast<POSIXThread*>(<br>+        GetThreadList().FindThreadByID(tid, false).get());<br>+<br>+    assert(thread);<br>+    thread->Notify(message);<br>+<br>+    m_message_queue.pop();<br>+}<br>+<br>+bool<br>+ProcessPOSIX::IsAlive()<br>+{<br>+    StateType state = GetPrivateState();<br>+    return state != eStateDetached && state != eStateExited && state != eStateInvalid;<br>+}<br>+<br>+size_t<br>+ProcessPOSIX::DoReadMemory(addr_t vm_addr,<br>+                           void *buf, size_t size, Error &error)<br>+{<br>+    assert(m_monitor);<br>+    return m_monitor->ReadMemory(vm_addr, buf, size, error);<br>+}<br>+<br>+size_t<br>+ProcessPOSIX::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,<br>+                            Error &error)<br>+{<br>+    assert(m_monitor);<br>+    return m_monitor->WriteMemory(vm_addr, buf, size, error);<br>+}<br>+<br>+addr_t<br>+ProcessPOSIX::DoAllocateMemory(size_t size, uint32_t permissions,<br>+                               Error &error)<br>+{<br>+    addr_t allocated_addr = LLDB_INVALID_ADDRESS;<br>+<br>+    unsigned prot = 0;<br>+    if (permissions & lldb::ePermissionsReadable)<br>+        prot |= eMmapProtRead;<br>+    if (permissions & lldb::ePermissionsWritable)<br>+        prot |= eMmapProtWrite;<br>+    if (permissions & lldb::ePermissionsExecutable)<br>+        prot |= eMmapProtExec;<br>+<br>+    if (InferiorCallMmap(this, allocated_addr, 0, size, prot,<br>+                         eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {<br>+        m_addr_to_mmap_size[allocated_addr] = size;<br>+        error.Clear();<br>+    } else {<br>+        allocated_addr = LLDB_INVALID_ADDRESS;<br>+        error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));<br>+    }<br>+<br>+    return allocated_addr;<br>+}<br>+<br>+Error<br>+ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr)<br>+{<br>+    Error error;<br>+    MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);<br>+    if (pos != m_addr_to_mmap_size.end() &&<br>+        InferiorCallMunmap(this, addr, pos->second))<br>+        m_addr_to_mmap_size.erase (pos);<br>+    else<br>+        error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr);<br>+<br>+    return error;<br>+}<br>+<br>+size_t<br>+ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)<br>+{<br>+    static const uint8_t g_i386_opcode[] = { 0xCC };<br>+<br>+    ArchSpec arch = GetTarget().GetArchitecture();<br>+    const uint8_t *opcode = NULL;<br>+    size_t opcode_size = 0;<br>+<br>+    switch (arch.GetCore())<br>+    {<br>+    default:<br>+        assert(false && "CPU type not supported!");<br>+        break;<br>+<br>+    case ArchSpec::eCore_x86_32_i386:<br>+    case ArchSpec::eCore_x86_64_x86_64:<br>+        opcode = g_i386_opcode;<br>+        opcode_size = sizeof(g_i386_opcode);<br>+        break;<br>+    }<br>+<br>+    bp_site->SetTrapOpcode(opcode, opcode_size);<br>+    return opcode_size;<br>+}<br>+<br>+Error<br>+ProcessPOSIX::EnableBreakpoint(BreakpointSite *bp_site)<br>+{<br>+    return EnableSoftwareBreakpoint(bp_site);<br>+}<br>+<br>+Error<br>+ProcessPOSIX::DisableBreakpoint(BreakpointSite *bp_site)<br>+{<br>+    return DisableSoftwareBreakpoint(bp_site);<br>+}<br>+<br>+uint32_t<br>+ProcessPOSIX::UpdateThreadListIfNeeded()<br>+{<br>+    // Do not allow recursive updates.<br>+    return m_thread_list.GetSize(false);<br>+}<br>+<br>+uint32_t<br>+ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)<br>+{<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));<br>+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))<br>+        log->Printf ("ProcessPOSIX::%s() (pid = %i)", __FUNCTION__, GetID());<br>+<br>+    // Update the process thread list with this new thread.<br>+    // FIXME: We should be using tid, not pid.<br>+    assert(m_monitor);<br>+    ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));<br>+    if (!thread_sp)<br>+        thread_sp.reset(new POSIXThread(*this, GetID()));<br>+<br>+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))<br>+        log->Printf ("ProcessPOSIX::%s() updated pid = %i", __FUNCTION__, GetID());<br>+    new_thread_list.AddThread(thread_sp);<br>+<br>+    return new_thread_list.GetSize(false);<br>+}<br>+<br>+ByteOrder<br>+ProcessPOSIX::GetByteOrder() const<br>+{<br>+    // FIXME: We should be able to extract this value directly.  See comment in<br>+    // ProcessPOSIX().<br>+    return m_byte_order;<br>+}<br>+<br>+size_t<br>+ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error)<br>+{<br>+    ssize_t status;<br>+    if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) <br>+    {<br>+        error.SetErrorToErrno();<br>+        return 0;<br>+    }<br>+    return status;<br>+}<br>+<br>+size_t<br>+ProcessPOSIX::GetSTDOUT(char *buf, size_t len, Error &error)<br>+{<br>+    ssize_t bytes_read;<br>+<br>+    // The terminal file descriptor is always in non-block mode.<br>+    if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0) <br>+    {<br>+        if (errno != EAGAIN)<br>+            error.SetErrorToErrno();<br>+        return 0;<br>+    }<br>+    return bytes_read;<br>+}<br>+<br>+size_t<br>+ProcessPOSIX::GetSTDERR(char *buf, size_t len, Error &error)<br>+{<br>+    return GetSTDOUT(buf, len, error);<br>+}<br>+<br>+UnixSignals &<br>+ProcessPOSIX::GetUnixSignals()<br>+{<br>+    return m_signals;<br>+}<br>+<br>+//------------------------------------------------------------------------------<br>+// Utility functions.<br>+<br>+bool<br>+ProcessPOSIX::HasExited()<br>+{<br>+    switch (GetPrivateState())<br>+    {<br>+    default:<br>+        break;<br>+<br>+    case eStateDetached:<br>+    case eStateExited:<br>+        return true;<br>+    }<br>+<br>+    return false;<br>+}<br>+<br>+bool<br>+ProcessPOSIX::IsStopped()<br>+{<br>+    switch (GetPrivateState())<br>+    {<br>+    default:<br>+        break;<br>+<br>+    case eStateStopped:<br>+    case eStateCrashed:<br>+    case eStateSuspended:<br>+        return true;<br>+    }<br>+<br>+    return false;<br>+}<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,180 @@<br>+//===-- ProcessPOSIX.h ------------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_ProcessPOSIX_H_<br>+#define liblldb_ProcessPOSIX_H_<br>+<br>+// C Includes<br>+<br>+// C++ Includes<br>+#include <queue><br>+<br>+// Other libraries and framework includes<br>+#include "lldb/Target/Process.h"<br>+#include "lldb/Target/UnixSignals.h"<br>+#include "ProcessMessage.h"<br>+<br>+class ProcessMonitor;<br>+<br>+class ProcessPOSIX :<br>+    public lldb_private::Process<br>+{<br>+public:<br>+<br>+    //------------------------------------------------------------------<br>+    // Constructors and destructors<br>+    //------------------------------------------------------------------<br>+    ProcessPOSIX(lldb_private::Target& target,<br>+                 lldb_private::Listener &listener);<br>+<br>+    virtual<br>+    ~ProcessPOSIX();<br>+<br>+    //------------------------------------------------------------------<br>+    // Process protocol.<br>+    //------------------------------------------------------------------<br>+    virtual bool<br>+    CanDebug(lldb_private::Target &target, bool plugin_specified_by_name);<br>+<br>+    virtual lldb_private::Error<br>+    WillLaunch(lldb_private::Module *module);<br>+<br>+    virtual lldb_private::Error<br>+    DoAttachToProcessWithID(lldb::pid_t pid);<br>+<br>+    virtual lldb_private::Error<br>+    DoLaunch (lldb_private::Module *exe_module, <br>+              const lldb_private::ProcessLaunchInfo &launch_info);<br>+<br>+    virtual void<br>+    DidLaunch();<br>+<br>+    virtual lldb_private::Error<br>+    DoResume();<br>+<br>+    virtual lldb_private::Error<br>+    DoHalt(bool &caused_stop);<br>+<br>+    virtual lldb_private::Error<br>+    DoDetach();<br>+<br>+    virtual lldb_private::Error<br>+    DoSignal(int signal);<br>+<br>+    virtual lldb_private::Error<br>+    DoDestroy();<br>+<br>+    virtual void<br>+    RefreshStateAfterStop();<br>+<br>+    virtual bool<br>+    IsAlive();<br>+<br>+    virtual size_t<br>+    DoReadMemory(lldb::addr_t vm_addr,<br>+                 void *buf,<br>+                 size_t size,<br>+                 lldb_private::Error &error);<br>+<br>+    virtual size_t<br>+    DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,<br>+                  lldb_private::Error &error);<br>+<br>+    virtual lldb::addr_t<br>+    DoAllocateMemory(size_t size, uint32_t permissions,<br>+                     lldb_private::Error &error);<br>+<br>+    virtual lldb_private::Error<br>+    DoDeallocateMemory(lldb::addr_t ptr);<br>+<br>+    virtual size_t<br>+    GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);<br>+<br>+    virtual lldb_private::Error<br>+    EnableBreakpoint(lldb_private::BreakpointSite *bp_site);<br>+<br>+    virtual lldb_private::Error<br>+    DisableBreakpoint(lldb_private::BreakpointSite *bp_site);<br>+<br>+    virtual uint32_t<br>+    UpdateThreadListIfNeeded();<br>+<br>+    virtual uint32_t<br>+    UpdateThreadList(lldb_private::ThreadList &old_thread_list, <br>+                     lldb_private::ThreadList &new_thread_list) = 0;<br>+<br>+    virtual lldb::ByteOrder<br>+    GetByteOrder() const;<br>+<br>+    virtual lldb::addr_t<br>+    GetImageInfoAddress();<br>+<br>+    virtual size_t<br>+    PutSTDIN(const char *buf, size_t len, lldb_private::Error &error);<br>+<br>+    virtual size_t<br>+    GetSTDOUT(char *buf, size_t len, lldb_private::Error &error);<br>+<br>+    virtual size_t<br>+    GetSTDERR(char *buf, size_t len, lldb_private::Error &error);<br>+<br>+    //--------------------------------------------------------------------------<br>+    // ProcessPOSIX internal API.<br>+<br>+    /// Registers the given message with this process.<br>+    void SendMessage(const ProcessMessage &message);<br>+<br>+    ProcessMonitor &<br>+    GetMonitor() { assert(m_monitor); return *m_monitor; }<br>+<br>+    lldb_private::UnixSignals &<br>+    GetUnixSignals();<br>+<br>+    const char *<br>+    GetFilePath(const lldb_private::ProcessLaunchInfo::FileAction *file_action,<br>+                const char *default_path);<br>+<br>+protected:<br>+    /// Target byte order.<br>+    lldb::ByteOrder m_byte_order;<br>+<br>+    /// Process monitor;<br>+    ProcessMonitor *m_monitor;<br>+<br>+    /// The module we are executing.<br>+    lldb_private::Module *m_module;<br>+<br>+    /// Message queue notifying this instance of inferior process state changes.<br>+    lldb_private::Mutex m_message_mutex;<br>+    std::queue<ProcessMessage> m_message_queue;<br>+<br>+    /// True when the process has entered a state of "limbo".<br>+    ///<br>+    /// This flag qualifies eStateStopped.  It lets us know that when we<br>+    /// continue from this state the process will exit.  Also, when true,<br>+    /// Process::m_exit_status is set.<br>+    bool m_in_limbo;<br>+<br>+    /// Drive any exit events to completion.<br>+    bool m_exit_now;<br>+<br>+    /// OS-specific signal set.<br>+    lldb_private::UnixSignals m_signals;<br>+<br>+    /// Returns true if the process has exited.<br>+    bool HasExited();<br>+<br>+    /// Returns true if the process is stopped.<br>+    bool IsStopped();<br>+<br>+    typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;<br>+    MMapMap m_addr_to_mmap_size;<br>+};<br>+<br>+#endif  // liblldb_MacOSXProcess_H_<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,195 @@<br>+//===-- ProcessPOSIXLog.cpp ---------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#include "ProcessPOSIXLog.h"<br>+<br>+#include "lldb/Interpreter/Args.h"<br>+#include "lldb/Core/StreamFile.h"<br>+<br>+#include "ProcessPOSIX.h"<br>+#include "ProcessPOSIXLog.h"<br>+<br>+using namespace lldb;<br>+using namespace lldb_private;<br>+<br>+<br>+// We want to avoid global constructors where code needs to be run so here we<br>+// control access to our static g_log_sp by hiding it in a singleton function<br>+// that will construct the static g_lob_sp the first time this function is <br>+// called.<br>+static LogSP &<br>+GetLog ()<br>+{<br>+    static LogSP g_log_sp;<br>+    return g_log_sp;<br>+}<br>+<br>+LogSP<br>+ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask)<br>+{<br>+    LogSP log(GetLog ());<br>+    if (log && mask)<br>+    {<br>+        uint32_t log_mask = log->GetMask().Get();<br>+        if ((log_mask & mask) != mask)<br>+            return LogSP();<br>+    }<br>+    return log;<br>+}<br>+<br>+void<br>+ProcessPOSIXLog::DisableLog (Args &args, Stream *feedback_strm)<br>+{<br>+    LogSP log (GetLog ());<br>+    if (log)<br>+    {<br>+        uint32_t flag_bits = 0;<br>+        <br>+        const size_t argc = args.GetArgumentCount ();<br>+        if (argc > 0)<br>+        {<br>+            flag_bits = log->GetMask().Get();<br>+            for (size_t i = 0; i < argc; ++i)<br>+            {<br>+                const char *arg = args.GetArgumentAtIndex (i);<br>+                <br>+<br>+                if      (::strcasecmp (arg, "all")        == 0 ) flag_bits &= ~POSIX_LOG_ALL;<br>+                else if (::strcasecmp (arg, "async")      == 0 ) flag_bits &= ~POSIX_LOG_ASYNC;<br>+                else if (::strncasecmp (arg, "break", 5)  == 0 ) flag_bits &= ~POSIX_LOG_BREAKPOINTS;<br>+                else if (::strncasecmp (arg, "comm", 4)   == 0 ) flag_bits &= ~POSIX_LOG_COMM;<br>+                else if (::strcasecmp (arg, "default")    == 0 ) flag_bits &= ~POSIX_LOG_DEFAULT;<br>+                else if (::strcasecmp (arg, "packets")    == 0 ) flag_bits &= ~POSIX_LOG_PACKETS;<br>+                else if (::strcasecmp (arg, "memory")     == 0 ) flag_bits &= ~POSIX_LOG_MEMORY;<br>+                else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_SHORT;<br>+                else if (::strcasecmp (arg, "data-long")  == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_LONG;<br>+                else if (::strcasecmp (arg, "process")    == 0 ) flag_bits &= ~POSIX_LOG_PROCESS;<br>+                else if (::strcasecmp (arg, "ptrace")     == 0 ) flag_bits &= ~POSIX_LOG_PTRACE;<br>+                else if (::strcasecmp (arg, "registers")  == 0 ) flag_bits &= ~POSIX_LOG_REGISTERS;<br>+                else if (::strcasecmp (arg, "step")       == 0 ) flag_bits &= ~POSIX_LOG_STEP;<br>+                else if (::strcasecmp (arg, "thread")     == 0 ) flag_bits &= ~POSIX_LOG_THREAD;<br>+                else if (::strcasecmp (arg, "verbose")    == 0 ) flag_bits &= ~POSIX_LOG_VERBOSE;<br>+                else if (::strncasecmp (arg, "watch", 5)  == 0 ) flag_bits &= ~POSIX_LOG_WATCHPOINTS;<br>+                else<br>+                {<br>+                    feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);<br>+                    ListLogCategories (feedback_strm);<br>+                }<br>+                <br>+            }<br>+        }<br>+        <br>+        if (flag_bits == 0)<br>+            GetLog ().reset();<br>+        else<br>+            log->GetMask().Reset (flag_bits);<br>+    }<br>+    <br>+    return;<br>+}<br>+<br>+LogSP<br>+ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm)<br>+{<br>+    // Try see if there already is a log - that way we can reuse its settings.<br>+    // We could reuse the log in toto, but we don't know that the stream is the same.<br>+    uint32_t flag_bits = 0;<br>+    LogSP log(GetLog ());<br>+    if (log)<br>+        flag_bits = log->GetMask().Get();<br>+<br>+    // Now make a new log with this stream if one was provided<br>+    if (log_stream_sp)<br>+    {<br>+        log = make_shared<Log>(log_stream_sp);<br>+        GetLog () = log;<br>+    }<br>+<br>+    if (log)<br>+    {<br>+        bool got_unknown_category = false;<br>+        const size_t argc = args.GetArgumentCount();<br>+        for (size_t i=0; i<argc; ++i)<br>+        {<br>+            const char *arg = args.GetArgumentAtIndex(i);<br>+<br>+            if      (::strcasecmp (arg, "all")        == 0 ) flag_bits |= POSIX_LOG_ALL;<br>+            else if (::strcasecmp (arg, "async")      == 0 ) flag_bits |= POSIX_LOG_ASYNC;<br>+            else if (::strncasecmp (arg, "break", 5)  == 0 ) flag_bits |= POSIX_LOG_BREAKPOINTS;<br>+            else if (::strncasecmp (arg, "comm", 4)   == 0 ) flag_bits |= POSIX_LOG_COMM;<br>+            else if (::strcasecmp (arg, "default")    == 0 ) flag_bits |= POSIX_LOG_DEFAULT;<br>+            else if (::strcasecmp (arg, "packets")    == 0 ) flag_bits |= POSIX_LOG_PACKETS;<br>+            else if (::strcasecmp (arg, "memory")     == 0 ) flag_bits |= POSIX_LOG_MEMORY;<br>+            else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= POSIX_LOG_MEMORY_DATA_SHORT;<br>+            else if (::strcasecmp (arg, "data-long")  == 0 ) flag_bits |= POSIX_LOG_MEMORY_DATA_LONG;<br>+            else if (::strcasecmp (arg, "process")    == 0 ) flag_bits |= POSIX_LOG_PROCESS;<br>+            else if (::strcasecmp (arg, "ptrace")     == 0 ) flag_bits |= POSIX_LOG_PTRACE;<br>+            else if (::strcasecmp (arg, "registers")  == 0 ) flag_bits |= POSIX_LOG_REGISTERS;<br>+            else if (::strcasecmp (arg, "step")       == 0 ) flag_bits |= POSIX_LOG_STEP;<br>+            else if (::strcasecmp (arg, "thread")     == 0 ) flag_bits |= POSIX_LOG_THREAD;<br>+            else if (::strcasecmp (arg, "verbose")    == 0 ) flag_bits |= POSIX_LOG_VERBOSE;<br>+            else if (::strncasecmp (arg, "watch", 5)  == 0 ) flag_bits |= POSIX_LOG_WATCHPOINTS;<br>+            else<br>+            {<br>+                feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);<br>+                if (got_unknown_category == false)<br>+                {<br>+                    got_unknown_category = true;<br>+                    ListLogCategories (feedback_strm);<br>+                }<br>+            }<br>+        }<br>+        if (flag_bits == 0)<br>+            flag_bits = POSIX_LOG_DEFAULT;<br>+        log->GetMask().Reset(flag_bits);<br>+        log->GetOptions().Reset(log_options);<br>+    }<br>+    return log;<br>+}<br>+<br>+void<br>+ProcessPOSIXLog::ListLogCategories (Stream *strm)<br>+{<br>+    strm->Printf ("Logging categories for '%s':\n"<br>+                  "  all - turn on all available logging categories\n"<br>+                  "  async - log asynchronous activity\n"<br>+                  "  break - log breakpoints\n"<br>+                  "  communication - log communication activity\n"<br>+                  "  default - enable the default set of logging categories for liblldb\n"<br>+                  "  packets - log gdb remote packets\n"<br>+                  "  memory - log memory reads and writes\n"<br>+                  "  data-short - log memory bytes for memory reads and writes for short transactions only\n"<br>+                  "  data-long - log memory bytes for memory reads and writes for all transactions\n"<br>+                  "  process - log process events and activities\n"<br>+#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION<br>+                  "  ptrace - log all calls to ptrace\n"<br>+#endif<br>+                  "  registers - log register read/writes\n"<br>+                  "  thread - log thread events and activities\n"<br>+                  "  step - log step related activities\n"<br>+                  "  verbose - enable verbose logging\n"<br>+                  "  watch - log watchpoint related activities\n", ProcessPOSIXLog::m_pluginname);<br>+}<br>+<br>+<br>+void<br>+ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...)<br>+{<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask));<br>+    if (log)<br>+    {<br>+        va_list args;<br>+        va_start (args, format);<br>+        log->VAPrintf (format, args);<br>+        va_end (args);<br>+    }<br>+}<br>+<br>+int ProcessPOSIXLog::m_nestinglevel;<br>+const char *ProcessPOSIXLog::m_pluginname = "";<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.h (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,106 @@<br>+//===-- ProcessLinuxLog.h -----------------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_ProcessLinuxLog_h_<br>+#define liblldb_ProcessLinuxLog_h_<br>+<br>+// C Includes<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+<br>+// Project includes<br>+#include "lldb/Core/Log.h"<br>+<br>+#define POSIX_LOG_VERBOSE                  (1u << 0)<br>+#define POSIX_LOG_PROCESS                  (1u << 1)<br>+#define POSIX_LOG_THREAD                   (1u << 2)<br>+#define POSIX_LOG_PACKETS                  (1u << 3)<br>+#define POSIX_LOG_MEMORY                   (1u << 4)    // Log memory reads/writes calls<br>+#define POSIX_LOG_MEMORY_DATA_SHORT        (1u << 5)    // Log short memory reads/writes bytes<br>+#define POSIX_LOG_MEMORY_DATA_LONG         (1u << 6)    // Log all memory reads/writes bytes<br>+#define POSIX_LOG_BREAKPOINTS              (1u << 7)<br>+#define POSIX_LOG_WATCHPOINTS              (1u << 8)<br>+#define POSIX_LOG_STEP                     (1u << 9)<br>+#define POSIX_LOG_COMM                     (1u << 10)<br>+#define POSIX_LOG_ASYNC                    (1u << 11)<br>+#define POSIX_LOG_PTRACE                   (1u << 12)<br>+#define POSIX_LOG_REGISTERS                (1u << 13)<br>+#define POSIX_LOG_ALL                      (UINT32_MAX)<br>+#define POSIX_LOG_DEFAULT                  POSIX_LOG_PACKETS<br>+<br>+// The size which determines "short memory reads/writes".<br>+#define POSIX_LOG_MEMORY_SHORT_BYTES       (4 * sizeof(ptrdiff_t))<br>+<br>+class ProcessPOSIXLog<br>+{<br>+    static int m_nestinglevel;<br>+    static const char *m_pluginname;<br>+<br>+public:<br>+    static void<br>+    RegisterPluginName(const char *pluginName)<br>+    {<br>+        m_pluginname = pluginName;<br>+    }<br>+<br>+<br>+    static lldb::LogSP<br>+    GetLogIfAllCategoriesSet(uint32_t mask = 0);<br>+<br>+    static void<br>+    DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm);<br>+<br>+    static lldb::LogSP<br>+    EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options,<br>+               lldb_private::Args &args, lldb_private::Stream *feedback_strm);<br>+<br>+    static void<br>+    ListLogCategories (lldb_private::Stream *strm);<br>+<br>+    static void<br>+    LogIf (uint32_t mask, const char *format, ...);<br>+<br>+    // The following functions can be used to enable the client to limit<br>+    // logging to only the top level function calls.  This is useful for<br>+    // recursive functions.  FIXME: not thread safe!<br>+    //     Example:<br>+    //     void NestingFunc() {<br>+    //         LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL));<br>+    //         if (log)<br>+    //         {<br>+    //             ProcessLinuxLog::IncNestLevel();<br>+    //             if (ProcessLinuxLog::AtTopNestLevel())<br>+    //                 log->Print(msg);<br>+    //         }<br>+    //         NestingFunc();<br>+    //         if (log)<br>+    //             ProcessLinuxLog::DecNestLevel();<br>+    //     }<br>+<br>+    static bool<br>+    AtTopNestLevel()<br>+    {<br>+        return m_nestinglevel == 1;<br>+    }<br>+<br>+    static void<br>+    IncNestLevel()<br>+    {<br>+        ++m_nestinglevel;<br>+    }<br>+<br>+    static void<br>+    DecNestLevel()<br>+    {<br>+        --m_nestinglevel;<br>+        assert(m_nestinglevel >= 0);<br>+    }<br>+};<br>+<br>+#endif  // liblldb_ProcessLinuxLog_h_<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,40 @@<br>+//===-- RegisterContextPOSIX.h --------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_RegisterContextPOSIX_H_<br>+#define liblldb_RegisterContextPOSIX_H_<br>+<br>+// C Includes<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+#include "lldb/Target/RegisterContext.h"<br>+<br>+//------------------------------------------------------------------------------<br>+/// @class RegisterContextPOSIX<br>+///<br>+/// @brief Extends RegisterClass with a few virtual operations useful on POSIX.<br>+class RegisterContextPOSIX<br>+    : public lldb_private::RegisterContext<br>+{<br>+public:<br>+    RegisterContextPOSIX(lldb_private::Thread &thread,<br>+                         uint32_t concrete_frame_idx)<br>+        : RegisterContext(thread, concrete_frame_idx) { }<br>+<br>+    /// Updates the register state of the associated thread after hitting a<br>+    /// breakpoint (if that make sense for the architecture).  Default<br>+    /// implementation simply returns true for architectures which do not<br>+    /// require any update.<br>+    ///<br>+    /// @return<br>+    ///    True if the operation succeeded and false otherwise.<br>+    virtual bool UpdateAfterBreakpoint() { return true; }<br>+};<br>+<br>+#endif // #ifndef liblldb_RegisterContextPOSIX_H_<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.cpp?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.cpp?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.cpp (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.cpp Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,643 @@<br>+//===-- RegisterContextPOSIX_i386.cpp ---------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#include "lldb/Core/DataExtractor.h"<br>+#include "lldb/Target/Thread.h"<br>+#include "lldb/Host/Endian.h"<br>+<br>+#include "ProcessPOSIX.h"<br>+#include "ProcessPOSIXLog.h"<br>+#include "ProcessMonitor.h"<br>+#include "RegisterContext_i386.h"<br>+<br>+using namespace lldb_private;<br>+using namespace lldb;<br>+<br>+enum<br>+{<br>+    k_first_gpr,<br>+    gpr_eax = k_first_gpr,<br>+    gpr_ebx,<br>+    gpr_ecx,<br>+    gpr_edx,<br>+    gpr_edi,<br>+    gpr_esi,<br>+    gpr_ebp,<br>+    gpr_esp,<br>+    gpr_ss,<br>+    gpr_eflags,<br>+#ifdef __FreeBSD__<br>+    gpr_orig_ax,<br>+#endif<br>+    gpr_eip,<br>+    gpr_cs,<br>+    gpr_ds,<br>+    gpr_es,<br>+    gpr_fs,<br>+    gpr_gs,<br>+    k_last_gpr = gpr_gs,<br>+<br>+    k_first_fpr,<br>+    fpu_fcw = k_first_fpr,<br>+    fpu_fsw,<br>+    fpu_ftw,<br>+    fpu_fop,<br>+    fpu_ip,<br>+    fpu_cs,<br>+    fpu_foo,<br>+    fpu_fos,<br>+    fpu_mxcsr,<br>+    fpu_stmm0,<br>+    fpu_stmm1,<br>+    fpu_stmm2,<br>+    fpu_stmm3,<br>+    fpu_stmm4,<br>+    fpu_stmm5,<br>+    fpu_stmm6,<br>+    fpu_stmm7,<br>+    fpu_xmm0,<br>+    fpu_xmm1,<br>+    fpu_xmm2,<br>+    fpu_xmm3,<br>+    fpu_xmm4,<br>+    fpu_xmm5,<br>+    fpu_xmm6,<br>+    fpu_xmm7,<br>+    k_last_fpr = fpu_xmm7,<br>+<br>+    k_num_registers,<br>+    k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,<br>+    k_num_fpu_registers = k_last_fpr - k_first_fpr + 1<br>+};<br>+<br>+// Number of register sets provided by this context.<br>+enum<br>+{<br>+    k_num_register_sets = 2<br>+};<br>+<br>+enum<br>+{<br>+    gcc_eax = 0,<br>+    gcc_ecx,<br>+    gcc_edx,<br>+    gcc_ebx,<br>+    gcc_ebp,<br>+    gcc_esp,<br>+    gcc_esi,<br>+    gcc_edi,<br>+    gcc_eip,<br>+    gcc_eflags<br>+};<br>+<br>+enum<br>+{<br>+    dwarf_eax = 0,<br>+    dwarf_ecx,<br>+    dwarf_edx,<br>+    dwarf_ebx,<br>+    dwarf_esp,<br>+    dwarf_ebp,<br>+    dwarf_esi,<br>+    dwarf_edi,<br>+    dwarf_eip,<br>+    dwarf_eflags,<br>+    dwarf_stmm0 = 11,<br>+    dwarf_stmm1,<br>+    dwarf_stmm2,<br>+    dwarf_stmm3,<br>+    dwarf_stmm4,<br>+    dwarf_stmm5,<br>+    dwarf_stmm6,<br>+    dwarf_stmm7,<br>+    dwarf_xmm0 = 21,<br>+    dwarf_xmm1,<br>+    dwarf_xmm2,<br>+    dwarf_xmm3,<br>+    dwarf_xmm4,<br>+    dwarf_xmm5,<br>+    dwarf_xmm6,<br>+    dwarf_xmm7<br>+};<br>+<br>+enum<br>+{<br>+    gdb_eax        =  0,<br>+    gdb_ecx        =  1,<br>+    gdb_edx        =  2,<br>+    gdb_ebx        =  3,<br>+    gdb_esp        =  4,<br>+    gdb_ebp        =  5,<br>+    gdb_esi        =  6,<br>+    gdb_edi        =  7,<br>+    gdb_eip        =  8,<br>+    gdb_eflags     =  9,<br>+    gdb_cs         = 10,<br>+    gdb_ss         = 11,<br>+    gdb_ds         = 12,<br>+    gdb_es         = 13,<br>+    gdb_fs         = 14,<br>+    gdb_gs         = 15,<br>+    gdb_stmm0      = 16,<br>+    gdb_stmm1      = 17,<br>+    gdb_stmm2      = 18,<br>+    gdb_stmm3      = 19,<br>+    gdb_stmm4      = 20,<br>+    gdb_stmm5      = 21,<br>+    gdb_stmm6      = 22,<br>+    gdb_stmm7      = 23,<br>+    gdb_fcw        = 24,<br>+    gdb_fsw        = 25,<br>+    gdb_ftw        = 26,<br>+    gdb_fpu_cs     = 27,<br>+    gdb_ip         = 28,<br>+    gdb_fpu_ds     = 29,<br>+    gdb_dp         = 30,<br>+    gdb_fop        = 31,<br>+    gdb_xmm0       = 32,<br>+    gdb_xmm1       = 33,<br>+    gdb_xmm2       = 34,<br>+    gdb_xmm3       = 35,<br>+    gdb_xmm4       = 36,<br>+    gdb_xmm5       = 37,<br>+    gdb_xmm6       = 38,<br>+    gdb_xmm7       = 39,<br>+    gdb_mxcsr      = 40,<br>+    gdb_mm0        = 41,<br>+    gdb_mm1        = 42,<br>+    gdb_mm2        = 43,<br>+    gdb_mm3        = 44,<br>+    gdb_mm4        = 45,<br>+    gdb_mm5        = 46,<br>+    gdb_mm6        = 47,<br>+    gdb_mm7        = 48<br>+};<br>+<br>+static const<br>+uint32_t g_gpr_regnums[k_num_gpr_registers] =<br>+{<br>+    gpr_eax,<br>+    gpr_ebx,<br>+    gpr_ecx,<br>+    gpr_edx,<br>+    gpr_edi,<br>+    gpr_esi,<br>+    gpr_ebp,<br>+    gpr_esp,<br>+    gpr_ss,<br>+    gpr_eflags,<br>+#ifdef __FreeBSD__<br>+    gpr_orig_ax,<br>+#endif<br>+    gpr_eip,<br>+    gpr_cs,<br>+    gpr_ds,<br>+    gpr_es,<br>+    gpr_fs,<br>+    gpr_gs,<br>+};<br>+<br>+static const uint32_t<br>+g_fpu_regnums[k_num_fpu_registers] =<br>+{<br>+    fpu_fcw,<br>+    fpu_fsw,<br>+    fpu_ftw,<br>+    fpu_fop,<br>+    fpu_ip,<br>+    fpu_cs,<br>+    fpu_foo,<br>+    fpu_fos,<br>+    fpu_mxcsr,<br>+    fpu_stmm0,<br>+    fpu_stmm1,<br>+    fpu_stmm2,<br>+    fpu_stmm3,<br>+    fpu_stmm4,<br>+    fpu_stmm5,<br>+    fpu_stmm6,<br>+    fpu_stmm7,<br>+    fpu_xmm0,<br>+    fpu_xmm1,<br>+    fpu_xmm2,<br>+    fpu_xmm3,<br>+    fpu_xmm4,<br>+    fpu_xmm5,<br>+    fpu_xmm6,<br>+    fpu_xmm7,<br>+};<br>+<br>+static const RegisterSet<br>+g_reg_sets[k_num_register_sets] =<br>+{<br>+    { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },<br>+    { "Floating Point Registers",  "fpu", k_num_fpu_registers, g_fpu_regnums }<br>+};<br>+<br>+// Computes the offset of the given GPR in the user data area.<br>+#define GPR_OFFSET(regname) \<br>+    (offsetof(RegisterContext_i386::UserArea, regs) + \<br>+     offsetof(RegisterContext_i386::GPR, regname))<br>+<br>+// Computes the offset of the given FPR in the user data area.<br>+#define FPR_OFFSET(regname) \<br>+    (offsetof(RegisterContext_i386::UserArea, i387) + \<br>+     offsetof(RegisterContext_i386::FPU, regname))<br>+<br>+// Number of bytes needed to represent a GPR.<br>+#define GPR_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg)<br>+<br>+// Number of bytes needed to represent a FPR.<br>+#define FPR_SIZE(reg) sizeof(((RegisterContext_i386::FPU*)NULL)->reg)<br>+<br>+// Number of bytes needed to represent the i'th FP register.<br>+#define FP_SIZE sizeof(((RegisterContext_i386::MMSReg*)NULL)->bytes)<br>+<br>+// Number of bytes needed to represent an XMM register.<br>+#define XMM_SIZE sizeof(RegisterContext_i386::XMMReg)<br>+<br>+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)        \<br>+    { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \<br>+      eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } }<br>+<br>+#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4)              \<br>+    { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \<br>+      eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } }<br>+<br>+#define DEFINE_FP(reg, i)                                          \<br>+    { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector,  \<br>+      eFormatVectorOfUInt8,                                        \<br>+      { dwarf_##reg##i, dwarf_##reg##i,                            \<br>+        LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } }<br>+<br>+#define DEFINE_XMM(reg, i)                                         \<br>+    { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \<br>+      eFormatVectorOfUInt8,                                        \<br>+      { dwarf_##reg##i, dwarf_##reg##i,                            \<br>+        LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } }<br>+<br>+static RegisterInfo<br>+g_register_infos[k_num_registers] =<br>+{<br>+    // General purpose registers.<br>+    DEFINE_GPR(eax,    NULL,    gcc_eax,    dwarf_eax,    LLDB_INVALID_REGNUM,    gdb_eax),<br>+    DEFINE_GPR(ebx,    NULL,    gcc_ebx,    dwarf_ebx,    LLDB_INVALID_REGNUM,    gdb_ebx),<br>+    DEFINE_GPR(ecx,    NULL,    gcc_ecx,    dwarf_ecx,    LLDB_INVALID_REGNUM,    gdb_ecx),<br>+    DEFINE_GPR(edx,    NULL,    gcc_edx,    dwarf_edx,    LLDB_INVALID_REGNUM,    gdb_edx),<br>+    DEFINE_GPR(edi,    NULL,    gcc_edi,    dwarf_edi,    LLDB_INVALID_REGNUM,    gdb_edi),<br>+    DEFINE_GPR(esi,    NULL,    gcc_esi,    dwarf_esi,    LLDB_INVALID_REGNUM,    gdb_esi),<br>+    DEFINE_GPR(ebp,    "fp",    gcc_ebp,    dwarf_ebp,    LLDB_INVALID_REGNUM,    gdb_ebp),<br>+    DEFINE_GPR(esp,    "sp",    gcc_esp,    dwarf_esp,    LLDB_INVALID_REGNUM,    gdb_esp),<br>+    DEFINE_GPR(ss,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_ss),<br>+    DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM,    gdb_eflags),<br>+    DEFINE_GPR(eip,    "pc",    gcc_eip,    dwarf_eip,    LLDB_INVALID_REGNUM,    gdb_eip),<br>+    DEFINE_GPR(cs,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_cs),<br>+    DEFINE_GPR(ds,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_ds),<br>+    DEFINE_GPR(es,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_es),<br>+    DEFINE_GPR(fs,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_fs),<br>+    DEFINE_GPR(gs,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_gs),<br>+<br>+    // Floating point registers.<br>+    DEFINE_FPR(fcw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw),<br>+    DEFINE_FPR(fsw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw),<br>+    DEFINE_FPR(ftw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw),<br>+    DEFINE_FPR(fop,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop),<br>+    DEFINE_FPR(ip,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip),<br>+    DEFINE_FPR(cs,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs),<br>+    DEFINE_FPR(foo,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp),<br>+    DEFINE_FPR(fos,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds),<br>+    DEFINE_FPR(mxcsr,     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr),<br>+<br>+    DEFINE_FP(stmm, 0),<br>+    DEFINE_FP(stmm, 1),<br>+    DEFINE_FP(stmm, 2),<br>+    DEFINE_FP(stmm, 3),<br>+    DEFINE_FP(stmm, 4),<br>+    DEFINE_FP(stmm, 5),<br>+    DEFINE_FP(stmm, 6),<br>+    DEFINE_FP(stmm, 7),<br>+<br>+    // XMM registers<br>+    DEFINE_XMM(xmm, 0),<br>+    DEFINE_XMM(xmm, 1),<br>+    DEFINE_XMM(xmm, 2),<br>+    DEFINE_XMM(xmm, 3),<br>+    DEFINE_XMM(xmm, 4),<br>+    DEFINE_XMM(xmm, 5),<br>+    DEFINE_XMM(xmm, 6),<br>+    DEFINE_XMM(xmm, 7),<br>+<br>+};<br>+<br>+#ifndef NDEBUG<br>+static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));<br>+#endif<br>+<br>+static unsigned GetRegOffset(unsigned reg)<br>+{<br>+    assert(reg < k_num_registers && "Invalid register number.");<br>+    return g_register_infos[reg].byte_offset;<br>+}<br>+<br>+static unsigned GetRegSize(unsigned reg)<br>+{<br>+    assert(reg < k_num_registers && "Invalid register number.");<br>+    return g_register_infos[reg].byte_size;<br>+}<br>+<br>+RegisterContext_i386::RegisterContext_i386(Thread &thread,<br>+                                                     uint32_t concrete_frame_idx)<br>+    : RegisterContextPOSIX(thread, concrete_frame_idx)<br>+{<br>+}<br>+<br>+RegisterContext_i386::~RegisterContext_i386()<br>+{<br>+}<br>+<br>+ProcessMonitor &<br>+RegisterContext_i386::GetMonitor()<br>+{<br>+    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(CalculateProcess());<br>+    return process->GetMonitor();<br>+}<br>+<br>+void<br>+RegisterContext_i386::Invalidate()<br>+{<br>+}<br>+<br>+void<br>+RegisterContext_i386::InvalidateAllRegisters()<br>+{<br>+}<br>+<br>+size_t<br>+RegisterContext_i386::GetRegisterCount()<br>+{<br>+    assert(k_num_register_infos == k_num_registers);<br>+    return k_num_registers;<br>+}<br>+<br>+const RegisterInfo *<br>+RegisterContext_i386::GetRegisterInfoAtIndex(uint32_t reg)<br>+{<br>+    assert(k_num_register_infos == k_num_registers);<br>+    if (reg < k_num_registers)<br>+        return &g_register_infos[reg];<br>+    else<br>+        return NULL;<br>+}<br>+<br>+size_t<br>+RegisterContext_i386::GetRegisterSetCount()<br>+{<br>+    return k_num_register_sets;<br>+}<br>+<br>+const RegisterSet *<br>+RegisterContext_i386::GetRegisterSet(uint32_t set)<br>+{<br>+    if (set < k_num_register_sets)<br>+        return &g_reg_sets[set];<br>+    else<br>+        return NULL;<br>+}<br>+<br>+unsigned<br>+RegisterContext_i386::GetRegisterIndexFromOffset(unsigned offset)<br>+{<br>+    unsigned reg;<br>+    for (reg = 0; reg < k_num_registers; reg++)<br>+    {<br>+        if (g_register_infos[reg].byte_offset == offset)<br>+            break;<br>+    }<br>+    assert(reg < k_num_registers && "Invalid register offset.");<br>+    return reg;<br>+}<br>+<br>+const char *<br>+RegisterContext_i386::GetRegisterName(unsigned reg)<br>+{<br>+    assert(reg < k_num_registers && "Invalid register offset.");<br>+    return g_register_infos[reg].name;<br>+}<br>+<br>+bool<br>+RegisterContext_i386::ReadRegister(const RegisterInfo *reg_info,<br>+                                        RegisterValue &value)<br>+{<br>+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];<br>+    ProcessMonitor &monitor = GetMonitor();<br>+    return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value);<br>+}<br>+<br>+bool<br>+RegisterContext_i386::ReadAllRegisterValues(DataBufferSP &data_sp)<br>+{<br>+    return false;<br>+}<br>+<br>+bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info,<br>+                                              const RegisterValue &value)<br>+{<br>+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];<br>+    ProcessMonitor &monitor = GetMonitor();<br>+    return monitor.WriteRegisterValue(GetRegOffset(reg), value);<br>+}<br>+<br>+bool<br>+RegisterContext_i386::WriteAllRegisterValues(const DataBufferSP &data)<br>+{<br>+    return false;<br>+}<br>+<br>+bool<br>+RegisterContext_i386::UpdateAfterBreakpoint()<br>+{<br>+    // PC points one byte past the int3 responsible for the breakpoint.<br>+    lldb::addr_t pc;<br>+<br>+    if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)<br>+        return false;<br>+<br>+    SetPC(pc - 1);<br>+    return true;<br>+}<br>+<br>+uint32_t<br>+RegisterContext_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind,<br>+                                                               uint32_t num)<br>+{<br>+    if (kind == eRegisterKindGeneric)<br>+    {<br>+        switch (num)<br>+        {<br>+        case LLDB_REGNUM_GENERIC_PC:    return gpr_eip;<br>+        case LLDB_REGNUM_GENERIC_SP:    return gpr_esp;<br>+        case LLDB_REGNUM_GENERIC_FP:    return gpr_ebp;<br>+        case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags;<br>+        case LLDB_REGNUM_GENERIC_RA:<br>+        default:<br>+            return LLDB_INVALID_REGNUM;<br>+        }<br>+    }<br>+<br>+    if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)<br>+    {<br>+        switch (num)<br>+        {<br>+        case dwarf_eax:  return gpr_eax;<br>+        case dwarf_edx:  return gpr_edx;<br>+        case dwarf_ecx:  return gpr_ecx;<br>+        case dwarf_ebx:  return gpr_ebx;<br>+        case dwarf_esi:  return gpr_esi;<br>+        case dwarf_edi:  return gpr_edi;<br>+        case dwarf_ebp:  return gpr_ebp;<br>+        case dwarf_esp:  return gpr_esp;<br>+        case dwarf_eip:  return gpr_eip;<br>+        case dwarf_xmm0: return fpu_xmm0;<br>+        case dwarf_xmm1: return fpu_xmm1;<br>+        case dwarf_xmm2: return fpu_xmm2;<br>+        case dwarf_xmm3: return fpu_xmm3;<br>+        case dwarf_xmm4: return fpu_xmm4;<br>+        case dwarf_xmm5: return fpu_xmm5;<br>+        case dwarf_xmm6: return fpu_xmm6;<br>+        case dwarf_xmm7: return fpu_xmm7;<br>+        case dwarf_stmm0: return fpu_stmm0;<br>+        case dwarf_stmm1: return fpu_stmm1;<br>+        case dwarf_stmm2: return fpu_stmm2;<br>+        case dwarf_stmm3: return fpu_stmm3;<br>+        case dwarf_stmm4: return fpu_stmm4;<br>+        case dwarf_stmm5: return fpu_stmm5;<br>+        case dwarf_stmm6: return fpu_stmm6;<br>+        case dwarf_stmm7: return fpu_stmm7;<br>+        default:<br>+            return LLDB_INVALID_REGNUM;<br>+        }<br>+    }<br>+<br>+    if (kind == eRegisterKindGDB)<br>+    {<br>+        switch (num)<br>+        {<br>+        case gdb_eax     : return gpr_eax;<br>+        case gdb_ebx     : return gpr_ebx;<br>+        case gdb_ecx     : return gpr_ecx;<br>+        case gdb_edx     : return gpr_edx;<br>+        case gdb_esi     : return gpr_esi;<br>+        case gdb_edi     : return gpr_edi;<br>+        case gdb_ebp     : return gpr_ebp;<br>+        case gdb_esp     : return gpr_esp;<br>+        case gdb_eip     : return gpr_eip;<br>+        case gdb_eflags  : return gpr_eflags;<br>+        case gdb_cs      : return gpr_cs;<br>+        case gdb_ss      : return gpr_ss;<br>+        case gdb_ds      : return gpr_ds;<br>+        case gdb_es      : return gpr_es;<br>+        case gdb_fs      : return gpr_fs;<br>+        case gdb_gs      : return gpr_gs;<br>+        case gdb_stmm0   : return fpu_stmm0;<br>+        case gdb_stmm1   : return fpu_stmm1;<br>+        case gdb_stmm2   : return fpu_stmm2;<br>+        case gdb_stmm3   : return fpu_stmm3;<br>+        case gdb_stmm4   : return fpu_stmm4;<br>+        case gdb_stmm5   : return fpu_stmm5;<br>+        case gdb_stmm6   : return fpu_stmm6;<br>+        case gdb_stmm7   : return fpu_stmm7;<br>+        case gdb_fcw     : return fpu_fcw;<br>+        case gdb_fsw     : return fpu_fsw;<br>+        case gdb_ftw     : return fpu_ftw;<br>+        case gdb_fpu_cs  : return fpu_cs;<br>+        case gdb_ip      : return fpu_ip;<br>+        case gdb_fpu_ds  : return fpu_fos;<br>+        case gdb_dp      : return fpu_foo;<br>+        case gdb_fop     : return fpu_fop;<br>+        case gdb_xmm0    : return fpu_xmm0;<br>+        case gdb_xmm1    : return fpu_xmm1;<br>+        case gdb_xmm2    : return fpu_xmm2;<br>+        case gdb_xmm3    : return fpu_xmm3;<br>+        case gdb_xmm4    : return fpu_xmm4;<br>+        case gdb_xmm5    : return fpu_xmm5;<br>+        case gdb_xmm6    : return fpu_xmm6;<br>+        case gdb_xmm7    : return fpu_xmm7;<br>+        case gdb_mxcsr   : return fpu_mxcsr;<br>+        default:<br>+            return LLDB_INVALID_REGNUM;<br>+        }<br>+    }<br>+    else if (kind == eRegisterKindLLDB)<br>+    {<br>+        return num;<br>+    }<br>+<br>+    return LLDB_INVALID_REGNUM;<br>+}<br>+<br>+bool<br>+RegisterContext_i386::HardwareSingleStep(bool enable)<br>+{<br>+    enum { TRACE_BIT = 0x100 };<br>+    uint64_t eflags;<br>+<br>+    if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL)<br>+        return false;<br>+<br>+    if (enable)<br>+    {<br>+        if (eflags & TRACE_BIT)<br>+            return true;<br>+<br>+        eflags |= TRACE_BIT;<br>+    }<br>+    else<br>+    {<br>+        if (!(eflags & TRACE_BIT))<br>+            return false;<br>+<br>+        eflags &= ~TRACE_BIT;<br>+    }<br>+<br>+    return WriteRegisterFromUnsigned(gpr_eflags, eflags);<br>+}<br>+<br>+void<br>+RegisterContext_i386::LogGPR(const char *title)<br>+{<br>+    LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));<br>+    if (log)<br>+    {<br>+        if (title)<br>+            log->Printf ("%s", title);<br>+        for (uint32_t i=0; i<k_num_gpr_registers; i++)<br>+        {<br>+            uint32_t reg = gpr_eax + i;<br>+            log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]);<br>+        }<br>+    }<br>+}<br>+<br>+bool<br>+RegisterContext_i386::ReadGPR()<br>+{<br>+    bool result;<br>+<br>+    ProcessMonitor &monitor = GetMonitor();<br>+    result = monitor.ReadGPR(&user.regs);<br>+    LogGPR("RegisterContext_i386::ReadGPR()");<br>+    return result;<br>+}<br>+<br>+bool<br>+RegisterContext_i386::ReadFPR()<br>+{<br>+    ProcessMonitor &monitor = GetMonitor();<br>+    return monitor.ReadFPR(&user.i387);<br>+}<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.h (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,169 @@<br>+//===-- RegisterContext_i386.h ------------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_RegisterContext_i386_h_<br>+#define liblldb_RegisterContext_i386_h_<br>+<br>+// C Includes<br>+// C++ Includes<br>+// Other libraries and framework includes<br>+// Project includes<br>+#include "lldb/Core/Log.h"<br>+#include "RegisterContextPOSIX.h"<br>+<br>+class RegisterContext_i386 : public RegisterContextPOSIX<br>+{<br>+public:<br>+    RegisterContext_i386(lldb_private::Thread &thread,<br>+                              uint32_t concreate_frame_idx);<br>+<br>+    ~RegisterContext_i386();<br>+<br>+    void<br>+    Invalidate();<br>+<br>+    void<br>+    InvalidateAllRegisters();<br>+<br>+    size_t<br>+    GetRegisterCount();<br>+<br>+    const lldb_private::RegisterInfo *<br>+    GetRegisterInfoAtIndex(uint32_t reg);<br>+<br>+    size_t<br>+    GetRegisterSetCount();<br>+<br>+    const lldb_private::RegisterSet *<br>+    GetRegisterSet(uint32_t set);<br>+<br>+    static unsigned<br>+    GetRegisterIndexFromOffset(unsigned offset);<br>+<br>+    static const char *<br>+    GetRegisterName(unsigned reg);<br>+<br>+    bool<br>+    ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value);<br>+<br>+    bool<br>+    ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data);<br>+<br>+    virtual bool<br>+    ReadRegister(const lldb_private::RegisterInfo *reg_info,<br>+                 lldb_private::RegisterValue &value);<br>+<br>+    bool<br>+    ReadAllRegisterValues(lldb::DataBufferSP &data_sp);<br>+<br>+    bool<br>+    WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value);<br>+<br>+    bool<br>+    WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data,<br>+                       uint32_t data_offset = 0);<br>+<br>+    virtual bool<br>+    WriteRegister(const lldb_private::RegisterInfo *reg_info,<br>+                  const lldb_private::RegisterValue &value);<br>+<br>+    bool<br>+    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);<br>+<br>+    uint32_t<br>+    ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);<br>+<br>+    bool<br>+    HardwareSingleStep(bool enable);<br>+<br>+    bool<br>+    UpdateAfterBreakpoint();<br>+<br>+    struct GPR<br>+    {<br>+        uint32_t ebx;<br>+        uint32_t ecx;<br>+        uint32_t edx;<br>+        uint32_t esi;<br>+        uint32_t edi;<br>+        uint32_t ebp;<br>+        uint32_t eax;<br>+        uint32_t ds;<br>+        uint32_t es;<br>+        uint32_t fs;<br>+        uint32_t gs;<br>+        uint32_t orig_ax;<br>+        uint32_t eip;<br>+        uint32_t cs;<br>+        uint32_t eflags;<br>+        uint32_t esp;<br>+        uint32_t ss;<br>+    };<br>+<br>+    struct MMSReg<br>+    {<br>+        uint8_t bytes[8];<br>+    };<br>+<br>+    struct XMMReg<br>+    {<br>+        uint8_t bytes[16];<br>+    };<br>+<br>+    struct FPU<br>+    {<br>+        uint16_t    fcw;<br>+        uint16_t    fsw;<br>+        uint16_t    ftw;<br>+        uint16_t    fop;<br>+        uint32_t    ip;<br>+        uint32_t    cs;<br>+        uint32_t    foo;<br>+        uint32_t    fos;<br>+        uint32_t    mxcsr;<br>+        uint32_t    reserved;<br>+        MMSReg      stmm[8];<br>+        XMMReg      xmm[8];<br>+        uint32_t    pad[56];<br>+    };<br>+<br>+    // A user area like this no longer exists on FreeBSD<br>+    // making this a Linux artifact. Nonetheless, it is safe<br>+    // leaving it here while the code is being cleaned up and generalized.<br>+<br>+    struct UserArea<br>+    {<br>+        GPR      regs;          // General purpose registers.<br>+        int32_t  fpvalid;       // True if FPU is being used.<br>+        FPU      i387;          // FPU registers.<br>+        uint32_t tsize;         // Text segment size.<br>+        uint32_t dsize;         // Data segment size.<br>+        uint32_t ssize;         // Stack segment size.<br>+        uint32_t start_code;    // VM address of text.<br>+        uint32_t start_stack;   // VM address of stack bottom (top in rsp).<br>+        int32_t  signal;        // Signal causing core dump.<br>+        int32_t  reserved;      // Unused.<br>+        uint32_t ar0;           // Location of GPR's.<br>+        FPU*     fpstate;       // Location of FPR's.<br>+        uint32_t magic;         // Identifier for core dumps.<br>+        char     u_comm[32];    // Command causing core dump.<br>+        uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7).<br>+    };<br>+private:<br>+    UserArea user;<br>+<br>+    ProcessMonitor &GetMonitor();<br>+<br>+    void LogGPR(const char *title);<br>+<br>+    bool ReadGPR();<br>+    bool ReadFPR();<br>+};<br>+<br>+#endif // #ifndef liblldb_RegisterContext_i386_h_<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,757 @@<br>+//===-- RegisterContext_x86_64.cpp -------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#include <cstring><br>+#include <errno.h><br>+#include <stdint.h><br>+<br>+#include "lldb/Core/DataBufferHeap.h"<br>+#include "lldb/Core/DataExtractor.h"<br>+#include "lldb/Core/Scalar.h"<br>+#include "lldb/Target/Thread.h"<br>+#include "lldb/Host/Endian.h"<br>+<br>+#include "ProcessPOSIX.h"<br>+#include "ProcessMonitor.h"<br>+#include "RegisterContext_x86_64.h"<br>+<br>+using namespace lldb_private;<br>+using namespace lldb;<br>+<br>+// Internal codes for all x86_64 registers.<br>+enum<br>+{<br>+    k_first_gpr,<br>+    gpr_rax = k_first_gpr,<br>+    gpr_rbx,<br>+    gpr_rcx,<br>+    gpr_rdx,<br>+    gpr_rdi,<br>+    gpr_rsi,<br>+    gpr_rbp,<br>+    gpr_rsp,<br>+    gpr_r8,<br>+    gpr_r9,<br>+    gpr_r10,<br>+    gpr_r11,<br>+    gpr_r12,<br>+    gpr_r13,<br>+    gpr_r14,<br>+    gpr_r15,<br>+    gpr_rip,<br>+    gpr_rflags,<br>+    gpr_cs,<br>+    gpr_fs,<br>+    gpr_gs,<br>+    gpr_ss,<br>+    gpr_ds,<br>+    gpr_es,<br>+    k_last_gpr = gpr_es,<br>+<br>+    k_first_fpr,<br>+    fpu_fcw = k_first_fpr,<br>+    fpu_fsw,<br>+    fpu_ftw,<br>+    fpu_fop,<br>+    fpu_ip,<br>+    fpu_cs,<br>+    fpu_dp,<br>+    fpu_ds,<br>+    fpu_mxcsr,<br>+    fpu_mxcsrmask,<br>+    fpu_stmm0,<br>+    fpu_stmm1,<br>+    fpu_stmm2,<br>+    fpu_stmm3,<br>+    fpu_stmm4,<br>+    fpu_stmm5,<br>+    fpu_stmm6,<br>+    fpu_stmm7,<br>+    fpu_xmm0,<br>+    fpu_xmm1,<br>+    fpu_xmm2,<br>+    fpu_xmm3,<br>+    fpu_xmm4,<br>+    fpu_xmm5,<br>+    fpu_xmm6,<br>+    fpu_xmm7,<br>+    fpu_xmm8,<br>+    fpu_xmm9,<br>+    fpu_xmm10,<br>+    fpu_xmm11,<br>+    fpu_xmm12,<br>+    fpu_xmm13,<br>+    fpu_xmm14,<br>+    fpu_xmm15,<br>+    k_last_fpr = fpu_xmm15,<br>+<br>+    k_num_registers,<br>+    k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,<br>+    k_num_fpu_registers = k_last_fpr - k_first_fpr + 1<br>+};<br>+<br>+// Number of register sets provided by this context.<br>+enum<br>+{<br>+    k_num_register_sets = 2<br>+};<br>+<br>+enum gcc_dwarf_regnums<br>+{<br>+    gcc_dwarf_gpr_rax = 0,<br>+    gcc_dwarf_gpr_rdx,<br>+    gcc_dwarf_gpr_rcx,<br>+    gcc_dwarf_gpr_rbx,<br>+    gcc_dwarf_gpr_rsi,<br>+    gcc_dwarf_gpr_rdi,<br>+    gcc_dwarf_gpr_rbp,<br>+    gcc_dwarf_gpr_rsp,<br>+    gcc_dwarf_gpr_r8,<br>+    gcc_dwarf_gpr_r9,<br>+    gcc_dwarf_gpr_r10,<br>+    gcc_dwarf_gpr_r11,<br>+    gcc_dwarf_gpr_r12,<br>+    gcc_dwarf_gpr_r13,<br>+    gcc_dwarf_gpr_r14,<br>+    gcc_dwarf_gpr_r15,<br>+    gcc_dwarf_gpr_rip,<br>+    gcc_dwarf_fpu_xmm0,<br>+    gcc_dwarf_fpu_xmm1,<br>+    gcc_dwarf_fpu_xmm2,<br>+    gcc_dwarf_fpu_xmm3,<br>+    gcc_dwarf_fpu_xmm4,<br>+    gcc_dwarf_fpu_xmm5,<br>+    gcc_dwarf_fpu_xmm6,<br>+    gcc_dwarf_fpu_xmm7,<br>+    gcc_dwarf_fpu_xmm8,<br>+    gcc_dwarf_fpu_xmm9,<br>+    gcc_dwarf_fpu_xmm10,<br>+    gcc_dwarf_fpu_xmm11,<br>+    gcc_dwarf_fpu_xmm12,<br>+    gcc_dwarf_fpu_xmm13,<br>+    gcc_dwarf_fpu_xmm14,<br>+    gcc_dwarf_fpu_xmm15,<br>+    gcc_dwarf_fpu_stmm0,<br>+    gcc_dwarf_fpu_stmm1,<br>+    gcc_dwarf_fpu_stmm2,<br>+    gcc_dwarf_fpu_stmm3,<br>+    gcc_dwarf_fpu_stmm4,<br>+    gcc_dwarf_fpu_stmm5,<br>+    gcc_dwarf_fpu_stmm6,<br>+    gcc_dwarf_fpu_stmm7<br>+};<br>+<br>+enum gdb_regnums<br>+{<br>+    gdb_gpr_rax     =   0,<br>+    gdb_gpr_rbx     =   1,<br>+    gdb_gpr_rcx     =   2,<br>+    gdb_gpr_rdx     =   3,<br>+    gdb_gpr_rsi     =   4,<br>+    gdb_gpr_rdi     =   5,<br>+    gdb_gpr_rbp     =   6,<br>+    gdb_gpr_rsp     =   7,<br>+    gdb_gpr_r8      =   8,<br>+    gdb_gpr_r9      =   9,<br>+    gdb_gpr_r10     =  10,<br>+    gdb_gpr_r11     =  11,<br>+    gdb_gpr_r12     =  12,<br>+    gdb_gpr_r13     =  13,<br>+    gdb_gpr_r14     =  14,<br>+    gdb_gpr_r15     =  15,<br>+    gdb_gpr_rip     =  16,<br>+    gdb_gpr_rflags  =  17,<br>+    gdb_gpr_cs      =  18,<br>+    gdb_gpr_ss      =  19,<br>+    gdb_gpr_ds      =  20,<br>+    gdb_gpr_es      =  21,<br>+    gdb_gpr_fs      =  22,<br>+    gdb_gpr_gs      =  23,<br>+    gdb_fpu_stmm0   =  24,<br>+    gdb_fpu_stmm1   =  25,<br>+    gdb_fpu_stmm2   =  26,<br>+    gdb_fpu_stmm3   =  27,<br>+    gdb_fpu_stmm4   =  28,<br>+    gdb_fpu_stmm5   =  29,<br>+    gdb_fpu_stmm6   =  30,<br>+    gdb_fpu_stmm7   =  31,<br>+    gdb_fpu_fcw     =  32,<br>+    gdb_fpu_fsw     =  33,<br>+    gdb_fpu_ftw     =  34,<br>+    gdb_fpu_cs      =  35,<br>+    gdb_fpu_ip      =  36,<br>+    gdb_fpu_ds      =  37,<br>+    gdb_fpu_dp      =  38,<br>+    gdb_fpu_fop     =  39,<br>+    gdb_fpu_xmm0    =  40,<br>+    gdb_fpu_xmm1    =  41,<br>+    gdb_fpu_xmm2    =  42,<br>+    gdb_fpu_xmm3    =  43,<br>+    gdb_fpu_xmm4    =  44,<br>+    gdb_fpu_xmm5    =  45,<br>+    gdb_fpu_xmm6    =  46,<br>+    gdb_fpu_xmm7    =  47,<br>+    gdb_fpu_xmm8    =  48,<br>+    gdb_fpu_xmm9    =  49,<br>+    gdb_fpu_xmm10   =  50,<br>+    gdb_fpu_xmm11   =  51,<br>+    gdb_fpu_xmm12   =  52,<br>+    gdb_fpu_xmm13   =  53,<br>+    gdb_fpu_xmm14   =  54,<br>+    gdb_fpu_xmm15   =  55,<br>+    gdb_fpu_mxcsr   =  56<br>+};<br>+<br>+static const<br>+uint32_t g_gpr_regnums[k_num_gpr_registers] =<br>+{<br>+    gpr_rax,<br>+    gpr_rbx,<br>+    gpr_rcx,<br>+    gpr_rdx,<br>+    gpr_rdi,<br>+    gpr_rsi,<br>+    gpr_rbp,<br>+    gpr_rsp,<br>+    gpr_r8,<br>+    gpr_r9,<br>+    gpr_r10,<br>+    gpr_r11,<br>+    gpr_r12,<br>+    gpr_r13,<br>+    gpr_r14,<br>+    gpr_r15,<br>+    gpr_rip,<br>+    gpr_rflags,<br>+    gpr_cs,<br>+    gpr_fs,<br>+    gpr_gs,<br>+    gpr_ss,<br>+    gpr_ds,<br>+    gpr_es<br>+};<br>+<br>+static const uint32_t<br>+g_fpu_regnums[k_num_fpu_registers] =<br>+{<br>+    fpu_fcw,<br>+    fpu_fsw,<br>+    fpu_ftw,<br>+    fpu_fop,<br>+    fpu_ip,<br>+    fpu_cs,<br>+    fpu_dp,<br>+    fpu_ds,<br>+    fpu_mxcsr,<br>+    fpu_mxcsrmask,<br>+    fpu_stmm0,<br>+    fpu_stmm1,<br>+    fpu_stmm2,<br>+    fpu_stmm3,<br>+    fpu_stmm4,<br>+    fpu_stmm5,<br>+    fpu_stmm6,<br>+    fpu_stmm7,<br>+    fpu_xmm0,<br>+    fpu_xmm1,<br>+    fpu_xmm2,<br>+    fpu_xmm3,<br>+    fpu_xmm4,<br>+    fpu_xmm5,<br>+    fpu_xmm6,<br>+    fpu_xmm7,<br>+    fpu_xmm8,<br>+    fpu_xmm9,<br>+    fpu_xmm10,<br>+    fpu_xmm11,<br>+    fpu_xmm12,<br>+    fpu_xmm13,<br>+    fpu_xmm14,<br>+    fpu_xmm15<br>+};<br>+<br>+static const RegisterSet<br>+g_reg_sets[k_num_register_sets] =<br>+{<br>+    { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },<br>+    { "Floating Point Registers",  "fpu", k_num_fpu_registers, g_fpu_regnums }<br>+};<br>+<br>+// Computes the offset of the given GPR in the user data area.<br>+#define GPR_OFFSET(regname) \<br>+    (offsetof(RegisterContext_x86_64::UserArea, regs) + \<br>+     offsetof(GPR, regname))<br>+<br>+// Computes the offset of the given FPR in the user data area.<br>+#define FPR_OFFSET(regname) \<br>+    (offsetof(RegisterContext_x86_64::UserArea, i387) + \<br>+     offsetof(RegisterContext_x86_64::FPU, regname))<br>+<br>+// Number of bytes needed to represent a GPR.<br>+#define GPR_SIZE(reg) sizeof(((GPR*)NULL)->reg)<br>+<br>+// Number of bytes needed to represent a FPR.<br>+#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FPU*)NULL)->reg)<br>+<br>+// Number of bytes needed to represent the i'th FP register.<br>+#define FP_SIZE sizeof(((RegisterContext_x86_64::MMSReg*)NULL)->bytes)<br>+<br>+// Number of bytes needed to represent an XMM register.<br>+#define XMM_SIZE sizeof(RegisterContext_x86_64::XMMReg)<br>+<br>+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)        \<br>+    { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \<br>+      eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } }<br>+<br>+#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4)              \<br>+    { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \<br>+      eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } }<br>+<br>+#define DEFINE_FP(reg, i)                                          \<br>+    { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector,  \<br>+      eFormatVectorOfUInt8,                                        \<br>+      { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i,            \<br>+        LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } }<br>+<br>+#define DEFINE_XMM(reg, i)                                         \<br>+    { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \<br>+      eFormatVectorOfUInt8,                                        \<br>+      { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i,            \<br>+        LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } }<br>+<br>+#define REG_CONTEXT_SIZE (sizeof(GPR) + sizeof(RegisterContext_x86_64::FPU))<br>+<br>+static RegisterInfo<br>+g_register_infos[k_num_registers] =<br>+{<br>+    // General purpose registers.<br>+    DEFINE_GPR(rax,    NULL,    gcc_dwarf_gpr_rax,   gcc_dwarf_gpr_rax,   LLDB_INVALID_REGNUM,       gdb_gpr_rax),<br>+    DEFINE_GPR(rbx,    NULL,    gcc_dwarf_gpr_rbx,   gcc_dwarf_gpr_rbx,   LLDB_INVALID_REGNUM,       gdb_gpr_rbx),<br>+    DEFINE_GPR(rcx,    NULL,    gcc_dwarf_gpr_rcx,   gcc_dwarf_gpr_rcx,   LLDB_INVALID_REGNUM,       gdb_gpr_rcx),<br>+    DEFINE_GPR(rdx,    NULL,    gcc_dwarf_gpr_rdx,   gcc_dwarf_gpr_rdx,   LLDB_INVALID_REGNUM,       gdb_gpr_rdx),<br>+    DEFINE_GPR(rdi,    NULL,    gcc_dwarf_gpr_rdi,   gcc_dwarf_gpr_rdi,   LLDB_INVALID_REGNUM,       gdb_gpr_rdi),<br>+    DEFINE_GPR(rsi,    NULL,    gcc_dwarf_gpr_rsi,   gcc_dwarf_gpr_rsi,   LLDB_INVALID_REGNUM,       gdb_gpr_rsi),<br>+    DEFINE_GPR(rbp,    "fp",    gcc_dwarf_gpr_rbp,   gcc_dwarf_gpr_rbp,   LLDB_REGNUM_GENERIC_FP,    gdb_gpr_rbp),<br>+    DEFINE_GPR(rsp,    "sp",    gcc_dwarf_gpr_rsp,   gcc_dwarf_gpr_rsp,   LLDB_REGNUM_GENERIC_SP,    gdb_gpr_rsp),<br>+    DEFINE_GPR(r8,     NULL,    gcc_dwarf_gpr_r8,    gcc_dwarf_gpr_r8,    LLDB_INVALID_REGNUM,       gdb_gpr_r8),<br>+    DEFINE_GPR(r9,     NULL,    gcc_dwarf_gpr_r9,    gcc_dwarf_gpr_r9,    LLDB_INVALID_REGNUM,       gdb_gpr_r9),<br>+    DEFINE_GPR(r10,    NULL,    gcc_dwarf_gpr_r10,   gcc_dwarf_gpr_r10,   LLDB_INVALID_REGNUM,       gdb_gpr_r10),<br>+    DEFINE_GPR(r11,    NULL,    gcc_dwarf_gpr_r11,   gcc_dwarf_gpr_r11,   LLDB_INVALID_REGNUM,       gdb_gpr_r11),<br>+    DEFINE_GPR(r12,    NULL,    gcc_dwarf_gpr_r12,   gcc_dwarf_gpr_r12,   LLDB_INVALID_REGNUM,       gdb_gpr_r12),<br>+    DEFINE_GPR(r13,    NULL,    gcc_dwarf_gpr_r13,   gcc_dwarf_gpr_r13,   LLDB_INVALID_REGNUM,       gdb_gpr_r13),<br>+    DEFINE_GPR(r14,    NULL,    gcc_dwarf_gpr_r14,   gcc_dwarf_gpr_r14,   LLDB_INVALID_REGNUM,       gdb_gpr_r14),<br>+    DEFINE_GPR(r15,    NULL,    gcc_dwarf_gpr_r15,   gcc_dwarf_gpr_r15,   LLDB_INVALID_REGNUM,       gdb_gpr_r15),<br>+    DEFINE_GPR(rip,    "pc",    gcc_dwarf_gpr_rip,   gcc_dwarf_gpr_rip,   LLDB_REGNUM_GENERIC_PC,    gdb_gpr_rip),<br>+    DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags),<br>+    DEFINE_GPR(cs,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_cs),<br>+    DEFINE_GPR(fs,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_fs),<br>+    DEFINE_GPR(gs,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_gs),<br>+    DEFINE_GPR(ss,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_ss),<br>+    DEFINE_GPR(ds,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_ds),<br>+    DEFINE_GPR(es,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_es),<br>+<br>+    // i387 Floating point registers.<br>+    DEFINE_FPR(fcw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw),<br>+    DEFINE_FPR(fsw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw),<br>+    DEFINE_FPR(ftw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw),<br>+    DEFINE_FPR(fop,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop),<br>+    DEFINE_FPR(ip,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip),<br>+    // FIXME: Extract segment from ip.<br>+    DEFINE_FPR(ip,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs),<br>+    DEFINE_FPR(dp,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp),<br>+    // FIXME: Extract segment from dp.<br>+    DEFINE_FPR(dp,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds),<br>+    DEFINE_FPR(mxcsr,     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr),<br>+    DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),<br>+<br>+    // FP registers.<br>+    DEFINE_FP(stmm, 0),<br>+    DEFINE_FP(stmm, 1),<br>+    DEFINE_FP(stmm, 2),<br>+    DEFINE_FP(stmm, 3),<br>+    DEFINE_FP(stmm, 4),<br>+    DEFINE_FP(stmm, 5),<br>+    DEFINE_FP(stmm, 6),<br>+    DEFINE_FP(stmm, 7),<br>+<br>+    // XMM registers<br>+    DEFINE_XMM(xmm, 0),<br>+    DEFINE_XMM(xmm, 1),<br>+    DEFINE_XMM(xmm, 2),<br>+    DEFINE_XMM(xmm, 3),<br>+    DEFINE_XMM(xmm, 4),<br>+    DEFINE_XMM(xmm, 5),<br>+    DEFINE_XMM(xmm, 6),<br>+    DEFINE_XMM(xmm, 7),<br>+    DEFINE_XMM(xmm, 8),<br>+    DEFINE_XMM(xmm, 9),<br>+    DEFINE_XMM(xmm, 10),<br>+    DEFINE_XMM(xmm, 11),<br>+    DEFINE_XMM(xmm, 12),<br>+    DEFINE_XMM(xmm, 13),<br>+    DEFINE_XMM(xmm, 14),<br>+    DEFINE_XMM(xmm, 15)<br>+};<br>+<br>+static unsigned GetRegOffset(unsigned reg)<br>+{<br>+    assert(reg < k_num_registers && "Invalid register number.");<br>+    return g_register_infos[reg].byte_offset;<br>+}<br>+<br>+static unsigned GetRegSize(unsigned reg)<br>+{<br>+    assert(reg < k_num_registers && "Invalid register number.");<br>+    return g_register_infos[reg].byte_size;<br>+}<br>+<br>+static bool IsGPR(unsigned reg)<br>+{<br>+    return reg <= k_last_gpr;   // GPR's come first.<br>+}<br>+<br>+static bool IsFPR(unsigned reg)<br>+{<br>+    return (k_first_fpr <= reg && reg <= k_last_fpr);<br>+}<br>+<br>+RegisterContext_x86_64::RegisterContext_x86_64(Thread &thread,<br>+                                                         uint32_t concrete_frame_idx)<br>+    : RegisterContextPOSIX(thread, concrete_frame_idx)<br>+{<br>+}<br>+<br>+RegisterContext_x86_64::~RegisterContext_x86_64()<br>+{<br>+}<br>+<br>+ProcessMonitor &<br>+RegisterContext_x86_64::GetMonitor()<br>+{<br>+    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(CalculateProcess());<br>+    return process->GetMonitor();<br>+}<br>+<br>+void<br>+RegisterContext_x86_64::Invalidate()<br>+{<br>+}<br>+<br>+void<br>+RegisterContext_x86_64::InvalidateAllRegisters()<br>+{<br>+}<br>+<br>+size_t<br>+RegisterContext_x86_64::GetRegisterCount()<br>+{<br>+    return k_num_registers;<br>+}<br>+<br>+const RegisterInfo *<br>+RegisterContext_x86_64::GetRegisterInfoAtIndex(uint32_t reg)<br>+{<br>+    if (reg < k_num_registers)<br>+        return &g_register_infos[reg];<br>+    else<br>+        return NULL;<br>+}<br>+<br>+size_t<br>+RegisterContext_x86_64::GetRegisterSetCount()<br>+{<br>+    return k_num_register_sets;<br>+}<br>+<br>+const RegisterSet *<br>+RegisterContext_x86_64::GetRegisterSet(uint32_t set)<br>+{<br>+    if (set < k_num_register_sets)<br>+        return &g_reg_sets[set];<br>+    else<br>+        return NULL;<br>+}<br>+<br>+unsigned<br>+RegisterContext_x86_64::GetRegisterIndexFromOffset(unsigned offset)<br>+{<br>+    unsigned reg;<br>+    for (reg = 0; reg < k_num_registers; reg++)<br>+    {<br>+        if (g_register_infos[reg].byte_offset == offset)<br>+            break;<br>+    }<br>+    assert(reg < k_num_registers && "Invalid register offset.");<br>+    return reg;<br>+}<br>+<br>+const char *<br>+RegisterContext_x86_64::GetRegisterName(unsigned reg)<br>+{<br>+    assert(reg < k_num_registers && "Invalid register offset.");<br>+    return g_register_infos[reg].name;<br>+}<br>+<br>+bool<br>+RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info,<br>+                                          RegisterValue &value)<br>+{<br>+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];<br>+    ProcessMonitor &monitor = GetMonitor();<br>+    return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value);<br>+}<br>+<br>+bool<br>+RegisterContext_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp)<br>+{<br>+    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));<br>+    if (data_sp && ReadGPR () && ReadFPR ())<br>+    {<br>+        uint8_t *dst = data_sp->GetBytes();<br>+        ::memcpy (dst, &user.regs, sizeof(user.regs));<br>+        dst += sizeof(user.regs);<br>+<br>+        ::memcpy (dst, &user.i387, sizeof(user.i387));<br>+        return true;<br>+    }<br>+    return false;<br>+}<br>+<br>+bool<br>+RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info,<br>+                                           const lldb_private::RegisterValue &value)<br>+{<br>+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];<br>+    ProcessMonitor &monitor = GetMonitor();<br>+    return monitor.WriteRegisterValue(GetRegOffset(reg), value);<br>+}<br>+<br>+bool<br>+RegisterContext_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp)<br>+{<br>+    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)<br>+    {<br>+        const uint8_t *src = data_sp->GetBytes();<br>+        ::memcpy (&user.regs, src, sizeof(user.regs));<br>+        src += sizeof(user.regs);<br>+<br>+        ::memcpy (&user.i387, src, sizeof(user.i387));<br>+        return WriteGPR() & WriteFPR();<br>+    }<br>+    return false;<br>+}<br>+<br>+bool<br>+RegisterContext_x86_64::UpdateAfterBreakpoint()<br>+{<br>+    // PC points one byte past the int3 responsible for the breakpoint.<br>+    lldb::addr_t pc;<br>+<br>+    if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)<br>+        return false;<br>+<br>+    SetPC(pc - 1);<br>+    return true;<br>+}<br>+<br>+uint32_t<br>+RegisterContext_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind,<br>+                                                                 uint32_t num)<br>+{<br>+    if (kind == eRegisterKindGeneric)<br>+    {<br>+        switch (num)<br>+        {<br>+        case LLDB_REGNUM_GENERIC_PC:    return gpr_rip;<br>+        case LLDB_REGNUM_GENERIC_SP:    return gpr_rsp;<br>+        case LLDB_REGNUM_GENERIC_FP:    return gpr_rbp;<br>+        case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags;<br>+        case LLDB_REGNUM_GENERIC_RA:<br>+        default:<br>+            return LLDB_INVALID_REGNUM;<br>+        }<br>+    }<br>+<br>+    if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)<br>+    {<br>+        switch (num)<br>+        {<br>+        case gcc_dwarf_gpr_rax:  return gpr_rax;<br>+        case gcc_dwarf_gpr_rdx:  return gpr_rdx;<br>+        case gcc_dwarf_gpr_rcx:  return gpr_rcx;<br>+        case gcc_dwarf_gpr_rbx:  return gpr_rbx;<br>+        case gcc_dwarf_gpr_rsi:  return gpr_rsi;<br>+        case gcc_dwarf_gpr_rdi:  return gpr_rdi;<br>+        case gcc_dwarf_gpr_rbp:  return gpr_rbp;<br>+        case gcc_dwarf_gpr_rsp:  return gpr_rsp;<br>+        case gcc_dwarf_gpr_r8:   return gpr_r8;<br>+        case gcc_dwarf_gpr_r9:   return gpr_r9;<br>+        case gcc_dwarf_gpr_r10:  return gpr_r10;<br>+        case gcc_dwarf_gpr_r11:  return gpr_r11;<br>+        case gcc_dwarf_gpr_r12:  return gpr_r12;<br>+        case gcc_dwarf_gpr_r13:  return gpr_r13;<br>+        case gcc_dwarf_gpr_r14:  return gpr_r14;<br>+        case gcc_dwarf_gpr_r15:  return gpr_r15;<br>+        case gcc_dwarf_gpr_rip:  return gpr_rip;<br>+        case gcc_dwarf_fpu_xmm0: return fpu_xmm0;<br>+        case gcc_dwarf_fpu_xmm1: return fpu_xmm1;<br>+        case gcc_dwarf_fpu_xmm2: return fpu_xmm2;<br>+        case gcc_dwarf_fpu_xmm3: return fpu_xmm3;<br>+        case gcc_dwarf_fpu_xmm4: return fpu_xmm4;<br>+        case gcc_dwarf_fpu_xmm5: return fpu_xmm5;<br>+        case gcc_dwarf_fpu_xmm6: return fpu_xmm6;<br>+        case gcc_dwarf_fpu_xmm7: return fpu_xmm7;<br>+        case gcc_dwarf_fpu_xmm8: return fpu_xmm8;<br>+        case gcc_dwarf_fpu_xmm9: return fpu_xmm9;<br>+        case gcc_dwarf_fpu_xmm10: return fpu_xmm10;<br>+        case gcc_dwarf_fpu_xmm11: return fpu_xmm11;<br>+        case gcc_dwarf_fpu_xmm12: return fpu_xmm12;<br>+        case gcc_dwarf_fpu_xmm13: return fpu_xmm13;<br>+        case gcc_dwarf_fpu_xmm14: return fpu_xmm14;<br>+        case gcc_dwarf_fpu_xmm15: return fpu_xmm15;<br>+        case gcc_dwarf_fpu_stmm0: return fpu_stmm0;<br>+        case gcc_dwarf_fpu_stmm1: return fpu_stmm1;<br>+        case gcc_dwarf_fpu_stmm2: return fpu_stmm2;<br>+        case gcc_dwarf_fpu_stmm3: return fpu_stmm3;<br>+        case gcc_dwarf_fpu_stmm4: return fpu_stmm4;<br>+        case gcc_dwarf_fpu_stmm5: return fpu_stmm5;<br>+        case gcc_dwarf_fpu_stmm6: return fpu_stmm6;<br>+        case gcc_dwarf_fpu_stmm7: return fpu_stmm7;<br>+        default:<br>+            return LLDB_INVALID_REGNUM;<br>+        }<br>+    }<br>+<br>+    if (kind == eRegisterKindGDB)<br>+    {<br>+        switch (num)<br>+        {<br>+        case gdb_gpr_rax     : return gpr_rax;<br>+        case gdb_gpr_rbx     : return gpr_rbx;<br>+        case gdb_gpr_rcx     : return gpr_rcx;<br>+        case gdb_gpr_rdx     : return gpr_rdx;<br>+        case gdb_gpr_rsi     : return gpr_rsi;<br>+        case gdb_gpr_rdi     : return gpr_rdi;<br>+        case gdb_gpr_rbp     : return gpr_rbp;<br>+        case gdb_gpr_rsp     : return gpr_rsp;<br>+        case gdb_gpr_r8      : return gpr_r8;<br>+        case gdb_gpr_r9      : return gpr_r9;<br>+        case gdb_gpr_r10     : return gpr_r10;<br>+        case gdb_gpr_r11     : return gpr_r11;<br>+        case gdb_gpr_r12     : return gpr_r12;<br>+        case gdb_gpr_r13     : return gpr_r13;<br>+        case gdb_gpr_r14     : return gpr_r14;<br>+        case gdb_gpr_r15     : return gpr_r15;<br>+        case gdb_gpr_rip     : return gpr_rip;<br>+        case gdb_gpr_rflags  : return gpr_rflags;<br>+        case gdb_gpr_cs      : return gpr_cs;<br>+        case gdb_gpr_ss      : return gpr_ss;<br>+        case gdb_gpr_ds      : return gpr_ds;<br>+        case gdb_gpr_es      : return gpr_es;<br>+        case gdb_gpr_fs      : return gpr_fs;<br>+        case gdb_gpr_gs      : return gpr_gs;<br>+        case gdb_fpu_stmm0   : return fpu_stmm0;<br>+        case gdb_fpu_stmm1   : return fpu_stmm1;<br>+        case gdb_fpu_stmm2   : return fpu_stmm2;<br>+        case gdb_fpu_stmm3   : return fpu_stmm3;<br>+        case gdb_fpu_stmm4   : return fpu_stmm4;<br>+        case gdb_fpu_stmm5   : return fpu_stmm5;<br>+        case gdb_fpu_stmm6   : return fpu_stmm6;<br>+        case gdb_fpu_stmm7   : return fpu_stmm7;<br>+        case gdb_fpu_fcw     : return fpu_fcw;<br>+        case gdb_fpu_fsw     : return fpu_fsw;<br>+        case gdb_fpu_ftw     : return fpu_ftw;<br>+        case gdb_fpu_cs      : return fpu_cs;<br>+        case gdb_fpu_ip      : return fpu_ip;<br>+        case gdb_fpu_ds      : return fpu_ds;<br>+        case gdb_fpu_dp      : return fpu_dp;<br>+        case gdb_fpu_fop     : return fpu_fop;<br>+        case gdb_fpu_xmm0    : return fpu_xmm0;<br>+        case gdb_fpu_xmm1    : return fpu_xmm1;<br>+        case gdb_fpu_xmm2    : return fpu_xmm2;<br>+        case gdb_fpu_xmm3    : return fpu_xmm3;<br>+        case gdb_fpu_xmm4    : return fpu_xmm4;<br>+        case gdb_fpu_xmm5    : return fpu_xmm5;<br>+        case gdb_fpu_xmm6    : return fpu_xmm6;<br>+        case gdb_fpu_xmm7    : return fpu_xmm7;<br>+        case gdb_fpu_xmm8    : return fpu_xmm8;<br>+        case gdb_fpu_xmm9    : return fpu_xmm9;<br>+        case gdb_fpu_xmm10   : return fpu_xmm10;<br>+        case gdb_fpu_xmm11   : return fpu_xmm11;<br>+        case gdb_fpu_xmm12   : return fpu_xmm12;<br>+        case gdb_fpu_xmm13   : return fpu_xmm13;<br>+        case gdb_fpu_xmm14   : return fpu_xmm14;<br>+        case gdb_fpu_xmm15   : return fpu_xmm15;<br>+        case gdb_fpu_mxcsr   : return fpu_mxcsr;<br>+        default:<br>+            return LLDB_INVALID_REGNUM;<br>+        }<br>+    }<br>+    else if (kind == eRegisterKindLLDB)<br>+    {<br>+        return num;<br>+    }<br>+<br>+    return LLDB_INVALID_REGNUM;<br>+}<br>+<br>+bool<br>+RegisterContext_x86_64::HardwareSingleStep(bool enable)<br>+{<br>+    enum { TRACE_BIT = 0x100 };<br>+    uint64_t rflags;<br>+<br>+    if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL)<br>+        return false;<br>+    <br>+    if (enable)<br>+    {<br>+        if (rflags & TRACE_BIT)<br>+            return true;<br>+<br>+        rflags |= TRACE_BIT;<br>+    }<br>+    else<br>+    {<br>+        if (!(rflags & TRACE_BIT))<br>+            return false;<br>+<br>+        rflags &= ~TRACE_BIT;<br>+    }<br>+<br>+    return WriteRegisterFromUnsigned(gpr_rflags, rflags);<br>+}<br>+<br>+bool<br>+RegisterContext_x86_64::ReadGPR()<br>+{<br>+     ProcessMonitor &monitor = GetMonitor();<br>+     return monitor.ReadGPR(&user.regs);<br>+}<br>+<br>+bool<br>+RegisterContext_x86_64::ReadFPR()<br>+{<br>+    ProcessMonitor &monitor = GetMonitor();<br>+    return monitor.ReadFPR(&user.i387);<br>+}<br>+<br>+bool<br>+RegisterContext_x86_64::WriteGPR()<br>+{<br>+     ProcessMonitor &monitor = GetMonitor();<br>+     return monitor.WriteGPR(&user.regs);<br>+}<br>+<br>+bool<br>+RegisterContext_x86_64::WriteFPR()<br>+{<br>+    ProcessMonitor &monitor = GetMonitor();<br>+    return monitor.WriteFPR(&user.i387);<br>+}<br><br>Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h?rev=147613&view=auto">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h?rev=147613&view=auto</a><br>==============================================================================<br>--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h (added)<br>+++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h Thu Jan  5 15:48:15 2012<br>@@ -0,0 +1,143 @@<br>+//===-- RegisterContext_x86_64.h ---------------------------*- C++ -*-===//<br>+//<br>+//                     The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef liblldb_RegisterContext_x86_64_H_<br>+#define liblldb_RegisterContext_x86_64_H_<br>+<br>+#include "lldb/Core/Log.h"<br>+#include "RegisterContextPOSIX.h"<br>+<br>+#ifdef __FreeBSD__<br>+#include "RegisterContextFreeBSD_x86_64.h"<br>+#endif<br>+<br>+#ifdef __linux__<br>+#include "RegisterContextLinux_x86_64.h"<br>+#endif<br>+<br>+class ProcessMonitor;<br>+<br>+class RegisterContext_x86_64<br>+  : public RegisterContextPOSIX<br>+{<br>+public:<br>+    RegisterContext_x86_64 (lldb_private::Thread &thread,<br>+                                 uint32_t concrete_frame_idx);<br>+<br>+    ~RegisterContext_x86_64();<br>+<br>+    void<br>+    Invalidate();<br>+<br>+    void<br>+    InvalidateAllRegisters();<br>+<br>+    size_t<br>+    GetRegisterCount();<br>+<br>+    const lldb_private::RegisterInfo *<br>+    GetRegisterInfoAtIndex(uint32_t reg);<br>+<br>+    size_t<br>+    GetRegisterSetCount();<br>+<br>+    const lldb_private::RegisterSet *<br>+    GetRegisterSet(uint32_t set);<br>+<br>+    static unsigned<br>+    GetRegisterIndexFromOffset(unsigned offset);<br>+<br>+    static const char *<br>+    GetRegisterName(unsigned reg);<br>+<br>+    virtual bool<br>+    ReadRegister(const lldb_private::RegisterInfo *reg_info,<br>+                 lldb_private::RegisterValue &value);<br>+<br>+    bool<br>+    ReadAllRegisterValues(lldb::DataBufferSP &data_sp);<br>+<br>+    virtual bool<br>+    WriteRegister(const lldb_private::RegisterInfo *reg_info,<br>+                  const lldb_private::RegisterValue &value);<br>+<br>+    bool<br>+    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);<br>+<br>+    uint32_t<br>+    ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);<br>+<br>+    bool<br>+    HardwareSingleStep(bool enable);<br>+<br>+    bool<br>+    UpdateAfterBreakpoint();<br>+<br>+    struct MMSReg<br>+    {<br>+        uint8_t bytes[10];<br>+        uint8_t pad[6];<br>+    };<br>+<br>+    struct XMMReg<br>+    {<br>+        uint8_t bytes[16];<br>+    };<br>+<br>+    struct FPU<br>+    {<br>+        uint16_t fcw;<br>+        uint16_t fsw;<br>+        uint16_t ftw;<br>+        uint16_t fop;<br>+        uint64_t ip;<br>+        uint64_t dp;<br>+        uint32_t mxcsr;<br>+        uint32_t mxcsrmask;<br>+        MMSReg   stmm[8];<br>+        XMMReg   xmm[16];<br>+        uint32_t padding[24];<br>+    };<br>+<br>+    struct UserArea<br>+    {<br>+        GPR      regs;          // General purpose registers.<br>+        int32_t  fpvalid;       // True if FPU is being used.<br>+        int32_t  pad0;<br>+        FPU      i387;          // FPU registers.<br>+        uint64_t tsize;         // Text segment size.<br>+        uint64_t dsize;         // Data segment size.<br>+        uint64_t ssize;         // Stack segment size.<br>+        uint64_t start_code;    // VM address of text.<br>+        uint64_t start_stack;   // VM address of stack bottom (top in rsp).<br>+        int64_t  signal;        // Signal causing core dump.<br>+        int32_t  reserved;      // Unused.<br>+        int32_t  pad1;<br>+        uint64_t ar0;           // Location of GPR's.<br>+        FPU*     fpstate;       // Location of FPR's.<br>+        uint64_t magic;         // Identifier for core dumps.<br>+        char     u_comm[32];    // Command causing core dump.<br>+        uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7).<br>+        uint64_t error_code;    // CPU error code.<br>+        uint64_t fault_address; // Control register CR3.<br>+    };<br>+<br>+private:<br>+    UserArea user;<br>+<br>+    ProcessMonitor &GetMonitor();<br>+<br>+    bool ReadGPR();<br>+    bool ReadFPR();<br>+<br>+    bool WriteGPR();<br>+    bool WriteFPR();<br>+};<br>+<br>+#endif // #ifndef liblldb_RegisterContext_x86_64_H_<br><br><br>_______________________________________________<br>lldb-commits mailing list<br><a href="mailto:lldb-commits@cs.uiuc.edu">lldb-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits<br></div></blockquote></div><br></div></body></html>