[Lldb-commits] [PATCH] Merge of Linux and FreeBSD
dawn at burble.org
dawn at burble.org
Wed Jan 4 15:26:04 PST 2012
This patch combines common code from Linux and FreeBSD into
a new POSIX platform. It also contains fixes for 64bit FreeBSD.
The patch is based on changes by Mark Peek <mp at FreeBSD.org> and
"K. Macy" <kmacy at freebsd.org> in their
github repo located at https://github.com/fbsd/lldb.
Ok to commit?
Thanks!
-Dawn
-------------- next part --------------
Index: include/lldb/Host/Host.h
===================================================================
--- include/lldb/Host/Host.h (revision 147560)
+++ include/lldb/Host/Host.h (working copy)
@@ -355,7 +355,10 @@
static Error
LaunchProcess (ProcessLaunchInfo &launch_info);
-
+
+ static lldb::DataBufferSP
+ GetAuxvData (lldb_private::Process *process);
+
static lldb::TargetSP
GetDummyTarget (Debugger &debugger);
Index: source/Plugins/Platform/Linux/PlatformLinux.h
===================================================================
--- source/Plugins/Platform/Linux/PlatformLinux.h (revision 147560)
+++ source/Plugins/Platform/Linux/PlatformLinux.h (working copy)
@@ -104,6 +104,7 @@
Attach(ProcessAttachInfo &attach_info, Debugger &debugger,
Target *target, Listener &listener, Error &error);
+ // Linux processes can not be launched by spawning and attaching.
virtual bool
CanDebugProcess ()
{
Index: source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
===================================================================
--- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (revision 147560)
+++ source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (working copy)
@@ -27,16 +27,13 @@
Platform *
PlatformFreeBSD::CreateInstance ()
{
- // The only time we create an instance is when we are creating a remote
- // freebsd platform
- const bool is_host = false;
- return new PlatformFreeBSD (is_host);
+ return new PlatformFreeBSD (true);
}
const char *
PlatformFreeBSD::GetPluginNameStatic()
{
- return "PlatformFreeBSD";
+ return "plugin.platform.freebsd";
}
const char *
@@ -66,7 +63,7 @@
{
#if defined (__FreeBSD__)
PlatformSP default_platform_sp (CreateInstance());
- //default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
+ default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
Platform::SetDefaultPlatform (default_platform_sp);
#endif
PluginManager::RegisterPlugin(PlatformFreeBSD::GetShortPluginNameStatic(false),
@@ -79,7 +76,7 @@
void
PlatformFreeBSD::Terminate ()
{
- PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance);
+ PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance);
}
//------------------------------------------------------------------
@@ -385,17 +382,16 @@
bool
PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
- bool sucess = false;
+ bool success = false;
if (IsHost())
{
- sucess = Platform::GetProcessInfo (pid, process_info);
+ success = Platform::GetProcessInfo (pid, process_info);
}
- else
+ else if (m_remote_platform_sp)
{
- if (m_remote_platform_sp)
- sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info);
+ success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
}
- return sucess;
+ return success;
}
@@ -438,11 +434,11 @@
}
lldb::ProcessSP
-PlatformFreeBSD::Attach(lldb::pid_t pid,
- Debugger &debugger,
- Target *target,
- Listener &listener,
- Error &error)
+PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
+ Debugger &debugger,
+ Target *target,
+ Listener &listener,
+ Error &error)
{
lldb::ProcessSP process_sp;
if (IsHost())
@@ -457,6 +453,7 @@
emptyFileSpec,
emptyArchSpec,
false,
+ m_remote_platform_sp,
new_target_sp);
target = new_target_sp.get();
}
@@ -472,13 +469,13 @@
process_sp = target->CreateProcess (listener, "gdb-remote");
if (process_sp)
- error = process_sp->Attach (pid);
+ error = process_sp->Attach (attach_info);
}
}
else
{
if (m_remote_platform_sp)
- process_sp = m_remote_platform_sp->Attach (pid, debugger, target, listener, error);
+ process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
else
error.SetErrorString ("the platform is not currently connected");
}
Index: source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
===================================================================
--- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (revision 147560)
+++ source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (working copy)
@@ -132,12 +132,16 @@
LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info);
virtual lldb::ProcessSP
- Attach(lldb::pid_t pid,
+ Attach(lldb_private::ProcessAttachInfo &attach_info,
lldb_private::Debugger &debugger,
lldb_private::Target *target,
lldb_private::Listener &listener,
lldb_private::Error &error);
+ // FreeBSD processes can not be launched by spawning and attaching.
+ virtual bool
+ CanDebugProcess () { return false; }
+
// Only on PlatformMacOSX:
virtual lldb_private::Error
GetFile (const lldb_private::FileSpec &platform_file,
Index: source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp
===================================================================
--- source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (revision 147560)
+++ source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (working copy)
@@ -1,191 +0,0 @@
-//===-- AuxVector.cpp -------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Target/Process.h"
-
-#include "AuxVector.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-static bool
-GetMaxU64(DataExtractor &data,
- uint32_t *offset, uint64_t *value, unsigned int byte_size)
-{
- uint32_t saved_offset = *offset;
- *value = data.GetMaxU64(offset, byte_size);
- return *offset != saved_offset;
-}
-
-static bool
-ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry,
- uint32_t *offset, unsigned int byte_size)
-{
- if (!GetMaxU64(data, offset, &entry.type, byte_size))
- return false;
-
- if (!GetMaxU64(data, offset, &entry.value, byte_size))
- return false;
-
- return true;
-}
-
-DataBufferSP
-AuxVector::GetAuxvData()
-{
- static const size_t path_size = 128;
- static char path[path_size];
- DataBufferSP buf_sp;
- int fd;
-
- // Ideally, we would simply create a FileSpec and call ReadFileContents.
- // However, files in procfs have zero size (since they are, in general,
- // dynamically generated by the kernel) which is incompatible with the
- // current ReadFileContents implementation. Therefore we simply stream the
- // data into a DataBuffer ourselves.
- if (snprintf(path, path_size, "/proc/%d/auxv", m_process->GetID()) < 0)
- return buf_sp;
-
- if ((fd = open(path, O_RDONLY, 0)) < 0)
- return buf_sp;
-
- size_t bytes_read = 0;
- std::auto_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
- for (;;)
- {
- size_t avail = buf_ap->GetByteSize() - bytes_read;
- ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail);
-
- if (status < 0)
- break;
-
- bytes_read += status;
-
- if (status == 0)
- {
- buf_ap->SetByteSize(bytes_read);
- buf_sp.reset(buf_ap.release());
- break;
- }
-
- if (avail - status == 0)
- buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
- }
-
- return buf_sp;
-}
-
-void
-AuxVector::ParseAuxv(DataExtractor &data)
-{
- const unsigned int byte_size = m_process->GetAddressByteSize();
- uint32_t offset = 0;
-
- for (;;)
- {
- Entry entry;
-
- if (!ParseAuxvEntry(data, entry, &offset, byte_size))
- break;
-
- if (entry.type == AT_NULL)
- break;
-
- if (entry.type == AT_IGNORE)
- continue;
-
- m_auxv.push_back(entry);
- }
-}
-
-AuxVector::AuxVector(Process *process)
- : m_process(process)
-{
- DataExtractor data;
- LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
-
- data.SetData(GetAuxvData());
- data.SetByteOrder(m_process->GetByteOrder());
- data.SetAddressByteSize(m_process->GetAddressByteSize());
-
- ParseAuxv(data);
-
- if (log)
- DumpToLog(log);
-}
-
-AuxVector::iterator
-AuxVector::FindEntry(EntryType type) const
-{
- for (iterator I = begin(); I != end(); ++I)
- {
- if (I->type == static_cast<uint64_t>(type))
- return I;
- }
-
- return end();
-}
-
-void
-AuxVector::DumpToLog(LogSP log) const
-{
- if (!log)
- return;
-
- log->PutCString("AuxVector: ");
- for (iterator I = begin(); I != end(); ++I)
- {
- log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value);
- }
-}
-
-const char *
-AuxVector::GetEntryName(EntryType type)
-{
- const char *name;
-
-#define ENTRY_NAME(_type) _type: name = #_type
- switch (type)
- {
- default:
- name = "unkown";
- break;
-
- case ENTRY_NAME(AT_NULL); break;
- case ENTRY_NAME(AT_IGNORE); break;
- case ENTRY_NAME(AT_EXECFD); break;
- case ENTRY_NAME(AT_PHDR); break;
- case ENTRY_NAME(AT_PHENT); break;
- case ENTRY_NAME(AT_PHNUM); break;
- case ENTRY_NAME(AT_PAGESZ); break;
- case ENTRY_NAME(AT_BASE); break;
- case ENTRY_NAME(AT_FLAGS); break;
- case ENTRY_NAME(AT_ENTRY); break;
- case ENTRY_NAME(AT_NOTELF); break;
- case ENTRY_NAME(AT_UID); break;
- case ENTRY_NAME(AT_EUID); break;
- case ENTRY_NAME(AT_GID); break;
- case ENTRY_NAME(AT_EGID); break;
- case ENTRY_NAME(AT_CLKTCK); break;
- }
-#undef ENTRY_NAME
-
- return name;
-}
-
Index: source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp
===================================================================
--- source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (revision 147560)
+++ source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (working copy)
@@ -1,322 +0,0 @@
-//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Core/ArchSpec.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Target.h"
-
-#include "DYLDRendezvous.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-/// Locates the address of the rendezvous structure. Returns the address on
-/// success and LLDB_INVALID_ADDRESS on failure.
-static addr_t
-ResolveRendezvousAddress(Process *process)
-{
- addr_t info_location;
- addr_t info_addr;
- Error error;
- size_t size;
-
- info_location = process->GetImageInfoAddress();
-
- if (info_location == LLDB_INVALID_ADDRESS)
- return LLDB_INVALID_ADDRESS;
-
- info_addr = 0;
- size = process->DoReadMemory(info_location, &info_addr,
- process->GetAddressByteSize(), error);
- if (size != process->GetAddressByteSize() || error.Fail())
- return LLDB_INVALID_ADDRESS;
-
- if (info_addr == 0)
- return LLDB_INVALID_ADDRESS;
-
- return info_addr;
-}
-
-DYLDRendezvous::DYLDRendezvous(Process *process)
- : m_process(process),
- m_rendezvous_addr(LLDB_INVALID_ADDRESS),
- m_current(),
- m_previous(),
- m_soentries(),
- m_added_soentries(),
- m_removed_soentries()
-{
-}
-
-bool
-DYLDRendezvous::Resolve()
-{
- const size_t word_size = 4;
- Rendezvous info;
- size_t address_size;
- size_t padding;
- addr_t info_addr;
- addr_t cursor;
-
- address_size = m_process->GetAddressByteSize();
- padding = address_size - word_size;
-
- if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
- cursor = info_addr = ResolveRendezvousAddress(m_process);
- else
- cursor = info_addr = m_rendezvous_addr;
-
- if (cursor == LLDB_INVALID_ADDRESS)
- return false;
-
- if (!(cursor = ReadMemory(cursor, &info.version, word_size)))
- return false;
-
- if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size)))
- return false;
-
- if (!(cursor = ReadMemory(cursor, &info.brk, address_size)))
- return false;
-
- if (!(cursor = ReadMemory(cursor, &info.state, word_size)))
- return false;
-
- if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size)))
- return false;
-
- // The rendezvous was successfully read. Update our internal state.
- m_rendezvous_addr = info_addr;
- m_previous = m_current;
- m_current = info;
-
- return UpdateSOEntries();
-}
-
-bool
-DYLDRendezvous::IsValid()
-{
- return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
-}
-
-bool
-DYLDRendezvous::UpdateSOEntries()
-{
- SOEntry entry;
-
- if (m_current.map_addr == 0)
- return false;
-
- // When the previous and current states are consistent this is the first
- // time we have been asked to update. Just take a snapshot of the currently
- // loaded modules.
- if (m_previous.state == eConsistent && m_current.state == eConsistent)
- return TakeSnapshot(m_soentries);
-
- // If we are about to add or remove a shared object clear out the current
- // state and take a snapshot of the currently loaded images.
- if (m_current.state == eAdd || m_current.state == eDelete)
- {
- assert(m_previous.state == eConsistent);
- m_soentries.clear();
- m_added_soentries.clear();
- m_removed_soentries.clear();
- return TakeSnapshot(m_soentries);
- }
- assert(m_current.state == eConsistent);
-
- // Otherwise check the previous state to determine what to expect and update
- // accordingly.
- if (m_previous.state == eAdd)
- return UpdateSOEntriesForAddition();
- else if (m_previous.state == eDelete)
- return UpdateSOEntriesForDeletion();
-
- return false;
-}
-
-bool
-DYLDRendezvous::UpdateSOEntriesForAddition()
-{
- SOEntry entry;
- iterator pos;
-
- assert(m_previous.state == eAdd);
-
- if (m_current.map_addr == 0)
- return false;
-
- for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
- {
- if (!ReadSOEntryFromMemory(cursor, entry))
- return false;
-
- if (entry.path.empty())
- continue;
-
- pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
- if (pos == m_soentries.end())
- {
- m_soentries.push_back(entry);
- m_added_soentries.push_back(entry);
- }
- }
-
- return true;
-}
-
-bool
-DYLDRendezvous::UpdateSOEntriesForDeletion()
-{
- SOEntryList entry_list;
- iterator pos;
-
- assert(m_previous.state == eDelete);
-
- if (!TakeSnapshot(entry_list))
- return false;
-
- for (iterator I = begin(); I != end(); ++I)
- {
- pos = std::find(entry_list.begin(), entry_list.end(), *I);
- if (pos == entry_list.end())
- m_removed_soentries.push_back(*I);
- }
-
- m_soentries = entry_list;
- return true;
-}
-
-bool
-DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
-{
- SOEntry entry;
-
- if (m_current.map_addr == 0)
- return false;
-
- for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
- {
- if (!ReadSOEntryFromMemory(cursor, entry))
- return false;
-
- if (entry.path.empty())
- continue;
-
- entry_list.push_back(entry);
- }
-
- return true;
-}
-
-addr_t
-DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size)
-{
- size_t bytes_read;
- Error error;
-
- bytes_read = m_process->DoReadMemory(addr, dst, size, error);
- if (bytes_read != size || error.Fail())
- return 0;
-
- return addr + bytes_read;
-}
-
-std::string
-DYLDRendezvous::ReadStringFromMemory(addr_t addr)
-{
- std::string str;
- Error error;
- size_t size;
- char c;
-
- if (addr == LLDB_INVALID_ADDRESS)
- return std::string();
-
- for (;;) {
- size = m_process->DoReadMemory(addr, &c, 1, error);
- if (size != 1 || error.Fail())
- return std::string();
- if (c == 0)
- break;
- else {
- str.push_back(c);
- addr++;
- }
- }
-
- return str;
-}
-
-bool
-DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
-{
- size_t address_size = m_process->GetAddressByteSize();
-
- entry.clear();
-
- if (!(addr = ReadMemory(addr, &entry.base_addr, address_size)))
- return false;
-
- if (!(addr = ReadMemory(addr, &entry.path_addr, address_size)))
- return false;
-
- if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size)))
- return false;
-
- if (!(addr = ReadMemory(addr, &entry.next, address_size)))
- return false;
-
- if (!(addr = ReadMemory(addr, &entry.prev, address_size)))
- return false;
-
- entry.path = ReadStringFromMemory(entry.path_addr);
-
- return true;
-}
-
-void
-DYLDRendezvous::DumpToLog(LogSP log) const
-{
- int state = GetState();
-
- if (!log)
- return;
-
- log->PutCString("DYLDRendezvous:");
- log->Printf(" Address: %lx", GetRendezvousAddress());
- log->Printf(" Version: %d", GetVersion());
- log->Printf(" Link : %lx", GetLinkMapAddress());
- log->Printf(" Break : %lx", GetBreakAddress());
- log->Printf(" LDBase : %lx", GetLDBase());
- log->Printf(" State : %s",
- (state == eConsistent) ? "consistent" :
- (state == eAdd) ? "add" :
- (state == eDelete) ? "delete" : "unknown");
-
- iterator I = begin();
- iterator E = end();
-
- if (I != E)
- log->PutCString("DYLDRendezvous SOEntries:");
-
- for (int i = 1; I != E; ++I, ++i)
- {
- log->Printf("\n SOEntry [%d] %s", i, I->path.c_str());
- log->Printf(" Base : %lx", I->base_addr);
- log->Printf(" Path : %lx", I->path_addr);
- log->Printf(" Dyn : %lx", I->dyn_addr);
- log->Printf(" Next : %lx", I->next);
- log->Printf(" Prev : %lx", I->prev);
- }
-}
Index: source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h
===================================================================
--- source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (revision 147560)
+++ source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (working copy)
@@ -1,97 +0,0 @@
-//===-- AuxVector.h ---------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_AuxVector_H_
-#define liblldb_AuxVector_H_
-
-// C Includes
-// C++ Includes
-#include <vector>
-
-// Other libraries and framework includes
-#include "lldb/lldb-forward-rtti.h"
-
-namespace lldb_private {
-class DataExtractor;
-}
-
-/// @class AuxVector
-/// @brief Represents a processes auxiliary vector.
-///
-/// When a process is loaded on Linux a vector of values is placed onto the
-/// stack communicating operating system specific information. On construction
-/// this class locates and parses this information and provides a simple
-/// read-only interface to the entries found.
-class AuxVector {
-
-public:
- AuxVector(lldb_private::Process *process);
-
- struct Entry {
- uint64_t type;
- uint64_t value;
-
- Entry() : type(0), value(0) { }
- };
-
- /// Constants describing the type of entry.
- enum EntryType {
- AT_NULL = 0, ///< End of auxv.
- AT_IGNORE = 1, ///< Ignore entry.
- AT_EXECFD = 2, ///< File descriptor of program.
- AT_PHDR = 3, ///< Program headers.
- AT_PHENT = 4, ///< Size of program header.
- AT_PHNUM = 5, ///< Number of program headers.
- AT_PAGESZ = 6, ///< Page size.
- AT_BASE = 7, ///< Interpreter base address.
- AT_FLAGS = 8, ///< Flags.
- AT_ENTRY = 9, ///< Program entry point.
- AT_NOTELF = 10, ///< Set if program is not an ELF.
- AT_UID = 11, ///< UID.
- AT_EUID = 12, ///< Effective UID.
- AT_GID = 13, ///< GID.
- AT_EGID = 14, ///< Effective GID.
- AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)).
- };
-
-private:
- typedef std::vector<Entry> EntryVector;
-
-public:
- typedef EntryVector::const_iterator iterator;
-
- iterator begin() const { return m_auxv.begin(); }
- iterator end() const { return m_auxv.end(); }
-
- iterator
- FindEntry(EntryType type) const;
-
- static const char *
- GetEntryName(const Entry &entry) {
- return GetEntryName(static_cast<EntryType>(entry.type));
- }
-
- static const char *
- GetEntryName(EntryType type);
-
- void
- DumpToLog(lldb::LogSP log) const;
-
-private:
- lldb_private::Process *m_process;
- EntryVector m_auxv;
-
- lldb::DataBufferSP
- GetAuxvData();
-
- void
- ParseAuxv(lldb_private::DataExtractor &data);
-};
-
-#endif
Index: source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h
===================================================================
--- source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (revision 147560)
+++ source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (working copy)
@@ -1,227 +0,0 @@
-//===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_Rendezvous_H_
-#define liblldb_Rendezvous_H_
-
-// C Includes
-// C++ Includes
-#include <list>
-#include <string>
-
-// Other libraries and framework includes
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-types.h"
-
-namespace lldb_private {
-class Process;
-}
-
-/// @class DYLDRendezvous
-/// @brief Interface to the runtime linker.
-///
-/// A structure is present in a processes memory space which is updated by the
-/// runtime liker each time a module is loaded or unloaded. This class provides
-/// an interface to this structure and maintains a consistent snapshot of the
-/// currently loaded modules.
-class DYLDRendezvous {
-
- // This structure is used to hold the contents of the debug rendezvous
- // information (struct r_debug) as found in the inferiors memory. Note that
- // the layout of this struct is not binary compatible, it is simply large
- // enough to hold the information on both 32 and 64 bit platforms.
- struct Rendezvous {
- uint64_t version;
- lldb::addr_t map_addr;
- lldb::addr_t brk;
- uint64_t state;
- lldb::addr_t ldbase;
-
- Rendezvous()
- : version(0), map_addr(0), brk(0), state(0), ldbase(0) { }
- };
-
-public:
- DYLDRendezvous(lldb_private::Process *process);
-
- /// Update the internal snapshot of runtime linker rendezvous and recompute
- /// the currently loaded modules.
- ///
- /// This method should be called once one start up, then once each time the
- /// runtime linker enters the function given by GetBreakAddress().
- ///
- /// @returns true on success and false on failure.
- ///
- /// @see GetBreakAddress().
- bool
- Resolve();
-
- /// @returns true if this rendezvous has been located in the inferiors
- /// address space and false otherwise.
- bool
- IsValid();
-
- /// @returns the address of the rendezvous structure in the inferiors
- /// address space.
- lldb::addr_t
- GetRendezvousAddress() const { return m_rendezvous_addr; }
-
- /// @returns the version of the rendezvous protocol being used.
- int
- GetVersion() const { return m_current.version; }
-
- /// @returns address in the inferiors address space containing the linked
- /// list of shared object descriptors.
- lldb::addr_t
- GetLinkMapAddress() const { return m_current.map_addr; }
-
- /// A breakpoint should be set at this address and Resolve called on each
- /// hit.
- ///
- /// @returns the address of a function called by the runtime linker each
- /// time a module is loaded/unloaded, or about to be loaded/unloaded.
- ///
- /// @see Resolve()
- lldb::addr_t
- GetBreakAddress() const { return m_current.brk; }
-
- /// Returns the current state of the rendezvous structure.
- int
- GetState() const { return m_current.state; }
-
- /// @returns the base address of the runtime linker in the inferiors address
- /// space.
- lldb::addr_t
- GetLDBase() const { return m_current.ldbase; }
-
- /// @returns true if modules have been loaded into the inferior since the
- /// last call to Resolve().
- bool
- ModulesDidLoad() const { return !m_added_soentries.empty(); }
-
- /// @returns true if modules have been unloaded from the inferior since the
- /// last call to Resolve().
- bool
- ModulesDidUnload() const { return !m_removed_soentries.empty(); }
-
- void
- DumpToLog(lldb::LogSP log) const;
-
- /// @brief Constants describing the state of the rendezvous.
- ///
- /// @see GetState().
- enum RendezvousState {
- eConsistent,
- eAdd,
- eDelete
- };
-
- /// @brief Structure representing the shared objects currently loaded into
- /// the inferior process.
- ///
- /// This object is a rough analogue to the struct link_map object which
- /// actually lives in the inferiors memory.
- struct SOEntry {
- lldb::addr_t base_addr; ///< Base address of the loaded object.
- lldb::addr_t path_addr; ///< String naming the shared object.
- lldb::addr_t dyn_addr; ///< Dynamic section of shared object.
- lldb::addr_t next; ///< Address of next so_entry.
- lldb::addr_t prev; ///< Address of previous so_entry.
- std::string path; ///< File name of shared object.
-
- SOEntry() { clear(); }
-
- bool operator ==(const SOEntry &entry) {
- return this->path == entry.path;
- }
-
- void clear() {
- base_addr = 0;
- path_addr = 0;
- dyn_addr = 0;
- next = 0;
- prev = 0;
- path.clear();
- }
- };
-
-protected:
- typedef std::list<SOEntry> SOEntryList;
-
-public:
- typedef SOEntryList::const_iterator iterator;
-
- /// Iterators over all currently loaded modules.
- iterator begin() const { return m_soentries.begin(); }
- iterator end() const { return m_soentries.end(); }
-
- /// Iterators over all modules loaded into the inferior since the last call
- /// to Resolve().
- iterator loaded_begin() const { return m_added_soentries.begin(); }
- iterator loaded_end() const { return m_added_soentries.end(); }
-
- /// Iterators over all modules unloaded from the inferior since the last
- /// call to Resolve().
- iterator unloaded_begin() const { return m_removed_soentries.begin(); }
- iterator unloaded_end() const { return m_removed_soentries.end(); }
-
-protected:
- lldb_private::Process *m_process;
-
- /// Location of the r_debug structure in the inferiors address space.
- lldb::addr_t m_rendezvous_addr;
-
- /// Current and previous snapshots of the rendezvous structure.
- Rendezvous m_current;
- Rendezvous m_previous;
-
- /// List of SOEntry objects corresponding to the current link map state.
- SOEntryList m_soentries;
-
- /// List of SOEntry's added to the link map since the last call to Resolve().
- SOEntryList m_added_soentries;
-
- /// List of SOEntry's removed from the link map since the last call to
- /// Resolve().
- SOEntryList m_removed_soentries;
-
- /// Reads @p size bytes from the inferiors address space starting at @p
- /// addr.
- ///
- /// @returns addr + size if the read was successful and false otherwise.
- lldb::addr_t
- ReadMemory(lldb::addr_t addr, void *dst, size_t size);
-
- /// Reads a null-terminated C string from the memory location starting at @p
- /// addr.
- std::string
- ReadStringFromMemory(lldb::addr_t addr);
-
- /// Reads an SOEntry starting at @p addr.
- bool
- ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
-
- /// Updates the current set of SOEntries, the set of added entries, and the
- /// set of removed entries.
- bool
- UpdateSOEntries();
-
- bool
- UpdateSOEntriesForAddition();
-
- bool
- UpdateSOEntriesForDeletion();
-
- /// Reads the current list of shared objects according to the link map
- /// supplied by the runtime linker.
- bool
- TakeSnapshot(SOEntryList &entry_list);
-};
-
-#endif
Index: source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp
===================================================================
--- source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (revision 147560)
+++ source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (working copy)
@@ -1,423 +0,0 @@
-//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Target/ThreadPlanRunToAddress.h"
-
-#include "AuxVector.h"
-#include "DynamicLoaderLinuxDYLD.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-void
-DynamicLoaderLinuxDYLD::Initialize()
-{
- PluginManager::RegisterPlugin(GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance);
-}
-
-void
-DynamicLoaderLinuxDYLD::Terminate()
-{
-}
-
-const char *
-DynamicLoaderLinuxDYLD::GetPluginName()
-{
- return "DynamicLoaderLinuxDYLD";
-}
-
-const char *
-DynamicLoaderLinuxDYLD::GetShortPluginName()
-{
- return "linux-dyld";
-}
-
-const char *
-DynamicLoaderLinuxDYLD::GetPluginNameStatic()
-{
- return "dynamic-loader.linux-dyld";
-}
-
-const char *
-DynamicLoaderLinuxDYLD::GetPluginDescriptionStatic()
-{
- return "Dynamic loader plug-in that watches for shared library "
- "loads/unloads in Linux processes.";
-}
-
-void
-DynamicLoaderLinuxDYLD::GetPluginCommandHelp(const char *command, Stream *strm)
-{
-}
-
-uint32_t
-DynamicLoaderLinuxDYLD::GetPluginVersion()
-{
- return 1;
-}
-
-DynamicLoader *
-DynamicLoaderLinuxDYLD::CreateInstance(Process *process, bool force)
-{
- bool create = force;
- if (!create)
- {
- const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
- if (triple_ref.getOS() == llvm::Triple::Linux)
- create = true;
- }
-
- if (create)
- return new DynamicLoaderLinuxDYLD (process);
- return NULL;
-}
-
-DynamicLoaderLinuxDYLD::DynamicLoaderLinuxDYLD(Process *process)
- : DynamicLoader(process),
- m_rendezvous(process),
- m_load_offset(LLDB_INVALID_ADDRESS),
- m_entry_point(LLDB_INVALID_ADDRESS),
- m_auxv(NULL)
-{
-}
-
-DynamicLoaderLinuxDYLD::~DynamicLoaderLinuxDYLD()
-{
-}
-
-void
-DynamicLoaderLinuxDYLD::DidAttach()
-{
- ModuleSP executable;
- addr_t load_offset;
-
- m_auxv.reset(new AuxVector(m_process));
-
- executable = m_process->GetTarget().GetExecutableModule();
- load_offset = ComputeLoadOffset();
-
- if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)
- {
- ModuleList module_list;
- module_list.Append(executable);
- UpdateLoadedSections(executable, load_offset);
- m_process->GetTarget().ModulesDidLoad(module_list);
- }
-}
-
-void
-DynamicLoaderLinuxDYLD::DidLaunch()
-{
- ModuleSP executable;
- addr_t load_offset;
-
- m_auxv.reset(new AuxVector(m_process));
-
- executable = m_process->GetTarget().GetExecutableModule();
- load_offset = ComputeLoadOffset();
-
- if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)
- {
- ModuleList module_list;
- module_list.Append(executable);
- UpdateLoadedSections(executable, load_offset);
- ProbeEntry();
- m_process->GetTarget().ModulesDidLoad(module_list);
- }
-}
-
-Error
-DynamicLoaderLinuxDYLD::ExecutePluginCommand(Args &command, Stream *strm)
-{
- return Error();
-}
-
-Log *
-DynamicLoaderLinuxDYLD::EnablePluginLogging(Stream *strm, Args &command)
-{
- return NULL;
-}
-
-Error
-DynamicLoaderLinuxDYLD::CanLoadImage()
-{
- return Error();
-}
-
-void
-DynamicLoaderLinuxDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
-{
- ObjectFile *obj_file = module->GetObjectFile();
- SectionList *sections = obj_file->GetSectionList();
- SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
- const size_t num_sections = sections->GetSize();
-
- for (unsigned i = 0; i < num_sections; ++i)
- {
- Section *section = sections->GetSectionAtIndex(i).get();
- lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr;
- lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section);
-
- // If the file address of the section is zero then this is not an
- // allocatable/loadable section (property of ELF sh_addr). Skip it.
- if (new_load_addr == base_addr)
- continue;
-
- if (old_load_addr == LLDB_INVALID_ADDRESS ||
- old_load_addr != new_load_addr)
- load_list.SetSectionLoadAddress(section, new_load_addr);
- }
-}
-
-void
-DynamicLoaderLinuxDYLD::ProbeEntry()
-{
- Breakpoint *entry_break;
- addr_t entry;
-
- if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
- return;
-
- entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get();
- entry_break->SetCallback(EntryBreakpointHit, this, true);
-}
-
-// The runtime linker has run and initialized the rendezvous structure once the
-// process has hit its entry point. When we hit the corresponding breakpoint we
-// interrogate the rendezvous structure to get the load addresses of all
-// dependent modules for the process. Similarly, we can discover the runtime
-// linker function and setup a breakpoint to notify us of any dynamically loaded
-// modules (via dlopen).
-bool
-DynamicLoaderLinuxDYLD::EntryBreakpointHit(void *baton,
- StoppointCallbackContext *context,
- user_id_t break_id,
- user_id_t break_loc_id)
-{
- DynamicLoaderLinuxDYLD* dyld_instance;
-
- dyld_instance = static_cast<DynamicLoaderLinuxDYLD*>(baton);
- dyld_instance->LoadAllCurrentModules();
- dyld_instance->SetRendezvousBreakpoint();
- return false; // Continue running.
-}
-
-void
-DynamicLoaderLinuxDYLD::SetRendezvousBreakpoint()
-{
- Breakpoint *dyld_break;
- addr_t break_addr;
-
- break_addr = m_rendezvous.GetBreakAddress();
- dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get();
- dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
-}
-
-bool
-DynamicLoaderLinuxDYLD::RendezvousBreakpointHit(void *baton,
- StoppointCallbackContext *context,
- user_id_t break_id,
- user_id_t break_loc_id)
-{
- DynamicLoaderLinuxDYLD* dyld_instance;
-
- dyld_instance = static_cast<DynamicLoaderLinuxDYLD*>(baton);
- dyld_instance->RefreshModules();
-
- // Return true to stop the target, false to just let the target run.
- return dyld_instance->GetStopWhenImagesChange();
-}
-
-void
-DynamicLoaderLinuxDYLD::RefreshModules()
-{
- if (!m_rendezvous.Resolve())
- return;
-
- DYLDRendezvous::iterator I;
- DYLDRendezvous::iterator E;
-
- ModuleList &loaded_modules = m_process->GetTarget().GetImages();
-
- if (m_rendezvous.ModulesDidLoad())
- {
- ModuleList new_modules;
-
- E = m_rendezvous.loaded_end();
- for (I = m_rendezvous.loaded_begin(); I != E; ++I)
- {
- FileSpec file(I->path.c_str(), true);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
- if (module_sp.get())
- new_modules.Append(module_sp);
- }
- m_process->GetTarget().ModulesDidLoad(new_modules);
- }
-
- if (m_rendezvous.ModulesDidUnload())
- {
- ModuleList old_modules;
-
- E = m_rendezvous.unloaded_end();
- for (I = m_rendezvous.unloaded_begin(); I != E; ++I)
- {
- FileSpec file(I->path.c_str(), true);
- ModuleSP module_sp =
- loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL);
- if (module_sp.get())
- old_modules.Append(module_sp);
- }
- m_process->GetTarget().ModulesDidUnload(old_modules);
- }
-}
-
-ThreadPlanSP
-DynamicLoaderLinuxDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop)
-{
- LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
- ThreadPlanSP thread_plan_sp;
-
- StackFrame *frame = thread.GetStackFrameAtIndex(0).get();
- const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol);
- Symbol *sym = context.symbol;
-
- if (sym == NULL || !sym->IsTrampoline())
- return thread_plan_sp;
-
- const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);
- if (!sym_name)
- return thread_plan_sp;
-
- SymbolContextList target_symbols;
- Target &target = thread.GetProcess().GetTarget();
- ModuleList &images = target.GetImages();
-
- images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols);
- size_t num_targets = target_symbols.GetSize();
- if (!num_targets)
- return thread_plan_sp;
-
- typedef std::vector<lldb::addr_t> AddressVector;
- AddressVector addrs;
- for (size_t i = 0; i < num_targets; ++i)
- {
- SymbolContext context;
- AddressRange range;
- if (target_symbols.GetContextAtIndex(i, context))
- {
- context.GetAddressRange(eSymbolContextEverything, 0, false, range);
- lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target);
- if (addr != LLDB_INVALID_ADDRESS)
- addrs.push_back(addr);
- }
- }
-
- if (addrs.size() > 0)
- {
- AddressVector::iterator start = addrs.begin();
- AddressVector::iterator end = addrs.end();
-
- std::sort(start, end);
- addrs.erase(std::unique(start, end), end);
- thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop));
- }
-
- return thread_plan_sp;
-}
-
-void
-DynamicLoaderLinuxDYLD::LoadAllCurrentModules()
-{
- DYLDRendezvous::iterator I;
- DYLDRendezvous::iterator E;
- ModuleList module_list;
-
- if (!m_rendezvous.Resolve())
- return;
-
- for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
- {
- FileSpec file(I->path.c_str(), false);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
- if (module_sp.get())
- module_list.Append(module_sp);
- }
-
- m_process->GetTarget().ModulesDidLoad(module_list);
-}
-
-ModuleSP
-DynamicLoaderLinuxDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr)
-{
- Target &target = m_process->GetTarget();
- ModuleList &modules = target.GetImages();
- ModuleSP module_sp;
-
- if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL)))
- {
- UpdateLoadedSections(module_sp, base_addr);
- }
- else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture())))
- {
- UpdateLoadedSections(module_sp, base_addr);
- modules.Append(module_sp);
- }
-
- return module_sp;
-}
-
-addr_t
-DynamicLoaderLinuxDYLD::ComputeLoadOffset()
-{
- addr_t virt_entry;
-
- if (m_load_offset != LLDB_INVALID_ADDRESS)
- return m_load_offset;
-
- if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
- return LLDB_INVALID_ADDRESS;
-
- ModuleSP module = m_process->GetTarget().GetExecutableModule();
- ObjectFile *exe = module->GetObjectFile();
- Address file_entry = exe->GetEntryPointAddress();
-
- if (!file_entry.IsValid())
- return LLDB_INVALID_ADDRESS;
-
- m_load_offset = virt_entry - file_entry.GetFileAddress();
- return m_load_offset;
-}
-
-addr_t
-DynamicLoaderLinuxDYLD::GetEntryPoint()
-{
- if (m_entry_point != LLDB_INVALID_ADDRESS)
- return m_entry_point;
-
- if (m_auxv.get() == NULL)
- return LLDB_INVALID_ADDRESS;
-
- AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY);
-
- if (I == m_auxv->end())
- return LLDB_INVALID_ADDRESS;
-
- m_entry_point = static_cast<addr_t>(I->value);
- return m_entry_point;
-}
Index: source/Plugins/DynamicLoader/Linux-DYLD/Makefile
===================================================================
--- source/Plugins/DynamicLoader/Linux-DYLD/Makefile (revision 147560)
+++ source/Plugins/DynamicLoader/Linux-DYLD/Makefile (working copy)
@@ -1,14 +0,0 @@
-##===- source/Plugins/DynamicLoader/Linux-DYLD/Makefile ----*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLDB_LEVEL := ../../../..
-LIBRARYNAME := lldbPluginDynamicLoaderLinux
-BUILD_ARCHIVE = 1
-
-include $(LLDB_LEVEL)/Makefile
Index: source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h
===================================================================
--- source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (revision 147560)
+++ source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (working copy)
@@ -1,165 +0,0 @@
-//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_DynamicLoaderLinux_H_
-#define liblldb_DynamicLoaderLinux_H_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Breakpoint/StoppointCallbackContext.h"
-#include "lldb/Target/DynamicLoader.h"
-
-#include "DYLDRendezvous.h"
-
-class AuxVector;
-
-class DynamicLoaderLinuxDYLD : public lldb_private::DynamicLoader
-{
-public:
-
- static void
- Initialize();
-
- static void
- Terminate();
-
- static const char *
- GetPluginNameStatic();
-
- static const char *
- GetPluginDescriptionStatic();
-
- static lldb_private::DynamicLoader *
- CreateInstance(lldb_private::Process *process, bool force);
-
- DynamicLoaderLinuxDYLD(lldb_private::Process *process);
-
- virtual
- ~DynamicLoaderLinuxDYLD();
-
- //------------------------------------------------------------------
- // DynamicLoader protocol
- //------------------------------------------------------------------
-
- virtual void
- DidAttach();
-
- virtual void
- DidLaunch();
-
- virtual lldb::ThreadPlanSP
- GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
- bool stop_others);
-
- virtual lldb_private::Error
- CanLoadImage();
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- virtual const char *
- GetPluginName();
-
- virtual const char *
- GetShortPluginName();
-
- virtual uint32_t
- GetPluginVersion();
-
- virtual void
- GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
-
- virtual lldb_private::Error
- ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);
-
- virtual lldb_private::Log *
- EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);
-
-protected:
- /// Runtime linker rendezvous structure.
- DYLDRendezvous m_rendezvous;
-
- /// Virtual load address of the inferior process.
- lldb::addr_t m_load_offset;
-
- /// Virtual entry address of the inferior process.
- lldb::addr_t m_entry_point;
-
- /// Auxiliary vector of the inferior process.
- std::auto_ptr<AuxVector> m_auxv;
-
- /// Enables a breakpoint on a function called by the runtime
- /// linker each time a module is loaded or unloaded.
- void
- SetRendezvousBreakpoint();
-
- /// Callback routine which updates the current list of loaded modules based
- /// on the information supplied by the runtime linker.
- static bool
- RendezvousBreakpointHit(void *baton,
- lldb_private::StoppointCallbackContext *context,
- lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id);
-
- /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set
- /// of loaded modules.
- void
- RefreshModules();
-
- /// Updates the load address of every allocatable section in @p module.
- ///
- /// @param module The module to traverse.
- ///
- /// @param base_addr The virtual base address @p module is loaded at.
- void
- UpdateLoadedSections(lldb::ModuleSP module,
- lldb::addr_t base_addr = 0);
-
- /// Locates or creates a module given by @p file and updates/loads the
- /// resulting module at the virtual base address @p base_addr.
- lldb::ModuleSP
- LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr);
-
- /// Resolves the entry point for the current inferior process and sets a
- /// breakpoint at that address.
- void
- ProbeEntry();
-
- /// Callback routine invoked when we hit the breakpoint on process entry.
- ///
- /// This routine is responsible for resolving the load addresses of all
- /// dependent modules required by the inferior and setting up the rendezvous
- /// breakpoint.
- static bool
- EntryBreakpointHit(void *baton,
- lldb_private::StoppointCallbackContext *context,
- lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id);
-
- /// Helper for the entry breakpoint callback. Resolves the load addresses
- /// of all dependent modules.
- void
- LoadAllCurrentModules();
-
- /// Computes a value for m_load_offset returning the computed address on
- /// success and LLDB_INVALID_ADDRESS on failure.
- lldb::addr_t
- ComputeLoadOffset();
-
- /// Computes a value for m_entry_point returning the computed address on
- /// success and LLDB_INVALID_ADDRESS on failure.
- lldb::addr_t
- GetEntryPoint();
-
-private:
- DISALLOW_COPY_AND_ASSIGN(DynamicLoaderLinuxDYLD);
-};
-
-#endif // liblldb_DynamicLoaderLinuxDYLD_H_
Index: source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
===================================================================
--- source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (revision 0)
+++ source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (revision 0)
@@ -0,0 +1,165 @@
+//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_DynamicLoaderPOSIX_H_
+#define liblldb_DynamicLoaderPOSIX_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Target/DynamicLoader.h"
+
+#include "DYLDRendezvous.h"
+
+class AuxVector;
+
+class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader
+{
+public:
+
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static const char *
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ static lldb_private::DynamicLoader *
+ CreateInstance(lldb_private::Process *process, bool force);
+
+ DynamicLoaderPOSIXDYLD(lldb_private::Process *process);
+
+ virtual
+ ~DynamicLoaderPOSIXDYLD();
+
+ //------------------------------------------------------------------
+ // DynamicLoader protocol
+ //------------------------------------------------------------------
+
+ virtual void
+ DidAttach();
+
+ virtual void
+ DidLaunch();
+
+ virtual lldb::ThreadPlanSP
+ GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
+ bool stop_others);
+
+ virtual lldb_private::Error
+ CanLoadImage();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual const char *
+ GetPluginName();
+
+ virtual const char *
+ GetShortPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+ virtual void
+ GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
+
+ virtual lldb_private::Error
+ ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);
+
+ virtual lldb_private::Log *
+ EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);
+
+protected:
+ /// Runtime linker rendezvous structure.
+ DYLDRendezvous m_rendezvous;
+
+ /// Virtual load address of the inferior process.
+ lldb::addr_t m_load_offset;
+
+ /// Virtual entry address of the inferior process.
+ lldb::addr_t m_entry_point;
+
+ /// Auxiliary vector of the inferior process.
+ std::auto_ptr<AuxVector> m_auxv;
+
+ /// Enables a breakpoint on a function called by the runtime
+ /// linker each time a module is loaded or unloaded.
+ void
+ SetRendezvousBreakpoint();
+
+ /// Callback routine which updates the current list of loaded modules based
+ /// on the information supplied by the runtime linker.
+ static bool
+ RendezvousBreakpointHit(void *baton,
+ lldb_private::StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set
+ /// of loaded modules.
+ void
+ RefreshModules();
+
+ /// Updates the load address of every allocatable section in @p module.
+ ///
+ /// @param module The module to traverse.
+ ///
+ /// @param base_addr The virtual base address @p module is loaded at.
+ void
+ UpdateLoadedSections(lldb::ModuleSP module,
+ lldb::addr_t base_addr = 0);
+
+ /// Locates or creates a module given by @p file and updates/loads the
+ /// resulting module at the virtual base address @p base_addr.
+ lldb::ModuleSP
+ LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr);
+
+ /// Resolves the entry point for the current inferior process and sets a
+ /// breakpoint at that address.
+ void
+ ProbeEntry();
+
+ /// Callback routine invoked when we hit the breakpoint on process entry.
+ ///
+ /// This routine is responsible for resolving the load addresses of all
+ /// dependent modules required by the inferior and setting up the rendezvous
+ /// breakpoint.
+ static bool
+ EntryBreakpointHit(void *baton,
+ lldb_private::StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ /// Helper for the entry breakpoint callback. Resolves the load addresses
+ /// of all dependent modules.
+ void
+ LoadAllCurrentModules();
+
+ /// Computes a value for m_load_offset returning the computed address on
+ /// success and LLDB_INVALID_ADDRESS on failure.
+ lldb::addr_t
+ ComputeLoadOffset();
+
+ /// Computes a value for m_entry_point returning the computed address on
+ /// success and LLDB_INVALID_ADDRESS on failure.
+ lldb::addr_t
+ GetEntryPoint();
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);
+};
+
+#endif // liblldb_DynamicLoaderPOSIXDYLD_H_
Index: source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
===================================================================
--- source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (revision 0)
+++ source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (revision 0)
@@ -0,0 +1,153 @@
+//===-- AuxVector.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+
+#include "AuxVector.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static bool
+GetMaxU64(DataExtractor &data,
+ uint32_t *offset, uint64_t *value, unsigned int byte_size)
+{
+ uint32_t saved_offset = *offset;
+ *value = data.GetMaxU64(offset, byte_size);
+ return *offset != saved_offset;
+}
+
+static bool
+ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry,
+ uint32_t *offset, unsigned int byte_size)
+{
+ if (!GetMaxU64(data, offset, &entry.type, byte_size))
+ return false;
+
+ if (!GetMaxU64(data, offset, &entry.value, byte_size))
+ return false;
+
+ return true;
+}
+
+DataBufferSP
+AuxVector::GetAuxvData()
+{
+
+ return lldb_private::Host::GetAuxvData(m_process);
+}
+
+void
+AuxVector::ParseAuxv(DataExtractor &data)
+{
+ const unsigned int byte_size = m_process->GetAddressByteSize();
+ uint32_t offset = 0;
+
+ for (;;)
+ {
+ Entry entry;
+
+ if (!ParseAuxvEntry(data, entry, &offset, byte_size))
+ break;
+
+ if (entry.type == AT_NULL)
+ break;
+
+ if (entry.type == AT_IGNORE)
+ continue;
+
+ m_auxv.push_back(entry);
+ }
+}
+
+AuxVector::AuxVector(Process *process)
+ : m_process(process)
+{
+ DataExtractor data;
+ LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
+ data.SetData(GetAuxvData());
+ data.SetByteOrder(m_process->GetByteOrder());
+ data.SetAddressByteSize(m_process->GetAddressByteSize());
+
+ ParseAuxv(data);
+
+ if (log)
+ DumpToLog(log);
+}
+
+AuxVector::iterator
+AuxVector::FindEntry(EntryType type) const
+{
+ for (iterator I = begin(); I != end(); ++I)
+ {
+ if (I->type == static_cast<uint64_t>(type))
+ return I;
+ }
+
+ return end();
+}
+
+void
+AuxVector::DumpToLog(LogSP log) const
+{
+ if (!log)
+ return;
+
+ log->PutCString("AuxVector: ");
+ for (iterator I = begin(); I != end(); ++I)
+ {
+ log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value);
+ }
+}
+
+const char *
+AuxVector::GetEntryName(EntryType type)
+{
+ const char *name;
+
+#define ENTRY_NAME(_type) _type: name = #_type
+ switch (type)
+ {
+ default:
+ name = "unkown";
+ break;
+
+ case ENTRY_NAME(AT_NULL); break;
+ case ENTRY_NAME(AT_IGNORE); break;
+ case ENTRY_NAME(AT_EXECFD); break;
+ case ENTRY_NAME(AT_PHDR); break;
+ case ENTRY_NAME(AT_PHENT); break;
+ case ENTRY_NAME(AT_PHNUM); break;
+ case ENTRY_NAME(AT_PAGESZ); break;
+ case ENTRY_NAME(AT_BASE); break;
+ case ENTRY_NAME(AT_FLAGS); break;
+ case ENTRY_NAME(AT_ENTRY); break;
+ case ENTRY_NAME(AT_NOTELF); break;
+ case ENTRY_NAME(AT_UID); break;
+ case ENTRY_NAME(AT_EUID); break;
+ case ENTRY_NAME(AT_GID); break;
+ case ENTRY_NAME(AT_EGID); break;
+ case ENTRY_NAME(AT_CLKTCK); break;
+ }
+#undef ENTRY_NAME
+
+ return name;
+}
+
Index: source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
===================================================================
--- source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (revision 0)
+++ source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (revision 0)
@@ -0,0 +1,330 @@
+//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "DYLDRendezvous.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+/// Locates the address of the rendezvous structure. Returns the address on
+/// success and LLDB_INVALID_ADDRESS on failure.
+static addr_t
+ResolveRendezvousAddress(Process *process)
+{
+ addr_t info_location;
+ addr_t info_addr;
+ Error error;
+ size_t size;
+
+ info_location = process->GetImageInfoAddress();
+
+ if (info_location == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ info_addr = 0;
+ size = process->DoReadMemory(info_location, &info_addr,
+ process->GetAddressByteSize(), error);
+ if (size != process->GetAddressByteSize() || error.Fail())
+ return LLDB_INVALID_ADDRESS;
+
+ if (info_addr == 0)
+ return LLDB_INVALID_ADDRESS;
+
+ return info_addr;
+}
+
+DYLDRendezvous::DYLDRendezvous(Process *process)
+ : m_process(process),
+ m_rendezvous_addr(LLDB_INVALID_ADDRESS),
+ m_current(),
+ m_previous(),
+ m_soentries(),
+ m_added_soentries(),
+ m_removed_soentries()
+{
+ // Cache a copy of the executable path
+ m_process->GetTarget().GetExecutableModule().get()->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
+}
+
+bool
+DYLDRendezvous::Resolve()
+{
+ const size_t word_size = 4;
+ Rendezvous info;
+ size_t address_size;
+ size_t padding;
+ addr_t info_addr;
+ addr_t cursor;
+
+ address_size = m_process->GetAddressByteSize();
+ padding = address_size - word_size;
+
+ if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
+ cursor = info_addr = ResolveRendezvousAddress(m_process);
+ else
+ cursor = info_addr = m_rendezvous_addr;
+
+ if (cursor == LLDB_INVALID_ADDRESS)
+ return false;
+
+ if (!(cursor = ReadMemory(cursor, &info.version, word_size)))
+ return false;
+
+ if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size)))
+ return false;
+
+ if (!(cursor = ReadMemory(cursor, &info.brk, address_size)))
+ return false;
+
+ if (!(cursor = ReadMemory(cursor, &info.state, word_size)))
+ return false;
+
+ if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size)))
+ return false;
+
+ // The rendezvous was successfully read. Update our internal state.
+ m_rendezvous_addr = info_addr;
+ m_previous = m_current;
+ m_current = info;
+
+ return UpdateSOEntries();
+}
+
+bool
+DYLDRendezvous::IsValid()
+{
+ return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntries()
+{
+ SOEntry entry;
+
+ if (m_current.map_addr == 0)
+ return false;
+
+ // When the previous and current states are consistent this is the first
+ // time we have been asked to update. Just take a snapshot of the currently
+ // loaded modules.
+ if (m_previous.state == eConsistent && m_current.state == eConsistent)
+ return TakeSnapshot(m_soentries);
+
+ // If we are about to add or remove a shared object clear out the current
+ // state and take a snapshot of the currently loaded images.
+ if (m_current.state == eAdd || m_current.state == eDelete)
+ {
+ assert(m_previous.state == eConsistent);
+ m_soentries.clear();
+ m_added_soentries.clear();
+ m_removed_soentries.clear();
+ return TakeSnapshot(m_soentries);
+ }
+ assert(m_current.state == eConsistent);
+
+ // Otherwise check the previous state to determine what to expect and update
+ // accordingly.
+ if (m_previous.state == eAdd)
+ return UpdateSOEntriesForAddition();
+ else if (m_previous.state == eDelete)
+ return UpdateSOEntriesForDeletion();
+
+ return false;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntriesForAddition()
+{
+ SOEntry entry;
+ iterator pos;
+
+ assert(m_previous.state == eAdd);
+
+ if (m_current.map_addr == 0)
+ return false;
+
+ for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
+ {
+ if (!ReadSOEntryFromMemory(cursor, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ // On Linux this is indicated by an empty path in the entry.
+ // On FreeBSD it is the name of the executable.
+ if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
+ continue;
+
+ pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
+ if (pos == m_soentries.end())
+ {
+ m_soentries.push_back(entry);
+ m_added_soentries.push_back(entry);
+ }
+ }
+
+ return true;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntriesForDeletion()
+{
+ SOEntryList entry_list;
+ iterator pos;
+
+ assert(m_previous.state == eDelete);
+
+ if (!TakeSnapshot(entry_list))
+ return false;
+
+ for (iterator I = begin(); I != end(); ++I)
+ {
+ pos = std::find(entry_list.begin(), entry_list.end(), *I);
+ if (pos == entry_list.end())
+ m_removed_soentries.push_back(*I);
+ }
+
+ m_soentries = entry_list;
+ return true;
+}
+
+bool
+DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
+{
+ SOEntry entry;
+
+ if (m_current.map_addr == 0)
+ return false;
+
+ for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
+ {
+ if (!ReadSOEntryFromMemory(cursor, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ // On Linux this is indicated by an empty path in the entry.
+ // On FreeBSD it is the name of the executable.
+ if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
+ continue;
+
+ entry_list.push_back(entry);
+ }
+
+ return true;
+}
+
+addr_t
+DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size)
+{
+ size_t bytes_read;
+ Error error;
+
+ bytes_read = m_process->DoReadMemory(addr, dst, size, error);
+ if (bytes_read != size || error.Fail())
+ return 0;
+
+ return addr + bytes_read;
+}
+
+std::string
+DYLDRendezvous::ReadStringFromMemory(addr_t addr)
+{
+ std::string str;
+ Error error;
+ size_t size;
+ char c;
+
+ if (addr == LLDB_INVALID_ADDRESS)
+ return std::string();
+
+ for (;;) {
+ size = m_process->DoReadMemory(addr, &c, 1, error);
+ if (size != 1 || error.Fail())
+ return std::string();
+ if (c == 0)
+ break;
+ else {
+ str.push_back(c);
+ addr++;
+ }
+ }
+
+ return str;
+}
+
+bool
+DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
+{
+ size_t address_size = m_process->GetAddressByteSize();
+
+ entry.clear();
+
+ if (!(addr = ReadMemory(addr, &entry.base_addr, address_size)))
+ return false;
+
+ if (!(addr = ReadMemory(addr, &entry.path_addr, address_size)))
+ return false;
+
+ if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size)))
+ return false;
+
+ if (!(addr = ReadMemory(addr, &entry.next, address_size)))
+ return false;
+
+ if (!(addr = ReadMemory(addr, &entry.prev, address_size)))
+ return false;
+
+ entry.path = ReadStringFromMemory(entry.path_addr);
+
+ return true;
+}
+
+void
+DYLDRendezvous::DumpToLog(LogSP log) const
+{
+ int state = GetState();
+
+ if (!log)
+ return;
+
+ log->PutCString("DYLDRendezvous:");
+ log->Printf(" Address: %lx", GetRendezvousAddress());
+ log->Printf(" Version: %d", GetVersion());
+ log->Printf(" Link : %lx", GetLinkMapAddress());
+ log->Printf(" Break : %lx", GetBreakAddress());
+ log->Printf(" LDBase : %lx", GetLDBase());
+ log->Printf(" State : %s",
+ (state == eConsistent) ? "consistent" :
+ (state == eAdd) ? "add" :
+ (state == eDelete) ? "delete" : "unknown");
+
+ iterator I = begin();
+ iterator E = end();
+
+ if (I != E)
+ log->PutCString("DYLDRendezvous SOEntries:");
+
+ for (int i = 1; I != E; ++I, ++i)
+ {
+ log->Printf("\n SOEntry [%d] %s", i, I->path.c_str());
+ log->Printf(" Base : %lx", I->base_addr);
+ log->Printf(" Path : %lx", I->path_addr);
+ log->Printf(" Dyn : %lx", I->dyn_addr);
+ log->Printf(" Next : %lx", I->next);
+ log->Printf(" Prev : %lx", I->prev);
+ }
+}
Index: source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
===================================================================
--- source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (revision 0)
+++ source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (revision 0)
@@ -0,0 +1,97 @@
+//===-- AuxVector.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_AuxVector_H_
+#define liblldb_AuxVector_H_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+#include "lldb/lldb-forward-rtti.h"
+
+namespace lldb_private {
+class DataExtractor;
+}
+
+/// @class AuxVector
+/// @brief Represents a processes auxiliary vector.
+///
+/// When a process is loaded on Linux a vector of values is placed onto the
+/// stack communicating operating system specific information. On construction
+/// this class locates and parses this information and provides a simple
+/// read-only interface to the entries found.
+class AuxVector {
+
+public:
+ AuxVector(lldb_private::Process *process);
+
+ struct Entry {
+ uint64_t type;
+ uint64_t value;
+
+ Entry() : type(0), value(0) { }
+ };
+
+ /// Constants describing the type of entry.
+ enum EntryType {
+ AT_NULL = 0, ///< End of auxv.
+ AT_IGNORE = 1, ///< Ignore entry.
+ AT_EXECFD = 2, ///< File descriptor of program.
+ AT_PHDR = 3, ///< Program headers.
+ AT_PHENT = 4, ///< Size of program header.
+ AT_PHNUM = 5, ///< Number of program headers.
+ AT_PAGESZ = 6, ///< Page size.
+ AT_BASE = 7, ///< Interpreter base address.
+ AT_FLAGS = 8, ///< Flags.
+ AT_ENTRY = 9, ///< Program entry point.
+ AT_NOTELF = 10, ///< Set if program is not an ELF.
+ AT_UID = 11, ///< UID.
+ AT_EUID = 12, ///< Effective UID.
+ AT_GID = 13, ///< GID.
+ AT_EGID = 14, ///< Effective GID.
+ AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)).
+ };
+
+private:
+ typedef std::vector<Entry> EntryVector;
+
+public:
+ typedef EntryVector::const_iterator iterator;
+
+ iterator begin() const { return m_auxv.begin(); }
+ iterator end() const { return m_auxv.end(); }
+
+ iterator
+ FindEntry(EntryType type) const;
+
+ static const char *
+ GetEntryName(const Entry &entry) {
+ return GetEntryName(static_cast<EntryType>(entry.type));
+ }
+
+ static const char *
+ GetEntryName(EntryType type);
+
+ void
+ DumpToLog(lldb::LogSP log) const;
+
+private:
+ lldb_private::Process *m_process;
+ EntryVector m_auxv;
+
+ lldb::DataBufferSP
+ GetAuxvData();
+
+ void
+ ParseAuxv(lldb_private::DataExtractor &data);
+};
+
+#endif
Index: source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
===================================================================
--- source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (revision 0)
+++ source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (revision 0)
@@ -0,0 +1,230 @@
+//===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Rendezvous_H_
+#define liblldb_Rendezvous_H_
+
+// C Includes
+// C++ Includes
+#include <list>
+#include <string>
+
+// Other libraries and framework includes
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private {
+class Process;
+}
+
+/// @class DYLDRendezvous
+/// @brief Interface to the runtime linker.
+///
+/// A structure is present in a processes memory space which is updated by the
+/// runtime liker each time a module is loaded or unloaded. This class provides
+/// an interface to this structure and maintains a consistent snapshot of the
+/// currently loaded modules.
+class DYLDRendezvous {
+
+ // This structure is used to hold the contents of the debug rendezvous
+ // information (struct r_debug) as found in the inferiors memory. Note that
+ // the layout of this struct is not binary compatible, it is simply large
+ // enough to hold the information on both 32 and 64 bit platforms.
+ struct Rendezvous {
+ uint64_t version;
+ lldb::addr_t map_addr;
+ lldb::addr_t brk;
+ uint64_t state;
+ lldb::addr_t ldbase;
+
+ Rendezvous()
+ : version(0), map_addr(0), brk(0), state(0), ldbase(0) { }
+ };
+
+public:
+ DYLDRendezvous(lldb_private::Process *process);
+
+ /// Update the internal snapshot of runtime linker rendezvous and recompute
+ /// the currently loaded modules.
+ ///
+ /// This method should be called once one start up, then once each time the
+ /// runtime linker enters the function given by GetBreakAddress().
+ ///
+ /// @returns true on success and false on failure.
+ ///
+ /// @see GetBreakAddress().
+ bool
+ Resolve();
+
+ /// @returns true if this rendezvous has been located in the inferiors
+ /// address space and false otherwise.
+ bool
+ IsValid();
+
+ /// @returns the address of the rendezvous structure in the inferiors
+ /// address space.
+ lldb::addr_t
+ GetRendezvousAddress() const { return m_rendezvous_addr; }
+
+ /// @returns the version of the rendezvous protocol being used.
+ int
+ GetVersion() const { return m_current.version; }
+
+ /// @returns address in the inferiors address space containing the linked
+ /// list of shared object descriptors.
+ lldb::addr_t
+ GetLinkMapAddress() const { return m_current.map_addr; }
+
+ /// A breakpoint should be set at this address and Resolve called on each
+ /// hit.
+ ///
+ /// @returns the address of a function called by the runtime linker each
+ /// time a module is loaded/unloaded, or about to be loaded/unloaded.
+ ///
+ /// @see Resolve()
+ lldb::addr_t
+ GetBreakAddress() const { return m_current.brk; }
+
+ /// Returns the current state of the rendezvous structure.
+ int
+ GetState() const { return m_current.state; }
+
+ /// @returns the base address of the runtime linker in the inferiors address
+ /// space.
+ lldb::addr_t
+ GetLDBase() const { return m_current.ldbase; }
+
+ /// @returns true if modules have been loaded into the inferior since the
+ /// last call to Resolve().
+ bool
+ ModulesDidLoad() const { return !m_added_soentries.empty(); }
+
+ /// @returns true if modules have been unloaded from the inferior since the
+ /// last call to Resolve().
+ bool
+ ModulesDidUnload() const { return !m_removed_soentries.empty(); }
+
+ void
+ DumpToLog(lldb::LogSP log) const;
+
+ /// @brief Constants describing the state of the rendezvous.
+ ///
+ /// @see GetState().
+ enum RendezvousState {
+ eConsistent,
+ eAdd,
+ eDelete
+ };
+
+ /// @brief Structure representing the shared objects currently loaded into
+ /// the inferior process.
+ ///
+ /// This object is a rough analogue to the struct link_map object which
+ /// actually lives in the inferiors memory.
+ struct SOEntry {
+ lldb::addr_t base_addr; ///< Base address of the loaded object.
+ lldb::addr_t path_addr; ///< String naming the shared object.
+ lldb::addr_t dyn_addr; ///< Dynamic section of shared object.
+ lldb::addr_t next; ///< Address of next so_entry.
+ lldb::addr_t prev; ///< Address of previous so_entry.
+ std::string path; ///< File name of shared object.
+
+ SOEntry() { clear(); }
+
+ bool operator ==(const SOEntry &entry) {
+ return this->path == entry.path;
+ }
+
+ void clear() {
+ base_addr = 0;
+ path_addr = 0;
+ dyn_addr = 0;
+ next = 0;
+ prev = 0;
+ path.clear();
+ }
+ };
+
+protected:
+ typedef std::list<SOEntry> SOEntryList;
+
+public:
+ typedef SOEntryList::const_iterator iterator;
+
+ /// Iterators over all currently loaded modules.
+ iterator begin() const { return m_soentries.begin(); }
+ iterator end() const { return m_soentries.end(); }
+
+ /// Iterators over all modules loaded into the inferior since the last call
+ /// to Resolve().
+ iterator loaded_begin() const { return m_added_soentries.begin(); }
+ iterator loaded_end() const { return m_added_soentries.end(); }
+
+ /// Iterators over all modules unloaded from the inferior since the last
+ /// call to Resolve().
+ iterator unloaded_begin() const { return m_removed_soentries.begin(); }
+ iterator unloaded_end() const { return m_removed_soentries.end(); }
+
+protected:
+ lldb_private::Process *m_process;
+
+ // Cached copy of executable pathname
+ char m_exe_path[PATH_MAX];
+
+ /// Location of the r_debug structure in the inferiors address space.
+ lldb::addr_t m_rendezvous_addr;
+
+ /// Current and previous snapshots of the rendezvous structure.
+ Rendezvous m_current;
+ Rendezvous m_previous;
+
+ /// List of SOEntry objects corresponding to the current link map state.
+ SOEntryList m_soentries;
+
+ /// List of SOEntry's added to the link map since the last call to Resolve().
+ SOEntryList m_added_soentries;
+
+ /// List of SOEntry's removed from the link map since the last call to
+ /// Resolve().
+ SOEntryList m_removed_soentries;
+
+ /// Reads @p size bytes from the inferiors address space starting at @p
+ /// addr.
+ ///
+ /// @returns addr + size if the read was successful and false otherwise.
+ lldb::addr_t
+ ReadMemory(lldb::addr_t addr, void *dst, size_t size);
+
+ /// Reads a null-terminated C string from the memory location starting at @p
+ /// addr.
+ std::string
+ ReadStringFromMemory(lldb::addr_t addr);
+
+ /// Reads an SOEntry starting at @p addr.
+ bool
+ ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
+
+ /// Updates the current set of SOEntries, the set of added entries, and the
+ /// set of removed entries.
+ bool
+ UpdateSOEntries();
+
+ bool
+ UpdateSOEntriesForAddition();
+
+ bool
+ UpdateSOEntriesForDeletion();
+
+ /// Reads the current list of shared objects according to the link map
+ /// supplied by the runtime linker.
+ bool
+ TakeSnapshot(SOEntryList &entry_list);
+};
+
+#endif
Index: source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
===================================================================
--- source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (revision 0)
+++ source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (revision 0)
@@ -0,0 +1,425 @@
+//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+
+#include "AuxVector.h"
+#include "DynamicLoaderPOSIXDYLD.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+DynamicLoaderPOSIXDYLD::Initialize()
+{
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ CreateInstance);
+}
+
+void
+DynamicLoaderPOSIXDYLD::Terminate()
+{
+}
+
+const char *
+DynamicLoaderPOSIXDYLD::GetPluginName()
+{
+ return "DynamicLoaderPOSIXDYLD";
+}
+
+const char *
+DynamicLoaderPOSIXDYLD::GetShortPluginName()
+{
+ return "linux-dyld";
+}
+
+const char *
+DynamicLoaderPOSIXDYLD::GetPluginNameStatic()
+{
+ return "dynamic-loader.linux-dyld";
+}
+
+const char *
+DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic()
+{
+ return "Dynamic loader plug-in that watches for shared library "
+ "loads/unloads in POSIX processes.";
+}
+
+void
+DynamicLoaderPOSIXDYLD::GetPluginCommandHelp(const char *command, Stream *strm)
+{
+}
+
+uint32_t
+DynamicLoaderPOSIXDYLD::GetPluginVersion()
+{
+ return 1;
+}
+
+DynamicLoader *
+DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, bool force)
+{
+ bool create = force;
+ if (!create)
+ {
+ const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
+ if (triple_ref.getOS() == llvm::Triple::Linux ||
+ triple_ref.getOS() == llvm::Triple::FreeBSD)
+ create = true;
+ }
+
+ if (create)
+ return new DynamicLoaderPOSIXDYLD (process);
+ return NULL;
+}
+
+DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process)
+ : DynamicLoader(process),
+ m_rendezvous(process),
+ m_load_offset(LLDB_INVALID_ADDRESS),
+ m_entry_point(LLDB_INVALID_ADDRESS),
+ m_auxv(NULL)
+{
+}
+
+DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD()
+{
+}
+
+void
+DynamicLoaderPOSIXDYLD::DidAttach()
+{
+ ModuleSP executable;
+ addr_t load_offset;
+
+ m_auxv.reset(new AuxVector(m_process));
+
+ executable = m_process->GetTarget().GetExecutableModule();
+ load_offset = ComputeLoadOffset();
+
+ if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)
+ {
+ ModuleList module_list;
+ module_list.Append(executable);
+ UpdateLoadedSections(executable, load_offset);
+ LoadAllCurrentModules();
+ m_process->GetTarget().ModulesDidLoad(module_list);
+ }
+}
+
+void
+DynamicLoaderPOSIXDYLD::DidLaunch()
+{
+ ModuleSP executable;
+ addr_t load_offset;
+
+ m_auxv.reset(new AuxVector(m_process));
+
+ executable = m_process->GetTarget().GetExecutableModule();
+ load_offset = ComputeLoadOffset();
+
+ if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)
+ {
+ ModuleList module_list;
+ module_list.Append(executable);
+ UpdateLoadedSections(executable, load_offset);
+ ProbeEntry();
+ m_process->GetTarget().ModulesDidLoad(module_list);
+ }
+}
+
+Error
+DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm)
+{
+ return Error();
+}
+
+Log *
+DynamicLoaderPOSIXDYLD::EnablePluginLogging(Stream *strm, Args &command)
+{
+ return NULL;
+}
+
+Error
+DynamicLoaderPOSIXDYLD::CanLoadImage()
+{
+ return Error();
+}
+
+void
+DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
+{
+ ObjectFile *obj_file = module->GetObjectFile();
+ SectionList *sections = obj_file->GetSectionList();
+ SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
+ const size_t num_sections = sections->GetSize();
+
+ for (unsigned i = 0; i < num_sections; ++i)
+ {
+ Section *section = sections->GetSectionAtIndex(i).get();
+ lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr;
+ lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section);
+
+ // If the file address of the section is zero then this is not an
+ // allocatable/loadable section (property of ELF sh_addr). Skip it.
+ if (new_load_addr == base_addr)
+ continue;
+
+ if (old_load_addr == LLDB_INVALID_ADDRESS ||
+ old_load_addr != new_load_addr)
+ load_list.SetSectionLoadAddress(section, new_load_addr);
+ }
+}
+
+void
+DynamicLoaderPOSIXDYLD::ProbeEntry()
+{
+ Breakpoint *entry_break;
+ addr_t entry;
+
+ if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
+ return;
+
+ entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get();
+ entry_break->SetCallback(EntryBreakpointHit, this, true);
+}
+
+// The runtime linker has run and initialized the rendezvous structure once the
+// process has hit its entry point. When we hit the corresponding breakpoint we
+// interrogate the rendezvous structure to get the load addresses of all
+// dependent modules for the process. Similarly, we can discover the runtime
+// linker function and setup a breakpoint to notify us of any dynamically loaded
+// modules (via dlopen).
+bool
+DynamicLoaderPOSIXDYLD::EntryBreakpointHit(void *baton,
+ StoppointCallbackContext *context,
+ user_id_t break_id,
+ user_id_t break_loc_id)
+{
+ DynamicLoaderPOSIXDYLD* dyld_instance;
+
+ dyld_instance = static_cast<DynamicLoaderPOSIXDYLD*>(baton);
+ dyld_instance->LoadAllCurrentModules();
+ dyld_instance->SetRendezvousBreakpoint();
+ return false; // Continue running.
+}
+
+void
+DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint()
+{
+ Breakpoint *dyld_break;
+ addr_t break_addr;
+
+ break_addr = m_rendezvous.GetBreakAddress();
+ dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get();
+ dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
+}
+
+bool
+DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(void *baton,
+ StoppointCallbackContext *context,
+ user_id_t break_id,
+ user_id_t break_loc_id)
+{
+ DynamicLoaderPOSIXDYLD* dyld_instance;
+
+ dyld_instance = static_cast<DynamicLoaderPOSIXDYLD*>(baton);
+ dyld_instance->RefreshModules();
+
+ // Return true to stop the target, false to just let the target run.
+ return dyld_instance->GetStopWhenImagesChange();
+}
+
+void
+DynamicLoaderPOSIXDYLD::RefreshModules()
+{
+ if (!m_rendezvous.Resolve())
+ return;
+
+ DYLDRendezvous::iterator I;
+ DYLDRendezvous::iterator E;
+
+ ModuleList &loaded_modules = m_process->GetTarget().GetImages();
+
+ if (m_rendezvous.ModulesDidLoad())
+ {
+ ModuleList new_modules;
+
+ E = m_rendezvous.loaded_end();
+ for (I = m_rendezvous.loaded_begin(); I != E; ++I)
+ {
+ FileSpec file(I->path.c_str(), true);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+ if (module_sp.get())
+ new_modules.Append(module_sp);
+ }
+ m_process->GetTarget().ModulesDidLoad(new_modules);
+ }
+
+ if (m_rendezvous.ModulesDidUnload())
+ {
+ ModuleList old_modules;
+
+ E = m_rendezvous.unloaded_end();
+ for (I = m_rendezvous.unloaded_begin(); I != E; ++I)
+ {
+ FileSpec file(I->path.c_str(), true);
+ ModuleSP module_sp =
+ loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL);
+ if (module_sp.get())
+ old_modules.Append(module_sp);
+ }
+ m_process->GetTarget().ModulesDidUnload(old_modules);
+ }
+}
+
+ThreadPlanSP
+DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop)
+{
+ LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ ThreadPlanSP thread_plan_sp;
+
+ StackFrame *frame = thread.GetStackFrameAtIndex(0).get();
+ const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol);
+ Symbol *sym = context.symbol;
+
+ if (sym == NULL || !sym->IsTrampoline())
+ return thread_plan_sp;
+
+ const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);
+ if (!sym_name)
+ return thread_plan_sp;
+
+ SymbolContextList target_symbols;
+ Target &target = thread.GetProcess().GetTarget();
+ ModuleList &images = target.GetImages();
+
+ images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols);
+ size_t num_targets = target_symbols.GetSize();
+ if (!num_targets)
+ return thread_plan_sp;
+
+ typedef std::vector<lldb::addr_t> AddressVector;
+ AddressVector addrs;
+ for (size_t i = 0; i < num_targets; ++i)
+ {
+ SymbolContext context;
+ AddressRange range;
+ if (target_symbols.GetContextAtIndex(i, context))
+ {
+ context.GetAddressRange(eSymbolContextEverything, 0, false, range);
+ lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target);
+ if (addr != LLDB_INVALID_ADDRESS)
+ addrs.push_back(addr);
+ }
+ }
+
+ if (addrs.size() > 0)
+ {
+ AddressVector::iterator start = addrs.begin();
+ AddressVector::iterator end = addrs.end();
+
+ std::sort(start, end);
+ addrs.erase(std::unique(start, end), end);
+ thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop));
+ }
+
+ return thread_plan_sp;
+}
+
+void
+DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()
+{
+ DYLDRendezvous::iterator I;
+ DYLDRendezvous::iterator E;
+ ModuleList module_list;
+
+ if (!m_rendezvous.Resolve())
+ return;
+
+ for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
+ {
+ FileSpec file(I->path.c_str(), false);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+ if (module_sp.get())
+ module_list.Append(module_sp);
+ }
+
+ m_process->GetTarget().ModulesDidLoad(module_list);
+}
+
+ModuleSP
+DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr)
+{
+ Target &target = m_process->GetTarget();
+ ModuleList &modules = target.GetImages();
+ ModuleSP module_sp;
+
+ if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL)))
+ {
+ UpdateLoadedSections(module_sp, base_addr);
+ }
+ else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture())))
+ {
+ UpdateLoadedSections(module_sp, base_addr);
+ modules.Append(module_sp);
+ }
+
+ return module_sp;
+}
+
+addr_t
+DynamicLoaderPOSIXDYLD::ComputeLoadOffset()
+{
+ addr_t virt_entry;
+
+ if (m_load_offset != LLDB_INVALID_ADDRESS)
+ return m_load_offset;
+
+ if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ ModuleSP module = m_process->GetTarget().GetExecutableModule();
+ ObjectFile *exe = module->GetObjectFile();
+ Address file_entry = exe->GetEntryPointAddress();
+
+ if (!file_entry.IsValid())
+ return LLDB_INVALID_ADDRESS;
+
+ m_load_offset = virt_entry - file_entry.GetFileAddress();
+ return m_load_offset;
+}
+
+addr_t
+DynamicLoaderPOSIXDYLD::GetEntryPoint()
+{
+ if (m_entry_point != LLDB_INVALID_ADDRESS)
+ return m_entry_point;
+
+ if (m_auxv.get() == NULL)
+ return LLDB_INVALID_ADDRESS;
+
+ AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY);
+
+ if (I == m_auxv->end())
+ return LLDB_INVALID_ADDRESS;
+
+ m_entry_point = static_cast<addr_t>(I->value);
+ return m_entry_point;
+}
Index: source/Plugins/DynamicLoader/POSIX-DYLD/Makefile
===================================================================
--- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile (revision 0)
+++ source/Plugins/DynamicLoader/POSIX-DYLD/Makefile (revision 0)
@@ -0,0 +1,14 @@
+##===- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile ----*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginDynamicLoaderPOSIX
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
Index: source/Plugins/Makefile
===================================================================
--- source/Plugins/Makefile (revision 147560)
+++ source/Plugins/Makefile (working copy)
@@ -30,7 +30,11 @@
endif
ifeq ($(HOST_OS),Linux)
-DIRS += Process/Linux DynamicLoader/Linux-DYLD
+DIRS += Process/Linux Process/POSIX DynamicLoader/POSIX-DYLD
endif
+ifeq ($(HOST_OS),FreeBSD)
+DIRS += Process/FreeBSD Process/POSIX DynamicLoader/POSIX-DYLD
+endif
+
include $(LLDB_LEVEL)/Makefile
Index: source/Plugins/Process/Linux/ProcessLinux.cpp
===================================================================
--- source/Plugins/Process/Linux/ProcessLinux.cpp (revision 147560)
+++ source/Plugins/Process/Linux/ProcessLinux.cpp (working copy)
@@ -20,10 +20,10 @@
#include "lldb/Target/Target.h"
#include "ProcessLinux.h"
-#include "ProcessLinuxLog.h"
+#include "ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "ProcessMonitor.h"
-#include "LinuxThread.h"
+#include "POSIXThread.h"
using namespace lldb;
using namespace lldb_private;
@@ -50,42 +50,21 @@
CreateInstance);
Log::Callbacks log_callbacks = {
- ProcessLinuxLog::DisableLog,
- ProcessLinuxLog::EnableLog,
- ProcessLinuxLog::ListLogCategories
+ ProcessPOSIXLog::DisableLog,
+ ProcessPOSIXLog::EnableLog,
+ ProcessPOSIXLog::ListLogCategories
};
Log::RegisterLogChannel (ProcessLinux::GetPluginNameStatic(), log_callbacks);
+ ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic());
}
}
-void
-ProcessLinux::Terminate()
-{
-}
-
-const char *
-ProcessLinux::GetPluginNameStatic()
-{
- return "plugin.process.linux";
-}
-
-const char *
-ProcessLinux::GetPluginDescriptionStatic()
-{
- return "Process plugin for Linux";
-}
-
-
//------------------------------------------------------------------------------
// Constructors and destructors.
ProcessLinux::ProcessLinux(Target& target, Listener &listener)
- : Process(target, listener),
- m_monitor(NULL),
- m_module(NULL),
- m_in_limbo(false),
- m_exit_now(false)
+ : ProcessPOSIX(target, listener)
{
#if 0
// FIXME: Putting this code in the ctor and saving the byte order in a
@@ -98,409 +77,28 @@
#endif
}
-ProcessLinux::~ProcessLinux()
-{
- delete m_monitor;
-}
-
-//------------------------------------------------------------------------------
-// Process protocol.
-
-bool
-ProcessLinux::CanDebug(Target &target, bool plugin_specified_by_name)
-{
- // For now we are just making sure the file exists for a given module
- ModuleSP exe_module_sp(target.GetExecutableModule());
- if (exe_module_sp.get())
- return exe_module_sp->GetFileSpec().Exists();
- return false;
-}
-
-Error
-ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid)
-{
- Error error;
- assert(m_monitor == NULL);
-
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS));
- if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
- log->Printf ("ProcessLinux::%s(pid = %i)", __FUNCTION__, GetID());
-
- m_monitor = new ProcessMonitor(this, pid, error);
-
- if (!error.Success())
- return error;
-
- SetID(pid);
- return error;
-}
-
-Error
-ProcessLinux::WillLaunch(Module* module)
-{
- Error error;
- return error;
-}
-
-Error
-ProcessLinux::DoLaunch (Module *module,
- const ProcessLaunchInfo &launch_info)
-{
- Error error;
- assert(m_monitor == NULL);
-
- SetPrivateState(eStateLaunching);
-
- const char *stdin_path = NULL;
- const char *stdout_path = NULL;
- const char *stderr_path = NULL;
- const char *working_dir = launch_info.GetWorkingDirectory();
-
- const ProcessLaunchInfo::FileAction *file_action;
- file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
- if (file_action)
- {
- if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
- stdin_path = file_action->GetPath();
- }
- file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
- if (file_action)
- {
- if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
- stdout_path = file_action->GetPath();
- }
- file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
- if (file_action)
- {
- if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
- stderr_path = file_action->GetPath();
- }
-
- m_monitor = new ProcessMonitor (this,
- module,
- launch_info.GetArguments().GetConstArgumentVector(),
- launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
- stdin_path,
- stdout_path,
- stderr_path,
- error);
-
- m_module = module;
-
- if (!error.Success())
- return error;
-
- SetID(m_monitor->GetPID());
- return error;
-}
-
void
-ProcessLinux::DidLaunch()
+ProcessLinux::Terminate()
{
}
-
-Error
-ProcessLinux::DoResume()
+const char *
+ProcessLinux::GetPluginNameStatic()
{
- StateType state = GetPrivateState();
-
- assert(state == eStateStopped || state == eStateCrashed);
-
- // We are about to resume a thread that will cause the process to exit so
- // set our exit status now. Do not change our state if the inferior
- // crashed.
- if (state == eStateStopped)
- {
- if (m_in_limbo)
- SetExitStatus(m_exit_status, NULL);
- else
- SetPrivateState(eStateRunning);
- }
-
- bool did_resume = false;
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i)
- {
- LinuxThread *thread = static_cast<LinuxThread*>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- did_resume = thread->Resume() || did_resume;
- }
- assert(did_resume && "Process resume failed!");
-
- return Error();
+ return "linux";
}
-addr_t
-ProcessLinux::GetImageInfoAddress()
+const char *
+ProcessLinux::GetPluginDescriptionStatic()
{
- Target *target = &GetTarget();
- ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
- Address addr = obj_file->GetImageInfoAddress();
-
- if (addr.IsValid())
- return addr.GetLoadAddress(target);
- else
- return LLDB_INVALID_ADDRESS;
+ return "Process plugin for Linux";
}
-Error
-ProcessLinux::DoHalt(bool &caused_stop)
-{
- Error error;
- if (IsStopped())
- {
- caused_stop = false;
- }
- else if (kill(GetID(), SIGSTOP))
- {
- caused_stop = false;
- error.SetErrorToErrno();
- }
- else
- {
- caused_stop = true;
- }
-
- return error;
-}
-
-Error
-ProcessLinux::DoDetach()
-{
- Error error;
-
- error = m_monitor->Detach();
- if (error.Success())
- SetPrivateState(eStateDetached);
-
- return error;
-}
-
-Error
-ProcessLinux::DoSignal(int signal)
-{
- Error error;
-
- if (kill(GetID(), signal))
- error.SetErrorToErrno();
-
- return error;
-}
-
-Error
-ProcessLinux::DoDestroy()
-{
- Error error;
-
- if (!HasExited())
- {
- // Drive the exit event to completion (do not keep the inferior in
- // limbo).
- m_exit_now = true;
-
- if (kill(m_monitor->GetPID(), SIGKILL) && error.Success())
- {
- error.SetErrorToErrno();
- return error;
- }
-
- SetPrivateState(eStateExited);
- }
-
- return error;
-}
-
-void
-ProcessLinux::SendMessage(const ProcessMessage &message)
-{
- Mutex::Locker lock(m_message_mutex);
-
- switch (message.GetKind())
- {
- default:
- assert(false && "Unexpected process message!");
- break;
-
- case ProcessMessage::eInvalidMessage:
- return;
-
- case ProcessMessage::eLimboMessage:
- m_in_limbo = true;
- m_exit_status = message.GetExitStatus();
- if (m_exit_now)
- {
- SetPrivateState(eStateExited);
- m_monitor->Detach();
- }
- else
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eExitMessage:
- m_exit_status = message.GetExitStatus();
- SetExitStatus(m_exit_status, NULL);
- break;
-
- case ProcessMessage::eTraceMessage:
- case ProcessMessage::eBreakpointMessage:
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eSignalMessage:
- case ProcessMessage::eSignalDeliveredMessage:
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eCrashMessage:
- SetPrivateState(eStateCrashed);
- break;
- }
-
- m_message_queue.push(message);
-}
-
-void
-ProcessLinux::RefreshStateAfterStop()
-{
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS));
- if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
- log->Printf ("ProcessLinux::%s()", __FUNCTION__);
-
- Mutex::Locker lock(m_message_mutex);
- if (m_message_queue.empty())
- return;
-
- ProcessMessage &message = m_message_queue.front();
-
- // Resolve the thread this message corresponds to and pass it along.
- // FIXME: we're really dealing with the pid here. This should get
- // fixed when this code is fixed to handle multiple threads.
- lldb::tid_t tid = message.GetTID();
- if (log)
- log->Printf ("ProcessLinux::%s() pid = %i", __FUNCTION__, tid);
- LinuxThread *thread = static_cast<LinuxThread*>(
- GetThreadList().FindThreadByID(tid, false).get());
-
- assert(thread);
- thread->Notify(message);
-
- m_message_queue.pop();
-}
-
-bool
-ProcessLinux::IsAlive()
-{
- StateType state = GetPrivateState();
- return state != eStateDetached && state != eStateExited && state != eStateInvalid;
-}
-
-size_t
-ProcessLinux::DoReadMemory(addr_t vm_addr,
- void *buf, size_t size, Error &error)
-{
- assert(m_monitor);
- return m_monitor->ReadMemory(vm_addr, buf, size, error);
-}
-
-size_t
-ProcessLinux::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
- Error &error)
-{
- assert(m_monitor);
- return m_monitor->WriteMemory(vm_addr, buf, size, error);
-}
-
-addr_t
-ProcessLinux::DoAllocateMemory(size_t size, uint32_t permissions,
- Error &error)
-{
- addr_t allocated_addr = LLDB_INVALID_ADDRESS;
-
- unsigned prot = 0;
- if (permissions & lldb::ePermissionsReadable)
- prot |= eMmapProtRead;
- if (permissions & lldb::ePermissionsWritable)
- prot |= eMmapProtWrite;
- if (permissions & lldb::ePermissionsExecutable)
- prot |= eMmapProtExec;
-
- if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
- eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
- m_addr_to_mmap_size[allocated_addr] = size;
- error.Clear();
- } else {
- allocated_addr = LLDB_INVALID_ADDRESS;
- error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
- }
-
- return allocated_addr;
-}
-
-Error
-ProcessLinux::DoDeallocateMemory(lldb::addr_t addr)
-{
- Error error;
- MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
- if (pos != m_addr_to_mmap_size.end() &&
- InferiorCallMunmap(this, addr, pos->second))
- m_addr_to_mmap_size.erase (pos);
- else
- error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr);
-
- return error;
-}
-
-size_t
-ProcessLinux::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
-{
- static const uint8_t g_i386_opcode[] = { 0xCC };
-
- ArchSpec arch = GetTarget().GetArchitecture();
- const uint8_t *opcode = NULL;
- size_t opcode_size = 0;
-
- switch (arch.GetCore())
- {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_64_x86_64:
- opcode = g_i386_opcode;
- opcode_size = sizeof(g_i386_opcode);
- break;
- }
-
- bp_site->SetTrapOpcode(opcode, opcode_size);
- return opcode_size;
-}
-
-Error
-ProcessLinux::EnableBreakpoint(BreakpointSite *bp_site)
-{
- return EnableSoftwareBreakpoint(bp_site);
-}
-
-Error
-ProcessLinux::DisableBreakpoint(BreakpointSite *bp_site)
-{
- return DisableSoftwareBreakpoint(bp_site);
-}
-
uint32_t
-ProcessLinux::UpdateThreadListIfNeeded()
-{
- // Do not allow recursive updates.
- return m_thread_list.GetSize(false);
-}
-
-uint32_t
ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
{
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
- if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
log->Printf ("ProcessLinux::%s() (pid = %i)", __FUNCTION__, GetID());
// Update the process thread list with this new thread.
@@ -508,62 +106,16 @@
assert(m_monitor);
ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
if (!thread_sp)
- thread_sp.reset(new LinuxThread(*this, GetID()));
+ thread_sp.reset(new POSIXThread(*this, GetID()));
- if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
log->Printf ("ProcessLinux::%s() updated pid = %i", __FUNCTION__, GetID());
new_thread_list.AddThread(thread_sp);
return new_thread_list.GetSize(false);
}
-ByteOrder
-ProcessLinux::GetByteOrder() const
-{
- // FIXME: We should be able to extract this value directly. See comment in
- // ProcessLinux().
- return m_byte_order;
-}
-size_t
-ProcessLinux::PutSTDIN(const char *buf, size_t len, Error &error)
-{
- ssize_t status;
- if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)
- {
- error.SetErrorToErrno();
- return 0;
- }
- return status;
-}
-
-size_t
-ProcessLinux::GetSTDOUT(char *buf, size_t len, Error &error)
-{
- ssize_t bytes_read;
-
- // The terminal file descriptor is always in non-block mode.
- if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0)
- {
- if (errno != EAGAIN)
- error.SetErrorToErrno();
- return 0;
- }
- return bytes_read;
-}
-
-size_t
-ProcessLinux::GetSTDERR(char *buf, size_t len, Error &error)
-{
- return GetSTDOUT(buf, len, error);
-}
-
-UnixSignals &
-ProcessLinux::GetUnixSignals()
-{
- return m_linux_signals;
-}
-
//------------------------------------------------------------------------------
// ProcessInterface protocol.
@@ -601,39 +153,3 @@
{
return NULL;
}
-
-//------------------------------------------------------------------------------
-// Utility functions.
-
-bool
-ProcessLinux::HasExited()
-{
- switch (GetPrivateState())
- {
- default:
- break;
-
- case eStateDetached:
- case eStateExited:
- return true;
- }
-
- return false;
-}
-
-bool
-ProcessLinux::IsStopped()
-{
- switch (GetPrivateState())
- {
- default:
- break;
-
- case eStateStopped:
- case eStateCrashed:
- case eStateSuspended:
- return true;
- }
-
- return false;
-}
Index: source/Plugins/Process/Linux/ProcessLinuxLog.cpp
===================================================================
--- source/Plugins/Process/Linux/ProcessLinuxLog.cpp (revision 147560)
+++ source/Plugins/Process/Linux/ProcessLinuxLog.cpp (working copy)
@@ -1,193 +0,0 @@
-//===-- ProcessLinuxLog.cpp ---------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ProcessLinuxLog.h"
-
-#include "lldb/Interpreter/Args.h"
-#include "lldb/Core/StreamFile.h"
-
-#include "ProcessLinux.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-
-// We want to avoid global constructors where code needs to be run so here we
-// control access to our static g_log_sp by hiding it in a singleton function
-// that will construct the static g_lob_sp the first time this function is
-// called.
-static LogSP &
-GetLog ()
-{
- static LogSP g_log_sp;
- return g_log_sp;
-}
-
-LogSP
-ProcessLinuxLog::GetLogIfAllCategoriesSet (uint32_t mask)
-{
- LogSP log(GetLog ());
- if (log && mask)
- {
- uint32_t log_mask = log->GetMask().Get();
- if ((log_mask & mask) != mask)
- return LogSP();
- }
- return log;
-}
-
-void
-ProcessLinuxLog::DisableLog (Args &args, Stream *feedback_strm)
-{
- LogSP log (GetLog ());
- if (log)
- {
- uint32_t flag_bits = 0;
-
- const size_t argc = args.GetArgumentCount ();
- if (argc > 0)
- {
- flag_bits = log->GetMask().Get();
- for (size_t i = 0; i < argc; ++i)
- {
- const char *arg = args.GetArgumentAtIndex (i);
-
-
- if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~LINUX_LOG_ALL;
- else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~LINUX_LOG_ASYNC;
- else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~LINUX_LOG_BREAKPOINTS;
- else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~LINUX_LOG_COMM;
- else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~LINUX_LOG_DEFAULT;
- else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~LINUX_LOG_PACKETS;
- else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY;
- else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_SHORT;
- else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_LONG;
- else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~LINUX_LOG_PROCESS;
- else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~LINUX_LOG_PTRACE;
- else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~LINUX_LOG_REGISTERS;
- else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~LINUX_LOG_STEP;
- else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~LINUX_LOG_THREAD;
- else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~LINUX_LOG_VERBOSE;
- else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~LINUX_LOG_WATCHPOINTS;
- else
- {
- feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
- ListLogCategories (feedback_strm);
- }
-
- }
- }
-
- if (flag_bits == 0)
- GetLog ().reset();
- else
- log->GetMask().Reset (flag_bits);
- }
-
- return;
-}
-
-LogSP
-ProcessLinuxLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm)
-{
- // Try see if there already is a log - that way we can reuse its settings.
- // We could reuse the log in toto, but we don't know that the stream is the same.
- uint32_t flag_bits = 0;
- LogSP log(GetLog ());
- if (log)
- flag_bits = log->GetMask().Get();
-
- // Now make a new log with this stream if one was provided
- if (log_stream_sp)
- {
- log = make_shared<Log>(log_stream_sp);
- GetLog () = log;
- }
-
- if (log)
- {
- bool got_unknown_category = false;
- const size_t argc = args.GetArgumentCount();
- for (size_t i=0; i<argc; ++i)
- {
- const char *arg = args.GetArgumentAtIndex(i);
-
- if (::strcasecmp (arg, "all") == 0 ) flag_bits |= LINUX_LOG_ALL;
- else if (::strcasecmp (arg, "async") == 0 ) flag_bits |= LINUX_LOG_ASYNC;
- else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits |= LINUX_LOG_BREAKPOINTS;
- else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits |= LINUX_LOG_COMM;
- else if (::strcasecmp (arg, "default") == 0 ) flag_bits |= LINUX_LOG_DEFAULT;
- else if (::strcasecmp (arg, "packets") == 0 ) flag_bits |= LINUX_LOG_PACKETS;
- else if (::strcasecmp (arg, "memory") == 0 ) flag_bits |= LINUX_LOG_MEMORY;
- else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= LINUX_LOG_MEMORY_DATA_SHORT;
- else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits |= LINUX_LOG_MEMORY_DATA_LONG;
- else if (::strcasecmp (arg, "process") == 0 ) flag_bits |= LINUX_LOG_PROCESS;
- else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits |= LINUX_LOG_PTRACE;
- else if (::strcasecmp (arg, "registers") == 0 ) flag_bits |= LINUX_LOG_REGISTERS;
- else if (::strcasecmp (arg, "step") == 0 ) flag_bits |= LINUX_LOG_STEP;
- else if (::strcasecmp (arg, "thread") == 0 ) flag_bits |= LINUX_LOG_THREAD;
- else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits |= LINUX_LOG_VERBOSE;
- else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits |= LINUX_LOG_WATCHPOINTS;
- else
- {
- feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
- if (got_unknown_category == false)
- {
- got_unknown_category = true;
- ListLogCategories (feedback_strm);
- }
- }
- }
- if (flag_bits == 0)
- flag_bits = LINUX_LOG_DEFAULT;
- log->GetMask().Reset(flag_bits);
- log->GetOptions().Reset(log_options);
- }
- return log;
-}
-
-void
-ProcessLinuxLog::ListLogCategories (Stream *strm)
-{
- strm->Printf ("Logging categories for '%s':\n"
- " all - turn on all available logging categories\n"
- " async - log asynchronous activity\n"
- " break - log breakpoints\n"
- " communication - log communication activity\n"
- " default - enable the default set of logging categories for liblldb\n"
- " packets - log gdb remote packets\n"
- " memory - log memory reads and writes\n"
- " data-short - log memory bytes for memory reads and writes for short transactions only\n"
- " data-long - log memory bytes for memory reads and writes for all transactions\n"
- " process - log process events and activities\n"
-#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION
- " ptrace - log all calls to ptrace\n"
-#endif
- " registers - log register read/writes\n"
- " thread - log thread events and activities\n"
- " step - log step related activities\n"
- " verbose - enable verbose logging\n"
- " watch - log watchpoint related activities\n", ProcessLinux::GetPluginNameStatic());
-}
-
-
-void
-ProcessLinuxLog::LogIf (uint32_t mask, const char *format, ...)
-{
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (mask));
- if (log)
- {
- va_list args;
- va_start (args, format);
- log->VAPrintf (format, args);
- va_end (args);
- }
-}
-
-int ProcessLinuxLog::m_nestinglevel;
Index: source/Plugins/Process/Linux/ProcessLinux.h
===================================================================
--- source/Plugins/Process/Linux/ProcessLinux.h (revision 147560)
+++ source/Plugins/Process/Linux/ProcessLinux.h (working copy)
@@ -19,11 +19,12 @@
#include "lldb/Target/Process.h"
#include "LinuxSignals.h"
#include "ProcessMessage.h"
+#include "ProcessPOSIX.h"
class ProcessMonitor;
class ProcessLinux :
- public lldb_private::Process
+ public ProcessPOSIX
{
public:
//------------------------------------------------------------------
@@ -51,97 +52,8 @@
ProcessLinux(lldb_private::Target& target,
lldb_private::Listener &listener);
- virtual
- ~ProcessLinux();
-
- //------------------------------------------------------------------
- // Process protocol.
- //------------------------------------------------------------------
- virtual bool
- CanDebug(lldb_private::Target &target, bool plugin_specified_by_name);
-
- virtual lldb_private::Error
- WillLaunch(lldb_private::Module *module);
-
- virtual lldb_private::Error
- DoAttachToProcessWithID(lldb::pid_t pid);
-
- virtual lldb_private::Error
- DoLaunch (lldb_private::Module *exe_module,
- const lldb_private::ProcessLaunchInfo &launch_info);
-
- virtual void
- DidLaunch();
-
- virtual lldb_private::Error
- DoResume();
-
- virtual lldb_private::Error
- DoHalt(bool &caused_stop);
-
- virtual lldb_private::Error
- DoDetach();
-
- virtual lldb_private::Error
- DoSignal(int signal);
-
- virtual lldb_private::Error
- DoDestroy();
-
- virtual void
- RefreshStateAfterStop();
-
- virtual bool
- IsAlive();
-
- virtual size_t
- DoReadMemory(lldb::addr_t vm_addr,
- void *buf,
- size_t size,
- lldb_private::Error &error);
-
- virtual size_t
- DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
- lldb_private::Error &error);
-
- virtual lldb::addr_t
- DoAllocateMemory(size_t size, uint32_t permissions,
- lldb_private::Error &error);
-
- virtual lldb_private::Error
- DoDeallocateMemory(lldb::addr_t ptr);
-
- virtual size_t
- GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
-
- virtual lldb_private::Error
- EnableBreakpoint(lldb_private::BreakpointSite *bp_site);
-
- virtual lldb_private::Error
- DisableBreakpoint(lldb_private::BreakpointSite *bp_site);
-
virtual uint32_t
- UpdateThreadListIfNeeded();
-
- uint32_t
- UpdateThreadList(lldb_private::ThreadList &old_thread_list,
- lldb_private::ThreadList &new_thread_list);
-
- virtual lldb::ByteOrder
- GetByteOrder() const;
-
- virtual lldb::addr_t
- GetImageInfoAddress();
-
- virtual size_t
- PutSTDIN(const char *buf, size_t len, lldb_private::Error &error);
-
- virtual size_t
- GetSTDOUT(char *buf, size_t len, lldb_private::Error &error);
-
- virtual size_t
- GetSTDERR(char *buf, size_t len, lldb_private::Error &error);
-
+ UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list);
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -165,59 +77,11 @@
EnablePluginLogging(lldb_private::Stream *strm,
lldb_private::Args &command);
- //--------------------------------------------------------------------------
- // ProcessLinux internal API.
-
- /// Registers the given message with this process.
- void SendMessage(const ProcessMessage &message);
-
- ProcessMonitor &
- GetMonitor() { assert(m_monitor); return *m_monitor; }
-
- lldb_private::UnixSignals &
- GetUnixSignals();
-
private:
- /// Target byte order.
- lldb::ByteOrder m_byte_order;
- /// Process monitor;
- ProcessMonitor *m_monitor;
-
- /// The module we are executing.
- lldb_private::Module *m_module;
-
- /// Message queue notifying this instance of inferior process state changes.
- lldb_private::Mutex m_message_mutex;
- std::queue<ProcessMessage> m_message_queue;
-
- /// True when the process has entered a state of "limbo".
- ///
- /// This flag qualifies eStateStopped. It lets us know that when we
- /// continue from this state the process will exit. Also, when true,
- /// Process::m_exit_status is set.
- bool m_in_limbo;
-
- /// Drive any exit events to completion.
- bool m_exit_now;
-
/// Linux-specific signal set.
LinuxSignals m_linux_signals;
- /// Updates the loaded sections provided by the executable.
- ///
- /// FIXME: It would probably be better to delegate this task to the
- /// DynamicLoader plugin, when we have one.
- void UpdateLoadedSections();
-
- /// Returns true if the process has exited.
- bool HasExited();
-
- /// Returns true if the process is stopped.
- bool IsStopped();
-
- typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
- MMapMap m_addr_to_mmap_size;
};
#endif // liblldb_MacOSXProcess_H_
Index: source/Plugins/Process/Linux/ProcessLinuxLog.h
===================================================================
--- source/Plugins/Process/Linux/ProcessLinuxLog.h (revision 147560)
+++ source/Plugins/Process/Linux/ProcessLinuxLog.h (working copy)
@@ -1,98 +0,0 @@
-//===-- ProcessLinuxLog.h -----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ProcessLinuxLog_h_
-#define liblldb_ProcessLinuxLog_h_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-
-// Project includes
-#include "lldb/Core/Log.h"
-
-#define LINUX_LOG_VERBOSE (1u << 0)
-#define LINUX_LOG_PROCESS (1u << 1)
-#define LINUX_LOG_THREAD (1u << 2)
-#define LINUX_LOG_PACKETS (1u << 3)
-#define LINUX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls
-#define LINUX_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes
-#define LINUX_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes
-#define LINUX_LOG_BREAKPOINTS (1u << 7)
-#define LINUX_LOG_WATCHPOINTS (1u << 8)
-#define LINUX_LOG_STEP (1u << 9)
-#define LINUX_LOG_COMM (1u << 10)
-#define LINUX_LOG_ASYNC (1u << 11)
-#define LINUX_LOG_PTRACE (1u << 12)
-#define LINUX_LOG_REGISTERS (1u << 13)
-#define LINUX_LOG_ALL (UINT32_MAX)
-#define LINUX_LOG_DEFAULT LINUX_LOG_PACKETS
-
-// The size which determines "short memory reads/writes".
-#define LINUX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t))
-
-class ProcessLinuxLog
-{
- static int m_nestinglevel;
-
-public:
- static lldb::LogSP
- GetLogIfAllCategoriesSet(uint32_t mask = 0);
-
- static void
- DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm);
-
- static lldb::LogSP
- EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options,
- lldb_private::Args &args, lldb_private::Stream *feedback_strm);
-
- static void
- ListLogCategories (lldb_private::Stream *strm);
-
- static void
- LogIf (uint32_t mask, const char *format, ...);
-
- // The following functions can be used to enable the client to limit
- // logging to only the top level function calls. This is useful for
- // recursive functions. FIXME: not thread safe!
- // Example:
- // void NestingFunc() {
- // LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(LINUX_LOG_ALL));
- // if (log)
- // {
- // ProcessLinuxLog::IncNestLevel();
- // if (ProcessLinuxLog::AtTopNestLevel())
- // log->Print(msg);
- // }
- // NestingFunc();
- // if (log)
- // ProcessLinuxLog::DecNestLevel();
- // }
-
- static bool
- AtTopNestLevel()
- {
- return m_nestinglevel == 1;
- }
-
- static void
- IncNestLevel()
- {
- ++m_nestinglevel;
- }
-
- static void
- DecNestLevel()
- {
- --m_nestinglevel;
- assert(m_nestinglevel >= 0);
- }
-};
-
-#endif // liblldb_ProcessLinuxLog_h_
Index: source/Plugins/Process/Linux/RegisterContextLinux.h
===================================================================
--- source/Plugins/Process/Linux/RegisterContextLinux.h (revision 147560)
+++ source/Plugins/Process/Linux/RegisterContextLinux.h (working copy)
@@ -1,40 +0,0 @@
-//===-- RegisterContext_x86_64.h --------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContextLinux_H_
-#define liblldb_RegisterContextLinux_H_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Target/RegisterContext.h"
-
-//------------------------------------------------------------------------------
-/// @class RegisterContextLinux
-///
-/// @brief Extends RegisterClass with a few virtual operations useful on Linux.
-class RegisterContextLinux
- : public lldb_private::RegisterContext
-{
-public:
- RegisterContextLinux(lldb_private::Thread &thread,
- uint32_t concrete_frame_idx)
- : RegisterContext(thread, concrete_frame_idx) { }
-
- /// Updates the register state of the associated thread after hitting a
- /// breakpoint (if that make sense for the architecture). Default
- /// implementation simply returns true for architectures which do not
- /// require any update.
- ///
- /// @return
- /// True if the operation succeeded and false otherwise.
- virtual bool UpdateAfterBreakpoint() { return true; }
-};
-
-#endif // #ifndef liblldb_RegisterContextLinux_H_
Index: source/Plugins/Process/Linux/LinuxStopInfo.cpp
===================================================================
--- source/Plugins/Process/Linux/LinuxStopInfo.cpp (revision 147560)
+++ source/Plugins/Process/Linux/LinuxStopInfo.cpp (working copy)
@@ -1,60 +0,0 @@
-//===-- LinuxStopInfo.cpp ---------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "LinuxStopInfo.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-
-//===----------------------------------------------------------------------===//
-// LinuxLimboStopInfo
-
-LinuxLimboStopInfo::~LinuxLimboStopInfo() { }
-
-lldb::StopReason
-LinuxLimboStopInfo::GetStopReason() const
-{
- return lldb::eStopReasonTrace;
-}
-
-const char *
-LinuxLimboStopInfo::GetDescription()
-{
- return "thread exiting";
-}
-
-bool
-LinuxLimboStopInfo::ShouldStop(Event *event_ptr)
-{
- return true;
-}
-
-bool
-LinuxLimboStopInfo::ShouldNotify(Event *event_ptr)
-{
- return true;
-}
-
-//===----------------------------------------------------------------------===//
-// LinuxCrashStopInfo
-
-LinuxCrashStopInfo::~LinuxCrashStopInfo() { }
-
-lldb::StopReason
-LinuxCrashStopInfo::GetStopReason() const
-{
- return lldb::eStopReasonException;
-}
-
-const char *
-LinuxCrashStopInfo::GetDescription()
-{
- return ProcessMessage::GetCrashReasonString(m_crash_reason);
-}
Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp
===================================================================
--- source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp (revision 147560)
+++ source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp (working copy)
@@ -1,650 +0,0 @@
-//===-- RegisterContextLinux_i386.cpp ---------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Host/Endian.h"
-
-#include "ProcessLinux.h"
-#include "ProcessLinuxLog.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextLinux_i386.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-enum
-{
- k_first_gpr,
- gpr_eax = k_first_gpr,
- gpr_ebx,
- gpr_ecx,
- gpr_edx,
- gpr_edi,
- gpr_esi,
- gpr_ebp,
- gpr_esp,
- gpr_ss,
- gpr_eflags,
- gpr_eip,
- gpr_cs,
- gpr_ds,
- gpr_es,
- gpr_fs,
- gpr_gs,
- k_last_gpr = gpr_gs,
-
- k_first_fpr,
- fpu_fcw = k_first_fpr,
- fpu_fsw,
- fpu_ftw,
- fpu_fop,
- fpu_ip,
- fpu_cs,
- fpu_foo,
- fpu_fos,
- fpu_mxcsr,
- fpu_stmm0,
- fpu_stmm1,
- fpu_stmm2,
- fpu_stmm3,
- fpu_stmm4,
- fpu_stmm5,
- fpu_stmm6,
- fpu_stmm7,
- fpu_xmm0,
- fpu_xmm1,
- fpu_xmm2,
- fpu_xmm3,
- fpu_xmm4,
- fpu_xmm5,
- fpu_xmm6,
- fpu_xmm7,
- k_last_fpr = fpu_xmm7,
-
- k_num_registers,
- k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
- k_num_fpu_registers = k_last_fpr - k_first_fpr + 1
-};
-
-// Number of register sets provided by this context.
-enum
-{
- k_num_register_sets = 2
-};
-
-enum
-{
- gcc_eax = 0,
- gcc_ecx,
- gcc_edx,
- gcc_ebx,
- gcc_ebp,
- gcc_esp,
- gcc_esi,
- gcc_edi,
- gcc_eip,
- gcc_eflags
-};
-
-enum
-{
- dwarf_eax = 0,
- dwarf_ecx,
- dwarf_edx,
- dwarf_ebx,
- dwarf_esp,
- dwarf_ebp,
- dwarf_esi,
- dwarf_edi,
- dwarf_eip,
- dwarf_eflags,
- dwarf_stmm0 = 11,
- dwarf_stmm1,
- dwarf_stmm2,
- dwarf_stmm3,
- dwarf_stmm4,
- dwarf_stmm5,
- dwarf_stmm6,
- dwarf_stmm7,
- dwarf_xmm0 = 21,
- dwarf_xmm1,
- dwarf_xmm2,
- dwarf_xmm3,
- dwarf_xmm4,
- dwarf_xmm5,
- dwarf_xmm6,
- dwarf_xmm7
-};
-
-enum
-{
- gdb_eax = 0,
- gdb_ecx = 1,
- gdb_edx = 2,
- gdb_ebx = 3,
- gdb_esp = 4,
- gdb_ebp = 5,
- gdb_esi = 6,
- gdb_edi = 7,
- gdb_eip = 8,
- gdb_eflags = 9,
- gdb_cs = 10,
- gdb_ss = 11,
- gdb_ds = 12,
- gdb_es = 13,
- gdb_fs = 14,
- gdb_gs = 15,
- gdb_stmm0 = 16,
- gdb_stmm1 = 17,
- gdb_stmm2 = 18,
- gdb_stmm3 = 19,
- gdb_stmm4 = 20,
- gdb_stmm5 = 21,
- gdb_stmm6 = 22,
- gdb_stmm7 = 23,
- gdb_fcw = 24,
- gdb_fsw = 25,
- gdb_ftw = 26,
- gdb_fpu_cs = 27,
- gdb_ip = 28,
- gdb_fpu_ds = 29,
- gdb_dp = 30,
- gdb_fop = 31,
- gdb_xmm0 = 32,
- gdb_xmm1 = 33,
- gdb_xmm2 = 34,
- gdb_xmm3 = 35,
- gdb_xmm4 = 36,
- gdb_xmm5 = 37,
- gdb_xmm6 = 38,
- gdb_xmm7 = 39,
- gdb_mxcsr = 40,
- gdb_mm0 = 41,
- gdb_mm1 = 42,
- gdb_mm2 = 43,
- gdb_mm3 = 44,
- gdb_mm4 = 45,
- gdb_mm5 = 46,
- gdb_mm6 = 47,
- gdb_mm7 = 48
-};
-
-static const
-uint32_t g_gpr_regnums[k_num_gpr_registers] =
-{
- gpr_eax,
- gpr_ebx,
- gpr_ecx,
- gpr_edx,
- gpr_edi,
- gpr_esi,
- gpr_ebp,
- gpr_esp,
- gpr_ss,
- gpr_eflags,
- gpr_eip,
- gpr_cs,
- gpr_ds,
- gpr_es,
- gpr_fs,
- gpr_gs,
-};
-
-static const uint32_t
-g_fpu_regnums[k_num_fpu_registers] =
-{
- fpu_fcw,
- fpu_fsw,
- fpu_ftw,
- fpu_fop,
- fpu_ip,
- fpu_cs,
- fpu_foo,
- fpu_fos,
- fpu_mxcsr,
- fpu_stmm0,
- fpu_stmm1,
- fpu_stmm2,
- fpu_stmm3,
- fpu_stmm4,
- fpu_stmm5,
- fpu_stmm6,
- fpu_stmm7,
- fpu_xmm0,
- fpu_xmm1,
- fpu_xmm2,
- fpu_xmm3,
- fpu_xmm4,
- fpu_xmm5,
- fpu_xmm6,
- fpu_xmm7,
-};
-
-static const RegisterSet
-g_reg_sets[k_num_register_sets] =
-{
- { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
- { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums }
-};
-
-// Computes the offset of the given GPR in the user data area.
-#define GPR_OFFSET(regname) \
- (offsetof(RegisterContextLinux_i386::UserArea, regs) + \
- offsetof(RegisterContextLinux_i386::GPR, regname))
-
-// Computes the offset of the given FPR in the user data area.
-#define FPR_OFFSET(regname) \
- (offsetof(RegisterContextLinux_i386::UserArea, i387) + \
- offsetof(RegisterContextLinux_i386::FPU, regname))
-
-// Number of bytes needed to represent a GPR.
-#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::GPR*)NULL)->reg)
-
-// Number of bytes needed to represent a FPR.
-#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::FPU*)NULL)->reg)
-
-// Number of bytes needed to represent the i'th FP register.
-#define FP_SIZE sizeof(((RegisterContextLinux_i386::MMSReg*)NULL)->bytes)
-
-// Number of bytes needed to represent an XMM register.
-#define XMM_SIZE sizeof(RegisterContextLinux_i386::XMMReg)
-
-#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
- { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } }
-
-#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \
- { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } }
-
-#define DEFINE_FP(reg, i) \
- { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \
- eFormatVectorOfUInt8, \
- { dwarf_##reg##i, dwarf_##reg##i, \
- LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } }
-
-#define DEFINE_XMM(reg, i) \
- { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \
- eFormatVectorOfUInt8, \
- { dwarf_##reg##i, dwarf_##reg##i, \
- LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } }
-
-static RegisterInfo
-g_register_infos[k_num_registers] =
-{
- // General purpose registers.
- DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax),
- DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx),
- DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx),
- DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx),
- DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi),
- DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi),
- DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp),
- DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp),
- DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss),
- DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags),
- DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip),
- DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs),
- DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds),
- DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es),
- DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs),
- DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs),
-
- // Floating point registers.
- DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw),
- DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw),
- DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw),
- DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop),
- DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip),
- DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs),
- DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp),
- DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds),
- DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr),
-
- DEFINE_FP(stmm, 0),
- DEFINE_FP(stmm, 1),
- DEFINE_FP(stmm, 2),
- DEFINE_FP(stmm, 3),
- DEFINE_FP(stmm, 4),
- DEFINE_FP(stmm, 5),
- DEFINE_FP(stmm, 6),
- DEFINE_FP(stmm, 7),
-
- // XMM registers
- DEFINE_XMM(xmm, 0),
- DEFINE_XMM(xmm, 1),
- DEFINE_XMM(xmm, 2),
- DEFINE_XMM(xmm, 3),
- DEFINE_XMM(xmm, 4),
- DEFINE_XMM(xmm, 5),
- DEFINE_XMM(xmm, 6),
- DEFINE_XMM(xmm, 7),
-
-};
-
-#ifndef NDEBUG
-static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
-#endif
-
-static unsigned GetRegOffset(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register number.");
- return g_register_infos[reg].byte_offset;
-}
-
-#if 0 // These functions are currently not in use.
-static unsigned GetRegSize(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register number.");
- return g_register_infos[reg].byte_size;
-}
-
-static bool IsGPR(unsigned reg)
-{
- return reg <= k_last_gpr; // GPR's come first.
-}
-
-static bool IsFPR(unsigned reg)
-{
- return (k_first_fpr <= reg && reg <= k_last_fpr);
-}
-#endif
-
-
-RegisterContextLinux_i386::RegisterContextLinux_i386(Thread &thread,
- uint32_t concrete_frame_idx)
- : RegisterContextLinux(thread, concrete_frame_idx)
-{
-}
-
-RegisterContextLinux_i386::~RegisterContextLinux_i386()
-{
-}
-
-ProcessMonitor &
-RegisterContextLinux_i386::GetMonitor()
-{
- ProcessLinux *process = static_cast<ProcessLinux*>(CalculateProcess());
- return process->GetMonitor();
-}
-
-void
-RegisterContextLinux_i386::Invalidate()
-{
-}
-
-void
-RegisterContextLinux_i386::InvalidateAllRegisters()
-{
-}
-
-size_t
-RegisterContextLinux_i386::GetRegisterCount()
-{
- assert(k_num_register_infos == k_num_registers);
- return k_num_registers;
-}
-
-const RegisterInfo *
-RegisterContextLinux_i386::GetRegisterInfoAtIndex(uint32_t reg)
-{
- assert(k_num_register_infos == k_num_registers);
- if (reg < k_num_registers)
- return &g_register_infos[reg];
- else
- return NULL;
-}
-
-size_t
-RegisterContextLinux_i386::GetRegisterSetCount()
-{
- return k_num_register_sets;
-}
-
-const RegisterSet *
-RegisterContextLinux_i386::GetRegisterSet(uint32_t set)
-{
- if (set < k_num_register_sets)
- return &g_reg_sets[set];
- else
- return NULL;
-}
-
-unsigned
-RegisterContextLinux_i386::GetRegisterIndexFromOffset(unsigned offset)
-{
- unsigned reg;
- for (reg = 0; reg < k_num_registers; reg++)
- {
- if (g_register_infos[reg].byte_offset == offset)
- break;
- }
- assert(reg < k_num_registers && "Invalid register offset.");
- return reg;
-}
-
-const char *
-RegisterContextLinux_i386::GetRegisterName(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register offset.");
- return g_register_infos[reg].name;
-}
-
-bool
-RegisterContextLinux_i386::ReadRegister(const RegisterInfo *reg_info,
- RegisterValue &value)
-{
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(GetRegOffset(reg), value);
-}
-
-bool
-RegisterContextLinux_i386::ReadAllRegisterValues(DataBufferSP &data_sp)
-{
- return false;
-}
-
-bool RegisterContextLinux_i386::WriteRegister(const RegisterInfo *reg_info,
- const RegisterValue &value)
-{
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(GetRegOffset(reg), value);
-}
-
-bool
-RegisterContextLinux_i386::WriteAllRegisterValues(const DataBufferSP &data)
-{
- return false;
-}
-
-bool
-RegisterContextLinux_i386::UpdateAfterBreakpoint()
-{
- // PC points one byte past the int3 responsible for the breakpoint.
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- SetPC(pc - 1);
- return true;
-}
-
-uint32_t
-RegisterContextLinux_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind,
- uint32_t num)
-{
- if (kind == eRegisterKindGeneric)
- {
- switch (num)
- {
- case LLDB_REGNUM_GENERIC_PC: return gpr_eip;
- case LLDB_REGNUM_GENERIC_SP: return gpr_esp;
- case LLDB_REGNUM_GENERIC_FP: return gpr_ebp;
- case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags;
- case LLDB_REGNUM_GENERIC_RA:
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
- {
- switch (num)
- {
- case dwarf_eax: return gpr_eax;
- case dwarf_edx: return gpr_edx;
- case dwarf_ecx: return gpr_ecx;
- case dwarf_ebx: return gpr_ebx;
- case dwarf_esi: return gpr_esi;
- case dwarf_edi: return gpr_edi;
- case dwarf_ebp: return gpr_ebp;
- case dwarf_esp: return gpr_esp;
- case dwarf_eip: return gpr_eip;
- case dwarf_xmm0: return fpu_xmm0;
- case dwarf_xmm1: return fpu_xmm1;
- case dwarf_xmm2: return fpu_xmm2;
- case dwarf_xmm3: return fpu_xmm3;
- case dwarf_xmm4: return fpu_xmm4;
- case dwarf_xmm5: return fpu_xmm5;
- case dwarf_xmm6: return fpu_xmm6;
- case dwarf_xmm7: return fpu_xmm7;
- case dwarf_stmm0: return fpu_stmm0;
- case dwarf_stmm1: return fpu_stmm1;
- case dwarf_stmm2: return fpu_stmm2;
- case dwarf_stmm3: return fpu_stmm3;
- case dwarf_stmm4: return fpu_stmm4;
- case dwarf_stmm5: return fpu_stmm5;
- case dwarf_stmm6: return fpu_stmm6;
- case dwarf_stmm7: return fpu_stmm7;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGDB)
- {
- switch (num)
- {
- case gdb_eax : return gpr_eax;
- case gdb_ebx : return gpr_ebx;
- case gdb_ecx : return gpr_ecx;
- case gdb_edx : return gpr_edx;
- case gdb_esi : return gpr_esi;
- case gdb_edi : return gpr_edi;
- case gdb_ebp : return gpr_ebp;
- case gdb_esp : return gpr_esp;
- case gdb_eip : return gpr_eip;
- case gdb_eflags : return gpr_eflags;
- case gdb_cs : return gpr_cs;
- case gdb_ss : return gpr_ss;
- case gdb_ds : return gpr_ds;
- case gdb_es : return gpr_es;
- case gdb_fs : return gpr_fs;
- case gdb_gs : return gpr_gs;
- case gdb_stmm0 : return fpu_stmm0;
- case gdb_stmm1 : return fpu_stmm1;
- case gdb_stmm2 : return fpu_stmm2;
- case gdb_stmm3 : return fpu_stmm3;
- case gdb_stmm4 : return fpu_stmm4;
- case gdb_stmm5 : return fpu_stmm5;
- case gdb_stmm6 : return fpu_stmm6;
- case gdb_stmm7 : return fpu_stmm7;
- case gdb_fcw : return fpu_fcw;
- case gdb_fsw : return fpu_fsw;
- case gdb_ftw : return fpu_ftw;
- case gdb_fpu_cs : return fpu_cs;
- case gdb_ip : return fpu_ip;
- case gdb_fpu_ds : return fpu_fos;
- case gdb_dp : return fpu_foo;
- case gdb_fop : return fpu_fop;
- case gdb_xmm0 : return fpu_xmm0;
- case gdb_xmm1 : return fpu_xmm1;
- case gdb_xmm2 : return fpu_xmm2;
- case gdb_xmm3 : return fpu_xmm3;
- case gdb_xmm4 : return fpu_xmm4;
- case gdb_xmm5 : return fpu_xmm5;
- case gdb_xmm6 : return fpu_xmm6;
- case gdb_xmm7 : return fpu_xmm7;
- case gdb_mxcsr : return fpu_mxcsr;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
- else if (kind == eRegisterKindLLDB)
- {
- return num;
- }
-
- return LLDB_INVALID_REGNUM;
-}
-
-bool
-RegisterContextLinux_i386::HardwareSingleStep(bool enable)
-{
- enum { TRACE_BIT = 0x100 };
- uint64_t eflags;
-
- if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL)
- return false;
-
- if (enable)
- {
- if (eflags & TRACE_BIT)
- return true;
-
- eflags |= TRACE_BIT;
- }
- else
- {
- if (!(eflags & TRACE_BIT))
- return false;
-
- eflags &= ~TRACE_BIT;
- }
-
- return WriteRegisterFromUnsigned(gpr_eflags, eflags);
-}
-
-void
-RegisterContextLinux_i386::LogGPR(const char *title)
-{
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS));
- if (log)
- {
- if (title)
- log->Printf ("%s", title);
- for (uint32_t i=0; i<k_num_gpr_registers; i++)
- {
- uint32_t reg = gpr_eax + i;
- log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]);
- }
- }
-}
-
-bool
-RegisterContextLinux_i386::ReadGPR()
-{
- bool result;
-
- ProcessMonitor &monitor = GetMonitor();
- result = monitor.ReadGPR(&user.regs);
- LogGPR("RegisterContextLinux_i386::ReadGPR()");
- return result;
-}
-
-bool
-RegisterContextLinux_i386::ReadFPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadFPR(&user.i387);
-}
Index: source/Plugins/Process/Linux/ProcessMessage.cpp
===================================================================
--- source/Plugins/Process/Linux/ProcessMessage.cpp (revision 147560)
+++ source/Plugins/Process/Linux/ProcessMessage.cpp (working copy)
@@ -1,245 +0,0 @@
-//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ProcessMessage.h"
-
-using namespace lldb_private;
-
-const char *
-ProcessMessage::GetCrashReasonString(CrashReason reason)
-{
- const char *str = NULL;
-
- switch (reason)
- {
- default:
- assert(false && "invalid CrashReason");
- break;
-
- case eInvalidAddress:
- str = "invalid address";
- break;
- case ePrivilegedAddress:
- str = "address access protected";
- break;
- case eIllegalOpcode:
- str = "illegal instruction";
- break;
- case eIllegalOperand:
- str = "illegal instruction operand";
- break;
- case eIllegalAddressingMode:
- str = "illegal addressing mode";
- break;
- case eIllegalTrap:
- str = "illegal trap";
- break;
- case ePrivilegedOpcode:
- str = "privileged instruction";
- break;
- case ePrivilegedRegister:
- str = "privileged register";
- break;
- case eCoprocessorError:
- str = "coprocessor error";
- break;
- case eInternalStackError:
- str = "internal stack error";
- break;
- case eIllegalAlignment:
- str = "illegal alignment";
- break;
- case eIllegalAddress:
- str = "illegal address";
- break;
- case eHardwareError:
- str = "hardware error";
- break;
- case eIntegerDivideByZero:
- str = "integer divide by zero";
- break;
- case eIntegerOverflow:
- str = "integer overflow";
- break;
- case eFloatDivideByZero:
- str = "floating point divide by zero";
- break;
- case eFloatOverflow:
- str = "floating point overflow";
- break;
- case eFloatUnderflow:
- str = "floating point underflow";
- break;
- case eFloatInexactResult:
- str = "inexact floating point result";
- break;
- case eFloatInvalidOperation:
- str = "invalid floating point operation";
- break;
- case eFloatSubscriptRange:
- str = "invalid floating point subscript range";
- break;
- }
-
- return str;
-}
-
-const char *
-ProcessMessage::PrintCrashReason(CrashReason reason)
-{
-#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
- // Just return the code in asci for integration builds.
- chcar str[8];
- sprintf(str, "%d", reason);
-#else
- const char *str = NULL;
-
- switch (reason)
- {
- default:
- assert(false && "invalid CrashReason");
- break;
-
- case eInvalidCrashReason:
- str = "eInvalidCrashReason";
- break;
-
- // SIGSEGV crash rcase easons.
- case eInvalidAddress:
- str = "eInvalidAddress";
- break;
- case ePrivilegedAddress:
- str = "ePrivilegedAddress";
- break;
-
- // SIGILL crash rcase easons.
- case eIllegalOpcode:
- str = "eIllegalOpcode";
- break;
- case eIllegalOperand:
- str = "eIllegalOperand";
- break;
- case eIllegalAddressingMode:
- str = "eIllegalAddressingMode";
- break;
- case eIllegalTrap:
- str = "eIllegalTrap";
- break;
- case ePrivilegedOpcode:
- str = "ePrivilegedOpcode";
- break;
- case ePrivilegedRegister:
- str = "ePrivilegedRegister";
- break;
- case eCoprocessorError:
- str = "eCoprocessorError";
- break;
- case eInternalStackError:
- str = "eInternalStackError";
- break;
-
- // SIGBUS crash rcase easons:
- case eIllegalAlignment:
- str = "eIllegalAlignment";
- break;
- case eIllegalAddress:
- str = "eIllegalAddress";
- break;
- case eHardwareError:
- str = "eHardwareError";
- break;
-
- // SIGFPE crash rcase easons:
- case eIntegerDivideByZero:
- str = "eIntegerDivideByZero";
- break;
- case eIntegerOverflow:
- str = "eIntegerOverflow";
- break;
- case eFloatDivideByZero:
- str = "eFloatDivideByZero";
- break;
- case eFloatOverflow:
- str = "eFloatOverflow";
- break;
- case eFloatUnderflow:
- str = "eFloatUnderflow";
- break;
- case eFloatInexactResult:
- str = "eFloatInexactResult";
- break;
- case eFloatInvalidOperation:
- str = "eFloatInvalidOperation";
- break;
- case eFloatSubscriptRange:
- str = "eFloatSubscriptRange";
- break;
- }
-#endif
-
- return str;
-}
-
-const char *
-ProcessMessage::PrintCrashReason() const
-{
- return PrintCrashReason(m_crash_reason);
-}
-
-const char *
-ProcessMessage::PrintKind(Kind kind)
-{
-#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
- // Just return the code in asci for integration builds.
- chcar str[8];
- sprintf(str, "%d", reason);
-#else
- const char *str = NULL;
-
- switch (kind)
- {
- default:
- assert(false && "invalid Kind");
- break;
-
- case eInvalidMessage:
- str = "eInvalidMessage";
- break;
- case eExitMessage:
- str = "eExitMessage";
- break;
- case eLimboMessage:
- str = "eLimboMessage";
- break;
- case eSignalMessage:
- str = "eSignalMessage";
- break;
- case eSignalDeliveredMessage:
- str = "eSignalDeliveredMessage";
- break;
- case eTraceMessage:
- str = "eTraceMessage";
- break;
- case eBreakpointMessage:
- str = "eBreakpointMessage";
- break;
- case eCrashMessage:
- str = "eCrashMessage";
- break;
- }
-#endif
-
- return str;
-}
-
-const char *
-ProcessMessage::PrintKind() const
-{
- return PrintKind(m_kind);
-}
Index: source/Plugins/Process/Linux/ProcessMonitor.cpp
===================================================================
--- source/Plugins/Process/Linux/ProcessMonitor.cpp (revision 147560)
+++ source/Plugins/Process/Linux/ProcessMonitor.cpp (working copy)
@@ -28,9 +28,9 @@
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/PseudoTerminal.h"
-#include "LinuxThread.h"
+#include "POSIXThread.h"
#include "ProcessLinux.h"
-#include "ProcessLinuxLog.h"
+#include "ProcessPOSIXLog.h"
#include "ProcessMonitor.h"
@@ -63,8 +63,8 @@
static void PtraceDisplayBytes(__ptrace_request &req, void *data)
{
StreamString buf;
- LogSP verbose_log (ProcessLinuxLog::GetLogIfAllCategoriesSet (
- LINUX_LOG_PTRACE | LINUX_LOG_VERBOSE));
+ LogSP verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (
+ POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE));
if (verbose_log)
{
@@ -120,7 +120,7 @@
{
long int result;
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PTRACE));
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE));
if (log)
log->Printf("ptrace(%s, %u, %p, %p) called from file %s line %d",
@@ -170,10 +170,10 @@
size_t remainder;
long data;
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL));
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
if (log)
- ProcessLinuxLog::IncNestLevel();
- if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY))
+ ProcessPOSIXLog::IncNestLevel();
+ if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__,
pid, word_size, (void*)vm_addr, buf, size);
@@ -187,7 +187,7 @@
{
error.SetErrorToErrno();
if (log)
- ProcessLinuxLog::DecNestLevel();
+ ProcessPOSIXLog::DecNestLevel();
return bytes_read;
}
@@ -200,10 +200,10 @@
for (unsigned i = 0; i < remainder; ++i)
dst[i] = ((data >> i*8) & 0xFF);
- if (log && ProcessLinuxLog::AtTopNestLevel() &&
- (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) ||
- (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) &&
- size <= LINUX_LOG_MEMORY_SHORT_BYTES)))
+ if (log && ProcessPOSIXLog::AtTopNestLevel() &&
+ (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
+ (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
+ size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
(void*)vm_addr, *(unsigned long*)dst, (unsigned long)data);
@@ -212,7 +212,7 @@
}
if (log)
- ProcessLinuxLog::DecNestLevel();
+ ProcessPOSIXLog::DecNestLevel();
return bytes_read;
}
@@ -224,10 +224,10 @@
size_t bytes_written = 0;
size_t remainder;
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL));
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
if (log)
- ProcessLinuxLog::IncNestLevel();
- if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY))
+ ProcessPOSIXLog::IncNestLevel();
+ if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__,
pid, word_size, (void*)vm_addr, buf, size);
@@ -244,10 +244,10 @@
for (unsigned i = 0; i < word_size; ++i)
data |= (unsigned long)src[i] << i*8;
- if (log && ProcessLinuxLog::AtTopNestLevel() &&
- (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) ||
- (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) &&
- size <= LINUX_LOG_MEMORY_SHORT_BYTES)))
+ if (log && ProcessPOSIXLog::AtTopNestLevel() &&
+ (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
+ (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
+ size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
(void*)vm_addr, *(unsigned long*)src, data);
@@ -255,7 +255,7 @@
{
error.SetErrorToErrno();
if (log)
- ProcessLinuxLog::DecNestLevel();
+ ProcessPOSIXLog::DecNestLevel();
return bytes_written;
}
}
@@ -266,7 +266,7 @@
buff, word_size, error) != word_size)
{
if (log)
- ProcessLinuxLog::DecNestLevel();
+ ProcessPOSIXLog::DecNestLevel();
return bytes_written;
}
@@ -276,14 +276,14 @@
buff, word_size, error) != word_size)
{
if (log)
- ProcessLinuxLog::DecNestLevel();
+ ProcessPOSIXLog::DecNestLevel();
return bytes_written;
}
- if (log && ProcessLinuxLog::AtTopNestLevel() &&
- (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) ||
- (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) &&
- size <= LINUX_LOG_MEMORY_SHORT_BYTES)))
+ if (log && ProcessPOSIXLog::AtTopNestLevel() &&
+ (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
+ (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
+ size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
(void*)vm_addr, *(unsigned long*)src, *(unsigned long*)buff);
}
@@ -292,7 +292,7 @@
src += word_size;
}
if (log)
- ProcessLinuxLog::DecNestLevel();
+ ProcessPOSIXLog::DecNestLevel();
return bytes_written;
}
@@ -420,7 +420,7 @@
ReadRegOperation::Execute(ProcessMonitor *monitor)
{
lldb::pid_t pid = monitor->GetPID();
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS));
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
// Set errno to zero so that we can detect a failed peek.
errno = 0;
@@ -434,7 +434,7 @@
}
if (log)
log->Printf ("ProcessMonitor::%s() reg %s: 0x%x", __FUNCTION__,
- LinuxThread::GetRegisterNameFromOffset(m_offset), data);
+ POSIXThread::GetRegisterNameFromOffset(m_offset), data);
}
//------------------------------------------------------------------------------
@@ -460,7 +460,7 @@
{
void* buf;
lldb::pid_t pid = monitor->GetPID();
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS));
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
if (sizeof(void*) == sizeof(uint64_t))
buf = (void*) m_value.GetAsUInt64();
@@ -472,7 +472,7 @@
if (log)
log->Printf ("ProcessMonitor::%s() reg %s: %p", __FUNCTION__,
- LinuxThread::GetRegisterNameFromOffset(m_offset), buf);
+ POSIXThread::GetRegisterNameFromOffset(m_offset), buf);
if (PTRACE(PTRACE_POKEUSER, pid, (void*)m_offset, buf))
m_result = false;
else
@@ -794,7 +794,7 @@
/// launching or attaching to the inferior process, and then 2) servicing
/// operations such as register reads/writes, stepping, etc. See the comments
/// on the Operation class for more info as to why this is needed.
-ProcessMonitor::ProcessMonitor(ProcessLinux *process,
+ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
Module *module,
const char *argv[],
const char *envp[],
@@ -802,7 +802,7 @@
const char *stdout_path,
const char *stderr_path,
lldb_private::Error &error)
- : m_process(process),
+ : m_process(static_cast<ProcessLinux *>(process)),
m_operation_thread(LLDB_INVALID_HOST_THREAD),
m_pid(LLDB_INVALID_PROCESS_ID),
m_terminal_fd(-1),
@@ -858,10 +858,10 @@
}
}
-ProcessMonitor::ProcessMonitor(ProcessLinux *process,
+ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
lldb::pid_t pid,
lldb_private::Error &error)
- : m_process(process),
+ : m_process(static_cast<ProcessLinux *>(process)),
m_operation_thread(LLDB_INVALID_HOST_THREAD),
m_pid(LLDB_INVALID_PROCESS_ID),
m_terminal_fd(-1),
@@ -978,7 +978,7 @@
lldb::pid_t pid;
lldb::ThreadSP inferior;
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS));
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
// Propagate the environment if one is not supplied.
if (envp == NULL || envp[0] == NULL)
@@ -1101,11 +1101,10 @@
if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error))
goto FINISH;
- // Update the process thread list with this new thread and mark it as
- // current.
+ // Update the process thread list with this new thread.
// FIXME: should we be letting UpdateThreadList handle this?
// FIXME: by using pids instead of tids, we can only support one thread.
- inferior.reset(new LinuxThread(process, pid));
+ inferior.reset(new POSIXThread(process, pid));
if (log)
log->Printf ("ProcessMonitor::%s() adding pid = %i", __FUNCTION__, pid);
process.GetThreadList().AddThread(inferior);
@@ -1167,9 +1166,8 @@
ProcessMonitor *monitor = args->m_monitor;
ProcessLinux &process = monitor->GetProcess();
-
lldb::ThreadSP inferior;
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS));
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
if (pid <= 1)
{
@@ -1192,13 +1190,11 @@
goto FINISH;
}
- // Update the process thread list with the attached thread and
- // mark it as current.
- inferior.reset(new LinuxThread(process, pid));
+ // Update the process thread list with the attached thread.
+ inferior.reset(new POSIXThread(process, pid));
if (log)
log->Printf ("ProcessMonitor::%s() adding tid = %i", __FUNCTION__, pid);
process.GetThreadList().AddThread(inferior);
- process.GetThreadList().SetSelectedThreadByID(pid);
// Let our process instance know the thread has stopped.
process.SendMessage(ProcessMessage::Trace(pid));
@@ -1568,7 +1564,7 @@
}
bool
-ProcessMonitor::ReadRegisterValue(unsigned offset, RegisterValue &value)
+ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value)
{
bool result;
ReadRegOperation op(offset, value, result);
Index: source/Plugins/Process/Linux/LinuxStopInfo.h
===================================================================
--- source/Plugins/Process/Linux/LinuxStopInfo.h (revision 147560)
+++ source/Plugins/Process/Linux/LinuxStopInfo.h (working copy)
@@ -1,92 +0,0 @@
-//===-- LinuxStopInfo.h -----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_LinuxStopInfo_H_
-#define liblldb_LinuxStopInfo_H_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Target/StopInfo.h"
-
-#include "LinuxThread.h"
-#include "ProcessMessage.h"
-
-//===----------------------------------------------------------------------===//
-/// @class LinuxStopInfo
-/// @brief Simple base class for all Linux-specific StopInfo objects.
-///
-class LinuxStopInfo
- : public lldb_private::StopInfo
-{
-public:
- LinuxStopInfo(lldb_private::Thread &thread, uint32_t status)
- : StopInfo(thread, status)
- { }
-};
-
-//===----------------------------------------------------------------------===//
-/// @class LinuxLimboStopInfo
-/// @brief Represents the stop state of a process ready to exit.
-///
-class LinuxLimboStopInfo
- : public LinuxStopInfo
-{
-public:
- LinuxLimboStopInfo(LinuxThread &thread)
- : LinuxStopInfo(thread, 0)
- { }
-
- ~LinuxLimboStopInfo();
-
- lldb::StopReason
- GetStopReason() const;
-
- const char *
- GetDescription();
-
- bool
- ShouldStop(lldb_private::Event *event_ptr);
-
- bool
- ShouldNotify(lldb_private::Event *event_ptr);
-};
-
-
-//===----------------------------------------------------------------------===//
-/// @class LinuxCrashStopInfo
-/// @brief Represents the stop state of process that is ready to crash.
-///
-class LinuxCrashStopInfo
- : public LinuxStopInfo
-{
-public:
- LinuxCrashStopInfo(LinuxThread &thread, uint32_t status,
- ProcessMessage::CrashReason reason)
- : LinuxStopInfo(thread, status),
- m_crash_reason(reason)
- { }
-
- ~LinuxCrashStopInfo();
-
- lldb::StopReason
- GetStopReason() const;
-
- const char *
- GetDescription();
-
- ProcessMessage::CrashReason
- GetCrashReason() const;
-
-private:
- ProcessMessage::CrashReason m_crash_reason;
-};
-
-#endif
Index: source/Plugins/Process/Linux/LinuxThread.cpp
===================================================================
--- source/Plugins/Process/Linux/LinuxThread.cpp (revision 147560)
+++ source/Plugins/Process/Linux/LinuxThread.cpp (working copy)
@@ -1,350 +0,0 @@
-//===-- LinuxThread.cpp -----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <errno.h>
-
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/Debugger.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/StopInfo.h"
-#include "lldb/Target/Target.h"
-#include "LinuxStopInfo.h"
-#include "LinuxThread.h"
-#include "ProcessLinux.h"
-#include "ProcessLinuxLog.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextLinux_i386.h"
-#include "RegisterContextLinux_x86_64.h"
-#include "UnwindLLDB.h"
-
-using namespace lldb_private;
-
-
-LinuxThread::LinuxThread(Process &process, lldb::tid_t tid)
- : Thread(process, tid),
- m_frame_ap(0)
-{
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
- if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
- log->Printf ("LinuxThread::%s (tid = %i)", __FUNCTION__, tid);
-}
-
-LinuxThread::~LinuxThread()
-{
- DestroyThread();
-}
-
-ProcessMonitor &
-LinuxThread::GetMonitor()
-{
- ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
- return process.GetMonitor();
-}
-
-void
-LinuxThread::RefreshStateAfterStop()
-{
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
- if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
- log->Printf ("LinuxThread::%s ()", __FUNCTION__);
-
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
- ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
- process.GetThreadList().RefreshStateAfterStop();
-}
-
-const char *
-LinuxThread::GetInfo()
-{
- return NULL;
-}
-
-lldb::RegisterContextSP
-LinuxThread::GetRegisterContext()
-{
- if (!m_reg_context_sp)
- {
- ArchSpec arch = Host::GetArchitecture();
-
- switch (arch.GetCore())
- {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- m_reg_context_sp.reset(new RegisterContextLinux_i386(*this, 0));
- break;
-
- case ArchSpec::eCore_x86_64_x86_64:
- m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
- break;
- }
- }
- return m_reg_context_sp;
-}
-
-lldb::RegisterContextSP
-LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
-{
- lldb::RegisterContextSP reg_ctx_sp;
- uint32_t concrete_frame_idx = 0;
-
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
- if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
- log->Printf ("LinuxThread::%s ()", __FUNCTION__);
-
- if (frame)
- concrete_frame_idx = frame->GetConcreteFrameIndex();
-
- if (concrete_frame_idx == 0)
- reg_ctx_sp = GetRegisterContext();
- else
- {
- assert(GetUnwinder());
- reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
- }
-
- return reg_ctx_sp;
-}
-
-lldb::StopInfoSP
-LinuxThread::GetPrivateStopReason()
-{
- return m_stop_info;
-}
-
-Unwind *
-LinuxThread::GetUnwinder()
-{
- if (m_unwinder_ap.get() == NULL)
- m_unwinder_ap.reset(new UnwindLLDB(*this));
-
- return m_unwinder_ap.get();
-}
-
-bool
-LinuxThread::WillResume(lldb::StateType resume_state)
-{
- SetResumeState(resume_state);
-
- ClearStackFrames();
- if (m_unwinder_ap.get())
- m_unwinder_ap->Clear();
-
- return Thread::WillResume(resume_state);
-}
-
-bool
-LinuxThread::Resume()
-{
- lldb::StateType resume_state = GetResumeState();
- ProcessMonitor &monitor = GetMonitor();
- bool status;
-
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
- if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
- log->Printf ("LinuxThread::%s ()", __FUNCTION__);
-
- switch (resume_state)
- {
- default:
- assert(false && "Unexpected state for resume!");
- status = false;
- break;
-
- case lldb::eStateRunning:
- SetState(resume_state);
- status = monitor.Resume(GetID(), GetResumeSignal());
- break;
-
- case lldb::eStateStepping:
- SetState(resume_state);
- status = monitor.SingleStep(GetID(), GetResumeSignal());
- break;
- }
-
- return status;
-}
-
-void
-LinuxThread::Notify(const ProcessMessage &message)
-{
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
- if (log)
- log->Printf ("LinuxThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind());
-
- switch (message.GetKind())
- {
- default:
- assert(false && "Unexpected message kind!");
- break;
-
- case ProcessMessage::eLimboMessage:
- LimboNotify(message);
- break;
-
- case ProcessMessage::eSignalMessage:
- SignalNotify(message);
- break;
-
- case ProcessMessage::eSignalDeliveredMessage:
- SignalDeliveredNotify(message);
- break;
-
- case ProcessMessage::eTraceMessage:
- TraceNotify(message);
- break;
-
- case ProcessMessage::eBreakpointMessage:
- BreakNotify(message);
- break;
-
- case ProcessMessage::eCrashMessage:
- CrashNotify(message);
- break;
- }
-}
-
-void
-LinuxThread::BreakNotify(const ProcessMessage &message)
-{
- bool status;
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
-
- assert(GetRegisterContextLinux());
- status = GetRegisterContextLinux()->UpdateAfterBreakpoint();
- assert(status && "Breakpoint update failed!");
-
- // With our register state restored, resolve the breakpoint object
- // corresponding to our current PC.
- assert(GetRegisterContext());
- lldb::addr_t pc = GetRegisterContext()->GetPC();
- if (log)
- log->Printf ("LinuxThread::%s () PC=0x%8.8llx", __FUNCTION__, pc);
- lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc));
- assert(bp_site);
- lldb::break_id_t bp_id = bp_site->GetID();
- assert(bp_site && bp_site->ValidForThisThread(this));
-
-
- m_breakpoint = bp_site;
- m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);
-}
-
-void
-LinuxThread::TraceNotify(const ProcessMessage &message)
-{
- m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
-}
-
-void
-LinuxThread::LimboNotify(const ProcessMessage &message)
-{
- m_stop_info = lldb::StopInfoSP(new LinuxLimboStopInfo(*this));
-}
-
-void
-LinuxThread::SignalNotify(const ProcessMessage &message)
-{
- int signo = message.GetSignal();
-
- m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);
- SetResumeSignal(signo);
-}
-
-void
-LinuxThread::SignalDeliveredNotify(const ProcessMessage &message)
-{
- int signo = message.GetSignal();
-
- // Just treat debugger generated signal events like breakpoints for now.
- m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
- SetResumeSignal(signo);
-}
-
-void
-LinuxThread::CrashNotify(const ProcessMessage &message)
-{
- int signo = message.GetSignal();
-
- assert(message.GetKind() == ProcessMessage::eCrashMessage);
-
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
- if (log)
- log->Printf ("LinuxThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason());
-
- m_stop_info = lldb::StopInfoSP(new LinuxCrashStopInfo(
- *this, signo, message.GetCrashReason()));
- SetResumeSignal(signo);
-}
-
-unsigned
-LinuxThread::GetRegisterIndexFromOffset(unsigned offset)
-{
- unsigned reg;
- ArchSpec arch = Host::GetArchitecture();
-
- switch (arch.GetCore())
- {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- reg = RegisterContextLinux_i386::GetRegisterIndexFromOffset(offset);
- break;
-
- case ArchSpec::eCore_x86_64_x86_64:
- reg = RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(offset);
- break;
- }
- return reg;
-}
-
-const char *
-LinuxThread::GetRegisterName(unsigned reg)
-{
- const char * name;
- ArchSpec arch = Host::GetArchitecture();
-
- switch (arch.GetCore())
- {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- name = RegisterContextLinux_i386::GetRegisterName(reg);
- break;
-
- case ArchSpec::eCore_x86_64_x86_64:
- name = RegisterContextLinux_x86_64::GetRegisterName(reg);
- break;
- }
- return name;
-}
-
-const char *
-LinuxThread::GetRegisterNameFromOffset(unsigned offset)
-{
- return GetRegisterName(GetRegisterIndexFromOffset(offset));
-}
-
Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.h
===================================================================
--- source/Plugins/Process/Linux/RegisterContextLinux_i386.h (revision 147560)
+++ source/Plugins/Process/Linux/RegisterContextLinux_i386.h (working copy)
@@ -1,169 +0,0 @@
-//===-- RegisterContextLinux_i386.h ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContextLinux_i386_h_
-#define liblldb_RegisterContextLinux_i386_h_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/Log.h"
-#include "RegisterContextLinux.h"
-
-class RegisterContextLinux_i386 : public RegisterContextLinux
-{
-public:
- RegisterContextLinux_i386(lldb_private::Thread &thread,
- uint32_t concreate_frame_idx);
-
- ~RegisterContextLinux_i386();
-
- void
- Invalidate();
-
- void
- InvalidateAllRegisters();
-
- size_t
- GetRegisterCount();
-
- const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(uint32_t reg);
-
- size_t
- GetRegisterSetCount();
-
- const lldb_private::RegisterSet *
- GetRegisterSet(uint32_t set);
-
- static unsigned
- GetRegisterIndexFromOffset(unsigned offset);
-
- static const char *
- GetRegisterName(unsigned reg);
-
-#if 0
- bool
- ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value);
-
- bool
- ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data);
-#endif
-
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value);
-
- bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
-
-#if 0
- bool
- WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value);
-
- bool
- WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data,
- uint32_t data_offset = 0);
-#endif
-
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value);
-
- bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
-
- uint32_t
- ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
-
- bool
- HardwareSingleStep(bool enable);
-
- bool
- UpdateAfterBreakpoint();
-
- struct GPR
- {
- uint32_t ebx;
- uint32_t ecx;
- uint32_t edx;
- uint32_t esi;
- uint32_t edi;
- uint32_t ebp;
- uint32_t eax;
- uint32_t ds;
- uint32_t es;
- uint32_t fs;
- uint32_t gs;
- uint32_t orig_ax;
- uint32_t eip;
- uint32_t cs;
- uint32_t eflags;
- uint32_t esp;
- uint32_t ss;
- };
-
- struct MMSReg
- {
- uint8_t bytes[8];
- };
-
- struct XMMReg
- {
- uint8_t bytes[16];
- };
-
- struct FPU
- {
- uint16_t fcw;
- uint16_t fsw;
- uint16_t ftw;
- uint16_t fop;
- uint32_t ip;
- uint32_t cs;
- uint32_t foo;
- uint32_t fos;
- uint32_t mxcsr;
- uint32_t reserved;
- MMSReg stmm[8];
- XMMReg xmm[8];
- uint32_t pad[56];
- };
-
- struct UserArea
- {
- GPR regs; // General purpose registers.
- int32_t fpvalid; // True if FPU is being used.
- FPU i387; // FPU registers.
- uint32_t tsize; // Text segment size.
- uint32_t dsize; // Data segment size.
- uint32_t ssize; // Stack segment size.
- uint32_t start_code; // VM address of text.
- uint32_t start_stack; // VM address of stack bottom (top in rsp).
- int32_t signal; // Signal causing core dump.
- int32_t reserved; // Unused.
- uint32_t ar0; // Location of GPR's.
- FPU* fpstate; // Location of FPR's.
- uint32_t magic; // Identifier for core dumps.
- char u_comm[32]; // Command causing core dump.
- uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7).
- };
-private:
- UserArea user;
-
- ProcessMonitor &GetMonitor();
-
- void LogGPR(const char *title);
-
- bool ReadGPR();
- bool ReadFPR();
-};
-
-#endif // #ifndef liblldb_RegisterContextLinux_i386_h_
Index: source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
===================================================================
--- source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp (revision 147560)
+++ source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp (working copy)
@@ -1,759 +0,0 @@
-//===-- RegisterContextLinux_x86_64.cpp -------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <cstring>
-#include <errno.h>
-#include <stdint.h>
-
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/Scalar.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Host/Endian.h"
-
-#include "ProcessLinux.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextLinux_x86_64.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-// Internal codes for all x86_64 registers.
-enum
-{
- k_first_gpr,
- gpr_rax = k_first_gpr,
- gpr_rbx,
- gpr_rcx,
- gpr_rdx,
- gpr_rdi,
- gpr_rsi,
- gpr_rbp,
- gpr_rsp,
- gpr_r8,
- gpr_r9,
- gpr_r10,
- gpr_r11,
- gpr_r12,
- gpr_r13,
- gpr_r14,
- gpr_r15,
- gpr_rip,
- gpr_rflags,
- gpr_cs,
- gpr_fs,
- gpr_gs,
- gpr_ss,
- gpr_ds,
- gpr_es,
- k_last_gpr = gpr_es,
-
- k_first_fpr,
- fpu_fcw = k_first_fpr,
- fpu_fsw,
- fpu_ftw,
- fpu_fop,
- fpu_ip,
- fpu_cs,
- fpu_dp,
- fpu_ds,
- fpu_mxcsr,
- fpu_mxcsrmask,
- fpu_stmm0,
- fpu_stmm1,
- fpu_stmm2,
- fpu_stmm3,
- fpu_stmm4,
- fpu_stmm5,
- fpu_stmm6,
- fpu_stmm7,
- fpu_xmm0,
- fpu_xmm1,
- fpu_xmm2,
- fpu_xmm3,
- fpu_xmm4,
- fpu_xmm5,
- fpu_xmm6,
- fpu_xmm7,
- fpu_xmm8,
- fpu_xmm9,
- fpu_xmm10,
- fpu_xmm11,
- fpu_xmm12,
- fpu_xmm13,
- fpu_xmm14,
- fpu_xmm15,
- k_last_fpr = fpu_xmm15,
-
- k_num_registers,
- k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
- k_num_fpu_registers = k_last_fpr - k_first_fpr + 1
-};
-
-// Number of register sets provided by this context.
-enum
-{
- k_num_register_sets = 2
-};
-
-enum gcc_dwarf_regnums
-{
- gcc_dwarf_gpr_rax = 0,
- gcc_dwarf_gpr_rdx,
- gcc_dwarf_gpr_rcx,
- gcc_dwarf_gpr_rbx,
- gcc_dwarf_gpr_rsi,
- gcc_dwarf_gpr_rdi,
- gcc_dwarf_gpr_rbp,
- gcc_dwarf_gpr_rsp,
- gcc_dwarf_gpr_r8,
- gcc_dwarf_gpr_r9,
- gcc_dwarf_gpr_r10,
- gcc_dwarf_gpr_r11,
- gcc_dwarf_gpr_r12,
- gcc_dwarf_gpr_r13,
- gcc_dwarf_gpr_r14,
- gcc_dwarf_gpr_r15,
- gcc_dwarf_gpr_rip,
- gcc_dwarf_fpu_xmm0,
- gcc_dwarf_fpu_xmm1,
- gcc_dwarf_fpu_xmm2,
- gcc_dwarf_fpu_xmm3,
- gcc_dwarf_fpu_xmm4,
- gcc_dwarf_fpu_xmm5,
- gcc_dwarf_fpu_xmm6,
- gcc_dwarf_fpu_xmm7,
- gcc_dwarf_fpu_xmm8,
- gcc_dwarf_fpu_xmm9,
- gcc_dwarf_fpu_xmm10,
- gcc_dwarf_fpu_xmm11,
- gcc_dwarf_fpu_xmm12,
- gcc_dwarf_fpu_xmm13,
- gcc_dwarf_fpu_xmm14,
- gcc_dwarf_fpu_xmm15,
- gcc_dwarf_fpu_stmm0,
- gcc_dwarf_fpu_stmm1,
- gcc_dwarf_fpu_stmm2,
- gcc_dwarf_fpu_stmm3,
- gcc_dwarf_fpu_stmm4,
- gcc_dwarf_fpu_stmm5,
- gcc_dwarf_fpu_stmm6,
- gcc_dwarf_fpu_stmm7
-};
-
-enum gdb_regnums
-{
- gdb_gpr_rax = 0,
- gdb_gpr_rbx = 1,
- gdb_gpr_rcx = 2,
- gdb_gpr_rdx = 3,
- gdb_gpr_rsi = 4,
- gdb_gpr_rdi = 5,
- gdb_gpr_rbp = 6,
- gdb_gpr_rsp = 7,
- gdb_gpr_r8 = 8,
- gdb_gpr_r9 = 9,
- gdb_gpr_r10 = 10,
- gdb_gpr_r11 = 11,
- gdb_gpr_r12 = 12,
- gdb_gpr_r13 = 13,
- gdb_gpr_r14 = 14,
- gdb_gpr_r15 = 15,
- gdb_gpr_rip = 16,
- gdb_gpr_rflags = 17,
- gdb_gpr_cs = 18,
- gdb_gpr_ss = 19,
- gdb_gpr_ds = 20,
- gdb_gpr_es = 21,
- gdb_gpr_fs = 22,
- gdb_gpr_gs = 23,
- gdb_fpu_stmm0 = 24,
- gdb_fpu_stmm1 = 25,
- gdb_fpu_stmm2 = 26,
- gdb_fpu_stmm3 = 27,
- gdb_fpu_stmm4 = 28,
- gdb_fpu_stmm5 = 29,
- gdb_fpu_stmm6 = 30,
- gdb_fpu_stmm7 = 31,
- gdb_fpu_fcw = 32,
- gdb_fpu_fsw = 33,
- gdb_fpu_ftw = 34,
- gdb_fpu_cs = 35,
- gdb_fpu_ip = 36,
- gdb_fpu_ds = 37,
- gdb_fpu_dp = 38,
- gdb_fpu_fop = 39,
- gdb_fpu_xmm0 = 40,
- gdb_fpu_xmm1 = 41,
- gdb_fpu_xmm2 = 42,
- gdb_fpu_xmm3 = 43,
- gdb_fpu_xmm4 = 44,
- gdb_fpu_xmm5 = 45,
- gdb_fpu_xmm6 = 46,
- gdb_fpu_xmm7 = 47,
- gdb_fpu_xmm8 = 48,
- gdb_fpu_xmm9 = 49,
- gdb_fpu_xmm10 = 50,
- gdb_fpu_xmm11 = 51,
- gdb_fpu_xmm12 = 52,
- gdb_fpu_xmm13 = 53,
- gdb_fpu_xmm14 = 54,
- gdb_fpu_xmm15 = 55,
- gdb_fpu_mxcsr = 56
-};
-
-static const
-uint32_t g_gpr_regnums[k_num_gpr_registers] =
-{
- gpr_rax,
- gpr_rbx,
- gpr_rcx,
- gpr_rdx,
- gpr_rdi,
- gpr_rsi,
- gpr_rbp,
- gpr_rsp,
- gpr_r8,
- gpr_r9,
- gpr_r10,
- gpr_r11,
- gpr_r12,
- gpr_r13,
- gpr_r14,
- gpr_r15,
- gpr_rip,
- gpr_rflags,
- gpr_cs,
- gpr_fs,
- gpr_gs,
- gpr_ss,
- gpr_ds,
- gpr_es
-};
-
-static const uint32_t
-g_fpu_regnums[k_num_fpu_registers] =
-{
- fpu_fcw,
- fpu_fsw,
- fpu_ftw,
- fpu_fop,
- fpu_ip,
- fpu_cs,
- fpu_dp,
- fpu_ds,
- fpu_mxcsr,
- fpu_mxcsrmask,
- fpu_stmm0,
- fpu_stmm1,
- fpu_stmm2,
- fpu_stmm3,
- fpu_stmm4,
- fpu_stmm5,
- fpu_stmm6,
- fpu_stmm7,
- fpu_xmm0,
- fpu_xmm1,
- fpu_xmm2,
- fpu_xmm3,
- fpu_xmm4,
- fpu_xmm5,
- fpu_xmm6,
- fpu_xmm7,
- fpu_xmm8,
- fpu_xmm9,
- fpu_xmm10,
- fpu_xmm11,
- fpu_xmm12,
- fpu_xmm13,
- fpu_xmm14,
- fpu_xmm15
-};
-
-static const RegisterSet
-g_reg_sets[k_num_register_sets] =
-{
- { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
- { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums }
-};
-
-// Computes the offset of the given GPR in the user data area.
-#define GPR_OFFSET(regname) \
- (offsetof(RegisterContextLinux_x86_64::UserArea, regs) + \
- offsetof(RegisterContextLinux_x86_64::GPR, regname))
-
-// Computes the offset of the given FPR in the user data area.
-#define FPR_OFFSET(regname) \
- (offsetof(RegisterContextLinux_x86_64::UserArea, i387) + \
- offsetof(RegisterContextLinux_x86_64::FPU, regname))
-
-// Number of bytes needed to represent a GPR.
-#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_x86_64::GPR*)NULL)->reg)
-
-// Number of bytes needed to represent a FPR.
-#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_x86_64::FPU*)NULL)->reg)
-
-// Number of bytes needed to represent the i'th FP register.
-#define FP_SIZE sizeof(((RegisterContextLinux_x86_64::MMSReg*)NULL)->bytes)
-
-// Number of bytes needed to represent an XMM register.
-#define XMM_SIZE sizeof(RegisterContextLinux_x86_64::XMMReg)
-
-#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
- { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } }
-
-#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \
- { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } }
-
-#define DEFINE_FP(reg, i) \
- { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \
- eFormatVectorOfUInt8, \
- { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \
- LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } }
-
-#define DEFINE_XMM(reg, i) \
- { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \
- eFormatVectorOfUInt8, \
- { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \
- LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } }
-
-#define REG_CONTEXT_SIZE (sizeof(RegisterContextLinux_x86_64::GPR) + sizeof(RegisterContextLinux_x86_64::FPU))
-
-static RegisterInfo
-g_register_infos[k_num_registers] =
-{
- // General purpose registers.
- DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax),
- DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx),
- DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx),
- DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx),
- DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi),
- DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi),
- DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp),
- DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp),
- DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8),
- DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9),
- DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10),
- DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11),
- DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12),
- DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13),
- DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14),
- DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15),
- DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip),
- DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags),
- DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs),
- DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs),
- DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs),
- DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss),
- DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds),
- DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es),
-
- // i387 Floating point registers.
- DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw),
- DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw),
- DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw),
- DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop),
- DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip),
- // FIXME: Extract segment from ip.
- DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs),
- DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp),
- // FIXME: Extract segment from dp.
- DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds),
- DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr),
- DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
-
- // FP registers.
- DEFINE_FP(stmm, 0),
- DEFINE_FP(stmm, 1),
- DEFINE_FP(stmm, 2),
- DEFINE_FP(stmm, 3),
- DEFINE_FP(stmm, 4),
- DEFINE_FP(stmm, 5),
- DEFINE_FP(stmm, 6),
- DEFINE_FP(stmm, 7),
-
- // XMM registers
- DEFINE_XMM(xmm, 0),
- DEFINE_XMM(xmm, 1),
- DEFINE_XMM(xmm, 2),
- DEFINE_XMM(xmm, 3),
- DEFINE_XMM(xmm, 4),
- DEFINE_XMM(xmm, 5),
- DEFINE_XMM(xmm, 6),
- DEFINE_XMM(xmm, 7),
- DEFINE_XMM(xmm, 8),
- DEFINE_XMM(xmm, 9),
- DEFINE_XMM(xmm, 10),
- DEFINE_XMM(xmm, 11),
- DEFINE_XMM(xmm, 12),
- DEFINE_XMM(xmm, 13),
- DEFINE_XMM(xmm, 14),
- DEFINE_XMM(xmm, 15)
-};
-
-static unsigned GetRegOffset(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register number.");
- return g_register_infos[reg].byte_offset;
-}
-
-#if 0 // These functions are currently not being used.
-static unsigned GetRegSize(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register number.");
- return g_register_infos[reg].byte_size;
-}
-
-static bool IsGPR(unsigned reg)
-{
- return reg <= k_last_gpr; // GPR's come first.
-}
-
-static bool IsFPR(unsigned reg)
-{
- return (k_first_fpr <= reg && reg <= k_last_fpr);
-}
-#endif
-
-RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread,
- uint32_t concrete_frame_idx)
- : RegisterContextLinux(thread, concrete_frame_idx)
-{
-}
-
-RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64()
-{
-}
-
-ProcessMonitor &
-RegisterContextLinux_x86_64::GetMonitor()
-{
- ProcessLinux *process = static_cast<ProcessLinux*>(CalculateProcess());
- return process->GetMonitor();
-}
-
-void
-RegisterContextLinux_x86_64::Invalidate()
-{
-}
-
-void
-RegisterContextLinux_x86_64::InvalidateAllRegisters()
-{
-}
-
-size_t
-RegisterContextLinux_x86_64::GetRegisterCount()
-{
- return k_num_registers;
-}
-
-const RegisterInfo *
-RegisterContextLinux_x86_64::GetRegisterInfoAtIndex(uint32_t reg)
-{
- if (reg < k_num_registers)
- return &g_register_infos[reg];
- else
- return NULL;
-}
-
-size_t
-RegisterContextLinux_x86_64::GetRegisterSetCount()
-{
- return k_num_register_sets;
-}
-
-const RegisterSet *
-RegisterContextLinux_x86_64::GetRegisterSet(uint32_t set)
-{
- if (set < k_num_register_sets)
- return &g_reg_sets[set];
- else
- return NULL;
-}
-
-unsigned
-RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(unsigned offset)
-{
- unsigned reg;
- for (reg = 0; reg < k_num_registers; reg++)
- {
- if (g_register_infos[reg].byte_offset == offset)
- break;
- }
- assert(reg < k_num_registers && "Invalid register offset.");
- return reg;
-}
-
-const char *
-RegisterContextLinux_x86_64::GetRegisterName(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register offset.");
- return g_register_infos[reg].name;
-}
-
-bool
-RegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
- RegisterValue &value)
-{
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(GetRegOffset(reg), value);
-}
-
-bool
-RegisterContextLinux_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp)
-{
- data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
- if (data_sp && ReadGPR () && ReadFPR ())
- {
- uint8_t *dst = data_sp->GetBytes();
- ::memcpy (dst, &user.regs, sizeof(user.regs));
- dst += sizeof(user.regs);
-
- ::memcpy (dst, &user.i387, sizeof(user.i387));
- return true;
- }
- return false;
-}
-
-bool
-RegisterContextLinux_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value)
-{
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(GetRegOffset(reg), value);
-}
-
-bool
-RegisterContextLinux_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp)
-{
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
- {
- const uint8_t *src = data_sp->GetBytes();
- ::memcpy (&user.regs, src, sizeof(user.regs));
- src += sizeof(user.regs);
-
- ::memcpy (&user.i387, src, sizeof(user.i387));
- return WriteGPR() & WriteFPR();
- }
- return false;
-}
-
-bool
-RegisterContextLinux_x86_64::UpdateAfterBreakpoint()
-{
- // PC points one byte past the int3 responsible for the breakpoint.
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- SetPC(pc - 1);
- return true;
-}
-
-uint32_t
-RegisterContextLinux_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind,
- uint32_t num)
-{
- if (kind == eRegisterKindGeneric)
- {
- switch (num)
- {
- case LLDB_REGNUM_GENERIC_PC: return gpr_rip;
- case LLDB_REGNUM_GENERIC_SP: return gpr_rsp;
- case LLDB_REGNUM_GENERIC_FP: return gpr_rbp;
- case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags;
- case LLDB_REGNUM_GENERIC_RA:
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
- {
- switch (num)
- {
- case gcc_dwarf_gpr_rax: return gpr_rax;
- case gcc_dwarf_gpr_rdx: return gpr_rdx;
- case gcc_dwarf_gpr_rcx: return gpr_rcx;
- case gcc_dwarf_gpr_rbx: return gpr_rbx;
- case gcc_dwarf_gpr_rsi: return gpr_rsi;
- case gcc_dwarf_gpr_rdi: return gpr_rdi;
- case gcc_dwarf_gpr_rbp: return gpr_rbp;
- case gcc_dwarf_gpr_rsp: return gpr_rsp;
- case gcc_dwarf_gpr_r8: return gpr_r8;
- case gcc_dwarf_gpr_r9: return gpr_r9;
- case gcc_dwarf_gpr_r10: return gpr_r10;
- case gcc_dwarf_gpr_r11: return gpr_r11;
- case gcc_dwarf_gpr_r12: return gpr_r12;
- case gcc_dwarf_gpr_r13: return gpr_r13;
- case gcc_dwarf_gpr_r14: return gpr_r14;
- case gcc_dwarf_gpr_r15: return gpr_r15;
- case gcc_dwarf_gpr_rip: return gpr_rip;
- case gcc_dwarf_fpu_xmm0: return fpu_xmm0;
- case gcc_dwarf_fpu_xmm1: return fpu_xmm1;
- case gcc_dwarf_fpu_xmm2: return fpu_xmm2;
- case gcc_dwarf_fpu_xmm3: return fpu_xmm3;
- case gcc_dwarf_fpu_xmm4: return fpu_xmm4;
- case gcc_dwarf_fpu_xmm5: return fpu_xmm5;
- case gcc_dwarf_fpu_xmm6: return fpu_xmm6;
- case gcc_dwarf_fpu_xmm7: return fpu_xmm7;
- case gcc_dwarf_fpu_xmm8: return fpu_xmm8;
- case gcc_dwarf_fpu_xmm9: return fpu_xmm9;
- case gcc_dwarf_fpu_xmm10: return fpu_xmm10;
- case gcc_dwarf_fpu_xmm11: return fpu_xmm11;
- case gcc_dwarf_fpu_xmm12: return fpu_xmm12;
- case gcc_dwarf_fpu_xmm13: return fpu_xmm13;
- case gcc_dwarf_fpu_xmm14: return fpu_xmm14;
- case gcc_dwarf_fpu_xmm15: return fpu_xmm15;
- case gcc_dwarf_fpu_stmm0: return fpu_stmm0;
- case gcc_dwarf_fpu_stmm1: return fpu_stmm1;
- case gcc_dwarf_fpu_stmm2: return fpu_stmm2;
- case gcc_dwarf_fpu_stmm3: return fpu_stmm3;
- case gcc_dwarf_fpu_stmm4: return fpu_stmm4;
- case gcc_dwarf_fpu_stmm5: return fpu_stmm5;
- case gcc_dwarf_fpu_stmm6: return fpu_stmm6;
- case gcc_dwarf_fpu_stmm7: return fpu_stmm7;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGDB)
- {
- switch (num)
- {
- case gdb_gpr_rax : return gpr_rax;
- case gdb_gpr_rbx : return gpr_rbx;
- case gdb_gpr_rcx : return gpr_rcx;
- case gdb_gpr_rdx : return gpr_rdx;
- case gdb_gpr_rsi : return gpr_rsi;
- case gdb_gpr_rdi : return gpr_rdi;
- case gdb_gpr_rbp : return gpr_rbp;
- case gdb_gpr_rsp : return gpr_rsp;
- case gdb_gpr_r8 : return gpr_r8;
- case gdb_gpr_r9 : return gpr_r9;
- case gdb_gpr_r10 : return gpr_r10;
- case gdb_gpr_r11 : return gpr_r11;
- case gdb_gpr_r12 : return gpr_r12;
- case gdb_gpr_r13 : return gpr_r13;
- case gdb_gpr_r14 : return gpr_r14;
- case gdb_gpr_r15 : return gpr_r15;
- case gdb_gpr_rip : return gpr_rip;
- case gdb_gpr_rflags : return gpr_rflags;
- case gdb_gpr_cs : return gpr_cs;
- case gdb_gpr_ss : return gpr_ss;
- case gdb_gpr_ds : return gpr_ds;
- case gdb_gpr_es : return gpr_es;
- case gdb_gpr_fs : return gpr_fs;
- case gdb_gpr_gs : return gpr_gs;
- case gdb_fpu_stmm0 : return fpu_stmm0;
- case gdb_fpu_stmm1 : return fpu_stmm1;
- case gdb_fpu_stmm2 : return fpu_stmm2;
- case gdb_fpu_stmm3 : return fpu_stmm3;
- case gdb_fpu_stmm4 : return fpu_stmm4;
- case gdb_fpu_stmm5 : return fpu_stmm5;
- case gdb_fpu_stmm6 : return fpu_stmm6;
- case gdb_fpu_stmm7 : return fpu_stmm7;
- case gdb_fpu_fcw : return fpu_fcw;
- case gdb_fpu_fsw : return fpu_fsw;
- case gdb_fpu_ftw : return fpu_ftw;
- case gdb_fpu_cs : return fpu_cs;
- case gdb_fpu_ip : return fpu_ip;
- case gdb_fpu_ds : return fpu_ds;
- case gdb_fpu_dp : return fpu_dp;
- case gdb_fpu_fop : return fpu_fop;
- case gdb_fpu_xmm0 : return fpu_xmm0;
- case gdb_fpu_xmm1 : return fpu_xmm1;
- case gdb_fpu_xmm2 : return fpu_xmm2;
- case gdb_fpu_xmm3 : return fpu_xmm3;
- case gdb_fpu_xmm4 : return fpu_xmm4;
- case gdb_fpu_xmm5 : return fpu_xmm5;
- case gdb_fpu_xmm6 : return fpu_xmm6;
- case gdb_fpu_xmm7 : return fpu_xmm7;
- case gdb_fpu_xmm8 : return fpu_xmm8;
- case gdb_fpu_xmm9 : return fpu_xmm9;
- case gdb_fpu_xmm10 : return fpu_xmm10;
- case gdb_fpu_xmm11 : return fpu_xmm11;
- case gdb_fpu_xmm12 : return fpu_xmm12;
- case gdb_fpu_xmm13 : return fpu_xmm13;
- case gdb_fpu_xmm14 : return fpu_xmm14;
- case gdb_fpu_xmm15 : return fpu_xmm15;
- case gdb_fpu_mxcsr : return fpu_mxcsr;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
- else if (kind == eRegisterKindLLDB)
- {
- return num;
- }
-
- return LLDB_INVALID_REGNUM;
-}
-
-bool
-RegisterContextLinux_x86_64::HardwareSingleStep(bool enable)
-{
- enum { TRACE_BIT = 0x100 };
- uint64_t rflags;
-
- if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL)
- return false;
-
- if (enable)
- {
- if (rflags & TRACE_BIT)
- return true;
-
- rflags |= TRACE_BIT;
- }
- else
- {
- if (!(rflags & TRACE_BIT))
- return false;
-
- rflags &= ~TRACE_BIT;
- }
-
- return WriteRegisterFromUnsigned(gpr_rflags, rflags);
-}
-
-bool
-RegisterContextLinux_x86_64::ReadGPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(&user.regs);
-}
-
-bool
-RegisterContextLinux_x86_64::ReadFPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadFPR(&user.i387);
-}
-
-bool
-RegisterContextLinux_x86_64::WriteGPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(&user.regs);
-}
-
-bool
-RegisterContextLinux_x86_64::WriteFPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteFPR(&user.i387);
-}
Index: source/Plugins/Process/Linux/ProcessMessage.h
===================================================================
--- source/Plugins/Process/Linux/ProcessMessage.h (revision 147560)
+++ source/Plugins/Process/Linux/ProcessMessage.h (working copy)
@@ -1,171 +0,0 @@
-//===-- ProcessMessage.h ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ProcessMessage_H_
-#define liblldb_ProcessMessage_H_
-
-#include <cassert>
-
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-types.h"
-
-class ProcessMessage
-{
-public:
-
- /// The type of signal this message can correspond to.
- enum Kind
- {
- eInvalidMessage,
- eExitMessage,
- eLimboMessage,
- eSignalMessage,
- eSignalDeliveredMessage,
- eTraceMessage,
- eBreakpointMessage,
- eCrashMessage
- };
-
- enum CrashReason
- {
- eInvalidCrashReason,
-
- // SIGSEGV crash reasons.
- eInvalidAddress,
- ePrivilegedAddress,
-
- // SIGILL crash reasons.
- eIllegalOpcode,
- eIllegalOperand,
- eIllegalAddressingMode,
- eIllegalTrap,
- ePrivilegedOpcode,
- ePrivilegedRegister,
- eCoprocessorError,
- eInternalStackError,
-
- // SIGBUS crash reasons,
- eIllegalAlignment,
- eIllegalAddress,
- eHardwareError,
-
- // SIGFPE crash reasons,
- eIntegerDivideByZero,
- eIntegerOverflow,
- eFloatDivideByZero,
- eFloatOverflow,
- eFloatUnderflow,
- eFloatInexactResult,
- eFloatInvalidOperation,
- eFloatSubscriptRange
- };
-
- ProcessMessage()
- : m_tid(LLDB_INVALID_PROCESS_ID),
- m_kind(eInvalidMessage),
- m_crash_reason(eInvalidCrashReason),
- m_status(0),
- m_addr(0) { }
-
- Kind GetKind() const { return m_kind; }
-
- lldb::tid_t GetTID() const { return m_tid; }
-
- /// Indicates that the thread @p tid is about to exit with status @p status.
- static ProcessMessage Limbo(lldb::tid_t tid, int status) {
- return ProcessMessage(tid, eLimboMessage, status);
- }
-
- /// Indicates that the thread @p tid had the signal @p signum delivered.
- static ProcessMessage Signal(lldb::tid_t tid, int signum) {
- return ProcessMessage(tid, eSignalMessage, signum);
- }
-
- /// Indicates that a signal @p signum generated by the debugging process was
- /// delivered to the thread @p tid.
- static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) {
- return ProcessMessage(tid, eSignalDeliveredMessage, signum);
- }
-
- /// Indicates that the thread @p tid encountered a trace point.
- static ProcessMessage Trace(lldb::tid_t tid) {
- return ProcessMessage(tid, eTraceMessage);
- }
-
- /// Indicates that the thread @p tid encountered a break point.
- static ProcessMessage Break(lldb::tid_t tid) {
- return ProcessMessage(tid, eBreakpointMessage);
- }
-
- /// Indicates that the thread @p tid crashed.
- static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason,
- int signo, lldb::addr_t fault_addr) {
- ProcessMessage message(pid, eCrashMessage, signo, fault_addr);
- message.m_crash_reason = reason;
- return message;
- }
-
- int GetExitStatus() const {
- assert(GetKind() == eExitMessage || GetKind() == eLimboMessage);
- return m_status;
- }
-
- int GetSignal() const {
- assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage ||
- GetKind() == eSignalDeliveredMessage);
- return m_status;
- }
-
- int GetStopStatus() const {
- assert(GetKind() == eSignalMessage);
- return m_status;
- }
-
- CrashReason GetCrashReason() const {
- assert(GetKind() == eCrashMessage);
- return m_crash_reason;
- }
-
- lldb::addr_t GetFaultAddress() const {
- assert(GetKind() == eCrashMessage);
- return m_addr;
- }
-
- static const char *
- GetCrashReasonString(CrashReason reason);
-
- const char *
- PrintCrashReason() const;
-
- static const char *
- PrintCrashReason(CrashReason reason);
-
- const char *
- PrintKind() const;
-
- static const char *
- PrintKind(Kind);
-
-private:
- ProcessMessage(lldb::tid_t tid, Kind kind,
- int status = 0, lldb::addr_t addr = 0)
- : m_tid(tid),
- m_kind(kind),
- m_crash_reason(eInvalidCrashReason),
- m_status(status),
- m_addr(addr) { }
-
- lldb::tid_t m_tid;
- Kind m_kind : 8;
- CrashReason m_crash_reason : 8;
- int m_status;
- lldb::addr_t m_addr;
-};
-
-#endif // #ifndef liblldb_ProcessMessage_H_
Index: source/Plugins/Process/Linux/ProcessMonitor.h
===================================================================
--- source/Plugins/Process/Linux/ProcessMonitor.h (revision 147560)
+++ source/Plugins/Process/Linux/ProcessMonitor.h (working copy)
@@ -24,10 +24,12 @@
class Error;
class Module;
class Scalar;
+
} // End lldb_private namespace.
class ProcessLinux;
class Operation;
+class ProcessPOSIX;
/// @class ProcessMonitor
/// @brief Manages communication with the inferior (debugee) process.
@@ -47,7 +49,7 @@
/// Launches an inferior process ready for debugging. Forms the
/// implementation of Process::DoLaunch.
- ProcessMonitor(ProcessLinux *process,
+ ProcessMonitor(ProcessPOSIX *process,
lldb_private::Module *module,
char const *argv[],
char const *envp[],
@@ -56,7 +58,7 @@
const char *stderr_path,
lldb_private::Error &error);
- ProcessMonitor(ProcessLinux *process,
+ ProcessMonitor(ProcessPOSIX *process,
lldb::pid_t pid,
lldb_private::Error &error);
@@ -104,7 +106,7 @@
///
/// This method is provided for use by RegisterContextLinux derivatives.
bool
- ReadRegisterValue(unsigned offset, lldb_private::RegisterValue &value);
+ ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value);
/// Writes the given value to the register identified by the given
/// (architecture dependent) offset.
Index: source/Plugins/Process/Linux/Makefile
===================================================================
--- source/Plugins/Process/Linux/Makefile (revision 147560)
+++ source/Plugins/Process/Linux/Makefile (working copy)
@@ -12,6 +12,6 @@
BUILD_ARCHIVE = 1
# Extend the include path so we may locate UnwindLLDB.h
-CPPFLAGS += -I $(LLDB_LEVEL)/source/Plugins/Utility
+CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility
include $(LLDB_LEVEL)/Makefile
Index: source/Plugins/Process/Linux/LinuxThread.h
===================================================================
--- source/Plugins/Process/Linux/LinuxThread.h (revision 147560)
+++ source/Plugins/Process/Linux/LinuxThread.h (working copy)
@@ -1,102 +0,0 @@
-//===-- LinuxThread.h -------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_LinuxThread_H_
-#define liblldb_LinuxThread_H_
-
-// C Includes
-// C++ Includes
-#include <memory>
-
-// Other libraries and framework includes
-#include "lldb/Target/Thread.h"
-
-class ProcessMessage;
-class ProcessMonitor;
-class RegisterContextLinux;
-
-//------------------------------------------------------------------------------
-// @class LinuxThread
-// @brief Abstraction of a linux process (thread).
-class LinuxThread
- : public lldb_private::Thread
-{
-public:
- LinuxThread(lldb_private::Process &process, lldb::tid_t tid);
-
- virtual ~LinuxThread();
-
- void
- RefreshStateAfterStop();
-
- bool
- WillResume(lldb::StateType resume_state);
-
- const char *
- GetInfo();
-
- virtual lldb::RegisterContextSP
- GetRegisterContext();
-
- virtual lldb::RegisterContextSP
- CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
-
- //--------------------------------------------------------------------------
- // These static functions provide a mapping from the register offset
- // back to the register index or name for use in debugging or log
- // output.
-
- static unsigned
- GetRegisterIndexFromOffset(unsigned offset);
-
- static const char *
- GetRegisterName(unsigned reg);
-
- static const char *
- GetRegisterNameFromOffset(unsigned offset);
-
- //--------------------------------------------------------------------------
- // These methods form a specialized interface to linux threads.
- //
- bool Resume();
-
- void Notify(const ProcessMessage &message);
-
-private:
- RegisterContextLinux *
- GetRegisterContextLinux ()
- {
- if (!m_reg_context_sp)
- GetRegisterContext();
- return (RegisterContextLinux *)m_reg_context_sp.get();
- }
-
- std::auto_ptr<lldb_private::StackFrame> m_frame_ap;
-
- lldb::BreakpointSiteSP m_breakpoint;
- lldb::StopInfoSP m_stop_info;
-
- ProcessMonitor &
- GetMonitor();
-
- lldb::StopInfoSP
- GetPrivateStopReason();
-
- void BreakNotify(const ProcessMessage &message);
- void TraceNotify(const ProcessMessage &message);
- void LimboNotify(const ProcessMessage &message);
- void SignalNotify(const ProcessMessage &message);
- void SignalDeliveredNotify(const ProcessMessage &message);
- void CrashNotify(const ProcessMessage &message);
-
- lldb_private::Unwind *
- GetUnwinder();
-};
-
-#endif // #ifndef liblldb_LinuxThread_H_
Index: source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
===================================================================
--- source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (revision 147560)
+++ source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (working copy)
@@ -10,67 +10,7 @@
#ifndef liblldb_RegisterContextLinux_x86_64_H_
#define liblldb_RegisterContextLinux_x86_64_H_
-#include "RegisterContextLinux.h"
-
-class ProcessMonitor;
-
-class RegisterContextLinux_x86_64
- : public RegisterContextLinux
-{
-public:
- RegisterContextLinux_x86_64 (lldb_private::Thread &thread,
- uint32_t concrete_frame_idx);
-
- ~RegisterContextLinux_x86_64();
-
- void
- Invalidate();
-
- void
- InvalidateAllRegisters();
-
- size_t
- GetRegisterCount();
-
- const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(uint32_t reg);
-
- size_t
- GetRegisterSetCount();
-
- const lldb_private::RegisterSet *
- GetRegisterSet(uint32_t set);
-
- static unsigned
- GetRegisterIndexFromOffset(unsigned offset);
-
- static const char *
- GetRegisterName(unsigned reg);
-
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value);
-
- bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
-
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value);
-
- bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
-
- uint32_t
- ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
-
- bool
- HardwareSingleStep(bool enable);
-
- bool
- UpdateAfterBreakpoint();
-
- struct GPR
+ typedef struct _GPR
{
uint64_t r15;
uint64_t r14;
@@ -99,67 +39,6 @@
uint64_t es;
uint64_t fs;
uint64_t gs;
- };
+ } GPR;
- struct MMSReg
- {
- uint8_t bytes[10];
- uint8_t pad[6];
- };
-
- struct XMMReg
- {
- uint8_t bytes[16];
- };
-
- struct FPU
- {
- uint16_t fcw;
- uint16_t fsw;
- uint16_t ftw;
- uint16_t fop;
- uint64_t ip;
- uint64_t dp;
- uint32_t mxcsr;
- uint32_t mxcsrmask;
- MMSReg stmm[8];
- XMMReg xmm[16];
- uint32_t padding[24];
- };
-
- struct UserArea
- {
- GPR regs; // General purpose registers.
- int32_t fpvalid; // True if FPU is being used.
- int32_t pad0;
- FPU i387; // FPU registers.
- uint64_t tsize; // Text segment size.
- uint64_t dsize; // Data segment size.
- uint64_t ssize; // Stack segment size.
- uint64_t start_code; // VM address of text.
- uint64_t start_stack; // VM address of stack bottom (top in rsp).
- int64_t signal; // Signal causing core dump.
- int32_t reserved; // Unused.
- int32_t pad1;
- uint64_t ar0; // Location of GPR's.
- FPU* fpstate; // Location of FPR's.
- uint64_t magic; // Identifier for core dumps.
- char u_comm[32]; // Command causing core dump.
- uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7).
- uint64_t error_code; // CPU error code.
- uint64_t fault_address; // Control register CR3.
- };
-
-private:
- UserArea user;
-
- ProcessMonitor &GetMonitor();
-
- bool ReadGPR();
- bool ReadFPR();
-
- bool WriteGPR();
- bool WriteFPR();
-};
-
-#endif // #ifndef liblldb_RegisterContextLinux_x86_64_H_
+#endif
Index: source/Plugins/Process/POSIX/POSIXThread.h
===================================================================
--- source/Plugins/Process/POSIX/POSIXThread.h (revision 0)
+++ source/Plugins/Process/POSIX/POSIXThread.h (revision 0)
@@ -0,0 +1,106 @@
+//===-- POSIXThread.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_POSIXThread_H_
+#define liblldb_POSIXThread_H_
+
+// C Includes
+// C++ Includes
+#include <memory>
+
+// Other libraries and framework includes
+#include "lldb/Target/Thread.h"
+#include "RegisterContextPOSIX.h"
+
+class ProcessMessage;
+class ProcessMonitor;
+class RegisterContextPOSIX;
+
+//------------------------------------------------------------------------------
+// @class POSIXThread
+// @brief Abstraction of a linux process (thread).
+class POSIXThread
+ : public lldb_private::Thread
+{
+public:
+ POSIXThread(lldb_private::Process &process, lldb::tid_t tid);
+
+ virtual ~POSIXThread();
+
+ void
+ RefreshStateAfterStop();
+
+ bool
+ WillResume(lldb::StateType resume_state);
+
+ const char *
+ GetInfo();
+
+ virtual lldb::RegisterContextSP
+ GetRegisterContext();
+
+ virtual lldb::RegisterContextSP
+ CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+ //--------------------------------------------------------------------------
+ // These static functions provide a mapping from the register offset
+ // back to the register index or name for use in debugging or log
+ // output.
+
+ static unsigned
+ GetRegisterIndexFromOffset(unsigned offset);
+
+ static const char *
+ GetRegisterName(unsigned reg);
+
+ static const char *
+ GetRegisterNameFromOffset(unsigned offset);
+
+ //--------------------------------------------------------------------------
+ // These methods form a specialized interface to linux threads.
+ //
+ bool Resume();
+
+ void Notify(const ProcessMessage &message);
+
+private:
+ RegisterContextPOSIX *
+ GetRegisterContextPOSIX ()
+ {
+ if (!m_reg_context_sp)
+ m_reg_context_sp = GetRegisterContext();
+#if 0
+ return dynamic_cast<RegisterContextPOSIX*>(m_reg_context_sp.get());
+#endif
+ return (RegisterContextPOSIX *)m_reg_context_sp.get();
+ }
+
+ std::auto_ptr<lldb_private::StackFrame> m_frame_ap;
+
+ lldb::BreakpointSiteSP m_breakpoint;
+ lldb::StopInfoSP m_stop_info;
+
+ ProcessMonitor &
+ GetMonitor();
+
+ lldb::StopInfoSP
+ GetPrivateStopReason();
+
+ void BreakNotify(const ProcessMessage &message);
+ void TraceNotify(const ProcessMessage &message);
+ void LimboNotify(const ProcessMessage &message);
+ void SignalNotify(const ProcessMessage &message);
+ void SignalDeliveredNotify(const ProcessMessage &message);
+ void CrashNotify(const ProcessMessage &message);
+
+ lldb_private::Unwind *
+ GetUnwinder();
+};
+
+#endif // #ifndef liblldb_POSIXThread_H_
Index: source/Plugins/Process/POSIX/ProcessPOSIX.cpp
===================================================================
--- source/Plugins/Process/POSIX/ProcessPOSIX.cpp (revision 0)
+++ source/Plugins/Process/POSIX/ProcessPOSIX.cpp (revision 0)
@@ -0,0 +1,594 @@
+//===-- ProcessPOSIX.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <errno.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Target.h"
+
+#include "ProcessPOSIX.h"
+#include "ProcessPOSIXLog.h"
+#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
+#include "ProcessMonitor.h"
+#include "POSIXThread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------------------
+// Static functions.
+#if 0
+Process*
+ProcessPOSIX::CreateInstance(Target& target, Listener &listener)
+{
+ return new ProcessPOSIX(target, listener);
+}
+
+
+void
+ProcessPOSIX::Initialize()
+{
+ static bool g_initialized = false;
+
+ if (!g_initialized)
+ {
+ g_initialized = true;
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ CreateInstance);
+
+ Log::Callbacks log_callbacks = {
+ ProcessPOSIXLog::DisableLog,
+ ProcessPOSIXLog::EnableLog,
+ ProcessPOSIXLog::ListLogCategories
+ };
+
+ Log::RegisterLogChannel (ProcessPOSIX::GetPluginNameStatic(), log_callbacks);
+ }
+}
+#endif
+
+//------------------------------------------------------------------------------
+// Constructors and destructors.
+
+ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener)
+ : Process(target, listener),
+ m_monitor(NULL),
+ m_module(NULL),
+ m_in_limbo(false),
+ m_exit_now(false)
+{
+ // FIXME: Putting this code in the ctor and saving the byte order in a
+ // member variable is a hack to avoid const qual issues in GetByteOrder.
+ ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();
+ m_byte_order = obj_file->GetByteOrder();
+}
+
+ProcessPOSIX::~ProcessPOSIX()
+{
+ delete m_monitor;
+}
+
+//------------------------------------------------------------------------------
+// Process protocol.
+
+bool
+ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name)
+{
+ // For now we are just making sure the file exists for a given module
+ ModuleSP exe_module_sp(target.GetExecutableModule());
+ if (exe_module_sp.get())
+ return exe_module_sp->GetFileSpec().Exists();
+ return false;
+}
+
+Error
+ProcessPOSIX::DoAttachToProcessWithID(lldb::pid_t pid)
+{
+ Error error;
+ assert(m_monitor == NULL);
+
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessPOSIX::%s(pid = %i)", __FUNCTION__, GetID());
+
+ m_monitor = new ProcessMonitor(this, pid, error);
+
+ if (!error.Success())
+ return error;
+
+ SetID(pid);
+ return error;
+}
+
+Error
+ProcessPOSIX::WillLaunch(Module* module)
+{
+ Error error;
+ return error;
+}
+
+const char *
+ProcessPOSIX::GetFilePath(
+ const lldb_private::ProcessLaunchInfo::FileAction *file_action,
+ const char *default_path)
+{
+ const char *pts_name = "/dev/pts/";
+ const char *path = NULL;
+
+ if (file_action)
+ {
+ if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
+ path = file_action->GetPath();
+ // By default the stdio paths passed in will be pseudo-terminal
+ // (/dev/pts). If so, convert to using a different default path
+ // instead to redirect I/O to the debugger console. This should
+ // also handle user overrides to /dev/null or a different file.
+ if (::strncmp(path, pts_name, ::strlen(pts_name)) == 0)
+ path = default_path;
+ }
+
+ return path;
+}
+
+Error
+ProcessPOSIX::DoLaunch (Module *module,
+ const ProcessLaunchInfo &launch_info)
+{
+ Error error;
+ assert(m_monitor == NULL);
+
+ SetPrivateState(eStateLaunching);
+
+ const lldb_private::ProcessLaunchInfo::FileAction *file_action;
+
+ // Default of NULL will mean to use existing open file descriptors
+ const char *stdin_path = NULL;
+ const char *stdout_path = NULL;
+ const char *stderr_path = NULL;
+
+ file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
+ stdin_path = GetFilePath(file_action, stdin_path);
+
+ file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
+ stdout_path = GetFilePath(file_action, stdout_path);
+
+ file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
+ stderr_path = GetFilePath(file_action, stderr_path);
+
+ m_monitor = new ProcessMonitor (this,
+ module,
+ launch_info.GetArguments().GetConstArgumentVector(),
+ launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
+ stdin_path,
+ stdout_path,
+ stderr_path,
+ error);
+
+ m_module = module;
+
+ if (!error.Success())
+ return error;
+
+ SetID(m_monitor->GetPID());
+ return error;
+}
+
+void
+ProcessPOSIX::DidLaunch()
+{
+}
+
+Error
+ProcessPOSIX::DoResume()
+{
+ StateType state = GetPrivateState();
+
+ assert(state == eStateStopped || state == eStateCrashed);
+
+ // We are about to resume a thread that will cause the process to exit so
+ // set our exit status now. Do not change our state if the inferior
+ // crashed.
+ if (state == eStateStopped)
+ {
+ if (m_in_limbo)
+ SetExitStatus(m_exit_status, NULL);
+ else
+ SetPrivateState(eStateRunning);
+ }
+
+ bool did_resume = false;
+ uint32_t thread_count = m_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < thread_count; ++i)
+ {
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ m_thread_list.GetThreadAtIndex(i, false).get());
+ did_resume = thread->Resume() || did_resume;
+ }
+ assert(did_resume && "Process resume failed!");
+
+ return Error();
+}
+
+addr_t
+ProcessPOSIX::GetImageInfoAddress()
+{
+ Target *target = &GetTarget();
+ ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
+ Address addr = obj_file->GetImageInfoAddress();
+
+ if (addr.IsValid())
+ return addr.GetLoadAddress(target);
+ else
+ return LLDB_INVALID_ADDRESS;
+}
+
+Error
+ProcessPOSIX::DoHalt(bool &caused_stop)
+{
+ Error error;
+
+ if (IsStopped())
+ {
+ caused_stop = false;
+ }
+ else if (kill(GetID(), SIGSTOP))
+ {
+ caused_stop = false;
+ error.SetErrorToErrno();
+ }
+ else
+ {
+ caused_stop = true;
+ }
+
+ return error;
+}
+
+Error
+ProcessPOSIX::DoDetach()
+{
+ Error error;
+
+ error = m_monitor->Detach();
+ if (error.Success())
+ SetPrivateState(eStateDetached);
+
+ return error;
+}
+
+Error
+ProcessPOSIX::DoSignal(int signal)
+{
+ Error error;
+
+ if (kill(GetID(), signal))
+ error.SetErrorToErrno();
+
+ return error;
+}
+
+Error
+ProcessPOSIX::DoDestroy()
+{
+ Error error;
+
+ if (!HasExited())
+ {
+ // Drive the exit event to completion (do not keep the inferior in
+ // limbo).
+ m_exit_now = true;
+
+ if (kill(m_monitor->GetPID(), SIGKILL) && error.Success())
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ SetPrivateState(eStateExited);
+ }
+
+ return error;
+}
+
+void
+ProcessPOSIX::SendMessage(const ProcessMessage &message)
+{
+ Mutex::Locker lock(m_message_mutex);
+
+ switch (message.GetKind())
+ {
+ default:
+ assert(false && "Unexpected process message!");
+ break;
+
+ case ProcessMessage::eInvalidMessage:
+ return;
+
+ case ProcessMessage::eLimboMessage:
+ m_in_limbo = true;
+ m_exit_status = message.GetExitStatus();
+ if (m_exit_now)
+ {
+ SetPrivateState(eStateExited);
+ m_monitor->Detach();
+ }
+ else
+ SetPrivateState(eStateStopped);
+ break;
+
+ case ProcessMessage::eExitMessage:
+ m_exit_status = message.GetExitStatus();
+ SetExitStatus(m_exit_status, NULL);
+ break;
+
+ case ProcessMessage::eTraceMessage:
+ case ProcessMessage::eBreakpointMessage:
+ SetPrivateState(eStateStopped);
+ break;
+
+ case ProcessMessage::eSignalMessage:
+ case ProcessMessage::eSignalDeliveredMessage:
+ SetPrivateState(eStateStopped);
+ break;
+
+ case ProcessMessage::eCrashMessage:
+ SetPrivateState(eStateCrashed);
+ break;
+ }
+
+ m_message_queue.push(message);
+}
+
+void
+ProcessPOSIX::RefreshStateAfterStop()
+{
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessPOSIX::%s()", __FUNCTION__);
+
+ Mutex::Locker lock(m_message_mutex);
+ if (m_message_queue.empty())
+ return;
+
+ ProcessMessage &message = m_message_queue.front();
+
+ // Resolve the thread this message corresponds to and pass it along.
+ // FIXME: we're really dealing with the pid here. This should get
+ // fixed when this code is fixed to handle multiple threads.
+ lldb::tid_t tid = message.GetTID();
+ if (log)
+ log->Printf ("ProcessPOSIX::%s() pid = %i", __FUNCTION__, tid);
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ GetThreadList().FindThreadByID(tid, false).get());
+
+ assert(thread);
+ thread->Notify(message);
+
+ m_message_queue.pop();
+}
+
+bool
+ProcessPOSIX::IsAlive()
+{
+ StateType state = GetPrivateState();
+ return state != eStateDetached && state != eStateExited && state != eStateInvalid;
+}
+
+size_t
+ProcessPOSIX::DoReadMemory(addr_t vm_addr,
+ void *buf, size_t size, Error &error)
+{
+ assert(m_monitor);
+ return m_monitor->ReadMemory(vm_addr, buf, size, error);
+}
+
+size_t
+ProcessPOSIX::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
+ Error &error)
+{
+ assert(m_monitor);
+ return m_monitor->WriteMemory(vm_addr, buf, size, error);
+}
+
+addr_t
+ProcessPOSIX::DoAllocateMemory(size_t size, uint32_t permissions,
+ Error &error)
+{
+ addr_t allocated_addr = LLDB_INVALID_ADDRESS;
+
+ unsigned prot = 0;
+ if (permissions & lldb::ePermissionsReadable)
+ prot |= eMmapProtRead;
+ if (permissions & lldb::ePermissionsWritable)
+ prot |= eMmapProtWrite;
+ if (permissions & lldb::ePermissionsExecutable)
+ prot |= eMmapProtExec;
+
+ if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
+ eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
+ m_addr_to_mmap_size[allocated_addr] = size;
+ error.Clear();
+ } else {
+ allocated_addr = LLDB_INVALID_ADDRESS;
+ error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
+ }
+
+ return allocated_addr;
+}
+
+Error
+ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr)
+{
+ Error error;
+ MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
+ if (pos != m_addr_to_mmap_size.end() &&
+ InferiorCallMunmap(this, addr, pos->second))
+ m_addr_to_mmap_size.erase (pos);
+ else
+ error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr);
+
+ return error;
+}
+
+size_t
+ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
+{
+ static const uint8_t g_i386_opcode[] = { 0xCC };
+
+ ArchSpec arch = GetTarget().GetArchitecture();
+ const uint8_t *opcode = NULL;
+ size_t opcode_size = 0;
+
+ switch (arch.GetCore())
+ {
+ default:
+ assert(false && "CPU type not supported!");
+ break;
+
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_64_x86_64:
+ opcode = g_i386_opcode;
+ opcode_size = sizeof(g_i386_opcode);
+ break;
+ }
+
+ bp_site->SetTrapOpcode(opcode, opcode_size);
+ return opcode_size;
+}
+
+Error
+ProcessPOSIX::EnableBreakpoint(BreakpointSite *bp_site)
+{
+ return EnableSoftwareBreakpoint(bp_site);
+}
+
+Error
+ProcessPOSIX::DisableBreakpoint(BreakpointSite *bp_site)
+{
+ return DisableSoftwareBreakpoint(bp_site);
+}
+
+uint32_t
+ProcessPOSIX::UpdateThreadListIfNeeded()
+{
+ // Do not allow recursive updates.
+ return m_thread_list.GetSize(false);
+}
+
+uint32_t
+ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
+{
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessPOSIX::%s() (pid = %i)", __FUNCTION__, GetID());
+
+ // Update the process thread list with this new thread.
+ // FIXME: We should be using tid, not pid.
+ assert(m_monitor);
+ ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
+ if (!thread_sp)
+ thread_sp.reset(new POSIXThread(*this, GetID()));
+
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessPOSIX::%s() updated pid = %i", __FUNCTION__, GetID());
+ new_thread_list.AddThread(thread_sp);
+
+ return new_thread_list.GetSize(false);
+}
+
+ByteOrder
+ProcessPOSIX::GetByteOrder() const
+{
+ // FIXME: We should be able to extract this value directly. See comment in
+ // ProcessPOSIX().
+ return m_byte_order;
+}
+
+size_t
+ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error)
+{
+ ssize_t status;
+ if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)
+ {
+ error.SetErrorToErrno();
+ return 0;
+ }
+ return status;
+}
+
+size_t
+ProcessPOSIX::GetSTDOUT(char *buf, size_t len, Error &error)
+{
+ ssize_t bytes_read;
+
+ // The terminal file descriptor is always in non-block mode.
+ if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0)
+ {
+ if (errno != EAGAIN)
+ error.SetErrorToErrno();
+ return 0;
+ }
+ return bytes_read;
+}
+
+size_t
+ProcessPOSIX::GetSTDERR(char *buf, size_t len, Error &error)
+{
+ return GetSTDOUT(buf, len, error);
+}
+
+UnixSignals &
+ProcessPOSIX::GetUnixSignals()
+{
+ return m_signals;
+}
+
+//------------------------------------------------------------------------------
+// Utility functions.
+
+bool
+ProcessPOSIX::HasExited()
+{
+ switch (GetPrivateState())
+ {
+ default:
+ break;
+
+ case eStateDetached:
+ case eStateExited:
+ return true;
+ }
+
+ return false;
+}
+
+bool
+ProcessPOSIX::IsStopped()
+{
+ switch (GetPrivateState())
+ {
+ default:
+ break;
+
+ case eStateStopped:
+ case eStateCrashed:
+ case eStateSuspended:
+ return true;
+ }
+
+ return false;
+}
Index: source/Plugins/Process/POSIX/RegisterContext_i386.cpp
===================================================================
--- source/Plugins/Process/POSIX/RegisterContext_i386.cpp (revision 0)
+++ source/Plugins/Process/POSIX/RegisterContext_i386.cpp (revision 0)
@@ -0,0 +1,643 @@
+//===-- RegisterContextPOSIX_i386.cpp ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Host/Endian.h"
+
+#include "ProcessPOSIX.h"
+#include "ProcessPOSIXLog.h"
+#include "ProcessMonitor.h"
+#include "RegisterContext_i386.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+enum
+{
+ k_first_gpr,
+ gpr_eax = k_first_gpr,
+ gpr_ebx,
+ gpr_ecx,
+ gpr_edx,
+ gpr_edi,
+ gpr_esi,
+ gpr_ebp,
+ gpr_esp,
+ gpr_ss,
+ gpr_eflags,
+#ifdef __FreeBSD__
+ gpr_orig_ax,
+#endif
+ gpr_eip,
+ gpr_cs,
+ gpr_ds,
+ gpr_es,
+ gpr_fs,
+ gpr_gs,
+ k_last_gpr = gpr_gs,
+
+ k_first_fpr,
+ fpu_fcw = k_first_fpr,
+ fpu_fsw,
+ fpu_ftw,
+ fpu_fop,
+ fpu_ip,
+ fpu_cs,
+ fpu_foo,
+ fpu_fos,
+ fpu_mxcsr,
+ fpu_stmm0,
+ fpu_stmm1,
+ fpu_stmm2,
+ fpu_stmm3,
+ fpu_stmm4,
+ fpu_stmm5,
+ fpu_stmm6,
+ fpu_stmm7,
+ fpu_xmm0,
+ fpu_xmm1,
+ fpu_xmm2,
+ fpu_xmm3,
+ fpu_xmm4,
+ fpu_xmm5,
+ fpu_xmm6,
+ fpu_xmm7,
+ k_last_fpr = fpu_xmm7,
+
+ k_num_registers,
+ k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
+ k_num_fpu_registers = k_last_fpr - k_first_fpr + 1
+};
+
+// Number of register sets provided by this context.
+enum
+{
+ k_num_register_sets = 2
+};
+
+enum
+{
+ gcc_eax = 0,
+ gcc_ecx,
+ gcc_edx,
+ gcc_ebx,
+ gcc_ebp,
+ gcc_esp,
+ gcc_esi,
+ gcc_edi,
+ gcc_eip,
+ gcc_eflags
+};
+
+enum
+{
+ dwarf_eax = 0,
+ dwarf_ecx,
+ dwarf_edx,
+ dwarf_ebx,
+ dwarf_esp,
+ dwarf_ebp,
+ dwarf_esi,
+ dwarf_edi,
+ dwarf_eip,
+ dwarf_eflags,
+ dwarf_stmm0 = 11,
+ dwarf_stmm1,
+ dwarf_stmm2,
+ dwarf_stmm3,
+ dwarf_stmm4,
+ dwarf_stmm5,
+ dwarf_stmm6,
+ dwarf_stmm7,
+ dwarf_xmm0 = 21,
+ dwarf_xmm1,
+ dwarf_xmm2,
+ dwarf_xmm3,
+ dwarf_xmm4,
+ dwarf_xmm5,
+ dwarf_xmm6,
+ dwarf_xmm7
+};
+
+enum
+{
+ gdb_eax = 0,
+ gdb_ecx = 1,
+ gdb_edx = 2,
+ gdb_ebx = 3,
+ gdb_esp = 4,
+ gdb_ebp = 5,
+ gdb_esi = 6,
+ gdb_edi = 7,
+ gdb_eip = 8,
+ gdb_eflags = 9,
+ gdb_cs = 10,
+ gdb_ss = 11,
+ gdb_ds = 12,
+ gdb_es = 13,
+ gdb_fs = 14,
+ gdb_gs = 15,
+ gdb_stmm0 = 16,
+ gdb_stmm1 = 17,
+ gdb_stmm2 = 18,
+ gdb_stmm3 = 19,
+ gdb_stmm4 = 20,
+ gdb_stmm5 = 21,
+ gdb_stmm6 = 22,
+ gdb_stmm7 = 23,
+ gdb_fcw = 24,
+ gdb_fsw = 25,
+ gdb_ftw = 26,
+ gdb_fpu_cs = 27,
+ gdb_ip = 28,
+ gdb_fpu_ds = 29,
+ gdb_dp = 30,
+ gdb_fop = 31,
+ gdb_xmm0 = 32,
+ gdb_xmm1 = 33,
+ gdb_xmm2 = 34,
+ gdb_xmm3 = 35,
+ gdb_xmm4 = 36,
+ gdb_xmm5 = 37,
+ gdb_xmm6 = 38,
+ gdb_xmm7 = 39,
+ gdb_mxcsr = 40,
+ gdb_mm0 = 41,
+ gdb_mm1 = 42,
+ gdb_mm2 = 43,
+ gdb_mm3 = 44,
+ gdb_mm4 = 45,
+ gdb_mm5 = 46,
+ gdb_mm6 = 47,
+ gdb_mm7 = 48
+};
+
+static const
+uint32_t g_gpr_regnums[k_num_gpr_registers] =
+{
+ gpr_eax,
+ gpr_ebx,
+ gpr_ecx,
+ gpr_edx,
+ gpr_edi,
+ gpr_esi,
+ gpr_ebp,
+ gpr_esp,
+ gpr_ss,
+ gpr_eflags,
+#ifdef __FreeBSD__
+ gpr_orig_ax,
+#endif
+ gpr_eip,
+ gpr_cs,
+ gpr_ds,
+ gpr_es,
+ gpr_fs,
+ gpr_gs,
+};
+
+static const uint32_t
+g_fpu_regnums[k_num_fpu_registers] =
+{
+ fpu_fcw,
+ fpu_fsw,
+ fpu_ftw,
+ fpu_fop,
+ fpu_ip,
+ fpu_cs,
+ fpu_foo,
+ fpu_fos,
+ fpu_mxcsr,
+ fpu_stmm0,
+ fpu_stmm1,
+ fpu_stmm2,
+ fpu_stmm3,
+ fpu_stmm4,
+ fpu_stmm5,
+ fpu_stmm6,
+ fpu_stmm7,
+ fpu_xmm0,
+ fpu_xmm1,
+ fpu_xmm2,
+ fpu_xmm3,
+ fpu_xmm4,
+ fpu_xmm5,
+ fpu_xmm6,
+ fpu_xmm7,
+};
+
+static const RegisterSet
+g_reg_sets[k_num_register_sets] =
+{
+ { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
+ { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums }
+};
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname) \
+ (offsetof(RegisterContext_i386::UserArea, regs) + \
+ offsetof(RegisterContext_i386::GPR, regname))
+
+// Computes the offset of the given FPR in the user data area.
+#define FPR_OFFSET(regname) \
+ (offsetof(RegisterContext_i386::UserArea, i387) + \
+ offsetof(RegisterContext_i386::FPU, regname))
+
+// Number of bytes needed to represent a GPR.
+#define GPR_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg)
+
+// Number of bytes needed to represent a FPR.
+#define FPR_SIZE(reg) sizeof(((RegisterContext_i386::FPU*)NULL)->reg)
+
+// Number of bytes needed to represent the i'th FP register.
+#define FP_SIZE sizeof(((RegisterContext_i386::MMSReg*)NULL)->bytes)
+
+// Number of bytes needed to represent an XMM register.
+#define XMM_SIZE sizeof(RegisterContext_i386::XMMReg)
+
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
+ { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } }
+
+#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \
+ { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } }
+
+#define DEFINE_FP(reg, i) \
+ { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \
+ eFormatVectorOfUInt8, \
+ { dwarf_##reg##i, dwarf_##reg##i, \
+ LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } }
+
+#define DEFINE_XMM(reg, i) \
+ { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \
+ eFormatVectorOfUInt8, \
+ { dwarf_##reg##i, dwarf_##reg##i, \
+ LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } }
+
+static RegisterInfo
+g_register_infos[k_num_registers] =
+{
+ // General purpose registers.
+ DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax),
+ DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx),
+ DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx),
+ DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx),
+ DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi),
+ DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi),
+ DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp),
+ DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp),
+ DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss),
+ DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags),
+ DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip),
+ DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs),
+ DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds),
+ DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es),
+ DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs),
+ DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs),
+
+ // Floating point registers.
+ DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw),
+ DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw),
+ DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw),
+ DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop),
+ DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip),
+ DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs),
+ DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp),
+ DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds),
+ DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr),
+
+ DEFINE_FP(stmm, 0),
+ DEFINE_FP(stmm, 1),
+ DEFINE_FP(stmm, 2),
+ DEFINE_FP(stmm, 3),
+ DEFINE_FP(stmm, 4),
+ DEFINE_FP(stmm, 5),
+ DEFINE_FP(stmm, 6),
+ DEFINE_FP(stmm, 7),
+
+ // XMM registers
+ DEFINE_XMM(xmm, 0),
+ DEFINE_XMM(xmm, 1),
+ DEFINE_XMM(xmm, 2),
+ DEFINE_XMM(xmm, 3),
+ DEFINE_XMM(xmm, 4),
+ DEFINE_XMM(xmm, 5),
+ DEFINE_XMM(xmm, 6),
+ DEFINE_XMM(xmm, 7),
+
+};
+
+#ifndef NDEBUG
+static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
+#endif
+
+static unsigned GetRegOffset(unsigned reg)
+{
+ assert(reg < k_num_registers && "Invalid register number.");
+ return g_register_infos[reg].byte_offset;
+}
+
+static unsigned GetRegSize(unsigned reg)
+{
+ assert(reg < k_num_registers && "Invalid register number.");
+ return g_register_infos[reg].byte_size;
+}
+
+RegisterContext_i386::RegisterContext_i386(Thread &thread,
+ uint32_t concrete_frame_idx)
+ : RegisterContextPOSIX(thread, concrete_frame_idx)
+{
+}
+
+RegisterContext_i386::~RegisterContext_i386()
+{
+}
+
+ProcessMonitor &
+RegisterContext_i386::GetMonitor()
+{
+ ProcessPOSIX *process = static_cast<ProcessPOSIX*>(CalculateProcess());
+ return process->GetMonitor();
+}
+
+void
+RegisterContext_i386::Invalidate()
+{
+}
+
+void
+RegisterContext_i386::InvalidateAllRegisters()
+{
+}
+
+size_t
+RegisterContext_i386::GetRegisterCount()
+{
+ assert(k_num_register_infos == k_num_registers);
+ return k_num_registers;
+}
+
+const RegisterInfo *
+RegisterContext_i386::GetRegisterInfoAtIndex(uint32_t reg)
+{
+ assert(k_num_register_infos == k_num_registers);
+ if (reg < k_num_registers)
+ return &g_register_infos[reg];
+ else
+ return NULL;
+}
+
+size_t
+RegisterContext_i386::GetRegisterSetCount()
+{
+ return k_num_register_sets;
+}
+
+const RegisterSet *
+RegisterContext_i386::GetRegisterSet(uint32_t set)
+{
+ if (set < k_num_register_sets)
+ return &g_reg_sets[set];
+ else
+ return NULL;
+}
+
+unsigned
+RegisterContext_i386::GetRegisterIndexFromOffset(unsigned offset)
+{
+ unsigned reg;
+ for (reg = 0; reg < k_num_registers; reg++)
+ {
+ if (g_register_infos[reg].byte_offset == offset)
+ break;
+ }
+ assert(reg < k_num_registers && "Invalid register offset.");
+ return reg;
+}
+
+const char *
+RegisterContext_i386::GetRegisterName(unsigned reg)
+{
+ assert(reg < k_num_registers && "Invalid register offset.");
+ return g_register_infos[reg].name;
+}
+
+bool
+RegisterContext_i386::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &value)
+{
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value);
+}
+
+bool
+RegisterContext_i386::ReadAllRegisterValues(DataBufferSP &data_sp)
+{
+ return false;
+}
+
+bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &value)
+{
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteRegisterValue(GetRegOffset(reg), value);
+}
+
+bool
+RegisterContext_i386::WriteAllRegisterValues(const DataBufferSP &data)
+{
+ return false;
+}
+
+bool
+RegisterContext_i386::UpdateAfterBreakpoint()
+{
+ // PC points one byte past the int3 responsible for the breakpoint.
+ lldb::addr_t pc;
+
+ if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+ return false;
+
+ SetPC(pc - 1);
+ return true;
+}
+
+uint32_t
+RegisterContext_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind,
+ uint32_t num)
+{
+ if (kind == eRegisterKindGeneric)
+ {
+ switch (num)
+ {
+ case LLDB_REGNUM_GENERIC_PC: return gpr_eip;
+ case LLDB_REGNUM_GENERIC_SP: return gpr_esp;
+ case LLDB_REGNUM_GENERIC_FP: return gpr_ebp;
+ case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags;
+ case LLDB_REGNUM_GENERIC_RA:
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ }
+
+ if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+ {
+ switch (num)
+ {
+ case dwarf_eax: return gpr_eax;
+ case dwarf_edx: return gpr_edx;
+ case dwarf_ecx: return gpr_ecx;
+ case dwarf_ebx: return gpr_ebx;
+ case dwarf_esi: return gpr_esi;
+ case dwarf_edi: return gpr_edi;
+ case dwarf_ebp: return gpr_ebp;
+ case dwarf_esp: return gpr_esp;
+ case dwarf_eip: return gpr_eip;
+ case dwarf_xmm0: return fpu_xmm0;
+ case dwarf_xmm1: return fpu_xmm1;
+ case dwarf_xmm2: return fpu_xmm2;
+ case dwarf_xmm3: return fpu_xmm3;
+ case dwarf_xmm4: return fpu_xmm4;
+ case dwarf_xmm5: return fpu_xmm5;
+ case dwarf_xmm6: return fpu_xmm6;
+ case dwarf_xmm7: return fpu_xmm7;
+ case dwarf_stmm0: return fpu_stmm0;
+ case dwarf_stmm1: return fpu_stmm1;
+ case dwarf_stmm2: return fpu_stmm2;
+ case dwarf_stmm3: return fpu_stmm3;
+ case dwarf_stmm4: return fpu_stmm4;
+ case dwarf_stmm5: return fpu_stmm5;
+ case dwarf_stmm6: return fpu_stmm6;
+ case dwarf_stmm7: return fpu_stmm7;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ }
+
+ if (kind == eRegisterKindGDB)
+ {
+ switch (num)
+ {
+ case gdb_eax : return gpr_eax;
+ case gdb_ebx : return gpr_ebx;
+ case gdb_ecx : return gpr_ecx;
+ case gdb_edx : return gpr_edx;
+ case gdb_esi : return gpr_esi;
+ case gdb_edi : return gpr_edi;
+ case gdb_ebp : return gpr_ebp;
+ case gdb_esp : return gpr_esp;
+ case gdb_eip : return gpr_eip;
+ case gdb_eflags : return gpr_eflags;
+ case gdb_cs : return gpr_cs;
+ case gdb_ss : return gpr_ss;
+ case gdb_ds : return gpr_ds;
+ case gdb_es : return gpr_es;
+ case gdb_fs : return gpr_fs;
+ case gdb_gs : return gpr_gs;
+ case gdb_stmm0 : return fpu_stmm0;
+ case gdb_stmm1 : return fpu_stmm1;
+ case gdb_stmm2 : return fpu_stmm2;
+ case gdb_stmm3 : return fpu_stmm3;
+ case gdb_stmm4 : return fpu_stmm4;
+ case gdb_stmm5 : return fpu_stmm5;
+ case gdb_stmm6 : return fpu_stmm6;
+ case gdb_stmm7 : return fpu_stmm7;
+ case gdb_fcw : return fpu_fcw;
+ case gdb_fsw : return fpu_fsw;
+ case gdb_ftw : return fpu_ftw;
+ case gdb_fpu_cs : return fpu_cs;
+ case gdb_ip : return fpu_ip;
+ case gdb_fpu_ds : return fpu_fos;
+ case gdb_dp : return fpu_foo;
+ case gdb_fop : return fpu_fop;
+ case gdb_xmm0 : return fpu_xmm0;
+ case gdb_xmm1 : return fpu_xmm1;
+ case gdb_xmm2 : return fpu_xmm2;
+ case gdb_xmm3 : return fpu_xmm3;
+ case gdb_xmm4 : return fpu_xmm4;
+ case gdb_xmm5 : return fpu_xmm5;
+ case gdb_xmm6 : return fpu_xmm6;
+ case gdb_xmm7 : return fpu_xmm7;
+ case gdb_mxcsr : return fpu_mxcsr;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ }
+ else if (kind == eRegisterKindLLDB)
+ {
+ return num;
+ }
+
+ return LLDB_INVALID_REGNUM;
+}
+
+bool
+RegisterContext_i386::HardwareSingleStep(bool enable)
+{
+ enum { TRACE_BIT = 0x100 };
+ uint64_t eflags;
+
+ if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL)
+ return false;
+
+ if (enable)
+ {
+ if (eflags & TRACE_BIT)
+ return true;
+
+ eflags |= TRACE_BIT;
+ }
+ else
+ {
+ if (!(eflags & TRACE_BIT))
+ return false;
+
+ eflags &= ~TRACE_BIT;
+ }
+
+ return WriteRegisterFromUnsigned(gpr_eflags, eflags);
+}
+
+void
+RegisterContext_i386::LogGPR(const char *title)
+{
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+ if (log)
+ {
+ if (title)
+ log->Printf ("%s", title);
+ for (uint32_t i=0; i<k_num_gpr_registers; i++)
+ {
+ uint32_t reg = gpr_eax + i;
+ log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]);
+ }
+ }
+}
+
+bool
+RegisterContext_i386::ReadGPR()
+{
+ bool result;
+
+ ProcessMonitor &monitor = GetMonitor();
+ result = monitor.ReadGPR(&user.regs);
+ LogGPR("RegisterContext_i386::ReadGPR()");
+ return result;
+}
+
+bool
+RegisterContext_i386::ReadFPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadFPR(&user.i387);
+}
Index: source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp
===================================================================
--- source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (revision 0)
+++ source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (revision 0)
@@ -0,0 +1,195 @@
+//===-- ProcessPOSIXLog.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProcessPOSIXLog.h"
+
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/StreamFile.h"
+
+#include "ProcessPOSIX.h"
+#include "ProcessPOSIXLog.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+// We want to avoid global constructors where code needs to be run so here we
+// control access to our static g_log_sp by hiding it in a singleton function
+// that will construct the static g_lob_sp the first time this function is
+// called.
+static LogSP &
+GetLog ()
+{
+ static LogSP g_log_sp;
+ return g_log_sp;
+}
+
+LogSP
+ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask)
+{
+ LogSP log(GetLog ());
+ if (log && mask)
+ {
+ uint32_t log_mask = log->GetMask().Get();
+ if ((log_mask & mask) != mask)
+ return LogSP();
+ }
+ return log;
+}
+
+void
+ProcessPOSIXLog::DisableLog (Args &args, Stream *feedback_strm)
+{
+ LogSP log (GetLog ());
+ if (log)
+ {
+ uint32_t flag_bits = 0;
+
+ const size_t argc = args.GetArgumentCount ();
+ if (argc > 0)
+ {
+ flag_bits = log->GetMask().Get();
+ for (size_t i = 0; i < argc; ++i)
+ {
+ const char *arg = args.GetArgumentAtIndex (i);
+
+
+ if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~POSIX_LOG_ALL;
+ else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~POSIX_LOG_ASYNC;
+ else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~POSIX_LOG_BREAKPOINTS;
+ else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~POSIX_LOG_COMM;
+ else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~POSIX_LOG_DEFAULT;
+ else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~POSIX_LOG_PACKETS;
+ else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY;
+ else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_SHORT;
+ else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_LONG;
+ else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~POSIX_LOG_PROCESS;
+ else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~POSIX_LOG_PTRACE;
+ else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~POSIX_LOG_REGISTERS;
+ else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~POSIX_LOG_STEP;
+ else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~POSIX_LOG_THREAD;
+ else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~POSIX_LOG_VERBOSE;
+ else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~POSIX_LOG_WATCHPOINTS;
+ else
+ {
+ feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+ ListLogCategories (feedback_strm);
+ }
+
+ }
+ }
+
+ if (flag_bits == 0)
+ GetLog ().reset();
+ else
+ log->GetMask().Reset (flag_bits);
+ }
+
+ return;
+}
+
+LogSP
+ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm)
+{
+ // Try see if there already is a log - that way we can reuse its settings.
+ // We could reuse the log in toto, but we don't know that the stream is the same.
+ uint32_t flag_bits = 0;
+ LogSP log(GetLog ());
+ if (log)
+ flag_bits = log->GetMask().Get();
+
+ // Now make a new log with this stream if one was provided
+ if (log_stream_sp)
+ {
+ log = make_shared<Log>(log_stream_sp);
+ GetLog () = log;
+ }
+
+ if (log)
+ {
+ bool got_unknown_category = false;
+ const size_t argc = args.GetArgumentCount();
+ for (size_t i=0; i<argc; ++i)
+ {
+ const char *arg = args.GetArgumentAtIndex(i);
+
+ if (::strcasecmp (arg, "all") == 0 ) flag_bits |= POSIX_LOG_ALL;
+ else if (::strcasecmp (arg, "async") == 0 ) flag_bits |= POSIX_LOG_ASYNC;
+ else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits |= POSIX_LOG_BREAKPOINTS;
+ else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits |= POSIX_LOG_COMM;
+ else if (::strcasecmp (arg, "default") == 0 ) flag_bits |= POSIX_LOG_DEFAULT;
+ else if (::strcasecmp (arg, "packets") == 0 ) flag_bits |= POSIX_LOG_PACKETS;
+ else if (::strcasecmp (arg, "memory") == 0 ) flag_bits |= POSIX_LOG_MEMORY;
+ else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= POSIX_LOG_MEMORY_DATA_SHORT;
+ else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits |= POSIX_LOG_MEMORY_DATA_LONG;
+ else if (::strcasecmp (arg, "process") == 0 ) flag_bits |= POSIX_LOG_PROCESS;
+ else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits |= POSIX_LOG_PTRACE;
+ else if (::strcasecmp (arg, "registers") == 0 ) flag_bits |= POSIX_LOG_REGISTERS;
+ else if (::strcasecmp (arg, "step") == 0 ) flag_bits |= POSIX_LOG_STEP;
+ else if (::strcasecmp (arg, "thread") == 0 ) flag_bits |= POSIX_LOG_THREAD;
+ else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits |= POSIX_LOG_VERBOSE;
+ else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits |= POSIX_LOG_WATCHPOINTS;
+ else
+ {
+ feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+ if (got_unknown_category == false)
+ {
+ got_unknown_category = true;
+ ListLogCategories (feedback_strm);
+ }
+ }
+ }
+ if (flag_bits == 0)
+ flag_bits = POSIX_LOG_DEFAULT;
+ log->GetMask().Reset(flag_bits);
+ log->GetOptions().Reset(log_options);
+ }
+ return log;
+}
+
+void
+ProcessPOSIXLog::ListLogCategories (Stream *strm)
+{
+ strm->Printf ("Logging categories for '%s':\n"
+ " all - turn on all available logging categories\n"
+ " async - log asynchronous activity\n"
+ " break - log breakpoints\n"
+ " communication - log communication activity\n"
+ " default - enable the default set of logging categories for liblldb\n"
+ " packets - log gdb remote packets\n"
+ " memory - log memory reads and writes\n"
+ " data-short - log memory bytes for memory reads and writes for short transactions only\n"
+ " data-long - log memory bytes for memory reads and writes for all transactions\n"
+ " process - log process events and activities\n"
+#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION
+ " ptrace - log all calls to ptrace\n"
+#endif
+ " registers - log register read/writes\n"
+ " thread - log thread events and activities\n"
+ " step - log step related activities\n"
+ " verbose - enable verbose logging\n"
+ " watch - log watchpoint related activities\n", ProcessPOSIXLog::m_pluginname);
+}
+
+
+void
+ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...)
+{
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask));
+ if (log)
+ {
+ va_list args;
+ va_start (args, format);
+ log->VAPrintf (format, args);
+ va_end (args);
+ }
+}
+
+int ProcessPOSIXLog::m_nestinglevel;
+const char *ProcessPOSIXLog::m_pluginname = "";
Index: source/Plugins/Process/POSIX/ProcessPOSIX.h
===================================================================
--- source/Plugins/Process/POSIX/ProcessPOSIX.h (revision 0)
+++ source/Plugins/Process/POSIX/ProcessPOSIX.h (revision 0)
@@ -0,0 +1,180 @@
+//===-- ProcessPOSIX.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessPOSIX_H_
+#define liblldb_ProcessPOSIX_H_
+
+// C Includes
+
+// C++ Includes
+#include <queue>
+
+// Other libraries and framework includes
+#include "lldb/Target/Process.h"
+#include "lldb/Target/UnixSignals.h"
+#include "ProcessMessage.h"
+
+class ProcessMonitor;
+
+class ProcessPOSIX :
+ public lldb_private::Process
+{
+public:
+
+ //------------------------------------------------------------------
+ // Constructors and destructors
+ //------------------------------------------------------------------
+ ProcessPOSIX(lldb_private::Target& target,
+ lldb_private::Listener &listener);
+
+ virtual
+ ~ProcessPOSIX();
+
+ //------------------------------------------------------------------
+ // Process protocol.
+ //------------------------------------------------------------------
+ virtual bool
+ CanDebug(lldb_private::Target &target, bool plugin_specified_by_name);
+
+ virtual lldb_private::Error
+ WillLaunch(lldb_private::Module *module);
+
+ virtual lldb_private::Error
+ DoAttachToProcessWithID(lldb::pid_t pid);
+
+ virtual lldb_private::Error
+ DoLaunch (lldb_private::Module *exe_module,
+ const lldb_private::ProcessLaunchInfo &launch_info);
+
+ virtual void
+ DidLaunch();
+
+ virtual lldb_private::Error
+ DoResume();
+
+ virtual lldb_private::Error
+ DoHalt(bool &caused_stop);
+
+ virtual lldb_private::Error
+ DoDetach();
+
+ virtual lldb_private::Error
+ DoSignal(int signal);
+
+ virtual lldb_private::Error
+ DoDestroy();
+
+ virtual void
+ RefreshStateAfterStop();
+
+ virtual bool
+ IsAlive();
+
+ virtual size_t
+ DoReadMemory(lldb::addr_t vm_addr,
+ void *buf,
+ size_t size,
+ lldb_private::Error &error);
+
+ virtual size_t
+ DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
+ lldb_private::Error &error);
+
+ virtual lldb::addr_t
+ DoAllocateMemory(size_t size, uint32_t permissions,
+ lldb_private::Error &error);
+
+ virtual lldb_private::Error
+ DoDeallocateMemory(lldb::addr_t ptr);
+
+ virtual size_t
+ GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
+
+ virtual lldb_private::Error
+ EnableBreakpoint(lldb_private::BreakpointSite *bp_site);
+
+ virtual lldb_private::Error
+ DisableBreakpoint(lldb_private::BreakpointSite *bp_site);
+
+ virtual uint32_t
+ UpdateThreadListIfNeeded();
+
+ virtual uint32_t
+ UpdateThreadList(lldb_private::ThreadList &old_thread_list,
+ lldb_private::ThreadList &new_thread_list) = 0;
+
+ virtual lldb::ByteOrder
+ GetByteOrder() const;
+
+ virtual lldb::addr_t
+ GetImageInfoAddress();
+
+ virtual size_t
+ PutSTDIN(const char *buf, size_t len, lldb_private::Error &error);
+
+ virtual size_t
+ GetSTDOUT(char *buf, size_t len, lldb_private::Error &error);
+
+ virtual size_t
+ GetSTDERR(char *buf, size_t len, lldb_private::Error &error);
+
+ //--------------------------------------------------------------------------
+ // ProcessPOSIX internal API.
+
+ /// Registers the given message with this process.
+ void SendMessage(const ProcessMessage &message);
+
+ ProcessMonitor &
+ GetMonitor() { assert(m_monitor); return *m_monitor; }
+
+ lldb_private::UnixSignals &
+ GetUnixSignals();
+
+ const char *
+ GetFilePath(const lldb_private::ProcessLaunchInfo::FileAction *file_action,
+ const char *default_path);
+
+protected:
+ /// Target byte order.
+ lldb::ByteOrder m_byte_order;
+
+ /// Process monitor;
+ ProcessMonitor *m_monitor;
+
+ /// The module we are executing.
+ lldb_private::Module *m_module;
+
+ /// Message queue notifying this instance of inferior process state changes.
+ lldb_private::Mutex m_message_mutex;
+ std::queue<ProcessMessage> m_message_queue;
+
+ /// True when the process has entered a state of "limbo".
+ ///
+ /// This flag qualifies eStateStopped. It lets us know that when we
+ /// continue from this state the process will exit. Also, when true,
+ /// Process::m_exit_status is set.
+ bool m_in_limbo;
+
+ /// Drive any exit events to completion.
+ bool m_exit_now;
+
+ /// OS-specific signal set.
+ lldb_private::UnixSignals m_signals;
+
+ /// Returns true if the process has exited.
+ bool HasExited();
+
+ /// Returns true if the process is stopped.
+ bool IsStopped();
+
+ typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
+ MMapMap m_addr_to_mmap_size;
+};
+
+#endif // liblldb_MacOSXProcess_H_
Index: source/Plugins/Process/POSIX/RegisterContext_i386.h
===================================================================
--- source/Plugins/Process/POSIX/RegisterContext_i386.h (revision 0)
+++ source/Plugins/Process/POSIX/RegisterContext_i386.h (revision 0)
@@ -0,0 +1,169 @@
+//===-- RegisterContext_i386.h ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContext_i386_h_
+#define liblldb_RegisterContext_i386_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Log.h"
+#include "RegisterContextPOSIX.h"
+
+class RegisterContext_i386 : public RegisterContextPOSIX
+{
+public:
+ RegisterContext_i386(lldb_private::Thread &thread,
+ uint32_t concreate_frame_idx);
+
+ ~RegisterContext_i386();
+
+ void
+ Invalidate();
+
+ void
+ InvalidateAllRegisters();
+
+ size_t
+ GetRegisterCount();
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(uint32_t reg);
+
+ size_t
+ GetRegisterSetCount();
+
+ const lldb_private::RegisterSet *
+ GetRegisterSet(uint32_t set);
+
+ static unsigned
+ GetRegisterIndexFromOffset(unsigned offset);
+
+ static const char *
+ GetRegisterName(unsigned reg);
+
+ bool
+ ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value);
+
+ bool
+ ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data);
+
+ virtual bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value);
+
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+ bool
+ WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value);
+
+ bool
+ WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data,
+ uint32_t data_offset = 0);
+
+ virtual bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value);
+
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
+
+ bool
+ HardwareSingleStep(bool enable);
+
+ bool
+ UpdateAfterBreakpoint();
+
+ struct GPR
+ {
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t esi;
+ uint32_t edi;
+ uint32_t ebp;
+ uint32_t eax;
+ uint32_t ds;
+ uint32_t es;
+ uint32_t fs;
+ uint32_t gs;
+ uint32_t orig_ax;
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t eflags;
+ uint32_t esp;
+ uint32_t ss;
+ };
+
+ struct MMSReg
+ {
+ uint8_t bytes[8];
+ };
+
+ struct XMMReg
+ {
+ uint8_t bytes[16];
+ };
+
+ struct FPU
+ {
+ uint16_t fcw;
+ uint16_t fsw;
+ uint16_t ftw;
+ uint16_t fop;
+ uint32_t ip;
+ uint32_t cs;
+ uint32_t foo;
+ uint32_t fos;
+ uint32_t mxcsr;
+ uint32_t reserved;
+ MMSReg stmm[8];
+ XMMReg xmm[8];
+ uint32_t pad[56];
+ };
+
+ // A user area like this no longer exists on FreeBSD
+ // making this a Linux artifact. Nonetheless, it is safe
+ // leaving it here while the code is being cleaned up and generalized.
+
+ struct UserArea
+ {
+ GPR regs; // General purpose registers.
+ int32_t fpvalid; // True if FPU is being used.
+ FPU i387; // FPU registers.
+ uint32_t tsize; // Text segment size.
+ uint32_t dsize; // Data segment size.
+ uint32_t ssize; // Stack segment size.
+ uint32_t start_code; // VM address of text.
+ uint32_t start_stack; // VM address of stack bottom (top in rsp).
+ int32_t signal; // Signal causing core dump.
+ int32_t reserved; // Unused.
+ uint32_t ar0; // Location of GPR's.
+ FPU* fpstate; // Location of FPR's.
+ uint32_t magic; // Identifier for core dumps.
+ char u_comm[32]; // Command causing core dump.
+ uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7).
+ };
+private:
+ UserArea user;
+
+ ProcessMonitor &GetMonitor();
+
+ void LogGPR(const char *title);
+
+ bool ReadGPR();
+ bool ReadFPR();
+};
+
+#endif // #ifndef liblldb_RegisterContext_i386_h_
Index: source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
===================================================================
--- source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (revision 0)
+++ source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (revision 0)
@@ -0,0 +1,757 @@
+//===-- RegisterContext_x86_64.cpp -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cstring>
+#include <errno.h>
+#include <stdint.h>
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Host/Endian.h"
+
+#include "ProcessPOSIX.h"
+#include "ProcessMonitor.h"
+#include "RegisterContext_x86_64.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+// Internal codes for all x86_64 registers.
+enum
+{
+ k_first_gpr,
+ gpr_rax = k_first_gpr,
+ gpr_rbx,
+ gpr_rcx,
+ gpr_rdx,
+ gpr_rdi,
+ gpr_rsi,
+ gpr_rbp,
+ gpr_rsp,
+ gpr_r8,
+ gpr_r9,
+ gpr_r10,
+ gpr_r11,
+ gpr_r12,
+ gpr_r13,
+ gpr_r14,
+ gpr_r15,
+ gpr_rip,
+ gpr_rflags,
+ gpr_cs,
+ gpr_fs,
+ gpr_gs,
+ gpr_ss,
+ gpr_ds,
+ gpr_es,
+ k_last_gpr = gpr_es,
+
+ k_first_fpr,
+ fpu_fcw = k_first_fpr,
+ fpu_fsw,
+ fpu_ftw,
+ fpu_fop,
+ fpu_ip,
+ fpu_cs,
+ fpu_dp,
+ fpu_ds,
+ fpu_mxcsr,
+ fpu_mxcsrmask,
+ fpu_stmm0,
+ fpu_stmm1,
+ fpu_stmm2,
+ fpu_stmm3,
+ fpu_stmm4,
+ fpu_stmm5,
+ fpu_stmm6,
+ fpu_stmm7,
+ fpu_xmm0,
+ fpu_xmm1,
+ fpu_xmm2,
+ fpu_xmm3,
+ fpu_xmm4,
+ fpu_xmm5,
+ fpu_xmm6,
+ fpu_xmm7,
+ fpu_xmm8,
+ fpu_xmm9,
+ fpu_xmm10,
+ fpu_xmm11,
+ fpu_xmm12,
+ fpu_xmm13,
+ fpu_xmm14,
+ fpu_xmm15,
+ k_last_fpr = fpu_xmm15,
+
+ k_num_registers,
+ k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
+ k_num_fpu_registers = k_last_fpr - k_first_fpr + 1
+};
+
+// Number of register sets provided by this context.
+enum
+{
+ k_num_register_sets = 2
+};
+
+enum gcc_dwarf_regnums
+{
+ gcc_dwarf_gpr_rax = 0,
+ gcc_dwarf_gpr_rdx,
+ gcc_dwarf_gpr_rcx,
+ gcc_dwarf_gpr_rbx,
+ gcc_dwarf_gpr_rsi,
+ gcc_dwarf_gpr_rdi,
+ gcc_dwarf_gpr_rbp,
+ gcc_dwarf_gpr_rsp,
+ gcc_dwarf_gpr_r8,
+ gcc_dwarf_gpr_r9,
+ gcc_dwarf_gpr_r10,
+ gcc_dwarf_gpr_r11,
+ gcc_dwarf_gpr_r12,
+ gcc_dwarf_gpr_r13,
+ gcc_dwarf_gpr_r14,
+ gcc_dwarf_gpr_r15,
+ gcc_dwarf_gpr_rip,
+ gcc_dwarf_fpu_xmm0,
+ gcc_dwarf_fpu_xmm1,
+ gcc_dwarf_fpu_xmm2,
+ gcc_dwarf_fpu_xmm3,
+ gcc_dwarf_fpu_xmm4,
+ gcc_dwarf_fpu_xmm5,
+ gcc_dwarf_fpu_xmm6,
+ gcc_dwarf_fpu_xmm7,
+ gcc_dwarf_fpu_xmm8,
+ gcc_dwarf_fpu_xmm9,
+ gcc_dwarf_fpu_xmm10,
+ gcc_dwarf_fpu_xmm11,
+ gcc_dwarf_fpu_xmm12,
+ gcc_dwarf_fpu_xmm13,
+ gcc_dwarf_fpu_xmm14,
+ gcc_dwarf_fpu_xmm15,
+ gcc_dwarf_fpu_stmm0,
+ gcc_dwarf_fpu_stmm1,
+ gcc_dwarf_fpu_stmm2,
+ gcc_dwarf_fpu_stmm3,
+ gcc_dwarf_fpu_stmm4,
+ gcc_dwarf_fpu_stmm5,
+ gcc_dwarf_fpu_stmm6,
+ gcc_dwarf_fpu_stmm7
+};
+
+enum gdb_regnums
+{
+ gdb_gpr_rax = 0,
+ gdb_gpr_rbx = 1,
+ gdb_gpr_rcx = 2,
+ gdb_gpr_rdx = 3,
+ gdb_gpr_rsi = 4,
+ gdb_gpr_rdi = 5,
+ gdb_gpr_rbp = 6,
+ gdb_gpr_rsp = 7,
+ gdb_gpr_r8 = 8,
+ gdb_gpr_r9 = 9,
+ gdb_gpr_r10 = 10,
+ gdb_gpr_r11 = 11,
+ gdb_gpr_r12 = 12,
+ gdb_gpr_r13 = 13,
+ gdb_gpr_r14 = 14,
+ gdb_gpr_r15 = 15,
+ gdb_gpr_rip = 16,
+ gdb_gpr_rflags = 17,
+ gdb_gpr_cs = 18,
+ gdb_gpr_ss = 19,
+ gdb_gpr_ds = 20,
+ gdb_gpr_es = 21,
+ gdb_gpr_fs = 22,
+ gdb_gpr_gs = 23,
+ gdb_fpu_stmm0 = 24,
+ gdb_fpu_stmm1 = 25,
+ gdb_fpu_stmm2 = 26,
+ gdb_fpu_stmm3 = 27,
+ gdb_fpu_stmm4 = 28,
+ gdb_fpu_stmm5 = 29,
+ gdb_fpu_stmm6 = 30,
+ gdb_fpu_stmm7 = 31,
+ gdb_fpu_fcw = 32,
+ gdb_fpu_fsw = 33,
+ gdb_fpu_ftw = 34,
+ gdb_fpu_cs = 35,
+ gdb_fpu_ip = 36,
+ gdb_fpu_ds = 37,
+ gdb_fpu_dp = 38,
+ gdb_fpu_fop = 39,
+ gdb_fpu_xmm0 = 40,
+ gdb_fpu_xmm1 = 41,
+ gdb_fpu_xmm2 = 42,
+ gdb_fpu_xmm3 = 43,
+ gdb_fpu_xmm4 = 44,
+ gdb_fpu_xmm5 = 45,
+ gdb_fpu_xmm6 = 46,
+ gdb_fpu_xmm7 = 47,
+ gdb_fpu_xmm8 = 48,
+ gdb_fpu_xmm9 = 49,
+ gdb_fpu_xmm10 = 50,
+ gdb_fpu_xmm11 = 51,
+ gdb_fpu_xmm12 = 52,
+ gdb_fpu_xmm13 = 53,
+ gdb_fpu_xmm14 = 54,
+ gdb_fpu_xmm15 = 55,
+ gdb_fpu_mxcsr = 56
+};
+
+static const
+uint32_t g_gpr_regnums[k_num_gpr_registers] =
+{
+ gpr_rax,
+ gpr_rbx,
+ gpr_rcx,
+ gpr_rdx,
+ gpr_rdi,
+ gpr_rsi,
+ gpr_rbp,
+ gpr_rsp,
+ gpr_r8,
+ gpr_r9,
+ gpr_r10,
+ gpr_r11,
+ gpr_r12,
+ gpr_r13,
+ gpr_r14,
+ gpr_r15,
+ gpr_rip,
+ gpr_rflags,
+ gpr_cs,
+ gpr_fs,
+ gpr_gs,
+ gpr_ss,
+ gpr_ds,
+ gpr_es
+};
+
+static const uint32_t
+g_fpu_regnums[k_num_fpu_registers] =
+{
+ fpu_fcw,
+ fpu_fsw,
+ fpu_ftw,
+ fpu_fop,
+ fpu_ip,
+ fpu_cs,
+ fpu_dp,
+ fpu_ds,
+ fpu_mxcsr,
+ fpu_mxcsrmask,
+ fpu_stmm0,
+ fpu_stmm1,
+ fpu_stmm2,
+ fpu_stmm3,
+ fpu_stmm4,
+ fpu_stmm5,
+ fpu_stmm6,
+ fpu_stmm7,
+ fpu_xmm0,
+ fpu_xmm1,
+ fpu_xmm2,
+ fpu_xmm3,
+ fpu_xmm4,
+ fpu_xmm5,
+ fpu_xmm6,
+ fpu_xmm7,
+ fpu_xmm8,
+ fpu_xmm9,
+ fpu_xmm10,
+ fpu_xmm11,
+ fpu_xmm12,
+ fpu_xmm13,
+ fpu_xmm14,
+ fpu_xmm15
+};
+
+static const RegisterSet
+g_reg_sets[k_num_register_sets] =
+{
+ { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
+ { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums }
+};
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname) \
+ (offsetof(RegisterContext_x86_64::UserArea, regs) + \
+ offsetof(GPR, regname))
+
+// Computes the offset of the given FPR in the user data area.
+#define FPR_OFFSET(regname) \
+ (offsetof(RegisterContext_x86_64::UserArea, i387) + \
+ offsetof(RegisterContext_x86_64::FPU, regname))
+
+// Number of bytes needed to represent a GPR.
+#define GPR_SIZE(reg) sizeof(((GPR*)NULL)->reg)
+
+// Number of bytes needed to represent a FPR.
+#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FPU*)NULL)->reg)
+
+// Number of bytes needed to represent the i'th FP register.
+#define FP_SIZE sizeof(((RegisterContext_x86_64::MMSReg*)NULL)->bytes)
+
+// Number of bytes needed to represent an XMM register.
+#define XMM_SIZE sizeof(RegisterContext_x86_64::XMMReg)
+
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
+ { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } }
+
+#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \
+ { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } }
+
+#define DEFINE_FP(reg, i) \
+ { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \
+ eFormatVectorOfUInt8, \
+ { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \
+ LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } }
+
+#define DEFINE_XMM(reg, i) \
+ { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \
+ eFormatVectorOfUInt8, \
+ { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \
+ LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } }
+
+#define REG_CONTEXT_SIZE (sizeof(GPR) + sizeof(RegisterContext_x86_64::FPU))
+
+static RegisterInfo
+g_register_infos[k_num_registers] =
+{
+ // General purpose registers.
+ DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax),
+ DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx),
+ DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx),
+ DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx),
+ DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi),
+ DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi),
+ DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp),
+ DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp),
+ DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8),
+ DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9),
+ DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10),
+ DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11),
+ DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12),
+ DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13),
+ DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14),
+ DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15),
+ DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip),
+ DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags),
+ DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs),
+ DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs),
+ DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs),
+ DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss),
+ DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds),
+ DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es),
+
+ // i387 Floating point registers.
+ DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw),
+ DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw),
+ DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw),
+ DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop),
+ DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip),
+ // FIXME: Extract segment from ip.
+ DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs),
+ DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp),
+ // FIXME: Extract segment from dp.
+ DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds),
+ DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr),
+ DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+
+ // FP registers.
+ DEFINE_FP(stmm, 0),
+ DEFINE_FP(stmm, 1),
+ DEFINE_FP(stmm, 2),
+ DEFINE_FP(stmm, 3),
+ DEFINE_FP(stmm, 4),
+ DEFINE_FP(stmm, 5),
+ DEFINE_FP(stmm, 6),
+ DEFINE_FP(stmm, 7),
+
+ // XMM registers
+ DEFINE_XMM(xmm, 0),
+ DEFINE_XMM(xmm, 1),
+ DEFINE_XMM(xmm, 2),
+ DEFINE_XMM(xmm, 3),
+ DEFINE_XMM(xmm, 4),
+ DEFINE_XMM(xmm, 5),
+ DEFINE_XMM(xmm, 6),
+ DEFINE_XMM(xmm, 7),
+ DEFINE_XMM(xmm, 8),
+ DEFINE_XMM(xmm, 9),
+ DEFINE_XMM(xmm, 10),
+ DEFINE_XMM(xmm, 11),
+ DEFINE_XMM(xmm, 12),
+ DEFINE_XMM(xmm, 13),
+ DEFINE_XMM(xmm, 14),
+ DEFINE_XMM(xmm, 15)
+};
+
+static unsigned GetRegOffset(unsigned reg)
+{
+ assert(reg < k_num_registers && "Invalid register number.");
+ return g_register_infos[reg].byte_offset;
+}
+
+static unsigned GetRegSize(unsigned reg)
+{
+ assert(reg < k_num_registers && "Invalid register number.");
+ return g_register_infos[reg].byte_size;
+}
+
+static bool IsGPR(unsigned reg)
+{
+ return reg <= k_last_gpr; // GPR's come first.
+}
+
+static bool IsFPR(unsigned reg)
+{
+ return (k_first_fpr <= reg && reg <= k_last_fpr);
+}
+
+RegisterContext_x86_64::RegisterContext_x86_64(Thread &thread,
+ uint32_t concrete_frame_idx)
+ : RegisterContextPOSIX(thread, concrete_frame_idx)
+{
+}
+
+RegisterContext_x86_64::~RegisterContext_x86_64()
+{
+}
+
+ProcessMonitor &
+RegisterContext_x86_64::GetMonitor()
+{
+ ProcessPOSIX *process = static_cast<ProcessPOSIX*>(CalculateProcess());
+ return process->GetMonitor();
+}
+
+void
+RegisterContext_x86_64::Invalidate()
+{
+}
+
+void
+RegisterContext_x86_64::InvalidateAllRegisters()
+{
+}
+
+size_t
+RegisterContext_x86_64::GetRegisterCount()
+{
+ return k_num_registers;
+}
+
+const RegisterInfo *
+RegisterContext_x86_64::GetRegisterInfoAtIndex(uint32_t reg)
+{
+ if (reg < k_num_registers)
+ return &g_register_infos[reg];
+ else
+ return NULL;
+}
+
+size_t
+RegisterContext_x86_64::GetRegisterSetCount()
+{
+ return k_num_register_sets;
+}
+
+const RegisterSet *
+RegisterContext_x86_64::GetRegisterSet(uint32_t set)
+{
+ if (set < k_num_register_sets)
+ return &g_reg_sets[set];
+ else
+ return NULL;
+}
+
+unsigned
+RegisterContext_x86_64::GetRegisterIndexFromOffset(unsigned offset)
+{
+ unsigned reg;
+ for (reg = 0; reg < k_num_registers; reg++)
+ {
+ if (g_register_infos[reg].byte_offset == offset)
+ break;
+ }
+ assert(reg < k_num_registers && "Invalid register offset.");
+ return reg;
+}
+
+const char *
+RegisterContext_x86_64::GetRegisterName(unsigned reg)
+{
+ assert(reg < k_num_registers && "Invalid register offset.");
+ return g_register_infos[reg].name;
+}
+
+bool
+RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &value)
+{
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value);
+}
+
+bool
+RegisterContext_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp)
+{
+ data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+ if (data_sp && ReadGPR () && ReadFPR ())
+ {
+ uint8_t *dst = data_sp->GetBytes();
+ ::memcpy (dst, &user.regs, sizeof(user.regs));
+ dst += sizeof(user.regs);
+
+ ::memcpy (dst, &user.i387, sizeof(user.i387));
+ return true;
+ }
+ return false;
+}
+
+bool
+RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value)
+{
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteRegisterValue(GetRegOffset(reg), value);
+}
+
+bool
+RegisterContext_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp)
+{
+ if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+ {
+ const uint8_t *src = data_sp->GetBytes();
+ ::memcpy (&user.regs, src, sizeof(user.regs));
+ src += sizeof(user.regs);
+
+ ::memcpy (&user.i387, src, sizeof(user.i387));
+ return WriteGPR() & WriteFPR();
+ }
+ return false;
+}
+
+bool
+RegisterContext_x86_64::UpdateAfterBreakpoint()
+{
+ // PC points one byte past the int3 responsible for the breakpoint.
+ lldb::addr_t pc;
+
+ if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+ return false;
+
+ SetPC(pc - 1);
+ return true;
+}
+
+uint32_t
+RegisterContext_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind,
+ uint32_t num)
+{
+ if (kind == eRegisterKindGeneric)
+ {
+ switch (num)
+ {
+ case LLDB_REGNUM_GENERIC_PC: return gpr_rip;
+ case LLDB_REGNUM_GENERIC_SP: return gpr_rsp;
+ case LLDB_REGNUM_GENERIC_FP: return gpr_rbp;
+ case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags;
+ case LLDB_REGNUM_GENERIC_RA:
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ }
+
+ if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+ {
+ switch (num)
+ {
+ case gcc_dwarf_gpr_rax: return gpr_rax;
+ case gcc_dwarf_gpr_rdx: return gpr_rdx;
+ case gcc_dwarf_gpr_rcx: return gpr_rcx;
+ case gcc_dwarf_gpr_rbx: return gpr_rbx;
+ case gcc_dwarf_gpr_rsi: return gpr_rsi;
+ case gcc_dwarf_gpr_rdi: return gpr_rdi;
+ case gcc_dwarf_gpr_rbp: return gpr_rbp;
+ case gcc_dwarf_gpr_rsp: return gpr_rsp;
+ case gcc_dwarf_gpr_r8: return gpr_r8;
+ case gcc_dwarf_gpr_r9: return gpr_r9;
+ case gcc_dwarf_gpr_r10: return gpr_r10;
+ case gcc_dwarf_gpr_r11: return gpr_r11;
+ case gcc_dwarf_gpr_r12: return gpr_r12;
+ case gcc_dwarf_gpr_r13: return gpr_r13;
+ case gcc_dwarf_gpr_r14: return gpr_r14;
+ case gcc_dwarf_gpr_r15: return gpr_r15;
+ case gcc_dwarf_gpr_rip: return gpr_rip;
+ case gcc_dwarf_fpu_xmm0: return fpu_xmm0;
+ case gcc_dwarf_fpu_xmm1: return fpu_xmm1;
+ case gcc_dwarf_fpu_xmm2: return fpu_xmm2;
+ case gcc_dwarf_fpu_xmm3: return fpu_xmm3;
+ case gcc_dwarf_fpu_xmm4: return fpu_xmm4;
+ case gcc_dwarf_fpu_xmm5: return fpu_xmm5;
+ case gcc_dwarf_fpu_xmm6: return fpu_xmm6;
+ case gcc_dwarf_fpu_xmm7: return fpu_xmm7;
+ case gcc_dwarf_fpu_xmm8: return fpu_xmm8;
+ case gcc_dwarf_fpu_xmm9: return fpu_xmm9;
+ case gcc_dwarf_fpu_xmm10: return fpu_xmm10;
+ case gcc_dwarf_fpu_xmm11: return fpu_xmm11;
+ case gcc_dwarf_fpu_xmm12: return fpu_xmm12;
+ case gcc_dwarf_fpu_xmm13: return fpu_xmm13;
+ case gcc_dwarf_fpu_xmm14: return fpu_xmm14;
+ case gcc_dwarf_fpu_xmm15: return fpu_xmm15;
+ case gcc_dwarf_fpu_stmm0: return fpu_stmm0;
+ case gcc_dwarf_fpu_stmm1: return fpu_stmm1;
+ case gcc_dwarf_fpu_stmm2: return fpu_stmm2;
+ case gcc_dwarf_fpu_stmm3: return fpu_stmm3;
+ case gcc_dwarf_fpu_stmm4: return fpu_stmm4;
+ case gcc_dwarf_fpu_stmm5: return fpu_stmm5;
+ case gcc_dwarf_fpu_stmm6: return fpu_stmm6;
+ case gcc_dwarf_fpu_stmm7: return fpu_stmm7;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ }
+
+ if (kind == eRegisterKindGDB)
+ {
+ switch (num)
+ {
+ case gdb_gpr_rax : return gpr_rax;
+ case gdb_gpr_rbx : return gpr_rbx;
+ case gdb_gpr_rcx : return gpr_rcx;
+ case gdb_gpr_rdx : return gpr_rdx;
+ case gdb_gpr_rsi : return gpr_rsi;
+ case gdb_gpr_rdi : return gpr_rdi;
+ case gdb_gpr_rbp : return gpr_rbp;
+ case gdb_gpr_rsp : return gpr_rsp;
+ case gdb_gpr_r8 : return gpr_r8;
+ case gdb_gpr_r9 : return gpr_r9;
+ case gdb_gpr_r10 : return gpr_r10;
+ case gdb_gpr_r11 : return gpr_r11;
+ case gdb_gpr_r12 : return gpr_r12;
+ case gdb_gpr_r13 : return gpr_r13;
+ case gdb_gpr_r14 : return gpr_r14;
+ case gdb_gpr_r15 : return gpr_r15;
+ case gdb_gpr_rip : return gpr_rip;
+ case gdb_gpr_rflags : return gpr_rflags;
+ case gdb_gpr_cs : return gpr_cs;
+ case gdb_gpr_ss : return gpr_ss;
+ case gdb_gpr_ds : return gpr_ds;
+ case gdb_gpr_es : return gpr_es;
+ case gdb_gpr_fs : return gpr_fs;
+ case gdb_gpr_gs : return gpr_gs;
+ case gdb_fpu_stmm0 : return fpu_stmm0;
+ case gdb_fpu_stmm1 : return fpu_stmm1;
+ case gdb_fpu_stmm2 : return fpu_stmm2;
+ case gdb_fpu_stmm3 : return fpu_stmm3;
+ case gdb_fpu_stmm4 : return fpu_stmm4;
+ case gdb_fpu_stmm5 : return fpu_stmm5;
+ case gdb_fpu_stmm6 : return fpu_stmm6;
+ case gdb_fpu_stmm7 : return fpu_stmm7;
+ case gdb_fpu_fcw : return fpu_fcw;
+ case gdb_fpu_fsw : return fpu_fsw;
+ case gdb_fpu_ftw : return fpu_ftw;
+ case gdb_fpu_cs : return fpu_cs;
+ case gdb_fpu_ip : return fpu_ip;
+ case gdb_fpu_ds : return fpu_ds;
+ case gdb_fpu_dp : return fpu_dp;
+ case gdb_fpu_fop : return fpu_fop;
+ case gdb_fpu_xmm0 : return fpu_xmm0;
+ case gdb_fpu_xmm1 : return fpu_xmm1;
+ case gdb_fpu_xmm2 : return fpu_xmm2;
+ case gdb_fpu_xmm3 : return fpu_xmm3;
+ case gdb_fpu_xmm4 : return fpu_xmm4;
+ case gdb_fpu_xmm5 : return fpu_xmm5;
+ case gdb_fpu_xmm6 : return fpu_xmm6;
+ case gdb_fpu_xmm7 : return fpu_xmm7;
+ case gdb_fpu_xmm8 : return fpu_xmm8;
+ case gdb_fpu_xmm9 : return fpu_xmm9;
+ case gdb_fpu_xmm10 : return fpu_xmm10;
+ case gdb_fpu_xmm11 : return fpu_xmm11;
+ case gdb_fpu_xmm12 : return fpu_xmm12;
+ case gdb_fpu_xmm13 : return fpu_xmm13;
+ case gdb_fpu_xmm14 : return fpu_xmm14;
+ case gdb_fpu_xmm15 : return fpu_xmm15;
+ case gdb_fpu_mxcsr : return fpu_mxcsr;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ }
+ else if (kind == eRegisterKindLLDB)
+ {
+ return num;
+ }
+
+ return LLDB_INVALID_REGNUM;
+}
+
+bool
+RegisterContext_x86_64::HardwareSingleStep(bool enable)
+{
+ enum { TRACE_BIT = 0x100 };
+ uint64_t rflags;
+
+ if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL)
+ return false;
+
+ if (enable)
+ {
+ if (rflags & TRACE_BIT)
+ return true;
+
+ rflags |= TRACE_BIT;
+ }
+ else
+ {
+ if (!(rflags & TRACE_BIT))
+ return false;
+
+ rflags &= ~TRACE_BIT;
+ }
+
+ return WriteRegisterFromUnsigned(gpr_rflags, rflags);
+}
+
+bool
+RegisterContext_x86_64::ReadGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadGPR(&user.regs);
+}
+
+bool
+RegisterContext_x86_64::ReadFPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadFPR(&user.i387);
+}
+
+bool
+RegisterContext_x86_64::WriteGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteGPR(&user.regs);
+}
+
+bool
+RegisterContext_x86_64::WriteFPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteFPR(&user.i387);
+}
Index: source/Plugins/Process/POSIX/ProcessPOSIXLog.h
===================================================================
--- source/Plugins/Process/POSIX/ProcessPOSIXLog.h (revision 0)
+++ source/Plugins/Process/POSIX/ProcessPOSIXLog.h (revision 0)
@@ -0,0 +1,106 @@
+//===-- ProcessLinuxLog.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessLinuxLog_h_
+#define liblldb_ProcessLinuxLog_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/Core/Log.h"
+
+#define POSIX_LOG_VERBOSE (1u << 0)
+#define POSIX_LOG_PROCESS (1u << 1)
+#define POSIX_LOG_THREAD (1u << 2)
+#define POSIX_LOG_PACKETS (1u << 3)
+#define POSIX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls
+#define POSIX_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes
+#define POSIX_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes
+#define POSIX_LOG_BREAKPOINTS (1u << 7)
+#define POSIX_LOG_WATCHPOINTS (1u << 8)
+#define POSIX_LOG_STEP (1u << 9)
+#define POSIX_LOG_COMM (1u << 10)
+#define POSIX_LOG_ASYNC (1u << 11)
+#define POSIX_LOG_PTRACE (1u << 12)
+#define POSIX_LOG_REGISTERS (1u << 13)
+#define POSIX_LOG_ALL (UINT32_MAX)
+#define POSIX_LOG_DEFAULT POSIX_LOG_PACKETS
+
+// The size which determines "short memory reads/writes".
+#define POSIX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t))
+
+class ProcessPOSIXLog
+{
+ static int m_nestinglevel;
+ static const char *m_pluginname;
+
+public:
+ static void
+ RegisterPluginName(const char *pluginName)
+ {
+ m_pluginname = pluginName;
+ }
+
+
+ static lldb::LogSP
+ GetLogIfAllCategoriesSet(uint32_t mask = 0);
+
+ static void
+ DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm);
+
+ static lldb::LogSP
+ EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options,
+ lldb_private::Args &args, lldb_private::Stream *feedback_strm);
+
+ static void
+ ListLogCategories (lldb_private::Stream *strm);
+
+ static void
+ LogIf (uint32_t mask, const char *format, ...);
+
+ // The following functions can be used to enable the client to limit
+ // logging to only the top level function calls. This is useful for
+ // recursive functions. FIXME: not thread safe!
+ // Example:
+ // void NestingFunc() {
+ // LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL));
+ // if (log)
+ // {
+ // ProcessLinuxLog::IncNestLevel();
+ // if (ProcessLinuxLog::AtTopNestLevel())
+ // log->Print(msg);
+ // }
+ // NestingFunc();
+ // if (log)
+ // ProcessLinuxLog::DecNestLevel();
+ // }
+
+ static bool
+ AtTopNestLevel()
+ {
+ return m_nestinglevel == 1;
+ }
+
+ static void
+ IncNestLevel()
+ {
+ ++m_nestinglevel;
+ }
+
+ static void
+ DecNestLevel()
+ {
+ --m_nestinglevel;
+ assert(m_nestinglevel >= 0);
+ }
+};
+
+#endif // liblldb_ProcessLinuxLog_h_
Index: source/Plugins/Process/POSIX/RegisterContext_x86_64.h
===================================================================
--- source/Plugins/Process/POSIX/RegisterContext_x86_64.h (revision 0)
+++ source/Plugins/Process/POSIX/RegisterContext_x86_64.h (revision 0)
@@ -0,0 +1,143 @@
+//===-- RegisterContext_x86_64.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContext_x86_64_H_
+#define liblldb_RegisterContext_x86_64_H_
+
+#include "lldb/Core/Log.h"
+#include "RegisterContextPOSIX.h"
+
+#ifdef __FreeBSD__
+#include "RegisterContextFreeBSD_x86_64.h"
+#endif
+
+#ifdef __linux__
+#include "RegisterContextLinux_x86_64.h"
+#endif
+
+class ProcessMonitor;
+
+class RegisterContext_x86_64
+ : public RegisterContextPOSIX
+{
+public:
+ RegisterContext_x86_64 (lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx);
+
+ ~RegisterContext_x86_64();
+
+ void
+ Invalidate();
+
+ void
+ InvalidateAllRegisters();
+
+ size_t
+ GetRegisterCount();
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(uint32_t reg);
+
+ size_t
+ GetRegisterSetCount();
+
+ const lldb_private::RegisterSet *
+ GetRegisterSet(uint32_t set);
+
+ static unsigned
+ GetRegisterIndexFromOffset(unsigned offset);
+
+ static const char *
+ GetRegisterName(unsigned reg);
+
+ virtual bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value);
+
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+ virtual bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value);
+
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
+
+ bool
+ HardwareSingleStep(bool enable);
+
+ bool
+ UpdateAfterBreakpoint();
+
+ struct MMSReg
+ {
+ uint8_t bytes[10];
+ uint8_t pad[6];
+ };
+
+ struct XMMReg
+ {
+ uint8_t bytes[16];
+ };
+
+ struct FPU
+ {
+ uint16_t fcw;
+ uint16_t fsw;
+ uint16_t ftw;
+ uint16_t fop;
+ uint64_t ip;
+ uint64_t dp;
+ uint32_t mxcsr;
+ uint32_t mxcsrmask;
+ MMSReg stmm[8];
+ XMMReg xmm[16];
+ uint32_t padding[24];
+ };
+
+ struct UserArea
+ {
+ GPR regs; // General purpose registers.
+ int32_t fpvalid; // True if FPU is being used.
+ int32_t pad0;
+ FPU i387; // FPU registers.
+ uint64_t tsize; // Text segment size.
+ uint64_t dsize; // Data segment size.
+ uint64_t ssize; // Stack segment size.
+ uint64_t start_code; // VM address of text.
+ uint64_t start_stack; // VM address of stack bottom (top in rsp).
+ int64_t signal; // Signal causing core dump.
+ int32_t reserved; // Unused.
+ int32_t pad1;
+ uint64_t ar0; // Location of GPR's.
+ FPU* fpstate; // Location of FPR's.
+ uint64_t magic; // Identifier for core dumps.
+ char u_comm[32]; // Command causing core dump.
+ uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7).
+ uint64_t error_code; // CPU error code.
+ uint64_t fault_address; // Control register CR3.
+ };
+
+private:
+ UserArea user;
+
+ ProcessMonitor &GetMonitor();
+
+ bool ReadGPR();
+ bool ReadFPR();
+
+ bool WriteGPR();
+ bool WriteFPR();
+};
+
+#endif // #ifndef liblldb_RegisterContext_x86_64_H_
Index: source/Plugins/Process/POSIX/RegisterContextPOSIX.h
===================================================================
--- source/Plugins/Process/POSIX/RegisterContextPOSIX.h (revision 0)
+++ source/Plugins/Process/POSIX/RegisterContextPOSIX.h (revision 0)
@@ -0,0 +1,40 @@
+//===-- RegisterContextPOSIX.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextPOSIX_H_
+#define liblldb_RegisterContextPOSIX_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Target/RegisterContext.h"
+
+//------------------------------------------------------------------------------
+/// @class RegisterContextPOSIX
+///
+/// @brief Extends RegisterClass with a few virtual operations useful on POSIX.
+class RegisterContextPOSIX
+ : public lldb_private::RegisterContext
+{
+public:
+ RegisterContextPOSIX(lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx)
+ : RegisterContext(thread, concrete_frame_idx) { }
+
+ /// Updates the register state of the associated thread after hitting a
+ /// breakpoint (if that make sense for the architecture). Default
+ /// implementation simply returns true for architectures which do not
+ /// require any update.
+ ///
+ /// @return
+ /// True if the operation succeeded and false otherwise.
+ virtual bool UpdateAfterBreakpoint() { return true; }
+};
+
+#endif // #ifndef liblldb_RegisterContextPOSIX_H_
Index: source/Plugins/Process/POSIX/ProcessMessage.cpp
===================================================================
--- source/Plugins/Process/POSIX/ProcessMessage.cpp (revision 0)
+++ source/Plugins/Process/POSIX/ProcessMessage.cpp (revision 0)
@@ -0,0 +1,245 @@
+//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProcessMessage.h"
+
+using namespace lldb_private;
+
+const char *
+ProcessMessage::GetCrashReasonString(CrashReason reason)
+{
+ const char *str = NULL;
+
+ switch (reason)
+ {
+ default:
+ assert(false && "invalid CrashReason");
+ break;
+
+ case eInvalidAddress:
+ str = "invalid address";
+ break;
+ case ePrivilegedAddress:
+ str = "address access protected";
+ break;
+ case eIllegalOpcode:
+ str = "illegal instruction";
+ break;
+ case eIllegalOperand:
+ str = "illegal instruction operand";
+ break;
+ case eIllegalAddressingMode:
+ str = "illegal addressing mode";
+ break;
+ case eIllegalTrap:
+ str = "illegal trap";
+ break;
+ case ePrivilegedOpcode:
+ str = "privileged instruction";
+ break;
+ case ePrivilegedRegister:
+ str = "privileged register";
+ break;
+ case eCoprocessorError:
+ str = "coprocessor error";
+ break;
+ case eInternalStackError:
+ str = "internal stack error";
+ break;
+ case eIllegalAlignment:
+ str = "illegal alignment";
+ break;
+ case eIllegalAddress:
+ str = "illegal address";
+ break;
+ case eHardwareError:
+ str = "hardware error";
+ break;
+ case eIntegerDivideByZero:
+ str = "integer divide by zero";
+ break;
+ case eIntegerOverflow:
+ str = "integer overflow";
+ break;
+ case eFloatDivideByZero:
+ str = "floating point divide by zero";
+ break;
+ case eFloatOverflow:
+ str = "floating point overflow";
+ break;
+ case eFloatUnderflow:
+ str = "floating point underflow";
+ break;
+ case eFloatInexactResult:
+ str = "inexact floating point result";
+ break;
+ case eFloatInvalidOperation:
+ str = "invalid floating point operation";
+ break;
+ case eFloatSubscriptRange:
+ str = "invalid floating point subscript range";
+ break;
+ }
+
+ return str;
+}
+
+const char *
+ProcessMessage::PrintCrashReason(CrashReason reason)
+{
+#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
+ // Just return the code in asci for integration builds.
+ chcar str[8];
+ sprintf(str, "%d", reason);
+#else
+ const char *str = NULL;
+
+ switch (reason)
+ {
+ default:
+ assert(false && "invalid CrashReason");
+ break;
+
+ case eInvalidCrashReason:
+ str = "eInvalidCrashReason";
+ break;
+
+ // SIGSEGV crash reasons.
+ case eInvalidAddress:
+ str = "eInvalidAddress";
+ break;
+ case ePrivilegedAddress:
+ str = "ePrivilegedAddress";
+ break;
+
+ // SIGILL crash reasons.
+ case eIllegalOpcode:
+ str = "eIllegalOpcode";
+ break;
+ case eIllegalOperand:
+ str = "eIllegalOperand";
+ break;
+ case eIllegalAddressingMode:
+ str = "eIllegalAddressingMode";
+ break;
+ case eIllegalTrap:
+ str = "eIllegalTrap";
+ break;
+ case ePrivilegedOpcode:
+ str = "ePrivilegedOpcode";
+ break;
+ case ePrivilegedRegister:
+ str = "ePrivilegedRegister";
+ break;
+ case eCoprocessorError:
+ str = "eCoprocessorError";
+ break;
+ case eInternalStackError:
+ str = "eInternalStackError";
+ break;
+
+ // SIGBUS crash reasons:
+ case eIllegalAlignment:
+ str = "eIllegalAlignment";
+ break;
+ case eIllegalAddress:
+ str = "eIllegalAddress";
+ break;
+ case eHardwareError:
+ str = "eHardwareError";
+ break;
+
+ // SIGFPE crash reasons:
+ case eIntegerDivideByZero:
+ str = "eIntegerDivideByZero";
+ break;
+ case eIntegerOverflow:
+ str = "eIntegerOverflow";
+ break;
+ case eFloatDivideByZero:
+ str = "eFloatDivideByZero";
+ break;
+ case eFloatOverflow:
+ str = "eFloatOverflow";
+ break;
+ case eFloatUnderflow:
+ str = "eFloatUnderflow";
+ break;
+ case eFloatInexactResult:
+ str = "eFloatInexactResult";
+ break;
+ case eFloatInvalidOperation:
+ str = "eFloatInvalidOperation";
+ break;
+ case eFloatSubscriptRange:
+ str = "eFloatSubscriptRange";
+ break;
+ }
+#endif
+
+ return str;
+}
+
+const char *
+ProcessMessage::PrintCrashReason() const
+{
+ return PrintCrashReason(m_crash_reason);
+}
+
+const char *
+ProcessMessage::PrintKind(Kind kind)
+{
+#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
+ // Just return the code in asci for integration builds.
+ chcar str[8];
+ sprintf(str, "%d", reason);
+#else
+ const char *str = NULL;
+
+ switch (kind)
+ {
+ default:
+ assert(false && "invalid Kind");
+ break;
+
+ case eInvalidMessage:
+ str = "eInvalidMessage";
+ break;
+ case eExitMessage:
+ str = "eExitMessage";
+ break;
+ case eLimboMessage:
+ str = "eLimboMessage";
+ break;
+ case eSignalMessage:
+ str = "eSignalMessage";
+ break;
+ case eSignalDeliveredMessage:
+ str = "eSignalDeliveredMessage";
+ break;
+ case eTraceMessage:
+ str = "eTraceMessage";
+ break;
+ case eBreakpointMessage:
+ str = "eBreakpointMessage";
+ break;
+ case eCrashMessage:
+ str = "eCrashMessage";
+ break;
+ }
+#endif
+
+ return str;
+}
+
+const char *
+ProcessMessage::PrintKind() const
+{
+ return PrintKind(m_kind);
+}
Index: source/Plugins/Process/POSIX/POSIXStopInfo.cpp
===================================================================
--- source/Plugins/Process/POSIX/POSIXStopInfo.cpp (revision 0)
+++ source/Plugins/Process/POSIX/POSIXStopInfo.cpp (revision 0)
@@ -0,0 +1,60 @@
+//===-- POSIXStopInfo.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "POSIXStopInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//===----------------------------------------------------------------------===//
+// POSIXLimboStopInfo
+
+POSIXLimboStopInfo::~POSIXLimboStopInfo() { }
+
+lldb::StopReason
+POSIXLimboStopInfo::GetStopReason() const
+{
+ return lldb::eStopReasonTrace;
+}
+
+const char *
+POSIXLimboStopInfo::GetDescription()
+{
+ return "thread exiting";
+}
+
+bool
+POSIXLimboStopInfo::ShouldStop(Event *event_ptr)
+{
+ return true;
+}
+
+bool
+POSIXLimboStopInfo::ShouldNotify(Event *event_ptr)
+{
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// POSIXCrashStopInfo
+
+POSIXCrashStopInfo::~POSIXCrashStopInfo() { }
+
+lldb::StopReason
+POSIXCrashStopInfo::GetStopReason() const
+{
+ return lldb::eStopReasonException;
+}
+
+const char *
+POSIXCrashStopInfo::GetDescription()
+{
+ return ProcessMessage::GetCrashReasonString(m_crash_reason);
+}
Index: source/Plugins/Process/POSIX/ProcessMessage.h
===================================================================
--- source/Plugins/Process/POSIX/ProcessMessage.h (revision 0)
+++ source/Plugins/Process/POSIX/ProcessMessage.h (revision 0)
@@ -0,0 +1,171 @@
+//===-- ProcessMessage.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessMessage_H_
+#define liblldb_ProcessMessage_H_
+
+#include <cassert>
+
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-types.h"
+
+class ProcessMessage
+{
+public:
+
+ /// The type of signal this message can correspond to.
+ enum Kind
+ {
+ eInvalidMessage,
+ eExitMessage,
+ eLimboMessage,
+ eSignalMessage,
+ eSignalDeliveredMessage,
+ eTraceMessage,
+ eBreakpointMessage,
+ eCrashMessage
+ };
+
+ enum CrashReason
+ {
+ eInvalidCrashReason,
+
+ // SIGSEGV crash reasons.
+ eInvalidAddress,
+ ePrivilegedAddress,
+
+ // SIGILL crash reasons.
+ eIllegalOpcode,
+ eIllegalOperand,
+ eIllegalAddressingMode,
+ eIllegalTrap,
+ ePrivilegedOpcode,
+ ePrivilegedRegister,
+ eCoprocessorError,
+ eInternalStackError,
+
+ // SIGBUS crash reasons,
+ eIllegalAlignment,
+ eIllegalAddress,
+ eHardwareError,
+
+ // SIGFPE crash reasons,
+ eIntegerDivideByZero,
+ eIntegerOverflow,
+ eFloatDivideByZero,
+ eFloatOverflow,
+ eFloatUnderflow,
+ eFloatInexactResult,
+ eFloatInvalidOperation,
+ eFloatSubscriptRange
+ };
+
+ ProcessMessage()
+ : m_tid(LLDB_INVALID_PROCESS_ID),
+ m_kind(eInvalidMessage),
+ m_crash_reason(eInvalidCrashReason),
+ m_status(0),
+ m_addr(0) { }
+
+ Kind GetKind() const { return m_kind; }
+
+ lldb::tid_t GetTID() const { return m_tid; }
+
+ /// Indicates that the thread @p tid is about to exit with status @p status.
+ static ProcessMessage Limbo(lldb::tid_t tid, int status) {
+ return ProcessMessage(tid, eLimboMessage, status);
+ }
+
+ /// Indicates that the thread @p tid had the signal @p signum delivered.
+ static ProcessMessage Signal(lldb::tid_t tid, int signum) {
+ return ProcessMessage(tid, eSignalMessage, signum);
+ }
+
+ /// Indicates that a signal @p signum generated by the debugging process was
+ /// delivered to the thread @p tid.
+ static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) {
+ return ProcessMessage(tid, eSignalDeliveredMessage, signum);
+ }
+
+ /// Indicates that the thread @p tid encountered a trace point.
+ static ProcessMessage Trace(lldb::tid_t tid) {
+ return ProcessMessage(tid, eTraceMessage);
+ }
+
+ /// Indicates that the thread @p tid encountered a break point.
+ static ProcessMessage Break(lldb::tid_t tid) {
+ return ProcessMessage(tid, eBreakpointMessage);
+ }
+
+ /// Indicates that the thread @p tid crashed.
+ static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason,
+ int signo, lldb::addr_t fault_addr) {
+ ProcessMessage message(pid, eCrashMessage, signo, fault_addr);
+ message.m_crash_reason = reason;
+ return message;
+ }
+
+ int GetExitStatus() const {
+ assert(GetKind() == eExitMessage || GetKind() == eLimboMessage);
+ return m_status;
+ }
+
+ int GetSignal() const {
+ assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage ||
+ GetKind() == eSignalDeliveredMessage);
+ return m_status;
+ }
+
+ int GetStopStatus() const {
+ assert(GetKind() == eSignalMessage);
+ return m_status;
+ }
+
+ CrashReason GetCrashReason() const {
+ assert(GetKind() == eCrashMessage);
+ return m_crash_reason;
+ }
+
+ lldb::addr_t GetFaultAddress() const {
+ assert(GetKind() == eCrashMessage);
+ return m_addr;
+ }
+
+ static const char *
+ GetCrashReasonString(CrashReason reason);
+
+ const char *
+ PrintCrashReason() const;
+
+ static const char *
+ PrintCrashReason(CrashReason reason);
+
+ const char *
+ PrintKind() const;
+
+ static const char *
+ PrintKind(Kind);
+
+private:
+ ProcessMessage(lldb::tid_t tid, Kind kind,
+ int status = 0, lldb::addr_t addr = 0)
+ : m_tid(tid),
+ m_kind(kind),
+ m_crash_reason(eInvalidCrashReason),
+ m_status(status),
+ m_addr(addr) { }
+
+ lldb::tid_t m_tid;
+ Kind m_kind : 8;
+ CrashReason m_crash_reason : 8;
+ int m_status;
+ lldb::addr_t m_addr;
+};
+
+#endif // #ifndef liblldb_ProcessMessage_H_
Index: source/Plugins/Process/POSIX/POSIXStopInfo.h
===================================================================
--- source/Plugins/Process/POSIX/POSIXStopInfo.h (revision 0)
+++ source/Plugins/Process/POSIX/POSIXStopInfo.h (revision 0)
@@ -0,0 +1,92 @@
+//===-- POSIXStopInfo.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_POSIXStopInfo_H_
+#define liblldb_POSIXStopInfo_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/StopInfo.h"
+
+#include "POSIXThread.h"
+#include "ProcessMessage.h"
+
+//===----------------------------------------------------------------------===//
+/// @class POSIXStopInfo
+/// @brief Simple base class for all POSIX-specific StopInfo objects.
+///
+class POSIXStopInfo
+ : public lldb_private::StopInfo
+{
+public:
+ POSIXStopInfo(lldb_private::Thread &thread, uint32_t status)
+ : StopInfo(thread, status)
+ { }
+};
+
+//===----------------------------------------------------------------------===//
+/// @class POSIXLimboStopInfo
+/// @brief Represents the stop state of a process ready to exit.
+///
+class POSIXLimboStopInfo
+ : public POSIXStopInfo
+{
+public:
+ POSIXLimboStopInfo(POSIXThread &thread)
+ : POSIXStopInfo(thread, 0)
+ { }
+
+ ~POSIXLimboStopInfo();
+
+ lldb::StopReason
+ GetStopReason() const;
+
+ const char *
+ GetDescription();
+
+ bool
+ ShouldStop(lldb_private::Event *event_ptr);
+
+ bool
+ ShouldNotify(lldb_private::Event *event_ptr);
+};
+
+
+//===----------------------------------------------------------------------===//
+/// @class POSIXCrashStopInfo
+/// @brief Represents the stop state of process that is ready to crash.
+///
+class POSIXCrashStopInfo
+ : public POSIXStopInfo
+{
+public:
+ POSIXCrashStopInfo(POSIXThread &thread, uint32_t status,
+ ProcessMessage::CrashReason reason)
+ : POSIXStopInfo(thread, status),
+ m_crash_reason(reason)
+ { }
+
+ ~POSIXCrashStopInfo();
+
+ lldb::StopReason
+ GetStopReason() const;
+
+ const char *
+ GetDescription();
+
+ ProcessMessage::CrashReason
+ GetCrashReason() const;
+
+private:
+ ProcessMessage::CrashReason m_crash_reason;
+};
+
+#endif
Index: source/Plugins/Process/POSIX/POSIXThread.cpp
===================================================================
--- source/Plugins/Process/POSIX/POSIXThread.cpp (revision 0)
+++ source/Plugins/Process/POSIX/POSIXThread.cpp (revision 0)
@@ -0,0 +1,352 @@
+//===-- POSIXThread.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <errno.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Debugger.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "POSIXStopInfo.h"
+#include "POSIXThread.h"
+#include "ProcessPOSIX.h"
+#include "ProcessPOSIXLog.h"
+#include "ProcessMonitor.h"
+#include "RegisterContext_i386.h"
+#include "RegisterContext_x86_64.h"
+#include "RegisterContextPOSIX.h"
+
+#include "UnwindLLDB.h"
+
+using namespace lldb_private;
+
+
+POSIXThread::POSIXThread(Process &process, lldb::tid_t tid)
+ : Thread(process, tid),
+ m_frame_ap(0)
+{
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("POSIXThread::%s (tid = %i)", __FUNCTION__, tid);
+}
+
+POSIXThread::~POSIXThread()
+{
+ DestroyThread();
+}
+
+ProcessMonitor &
+POSIXThread::GetMonitor()
+{
+ ProcessPOSIX &process = static_cast<ProcessPOSIX&>(GetProcess());
+ return process.GetMonitor();
+}
+
+void
+POSIXThread::RefreshStateAfterStop()
+{
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("POSIXThread::%s ()", __FUNCTION__);
+
+ // Let all threads recover from stopping and do any clean up based
+ // on the previous thread state (if any).
+ ProcessPOSIX &process = static_cast<ProcessPOSIX&>(GetProcess());
+ process.GetThreadList().RefreshStateAfterStop();
+}
+
+const char *
+POSIXThread::GetInfo()
+{
+ return NULL;
+}
+
+lldb::RegisterContextSP
+POSIXThread::GetRegisterContext()
+{
+ if (!m_reg_context_sp)
+ {
+ ArchSpec arch = Host::GetArchitecture();
+
+ switch (arch.GetCore())
+ {
+ default:
+ assert(false && "CPU type not supported!");
+ break;
+
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ m_reg_context_sp.reset(new RegisterContext_i386(*this, 0));
+ break;
+
+ case ArchSpec::eCore_x86_64_x86_64:
+ m_reg_context_sp.reset(new RegisterContext_x86_64(*this, 0));
+ break;
+ }
+ }
+ return m_reg_context_sp;
+}
+
+lldb::RegisterContextSP
+POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
+{
+ lldb::RegisterContextSP reg_ctx_sp;
+ uint32_t concrete_frame_idx = 0;
+
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("POSIXThread::%s ()", __FUNCTION__);
+
+ if (frame)
+ concrete_frame_idx = frame->GetConcreteFrameIndex();
+
+ if (concrete_frame_idx == 0)
+ reg_ctx_sp = GetRegisterContext();
+ else
+ {
+ assert(GetUnwinder());
+ reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
+ }
+
+ return reg_ctx_sp;
+}
+
+lldb::StopInfoSP
+POSIXThread::GetPrivateStopReason()
+{
+ return m_stop_info;
+}
+
+Unwind *
+POSIXThread::GetUnwinder()
+{
+ if (m_unwinder_ap.get() == NULL)
+ m_unwinder_ap.reset(new UnwindLLDB(*this));
+
+ return m_unwinder_ap.get();
+}
+
+bool
+POSIXThread::WillResume(lldb::StateType resume_state)
+{
+ SetResumeState(resume_state);
+
+ ClearStackFrames();
+ if (m_unwinder_ap.get())
+ m_unwinder_ap->Clear();
+
+ return Thread::WillResume(resume_state);
+}
+
+bool
+POSIXThread::Resume()
+{
+ lldb::StateType resume_state = GetResumeState();
+ ProcessMonitor &monitor = GetMonitor();
+ bool status;
+
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("POSIXThread::%s ()", __FUNCTION__);
+
+ switch (resume_state)
+ {
+ default:
+ assert(false && "Unexpected state for resume!");
+ status = false;
+ break;
+
+ case lldb::eStateRunning:
+ SetState(resume_state);
+ status = monitor.Resume(GetID(), GetResumeSignal());
+ break;
+
+ case lldb::eStateStepping:
+ SetState(resume_state);
+ status = monitor.SingleStep(GetID(), GetResumeSignal());
+ break;
+ }
+
+ return status;
+}
+
+void
+POSIXThread::Notify(const ProcessMessage &message)
+{
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf ("POSIXThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind());
+
+ switch (message.GetKind())
+ {
+ default:
+ assert(false && "Unexpected message kind!");
+ break;
+
+ case ProcessMessage::eLimboMessage:
+ LimboNotify(message);
+ break;
+
+ case ProcessMessage::eSignalMessage:
+ SignalNotify(message);
+ break;
+
+ case ProcessMessage::eSignalDeliveredMessage:
+ SignalDeliveredNotify(message);
+ break;
+
+ case ProcessMessage::eTraceMessage:
+ TraceNotify(message);
+ break;
+
+ case ProcessMessage::eBreakpointMessage:
+ BreakNotify(message);
+ break;
+
+ case ProcessMessage::eCrashMessage:
+ CrashNotify(message);
+ break;
+ }
+}
+
+void
+POSIXThread::BreakNotify(const ProcessMessage &message)
+{
+ bool status;
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+
+ assert(GetRegisterContext());
+ status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint();
+ assert(status && "Breakpoint update failed!");
+
+ // With our register state restored, resolve the breakpoint object
+ // corresponding to our current PC.
+ assert(GetRegisterContext());
+ lldb::addr_t pc = GetRegisterContext()->GetPC();
+ if (log)
+ log->Printf ("POSIXThread::%s () PC=0x%8.8llx", __FUNCTION__, pc);
+ lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc));
+ assert(bp_site);
+ lldb::break_id_t bp_id = bp_site->GetID();
+ assert(bp_site && bp_site->ValidForThisThread(this));
+
+
+ m_breakpoint = bp_site;
+ m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);
+}
+
+void
+POSIXThread::TraceNotify(const ProcessMessage &message)
+{
+ m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
+}
+
+void
+POSIXThread::LimboNotify(const ProcessMessage &message)
+{
+ m_stop_info = lldb::StopInfoSP(new POSIXLimboStopInfo(*this));
+}
+
+void
+POSIXThread::SignalNotify(const ProcessMessage &message)
+{
+ int signo = message.GetSignal();
+
+ m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);
+ SetResumeSignal(signo);
+}
+
+void
+POSIXThread::SignalDeliveredNotify(const ProcessMessage &message)
+{
+ int signo = message.GetSignal();
+
+ // Just treat debugger generated signal events like breakpoints for now.
+ m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
+ SetResumeSignal(signo);
+}
+
+void
+POSIXThread::CrashNotify(const ProcessMessage &message)
+{
+ int signo = message.GetSignal();
+
+ assert(message.GetKind() == ProcessMessage::eCrashMessage);
+
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason());
+
+ m_stop_info = lldb::StopInfoSP(new POSIXCrashStopInfo(
+ *this, signo, message.GetCrashReason()));
+ SetResumeSignal(signo);
+}
+
+unsigned
+POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
+{
+ unsigned reg;
+ ArchSpec arch = Host::GetArchitecture();
+
+ switch (arch.GetCore())
+ {
+ default:
+ assert(false && "CPU type not supported!");
+ break;
+
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ reg = RegisterContext_i386::GetRegisterIndexFromOffset(offset);
+ break;
+
+ case ArchSpec::eCore_x86_64_x86_64:
+ reg = RegisterContext_x86_64::GetRegisterIndexFromOffset(offset);
+ break;
+ }
+ return reg;
+}
+
+const char *
+POSIXThread::GetRegisterName(unsigned reg)
+{
+ const char * name;
+ ArchSpec arch = Host::GetArchitecture();
+
+ switch (arch.GetCore())
+ {
+ default:
+ assert(false && "CPU type not supported!");
+ break;
+
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ name = RegisterContext_i386::GetRegisterName(reg);
+ break;
+
+ case ArchSpec::eCore_x86_64_x86_64:
+ name = RegisterContext_x86_64::GetRegisterName(reg);
+ break;
+ }
+ return name;
+}
+
+const char *
+POSIXThread::GetRegisterNameFromOffset(unsigned offset)
+{
+ return GetRegisterName(GetRegisterIndexFromOffset(offset));
+}
+
Index: source/Plugins/Process/POSIX/Makefile
===================================================================
--- source/Plugins/Process/POSIX/Makefile (revision 0)
+++ source/Plugins/Process/POSIX/Makefile (revision 0)
@@ -0,0 +1,28 @@
+##===- source/Plugins/Process/POSIX/Makefile ---------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginProcessPOSIX
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/../../Makefile.config
+
+# Extend the include path so we may locate UnwindLLDB.h
+CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility
+
+ifeq ($(HOST_OS),Linux)
+CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Linux
+endif
+
+ifeq ($(HOST_OS),FreeBSD)
+# Extend the include path so we may locate ProcessMonitor
+CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/FreeBSD
+endif
+
+include $(LLDB_LEVEL)/Makefile
Index: source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
===================================================================
--- source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (revision 0)
+++ source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (revision 0)
@@ -0,0 +1,84 @@
+//===-- ProcessFreeBSD.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessFreeBSD_H_
+#define liblldb_ProcessFreeBSD_H_
+
+// C Includes
+
+// C++ Includes
+#include <queue>
+
+// Other libraries and framework includes
+#include "lldb/Target/Process.h"
+#include "lldb/Target/ThreadList.h"
+#include "ProcessMessage.h"
+#include "ProcessPOSIX.h"
+
+class ProcessMonitor;
+
+class ProcessFreeBSD :
+ public ProcessPOSIX
+{
+
+public:
+ //------------------------------------------------------------------
+ // Static functions.
+ //------------------------------------------------------------------
+ static Process*
+ CreateInstance(lldb_private::Target& target,
+ lldb_private::Listener &listener);
+
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static const char *
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ //------------------------------------------------------------------
+ // Constructors and destructors
+ //------------------------------------------------------------------
+ ProcessFreeBSD(lldb_private::Target& target,
+ lldb_private::Listener &listener);
+
+ virtual uint32_t
+ UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list);
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual const char *
+ GetPluginName();
+
+ virtual const char *
+ GetShortPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+ virtual void
+ GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
+
+ virtual lldb_private::Error
+ ExecutePluginCommand(lldb_private::Args &command,
+ lldb_private::Stream *strm);
+
+ virtual lldb_private::Log *
+ EnablePluginLogging(lldb_private::Stream *strm,
+ lldb_private::Args &command);
+
+};
+
+#endif // liblldb_MacOSXProcess_H_
Index: source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
===================================================================
--- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 0)
+++ source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 0)
@@ -0,0 +1,1558 @@
+//===-- ProcessMonitor.cpp ------------------------------------ -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <errno.h>
+#include <poll.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/ptrace.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/Error.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Utility/PseudoTerminal.h"
+
+
+#include "POSIXThread.h"
+#include "ProcessFreeBSD.h"
+#include "ProcessPOSIXLog.h"
+#include "ProcessMonitor.h"
+
+extern "C" {
+ extern char ** environ;
+ }
+
+using namespace lldb;
+using namespace lldb_private;
+
+// We disable the tracing of ptrace calls for integration builds to
+// avoid the additional indirection and checks.
+#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION
+// Wrapper for ptrace to catch errors and log calls.
+
+const char *
+Get_PT_IO_OP(int op)
+{
+ switch (op) {
+ case PIOD_READ_D: return "READ_D";
+ case PIOD_WRITE_D: return "WRITE_D";
+ case PIOD_READ_I: return "READ_I";
+ case PIOD_WRITE_I: return "WRITE_I";
+ default: return "Unknown op";
+ }
+}
+
+extern long
+PtraceWrapper(int req, ::pid_t pid, void *addr, int data,
+ const char* reqName, const char* file, int line)
+{
+ long int result;
+
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+
+ if (log) {
+ log->Printf("ptrace(%s, %u, %p, %x) called from file %s line %d",
+ reqName, pid, addr, data, file, line);
+ if (req == PT_IO) {
+ struct ptrace_io_desc *pi = (struct ptrace_io_desc *) addr;
+
+ log->Printf("PT_IO: op=%s offs=%zx size=%ld",
+ Get_PT_IO_OP(pi->piod_op), pi->piod_offs, pi->piod_len);
+ }
+ }
+
+ //PtraceDisplayBytes(req, data);
+
+ errno = 0;
+ result = ptrace(req, pid, (caddr_t) addr, data);
+
+ //PtraceDisplayBytes(req, data);
+
+ if (log && (result == -1 || errno != 0))
+ {
+ const char* str;
+ switch (errno)
+ {
+ case ESRCH: str = "ESRCH"; break;
+ case EINVAL: str = "EINVAL"; break;
+ case EBUSY: str = "EBUSY"; break;
+ case EPERM: str = "EPERM"; break;
+ default: str = "<unknown>";
+ }
+ log->Printf("ptrace() failed; errno=%d (%s)", errno, str);
+ }
+
+ if (log) {
+ if (req == PT_GETREGS) {
+ struct reg *r = (struct reg *) addr;
+
+ log->Printf("PT_GETREGS: ip=0x%lx", r->r_rip);
+ log->Printf("PT_GETREGS: sp=0x%lx", r->r_rsp);
+ log->Printf("PT_GETREGS: bp=0x%lx", r->r_rbp);
+ log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax);
+ }
+ }
+
+ return result;
+}
+
+#define PTRACE(req, pid, addr, data) \
+ PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__)
+#else
+#define PTRACE ptrace
+#endif
+
+//------------------------------------------------------------------------------
+// Static implementations of ProcessMonitor::ReadMemory and
+// ProcessMonitor::WriteMemory. This enables mutual recursion between these
+// functions without needed to go thru the thread funnel.
+
+static size_t
+DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf, size_t size,
+ Error &error)
+{
+ struct ptrace_io_desc pi_desc;
+
+ pi_desc.piod_op = PIOD_READ_D;
+ pi_desc.piod_offs = (void *)vm_addr;
+ pi_desc.piod_addr = buf;
+ pi_desc.piod_len = size;
+
+ if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0)
+ error.SetErrorToErrno();
+ return pi_desc.piod_len;
+}
+
+static size_t
+DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, const void *buf,
+ size_t size, Error &error)
+{
+ struct ptrace_io_desc pi_desc;
+
+ pi_desc.piod_op = PIOD_WRITE_D;
+ pi_desc.piod_offs = (void *)vm_addr;
+ pi_desc.piod_addr = (void *)buf;
+ pi_desc.piod_len = size;
+
+ if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0)
+ error.SetErrorToErrno();
+ return pi_desc.piod_len;
+}
+
+// Simple helper function to ensure flags are enabled on the given file
+// descriptor.
+static bool
+EnsureFDFlags(int fd, int flags, Error &error)
+{
+ int status;
+
+ if ((status = fcntl(fd, F_GETFL)) == -1)
+ {
+ error.SetErrorToErrno();
+ return false;
+ }
+
+ if (fcntl(fd, F_SETFL, status | flags) == -1)
+ {
+ error.SetErrorToErrno();
+ return false;
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+/// @class Operation
+/// @brief Represents a ProcessMonitor operation.
+///
+/// Under FreeBSD, it is not possible to ptrace() from any other thread but the
+/// one that spawned or attached to the process from the start. Therefore, when
+/// a ProcessMonitor is asked to deliver or change the state of an inferior
+/// process the operation must be "funneled" to a specific thread to perform the
+/// task. The Operation class provides an abstract base for all services the
+/// ProcessMonitor must perform via the single virtual function Execute, thus
+/// encapsulating the code that needs to run in the privileged context.
+class Operation
+{
+public:
+ virtual void Execute(ProcessMonitor *monitor) = 0;
+};
+
+//------------------------------------------------------------------------------
+/// @class ReadOperation
+/// @brief Implements ProcessMonitor::ReadMemory.
+class ReadOperation : public Operation
+{
+public:
+ ReadOperation(lldb::addr_t addr, void *buff, size_t size,
+ Error &error, size_t &result)
+ : m_addr(addr), m_buff(buff), m_size(size),
+ m_error(error), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::addr_t m_addr;
+ void *m_buff;
+ size_t m_size;
+ Error &m_error;
+ size_t &m_result;
+};
+
+void
+ReadOperation::Execute(ProcessMonitor *monitor)
+{
+ lldb::pid_t pid = monitor->GetPID();
+
+ m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error);
+}
+
+//------------------------------------------------------------------------------
+/// @class ReadOperation
+/// @brief Implements ProcessMonitor::WriteMemory.
+class WriteOperation : public Operation
+{
+public:
+ WriteOperation(lldb::addr_t addr, const void *buff, size_t size,
+ Error &error, size_t &result)
+ : m_addr(addr), m_buff(buff), m_size(size),
+ m_error(error), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::addr_t m_addr;
+ const void *m_buff;
+ size_t m_size;
+ Error &m_error;
+ size_t &m_result;
+};
+
+void
+WriteOperation::Execute(ProcessMonitor *monitor)
+{
+ lldb::pid_t pid = monitor->GetPID();
+
+ m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error);
+}
+
+//------------------------------------------------------------------------------
+/// @class ReadRegOperation
+/// @brief Implements ProcessMonitor::ReadRegisterValue.
+class ReadRegOperation : public Operation
+{
+public:
+ ReadRegOperation(unsigned offset, unsigned size, RegisterValue &value, bool &result)
+ : m_offset(offset), m_size(size), m_value(value), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ unsigned m_offset;
+ unsigned m_size;
+ RegisterValue &m_value;
+ bool &m_result;
+};
+
+void
+ReadRegOperation::Execute(ProcessMonitor *monitor)
+{
+ lldb::pid_t pid = monitor->GetPID();
+ struct reg regs;
+ int rc;
+
+ if ((rc = PTRACE(PT_GETREGS, pid, (caddr_t)®s, 0)) < 0) {
+ m_result = false;
+ } else {
+ if (m_size == sizeof(uintptr_t))
+ m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset);
+ else
+ memcpy(&m_value, (((caddr_t)®s) + m_offset), m_size);
+ m_result = true;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// @class WriteRegOperation
+/// @brief Implements ProcessMonitor::WriteRegisterValue.
+class WriteRegOperation : public Operation
+{
+public:
+ WriteRegOperation(unsigned offset, const RegisterValue &value, bool &result)
+ : m_offset(offset), m_value(value), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ unsigned m_offset;
+ const RegisterValue &m_value;
+ bool &m_result;
+};
+
+void
+WriteRegOperation::Execute(ProcessMonitor *monitor)
+{
+ lldb::pid_t pid = monitor->GetPID();
+ struct reg regs;
+
+ if (PTRACE(PT_GETREGS, pid, (caddr_t)®s, 0) < 0) {
+ m_result = false;
+ return;
+ }
+ *(uintptr_t *)(((caddr_t)®s) + m_offset) = (uintptr_t)m_value.GetAsUInt64();
+ if (PTRACE(PT_SETREGS, pid, (caddr_t)®s, 0) < 0)
+ m_result = false;
+ else
+ m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class ReadGPROperation
+/// @brief Implements ProcessMonitor::ReadGPR.
+class ReadGPROperation : public Operation
+{
+public:
+ ReadGPROperation(void *buf, bool &result)
+ : m_buf(buf), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ void *m_buf;
+ bool &m_result;
+};
+
+void
+ReadGPROperation::Execute(ProcessMonitor *monitor)
+{
+ int rc;
+
+ errno = 0;
+ rc = PTRACE(PT_GETREGS, monitor->GetPID(), (caddr_t)m_buf, 0);
+ if (errno != 0)
+ m_result = false;
+ else
+ m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class ReadFPROperation
+/// @brief Implements ProcessMonitor::ReadFPR.
+class ReadFPROperation : public Operation
+{
+public:
+ ReadFPROperation(void *buf, bool &result)
+ : m_buf(buf), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ void *m_buf;
+ bool &m_result;
+};
+
+void
+ReadFPROperation::Execute(ProcessMonitor *monitor)
+{
+ if (PTRACE(PT_GETFPREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0)
+ m_result = false;
+ else
+ m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class WriteGPROperation
+/// @brief Implements ProcessMonitor::WriteGPR.
+class WriteGPROperation : public Operation
+{
+public:
+ WriteGPROperation(void *buf, bool &result)
+ : m_buf(buf), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ void *m_buf;
+ bool &m_result;
+};
+
+void
+WriteGPROperation::Execute(ProcessMonitor *monitor)
+{
+ if (PTRACE(PT_SETREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0)
+ m_result = false;
+ else
+ m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class WriteFPROperation
+/// @brief Implements ProcessMonitor::WriteFPR.
+class WriteFPROperation : public Operation
+{
+public:
+ WriteFPROperation(void *buf, bool &result)
+ : m_buf(buf), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ void *m_buf;
+ bool &m_result;
+};
+
+void
+WriteFPROperation::Execute(ProcessMonitor *monitor)
+{
+ if (PTRACE(PT_SETFPREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0)
+ m_result = false;
+ else
+ m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class ResumeOperation
+/// @brief Implements ProcessMonitor::Resume.
+class ResumeOperation : public Operation
+{
+public:
+ ResumeOperation(lldb::tid_t tid, uint32_t signo, bool &result) :
+ m_tid(tid), m_signo(signo), m_result(result) { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::tid_t m_tid;
+ uint32_t m_signo;
+ bool &m_result;
+};
+
+void
+ResumeOperation::Execute(ProcessMonitor *monitor)
+{
+ int data = 0;
+
+ if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
+ data = m_signo;
+
+ if (PTRACE(PT_CONTINUE, m_tid, (caddr_t)1, data))
+ m_result = false;
+ else
+ m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class ResumeOperation
+/// @brief Implements ProcessMonitor::SingleStep.
+class SingleStepOperation : public Operation
+{
+public:
+ SingleStepOperation(lldb::tid_t tid, uint32_t signo, bool &result)
+ : m_tid(tid), m_signo(signo), m_result(result) { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::tid_t m_tid;
+ uint32_t m_signo;
+ bool &m_result;
+};
+
+void
+SingleStepOperation::Execute(ProcessMonitor *monitor)
+{
+ int data = 0;
+
+ if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
+ data = m_signo;
+
+ if (PTRACE(PT_STEP, m_tid, NULL, data))
+ m_result = false;
+ else
+ m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class SiginfoOperation
+/// @brief Implements ProcessMonitor::GetSignalInfo.
+class SiginfoOperation : public Operation
+{
+public:
+ SiginfoOperation(lldb::tid_t tid, void *info, bool &result)
+ : m_tid(tid), m_info(info), m_result(result) { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::tid_t m_tid;
+ void *m_info;
+ bool &m_result;
+};
+
+void
+SiginfoOperation::Execute(ProcessMonitor *monitor)
+{
+ struct ptrace_lwpinfo plwp;
+
+ if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp)))
+ m_result = false;
+ else {
+ memcpy(m_info, &plwp.pl_siginfo, sizeof(siginfo_t));
+ m_result = true;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// @class EventMessageOperation
+/// @brief Implements ProcessMonitor::GetEventMessage.
+class EventMessageOperation : public Operation
+{
+public:
+ EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result)
+ : m_tid(tid), m_message(message), m_result(result) { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::tid_t m_tid;
+ unsigned long *m_message;
+ bool &m_result;
+};
+
+void
+EventMessageOperation::Execute(ProcessMonitor *monitor)
+{
+ struct ptrace_lwpinfo plwp;
+
+ if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp)))
+ m_result = false;
+ else {
+ if (plwp.pl_flags & PL_FLAG_FORKED) {
+ m_message = (unsigned long *)plwp.pl_child_pid;
+ m_result = true;
+ } else
+ m_result = false;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// @class KillOperation
+/// @brief Implements ProcessMonitor::BringProcessIntoLimbo.
+class KillOperation : public Operation
+{
+public:
+ KillOperation(bool &result) : m_result(result) { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ bool &m_result;
+};
+
+void
+KillOperation::Execute(ProcessMonitor *monitor)
+{
+ lldb::pid_t pid = monitor->GetPID();
+
+ if (PTRACE(PT_KILL, pid, NULL, 0))
+ m_result = false;
+ else
+ m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class KillOperation
+/// @brief Implements ProcessMonitor::BringProcessIntoLimbo.
+class DetachOperation : public Operation
+{
+public:
+ DetachOperation(Error &result) : m_error(result) { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ Error &m_error;
+};
+
+void
+DetachOperation::Execute(ProcessMonitor *monitor)
+{
+ lldb::pid_t pid = monitor->GetPID();
+
+ if (PTRACE(PT_DETACH, pid, NULL, 0) < 0)
+ m_error.SetErrorToErrno();
+
+}
+
+ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor)
+ : m_monitor(monitor)
+{
+ sem_init(&m_semaphore, 0, 0);
+}
+
+ProcessMonitor::OperationArgs::~OperationArgs()
+{
+ sem_destroy(&m_semaphore);
+}
+
+ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,
+ lldb_private::Module *module,
+ char const **argv,
+ char const **envp,
+ const char *stdin_path,
+ const char *stdout_path,
+ const char *stderr_path)
+ : OperationArgs(monitor),
+ m_module(module),
+ m_argv(argv),
+ m_envp(envp),
+ m_stdin_path(stdin_path),
+ m_stdout_path(stdout_path),
+ m_stderr_path(stderr_path) { }
+
+ProcessMonitor::LaunchArgs::~LaunchArgs()
+{ }
+
+ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor,
+ lldb::pid_t pid)
+ : OperationArgs(monitor), m_pid(pid) { }
+
+ProcessMonitor::AttachArgs::~AttachArgs()
+{ }
+
+//------------------------------------------------------------------------------
+/// The basic design of the ProcessMonitor is built around two threads.
+///
+/// One thread (@see SignalThread) simply blocks on a call to waitpid() looking
+/// for changes in the debugee state. When a change is detected a
+/// ProcessMessage is sent to the associated ProcessFreeBSD instance. This thread
+/// "drives" state changes in the debugger.
+///
+/// The second thread (@see OperationThread) is responsible for two things 1)
+/// launching or attaching to the inferior process, and then 2) servicing
+/// operations such as register reads/writes, stepping, etc. See the comments
+/// on the Operation class for more info as to why this is needed.
+ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
+ Module *module,
+ const char *argv[],
+ const char *envp[],
+ const char *stdin_path,
+ const char *stdout_path,
+ const char *stderr_path,
+ lldb_private::Error &error)
+ : m_process(static_cast<ProcessFreeBSD *>(process)),
+ m_operation_thread(LLDB_INVALID_HOST_THREAD),
+ m_monitor_thread(LLDB_INVALID_HOST_THREAD),
+ m_pid(LLDB_INVALID_PROCESS_ID),
+ m_server_mutex(Mutex::eMutexTypeRecursive),
+ m_terminal_fd(-1),
+ m_client_fd(-1),
+ m_server_fd(-1)
+{
+ std::auto_ptr<LaunchArgs> args;
+
+ args.reset(new LaunchArgs(this, module, argv, envp,
+ stdin_path, stdout_path, stderr_path));
+
+
+ // Server/client descriptors.
+ if (!EnableIPC())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Monitor failed to initialize.");
+ }
+
+ StartLaunchOpThread(args.get(), error);
+ if (!error.Success())
+ return;
+
+WAIT_AGAIN:
+ // Wait for the operation thread to initialize.
+ if (sem_wait(&args->m_semaphore))
+ {
+ if (errno == EINTR)
+ goto WAIT_AGAIN;
+ else
+ {
+ error.SetErrorToErrno();
+ return;
+ }
+ }
+
+ // Check that the launch was a success.
+ if (!args->m_error.Success())
+ {
+ StopLaunchOpThread();
+ error = args->m_error;
+ return;
+ }
+
+ // Finally, start monitoring the child process for change in state.
+ m_monitor_thread = Host::StartMonitoringChildProcess(
+ ProcessMonitor::MonitorCallback, this, GetPID(), true);
+ if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Process launch failed.");
+ return;
+ }
+}
+
+ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
+ lldb::pid_t pid,
+ lldb_private::Error &error)
+ : m_process(static_cast<ProcessFreeBSD *>(process)),
+ m_operation_thread(LLDB_INVALID_HOST_THREAD),
+ m_monitor_thread(LLDB_INVALID_HOST_THREAD),
+ m_pid(pid),
+ m_server_mutex(Mutex::eMutexTypeRecursive),
+ m_terminal_fd(-1),
+ m_client_fd(-1),
+ m_server_fd(-1)
+{
+ std::auto_ptr<AttachArgs> args;
+
+ args.reset(new AttachArgs(this, pid));
+
+ // Server/client descriptors.
+ if (!EnableIPC())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Monitor failed to initialize.");
+ }
+
+ StartAttachOpThread(args.get(), error);
+ if (!error.Success())
+ return;
+
+WAIT_AGAIN:
+ // Wait for the operation thread to initialize.
+ if (sem_wait(&args->m_semaphore))
+ {
+ if (errno == EINTR)
+ goto WAIT_AGAIN;
+ else
+ {
+ error.SetErrorToErrno();
+ return;
+ }
+ }
+
+ // Check that the launch was a success.
+ if (!args->m_error.Success())
+ {
+ StopAttachOpThread();
+ error = args->m_error;
+ return;
+ }
+
+ // Finally, start monitoring the child process for change in state.
+ m_monitor_thread = Host::StartMonitoringChildProcess(
+ ProcessMonitor::MonitorCallback, this, GetPID(), true);
+ if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Process attach failed.");
+ return;
+ }
+}
+
+ProcessMonitor::~ProcessMonitor()
+{
+ StopMonitor();
+}
+
+//------------------------------------------------------------------------------
+// Thread setup and tear down.
+void
+ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error)
+{
+ static const char *g_thread_name = "lldb.process.freebsd.operation";
+
+ if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
+ return;
+
+ m_operation_thread =
+ Host::ThreadCreate(g_thread_name, LaunchOpThread, args, &error);
+}
+
+void
+ProcessMonitor::StopLaunchOpThread()
+{
+ lldb::thread_result_t result;
+
+ if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
+ return;
+
+ Host::ThreadCancel(m_operation_thread, NULL);
+ Host::ThreadJoin(m_operation_thread, &result, NULL);
+}
+
+void *
+ProcessMonitor::LaunchOpThread(void *arg)
+{
+ LaunchArgs *args = static_cast<LaunchArgs*>(arg);
+
+ if (!Launch(args)) {
+ sem_post(&args->m_semaphore);
+ return NULL;
+ }
+
+ ServeOperation(args);
+ return NULL;
+}
+
+bool
+ProcessMonitor::Launch(LaunchArgs *args)
+{
+ ProcessMonitor *monitor = args->m_monitor;
+ ProcessFreeBSD &process = monitor->GetProcess();
+ const char **argv = args->m_argv;
+ const char **envp = args->m_envp;
+ const char *stdin_path = args->m_stdin_path;
+ const char *stdout_path = args->m_stdout_path;
+ const char *stderr_path = args->m_stderr_path;
+ lldb::pid_t pid;
+
+ lldb::ThreadSP inferior;
+
+ // Propagate the environment if one is not supplied.
+ if (envp == NULL || envp[0] == NULL)
+ envp = const_cast<const char **>(environ);
+
+ // Recognized child exit status codes.
+ enum {
+ ePtraceFailed = 1,
+ eDupStdinFailed,
+ eDupStdoutFailed,
+ eDupStderrFailed,
+ eExecFailed
+ };
+
+ pid = fork();
+
+ // Child process.
+ if (pid == 0)
+ {
+ // Trace this process.
+ if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0)
+ exit(ePtraceFailed);
+
+ // Do not inherit setgid powers.
+ setgid(getgid());
+
+ // Let us have our own process group.
+ setpgid(0, 0);
+
+ // Dup file descriptors if needed.
+ //
+ // FIXME: If two or more of the paths are the same we needlessly open
+ // the same file multiple times.
+ if (stdin_path != NULL && stdin_path[0])
+ if (!DupDescriptor(stdin_path, STDIN_FILENO, O_RDONLY))
+ exit(eDupStdinFailed);
+
+ if (stdout_path != NULL && stdout_path[0])
+ if (!DupDescriptor(stdout_path, STDOUT_FILENO, O_WRONLY | O_CREAT))
+ exit(eDupStdoutFailed);
+
+ if (stderr_path != NULL && stderr_path[0])
+ if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT))
+ exit(eDupStderrFailed);
+
+ // Execute. We should never return.
+ execve(argv[0],
+ const_cast<char *const *>(argv),
+ const_cast<char *const *>(envp));
+ exit(eExecFailed);
+ }
+
+ // Wait for the child process to to trap on its call to execve.
+ ::pid_t wpid;
+ int status;
+ if ((wpid = waitpid(pid, &status, 0)) < 0)
+ {
+ args->m_error.SetErrorToErrno();
+ goto FINISH;
+ }
+ else if (WIFEXITED(status))
+ {
+ // open, dup or execve likely failed for some reason.
+ args->m_error.SetErrorToGenericError();
+ switch (WEXITSTATUS(status))
+ {
+ case ePtraceFailed:
+ args->m_error.SetErrorString("Child ptrace failed.");
+ break;
+ case eDupStdinFailed:
+ args->m_error.SetErrorString("Child open stdin failed.");
+ break;
+ case eDupStdoutFailed:
+ args->m_error.SetErrorString("Child open stdout failed.");
+ break;
+ case eDupStderrFailed:
+ args->m_error.SetErrorString("Child open stderr failed.");
+ break;
+ case eExecFailed:
+ args->m_error.SetErrorString("Child exec failed.");
+ break;
+ default:
+ args->m_error.SetErrorString("Child returned unknown exit status.");
+ break;
+ }
+ goto FINISH;
+ }
+ assert(WIFSTOPPED(status) && wpid == pid &&
+ "Could not sync with inferior process.");
+
+#ifdef notyet
+ // Have the child raise an event on exit. This is used to keep the child in
+ // limbo until it is destroyed.
+ if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEEXIT) < 0)
+ {
+ args->m_error.SetErrorToErrno();
+ goto FINISH;
+ }
+#endif
+ // XXX - Release the master terminal descriptor and pass it off to the
+ // XXX - ProcessMonitor instance. Similarly stash the inferior pid.
+ // For now just use stdin fd
+ monitor->m_terminal_fd = STDIN_FILENO;
+ monitor->m_pid = pid;
+
+ // Set the terminal fd to be in non blocking mode (it simplifies the
+ // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking
+ // descriptor to read from).
+ if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error))
+ goto FINISH;
+
+ // Update the process thread list with this new thread.
+ inferior.reset(new POSIXThread(process, pid));
+ process.GetThreadList().AddThread(inferior);
+
+ // Let our process instance know the thread has stopped.
+ process.SendMessage(ProcessMessage::Trace(pid));
+
+FINISH:
+ return args->m_error.Success();
+}
+
+bool
+ProcessMonitor::EnableIPC()
+{
+ int fd[2];
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd))
+ return false;
+
+ m_client_fd = fd[0];
+ m_server_fd = fd[1];
+ return true;
+}
+
+void
+ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error)
+{
+ static const char *g_thread_name = "lldb.process.freebsd.operation";
+
+ if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
+ return;
+
+ m_operation_thread =
+ Host::ThreadCreate(g_thread_name, AttachOpThread, args, &error);
+}
+
+void
+ProcessMonitor::StopAttachOpThread()
+{
+ assert(!"Not implemented yet!!!");
+}
+
+void *
+ProcessMonitor::AttachOpThread(void *arg)
+{
+ AttachArgs *args = static_cast<AttachArgs*>(arg);
+
+ if (!Attach(args))
+ return NULL;
+
+ ServeOperation(args);
+ return NULL;
+}
+
+bool
+ProcessMonitor::Attach(AttachArgs *args)
+{
+ lldb::pid_t pid = args->m_pid;
+
+ ProcessMonitor *monitor = args->m_monitor;
+ ProcessFreeBSD &process = monitor->GetProcess();
+ ThreadList &tl = process.GetThreadList();
+ lldb::ThreadSP inferior;
+
+ if (pid <= 1)
+ {
+ args->m_error.SetErrorToGenericError();
+ args->m_error.SetErrorString("Attaching to process 1 is not allowed.");
+ goto FINISH;
+ }
+
+ // Attach to the requested process.
+ if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0)
+ {
+ args->m_error.SetErrorToErrno();
+ goto FINISH;
+ }
+
+ int status;
+ if ((status = waitpid(pid, NULL, 0)) < 0)
+ {
+ args->m_error.SetErrorToErrno();
+ goto FINISH;
+ }
+
+ // Update the process thread list with the attached thread.
+ inferior.reset(new POSIXThread(process, pid));
+ tl.AddThread(inferior);
+
+ // Let our process instance know the thread has stopped.
+ process.SendMessage(ProcessMessage::Trace(pid));
+
+ FINISH:
+ return args->m_error.Success();
+}
+
+bool
+ProcessMonitor::MonitorCallback(void *callback_baton,
+ lldb::pid_t pid,
+ bool exited,
+ int signal,
+ int status)
+{
+ ProcessMessage message;
+ ProcessMonitor *monitor = static_cast<ProcessMonitor*>(callback_baton);
+ ProcessFreeBSD *process = monitor->m_process;
+ bool stop_monitoring;
+ siginfo_t info;
+
+ if (!monitor->GetSignalInfo(pid, &info))
+ stop_monitoring = true; // pid is gone. Bail.
+ else {
+ switch (info.si_signo)
+ {
+ case SIGTRAP:
+ message = MonitorSIGTRAP(monitor, &info, pid);
+ break;
+
+ default:
+ message = MonitorSignal(monitor, &info, pid);
+ break;
+ }
+
+ process->SendMessage(message);
+ stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage;
+ }
+
+ return stop_monitoring;
+}
+
+ProcessMessage
+ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
+ const siginfo_t *info, lldb::pid_t pid)
+{
+ ProcessMessage message;
+
+ assert(info->si_signo == SIGTRAP && "Unexpected child signal!");
+
+ switch (info->si_code)
+ {
+ default:
+ assert(false && "Unexpected SIGTRAP code!");
+ break;
+
+ case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */):
+ {
+ // The inferior process is about to exit. Maintain the process in a
+ // state of "limbo" until we are explicitly commanded to detach,
+ // destroy, resume, etc.
+ unsigned long data = 0;
+ if (!monitor->GetEventMessage(pid, &data))
+ data = -1;
+ message = ProcessMessage::Limbo(pid, (data >> 8));
+ break;
+ }
+
+ case 0:
+ case TRAP_TRACE:
+ message = ProcessMessage::Trace(pid);
+ break;
+
+ case SI_KERNEL:
+ case TRAP_BRKPT:
+ message = ProcessMessage::Break(pid);
+ break;
+ }
+
+ return message;
+}
+
+ProcessMessage
+ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
+ const siginfo_t *info, lldb::pid_t pid)
+{
+ ProcessMessage message;
+ int signo = info->si_signo;
+
+ // POSIX says that process behaviour is undefined after it ignores a SIGFPE,
+ // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a
+ // kill(2) or raise(3). Similarly for tgkill(2) on FreeBSD.
+ //
+ // IOW, user generated signals never generate what we consider to be a
+ // "crash".
+ //
+ // Similarly, ACK signals generated by this monitor.
+ if (info->si_code == SI_USER)
+ {
+ if (info->si_pid == getpid())
+ return ProcessMessage::SignalDelivered(pid, signo);
+ else
+ return ProcessMessage::Signal(pid, signo);
+ }
+
+ if (signo == SIGSEGV) {
+ lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
+ ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info);
+ return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+ }
+
+ if (signo == SIGILL) {
+ lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
+ ProcessMessage::CrashReason reason = GetCrashReasonForSIGILL(info);
+ return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+ }
+
+ if (signo == SIGFPE) {
+ lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
+ ProcessMessage::CrashReason reason = GetCrashReasonForSIGFPE(info);
+ return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+ }
+
+ if (signo == SIGBUS) {
+ lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
+ ProcessMessage::CrashReason reason = GetCrashReasonForSIGBUS(info);
+ return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+ }
+
+ // Everything else is "normal" and does not require any special action on
+ // our part.
+ return ProcessMessage::Signal(pid, signo);
+}
+
+ProcessMessage::CrashReason
+ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info)
+{
+ ProcessMessage::CrashReason reason;
+ assert(info->si_signo == SIGSEGV);
+
+ reason = ProcessMessage::eInvalidCrashReason;
+
+ switch (info->si_code)
+ {
+ default:
+ assert(false && "unexpected si_code for SIGSEGV");
+ break;
+ case SEGV_MAPERR:
+ reason = ProcessMessage::eInvalidAddress;
+ break;
+ case SEGV_ACCERR:
+ reason = ProcessMessage::ePrivilegedAddress;
+ break;
+ }
+
+ return reason;
+}
+
+ProcessMessage::CrashReason
+ProcessMonitor::GetCrashReasonForSIGILL(const siginfo_t *info)
+{
+ ProcessMessage::CrashReason reason;
+ assert(info->si_signo == SIGILL);
+
+ reason = ProcessMessage::eInvalidCrashReason;
+
+ switch (info->si_code)
+ {
+ default:
+ assert(false && "unexpected si_code for SIGILL");
+ break;
+ case ILL_ILLOPC:
+ reason = ProcessMessage::eIllegalOpcode;
+ break;
+ case ILL_ILLOPN:
+ reason = ProcessMessage::eIllegalOperand;
+ break;
+ case ILL_ILLADR:
+ reason = ProcessMessage::eIllegalAddressingMode;
+ break;
+ case ILL_ILLTRP:
+ reason = ProcessMessage::eIllegalTrap;
+ break;
+ case ILL_PRVOPC:
+ reason = ProcessMessage::ePrivilegedOpcode;
+ break;
+ case ILL_PRVREG:
+ reason = ProcessMessage::ePrivilegedRegister;
+ break;
+ case ILL_COPROC:
+ reason = ProcessMessage::eCoprocessorError;
+ break;
+ case ILL_BADSTK:
+ reason = ProcessMessage::eInternalStackError;
+ break;
+ }
+
+ return reason;
+}
+
+ProcessMessage::CrashReason
+ProcessMonitor::GetCrashReasonForSIGFPE(const siginfo_t *info)
+{
+ ProcessMessage::CrashReason reason;
+ assert(info->si_signo == SIGFPE);
+
+ reason = ProcessMessage::eInvalidCrashReason;
+
+ switch (info->si_code)
+ {
+ default:
+ assert(false && "unexpected si_code for SIGFPE");
+ break;
+ case FPE_INTDIV:
+ reason = ProcessMessage::eIntegerDivideByZero;
+ break;
+ case FPE_INTOVF:
+ reason = ProcessMessage::eIntegerOverflow;
+ break;
+ case FPE_FLTDIV:
+ reason = ProcessMessage::eFloatDivideByZero;
+ break;
+ case FPE_FLTOVF:
+ reason = ProcessMessage::eFloatOverflow;
+ break;
+ case FPE_FLTUND:
+ reason = ProcessMessage::eFloatUnderflow;
+ break;
+ case FPE_FLTRES:
+ reason = ProcessMessage::eFloatInexactResult;
+ break;
+ case FPE_FLTINV:
+ reason = ProcessMessage::eFloatInvalidOperation;
+ break;
+ case FPE_FLTSUB:
+ reason = ProcessMessage::eFloatSubscriptRange;
+ break;
+ }
+
+ return reason;
+}
+
+ProcessMessage::CrashReason
+ProcessMonitor::GetCrashReasonForSIGBUS(const siginfo_t *info)
+{
+ ProcessMessage::CrashReason reason;
+ assert(info->si_signo == SIGBUS);
+
+ reason = ProcessMessage::eInvalidCrashReason;
+
+ switch (info->si_code)
+ {
+ default:
+ assert(false && "unexpected si_code for SIGBUS");
+ break;
+ case BUS_ADRALN:
+ reason = ProcessMessage::eIllegalAlignment;
+ break;
+ case BUS_ADRERR:
+ reason = ProcessMessage::eIllegalAddress;
+ break;
+ case BUS_OBJERR:
+ reason = ProcessMessage::eHardwareError;
+ break;
+ }
+
+ return reason;
+}
+
+void
+ProcessMonitor::ServeOperation(OperationArgs *args)
+{
+ int status;
+ pollfd fdset;
+
+ ProcessMonitor *monitor = args->m_monitor;
+
+ fdset.fd = monitor->m_server_fd;
+ fdset.events = POLLIN | POLLPRI;
+ fdset.revents = 0;
+
+ // We are finised with the arguments and are ready to go. Sync with the
+ // parent thread and start serving operations on the inferior.
+ sem_post(&args->m_semaphore);
+
+ for (;;)
+ {
+ if ((status = poll(&fdset, 1, -1)) < 0)
+ {
+ switch (errno)
+ {
+ default:
+ assert(false && "Unexpected poll() failure!");
+ continue;
+
+ case EINTR: continue; // Just poll again.
+ case EBADF: return; // Connection terminated.
+ }
+ }
+
+ assert(status == 1 && "Too many descriptors!");
+
+ if (fdset.revents & POLLIN)
+ {
+ Operation *op = NULL;
+
+ READ_AGAIN:
+ if ((status = read(fdset.fd, &op, sizeof(op))) < 0)
+ {
+ // There is only one acceptable failure.
+ assert(errno == EINTR);
+ goto READ_AGAIN;
+ }
+
+ assert(status == sizeof(op));
+ op->Execute(monitor);
+ write(fdset.fd, &op, sizeof(op));
+ }
+ }
+}
+
+void
+ProcessMonitor::DoOperation(Operation *op)
+{
+ int status;
+ Operation *ack = NULL;
+ Mutex::Locker lock(m_server_mutex);
+
+ // FIXME: Do proper error checking here.
+ write(m_client_fd, &op, sizeof(op));
+
+READ_AGAIN:
+ if ((status = read(m_client_fd, &ack, sizeof(ack))) < 0)
+ {
+ // If interrupted by a signal handler try again. Otherwise the monitor
+ // thread probably died and we have a stale file descriptor -- abort the
+ // operation.
+ if (errno == EINTR)
+ goto READ_AGAIN;
+ return;
+ }
+
+ assert(status == sizeof(ack));
+ assert(ack == op && "Invalid monitor thread response!");
+}
+
+size_t
+ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
+ Error &error)
+{
+ size_t result;
+ ReadOperation op(vm_addr, buf, size, error, result);
+ DoOperation(&op);
+ return result;
+}
+
+size_t
+ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
+ lldb_private::Error &error)
+{
+ size_t result;
+ WriteOperation op(vm_addr, buf, size, error, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value)
+{
+ bool result;
+ ReadRegOperation op(offset, size, value, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::WriteRegisterValue(unsigned offset, const RegisterValue &value)
+{
+ bool result;
+ WriteRegOperation op(offset, value, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::ReadGPR(void *buf)
+{
+ bool result;
+ ReadGPROperation op(buf, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::ReadFPR(void *buf)
+{
+ bool result;
+ ReadFPROperation op(buf, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::WriteGPR(void *buf)
+{
+ bool result;
+ WriteGPROperation op(buf, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::WriteFPR(void *buf)
+{
+ bool result;
+ WriteFPROperation op(buf, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo)
+{
+ bool result;
+ ResumeOperation op(tid, signo, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::SingleStep(lldb::tid_t tid, uint32_t signo)
+{
+ bool result;
+ SingleStepOperation op(tid, signo, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::BringProcessIntoLimbo()
+{
+ bool result;
+ KillOperation op(result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo)
+{
+ bool result;
+ SiginfoOperation op(tid, siginfo, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message)
+{
+ bool result;
+ EventMessageOperation op(tid, message, result);
+ DoOperation(&op);
+ return result;
+}
+
+Error
+ProcessMonitor::Detach()
+{
+ Error result;
+ DetachOperation op(result);
+ DoOperation(&op);
+ StopMonitor();
+ return result;
+}
+
+bool
+ProcessMonitor::DupDescriptor(const char *path, int fd, int flags)
+{
+ int target_fd = open(path, flags, 0666);
+
+ if (target_fd == -1)
+ return false;
+
+ return (dup2(target_fd, fd) == -1) ? false : true;
+}
+
+void
+ProcessMonitor::StopMonitoringChildProcess()
+{
+ lldb::thread_result_t thread_result;
+
+ if (IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))
+ {
+ Host::ThreadCancel(m_monitor_thread, NULL);
+ Host::ThreadJoin(m_monitor_thread, &thread_result, NULL);
+ m_monitor_thread = LLDB_INVALID_HOST_THREAD;
+ }
+}
+
+void
+ProcessMonitor::StopMonitor()
+{
+ StopMonitoringChildProcess();
+ StopLaunchOpThread();
+ CloseFD(m_terminal_fd);
+ CloseFD(m_client_fd);
+ CloseFD(m_server_fd);
+}
+
+void
+ProcessMonitor::CloseFD(int &fd)
+{
+ if (fd != -1)
+ {
+ close(fd);
+ fd = -1;
+ }
+}
Index: source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h
===================================================================
--- source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (revision 0)
+++ source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (revision 0)
@@ -0,0 +1,43 @@
+//===-- RegisterContextFreeBSD_x86_64.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_
+#define liblldb_RegisterContextFreeBSD_x86_64_H_
+
+ typedef struct _GPR
+ {
+ uint64_t r15;
+ uint64_t r14;
+ uint64_t r13;
+ uint64_t r12;
+ uint64_t r11;
+ uint64_t r10;
+ uint64_t r9;
+ uint64_t r8;
+ uint64_t rdi;
+ uint64_t rsi;
+ uint64_t rbp;
+ uint64_t rbx;
+ uint64_t rdx;
+ uint64_t rcx;
+ uint64_t rax;
+ uint32_t trapno;
+ uint16_t fs;
+ uint16_t gs;
+ uint32_t err;
+ uint16_t es;
+ uint16_t ds;
+ uint64_t rip;
+ uint64_t cs;
+ uint64_t rflags;
+ uint64_t rsp;
+ uint64_t ss;
+ } GPR;
+
+#endif
Index: source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
===================================================================
--- source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (revision 0)
+++ source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (revision 0)
@@ -0,0 +1,136 @@
+//===-- ProcessFreeBSD.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <errno.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Target.h"
+
+#include "ProcessFreeBSD.h"
+#include "ProcessPOSIXLog.h"
+#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
+#include "ProcessMonitor.h"
+#include "POSIXThread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------------------
+// Static functions.
+
+Process*
+ProcessFreeBSD::CreateInstance(Target& target, Listener &listener)
+{
+ return new ProcessFreeBSD(target, listener);
+}
+
+void
+ProcessFreeBSD::Initialize()
+{
+ static bool g_initialized = false;
+
+ if (!g_initialized)
+ {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ CreateInstance);
+ Log::Callbacks log_callbacks = {
+ ProcessPOSIXLog::DisableLog,
+ ProcessPOSIXLog::EnableLog,
+ ProcessPOSIXLog::ListLogCategories
+ };
+
+ Log::RegisterLogChannel (ProcessFreeBSD::GetPluginNameStatic(), log_callbacks);
+ ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic());
+ g_initialized = true;
+ }
+}
+
+const char *
+ProcessFreeBSD::GetPluginNameStatic()
+{
+ return "freebsd";
+}
+
+const char *
+ProcessFreeBSD::GetPluginDescriptionStatic()
+{
+ return "Process plugin for FreeBSD";
+}
+
+//------------------------------------------------------------------------------
+// ProcessInterface protocol.
+
+const char *
+ProcessFreeBSD::GetPluginName()
+{
+ return "process.freebsd";
+}
+
+const char *
+ProcessFreeBSD::GetShortPluginName()
+{
+ return "process.freebsd";
+}
+
+uint32_t
+ProcessFreeBSD::GetPluginVersion()
+{
+ return 1;
+}
+
+void
+ProcessFreeBSD::GetPluginCommandHelp(const char *command, Stream *strm)
+{
+}
+
+Error
+ProcessFreeBSD::ExecutePluginCommand(Args &command, Stream *strm)
+{
+ return Error(1, eErrorTypeGeneric);
+}
+
+Log *
+ProcessFreeBSD::EnablePluginLogging(Stream *strm, Args &command)
+{
+ return NULL;
+}
+
+//------------------------------------------------------------------------------
+// Constructors and destructors.
+
+ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener)
+ : ProcessPOSIX(target, listener)
+{
+ // FIXME: Putting this code in the ctor and saving the byte order in a
+ // member variable is a hack to avoid const qual issues in GetByteOrder.
+ ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();
+ m_byte_order = obj_file->GetByteOrder();
+}
+
+void
+ProcessFreeBSD::Terminate()
+{
+}
+
+uint32_t
+ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
+{
+ // XXX haxx
+ new_thread_list = old_thread_list;
+
+ return 0;
+}
Index: source/Plugins/Process/FreeBSD/ProcessMonitor.h
===================================================================
--- source/Plugins/Process/FreeBSD/ProcessMonitor.h (revision 0)
+++ source/Plugins/Process/FreeBSD/ProcessMonitor.h (revision 0)
@@ -0,0 +1,292 @@
+//===-- ProcessMonitor.h -------------------------------------- -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessMonitor_H_
+#define liblldb_ProcessMonitor_H_
+
+// C Includes
+#include <semaphore.h>
+#include <signal.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/lldb-types.h"
+#include "lldb/Host/Mutex.h"
+
+namespace lldb_private
+{
+class Error;
+class Module;
+class Scalar;
+} // End lldb_private namespace.
+
+class ProcessFreeBSD;
+class Operation;
+
+/// @class ProcessMonitor
+/// @brief Manages communication with the inferior (debugee) process.
+///
+/// Upon construction, this class prepares and launches an inferior process for
+/// debugging.
+///
+/// Changes in the inferior process state are propagated to the associated
+/// ProcessFreeBSD instance by calling ProcessFreeBSD::SendMessage with the
+/// appropriate ProcessMessage events.
+///
+/// A purposely minimal set of operations are provided to interrogate and change
+/// the inferior process state.
+class ProcessMonitor
+{
+public:
+
+ /// Launches an inferior process ready for debugging. Forms the
+ /// implementation of Process::DoLaunch.
+ ProcessMonitor(ProcessPOSIX *process,
+ lldb_private::Module *module,
+ char const *argv[],
+ char const *envp[],
+ const char *stdin_path,
+ const char *stdout_path,
+ const char *stderr_path,
+ lldb_private::Error &error);
+
+ ProcessMonitor(ProcessPOSIX *process,
+ lldb::pid_t pid,
+ lldb_private::Error &error);
+
+ ~ProcessMonitor();
+
+ /// Provides the process number of debugee.
+ lldb::pid_t
+ GetPID() const { return m_pid; }
+
+ /// Returns the process associated with this ProcessMonitor.
+ ProcessFreeBSD &
+ GetProcess() { return *m_process; }
+
+ /// Returns a file descriptor to the controlling terminal of the inferior
+ /// process.
+ ///
+ /// Reads from this file descriptor yield both the standard output and
+ /// standard error of this debugee. Even if stderr and stdout were
+ /// redirected on launch it may still happen that data is available on this
+ /// descriptor (if the inferior process opens /dev/tty, for example).
+ ///
+ /// If this monitor was attached to an existing process this method returns
+ /// -1.
+ int
+ GetTerminalFD() const { return m_terminal_fd; }
+
+ /// Reads @p size bytes from address @vm_adder in the inferior process
+ /// address space.
+ ///
+ /// This method is provided to implement Process::DoReadMemory.
+ size_t
+ ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
+ lldb_private::Error &error);
+
+ /// Writes @p size bytes from address @p vm_adder in the inferior process
+ /// address space.
+ ///
+ /// This method is provided to implement Process::DoWriteMemory.
+ size_t
+ WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
+ lldb_private::Error &error);
+
+ /// Reads the contents from the register identified by the given (architecture
+ /// dependent) offset.
+ ///
+ /// This method is provided for use by RegisterContextFreeBSD derivatives.
+ bool
+ ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value);
+
+ /// Writes the given value to the register identified by the given
+ /// (architecture dependent) offset.
+ ///
+ /// This method is provided for use by RegisterContextFreeBSD derivatives.
+ bool
+ WriteRegisterValue(unsigned offset, const lldb_private::RegisterValue &value);
+
+ /// Reads all general purpose registers into the specified buffer.
+ bool
+ ReadGPR(void *buf);
+
+ /// Reads all floating point registers into the specified buffer.
+ bool
+ ReadFPR(void *buf);
+
+ /// Writes all general purpose registers into the specified buffer.
+ bool
+ WriteGPR(void *buf);
+
+ /// Writes all floating point registers into the specified buffer.
+ bool
+ WriteFPR(void *buf);
+
+ /// Writes a siginfo_t structure corresponding to the given thread ID to the
+ /// memory region pointed to by @p siginfo.
+ bool
+ GetSignalInfo(lldb::tid_t tid, void *siginfo);
+
+ /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
+ /// corresponding to the given thread IDto the memory pointed to by @p
+ /// message.
+ bool
+ GetEventMessage(lldb::tid_t tid, unsigned long *message);
+
+ /// Resumes the given thread. If @p signo is anything but
+ /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+ bool
+ Resume(lldb::tid_t tid, uint32_t signo);
+
+ /// Single steps the given thread. If @p signo is anything but
+ /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+ bool
+ SingleStep(lldb::tid_t tid, uint32_t signo);
+
+ /// Sends the inferior process a PTRACE_KILL signal. The inferior will
+ /// still exists and can be interrogated. Once resumed it will exit as
+ /// though it received a SIGKILL.
+ bool
+ BringProcessIntoLimbo();
+
+ lldb_private::Error
+ Detach();
+
+
+private:
+ ProcessFreeBSD *m_process;
+
+ lldb::thread_t m_operation_thread;
+ lldb::thread_t m_monitor_thread;
+ lldb::pid_t m_pid;
+
+
+ lldb_private::Mutex m_server_mutex;
+ int m_terminal_fd;
+ int m_client_fd;
+ int m_server_fd;
+
+ struct OperationArgs
+ {
+ OperationArgs(ProcessMonitor *monitor);
+
+ ~OperationArgs();
+
+ ProcessMonitor *m_monitor; // The monitor performing the attach.
+ sem_t m_semaphore; // Posted to once operation complete.
+ lldb_private::Error m_error; // Set if process operation failed.
+ };
+
+ /// @class LauchArgs
+ ///
+ /// @brief Simple structure to pass data to the thread responsible for
+ /// launching a child process.
+ struct LaunchArgs : OperationArgs
+ {
+ LaunchArgs(ProcessMonitor *monitor,
+ lldb_private::Module *module,
+ char const **argv,
+ char const **envp,
+ const char *stdin_path,
+ const char *stdout_path,
+ const char *stderr_path);
+
+ ~LaunchArgs();
+
+ lldb_private::Module *m_module; // The executable image to launch.
+ char const **m_argv; // Process arguments.
+ char const **m_envp; // Process environment.
+ const char *m_stdin_path; // Redirect stdin or NULL.
+ const char *m_stdout_path; // Redirect stdout or NULL.
+ const char *m_stderr_path; // Redirect stderr or NULL.
+ };
+
+ void
+ StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error);
+
+ void
+ StopLaunchOpThread();
+
+ static void *
+ LaunchOpThread(void *arg);
+
+ static bool
+ Launch(LaunchArgs *args);
+
+ bool
+ EnableIPC();
+
+ struct AttachArgs : OperationArgs
+ {
+ AttachArgs(ProcessMonitor *monitor,
+ lldb::pid_t pid);
+
+ ~AttachArgs();
+
+ lldb::pid_t m_pid; // pid of the process to be attached.
+ };
+
+ void
+ StartAttachOpThread(AttachArgs *args, lldb_private::Error &error);
+
+ void
+ StopAttachOpThread();
+
+ static void *
+ AttachOpThread(void *args);
+
+ static bool
+ Attach(AttachArgs *args);
+
+ static void
+ ServeOperation(OperationArgs *args);
+
+ static bool
+ DupDescriptor(const char *path, int fd, int flags);
+
+ static bool
+ MonitorCallback(void *callback_baton,
+ lldb::pid_t pid, bool exited, int signal, int status);
+
+ static ProcessMessage
+ MonitorSIGTRAP(ProcessMonitor *monitor,
+ const siginfo_t *info, lldb::pid_t pid);
+
+ static ProcessMessage
+ MonitorSignal(ProcessMonitor *monitor,
+ const siginfo_t *info, lldb::pid_t pid);
+
+ static ProcessMessage::CrashReason
+ GetCrashReasonForSIGSEGV(const siginfo_t *info);
+
+ static ProcessMessage::CrashReason
+ GetCrashReasonForSIGILL(const siginfo_t *info);
+
+ static ProcessMessage::CrashReason
+ GetCrashReasonForSIGFPE(const siginfo_t *info);
+
+ static ProcessMessage::CrashReason
+ GetCrashReasonForSIGBUS(const siginfo_t *info);
+
+ void
+ DoOperation(Operation *op);
+
+ /// Stops the child monitor thread.
+ void
+ StopMonitoringChildProcess();
+
+ void
+ StopMonitor();
+
+ void
+ CloseFD(int &fd);
+};
+
+#endif // #ifndef liblldb_ProcessMonitor_H_
Index: source/Plugins/Process/FreeBSD/Makefile
===================================================================
--- source/Plugins/Process/FreeBSD/Makefile (revision 0)
+++ source/Plugins/Process/FreeBSD/Makefile (revision 0)
@@ -0,0 +1,17 @@
+##===- source/Plugins/Process/FreeBSD/Makefile ---------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginProcessFreeBSD
+BUILD_ARCHIVE = 1
+
+# Extend the include path so we may locate UnwindLLDB.h
+CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility
+
+include $(LLDB_LEVEL)/Makefile
Index: source/Target/Platform.cpp
===================================================================
--- source/Target/Platform.cpp (revision 147560)
+++ source/Target/Platform.cpp (working copy)
@@ -572,6 +572,16 @@
Error &error)
{
ProcessSP process_sp;
+
+ launch_info.GetFlags ().Set (eLaunchFlagDebug);
+ const char *plugin_name = launch_info.GetProcessPluginName();
+ process_sp = target->CreateProcess (listener, plugin_name).get();
+ error = process_sp->Launch (launch_info);
+ return process_sp;
+
+
+#if 0
+ ProcessSP process_sp;
// Make sure we stop at the entry point
launch_info.GetFlags ().Set (eLaunchFlagDebug);
error = LaunchProcess (launch_info);
@@ -602,4 +612,5 @@
}
}
return process_sp;
+#endif
}
Index: source/Target/TargetList.cpp
===================================================================
--- source/Target/TargetList.cpp (revision 147560)
+++ source/Target/TargetList.cpp (working copy)
@@ -72,7 +72,8 @@
if (!platform_sp)
platform_sp = debugger.GetPlatformList().GetSelectedPlatform ();
- ArchSpec arch;
+ // Unclear why I need to init this and others don't
+ ArchSpec arch = Host::GetArchitecture(Host::eSystemDefaultArchitecture);
if (triple_cstr)
{
@@ -83,6 +84,7 @@
return error;
}
}
+
error = TargetList::CreateTarget (debugger,
file,
arch,
Index: source/Host/linux/Host.cpp
===================================================================
--- source/Host/linux/Host.cpp (revision 147560)
+++ source/Host/linux/Host.cpp (working copy)
@@ -10,12 +10,20 @@
// C Includes
#include <stdio.h>
#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Error.h"
+#include "lldb/Target/Process.h"
+
#include "lldb/Host/Host.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
using namespace lldb;
using namespace lldb_private;
@@ -43,3 +51,48 @@
return error;
}
+lldb::DataBufferSP
+Host::GetAuxvData(lldb_private::Process *process)
+{
+ static const size_t path_size = 128;
+ static char path[path_size];
+ lldb::DataBufferSP buf_sp;
+
+ int fd;
+
+ // Ideally, we would simply create a FileSpec and call ReadFileContents.
+ // However, files in procfs have zero size (since they are, in general,
+ // dynamically generated by the kernel) which is incompatible with the
+ // current ReadFileContents implementation. Therefore we simply stream the
+ // data into a DataBuffer ourselves.
+ if (snprintf(path, path_size, "/proc/%d/auxv", process->GetID()) < 0)
+ return buf_sp;
+
+ if ((fd = open(path, O_RDONLY, 0)) < 0)
+ return buf_sp;
+
+ size_t bytes_read = 0;
+ std::auto_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
+ for (;;)
+ {
+ size_t avail = buf_ap->GetByteSize() - bytes_read;
+ ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail);
+
+ if (status < 0)
+ break;
+
+ bytes_read += status;
+
+ if (status == 0)
+ {
+ buf_ap->SetByteSize(bytes_read);
+ buf_sp.reset(buf_ap.release());
+ break;
+ }
+
+ if (avail - status == 0)
+ buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
+ }
+
+ return buf_sp;
+}
Index: source/Host/freebsd/Host.cpp
===================================================================
--- source/Host/freebsd/Host.cpp (revision 147560)
+++ source/Host/freebsd/Host.cpp (working copy)
@@ -9,12 +9,18 @@
// C Includes
#include <stdio.h>
+#include <dlfcn.h>
#include <execinfo.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/utsname.h>
#include <sys/sysctl.h>
+#include <sys/ptrace.h>
+#include <sys/exec.h>
+#include <machine/elf.h>
+
+
// C++ Includes
// Other libraries and framework includes
// Project includes
@@ -26,15 +32,19 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Target/Process.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
#include "llvm/Support/Host.h"
+
extern "C" {
- char **environ;
+ extern char **environ;
}
using namespace lldb;
using namespace lldb_private;
+
class FreeBSDThread
{
public:
@@ -77,7 +87,7 @@
std::vector<void *> frame_buffer (max_frames, NULL);
int count = ::backtrace (&frame_buffer[0], frame_buffer.size());
::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd);
-
+
const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR);
if (::lseek(backtrace_fd, 0, SEEK_SET) == 0)
@@ -101,7 +111,7 @@
{
char *v;
char **var = environ;
- for (var = environ; var != NULL; ++var) {
+ for (; var != NULL && *var != NULL; ++var) {
v = strchr(*var, (int)'-');
if (v == NULL)
continue;
@@ -168,49 +178,47 @@
ProcessInstanceInfo &process_info)
{
if (process_info.ProcessIDIsValid()) {
- int mib[3] = { CTL_KERN, KERN_PROC_ARGS, process_info.GetProcessID() };
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, process_info.GetProcessID() };
char arg_data[8192];
size_t arg_data_size = sizeof(arg_data);
- if (::sysctl (mib, 3, arg_data, &arg_data_size , NULL, 0) == 0)
+ if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0)
{
DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *));
uint32_t offset = 0;
- uint32_t start_offset;
- uint32_t argc = data.GetU32 (&offset);
const char *cstr;
-
+
cstr = data.GetCStr (&offset);
if (cstr)
{
process_info.GetExecutableFile().SetFile(cstr, false);
- if (match_info_ptr == NULL ||
+ if (!(match_info_ptr == NULL ||
NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(),
match_info_ptr->GetNameMatchType(),
- match_info_ptr->GetProcessInfo().GetName()))
+ match_info_ptr->GetProcessInfo().GetName())))
+ return false;
+
+ Args &proc_args = process_info.GetArguments();
+ while (1)
{
- // Skip NULLs
- while (1)
+ const uint8_t *p = data.PeekData(offset, 1);
+ while ((p != NULL) && (*p == '\0') && offset < arg_data_size)
{
- const uint8_t *p = data.PeekData(offset, 1);
- if ((p == NULL) || (*p != '\0'))
- break;
++offset;
+ p = data.PeekData(offset, 1);
}
- // Now extract all arguments
- Args &proc_args = process_info.GetArguments();
- for (int i=0; i<argc; ++i)
- {
- start_offset = offset;
- cstr = data.GetCStr(&offset);
- if (cstr)
- proc_args.AppendArgument(cstr);
- }
- return true;
+ if (p == NULL || offset >= arg_data_size)
+ return true;
+
+ cstr = data.GetCStr(&offset);
+ if (cstr)
+ proc_args.AppendArgument(cstr);
+ else
+ return true;
}
}
- }
+ }
}
return false;
}
@@ -219,8 +227,8 @@
GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info)
{
if (process_info.ProcessIDIsValid()) {
- // TODO: This
- // return true;
+ process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
+ return true;
}
process_info.GetArchitecture().Clear();
return false;
@@ -249,7 +257,7 @@
if (proc_kinfo.ki_ngroups > 0)
process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]);
else
- process_info.SetEffectiveGroupID (UINT32_MAX);
+ process_info.SetEffectiveGroupID (UINT32_MAX);
return true;
}
}
@@ -258,7 +266,7 @@
process_info.SetUserID (UINT32_MAX);
process_info.SetGroupID (UINT32_MAX);
process_info.SetEffectiveUserID (UINT32_MAX);
- process_info.SetEffectiveGroupID (UINT32_MAX);
+ process_info.SetEffectiveGroupID (UINT32_MAX);
return false;
}
@@ -275,3 +283,46 @@
process_info.Clear();
return false;
}
+
+lldb::DataBufferSP
+Host::GetAuxvData(lldb_private::Process *process)
+{
+ int mib[2] = { CTL_KERN, KERN_PS_STRINGS };
+ void *ps_strings_addr, *auxv_addr;
+ size_t ps_strings_size = sizeof(void *);
+ Elf_Auxinfo aux_info[AT_COUNT];
+ struct ps_strings ps_strings;
+ struct ptrace_io_desc pid;
+ DataBufferSP buf_sp;
+ std::auto_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
+
+ if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) {
+ pid.piod_op = PIOD_READ_D;
+ pid.piod_addr = &ps_strings;
+ pid.piod_offs = ps_strings_addr;
+ pid.piod_len = sizeof(ps_strings);
+ if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) {
+ perror("failed to fetch ps_strings");
+ buf_ap.release();
+ goto done;
+ }
+
+ auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1;
+
+ pid.piod_addr = aux_info;
+ pid.piod_offs = auxv_addr;
+ pid.piod_len = sizeof(aux_info);
+ if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) {
+ perror("failed to fetch aux_info");
+ buf_ap.release();
+ goto done;
+ }
+ memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len);
+ buf_sp.reset(buf_ap.release());
+ } else {
+ perror("sysctl failed on ps_strings");
+ }
+
+ done:
+ return buf_sp;
+}
Index: source/lldb.cpp
===================================================================
--- source/lldb.cpp (revision 147560)
+++ source/lldb.cpp (working copy)
@@ -52,13 +52,16 @@
#endif
#if defined (__linux__)
-#include "Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h"
+#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
#include "Plugins/Platform/Linux/PlatformLinux.h"
#include "Plugins/Process/Linux/ProcessLinux.h"
#endif
#if defined (__FreeBSD__)
+#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
#include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h"
+#include "Plugins/Process/POSIX/ProcessPOSIX.h"
+#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h"
#endif
#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"
@@ -120,10 +123,12 @@
//----------------------------------------------------------------------
PlatformLinux::Initialize();
ProcessLinux::Initialize();
- DynamicLoaderLinuxDYLD::Initialize();
+ DynamicLoaderPOSIXDYLD::Initialize();
#endif
#if defined (__FreeBSD__)
- PlatformFreeBSD::Initialize();
+ PlatformFreeBSD::Initialize();
+ ProcessFreeBSD::Initialize();
+ DynamicLoaderPOSIXDYLD::Initialize();
#endif
//----------------------------------------------------------------------
// Platform agnostic plugins
@@ -190,11 +195,13 @@
#if defined (__linux__)
PlatformLinux::Terminate();
ProcessLinux::Terminate();
- DynamicLoaderLinuxDYLD::Terminate();
+ DynamicLoaderPOSIXDYLD::Terminate();
#endif
#if defined (__FreeBSD__)
- PlatformFreeBSD::Terminate();
+ PlatformFreeBSD::Terminate();
+ ProcessFreeBSD::Terminate();
+ DynamicLoaderPOSIXDYLD::Terminate();
#endif
DynamicLoaderStatic::Terminate();
Index: tools/driver/Makefile
===================================================================
--- tools/driver/Makefile (revision 147560)
+++ tools/driver/Makefile (working copy)
@@ -25,7 +25,6 @@
ifeq ($(HOST_OS),FreeBSD)
CPP.Flags += -I/usr/include/edit #-v
- LD.Flags += -lEnhancedDisassembly
LD.Flags += -Wl,-rpath,$(LibDir)
endif
Index: lib/Makefile
===================================================================
--- lib/Makefile (revision 147560)
+++ lib/Makefile (working copy)
@@ -81,15 +81,19 @@
endif
ifeq ($(HOST_OS),Linux)
- USEDLIBS += lldbPluginProcessLinux.a \
- lldbPluginDynamicLoaderLinux.a \
+ USEDLIBS += lldbPluginProcessPOSIX.a \
+ lldbPluginProcessLinux.a \
+ lldbPluginDynamicLoaderPOSIX.a \
lldbPluginPlatformLinux.a \
lldbHostLinux.a
endif
ifeq ($(HOST_OS),FreeBSD)
USEDLIBS += lldbHostFreeBSD.a \
- lldbPluginPlatformFreeBSD.a
+ lldbPluginDynamicLoaderPOSIX.a \
+ lldbPluginProcessPOSIX.a \
+ lldbPluginProcessFreeBSD.a \
+ lldbPluginPlatformFreeBSD.a
endif
include $(LEVEL)/Makefile.common
@@ -130,8 +134,8 @@
# Include everything from the .a's into the shared library.
ProjLibsOptions := -Wl,--whole-archive $(ProjLibsOptions) \
-Wl,--no-whole-archive
- # Don't allow unresolved symbols.
- LLVMLibsOptions += -Wl,--no-undefined
+ # Allow unresolved symbols.
+ LLVMLibsOptions += -Wl,--allow-shlib-undefined
# Link in python
LD.Flags += $(PYTHON_BUILD_FLAGS) -lrt -L/usr/local/lib -lexecinfo
endif
Index: Makefile
===================================================================
--- Makefile (revision 147560)
+++ Makefile (working copy)
@@ -39,6 +39,7 @@
CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source
CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Utility
CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Utility
+CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/POSIX
ifeq ($(HOST_OS),Darwin)
CPP.Flags += -F/System/Library/Frameworks -F/System/Library/PrivateFrameworks
endif
More information about the lldb-commits
mailing list