forked from OSchip/llvm-project
[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
This commit is contained in:
parent
96054a1857
commit
1ff411295f
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue