(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.target/
aarch64/
sls-mitigation/
sls-miti-retbr.c
       1  /* We ensure that -Wpedantic is off since it complains about the trampolines
       2     we explicitly want to test.  */
       3  /* { dg-additional-options "-mharden-sls=retbr -Wno-pedantic " } */
       4  /*
       5     Ensure that the SLS hardening of RET and BR leaves no unprotected RET/BR
       6     instructions.
       7    */
       8  typedef int (foo) (int, int);
       9  typedef void (bar) (int, int);
      10  struct sls_testclass {
      11      foo *x;
      12      bar *y;
      13      int left;
      14      int right;
      15  };
      16  
      17  int
      18  retbr_sibcall_value_insn (struct sls_testclass x)
      19  {
      20    return x.x(x.left, x.right);
      21  }
      22  
      23  void
      24  retbr_sibcall_insn (struct sls_testclass x)
      25  {
      26    x.y(x.left, x.right);
      27  }
      28  
      29  /* Aim to test two different returns.
      30     One that introduces a tail call in the middle of the function, and one that
      31     has a normal return.  */
      32  int
      33  retbr_multiple_returns (struct sls_testclass x)
      34  {
      35    int temp;
      36    if (x.left % 10)
      37      return x.x(x.left, 100);
      38    else if (x.right % 20)
      39      {
      40        return x.x(x.left * x.right, 100);
      41      }
      42    temp = x.left % x.right;
      43    temp *= 100;
      44    temp /= 2;
      45    return temp % 3;
      46  }
      47  
      48  void
      49  retbr_multiple_returns_void (struct sls_testclass x)
      50  {
      51    if (x.left % 10)
      52      {
      53        x.y(x.left, 100);
      54      }
      55    else if (x.right % 20)
      56      {
      57        x.y(x.left * x.right, 100);
      58      }
      59    return;
      60  }
      61  
      62  /* Testing the casesi jump via register.  */
      63  __attribute__ ((optimize ("Os")))
      64  int
      65  retbr_casesi_dispatch (struct sls_testclass x)
      66  {
      67    switch (x.left)
      68      {
      69      case -5:
      70        return -2;
      71      case -3:
      72        return -1;
      73      case 0:
      74        return 0;
      75      case 3:
      76        return 1;
      77      case 5:
      78        break;
      79      default:
      80        __builtin_unreachable ();
      81      }
      82    return x.right;
      83  }
      84  
      85  /* Testing the BR in trampolines is mitigated against.  */
      86  void f1 (void *);
      87  void f3 (void *, void (*)(void *));
      88  void f2 (void *);
      89  
      90  int
      91  retbr_trampolines (void *a, int b)
      92  {
      93    if (!b)
      94      {
      95        f1 (a);
      96        return 1;
      97      }
      98    if (b)
      99      {
     100        void retbr_tramp_internal (void *c)
     101        {
     102  	if (c == a)
     103  	  f2 (c);
     104        }
     105        f3 (a, retbr_tramp_internal);
     106      }
     107    return 0;
     108  }
     109  
     110  /* Testing the indirect_jump pattern.  */
     111  void
     112  retbr_indirect_jump (int *buf)
     113  {
     114    __builtin_longjmp(buf, 1);
     115  }
     116  
     117  /* Ensure there are no BR or RET instructions which are not directly followed
     118     by a speculation barrier.  */
     119  /* { dg-final { scan-assembler-not {\t(br|ret|retaa|retab)\tx[0-9][0-9]?\n\t(?!dsb\tsy\n\tisb|sb)} } } */