@@ -499,76 +499,119 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
499
499
return Status (" Failed to write register value" );
500
500
}
501
501
502
- Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues (
503
- lldb::WritableDataBufferSP &data_sp) {
504
- // AArch64 register data must contain GPRs and either FPR or SVE registers.
505
- // SVE registers can be non-streaming (aka SVE) or streaming (aka SSVE).
506
- // Finally an optional MTE register. Pointer Authentication (PAC) registers
507
- // are read-only and will be skipped.
502
+ enum RegisterSetType : uint32_t {
503
+ GPR,
504
+ SVE, // Used for SVE and SSVE.
505
+ FPR, // When there is no SVE, or SVE in FPSIMD mode.
506
+ MTE,
507
+ TLS,
508
+ };
509
+
510
+ static uint8_t *AddRegisterSetType (uint8_t *dst,
511
+ RegisterSetType register_set_type) {
512
+ *(reinterpret_cast <uint32_t *>(dst)) = register_set_type;
513
+ return dst + sizeof (uint32_t );
514
+ }
508
515
509
- // In order to create register data checkpoint we first read all register
510
- // values if not done already and calculate total size of register set data.
511
- // We store all register values in data_sp by copying full PTrace data that
512
- // corresponds to register sets enabled by current register context.
516
+ static uint8_t * AddSavedRegistersData ( uint8_t *dst, void *src, size_t size) {
517
+ ::memcpy (dst, src, size);
518
+ return dst + size;
519
+ }
513
520
521
+ static uint8_t *AddSavedRegisters (uint8_t *dst,
522
+ enum RegisterSetType register_set_type,
523
+ void *src, size_t size) {
524
+ dst = AddRegisterSetType (dst, register_set_type);
525
+ return AddSavedRegistersData (dst, src, size);
526
+ }
527
+
528
+ Status
529
+ NativeRegisterContextLinux_arm64::CacheAllRegisters (uint32_t &cached_size) {
514
530
Status error;
515
- uint32_t reg_data_byte_size = GetGPRBufferSize ();
531
+ cached_size = sizeof (RegisterSetType) + GetGPRBufferSize ();
516
532
error = ReadGPR ();
517
533
if (error.Fail ())
518
534
return error;
519
535
520
536
// If SVE is enabled we need not copy FPR separately.
521
537
if (GetRegisterInfo ().IsSVEEnabled () || GetRegisterInfo ().IsSSVEEnabled ()) {
522
- reg_data_byte_size += GetSVEBufferSize ();
523
- // Also store the current SVE mode.
524
- reg_data_byte_size += sizeof (uint32_t );
538
+ // Store mode and register data.
539
+ cached_size +=
540
+ sizeof (RegisterSetType) + sizeof (m_sve_state) + GetSVEBufferSize ( );
525
541
error = ReadAllSVE ();
526
542
} else {
527
- reg_data_byte_size += GetFPRSize ();
543
+ cached_size += sizeof (RegisterSetType) + GetFPRSize ();
528
544
error = ReadFPR ();
529
545
}
530
546
if (error.Fail ())
531
547
return error;
532
548
533
549
if (GetRegisterInfo ().IsMTEEnabled ()) {
534
- reg_data_byte_size += GetMTEControlSize ();
550
+ cached_size += sizeof (RegisterSetType) + GetMTEControlSize ();
535
551
error = ReadMTEControl ();
536
552
if (error.Fail ())
537
553
return error;
538
554
}
539
555
540
556
// tpidr is always present but tpidr2 depends on SME.
541
- reg_data_byte_size += GetTLSBufferSize ();
557
+ cached_size += sizeof (RegisterSetType) + GetTLSBufferSize ();
542
558
error = ReadTLS ();
559
+
560
+ return error;
561
+ }
562
+
563
+ Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues (
564
+ lldb::WritableDataBufferSP &data_sp) {
565
+ // AArch64 register data must contain GPRs and either FPR or SVE registers.
566
+ // SVE registers can be non-streaming (aka SVE) or streaming (aka SSVE).
567
+ // Finally an optional MTE register. Pointer Authentication (PAC) registers
568
+ // are read-only and will be skipped.
569
+
570
+ // In order to create register data checkpoint we first read all register
571
+ // values if not done already and calculate total size of register set data.
572
+ // We store all register values in data_sp by copying full PTrace data that
573
+ // corresponds to register sets enabled by current register context.
574
+
575
+ uint32_t reg_data_byte_size = 0 ;
576
+ Status error = CacheAllRegisters (reg_data_byte_size);
543
577
if (error.Fail ())
544
578
return error;
545
579
546
580
data_sp.reset (new DataBufferHeap (reg_data_byte_size, 0 ));
547
581
uint8_t *dst = data_sp->GetBytes ();
548
582
549
- ::memcpy (dst, GetGPRBuffer(), GetGPRBufferSize());
550
- dst += GetGPRBufferSize ();
583
+ dst = AddSavedRegisters (dst, RegisterSetType::GPR, GetGPRBuffer (),
584
+ GetGPRBufferSize () );
551
585
552
586
if (GetRegisterInfo ().IsSVEEnabled () || GetRegisterInfo ().IsSSVEEnabled ()) {
553
- *dst = static_cast <uint8_t >(m_sve_state);
587
+ dst = AddRegisterSetType (dst, RegisterSetType::SVE);
588
+ *(reinterpret_cast <SVEState *>(dst)) = m_sve_state;
554
589
dst += sizeof (m_sve_state);
555
- ::memcpy (dst, GetSVEBuffer(), GetSVEBufferSize());
556
- dst += GetSVEBufferSize ();
590
+ dst = AddSavedRegistersData (dst, GetSVEBuffer (), GetSVEBufferSize ());
557
591
} else {
558
- ::memcpy (dst, GetFPRBuffer(), GetFPRSize());
559
- dst += GetFPRSize ();
592
+ dst = AddSavedRegisters (dst, RegisterSetType::FPR, GetFPRBuffer (),
593
+ GetFPRSize () );
560
594
}
561
595
562
596
if (GetRegisterInfo ().IsMTEEnabled ()) {
563
- ::memcpy (dst, GetMTEControl(), GetMTEControlSize());
564
- dst += GetMTEControlSize ();
597
+ dst = AddSavedRegisters (dst, RegisterSetType::MTE, GetMTEControl (),
598
+ GetMTEControlSize () );
565
599
}
566
600
567
- ::memcpy (dst, GetTLSBuffer(), GetTLSBufferSize());
601
+ dst = AddSavedRegisters (dst, RegisterSetType::TLS, GetTLSBuffer (),
602
+ GetTLSBufferSize ());
568
603
569
604
return error;
570
605
}
571
606
607
+ static Status RestoreRegisters (void *buffer, const uint8_t **src, size_t len,
608
+ bool &is_valid, std::function<Status()> writer) {
609
+ ::memcpy (buffer, *src, len);
610
+ is_valid = true ;
611
+ *src += len;
612
+ return writer ();
613
+ }
614
+
572
615
Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues (
573
616
const lldb::DataBufferSP &data_sp) {
574
617
// AArch64 register data must contain GPRs, either FPR or SVE registers
@@ -599,7 +642,8 @@ Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
599
642
return error;
600
643
}
601
644
602
- uint64_t reg_data_min_size = GetGPRBufferSize () + GetFPRSize ();
645
+ uint64_t reg_data_min_size =
646
+ GetGPRBufferSize () + GetFPRSize () + 2 * (sizeof (RegisterSetType));
603
647
if (data_sp->GetByteSize () < reg_data_min_size) {
604
648
error.SetErrorStringWithFormat (
605
649
" NativeRegisterContextLinux_arm64::%s data_sp contained insufficient "
@@ -608,82 +652,67 @@ Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
608
652
return error;
609
653
}
610
654
611
- // Register data starts with GPRs
612
- ::memcpy (GetGPRBuffer(), src, GetGPRBufferSize());
613
- m_gpr_is_valid = true ;
614
-
615
- error = WriteGPR ();
616
- if (error.Fail ())
617
- return error;
618
-
619
- src += GetGPRBufferSize ();
620
-
621
- // Verify if register data may contain SVE register values.
622
- bool contains_sve_reg_data =
623
- (data_sp->GetByteSize () > (reg_data_min_size + GetSVEHeaderSize ()));
624
-
625
- if (contains_sve_reg_data) {
626
- // Restore to the correct mode, streaming or not.
627
- m_sve_state = static_cast <SVEState>(*src);
628
- src += sizeof (m_sve_state);
629
-
630
- // We have SVE register data first write SVE header.
631
- ::memcpy (GetSVEHeader(), src, GetSVEHeaderSize());
632
- if (!sve::vl_valid (m_sve_header.vl )) {
633
- m_sve_header_is_valid = false ;
634
- error.SetErrorStringWithFormat (" NativeRegisterContextLinux_arm64::%s "
635
- " Invalid SVE header in data_sp" ,
636
- __FUNCTION__);
637
- return error;
638
- }
639
- m_sve_header_is_valid = true ;
640
- error = WriteSVEHeader ();
641
- if (error.Fail ())
642
- return error;
643
-
644
- // SVE header has been written configure SVE vector length if needed.
645
- ConfigureRegisterContext ();
655
+ const uint8_t *end = src + data_sp->GetByteSize ();
656
+ while (src < end) {
657
+ const RegisterSetType kind =
658
+ *reinterpret_cast <const RegisterSetType *>(src);
659
+ src += sizeof (RegisterSetType);
660
+
661
+ switch (kind) {
662
+ case RegisterSetType::GPR:
663
+ error = RestoreRegisters (
664
+ GetGPRBuffer (), &src, GetGPRBufferSize (), m_gpr_is_valid,
665
+ std::bind (&NativeRegisterContextLinux_arm64::WriteGPR, this ));
666
+ break ;
667
+ case RegisterSetType::SVE:
668
+ // Restore to the correct mode, streaming or not.
669
+ m_sve_state = static_cast <SVEState>(*src);
670
+ src += sizeof (m_sve_state);
671
+
672
+ // First write SVE header. We do not use RestoreRegisters because we do
673
+ // not want src to be modified yet.
674
+ ::memcpy (GetSVEHeader(), src, GetSVEHeaderSize());
675
+ if (!sve::vl_valid (m_sve_header.vl )) {
676
+ m_sve_header_is_valid = false ;
677
+ error.SetErrorStringWithFormat (" NativeRegisterContextLinux_arm64::%s "
678
+ " Invalid SVE header in data_sp" ,
679
+ __FUNCTION__);
680
+ return error;
681
+ }
682
+ m_sve_header_is_valid = true ;
683
+ error = WriteSVEHeader ();
684
+ if (error.Fail ())
685
+ return error;
646
686
647
- // Make sure data_sp contains sufficient data to write all SVE registers.
648
- reg_data_min_size = GetGPRBufferSize () + GetSVEBufferSize ();
649
- if (data_sp->GetByteSize () < reg_data_min_size) {
650
- error.SetErrorStringWithFormat (
651
- " NativeRegisterContextLinux_arm64::%s data_sp contained insufficient "
652
- " register data bytes, expected %" PRIu64 " , actual %" PRIu64,
653
- __FUNCTION__, reg_data_min_size, data_sp->GetByteSize ());
654
- return error;
687
+ // SVE header has been written configure SVE vector length if needed.
688
+ ConfigureRegisterContext ();
689
+
690
+ // Write header and register data, incrementing src this time.
691
+ error = RestoreRegisters (
692
+ GetSVEBuffer (), &src, GetSVEBufferSize (), m_sve_buffer_is_valid,
693
+ std::bind (&NativeRegisterContextLinux_arm64::WriteAllSVE, this ));
694
+ break ;
695
+ case RegisterSetType::FPR:
696
+ error = RestoreRegisters (
697
+ GetFPRBuffer (), &src, GetFPRSize (), m_fpu_is_valid,
698
+ std::bind (&NativeRegisterContextLinux_arm64::WriteFPR, this ));
699
+ break ;
700
+ case RegisterSetType::MTE:
701
+ error = RestoreRegisters (
702
+ GetMTEControl (), &src, GetMTEControlSize (), m_mte_ctrl_is_valid,
703
+ std::bind (&NativeRegisterContextLinux_arm64::WriteMTEControl, this ));
704
+ break ;
705
+ case RegisterSetType::TLS:
706
+ error = RestoreRegisters (
707
+ GetTLSBuffer (), &src, GetTLSBufferSize (), m_tls_is_valid,
708
+ std::bind (&NativeRegisterContextLinux_arm64::WriteTLS, this ));
709
+ break ;
655
710
}
656
711
657
- ::memcpy (GetSVEBuffer(), src, GetSVEBufferSize());
658
- m_sve_buffer_is_valid = true ;
659
- error = WriteAllSVE ();
660
- src += GetSVEBufferSize ();
661
- } else {
662
- ::memcpy (GetFPRBuffer(), src, GetFPRSize());
663
- m_fpu_is_valid = true ;
664
- error = WriteFPR ();
665
- src += GetFPRSize ();
666
- }
667
-
668
- if (error.Fail ())
669
- return error;
670
-
671
- if (GetRegisterInfo ().IsMTEEnabled () &&
672
- data_sp->GetByteSize () > reg_data_min_size) {
673
- ::memcpy (GetMTEControl(), src, GetMTEControlSize());
674
- m_mte_ctrl_is_valid = true ;
675
- error = WriteMTEControl ();
676
712
if (error.Fail ())
677
713
return error;
678
- src += GetMTEControlSize ();
679
714
}
680
715
681
- // There is always a TLS set. It changes size based on system properties, it's
682
- // not something an expression can change.
683
- ::memcpy (GetTLSBuffer(), src, GetTLSBufferSize());
684
- m_tls_is_valid = true ;
685
- error = WriteTLS ();
686
-
687
716
return error;
688
717
}
689
718
0 commit comments