aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichał Górny <mgorny@gentoo.org>2020-01-12 22:49:36 +0100
committerMichał Górny <mgorny@gentoo.org>2020-02-07 17:48:33 +0100
commit1ff411295f92cddfce21521594d58cf407a15189 (patch)
tree7747f4905ec6417a4e3e6fafbd2888777c8fa1e8
parent96054a1857e597ec15c36b935ea076a550047f02 (diff)
downloadllvm-1ff411295f92cddfce21521594d58cf407a15189.zip
llvm-1ff411295f92cddfce21521594d58cf407a15189.tar.gz
llvm-1ff411295f92cddfce21521594d58cf407a15189.tar.bz2
[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
-rw-r--r--lldb/source/Host/netbsd/Host.cpp30
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp57
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h3
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 <limits.h>
-#include <elf.h>
#include <kvm.h>
#include <sys/exec.h>
#include <sys/ptrace.h>
+#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<lldb_private::RegisterInfo> &GetPrivateRegisterInfoVector() {
+ static std::vector<lldb_private::RegisterInfo> g_register_infos;
+ return g_register_infos;
+}
+
+static const RegisterInfo *
+GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) {
+ std::vector<lldb_private::RegisterInfo> &g_register_infos =
+ GetPrivateRegisterInfoVector();
+
+ // Allocate RegisterInfo only once
+ if (g_register_infos.empty()) {
+ // Copy the register information from base class
+ std::unique_ptr<RegisterContextNetBSD_i386> 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<uint32_t>(GetPrivateRegisterInfoVector().size());
+ }
case llvm::Triple::x86_64:
return static_cast<uint32_t>(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<uint32_t>(k_num_user_registers_i386);
+ case llvm::Triple::x86_64:
+ return static_cast<uint32_t>(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