2 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
7 #ifndef NATIVE_CLIENT_TESTS_COMMON_REGISTER_SET_H_
8 #define NATIVE_CLIENT_TESTS_COMMON_REGISTER_SET_H_
10 #include "native_client/src/include/nacl/nacl_exception.h"
11 #include "native_client/src/include/nacl_macros.h"
12 #include "native_client/src/trusted/service_runtime/nacl_config.h"
13 #include "native_client/src/trusted/service_runtime/nacl_signal.h"
17 * Non-SFI NaCl does not need alignment with 0xc0000000 etc, and it is
18 * actually harmful to do so. Use this macro to enable NaCl only
21 #if defined(__native_client_nonsfi__)
22 #define SFI_OR_NONSFI_CODE(nacl, nonsfi) nonsfi
24 #define SFI_OR_NONSFI_CODE(nacl, nonsfi) nacl
28 * ASM_WITH_REGS(regs, asm_code) executes asm_code with most registers
29 * restored from regs, a pointer of type "struct NaClSignalContext *".
32 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
34 # define ASM_WITH_REGS(regs, asm_code) \
37 "movl 0x04(%%eax), %%ecx\n" \
38 "movl 0x08(%%eax), %%edx\n" \
39 "movl 0x0c(%%eax), %%ebx\n" \
40 "movl 0x10(%%eax), %%esp\n" \
41 "movl 0x14(%%eax), %%ebp\n" \
42 "movl 0x18(%%eax), %%esi\n" \
43 "movl 0x1c(%%eax), %%edi\n" \
44 "movl 0x00(%%eax), %%eax\n" \
47 : : "r"(regs) : "memory")
49 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
51 # define ASM_WITH_REGS(regs, asm_code) \
53 "naclrestbp %0, %%r15\n" \
54 "movq 0x00(%%rbp), %%rax\n" \
55 "movq 0x08(%%rbp), %%rbx\n" \
56 "movq 0x10(%%rbp), %%rcx\n" \
57 "movq 0x18(%%rbp), %%rdx\n" \
58 "movq 0x20(%%rbp), %%rsi\n" \
59 "movq 0x28(%%rbp), %%rdi\n" \
60 /* Handle %rbp (0x30) later */ \
61 "naclrestsp 0x38(%%rbp), %%r15\n" \
62 "movq 0x40(%%rbp), %%r8\n" \
63 "movq 0x48(%%rbp), %%r9\n" \
64 "movq 0x50(%%rbp), %%r10\n" \
65 "movq 0x58(%%rbp), %%r11\n" \
66 "movq 0x60(%%rbp), %%r12\n" \
67 "movq 0x68(%%rbp), %%r13\n" \
68 "movq 0x70(%%rbp), %%r14\n" \
69 "naclrestbp 0x30(%%rbp), %%r15\n" \
72 : : "r"(regs) : "memory")
74 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
77 * In principle we should be able to do just "ldmia r0, {r0-lr}", but:
78 * * We have to skip r9, since the validator currently makes it
79 * read-only (though service_runtime no longer trusts its
81 * * Oddly, PNaCl/Clang seems to have problems with '{' in inline
84 * Rather than debug Clang, I'm just writing out the register
85 * restoration in the long form.
87 # define REGS_MASK_R0 SFI_OR_NONSFI_CODE("bic r0, r0, #0xc0000000\n", "")
88 # define ASM_WITH_REGS(regs, asm_code) \
92 /* Set CPSR (flags) register, a.k.a. APSR for user mode */ \
93 REGS_MASK_R0 "ldr r1, [r0, #0x40]\n" \
94 "msr apsr_nzcvqg, r1\n" \
95 /* Set stack pointer */ \
96 REGS_MASK_R0 "ldr r1, [r0, #0x34]\n" \
97 SFI_OR_NONSFI_CODE("bic sp, r1, #0xc0000000\n", "mov sp, r1\n") \
98 /* Ensure later superinstructions don't cross bundle boundaries */ \
100 /* Set general purpose registers */ \
101 REGS_MASK_R0 "ldr r1, [r0, #0x04]\n" \
102 REGS_MASK_R0 "ldr r2, [r0, #0x08]\n" \
103 REGS_MASK_R0 "ldr r3, [r0, #0x0c]\n" \
104 REGS_MASK_R0 "ldr r4, [r0, #0x10]\n" \
105 REGS_MASK_R0 "ldr r5, [r0, #0x14]\n" \
106 REGS_MASK_R0 "ldr r6, [r0, #0x18]\n" \
107 REGS_MASK_R0 "ldr r7, [r0, #0x1c]\n" \
108 REGS_MASK_R0 "ldr r8, [r0, #0x20]\n" \
109 /* Skip r9, which is not supposed to be settable or readable */ \
110 REGS_MASK_R0 "ldr r10, [r0, #0x28]\n" \
111 REGS_MASK_R0 "ldr r11, [r0, #0x2c]\n" \
112 REGS_MASK_R0 "ldr r12, [r0, #0x30]\n" \
113 REGS_MASK_R0 "ldr lr, [r0, #0x38]\n" \
114 /* Lastly, restore r0 */ \
115 REGS_MASK_R0 "ldr r0, [r0, #0x00]\n" \
116 ".p2align 4\n" /* Align for whatever comes after */ \
118 : : "r"(regs) : "memory")
120 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
122 # define REGS_MASK_A0 "and $a0, $a0, $t7\n"
123 # define ASM_WITH_REGS(regs, asm_code) \
128 /* We skip setting zero register because it's unsettable. */ \
129 REGS_MASK_A0 "lw $at, 4($a0)\n" \
130 REGS_MASK_A0 "lw $v0, 8($a0)\n" \
131 REGS_MASK_A0 "lw $v1, 12($a0)\n" \
132 REGS_MASK_A0 "lw $a1, 20($a0)\n" \
133 REGS_MASK_A0 "lw $a2, 24($a0)\n" \
134 REGS_MASK_A0 "lw $a3, 28($a0)\n" \
135 REGS_MASK_A0 "lw $t0, 32($a0)\n" \
136 REGS_MASK_A0 "lw $t1, 36($a0)\n" \
137 REGS_MASK_A0 "lw $t2, 40($a0)\n" \
138 REGS_MASK_A0 "lw $t3, 44($a0)\n" \
139 REGS_MASK_A0 "lw $t4, 48($a0)\n" \
140 REGS_MASK_A0 "lw $t5, 52($a0)\n" \
141 /* We skip setting t6 and t7 because those are mask registers. */ \
142 REGS_MASK_A0 "lw $s0, 64($a0)\n" \
143 REGS_MASK_A0 "lw $s1, 68($a0)\n" \
144 REGS_MASK_A0 "lw $s2, 72($a0)\n" \
145 REGS_MASK_A0 "lw $s3, 76($a0)\n" \
146 REGS_MASK_A0 "lw $s4, 80($a0)\n" \
147 REGS_MASK_A0 "lw $s5, 84($a0)\n" \
148 REGS_MASK_A0 "lw $s6, 88($a0)\n" \
149 REGS_MASK_A0 "lw $s7, 92($a0)\n" \
150 /* We skip setting t8 because that register hold TLS index. */ \
151 REGS_MASK_A0 "lw $t9, 100($a0)\n" \
152 /* We skip setting k0 and k1 registers, they are changed by kernel. */ \
153 REGS_MASK_A0 "lw $gp, 112($a0)\n" \
154 REGS_MASK_A0 "lw $sp, 116($a0)\n" \
155 /* Value change of sp requires masking instruction. */ \
156 "and $sp, $sp, $t7\n" \
158 REGS_MASK_A0 "lw $fp, 120($a0)\n" \
159 REGS_MASK_A0 "lw $ra, 124($a0)\n" \
160 REGS_MASK_A0 "lw $a0, 16($a0)\n" \
161 ".p2align 4\n" /* Align for whatever comes after. */ \
163 : : "r"(regs) : "memory")
166 # error Unsupported architecture
170 * JUMP_WITH_REGS(regs, dest) jumps to symbol |dest| with most
171 * registers restored from |regs|, a pointer of type "struct
172 * NaClSignalContext *".
174 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
175 # define JUMP_WITH_REGS(regs, dest) ASM_WITH_REGS(regs, "jmp " #dest)
176 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
177 # define JUMP_WITH_REGS(regs, dest) ASM_WITH_REGS(regs, "b " #dest)
178 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
179 # define JUMP_WITH_REGS(regs, dest) ASM_WITH_REGS(regs, \
183 # error Unsupported architecture
186 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
189 * Normally it is possible to save x86 flags using the 'pushf'
190 * instruction. However, 'pushf' is disallowed under NaCl. Instead,
191 * we can read a subset of the flags indirectly using conditional
195 * CF (carry), PF (parity), ZF (zero), SF (sign), OF (overflow)
197 * We don't attempt to check:
198 * AF (for BCD arithmetic only, which is not allowed by the validator)
199 * TF (trap flag: not settable or observable by untrusted code)
200 * DF (direction flag: indirectly observable, but it's a hassle to do so)
202 extern const uint8_t kX86FlagBits[5];
204 /* We use 'mov' and 'lea' because they do not modify the flags. */
205 # define SAVE_X86_FLAGS_INTO_REG(reg) \
207 "jnc 0f; lea 1<<0("reg"), "reg"; 0:\n" \
208 "jnp 0f; lea 1<<2("reg"), "reg"; 0:\n" \
209 "jnz 0f; lea 1<<6("reg"), "reg"; 0:\n" \
210 "jns 0f; lea 1<<7("reg"), "reg"; 0:\n" \
211 "jno 0f; lea 1<<11("reg"), "reg"; 0:\n"
213 /* Reset flags to RESET_X86_FLAGS_VALUE without modifying any registers. */
214 #define RESET_X86_FLAGS "testl $0, %%eax\n"
215 #define RESET_X86_FLAGS_VALUE ((1 << 2) | (1 << 6))
217 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
220 * These are the only ARM CPSR bits that user code and untrusted code
221 * can read and modify, excluding the IT bits which are for Thumb-2
222 * (for If-Then-Else instructions).
224 # define REGS_ARM_USER_CPSR_FLAGS_MASK \
230 (1<<19) | (1<<18) | (1<<17) | (1<<16) /* GE bits */)
235 * REGS_SAVER_FUNC(def_func, callee_func) defines a function named
236 * def_func which saves all registers on the stack and passes them to
237 * callee_func in the form of a "struct NaClSignalContext *".
240 #define REGS_SAVER_FUNC(def_func, callee_func) \
241 void def_func(void); \
242 REGS_SAVER_FUNC_NOPROTO(def_func, callee_func)
244 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
246 # define REGS_SAVER_FUNC_NOPROTO(def_func, callee_func) \
247 void callee_func(struct NaClSignalContext *regs); \
249 ".pushsection .text, \"ax\", @progbits\n" \
251 ".global " #def_func "\n"\
253 /* Push most of "struct NaClSignalContext" in reverse order. */ \
254 "push $0\n" /* Leave space for flags */ \
255 "push $0\n" /* Leave space for prog_ctr */ \
265 SAVE_X86_FLAGS_INTO_REG("%eax") \
266 "movl %eax, 0x24(%esp)\n" \
267 /* Obtain def_func from GOT to fill prog_ctr with known value. */ \
270 "1: addl $_GLOBAL_OFFSET_TABLE_ + (1b - 0b), %eax\n" \
271 "movl " #def_func "@GOT(%eax), %eax\n" \
272 "movl %eax, 0x20(%esp)\n" \
273 /* Adjust saved %esp value to account for preceding pushes. */ \
274 "addl $5 * 4, 0x10(%esp)\n" \
275 /* Save argument to callee_func() temporarily. */ \
277 /* Align the stack pointer and leave space for an argument. */ \
280 /* Set argument to callee_func(). */ \
281 "mov %eax, (%esp)\n" \
282 "call " #callee_func "\n" \
285 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
287 # define REGS_SAVER_FUNC_NOPROTO(def_func, callee_func) \
288 void callee_func(struct NaClSignalContext *regs); \
290 ".pushsection .text, \"ax\", @progbits\n" \
292 ".global " #def_func "\n"\
294 /* Push most of "struct NaClSignalContext" in reverse order. */ \
295 "push $0\n" /* Leave space for flags */ \
296 "push $0\n" /* Leave space for prog_ctr */ \
314 SAVE_X86_FLAGS_INTO_REG("%rax") \
315 "movl %eax, 0x88(%rsp)\n" \
316 /* Fill out prog_ctr with known value */ \
317 "leaq " #def_func "(%rip), %rax\n" \
318 "movq %rax, 0x80(%rsp)\n" \
319 /* Adjust saved %rsp value to account for preceding pushes. */ \
320 "addq $10 * 8, 0x38(%rsp)\n" \
321 /* Set argument to callee_func(). */ \
322 "movl %esp, %edi\n" \
323 /* Align the stack pointer */ \
325 "addq %r15, %rsp\n" \
326 "call " #callee_func "\n" \
329 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
332 * "push {sp}" is undefined ("unpredictable") on ARM, so we move sp to
333 * a temporary register to push its original value. (Indeed, whether
334 * sp is modified before or after being written differs between QEMU
335 * and the Panda boards.)
337 # define REGS_SAVER_FUNC_NOPROTO(def_func, callee_func) \
338 void callee_func(struct NaClSignalContext *regs); \
340 ".pushsection .text, \"ax\", %progbits\n" \
342 ".global " #def_func "\n"\
344 "push {r0}\n" /* Leave space for cpsr */ \
345 "push {r0}\n" /* Leave space for prog_ctr */ \
347 /* Save r0-r12 and sp; adjust sp for the pushes above */ \
348 "add r14, sp, #0xc\n" \
349 "push {r10-r12, r14}\n" \
350 /* Push a dummy value for r9, which the tests need not compare */ \
353 /* Save the rest of struct NaClSignalContext */ \
355 /* Now save a correct prog_ctr value */ \
356 "adr r0, " #def_func "\n" \
357 "str r0, [sp, #0x3c]\n" \
358 /* Save CPSR (flags) register, a.k.a. APSR for user mode */ \
360 "str r0, [sp, #0x40]\n" \
361 /* Set argument to callee_func() */ \
363 /* Align the stack pointer */ \
364 SFI_OR_NONSFI_CODE("bic sp, sp, #0xc000000f\n", "") \
365 "b " #callee_func "\n" \
368 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
370 # define REGS_SAVER_FUNC_NOPROTO(def_func, callee_func) \
371 void callee_func(struct NaClSignalContext *regs); \
373 ".pushsection .text, \"ax\", %progbits\n" \
376 ".global " #def_func "\n"\
378 /* Make space on stack for all registers. */ \
379 "add $sp, $sp, -132\n" \
380 "and $sp, $sp, $t7\n"\
381 "sw $zero, 0($sp)\n" \
384 "sw $v1, 12($sp)\n" \
385 "sw $a0, 16($sp)\n" \
386 "sw $a1, 20($sp)\n" \
387 "sw $a2, 24($sp)\n" \
388 "sw $a3, 28($sp)\n" \
389 "sw $t0, 32($sp)\n" \
390 "sw $t1, 36($sp)\n" \
391 "sw $t2, 40($sp)\n" \
392 "sw $t3, 44($sp)\n" \
393 "sw $t4, 48($sp)\n" \
394 "sw $t5, 52($sp)\n" \
395 "sw $t6, 56($sp)\n" \
396 "sw $t7, 60($sp)\n" \
397 "sw $s0, 64($sp)\n" \
398 "sw $s1, 68($sp)\n" \
399 "sw $s2, 72($sp)\n" \
400 "sw $s3, 76($sp)\n" \
401 "sw $s4, 80($sp)\n" \
402 "sw $s5, 84($sp)\n" \
403 "sw $s6, 88($sp)\n" \
404 "sw $s7, 92($sp)\n" \
405 "sw $t8, 96($sp)\n" \
406 "sw $t9, 100($sp)\n" \
407 /* We skip saving k0 and k1 registers, they are changed by kernel. */ \
408 "sw $gp, 112($sp)\n" \
409 /* Store the value stack_ptr had on entry of this function. */ \
410 "add $t1, $sp, 132\n" \
411 "sw $t1, 116($sp)\n" \
412 "sw $fp, 120($sp)\n" \
413 "sw $ra, 124($sp)\n" \
414 /* Save a correct prog_ctr value. */ \
415 "lui $t1, %hi(" #def_func ")\n" \
416 "addiu $t1, $t1, %lo(" #def_func ")\n" \
417 "sw $t1, 128($sp)\n" \
418 /* Prepare argument for callee_func. */ \
420 /* Align the stack pointer. */ \
421 "sll $t1, $t7, 3\n" \
422 "and $sp, $sp, $t1\n" \
423 "and $sp, $sp, $t7\n" \
424 /* Make space on stack for convention calling registers. */ \
425 "add $sp, $sp, -16\n" \
426 "and $sp, $sp, $t7\n" \
427 /* Set $t9 to callee_func as required by ABI for PIC code. */ \
428 "lui $t9, %hi(" #callee_func ")\n" \
429 "b " #callee_func "\n" \
430 "addiu $t9, $t9, %lo(" #callee_func ")\n" \
438 # error Unsupported architecture
441 /* Initialize the register set with arbitrary test data. */
442 void RegsFillTestValues(struct NaClSignalContext *regs, int seed);
444 /* Adjust registers to follow the sandbox's constraints. */
445 void RegsApplySandboxConstraints(struct NaClSignalContext *regs);
447 /* This compares for equality all registers saved by REGS_SAVER_FUNC. */
448 void RegsAssertEqual(const struct NaClSignalContext *actual,
449 const struct NaClSignalContext *expected);
452 * Copy a NaClUserRegisterState into a NaClSignalContext, leaving
453 * trusted registers in the NaClSignalContext with unspecified values.
455 void RegsCopyFromUserRegisterState(struct NaClSignalContext *dest,
456 const NaClUserRegisterState *src);
458 /* Zero out registers that are clobbered by function calls. */
459 void RegsUnsetNonCalleeSavedRegisters(struct NaClSignalContext *regs);
462 * For a function called with register state |regs|, extract the first
463 * argument. This is useful for a function entry point defined by
466 uintptr_t RegsGetArg1(const struct NaClSignalContext *regs);