Skip to content

Commit e46c664

Browse files
gbuenoandradelabath
authored andcommitted
[lldb] Fix offset intersection bug between MPX and AVX registers
Summary: This change increases the offset of MPX registers (by 128) so they do not overlap with the offset associated with AVX registers. That was causing MPX data in GDBRemoteRegisterContext::m_reg_data to get overwritten. Reviewers: labath Reviewed By: labath Subscribers: JDevlieghere, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D68874
1 parent 92aa0c2 commit e46c664

File tree

8 files changed

+103
-4
lines changed

8 files changed

+103
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CXX_SOURCES := main.cpp
2+
3+
include Makefile.rules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""
2+
Test Intel(R) MPX registers do not get overwritten by AVX data.
3+
"""
4+
5+
from __future__ import print_function
6+
7+
8+
import lldb
9+
from lldbsuite.test.decorators import *
10+
from lldbsuite.test.lldbtest import *
11+
from lldbsuite.test import lldbutil
12+
13+
14+
class MPXOffsetIntersectionTestCase(TestBase):
15+
16+
mydir = TestBase.compute_mydir(__file__)
17+
18+
AVX_REGS = ('ymm' + str(i) for i in range(16))
19+
YMM_VALUE = '{' + ' '.join(('0x00' for _ in range(32))) + '}'
20+
21+
MPX_REGULAR_REGS = ('bnd0', 'bnd1', 'bnd2', 'bnd3')
22+
MPX_CONFIG_REGS = ('bndcfgu', 'bndstatus')
23+
BND_VALUE = '{' + ' '.join(('0xff' for _ in range(16))) + '}'
24+
25+
def setUp(self):
26+
TestBase.setUp(self)
27+
28+
@skipIf(oslist=no_match(['linux']))
29+
@skipIf(archs=no_match(['x86_64']))
30+
def test_mpx_registers_offset_intersection(self):
31+
"""Test if AVX data does not overwrite MPX values."""
32+
self.build()
33+
self.mpx_registers_offset_intersection()
34+
35+
def mpx_registers_offset_intersection(self):
36+
exe = self.getBuildArtifact('a.out')
37+
self.runCmd('file ' + exe, CURRENT_EXECUTABLE_SET)
38+
self.runCmd('run', RUN_SUCCEEDED)
39+
target = self.dbg.GetSelectedTarget()
40+
process = target.GetProcess()
41+
thread = process.GetThreadAtIndex(0)
42+
currentFrame = thread.GetFrameAtIndex(0)
43+
44+
has_avx = False
45+
has_mpx = False
46+
for registerSet in currentFrame.GetRegisters():
47+
if 'advanced vector extensions' in registerSet.GetName().lower():
48+
has_avx = True
49+
if 'memory protection extension' in registerSet.GetName().lower():
50+
has_mpx = True
51+
if not (has_avx and has_mpx):
52+
self.skipTest('Both AVX and MPX registers must be supported.')
53+
54+
for reg in self.AVX_REGS:
55+
self.runCmd('register write ' + reg + " '" + self.YMM_VALUE + " '")
56+
for reg in self.MPX_REGULAR_REGS + self.MPX_CONFIG_REGS:
57+
self.runCmd('register write ' + reg + " '" + self.BND_VALUE + " '")
58+
59+
self.verify_mpx()
60+
self.verify_avx()
61+
self.verify_mpx()
62+
63+
def verify_mpx(self):
64+
for reg in self.MPX_REGULAR_REGS:
65+
self.expect('register read ' + reg,
66+
substrs = [reg + ' = {0xffffffffffffffff 0xffffffffffffffff}'])
67+
for reg in self.MPX_CONFIG_REGS:
68+
self.expect('register read ' + reg,
69+
substrs = [reg + ' = {0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff}'])
70+
71+
def verify_avx(self):
72+
for reg in self.AVX_REGS:
73+
self.expect('register read ' + reg, substrs = [reg + ' = ' + self.YMM_VALUE])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <cstdint>
2+
3+
int main() {
4+
asm volatile("int3");
5+
return 0;
6+
}

lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Status NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index,
3434
if (!reg_info)
3535
return Status("register %" PRIu32 " not found", reg_index);
3636

37-
return DoReadRegisterValue(reg_info->byte_offset, reg_info->name,
37+
return DoReadRegisterValue(GetPtraceOffset(reg_index), reg_info->name,
3838
reg_info->byte_size, reg_value);
3939
}
4040

@@ -91,7 +91,8 @@ NativeRegisterContextLinux::WriteRegisterRaw(uint32_t reg_index,
9191
"for write register index %" PRIu32,
9292
__FUNCTION__, reg_to_write);
9393

94-
return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, reg_value);
94+
return DoWriteRegisterValue(GetPtraceOffset(reg_index), reg_info->name,
95+
reg_value);
9596
}
9697

9798
Status NativeRegisterContextLinux::ReadGPR() {

lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ class NativeRegisterContextLinux : public NativeRegisterContextRegisterInfo {
6060

6161
virtual size_t GetFPRSize() = 0;
6262

63+
virtual uint32_t GetPtraceOffset(uint32_t reg_index) {
64+
return GetRegisterInfoAtIndex(reg_index)->byte_offset;
65+
}
66+
6367
// The Do*** functions are executed on the privileged thread and can perform
6468
// ptrace
6569
// operations directly.

lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,4 +1213,11 @@ uint32_t NativeRegisterContextLinux_x86_64::NumSupportedHardwareWatchpoints() {
12131213
return 4;
12141214
}
12151215

1216+
uint32_t
1217+
NativeRegisterContextLinux_x86_64::GetPtraceOffset(uint32_t reg_index) {
1218+
// If register is MPX, remove extra factor from gdb offset
1219+
return GetRegisterInfoAtIndex(reg_index)->byte_offset -
1220+
(IsMPX(reg_index) ? 128 : 0);
1221+
}
1222+
12161223
#endif // defined(__i386__) || defined(__x86_64__)

lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux {
7575

7676
Status WriteFPR() override;
7777

78+
uint32_t GetPtraceOffset(uint32_t reg_index) override;
79+
7880
private:
7981
// Private member types.
8082
enum class XStateType { Invalid, FXSAVE, XSAVE };

lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,18 @@
2525
LLVM_EXTENSION offsetof(FPR, xsave) + \
2626
LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + (32 * reg_index))
2727

28+
// Guarantees BNDR/BNDC offsets do not overlap with YMM offsets.
29+
#define GDB_REMOTE_OFFSET 128
30+
2831
#define BNDR_OFFSET(reg_index) \
2932
(LLVM_EXTENSION offsetof(UserArea, fpr) + \
3033
LLVM_EXTENSION offsetof(FPR, xsave) + \
31-
LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index]))
34+
LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index]) + GDB_REMOTE_OFFSET)
3235

3336
#define BNDC_OFFSET(reg_index) \
3437
(LLVM_EXTENSION offsetof(UserArea, fpr) + \
3538
LLVM_EXTENSION offsetof(FPR, xsave) + \
36-
LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index]))
39+
LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index]) + GDB_REMOTE_OFFSET)
3740

3841
#ifdef DECLARE_REGISTER_INFOS_X86_64_STRUCT
3942

0 commit comments

Comments
 (0)