From 1ff411295f92cddfce21521594d58cf407a15189 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Micha=C5=82=20G=C3=B3rny?= Date: Sun, 12 Jan 2020 22:49:36 +0100 Subject: [PATCH] [lldb] Improve debugging 32-bit programs on NetBSD/amd64 Implement detection of ELF binary format, and support for i386 register context on amd64 when a 32-bit executable is being debugged. This is roughly based on the code from Linux. Differential Revision: https://reviews.llvm.org/D73974 --- lldb/source/Host/netbsd/Host.cpp | 30 ++++++++++-- .../Utility/RegisterContextNetBSD_x86_64.cpp | 57 +++++++++++++++++++++- .../Process/Utility/RegisterContextNetBSD_x86_64.h | 3 ++ 3 files changed, 85 insertions(+), 5 deletions(-) diff --git a/lldb/source/Host/netbsd/Host.cpp b/lldb/source/Host/netbsd/Host.cpp index 0733c62..fb0be47 100644 --- 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 GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, } 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.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp index 8c3698a..21aad92 100644 --- 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 @@ struct UserArea { #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 @@ PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { 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 @@ PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) { } } +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 @@ const RegisterInfo *RegisterContextNetBSD_x86_64::GetRegisterInfo() const { uint32_t RegisterContextNetBSD_x86_64::GetRegisterCount() const { return m_register_count; } + +uint32_t RegisterContextNetBSD_x86_64::GetUserRegisterCount() const { + return m_user_register_count; +} diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h index 4820ef8..7cba781 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h @@ -22,9 +22,12 @@ public: 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 -- 2.7.4