diff --git a/lldb/source/Host/netbsd/Host.cpp b/lldb/source/Host/netbsd/Host.cpp --- a/lldb/source/Host/netbsd/Host.cpp +++ b/lldb/source/Host/netbsd/Host.cpp @@ -15,11 +15,11 @@ #include -#include #include #include #include +#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Utility/DataBufferHeap.h" @@ -31,6 +31,7 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" +#include "llvm/Object/ELF.h" #include "llvm/Support/Host.h" extern "C" { @@ -100,10 +101,31 @@ } static bool GetNetBSDProcessCPUType(ProcessInstanceInfo &process_info) { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (process_info.ProcessIDIsValid()) { - process_info.GetArchitecture() = - HostInfo::GetArchitecture(HostInfo::eArchKindDefault); - return true; + auto buffer_sp = FileSystem::Instance().CreateDataBuffer( + process_info.GetExecutableFile(), 0x20, 0); + if (buffer_sp) { + uint8_t exe_class = + llvm::object::getElfArchType( + {buffer_sp->GetChars(), size_t(buffer_sp->GetByteSize())}) + .first; + + switch (exe_class) { + case llvm::ELF::ELFCLASS32: + process_info.GetArchitecture() = + HostInfo::GetArchitecture(HostInfo::eArchKind32); + return true; + case llvm::ELF::ELFCLASS64: + process_info.GetArchitecture() = + HostInfo::GetArchitecture(HostInfo::eArchKind64); + return true; + default: + LLDB_LOG(log, "Unknown elf class ({0}) in file {1}", exe_class, + process_info.GetExecutableFile()); + } + } } process_info.GetArchitecture().Clear(); return false; diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h --- a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h @@ -22,9 +22,12 @@ uint32_t GetRegisterCount() const override; + uint32_t GetUserRegisterCount() const override; + private: const lldb_private::RegisterInfo *m_register_info_p; const uint32_t m_register_count; + const uint32_t m_user_register_count; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp --- a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "RegisterContextNetBSD_x86_64.h" +#include "RegisterContextNetBSD_i386.h" #include "RegisterContextPOSIX_x86.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Compiler.h" @@ -83,9 +84,40 @@ #include "RegisterInfos_x86_64.h" #undef DECLARE_REGISTER_INFOS_X86_64_STRUCT +static std::vector &GetPrivateRegisterInfoVector() { + static std::vector g_register_infos; + return g_register_infos; +} + +static const RegisterInfo * +GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) { + std::vector &g_register_infos = + GetPrivateRegisterInfoVector(); + + // Allocate RegisterInfo only once + if (g_register_infos.empty()) { + // Copy the register information from base class + std::unique_ptr reg_interface( + new RegisterContextNetBSD_i386(arch)); + const RegisterInfo *base_info = reg_interface->GetRegisterInfo(); + g_register_infos.insert(g_register_infos.end(), &base_info[0], + &base_info[k_num_registers_i386]); + +// Include RegisterInfos_x86_64 to update the g_register_infos structure +// with x86_64 offsets. +#define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS +#include "RegisterInfos_x86_64.h" +#undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS + } + + return &g_register_infos[0]; +} + static const RegisterInfo * PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { switch (target_arch.GetMachine()) { + case llvm::Triple::x86: + return GetRegisterInfo_i386(target_arch); case llvm::Triple::x86_64: return g_register_infos_x86_64; default: @@ -97,6 +129,11 @@ static uint32_t PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) { switch (target_arch.GetMachine()) { + case llvm::Triple::x86: { + assert(!GetPrivateRegisterInfoVector().empty() && + "i386 register info not yet filled."); + return static_cast(GetPrivateRegisterInfoVector().size()); + } case llvm::Triple::x86_64: return static_cast(sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[0])); @@ -106,11 +143,25 @@ } } +static uint32_t +PrivateGetUserRegisterCount(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::x86: + return static_cast(k_num_user_registers_i386); + case llvm::Triple::x86_64: + return static_cast(k_num_user_registers_x86_64); + default: + assert(false && "Unhandled target architecture."); + return 0; + } +} + RegisterContextNetBSD_x86_64::RegisterContextNetBSD_x86_64( const ArchSpec &target_arch) : lldb_private::RegisterInfoInterface(target_arch), m_register_info_p(PrivateGetRegisterInfoPtr(target_arch)), - m_register_count(PrivateGetRegisterCount(target_arch)) {} + m_register_count(PrivateGetRegisterCount(target_arch)), + m_user_register_count(PrivateGetUserRegisterCount(target_arch)) {} size_t RegisterContextNetBSD_x86_64::GetGPRSize() const { return sizeof(GPR); } @@ -121,3 +172,7 @@ uint32_t RegisterContextNetBSD_x86_64::GetRegisterCount() const { return m_register_count; } + +uint32_t RegisterContextNetBSD_x86_64::GetUserRegisterCount() const { + return m_user_register_count; +}