AppArmor parser development notes and tips
==========================================

Debugging the build
-------------------
Adding V=1 as argument to make should result in build commands that are
normally quieter generating more verbose output. This can help diagnose
when something is going wrong at build time.

Distribution vendors may wish to enable this option all
the time to assist debugging build failures in remote build
environments. Generally, they should not need to enable any other
build flags/options.

Building the parser with debugging information
----------------------------------------------
Setting DEBUG=1 with make will enable debugging output in the parser
(i.e. PDEBUG statements will be emitted instead of dropped). Usually,
partial compilation between debug and non-debug will cause compilation
problems, so it's usually best to do something like

  make clean all DEBUG=1

Test Coverage
-------------
The parser can be built to generate test coverage information, by
setting the COVERAGE variable for make. As with debugging, partial
compilation is usually problematic, so it's recommended to do:

  make clean all COVERAGE=1

and then run whatever tests. Because the unit tests are built with the
make check target, in order to see what coverage they provide, they will
also need to be built with the COVERAGE flag set:

  make tests COVERAGE=1

or, if running the unit tests with all the other parser tests:

  make check COVERAGE=1

Coverage information will be written out in files in the source build
tree (*.gcno and *.gcda files). The 'gcovr' utility is useful for
reading and summarizing the results; to do so, after running your
tests, do something like:

  gcovr -r /PATH/TO/YOUR/PARSER/BUILD/TREE

Of course, having test coverage over a given line of code
won't indicate that the code is bug free; however, not having
coverage indicates that the tests do not exercise the given code at
all. That said, 100% coverage is unlikely to be possible in a testing
environment, given checks for things like error handling for failed
memory allocations.

Finding memory leaks
--------------------
The tst/ subdirectory has a python script for running valgrind on the
parser over the test files in the simple_tests/ tree. This can take
over 24 hours to complete, so it is not part of the default tests;
however, it can be run manually or via the 'valgrind' make target.

Valgrind reports some false positives for some additional checks it
makes; the script attempts to suppress those (read the valgrind
documentation for more details on suppressions). It can also emit the
suppressions via the --dump-suppressions argument, to be used for manual
valgrind runs.

An example manual valgrind run could be something like:

  ./tst/valgrind_simply.py --dump-suppressions > /tmp/valgrind.suppression
  valgrind --leak-check=full --suppressions=/tmp/valgrind.suppression ./apparmor_parser -QK /path/to/profile

Profiling (for performance) the parser
--------------------------------------

# Using valgrind's callgrind tool

Valgrind provides the callgrind tool to give some indication where
hot spots are in the parser. To do so, do:

  valgrind --tool=callgrind ./apparmor_parser PARSER_ARGS

This will generate a data file that a tool like kcachegrind can read.

# Using gprof

This can be enabled by adding the -pg argument as a CFLAG [1] at build
time and then exercising the parser. A data file will be generated
that gprof(1) can then read to show where the parser is spending the
most time.

[1] Unfortunately, only the DEBUG option in the Makefile does this,
    which enables other debugging options that alters the parser in
    ways that make it a less accurate representation of real world
    performance. This needs to be fixed.
