Skip to content

Commit 09ede9d

Browse files
committedJun 24, 2019
[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
1 parent dbb6c03 commit 09ede9d

File tree

9 files changed

+2118
-11
lines changed

9 files changed

+2118
-11
lines changed
 

‎lldb/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestRegistersIterator.py

-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ def setUp(self):
2626
'main.cpp', '// Set break point at this line.')
2727

2828
@add_test_categories(['pyapi'])
29-
@expectedFailureAll(oslist=["windows"])
3029
def test_iter_registers(self):
3130
"""Test iterator works correctly for lldbutil.iter_registers()."""
3231
self.build()

‎lldb/source/API/SystemInitializerFull.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h"
3535
#include "Plugins/ABI/SysV-s390x/ABISysV_s390x.h"
3636
#include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h"
37+
#include "Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.h"
3738
#include "Plugins/Architecture/Arm/ArchitectureArm.h"
3839
#include "Plugins/Architecture/Mips/ArchitectureMips.h"
3940
#include "Plugins/Architecture/PPC64/ArchitecturePPC64.h"
@@ -186,6 +187,7 @@ llvm::Error SystemInitializerFull::Initialize() {
186187
ABISysV_mips::Initialize();
187188
ABISysV_mips64::Initialize();
188189
ABISysV_s390x::Initialize();
190+
ABIWindows_x86_64::Initialize();
189191

190192
ArchitectureArm::Initialize();
191193
ArchitectureMips::Initialize();
@@ -299,6 +301,7 @@ void SystemInitializerFull::Terminate() {
299301
ABISysV_mips::Terminate();
300302
ABISysV_mips64::Terminate();
301303
ABISysV_s390x::Terminate();
304+
ABIWindows_x86_64::Terminate();
302305
DisassemblerLLVMC::Terminate();
303306

304307
JITLoaderGDB::Terminate();

‎lldb/source/Plugins/ABI/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ add_subdirectory(SysV-x86_64)
1111
add_subdirectory(MacOSX-i386)
1212
add_subdirectory(MacOSX-arm)
1313
add_subdirectory(MacOSX-arm64)
14+
add_subdirectory(Windows-x86_64)

‎lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,19 @@ size_t ABISysV_x86_64::GetRedZoneSize() const { return 128; }
220220

221221
ABISP
222222
ABISysV_x86_64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
223-
if (arch.GetTriple().getArch() == llvm::Triple::x86_64) {
224-
return ABISP(new ABISysV_x86_64(process_sp));
223+
const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
224+
const llvm::Triple::OSType os_type = arch.GetTriple().getOS();
225+
if (arch_type == llvm::Triple::x86_64) {
226+
switch(os_type) {
227+
case llvm::Triple::OSType::MacOSX:
228+
case llvm::Triple::OSType::Linux:
229+
case llvm::Triple::OSType::FreeBSD:
230+
case llvm::Triple::OSType::Solaris:
231+
case llvm::Triple::OSType::UnknownOS:
232+
return ABISP(new ABISysV_x86_64(process_sp));
233+
default:
234+
return ABISP();
235+
}
225236
}
226237
return ABISP();
227238
}

‎lldb/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.cpp

+1,809
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//===-- ABIWindows_x86_64.h ----------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef liblldb_ABIWindows_x86_64_h_
10+
#define liblldb_ABIWindows_x86_64_h_
11+
12+
#include "lldb/Target/ABI.h"
13+
#include "lldb/lldb-private.h"
14+
15+
class ABIWindows_x86_64 : public lldb_private::ABI {
16+
public:
17+
~ABIWindows_x86_64() override = default;
18+
19+
size_t GetRedZoneSize() const override;
20+
21+
bool PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp,
22+
lldb::addr_t functionAddress,
23+
lldb::addr_t returnAddress,
24+
llvm::ArrayRef<lldb::addr_t> args) const override;
25+
26+
bool GetArgumentValues(lldb_private::Thread &thread,
27+
lldb_private::ValueList &values) const override;
28+
29+
lldb_private::Status
30+
SetReturnValueObject(lldb::StackFrameSP &frame_sp,
31+
lldb::ValueObjectSP &new_value) override;
32+
33+
lldb::ValueObjectSP
34+
GetReturnValueObjectImpl(lldb_private::Thread &thread,
35+
lldb_private::CompilerType &type) const override;
36+
37+
bool
38+
CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
39+
40+
bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
41+
42+
bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
43+
44+
// In Windows_x86_64 ABI, stack will always be maintained 16-byte aligned
45+
bool CallFrameAddressIsValid(lldb::addr_t cfa) override {
46+
if (cfa & (16ull - 1ull))
47+
return false; // Not 16 byte aligned
48+
if (cfa == 0)
49+
return false; // Zero is not a valid stack address
50+
return true;
51+
}
52+
53+
bool CodeAddressIsValid(lldb::addr_t pc) override {
54+
// We have a 64 bit address space, so anything is valid as opcodes
55+
// aren't fixed width...
56+
return true;
57+
}
58+
59+
const lldb_private::RegisterInfo *
60+
GetRegisterInfoArray(uint32_t &count) override;
61+
62+
bool GetPointerReturnRegister(const char *&name) override;
63+
64+
//------------------------------------------------------------------
65+
// Static Functions
66+
//------------------------------------------------------------------
67+
68+
static void Initialize();
69+
70+
static void Terminate();
71+
72+
static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, const lldb_private::ArchSpec &arch);
73+
74+
static lldb_private::ConstString GetPluginNameStatic();
75+
76+
//------------------------------------------------------------------
77+
// PluginInterface protocol
78+
//------------------------------------------------------------------
79+
80+
lldb_private::ConstString GetPluginName() override;
81+
82+
uint32_t GetPluginVersion() override;
83+
84+
protected:
85+
void CreateRegisterMapIfNeeded();
86+
87+
lldb::ValueObjectSP
88+
GetReturnValueObjectSimple(lldb_private::Thread &thread,
89+
lldb_private::CompilerType &ast_type) const;
90+
91+
bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info);
92+
93+
private:
94+
ABIWindows_x86_64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) {
95+
// Call CreateInstance instead.
96+
}
97+
};
98+
99+
#endif // liblldb_ABISysV_x86_64_h_
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
add_lldb_library(lldbPluginABIWindows_x86_64 PLUGIN
2+
ABIWindows_x86_64.cpp
3+
4+
LINK_LIBS
5+
lldbCore
6+
lldbSymbol
7+
lldbTarget
8+
LINK_COMPONENTS
9+
Support
10+
)

‎lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp

+16-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
using namespace lldb;
2222
using namespace lldb_private;
2323

24-
const DWORD kWinContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
24+
const DWORD kWinContextFlags = CONTEXT_ALL;
2525

2626
// Constructors and Destructors
2727
RegisterContextWindows::RegisterContextWindows(Thread &thread,
@@ -114,8 +114,18 @@ bool RegisterContextWindows::CacheAllRegisterValues() {
114114
return true;
115115

116116
TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
117-
memset(&m_context, 0, sizeof(m_context));
118-
m_context.ContextFlags = kWinContextFlags;
117+
uint8_t buffer[2048];
118+
memset(buffer, 0, sizeof(buffer));
119+
PCONTEXT tmpContext = NULL;
120+
DWORD contextLength = (DWORD)sizeof(buffer);
121+
if (!::InitializeContext(buffer, kWinContextFlags, &tmpContext,
122+
&contextLength)) {
123+
return false;
124+
}
125+
memcpy(&m_context, tmpContext, sizeof(m_context));
126+
if (!::SuspendThread(wthread.GetHostThread().GetNativeThread().GetSystemHandle())) {
127+
return false;
128+
}
119129
if (!::GetThreadContext(
120130
wthread.GetHostThread().GetNativeThread().GetSystemHandle(),
121131
&m_context)) {
@@ -125,6 +135,9 @@ bool RegisterContextWindows::CacheAllRegisterValues() {
125135
::GetLastError());
126136
return false;
127137
}
138+
if (!::ResumeThread(wthread.GetHostThread().GetNativeThread().GetSystemHandle())) {
139+
return false;
140+
}
128141
LLDB_LOG(log, "successfully updated the register values.");
129142
m_context_stale = false;
130143
return true;

‎lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp

+167-5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ using namespace lldb_private;
2424

2525
#define DEFINE_GPR(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatHexUppercase
2626
#define DEFINE_GPR_BIN(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatBinary
27+
#define DEFINE_FPU_XMM(reg) \
28+
#reg, NULL, 16, 0, eEncodingUint, eFormatVectorOfUInt64, \
29+
{dwarf_##reg##_x86_64, dwarf_##reg##_x86_64, LLDB_INVALID_REGNUM, \
30+
LLDB_INVALID_REGNUM, lldb_##reg##_x86_64}, \
31+
nullptr, nullptr, nullptr, 0
2732

2833
namespace {
2934

@@ -51,7 +56,24 @@ enum RegisterIndex {
5156
eRegisterIndexR14,
5257
eRegisterIndexR15,
5358
eRegisterIndexRip,
54-
eRegisterIndexRflags
59+
eRegisterIndexRflags,
60+
61+
eRegisterIndexXmm0,
62+
eRegisterIndexXmm1,
63+
eRegisterIndexXmm2,
64+
eRegisterIndexXmm3,
65+
eRegisterIndexXmm4,
66+
eRegisterIndexXmm5,
67+
eRegisterIndexXmm6,
68+
eRegisterIndexXmm7,
69+
eRegisterIndexXmm8,
70+
eRegisterIndexXmm9,
71+
eRegisterIndexXmm10,
72+
eRegisterIndexXmm11,
73+
eRegisterIndexXmm12,
74+
eRegisterIndexXmm13,
75+
eRegisterIndexXmm14,
76+
eRegisterIndexXmm15
5577
};
5678

5779
// Array of all register information supported by Windows x86
@@ -133,14 +155,14 @@ RegisterInfo g_register_infos[] = {
133155
nullptr,
134156
0},
135157
{DEFINE_GPR(r10, nullptr),
136-
{dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_REGNUM_GENERIC_ARG5,
158+
{dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM,
137159
LLDB_INVALID_REGNUM, lldb_r10_x86_64},
138160
nullptr,
139161
nullptr,
140162
nullptr,
141163
0},
142164
{DEFINE_GPR(r11, nullptr),
143-
{dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_REGNUM_GENERIC_ARG6,
165+
{dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM,
144166
LLDB_INVALID_REGNUM, lldb_r11_x86_64},
145167
nullptr,
146168
nullptr,
@@ -188,6 +210,22 @@ RegisterInfo g_register_infos[] = {
188210
nullptr,
189211
nullptr,
190212
0},
213+
{DEFINE_FPU_XMM(xmm0)},
214+
{DEFINE_FPU_XMM(xmm1)},
215+
{DEFINE_FPU_XMM(xmm2)},
216+
{DEFINE_FPU_XMM(xmm3)},
217+
{DEFINE_FPU_XMM(xmm4)},
218+
{DEFINE_FPU_XMM(xmm5)},
219+
{DEFINE_FPU_XMM(xmm6)},
220+
{DEFINE_FPU_XMM(xmm7)},
221+
{DEFINE_FPU_XMM(xmm8)},
222+
{DEFINE_FPU_XMM(xmm9)},
223+
{DEFINE_FPU_XMM(xmm10)},
224+
{DEFINE_FPU_XMM(xmm11)},
225+
{DEFINE_FPU_XMM(xmm12)},
226+
{DEFINE_FPU_XMM(xmm13)},
227+
{DEFINE_FPU_XMM(xmm14)},
228+
{DEFINE_FPU_XMM(xmm15)}
191229
};
192230

193231
static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -202,10 +240,20 @@ uint32_t g_gpr_reg_indices[] = {
202240
eRegisterIndexR12, eRegisterIndexR13, eRegisterIndexR14,
203241
eRegisterIndexR15, eRegisterIndexRip, eRegisterIndexRflags};
204242

243+
uint32_t g_fpu_reg_indices[] = {
244+
eRegisterIndexXmm0, eRegisterIndexXmm1, eRegisterIndexXmm2,
245+
eRegisterIndexXmm3, eRegisterIndexXmm4, eRegisterIndexXmm5,
246+
eRegisterIndexXmm6, eRegisterIndexXmm7, eRegisterIndexXmm8,
247+
eRegisterIndexXmm9, eRegisterIndexXmm10, eRegisterIndexXmm11,
248+
eRegisterIndexXmm12, eRegisterIndexXmm13, eRegisterIndexXmm14,
249+
eRegisterIndexXmm15
250+
};
251+
205252
RegisterSet g_register_sets[] = {
206253
{"General Purpose Registers", "gpr",
207254
llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices},
208-
};
255+
{"Floating Point Registers", "fpu",
256+
llvm::array_lengthof(g_fpu_reg_indices), g_fpu_reg_indices}};
209257
}
210258

211259
// Constructors and Destructors
@@ -242,7 +290,9 @@ bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info,
242290
if (reg_info == nullptr)
243291
return false;
244292

245-
switch (reg_info->kinds[eRegisterKindLLDB]) {
293+
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
294+
295+
switch (reg) {
246296
case lldb_rax_x86_64:
247297
reg_value.SetUInt64(m_context.Rax);
248298
break;
@@ -297,6 +347,70 @@ bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info,
297347
case lldb_rflags_x86_64:
298348
reg_value.SetUInt64(m_context.EFlags);
299349
break;
350+
case lldb_xmm0_x86_64:
351+
reg_value.SetBytes(&m_context.Xmm0,
352+
reg_info->byte_size, endian::InlHostByteOrder());
353+
break;
354+
case lldb_xmm1_x86_64:
355+
reg_value.SetBytes(&m_context.Xmm1,
356+
reg_info->byte_size, endian::InlHostByteOrder());
357+
break;
358+
case lldb_xmm2_x86_64:
359+
reg_value.SetBytes(&m_context.Xmm2,
360+
reg_info->byte_size, endian::InlHostByteOrder());
361+
break;
362+
case lldb_xmm3_x86_64:
363+
reg_value.SetBytes(&m_context.Xmm3,
364+
reg_info->byte_size, endian::InlHostByteOrder());
365+
break;
366+
case lldb_xmm4_x86_64:
367+
reg_value.SetBytes(&m_context.Xmm4,
368+
reg_info->byte_size, endian::InlHostByteOrder());
369+
break;
370+
case lldb_xmm5_x86_64:
371+
reg_value.SetBytes(&m_context.Xmm5,
372+
reg_info->byte_size, endian::InlHostByteOrder());
373+
break;
374+
case lldb_xmm6_x86_64:
375+
reg_value.SetBytes(&m_context.Xmm6,
376+
reg_info->byte_size, endian::InlHostByteOrder());
377+
break;
378+
case lldb_xmm7_x86_64:
379+
reg_value.SetBytes(&m_context.Xmm7,
380+
reg_info->byte_size, endian::InlHostByteOrder());
381+
break;
382+
case lldb_xmm8_x86_64:
383+
reg_value.SetBytes(&m_context.Xmm8,
384+
reg_info->byte_size, endian::InlHostByteOrder());
385+
break;
386+
case lldb_xmm9_x86_64:
387+
reg_value.SetBytes(&m_context.Xmm9,
388+
reg_info->byte_size, endian::InlHostByteOrder());
389+
break;
390+
case lldb_xmm10_x86_64:
391+
reg_value.SetBytes(&m_context.Xmm10,
392+
reg_info->byte_size, endian::InlHostByteOrder());
393+
break;
394+
case lldb_xmm11_x86_64:
395+
reg_value.SetBytes(&m_context.Xmm11,
396+
reg_info->byte_size, endian::InlHostByteOrder());
397+
break;
398+
case lldb_xmm12_x86_64:
399+
reg_value.SetBytes(&m_context.Xmm12,
400+
reg_info->byte_size, endian::InlHostByteOrder());
401+
break;
402+
case lldb_xmm13_x86_64:
403+
reg_value.SetBytes(&m_context.Xmm13,
404+
reg_info->byte_size, endian::InlHostByteOrder());
405+
break;
406+
case lldb_xmm14_x86_64:
407+
reg_value.SetBytes(&m_context.Xmm14,
408+
reg_info->byte_size, endian::InlHostByteOrder());
409+
break;
410+
case lldb_xmm15_x86_64:
411+
reg_value.SetBytes(&m_context.Xmm15,
412+
reg_info->byte_size, endian::InlHostByteOrder());
413+
break;
300414
}
301415
return true;
302416
}
@@ -365,6 +479,54 @@ bool RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info,
365479
case lldb_rflags_x86_64:
366480
m_context.EFlags = reg_value.GetAsUInt64();
367481
break;
482+
case lldb_xmm0_x86_64:
483+
memcpy(&m_context.Xmm0, reg_value.GetBytes(), 16);
484+
break;
485+
case lldb_xmm1_x86_64:
486+
memcpy(&m_context.Xmm1, reg_value.GetBytes(), 16);
487+
break;
488+
case lldb_xmm2_x86_64:
489+
memcpy(&m_context.Xmm2, reg_value.GetBytes(), 16);
490+
break;
491+
case lldb_xmm3_x86_64:
492+
memcpy(&m_context.Xmm3, reg_value.GetBytes(), 16);
493+
break;
494+
case lldb_xmm4_x86_64:
495+
memcpy(&m_context.Xmm4, reg_value.GetBytes(), 16);
496+
break;
497+
case lldb_xmm5_x86_64:
498+
memcpy(&m_context.Xmm5, reg_value.GetBytes(), 16);
499+
break;
500+
case lldb_xmm6_x86_64:
501+
memcpy(&m_context.Xmm6, reg_value.GetBytes(), 16);
502+
break;
503+
case lldb_xmm7_x86_64:
504+
memcpy(&m_context.Xmm7, reg_value.GetBytes(), 16);
505+
break;
506+
case lldb_xmm8_x86_64:
507+
memcpy(&m_context.Xmm8, reg_value.GetBytes(), 16);
508+
break;
509+
case lldb_xmm9_x86_64:
510+
memcpy(&m_context.Xmm9, reg_value.GetBytes(), 16);
511+
break;
512+
case lldb_xmm10_x86_64:
513+
memcpy(&m_context.Xmm10, reg_value.GetBytes(), 16);
514+
break;
515+
case lldb_xmm11_x86_64:
516+
memcpy(&m_context.Xmm11, reg_value.GetBytes(), 16);
517+
break;
518+
case lldb_xmm12_x86_64:
519+
memcpy(&m_context.Xmm12, reg_value.GetBytes(), 16);
520+
break;
521+
case lldb_xmm13_x86_64:
522+
memcpy(&m_context.Xmm13, reg_value.GetBytes(), 16);
523+
break;
524+
case lldb_xmm14_x86_64:
525+
memcpy(&m_context.Xmm14, reg_value.GetBytes(), 16);
526+
break;
527+
case lldb_xmm15_x86_64:
528+
memcpy(&m_context.Xmm15, reg_value.GetBytes(), 16);
529+
break;
368530
}
369531

370532
// Physically update the registers in the target process.

0 commit comments

Comments
 (0)
Please sign in to comment.