Upstream version 10.39.225.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  * ASM_WITH_REGS(regs, asm_code) executes asm_code with most registers
17  * restored from regs, a pointer of type "struct NaClSignalContext *".
18  */
19
20 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
21
22 # define ASM_WITH_REGS(regs, asm_code) \
23     __asm__( \
24         "movl %0, %%eax\n" \
25         "movl 0x04(%%eax), %%ecx\n" \
26         "movl 0x08(%%eax), %%edx\n" \
27         "movl 0x0c(%%eax), %%ebx\n" \
28         "movl 0x10(%%eax), %%esp\n" \
29         "movl 0x14(%%eax), %%ebp\n" \
30         "movl 0x18(%%eax), %%esi\n" \
31         "movl 0x1c(%%eax), %%edi\n" \
32         "movl 0x00(%%eax), %%eax\n" \
33         RESET_X86_FLAGS \
34         asm_code \
35         : : "r"(regs) : "memory")
36
37 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
38
39 # define ASM_WITH_REGS(regs, asm_code) \
40     __asm__( \
41         "naclrestbp %0, %%r15\n" \
42         "movq 0x00(%%rbp), %%rax\n" \
43         "movq 0x08(%%rbp), %%rbx\n" \
44         "movq 0x10(%%rbp), %%rcx\n" \
45         "movq 0x18(%%rbp), %%rdx\n" \
46         "movq 0x20(%%rbp), %%rsi\n" \
47         "movq 0x28(%%rbp), %%rdi\n" \
48         /* Handle %rbp (0x30) later */ \
49         "naclrestsp 0x38(%%rbp), %%r15\n" \
50         "movq 0x40(%%rbp), %%r8\n" \
51         "movq 0x48(%%rbp), %%r9\n" \
52         "movq 0x50(%%rbp), %%r10\n" \
53         "movq 0x58(%%rbp), %%r11\n" \
54         "movq 0x60(%%rbp), %%r12\n" \
55         "movq 0x68(%%rbp), %%r13\n" \
56         "movq 0x70(%%rbp), %%r14\n" \
57         "naclrestbp 0x30(%%rbp), %%r15\n" \
58         RESET_X86_FLAGS \
59         asm_code \
60         : : "r"(regs) : "memory")
61
62 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
63
64 /*
65  * In principle we should be able to do just "ldmia r0, {r0-lr}", but:
66  *   * We have to skip r9, since the validator currently makes it
67  *     read-only (though service_runtime no longer trusts its
68  *     content).
69  *   * Oddly, PNaCl/Clang seems to have problems with '{' in inline
70  *     assembly.
71  *
72  * Rather than debug Clang, I'm just writing out the register
73  * restoration in the long form.
74  */
75 # define REGS_MASK_R0 "bic r0, r0, #0xc0000000\n"
76 # define ASM_WITH_REGS(regs, asm_code) \
77     __asm__( \
78         ".p2align 4\n" \
79         "mov r0, %0\n" \
80         /* Set CPSR (flags) register, a.k.a. APSR for user mode */ \
81         REGS_MASK_R0 "ldr r1, [r0, #0x40]\n" \
82         "msr apsr_nzcvqg, r1\n" \
83         /* Set stack pointer */ \
84         REGS_MASK_R0 "ldr r1, [r0, #0x34]\n" \
85         "bic sp, r1, #0xc0000000\n" \
86         /* Ensure later superinstructions don't cross bundle boundaries */ \
87         "nop\n" \
88         /* Set general purpose registers */ \
89         REGS_MASK_R0 "ldr r1, [r0, #0x04]\n" \
90         REGS_MASK_R0 "ldr r2, [r0, #0x08]\n" \
91         REGS_MASK_R0 "ldr r3, [r0, #0x0c]\n" \
92         REGS_MASK_R0 "ldr r4, [r0, #0x10]\n" \
93         REGS_MASK_R0 "ldr r5, [r0, #0x14]\n" \
94         REGS_MASK_R0 "ldr r6, [r0, #0x18]\n" \
95         REGS_MASK_R0 "ldr r7, [r0, #0x1c]\n" \
96         REGS_MASK_R0 "ldr r8, [r0, #0x20]\n" \
97         /* Skip r9, which is not supposed to be settable or readable */ \
98         REGS_MASK_R0 "ldr r10, [r0, #0x28]\n" \
99         REGS_MASK_R0 "ldr r11, [r0, #0x2c]\n" \
100         REGS_MASK_R0 "ldr r12, [r0, #0x30]\n" \
101         REGS_MASK_R0 "ldr lr, [r0, #0x38]\n" \
102         /* Lastly, restore r0 */ \
103         REGS_MASK_R0 "ldr r0, [r0, #0x00]\n" \
104         ".p2align 4\n"  /* Align for whatever comes after */ \
105         asm_code \
106         : : "r"(regs) : "memory")
107
108 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
109
110 # define REGS_MASK_A0 "and $a0, $a0, $t7\n"
111 # define ASM_WITH_REGS(regs, asm_code) \
112     __asm__( \
113         ".p2align 4\n" \
114         "move $a0, %0\n" \
115         "nop\n" \
116         /* We skip setting zero register because it's unsettable. */ \
117         REGS_MASK_A0 "lw $at, 4($a0)\n" \
118         REGS_MASK_A0 "lw $v0, 8($a0)\n" \
119         REGS_MASK_A0 "lw $v1, 12($a0)\n" \
120         REGS_MASK_A0 "lw $a1, 20($a0)\n" \
121         REGS_MASK_A0 "lw $a2, 24($a0)\n" \
122         REGS_MASK_A0 "lw $a3, 28($a0)\n" \
123         REGS_MASK_A0 "lw $t0, 32($a0)\n" \
124         REGS_MASK_A0 "lw $t1, 36($a0)\n" \
125         REGS_MASK_A0 "lw $t2, 40($a0)\n" \
126         REGS_MASK_A0 "lw $t3, 44($a0)\n" \
127         REGS_MASK_A0 "lw $t4, 48($a0)\n" \
128         REGS_MASK_A0 "lw $t5, 52($a0)\n" \
129         /* We skip setting t6 and t7 because those are mask registers. */ \
130         REGS_MASK_A0 "lw $s0, 64($a0)\n" \
131         REGS_MASK_A0 "lw $s1, 68($a0)\n" \
132         REGS_MASK_A0 "lw $s2, 72($a0)\n" \
133         REGS_MASK_A0 "lw $s3, 76($a0)\n" \
134         REGS_MASK_A0 "lw $s4, 80($a0)\n" \
135         REGS_MASK_A0 "lw $s5, 84($a0)\n" \
136         REGS_MASK_A0 "lw $s6, 88($a0)\n" \
137         REGS_MASK_A0 "lw $s7, 92($a0)\n" \
138         /* We skip setting t8 because that register hold TLS index. */ \
139         REGS_MASK_A0 "lw $t9, 100($a0)\n" \
140         /* We skip setting k0 and k1 registers, they are changed by kernel. */ \
141         REGS_MASK_A0 "lw $gp, 112($a0)\n" \
142         REGS_MASK_A0 "lw $sp, 116($a0)\n" \
143         /* Value change of sp requires masking instruction. */ \
144         "and $sp, $sp, $t7\n" \
145         "nop\n" \
146         REGS_MASK_A0 "lw $fp, 120($a0)\n" \
147         REGS_MASK_A0 "lw $ra, 124($a0)\n" \
148         REGS_MASK_A0 "lw $a0, 16($a0)\n" \
149         ".p2align 4\n"  /* Align for whatever comes after. */ \
150         asm_code \
151         : : "r"(regs) : "memory")
152
153 #else
154 # error Unsupported architecture
155 #endif
156
157 /*
158  * JUMP_WITH_REGS(regs, dest) jumps to symbol |dest| with most
159  * registers restored from |regs|, a pointer of type "struct
160  * NaClSignalContext *".
161  */
162 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
163 # define JUMP_WITH_REGS(regs, dest) ASM_WITH_REGS(regs, "jmp " #dest)
164 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
165 # define JUMP_WITH_REGS(regs, dest) ASM_WITH_REGS(regs, "b " #dest)
166 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
167 # define JUMP_WITH_REGS(regs, dest) ASM_WITH_REGS(regs, \
168                                                   "b " #dest "\n" \
169                                                   "nop\n")
170 #else
171 # error Unsupported architecture
172 #endif
173
174 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
175
176 /*
177  * Normally it is possible to save x86 flags using the 'pushf'
178  * instruction.  However, 'pushf' is disallowed under NaCl.  Instead,
179  * we can read a subset of the flags indirectly using conditional
180  * instructions.
181  *
182  * We save 5 flags:
183  *   CF (carry), PF (parity), ZF (zero), SF (sign), OF (overflow)
184  *
185  * We don't attempt to check:
186  *   AF (for BCD arithmetic only, which is not allowed by the validator)
187  *   TF (trap flag:  not settable or observable by untrusted code)
188  *   DF (direction flag:  indirectly observable, but it's a hassle to do so)
189  */
190 extern const uint8_t kX86FlagBits[5];
191
192 /* We use 'mov' and 'lea' because they do not modify the flags. */
193 # define SAVE_X86_FLAGS_INTO_REG(reg) \
194     "mov $0, "reg"\n" \
195     "jnc 0f; lea 1<<0("reg"), "reg"; 0:\n" \
196     "jnp 0f; lea 1<<2("reg"), "reg"; 0:\n" \
197     "jnz 0f; lea 1<<6("reg"), "reg"; 0:\n" \
198     "jns 0f; lea 1<<7("reg"), "reg"; 0:\n" \
199     "jno 0f; lea 1<<11("reg"), "reg"; 0:\n"
200
201 /* Reset flags to RESET_X86_FLAGS_VALUE without modifying any registers. */
202 #define RESET_X86_FLAGS "testl $0, %%eax\n"
203 #define RESET_X86_FLAGS_VALUE ((1 << 2) | (1 << 6))
204
205 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
206
207 /*
208  * These are the only ARM CPSR bits that user code and untrusted code
209  * can read and modify, excluding the IT bits which are for Thumb-2
210  * (for If-Then-Else instructions).
211  */
212 # define REGS_ARM_USER_CPSR_FLAGS_MASK \
213     ((1<<31) | /* N */ \
214      (1<<30) | /* Z */ \
215      (1<<29) | /* C */ \
216      (1<<28) | /* V */ \
217      (1<<27) | /* Q */ \
218      (1<<19) | (1<<18) | (1<<17) | (1<<16) /* GE bits */)
219
220 #endif
221
222 /*
223  * REGS_SAVER_FUNC(def_func, callee_func) defines a function named
224  * def_func which saves all registers on the stack and passes them to
225  * callee_func in the form of a "struct NaClSignalContext *".
226  */
227
228 #define REGS_SAVER_FUNC(def_func, callee_func) \
229     void def_func(void); \
230     REGS_SAVER_FUNC_NOPROTO(def_func, callee_func)
231
232 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
233
234 # define REGS_SAVER_FUNC_NOPROTO(def_func, callee_func) \
235     void callee_func(struct NaClSignalContext *regs); \
236     __asm__( \
237         ".pushsection .text, \"ax\", @progbits\n" \
238         ".p2align 5\n" \
239         ".global " #def_func "\n"\
240         #def_func ":\n" \
241         /* Push most of "struct NaClSignalContext" in reverse order. */ \
242         "push $0\n"  /* Leave space for flags */ \
243         "push $0\n"  /* Leave space for prog_ctr */ \
244         "push %edi\n" \
245         "push %esi\n" \
246         "push %ebp\n" \
247         "push %esp\n" \
248         "push %ebx\n" \
249         "push %edx\n" \
250         "push %ecx\n" \
251         "push %eax\n" \
252         /* Save flags. */ \
253         SAVE_X86_FLAGS_INTO_REG("%eax") \
254         "movl %eax, 0x24(%esp)\n" \
255         /* Obtain def_func from GOT to fill prog_ctr with known value. */ \
256         "call 0f\n" \
257         "0: popl %eax\n" \
258         "1: addl $_GLOBAL_OFFSET_TABLE_ + (1b - 0b), %eax\n" \
259         "movl " #def_func "@GOT(%eax), %eax\n" \
260         "movl %eax, 0x20(%esp)\n" \
261         /* Adjust saved %esp value to account for preceding pushes. */ \
262         "addl $5 * 4, 0x10(%esp)\n" \
263         /* Save argument to callee_func() temporarily. */ \
264         "mov %esp, %eax\n" \
265         /* Align the stack pointer and leave space for an argument. */ \
266         "pushl $0\n" \
267         "and $~15, %esp\n" \
268         /* Set argument to callee_func(). */ \
269         "mov %eax, (%esp)\n" \
270         "call " #callee_func "\n" \
271         ".popsection\n")
272
273 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
274
275 # define REGS_SAVER_FUNC_NOPROTO(def_func, callee_func) \
276     void callee_func(struct NaClSignalContext *regs); \
277     __asm__( \
278         ".pushsection .text, \"ax\", @progbits\n" \
279         ".p2align 5\n" \
280         ".global " #def_func "\n"\
281         #def_func ":\n" \
282         /* Push most of "struct NaClSignalContext" in reverse order. */ \
283         "push $0\n"  /* Leave space for flags */ \
284         "push $0\n"  /* Leave space for prog_ctr */ \
285         "push %r15\n" \
286         "push %r14\n" \
287         "push %r13\n" \
288         "push %r12\n" \
289         "push %r11\n" \
290         "push %r10\n" \
291         "push %r9\n" \
292         "push %r8\n" \
293         "push %rsp\n" \
294         "push %rbp\n" \
295         "push %rdi\n" \
296         "push %rsi\n" \
297         "push %rdx\n" \
298         "push %rcx\n" \
299         "push %rbx\n" \
300         "push %rax\n" \
301         /* Save flags. */ \
302         SAVE_X86_FLAGS_INTO_REG("%rax") \
303         "movl %eax, 0x88(%rsp)\n" \
304         /* Fill out prog_ctr with known value */ \
305         "leaq " #def_func "(%rip), %rax\n" \
306         "movq %rax, 0x80(%rsp)\n" \
307         /* Adjust saved %rsp value to account for preceding pushes. */ \
308         "addq $10 * 8, 0x38(%rsp)\n" \
309         /* Set argument to callee_func(). */ \
310         "movl %esp, %edi\n" \
311         /* Align the stack pointer */ \
312         "and $~15, %esp\n" \
313         "addq %r15, %rsp\n" \
314         "call " #callee_func "\n" \
315         ".popsection\n")
316
317 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
318
319 /*
320  * "push {sp}" is undefined ("unpredictable") on ARM, so we move sp to
321  * a temporary register to push its original value.  (Indeed, whether
322  * sp is modified before or after being written differs between QEMU
323  * and the Panda boards.)
324  */
325 # define REGS_SAVER_FUNC_NOPROTO(def_func, callee_func) \
326     void callee_func(struct NaClSignalContext *regs); \
327     __asm__( \
328         ".pushsection .text, \"ax\", %progbits\n" \
329         ".p2align 4\n" \
330         ".global " #def_func "\n"\
331         #def_func ":\n" \
332         "push {r0}\n"  /* Leave space for cpsr */ \
333         "push {r0}\n"  /* Leave space for prog_ctr */ \
334         "push {r14}\n" \
335         /* Save r0-r12 and sp; adjust sp for the pushes above */ \
336         "add r14, sp, #0xc\n" \
337         "push {r10-r12, r14}\n" \
338         /* Push a dummy value for r9, which the tests need not compare */ \
339         "mov r10, #0\n" \
340         "push {r10}\n" \
341         /* Save the rest of struct NaClSignalContext */ \
342         "push {r0-r8}\n" \
343         /* Now save a correct prog_ctr value */ \
344         "adr r0, " #def_func "\n" \
345         "str r0, [sp, #0x3c]\n" \
346         /* Save CPSR (flags) register, a.k.a. APSR for user mode */ \
347         "mrs r0, apsr\n" \
348         "str r0, [sp, #0x40]\n" \
349         /* Set argument to callee_func() */ \
350         "mov r0, sp\n" \
351         /* Align the stack pointer */ \
352         "bic sp, sp, #0xc000000f\n" \
353         "b " #callee_func "\n" \
354         ".popsection\n")
355
356 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
357
358 # define REGS_SAVER_FUNC_NOPROTO(def_func, callee_func) \
359     void callee_func(struct NaClSignalContext *regs); \
360     __asm__( \
361         ".pushsection .text, \"ax\", %progbits\n" \
362         ".set noreorder\n" \
363         ".p2align 4\n" \
364         ".global " #def_func "\n"\
365         #def_func ":\n" \
366         /* Make space on stack for all registers. */ \
367         "add $sp, $sp, -132\n" \
368         "and $sp, $sp, $t7\n"\
369         "sw $zero, 0($sp)\n" \
370         "sw $at, 4($sp)\n" \
371         "sw $v0, 8($sp)\n" \
372         "sw $v1, 12($sp)\n" \
373         "sw $a0, 16($sp)\n" \
374         "sw $a1, 20($sp)\n" \
375         "sw $a2, 24($sp)\n" \
376         "sw $a3, 28($sp)\n" \
377         "sw $t0, 32($sp)\n" \
378         "sw $t1, 36($sp)\n" \
379         "sw $t2, 40($sp)\n" \
380         "sw $t3, 44($sp)\n" \
381         "sw $t4, 48($sp)\n" \
382         "sw $t5, 52($sp)\n" \
383         "sw $t6, 56($sp)\n" \
384         "sw $t7, 60($sp)\n" \
385         "sw $s0, 64($sp)\n" \
386         "sw $s1, 68($sp)\n" \
387         "sw $s2, 72($sp)\n" \
388         "sw $s3, 76($sp)\n" \
389         "sw $s4, 80($sp)\n" \
390         "sw $s5, 84($sp)\n" \
391         "sw $s6, 88($sp)\n" \
392         "sw $s7, 92($sp)\n" \
393         "sw $t8, 96($sp)\n" \
394         "sw $t9, 100($sp)\n" \
395         /* We skip saving k0 and k1 registers, they are changed by kernel. */ \
396         "sw $gp, 112($sp)\n" \
397         /* Store the value stack_ptr had on entry of this function. */ \
398         "add $t1, $sp, 132\n" \
399         "sw $t1, 116($sp)\n" \
400         "sw $fp, 120($sp)\n" \
401         "sw $ra, 124($sp)\n" \
402         /* Save a correct prog_ctr value. */ \
403         "lui $t1, %hi(" #def_func ")\n" \
404         "addiu $t1, $t1, %lo(" #def_func ")\n" \
405         "sw $t1, 128($sp)\n" \
406         /* Prepare argument for callee_func. */ \
407         "move $a0, $sp\n" \
408         /* Align the stack pointer. */ \
409         "sll $t1, $t7, 3\n" \
410         "and $sp, $sp, $t1\n" \
411         "and $sp, $sp, $t7\n" \
412         /* Make space on stack for convention calling registers. */ \
413         "add $sp, $sp, -16\n" \
414         "and $sp, $sp, $t7\n" \
415         /* Set $t9 to callee_func as required by ABI for PIC code. */ \
416         "lui $t9, %hi(" #callee_func ")\n" \
417         "b " #callee_func "\n" \
418         "addiu $t9, $t9, %lo(" #callee_func ")\n" \
419         "nop\n" \
420         "nop \n" \
421         "nop\n" \
422         ".set reorder\n" \
423         ".popsection\n")
424
425 #else
426 # error Unsupported architecture
427 #endif
428
429 /* Initialize the register set with arbitrary test data. */
430 void RegsFillTestValues(struct NaClSignalContext *regs, int seed);
431
432 /* Adjust registers to follow the sandbox's constraints. */
433 void RegsApplySandboxConstraints(struct NaClSignalContext *regs);
434
435 /* This compares for equality all registers saved by REGS_SAVER_FUNC. */
436 void RegsAssertEqual(const struct NaClSignalContext *actual,
437                      const struct NaClSignalContext *expected);
438
439 /*
440  * Copy a NaClUserRegisterState into a NaClSignalContext, leaving
441  * trusted registers in the NaClSignalContext with unspecified values.
442  */
443 void RegsCopyFromUserRegisterState(struct NaClSignalContext *dest,
444                                    const NaClUserRegisterState *src);
445
446 /* Zero out registers that are clobbered by function calls. */
447 void RegsUnsetNonCalleeSavedRegisters(struct NaClSignalContext *regs);
448
449 /*
450  * For a function called with register state |regs|, extract the first
451  * argument.  This is useful for a function entry point defined by
452  * REGS_SAVER_FUNC.
453  */
454 uintptr_t RegsGetArg1(const struct NaClSignalContext *regs);
455
456 #endif