Index: source/Host/common/Host.cpp =================================================================== --- source/Host/common/Host.cpp +++ source/Host/common/Host.cpp @@ -679,7 +679,7 @@ sigemptyset(&no_signals); sigfillset(&all_signals); ::posix_spawnattr_setsigmask(&attr, &no_signals); -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) ::posix_spawnattr_setsigdefault(&attr, &no_signals); #else ::posix_spawnattr_setsigdefault(&attr, &all_signals); Index: source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -379,12 +379,13 @@ } bool DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) { - // On Linux the executable is indicated by an empty path in the entry. On - // FreeBSD and on Android it is the full path to the executable. + // On some systes the executable is indicated by an empty path in the entry. + // On others it is the full path to the executable. auto triple = m_process->GetTarget().GetArchitecture().GetTriple(); switch (triple.getOS()) { case llvm::Triple::FreeBSD: + case llvm::Triple::NetBSD: return entry.file_spec == m_exe_file_spec; case llvm::Triple::Linux: if (triple.isAndroid()) Index: source/Plugins/Process/NetBSD/NativeProcessNetBSD.h =================================================================== --- source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -131,6 +131,8 @@ void SigchldHandler(); ::pid_t Attach(lldb::pid_t pid, Error &error); + + Error ReinitializeThreads(); }; } // namespace process_netbsd Index: source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp =================================================================== --- source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -235,6 +235,24 @@ } SetState(StateType::eStateStopped, true); break; + case TRAP_TRACE: + for (const auto &thread_sp : m_threads) { + static_pointer_cast(thread_sp)->SetStoppedByTrace(); + } + SetState(StateType::eStateStopped, true); + break; + case TRAP_EXEC: { + Error error = ReinitializeThreads(); + if (error.Fail()) { + SetState(StateType::eStateInvalid); + return; + } + + // Let our delegate know we have just exec'd. + NotifyDidExec(); + + SetState(StateType::eStateStopped, true); + } break; } } } @@ -389,11 +407,13 @@ return Error(); } + Error error; + switch (action->state) { case eStateRunning: { // Run the thread, possibly feeding it the signal. - Error error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), - (void *)1, action->signal); + error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1, + action->signal); if (!error.Success()) return error; for (const auto &thread_sp : m_threads) { @@ -403,7 +423,15 @@ break; } case eStateStepping: - return Error("Not implemented"); + // Run the thread, possibly feeding it the signal. + error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1, + action->signal); + if (!error.Success()) + return error; + for (const auto &thread_sp : m_threads) { + static_pointer_cast(thread_sp)->SetStepping(); + } + SetState(eStateStepping, true); break; case eStateSuspended: @@ -732,22 +760,11 @@ ResolveProcessArchitecture(m_pid, m_arch); - /* Initialize threads */ - struct ptrace_lwpinfo info = {}; - error = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info)); + error = ReinitializeThreads(); if (error.Fail()) { SetState(StateType::eStateInvalid); return error; } - while (info.pl_lwpid != 0) { - NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid); - thread_sp->SetStoppedBySignal(SIGSTOP); - error = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info)); - if (error.Fail()) { - SetState(StateType::eStateInvalid); - return error; - } - } /* Set process stopped */ SetState(StateType::eStateStopped); @@ -850,9 +867,6 @@ ::pid_t NativeProcessNetBSD::Attach(lldb::pid_t pid, Error &error) { 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."); @@ -874,21 +888,11 @@ m_pid = pid; /* Initialize threads */ - struct ptrace_lwpinfo info = {}; - error = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info)); + error = ReinitializeThreads(); if (error.Fail()) { SetState(StateType::eStateInvalid); return -1; } - while (info.pl_lwpid != 0) { - NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid); - thread_sp->SetStoppedBySignal(SIGSTOP); - error = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info)); - if (error.Fail()) { - SetState(StateType::eStateInvalid); - return -1; - } - } // Let our process instance know the thread has stopped. SetState(StateType::eStateStopped); @@ -989,3 +993,26 @@ return buf; } + +Error NativeProcessNetBSD::ReinitializeThreads() { + // Clear old threads + m_threads.clear(); + + // Initialize new thread + struct ptrace_lwpinfo info = {}; + Error error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info)); + if (error.Fail()) { + return error; + } + // Reinitialize from scratch threads and register them in process + while (info.pl_lwpid != 0) { + NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid); + thread_sp->SetStoppedByExec(); + error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info)); + if (error.Fail()) { + return error; + } + } + + return error; +} Index: source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h =================================================================== --- source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h +++ source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h @@ -37,13 +37,24 @@ protected: virtual Error ReadGPR(); virtual Error WriteGPR(); + + virtual Error ReadFPR(); + virtual Error WriteFPR(); + virtual void *GetGPRBuffer() { return nullptr; } virtual size_t GetGPRSize() { return GetRegisterInfoInterface().GetGPRSize(); } + + virtual void *GetFPRBuffer() { return nullptr; } + virtual size_t GetFPRSize() { return 0; } + virtual Error DoReadGPR(void *buf); virtual Error DoWriteGPR(void *buf); + virtual Error DoReadFPR(void *buf); + virtual Error DoWriteFPR(void *buf); + virtual NativeProcessNetBSD &GetProcess(); virtual ::pid_t GetProcessPid(); }; Index: source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp =================================================================== --- source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp +++ source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp @@ -41,6 +41,22 @@ return DoWriteGPR(buf); } +Error NativeRegisterContextNetBSD::ReadFPR() { + void *buf = GetFPRBuffer(); + if (!buf) + return Error("FPR buffer is NULL"); + + return DoReadFPR(buf); +} + +Error NativeRegisterContextNetBSD::WriteFPR() { + void *buf = GetFPRBuffer(); + if (!buf) + return Error("FPR buffer is NULL"); + + return DoWriteFPR(buf); +} + Error NativeRegisterContextNetBSD::DoReadGPR(void *buf) { return NativeProcessNetBSD::PtraceWrapper(PT_GETREGS, GetProcessPid(), buf, m_thread.GetID()); @@ -51,6 +67,16 @@ m_thread.GetID()); } +Error NativeRegisterContextNetBSD::DoReadFPR(void *buf) { + return NativeProcessNetBSD::PtraceWrapper(PT_GETFPREGS, GetProcessPid(), buf, + m_thread.GetID()); +} + +Error NativeRegisterContextNetBSD::DoWriteFPR(void *buf) { + return NativeProcessNetBSD::PtraceWrapper(PT_SETFPREGS, GetProcessPid(), buf, + m_thread.GetID()); +} + NativeProcessNetBSD &NativeRegisterContextNetBSD::GetProcess() { auto process_sp = std::static_pointer_cast(m_thread.GetProcess()); Index: source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h =================================================================== --- source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h +++ source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h @@ -48,13 +48,15 @@ protected: void *GetGPRBuffer() override { return &m_gpr_x86_64; } + void *GetFPRBuffer() override { return &m_fpr_x86_64; } private: // Private member types. - enum { GPRegSet }; + enum { GPRegSet, FPRegSet }; // Private member variables. struct reg m_gpr_x86_64; + struct fpreg m_fpr_x86_64; int GetSetForNativeRegNum(int reg_num) const; Index: source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp =================================================================== --- source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -154,6 +154,9 @@ case GPRegSet: ReadGPR(); return 0; + case FPRegSet: + ReadFPR(); + return 0; default: break; } @@ -164,6 +167,9 @@ case GPRegSet: WriteGPR(); return 0; + case FPRegSet: + WriteFPR(); + return 0; default: break; } Index: source/Plugins/Process/NetBSD/NativeThreadNetBSD.h =================================================================== --- source/Plugins/Process/NetBSD/NativeThreadNetBSD.h +++ source/Plugins/Process/NetBSD/NativeThreadNetBSD.h @@ -51,8 +51,11 @@ void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr); void SetStoppedByBreakpoint(); + void SetStoppedByTrace(); + void SetStoppedByExec(); void SetStopped(); void SetRunning(); + void SetStepping(); // --------------------------------------------------------------------- // Member Variables Index: source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp =================================================================== --- source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp +++ source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp @@ -56,6 +56,18 @@ m_stop_info.details.signal.signo = SIGTRAP; } +void NativeThreadNetBSD::SetStoppedByTrace() { + SetStopped(); + m_stop_info.reason = StopReason::eStopReasonTrace; + m_stop_info.details.signal.signo = SIGTRAP; +} + +void NativeThreadNetBSD::SetStoppedByExec() { + SetStopped(); + m_stop_info.reason = StopReason::eStopReasonExec; + m_stop_info.details.signal.signo = SIGTRAP; +} + void NativeThreadNetBSD::SetStopped() { const StateType new_state = StateType::eStateStopped; m_state = new_state; @@ -67,6 +79,11 @@ m_stop_info.reason = StopReason::eStopReasonNone; } +void NativeThreadNetBSD::SetStepping() { + m_state = StateType::eStateStepping; + m_stop_info.reason = StopReason::eStopReasonNone; +} + std::string NativeThreadNetBSD::GetName() { return std::string(""); } lldb::StateType NativeThreadNetBSD::GetState() { return m_state; } Index: source/Plugins/Process/elf-core/ProcessElfCore.cpp =================================================================== --- source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -62,8 +62,8 @@ // to ignore possible presence of the header extension. const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr); - auto data_sp = - DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), header_size, 0); + auto data_sp = DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), + header_size, 0); if (data_sp && data_sp->GetByteSize() == header_size && elf::ELFHeader::MagicBytesMatch(data_sp->GetBytes())) { elf::ELFHeader elf_header; @@ -223,7 +223,7 @@ bool siginfo_signal_found = false; bool prstatus_signal_found = false; // Check we found a signal in a SIGINFO note. - for (const auto &thread_data: m_thread_data) { + for (const auto &thread_data : m_thread_data) { if (thread_data.signo != 0) siginfo_signal_found = true; if (thread_data.prstatus_sig != 0) @@ -233,7 +233,7 @@ // If we don't have signal from SIGINFO use the signal from each threads // PRSTATUS note. if (prstatus_signal_found) { - for (auto &thread_data: m_thread_data) + for (auto &thread_data : m_thread_data) thread_data.signo = thread_data.prstatus_sig; } else if (m_thread_data.size() > 0) { // If all else fails force the first thread to be SIGSTOP @@ -449,6 +449,11 @@ }; } +namespace NETBSD { + +enum { NT_PROCINFO = 1, NT_AUXV, NT_AMD64_REGS = 33, NT_AMD64_FPREGS = 35 }; +} + // Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, ArchSpec &arch) { @@ -485,13 +490,23 @@ thread_data.name = data.GetCStr(&offset, 20); } -static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data) -{ +static void ParseNetBSDProcInfo(ThreadData &thread_data, DataExtractor &data) { + lldb::offset_t offset = 0; + + int version = data.GetU32(&offset); + if (version != 1) + return; + + offset += 4; + thread_data.signo = data.GetU32(&offset); +} + +static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data) { lldb::offset_t offset = 0; - + int version = data.GetU32(&offset); if (version != 1) - return; + return; offset += 4; thread_data.signo = data.GetU32(&offset); @@ -585,23 +600,38 @@ default: break; } + } else if (note.n_name.substr(0, 11) == "NetBSD-CORE") { + // NetBSD per-thread information is stored in notes named + // "NetBSD-CORE@nnn" so match on the initial part of the string. + m_os = llvm::Triple::NetBSD; + if (note.n_type == NETBSD::NT_PROCINFO) { + ParseNetBSDProcInfo(*thread_data, note_data); + } else if (note.n_type == NETBSD::NT_AUXV) { + m_auxv = DataExtractor(note_data); + } else if (arch.GetMachine() == llvm::Triple::x86_64 && + note.n_type == NETBSD::NT_AMD64_REGS) { + thread_data->gpregset = note_data; + } else if (arch.GetMachine() == llvm::Triple::x86_64 && + note.n_type == NETBSD::NT_AMD64_FPREGS) { + thread_data->fpregset = note_data; + } } else if (note.n_name.substr(0, 7) == "OpenBSD") { // OpenBSD per-thread information is stored in notes named // "OpenBSD@nnn" so match on the initial part of the string. m_os = llvm::Triple::OpenBSD; switch (note.n_type) { case NT_OPENBSD_PROCINFO: - ParseOpenBSDProcInfo(*thread_data, note_data); - break; + ParseOpenBSDProcInfo(*thread_data, note_data); + break; case NT_OPENBSD_AUXV: - m_auxv = DataExtractor(note_data); - break; + m_auxv = DataExtractor(note_data); + break; case NT_OPENBSD_REGS: - thread_data->gpregset = note_data; - break; + thread_data->gpregset = note_data; + break; case NT_OPENBSD_FPREGS: - thread_data->fpregset = note_data; - break; + thread_data->fpregset = note_data; + break; } } else if (note.n_name == "CORE") { switch (note.n_type) { Index: source/Plugins/Process/elf-core/ThreadElfCore.cpp =================================================================== --- source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -21,6 +21,7 @@ #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" #include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" +#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h" #include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h" #include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" @@ -112,6 +113,17 @@ break; } + case llvm::Triple::NetBSD: { + switch (arch.GetMachine()) { + case llvm::Triple::x86_64: + reg_interface = new RegisterContextNetBSD_x86_64(arch); + break; + default: + break; + } + break; + } + case llvm::Triple::Linux: { switch (arch.GetMachine()) { case llvm::Triple::arm: @@ -144,8 +156,8 @@ reg_interface = new RegisterInfoPOSIX_arm(arch); break; case llvm::Triple::x86: - reg_interface = new RegisterContextOpenBSD_i386(arch); - break; + reg_interface = new RegisterContextOpenBSD_i386(arch); + break; case llvm::Triple::x86_64: reg_interface = new RegisterContextOpenBSD_x86_64(arch); break; @@ -260,7 +272,6 @@ pr_cstime.tv_sec = data.GetPointer(&offset); pr_cstime.tv_usec = data.GetPointer(&offset); - return error; } @@ -317,9 +328,7 @@ //---------------------------------------------------------------- // Parse SIGINFO from NOTE entry //---------------------------------------------------------------- -ELFLinuxSigInfo::ELFLinuxSigInfo() { - memset(this, 0, sizeof(ELFLinuxSigInfo)); -} +ELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo)); } Error ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) { Error error;