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 #include "native_client/tests/common/register_set.h"
13 #include "native_client/src/include/nacl_assert.h"
15 #if defined(__native_client__)
16 # include "native_client/src/untrusted/nacl/nacl_thread.h"
24 int user_register_state_reg_offset;
25 int user_register_state_reg_size;
28 #define DEFINE_REG(regname) \
31 offsetof(struct NaClSignalContext, regname), \
32 sizeof(((struct NaClSignalContext *) NULL)->regname), \
33 offsetof(NaClUserRegisterState, regname), \
34 sizeof(((NaClUserRegisterState *) NULL)->regname) \
37 const struct RegInfo kRegs[] = {
39 * We do not look at x86 segment registers because they are not
40 * saved by REGS_SAVER_FUNC.
42 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
47 DEFINE_REG(stack_ptr),
53 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
61 DEFINE_REG(stack_ptr),
72 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
86 DEFINE_REG(stack_ptr),
90 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
119 DEFINE_REG(global_ptr),
120 DEFINE_REG(stack_ptr),
121 DEFINE_REG(frame_ptr),
122 DEFINE_REG(return_addr),
125 # error Unsupported architecture
131 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
132 /* Flags readable and writable by untrusted code. */
133 const uint8_t kX86FlagBits[5] = { 0, 2, 6, 7, 11 };
135 * kX86KnownFlagsMask contains kX86FlagBits plus the trap flag (which
136 * is not readable or writable by untrusted code) so that trusted-code
137 * tests will check that the trap flag is still set.
139 static const uint32_t kX86KnownFlagsMask =
140 (1<<0) | (1<<2) | (1<<6) | (1<<7) | (1<<11) |
141 (1<<8); /* Trap flag */
144 void RegsFillTestValues(struct NaClSignalContext *regs, int seed) {
146 for (index = 0; index < sizeof(*regs); index++) {
147 ((char *) regs)[index] = index + seed + 1;
149 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
150 /* Set x86 flags to a value that we know will work. */
151 regs->flags = RESET_X86_FLAGS_VALUE;
155 #if defined(__native_client__)
156 void RegsApplySandboxConstraints(struct NaClSignalContext *regs) {
157 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
159 __asm__("mov %%r15, %0" : "=r"(r15));
161 regs->prog_ctr = r15 + (uint32_t) regs->prog_ctr;
162 regs->stack_ptr = r15 + (uint32_t) regs->stack_ptr;
163 regs->rbp = r15 + (uint32_t) regs->rbp;
165 UNREFERENCED_PARAMETER(regs);
170 static uint64_t RegsGetRegValue(const struct NaClSignalContext *regs,
171 unsigned int regnum) {
172 uintptr_t ptr = (uintptr_t) regs + kRegs[regnum].reg_offset;
173 assert(regnum < NACL_ARRAY_SIZE(kRegs));
174 if (kRegs[regnum].reg_size == 4) {
175 return *(uint32_t *) ptr;
176 } else if (kRegs[regnum].reg_size == 8) {
177 return *(uint64_t *) ptr;
179 fprintf(stderr, "Unknown register size: %i\n", kRegs[regnum].reg_size);
184 static void RegsDump(const struct NaClSignalContext *regs) {
186 for (regnum = 0; regnum < NACL_ARRAY_SIZE(kRegs); regnum++) {
187 long long value = RegsGetRegValue(regs, regnum);
188 fprintf(stderr, " %s=0x%llx (%lld)\n",
189 kRegs[regnum].reg_name, value, value);
193 static void RegsNormalizeFlags(struct NaClSignalContext *regs) {
194 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
195 regs->flags &= kX86KnownFlagsMask;
196 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
197 regs->cpsr &= REGS_ARM_USER_CPSR_FLAGS_MASK;
198 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
199 /* No flags field on MIPS. */
200 UNREFERENCED_PARAMETER(regs);
204 void RegsAssertEqual(const struct NaClSignalContext *actual,
205 const struct NaClSignalContext *expected) {
209 /* Make a copy so that we can ignore some of the x86/ARM flags. */
210 struct NaClSignalContext copy_actual = *actual;
211 struct NaClSignalContext copy_expected = *expected;
212 RegsNormalizeFlags(©_actual);
213 RegsNormalizeFlags(©_expected);
215 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
217 * We skip comparison of r9 because it is not supposed to be
218 * settable or readable by untrusted code. However, for debugging
219 * purposes we still include r9 in register dumps printed by
220 * RegsDump(), so r9 remains listed in kRegs[].
222 copy_expected.r9 = copy_actual.r9;
223 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
225 * The registers below are all read-only, so we skip their comparison. We
226 * expect t6 and t7 to hold control flow masks. For t8, which holds TLS
227 * index, we skip comparison. Zero register holds zero always. All of the
228 * above named registers are not settable by untrusted code. We also skip
229 * comparison for k0 and k1 registers because those are registers reserved for
230 * use by interrupt/trap handler and therefore volatile.
231 * However, for debugging purposes we still include those in register dumps
232 * printed by RegsDump(), so they remain listed in kRegs[].
234 copy_expected.zero = 0;
235 copy_expected.t6 = NACL_CONTROL_FLOW_MASK;
236 copy_expected.t7 = NACL_DATA_FLOW_MASK;
237 copy_expected.t8 = copy_actual.t8;
238 copy_expected.k0 = copy_actual.k0;
239 copy_expected.k1 = copy_actual.k1;
242 for (regnum = 0; regnum < NACL_ARRAY_SIZE(kRegs); regnum++) {
243 if (RegsGetRegValue(©_actual, regnum) !=
244 RegsGetRegValue(©_expected, regnum)) {
245 fprintf(stderr, "Mismatch in register %s\n", kRegs[regnum].reg_name);
250 fprintf(stderr, "Expected register state:\n");
252 fprintf(stderr, "Actual register state:\n");
258 void RegsCopyFromUserRegisterState(struct NaClSignalContext *dest,
259 const NaClUserRegisterState *src) {
262 /* Fill out trusted registers with dummy values. */
263 memset(dest, 0xff, sizeof(*dest));
265 for (regnum = 0; regnum < NACL_ARRAY_SIZE(kRegs); regnum++) {
266 ASSERT_EQ(kRegs[regnum].reg_size,
267 kRegs[regnum].user_register_state_reg_size);
268 memcpy((char *) dest + kRegs[regnum].reg_offset,
269 (char *) src + kRegs[regnum].user_register_state_reg_offset,
270 kRegs[regnum].reg_size);
274 void RegsUnsetNonCalleeSavedRegisters(struct NaClSignalContext *regs) {
275 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
280 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
291 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
299 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
317 regs->global_ptr = 0;
318 regs->return_addr = 0;
320 # error Unsupported architecture
324 #if defined(__native_client__)
325 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
327 uintptr_t RegsGetArg1(const struct NaClSignalContext *regs) {
328 return ((uint32_t *) regs->stack_ptr)[1];
331 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
333 uintptr_t RegsGetArg1(const struct NaClSignalContext *regs) {
337 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
339 uintptr_t RegsGetArg1(const struct NaClSignalContext *regs) {
343 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
345 uintptr_t RegsGetArg1(const struct NaClSignalContext *regs) {
350 # error Unsupported architecture