Search code examples
caddress-sanitizer

why asan linker flag is needed


Could someone help me understand, why after generating the object file with using ASan flag (compiler flag), when linking the object file still needs the same flag? (linker flag)

For example

clang -fsanitize=address -c test.c
clang -fsanitize=address test.o -o test.exe

Solution

  • When you compile your program with Address Sanitizer, it instruments every memory access and prefixes it with a check and includes the function calls to report memory access errors.

    For e.g.

    Sample program which leaks memory and try to access array beyond its size:

    #include <stdio.h>
    #include <stdlib.h>
    
    void fun (void) {
        void *p = malloc(1);
        char a[] = "abc";
    
        printf ("%c\n", a[4]);
    }
    
    int main (void) {
        fun();
        return 0;
    }
    

    Compiling:

    # gcc -fsanitize=address -g -c test.c
    # ls
    test.c  test.o
    

    Linking without -fsanitize=address:

    # gcc -g test.o -o test.exe
    test.o: In function `fun':
    /root/mywork/asan/sample7/test.c:4: undefined reference to `__asan_option_detect_stack_use_after_return'
    /root/mywork/asan/sample7/test.c:4: undefined reference to `__asan_stack_malloc_1'
    /root/mywork/asan/sample7/test.c:6: undefined reference to `__asan_report_store4'
    /root/mywork/asan/sample7/test.c:8: undefined reference to `__asan_report_load1'
    test.o: In function `_GLOBAL__sub_D_00099_0_fun':
    /root/mywork/asan/sample7/test.c:14: undefined reference to `__asan_unregister_globals'
    test.o: In function `_GLOBAL__sub_I_00099_1_fun':
    /root/mywork/asan/sample7/test.c:14: undefined reference to `__asan_init'
    /root/mywork/asan/sample7/test.c:14: undefined reference to `__asan_version_mismatch_check_v8'
    /root/mywork/asan/sample7/test.c:14: undefined reference to `__asan_register_globals'
    collect2: error: ld returned 1 exit status
    

    The code of test.o is instrumented by Address Sanitizer. The Address Sanitizer runtime library replaces malloc() call with its own malloc() function call (which allocate requested amount of memory with redzone around it) and provides error reporting function like __asan_report_load1(), __asan_report_store4() etc. In order to resolve these functions, the -fsanitize=address flag is required at the time of linking to tell linker to check the ASan runtime library to resolve the references.

    Linking with -fsanitize=address:

    # gcc -fsanitize=address -g test.o -o test.exe
    # ls
    test.c  test.exe  test.o
    

    If you don't want to use -fsanitize=address flag with linker, you can provide the Address Sanitizer library to the linker which it can use to resolve the references:

    # ls
    test.c  test.o
    # gcc -lasan -g test.o -o test.exe
    # ls
    test.c  test.exe  test.o