From: Nicholas Nethercote Date: Fri, 27 Sep 2002 10:29:51 +0000 (+0000) Subject: Added some reasonably thorough documentation on how to write skins. Also added X-Git-Tag: svn/VALGRIND_1_9_4~299 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ad2f86232e7f88fdddcaabf41e2a1db5191b20d9;p=thirdparty%2Fvalgrind.git Added some reasonably thorough documentation on how to write skins. Also added an example skin which is referred to in the documentation, and is designed to be a template which can be copied. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1122 --- diff --git a/coregrind/docs/Makefile.am b/coregrind/docs/Makefile.am index e8a58fa18e..c11ba7f090 100644 --- a/coregrind/docs/Makefile.am +++ b/coregrind/docs/Makefile.am @@ -1,5 +1,5 @@ docdir = $(datadir)/doc/valgrind -doc_DATA = index.html manual.html nav.html techdocs.html +doc_DATA = index.html manual.html nav.html techdocs.html skins.html EXTRA_DIST = $(doc_DATA) diff --git a/coregrind/docs/skins.html b/coregrind/docs/skins.html new file mode 100644 index 0000000000..18d2faaf6c --- /dev/null +++ b/coregrind/docs/skins.html @@ -0,0 +1,650 @@ + + + + Valgrind + + + + +  +

Valgrind Skins

+
+ A guide to writing new skins for Valgrind
+ This guide was last updated on 20020926 +
+

+ +

+jseward@acm.org
+Copyright © 2000-2002 Julian Seward +

+Valgrind is licensed under the GNU General Public License, +version 2
+An open-source tool for supervising execution of Linux-x86 executables. +

+ +

+ +


+ +

Contents of this manual

+ +

Introduction

+ 1.1  Supervised Execution
+ 1.2  Skins
+ 1.3  Execution Spaces
+ +

Writing a Skin

+ 2.1  Why write a skin?
+ 2.2  How skins work
+ 2.3  Getting the code
+ 2.4  Getting started
+ 2.5  Writing the code
+ 2.6  Initialisation
+ 2.7  Instrumentation
+ 2.8  Finalisation
+ 2.9  Other important information
+ 2.10  Words of advice
+ +

Advanced Topics

+ 3.1  Suppressions
+ 3.2  Documentation
+ 3.3  Regression tests
+ 3.4  Profiling
+ 3.5  Other makefile hackery
+ +

Final Words

+ +
+ + +

1  Introduction

+ + +

1.1  Supervised Execution

+ +Valgrind provides a generic infrastructure for supervising the execution of +programs. This is done by providing a way to instrument programs in very +precise ways, making it relatively easy to support activities such as dynamic +error detection and profiling.

+ +Although writing a skin is not easy, and requires learning quite a few things +about Valgrind, it is much easier than instrumenting a program from scratch +yourself. + + +

1.2  Skins

+The key idea behind Valgrind's architecture is the division between its +``core'' and ``skins''. +

+The core provides the common low-level infrastructure to support program +instrumentation, including the x86-to-x86 JIT compiler, low-level memory +manager, signal handling and a scheduler (for pthreads). It also provides +certain services that are useful to some but not all skins, such as support +for error recording and suppression. +

+But the core leaves certain operations undefined, which must be filled by skins. +Most notably, skins define how program code should be instrumented. They can +also define certain variables to indicate to the core that they would like to +use certain services, or be notified when certain interesting events occur. +

+Each skin that is written defines a new program supervision tool. Writing a +new tool just requires writing a new skin. The core takes care of all the hard +work. +

+ + +

1.3  Execution Spaces

+An important concept to understand before writing a skin is that there are +three spaces in which program code executes: + +
    +
  1. User space: this covers most of the program's execution. The skin is + given the code and can instrument it any way it likes, providing (more or + less) total control over the code.

    + + Code executed in user space includes all the program code, almost all of + the C library (including things like the dynamic linker), and almost + all parts of all other libraries. +

  2. + +

  3. Core space: a small proportion of the program's execution takes place + entirely within Valgrind's core. This includes:

    + +

      +
    • Dynamic memory management (malloc() etc.)
    • + +
    • Pthread operations and scheduling
    • + +
    • Signal handling
    • +

    + + A skin has no control over these operations; it never ``sees'' the code + doing this work and thus cannot instrument it. However, the core + provides hooks so a skin can be notified when certain interesting events + happen, for example when when dynamic memory is allocated or freed, the + stack pointer is changed, or a pthread mutex is locked, etc.

    + + Note that these hooks only notify skins of events relevant to user + space. For example, when the core allocates some memory for its own use, + the skin is not notified of this, because it's not directly part of the + supervised program's execution. +

  4. + +

  5. Kernel space: execution in the kernel. Two kinds:

    + +

      +
    1. System calls: can't be directly observed by either the skin or the + core. But the core does have some idea of what happens to the + arguments, and it provides hooks for a skin to wrap system calls. +
    2. + +

    3. Other: all other kernel activity (e.g. process scheduling) is + totally opaque and irrelevant to the program. +
    4. +

    +
  6. + + It should be noted that a skin only has direct control over code executed in + user space. This is the vast majority of code executed, but it is not + absolutely all of it, so any profiling information recorded by a skin won't + be totally accurate. +

+ + + +

2  Writing a Skin

+ + +

2.1  Why write a skin?

+ +Before you write a skin, you should have some idea of what it should do. What +is it you want to know about your programs of interest? Consider some existing +skins: + + + +These examples give a reasonable idea of what kinds of things Valgrind can be +used for. The instrumentation can range from very lightweight (e.g. counting +the number of times a particular functin is called) to very intrusive (e.g. +memcheck's memory checking). + +
+

2.2  How skins work

+ +Skins must define various functions for instrumenting programs that are called +by Valgrind's core, yet they must be implemented in such a way that they can be +written and compiled without touching Valgrind's core. This is important, +because one of our aims is to allow people to write and distribute their own +skins that can be plugged into Valgrind's core easily.

+ +This is achieved by packaging each skin into a separate shared object which is +then loaded ahead of the core shared object valgrind.so, using the +dynamic linker's LD_PRELOAD variable. Any functions defined in +the skin that share the name with a function defined in core (such as +the instrumentation function SK_(instrument)()) override the +core's definition. Thus the core can call the necessary skin functions.

+ +This magic is all done for you; the shared object used is chosen with the +--skin option to the valgrind startup script. The +default skin used is memcheck, Valgrind's original memory checker. + + +

2.3  Getting the code

+ +To write your own skin, you'll need to check out a copy of Valgrind from the +CVS repository, rather than using a packaged distribution. This is because it +contains several extra files needed for writing skins.

+ +To check out the code from the CVS repository, first login: +

+cvs -d:pserver:anonymous@cvs.valgrind.sourceforge.net:/cvsroot/valgrind login +
+ +Then checkout the code. To get a copy of the current development version +(recommended for the brave only): +
+cvs -z3 -d:pserver:anonymous@cvs.valgrind.sourceforge.net:/cvsroot/valgrind co valgrind +
+ +To get a copy of the stable released branch: +
+cvs -z3 -d:pserver:anonymous@cvs.valgrind.sourceforge.net:/cvsroot/valgrind co -r TAG valgrind +
+ +where TAG has the form VALGRIND_X_Y_Z for +version X.Y.Z. + +
+

2.4  Getting started

+ +Valgrind uses GNU automake and autoconf for the +creation of Makefiles and configuration. But don't worry, these instructions +should be enough to get you started even if you know nothing about those +tools.

+ +In what follows, all filenames are relative to Valgrind's top-level directory +valgrind/. + +

    +
  1. Choose a name for the skin, and an abbreviation that can be used as a + short prefix. We'll use foobar and fb as an + example. +
  2. + +

  3. Make a new directory foobar/ which will hold the skin. +
  4. + +

  5. Copy example/Makefile.am into foobar/. + Edit it by replacing all occurrences of the string + ``example'' with ``foobar'' and the one + occurrence of the string ``ex_'' with ``fb_''. + It might be worth trying to understand this file, at least a little; you + might have to do more complicated things with it later on. In + particular, the name of the vgskin_foobar_so_SOURCES variable + determines the name of the skin's shared object, which determines what + name must be passed to the --skin option to use the skin. +
  6. + +

  7. Copy example/ex_main.c into + foobar/, renaming it as fb_main.c. + Edit it by changing the two lines in SK_(pre_clo_init)() to: +
    +    needs->name        = "foobar";
    +    needs->description = "a foobarring tool";
    + + (setting needs->description appropriately). +
  8. + +

  9. Edit Makefile.am, adding the new directory + foobar to the SUBDIRS variable. +
  10. + +

  11. Edit configure.in, adding foobar/Makefile to the + AC_OUTPUT list. +
  12. + +

  13. Run: +
    +    autogen.sh
    +    ./configure --prefix=`pwd`/inst
    +    make install
    + + It should automake, configure and compile without errors, putting copies + of the skin's shared object vgskin_foobar.so in + foobar/ and + inst/lib/valgrind/. +
  14. + +

  15. You can test it with a command like +
    +    inst/bin/valgrind --skin=foobar date
    + + (almost any program should work; date is just an example). + The output should be something like this: +
    +==738== foobar-1.1.0, a foobarring tool for x86 GNU/Linux.
    +==738== Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.
    +==738== Estimated CPU clock rate is 1400 MHz
    +==738== For more details, rerun with: -v
    +==738== 
    +Wed Sep 25 10:31:54 BST 2002
    +==738==
    + + The skin does nothing except run the program uninstrumented. +
  16. +

+ +These steps don't have to be followed exactly - you can choose different names +for your source files, and use a different --prefix for +./configure.

+ +Now that we've setup, built and tested the simplest possible skin, onto the +interesting stuff... + + + +

2.5  Writing the code

+ +A skin must define at least these four functions: +
+    SK_(pre_clo_init)()
+    SK_(post_clo_init)()
+    SK_(instrument)()
+    SK_(fini)()
+
+ +In addition, if a skin wants to use some of the optional services provided by +the core, it may have to define other functions. + + +

2.6  Initialisation

+ +Most of the initialisation should be done in SK_(pre_clo_init)(). +Only use SK_(post_clo_init)() if a skin provides command line +options and must do some initialisation after option processing takes place +(``clo'' stands for ``command line options'').

+ +The first argument to SK_(pre_clo_init)() must be initialised with +the ``needs'' for a skin. Of these, name and +description are compulsory. The rest are mostly booleans, and can +be left untouched (they default to False). They determine whether +a skin can do various things such as: record, report and suppress errors; +process command line options; wrap system calls; record extra information +about malloc'd blocks, etc.

+ +For example, if a skin wants the core's help in recording and reporting errors, +it must set the skin_errors need to True, and then +provide definitions of six functions for comparing errors, printing out errors, +reading suppressions from a suppressions file, etc. While writing these +functions requires some work, it's much less than doing error handling from +scratch because the core is doing most of the work. See the type +VgNeeds in include/vg_skin.h for full details of all +the needs.

+ +The second argument to SK_(pre_clo_init)() must be initialised to +indicate which events in core the skin wants to be notified about. These +include things such as blocks of memory being malloc'd, the stack pointer +changing, a mutex being locked, etc. If a skin wants to know about this, +it should set the relevant pointer in the structure to point to a function, +which will be called when that event happens.

+ +For example, if the skin want to be notified when a new block of memory is +malloc'd, it should set the new_mem_heap function pointer, and the +assigned function will be called each time this happens. See the type +VgTrackEvents in include/vg_skin.h for full details +of all the trackable events.

+ + +

2.7  Instrumentation

+ +SK_(instrument)() is the interesting one. It allows you to +instrument UCode, which is Valgrind's RISC-like intermediate language. +UCode is described in the technical docs. + +The easiest way to instrument UCode is to insert calls to C functions when +interesting things happen. See the skin ``lackey'' +(lackey/lk_main.c) for a simple example of this, or +Cachegrind (cachegrind/cg_main.c) for a more complex +example.

+ +A much more complicated way to instrument UCode, albeit one that might result +in faster instrumented programs, is to extend UCode with new UCode +instructions. This is recommended for advanced Valgrind hackers only! See the +``memcheck'' skin for an example. + + +

2.8  Finalisation

+ +This is where you can present the final results, such as a summary of the +information collected. Any log files should be written out at this point. + + +

2.9  Other important information

+ +Please note that the core/skin split infrastructure is all very new, and not +very well documented. Here are some important points, but there are +undoubtedly many others that I should note but haven't thought of.

+ +The file include/vg_skin.h contains all the types, +macros, functions, etc. that a skin should (hopefully) need, and is the only +.h file a skin should need to #include.

+ +In particular, you probably shouldn't use anything from the C library (there +are deep reasons for this, trust us). Valgrind provides an implementation of a +reasonable subset of the C library, details of which are in +vg_skin.h.

+ +Similarly, when writing a skin, you shouldn't need to look at any of the code +in Valgrind's core. Although it might be useful sometimes to help understand +something.

+ +vg_skin.h has a reasonable amount of documentation in it that +should hopefully be enough to get you going. But ultimately, the skins +distributed (memcheck, addrcheck, cachegrind, lackey, etc.) are probably the +best documentation of all, for the moment.

+ +Note that the VG_ and SK_ macros are used heavily. +These just prepend longer strings in front of names to avoid potential +namespace clashes. We strongly recommend using the SK_ macro +for any global functions and variables in your skin.

+ + +

2.10  Words of Advice

+ +Writing and debugging skins is not trivial. Here are some suggestions for +solving common problems.

+ +If you are getting segmentation faults in C functions used by your skin, the +usual GDB command: +

gdb prog core
+usually gives the location of the segmentation fault.

+ +If you want to debug C functions used by your skin, you can attach GDB to +Valgrind with some effort: +

+ +GDB may be able to give you useful information.

+ +If you just want to know whether a program point has been reached, using the +OINK macro (in include/vg_skin.h) can be easier than +using GDB.

+ +If you are having problems with your UCode instrumentation, it's likely that +GDB won't be able to help at all. In this case, Valgrind's +--trace-codegen option is invaluable for observing the results of +instrumentation.

+ +The other debugging command line options can be useful too (run valgrind +-h for the list).

+ + +

3  Advanced Topics

+ +Once a skin becomes more complicated, there are some extra things you may +want/need to do. + + +

3.1  Suppressions

+ +If your skin reports errors and you want to suppress some common ones, you can +add suppressions to the suppression files. The relevant files are +valgrind/*.supp; the final suppression file is aggregated from +these files by combining the relevant .supp files depending on the +versions of linux, X and glibc on a system. + +
+

3.2  Documentation

+ +If you are feeling conscientious and want to write some HTML documentation for +your skin, follow these steps (using foobar as the example skin +name again): + +
    +
  1. Make a directory foobar/docs/. +
  2. + +

  3. Edit foobar/Makefile.am, adding docs to + the SUBDIRS variable. +
  4. + +

  5. Edit configure.in, adding + foobar/docs/Makefile to the AC_OUTPUT list. +
  6. + +

  7. Write foobar/docs/Makefile.am. Use + memcheck/docs/Makefile.am as an example. +
  8. + +
  9. Write the documentation; the top-level file should be called + foobar/docs/index.html. +
  10. + +

  11. (optional) Add a link in the main documentation index + docs/index.html to + foobar/docs/index.html +
  12. +

+ +
+

3.3  Regression tests

+ +Valgrind has some support for regression tests. If you want to write +regression tests for your skin: + +
    +
  1. Make a directory foobar/tests/. +
  2. + +

  3. Edit foobar/Makefile.am, adding tests to + the SUBDIRS variable. +
  4. + +

  5. Edit configure.in, adding + foobar/tests/Makefile to the AC_OUTPUT list. +
  6. + +

  7. Write foobar/tests/Makefile.am. Use + memcheck/tests/Makefile.am as an example. +
  8. + +

  9. Write the tests, .vgtest test description files, + .stdout.exp and .stderr.exp expected output + files. (Note that Valgrind's output goes to stderr.) Some details + on writing and running tests are given in the comments at the top of the + testing script tests/vg_regtest. +
  10. + +

  11. Write a filter for stderr results foobar/tests/filter_stderr. + It can call the existing filters in tests/. See + memcheck/tests/filter_stderr for an example; in particular + note the $dir trick that ensures the filter works correctly + from any directory. +
  12. +

+ +
+

3.4  Profiling

+ +To do simple tick-based profiling of a skin, include the line +
+#include "vg_profile.c" +
+in the skin somewhere, and rebuild (you may have to make clean +first). Then run Valgrind with the --profile=yes option.

+ +The profiler is stack-based; you can register a profiling event with +VGP_(register_profile_event)() and then use the +VGP_PUSHCC and VGP_POPCC macros to record time spent +doing certain things. New profiling event numbers must not overlap with the +core profiling event numbers. See include/vg_skin.h for details +and the ``memcheck'' skin for an example. + + + +

3.5  Other makefile hackery

+ +If you add any directories under valgrind/foobar/, you will +need to add an appropriate Makefile.am to it, and add a +corresponding entry to the AC_OUTPUT list in +valgrind/configure.in.

+ +If you add any scripts to your skin (see Cachegrind for an example) you need to +add them to the bin_SCRIPTS variable in +valgrind/foobar/Makefile.am.

+ + + +

4  Final Words

+ +This whole core/skin business is very new and experimental, and under active +development.

+ +The first consequence of this is that the core/skin interface is quite +immature. It will almost certainly change in the future; we have no intention +of freezing it and then regretting the inevitable stupidities. Hopefully most +of the future changes will be to add new features, hooks, functions, etc, +rather than to change old ones, which should cause a minimum of trouble for +existing skins, but we can't guarantee it. Just something to be aware of.

+ +The second consequence of this is that we'd love to hear your feedback about +it: + +

+ +or anything else!

+ +Happy programming. + diff --git a/docs/index.html b/docs/index.html index 9db334733d..7e31b94f5d 100644 --- a/docs/index.html +++ b/docs/index.html @@ -26,8 +26,9 @@

Documentation Contents

- Core
memcheck
Cachegrind
+ Core
+ Skins
diff --git a/example/Makefile.am b/example/Makefile.am new file mode 100644 index 0000000000..3ba7f594da --- /dev/null +++ b/example/Makefile.am @@ -0,0 +1,18 @@ + +SUBDIRS = . + +CFLAGS = $(WERROR) -DVG_LIBDIR="\"$(libdir)"\" \ + -Winline -Wall -Wshadow -O -fomit-frame-pointer @PREFERRED_STACK_BOUNDARY@ -g + +valdir = $(libdir)/valgrind + +INCLUDES = -I$(top_srcdir)/include + +val_PROGRAMS = vgskin_example.so + +vgskin_example_so_SOURCES = ex_main.c +vgskin_example_so_LDFLAGS = -shared + +##vgskin_example.so$(EXEEXT): $(vgskin_example_so_OBJECTS) +## $(CC) $(CFLAGS) $(LDFLAGS) -shared -o vgskin_example.so \ +## $(vgskin_example_so_OBJECTS) diff --git a/example/ex_main.c b/example/ex_main.c new file mode 100644 index 0000000000..a9d51fd051 --- /dev/null +++ b/example/ex_main.c @@ -0,0 +1,29 @@ + +/*--------------------------------------------------------------------*/ +/*--- An example skin. ex_main.c ---*/ +/*--------------------------------------------------------------------*/ + +#include "vg_skin.h" + +void SK_(pre_clo_init)(VgNeeds* needs, VgTrackEvents* track) +{ + needs->name = "example"; + needs->description = "an example Valgrind skin"; +} + +void SK_(post_clo_init)(void) +{ +} + +UCodeBlock* SK_(instrument)(UCodeBlock* cb, Addr a) +{ + return cb; +} + +void SK_(fini)(void) +{ +} + +/*--------------------------------------------------------------------*/ +/*--- end ex_main.c ---*/ +/*--------------------------------------------------------------------*/