[444] | 1 | /* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd. All rights reserved. |
---|
| 2 | |
---|
| 3 | Redistribution and use in source and binary forms, with or without |
---|
| 4 | modification, are permitted provided that the following conditions |
---|
| 5 | are met: |
---|
| 6 | 1. Redistributions of source code must retain the above copyright |
---|
| 7 | notice, this list of conditions and the following disclaimer. |
---|
| 8 | 2. Redistributions in binary form must reproduce the above copyright |
---|
| 9 | notice, this list of conditions and the following disclaimer in the |
---|
| 10 | documentation and/or other materials provided with the distribution. |
---|
| 11 | 3. The name of the company may not be used to endorse or promote |
---|
| 12 | products derived from this software without specific prior written |
---|
| 13 | permission. |
---|
| 14 | |
---|
| 15 | THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED |
---|
| 16 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
---|
| 17 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
---|
| 18 | IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
---|
| 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
---|
| 20 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
---|
| 21 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
---|
| 22 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
---|
| 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
---|
| 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ |
---|
| 25 | |
---|
| 26 | #include "newlib.h" |
---|
| 27 | #include "svc.h" |
---|
| 28 | |
---|
| 29 | /* ANSI concatenation macros. */ |
---|
| 30 | #define CONCAT(a, b) CONCAT2(a, b) |
---|
| 31 | #define CONCAT2(a, b) a ## b |
---|
| 32 | |
---|
| 33 | #ifdef __USER_LABEL_PREFIX__ |
---|
| 34 | #define FUNCTION( name ) CONCAT (__USER_LABEL_PREFIX__, name) |
---|
| 35 | #else |
---|
| 36 | #error __USER_LABEL_PREFIX is not defined |
---|
| 37 | #endif |
---|
| 38 | |
---|
| 39 | #ifdef HAVE_INITFINI_ARRAY |
---|
| 40 | #define _init __libc_init_array |
---|
| 41 | #define _fini __libc_fini_array |
---|
| 42 | #endif |
---|
| 43 | |
---|
| 44 | /* In ELF64, the large addressing model is used and R_AARCH64_ABS64 |
---|
| 45 | reloc is generated to relocate a 64-bit address. Since 64-bit |
---|
| 46 | relocation is not available in ELF32, in order to have |
---|
| 47 | a single code path for both ELF64 and ELF32 classes, we synthesize |
---|
| 48 | a 64-bit relocation by using R_AARCH64_P32_ABS32 on one of the two |
---|
| 49 | .word directives, depending on the endianness. */ |
---|
| 50 | |
---|
| 51 | .macro GEN_DWORD name |
---|
| 52 | #if defined(__ILP32__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
---|
| 53 | .word \name |
---|
| 54 | .word 0 |
---|
| 55 | #elif defined(__ILP32__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
---|
| 56 | .word 0 |
---|
| 57 | .word \name |
---|
| 58 | #else |
---|
| 59 | .dword \name |
---|
| 60 | #endif |
---|
| 61 | .endm |
---|
| 62 | |
---|
| 63 | /* Help tackle the pointer size difference between ELF64 and ELF32. */ |
---|
| 64 | #ifdef __ILP32__ |
---|
| 65 | #define PTR_REG(n) w##n |
---|
| 66 | #define PTR_SIZE 4 |
---|
| 67 | #define PTR_LOG_SIZE 2 |
---|
| 68 | #else |
---|
| 69 | #define PTR_REG(n) x##n |
---|
| 70 | #define PTR_SIZE 8 |
---|
| 71 | #define PTR_LOG_SIZE 3 |
---|
| 72 | #endif |
---|
| 73 | |
---|
| 74 | .text |
---|
| 75 | .macro FUNC_START name |
---|
| 76 | .global \name |
---|
| 77 | \name: |
---|
| 78 | .endm |
---|
| 79 | |
---|
| 80 | .align 2 |
---|
| 81 | |
---|
| 82 | FUNC_START _mainCRTStartup |
---|
| 83 | FUNC_START _start |
---|
| 84 | |
---|
| 85 | /* Start by setting up a stack */ |
---|
| 86 | #ifdef ARM_RDI_MONITOR |
---|
| 87 | /* Issue Angel SVC to read memory info. |
---|
| 88 | |
---|
| 89 | ptr to ptr to 4 words to receive data. */ |
---|
| 90 | adr x1, .LC0 |
---|
| 91 | mov w0, #AngelSVC_Reason_HeapInfo |
---|
| 92 | AngelSVCAsm AngelSVC |
---|
| 93 | |
---|
| 94 | /* Initialise the stack pointer */ |
---|
| 95 | |
---|
| 96 | /* We currently choose to use the heap_limit field rather than |
---|
| 97 | stack_base because the AEM validation model |
---|
| 98 | returns sane values in the heap fields, but 0 in the stack |
---|
| 99 | fields. Note on the VE AEM model it is necessary to pass |
---|
| 100 | command line options to the AEM in order to define the values |
---|
| 101 | exposed here in the HeapInfo Angel call. */ |
---|
| 102 | ldr x0, .LC0 /* point at returned values */ |
---|
| 103 | ldr x1, [x0, #8] /* get heap_limit */ |
---|
| 104 | |
---|
| 105 | /* Set __heap_limit. */ |
---|
| 106 | #ifdef __ILP32__ |
---|
| 107 | /* Sanity check on the __heap_limit. */ |
---|
| 108 | tst x1, #0xffffffff00000000 |
---|
| 109 | bne .Linsanepar |
---|
| 110 | #endif |
---|
| 111 | cmp x1, xzr |
---|
| 112 | beq .LC4 |
---|
| 113 | adrp x2, __heap_limit |
---|
| 114 | add x2, x2, #:lo12:__heap_limit |
---|
| 115 | str x1, [x2] |
---|
| 116 | .LC4: |
---|
| 117 | |
---|
| 118 | ldr x1, [x0] /* get heap_base */ |
---|
| 119 | #ifdef __ILP32__ |
---|
| 120 | /* Sanity check on the heap base. */ |
---|
| 121 | tst x1, #0xffffffff00000000 |
---|
| 122 | bne .Linsanepar |
---|
| 123 | #endif |
---|
| 124 | cmp x1, xzr |
---|
| 125 | bne .LC5 |
---|
| 126 | /* If the heap base value [x0, #0] is 0 then the heap base is actually |
---|
| 127 | at the end of program data (i.e. __end__) */ |
---|
| 128 | ldr x1, .LC3 |
---|
| 129 | str x1, [x0, #0] |
---|
| 130 | .LC5: |
---|
| 131 | ldr x1, [x0, #16] /* get stack_base */ |
---|
| 132 | |
---|
| 133 | #ifdef __ILP32__ |
---|
| 134 | /* Sanity check on the stack_base. */ |
---|
| 135 | tst x1, #0xffffffff00000000 |
---|
| 136 | bne .Linsanepar |
---|
| 137 | #endif |
---|
| 138 | cmp x1, xzr |
---|
| 139 | bne .LC6 |
---|
| 140 | #endif |
---|
| 141 | ldr x1, .Lstack /* Set up the stack pointer to a fixed value */ |
---|
| 142 | .LC6: |
---|
| 143 | |
---|
| 144 | /* Ensure quad-word stack alignment. */ |
---|
| 145 | and x0, x1, #~15 |
---|
| 146 | mov sp, x0 |
---|
| 147 | |
---|
| 148 | /* Setup an initial dummy frame with saved fp=0 and saved lr=0 */ |
---|
| 149 | mov x29, 0 |
---|
| 150 | stp x29, x29, [sp, #-16]! |
---|
| 151 | mov x29, sp |
---|
| 152 | |
---|
| 153 | /* Initialize exception vector table, flatmap, etc. */ |
---|
| 154 | bl FUNCTION (_cpu_init_hook) |
---|
| 155 | |
---|
| 156 | /* Zero the memory in the .bss section. */ |
---|
| 157 | ldr x0, .LC1 /* First arg: start of memory block */ |
---|
| 158 | mov w1, #0 /* Second arg: fill value */ |
---|
| 159 | ldr x2, .LC2 |
---|
| 160 | sub x2, x2, x0 /* Third arg: length of block */ |
---|
| 161 | bl FUNCTION (memset) |
---|
| 162 | |
---|
| 163 | #ifdef ARM_RDI_MONITOR |
---|
| 164 | /* Need to set up standard file handles */ |
---|
| 165 | bl FUNCTION (initialise_monitor_handles) |
---|
| 166 | #endif |
---|
| 167 | |
---|
| 168 | /* .init and .fini sections are used to create constructors |
---|
| 169 | and destructors. Here we call the _init function and arrange |
---|
| 170 | for _fini to be called at program exit. */ |
---|
| 171 | ldr x0, .Lfini |
---|
| 172 | bl FUNCTION (atexit) |
---|
| 173 | |
---|
| 174 | bl FUNCTION (_init) |
---|
| 175 | |
---|
| 176 | #ifdef ARM_RDI_MONITOR |
---|
| 177 | /* Fetch and parse the command line. */ |
---|
| 178 | ldr x1, .Lcmdline /* Command line descriptor. */ |
---|
| 179 | mov w0, #AngelSVC_Reason_GetCmdLine |
---|
| 180 | AngelSVCAsm AngelSVC |
---|
| 181 | ldr x8, .Lcmdline |
---|
| 182 | ldr x8, [x8] |
---|
| 183 | |
---|
| 184 | mov x0, #0 /* argc */ |
---|
| 185 | mov x1, sp /* argv */ |
---|
| 186 | ldr x2, .Lenvp /* envp */ |
---|
| 187 | |
---|
| 188 | /* Put NULL at end of argv array. */ |
---|
| 189 | str PTR_REG (0), [x1, #-PTR_SIZE]! |
---|
| 190 | |
---|
| 191 | /* Skip leading blanks. */ |
---|
| 192 | .Lnext: ldrb w3, [x8], #1 |
---|
| 193 | cbz w3, .Lendstr |
---|
| 194 | cmp w3, #' ' |
---|
| 195 | b.eq .Lnext |
---|
| 196 | |
---|
| 197 | mov w4, #' ' /* Terminator is space. */ |
---|
| 198 | |
---|
| 199 | /* See whether we are scanning a quoted string by checking for |
---|
| 200 | opening quote (" or '). */ |
---|
| 201 | subs w9, w3, #'\"' |
---|
| 202 | sub x8, x8, #1 /* Backup if no match. */ |
---|
| 203 | ccmp w9, #('\'' - '\"'), 0x4 /* FLG_Z */, ne |
---|
| 204 | csel w4, w3, w4, eq /* Terminator = quote if match. */ |
---|
| 205 | cinc x8, x8, eq |
---|
| 206 | |
---|
| 207 | /* Push arg pointer to argv, and bump argc. */ |
---|
| 208 | str PTR_REG (8), [x1, #-PTR_SIZE]! |
---|
| 209 | add x0, x0, #1 |
---|
| 210 | |
---|
| 211 | /* Find end of arg string. */ |
---|
| 212 | 1: ldrb w3, [x8], #1 |
---|
| 213 | cbz w3, .Lendstr |
---|
| 214 | cmp w4, w3 /* Reached terminator? */ |
---|
| 215 | b.ne 1b |
---|
| 216 | |
---|
| 217 | /* Terminate the arg string with NUL char. */ |
---|
| 218 | mov w4, #0 |
---|
| 219 | strb w4, [x8, #-1] |
---|
| 220 | b .Lnext |
---|
| 221 | |
---|
| 222 | /* Reverse argv array. */ |
---|
| 223 | .Lendstr: |
---|
| 224 | add x3, x1, #0 /* sp = &argv[0] */ |
---|
| 225 | add x4, x1, w0, uxtw #PTR_LOG_SIZE /* ep = &argv[argc] */ |
---|
| 226 | cmp x4, x3 |
---|
| 227 | b.lo 2f |
---|
| 228 | 1: ldr PTR_REG (5), [x4, #-PTR_SIZE] /* PTR_REG (5) = ep[-1] */ |
---|
| 229 | ldr PTR_REG (6), [x3] /* PTR_REG (6) = *sp */ |
---|
| 230 | str PTR_REG (6), [x4, #-PTR_SIZE]! /* *--ep = PTR_REG (6) */ |
---|
| 231 | str PTR_REG (5), [x3], #PTR_SIZE /* *sp++ = PTR_REG (5) */ |
---|
| 232 | cmp x4, x3 |
---|
| 233 | b.hi 1b |
---|
| 234 | 2: |
---|
| 235 | /* Move sp to the 16B boundary below argv. */ |
---|
| 236 | and x4, x1, ~15 |
---|
| 237 | mov sp, x4 |
---|
| 238 | |
---|
| 239 | #else |
---|
| 240 | mov x0, #0 /* argc = 0 */ |
---|
| 241 | mov x1, #0 /* argv = NULL */ |
---|
| 242 | #endif |
---|
| 243 | |
---|
| 244 | bl FUNCTION (main) |
---|
| 245 | |
---|
| 246 | b FUNCTION (exit) /* Cannot return. */ |
---|
| 247 | |
---|
| 248 | #if defined (ARM_RDI_MONITOR) && defined (__ILP32__) |
---|
| 249 | .Linsanepar: |
---|
| 250 | /* Exit with 1 if the parameter is not within the 32-bit address |
---|
| 251 | space. */ |
---|
| 252 | mov x1, ADP_Stopped_ApplicationExit & 0xff |
---|
| 253 | movk x1, ADP_Stopped_ApplicationExit >> 16, lsl #16 |
---|
| 254 | adrp x0, HeapBase /* Reuse to construct the parameter block. */ |
---|
| 255 | add x0, x0, #:lo12:HeapBase |
---|
| 256 | str x1, [x0] |
---|
| 257 | mov x1, 1 |
---|
| 258 | str x1, [x0, #8] |
---|
| 259 | mov w1, #AngelSVC_Reason_ReportException |
---|
| 260 | AngelSVCAsm AngelSVC |
---|
| 261 | b . |
---|
| 262 | #endif |
---|
| 263 | |
---|
| 264 | /* Function initializing exception vector table, flatmap, etc. |
---|
| 265 | Declared as weak symbol so that user can override this definition |
---|
| 266 | by linking in their own version of the function. */ |
---|
| 267 | .weak FUNCTION (_cpu_init_hook) |
---|
| 268 | FUNCTION (_cpu_init_hook): |
---|
| 269 | ret |
---|
| 270 | |
---|
| 271 | .align 3 |
---|
| 272 | #ifdef ARM_RDI_MONITOR |
---|
| 273 | .LC0: |
---|
| 274 | GEN_DWORD HeapBase |
---|
| 275 | .LC3: |
---|
| 276 | GEN_DWORD __end__ |
---|
| 277 | #endif |
---|
| 278 | .Lstack: |
---|
| 279 | GEN_DWORD __stack |
---|
| 280 | .weak __stack |
---|
| 281 | |
---|
| 282 | .LC1: |
---|
| 283 | GEN_DWORD __bss_start__ |
---|
| 284 | .LC2: |
---|
| 285 | GEN_DWORD __bss_end__ |
---|
| 286 | .Lfini: |
---|
| 287 | GEN_DWORD FUNCTION(_fini) |
---|
| 288 | #ifdef ARM_RDI_MONITOR |
---|
| 289 | .Lenvp: |
---|
| 290 | GEN_DWORD env |
---|
| 291 | .Lcmdline: |
---|
| 292 | GEN_DWORD AngelSVCArgs |
---|
| 293 | /* Workspace for Angel calls. */ |
---|
| 294 | .data |
---|
| 295 | .align 3 |
---|
| 296 | /* Data returned by monitor SVC. */ |
---|
| 297 | #if defined(__ILP32__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
---|
| 298 | .set __stack_base__, StackBase + 4 |
---|
| 299 | #else |
---|
| 300 | .set __stack_base__, StackBase |
---|
| 301 | #endif |
---|
| 302 | .global __stack_base__ |
---|
| 303 | HeapBase: .dword 0 |
---|
| 304 | HeapLimit: .dword 0 |
---|
| 305 | StackBase: .dword 0 |
---|
| 306 | StackLimit: .dword 0 |
---|
| 307 | env: .dword 0 /* Dummy environment array */ |
---|
| 308 | CommandLine: .space 256,0 /* Maximum length of 255 chars handled. */ |
---|
| 309 | AngelSVCArgs: |
---|
| 310 | GEN_DWORD CommandLine |
---|
| 311 | .dword 255 |
---|
| 312 | #endif |
---|