Skip to content

Commit 1ff4112

Browse files
committed
[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
1 parent 96054a1 commit 1ff4112

File tree

3 files changed

+85
-5
lines changed

3 files changed

+85
-5
lines changed

‎lldb/source/Host/netbsd/Host.cpp

+26-4
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515

1616
#include <limits.h>
1717

18-
#include <elf.h>
1918
#include <kvm.h>
2019
#include <sys/exec.h>
2120
#include <sys/ptrace.h>
2221

22+
#include "lldb/Host/FileSystem.h"
2323
#include "lldb/Host/Host.h"
2424
#include "lldb/Host/HostInfo.h"
2525
#include "lldb/Utility/DataBufferHeap.h"
@@ -31,6 +31,7 @@
3131
#include "lldb/Utility/Status.h"
3232
#include "lldb/Utility/StreamString.h"
3333

34+
#include "llvm/Object/ELF.h"
3435
#include "llvm/Support/Host.h"
3536

3637
extern "C" {
@@ -100,10 +101,31 @@ static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
100101
}
101102

102103
static bool GetNetBSDProcessCPUType(ProcessInstanceInfo &process_info) {
104+
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
105+
103106
if (process_info.ProcessIDIsValid()) {
104-
process_info.GetArchitecture() =
105-
HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
106-
return true;
107+
auto buffer_sp = FileSystem::Instance().CreateDataBuffer(
108+
process_info.GetExecutableFile(), 0x20, 0);
109+
if (buffer_sp) {
110+
uint8_t exe_class =
111+
llvm::object::getElfArchType(
112+
{buffer_sp->GetChars(), size_t(buffer_sp->GetByteSize())})
113+
.first;
114+
115+
switch (exe_class) {
116+
case llvm::ELF::ELFCLASS32:
117+
process_info.GetArchitecture() =
118+
HostInfo::GetArchitecture(HostInfo::eArchKind32);
119+
return true;
120+
case llvm::ELF::ELFCLASS64:
121+
process_info.GetArchitecture() =
122+
HostInfo::GetArchitecture(HostInfo::eArchKind64);
123+
return true;
124+
default:
125+
LLDB_LOG(log, "Unknown elf class ({0}) in file {1}", exe_class,
126+
process_info.GetExecutableFile());
127+
}
128+
}
107129
}
108130
process_info.GetArchitecture().Clear();
109131
return false;

‎lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp

+56-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "RegisterContextNetBSD_x86_64.h"
10+
#include "RegisterContextNetBSD_i386.h"
1011
#include "RegisterContextPOSIX_x86.h"
1112
#include "llvm/ADT/Triple.h"
1213
#include "llvm/Support/Compiler.h"
@@ -83,9 +84,40 @@ struct UserArea {
8384
#include "RegisterInfos_x86_64.h"
8485
#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
8586

87+
static std::vector<lldb_private::RegisterInfo> &GetPrivateRegisterInfoVector() {
88+
static std::vector<lldb_private::RegisterInfo> g_register_infos;
89+
return g_register_infos;
90+
}
91+
92+
static const RegisterInfo *
93+
GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) {
94+
std::vector<lldb_private::RegisterInfo> &g_register_infos =
95+
GetPrivateRegisterInfoVector();
96+
97+
// Allocate RegisterInfo only once
98+
if (g_register_infos.empty()) {
99+
// Copy the register information from base class
100+
std::unique_ptr<RegisterContextNetBSD_i386> reg_interface(
101+
new RegisterContextNetBSD_i386(arch));
102+
const RegisterInfo *base_info = reg_interface->GetRegisterInfo();
103+
g_register_infos.insert(g_register_infos.end(), &base_info[0],
104+
&base_info[k_num_registers_i386]);
105+
106+
// Include RegisterInfos_x86_64 to update the g_register_infos structure
107+
// with x86_64 offsets.
108+
#define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
109+
#include "RegisterInfos_x86_64.h"
110+
#undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
111+
}
112+
113+
return &g_register_infos[0];
114+
}
115+
86116
static const RegisterInfo *
87117
PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) {
88118
switch (target_arch.GetMachine()) {
119+
case llvm::Triple::x86:
120+
return GetRegisterInfo_i386(target_arch);
89121
case llvm::Triple::x86_64:
90122
return g_register_infos_x86_64;
91123
default:
@@ -97,6 +129,11 @@ PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) {
97129
static uint32_t
98130
PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) {
99131
switch (target_arch.GetMachine()) {
132+
case llvm::Triple::x86: {
133+
assert(!GetPrivateRegisterInfoVector().empty() &&
134+
"i386 register info not yet filled.");
135+
return static_cast<uint32_t>(GetPrivateRegisterInfoVector().size());
136+
}
100137
case llvm::Triple::x86_64:
101138
return static_cast<uint32_t>(sizeof(g_register_infos_x86_64) /
102139
sizeof(g_register_infos_x86_64[0]));
@@ -106,11 +143,25 @@ PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) {
106143
}
107144
}
108145

146+
static uint32_t
147+
PrivateGetUserRegisterCount(const lldb_private::ArchSpec &target_arch) {
148+
switch (target_arch.GetMachine()) {
149+
case llvm::Triple::x86:
150+
return static_cast<uint32_t>(k_num_user_registers_i386);
151+
case llvm::Triple::x86_64:
152+
return static_cast<uint32_t>(k_num_user_registers_x86_64);
153+
default:
154+
assert(false && "Unhandled target architecture.");
155+
return 0;
156+
}
157+
}
158+
109159
RegisterContextNetBSD_x86_64::RegisterContextNetBSD_x86_64(
110160
const ArchSpec &target_arch)
111161
: lldb_private::RegisterInfoInterface(target_arch),
112162
m_register_info_p(PrivateGetRegisterInfoPtr(target_arch)),
113-
m_register_count(PrivateGetRegisterCount(target_arch)) {}
163+
m_register_count(PrivateGetRegisterCount(target_arch)),
164+
m_user_register_count(PrivateGetUserRegisterCount(target_arch)) {}
114165

115166
size_t RegisterContextNetBSD_x86_64::GetGPRSize() const { return sizeof(GPR); }
116167

@@ -121,3 +172,7 @@ const RegisterInfo *RegisterContextNetBSD_x86_64::GetRegisterInfo() const {
121172
uint32_t RegisterContextNetBSD_x86_64::GetRegisterCount() const {
122173
return m_register_count;
123174
}
175+
176+
uint32_t RegisterContextNetBSD_x86_64::GetUserRegisterCount() const {
177+
return m_user_register_count;
178+
}

‎lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h

+3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@ class RegisterContextNetBSD_x86_64
2222

2323
uint32_t GetRegisterCount() const override;
2424

25+
uint32_t GetUserRegisterCount() const override;
26+
2527
private:
2628
const lldb_private::RegisterInfo *m_register_info_p;
2729
const uint32_t m_register_count;
30+
const uint32_t m_user_register_count;
2831
};
2932

3033
#endif

0 commit comments

Comments
 (0)