DEV Community

Yuki Kimoto
Yuki Kimoto

Posted on

Enabling AddressSanitizer (ASan) in Makefile.PL for Linux Environments


Note: This method is designed for Linux systems where LD_PRELOAD is available.
AddressSanitizer (ASan) is a powerful tool for detecting memory corruption in C/C++ code. When developing Perl XS modules, you can integrate ASan support directly into your Makefile.PL to make debugging seamless.

Add the 'asan-on-linux' Option



First, use GetOptions to provide a dedicated flag for ASan. This allows users to enable memory sanitization explicitly. We also set up a temporary directory to store ASan's detailed log files.

use Getopt::Long;
use File::Path 'mkpath';

GetOptions('asan-on-linux' => \my $asan_on_linux);

my @ccflags;
my @ldflags;
my $asan_logs_dir = ".tmp/asan_logs";

if ($asan_on_linux) {
    push @ccflags, "-fsanitize=address", "-fno-omit-frame-pointer";
    push @ldflags, "-fsanitize=address";
    
    mkpath $asan_logs_dir unless -d $asan_logs_dir;
}

Automate Library Preloading via Makefile Macros



Since the standard perl binary isn't typically compiled with ASan, we must ensure libasan.so is correctly preloaded before the interpreter starts. By using the macro parameter in WriteMakefile, we can automate this process for make test.

use Config;

WriteMakefile(
    NAME              => 'My::Module',
    CCFLAGS           => "$Config{ccflags} " . join(' ', @ccflags),
    LDDLFLAGS         => "$Config{lddlflags} " . join(' ', @ldflags),
    # ...
    macro => {
        $asan_on_linux ? (
            'override FULLPERL' => qq|LD_PRELOAD=\$\$($Config{cc} -print-file-name=libasan.so) ASAN_OPTIONS="log_path=$asan_logs_dir/asan.log:exitcode=0" $^X|
        ) : (),
    },
);

How to Handle Memory Issues



When ASan is enabled, the behavior depends on the type of memory issue:


  • Memory Corruption: Issues like buffer overflows or use-after-free will cause a Segmentation Fault (Segfault) immediately. When this happens, you must fix the code until all tests pass without crashing.
  • Memory Leaks: Unlike corruption, memory leaks do not cause a crash. To find them, you must check the logs after running your tests.


ASan generates a separate log file for each process. To efficiently find both corruption reports and leaks related to your specific module, use the following Perl one-liner (Replace My::Module with your module's name):

perl -00 -ne 'print "--- File: $ARGV ---\n$_\n" if /My::Module/' .tmp/asan_logs/* > .tmp/asan_summary.log


This command uses Perl's "paragraph mode" (-00) to extract the entire stack trace, allowing you to see exactly where the issue (crash or leak) was triggered in your native code.


Appendix: Platform Compatibility

macOS (Untested Hint)



On macOS, you might try DYLD_INSERT_LIBRARIES instead of LD_PRELOAD. However, System Integrity Protection (SIP) often prevents preloading into system binaries like /usr/bin/perl. You would likely need to use a perl installed via perlbrew or plenv.

Windows (Not Supported)



This mechanism is not applicable to Windows. Windows lacks LD_PRELOAD, and memory sanitization requires a fundamentally different configuration, typically involving a specially compiled perl interpreter.



Author: Yuki Kimoto

Top comments (0)