[Lldb-commits] [PATCH] RegisterContextLinux_x86_64.h missing
Johnny Chen
johnny.chen at apple.com
Thu Jan 5 15:57:16 PST 2012
Hi Dawn,
Did r147627 fix the problem I caused?
On Jan 5, 2012, at 3:44 PM, dawn at burble.org wrote:
> Just changing the subject so it's obvious that a patch was attached
> to my previous email (please see email).
>
> FYI - I pulled a new tree and diffed against the tree I used to create the
> original patch from, and have confirmed that RegisterContextLinux_x86_64.h
> is the only file whose patch did not get applied correctly.
>
> On Thu, Jan 05, 2012 at 03:10:02PM -0800, dawn at burble.org wrote:
>> Almost there...
>>
>> Comparing this new list with what was missing from the last one, the
>> following file appears to have been wrongly deleted:
>>
>> M source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
>>
>> Please add this file back and apply the attached the diff.
>>
>> Thank you!
>> -Dawn
>>
>> On Thu, Jan 05, 2012 at 09:48:16PM -0000, Johnny Chen wrote:
>>> Author: johnny
>>> Date: Thu Jan 5 15:48:15 2012
>>> New Revision: 147613
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=147613&view=rev
>>> Log:
>>> Fix incomplete commit of http://llvm.org/viewvc/llvm-project?rev=147609&view=rev:
>>>
>>> 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.
>>>
>>> Added:
>>> lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/
>>> lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
>>> lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
>>> lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
>>> lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
>>> lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
>>> lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
>>> lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile
>>> lldb/trunk/source/Plugins/Process/FreeBSD/
>>> lldb/trunk/source/Plugins/Process/FreeBSD/Makefile
>>> lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
>>> lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
>>> lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
>>> lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h
>>> lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h
>>> lldb/trunk/source/Plugins/Process/POSIX/
>>> lldb/trunk/source/Plugins/Process/POSIX/Makefile
>>> lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.cpp
>>> lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.h
>>> lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp
>>> lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h
>>> lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.cpp
>>> lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.h
>>> lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
>>> lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h
>>> lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp
>>> lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.h
>>> lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
>>> lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.cpp
>>> lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.h
>>> lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
>>> lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h
>>> Removed:
>>> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/
>>> lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp
>>> lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h
>>> lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp
>>> lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h
>>> lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp
>>> lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h
>>> lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp
>>> lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h
>>> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h
>>> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp
>>> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h
>>> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
>>> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
>>>
>>> Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (added)
>>> +++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp Thu Jan 5 15:48:15 2012
>>> @@ -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;
>>> +}
>>> +
>>>
>>> Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (added)
>>> +++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h Thu Jan 5 15:48:15 2012
>>> @@ -0,0 +1,97 @@
>>> +//===-- AuxVector.h ---------------------------------------------*- C++ -*-===//
>>> +//
>>> +// The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is distributed under the University of Illinois Open Source
>>> +// License. See LICENSE.TXT for details.
>>> +//
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#ifndef liblldb_AuxVector_H_
>>> +#define liblldb_AuxVector_H_
>>> +
>>> +// C Includes
>>> +// C++ Includes
>>> +#include <vector>
>>> +
>>> +// Other libraries and framework includes
>>> +#include "lldb/lldb-forward-rtti.h"
>>> +
>>> +namespace lldb_private {
>>> +class DataExtractor;
>>> +}
>>> +
>>> +/// @class AuxVector
>>> +/// @brief Represents a processes auxiliary vector.
>>> +///
>>> +/// When a process is loaded on Linux a vector of values is placed onto the
>>> +/// stack communicating operating system specific information. On construction
>>> +/// this class locates and parses this information and provides a simple
>>> +/// read-only interface to the entries found.
>>> +class AuxVector {
>>> +
>>> +public:
>>> + AuxVector(lldb_private::Process *process);
>>> +
>>> + struct Entry {
>>> + uint64_t type;
>>> + uint64_t value;
>>> +
>>> + Entry() : type(0), value(0) { }
>>> + };
>>> +
>>> + /// Constants describing the type of entry.
>>> + enum EntryType {
>>> + AT_NULL = 0, ///< End of auxv.
>>> + AT_IGNORE = 1, ///< Ignore entry.
>>> + AT_EXECFD = 2, ///< File descriptor of program.
>>> + AT_PHDR = 3, ///< Program headers.
>>> + AT_PHENT = 4, ///< Size of program header.
>>> + AT_PHNUM = 5, ///< Number of program headers.
>>> + AT_PAGESZ = 6, ///< Page size.
>>> + AT_BASE = 7, ///< Interpreter base address.
>>> + AT_FLAGS = 8, ///< Flags.
>>> + AT_ENTRY = 9, ///< Program entry point.
>>> + AT_NOTELF = 10, ///< Set if program is not an ELF.
>>> + AT_UID = 11, ///< UID.
>>> + AT_EUID = 12, ///< Effective UID.
>>> + AT_GID = 13, ///< GID.
>>> + AT_EGID = 14, ///< Effective GID.
>>> + AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)).
>>> + };
>>> +
>>> +private:
>>> + typedef std::vector<Entry> EntryVector;
>>> +
>>> +public:
>>> + typedef EntryVector::const_iterator iterator;
>>> +
>>> + iterator begin() const { return m_auxv.begin(); }
>>> + iterator end() const { return m_auxv.end(); }
>>> +
>>> + iterator
>>> + FindEntry(EntryType type) const;
>>> +
>>> + static const char *
>>> + GetEntryName(const Entry &entry) {
>>> + return GetEntryName(static_cast<EntryType>(entry.type));
>>> + }
>>> +
>>> + static const char *
>>> + GetEntryName(EntryType type);
>>> +
>>> + void
>>> + DumpToLog(lldb::LogSP log) const;
>>> +
>>> +private:
>>> + lldb_private::Process *m_process;
>>> + EntryVector m_auxv;
>>> +
>>> + lldb::DataBufferSP
>>> + GetAuxvData();
>>> +
>>> + void
>>> + ParseAuxv(lldb_private::DataExtractor &data);
>>> +};
>>> +
>>> +#endif
>>>
>>> Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (added)
>>> +++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp Thu Jan 5 15:48:15 2012
>>> @@ -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);
>>> + }
>>> +}
>>>
>>> Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (added)
>>> +++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h Thu Jan 5 15:48:15 2012
>>> @@ -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
>>>
>>> Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (added)
>>> +++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp Thu Jan 5 15:48:15 2012
>>> @@ -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;
>>> +}
>>>
>>> Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (added)
>>> +++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h Thu Jan 5 15:48:15 2012
>>> @@ -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_
>>>
>>> Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile (added)
>>> +++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile Thu Jan 5 15:48:15 2012
>>> @@ -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
>>>
>>> Added: lldb/trunk/source/Plugins/Process/FreeBSD/Makefile
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/Makefile?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/FreeBSD/Makefile (added)
>>> +++ lldb/trunk/source/Plugins/Process/FreeBSD/Makefile Thu Jan 5 15:48:15 2012
>>> @@ -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
>>>
>>> Added: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (added)
>>> +++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp Thu Jan 5 15:48:15 2012
>>> @@ -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;
>>> +}
>>>
>>> Added: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (added)
>>> +++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h Thu Jan 5 15:48:15 2012
>>> @@ -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_
>>>
>>> Added: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (added)
>>> +++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp Thu Jan 5 15:48:15 2012
>>> @@ -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;
>>> + }
>>> +}
>>>
>>> Added: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h (added)
>>> +++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h Thu Jan 5 15:48:15 2012
>>> @@ -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_
>>>
>>> Added: lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (added)
>>> +++ lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h Thu Jan 5 15:48:15 2012
>>> @@ -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
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp?rev=147612&view=auto
>>> ==============================================================================
>>> (empty)
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h?rev=147612&view=auto
>>> ==============================================================================
>>> (empty)
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp?rev=147612&view=auto
>>> ==============================================================================
>>> (empty)
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h?rev=147612&view=auto
>>> ==============================================================================
>>> (empty)
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp?rev=147612&view=auto
>>> ==============================================================================
>>> (empty)
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h?rev=147612&view=auto
>>> ==============================================================================
>>> (empty)
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp?rev=147612&view=auto
>>> ==============================================================================
>>> (empty)
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h?rev=147612&view=auto
>>> ==============================================================================
>>> (empty)
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h?rev=147612&view=auto
>>> ==============================================================================
>>> (empty)
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp?rev=147612&view=auto
>>> ==============================================================================
>>> (empty)
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h?rev=147612&view=auto
>>> ==============================================================================
>>> (empty)
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp?rev=147612&view=auto
>>> ==============================================================================
>>> (empty)
>>>
>>> Removed: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h?rev=147612&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (original)
>>> +++ lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (removed)
>>> @@ -1,44 +0,0 @@
>>> -//===-- RegisterContextLinux_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_x86_64_H_
>>> -#define liblldb_RegisterContextLinux_x86_64_H_
>>> -
>>> - typedef struct _GPR
>>> - {
>>> - uint64_t r15;
>>> - uint64_t r14;
>>> - uint64_t r13;
>>> - uint64_t r12;
>>> - uint64_t rbp;
>>> - uint64_t rbx;
>>> - uint64_t r11;
>>> - uint64_t r10;
>>> - uint64_t r9;
>>> - uint64_t r8;
>>> - uint64_t rax;
>>> - uint64_t rcx;
>>> - uint64_t rdx;
>>> - uint64_t rsi;
>>> - uint64_t rdi;
>>> - uint64_t orig_ax;
>>> - uint64_t rip;
>>> - uint64_t cs;
>>> - uint64_t rflags;
>>> - uint64_t rsp;
>>> - uint64_t ss;
>>> - uint64_t fs_base;
>>> - uint64_t gs_base;
>>> - uint64_t ds;
>>> - uint64_t es;
>>> - uint64_t fs;
>>> - uint64_t gs;
>>> - } GPR;
>>> -
>>> -#endif
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/Makefile
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/Makefile?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/Makefile (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/Makefile Thu Jan 5 15:48:15 2012
>>> @@ -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
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.cpp?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.cpp (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.cpp Thu Jan 5 15:48:15 2012
>>> @@ -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);
>>> +}
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.h (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.h Thu Jan 5 15:48:15 2012
>>> @@ -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
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp Thu Jan 5 15:48:15 2012
>>> @@ -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));
>>> +}
>>> +
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h Thu Jan 5 15:48:15 2012
>>> @@ -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_
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.cpp?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.cpp (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.cpp Thu Jan 5 15:48:15 2012
>>> @@ -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);
>>> +}
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.h (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.h Thu Jan 5 15:48:15 2012
>>> @@ -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_
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp Thu Jan 5 15:48:15 2012
>>> @@ -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;
>>> +}
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h Thu Jan 5 15:48:15 2012
>>> @@ -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_
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp Thu Jan 5 15:48:15 2012
>>> @@ -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 = "";
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.h (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.h Thu Jan 5 15:48:15 2012
>>> @@ -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_
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h Thu Jan 5 15:48:15 2012
>>> @@ -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_
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.cpp?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.cpp (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.cpp Thu Jan 5 15:48:15 2012
>>> @@ -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);
>>> +}
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.h (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.h Thu Jan 5 15:48:15 2012
>>> @@ -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_
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp Thu Jan 5 15:48:15 2012
>>> @@ -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);
>>> +}
>>>
>>> Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h?rev=147613&view=auto
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h (added)
>>> +++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h Thu Jan 5 15:48:15 2012
>>> @@ -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_
>>>
>>>
>>> _______________________________________________
>>> lldb-commits mailing list
>>> lldb-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
>
>> 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
>
>> _______________________________________________
>> lldb-commits mailing list
>> lldb-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
>
More information about the lldb-commits
mailing list