Skip to content

Commit

Permalink
Port address sanitizer to LoongArch
Browse files Browse the repository at this point in the history
Depends on D129371.

It survived all GCC ASan tests.

Changes are trivial and mostly "borrowed" RISC-V logics, except that a different SHADOW_OFFSET is used.

Reviewed By: SixWeining, MaskRay, XiaodongLoong

Differential Revision: https://reviews.llvm.org/D129418
  • Loading branch information
xry111 authored and SixWeining committed Jul 21, 2022
1 parent 9c22853 commit bba1f26
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 3 deletions.
3 changes: 2 additions & 1 deletion compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
Expand Up @@ -27,7 +27,8 @@ set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64} ${RISCV64}
${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9}
${HEXAGON} ${LOONGARCH64})
set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON})
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
${LOONGARCH64})
set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})

if(ANDROID)
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/lib/asan/asan_interceptors_vfork.S
Expand Up @@ -6,6 +6,7 @@
#include "sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S"
#include "sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S"
#include "sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S"
#include "sanitizer_common/sanitizer_common_interceptors_vfork_loongarch64.inc.S"
#include "sanitizer_common/sanitizer_common_interceptors_vfork_riscv64.inc.S"
#include "sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S"
#endif
Expand Down
9 changes: 9 additions & 0 deletions compiler-rt/lib/asan/asan_mapping.h
Expand Up @@ -114,6 +114,13 @@
// || `[0x0080000000000, 0x008ffffffffff]` || LowShadow ||
// || `[0x0000000000000, 0x007ffffffffff]` || LowMem ||
//
// Default Linux/LoongArch64 (47-bit VMA) mapping:
// || `[0x500000000000, 0x7fffffffffff]` || HighMem ||
// || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow ||
// || `[0x480000000000, 0x49ffffffffff]` || ShadowGap ||
// || `[0x400000000000, 0x47ffffffffff]` || LowShadow ||
// || `[0x000000000000, 0x3fffffffffff]` || LowMem ||
//
// Shadow mapping on FreeBSD/x86-64 with SHADOW_OFFSET == 0x400000000000:
// || `[0x500000000000, 0x7fffffffffff]` || HighMem ||
// || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow ||
Expand Down Expand Up @@ -196,6 +203,8 @@
# define ASAN_SHADOW_OFFSET_CONST 0x0000002000000000
# elif defined(__sparc__)
# define ASAN_SHADOW_OFFSET_CONST 0x0000080000000000
# elif SANITIZER_LOONGARCH64
# define ASAN_SHADOW_OFFSET_CONST 0x0000400000000000
# elif SANITIZER_WINDOWS64
# define ASAN_SHADOW_OFFSET_DYNAMIC
# else
Expand Down
@@ -0,0 +1,63 @@
#if defined(__loongarch_lp64) && defined(__linux__)

#include "sanitizer_common/sanitizer_asm.h"

ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
ASM_HIDDEN(_ZN14__interception10real_vforkE)

.bss
.type _ZN14__interception10real_vforkE, @object
.size _ZN14__interception10real_vforkE, 8
_ZN14__interception10real_vforkE:
.zero 8

.text
.globl ASM_WRAPPER_NAME(vfork)
ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
ASM_WRAPPER_NAME(vfork):
// Save ra in the off-stack spill area.
// allocate space on stack
addi.d $sp, $sp, -16
// store $ra value
st.d $ra, $sp, 8
bl COMMON_INTERCEPTOR_SPILL_AREA
// restore previous values from stack
ld.d $ra, $sp, 8
// adjust stack
addi.d $sp, $sp, 16
// store $ra by $a0
st.d $ra, $a0, 0

// Call real vfork. This may return twice. User code that runs between the first and the second return
// may clobber the stack frame of the interceptor; that's why it does not have a frame.
la.local $a0, _ZN14__interception10real_vforkE
ld.d $a0, $a0, 0
jirl $ra, $a0, 0

// adjust stack
addi.d $sp, $sp, -16
// store $a0 by adjusted stack
st.d $a0, $sp, 8
// jump to exit label if $a0 is 0
beqz $a0, .L_exit

// $a0 != 0 => parent process. Clear stack shadow.
// put old $sp to $a0
addi.d $a0, $sp, 16
bl %plt(COMMON_INTERCEPTOR_HANDLE_VFORK)

.L_exit:
// Restore $ra
bl COMMON_INTERCEPTOR_SPILL_AREA
ld.d $ra, $a0, 0
// load value by stack
ld.d $a0, $sp, 8
// adjust stack
addi.d $sp, $sp, 16
jr $ra
ASM_SIZE(vfork)

.weak vfork
.set vfork, ASM_WRAPPER_NAME(vfork)

#endif
4 changes: 2 additions & 2 deletions compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp
Expand Up @@ -121,7 +121,7 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
uhwptr pc1 = caller_frame[2];
#elif defined(__s390__)
uhwptr pc1 = frame[14];
#elif defined(__riscv)
#elif defined(__loongarch__) || defined(__riscv)
// frame[-1] contains the return address
uhwptr pc1 = frame[-1];
#else
Expand All @@ -136,7 +136,7 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
trace_buffer[size++] = (uptr) pc1;
}
bottom = (uptr)frame;
#if defined(__riscv)
#if defined(__loongarch__) || defined(__riscv)
// frame[-2] contain fp of the previous frame
uptr new_bp = (uptr)frame[-2];
#else
Expand Down

0 comments on commit bba1f26

Please sign in to comment.