• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_EXECUTION_ARM64_POINTER_AUTHENTICATION_ARM64_H_
6 #define V8_EXECUTION_ARM64_POINTER_AUTHENTICATION_ARM64_H_
7 
8 #include "src/common/globals.h"
9 #include "src/deoptimizer/deoptimizer.h"
10 #include "src/execution/arm64/simulator-arm64.h"
11 #include "src/execution/pointer-authentication.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 // The following functions execute on the host and therefore need a different
17 // path based on whether we are simulating arm64 or not.
18 
19 // clang-format fails to detect this file as C++, turn it off.
20 // clang-format off
21 
22 // Authenticate the address stored in {pc_address}. {offset_from_sp} is the
23 // offset between {pc_address} and the pointer used as a context for signing.
AuthenticatePC(Address * pc_address,unsigned offset_from_sp)24 V8_INLINE Address PointerAuthentication::AuthenticatePC(
25     Address* pc_address, unsigned offset_from_sp) {
26   uint64_t sp = reinterpret_cast<uint64_t>(pc_address) + offset_from_sp;
27   uint64_t pc = static_cast<uint64_t>(*pc_address);
28 #ifdef USE_SIMULATOR
29   pc = Simulator::AuthPAC(pc, sp, Simulator::kPACKeyIB,
30                           Simulator::kInstructionPointer);
31 #else
32   asm volatile(
33       "  mov x17, %[pc]\n"
34       "  mov x16, %[stack_ptr]\n"
35       "  autib1716\n"
36       "  ldr xzr, [x17]\n"
37       "  mov %[pc], x17\n"
38       : [pc] "+r"(pc)
39       : [stack_ptr] "r"(sp)
40       : "x16", "x17");
41 #endif
42   return pc;
43 }
44 
45 // Strip Pointer Authentication Code (PAC) from {pc} and return the raw value.
StripPAC(Address pc)46 V8_INLINE Address PointerAuthentication::StripPAC(Address pc) {
47 #ifdef USE_SIMULATOR
48   return Simulator::StripPAC(pc, Simulator::kInstructionPointer);
49 #else
50   asm volatile(
51       "  mov x16, lr\n"
52       "  mov lr, %[pc]\n"
53       "  xpaclri\n"
54       "  mov %[pc], lr\n"
55       "  mov lr, x16\n"
56       : [pc] "+r"(pc)
57       :
58       : "x16", "lr");
59   return pc;
60 #endif
61 }
62 
63 // Authenticate the address stored in {pc_address} and replace it with
64 // {new_pc}, after signing it. {offset_from_sp} is the offset between
65 // {pc_address} and the pointer used as a context for signing.
ReplacePC(Address * pc_address,Address new_pc,int offset_from_sp)66 V8_INLINE void PointerAuthentication::ReplacePC(Address* pc_address,
67                                                 Address new_pc,
68                                                 int offset_from_sp) {
69   uint64_t sp = reinterpret_cast<uint64_t>(pc_address) + offset_from_sp;
70   uint64_t old_pc = static_cast<uint64_t>(*pc_address);
71 #ifdef USE_SIMULATOR
72   uint64_t auth_old_pc = Simulator::AuthPAC(old_pc, sp, Simulator::kPACKeyIB,
73                                             Simulator::kInstructionPointer);
74   uint64_t raw_old_pc =
75       Simulator::StripPAC(old_pc, Simulator::kInstructionPointer);
76   // Verify that the old address is authenticated.
77   CHECK_EQ(auth_old_pc, raw_old_pc);
78   new_pc = Simulator::AddPAC(new_pc, sp, Simulator::kPACKeyIB,
79                              Simulator::kInstructionPointer);
80 #else
81   // Only store newly signed address after we have verified that the old
82   // address is authenticated.
83   asm volatile(
84       "  mov x17, %[new_pc]\n"
85       "  mov x16, %[sp]\n"
86       "  pacib1716\n"
87       "  mov %[new_pc], x17\n"
88       "  mov x17, %[old_pc]\n"
89       "  autib1716\n"
90       "  ldr xzr, [x17]\n"
91       : [new_pc] "+&r"(new_pc)
92       : [sp] "r"(sp), [old_pc] "r"(old_pc)
93       : "x16", "x17");
94 #endif
95   *pc_address = new_pc;
96 }
97 
98 
99 // Sign {pc} using {sp}.
SignAndCheckPC(Address pc,Address sp)100 V8_INLINE Address PointerAuthentication::SignAndCheckPC(Address pc,
101                                                           Address sp) {
102 #ifdef USE_SIMULATOR
103   pc = Simulator::AddPAC(pc, sp, Simulator::kPACKeyIB,
104                         Simulator::kInstructionPointer);
105   CHECK(Deoptimizer::IsValidReturnAddress(PointerAuthentication::StripPAC(pc)));
106   return pc;
107 #else
108   asm volatile(
109     "  mov x17, %[pc]\n"
110     "  mov x16, %[sp]\n"
111     "  pacib1716\n"
112     "  mov %[pc], x17\n"
113     : [pc] "+r"(pc)
114     : [sp] "r"(sp)
115     : "x16", "x17");
116   CHECK(Deoptimizer::IsValidReturnAddress(PointerAuthentication::StripPAC(pc)));
117   return pc;
118 #endif
119 }
120 
121 // clang-format on
122 
123 }  // namespace internal
124 }  // namespace v8
125 #endif  // V8_EXECUTION_ARM64_POINTER_AUTHENTICATION_ARM64_H_
126