Changeset 219885 in webkit for trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.cpp
- Timestamp:
- Jul 25, 2017, 1:56:04 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.cpp
r219740 r219885 187 187 // MacroAssemblerARMv7::probe() has already generated code to store some values. 188 188 // The top of stack now looks like this: 189 // esp[0 * ptrSize]: probe Function190 // esp[1 * ptrSize]: arg189 // esp[0 * ptrSize]: probe handler function 190 // esp[1 * ptrSize]: probe arg 191 191 // esp[2 * ptrSize]: saved r0 192 192 // esp[3 * ptrSize]: saved ip … … 255 255 // 1. Normal ARM calling convention relies on moving lr to pc to return to 256 256 // the caller. In our case, the address to return to is specified by 257 // ProbeContext.cpu. pc. And at that moment, we won't have any available257 // ProbeContext.cpu.gprs[pc]. And at that moment, we won't have any available 258 258 // scratch registers to hold the return address (lr needs to hold 259 // ProbeContext.cpu. lr, not the return address).259 // ProbeContext.cpu.gprs[lr], not the return address). 260 260 // 261 261 // The solution is to store the return address on the stack and load the … … 263 263 // 264 264 // 2. Issue 1 means we will need to write to the stack location at 265 // ProbeContext.cpu.sp - 4. But if the user probe function had modified 266 // the value of ProbeContext.cpu.sp to point in the range between 267 // &ProbeContext.cpu.ip thru &ProbeContext.cpu.aspr, then the action for 268 // Issue 1 may trash the values to be restored before we can restore 269 // them. 265 // ProbeContext.cpu.gprs[sp] - PTR_SIZE. But if the user probe function had 266 // modified the value of ProbeContext.cpu.gprs[sp] to point in the range between 267 // &ProbeContext.cpu.gprs[ip] thru &ProbeContext.cpu.sprs[aspr], then the action 268 // for Issue 1 may trash the values to be restored before we can restore them. 270 269 // 271 // The solution is to check if ProbeContext.cpu. spcontains a value in270 // The solution is to check if ProbeContext.cpu.gprs[sp] contains a value in 272 271 // the undesirable range. If so, we copy the remaining ProbeContext 273 // register data to a safe range (at memory lower than where 274 // ProbeContext.cpu.sp points) first, and restore the remaining register 275 // from this new range. 276 277 "add ip, sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_APSR_OFFSET) "\n" 272 // register data to a safe area first, and restore the remaining register 273 // from this new safe area. 274 275 // The restore area for the pc will be located at 1 word below the resultant sp. 276 // All restore values are located at offset <= PROBE_CPU_APSR_OFFSET. Hence, 277 // we need to make sure that resultant sp > offset of apsr + 1. 278 "add ip, sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_APSR_OFFSET + PTR_SIZE) "\n" 278 279 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_SP_OFFSET) "]" "\n" 279 280 "cmp lr, ip" "\n" … … 281 282 "bgt " SYMBOL_STRING(ctiMasmProbeTrampolineEnd) "\n" 282 283 283 // We get here because the new expected stack pointer location is lower 284 // than where it's supposed to be. This means the safe range of stack 285 // memory where we'll be copying the remaining register restore values to 286 // might be in a region of memory below the sp i.e. unallocated stack 287 // memory. This, in turn, makes it vulnerable to interrupts potentially 288 // trashing the copied values. To prevent that, we must first allocate the 289 // needed stack memory by adjusting the sp before the copying. 290 291 "sub lr, lr, #(6 * " STRINGIZE_VALUE_OF(PTR_SIZE) 292 " + " STRINGIZE_VALUE_OF(PROBE_CPU_IP_OFFSET) ")" "\n" 293 294 "mov ip, sp" "\n" 295 "mov sp, lr" "\n" 296 "mov lr, ip" "\n" 297 284 // Getting here means that the restore area will overlap the ProbeContext data 285 // that we will need to get the restoration values from. So, let's move that 286 // data to a safe place before we start writing into the restore area. 287 // Let's locate the "safe area" at 2x sizeof(ProbeContext) below where the 288 // restore area. This ensures that: 289 // 1. The safe area does not overlap the restore area. 290 // 2. The safe area does not overlap the ProbeContext. 291 // This makes it so that we can use memcpy (does not require memmove) semantics 292 // to copy the restore values to the safe area. 293 294 // lr already contains [sp, #STRINGIZE_VALUE_OF(PROBE_CPU_SP_OFFSET)]. 295 "sub lr, lr, #(2 * " STRINGIZE_VALUE_OF(PROBE_ALIGNED_SIZE) ")" "\n" 296 297 "mov ip, sp" "\n" // Save the original ProbeContext*. 298 299 // Make sure the stack pointer points to the safe area. This ensures that the 300 // safe area is protected from interrupt handlers overwriting it. 301 "mov sp, lr" "\n" // sp now points to the new ProbeContext in the safe area. 302 303 "mov lr, ip" "\n" // Use lr as the old ProbeContext*. 304 305 // Copy the restore data to the new ProbeContext*. 298 306 "ldr ip, [lr, #" STRINGIZE_VALUE_OF(PROBE_CPU_IP_OFFSET) "]" "\n" 299 307 "str ip, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_IP_OFFSET) "]" "\n" … … 307 315 "str ip, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_APSR_OFFSET) "]" "\n" 308 316 317 // ctiMasmProbeTrampolineEnd expects lr to contain the sp value to be restored. 318 // Since we used it as scratch above, let's restore it. 319 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_SP_OFFSET) "]" "\n" 320 309 321 ".thumb_func " THUMB_FUNC_PARAM(ctiMasmProbeTrampolineEnd) "\n" 310 322 SYMBOL_STRING(ctiMasmProbeTrampolineEnd) ":" "\n" 323 324 // Set up the restore area for sp and pc. 325 // lr already contains [sp, #STRINGIZE_VALUE_OF(PROBE_CPU_SP_OFFSET)]. 326 327 // Push the pc on to the restore area. 311 328 "ldr ip, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_PC_OFFSET) "]" "\n" 312 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_SP_OFFSET) "]" "\n"313 329 "sub lr, lr, #" STRINGIZE_VALUE_OF(PTR_SIZE) "\n" 314 330 "str ip, [lr]" "\n" 331 // Point sp to the restore area. 315 332 "str lr, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_SP_OFFSET) "]" "\n" 316 333 334 // All done with math i.e. won't trash the status register (apsr) and don't need 335 // scratch registers (lr and ip) anymore. Restore apsr, lr, and ip. 317 336 "ldr ip, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_APSR_OFFSET) "]" "\n" 318 337 "msr APSR, ip" "\n" 319 "ldr ip, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_LR_OFFSET) "]" "\n" 320 "mov lr, ip" "\n" 338 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_LR_OFFSET) "]" "\n" 321 339 "ldr ip, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_IP_OFFSET) "]" "\n" 340 341 // Restore the sp and pc. 322 342 "ldr sp, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_SP_OFFSET) "]" "\n" 323 324 343 "pop { pc }" "\n" 325 344 );
Note:
See TracChangeset
for help on using the changeset viewer.