<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)®s, 0)) < 0) {<br>+ m_result = false;<br>+ } else {<br>+ if (m_size == sizeof(uintptr_t))<br>+ m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset);<br>+ else <br>+ memcpy(&m_value, (((caddr_t)®s) + 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)®s, 0) < 0) {<br>+ m_result = false;<br>+ return;<br>+ }<br>+ *(uintptr_t *)(((caddr_t)®s) + m_offset) = (uintptr_t)m_value.GetAsUInt64();<br>+ if (PTRACE(PT_SETREGS, pid, (caddr_t)®s, 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>