Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / native_client / tests / common / register_set.h
1 /*
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.
5  */
6
7 #ifndef NATIVE_CLIENT_TESTS_COMMON_REGISTER_SET_H_
8 #define NATIVE_CLIENT_TESTS_COMMON_REGISTER_SET_H_
9
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"
14
15
16 /*
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
19  * conditions.
20  */
21 #if defined(__native_client_nonsfi__)
22 #define SFI_OR_NONSFI_CODE(nacl, nonsfi) nonsfi
23 #else
24 #define SFI_OR_NONSFI_CODE(nacl, nonsfi) nacl
25 #endif
26
27 /*
28  * ASM_WITH_REGS(regs, asm_code) executes asm_code with most registers
29  * restored from regs, a pointer of type "struct NaClSignalContext *".
30  */
31
32 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
33
34 # define ASM_WITH_REGS(regs, asm_code) \
35     __asm__( \
36         "movl %0, %%eax\n" \
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" \
45         RESET_X86_FLAGS \
46         asm_code \
47         : : "r"(regs) : "memory")
48
49 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
50
51 # define ASM_WITH_REGS(regs, asm_code) \
52     __asm__( \
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" \
70         RESET_X86_FLAGS \
71         asm_code \
72         : : "r"(regs) : "memory")
73
74 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
75
76 /*
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
80  *     content).
81  *   * Oddly, PNaCl/Clang seems to have problems with '{' in inline
82  *     assembly.
83  *
84  * Rather than debug Clang, I'm just writing out the register
85  * restoration in the long form.
86  */
87 # define REGS_MASK_R0 SFI_OR_NONSFI_CODE("bic r0, r0, #0xc0000000\n", "")
88 # define ASM_WITH_REGS(regs, asm_code) \
89     __asm__( \
90         ".p2align 4\n" \
91         "mov r0, %0\n" \
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 */ \
99         "nop\n" \
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 */ \
117         asm_code \
118         : : "r"(regs) : "memory")
119
120 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
121
122 # define REGS_MASK_A0 "and $a0, $a0, $t7\n"
123 # define ASM_WITH_REGS(regs, asm_code) \
124     __asm__( \
125         ".p2align 4\n" \
126         "move $a0, %0\n" \
127         "nop\n" \
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" \
157         "nop\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. */ \
162         asm_code \
163         : : "r"(regs) : "memory")
164
165 #else
166 # error Unsupported architecture
167 #endif
168
169 /*
170  * JUMP_WITH_REGS(regs, dest) jumps to symbol |dest| with most
171  * registers restored from |regs|, a pointer of type "struct
172  * NaClSignalContext *".
173  */
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, \
180                                                   "b " #dest "\n" \
181                                                   "nop\n")
182 #else
183 # error Unsupported architecture
184 #endif
185
186 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
187
188 /*
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
192  * instructions.
193  *
194  * We save 5 flags:
195  *   CF (carry), PF (parity), ZF (zero), SF (sign), OF (overflow)
196  *
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)
201  */
202 extern const uint8_t kX86FlagBits[5];
203
204 /* We use 'mov' and 'lea' because they do not modify the flags. */
205 # define SAVE_X86_FLAGS_INTO_REG(reg) \
206     "mov $0, "reg"\n" \
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"
212
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))
216
217 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
218
219 /*
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).
223  */
224 # define REGS_ARM_USER_CPSR_FLAGS_MASK \
225     ((1<<31) | /* N */ \
226      (1<<30) | /* Z */ \
227      (1<<29) | /* C */ \
228      (1<<28) | /* V */ \
229      (1<<27) | /* Q */ \
230      (1<<19) | (1<<18) | (1<<17) | (1<<16) /* GE bits */)
231
232 #endif
233
234 /*
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 *".
238  */
239
240 #define REGS_SAVER_FUNC(def_func, callee_func) \
241     void def_func(void); \
242     REGS_SAVER_FUNC_NOPROTO(def_func, callee_func)
243
244 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
245
246 # define REGS_SAVER_FUNC_NOPROTO(def_func, callee_func) \
247     void callee_func(struct NaClSignalContext *regs); \
248     __asm__( \
249         ".pushsection .text, \"ax\", @progbits\n" \
250         ".p2align 5\n" \
251         ".global " #def_func "\n"\
252         #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 */ \
256         "push %edi\n" \
257         "push %esi\n" \
258         "push %ebp\n" \
259         "push %esp\n" \
260         "push %ebx\n" \
261         "push %edx\n" \
262         "push %ecx\n" \
263         "push %eax\n" \
264         /* Save flags. */ \
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. */ \
268         "call 0f\n" \
269         "0: popl %eax\n" \
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. */ \
276         "mov %esp, %eax\n" \
277         /* Align the stack pointer and leave space for an argument. */ \
278         "pushl $0\n" \
279         "and $~15, %esp\n" \
280         /* Set argument to callee_func(). */ \
281         "mov %eax, (%esp)\n" \
282         "call " #callee_func "\n" \
283         ".popsection\n")
284
285 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
286
287 # define REGS_SAVER_FUNC_NOPROTO(def_func, callee_func) \
288     void callee_func(struct NaClSignalContext *regs); \
289     __asm__( \
290         ".pushsection .text, \"ax\", @progbits\n" \
291         ".p2align 5\n" \
292         ".global " #def_func "\n"\
293         #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 */ \
297         "push %r15\n" \
298         "push %r14\n" \
299         "push %r13\n" \
300         "push %r12\n" \
301         "push %r11\n" \
302         "push %r10\n" \
303         "push %r9\n" \
304         "push %r8\n" \
305         "push %rsp\n" \
306         "push %rbp\n" \
307         "push %rdi\n" \
308         "push %rsi\n" \
309         "push %rdx\n" \
310         "push %rcx\n" \
311         "push %rbx\n" \
312         "push %rax\n" \
313         /* Save flags. */ \
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 */ \
324         "and $~15, %esp\n" \
325         "addq %r15, %rsp\n" \
326         "call " #callee_func "\n" \
327         ".popsection\n")
328
329 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
330
331 /*
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.)
336  */
337 # define REGS_SAVER_FUNC_NOPROTO(def_func, callee_func) \
338     void callee_func(struct NaClSignalContext *regs); \
339     __asm__( \
340         ".pushsection .text, \"ax\", %progbits\n" \
341         ".p2align 4\n" \
342         ".global " #def_func "\n"\
343         #def_func ":\n" \
344         "push {r0}\n"  /* Leave space for cpsr */ \
345         "push {r0}\n"  /* Leave space for prog_ctr */ \
346         "push {r14}\n" \
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 */ \
351         "mov r10, #0\n" \
352         "push {r10}\n" \
353         /* Save the rest of struct NaClSignalContext */ \
354         "push {r0-r8}\n" \
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 */ \
359         "mrs r0, apsr\n" \
360         "str r0, [sp, #0x40]\n" \
361         /* Set argument to callee_func() */ \
362         "mov r0, sp\n" \
363         /* Align the stack pointer */ \
364         SFI_OR_NONSFI_CODE("bic sp, sp, #0xc000000f\n", "") \
365         "b " #callee_func "\n" \
366         ".popsection\n")
367
368 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
369
370 # define REGS_SAVER_FUNC_NOPROTO(def_func, callee_func) \
371     void callee_func(struct NaClSignalContext *regs); \
372     __asm__( \
373         ".pushsection .text, \"ax\", %progbits\n" \
374         ".set noreorder\n" \
375         ".p2align 4\n" \
376         ".global " #def_func "\n"\
377         #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" \
382         "sw $at, 4($sp)\n" \
383         "sw $v0, 8($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. */ \
419         "move $a0, $sp\n" \
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" \
431         "nop\n" \
432         "nop \n" \
433         "nop\n" \
434         ".set reorder\n" \
435         ".popsection\n")
436
437 #else
438 # error Unsupported architecture
439 #endif
440
441 /* Initialize the register set with arbitrary test data. */
442 void RegsFillTestValues(struct NaClSignalContext *regs, int seed);
443
444 /* Adjust registers to follow the sandbox's constraints. */
445 void RegsApplySandboxConstraints(struct NaClSignalContext *regs);
446
447 /* This compares for equality all registers saved by REGS_SAVER_FUNC. */
448 void RegsAssertEqual(const struct NaClSignalContext *actual,
449                      const struct NaClSignalContext *expected);
450
451 /*
452  * Copy a NaClUserRegisterState into a NaClSignalContext, leaving
453  * trusted registers in the NaClSignalContext with unspecified values.
454  */
455 void RegsCopyFromUserRegisterState(struct NaClSignalContext *dest,
456                                    const NaClUserRegisterState *src);
457
458 /* Zero out registers that are clobbered by function calls. */
459 void RegsUnsetNonCalleeSavedRegisters(struct NaClSignalContext *regs);
460
461 /*
462  * For a function called with register state |regs|, extract the first
463  * argument.  This is useful for a function entry point defined by
464  * REGS_SAVER_FUNC.
465  */
466 uintptr_t RegsGetArg1(const struct NaClSignalContext *regs);
467
468 #endif