1/* 2 * Copyright (c) 2011 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#include "native_client/src/include/arm_sandbox.h" 7#include "native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h" 8#include "native_client/src/trusted/service_runtime/nacl_config.h" 9 10/* the macros below are used with movw/movt and absolute values */ 11/* llvm-mc does not like the use of :lower16:/:upper16: with absolute values */ 12/* c.f.: http://llvm.org/bugs/show_bug.cgi?id=8721 */ 13#define lower_16(x) ((x) & 0xffff) 14#define upper_16(x) (((x) >> 16) & 0xffff) 15 16 17 /* 18 * Code to test various address layout boundary conditions. 19 * This is a translation from the x86-{32,64} code, and is 20 * not intended to be super efficent, just good enough to 21 * print out the values that are designed, while maintaining 22 * strict control over the address space layout. 23 */ 24 25 .text 26start_of_text: 27 /* 28 * write_num_10 omitted. __aeabi_udivmod is too long/complex 29 * to replicate, we cannot link against glibc to get _udivsi3.o 30 * and pick up transitive dependencies. Plus, we don't actually 31 * use decimal output (yet). 32 * 33 * One alternative would be to link using: 34 * 35 * ${LD} --native-client -e _start -Ttext 0x20000 -o ${TARGET} \ 36 * ${SOURCES} ${GLIBC} ${TEXT_EXTEND} 37 * 38 * i.e., to load the text pad as a separate .o *after* external 39 * references are resolved from glibc, with link-time 40 * expansion/computation of the (TEXT_EXTEND - (. - start_of_text))/4 41 * fill expression (is that possible?). 42 */ 43 44 /* 45 * write_num_16. Write an unsigned value in hex. 46 * r0 is descriptor number, r1 is unsigned value to write. 47 */ 48 .p2align 4 49write_num_16: 50 push {r4, lr} 51 mov r3, sp 52 /* r12 is caller-saved: use it as a temporary register */ 53 sub r12, sp, #0x10 54 bic sp, r12, #0xc0000000 55 56 mov r2, #0 57do_digit_16: 58 sub r3, r3, #1 59 add r2, r2, #1 60 and r4, r1, #0xf 61 62 add r4, r4, #'0' 63 cmp r4, #'9' 64 ble do_digit_not_upper 65 add r4, r4, #('a'-'0'-10) 66 67do_digit_not_upper: 68 bic r3, r3, #0xc0000000 69 strb r4, [r3] 70 lsrs r1, r1, #4 71 bne do_digit_16 72 73 mov r1, r3 74 movw r3, lower_16(NACL_SYSCALL_ADDR(NACL_sys_write)) 75 movt r3, upper_16(NACL_SYSCALL_ADDR(NACL_sys_write)) 76 nop 77 78 nop 79 nop 80 bic r3, r3, #0xc000000f 81 blx r3 82 83 /* r12 is caller-saved: use it as a temporary register */ 84 add r12, sp, #0x10 85 bic sp, r12, #0xc0000000 86 pop {r4, lr} 87 nop 88 89 bic lr, lr, #0xc000000f 90 bx lr 91 92 .p2align 4 93 /* 94 * r0 is descriptor number, r1 is character to write 95 */ 96write_char: 97 push {lr} 98 /* r12 is caller-saved: use it as a temporary register */ 99 sub r12, sp, #0x10 100 bic sp, r12, #0xc0000000 101 strb r1, [sp] 102 103 mov r1, sp 104 mov r2, #1 105 movw r3, lower_16(NACL_SYSCALL_ADDR(NACL_sys_write)) 106 movt r3, upper_16(NACL_SYSCALL_ADDR(NACL_sys_write)) 107 108 nop 109 nop 110 bic r3, r3, #0xc000000f 111 blx r3 112 113 /* r12 is caller-saved: use it as a temporary register */ 114 add r12, sp, #0x10 115 bic sp, r12, #0xc0000000 116 pop {lr} 117 nop 118 119 bic lr, lr, #0xc000000f 120 bx lr 121 122 .p2align 4 123 .globl _start 124_start: 125 /* basic I/O test */ 126 mov r0, #1 127 movw r1, #0xbeef 128 movt r1, #0xdead 129 bl write_num_16 130 131 mov r0, #1 132 mov r1, #'\n' 133 nop 134 bl write_char 135 136 movw r1, :lower16:(end_of_text) 137 movt r1, :upper16:(end_of_text) 138 mov r0, #1 139 bl write_num_16 140 141 mov r0, #1 142 mov r1, #'\n' 143 nop 144 bl write_char 145 146 mov r0, #0 147 movw r3, lower_16(NACL_SYSCALL_ADDR(NACL_sys_brk)) 148 movt r3, upper_16(NACL_SYSCALL_ADDR(NACL_sys_brk)) 149 nop 150 151 nop 152 nop 153 bic r3, r3, #0xc000000f 154 blx r3 155 156 mov r4, r0 /* save a copy of break addr */ 157 mov r1, r0 158 mov r0, #1 159 bl write_num_16 160 161 mov r0, #1 162 mov r1, #'\n' 163 nop 164 bl write_char 165 166 mov r5, #0 /* r5 holds eventual exit status */ 167 movw r1, lower_16(EXPECTED_BREAK) 168 movt r1, upper_16(EXPECTED_BREAK) 169 cmp r1, r4 170 171 movne r5, #1 172 mov r0, #1 /* r1 still has EXPECTED_BREAK */ 173 nop 174 bl write_num_16 175 176 mov r1, #'\n' 177 mov r0, #1 178 nop 179 bl write_char 180 181#if defined(EXPECTED_RODATA) 182 mov r2, #12 183 movw r1, :lower16:(ro_str) 184 movt r1, :upper16:(ro_str) 185 mov r0, #1 186 187 movw r3, lower_16(NACL_SYSCALL_ADDR(NACL_sys_write)) 188 movt r3, upper_16(NACL_SYSCALL_ADDR(NACL_sys_write)) 189 bic r3, r3, #0xc000000f 190 blx r3 191 192 /* Truncate the address to page boundary for comparison. */ 193 movw r4, #0 194 movt r4, :upper16:(ro_str) 195 nop 196 nop 197 198 mov r0, #1 199 mov r1, r4 200 nop 201 bl write_num_16 202 203 mov r1, #'\n' 204 mov r0, #1 205 nop 206 bl write_char 207 208 movw r1, lower_16(EXPECTED_RODATA) 209 movt r1, upper_16(EXPECTED_RODATA) 210 nop 211 nop 212 213 cmp r1, r4 214 movne r5, #2 215 mov r0, #1 /* r1 still has EXPECTED_RODATA */ 216 bl write_num_16 217 218 mov r1, #'\n' 219 mov r0, #2 220 nop 221 bl write_char 222#endif 223 224 movw r3, lower_16(NACL_SYSCALL_ADDR(NACL_sys_exit)) 225 movt r3, upper_16(NACL_SYSCALL_ADDR(NACL_sys_exit)) 226 mov r0, r5 227 nop 228 229 nop 230 nop 231 bic r3, r3, #0xc000000f 232 blx r3 233#if defined(PNACL_AS) 234/* NOTE: unlike x86 the alignment directive on ARM takes 235 the logarithm of the alignment */ 236#define POW2_BIGGER_THAN_DOT 14 237 .align32 POW2_BIGGER_THAN_DOT, NACL_INSTR_ARM_HALT_FILL 238 .fill (TEXT_EXTEND - (1 << POW2_BIGGER_THAN_DOT))/4, 4, \ 239 NACL_INSTR_ARM_HALT_FILL 240#else 241 .fill (TEXT_EXTEND - (. - start_of_text))/4, 4, \ 242 NACL_INSTR_ARM_HALT_FILL 243#endif 244 245end_of_text: 246 247#if defined(EXPECTED_RODATA) 248 .section .rodata 249ro_str: .ascii "Hello world\n" 250 /* 123456789012 */ 251#endif 252