//===-- NativeProcessLinux.cpp -------------------------------- -*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "NativeProcessLinux.h"

// C Includes
#include <errno.h>
#include <semaphore.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>

// C++ Includes
#include <fstream>
#include <mutex>
#include <sstream>
#include <string>
#include <unordered_map>

// Other libraries and framework includes
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/State.h"
#include "lldb/Host/common/NativeBreakpoint.h"
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/PseudoTerminal.h"
#include "lldb/Utility/StringExtractor.h"

#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "NativeThreadLinux.h"
#include "ProcFileReader.h"
#include "Procfs.h"

// System includes - They have to be included after framework includes because they define some
// macros which collide with variable names in other modules
#include <linux/unistd.h>
#include <sys/socket.h>

#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/wait.h>

#include "lldb/Host/linux/Personality.h"
#include "lldb/Host/linux/Ptrace.h"
#include "lldb/Host/linux/Signalfd.h"
#include "lldb/Host/linux/Uio.h"
#include "lldb/Host/android/Android.h"

#define LLDB_PERSONALITY_GET_CURRENT_SETTINGS  0xffffffff

// Support hardware breakpoints in case it has not been defined
#ifndef TRAP_HWBKPT
  #define TRAP_HWBKPT 4
#endif

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_linux;
using namespace llvm;

// Private bits we only need internally.

static bool ProcessVmReadvSupported()
{
    static bool is_supported;
    static std::once_flag flag;

    std::call_once(flag, [] {
        Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

        uint32_t source = 0x47424742;
        uint32_t dest = 0;

        struct iovec local, remote;
        remote.iov_base = &source;
        local.iov_base = &dest;
        remote.iov_len = local.iov_len = sizeof source;

        // We shall try if cross-process-memory reads work by attempting to read a value from our own process.
        ssize_t res = process_vm_readv(getpid(), &local, 1, &remote, 1, 0);
        is_supported = (res == sizeof(source) && source == dest);
        if (log)
        {
            if (is_supported)
                log->Printf("%s: Detected kernel support for process_vm_readv syscall. Fast memory reads enabled.",
                        __FUNCTION__);
            else
                log->Printf("%s: syscall process_vm_readv failed (error: %s). Fast memory reads disabled.",
                        __FUNCTION__, strerror(errno));
        }
    });

    return is_supported;
}

namespace
{
    Error
    ResolveProcessArchitecture (lldb::pid_t pid, Platform &platform, ArchSpec &arch)
    {
        // Grab process info for the running process.
        ProcessInstanceInfo process_info;
        if (!platform.GetProcessInfo (pid, process_info))
            return Error("failed to get process info");

        // Resolve the executable module.
        ModuleSP exe_module_sp;
        ModuleSpec exe_module_spec(process_info.GetExecutableFile(), process_info.GetArchitecture());
        FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths ());
        Error error = platform.ResolveExecutable(
            exe_module_spec,
            exe_module_sp,
            executable_search_paths.GetSize () ? &executable_search_paths : NULL);

        if (!error.Success ())
            return error;

        // Check if we've got our architecture from the exe_module.
        arch = exe_module_sp->GetArchitecture ();
        if (arch.IsValid ())
            return Error();
        else
            return Error("failed to retrieve a valid architecture from the exe module");
    }

    void
    DisplayBytes (StreamString &s, void *bytes, uint32_t count)
    {
        uint8_t *ptr = (uint8_t *)bytes;
        const uint32_t loop_count = std::min<uint32_t>(DEBUG_PTRACE_MAXBYTES, count);
        for(uint32_t i=0; i<loop_count; i++)
        {
            s.Printf ("[%x]", *ptr);
            ptr++;
        }
    }

    void
    PtraceDisplayBytes(int &req, void *data, size_t data_size)
    {
        StreamString buf;
        Log *verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (
                    POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE));

        if (verbose_log)
        {
            switch(req)
            {
            case PTRACE_POKETEXT:
            {
                DisplayBytes(buf, &data, 8);
                verbose_log->Printf("PTRACE_POKETEXT %s", buf.GetData());
                break;
            }
            case PTRACE_POKEDATA:
            {
                DisplayBytes(buf, &data, 8);
                verbose_log->Printf("PTRACE_POKEDATA %s", buf.GetData());
                break;
            }
            case PTRACE_POKEUSER:
            {
                DisplayBytes(buf, &data, 8);
                verbose_log->Printf("PTRACE_POKEUSER %s", buf.GetData());
                break;
            }
            case PTRACE_SETREGS:
            {
                DisplayBytes(buf, data, data_size);
                verbose_log->Printf("PTRACE_SETREGS %s", buf.GetData());
                break;
            }
            case PTRACE_SETFPREGS:
            {
                DisplayBytes(buf, data, data_size);
                verbose_log->Printf("PTRACE_SETFPREGS %s", buf.GetData());
                break;
            }
            case PTRACE_SETSIGINFO:
            {
                DisplayBytes(buf, data, sizeof(siginfo_t));
                verbose_log->Printf("PTRACE_SETSIGINFO %s", buf.GetData());
                break;
            }
            case PTRACE_SETREGSET:
            {
                // Extract iov_base from data, which is a pointer to the struct IOVEC
                DisplayBytes(buf, *(void **)data, data_size);
                verbose_log->Printf("PTRACE_SETREGSET %s", buf.GetData());
                break;
            }
            default:
            {
            }
            }
        }
    }

    //------------------------------------------------------------------------------
    // Static implementations of NativeProcessLinux::ReadMemory and
    // NativeProcessLinux::WriteMemory.  This enables mutual recursion between these
    // functions without needed to go thru the thread funnel.

    Error
    DoReadMemory(
        lldb::pid_t pid,
        lldb::addr_t vm_addr,
        void *buf,
        size_t size,
        size_t &bytes_read)
    {
        // ptrace word size is determined by the host, not the child
        static const unsigned word_size = sizeof(void*);
        unsigned char *dst = static_cast<unsigned char*>(buf);
        size_t remainder;
        long data;

        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
        if (log)
            ProcessPOSIXLog::IncNestLevel();
        if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
            log->Printf ("NativeProcessLinux::%s(%" PRIu64 ", %d, %p, %p, %zd, _)", __FUNCTION__,
                    pid, word_size, (void*)vm_addr, buf, size);

        assert(sizeof(data) >= word_size);
        for (bytes_read = 0; bytes_read < size; bytes_read += remainder)
        {
            Error error = NativeProcessLinux::PtraceWrapper(PTRACE_PEEKDATA, pid, (void*)vm_addr, nullptr, 0, &data);
            if (error.Fail())
            {
                if (log)
                    ProcessPOSIXLog::DecNestLevel();
                return error;
            }

            remainder = size - bytes_read;
            remainder = remainder > word_size ? word_size : remainder;

            // Copy the data into our buffer
            for (unsigned i = 0; i < remainder; ++i)
                dst[i] = ((data >> i*8) & 0xFF);

            if (log && ProcessPOSIXLog::AtTopNestLevel() &&
                    (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
                            (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
                                    size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
            {
                uintptr_t print_dst = 0;
                // Format bytes from data by moving into print_dst for log output
                for (unsigned i = 0; i < remainder; ++i)
                    print_dst |= (((data >> i*8) & 0xFF) << i*8);
                log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
                        (void*)vm_addr, print_dst, (unsigned long)data);
            }
            vm_addr += word_size;
            dst += word_size;
        }

        if (log)
            ProcessPOSIXLog::DecNestLevel();
        return Error();
    }

    Error
    DoWriteMemory(
        lldb::pid_t pid,
        lldb::addr_t vm_addr,
        const void *buf,
        size_t size,
        size_t &bytes_written)
    {
        // ptrace word size is determined by the host, not the child
        static const unsigned word_size = sizeof(void*);
        const unsigned char *src = static_cast<const unsigned char*>(buf);
        size_t remainder;
        Error error;

        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
        if (log)
            ProcessPOSIXLog::IncNestLevel();
        if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
            log->Printf ("NativeProcessLinux::%s(%" PRIu64 ", %u, %p, %p, %" PRIu64 ")", __FUNCTION__,
                    pid, word_size, (void*)vm_addr, buf, size);

        for (bytes_written = 0; bytes_written < size; bytes_written += remainder)
        {
            remainder = size - bytes_written;
            remainder = remainder > word_size ? word_size : remainder;

            if (remainder == word_size)
            {
                unsigned long data = 0;
                assert(sizeof(data) >= word_size);
                for (unsigned i = 0; i < word_size; ++i)
                    data |= (unsigned long)src[i] << i*8;

                if (log && ProcessPOSIXLog::AtTopNestLevel() &&
                        (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
                                (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
                                        size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
                    log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
                            (void*)vm_addr, *(const unsigned long*)src, data);

                error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data);
                if (error.Fail())
                {
                    if (log)
                        ProcessPOSIXLog::DecNestLevel();
                    return error;
                }
            }
            else
            {
                unsigned char buff[8];
                size_t bytes_read;
                error = DoReadMemory(pid, vm_addr, buff, word_size, bytes_read);
                if (error.Fail())
                {
                    if (log)
                        ProcessPOSIXLog::DecNestLevel();
                    return error;
                }

                memcpy(buff, src, remainder);

                size_t bytes_written_rec;
                error = DoWriteMemory(pid, vm_addr, buff, word_size, bytes_written_rec);
                if (error.Fail())
                {
                    if (log)
                        ProcessPOSIXLog::DecNestLevel();
                    return error;
                }

                if (log && ProcessPOSIXLog::AtTopNestLevel() &&
                        (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
                                (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
                                        size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
                    log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
                            (void*)vm_addr, *(const unsigned long*)src, *(unsigned long*)buff);
            }

            vm_addr += word_size;
            src += word_size;
        }
        if (log)
            ProcessPOSIXLog::DecNestLevel();
        return error;
    }
} // end of anonymous namespace

// Simple helper function to ensure flags are enabled on the given file
// descriptor.
static Error
EnsureFDFlags(int fd, int flags)
{
    Error error;

    int status = fcntl(fd, F_GETFL);
    if (status == -1)
    {
        error.SetErrorToErrno();
        return error;
    }

    if (fcntl(fd, F_SETFL, status | flags) == -1)
    {
        error.SetErrorToErrno();
        return error;
    }

    return error;
}

// This class encapsulates the privileged thread which performs all ptrace and wait operations on
// the inferior. The thread consists of a main loop which waits for events and processes them
//   - SIGCHLD (delivered over a signalfd file descriptor): These signals notify us of events in
//     the inferior process. Upon receiving this signal we do a waitpid to get more information
//     and dispatch to NativeProcessLinux::MonitorCallback.
//   - requests for ptrace operations: These initiated via the DoOperation method, which funnels
//     them to the Monitor thread via m_operation member. The Monitor thread is signaled over a
//     pipe, and the completion of the operation is signalled over the semaphore.
//   - thread exit event: this is signaled from the Monitor destructor by closing the write end
//     of the command pipe.
class NativeProcessLinux::Monitor
{
private:
    // The initial monitor operation (launch or attach). It returns a inferior process id.
    std::unique_ptr<InitialOperation> m_initial_operation_up;

    ::pid_t                           m_child_pid = -1;
    NativeProcessLinux              * m_native_process;

    enum { READ, WRITE };
    int        m_pipefd[2] = {-1, -1};
    int        m_signal_fd = -1;
    HostThread m_thread;

    // current operation which must be executed on the priviliged thread
    Mutex            m_operation_mutex;
    const Operation *m_operation = nullptr;
    sem_t            m_operation_sem;
    Error            m_operation_error;

    unsigned   m_operation_nesting_level = 0;

    static constexpr char operation_command   = 'o';
    static constexpr char begin_block_command = '{';
    static constexpr char end_block_command   = '}';

    void
    HandleSignals();

    void
    HandleWait();

    // Returns true if the thread should exit.
    bool
    HandleCommands();

    void
    MainLoop();

    static void *
    RunMonitor(void *arg);

    Error
    WaitForAck();

    void
    BeginOperationBlock()
    {
        write(m_pipefd[WRITE], &begin_block_command, sizeof operation_command);
        WaitForAck();
    }

    void
    EndOperationBlock()
    {
        write(m_pipefd[WRITE], &end_block_command, sizeof operation_command);
        WaitForAck();
    }

public:
    Monitor(const InitialOperation &initial_operation,
            NativeProcessLinux *native_process)
        : m_initial_operation_up(new InitialOperation(initial_operation)),
          m_native_process(native_process)
    {
        sem_init(&m_operation_sem, 0, 0);
    }

    ~Monitor();

    Error
    Initialize();

    void
    Terminate();

    Error
    DoOperation(const Operation &op);

    class ScopedOperationLock {
        Monitor &m_monitor;

    public:
        ScopedOperationLock(Monitor &monitor)
            : m_monitor(monitor)
        { m_monitor.BeginOperationBlock(); }

        ~ScopedOperationLock()
        { m_monitor.EndOperationBlock(); }
    };
};
constexpr char NativeProcessLinux::Monitor::operation_command;
constexpr char NativeProcessLinux::Monitor::begin_block_command;
constexpr char NativeProcessLinux::Monitor::end_block_command;

Error
NativeProcessLinux::Monitor::Initialize()
{
    Error error;

    // We get a SIGCHLD every time something interesting happens with the inferior. We shall be
    // listening for these signals over a signalfd file descriptors. This allows us to wait for
    // multiple kinds of events with select.
    sigset_t signals;
    sigemptyset(&signals);
    sigaddset(&signals, SIGCHLD);
    m_signal_fd = signalfd(-1, &signals, SFD_NONBLOCK | SFD_CLOEXEC);
    if (m_signal_fd < 0)
    {
        return Error("NativeProcessLinux::Monitor::%s failed due to signalfd failure. Monitoring the inferior will be impossible: %s",
                    __FUNCTION__, strerror(errno));

    }

    if (pipe2(m_pipefd, O_CLOEXEC) == -1)
    {
        error.SetErrorToErrno();
        return error;
    }

    if ((error = EnsureFDFlags(m_pipefd[READ], O_NONBLOCK)).Fail()) {
        return error;
    }

    static const char g_thread_name[] = "lldb.process.nativelinux.monitor";
    m_thread = ThreadLauncher::LaunchThread(g_thread_name, Monitor::RunMonitor, this, nullptr);
    if (!m_thread.IsJoinable())
        return Error("Failed to create monitor thread for NativeProcessLinux.");

    // Wait for initial operation to complete.
    return WaitForAck();
}

Error
NativeProcessLinux::Monitor::DoOperation(const Operation &op)
{
    if (m_thread.EqualsThread(pthread_self())) {
        // If we're on the Monitor thread, we can simply execute the operation.
        return op();
    }

    // Otherwise we need to pass the operation to the Monitor thread so it can handle it.
    Mutex::Locker lock(m_operation_mutex);

    m_operation = &op;

    // notify the thread that an operation is ready to be processed
    write(m_pipefd[WRITE], &operation_command, sizeof operation_command);

    return WaitForAck();
}

void
NativeProcessLinux::Monitor::Terminate()
{
    if (m_pipefd[WRITE] >= 0)
    {
        close(m_pipefd[WRITE]);
        m_pipefd[WRITE] = -1;
    }
    if (m_thread.IsJoinable())
        m_thread.Join(nullptr);
}

NativeProcessLinux::Monitor::~Monitor()
{
    Terminate();
    if (m_pipefd[READ] >= 0)
        close(m_pipefd[READ]);
    if (m_signal_fd >= 0)
        close(m_signal_fd);
    sem_destroy(&m_operation_sem);
}

void
NativeProcessLinux::Monitor::HandleSignals()
{
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

    // We don't really care about the content of the SIGCHLD siginfo structure, as we will get
    // all the information from waitpid(). We just need to read all the signals so that we can
    // sleep next time we reach select().
    while (true)
    {
        signalfd_siginfo info;
        ssize_t size = read(m_signal_fd, &info, sizeof info);
        if (size == -1)
        {
            if (errno == EAGAIN || errno == EWOULDBLOCK)
                break; // We are done.
            if (errno == EINTR)
                continue;
            if (log)
                log->Printf("NativeProcessLinux::Monitor::%s reading from signalfd file descriptor failed: %s",
                        __FUNCTION__, strerror(errno));
            break;
        }
        if (size != sizeof info)
        {
            // We got incomplete information structure. This should not happen, let's just log
            // that.
            if (log)
                log->Printf("NativeProcessLinux::Monitor::%s reading from signalfd file descriptor returned incomplete data: "
                        "structure size is %zd, read returned %zd bytes",
                        __FUNCTION__, sizeof info, size);
            break;
        }
        if (log)
            log->Printf("NativeProcessLinux::Monitor::%s received signal %s(%d).", __FUNCTION__,
                Host::GetSignalAsCString(info.ssi_signo), info.ssi_signo);
    }
}

void
NativeProcessLinux::Monitor::HandleWait()
{
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
    // Process all pending waitpid notifications.
    while (true)
    {
        int status = -1;
        ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG);

        if (wait_pid == 0)
            break; // We are done.

        if (wait_pid == -1)
        {
            if (errno == EINTR)
                continue;

            if (log)
              log->Printf("NativeProcessLinux::Monitor::%s waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG) failed: %s",
                      __FUNCTION__, strerror(errno));
            break;
        }

        bool exited = false;
        int signal = 0;
        int exit_status = 0;
        const char *status_cstr = NULL;
        if (WIFSTOPPED(status))
        {
            signal = WSTOPSIG(status);
            status_cstr = "STOPPED";
        }
        else if (WIFEXITED(status))
        {
            exit_status = WEXITSTATUS(status);
            status_cstr = "EXITED";
            exited = true;
        }
        else if (WIFSIGNALED(status))
        {
            signal = WTERMSIG(status);
            status_cstr = "SIGNALED";
            if (wait_pid == m_child_pid) {
                exited = true;
                exit_status = -1;
            }
        }
        else
            status_cstr = "(\?\?\?)";

        if (log)
            log->Printf("NativeProcessLinux::Monitor::%s: waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG)"
                "=> pid = %" PRIi32 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i",
                __FUNCTION__, wait_pid, status, status_cstr, signal, exit_status);

        m_native_process->MonitorCallback (wait_pid, exited, signal, exit_status);
    }
}

bool
NativeProcessLinux::Monitor::HandleCommands()
{
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

    while (true)
    {
        char command = 0;
        ssize_t size = read(m_pipefd[READ], &command, sizeof command);
        if (size == -1)
        {
            if (errno == EAGAIN || errno == EWOULDBLOCK)
                return false;
            if (errno == EINTR)
                continue;
            if (log)
                log->Printf("NativeProcessLinux::Monitor::%s exiting because read from command file descriptor failed: %s", __FUNCTION__, strerror(errno));
            return true;
        }
        if (size == 0) // end of file - write end closed
        {
            if (log)
                log->Printf("NativeProcessLinux::Monitor::%s exit command received, exiting...", __FUNCTION__);
            assert(m_operation_nesting_level == 0 && "Unbalanced begin/end block commands detected");
            return true; // We are done.
        }

        switch (command)
        {
        case operation_command:
            m_operation_error = (*m_operation)();
            break;
        case begin_block_command:
            ++m_operation_nesting_level;
            break;
        case end_block_command:
            assert(m_operation_nesting_level > 0);
            --m_operation_nesting_level;
            break;
        default:
            if (log)
                log->Printf("NativeProcessLinux::Monitor::%s received unknown command '%c'",
                        __FUNCTION__, command);
        }

        // notify calling thread that the command has been processed
        sem_post(&m_operation_sem);
    }
}

void
NativeProcessLinux::Monitor::MainLoop()
{
    ::pid_t child_pid = (*m_initial_operation_up)(m_operation_error);
    m_initial_operation_up.reset();
    m_child_pid = child_pid;
    sem_post(&m_operation_sem);

    while (true)
    {
        fd_set fds;
        FD_ZERO(&fds);
        // Only process waitpid events if we are outside of an operation block. Any pending
        // events will be processed after we leave the block.
        if (m_operation_nesting_level == 0)
            FD_SET(m_signal_fd, &fds);
        FD_SET(m_pipefd[READ], &fds);

        int max_fd = std::max(m_signal_fd, m_pipefd[READ]) + 1;
        int r = select(max_fd, &fds, nullptr, nullptr, nullptr);
        if (r < 0)
        {
            Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
            if (log)
                log->Printf("NativeProcessLinux::Monitor::%s exiting because select failed: %s",
                        __FUNCTION__, strerror(errno));
            return;
        }

        if (FD_ISSET(m_pipefd[READ], &fds))
        {
            if (HandleCommands())
                return;
        }

        if (FD_ISSET(m_signal_fd, &fds))
        {
            HandleSignals();
            HandleWait();
        }
    }
}

Error
NativeProcessLinux::Monitor::WaitForAck()
{
    Error error;
    while (sem_wait(&m_operation_sem) != 0)
    {
        if (errno == EINTR)
            continue;

        error.SetErrorToErrno();
        return error;
    }

    return m_operation_error;
}

void *
NativeProcessLinux::Monitor::RunMonitor(void *arg)
{
    static_cast<Monitor *>(arg)->MainLoop();
    return nullptr;
}


NativeProcessLinux::LaunchArgs::LaunchArgs(Module *module,
                                       char const **argv,
                                       char const **envp,
                                       const FileSpec &stdin_file_spec,
                                       const FileSpec &stdout_file_spec,
                                       const FileSpec &stderr_file_spec,
                                       const FileSpec &working_dir,
                                       const ProcessLaunchInfo &launch_info)
    : m_module(module),
      m_argv(argv),
      m_envp(envp),
      m_stdin_file_spec(stdin_file_spec),
      m_stdout_file_spec(stdout_file_spec),
      m_stderr_file_spec(stderr_file_spec),
      m_working_dir(working_dir),
      m_launch_info(launch_info)
{
}

NativeProcessLinux::LaunchArgs::~LaunchArgs()
{ }

// -----------------------------------------------------------------------------
// Public Static Methods
// -----------------------------------------------------------------------------

Error
NativeProcessProtocol::Launch (
    ProcessLaunchInfo &launch_info,
    NativeProcessProtocol::NativeDelegate &native_delegate,
    NativeProcessProtocolSP &native_process_sp)
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    lldb::ModuleSP exe_module_sp;
    PlatformSP platform_sp (Platform::GetHostPlatform ());
    Error error = platform_sp->ResolveExecutable(
            ModuleSpec(launch_info.GetExecutableFile(), launch_info.GetArchitecture()),
            exe_module_sp,
            nullptr);

    if (! error.Success())
        return error;

    // Verify the working directory is valid if one was specified.
    FileSpec working_dir{launch_info.GetWorkingDirectory()};
    if (working_dir &&
            (!working_dir.ResolvePath() ||
             working_dir.GetFileType() != FileSpec::eFileTypeDirectory))
    {
        error.SetErrorStringWithFormat ("No such file or directory: %s",
                working_dir.GetCString());
        return error;
    }

    const FileAction *file_action;

    // Default of empty will mean to use existing open file descriptors.
    FileSpec stdin_file_spec{};
    FileSpec stdout_file_spec{};
    FileSpec stderr_file_spec{};

    file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
    if (file_action)
        stdin_file_spec = file_action->GetFileSpec();

    file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
    if (file_action)
        stdout_file_spec = file_action->GetFileSpec();

    file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
    if (file_action)
        stderr_file_spec = file_action->GetFileSpec();

    if (log)
    {
        if (stdin_file_spec)
            log->Printf ("NativeProcessLinux::%s setting STDIN to '%s'",
                    __FUNCTION__, stdin_file_spec.GetCString());
        else
            log->Printf ("NativeProcessLinux::%s leaving STDIN as is", __FUNCTION__);

        if (stdout_file_spec)
            log->Printf ("NativeProcessLinux::%s setting STDOUT to '%s'",
                    __FUNCTION__, stdout_file_spec.GetCString());
        else
            log->Printf ("NativeProcessLinux::%s leaving STDOUT as is", __FUNCTION__);

        if (stderr_file_spec)
            log->Printf ("NativeProcessLinux::%s setting STDERR to '%s'",
                    __FUNCTION__, stderr_file_spec.GetCString());
        else
            log->Printf ("NativeProcessLinux::%s leaving STDERR as is", __FUNCTION__);
    }

    // Create the NativeProcessLinux in launch mode.
    native_process_sp.reset (new NativeProcessLinux ());

    if (log)
    {
        int i = 0;
        for (const char **args = launch_info.GetArguments ().GetConstArgumentVector (); *args; ++args, ++i)
        {
            log->Printf ("NativeProcessLinux::%s arg %d: \"%s\"", __FUNCTION__, i, *args ? *args : "nullptr");
            ++i;
        }
    }

    if (!native_process_sp->RegisterNativeDelegate (native_delegate))
    {
        native_process_sp.reset ();
        error.SetErrorStringWithFormat ("failed to register the native delegate");
        return error;
    }

    std::static_pointer_cast<NativeProcessLinux> (native_process_sp)->LaunchInferior (
            exe_module_sp.get(),
            launch_info.GetArguments ().GetConstArgumentVector (),
            launch_info.GetEnvironmentEntries ().GetConstArgumentVector (),
            stdin_file_spec,
            stdout_file_spec,
            stderr_file_spec,
            working_dir,
            launch_info,
            error);

    if (error.Fail ())
    {
        native_process_sp.reset ();
        if (log)
            log->Printf ("NativeProcessLinux::%s failed to launch process: %s", __FUNCTION__, error.AsCString ());
        return error;
    }

    launch_info.SetProcessID (native_process_sp->GetID ());

    return error;
}

Error
NativeProcessProtocol::Attach (
    lldb::pid_t pid,
    NativeProcessProtocol::NativeDelegate &native_delegate,
    NativeProcessProtocolSP &native_process_sp)
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log && log->GetMask ().Test (POSIX_LOG_VERBOSE))
        log->Printf ("NativeProcessLinux::%s(pid = %" PRIi64 ")", __FUNCTION__, pid);

    // Grab the current platform architecture.  This should be Linux,
    // since this code is only intended to run on a Linux host.
    PlatformSP platform_sp (Platform::GetHostPlatform ());
    if (!platform_sp)
        return Error("failed to get a valid default platform");

    // Retrieve the architecture for the running process.
    ArchSpec process_arch;
    Error error = ResolveProcessArchitecture (pid, *platform_sp.get (), process_arch);
    if (!error.Success ())
        return error;

    std::shared_ptr<NativeProcessLinux> native_process_linux_sp (new NativeProcessLinux ());

    if (!native_process_linux_sp->RegisterNativeDelegate (native_delegate))
    {
        error.SetErrorStringWithFormat ("failed to register the native delegate");
        return error;
    }

    native_process_linux_sp->AttachToInferior (pid, error);
    if (!error.Success ())
        return error;

    native_process_sp = native_process_linux_sp;
    return error;
}

// -----------------------------------------------------------------------------
// Public Instance Methods
// -----------------------------------------------------------------------------

NativeProcessLinux::NativeProcessLinux () :
    NativeProcessProtocol (LLDB_INVALID_PROCESS_ID),
    m_arch (),
    m_supports_mem_region (eLazyBoolCalculate),
    m_mem_region_cache (),
    m_mem_region_cache_mutex ()
{
}

//------------------------------------------------------------------------------
// NativeProcessLinux spawns a new thread which performs all operations on the inferior process.
// Refer to Monitor and Operation classes to see why this is necessary.
//------------------------------------------------------------------------------
void
NativeProcessLinux::LaunchInferior (
    Module *module,
    const char *argv[],
    const char *envp[],
    const FileSpec &stdin_file_spec,
    const FileSpec &stdout_file_spec,
    const FileSpec &stderr_file_spec,
    const FileSpec &working_dir,
    const ProcessLaunchInfo &launch_info,
    Error &error)
{
    if (module)
        m_arch = module->GetArchitecture ();

    SetState (eStateLaunching);

    std::unique_ptr<LaunchArgs> args(
        new LaunchArgs(module, argv, envp,
                       stdin_file_spec,
                       stdout_file_spec,
                       stderr_file_spec,
                       working_dir,
                       launch_info));

    StartMonitorThread ([&] (Error &e) { return Launch(args.get(), e); }, error);
    if (!error.Success ())
        return;
}

void
NativeProcessLinux::AttachToInferior (lldb::pid_t pid, Error &error)
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ")", __FUNCTION__, pid);

    // We can use the Host for everything except the ResolveExecutable portion.
    PlatformSP platform_sp = Platform::GetHostPlatform ();
    if (!platform_sp)
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 "): no default platform set", __FUNCTION__, pid);
        error.SetErrorString ("no default platform available");
        return;
    }

    // Gather info about the process.
    ProcessInstanceInfo process_info;
    if (!platform_sp->GetProcessInfo (pid, process_info))
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 "): failed to get process info", __FUNCTION__, pid);
        error.SetErrorString ("failed to get process info");
        return;
    }

    // Resolve the executable module
    ModuleSP exe_module_sp;
    FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
    ModuleSpec exe_module_spec(process_info.GetExecutableFile(), process_info.GetArchitecture());
    error = platform_sp->ResolveExecutable(exe_module_spec, exe_module_sp,
                                           executable_search_paths.GetSize() ? &executable_search_paths : NULL);
    if (!error.Success())
        return;

    // Set the architecture to the exe architecture.
    m_arch = exe_module_sp->GetArchitecture();
    if (log)
        log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ") detected architecture %s", __FUNCTION__, pid, m_arch.GetArchitectureName ());

    m_pid = pid;
    SetState(eStateAttaching);

    StartMonitorThread ([=] (Error &e) { return Attach(pid, e); }, error);
    if (!error.Success ())
        return;
}

void
NativeProcessLinux::Terminate ()
{
    m_monitor_up->Terminate();
}

::pid_t
NativeProcessLinux::Launch(LaunchArgs *args, Error &error)
{
    assert (args && "null args");

    const char **argv = args->m_argv;
    const char **envp = args->m_envp;
    const FileSpec working_dir = args->m_working_dir;

    lldb_utility::PseudoTerminal terminal;
    const size_t err_len = 1024;
    char err_str[err_len];
    lldb::pid_t pid;
    NativeThreadProtocolSP thread_sp;

    lldb::ThreadSP inferior;

    // Propagate the environment if one is not supplied.
    if (envp == NULL || envp[0] == NULL)
        envp = const_cast<const char **>(environ);

    if ((pid = terminal.Fork(err_str, err_len)) == static_cast<lldb::pid_t> (-1))
    {
        error.SetErrorToGenericError();
        error.SetErrorStringWithFormat("Process fork failed: %s", err_str);
        return -1;
    }

    // Recognized child exit status codes.
    enum {
        ePtraceFailed = 1,
        eDupStdinFailed,
        eDupStdoutFailed,
        eDupStderrFailed,
        eChdirFailed,
        eExecFailed,
        eSetGidFailed
    };

    // Child process.
    if (pid == 0)
    {
        // FIXME consider opening a pipe between parent/child and have this forked child
        // send log info to parent re: launch status, in place of the log lines removed here.

        // Start tracing this child that is about to exec.
        error = PtraceWrapper(PTRACE_TRACEME, 0);
        if (error.Fail())
            exit(ePtraceFailed);

        // terminal has already dupped the tty descriptors to stdin/out/err.
        // This closes original fd from which they were copied (and avoids
        // leaking descriptors to the debugged process.
        terminal.CloseSlaveFileDescriptor();

        // Do not inherit setgid powers.
        if (setgid(getgid()) != 0)
            exit(eSetGidFailed);

        // Attempt to have our own process group.
        if (setpgid(0, 0) != 0)
        {
            // FIXME log that this failed. This is common.
            // Don't allow this to prevent an inferior exec.
        }

        // Dup file descriptors if needed.
        if (args->m_stdin_file_spec)
            if (!DupDescriptor(args->m_stdin_file_spec, STDIN_FILENO, O_RDONLY))
                exit(eDupStdinFailed);

        if (args->m_stdout_file_spec)
            if (!DupDescriptor(args->m_stdout_file_spec, STDOUT_FILENO, O_WRONLY | O_CREAT | O_TRUNC))
                exit(eDupStdoutFailed);

        if (args->m_stderr_file_spec)
            if (!DupDescriptor(args->m_stderr_file_spec, STDERR_FILENO, O_WRONLY | O_CREAT | O_TRUNC))
                exit(eDupStderrFailed);

        // Close everything besides stdin, stdout, and stderr that has no file
        // action to avoid leaking
        for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd)
            if (!args->m_launch_info.GetFileActionForFD(fd))
                close(fd);

        // Change working directory
        if (working_dir && 0 != ::chdir(working_dir.GetCString()))
              exit(eChdirFailed);

        // Disable ASLR if requested.
        if (args->m_launch_info.GetFlags ().Test (lldb::eLaunchFlagDisableASLR))
        {
            const int old_personality = personality (LLDB_PERSONALITY_GET_CURRENT_SETTINGS);
            if (old_personality == -1)
            {
                // Can't retrieve Linux personality.  Cannot disable ASLR.
            }
            else
            {
                const int new_personality = personality (ADDR_NO_RANDOMIZE | old_personality);
                if (new_personality == -1)
                {
                    // Disabling ASLR failed.
                }
                else
                {
                    // Disabling ASLR succeeded.
                }
            }
        }

        // Execute.  We should never return...
        execve(argv[0],
               const_cast<char *const *>(argv),
               const_cast<char *const *>(envp));

        // ...unless exec fails.  In which case we definitely need to end the child here.
        exit(eExecFailed);
    }

    //
    // This is the parent code here.
    //
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    // Wait for the child process to trap on its call to execve.
    ::pid_t wpid;
    int status;
    if ((wpid = waitpid(pid, &status, 0)) < 0)
    {
        error.SetErrorToErrno();
        if (log)
            log->Printf ("NativeProcessLinux::%s waitpid for inferior failed with %s",
                    __FUNCTION__, error.AsCString ());

        // Mark the inferior as invalid.
        // FIXME this could really use a new state - eStateLaunchFailure.  For now, using eStateInvalid.
        SetState (StateType::eStateInvalid);

        return -1;
    }
    else if (WIFEXITED(status))
    {
        // open, dup or execve likely failed for some reason.
        error.SetErrorToGenericError();
        switch (WEXITSTATUS(status))
        {
            case ePtraceFailed:
                error.SetErrorString("Child ptrace failed.");
                break;
            case eDupStdinFailed:
                error.SetErrorString("Child open stdin failed.");
                break;
            case eDupStdoutFailed:
                error.SetErrorString("Child open stdout failed.");
                break;
            case eDupStderrFailed:
                error.SetErrorString("Child open stderr failed.");
                break;
            case eChdirFailed:
                error.SetErrorString("Child failed to set working directory.");
                break;
            case eExecFailed:
                error.SetErrorString("Child exec failed.");
                break;
            case eSetGidFailed:
                error.SetErrorString("Child setgid failed.");
                break;
            default:
                error.SetErrorString("Child returned unknown exit status.");
                break;
        }

        if (log)
        {
            log->Printf ("NativeProcessLinux::%s inferior exited with status %d before issuing a STOP",
                    __FUNCTION__,
                    WEXITSTATUS(status));
        }

        // Mark the inferior as invalid.
        // FIXME this could really use a new state - eStateLaunchFailure.  For now, using eStateInvalid.
        SetState (StateType::eStateInvalid);

        return -1;
    }
    assert(WIFSTOPPED(status) && (wpid == static_cast< ::pid_t> (pid)) &&
           "Could not sync with inferior process.");

    if (log)
        log->Printf ("NativeProcessLinux::%s inferior started, now in stopped state", __FUNCTION__);

    error = SetDefaultPtraceOpts(pid);
    if (error.Fail())
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s inferior failed to set default ptrace options: %s",
                    __FUNCTION__, error.AsCString ());

        // Mark the inferior as invalid.
        // FIXME this could really use a new state - eStateLaunchFailure.  For now, using eStateInvalid.
        SetState (StateType::eStateInvalid);

        return -1;
    }

    // Release the master terminal descriptor and pass it off to the
    // NativeProcessLinux instance.  Similarly stash the inferior pid.
    m_terminal_fd = terminal.ReleaseMasterFileDescriptor();
    m_pid = pid;

    // Set the terminal fd to be in non blocking mode (it simplifies the
    // implementation of ProcessLinux::GetSTDOUT to have a non-blocking
    // descriptor to read from).
    error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
    if (error.Fail())
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s inferior EnsureFDFlags failed for ensuring terminal O_NONBLOCK setting: %s",
                    __FUNCTION__, error.AsCString ());

        // Mark the inferior as invalid.
        // FIXME this could really use a new state - eStateLaunchFailure.  For now, using eStateInvalid.
        SetState (StateType::eStateInvalid);

        return -1;
    }

    if (log)
        log->Printf ("NativeProcessLinux::%s() adding pid = %" PRIu64, __FUNCTION__, pid);

    thread_sp = AddThread (pid);
    assert (thread_sp && "AddThread() returned a nullptr thread");
    std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetStoppedBySignal (SIGSTOP);
    ThreadWasCreated(pid);

    // Let our process instance know the thread has stopped.
    SetCurrentThreadID (thread_sp->GetID ());
    SetState (StateType::eStateStopped);

    if (log)
    {
        if (error.Success ())
        {
            log->Printf ("NativeProcessLinux::%s inferior launching succeeded", __FUNCTION__);
        }
        else
        {
            log->Printf ("NativeProcessLinux::%s inferior launching failed: %s",
                __FUNCTION__, error.AsCString ());
            return -1;
        }
    }
    return pid;
}

::pid_t
NativeProcessLinux::Attach(lldb::pid_t pid, Error &error)
{
    lldb::ThreadSP inferior;
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    // Use a map to keep track of the threads which we have attached/need to attach.
    Host::TidMap tids_to_attach;
    if (pid <= 1)
    {
        error.SetErrorToGenericError();
        error.SetErrorString("Attaching to process 1 is not allowed.");
        return -1;
    }

    while (Host::FindProcessThreads(pid, tids_to_attach))
    {
        for (Host::TidMap::iterator it = tids_to_attach.begin();
             it != tids_to_attach.end();)
        {
            if (it->second == false)
            {
                lldb::tid_t tid = it->first;

                // Attach to the requested process.
                // An attach will cause the thread to stop with a SIGSTOP.
                error = PtraceWrapper(PTRACE_ATTACH, tid);
                if (error.Fail())
                {
                    // No such thread. The thread may have exited.
                    // More error handling may be needed.
                    if (error.GetError() == ESRCH)
                    {
                        it = tids_to_attach.erase(it);
                        continue;
                    }
                    else
                        return -1;
                }

                int status;
                // Need to use __WALL otherwise we receive an error with errno=ECHLD
                // At this point we should have a thread stopped if waitpid succeeds.
                if ((status = waitpid(tid, NULL, __WALL)) < 0)
                {
                    // No such thread. The thread may have exited.
                    // More error handling may be needed.
                    if (errno == ESRCH)
                    {
                        it = tids_to_attach.erase(it);
                        continue;
                    }
                    else
                    {
                        error.SetErrorToErrno();
                        return -1;
                    }
                }

                error = SetDefaultPtraceOpts(tid);
                if (error.Fail())
                    return -1;

                if (log)
                    log->Printf ("NativeProcessLinux::%s() adding tid = %" PRIu64, __FUNCTION__, tid);

                it->second = true;

                // Create the thread, mark it as stopped.
                NativeThreadProtocolSP thread_sp (AddThread (static_cast<lldb::tid_t> (tid)));
                assert (thread_sp && "AddThread() returned a nullptr");

                // This will notify this is a new thread and tell the system it is stopped.
                std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetStoppedBySignal (SIGSTOP);
                ThreadWasCreated(tid);
                SetCurrentThreadID (thread_sp->GetID ());
            }

            // move the loop forward
            ++it;
        }
    }

    if (tids_to_attach.size() > 0)
    {
        m_pid = pid;
        // Let our process instance know the thread has stopped.
        SetState (StateType::eStateStopped);
    }
    else
    {
        error.SetErrorToGenericError();
        error.SetErrorString("No such process.");
        return -1;
    }

    return pid;
}

Error
NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid)
{
    long ptrace_opts = 0;

    // Have the child raise an event on exit.  This is used to keep the child in
    // limbo until it is destroyed.
    ptrace_opts |= PTRACE_O_TRACEEXIT;

    // Have the tracer trace threads which spawn in the inferior process.
    // TODO: if we want to support tracing the inferiors' child, add the
    // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK)
    ptrace_opts |= PTRACE_O_TRACECLONE;

    // Have the tracer notify us before execve returns
    // (needed to disable legacy SIGTRAP generation)
    ptrace_opts |= PTRACE_O_TRACEEXEC;

    return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void*)ptrace_opts);
}

static ExitType convert_pid_status_to_exit_type (int status)
{
    if (WIFEXITED (status))
        return ExitType::eExitTypeExit;
    else if (WIFSIGNALED (status))
        return ExitType::eExitTypeSignal;
    else if (WIFSTOPPED (status))
        return ExitType::eExitTypeStop;
    else
    {
        // We don't know what this is.
        return ExitType::eExitTypeInvalid;
    }
}

static int convert_pid_status_to_return_code (int status)
{
    if (WIFEXITED (status))
        return WEXITSTATUS (status);
    else if (WIFSIGNALED (status))
        return WTERMSIG (status);
    else if (WIFSTOPPED (status))
        return WSTOPSIG (status);
    else
    {
        // We don't know what this is.
        return ExitType::eExitTypeInvalid;
    }
}

// Handles all waitpid events from the inferior process.
void
NativeProcessLinux::MonitorCallback(lldb::pid_t pid,
                                    bool exited,
                                    int signal,
                                    int status)
{
    Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));

    // Certain activities differ based on whether the pid is the tid of the main thread.
    const bool is_main_thread = (pid == GetID ());

    // Handle when the thread exits.
    if (exited)
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s() got exit signal(%d) , tid = %"  PRIu64 " (%s main thread)", __FUNCTION__, signal, pid, is_main_thread ? "is" : "is not");

        // This is a thread that exited.  Ensure we're not tracking it anymore.
        const bool thread_found = StopTrackingThread (pid);

        if (is_main_thread)
        {
            // We only set the exit status and notify the delegate if we haven't already set the process
            // state to an exited state.  We normally should have received a SIGTRAP | (PTRACE_EVENT_EXIT << 8)
            // for the main thread.
            const bool already_notified = (GetState() == StateType::eStateExited) || (GetState () == StateType::eStateCrashed);
            if (!already_notified)
            {
                if (log)
                    log->Printf ("NativeProcessLinux::%s() tid = %"  PRIu64 " handling main thread exit (%s), expected exit state already set but state was %s instead, setting exit state now", __FUNCTION__, pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found", StateAsCString (GetState ()));
                // The main thread exited.  We're done monitoring.  Report to delegate.
                SetExitStatus (convert_pid_status_to_exit_type (status), convert_pid_status_to_return_code (status), nullptr, true);

                // Notify delegate that our process has exited.
                SetState (StateType::eStateExited, true);
            }
            else
            {
                if (log)
                    log->Printf ("NativeProcessLinux::%s() tid = %"  PRIu64 " main thread now exited (%s)", __FUNCTION__, pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found");
            }
        }
        else
        {
            // Do we want to report to the delegate in this case?  I think not.  If this was an orderly
            // thread exit, we would already have received the SIGTRAP | (PTRACE_EVENT_EXIT << 8) signal,
            // and we would have done an all-stop then.
            if (log)
                log->Printf ("NativeProcessLinux::%s() tid = %"  PRIu64 " handling non-main thread exit (%s)", __FUNCTION__, pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found");
        }
        return;
    }

    // Get details on the signal raised.
    siginfo_t info;
    const auto err = GetSignalInfo(pid, &info);
    if (err.Success())
    {
        // We have retrieved the signal info.  Dispatch appropriately.
        if (info.si_signo == SIGTRAP)
            MonitorSIGTRAP(&info, pid);
        else
            MonitorSignal(&info, pid, exited);
    }
    else
    {
        if (err.GetError() == EINVAL)
        {
            // This is a group stop reception for this tid.
            // We can reach here if we reinject SIGSTOP, SIGSTP, SIGTTIN or SIGTTOU into the
            // tracee, triggering the group-stop mechanism. Normally receiving these would stop
            // the process, pending a SIGCONT. Simulating this state in a debugger is hard and is
            // generally not needed (one use case is debugging background task being managed by a
            // shell). For general use, it is sufficient to stop the process in a signal-delivery
            // stop which happens before the group stop. This done by MonitorSignal and works
            // correctly for all signals.
            if (log)
                log->Printf("NativeProcessLinux::%s received a group stop for pid %" PRIu64 " tid %" PRIu64 ". Transparent handling of group stops not supported, resuming the thread.", __FUNCTION__, GetID (), pid);
            Resume(pid, signal);
        }
        else
        {
            // ptrace(GETSIGINFO) failed (but not due to group-stop).

            // A return value of ESRCH means the thread/process is no longer on the system,
            // so it was killed somehow outside of our control.  Either way, we can't do anything
            // with it anymore.

            // Stop tracking the metadata for the thread since it's entirely off the system now.
            const bool thread_found = StopTrackingThread (pid);

            if (log)
                log->Printf ("NativeProcessLinux::%s GetSignalInfo failed: %s, tid = %" PRIu64 ", signal = %d, status = %d (%s, %s, %s)",
                             __FUNCTION__, err.AsCString(), pid, signal, status, err.GetError() == ESRCH ? "thread/process killed" : "unknown reason", is_main_thread ? "is main thread" : "is not main thread", thread_found ? "thread metadata removed" : "thread metadata not found");

            if (is_main_thread)
            {
                // Notify the delegate - our process is not available but appears to have been killed outside
                // our control.  Is eStateExited the right exit state in this case?
                SetExitStatus (convert_pid_status_to_exit_type (status), convert_pid_status_to_return_code (status), nullptr, true);
                SetState (StateType::eStateExited, true);
            }
            else
            {
                // This thread was pulled out from underneath us.  Anything to do here? Do we want to do an all stop?
                if (log)
                    log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 " non-main thread exit occurred, didn't tell delegate anything since thread disappeared out from underneath us", __FUNCTION__, GetID (), pid);
            }
        }
    }
}

void
NativeProcessLinux::WaitForNewThread(::pid_t tid)
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    NativeThreadProtocolSP new_thread_sp = GetThreadByID(tid);

    if (new_thread_sp)
    {
        // We are already tracking the thread - we got the event on the new thread (see
        // MonitorSignal) before this one. We are done.
        return;
    }

    // The thread is not tracked yet, let's wait for it to appear.
    int status = -1;
    ::pid_t wait_pid;
    do
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s() received thread creation event for tid %" PRIu32 ". tid not tracked yet, waiting for thread to appear...", __FUNCTION__, tid);
        wait_pid = waitpid(tid, &status, __WALL);
    }
    while (wait_pid == -1 && errno == EINTR);
    // Since we are waiting on a specific tid, this must be the creation event. But let's do
    // some checks just in case.
    if (wait_pid != tid) {
        if (log)
            log->Printf ("NativeProcessLinux::%s() waiting for tid %" PRIu32 " failed. Assuming the thread has disappeared in the meantime", __FUNCTION__, tid);
        // The only way I know of this could happen is if the whole process was
        // SIGKILLed in the mean time. In any case, we can't do anything about that now.
        return;
    }
    if (WIFEXITED(status))
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s() waiting for tid %" PRIu32 " returned an 'exited' event. Not tracking the thread.", __FUNCTION__, tid);
        // Also a very improbable event.
        return;
    }

    siginfo_t info;
    Error error = GetSignalInfo(tid, &info);
    if (error.Fail())
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32 " failed. Assuming the thread has disappeared in the meantime.", __FUNCTION__, tid);
        return;
    }

    if (((info.si_pid != 0) || (info.si_code != SI_USER)) && log)
    {
        // We should be getting a thread creation signal here, but we received something
        // else. There isn't much we can do about it now, so we will just log that. Since the
        // thread is alive and we are receiving events from it, we shall pretend that it was
        // created properly.
        log->Printf ("NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32 " received unexpected signal with code %d from pid %d.", __FUNCTION__, tid, info.si_code, info.si_pid);
    }

    if (log)
        log->Printf ("NativeProcessLinux::%s() pid = %" PRIu64 ": tracking new thread tid %" PRIu32,
                 __FUNCTION__, GetID (), tid);

    new_thread_sp = AddThread(tid);
    std::static_pointer_cast<NativeThreadLinux> (new_thread_sp)->SetRunning ();
    Resume (tid, LLDB_INVALID_SIGNAL_NUMBER);
    ThreadWasCreated(tid);
}

void
NativeProcessLinux::MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid)
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    const bool is_main_thread = (pid == GetID ());

    assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!");
    if (!info)
        return;

    Mutex::Locker locker (m_threads_mutex);

    // See if we can find a thread for this signal.
    NativeThreadProtocolSP thread_sp = GetThreadByID (pid);
    if (!thread_sp)
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " no thread found for tid %" PRIu64, __FUNCTION__, GetID (), pid);
    }

    switch (info->si_code)
    {
    // TODO: these two cases are required if we want to support tracing of the inferiors' children.  We'd need this to debug a monitor.
    // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)):
    // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):

    case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)):
    {
        // This is the notification on the parent thread which informs us of new thread
        // creation.
        // We don't want to do anything with the parent thread so we just resume it. In case we
        // want to implement "break on thread creation" functionality, we would need to stop
        // here.

        unsigned long event_message = 0;
        if (GetEventMessage (pid, &event_message).Fail())
        {
            if (log)
                log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " received thread creation event but GetEventMessage failed so we don't know the new tid", __FUNCTION__, pid);
        } else 
            WaitForNewThread(event_message);

        Resume (pid, LLDB_INVALID_SIGNAL_NUMBER);
        break;
    }

    case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)):
    {
        NativeThreadProtocolSP main_thread_sp;
        if (log)
            log->Printf ("NativeProcessLinux::%s() received exec event, code = %d", __FUNCTION__, info->si_code ^ SIGTRAP);

        // Exec clears any pending notifications.
        m_pending_notification_up.reset ();

        // Remove all but the main thread here.  Linux fork creates a new process which only copies the main thread.  Mutexes are in undefined state.
        if (log)
            log->Printf ("NativeProcessLinux::%s exec received, stop tracking all but main thread", __FUNCTION__);

        for (auto thread_sp : m_threads)
        {
            const bool is_main_thread = thread_sp && thread_sp->GetID () == GetID ();
            if (is_main_thread)
            {
                main_thread_sp = thread_sp;
                if (log)
                    log->Printf ("NativeProcessLinux::%s found main thread with tid %" PRIu64 ", keeping", __FUNCTION__, main_thread_sp->GetID ());
            }
            else
            {
                // Tell thread coordinator this thread is dead.
                if (log)
                    log->Printf ("NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64 " due to exec", __FUNCTION__, thread_sp->GetID ());
            }
        }

        m_threads.clear ();

        if (main_thread_sp)
        {
            m_threads.push_back (main_thread_sp);
            SetCurrentThreadID (main_thread_sp->GetID ());
            std::static_pointer_cast<NativeThreadLinux> (main_thread_sp)->SetStoppedByExec ();
        }
        else
        {
            SetCurrentThreadID (LLDB_INVALID_THREAD_ID);
            if (log)
                log->Printf ("NativeProcessLinux::%s pid %" PRIu64 "no main thread found, discarded all threads, we're in a no-thread state!", __FUNCTION__, GetID ());
        }

        // Tell coordinator about about the "new" (since exec) stopped main thread.
        const lldb::tid_t main_thread_tid = GetID ();
        ThreadWasCreated(main_thread_tid);

        // NOTE: ideally these next statements would execute at the same time as the coordinator thread create was executed.
        // Consider a handler that can execute when that happens.
        // Let our delegate know we have just exec'd.
        NotifyDidExec ();

        // If we have a main thread, indicate we are stopped.
        assert (main_thread_sp && "exec called during ptraced process but no main thread metadata tracked");

        // Let the process know we're stopped.
        StopRunningThreads (pid);

        break;
    }

    case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)):
    {
        // The inferior process or one of its threads is about to exit.
        // We don't want to do anything with the thread so we just resume it. In case we
        // want to implement "break on thread exit" functionality, we would need to stop
        // here.

        unsigned long data = 0;
        if (GetEventMessage(pid, &data).Fail())
            data = -1;

        if (log)
        {
            log->Printf ("NativeProcessLinux::%s() received PTRACE_EVENT_EXIT, data = %lx (WIFEXITED=%s,WIFSIGNALED=%s), pid = %" PRIu64 " (%s)",
                         __FUNCTION__,
                         data, WIFEXITED (data) ? "true" : "false", WIFSIGNALED (data) ? "true" : "false",
                         pid,
                    is_main_thread ? "is main thread" : "not main thread");
        }

        if (is_main_thread)
        {
            SetExitStatus (convert_pid_status_to_exit_type (data), convert_pid_status_to_return_code (data), nullptr, true);
        }

        Resume(pid, LLDB_INVALID_SIGNAL_NUMBER);

        break;
    }

    case 0:
    case TRAP_TRACE:  // We receive this on single stepping.
    case TRAP_HWBKPT: // We receive this on watchpoint hit
        if (thread_sp)
        {
            // If a watchpoint was hit, report it
            uint32_t wp_index;
            Error error = thread_sp->GetRegisterContext()->GetWatchpointHitIndex(wp_index, (lldb::addr_t)info->si_addr);
            if (error.Fail() && log)
                log->Printf("NativeProcessLinux::%s() "
                            "received error while checking for watchpoint hits, "
                            "pid = %" PRIu64 " error = %s",
                            __FUNCTION__, pid, error.AsCString());
            if (wp_index != LLDB_INVALID_INDEX32)
            {
                MonitorWatchpoint(pid, thread_sp, wp_index);
                break;
            }
        }
        // Otherwise, report step over
        MonitorTrace(pid, thread_sp);
        break;

    case SI_KERNEL:
#if defined __mips__
        // For mips there is no special signal for watchpoint
        // So we check for watchpoint in kernel trap
        if (thread_sp)
        {
            // If a watchpoint was hit, report it
            uint32_t wp_index;
            Error error = thread_sp->GetRegisterContext()->GetWatchpointHitIndex(wp_index, LLDB_INVALID_ADDRESS);
            if (error.Fail() && log)
                log->Printf("NativeProcessLinux::%s() "
                            "received error while checking for watchpoint hits, "
                            "pid = %" PRIu64 " error = %s",
                            __FUNCTION__, pid, error.AsCString());
            if (wp_index != LLDB_INVALID_INDEX32)
            {
                MonitorWatchpoint(pid, thread_sp, wp_index);
                break;
            }
        }
        // NO BREAK
#endif
    case TRAP_BRKPT:
        MonitorBreakpoint(pid, thread_sp);
        break;

    case SIGTRAP:
    case (SIGTRAP | 0x80):
        if (log)
            log->Printf ("NativeProcessLinux::%s() received unknown SIGTRAP system call stop event, pid %" PRIu64 "tid %" PRIu64 ", resuming", __FUNCTION__, GetID (), pid);

        // Ignore these signals until we know more about them.
        Resume(pid, LLDB_INVALID_SIGNAL_NUMBER);
        break;

    default:
        assert(false && "Unexpected SIGTRAP code!");
        if (log)
            log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 "tid %" PRIu64 " received unhandled SIGTRAP code: 0x%d",
                    __FUNCTION__, GetID (), pid, info->si_code);
        break;
        
    }
}

void
NativeProcessLinux::MonitorTrace(lldb::pid_t pid, NativeThreadProtocolSP thread_sp)
{
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf("NativeProcessLinux::%s() received trace event, pid = %" PRIu64 " (single stepping)",
                __FUNCTION__, pid);

    if (thread_sp)
        std::static_pointer_cast<NativeThreadLinux>(thread_sp)->SetStoppedByTrace();

    // This thread is currently stopped.
    ThreadDidStop(pid, false);

    // Here we don't have to request the rest of the threads to stop or request a deferred stop.
    // This would have already happened at the time the Resume() with step operation was signaled.
    // At this point, we just need to say we stopped, and the deferred notifcation will fire off
    // once all running threads have checked in as stopped.
    SetCurrentThreadID(pid);
    // Tell the process we have a stop (from software breakpoint).
    StopRunningThreads(pid);
}

void
NativeProcessLinux::MonitorBreakpoint(lldb::pid_t pid, NativeThreadProtocolSP thread_sp)
{
    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS));
    if (log)
        log->Printf("NativeProcessLinux::%s() received breakpoint event, pid = %" PRIu64,
                __FUNCTION__, pid);

    // This thread is currently stopped.
    ThreadDidStop(pid, false);

    // Mark the thread as stopped at breakpoint.
    if (thread_sp)
    {
        std::static_pointer_cast<NativeThreadLinux>(thread_sp)->SetStoppedByBreakpoint();
        Error error = FixupBreakpointPCAsNeeded(thread_sp);
        if (error.Fail())
            if (log)
                log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 " fixup: %s",
                        __FUNCTION__, pid, error.AsCString());

        if (m_threads_stepping_with_breakpoint.find(pid) != m_threads_stepping_with_breakpoint.end())
            std::static_pointer_cast<NativeThreadLinux>(thread_sp)->SetStoppedByTrace();
    }
    else
        if (log)
            log->Printf("NativeProcessLinux::%s()  pid = %" PRIu64 ": "
                    "warning, cannot process software breakpoint since no thread metadata",
                    __FUNCTION__, pid);


    // We need to tell all other running threads before we notify the delegate about this stop.
    StopRunningThreads(pid);
}

void
NativeProcessLinux::MonitorWatchpoint(lldb::pid_t pid, NativeThreadProtocolSP thread_sp, uint32_t wp_index)
{
    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_WATCHPOINTS));
    if (log)
        log->Printf("NativeProcessLinux::%s() received watchpoint event, "
                    "pid = %" PRIu64 ", wp_index = %" PRIu32,
                    __FUNCTION__, pid, wp_index);

    // This thread is currently stopped.
    ThreadDidStop(pid, false);

    // Mark the thread as stopped at watchpoint.
    // The address is at (lldb::addr_t)info->si_addr if we need it.
    lldbassert(thread_sp && "thread_sp cannot be NULL");
    std::static_pointer_cast<NativeThreadLinux>(thread_sp)->SetStoppedByWatchpoint(wp_index);

    // We need to tell all other running threads before we notify the delegate about this stop.
    StopRunningThreads(pid);
}

void
NativeProcessLinux::MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool exited)
{
    assert (info && "null info");
    if (!info)
        return;

    const int signo = info->si_signo;
    const bool is_from_llgs = info->si_pid == getpid ();

    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    // 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 Linux.
    //
    // IOW, user generated signals never generate what we consider to be a
    // "crash".
    //
    // Similarly, ACK signals generated by this monitor.

    Mutex::Locker locker (m_threads_mutex);

    // See if we can find a thread for this signal.
    NativeThreadProtocolSP thread_sp = GetThreadByID (pid);
    if (!thread_sp)
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " no thread found for tid %" PRIu64, __FUNCTION__, GetID (), pid);
    }

    // Handle the signal.
    if (info->si_code == SI_TKILL || info->si_code == SI_USER)
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s() received signal %s (%d) with code %s, (siginfo pid = %d (%s), waitpid pid = %" PRIu64 ")",
                            __FUNCTION__,
                            Host::GetSignalAsCString(signo),
                            signo,
                            (info->si_code == SI_TKILL ? "SI_TKILL" : "SI_USER"),
                            info->si_pid,
                            is_from_llgs ? "from llgs" : "not from llgs",
                            pid);
    }

    // Check for new thread notification.
    if ((info->si_pid == 0) && (info->si_code == SI_USER))
    {
        // A new thread creation is being signaled. This is one of two parts that come in
        // a non-deterministic order. This code handles the case where the new thread event comes
        // before the event on the parent thread. For the opposite case see code in
        // MonitorSIGTRAP.
        if (log)
            log->Printf ("NativeProcessLinux::%s() pid = %" PRIu64 " tid %" PRIu64 ": new thread notification",
                     __FUNCTION__, GetID (), pid);

        thread_sp = AddThread(pid);
        assert (thread_sp.get() && "failed to create the tracking data for newly created inferior thread");
        // We can now resume the newly created thread.
        std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetRunning ();
        Resume (pid, LLDB_INVALID_SIGNAL_NUMBER);
        ThreadWasCreated(pid);
        // Done handling.
        return;
    }

    // Check for thread stop notification.
    if (is_from_llgs && (info->si_code == SI_TKILL) && (signo == SIGSTOP))
    {
        // This is a tgkill()-based stop.
        if (thread_sp)
        {
            if (log)
                log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64 ", thread stopped",
                             __FUNCTION__,
                             GetID (),
                             pid);

            // Check that we're not already marked with a stop reason.
            // Note this thread really shouldn't already be marked as stopped - if we were, that would imply that
            // the kernel signaled us with the thread stopping which we handled and marked as stopped,
            // and that, without an intervening resume, we received another stop.  It is more likely
            // that we are missing the marking of a run state somewhere if we find that the thread was
            // marked as stopped.
            std::shared_ptr<NativeThreadLinux> linux_thread_sp = std::static_pointer_cast<NativeThreadLinux> (thread_sp);
            assert (linux_thread_sp && "linux_thread_sp is null!");

            const StateType thread_state = linux_thread_sp->GetState ();
            if (!StateIsStoppedState (thread_state, false))
            {
                // An inferior thread has stopped because of a SIGSTOP we have sent it.
                // Generally, these are not important stops and we don't want to report them as
                // they are just used to stop other threads when one thread (the one with the
                // *real* stop reason) hits a breakpoint (watchpoint, etc...). However, in the
                // case of an asynchronous Interrupt(), this *is* the real stop reason, so we
                // leave the signal intact if this is the thread that was chosen as the
                // triggering thread.
                if (m_pending_notification_up && m_pending_notification_up->triggering_tid == pid)
                    linux_thread_sp->SetStoppedBySignal(SIGSTOP, info);
                else
                    linux_thread_sp->SetStoppedBySignal(0);

                SetCurrentThreadID (thread_sp->GetID ());
                ThreadDidStop (thread_sp->GetID (), true);
            }
            else
            {
                if (log)
                {
                    // Retrieve the signal name if the thread was stopped by a signal.
                    int stop_signo = 0;
                    const bool stopped_by_signal = linux_thread_sp->IsStopped (&stop_signo);
                    const char *signal_name = stopped_by_signal ? Host::GetSignalAsCString(stop_signo) : "<not stopped by signal>";
                    if (!signal_name)
                        signal_name = "<no-signal-name>";

                    log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64 ", thread was already marked as a stopped state (state=%s, signal=%d (%s)), leaving stop signal as is",
                                 __FUNCTION__,
                                 GetID (),
                                 linux_thread_sp->GetID (),
                                 StateAsCString (thread_state),
                                 stop_signo,
                                 signal_name);
                }
                ThreadDidStop (thread_sp->GetID (), false);
            }
        }

        // Done handling.
        return;
    }

    if (log)
        log->Printf ("NativeProcessLinux::%s() received signal %s", __FUNCTION__, Host::GetSignalAsCString(signo));

    // This thread is stopped.
    ThreadDidStop (pid, false);

    if (thread_sp)
        std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetStoppedBySignal(signo, info);

    // Send a stop to the debugger after we get all other threads to stop.
    StopRunningThreads (pid);
}

namespace {

struct EmulatorBaton
{
    NativeProcessLinux* m_process;
    NativeRegisterContext* m_reg_context;

    // eRegisterKindDWARF -> RegsiterValue
    std::unordered_map<uint32_t, RegisterValue> m_register_values;

    EmulatorBaton(NativeProcessLinux* process, NativeRegisterContext* reg_context) :
            m_process(process), m_reg_context(reg_context) {}
};

} // anonymous namespace

static size_t
ReadMemoryCallback (EmulateInstruction *instruction,
                    void *baton,
                    const EmulateInstruction::Context &context, 
                    lldb::addr_t addr, 
                    void *dst,
                    size_t length)
{
    EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);

    size_t bytes_read;
    emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read);
    return bytes_read;
}

static bool
ReadRegisterCallback (EmulateInstruction *instruction,
                      void *baton,
                      const RegisterInfo *reg_info,
                      RegisterValue &reg_value)
{
    EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);

    auto it = emulator_baton->m_register_values.find(reg_info->kinds[eRegisterKindDWARF]);
    if (it != emulator_baton->m_register_values.end())
    {
        reg_value = it->second;
        return true;
    }

    // The emulator only fill in the dwarf regsiter numbers (and in some case
    // the generic register numbers). Get the full register info from the
    // register context based on the dwarf register numbers.
    const RegisterInfo* full_reg_info = emulator_baton->m_reg_context->GetRegisterInfo(
            eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);

    Error error = emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value);
    if (error.Success())
        return true;

    return false;
}

static bool
WriteRegisterCallback (EmulateInstruction *instruction,
                       void *baton,
                       const EmulateInstruction::Context &context,
                       const RegisterInfo *reg_info,
                       const RegisterValue &reg_value)
{
    EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);
    emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = reg_value;
    return true;
}

static size_t
WriteMemoryCallback (EmulateInstruction *instruction,
                     void *baton,
                     const EmulateInstruction::Context &context, 
                     lldb::addr_t addr, 
                     const void *dst,
                     size_t length)
{
    return length;
}

static lldb::addr_t
ReadFlags (NativeRegisterContext* regsiter_context)
{
    const RegisterInfo* flags_info = regsiter_context->GetRegisterInfo(
            eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
    return regsiter_context->ReadRegisterAsUnsigned(flags_info, LLDB_INVALID_ADDRESS);
}

Error
NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadProtocolSP thread_sp)
{
    Error error;
    NativeRegisterContextSP register_context_sp = thread_sp->GetRegisterContext();

    std::unique_ptr<EmulateInstruction> emulator_ap(
        EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying, nullptr));

    if (emulator_ap == nullptr)
        return Error("Instruction emulator not found!");

    EmulatorBaton baton(this, register_context_sp.get());
    emulator_ap->SetBaton(&baton);
    emulator_ap->SetReadMemCallback(&ReadMemoryCallback);
    emulator_ap->SetReadRegCallback(&ReadRegisterCallback);
    emulator_ap->SetWriteMemCallback(&WriteMemoryCallback);
    emulator_ap->SetWriteRegCallback(&WriteRegisterCallback);

    if (!emulator_ap->ReadInstruction())
        return Error("Read instruction failed!");

    bool emulation_result = emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);

    const RegisterInfo* reg_info_pc = register_context_sp->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
    const RegisterInfo* reg_info_flags = register_context_sp->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);

    auto pc_it = baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);
    auto flags_it = baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]);

    lldb::addr_t next_pc;
    lldb::addr_t next_flags;
    if (emulation_result)
    {
        assert(pc_it != baton.m_register_values.end() && "Emulation was successfull but PC wasn't updated");
        next_pc = pc_it->second.GetAsUInt64();

        if (flags_it != baton.m_register_values.end())
            next_flags = flags_it->second.GetAsUInt64();
        else
            next_flags = ReadFlags (register_context_sp.get());
    }
    else if (pc_it == baton.m_register_values.end())
    {
        // Emulate instruction failed and it haven't changed PC. Advance PC
        // with the size of the current opcode because the emulation of all
        // PC modifying instruction should be successful. The failure most
        // likely caused by a not supported instruction which don't modify PC.
        next_pc = register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize();
        next_flags = ReadFlags (register_context_sp.get());
    }
    else
    {
        // The instruction emulation failed after it modified the PC. It is an
        // unknown error where we can't continue because the next instruction is
        // modifying the PC but we don't  know how.
        return Error ("Instruction emulation failed unexpectedly.");
    }

    if (m_arch.GetMachine() == llvm::Triple::arm)
    {
        if (next_flags & 0x20)
        {
            // Thumb mode
            error = SetSoftwareBreakpoint(next_pc, 2);
        }
        else
        {
            // Arm mode
            error = SetSoftwareBreakpoint(next_pc, 4);
        }
    }
    else if (m_arch.GetMachine() == llvm::Triple::mips64
            || m_arch.GetMachine() == llvm::Triple::mips64el
            || m_arch.GetMachine() == llvm::Triple::mips
            || m_arch.GetMachine() == llvm::Triple::mipsel)
        error = SetSoftwareBreakpoint(next_pc, 4);
    else
    {
        // No size hint is given for the next breakpoint
        error = SetSoftwareBreakpoint(next_pc, 0);
    }

    if (error.Fail())
        return error;

    m_threads_stepping_with_breakpoint.insert({thread_sp->GetID(), next_pc});

    return Error();
}

bool
NativeProcessLinux::SupportHardwareSingleStepping() const
{
    if (m_arch.GetMachine() == llvm::Triple::arm
        || m_arch.GetMachine() == llvm::Triple::mips64 || m_arch.GetMachine() == llvm::Triple::mips64el
        || m_arch.GetMachine() == llvm::Triple::mips || m_arch.GetMachine() == llvm::Triple::mipsel)
        return false;
    return true;
}

Error
NativeProcessLinux::Resume (const ResumeActionList &resume_actions)
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
    if (log)
        log->Printf ("NativeProcessLinux::%s called: pid %" PRIu64, __FUNCTION__, GetID ());

    bool software_single_step = !SupportHardwareSingleStepping();

    Monitor::ScopedOperationLock monitor_lock(*m_monitor_up);
    Mutex::Locker locker (m_threads_mutex);

    if (software_single_step)
    {
        for (auto thread_sp : m_threads)
        {
            assert (thread_sp && "thread list should not contain NULL threads");

            const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true);
            if (action == nullptr)
                continue;

            if (action->state == eStateStepping)
            {
                Error error = SetupSoftwareSingleStepping(thread_sp);
                if (error.Fail())
                    return error;
            }
        }
    }

    for (auto thread_sp : m_threads)
    {
        assert (thread_sp && "thread list should not contain NULL threads");

        const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true);

        if (action == nullptr)
        {
            if (log)
                log->Printf ("NativeProcessLinux::%s no action specified for pid %" PRIu64 " tid %" PRIu64,
                    __FUNCTION__, GetID (), thread_sp->GetID ());
            continue;
        }

        if (log)
        {
            log->Printf ("NativeProcessLinux::%s processing resume action state %s for pid %" PRIu64 " tid %" PRIu64, 
                    __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ());
        }

        switch (action->state)
        {
        case eStateRunning:
        {
            // Run the thread, possibly feeding it the signal.
            const int signo = action->signal;
            ResumeThread(thread_sp->GetID (),
                    [=](lldb::tid_t tid_to_resume, bool supress_signal)
                    {
                        std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetRunning ();
                        // Pass this signal number on to the inferior to handle.
                        const auto resume_result = Resume (tid_to_resume, (signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
                        if (resume_result.Success())
                            SetState(eStateRunning, true);
                        return resume_result;
                    },
                    false);
            break;
        }

        case eStateStepping:
        {
            // Request the step.
            const int signo = action->signal;
            ResumeThread(thread_sp->GetID (),
                    [=](lldb::tid_t tid_to_step, bool supress_signal)
                    {
                        std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetStepping ();

                        Error step_result;
                        if (software_single_step)
                            step_result = Resume (tid_to_step, (signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
                        else
                            step_result = SingleStep (tid_to_step,(signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);

                        assert (step_result.Success() && "SingleStep() failed");
                        if (step_result.Success())
                            SetState(eStateStepping, true);
                        return step_result;
                    },
                    false);
            break;
        }

        case eStateSuspended:
        case eStateStopped:
            lldbassert(0 && "Unexpected state");

        default:
            return Error ("NativeProcessLinux::%s (): unexpected state %s specified for pid %" PRIu64 ", tid %" PRIu64,
                    __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ());
        }
    }

    return Error();
}

Error
NativeProcessLinux::Halt ()
{
    Error error;

    if (kill (GetID (), SIGSTOP) != 0)
        error.SetErrorToErrno ();

    return error;
}

Error
NativeProcessLinux::Detach ()
{
    Error error;

    // Tell ptrace to detach from the process.
    if (GetID () != LLDB_INVALID_PROCESS_ID)
        error = Detach (GetID ());

    // Stop monitoring the inferior.
    m_monitor_up->Terminate();

    // No error.
    return error;
}

Error
NativeProcessLinux::Signal (int signo)
{
    Error error;

    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf ("NativeProcessLinux::%s: sending signal %d (%s) to pid %" PRIu64,
                __FUNCTION__, signo, Host::GetSignalAsCString(signo), GetID());

    if (kill(GetID(), signo))
        error.SetErrorToErrno();

    return error;
}

Error
NativeProcessLinux::Interrupt ()
{
    // Pick a running thread (or if none, a not-dead stopped thread) as
    // the chosen thread that will be the stop-reason thread.
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    NativeThreadProtocolSP running_thread_sp;
    NativeThreadProtocolSP stopped_thread_sp;
        
    if (log)
        log->Printf ("NativeProcessLinux::%s selecting running thread for interrupt target", __FUNCTION__);

    Monitor::ScopedOperationLock monitor_lock(*m_monitor_up);
    Mutex::Locker locker (m_threads_mutex);

    for (auto thread_sp : m_threads)
    {
        // The thread shouldn't be null but lets just cover that here.
        if (!thread_sp)
            continue;

        // If we have a running or stepping thread, we'll call that the
        // target of the interrupt.
        const auto thread_state = thread_sp->GetState ();
        if (thread_state == eStateRunning ||
            thread_state == eStateStepping)
        {
            running_thread_sp = thread_sp;
            break;
        }
        else if (!stopped_thread_sp && StateIsStoppedState (thread_state, true))
        {
            // Remember the first non-dead stopped thread.  We'll use that as a backup if there are no running threads.
            stopped_thread_sp = thread_sp;
        }
    }

    if (!running_thread_sp && !stopped_thread_sp)
    {
        Error error("found no running/stepping or live stopped threads as target for interrupt");
        if (log)
            log->Printf ("NativeProcessLinux::%s skipping due to error: %s", __FUNCTION__, error.AsCString ());

        return error;
    }

    NativeThreadProtocolSP deferred_signal_thread_sp = running_thread_sp ? running_thread_sp : stopped_thread_sp;

    if (log)
        log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " %s tid %" PRIu64 " chosen for interrupt target",
                     __FUNCTION__,
                     GetID (),
                     running_thread_sp ? "running" : "stopped",
                     deferred_signal_thread_sp->GetID ());

    StopRunningThreads(deferred_signal_thread_sp->GetID());

    return Error();
}

Error
NativeProcessLinux::Kill ()
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf ("NativeProcessLinux::%s called for PID %" PRIu64, __FUNCTION__, GetID ());

    Error error;

    switch (m_state)
    {
        case StateType::eStateInvalid:
        case StateType::eStateExited:
        case StateType::eStateCrashed:
        case StateType::eStateDetached:
        case StateType::eStateUnloaded:
            // Nothing to do - the process is already dead.
            if (log)
                log->Printf ("NativeProcessLinux::%s ignored for PID %" PRIu64 " due to current state: %s", __FUNCTION__, GetID (), StateAsCString (m_state));
            return error;

        case StateType::eStateConnected:
        case StateType::eStateAttaching:
        case StateType::eStateLaunching:
        case StateType::eStateStopped:
        case StateType::eStateRunning:
        case StateType::eStateStepping:
        case StateType::eStateSuspended:
            // We can try to kill a process in these states.
            break;
    }

    if (kill (GetID (), SIGKILL) != 0)
    {
        error.SetErrorToErrno ();
        return error;
    }

    return error;
}

static Error
ParseMemoryRegionInfoFromProcMapsLine (const std::string &maps_line, MemoryRegionInfo &memory_region_info)
{
    memory_region_info.Clear();

    StringExtractor line_extractor (maps_line.c_str ());

    // Format: {address_start_hex}-{address_end_hex} perms offset  dev   inode   pathname
    // perms: rwxp   (letter is present if set, '-' if not, final character is p=private, s=shared).

    // Parse out the starting address
    lldb::addr_t start_address = line_extractor.GetHexMaxU64 (false, 0);

    // Parse out hyphen separating start and end address from range.
    if (!line_extractor.GetBytesLeft () || (line_extractor.GetChar () != '-'))
        return Error ("malformed /proc/{pid}/maps entry, missing dash between address range");

    // Parse out the ending address
    lldb::addr_t end_address = line_extractor.GetHexMaxU64 (false, start_address);

    // Parse out the space after the address.
    if (!line_extractor.GetBytesLeft () || (line_extractor.GetChar () != ' '))
        return Error ("malformed /proc/{pid}/maps entry, missing space after range");

    // Save the range.
    memory_region_info.GetRange ().SetRangeBase (start_address);
    memory_region_info.GetRange ().SetRangeEnd (end_address);

    // Parse out each permission entry.
    if (line_extractor.GetBytesLeft () < 4)
        return Error ("malformed /proc/{pid}/maps entry, missing some portion of permissions");

    // Handle read permission.
    const char read_perm_char = line_extractor.GetChar ();
    if (read_perm_char == 'r')
        memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eYes);
    else
    {
        assert ( (read_perm_char == '-') && "unexpected /proc/{pid}/maps read permission char" );
        memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo);
    }

    // Handle write permission.
    const char write_perm_char = line_extractor.GetChar ();
    if (write_perm_char == 'w')
        memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eYes);
    else
    {
        assert ( (write_perm_char == '-') && "unexpected /proc/{pid}/maps write permission char" );
        memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo);
    }

    // Handle execute permission.
    const char exec_perm_char = line_extractor.GetChar ();
    if (exec_perm_char == 'x')
        memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eYes);
    else
    {
        assert ( (exec_perm_char == '-') && "unexpected /proc/{pid}/maps exec permission char" );
        memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo);
    }

    return Error ();
}

Error
NativeProcessLinux::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info)
{
    // FIXME review that the final memory region returned extends to the end of the virtual address space,
    // with no perms if it is not mapped.

    // Use an approach that reads memory regions from /proc/{pid}/maps.
    // Assume proc maps entries are in ascending order.
    // FIXME assert if we find differently.
    Mutex::Locker locker (m_mem_region_cache_mutex);

    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    Error error;

    if (m_supports_mem_region == LazyBool::eLazyBoolNo)
    {
        // We're done.
        error.SetErrorString ("unsupported");
        return error;
    }

    // If our cache is empty, pull the latest.  There should always be at least one memory region
    // if memory region handling is supported.
    if (m_mem_region_cache.empty ())
    {
        error = ProcFileReader::ProcessLineByLine (GetID (), "maps",
             [&] (const std::string &line) -> bool
             {
                 MemoryRegionInfo info;
                 const Error parse_error = ParseMemoryRegionInfoFromProcMapsLine (line, info);
                 if (parse_error.Success ())
                 {
                     m_mem_region_cache.push_back (info);
                     return true;
                 }
                 else
                 {
                     if (log)
                         log->Printf ("NativeProcessLinux::%s failed to parse proc maps line '%s': %s", __FUNCTION__, line.c_str (), error.AsCString ());
                     return false;
                 }
             });

        // If we had an error, we'll mark unsupported.
        if (error.Fail ())
        {
            m_supports_mem_region = LazyBool::eLazyBoolNo;
            return error;
        }
        else if (m_mem_region_cache.empty ())
        {
            // No entries after attempting to read them.  This shouldn't happen if /proc/{pid}/maps
            // is supported.  Assume we don't support map entries via procfs.
            if (log)
                log->Printf ("NativeProcessLinux::%s failed to find any procfs maps entries, assuming no support for memory region metadata retrieval", __FUNCTION__);
            m_supports_mem_region = LazyBool::eLazyBoolNo;
            error.SetErrorString ("not supported");
            return error;
        }

        if (log)
            log->Printf ("NativeProcessLinux::%s read %" PRIu64 " memory region entries from /proc/%" PRIu64 "/maps", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ()), GetID ());

        // We support memory retrieval, remember that.
        m_supports_mem_region = LazyBool::eLazyBoolYes;
    }
    else
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s reusing %" PRIu64 " cached memory region entries", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ()));
    }

    lldb::addr_t prev_base_address = 0;

    // FIXME start by finding the last region that is <= target address using binary search.  Data is sorted.
    // There can be a ton of regions on pthreads apps with lots of threads.
    for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end (); ++it)
    {
        MemoryRegionInfo &proc_entry_info = *it;

        // Sanity check assumption that /proc/{pid}/maps entries are ascending.
        assert ((proc_entry_info.GetRange ().GetRangeBase () >= prev_base_address) && "descending /proc/pid/maps entries detected, unexpected");
        prev_base_address = proc_entry_info.GetRange ().GetRangeBase ();

        // If the target address comes before this entry, indicate distance to next region.
        if (load_addr < proc_entry_info.GetRange ().GetRangeBase ())
        {
            range_info.GetRange ().SetRangeBase (load_addr);
            range_info.GetRange ().SetByteSize (proc_entry_info.GetRange ().GetRangeBase () - load_addr);
            range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo);
            range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo);
            range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo);

            return error;
        }
        else if (proc_entry_info.GetRange ().Contains (load_addr))
        {
            // The target address is within the memory region we're processing here.
            range_info = proc_entry_info;
            return error;
        }

        // The target memory address comes somewhere after the region we just parsed.
    }

    // If we made it here, we didn't find an entry that contained the given address. Return the
    // load_addr as start and the amount of bytes betwwen load address and the end of the memory as
    // size.
    range_info.GetRange ().SetRangeBase (load_addr);
    switch (m_arch.GetAddressByteSize())
    {
        case 4:
            range_info.GetRange ().SetByteSize (0x100000000ull - load_addr);
            break;
        case 8:
            range_info.GetRange ().SetByteSize (0ull - load_addr);
            break;
        default:
            assert(false && "Unrecognized data byte size");
            break;
    }
    range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo);
    range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo);
    range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo);
    return error;
}

void
NativeProcessLinux::DoStopIDBumped (uint32_t newBumpId)
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf ("NativeProcessLinux::%s(newBumpId=%" PRIu32 ") called", __FUNCTION__, newBumpId);

    {
        Mutex::Locker locker (m_mem_region_cache_mutex);
        if (log)
            log->Printf ("NativeProcessLinux::%s clearing %" PRIu64 " entries from the cache", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ()));
        m_mem_region_cache.clear ();
    }
}

Error
NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr)
{
    // FIXME implementing this requires the equivalent of
    // InferiorCallPOSIX::InferiorCallMmap, which depends on
    // functional ThreadPlans working with Native*Protocol.
#if 1
    return Error ("not implemented yet");
#else
    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;

    // TODO implement this directly in NativeProcessLinux
    // (and lift to NativeProcessPOSIX if/when that class is
    // refactored out).
    if (InferiorCallMmap(this, addr, 0, size, prot,
                         eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
        m_addr_to_mmap_size[addr] = size;
        return Error ();
    } else {
        addr = LLDB_INVALID_ADDRESS;
        return Error("unable to allocate %" PRIu64 " bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
    }
#endif
}

Error
NativeProcessLinux::DeallocateMemory (lldb::addr_t addr)
{
    // FIXME see comments in AllocateMemory - required lower-level
    // bits not in place yet (ThreadPlans)
    return Error ("not implemented");
}

lldb::addr_t
NativeProcessLinux::GetSharedLibraryInfoAddress ()
{
#if 1
    // punt on this for now
    return LLDB_INVALID_ADDRESS;
#else
    // Return the image info address for the exe module
#if 1
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    ModuleSP module_sp;
    Error error = GetExeModuleSP (module_sp);
    if (error.Fail ())
    {
         if (log)
            log->Warning ("NativeProcessLinux::%s failed to retrieve exe module: %s", __FUNCTION__, error.AsCString ());
        return LLDB_INVALID_ADDRESS;
    }

    if (module_sp == nullptr)
    {
         if (log)
            log->Warning ("NativeProcessLinux::%s exe module returned was NULL", __FUNCTION__);
         return LLDB_INVALID_ADDRESS;
    }

    ObjectFileSP object_file_sp = module_sp->GetObjectFile ();
    if (object_file_sp == nullptr)
    {
         if (log)
            log->Warning ("NativeProcessLinux::%s exe module returned a NULL object file", __FUNCTION__);
         return LLDB_INVALID_ADDRESS;
    }

    return obj_file_sp->GetImageInfoAddress();
#else
    Target *target = &GetTarget();
    ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
    Address addr = obj_file->GetImageInfoAddress(target);

    if (addr.IsValid())
        return addr.GetLoadAddress(target);
    return LLDB_INVALID_ADDRESS;
#endif
#endif // punt on this for now
}

size_t
NativeProcessLinux::UpdateThreads ()
{
    // The NativeProcessLinux monitoring threads are always up to date
    // with respect to thread state and they keep the thread list
    // populated properly. All this method needs to do is return the
    // thread count.
    Mutex::Locker locker (m_threads_mutex);
    return m_threads.size ();
}

bool
NativeProcessLinux::GetArchitecture (ArchSpec &arch) const
{
    arch = m_arch;
    return true;
}

Error
NativeProcessLinux::GetSoftwareBreakpointPCOffset (NativeRegisterContextSP context_sp, uint32_t &actual_opcode_size)
{
    // FIXME put this behind a breakpoint protocol class that can be
    // set per architecture.  Need ARM, MIPS support here.
    static const uint8_t g_i386_opcode [] = { 0xCC };

    switch (m_arch.GetMachine ())
    {
        case llvm::Triple::x86:
        case llvm::Triple::x86_64:
            actual_opcode_size = static_cast<uint32_t> (sizeof(g_i386_opcode));
            return Error ();

        case llvm::Triple::arm:
        case llvm::Triple::aarch64:
        case llvm::Triple::mips64:
        case llvm::Triple::mips64el:
        case llvm::Triple::mips:
        case llvm::Triple::mipsel:
            // On these architectures the PC don't get updated for breakpoint hits
            actual_opcode_size = 0;
            return Error ();
        
        default:
            assert(false && "CPU type not supported!");
            return Error ("CPU type not supported");
    }
}

Error
NativeProcessLinux::SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware)
{
    if (hardware)
        return Error ("NativeProcessLinux does not support hardware breakpoints");
    else
        return SetSoftwareBreakpoint (addr, size);
}

Error
NativeProcessLinux::GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint,
                                                     size_t &actual_opcode_size,
                                                     const uint8_t *&trap_opcode_bytes)
{
    // FIXME put this behind a breakpoint protocol class that can be set per
    // architecture.  Need MIPS support here.
    static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 };
    // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
    // linux kernel does otherwise.
    static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 };
    static const uint8_t g_i386_opcode [] = { 0xCC };
    static const uint8_t g_mips64_opcode[] = { 0x00, 0x00, 0x00, 0x0d };
    static const uint8_t g_mips64el_opcode[] = { 0x0d, 0x00, 0x00, 0x00 };
    static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };

    switch (m_arch.GetMachine ())
    {
    case llvm::Triple::aarch64:
        trap_opcode_bytes = g_aarch64_opcode;
        actual_opcode_size = sizeof(g_aarch64_opcode);
        return Error ();

    case llvm::Triple::arm:
        switch (trap_opcode_size_hint)
        {
        case 2:
            trap_opcode_bytes = g_thumb_breakpoint_opcode;
            actual_opcode_size = sizeof(g_thumb_breakpoint_opcode);
            return Error ();
        case 4:
            trap_opcode_bytes = g_arm_breakpoint_opcode;
            actual_opcode_size = sizeof(g_arm_breakpoint_opcode);
            return Error ();
        default:
            assert(false && "Unrecognised trap opcode size hint!");
            return Error ("Unrecognised trap opcode size hint!");
        }

    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
        trap_opcode_bytes = g_i386_opcode;
        actual_opcode_size = sizeof(g_i386_opcode);
        return Error ();

    case llvm::Triple::mips:
    case llvm::Triple::mips64:
        trap_opcode_bytes = g_mips64_opcode;
        actual_opcode_size = sizeof(g_mips64_opcode);
        return Error ();

    case llvm::Triple::mipsel:
    case llvm::Triple::mips64el:
        trap_opcode_bytes = g_mips64el_opcode;
        actual_opcode_size = sizeof(g_mips64el_opcode);
        return Error ();

    default:
        assert(false && "CPU type not supported!");
        return Error ("CPU type not supported");
    }
}

#if 0
ProcessMessage::CrashReason
NativeProcessLinux::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 SI_KERNEL:
        // Linux will occasionally send spurious SI_KERNEL codes.
        // (this is poorly documented in sigaction)
        // One way to get this is via unaligned SIMD loads.
        reason = ProcessMessage::eInvalidAddress; // for lack of anything better
        break;
    case SEGV_MAPERR:
        reason = ProcessMessage::eInvalidAddress;
        break;
    case SEGV_ACCERR:
        reason = ProcessMessage::ePrivilegedAddress;
        break;
    }

    return reason;
}
#endif


#if 0
ProcessMessage::CrashReason
NativeProcessLinux::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;
}
#endif

#if 0
ProcessMessage::CrashReason
NativeProcessLinux::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;
}
#endif

#if 0
ProcessMessage::CrashReason
NativeProcessLinux::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;
}
#endif

Error
NativeProcessLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
{
    // The base SetWatchpoint will end up executing monitor operations. Let's lock the monitor
    // for it.
    Monitor::ScopedOperationLock monitor_lock(*m_monitor_up);
    return NativeProcessProtocol::SetWatchpoint(addr, size, watch_flags, hardware);
}

Error
NativeProcessLinux::RemoveWatchpoint (lldb::addr_t addr)
{
    // The base RemoveWatchpoint will end up executing monitor operations. Let's lock the monitor
    // for it.
    Monitor::ScopedOperationLock monitor_lock(*m_monitor_up);
    return NativeProcessProtocol::RemoveWatchpoint(addr);
}

Error
NativeProcessLinux::ReadMemory (lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)
{
    if (ProcessVmReadvSupported()) {
        // The process_vm_readv path is about 50 times faster than ptrace api. We want to use
        // this syscall if it is supported.

        const ::pid_t pid = GetID();

        struct iovec local_iov, remote_iov;
        local_iov.iov_base = buf;
        local_iov.iov_len = size;
        remote_iov.iov_base = reinterpret_cast<void *>(addr);
        remote_iov.iov_len = size;

        bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0);
        const bool success = bytes_read == size;

        Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
        if (log)
            log->Printf ("NativeProcessLinux::%s using process_vm_readv to read %zd bytes from inferior address 0x%" PRIx64": %s",
                    __FUNCTION__, size, addr, success ? "Success" : strerror(errno));

        if (success)
            return Error();
        // else
        //     the call failed for some reason, let's retry the read using ptrace api.
    }

    return DoOperation([&] { return DoReadMemory(GetID(), addr, buf, size, bytes_read); });
}

Error
NativeProcessLinux::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)
{
    Error error = ReadMemory(addr, buf, size, bytes_read);
    if (error.Fail()) return error;
    return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size);
}

Error
NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written)
{
    return DoOperation([&] { return DoWriteMemory(GetID(), addr, buf, size, bytes_written); });
}

Error
NativeProcessLinux::Resume (lldb::tid_t tid, uint32_t signo)
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    if (log)
        log->Printf ("NativeProcessLinux::%s() resuming thread = %"  PRIu64 " with signal %s", __FUNCTION__, tid,
                                 Host::GetSignalAsCString(signo));



    intptr_t data = 0;

    if (signo != LLDB_INVALID_SIGNAL_NUMBER)
        data = signo;

    Error error = DoOperation([&] { return PtraceWrapper(PTRACE_CONT, tid, nullptr, (void*)data); });

    if (log)
        log->Printf ("NativeProcessLinux::%s() resuming thread = %"  PRIu64 " result = %s", __FUNCTION__, tid, error.Success() ? "true" : "false");
    return error;
}

Error
NativeProcessLinux::SingleStep(lldb::tid_t tid, uint32_t signo)
{
    intptr_t data = 0;

    if (signo != LLDB_INVALID_SIGNAL_NUMBER)
        data = signo;

    return DoOperation([&] { return PtraceWrapper(PTRACE_SINGLESTEP, tid, nullptr, (void*)data); });
}

Error
NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo)
{
    return DoOperation([&] { return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo); });
}

Error
NativeProcessLinux::GetEventMessage(lldb::tid_t tid, unsigned long *message)
{
    return DoOperation([&] { return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message); });
}

Error
NativeProcessLinux::Detach(lldb::tid_t tid)
{
    if (tid == LLDB_INVALID_THREAD_ID)
        return Error();

    return DoOperation([&] { return PtraceWrapper(PTRACE_DETACH, tid); });
}

bool
NativeProcessLinux::DupDescriptor(const FileSpec &file_spec, int fd, int flags)
{
    int target_fd = open(file_spec.GetCString(), flags, 0666);

    if (target_fd == -1)
        return false;

    if (dup2(target_fd, fd) == -1)
        return false;

    return (close(target_fd) == -1) ? false : true;
}

void
NativeProcessLinux::StartMonitorThread(const InitialOperation &initial_operation, Error &error)
{
    m_monitor_up.reset(new Monitor(initial_operation, this));
    error = m_monitor_up->Initialize();
    if (error.Fail()) {
        m_monitor_up.reset();
    }
}

bool
NativeProcessLinux::HasThreadNoLock (lldb::tid_t thread_id)
{
    for (auto thread_sp : m_threads)
    {
        assert (thread_sp && "thread list should not contain NULL threads");
        if (thread_sp->GetID () == thread_id)
        {
            // We have this thread.
            return true;
        }
    }

    // We don't have this thread.
    return false;
}

NativeThreadProtocolSP
NativeProcessLinux::MaybeGetThreadNoLock (lldb::tid_t thread_id)
{
    // CONSIDER organize threads by map - we can do better than linear.
    for (auto thread_sp : m_threads)
    {
        if (thread_sp->GetID () == thread_id)
            return thread_sp;
    }

    // We don't have this thread.
    return NativeThreadProtocolSP ();
}

bool
NativeProcessLinux::StopTrackingThread (lldb::tid_t thread_id)
{
    Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);

    if (log)
        log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, thread_id);

    bool found = false;

    Mutex::Locker locker (m_threads_mutex);
    for (auto it = m_threads.begin (); it != m_threads.end (); ++it)
    {
        if (*it && ((*it)->GetID () == thread_id))
        {
            m_threads.erase (it);
            found = true;
            break;
        }
    }

    // If we have a pending notification, remove this from the set.
    if (m_pending_notification_up)
    {
        m_pending_notification_up->wait_for_stop_tids.erase(thread_id);
        SignalIfAllThreadsStopped();
    }

    return found;
}

NativeThreadProtocolSP
NativeProcessLinux::AddThread (lldb::tid_t thread_id)
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));

    Mutex::Locker locker (m_threads_mutex);

    if (log)
    {
        log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " adding thread with tid %" PRIu64,
                __FUNCTION__,
                GetID (),
                thread_id);
    }

    assert (!HasThreadNoLock (thread_id) && "attempted to add a thread by id that already exists");

    // If this is the first thread, save it as the current thread
    if (m_threads.empty ())
        SetCurrentThreadID (thread_id);

    NativeThreadProtocolSP thread_sp (new NativeThreadLinux (this, thread_id));
    m_threads.push_back (thread_sp);

    return thread_sp;
}

Error
NativeProcessLinux::FixupBreakpointPCAsNeeded (NativeThreadProtocolSP &thread_sp)
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));

    Error error;

    // Get a linux thread pointer.
    if (!thread_sp)
    {
        error.SetErrorString ("null thread_sp");
        if (log)
            log->Printf ("NativeProcessLinux::%s failed: %s", __FUNCTION__, error.AsCString ());
        return error;
    }
    std::shared_ptr<NativeThreadLinux> linux_thread_sp = std::static_pointer_cast<NativeThreadLinux> (thread_sp);

    // Find out the size of a breakpoint (might depend on where we are in the code).
    NativeRegisterContextSP context_sp = linux_thread_sp->GetRegisterContext ();
    if (!context_sp)
    {
        error.SetErrorString ("cannot get a NativeRegisterContext for the thread");
        if (log)
            log->Printf ("NativeProcessLinux::%s failed: %s", __FUNCTION__, error.AsCString ());
        return error;
    }

    uint32_t breakpoint_size = 0;
    error = GetSoftwareBreakpointPCOffset (context_sp, breakpoint_size);
    if (error.Fail ())
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s GetBreakpointSize() failed: %s", __FUNCTION__, error.AsCString ());
        return error;
    }
    else
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s breakpoint size: %" PRIu32, __FUNCTION__, breakpoint_size);
    }

    // First try probing for a breakpoint at a software breakpoint location: PC - breakpoint size.
    const lldb::addr_t initial_pc_addr = context_sp->GetPCfromBreakpointLocation ();
    lldb::addr_t breakpoint_addr = initial_pc_addr;
    if (breakpoint_size > 0)
    {
        // Do not allow breakpoint probe to wrap around.
        if (breakpoint_addr >= breakpoint_size)
            breakpoint_addr -= breakpoint_size;
    }

    // Check if we stopped because of a breakpoint.
    NativeBreakpointSP breakpoint_sp;
    error = m_breakpoint_list.GetBreakpoint (breakpoint_addr, breakpoint_sp);
    if (!error.Success () || !breakpoint_sp)
    {
        // We didn't find one at a software probe location.  Nothing to do.
        if (log)
            log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " no lldb breakpoint found at current pc with adjustment: 0x%" PRIx64, __FUNCTION__, GetID (), breakpoint_addr);
        return Error ();
    }

    // If the breakpoint is not a software breakpoint, nothing to do.
    if (!breakpoint_sp->IsSoftwareBreakpoint ())
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " breakpoint found at 0x%" PRIx64 ", not software, nothing to adjust", __FUNCTION__, GetID (), breakpoint_addr);
        return Error ();
    }

    //
    // We have a software breakpoint and need to adjust the PC.
    //

    // Sanity check.
    if (breakpoint_size == 0)
    {
        // Nothing to do!  How did we get here?
        if (log)
            log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " breakpoint found at 0x%" PRIx64 ", it is software, but the size is zero, nothing to do (unexpected)", __FUNCTION__, GetID (), breakpoint_addr);
        return Error ();
    }

    // Change the program counter.
    if (log)
        log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 ": changing PC from 0x%" PRIx64 " to 0x%" PRIx64, __FUNCTION__, GetID (), linux_thread_sp->GetID (), initial_pc_addr, breakpoint_addr);

    error = context_sp->SetPC (breakpoint_addr);
    if (error.Fail ())
    {
        if (log)
            log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 ": failed to set PC: %s", __FUNCTION__, GetID (), linux_thread_sp->GetID (), error.AsCString ());
        return error;
    }

    return error;
}

Error
NativeProcessLinux::GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec)
{
    char maps_file_name[32];
    snprintf(maps_file_name, sizeof(maps_file_name), "/proc/%" PRIu64 "/maps", GetID());

    FileSpec maps_file_spec(maps_file_name, false);
    if (!maps_file_spec.Exists()) {
        file_spec.Clear();
        return Error("/proc/%" PRIu64 "/maps file doesn't exists!", GetID());
    }

    FileSpec module_file_spec(module_path, true);

    std::ifstream maps_file(maps_file_name);
    std::string maps_data_str((std::istreambuf_iterator<char>(maps_file)), std::istreambuf_iterator<char>());
    StringRef maps_data(maps_data_str.c_str());

    while (!maps_data.empty())
    {
        StringRef maps_row;
        std::tie(maps_row, maps_data) = maps_data.split('\n');

        SmallVector<StringRef, 16> maps_columns;
        maps_row.split(maps_columns, StringRef(" "), -1, false);

        if (maps_columns.size() >= 6)
        {
            file_spec.SetFile(maps_columns[5].str().c_str(), false);
            if (file_spec.GetFilename() == module_file_spec.GetFilename())
                return Error();
        }
    }

    file_spec.Clear();
    return Error("Module file (%s) not found in /proc/%" PRIu64 "/maps file!",
                 module_file_spec.GetFilename().AsCString(), GetID());
}

Error
NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef& file_name, lldb::addr_t& load_addr)
{
    load_addr = LLDB_INVALID_ADDRESS;
    Error error = ProcFileReader::ProcessLineByLine (GetID (), "maps",
        [&] (const std::string &line) -> bool
        {
            StringRef maps_row(line);
 
            SmallVector<StringRef, 16> maps_columns;
            maps_row.split(maps_columns, StringRef(" "), -1, false);
 
            if (maps_columns.size() < 6)
            {
                // Return true to continue reading the proc file
                return true;
            }

            if (maps_columns[5] == file_name)
            {
                StringExtractor addr_extractor(maps_columns[0].str().c_str());
                load_addr = addr_extractor.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); 

                // Return false to stop reading the proc file further
                return false;
            }
 
            // Return true to continue reading the proc file
            return true;
        });
    return error; 
}

Error
NativeProcessLinux::ResumeThread(
        lldb::tid_t tid,
        NativeThreadLinux::ResumeThreadFunction request_thread_resume_function,
        bool error_when_already_running)
{
    Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);

    if (log)
        log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ", error_when_already_running: %s)",
                __FUNCTION__, tid, error_when_already_running?"true":"false");
    
    auto thread_sp = std::static_pointer_cast<NativeThreadLinux>(GetThreadByID(tid));
    lldbassert(thread_sp != nullptr);

    auto& context = thread_sp->GetThreadContext();
    // Tell the thread to resume if we don't already think it is running.
    const bool is_stopped = StateIsStoppedState(thread_sp->GetState(), true);

    lldbassert(!(error_when_already_running && !is_stopped));

    if (!is_stopped)
    {
        // It's not an error, just a log, if the error_when_already_running flag is not set.
        // This covers cases where, for instance, we're just trying to resume all threads
        // from the user side.
        if (log)
            log->Printf("NativeProcessLinux::%s tid %" PRIu64 " optional resume skipped since it is already running",
                    __FUNCTION__,
                    tid);
        return Error();
    }

    // Before we do the resume below, first check if we have a pending
    // stop notification that is currently waiting for
    // this thread to stop.  This is potentially a buggy situation since
    // we're ostensibly waiting for threads to stop before we send out the
    // pending notification, and here we are resuming one before we send
    // out the pending stop notification.
    if (m_pending_notification_up && log && m_pending_notification_up->wait_for_stop_tids.count (tid) > 0)
    {
        log->Printf("NativeProcessLinux::%s about to resume tid %" PRIu64 " per explicit request but we have a pending stop notification (tid %" PRIu64 ") that is actively waiting for this thread to stop. Valid sequence of events?", __FUNCTION__, tid, m_pending_notification_up->triggering_tid);
    }

    // Request a resume.  We expect this to be synchronous and the system
    // to reflect it is running after this completes.
    const auto error = request_thread_resume_function (tid, false);
    if (error.Success())
        context.request_resume_function = request_thread_resume_function;
    else if (log)
    {
        log->Printf("NativeProcessLinux::%s failed to resume thread tid  %" PRIu64 ": %s",
                         __FUNCTION__, tid, error.AsCString ());
    }

    return error;
}

//===----------------------------------------------------------------------===//

void
NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid)
{
    Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);

    if (log)
    {
        log->Printf("NativeProcessLinux::%s about to process event: (triggering_tid: %" PRIu64 ")",
                __FUNCTION__, triggering_tid);
    }

    DoStopThreads(PendingNotificationUP(new PendingNotification(triggering_tid)));

    if (log)
    {
        log->Printf("NativeProcessLinux::%s event processing done", __FUNCTION__);
    }
}

void
NativeProcessLinux::SignalIfAllThreadsStopped()
{
    if (m_pending_notification_up && m_pending_notification_up->wait_for_stop_tids.empty ())
    {
        Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS));

        // Clear any temporary breakpoints we used to implement software single stepping.
        for (const auto &thread_info: m_threads_stepping_with_breakpoint)
        {
            Error error = RemoveBreakpoint (thread_info.second);
            if (error.Fail())
                if (log)
                    log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 " remove stepping breakpoint: %s",
                            __FUNCTION__, thread_info.first, error.AsCString());
        }
        m_threads_stepping_with_breakpoint.clear();

        // Notify the delegate about the stop
        SetCurrentThreadID(m_pending_notification_up->triggering_tid);
        SetState(StateType::eStateStopped, true);
        m_pending_notification_up.reset();
    }
}

void
NativeProcessLinux::RequestStopOnAllRunningThreads()
{
    // Request a stop for all the thread stops that need to be stopped
    // and are not already known to be stopped.  Keep a list of all the
    // threads from which we still need to hear a stop reply.

    ThreadIDSet sent_tids;
    for (const auto &thread_sp: m_threads)
    {
        // We only care about running threads
        if (StateIsStoppedState(thread_sp->GetState(), true))
            continue;

        static_pointer_cast<NativeThreadLinux>(thread_sp)->RequestStop();
        sent_tids.insert (thread_sp->GetID());
    }

    // Set the wait list to the set of tids for which we requested stops.
    m_pending_notification_up->wait_for_stop_tids.swap (sent_tids);
}


Error
NativeProcessLinux::ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs)
{
    Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);

    if (log)
        log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ", %sinitiated by llgs)",
                __FUNCTION__, tid, initiated_by_llgs?"":"not ");

    // Ensure we know about the thread.
    auto thread_sp = std::static_pointer_cast<NativeThreadLinux>(GetThreadByID(tid));
    lldbassert(thread_sp != nullptr);

    // Update the global list of known thread states.  This one is definitely stopped.
    auto& context = thread_sp->GetThreadContext();
    const auto stop_was_requested = context.stop_requested;
    context.stop_requested = false;

    // If we have a pending notification, remove this from the set.
    if (m_pending_notification_up)
    {
        m_pending_notification_up->wait_for_stop_tids.erase(tid);
        SignalIfAllThreadsStopped();
    }

    Error error;
    if (initiated_by_llgs && context.request_resume_function && !stop_was_requested)
    {
        // We can end up here if stop was initiated by LLGS but by this time a
        // thread stop has occurred - maybe initiated by another event.
        if (log)
            log->Printf("Resuming thread %"  PRIu64 " since stop wasn't requested", tid);
        error = context.request_resume_function (tid, true);
        if (error.Fail() && log)
        {
                log->Printf("NativeProcessLinux::%s failed to resume thread tid  %" PRIu64 ": %s",
                        __FUNCTION__, tid, error.AsCString ());
        }
    }
    return error;
}

void
NativeProcessLinux::DoStopThreads(PendingNotificationUP &&notification_up)
{
    Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);
    if (m_pending_notification_up && log)
    {
        // Yikes - we've already got a pending signal notification in progress.
        // Log this info.  We lose the pending notification here.
        log->Printf("NativeProcessLinux::%s dropping existing pending signal notification for tid %" PRIu64 ", to be replaced with signal for tid %" PRIu64,
                   __FUNCTION__,
                   m_pending_notification_up->triggering_tid,
                   notification_up->triggering_tid);
    }
    m_pending_notification_up = std::move(notification_up);

    RequestStopOnAllRunningThreads();

    SignalIfAllThreadsStopped();
}

void
NativeProcessLinux::ThreadWasCreated (lldb::tid_t tid)
{
    Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);

    if (log)
        log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, tid);

    auto thread_sp = std::static_pointer_cast<NativeThreadLinux>(GetThreadByID(tid));
    lldbassert(thread_sp != nullptr);

    if (m_pending_notification_up && StateIsRunningState(thread_sp->GetState()))
    {
        // We will need to wait for this new thread to stop as well before firing the
        // notification.
        m_pending_notification_up->wait_for_stop_tids.insert(tid);
        thread_sp->RequestStop();
    }
}

Error
NativeProcessLinux::DoOperation(const Operation &op)
{
    return m_monitor_up->DoOperation(op);
}

// Wrapper for ptrace to catch errors and log calls.
// Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*)
Error
NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, long *result)
{
    Error error;
    long int ret;

    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE));

    PtraceDisplayBytes(req, data, data_size);

    errno = 0;
    if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET)
        ret = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data);
    else
        ret = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data);

    if (ret == -1)
        error.SetErrorToErrno();

    if (result)
        *result = ret;

    if (log)
        log->Printf("ptrace(%d, %" PRIu64 ", %p, %p, %zu)=%lX", req, pid, addr, data, data_size, ret);

    PtraceDisplayBytes(req, data, data_size);

    if (log && error.GetError() != 0)
    {
        const char* str;
        switch (error.GetError())
        {
        case ESRCH:  str = "ESRCH"; break;
        case EINVAL: str = "EINVAL"; break;
        case EBUSY:  str = "EBUSY"; break;
        case EPERM:  str = "EPERM"; break;
        default:     str = error.AsCString();
        }
        log->Printf("ptrace() failed; errno=%d (%s)", error.GetError(), str);
    }

    return error;
}
