Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -2191,7 +2191,16 @@ return Version; } +static bool isAlreadyAsanInstrumented(const Module &M) { + // Looks for a function inserted by the second (module) pass of + // ASAN, to detect modules fully ASAN instrumented. + return M.getFunction(kAsanPoisonGlobalsName) != nullptr; +} + bool AddressSanitizerModule::runOnModule(Module &M) { + // Skip modules which already have ASan instrumentation. + if (isAlreadyAsanInstrumented(M)) + return false; C = &(M.getContext()); int LongSize = M.getDataLayout().getPointerSizeInBits(); IntptrTy = Type::getIntNTy(*C, LongSize); @@ -2314,6 +2323,10 @@ // virtual bool AddressSanitizer::doInitialization(Module &M) { + // Skip modules which already have ASan instrumentation. + if (isAlreadyAsanInstrumented(M)) + return false; + // Initialize the private fields. No one has accessed them before. GlobalsMD.init(M); @@ -2405,6 +2418,9 @@ } bool AddressSanitizer::runOnFunction(Function &F) { + // Skip modules which already have ASan instrumentation. + if (isAlreadyAsanInstrumented(*F.getParent())) + return false; if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return false; if (!ClDebugFunc.empty() && ClDebugFunc == F.getName()) return false; if (F.getName().startswith("__asan_")) return false; Index: test/Instrumentation/AddressSanitizer/skip-previously-instrumented.ll =================================================================== --- /dev/null +++ test/Instrumentation/AddressSanitizer/skip-previously-instrumented.ll @@ -0,0 +1,177 @@ +; Test to ensure previously-instrumented IR is handled gracefully +; (ASAN skipped and not aborted). +; RUN: opt < %s -asan -asan-module -S | FileCheck %s +source_filename = "hello.c" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" +; Make sure that it compiled successfully +; CHECK: %call = call i32 (i8*, ...) @printf + +@.str = internal unnamed_addr constant { [13 x i8], [51 x i8] } { [13 x i8] c"hello world\0A\00", [51 x i8] zeroinitializer }, align 32 +@__asan_gen_ = private constant [8 x i8] c"hello.c\00", align 1 +@__asan_gen_.1 = private unnamed_addr constant [17 x i8] c"\00", align 1 +@__asan_gen_.2 = private unnamed_addr constant [8 x i8] c"hello.c\00", align 1 +@__asan_gen_.3 = private unnamed_addr constant { [8 x i8]*, i32, i32 } { [8 x i8]* @__asan_gen_.2, i32 5, i32 12 } +@0 = internal global [1 x { i64, i64, i64, i64, i64, i64, i64, i64 }] [{ i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint ({ [13 x i8], [51 x i8] }* @.str to i64), i64 13, i64 64, i64 ptrtoint ([17 x i8]* @__asan_gen_.1 to i64), i64 ptrtoint ([8 x i8]* @__asan_gen_ to i64), i64 0, i64 ptrtoint ({ [8 x i8]*, i32, i32 }* @__asan_gen_.3 to i64), i64 0 }] +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_ctor, i8* null }] +@llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_dtor, i8* null }] + +; Function Attrs: noinline nounwind optnone sanitize_address uwtable +define i32 @main() #0 { +entry: + %retval = alloca i32, align 4 + store i32 0, i32* %retval, align 4 + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ({ [13 x i8], [51 x i8] }, { [13 x i8], [51 x i8] }* @.str, i32 0, i32 0, i32 0)) + ret i32 0 +} + +declare i32 @printf(i8*, ...) #1 + +declare void @__asan_report_load_n(i64, i64) + +declare void @__asan_loadN(i64, i64) + +declare void @__asan_report_load1(i64) + +declare void @__asan_load1(i64) + +declare void @__asan_report_load2(i64) + +declare void @__asan_load2(i64) + +declare void @__asan_report_load4(i64) + +declare void @__asan_load4(i64) + +declare void @__asan_report_load8(i64) + +declare void @__asan_load8(i64) + +declare void @__asan_report_load16(i64) + +declare void @__asan_load16(i64) + +declare void @__asan_report_store_n(i64, i64) + +declare void @__asan_storeN(i64, i64) + +declare void @__asan_report_store1(i64) + +declare void @__asan_store1(i64) + +declare void @__asan_report_store2(i64) + +declare void @__asan_store2(i64) + +declare void @__asan_report_store4(i64) + +declare void @__asan_store4(i64) + +declare void @__asan_report_store8(i64) + +declare void @__asan_store8(i64) + +declare void @__asan_report_store16(i64) + +declare void @__asan_store16(i64) + +declare void @__asan_report_exp_load_n(i64, i64, i32) + +declare void @__asan_exp_loadN(i64, i64, i32) + +declare void @__asan_report_exp_load1(i64, i32) + +declare void @__asan_exp_load1(i64, i32) + +declare void @__asan_report_exp_load2(i64, i32) + +declare void @__asan_exp_load2(i64, i32) + +declare void @__asan_report_exp_load4(i64, i32) + +declare void @__asan_exp_load4(i64, i32) + +declare void @__asan_report_exp_load8(i64, i32) + +declare void @__asan_exp_load8(i64, i32) + +declare void @__asan_report_exp_load16(i64, i32) + +declare void @__asan_exp_load16(i64, i32) + +declare void @__asan_report_exp_store_n(i64, i64, i32) + +declare void @__asan_exp_storeN(i64, i64, i32) + +declare void @__asan_report_exp_store1(i64, i32) + +declare void @__asan_exp_store1(i64, i32) + +declare void @__asan_report_exp_store2(i64, i32) + +declare void @__asan_exp_store2(i64, i32) + +declare void @__asan_report_exp_store4(i64, i32) + +declare void @__asan_exp_store4(i64, i32) + +declare void @__asan_report_exp_store8(i64, i32) + +declare void @__asan_exp_store8(i64, i32) + +declare void @__asan_report_exp_store16(i64, i32) + +declare void @__asan_exp_store16(i64, i32) + +declare i8* @__asan_memmove(i8*, i8*, i64) + +declare i8* @__asan_memcpy(i8*, i8*, i64) + +declare i8* @__asan_memset(i8*, i32, i64) + +declare void @__asan_handle_no_return() + +declare void @__sanitizer_ptr_cmp(i64, i64) + +declare void @__sanitizer_ptr_sub(i64, i64) + +declare void @__asan_before_dynamic_init(i64) + +declare void @__asan_after_dynamic_init() + +declare void @__asan_register_globals(i64, i64) + +declare void @__asan_unregister_globals(i64, i64) + +declare void @__asan_register_image_globals(i64) + +declare void @__asan_unregister_image_globals(i64) + +declare void @__asan_register_elf_globals(i64, i64, i64) + +declare void @__asan_unregister_elf_globals(i64, i64, i64) + +declare void @__asan_init() + +define internal void @asan.module_ctor() { + call void @__asan_init() + call void @__asan_version_mismatch_check_v8() + call void @__asan_register_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1) + ret void +} + +declare void @__asan_version_mismatch_check_v8() + +define internal void @asan.module_dtor() { + call void @__asan_unregister_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1) + ret void +} + +!llvm.asan.globals = !{!0} +!llvm.module.flags = !{!2} +!llvm.ident = !{!3} + +!0 = !{[13 x i8]* getelementptr inbounds ({ [13 x i8], [51 x i8] }, { [13 x i8], [51 x i8] }* @.str, i32 0, i32 0), !1, !"", i1 false, i1 false} +!1 = !{!"hello.c", i32 5, i32 12} +!2 = !{i32 1, !"wchar_size", i32 4} +!3 = !{!"clang version 6.0.0 (trunk 320030) (llvm/trunk 320068)"}