diff options
Diffstat (limited to 'chromium/v8/src/heap/base')
13 files changed, 760 insertions, 0 deletions
diff --git a/chromium/v8/src/heap/base/asm/arm/push_registers_asm.cc b/chromium/v8/src/heap/base/asm/arm/push_registers_asm.cc new file mode 100644 index 00000000000..5246c3f6c3e --- /dev/null +++ b/chromium/v8/src/heap/base/asm/arm/push_registers_asm.cc @@ -0,0 +1,39 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Push all callee-saved registers to get them on the stack for conservative +// stack scanning. +// +// See asm/x64/push_registers_clang.cc for why the function is not generated +// using clang. +// +// Do not depend on V8_TARGET_OS_* defines as some embedders may override the +// GN toolchain (e.g. ChromeOS) and not provide them. + +// We maintain 8-byte alignment at calls by pushing an additional +// non-callee-saved register (r3). +// +// Calling convention source: +// https://en.wikipedia.org/wiki/Calling_convention#ARM_(A32) +// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html +asm(".globl PushAllRegistersAndIterateStack \n" + ".type PushAllRegistersAndIterateStack, %function \n" + ".hidden PushAllRegistersAndIterateStack \n" + "PushAllRegistersAndIterateStack: \n" + // Push all callee-saved registers and save return address. + // Only {r4-r11} are callee-saved registers. Push r3 in addition to align + // the stack back to 8 bytes. + " push {r3-r11, lr} \n" + // Pass 1st parameter (r0) unchanged (Stack*). + // Pass 2nd parameter (r1) unchanged (StackVisitor*). + // Save 3rd parameter (r2; IterateStackCallback). + " mov r3, r2 \n" + // Pass 3rd parameter as sp (stack pointer). + " mov r2, sp \n" + // Call the callback. + " blx r3 \n" + // Discard all the registers. + " add sp, sp, #36 \n" + // Pop lr into pc which returns and switches mode if needed. + " pop {pc} \n"); diff --git a/chromium/v8/src/heap/base/asm/arm64/push_registers_asm.cc b/chromium/v8/src/heap/base/asm/arm64/push_registers_asm.cc new file mode 100644 index 00000000000..30d4de1f308 --- /dev/null +++ b/chromium/v8/src/heap/base/asm/arm64/push_registers_asm.cc @@ -0,0 +1,52 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Push all callee-saved registers to get them on the stack for conservative +// stack scanning. +// +// See asm/x64/push_registers_clang.cc for why the function is not generated +// using clang. +// +// Do not depend on V8_TARGET_OS_* defines as some embedders may override the +// GN toolchain (e.g. ChromeOS) and not provide them. + +// We maintain 16-byte alignment. +// +// Calling convention source: +// https://en.wikipedia.org/wiki/Calling_convention#ARM_(A64) + +asm( +#if defined(__APPLE__) + ".globl _PushAllRegistersAndIterateStack \n" + ".private_extern _PushAllRegistersAndIterateStack \n" + "_PushAllRegistersAndIterateStack: \n" +#else // !defined(__APPLE__) + ".globl PushAllRegistersAndIterateStack \n" +#if !defined(_WIN64) + ".type PushAllRegistersAndIterateStack, %function \n" + ".hidden PushAllRegistersAndIterateStack \n" +#endif // !defined(_WIN64) + "PushAllRegistersAndIterateStack: \n" +#endif // !defined(__APPLE__) + // x19-x29 are callee-saved. + " stp x19, x20, [sp, #-16]! \n" + " stp x21, x22, [sp, #-16]! \n" + " stp x23, x24, [sp, #-16]! \n" + " stp x25, x26, [sp, #-16]! \n" + " stp x27, x28, [sp, #-16]! \n" + " stp fp, lr, [sp, #-16]! \n" + // Maintain frame pointer. + " mov fp, sp \n" + // Pass 1st parameter (x0) unchanged (Stack*). + // Pass 2nd parameter (x1) unchanged (StackVisitor*). + // Save 3rd parameter (x2; IterateStackCallback) + " mov x7, x2 \n" + // Pass 3rd parameter as sp (stack pointer). + " mov x2, sp \n" + " blr x7 \n" + // Load return address. + " ldr lr, [sp, #8] \n" + // Restore frame pointer and pop all callee-saved registers. + " ldr fp, [sp], #96 \n" + " ret \n"); diff --git a/chromium/v8/src/heap/base/asm/arm64/push_registers_masm.S b/chromium/v8/src/heap/base/asm/arm64/push_registers_masm.S new file mode 100644 index 00000000000..9773654ffcf --- /dev/null +++ b/chromium/v8/src/heap/base/asm/arm64/push_registers_masm.S @@ -0,0 +1,32 @@ +; Copyright 2020 the V8 project authors. All rights reserved. +; Use of this source code is governed by a BSD-style license that can be +; found in the LICENSE file. + +; This file is exactly the same as push_registers_asm.cc, just formatted for +; the Microsoft Arm Assembler. + + AREA |.text|, CODE, ALIGN=4, READONLY + EXPORT PushAllRegistersAndIterateStack +PushAllRegistersAndIterateStack + ; x19-x29 are callee-saved + STP x19, x20, [sp, #-16]! + STP x21, x22, [sp, #-16]! + STP x23, x24, [sp, #-16]! + STP x25, x26, [sp, #-16]! + STP x27, x28, [sp, #-16]! + STP fp, lr, [sp, #-16]! + ; Maintain frame pointer + MOV fp, sp + ; Pass 1st parameter (x0) unchanged (Stack*). + ; Pass 2nd parameter (x1) unchanged (StackVisitor*). + ; Save 3rd parameter (x2; IterateStackCallback) + MOV x7, x2 + ; Pass 3rd parameter as sp (stack pointer) + MOV x2, sp + BLR x7 + ; Load return address + LDR lr, [sp, #8] + ; Restore frame pointer and pop all callee-saved registers. + LDR fp, [sp], #96 + RET + END
\ No newline at end of file diff --git a/chromium/v8/src/heap/base/asm/ia32/push_registers_asm.cc b/chromium/v8/src/heap/base/asm/ia32/push_registers_asm.cc new file mode 100644 index 00000000000..ed9c14a50e9 --- /dev/null +++ b/chromium/v8/src/heap/base/asm/ia32/push_registers_asm.cc @@ -0,0 +1,53 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Push all callee-saved registers to get them on the stack for conservative +// stack scanning. +// +// See asm/x64/push_registers_clang.cc for why the function is not generated +// using clang. +// +// Do not depend on V8_TARGET_OS_* defines as some embedders may override the +// GN toolchain (e.g. ChromeOS) and not provide them. + +// We maintain 16-byte alignment at calls. There is an 4-byte return address +// on the stack and we push 28 bytes which maintains 16-byte stack alignment +// at the call. +// +// The following assumes cdecl calling convention. +// Source: https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl +asm( +#ifdef _WIN32 + ".globl _PushAllRegistersAndIterateStack \n" + "_PushAllRegistersAndIterateStack: \n" +#else // !_WIN32 + ".globl PushAllRegistersAndIterateStack \n" + ".type PushAllRegistersAndIterateStack, %function \n" + ".hidden PushAllRegistersAndIterateStack \n" + "PushAllRegistersAndIterateStack: \n" +#endif // !_WIN32 + // [ IterateStackCallback ] + // [ StackVisitor* ] + // [ Stack* ] + // [ ret ] + // ebp is callee-saved. Maintain proper frame pointer for debugging. + " push %ebp \n" + " movl %esp, %ebp \n" + " push %ebx \n" + " push %esi \n" + " push %edi \n" + // Save 3rd parameter (IterateStackCallback). + " movl 28(%esp), %ecx \n" + // Pass 3rd parameter as esp (stack pointer). + " push %esp \n" + // Pass 2nd parameter (StackVisitor*). + " push 28(%esp) \n" + // Pass 1st parameter (Stack*). + " push 28(%esp) \n" + " call *%ecx \n" + // Pop the callee-saved registers. + " addl $24, %esp \n" + // Restore rbp as it was used as frame pointer. + " pop %ebp \n" + " ret \n"); diff --git a/chromium/v8/src/heap/base/asm/ia32/push_registers_masm.S b/chromium/v8/src/heap/base/asm/ia32/push_registers_masm.S new file mode 100644 index 00000000000..a35fd6e527d --- /dev/null +++ b/chromium/v8/src/heap/base/asm/ia32/push_registers_masm.S @@ -0,0 +1,48 @@ +;; Copyright 2020 the V8 project authors. All rights reserved. +;; Use of this source code is governed by a BSD-style license that can be +;; found in the LICENSE file. + +;; MASM syntax +;; https://docs.microsoft.com/en-us/cpp/assembler/masm/microsoft-macro-assembler-reference?view=vs-2019 + +.model flat, C + +public PushAllRegistersAndIterateStack + +.code +PushAllRegistersAndIterateStack: + ;; Push all callee-saved registers to get them on the stack for conservative + ;; stack scanning. + ;; + ;; We maintain 16-byte alignment at calls. There is an 8-byte return address + ;; on the stack and we push 72 bytes which maintains 16-byte stack alignment + ;; at the call. + ;; + ;; The following assumes cdecl calling convention. + ;; Source: https://docs.microsoft.com/en-us/cpp/cpp/cdecl?view=vs-2019 + ;; + ;; [ IterateStackCallback ] + ;; [ StackVisitor* ] + ;; [ Stack* ] + ;; [ ret ] + push ebp + mov ebp, esp + push ebx + push esi + push edi + ;; Save 3rd parameter (IterateStackCallback). + mov ecx, [ esp + 28 ] + ;; Pass 3rd parameter as esp (stack pointer). + push esp + ;; Pass 2nd parameter (StackVisitor*). + push [ esp + 28 ] + ;; Pass 1st parameter (Stack*). + push [ esp + 28 ] + call ecx + ;; Pop the callee-saved registers. + add esp, 24 + ;; Restore rbp as it was used as frame pointer. + pop ebp + ret + +end diff --git a/chromium/v8/src/heap/base/asm/mips/push_registers_asm.cc b/chromium/v8/src/heap/base/asm/mips/push_registers_asm.cc new file mode 100644 index 00000000000..4a46caa6c52 --- /dev/null +++ b/chromium/v8/src/heap/base/asm/mips/push_registers_asm.cc @@ -0,0 +1,48 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Push all callee-saved registers to get them on the stack for conservative +// stack scanning. +// +// See asm/x64/push_registers_clang.cc for why the function is not generated +// using clang. +// +// Do not depend on V8_TARGET_OS_* defines as some embedders may override the +// GN toolchain (e.g. ChromeOS) and not provide them. +asm(".set noreorder \n" + ".global PushAllRegistersAndIterateStack \n" + ".type PushAllRegistersAndIterateStack, %function \n" + ".hidden PushAllRegistersAndIterateStack \n" + "PushAllRegistersAndIterateStack: \n" + // Push all callee-saved registers and save return address. + " addiu $sp, $sp, -48 \n" + " sw $ra, 44($sp) \n" + " sw $s8, 40($sp) \n" + " sw $sp, 36($sp) \n" + " sw $gp, 32($sp) \n" + " sw $s7, 28($sp) \n" + " sw $s6, 24($sp) \n" + " sw $s5, 20($sp) \n" + " sw $s4, 16($sp) \n" + " sw $s3, 12($sp) \n" + " sw $s2, 8($sp) \n" + " sw $s1, 4($sp) \n" + " sw $s0, 0($sp) \n" + // Maintain frame pointer. + " move $s8, $sp \n" + // Pass 1st parameter (a0) unchanged (Stack*). + // Pass 2nd parameter (a1) unchanged (StackVisitor*). + // Save 3rd parameter (a2; IterateStackCallback). + " move $a3, $a2 \n" + // Call the callback. + " jalr $a3 \n" + // Delay slot: Pass 3rd parameter as sp (stack pointer). + " move $a2, $sp \n" + // Load return address. + " lw $ra, 44($sp) \n" + // Restore frame pointer. + " lw $s8, 40($sp) \n" + " jr $ra \n" + // Delay slot: Discard all callee-saved registers. + " addiu $sp, $sp, 48 \n"); diff --git a/chromium/v8/src/heap/base/asm/mips64/push_registers_asm.cc b/chromium/v8/src/heap/base/asm/mips64/push_registers_asm.cc new file mode 100644 index 00000000000..6befa3bcc0c --- /dev/null +++ b/chromium/v8/src/heap/base/asm/mips64/push_registers_asm.cc @@ -0,0 +1,48 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Push all callee-saved registers to get them on the stack for conservative +// stack scanning. +// +// See asm/x64/push_registers_clang.cc for why the function is not generated +// using clang. +// +// Do not depend on V8_TARGET_OS_* defines as some embedders may override the +// GN toolchain (e.g. ChromeOS) and not provide them. +asm(".set noreorder \n" + ".global PushAllRegistersAndIterateStack \n" + ".type PushAllRegistersAndIterateStack, %function \n" + ".hidden PushAllRegistersAndIterateStack \n" + "PushAllRegistersAndIterateStack: \n" + // Push all callee-saved registers and save return address. + " daddiu $sp, $sp, -96 \n" + " sd $ra, 88($sp) \n" + " sd $s8, 80($sp) \n" + " sd $sp, 72($sp) \n" + " sd $gp, 64($sp) \n" + " sd $s7, 56($sp) \n" + " sd $s6, 48($sp) \n" + " sd $s5, 40($sp) \n" + " sd $s4, 32($sp) \n" + " sd $s3, 24($sp) \n" + " sd $s2, 16($sp) \n" + " sd $s1, 8($sp) \n" + " sd $s0, 0($sp) \n" + // Maintain frame pointer. + " move $s8, $sp \n" + // Pass 1st parameter (a0) unchanged (Stack*). + // Pass 2nd parameter (a1) unchanged (StackVisitor*). + // Save 3rd parameter (a2; IterateStackCallback). + " move $a3, $a2 \n" + // Call the callback. + " jalr $a3 \n" + // Delay slot: Pass 3rd parameter as sp (stack pointer). + " move $a2, $sp \n" + // Load return address. + " ld $ra, 88($sp) \n" + // Restore frame pointer. + " ld $s8, 80($sp) \n" + " jr $ra \n" + // Delay slot: Discard all callee-saved registers. + " daddiu $sp, $sp, 96 \n"); diff --git a/chromium/v8/src/heap/base/asm/ppc/push_registers_asm.cc b/chromium/v8/src/heap/base/asm/ppc/push_registers_asm.cc new file mode 100644 index 00000000000..6936819ba2b --- /dev/null +++ b/chromium/v8/src/heap/base/asm/ppc/push_registers_asm.cc @@ -0,0 +1,94 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Push all callee-saved registers to get them on the stack for conservative +// stack scanning. +// +// See asm/x64/push_registers_clang.cc for why the function is not generated +// using clang. + +// Do not depend on V8_TARGET_OS_* defines as some embedders may override the +// GN toolchain (e.g. ChromeOS) and not provide them. + +// PPC ABI source: +// http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html + +// AIX Runtime process stack: +// https://www.ibm.com/support/knowledgecenter/ssw_aix_71/assembler/idalangref_runtime_process.html +asm( +#if defined(_AIX) + ".globl .PushAllRegistersAndIterateStack, hidden \n" + ".csect .text[PR] \n" + ".PushAllRegistersAndIterateStack: \n" +#else + ".globl PushAllRegistersAndIterateStack \n" + ".type PushAllRegistersAndIterateStack, %function \n" + ".hidden PushAllRegistersAndIterateStack \n" + "PushAllRegistersAndIterateStack: \n" +#endif + // Push all callee-saved registers. + // lr, TOC pointer, r16 to r31. 160 bytes. + // The parameter save area shall be allocated by the caller. 112 btes. + // At anytime, SP (r1) needs to be multiple of 16 (i.e. 16-aligned). + " mflr 0 \n" + " std 0, 16(1) \n" +#if defined(_AIX) + " std 2, 40(1) \n" +#else + " std 2, 24(1) \n" +#endif + " stdu 1, -256(1) \n" + " std 14, 112(1) \n" + " std 15, 120(1) \n" + " std 16, 128(1) \n" + " std 17, 136(1) \n" + " std 18, 144(1) \n" + " std 19, 152(1) \n" + " std 20, 160(1) \n" + " std 21, 168(1) \n" + " std 22, 176(1) \n" + " std 23, 184(1) \n" + " std 24, 192(1) \n" + " std 25, 200(1) \n" + " std 26, 208(1) \n" + " std 27, 216(1) \n" + " std 28, 224(1) \n" + " std 29, 232(1) \n" + " std 30, 240(1) \n" + " std 31, 248(1) \n" + // Pass 1st parameter (r3) unchanged (Stack*). + // Pass 2nd parameter (r4) unchanged (StackVisitor*). + // Save 3rd parameter (r5; IterateStackCallback). + " mr 6, 5 \n" +#if defined(_AIX) + // Set up TOC for callee. + " ld 2,8(5) \n" + // AIX uses function decorators, which means that + // pointers to functions do not point to code, but + // instead point to metadata about them, hence + // need to deterrence. + " ld 6,0(6) \n" +#endif + // Pass 3rd parameter as sp (stack pointer). + " mr 5, 1 \n" +#if !defined(_AIX) + // Set up r12 to be equal to the callee address (in order for TOC + // relocation). Only needed on LE Linux. + " mr 12, 6 \n" +#endif + // Call the callback. + " mtctr 6 \n" + " bctrl \n" + // Discard all the registers. + " addi 1, 1, 256 \n" + // Restore lr. + " ld 0, 16(1) \n" + " mtlr 0 \n" +#if defined(_AIX) + // Restore TOC pointer. + " ld 2, 40(1) \n" +#else + " ld 2, 24(1) \n" +#endif + " blr \n"); diff --git a/chromium/v8/src/heap/base/asm/s390/push_registers_asm.cc b/chromium/v8/src/heap/base/asm/s390/push_registers_asm.cc new file mode 100644 index 00000000000..6b9b2c08536 --- /dev/null +++ b/chromium/v8/src/heap/base/asm/s390/push_registers_asm.cc @@ -0,0 +1,35 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Push all callee-saved registers to get them on the stack for conservative +// stack scanning. + +// See asm/x64/push_registers_clang.cc for why the function is not generated +// using clang. + +// Do not depend on V8_TARGET_OS_* defines as some embedders may override the +// GN toolchain (e.g. ChromeOS) and not provide them. + +// S390 ABI source: +// http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html +asm(".globl PushAllRegistersAndIterateStack \n" + ".type PushAllRegistersAndIterateStack, %function \n" + ".hidden PushAllRegistersAndIterateStack \n" + "PushAllRegistersAndIterateStack: \n" + // Push all callee-saved registers. + // r6-r13, r14 and sp(r15) + " stmg %r6, %sp, 48(%sp) \n" + // Allocate frame. + " lay %sp, -160(%sp) \n" + // Pass 1st parameter (r2) unchanged (Stack*). + // Pass 2nd parameter (r3) unchanged (StackVisitor*). + // Save 3rd parameter (r4; IterateStackCallback). + " lgr %r5, %r4 \n" + // Pass sp as 3rd parameter. 160+48 to point + // to callee saved region stored above. + " lay %r4, 208(%sp) \n" + // Call the callback. + " basr %r14, %r5 \n" + " lmg %r14,%sp, 272(%sp) \n" + " br %r14 \n"); diff --git a/chromium/v8/src/heap/base/asm/x64/push_registers_asm.cc b/chromium/v8/src/heap/base/asm/x64/push_registers_asm.cc new file mode 100644 index 00000000000..68f7918c93c --- /dev/null +++ b/chromium/v8/src/heap/base/asm/x64/push_registers_asm.cc @@ -0,0 +1,94 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Push all callee-saved registers to get them on the stack for conservative +// stack scanning. +// +// We cannot rely on clang generating the function and right symbol mangling +// as `__attribite__((naked))` does not prevent clang from generating TSAN +// function entry stubs (`__tsan_func_entry`). Even with +// `__attribute__((no_sanitize_thread)` annotation clang generates the entry +// stub. +// See https://bugs.llvm.org/show_bug.cgi?id=45400. + +// Do not depend on V8_TARGET_OS_* defines as some embedders may override the +// GN toolchain (e.g. ChromeOS) and not provide them. +// _WIN64 Defined as 1 when the compilation target is 64-bit ARM or x64. +// Otherwise, undefined. +#ifdef _WIN64 + +// We maintain 16-byte alignment at calls. There is an 8-byte return address +// on the stack and we push 72 bytes which maintains 16-byte stack alignment +// at the call. +// Source: https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention +asm(".globl PushAllRegistersAndIterateStack \n" + "PushAllRegistersAndIterateStack: \n" + // rbp is callee-saved. Maintain proper frame pointer for debugging. + " push %rbp \n" + " mov %rsp, %rbp \n" + // Dummy for alignment. + " push $0xCDCDCD \n" + " push %rsi \n" + " push %rdi \n" + " push %rbx \n" + " push %r12 \n" + " push %r13 \n" + " push %r14 \n" + " push %r15 \n" + // Pass 1st parameter (rcx) unchanged (Stack*). + // Pass 2nd parameter (rdx) unchanged (StackVisitor*). + // Save 3rd parameter (r8; IterateStackCallback) + " mov %r8, %r9 \n" + // Pass 3rd parameter as rsp (stack pointer). + " mov %rsp, %r8 \n" + // Call the callback. + " call *%r9 \n" + // Pop the callee-saved registers. + " add $64, %rsp \n" + // Restore rbp as it was used as frame pointer. + " pop %rbp \n" + " ret \n"); + +#else // !_WIN64 + +// We maintain 16-byte alignment at calls. There is an 8-byte return address +// on the stack and we push 56 bytes which maintains 16-byte stack alignment +// at the call. +// Source: https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf +asm( +#ifdef __APPLE__ + ".globl _PushAllRegistersAndIterateStack \n" + ".private_extern _PushAllRegistersAndIterateStack \n" + "_PushAllRegistersAndIterateStack: \n" +#else // !__APPLE__ + ".globl PushAllRegistersAndIterateStack \n" + ".type PushAllRegistersAndIterateStack, %function \n" + ".hidden PushAllRegistersAndIterateStack \n" + "PushAllRegistersAndIterateStack: \n" +#endif // !__APPLE__ + // rbp is callee-saved. Maintain proper frame pointer for debugging. + " push %rbp \n" + " mov %rsp, %rbp \n" + // Dummy for alignment. + " push $0xCDCDCD \n" + " push %rbx \n" + " push %r12 \n" + " push %r13 \n" + " push %r14 \n" + " push %r15 \n" + // Pass 1st parameter (rdi) unchanged (Stack*). + // Pass 2nd parameter (rsi) unchanged (StackVisitor*). + // Save 3rd parameter (rdx; IterateStackCallback) + " mov %rdx, %r8 \n" + // Pass 3rd parameter as rsp (stack pointer). + " mov %rsp, %rdx \n" + // Call the callback. + " call *%r8 \n" + // Pop the callee-saved registers. + " add $48, %rsp \n" + // Restore rbp as it was used as frame pointer. + " pop %rbp \n" + " ret \n"); + +#endif // !_WIN64 diff --git a/chromium/v8/src/heap/base/asm/x64/push_registers_masm.S b/chromium/v8/src/heap/base/asm/x64/push_registers_masm.S new file mode 100644 index 00000000000..627843830fa --- /dev/null +++ b/chromium/v8/src/heap/base/asm/x64/push_registers_masm.S @@ -0,0 +1,45 @@ +;; Copyright 2020 the V8 project authors. All rights reserved. +;; Use of this source code is governed by a BSD-style license that can be +;; found in the LICENSE file. + +;; MASM syntax +;; https://docs.microsoft.com/en-us/cpp/assembler/masm/microsoft-macro-assembler-reference?view=vs-2019 + +public PushAllRegistersAndIterateStack + +.code +PushAllRegistersAndIterateStack: + ;; Push all callee-saved registers to get them on the stack for conservative + ;; stack scanning. + ;; + ;; We maintain 16-byte alignment at calls. There is an 8-byte return address + ;; on the stack and we push 72 bytes which maintains 16-byte stack alignment + ;; at the call. + ;; Source: https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention + ;; + ;; rbp is callee-saved. Maintain proper frame pointer for debugging. + push rbp + mov rbp, rsp + push 0CDCDCDh ;; Dummy for alignment. + push rsi + push rdi + push rbx + push r12 + push r13 + push r14 + push r15 + ;; Pass 1st parameter (rcx) unchanged (Stack*). + ;; Pass 2nd parameter (rdx) unchanged (StackVisitor*). + ;; Save 3rd parameter (r8; IterateStackCallback) + mov r9, r8 + ;; Pass 3rd parameter as rsp (stack pointer). + mov r8, rsp + ;; Call the callback. + call r9 + ;; Pop the callee-saved registers. + add rsp, 64 + ;; Restore rbp as it was used as frame pointer. + pop rbp + ret + +end diff --git a/chromium/v8/src/heap/base/stack.cc b/chromium/v8/src/heap/base/stack.cc new file mode 100644 index 00000000000..cd284444747 --- /dev/null +++ b/chromium/v8/src/heap/base/stack.cc @@ -0,0 +1,129 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/heap/base/stack.h" + +#include <limits> + +#include "src/base/platform/platform.h" +#include "src/heap/cppgc/globals.h" +#include "src/heap/cppgc/sanitizers.h" + +namespace heap { +namespace base { + +using IterateStackCallback = void (*)(const Stack*, StackVisitor*, intptr_t*); +extern "C" void PushAllRegistersAndIterateStack(const Stack*, StackVisitor*, + IterateStackCallback); + +Stack::Stack(const void* stack_start) : stack_start_(stack_start) {} + +bool Stack::IsOnStack(void* slot) const { + void* raw_slot = v8::base::Stack::GetStackSlot(slot); + return v8::base::Stack::GetCurrentStackPosition() <= raw_slot && + raw_slot <= stack_start_; +} + +namespace { + +#ifdef V8_USE_ADDRESS_SANITIZER + +// No ASAN support as accessing fake frames otherwise results in +// "stack-use-after-scope" warnings. +NO_SANITIZE_ADDRESS +void IterateAsanFakeFrameIfNecessary(StackVisitor* visitor, + void* asan_fake_stack, + const void* stack_start, + const void* stack_end, void* address) { + // When using ASAN fake stack a pointer to the fake frame is kept on the + // native frame. In case |addr| points to a fake frame of the current stack + // iterate the fake frame. Frame layout see + // https://github.com/google/sanitizers/wiki/AddressSanitizerUseAfterReturn + if (asan_fake_stack) { + void* fake_frame_begin; + void* fake_frame_end; + void* real_stack_frame = __asan_addr_is_in_fake_stack( + asan_fake_stack, address, &fake_frame_begin, &fake_frame_end); + if (real_stack_frame) { + // |address| points to a fake frame. Check that the fake frame is part + // of this stack. + if (stack_start >= real_stack_frame && real_stack_frame >= stack_end) { + // Iterate the fake frame. + for (void** current = reinterpret_cast<void**>(fake_frame_begin); + current < fake_frame_end; ++current) { + void* addr = *current; + if (addr == nullptr) continue; + visitor->VisitPointer(addr); + } + } + } + } +} + +#endif // V8_USE_ADDRESS_SANITIZER + +void IterateSafeStackIfNecessary(StackVisitor* visitor) { +#if defined(__has_feature) +#if __has_feature(safe_stack) + // Source: + // https://github.com/llvm/llvm-project/blob/master/compiler-rt/lib/safestack/safestack.cpp + constexpr size_t kSafeStackAlignmentBytes = 16; + void* stack_end = __builtin___get_unsafe_stack_ptr(); + void* stack_start = __builtin___get_unsafe_stack_top(); + CHECK_GT(stack_start, stack_end); + CHECK_EQ(0u, reinterpret_cast<uintptr_t>(stack_end) & + (kSafeStackAlignmentBytes - 1)); + CHECK_EQ(0u, reinterpret_cast<uintptr_t>(stack_start) & + (kSafeStackAlignmentBytes - 1)); + void** current = reinterpret_cast<void**>(stack_end); + for (; current < stack_start; ++current) { + void* address = *current; + if (address == nullptr) continue; + visitor->VisitPointer(address); + } +#endif // __has_feature(safe_stack) +#endif // defined(__has_feature) +} + +// Called by the trampoline that pushes registers on the stack. This method +// should never be inlined to ensure that a possible redzone cannot contain +// any data that needs to be scanned. +V8_NOINLINE +// No ASAN support as method accesses redzones while walking the stack. +NO_SANITIZE_ADDRESS +void IteratePointersImpl(const Stack* stack, StackVisitor* visitor, + intptr_t* stack_end) { +#ifdef V8_USE_ADDRESS_SANITIZER + void* asan_fake_stack = __asan_get_current_fake_stack(); +#endif // V8_USE_ADDRESS_SANITIZER + // All supported platforms should have their stack aligned to at least + // sizeof(void*). + constexpr size_t kMinStackAlignment = sizeof(void*); + void** current = reinterpret_cast<void**>(stack_end); + CHECK_EQ(0u, reinterpret_cast<uintptr_t>(current) & (kMinStackAlignment - 1)); + for (; current < stack->stack_start(); ++current) { + // MSAN: Instead of unpoisoning the whole stack, the slot's value is copied + // into a local which is unpoisoned. + void* address = *current; + MSAN_UNPOISON(&address, sizeof(address)); + if (address == nullptr) continue; + visitor->VisitPointer(address); +#ifdef V8_USE_ADDRESS_SANITIZER + IterateAsanFakeFrameIfNecessary(visitor, asan_fake_stack, + stack->stack_start(), stack_end, address); +#endif // V8_USE_ADDRESS_SANITIZER + } +} + +} // namespace + +void Stack::IteratePointers(StackVisitor* visitor) const { + PushAllRegistersAndIterateStack(this, visitor, &IteratePointersImpl); + // No need to deal with callee-saved registers as they will be kept alive by + // the regular conservative stack iteration. + IterateSafeStackIfNecessary(visitor); +} + +} // namespace base +} // namespace heap diff --git a/chromium/v8/src/heap/base/stack.h b/chromium/v8/src/heap/base/stack.h new file mode 100644 index 00000000000..a46e6e660ed --- /dev/null +++ b/chromium/v8/src/heap/base/stack.h @@ -0,0 +1,43 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_HEAP_BASE_STACK_H_ +#define V8_HEAP_BASE_STACK_H_ + +#include "src/base/macros.h" + +namespace heap { +namespace base { + +class StackVisitor { + public: + virtual void VisitPointer(const void* address) = 0; +}; + +// Abstraction over the stack. Supports handling of: +// - native stack; +// - ASAN/MSAN; +// - SafeStack: https://releases.llvm.org/10.0.0/tools/clang/docs/SafeStack.html +class V8_EXPORT_PRIVATE Stack final { + public: + explicit Stack(const void* stack_start); + + // Returns true if |slot| is part of the stack and false otherwise. + bool IsOnStack(void* slot) const; + + // Word-aligned iteration of the stack. Slot values are passed on to + // |visitor|. + void IteratePointers(StackVisitor* visitor) const; + + // Returns the start of the stack. + const void* stack_start() const { return stack_start_; } + + private: + const void* stack_start_; +}; + +} // namespace base +} // namespace heap + +#endif // V8_HEAP_BASE_STACK_H_ |
