forked from OSchip/llvm-project
[ABI] Implement Windows ABI for x86_64
Summary: Implement the ABI for WIndows-x86_64 including register info and calling convention. Handled nested struct returned in register (SysV doesn't have it supported) Reviewers: xiaobai, compnerd Reviewed By: compnerd Subscribers: labath, jasonmolenda, fedor.sergeev, mgorny, teemperor, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D62213 llvm-svn: 364216
This commit is contained in:
parent
dbb6c03175
commit
09ede9d65f
|
@ -26,7 +26,6 @@ class RegistersIteratorTestCase(TestBase):
|
|||
'main.cpp', '// Set break point at this line.')
|
||||
|
||||
@add_test_categories(['pyapi'])
|
||||
@expectedFailureAll(oslist=["windows"])
|
||||
def test_iter_registers(self):
|
||||
"""Test iterator works correctly for lldbutil.iter_registers()."""
|
||||
self.build()
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h"
|
||||
#include "Plugins/ABI/SysV-s390x/ABISysV_s390x.h"
|
||||
#include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h"
|
||||
#include "Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.h"
|
||||
#include "Plugins/Architecture/Arm/ArchitectureArm.h"
|
||||
#include "Plugins/Architecture/Mips/ArchitectureMips.h"
|
||||
#include "Plugins/Architecture/PPC64/ArchitecturePPC64.h"
|
||||
|
@ -186,6 +187,7 @@ llvm::Error SystemInitializerFull::Initialize() {
|
|||
ABISysV_mips::Initialize();
|
||||
ABISysV_mips64::Initialize();
|
||||
ABISysV_s390x::Initialize();
|
||||
ABIWindows_x86_64::Initialize();
|
||||
|
||||
ArchitectureArm::Initialize();
|
||||
ArchitectureMips::Initialize();
|
||||
|
@ -299,6 +301,7 @@ void SystemInitializerFull::Terminate() {
|
|||
ABISysV_mips::Terminate();
|
||||
ABISysV_mips64::Terminate();
|
||||
ABISysV_s390x::Terminate();
|
||||
ABIWindows_x86_64::Terminate();
|
||||
DisassemblerLLVMC::Terminate();
|
||||
|
||||
JITLoaderGDB::Terminate();
|
||||
|
|
|
@ -11,3 +11,4 @@ add_subdirectory(SysV-x86_64)
|
|||
add_subdirectory(MacOSX-i386)
|
||||
add_subdirectory(MacOSX-arm)
|
||||
add_subdirectory(MacOSX-arm64)
|
||||
add_subdirectory(Windows-x86_64)
|
||||
|
|
|
@ -220,8 +220,19 @@ size_t ABISysV_x86_64::GetRedZoneSize() const { return 128; }
|
|||
|
||||
ABISP
|
||||
ABISysV_x86_64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
|
||||
if (arch.GetTriple().getArch() == llvm::Triple::x86_64) {
|
||||
return ABISP(new ABISysV_x86_64(process_sp));
|
||||
const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
|
||||
const llvm::Triple::OSType os_type = arch.GetTriple().getOS();
|
||||
if (arch_type == llvm::Triple::x86_64) {
|
||||
switch(os_type) {
|
||||
case llvm::Triple::OSType::MacOSX:
|
||||
case llvm::Triple::OSType::Linux:
|
||||
case llvm::Triple::OSType::FreeBSD:
|
||||
case llvm::Triple::OSType::Solaris:
|
||||
case llvm::Triple::OSType::UnknownOS:
|
||||
return ABISP(new ABISysV_x86_64(process_sp));
|
||||
default:
|
||||
return ABISP();
|
||||
}
|
||||
}
|
||||
return ABISP();
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,99 @@
|
|||
//===-- ABIWindows_x86_64.h ----------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef liblldb_ABIWindows_x86_64_h_
|
||||
#define liblldb_ABIWindows_x86_64_h_
|
||||
|
||||
#include "lldb/Target/ABI.h"
|
||||
#include "lldb/lldb-private.h"
|
||||
|
||||
class ABIWindows_x86_64 : public lldb_private::ABI {
|
||||
public:
|
||||
~ABIWindows_x86_64() override = default;
|
||||
|
||||
size_t GetRedZoneSize() const override;
|
||||
|
||||
bool PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp,
|
||||
lldb::addr_t functionAddress,
|
||||
lldb::addr_t returnAddress,
|
||||
llvm::ArrayRef<lldb::addr_t> args) const override;
|
||||
|
||||
bool GetArgumentValues(lldb_private::Thread &thread,
|
||||
lldb_private::ValueList &values) const override;
|
||||
|
||||
lldb_private::Status
|
||||
SetReturnValueObject(lldb::StackFrameSP &frame_sp,
|
||||
lldb::ValueObjectSP &new_value) override;
|
||||
|
||||
lldb::ValueObjectSP
|
||||
GetReturnValueObjectImpl(lldb_private::Thread &thread,
|
||||
lldb_private::CompilerType &type) const override;
|
||||
|
||||
bool
|
||||
CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
|
||||
|
||||
bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
|
||||
|
||||
bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
|
||||
|
||||
// In Windows_x86_64 ABI, stack will always be maintained 16-byte aligned
|
||||
bool CallFrameAddressIsValid(lldb::addr_t cfa) override {
|
||||
if (cfa & (16ull - 1ull))
|
||||
return false; // Not 16 byte aligned
|
||||
if (cfa == 0)
|
||||
return false; // Zero is not a valid stack address
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodeAddressIsValid(lldb::addr_t pc) override {
|
||||
// We have a 64 bit address space, so anything is valid as opcodes
|
||||
// aren't fixed width...
|
||||
return true;
|
||||
}
|
||||
|
||||
const lldb_private::RegisterInfo *
|
||||
GetRegisterInfoArray(uint32_t &count) override;
|
||||
|
||||
bool GetPointerReturnRegister(const char *&name) override;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Static Functions
|
||||
//------------------------------------------------------------------
|
||||
|
||||
static void Initialize();
|
||||
|
||||
static void Terminate();
|
||||
|
||||
static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, const lldb_private::ArchSpec &arch);
|
||||
|
||||
static lldb_private::ConstString GetPluginNameStatic();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// PluginInterface protocol
|
||||
//------------------------------------------------------------------
|
||||
|
||||
lldb_private::ConstString GetPluginName() override;
|
||||
|
||||
uint32_t GetPluginVersion() override;
|
||||
|
||||
protected:
|
||||
void CreateRegisterMapIfNeeded();
|
||||
|
||||
lldb::ValueObjectSP
|
||||
GetReturnValueObjectSimple(lldb_private::Thread &thread,
|
||||
lldb_private::CompilerType &ast_type) const;
|
||||
|
||||
bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info);
|
||||
|
||||
private:
|
||||
ABIWindows_x86_64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) {
|
||||
// Call CreateInstance instead.
|
||||
}
|
||||
};
|
||||
|
||||
#endif // liblldb_ABISysV_x86_64_h_
|
|
@ -0,0 +1,10 @@
|
|||
add_lldb_library(lldbPluginABIWindows_x86_64 PLUGIN
|
||||
ABIWindows_x86_64.cpp
|
||||
|
||||
LINK_LIBS
|
||||
lldbCore
|
||||
lldbSymbol
|
||||
lldbTarget
|
||||
LINK_COMPONENTS
|
||||
Support
|
||||
)
|
|
@ -21,7 +21,7 @@
|
|||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
const DWORD kWinContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
|
||||
const DWORD kWinContextFlags = CONTEXT_ALL;
|
||||
|
||||
// Constructors and Destructors
|
||||
RegisterContextWindows::RegisterContextWindows(Thread &thread,
|
||||
|
@ -114,8 +114,18 @@ bool RegisterContextWindows::CacheAllRegisterValues() {
|
|||
return true;
|
||||
|
||||
TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
|
||||
memset(&m_context, 0, sizeof(m_context));
|
||||
m_context.ContextFlags = kWinContextFlags;
|
||||
uint8_t buffer[2048];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
PCONTEXT tmpContext = NULL;
|
||||
DWORD contextLength = (DWORD)sizeof(buffer);
|
||||
if (!::InitializeContext(buffer, kWinContextFlags, &tmpContext,
|
||||
&contextLength)) {
|
||||
return false;
|
||||
}
|
||||
memcpy(&m_context, tmpContext, sizeof(m_context));
|
||||
if (!::SuspendThread(wthread.GetHostThread().GetNativeThread().GetSystemHandle())) {
|
||||
return false;
|
||||
}
|
||||
if (!::GetThreadContext(
|
||||
wthread.GetHostThread().GetNativeThread().GetSystemHandle(),
|
||||
&m_context)) {
|
||||
|
@ -125,6 +135,9 @@ bool RegisterContextWindows::CacheAllRegisterValues() {
|
|||
::GetLastError());
|
||||
return false;
|
||||
}
|
||||
if (!::ResumeThread(wthread.GetHostThread().GetNativeThread().GetSystemHandle())) {
|
||||
return false;
|
||||
}
|
||||
LLDB_LOG(log, "successfully updated the register values.");
|
||||
m_context_stale = false;
|
||||
return true;
|
||||
|
|
|
@ -24,6 +24,11 @@ using namespace lldb_private;
|
|||
|
||||
#define DEFINE_GPR(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatHexUppercase
|
||||
#define DEFINE_GPR_BIN(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatBinary
|
||||
#define DEFINE_FPU_XMM(reg) \
|
||||
#reg, NULL, 16, 0, eEncodingUint, eFormatVectorOfUInt64, \
|
||||
{dwarf_##reg##_x86_64, dwarf_##reg##_x86_64, LLDB_INVALID_REGNUM, \
|
||||
LLDB_INVALID_REGNUM, lldb_##reg##_x86_64}, \
|
||||
nullptr, nullptr, nullptr, 0
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -51,7 +56,24 @@ enum RegisterIndex {
|
|||
eRegisterIndexR14,
|
||||
eRegisterIndexR15,
|
||||
eRegisterIndexRip,
|
||||
eRegisterIndexRflags
|
||||
eRegisterIndexRflags,
|
||||
|
||||
eRegisterIndexXmm0,
|
||||
eRegisterIndexXmm1,
|
||||
eRegisterIndexXmm2,
|
||||
eRegisterIndexXmm3,
|
||||
eRegisterIndexXmm4,
|
||||
eRegisterIndexXmm5,
|
||||
eRegisterIndexXmm6,
|
||||
eRegisterIndexXmm7,
|
||||
eRegisterIndexXmm8,
|
||||
eRegisterIndexXmm9,
|
||||
eRegisterIndexXmm10,
|
||||
eRegisterIndexXmm11,
|
||||
eRegisterIndexXmm12,
|
||||
eRegisterIndexXmm13,
|
||||
eRegisterIndexXmm14,
|
||||
eRegisterIndexXmm15
|
||||
};
|
||||
|
||||
// Array of all register information supported by Windows x86
|
||||
|
@ -133,14 +155,14 @@ RegisterInfo g_register_infos[] = {
|
|||
nullptr,
|
||||
0},
|
||||
{DEFINE_GPR(r10, nullptr),
|
||||
{dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_REGNUM_GENERIC_ARG5,
|
||||
{dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM,
|
||||
LLDB_INVALID_REGNUM, lldb_r10_x86_64},
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
0},
|
||||
{DEFINE_GPR(r11, nullptr),
|
||||
{dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_REGNUM_GENERIC_ARG6,
|
||||
{dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM,
|
||||
LLDB_INVALID_REGNUM, lldb_r11_x86_64},
|
||||
nullptr,
|
||||
nullptr,
|
||||
|
@ -188,6 +210,22 @@ RegisterInfo g_register_infos[] = {
|
|||
nullptr,
|
||||
nullptr,
|
||||
0},
|
||||
{DEFINE_FPU_XMM(xmm0)},
|
||||
{DEFINE_FPU_XMM(xmm1)},
|
||||
{DEFINE_FPU_XMM(xmm2)},
|
||||
{DEFINE_FPU_XMM(xmm3)},
|
||||
{DEFINE_FPU_XMM(xmm4)},
|
||||
{DEFINE_FPU_XMM(xmm5)},
|
||||
{DEFINE_FPU_XMM(xmm6)},
|
||||
{DEFINE_FPU_XMM(xmm7)},
|
||||
{DEFINE_FPU_XMM(xmm8)},
|
||||
{DEFINE_FPU_XMM(xmm9)},
|
||||
{DEFINE_FPU_XMM(xmm10)},
|
||||
{DEFINE_FPU_XMM(xmm11)},
|
||||
{DEFINE_FPU_XMM(xmm12)},
|
||||
{DEFINE_FPU_XMM(xmm13)},
|
||||
{DEFINE_FPU_XMM(xmm14)},
|
||||
{DEFINE_FPU_XMM(xmm15)}
|
||||
};
|
||||
|
||||
static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
|
||||
|
@ -202,10 +240,20 @@ uint32_t g_gpr_reg_indices[] = {
|
|||
eRegisterIndexR12, eRegisterIndexR13, eRegisterIndexR14,
|
||||
eRegisterIndexR15, eRegisterIndexRip, eRegisterIndexRflags};
|
||||
|
||||
uint32_t g_fpu_reg_indices[] = {
|
||||
eRegisterIndexXmm0, eRegisterIndexXmm1, eRegisterIndexXmm2,
|
||||
eRegisterIndexXmm3, eRegisterIndexXmm4, eRegisterIndexXmm5,
|
||||
eRegisterIndexXmm6, eRegisterIndexXmm7, eRegisterIndexXmm8,
|
||||
eRegisterIndexXmm9, eRegisterIndexXmm10, eRegisterIndexXmm11,
|
||||
eRegisterIndexXmm12, eRegisterIndexXmm13, eRegisterIndexXmm14,
|
||||
eRegisterIndexXmm15
|
||||
};
|
||||
|
||||
RegisterSet g_register_sets[] = {
|
||||
{"General Purpose Registers", "gpr",
|
||||
llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices},
|
||||
};
|
||||
{"Floating Point Registers", "fpu",
|
||||
llvm::array_lengthof(g_fpu_reg_indices), g_fpu_reg_indices}};
|
||||
}
|
||||
|
||||
// Constructors and Destructors
|
||||
|
@ -242,7 +290,9 @@ bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info,
|
|||
if (reg_info == nullptr)
|
||||
return false;
|
||||
|
||||
switch (reg_info->kinds[eRegisterKindLLDB]) {
|
||||
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
|
||||
|
||||
switch (reg) {
|
||||
case lldb_rax_x86_64:
|
||||
reg_value.SetUInt64(m_context.Rax);
|
||||
break;
|
||||
|
@ -297,6 +347,70 @@ bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info,
|
|||
case lldb_rflags_x86_64:
|
||||
reg_value.SetUInt64(m_context.EFlags);
|
||||
break;
|
||||
case lldb_xmm0_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm0,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm1_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm1,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm2_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm2,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm3_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm3,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm4_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm4,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm5_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm5,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm6_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm6,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm7_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm7,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm8_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm8,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm9_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm9,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm10_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm10,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm11_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm11,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm12_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm12,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm13_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm13,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm14_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm14,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
case lldb_xmm15_x86_64:
|
||||
reg_value.SetBytes(&m_context.Xmm15,
|
||||
reg_info->byte_size, endian::InlHostByteOrder());
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -365,6 +479,54 @@ bool RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info,
|
|||
case lldb_rflags_x86_64:
|
||||
m_context.EFlags = reg_value.GetAsUInt64();
|
||||
break;
|
||||
case lldb_xmm0_x86_64:
|
||||
memcpy(&m_context.Xmm0, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm1_x86_64:
|
||||
memcpy(&m_context.Xmm1, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm2_x86_64:
|
||||
memcpy(&m_context.Xmm2, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm3_x86_64:
|
||||
memcpy(&m_context.Xmm3, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm4_x86_64:
|
||||
memcpy(&m_context.Xmm4, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm5_x86_64:
|
||||
memcpy(&m_context.Xmm5, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm6_x86_64:
|
||||
memcpy(&m_context.Xmm6, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm7_x86_64:
|
||||
memcpy(&m_context.Xmm7, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm8_x86_64:
|
||||
memcpy(&m_context.Xmm8, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm9_x86_64:
|
||||
memcpy(&m_context.Xmm9, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm10_x86_64:
|
||||
memcpy(&m_context.Xmm10, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm11_x86_64:
|
||||
memcpy(&m_context.Xmm11, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm12_x86_64:
|
||||
memcpy(&m_context.Xmm12, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm13_x86_64:
|
||||
memcpy(&m_context.Xmm13, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm14_x86_64:
|
||||
memcpy(&m_context.Xmm14, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
case lldb_xmm15_x86_64:
|
||||
memcpy(&m_context.Xmm15, reg_value.GetBytes(), 16);
|
||||
break;
|
||||
}
|
||||
|
||||
// Physically update the registers in the target process.
|
||||
|
|
Loading…
Reference in New Issue