To use Lackwit to analyze a program, you first use the front-end tool (called "Lackwit") to construct a database containing information about the program. Then you use another tool ("BackEnd") to analyze the contents of the database, answer queries and display the results.
In the instructions below, we assume that $LACKWIT_HOME has been set to the Lackwit installation directory. The examples show how to analyze the code in $LACKWIT_HOME/demo/lislook.
setenv LACKWITDB $LACKWIT_HOME/demo/lislook
setenv PATH $LACKWIT_HOME/bin:$PATH
EmitHeaders $LACKWIT_HOME/lib/Default.sigs cc -c $LACKWIT_HOME/lib/libc.c -o /dev/nullYou can use any C compiler here. You should ignore the warnings and errors generated by the compiler.
rm -f *.o gmakeThis will work no matter what build process you use, as long as it searches your path to find which compiler to run. If your compiler isn't called 'gcc' or 'cc', just make a link in the Lackwit 'bin' directory from the compiler name to the 'wrap_compiler' script. One other thing: the build process must use the '-c' option to compile files; one-step compilation-and-link such as "gcc test.c -o a.out" will not work.
BackEndBackEnd will chug along; eventually, it will prompt you for a query.
searchlocal lis_loadAdb:dbnameThis will output a list of the other pointer variables that may contain the pointer values that occur in dbname. Only the variables that actually have some operation performed on them are shown. (For example, if the pointer is stored in a structure which is simply passed on through a function without being actually accessed, that function will not show up in the output.)
davinci lis_loadAdb:dbnameThis will launch DaVinci to display a graph of the function call connections that pass around the pointer values, and where the operations actually occur. This requires that you have DaVinci installed on the machine hosting BackEnd. DaVinci must be installed separately from Lackwit; see the DaVinci Web page for details.
searchglobal "dealloc ! alloc &"This will find all the variables that are NOT marked with the "dealloc" tag (that says that the value may eventually be passed to "free"), but that ARE marked with the "alloc" tag (that says that the value may eventually be passed to "malloc"). The argument is an expression in Reverse Polish Notation that is equivalent to "(NOT dealloc) AND alloc". Other literals that can be used in these queries are "ref" (to indicate that this value may occupy memory), "assign" (to indicate that the memory for this value may be overwritten with an assignment), and "deref" (to indicate that the memory for this value may be read). E.g. "assign ! ref &" will find constants and "deref ! ref &" will find unused data.
For more information about queries, see the reference documentation.
Some C compilers accept extensions to C that Lackwit doesn't understand. Even if you don't use these extensions in your programs, the vendor's .h files often use them and this can cause problems for Lackwit. Sometimes errors occur when you accidentally process C++ code with Lackwit, or process code that contains compilation errors. Warnings are produced when you use unknown identifiers in programs, and for certain non-fatal compiler errors. If only warnings are generated, then they can usually be safely ignored.
The problems caused by compiler extensions can often be fixed by passing certain options into the Lackwit front-end to tell it how to treat the unknown constructs. Run 'Lackwit -help' for a list of the available options, and look at the 'wrap_compiler' script for a list of options that cover most of the extensions provied by 'gcc'. Many other extensions can be handled by adapting that list. If all else fails, send me some preprocessed example code that triggers the problem.
These messages are generated when there are non-static symbols with the same name defined in different files. The system chooses one definition (the one from the module that was most recently added to the database) and uses that, which is often the right choice. However it may indicate that there are actually multiple different programs being built, in which case you should use a different database for each program.
These are internal errors in the Lackwit system. Please send preprocessed code that reproduces the errors to me.
These errors occur when some referenced symbols were not defined. Usually these are library functions that I haven't provided dummy code for. The best approach for these is to provide the code, if you can. The system assumes that the undefined functions simply don't do anything, and references to undefined variables are simply ignored.
Unfortunately, Lackwit is not fully "conservative"; some programs use (or more often abuse) language features in ways that cause the tool to miss some variables that it should include in response to a query. These features are generally non-portable and usually occur in programs that are very low-level systems code, very poorly designed, or buggy (or some combination of these :-) ).
Given these restrictions, Lackwit's results cannot be fully trusted for certain programs. If your knowledge of the code base or of the coding standard in use lets you rule out these kinds of behaviours, then there's nothing to worry about. (But be aware that most programs have bugs and bugs may cause these behaviours.) Otherwise, you can use Lackwit as a tool to aid your understanding of programs, keeping in mind that the only sure way to know what a C program does is to test it on the target machine.
Lackwit can be customized in many ways. The type system can be customized to give different interpretations of the basic operators, which can be helpful when using Lackwit for specialized applications. Also, user-defined functions can be given the same "tagging" support that "malloc" and "free" have, so that queries can be written to, for example, find windows that are never closed. For more information about how to do this kind of thing, you'll have to write to me personally.