Address Sanitizer now available for Xbox Developers

(ASan) is a valuable tool for lighting up hard-to-find memory bugs.

July 29, 2021
a collection of devices showing gaming UI

Introduction

Address Sanitizer (ASan) is a valuable tool for lighting up hard-to-find memory bugs. Since the MSVC release in Visual Studio version 16.9, we've been working with our partners to bring ASan to the Xbox platform.

In this blog post, we will showcase how to get ASan working with the Xbox platform.

Building with Address Sanitizer

Setting up an Xbox project for ASan should follow the same guidelines as the PC version, with the Address Sanitizer being integrated into the usual Visual Studio debugging experience. However, there are some specific use-cases for Xbox developers that were not supported by default under ASan.

a screenshot of a computer screen showing Address Sanitizer

Modern games consist of highly complicated, multi-threaded code whose goal is to run as fast as possible while holding a target frame rate. This means that the code is tested frequently through development by means of an automated build and test setup. These server machines may build the code, deploy it to a console, and run the game without a debugger connection meaning that they might miss any ASan error reports shown in the debug output. Ideally, the test server could collect crash dumps from any Asan errors, but due to differences in the Xbox GDK, extra steps must be taken to extract Address Sanitizer crash dump information from automated runs.

Enhanced Debugger Support

MSVC's ASan implementation can create a crash dump with detailed exception information, but this could only be enabled from an environment variable which isn't supported on Xbox. To get crash dumps on Xbox, developers must specify a function in their code to supply the dump filename.

Here are two examples of what the function looks like:

extern "C" const wchar_t* __vcasan_save_dumps()
{
    return L"myCrashDump.dmp";
}
extern "C" const WCHAR* __vcasan_save_dumps()
{
    // Choose to create a crash dump based on a runtime flag
    if ( gCollectCrashDumps )
    {
        return L"myCrashDump.dmp";
    }
    else
    {
        // Returning NULL stops ASan creating a crash dump
        return NULL;
    };
}
There are no specific requirements around the name returned by this function, but it must be a valid filepath on the target device where the code is being run.

Now that we can support crash dumps on Xbox, we also decided to give developers more flexibility around the type of crash dump that is produced. There are instances where a simple "Triage" dump is sufficient to see the callstack of where the process failed, but within games, there is usually the requirements to see more of the surrounding memory when the issue occurred. To this end, we have provided three configurable crash dump types that are supported by the Xbox platform and match the crash dumps developers expect from their Xbox consoles.

Note: As with the previous function, this override is optional on Xbox, but it is highly recommended if you want to use crash dumps to collect ASan information without a debugger attached.  If you provide the dump filename but not a dumptype override, then it will fail to generate a valid crash dump on Xbox.

This callback returns a number to indicate the dump type required. Valid types are shown in the example below:​

extern "C" const signed int __vcasan_override_dumptype()
{
    // The current valid values are:
    // 0 : Triage Dump
    // 1 : Mini Dump
    // 2 : Heap Dump
    // Values outside this range are defaulted to 2 (Full Heap)

    // This example uses Heap Dumps which give the most information
    return 2;
}
Both callback functions are available as part of 16.9.8, 16.10.2 or a future 16.11 preview release of Visual Studio.

Example code

This code demonstrates how easily these functions can be added into an existing codebase and adapted as required:

#include <cstdio>

extern "C" const wchar_t* __vcasan_save_dumps()
{
    // Specify dump filename
    return L"myCrashDump.dmp";
}

extern "C" const signed int __vcasan_override_dumptype()
{
    // Full Heap dump requested
    return 2;
}

static const int arraySize = 8;
static int asanArray[arraySize];
static int asanAccumulator = 0;

int main()
{
    // ASan should use the callback functions that we have provided
    for (int loop = 0; loop <= arraySize; loop++)
    {
        // We don't really care about accumulating the values
        // We just want to access outside the array causing an ASan error
        asanAccumulator += asanArray[loop];
    }

    // If we get here, we have failed as ASAN should have caught the error above
    printf("fail");

    return 0;
}

Compile the code via this command line:

cl /nologo /fsanitize=address /Zi AsanTest.cpp
This code, when run should throw an ASan exception and produce a crash dump as specified by our functions above. You can integrate these functions into existing code and generate crash dumps of your choosing.

Summary

With Address Sanitizer now being available on Xbox, developers can leverage this powerful technology to help debug memory issues in their titles.  Combined with the crash dump changes detailed here, it should provide all the flexibility required to support your automated tests suites and enable you to find issues quickly and easily.  We welcome any feedback on these changes and would ask you to raise any issues through the Xbox forums in the usual way.

Further references for more information: