[llvm-dev] How does -fsanitize=address work under the hood?

Mitch Phillips via llvm-dev llvm-dev at lists.llvm.org
Tue Apr 13 08:52:16 PDT 2021


We also have a Wiki page explaining the basics of the algorithm:
https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm

On Tue, Apr 13, 2021 at 8:18 AM Victor Campos via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> I recommend reading Address Sanitizer's paper:
>
> https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37752.pdf
>
> It's an easy and quite interesting read.
>
> Cheers,
> Victor.
>
> On Tue, 13 Apr 2021, at 15:42, Peng Yu via llvm-dev wrote:
> > Hi,
> >
> > I am trying to see what -fsanitize=address does using the following
> > example. I see a number of _asan function and variables. But it is
> > still not clear how the original program is transformed so that memory
> > error will be catched. Could anybody help explain how it works?
> > Thanks.
> >
> > Also, many functions (like __asan_report_load16) are not used. Why are
> > they declared? Thanks.
> >
> > $ diff <(clang -Wno-array-bounds -S -emit-llvm -x c -o - - <<< 'int
> > main() { int a[2] = {1, 0}; int b=a[2]; return 0; }') <(clang
> > -Wno-array-bounds -fsanitize=address -S -emit-llvm -x c -o - -<<< 'int
> > main() { int a[2] = {1, 0}; int b=a[2]; return 0; }')
> > < @__const.main.a = private unnamed_addr constant [2 x i32] [i32 1,
> > i32 0], align 4
> > < ; Function Attrs: noinline nounwind optnone ssp uwtable
> > ---
> > > @__const.main.a = internal constant { [2 x i32], [56 x i8] } { [2 x
> i32] [i32 1, i32 0], [56 x i8] zeroinitializer }, align 32
> > > @__asan_option_detect_stack_use_after_return = external global i32
> > > @___asan_gen_ = private unnamed_addr constant [11 x i8] c"1 32 8 1
> a\00", align 1
> > > @___asan_gen_.1 = private constant [2 x i8] c"-\00", align 1
> > > @___asan_gen_.2 = private unnamed_addr constant [15 x i8]
> c"__const.main.a\00", align 1
> > > @__asan_global___const.main.a = internal global { i64, i64, i64, i64,
> i64, i64, i64, i64 } { i64 ptrtoint ({ [2 x i32], [56 x i8] }*
> @__const.main.a to i64), i64 8, i64 64, i64 ptrtoint ([15 x i8]*
> @___asan_gen_.2 to i64), i64 ptrtoint ([2 x i8]* @___asan_gen_.1 to i64),
> i64 0, i64 0, i64 -1 }, section "__DATA,__asan_globals,regular"
> > > @__asan_binder___const.main.a = internal global { i64, i64 } { i64
> ptrtoint ({ [2 x i32], [56 x i8] }* @__const.main.a to i64), i64 ptrtoint
> ({ i64, i64, i64, i64, i64, i64, i64, i64 }* @__asan_global___const.main.a
> to i64) }, section "__DATA,__asan_liveness,regular,live_support"
> > > @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast ({ [2 x
> i32], [56 x i8] }* @__const.main.a to i8*), i8* bitcast ({ i64, i64 }*
> @__asan_binder___const.main.a to i8*)], section "llvm.metadata"
> > > @___asan_globals_registered = common hidden global 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 ssp
> uwtable
> > 9,17c19,121
> > <   %1 = alloca i32, align 4
> > <   %2 = alloca [2 x i32], align 4
> > <   %3 = alloca i32, align 4
> > <   store i32 0, i32* %1, align 4
> > <   %4 = bitcast [2 x i32]* %2 to i8*
> > <   call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %4, i8* align 4
> > bitcast ([2 x i32]* @__const.main.a to i8*), i64 8, i1 false)
> > <   %5 = getelementptr inbounds [2 x i32], [2 x i32]* %2, i64 0, i64 2
> > <   %6 = load i32, i32* %5, align 4
> > <   store i32 %6, i32* %3, align 4
> > ---
> > > entry:
> > >   %retval = alloca i32, align 4
> > >   %b = alloca i32, align 4
> > >   %asan_local_stack_base = alloca i64
> > >   %0 = load i32, i32* @__asan_option_detect_stack_use_after_return
> > >   %1 = icmp ne i32 %0, 0
> > >   br i1 %1, label %2, label %4
> > >
> > > 2:                                                ; preds = %entry
> > >   %3 = call i64 @__asan_stack_malloc_0(i64 64)
> > >   br label %4
> > >
> > > 4:                                                ; preds = %entry, %2
> > >   %5 = phi i64 [ 0, %entry ], [ %3, %2 ]
> > >   %6 = icmp eq i64 %5, 0
> > >   br i1 %6, label %7, label %9
> > >
> > > 7:                                                ; preds = %4
> > >   %MyAlloca = alloca i8, i64 64, align 32
> > >   %8 = ptrtoint i8* %MyAlloca to i64
> > >   br label %9
> > >
> > > 9:                                                ; preds = %4, %7
> > >   %10 = phi i64 [ %5, %4 ], [ %8, %7 ]
> > >   store i64 %10, i64* %asan_local_stack_base
> > >   %11 = add i64 %10, 32
> > >   %12 = inttoptr i64 %11 to [2 x i32]*
> > >   %13 = inttoptr i64 %10 to i64*
> > >   store i64 1102416563, i64* %13
> > >   %14 = add i64 %10, 8
> > >   %15 = inttoptr i64 %14 to i64*
> > >   store i64 ptrtoint ([11 x i8]* @___asan_gen_ to i64), i64* %15
> > >   %16 = add i64 %10, 16
> > >   %17 = inttoptr i64 %16 to i64*
> > >   store i64 ptrtoint (i32 ()* @main to i64), i64* %17
> > >   %18 = lshr i64 %10, 3
> > >   %19 = or i64 %18, 17592186044416
> > >   %20 = add i64 %19, 0
> > >   %21 = inttoptr i64 %20 to i64*
> > >   store i64 -868082052615769615, i64* %21, align 1
> > >   store i32 0, i32* %retval, align 4
> > >   %22 = bitcast [2 x i32]* %12 to i8*
> > >   %23 = add i64 %19, 4
> > >   %24 = inttoptr i64 %23 to i8*
> > >   store i8 0, i8* %24, align 1
> > >   call void @llvm.lifetime.start.p0i8(i64 8, i8* %22) #2
> > >   %25 = bitcast [2 x i32]* %12 to i8*
> > >   %26 = call i8* @__asan_memcpy(i8* %25, i8* bitcast ({ [2 x i32], [56
> x i8] }* @__const.main.a to i8*), i64 8)
> > >   %27 = bitcast i32* %b to i8*
> > >   call void @llvm.lifetime.start.p0i8(i64 4, i8* %27) #2
> > >   %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* %12, i64 0,
> i64 2
> > >   %28 = ptrtoint i32* %arrayidx to i64
> > >   %29 = lshr i64 %28, 3
> > >   %30 = or i64 %29, 17592186044416
> > >   %31 = inttoptr i64 %30 to i8*
> > >   %32 = load i8, i8* %31
> > >   %33 = icmp ne i8 %32, 0
> > >   br i1 %33, label %34, label %40, !prof !4
> > >
> > > 34:                                               ; preds = %9
> > >   %35 = and i64 %28, 7
> > >   %36 = add i64 %35, 3
> > >   %37 = trunc i64 %36 to i8
> > >   %38 = icmp sge i8 %37, %32
> > >   br i1 %38, label %39, label %40
> > >
> > > 39:                                               ; preds = %34
> > >   call void @__asan_report_load4(i64 %28)
> > >   call void asm sideeffect "", ""()
> > >   unreachable
> > >
> > > 40:                                               ; preds = %34, %9
> > >   %41 = load i32, i32* %arrayidx, align 4
> > >   store i32 %41, i32* %b, align 4
> > >   %42 = bitcast i32* %b to i8*
> > >   call void @llvm.lifetime.end.p0i8(i64 4, i8* %42) #2
> > >   %43 = bitcast [2 x i32]* %12 to i8*
> > >   %44 = add i64 %19, 4
> > >   %45 = inttoptr i64 %44 to i8*
> > >   store i8 -8, i8* %45, align 1
> > >   call void @llvm.lifetime.end.p0i8(i64 8, i8* %43) #2
> > >   store i64 1172321806, i64* %13
> > >   %46 = icmp ne i64 %5, 0
> > >   br i1 %46, label %47, label %54
> > >
> > > 47:                                               ; preds = %40
> > >   %48 = add i64 %19, 0
> > >   %49 = inttoptr i64 %48 to i64*
> > >   store i64 -723401728380766731, i64* %49, align 1
> > >   %50 = add i64 %5, 56
> > >   %51 = inttoptr i64 %50 to i64*
> > >   %52 = load i64, i64* %51
> > >   %53 = inttoptr i64 %52 to i8*
> > >   store i8 0, i8* %53
> > >   br label %57
> > >
> > > 54:                                               ; preds = %40
> > >   %55 = add i64 %19, 0
> > >   %56 = inttoptr i64 %55 to i64*
> > >   store i64 0, i64* %56, align 1
> > >   br label %57
> > >
> > > 57:                                               ; preds = %54, %47
> > 20a125,126
> > > declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
> > > ; Function Attrs: argmemonly nounwind willreturn
> > 21a128,235
> > > ; Function Attrs: argmemonly nounwind willreturn
> > > declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #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 i64 @__asan_stack_malloc_0(i64)
> > > declare void @__asan_stack_free_0(i64, i64)
> > > declare i64 @__asan_stack_malloc_1(i64)
> > > declare void @__asan_stack_free_1(i64, i64)
> > > declare i64 @__asan_stack_malloc_2(i64)
> > > declare void @__asan_stack_free_2(i64, i64)
> > > declare i64 @__asan_stack_malloc_3(i64)
> > > declare void @__asan_stack_free_3(i64, i64)
> > > declare i64 @__asan_stack_malloc_4(i64)
> > > declare void @__asan_stack_free_4(i64, i64)
> > > declare i64 @__asan_stack_malloc_5(i64)
> > > declare void @__asan_stack_free_5(i64, i64)
> > > declare i64 @__asan_stack_malloc_6(i64)
> > > declare void @__asan_stack_free_6(i64, i64)
> > > declare i64 @__asan_stack_malloc_7(i64)
> > > declare void @__asan_stack_free_7(i64, i64)
> > > declare i64 @__asan_stack_malloc_8(i64)
> > > declare void @__asan_stack_free_8(i64, i64)
> > > declare i64 @__asan_stack_malloc_9(i64)
> > > declare void @__asan_stack_free_9(i64, i64)
> > > declare i64 @__asan_stack_malloc_10(i64)
> > > declare void @__asan_stack_free_10(i64, i64)
> > > declare void @__asan_poison_stack_memory(i64, i64)
> > > declare void @__asan_unpoison_stack_memory(i64, i64)
> > > declare void @__asan_set_shadow_00(i64, i64)
> > > declare void @__asan_set_shadow_f1(i64, i64)
> > > declare void @__asan_set_shadow_f2(i64, i64)
> > > declare void @__asan_set_shadow_f3(i64, i64)
> > > declare void @__asan_set_shadow_f5(i64, i64)
> > > declare void @__asan_set_shadow_f8(i64, i64)
> > > declare void @__asan_alloca_poison(i64, i64)
> > > declare void @__asan_allocas_unpoison(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_apple_clang_1200()
> > >   call void @__asan_register_image_globals(i64 ptrtoint (i64*
> @___asan_globals_registered to i64))
> > >   ret void
> > > }
> > > declare void @__asan_version_mismatch_check_apple_clang_1200()
> > > define internal void @asan.module_dtor() {
> > >   call void @__asan_unregister_image_globals(i64 ptrtoint (i64*
> @___asan_globals_registered to i64))
> > >   ret void
> > > }
> > 23c237
> > < attributes #0 = { noinline nounwind optnone ssp uwtable
> > "correctly-rounded-divide-sqrt-fp-math"="false"
> > "darwin-stkchk-strong-link" "disable-tail-calls"="false"
> > "frame-pointer"="all" "less-precise-fpmad"="false"
> > "min-legal-vector-width"="0" "no-infs-fp-math"="false"
> > "no-jump-tables"="false" "no-nans-fp-math"="false"
> > "no-signed-zeros-fp-math"="false" "no-trapping-math"="false"
> > "probe-stack"="___chkstk_darwin" "stack-protector-buffer-size"="8"
> > "target-cpu"="penryn"
> >
> "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87"
> > "unsafe-fp-math"="false" "use-soft-float"="false" }
> > ---
> > > attributes #0 = { noinline nounwind optnone sanitize_address ssp
> uwtable "correctly-rounded-divide-sqrt-fp-math"="false"
> "disable-tail-calls"="false" "frame-pointer"="all"
> "less-precise-fpmad"="false" "min-legal-vector-width"="0"
> "no-infs-fp-math"="false" "no-jump-tables"="false"
> "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false"
> "no-trapping-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="penryn"
> "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> > 24a239
> > > attributes #2 = { nounwind }
> > 32a248
> > > !4 = !{!"branch_weights", i32 1, i32 100000}
> >
> > --
> > Regards,
> > Peng
> > _______________________________________________
> > LLVM Developers mailing list
> > llvm-dev at lists.llvm.org
> > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
> >
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210413/554810ce/attachment.html>


More information about the llvm-dev mailing list