diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 |
| commit | c0981da47d5696fe36474fcf86b4ce03ae3ff818 (patch) | |
| tree | f42add1021b9f2ac6a69ac7cf6c4499962739a45 /lldb/source/Plugins/Process/FreeBSD | |
| parent | 344a3780b2e33f6ca763666c380202b18aab72a3 (diff) | |
Diffstat (limited to 'lldb/source/Plugins/Process/FreeBSD')
4 files changed, 100 insertions, 6 deletions
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp index d6426b3d2367..a62d3c1ba052 100644 --- a/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp @@ -130,8 +130,12 @@ NativeProcessFreeBSD::Factory::Attach( NativeProcessFreeBSD::Extension NativeProcessFreeBSD::Factory::GetSupportedExtensions() const { - return Extension::multiprocess | Extension::fork | Extension::vfork | - Extension::pass_signals | Extension::auxv | Extension::libraries_svr4; + return +#if defined(PT_COREDUMP) + Extension::savecore | +#endif + Extension::multiprocess | Extension::fork | Extension::vfork | + Extension::pass_signals | Extension::auxv | Extension::libraries_svr4; } // Public Instance Methods @@ -1009,3 +1013,36 @@ void NativeProcessFreeBSD::MonitorClone(::pid_t child_pid, bool is_vfork, } } } + +llvm::Expected<std::string> +NativeProcessFreeBSD::SaveCore(llvm::StringRef path_hint) { +#if defined(PT_COREDUMP) + using namespace llvm::sys::fs; + + llvm::SmallString<128> path{path_hint}; + Status error; + struct ptrace_coredump pc = {}; + + // Try with the suggested path first. If there is no suggested path or it + // failed to open, use a temporary file. + if (path.empty() || + openFile(path, pc.pc_fd, CD_CreateNew, FA_Write, OF_None)) { + if (std::error_code errc = + createTemporaryFile("lldb", "core", pc.pc_fd, path)) + return llvm::createStringError(errc, "Unable to create a temporary file"); + } + error = PtraceWrapper(PT_COREDUMP, GetID(), &pc, sizeof(pc)); + + std::error_code close_err = closeFile(pc.pc_fd); + if (error.Fail()) + return error.ToError(); + if (close_err) + return llvm::createStringError( + close_err, "Unable to close the core dump after writing"); + return path.str().str(); +#else // !defined(PT_COREDUMP) + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "PT_COREDUMP not supported in the FreeBSD version used to build LLDB"); +#endif +} diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h b/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h index 7ec9d17d4cf4..44b8a53699bb 100644 --- a/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h +++ b/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h @@ -91,6 +91,8 @@ public: bool SupportHardwareSingleStepping() const; + llvm::Expected<std::string> SaveCore(llvm::StringRef path_hint) override; + protected: llvm::Expected<llvm::ArrayRef<uint8_t>> GetSoftwareBreakpointTrapOpcode(size_t size_hint) override; diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp index 8e722c09314c..d93b7fd33815 100644 --- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp @@ -15,6 +15,7 @@ #include "lldb/Utility/Status.h" #include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h" +#include "Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h" // clang-format off #include <sys/param.h> @@ -59,11 +60,32 @@ uint32_t NativeRegisterContextFreeBSD_mips64::GetUserRegisterCount() const { return count; } +llvm::Optional<NativeRegisterContextFreeBSD_mips64::RegSetKind> +NativeRegisterContextFreeBSD_mips64::GetSetForNativeRegNum( + uint32_t reg_num) const { + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::mips64: + if (reg_num >= k_first_gpr_mips64 && reg_num <= k_last_gpr_mips64) + return GPRegSet; + if (reg_num >= k_first_fpr_mips64 && reg_num <= k_last_fpr_mips64) + return FPRegSet; + break; + default: + llvm_unreachable("Unhandled target architecture."); + } + + llvm_unreachable("Register does not belong to any register set"); +} + Status NativeRegisterContextFreeBSD_mips64::ReadRegisterSet(RegSetKind set) { switch (set) { case GPRegSet: return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(), m_reg_data.data()); + case FPRegSet: + return NativeProcessFreeBSD::PtraceWrapper( + PT_GETFPREGS, m_thread.GetID(), + m_reg_data.data() + GetRegisterInfo().GetGPRSize()); } llvm_unreachable("NativeRegisterContextFreeBSD_mips64::ReadRegisterSet"); } @@ -73,6 +95,10 @@ Status NativeRegisterContextFreeBSD_mips64::WriteRegisterSet(RegSetKind set) { case GPRegSet: return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(), m_reg_data.data()); + case FPRegSet: + return NativeProcessFreeBSD::PtraceWrapper( + PT_SETFPREGS, m_thread.GetID(), + m_reg_data.data() + GetRegisterInfo().GetGPRSize()); } llvm_unreachable("NativeRegisterContextFreeBSD_mips64::WriteRegisterSet"); } @@ -94,7 +120,16 @@ NativeRegisterContextFreeBSD_mips64::ReadRegister(const RegisterInfo *reg_info, ? reg_info->name : "<unknown register>"); - RegSetKind set = GPRegSet; + llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); + if (!opt_set) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", + reg_info->name); + return error; + } + + RegSetKind set = opt_set.getValue(); error = ReadRegisterSet(set); if (error.Fail()) return error; @@ -119,7 +154,16 @@ Status NativeRegisterContextFreeBSD_mips64::WriteRegister( ? reg_info->name : "<unknown register>"); - RegSetKind set = GPRegSet; + llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); + if (!opt_set) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", + reg_info->name); + return error; + } + + RegSetKind set = opt_set.getValue(); error = ReadRegisterSet(set); if (error.Fail()) return error; @@ -139,6 +183,10 @@ Status NativeRegisterContextFreeBSD_mips64::ReadAllRegisterValues( if (error.Fail()) return error; + error = ReadRegisterSet(FPRegSet); + if (error.Fail()) + return error; + data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0)); uint8_t *dst = data_sp->GetBytes(); ::memcpy(dst, m_reg_data.data(), m_reg_data.size()); @@ -175,7 +223,11 @@ Status NativeRegisterContextFreeBSD_mips64::WriteAllRegisterValues( } ::memcpy(m_reg_data.data(), src, m_reg_data.size()); - return WriteRegisterSet(GPRegSet); + error = WriteRegisterSet(GPRegSet); + if (error.Fail()) + return error; + + return WriteRegisterSet(FPRegSet); } llvm::Error NativeRegisterContextFreeBSD_mips64::CopyHardwareWatchpointsFrom( diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h index 6a3eb86a9231..8e300ed829c9 100644 --- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h +++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h @@ -54,8 +54,11 @@ public: private: enum RegSetKind { GPRegSet, + FPRegSet, }; - std::array<uint8_t, sizeof(reg)> m_reg_data; + std::array<uint8_t, sizeof(reg) + sizeof(fpreg)> m_reg_data; + + llvm::Optional<RegSetKind> GetSetForNativeRegNum(uint32_t reg_num) const; Status ReadRegisterSet(RegSetKind set); Status WriteRegisterSet(RegSetKind set); |
