|
From: omo <om...@do...> - 2008-06-16 14:18:04
|
Hello, I've prototyped a simple fault injector for malloc()-like routines, called "Failgrind". The tool can make fail malloc() and its variants which are called from specific functions. the basic idea is similar to the bug: http://bugs.kde.org/show_bug.cgi?id=163266 and failmalloc http://www.nongnu.org/failmalloc/ . This is just a small, proof-of-concept prototype, and there will be a lot of TODOs. Which is better to the patch to massif or current "separate tool" style? What are missing features? How should they be implemented? How to intercept specific functions? Does this type of tool make sense at all? Any comments, advices and ideas are welcome. Thank you in advance. ---- * Availabitity I host the code on my mercurial repository: - http://dodgson.org/omo/failgrind/hg/ snapshot is available at - http://dodgson.org/omo/failgrind/hg/?archive/tip.tar.gz The implemention is done as a separate valgrind tool and small patch to base Makefiles. $ tar xvjf ~/Download/valgrind-3.3.0.tar.bz2 $ tar xvzf ~/Download/failgrind-xxx.tar.gz $ mv failgrind-3336efc98b98 valgrind-3.3.0/failgrind $ cd valgrind-3.3.0 $ patch -p1 < failgrind/3_3_0_root.patch $ ./failgrind/autogen.sh $ ./configure --prefix=`pwd`/inst $ make && make install * Usage example Assume we have following code : ---- /* hello.c */ #include <stdlib.h> #include <stdio.h> void* fine() { return malloc(16); } void* how_are_you() { return fine(); } void* hello() { return malloc(16); } void* bye() { return malloc(16); } int main(int argc, char* argv[]) { void* h = 0; void* b = 0; void* hau = 0; h = hello(); if (!h) { printf("failed to alloc hello\n"); return 1; } hau = how_are_you(); if (!hau) { printf("failed to alloc how_are_you\n"); free(h); return 1; } b = bye(); if (!b) { printf("failed to alloc bye\n"); free(hau); free(h); return 1; } printf("all allocted successfully\n"); free(b); free(hau); free(h); return 0; } ---- Which run successfully on normal setting. $ gcc failgrind/tests/hello.c $ ./a.out all allocated successfully Using Failgrind, we can make it fail. $ ./inst/bin/valgrind -q --tool=failgrind --fail-conds=bye ./a.out failed to alloc bye Note that malloc() on bye() failed. Here are more examples: # didn't match bye() $ ./inst/bin/valgrind -q --tool=failgrind --fail-conds=bye/how_are_you ./a.out all allocated successfully # did match! $ ./inst/bin/valgrind -q --tool=failgrind --fail-conds=fine/how_are_you ./a.out failed to alloc how_are_you # invocation order is not what we expect. $ ./inst/bin/valgrind -q --tool=failgrind --fail-conds=how_are_you/fine ./a.out all allocated successfully * Possible TODOs - Port failmalloc features. - Support other functions to fail. - Add client request to controll the behaviour from unit-testing. - Add simpel memory leak detection. because Valgrind seems not to allow using two tools together, we cannot use Massif when we use Failgrind. -- morita |