diff --git a/compiler-rt/include/sanitizer/hwasan_interface.h b/compiler-rt/include/sanitizer/hwasan_interface.h --- a/compiler-rt/include/sanitizer/hwasan_interface.h +++ b/compiler-rt/include/sanitizer/hwasan_interface.h @@ -50,6 +50,10 @@ // does would cause false reports. void __hwasan_handle_longjmp(const void *sp_dst); + // Set memory tag for the part of the current thread stack below sp_dst to + // zero. Call this in vfork() before returning in the parent process. + void __hwasan_handle_vfork(const void *sp_dst); + // Libc hook for thread creation. Should be called in the child thread before // any instrumented code. void __hwasan_thread_enter(); @@ -65,6 +69,10 @@ // Print one-line report about the memory usage of the current process. void __hwasan_print_memory_usage(); + /* Returns the offset of the first byte in the memory range that can not be + * accessed through the pointer in x, or -1 if the whole range is good. */ + intptr_t __hwasan_test_shadow(const volatile void *x, size_t size); + int __sanitizer_posix_memalign(void **memptr, size_t alignment, size_t size); void * __sanitizer_memalign(size_t alignment, size_t size); void * __sanitizer_aligned_alloc(size_t alignment, size_t size); diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt --- a/compiler-rt/lib/asan/CMakeLists.txt +++ b/compiler-rt/lib/asan/CMakeLists.txt @@ -32,6 +32,10 @@ asan_thread.cc asan_win.cc) +if (NOT WIN32) + list(APPEND ASAN_SOURCES asan_interceptors_vfork.S) +endif() + set(ASAN_CXX_SOURCES asan_new_delete.cc) diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc --- a/compiler-rt/lib/asan/asan_interceptors.cc +++ b/compiler-rt/lib/asan/asan_interceptors.cc @@ -579,6 +579,10 @@ } #endif // ASAN_INTERCEPT___CXA_ATEXIT +#if defined(__linux__) +DEFINE_REAL(void, vfork); +#endif + // ---------------------- InitializeAsanInterceptors ---------------- {{{1 namespace __asan { void InitializeAsanInterceptors() { @@ -656,6 +660,10 @@ ASAN_INTERCEPT_FUNC(__cxa_atexit); #endif +#if defined(__linux__) + __interception::GetRealFunctionAddress("vfork", (uptr *)&REAL(vfork), 0, 0); +#endif + InitializePlatformInterceptors(); VReport(1, "AddressSanitizer: libc interceptors initialized\n"); diff --git a/compiler-rt/lib/asan/asan_interceptors_vfork.S b/compiler-rt/lib/asan/asan_interceptors_vfork.S new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/asan/asan_interceptors_vfork.S @@ -0,0 +1,12 @@ +#include "sanitizer_common/sanitizer_asm.h" + +#if defined(__linux__) +#define COMMON_INTERCEPTOR_SPILL_AREA __asan_extra_spill_area +#define COMMON_INTERCEPTOR_HANDLE_VFORK __asan_handle_vfork +#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_x86_64.inc.S" +#include "sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S" +#endif + +NO_EXEC_STACK_DIRECTIVE diff --git a/compiler-rt/lib/asan/asan_interface.inc b/compiler-rt/lib/asan/asan_interface.inc --- a/compiler-rt/lib/asan/asan_interface.inc +++ b/compiler-rt/lib/asan/asan_interface.inc @@ -38,6 +38,7 @@ INTERFACE_FUNCTION(__asan_get_report_sp) INTERFACE_FUNCTION(__asan_get_shadow_mapping) INTERFACE_FUNCTION(__asan_handle_no_return) +INTERFACE_FUNCTION(__asan_handle_vfork) INTERFACE_FUNCTION(__asan_init) INTERFACE_FUNCTION(__asan_load_cxx_array_cookie) INTERFACE_FUNCTION(__asan_load1) diff --git a/compiler-rt/lib/asan/asan_interface_internal.h b/compiler-rt/lib/asan/asan_interface_internal.h --- a/compiler-rt/lib/asan/asan_interface_internal.h +++ b/compiler-rt/lib/asan/asan_interface_internal.h @@ -249,6 +249,8 @@ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char* __asan_default_suppressions(); + + SANITIZER_INTERFACE_ATTRIBUTE void __asan_handle_vfork(void *sp); } // extern "C" #endif // ASAN_INTERFACE_INTERNAL_H diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -597,6 +597,19 @@ curr_thread->fake_stack()->HandleNoReturn(); } +extern "C" void *__asan_extra_spill_area() { + AsanThread *t = GetCurrentThread(); + CHECK(t); + return t->extra_spill_area(); +} + +void __asan_handle_vfork(void *sp) { + AsanThread *t = GetCurrentThread(); + CHECK(t); + uptr bottom = t->stack_bottom(); + PoisonShadow(bottom, (uptr)sp - bottom, 0); +} + void NOINLINE __asan_set_death_callback(void (*callback)(void)) { SetUserDieCallback(callback); } diff --git a/compiler-rt/lib/asan/asan_thread.h b/compiler-rt/lib/asan/asan_thread.h --- a/compiler-rt/lib/asan/asan_thread.h +++ b/compiler-rt/lib/asan/asan_thread.h @@ -130,6 +130,8 @@ AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; } AsanStats &stats() { return stats_; } + void *extra_spill_area() { return &extra_spill_area_; } + private: // NOTE: There is no AsanThread constructor. It is allocated // via mmap() and *must* be valid in zero-initialized state. @@ -165,6 +167,7 @@ AsanThreadLocalMallocStorage malloc_storage_; AsanStats stats_; bool unwinding_; + uptr extra_spill_area_; }; // ScopedUnwinding is a scope for stacktracing member of a context diff --git a/compiler-rt/lib/hwasan/CMakeLists.txt b/compiler-rt/lib/hwasan/CMakeLists.txt --- a/compiler-rt/lib/hwasan/CMakeLists.txt +++ b/compiler-rt/lib/hwasan/CMakeLists.txt @@ -6,6 +6,7 @@ hwasan_allocator.cc hwasan_dynamic_shadow.cc hwasan_interceptors.cc + hwasan_interceptors_vfork.S hwasan_linux.cc hwasan_memintrinsics.cc hwasan_poisoning.cc diff --git a/compiler-rt/lib/hwasan/hwasan.cc b/compiler-rt/lib/hwasan/hwasan.cc --- a/compiler-rt/lib/hwasan/hwasan.cc +++ b/compiler-rt/lib/hwasan/hwasan.cc @@ -477,6 +477,30 @@ TagMemory(sp, dst - sp, 0); } +void __hwasan_handle_vfork(const void *sp_dst) { + uptr sp = (uptr)sp_dst; + Thread *t = GetCurrentThread(); + CHECK(t); + uptr top = t->stack_top(); + uptr bottom = t->stack_bottom(); + static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M + if (top == 0 || bottom == 0 || sp < bottom || sp >= top || + sp - bottom > kMaxExpectedCleanupSize) { + Report( + "WARNING: HWASan is ignoring requested __hwasan_handle_vfork: " + "stack top: %zx; current %zx; bottom: %zx \n" + "False positive error reports may follow\n", + top, sp, bottom); + return; + } + TagMemory(bottom, sp - bottom, 0); +} + +extern "C" void *__hwasan_extra_spill_area() { + Thread *t = GetCurrentThread(); + return &t->vfork_spill(); +} + void __hwasan_print_memory_usage() { InternalScopedString s(kMemoryUsageBufferSize); HwasanFormatMemoryUsage(s); diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cc b/compiler-rt/lib/hwasan/hwasan_interceptors.cc --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cc +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cc @@ -227,6 +227,10 @@ } #endif +#if HWASAN_WITH_INTERCEPTORS +DEFINE_REAL(void, vfork); +#endif + static void BeforeFork() { StackDepotLockAll(); } @@ -265,7 +269,8 @@ INTERCEPT_FUNCTION(fork); -#if HWASAN_WITH_INTERCEPTORS +#if HWASAN_WITH_INTERCEPTORS && defined(__linux__) + __interception::GetRealFunctionAddress("vfork", (uptr *)&REAL(vfork), 0, 0); #if !defined(__aarch64__) INTERCEPT_FUNCTION(pthread_create); #endif diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors_vfork.S b/compiler-rt/lib/hwasan/hwasan_interceptors_vfork.S new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/hwasan/hwasan_interceptors_vfork.S @@ -0,0 +1,10 @@ +#include "sanitizer_common/sanitizer_asm.h" + +#if defined(__linux__) +#define COMMON_INTERCEPTOR_SPILL_AREA __hwasan_extra_spill_area +#define COMMON_INTERCEPTOR_HANDLE_VFORK __hwasan_handle_vfork +#include "sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S" +#include "sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S" +#endif + +NO_EXEC_STACK_DIRECTIVE diff --git a/compiler-rt/lib/hwasan/hwasan_interface_internal.h b/compiler-rt/lib/hwasan/hwasan_interface_internal.h --- a/compiler-rt/lib/hwasan/hwasan_interface_internal.h +++ b/compiler-rt/lib/hwasan/hwasan_interface_internal.h @@ -116,6 +116,9 @@ SANITIZER_INTERFACE_ATTRIBUTE void __hwasan_handle_longjmp(const void *sp_dst); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_handle_vfork(const void *sp_dst); + SANITIZER_INTERFACE_ATTRIBUTE u16 __sanitizer_unaligned_load16(const uu16 *p); diff --git a/compiler-rt/lib/hwasan/hwasan_thread.h b/compiler-rt/lib/hwasan/hwasan_thread.h --- a/compiler-rt/lib/hwasan/hwasan_thread.h +++ b/compiler-rt/lib/hwasan/hwasan_thread.h @@ -67,11 +67,14 @@ Print("Thread: "); } + uptr &vfork_spill() { return vfork_spill_; } + private: // NOTE: There is no Thread constructor. It is allocated // via mmap() and *must* be valid in zero-initialized state. void ClearShadowForThreadStackAndTLS(); void Print(const char *prefix); + uptr vfork_spill_; uptr stack_top_; uptr stack_bottom_; uptr tls_begin_; diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt --- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt @@ -126,6 +126,7 @@ sanitizer_common_interceptors.inc sanitizer_common_interceptors_format.inc sanitizer_common_interceptors_ioctl.inc + sanitizer_common_interceptors_vfork_aarch64.inc.S sanitizer_common_interface.inc sanitizer_common_interface_posix.inc sanitizer_common_syscalls.inc diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_asm.h b/compiler-rt/lib/sanitizer_common/sanitizer_asm.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_asm.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_asm.h @@ -44,7 +44,7 @@ #if !defined(__APPLE__) # define ASM_HIDDEN(symbol) .hidden symbol -# define ASM_TYPE_FUNCTION(symbol) .type symbol, @function +# define ASM_TYPE_FUNCTION(symbol) .type symbol, %function # define ASM_SIZE(symbol) .size symbol, .-symbol # define ASM_SYMBOL(symbol) symbol # define ASM_SYMBOL_INTERCEPTOR(symbol) symbol diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S @@ -0,0 +1,43 @@ +#if defined(__aarch64__) && defined(__linux__) + +#include "sanitizer_common/sanitizer_asm.h" + +ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA) + +.comm _ZN14__interception10real_vforkE,8,8 +.globl ASM_SYMBOL_INTERCEPTOR(vfork) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(vfork)) +ASM_SYMBOL_INTERCEPTOR(vfork): + // Save x30 in the off-stack spill area. + stp xzr, x30, [sp, #-16]! + bl COMMON_INTERCEPTOR_SPILL_AREA + ldp xzr, x30, [sp], 16 + str x30, [x0] + + // 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. + adrp x0, _ZN14__interception10real_vforkE + ldr x0, [x0, :lo12:_ZN14__interception10real_vforkE] + blr x0 + + stp x0, xzr, [sp, #-16]! + cmp x0, #0 + b.eq .L_exit + + // x0 != 0 => parent process. Clear stack shadow. + add x0, sp, #16 + bl COMMON_INTERCEPTOR_HANDLE_VFORK + +.L_exit: + // Restore x30. + bl COMMON_INTERCEPTOR_SPILL_AREA + ldr x30, [x0] + ldp x0, xzr, [sp], 16 + + ret +ASM_SIZE(vfork) + +.globl __interceptor_vfork +.set __interceptor_vfork, ASM_SYMBOL_INTERCEPTOR(vfork) + +#endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S @@ -0,0 +1,49 @@ +#if defined(__arm__) && defined(__linux__) + +#include "sanitizer_common/sanitizer_asm.h" + +ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA) + +.comm _ZN14__interception10real_vforkE,4,4 +.globl ASM_SYMBOL_INTERCEPTOR(vfork) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(vfork)) +ASM_SYMBOL_INTERCEPTOR(vfork): + // Save LR in the off-stack spill area. + push {r4, lr} + bl COMMON_INTERCEPTOR_SPILL_AREA + pop {r4, lr} + str lr, [r0] + + // 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. + ldr r0, .LCPI0_0 +.LPC0_0: + ldr r0, [pc, r0] + mov lr, pc + bx r0 + + push {r0, r4} + cmp r0, #0 + beq .L_exit + + // r0 != 0 => parent process. Clear stack shadow. + add r0, sp, #8 + bl COMMON_INTERCEPTOR_HANDLE_VFORK + +.L_exit: + // Restore LR. + bl COMMON_INTERCEPTOR_SPILL_AREA + ldr lr, [r0] + pop {r0, r4} + + mov pc, lr + +.LCPI0_0: + .long _ZN14__interception10real_vforkE - (.LPC0_0+8) + +ASM_SIZE(vfork) + +.globl __interceptor_vfork +.set __interceptor_vfork, ASM_SYMBOL_INTERCEPTOR(vfork) + +#endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S @@ -0,0 +1,45 @@ +#if defined(__i386__) && defined(__linux__) + +#include "sanitizer_common/sanitizer_asm.h" + +.comm _ZN14__interception10real_vforkE,4,4 +.globl ASM_SYMBOL_INTERCEPTOR(vfork) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(vfork)) +ASM_SYMBOL_INTERCEPTOR(vfork): + // Store return address in the spill area and tear down the stack frame. + sub $12, %esp + call COMMON_INTERCEPTOR_SPILL_AREA + mov 12(%esp), %ecx + mov %ecx, (%eax) + add $16, %esp + + + call *_ZN14__interception10real_vforkE + + // Restore return address from the spill area. + sub $16, %esp + mov %eax, 4(%esp) + call COMMON_INTERCEPTOR_SPILL_AREA + mov (%eax), %ecx + mov %ecx, 12(%esp) + mov 4(%esp), %eax + + + // Call handle_vfork in the parent process (%rax != 0). + test %eax, %eax + je .L_exit + + lea 16(%esp), %ecx + mov %ecx, (%esp) + call COMMON_INTERCEPTOR_HANDLE_VFORK + +.L_exit: + mov 4(%esp), %eax + add $12, %esp + ret +ASM_SIZE(vfork) + +.globl __interceptor_vfork +.set __interceptor_vfork, ASM_SYMBOL_INTERCEPTOR(vfork) + +#endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S @@ -0,0 +1,41 @@ +#if defined(__x86_64__) && defined(__linux__) + +#include "sanitizer_common/sanitizer_asm.h" + +.comm _ZN14__interception10real_vforkE,8,8 +.globl ASM_SYMBOL_INTERCEPTOR(vfork) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(vfork)) +ASM_SYMBOL_INTERCEPTOR(vfork): + // Store return address in the spill area and tear down the stack frame. + push %rcx + call COMMON_INTERCEPTOR_SPILL_AREA + pop %rcx + pop %rdi + mov %rdi, (%rax) + + call *_ZN14__interception10real_vforkE(%rip) + + // Restore return address from the spill area. + push %rcx + push %rax + call COMMON_INTERCEPTOR_SPILL_AREA + mov (%rax), %rdx + mov %rdx, 8(%rsp) + mov (%rsp), %rax + + // Call handle_vfork in the parent process (%rax != 0). + test %rax, %rax + je .L_exit + + lea 16(%rsp), %rdi + call COMMON_INTERCEPTOR_HANDLE_VFORK + +.L_exit: + pop %rax + ret +ASM_SIZE(vfork) + +.globl __interceptor_vfork +.set __interceptor_vfork, ASM_SYMBOL_INTERCEPTOR(vfork) + +#endif diff --git a/compiler-rt/test/asan/CMakeLists.txt b/compiler-rt/test/asan/CMakeLists.txt --- a/compiler-rt/test/asan/CMakeLists.txt +++ b/compiler-rt/test/asan/CMakeLists.txt @@ -45,14 +45,8 @@ endif() foreach(arch ${ASAN_TEST_ARCH}) - if(ANDROID) - set(ASAN_TEST_TARGET_ARCH ${arch}-android) - else() - set(ASAN_TEST_TARGET_ARCH ${arch}) - endif() - + set(ASAN_TEST_TARGET_ARCH ${arch}) set(ASAN_TEST_APPLE_PLATFORM "osx") - string(TOLOWER "-${arch}-${OS_NAME}" ASAN_TEST_CONFIG_SUFFIX) get_bits_for_arch(${arch} ASAN_TEST_BITS) get_test_cc_for_arch(${arch} ASAN_TEST_TARGET_CC ASAN_TEST_TARGET_CFLAGS) diff --git a/compiler-rt/test/asan/TestCases/Linux/vfork.cc b/compiler-rt/test/asan/TestCases/Linux/vfork.cc new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Linux/vfork.cc @@ -0,0 +1,31 @@ +// https://github.com/google/sanitizers/issues/925 +// RUN: %clang_asan -O0 %s -o %t && %run %t 2>&1 + +// REQUIRES: aarch64-target-arch || x86_64-target-arch || i386-target-arch || arm-target-arch + +#include +#include +#include +#include +#include +#include + +__attribute__((noinline, no_sanitize("address"))) void child() { + alignas(8) char x[100000]; + __asan_poison_memory_region(x, sizeof(x)); + _exit(0); +} + +__attribute__((noinline, no_sanitize("address"))) void parent() { + alignas(8) char x[100000]; + assert(__asan_address_is_poisoned(x + 5000) == 0); +} + +int main(int argc, char **argv) { + if (vfork()) + parent(); + else + child(); + + return 0; +} diff --git a/compiler-rt/test/hwasan/TestCases/Linux/vfork.c b/compiler-rt/test/hwasan/TestCases/Linux/vfork.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/Linux/vfork.c @@ -0,0 +1,32 @@ +// https://github.com/google/sanitizers/issues/925 +// RUN: %clang_hwasan -O0 %s -o %t && %run %t 2>&1 + +// REQUIRES: aarch64-target-arch || x86_64-target-arch + +#include +#include +#include +#include +#include +#include + +__attribute__((noinline, no_sanitize("hwaddress"))) void child() { + char x[10000]; + __hwasan_tag_memory(x, 0xAA, sizeof(x)); + _exit(0); +} + +__attribute__((noinline, no_sanitize("hwaddress"))) void parent() { + char x[10000]; + __hwasan_print_shadow(&x, sizeof(x)); + assert(__hwasan_test_shadow(x, sizeof(x)) == -1); +} + +int main(int argc, char **argv) { + if (vfork()) + parent(); + else + child(); + + return 0; +} diff --git a/compiler-rt/test/scudo/CMakeLists.txt b/compiler-rt/test/scudo/CMakeLists.txt --- a/compiler-rt/test/scudo/CMakeLists.txt +++ b/compiler-rt/test/scudo/CMakeLists.txt @@ -15,15 +15,7 @@ set(SCUDO_TEST_ARCH ${SCUDO_SUPPORTED_ARCH}) foreach(arch ${SCUDO_TEST_ARCH}) - if(ANDROID) - if (${arch} STREQUAL "i386") - set(SCUDO_TEST_TARGET_ARCH i686-android) - else() - set(SCUDO_TEST_TARGET_ARCH ${arch}-android) - endif() - else() - set(SCUDO_TEST_TARGET_ARCH ${arch}) - endif() + set(SCUDO_TEST_TARGET_ARCH ${arch}) string(TOLOWER "-${arch}" SCUDO_TEST_CONFIG_SUFFIX) get_test_cc_for_arch(${arch} SCUDO_TEST_TARGET_CC SCUDO_TEST_TARGET_CFLAGS) string(TOUPPER ${arch} ARCH_UPPER_CASE) diff --git a/llvm/utils/gn/secondary/compiler-rt/lib/hwasan/BUILD.gn b/llvm/utils/gn/secondary/compiler-rt/lib/hwasan/BUILD.gn --- a/llvm/utils/gn/secondary/compiler-rt/lib/hwasan/BUILD.gn +++ b/llvm/utils/gn/secondary/compiler-rt/lib/hwasan/BUILD.gn @@ -44,6 +44,7 @@ "hwasan_dynamic_shadow.h", "hwasan_flags.h", "hwasan_interceptors.cc", + "hwasan_interceptors_vfork.S", "hwasan_interface_internal.h", "hwasan_linux.cc", "hwasan_malloc_bisect.h",