# Writing a plugin module for eztrace

## Introduction

This is an example of plugin module for eztrace.
This directory contains 2 sub-directories:


- `libexample_orig`
This is an example library with functions that we want to trace using
eztrace. This library implements two simple functions
(`example_function1` and `example_function2`).
This directory also includes a simple program that uses this library.

- `libexample_eztrace`
This directory contains an example plugin for eztrace. This plugin
allows to trace the libexample functions with eztrace.

## Creating an eztrace plugin
(see libexample_eztrace/example.c)


### Declaring a plugin

First let's give name to our plugin and declare it. This is done with a few C macros:

```
#define CURRENT_MODULE example
DECLARE_CURRENT_MODULE;
```

Then, we register the plugin to eztrace. This allows eztrace_avail to
describe available plugins, and to initialize all the plugins selected
by a user:

```
void __example_init(void) __attribute__ ((constructor));
/* Initialize the current library */
void __example_init(void) {
  EZT_REGISTER_MODULE(example, "Example module", init_example, finalize_example);
}
```

### Instrumenting functions

For recording events, eztrace relies on functions that redefines the
functions that have to be traced (eg. MPI_Send, pthread_create, etc.)
Writing a plugin module for eztrace thus boils down to redefining all
the needed functions (for example `example_function1` and
`example_function2`). Each redefined function `f` has to record an event
and to call the original `f` function. Usually such a function looks
like this:

```
int f(int arg1, double arg2)
{
  FUNCTION_ENTRY_WITH_ARGS(arg1, arg2);
  int ret = f_orig(arg1, arg2);
  FUNCTION_EXIT_WITH_ARGS(ret);
  return ret;
}
```

This function records an event, calls the original `f` function, and
records another after `f`.  In order to call the original `f`
function, we need to retrieve its address. This is done by describing the functions to be intercepted by eztrace:

```
PPTRACE_START_INTERCEPT_FUNCTIONS(example)
  INTERCEPT3("f", f_orig)
  INTERCEPT3("bar", bar_orig)
PPTRACE_END_INTERCEPT_FUNCTIONS(example);
```

This macro replace the original `f` function with the one defined in the
current module. It copies the address of the original function in the
`f_orig` variable.


We also need to provide an initialization function:
```
static void init_example() {
  INSTRUMENT_FUNCTIONS(example);

  if (eztrace_autostart_enabled())
    eztrace_start();

  __example_initialized = 1;
}
```
