ASX C/C++ Dead Function Eliminator

This program uses the output produced by ASX in order to discover unreachable functions within the source code. It optionally permits automated removal of such unreachable functions.

The supporting paper can be found here.

Download Xcise

Xcise is a C/C++ dead code detection and elimination tool that uses as its input the output of the ASX fact extraction tool.

The latest builds of Xcise are available below. While effort has been made to test Xcise the software may contain bugs.

Xcise 2.0.6 [xcise-2.0.6.zip] [xcise-2.0.6.exe]
Xcise 2.0.5 [xcise-2.0.5.zip] [xcise-2.0.5.exe]
Xcise 2.0.4 [xcise-2.0.4.zip] [xcise-2.0.4.exe]
Xcise 2.0.3 [xcise-2.0.3.zip] [xcise-2.0.3.exe]
Xcise 2.0.2 [xcise-2.0.2.zip] [xcise-2.0.2.exe]
Xcise 2.0.1 [xcise-2.0.1.zip] [xcise-2.0.1.exe]
Xcise 2.0.0 [xcise-2.0.0.zip] [xcise-2.0.0.exe]
Xcise 1.0.1 [xcise-1.0.1.zip] [xcise-1.0.1.exe]
Xcise 1.0.0 [xcise-1.0.0.zip] [xcise-1.0.0.exe]

Xcise is being constantly developed and improved; check back often for newer versions.


This program takes as its standard input output earlier produced by ASX (2.0.5 or later for version 1 and 2.0.6 for version 2) and by default reports on standard output those functions which according to the graph produced by ASX are unreachable from either main() or wmain(). With appropriate options it will make a best effort to either produce new versions of the source code with the "dead functions" commented out by using #ifdefs, or directly update the source code with such #ifdefs. The location of source code is presumed to be as specified in the input TA file, and the start of functions as specified by the lineno attributes contained within this TA file.

The code does not currently comment out structures which themselves contain pointers to dead functions. These must be manually removed in order for code modified by this program to compile.

Failure to correctly comment out precisely those functions that are indeed unreachable in most cases should be viewed as a bug in this software; in ASX or in both tools. However macro's that contain unbalanced opening and closing brackets will defeat the ability for this program to correctly identify start and end of functions, since fundamentally this exercise relies heavily on matching visible brackets. Macro's that contain within them declarations of multiple functions may also when commented out violate the objectives of this program. And clearly, erroneous input from ASX can invalidate the whole task of identifying which functions are dead and which are not. In particular, ASX should be instructed to recover information not only about functions, but also about variables, since variables may themselves be used (via function pointers) to invoke functions. It should also be noted that no changes to source code should be made between executing ASX and running Xcise.


xcise [-d] [-f] [-F] [-n] [-t] [-T] [-r|-s|-u [-b]|-w [-v]] [-p <path>] < facts.ta


By default dead functions are simply reported on standard output. This is equivalent to setting the -v option.

The -s option removes earlier #ifdef _DEAD_ ... #endif pairs earlier inserted into the source code.

The -v option requests that the listing of dead functions is to emitted as well as source code being updated.

The -w option instructs xcise to generate new source files, with suffix ".dead" containing suitably added #ifdefs. This option is suitable when manual review of changes made to the source is deemed desirable, since it permits comparison of before and after image, without applying any change to the source code read.

The -u option instructs xcise to update the source directly. It is highly recommended that source be backed up, prior to employing this option.

The -b option causes all updated files using the -u option to first be copied to the same file name with the suffix ".bak" added. This option presuming the copy works, will backup files before updating them.

The -p option instructs xcise not to update any files, whose path prefix does not match the provided path prefix. This avoids xcise updating system header files, and other shared source files, not intended to touched.

The -n option instructs xcise to retain all polymorphic functions. There are a number of reasons why one might not wish to remove such functions from source.

The -d debug option causes source code scanned to be annotated and written out with an extension of ".scan". This will produce a large number of files but helps reveal where boundaries in source code are computed to be.

The -f option causes the output report to show for each dead function what references in the input TA pointed either at it, or at its address. This is useful primarily for debugging, so as to ensure that no potentially relevant references to code reported as dead have been missed by xcise.

The -F option causes the output report to show for each dead function what references in the input TA are pointed at by this dead function. This is useful if one wishes to understand how dead code might be related to other dead code.

The -t option causes the compiler options used to create a preprocessed file, suitable for discovering boundaries, to be shown. This might be useful if a compile time error is observed when using xcise.

The -T option causes the visit history of how functions were discovered to be useful to be printed on standard output. It is intended primarily for debugging.


Xcise is written in C++, primarily because C++ can be expected to run much faster than Java. Xcise therefore employs a C++ translation of the Java code used by LSEdit to translate the input TA into a graph. Once read nodes in this graph are visited to determine which functions in the code are reachable from main and/or wmain. Once this is determined, the core of this program involves determining given only the line number on which a function bodies '{' occurs, what lines of source code then should be #ifdef'd out to effectively remove this function (and only this function).

Xcise must ensure that functions contained in header files are not removed, if accessed from any source containing this header file, even if not accessed from all, and must anticipate that in the source to be edited, entire functions might logically be included in code, not as functions but as expansion of macros. Further this logic must work in the presence of #if[def] statements themselves embedded within a function. This is achieved by presuming such preprocessor directives always evaluate to true.

The #ifdef uses _DEAD_ as the macro which if defined, causes inclusion of dead code for compilation, and which if not defined causes exclusion of dead code from compilation. Following this #ifdef is the date and time that the #ifdef was added to the code. Other useful commentary information could be trivially added to the output produced by this program.


Currently this software does not comment out structures not themselves accessed, even if such structures contain within them pointers to code commented out as dead code. Manual commenting out of such structures in cases where they do indeed point to commented out dead code, will be required to compile code processed by xcise.

Identifying start and end point of functions armed only with a machine code understanding of the line on which a function starts, is non-trivial and likely to prove error prone in some cases. It should therefore not be presumed that this program will always correctly locate #ifdef statements.

Testing of this program lead to identification of problems within ASX. The earliest version of ASX which correctly caused removal by xcise of only dead code was 2.0.5. Note that any omissions in the information produced by ASX, may cause Xcise to flag functions as not being reachable, which in reality are reachable from main or wmain.

The commenting out of dead functions is achieved by computing line numbers in the source that match line number information in the post processed source. If the source itself contains incorrect #line information, this will cause misalignment of the post-processed source with the actual source being modified, and potentially cause if defs to be inserted at the wrong place within the source.

Subject to change.. still under development.

Developed by

  • Ian Davis.


  • swag:~ijdavis/src/xcise -- source code
  • swag:~ijdavis/bin/xcise -- executable

Supported platforms

In theory Xcise should be compilable and runnable on many platforms. However ASX which provides the input to xcise currently only runs on machines which produce assembler that conforms with the GNU i386 instruction format.

Contact information

For more information on ASX please contact us at .