Skip to content

Commit 5146a9e

Browse files
committed
Initial support for native debugging of x86/x64 Windows processes
Summary: Thanks to Hui Huang and the reviewers for all the help with this patch. Reviewers: labath, Hui, jfb, clayborg, amccarth Reviewed By: labath Subscribers: amccarth, compnerd, dexonsmith, mgorny, jfb, teemperor, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D63165 llvm-svn: 368759
1 parent b809187 commit 5146a9e

25 files changed

+2916
-9
lines changed

lldb/packages/Python/lldbsuite/test/tools/lldb-server/register-reading/main.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#include <cstdint>
22

3-
struct alignas(16) xmm_t {
4-
uint64_t a, b;
5-
};
6-
73
int main() {
4+
#if defined(__x86_64__)
5+
struct alignas(16) xmm_t {
6+
uint64_t a, b;
7+
};
88
uint64_t r8 = 0x0102030405060708;
99
uint64_t r9 = 0x1112131415161718;
1010
uint64_t r10 = 0x2122232425262728;
@@ -49,6 +49,6 @@ int main() {
4949
: "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
5050
"%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13",
5151
"%xmm14", "%xmm15");
52-
52+
#endif
5353
return 0;
5454
}

lldb/source/Plugins/Process/Utility/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ add_lldb_library(lldbPluginProcessUtility PLUGIN
4343
RegisterContextPOSIX_s390x.cpp
4444
RegisterContextPOSIX_x86.cpp
4545
RegisterContextThreadMemory.cpp
46+
RegisterContextWindows_i386.cpp
47+
RegisterContextWindows_x86_64.cpp
4648
RegisterInfoPOSIX_arm.cpp
4749
RegisterInfoPOSIX_arm64.cpp
4850
RegisterInfoPOSIX_ppc64le.cpp
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//===-- RegisterContextWindows_i386.cpp -------------------------*- 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+
#include "RegisterContextWindows_i386.h"
10+
#include "RegisterContext_x86.h"
11+
#include "lldb-x86-register-enums.h"
12+
13+
using namespace lldb_private;
14+
using namespace lldb;
15+
16+
namespace {
17+
// Declare our g_register_infos structure.
18+
typedef struct _GPR {
19+
uint32_t eax;
20+
uint32_t ebx;
21+
uint32_t ecx;
22+
uint32_t edx;
23+
uint32_t edi;
24+
uint32_t esi;
25+
uint32_t ebp;
26+
uint32_t esp;
27+
uint32_t eip;
28+
uint32_t eflags;
29+
uint32_t cs;
30+
uint32_t fs;
31+
uint32_t gs;
32+
uint32_t ss;
33+
uint32_t ds;
34+
uint32_t es;
35+
} GPR;
36+
37+
#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname))
38+
39+
#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
40+
{ \
41+
#reg, alt, sizeof(((GPR *)nullptr)->reg), GPR_OFFSET(reg), eEncodingUint, \
42+
eFormatHex, \
43+
{kind1, kind2, kind3, kind4, lldb_##reg##_i386 }, nullptr, nullptr, \
44+
nullptr, 0 \
45+
}
46+
47+
// clang-format off
48+
static RegisterInfo g_register_infos_i386[] = {
49+
// General purpose registers EH_Frame DWARF Generic Process Plugin
50+
// =========================== ================== ================ ========================= ====================
51+
DEFINE_GPR(eax, nullptr, ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
52+
DEFINE_GPR(ebx, nullptr, ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
53+
DEFINE_GPR(ecx, nullptr, ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
54+
DEFINE_GPR(edx, nullptr, ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
55+
DEFINE_GPR(edi, nullptr, ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
56+
DEFINE_GPR(esi, nullptr, ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
57+
DEFINE_GPR(ebp, "fp", ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
58+
DEFINE_GPR(esp, "sp", ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
59+
DEFINE_GPR(eip, "pc", ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
60+
DEFINE_GPR(eflags, "flags", ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
61+
DEFINE_GPR(cs, nullptr, LLDB_INVALID_REGNUM, dwarf_cs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
62+
DEFINE_GPR(fs, nullptr, LLDB_INVALID_REGNUM, dwarf_fs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
63+
DEFINE_GPR(gs, nullptr, LLDB_INVALID_REGNUM, dwarf_gs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
64+
DEFINE_GPR(ss, nullptr, LLDB_INVALID_REGNUM, dwarf_ss_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
65+
DEFINE_GPR(ds, nullptr, LLDB_INVALID_REGNUM, dwarf_ds_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
66+
DEFINE_GPR(es, nullptr, LLDB_INVALID_REGNUM, dwarf_es_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
67+
};
68+
// clang-format on
69+
} // namespace
70+
71+
RegisterContextWindows_i386::RegisterContextWindows_i386(
72+
const ArchSpec &target_arch)
73+
: lldb_private::RegisterInfoInterface(target_arch) {
74+
assert(target_arch.GetMachine() == llvm::Triple::x86);
75+
}
76+
77+
const RegisterInfo *RegisterContextWindows_i386::GetRegisterInfo() const {
78+
return g_register_infos_i386;
79+
}
80+
81+
uint32_t RegisterContextWindows_i386::GetRegisterCount() const {
82+
return llvm::array_lengthof(g_register_infos_i386);
83+
}
84+
85+
uint32_t RegisterContextWindows_i386::GetUserRegisterCount() const {
86+
return llvm::array_lengthof(g_register_infos_i386);
87+
}
88+
89+
size_t RegisterContextWindows_i386::GetGPRSize() const { return sizeof(GPR); }
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===-- RegisterContextWindows_i386.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_RegisterContextWindows_i386_H_
10+
#define liblldb_RegisterContextWindows_i386_H_
11+
12+
#include "RegisterInfoInterface.h"
13+
14+
class RegisterContextWindows_i386 : public lldb_private::RegisterInfoInterface {
15+
public:
16+
RegisterContextWindows_i386(const lldb_private::ArchSpec &target_arch);
17+
18+
size_t GetGPRSize() const override;
19+
20+
const lldb_private::RegisterInfo *GetRegisterInfo() const override;
21+
22+
uint32_t GetRegisterCount() const override;
23+
24+
uint32_t GetUserRegisterCount() const override;
25+
};
26+
27+
#endif
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
//===-- RegisterContextWindows_x86_64.cpp -----------------------*- 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+
#include "RegisterContextWindows_x86_64.h"
10+
#include "RegisterContext_x86.h"
11+
#include "lldb-x86-register-enums.h"
12+
13+
#include <vector>
14+
15+
using namespace lldb_private;
16+
using namespace lldb;
17+
18+
namespace {
19+
typedef struct _GPR {
20+
uint64_t rax;
21+
uint64_t rcx;
22+
uint64_t rdx;
23+
uint64_t rbx;
24+
uint64_t rsp;
25+
uint64_t rbp;
26+
uint64_t rsi;
27+
uint64_t rdi;
28+
uint64_t r8;
29+
uint64_t r9;
30+
uint64_t r10;
31+
uint64_t r11;
32+
uint64_t r12;
33+
uint64_t r13;
34+
uint64_t r14;
35+
uint64_t r15;
36+
uint64_t rip;
37+
uint64_t rflags;
38+
uint16_t cs;
39+
uint16_t fs;
40+
uint16_t gs;
41+
uint16_t ss;
42+
uint16_t ds;
43+
uint16_t es;
44+
} GPR;
45+
46+
#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname))
47+
#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
48+
{ \
49+
#reg, alt, sizeof(((GPR *)nullptr)->reg), GPR_OFFSET(reg), eEncodingUint, \
50+
eFormatHex, \
51+
{kind1, kind2, kind3, kind4, lldb_##reg##_x86_64 }, nullptr, nullptr, \
52+
nullptr, 0 \
53+
}
54+
55+
typedef struct _FPReg {
56+
XMMReg xmm0;
57+
XMMReg xmm1;
58+
XMMReg xmm2;
59+
XMMReg xmm3;
60+
XMMReg xmm4;
61+
XMMReg xmm5;
62+
XMMReg xmm6;
63+
XMMReg xmm7;
64+
XMMReg xmm8;
65+
XMMReg xmm9;
66+
XMMReg xmm10;
67+
XMMReg xmm11;
68+
XMMReg xmm12;
69+
XMMReg xmm13;
70+
XMMReg xmm14;
71+
XMMReg xmm15;
72+
} FPReg;
73+
74+
#define FPR_OFFSET(regname) \
75+
(sizeof(GPR) + LLVM_EXTENSION offsetof(FPReg, regname))
76+
77+
#define DEFINE_XMM(reg) \
78+
#reg, NULL, sizeof(((FPReg *)nullptr)->reg), FPR_OFFSET(reg), eEncodingUint, \
79+
eFormatVectorOfUInt64, \
80+
{dwarf_##reg##_x86_64, dwarf_##reg##_x86_64, LLDB_INVALID_REGNUM, \
81+
LLDB_INVALID_REGNUM, lldb_##reg##_x86_64 }, \
82+
nullptr, nullptr, nullptr, 0
83+
84+
// clang-format off
85+
static RegisterInfo g_register_infos_x86_64[] = {
86+
// General purpose registers EH_Frame DWARF Generic Process Plugin
87+
// =========================== ================== ================ ========================= ====================
88+
DEFINE_GPR(rax, nullptr, dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
89+
DEFINE_GPR(rbx, nullptr, dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
90+
DEFINE_GPR(rcx, "arg4", dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
91+
DEFINE_GPR(rdx, "arg3", dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
92+
DEFINE_GPR(rdi, "arg1", dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
93+
DEFINE_GPR(rsi, "arg2", dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM),
94+
DEFINE_GPR(rbp, "fp", dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
95+
DEFINE_GPR(rsp, "sp", dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
96+
DEFINE_GPR(r8, "arg5", dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM),
97+
DEFINE_GPR(r9, "arg6", dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM),
98+
DEFINE_GPR(r10, nullptr, dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
99+
DEFINE_GPR(r11, nullptr, dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
100+
DEFINE_GPR(r12, nullptr, dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
101+
DEFINE_GPR(r13, nullptr, dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
102+
DEFINE_GPR(r14, nullptr, dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
103+
DEFINE_GPR(r15, nullptr, dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
104+
DEFINE_GPR(rip, "pc", dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
105+
DEFINE_GPR(rflags, "flags", dwarf_rflags_x86_64, dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
106+
DEFINE_GPR(cs, nullptr, dwarf_cs_x86_64, dwarf_cs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
107+
DEFINE_GPR(fs, nullptr, dwarf_fs_x86_64, dwarf_fs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
108+
DEFINE_GPR(gs, nullptr, dwarf_gs_x86_64, dwarf_gs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
109+
DEFINE_GPR(ss, nullptr, dwarf_ss_x86_64, dwarf_ss_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
110+
DEFINE_GPR(ds, nullptr, dwarf_ds_x86_64, dwarf_ds_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
111+
DEFINE_GPR(es, nullptr, dwarf_es_x86_64, dwarf_es_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
112+
DEFINE_XMM(xmm0),
113+
DEFINE_XMM(xmm1),
114+
DEFINE_XMM(xmm2),
115+
DEFINE_XMM(xmm3),
116+
DEFINE_XMM(xmm4),
117+
DEFINE_XMM(xmm5),
118+
DEFINE_XMM(xmm6),
119+
DEFINE_XMM(xmm7),
120+
DEFINE_XMM(xmm8),
121+
DEFINE_XMM(xmm9),
122+
DEFINE_XMM(xmm10),
123+
DEFINE_XMM(xmm11),
124+
DEFINE_XMM(xmm12),
125+
DEFINE_XMM(xmm13),
126+
DEFINE_XMM(xmm14),
127+
DEFINE_XMM(xmm15)
128+
};
129+
// clang-format on
130+
} // namespace
131+
132+
RegisterContextWindows_x86_64::RegisterContextWindows_x86_64(
133+
const ArchSpec &target_arch)
134+
: lldb_private::RegisterInfoInterface(target_arch) {
135+
assert(target_arch.GetMachine() == llvm::Triple::x86_64);
136+
}
137+
138+
const RegisterInfo *RegisterContextWindows_x86_64::GetRegisterInfo() const {
139+
return g_register_infos_x86_64;
140+
}
141+
142+
uint32_t RegisterContextWindows_x86_64::GetRegisterCount() const {
143+
return llvm::array_lengthof(g_register_infos_x86_64);
144+
}
145+
146+
uint32_t RegisterContextWindows_x86_64::GetUserRegisterCount() const {
147+
return llvm::array_lengthof(g_register_infos_x86_64);
148+
}
149+
150+
size_t RegisterContextWindows_x86_64::GetGPRSize() const { return sizeof(GPR); }
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===-- RegisterContextWindows_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_RegisterContextWindows_x86_64_H_
10+
#define liblldb_RegisterContextWindows_x86_64_H_
11+
12+
#include "RegisterInfoInterface.h"
13+
14+
class RegisterContextWindows_x86_64
15+
: public lldb_private::RegisterInfoInterface {
16+
public:
17+
RegisterContextWindows_x86_64(const lldb_private::ArchSpec &target_arch);
18+
19+
size_t GetGPRSize() const override;
20+
21+
const lldb_private::RegisterInfo *GetRegisterInfo() const override;
22+
23+
uint32_t GetRegisterCount() const override;
24+
25+
uint32_t GetUserRegisterCount() const override;
26+
};
27+
28+
#endif

lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
add_lldb_library(lldbPluginProcessWindowsCommon PLUGIN
33
DebuggerThread.cpp
44
LocalDebugDelegate.cpp
5+
NativeProcessWindows.cpp
6+
NativeRegisterContextWindows.cpp
7+
NativeRegisterContextWindows_i386.cpp
8+
NativeRegisterContextWindows_WoW64.cpp
9+
NativeRegisterContextWindows_x86_64.cpp
10+
NativeThreadWindows.cpp
511
ProcessDebugger.cpp
612
ProcessWindows.cpp
713
ProcessWindowsLog.cpp

lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
#include "llvm/Support/Threading.h"
3030
#include "llvm/Support/raw_ostream.h"
3131

32+
#ifndef STATUS_WX86_BREAKPOINT
33+
#define STATUS_WX86_BREAKPOINT 0x4000001FL // For WOW64
34+
#endif
35+
3236
using namespace lldb;
3337
using namespace lldb_private;
3438

@@ -350,7 +354,8 @@ DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info,
350354
// we use simply to wake up the DebuggerThread so that we can close out the
351355
// debug loop.
352356
if (m_pid_to_detach != 0 &&
353-
info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) {
357+
(info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT ||
358+
info.ExceptionRecord.ExceptionCode == STATUS_WX86_BREAKPOINT)) {
354359
LLDB_LOG(log, "Breakpoint exception is cue to detach from process {0:x}",
355360
m_pid_to_detach.load());
356361
::DebugActiveProcessStop(m_pid_to_detach);

0 commit comments

Comments
 (0)