19
19
20
20
#include " Plugins/Process/Utility/RegisterContextLinux_i386.h"
21
21
#include " Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
22
-
22
+ # include < cpuid.h >
23
23
#include < linux/elf.h>
24
24
25
+ // Newer toolchains define __get_cpuid_count in cpuid.h, but some
26
+ // older-but-still-supported ones (e.g. gcc 5.4.0) don't, so we
27
+ // define it locally here, following the definition in clang/lib/Headers.
28
+ static inline int get_cpuid_count (unsigned int __leaf,
29
+ unsigned int __subleaf,
30
+ unsigned int *__eax, unsigned int *__ebx,
31
+ unsigned int *__ecx, unsigned int *__edx)
32
+ {
33
+ unsigned int __max_leaf = __get_cpuid_max (__leaf & 0x80000000 , 0 );
34
+
35
+ if (__max_leaf == 0 || __max_leaf < __leaf)
36
+ return 0 ;
37
+
38
+ __cpuid_count (__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
39
+ return 1 ;
40
+ }
41
+
25
42
using namespace lldb_private ;
26
43
using namespace lldb_private ::process_linux;
27
44
@@ -268,12 +285,29 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) {
268
285
}
269
286
}
270
287
288
+ // Return the size of the XSTATE area supported on this cpu. It is necessary to
289
+ // allocate the full size of the area even if we do not use/recognise all of it
290
+ // because ptrace(PTRACE_SETREGSET, NT_X86_XSTATE) will refuse to write to it if
291
+ // we do not pass it a buffer of sufficient size. The size is always at least
292
+ // sizeof(FPR) so that the allocated buffer can be safely cast to FPR*.
293
+ static std::size_t GetXSTATESize () {
294
+ unsigned int eax, ebx, ecx, edx;
295
+ // First check whether the XSTATE are is supported at all.
296
+ if (!__get_cpuid (1 , &eax, &ebx, &ecx, &edx) || !(ecx & bit_XSAVE))
297
+ return sizeof (FPR);
298
+
299
+ // Then fetch the maximum size of the area.
300
+ if (!get_cpuid_count (0x0d , 0 , &eax, &ebx, &ecx, &edx))
301
+ return sizeof (FPR);
302
+ return std::max<std::size_t >(ecx, sizeof (FPR));
303
+ }
304
+
271
305
NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (
272
306
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
273
307
: NativeRegisterContextLinux(native_thread,
274
308
CreateRegisterInfoInterface (target_arch)),
275
- m_xstate_type(XStateType::Invalid), m_fpr (), m_iovec(), m_ymm_set (),
276
- m_mpx_set(), m_reg_info(), m_gpr_x86_64() {
309
+ m_xstate_type(XStateType::Invalid), m_ymm_set (), m_mpx_set (),
310
+ m_reg_info(), m_gpr_x86_64() {
277
311
// Set up data about ranges of valid registers.
278
312
switch (target_arch.GetMachine ()) {
279
313
case llvm::Triple::x86:
@@ -329,14 +363,13 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
329
363
break ;
330
364
}
331
365
332
- // Initialize m_iovec to point to the buffer and buffer size using the
333
- // conventions of Berkeley style UIO structures, as required by PTRACE
334
- // extensions.
335
- m_iovec.iov_base = &m_fpr;
336
- m_iovec.iov_len = sizeof (m_fpr);
366
+ std::size_t xstate_size = GetXSTATESize ();
367
+ m_xstate.reset (static_cast <FPR *>(std::malloc (xstate_size)));
368
+ m_iovec.iov_base = m_xstate.get ();
369
+ m_iovec.iov_len = xstate_size;
337
370
338
371
// Clear out the FPR state.
339
- ::memset (&m_fpr , 0 , sizeof (m_fpr) );
372
+ ::memset (m_xstate.get() , 0, xstate_size );
340
373
341
374
// Store byte offset of fctrl (i.e. first register of FPR)
342
375
const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName (" fctrl" );
@@ -439,14 +472,17 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
439
472
440
473
if (byte_order != lldb::eByteOrderInvalid) {
441
474
if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st )
442
- reg_value.SetBytes (m_fpr.fxsave .stmm [reg - m_reg_info.first_st ].bytes ,
443
- reg_info->byte_size , byte_order);
475
+ reg_value.SetBytes (
476
+ m_xstate->fxsave .stmm [reg - m_reg_info.first_st ].bytes ,
477
+ reg_info->byte_size , byte_order);
444
478
if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm )
445
- reg_value.SetBytes (m_fpr.fxsave .stmm [reg - m_reg_info.first_mm ].bytes ,
446
- reg_info->byte_size , byte_order);
479
+ reg_value.SetBytes (
480
+ m_xstate->fxsave .stmm [reg - m_reg_info.first_mm ].bytes ,
481
+ reg_info->byte_size , byte_order);
447
482
if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm )
448
- reg_value.SetBytes (m_fpr.fxsave .xmm [reg - m_reg_info.first_xmm ].bytes ,
449
- reg_info->byte_size , byte_order);
483
+ reg_value.SetBytes (
484
+ m_xstate->fxsave .xmm [reg - m_reg_info.first_xmm ].bytes ,
485
+ reg_info->byte_size , byte_order);
450
486
if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm ) {
451
487
// Concatenate ymm using the register halves in xmm.bytes and
452
488
// ymmh.bytes
@@ -488,7 +524,7 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
488
524
return error;
489
525
}
490
526
491
- // Get pointer to m_fpr. fxsave variable and set the data from it.
527
+ // Get pointer to m_xstate-> fxsave variable and set the data from it.
492
528
493
529
// Byte offsets of all registers are calculated wrt 'UserArea' structure.
494
530
// However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)}
@@ -499,9 +535,9 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
499
535
// Since, FPR structure is also one of the member of UserArea structure.
500
536
// byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
501
537
// byte_offset(fctrl wrt UserArea)
502
- assert ((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof (m_fpr ));
503
- uint8_t *src =
504
- ( uint8_t *)&m_fpr + reg_info-> byte_offset - m_fctrl_offset_in_userarea;
538
+ assert ((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof (FPR ));
539
+ uint8_t *src = ( uint8_t *)m_xstate. get () + reg_info-> byte_offset -
540
+ m_fctrl_offset_in_userarea;
505
541
switch (reg_info->byte_size ) {
506
542
case 1 :
507
543
reg_value.SetUInt8 (*(uint8_t *)src);
@@ -527,7 +563,7 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
527
563
528
564
void NativeRegisterContextLinux_x86_64::UpdateXSTATEforWrite (
529
565
uint32_t reg_index) {
530
- XSAVE_HDR::XFeature &xstate_bv = m_fpr. xsave .header .xstate_bv ;
566
+ XSAVE_HDR::XFeature &xstate_bv = m_xstate-> xsave .header .xstate_bv ;
531
567
if (IsFPR (reg_index)) {
532
568
// IsFPR considers both %st and %xmm registers as floating point, but these
533
569
// map to two features. Set both flags, just in case.
@@ -559,15 +595,15 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister(
559
595
if (IsFPR (reg_index) || IsAVX (reg_index) || IsMPX (reg_index)) {
560
596
if (reg_info->encoding == lldb::eEncodingVector) {
561
597
if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st )
562
- ::memcpy (m_fpr. fxsave.stmm[reg_index - m_reg_info.first_st].bytes,
598
+ ::memcpy (m_xstate-> fxsave.stmm[reg_index - m_reg_info.first_st].bytes,
563
599
reg_value.GetBytes(), reg_value.GetByteSize());
564
600
565
601
if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm )
566
- ::memcpy (m_fpr. fxsave.stmm[reg_index - m_reg_info.first_mm].bytes,
602
+ ::memcpy (m_xstate-> fxsave.stmm[reg_index - m_reg_info.first_mm].bytes,
567
603
reg_value.GetBytes(), reg_value.GetByteSize());
568
604
569
605
if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm )
570
- ::memcpy (m_fpr. fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes,
606
+ ::memcpy (m_xstate-> fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes,
571
607
reg_value.GetBytes(), reg_value.GetByteSize());
572
608
573
609
if (reg_index >= m_reg_info.first_ymm &&
@@ -596,7 +632,7 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister(
596
632
return Status (" CopyMPXtoXSTATE() failed" );
597
633
}
598
634
} else {
599
- // Get pointer to m_fpr. fxsave variable and set the data to it.
635
+ // Get pointer to m_xstate-> fxsave variable and set the data to it.
600
636
601
637
// Byte offsets of all registers are calculated wrt 'UserArea' structure.
602
638
// However, WriteFPR() takes m_fpr (of type FPR structure) and writes
@@ -608,8 +644,8 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister(
608
644
// byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
609
645
// byte_offset(fctrl wrt UserArea)
610
646
assert ((reg_info->byte_offset - m_fctrl_offset_in_userarea) <
611
- sizeof (m_fpr ));
612
- uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset -
647
+ sizeof (FPR ));
648
+ uint8_t *dst = (uint8_t *)m_xstate. get () + reg_info->byte_offset -
613
649
m_fctrl_offset_in_userarea;
614
650
switch (reg_info->byte_size ) {
615
651
case 1 :
@@ -667,7 +703,7 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues(
667
703
::memcpy (dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
668
704
dst += GetRegisterInfoInterface ().GetGPRSize ();
669
705
if (m_xstate_type == XStateType::FXSAVE)
670
- ::memcpy (dst, &m_fpr. fxsave, sizeof (m_fpr. fxsave));
706
+ ::memcpy (dst, &m_xstate-> fxsave, sizeof (m_xstate-> fxsave));
671
707
else if (m_xstate_type == XStateType::XSAVE) {
672
708
lldb::ByteOrder byte_order = GetByteOrder ();
673
709
@@ -700,7 +736,7 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues(
700
736
}
701
737
}
702
738
// Copy the extended register state including the assembled ymm registers.
703
- ::memcpy (dst, &m_fpr , sizeof (m_fpr ));
739
+ ::memcpy (dst, m_xstate.get() , sizeof(FPR ));
704
740
} else {
705
741
assert (false && " how do we save the floating point registers?" );
706
742
error.SetErrorString (" unsure how to save the floating point registers" );
@@ -758,9 +794,9 @@ Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues(
758
794
759
795
src += GetRegisterInfoInterface ().GetGPRSize ();
760
796
if (m_xstate_type == XStateType::FXSAVE)
761
- ::memcpy (&m_fpr. fxsave, src, sizeof (m_fpr. fxsave));
797
+ ::memcpy (&m_xstate-> fxsave, src, sizeof (m_xstate-> fxsave));
762
798
else if (m_xstate_type == XStateType::XSAVE)
763
- ::memcpy (&m_fpr. xsave, src, sizeof (m_fpr. xsave));
799
+ ::memcpy (&m_xstate-> xsave, src, sizeof (m_xstate-> xsave));
764
800
765
801
error = WriteFPR ();
766
802
if (error.Fail ())
@@ -814,12 +850,12 @@ bool NativeRegisterContextLinux_x86_64::IsCPUFeatureAvailable(
814
850
return true ;
815
851
case RegSet::avx: // Check if CPU has AVX and if there is kernel support, by
816
852
// reading in the XCR0 area of XSAVE.
817
- if ((m_fpr. xsave .i387 .xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX)
853
+ if ((m_xstate-> xsave .i387 .xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX)
818
854
return true ;
819
855
break ;
820
856
case RegSet::mpx: // Check if CPU has MPX and if there is kernel support, by
821
857
// reading in the XCR0 area of XSAVE.
822
- if ((m_fpr. xsave .i387 .xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX)
858
+ if ((m_xstate-> xsave .i387 .xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX)
823
859
return true ;
824
860
break ;
825
861
}
@@ -856,10 +892,10 @@ Status NativeRegisterContextLinux_x86_64::WriteFPR() {
856
892
switch (m_xstate_type) {
857
893
case XStateType::FXSAVE:
858
894
return WriteRegisterSet (
859
- &m_iovec, sizeof (m_fpr. fxsave ),
895
+ &m_iovec, sizeof (m_xstate-> fxsave ),
860
896
fxsr_regset (GetRegisterInfoInterface ().GetTargetArchitecture ()));
861
897
case XStateType::XSAVE:
862
- return WriteRegisterSet (&m_iovec, sizeof (m_fpr. xsave ), NT_X86_XSTATE);
898
+ return WriteRegisterSet (&m_iovec, sizeof (m_xstate-> xsave ), NT_X86_XSTATE);
863
899
default :
864
900
return Status (" Unrecognized FPR type." );
865
901
}
@@ -879,22 +915,22 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM(
879
915
880
916
if (byte_order == lldb::eByteOrderLittle) {
881
917
::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
882
- m_fpr. fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
918
+ m_xstate-> fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
883
919
sizeof (XMMReg));
884
920
::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes +
885
921
sizeof (XMMReg),
886
- m_fpr. xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
922
+ m_xstate-> xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
887
923
sizeof(YMMHReg));
888
924
return true ;
889
925
}
890
926
891
927
if (byte_order == lldb::eByteOrderBig) {
892
928
::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes +
893
929
sizeof (XMMReg),
894
- m_fpr. fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
930
+ m_xstate-> fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
895
931
sizeof(XMMReg));
896
932
::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
897
- m_fpr. xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
933
+ m_xstate-> xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
898
934
sizeof (YMMHReg));
899
935
return true ;
900
936
}
@@ -907,19 +943,19 @@ bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(
907
943
return false ;
908
944
909
945
if (byte_order == lldb::eByteOrderLittle) {
910
- ::memcpy (m_fpr. fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
946
+ ::memcpy (m_xstate-> fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
911
947
m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof (XMMReg));
912
- ::memcpy (m_fpr. xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
948
+ ::memcpy (m_xstate-> xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
913
949
m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof (XMMReg),
914
950
sizeof(YMMHReg));
915
951
return true ;
916
952
}
917
953
918
954
if (byte_order == lldb::eByteOrderBig) {
919
- ::memcpy (m_fpr. fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
955
+ ::memcpy (m_xstate-> fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
920
956
m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof (XMMReg),
921
957
sizeof(XMMReg));
922
- ::memcpy (m_fpr. xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
958
+ ::memcpy (m_xstate-> xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
923
959
m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof (YMMHReg));
924
960
return true ;
925
961
}
@@ -929,7 +965,7 @@ bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(
929
965
void *NativeRegisterContextLinux_x86_64::GetFPRBuffer () {
930
966
switch (m_xstate_type) {
931
967
case XStateType::FXSAVE:
932
- return &m_fpr. fxsave ;
968
+ return &m_xstate-> fxsave ;
933
969
case XStateType::XSAVE:
934
970
return &m_iovec;
935
971
default :
@@ -940,7 +976,7 @@ void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() {
940
976
size_t NativeRegisterContextLinux_x86_64::GetFPRSize () {
941
977
switch (m_xstate_type) {
942
978
case XStateType::FXSAVE:
943
- return sizeof (m_fpr. fxsave );
979
+ return sizeof (m_xstate-> fxsave );
944
980
case XStateType::XSAVE:
945
981
return sizeof (m_iovec);
946
982
default :
@@ -953,14 +989,14 @@ Status NativeRegisterContextLinux_x86_64::ReadFPR() {
953
989
954
990
// Probe XSAVE and if it is not supported fall back to FXSAVE.
955
991
if (m_xstate_type != XStateType::FXSAVE) {
956
- error = ReadRegisterSet (&m_iovec, sizeof (m_fpr. xsave ), NT_X86_XSTATE);
992
+ error = ReadRegisterSet (&m_iovec, sizeof (m_xstate-> xsave ), NT_X86_XSTATE);
957
993
if (!error.Fail ()) {
958
994
m_xstate_type = XStateType::XSAVE;
959
995
return error;
960
996
}
961
997
}
962
998
error = ReadRegisterSet (
963
- &m_iovec, sizeof (m_fpr. xsave ),
999
+ &m_iovec, sizeof (m_xstate-> xsave ),
964
1000
fxsr_regset (GetRegisterInfoInterface ().GetTargetArchitecture ()));
965
1001
if (!error.Fail ()) {
966
1002
m_xstate_type = XStateType::FXSAVE;
@@ -982,11 +1018,11 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) {
982
1018
983
1019
if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr ) {
984
1020
::memcpy (m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,
985
- m_fpr. xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
1021
+ m_xstate-> xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
986
1022
sizeof (MPXReg));
987
1023
} else {
988
1024
::memcpy (m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,
989
- m_fpr. xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
1025
+ m_xstate-> xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
990
1026
sizeof (MPXCsr));
991
1027
}
992
1028
return true ;
@@ -997,10 +1033,10 @@ bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) {
997
1033
return false ;
998
1034
999
1035
if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr ) {
1000
- ::memcpy (m_fpr. xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
1036
+ ::memcpy (m_xstate-> xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
1001
1037
m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof (MPXReg));
1002
1038
} else {
1003
- ::memcpy (m_fpr. xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
1039
+ ::memcpy (m_xstate-> xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
1004
1040
m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof (MPXCsr));
1005
1041
}
1006
1042
return true ;
0 commit comments