File: README.md

package info (click to toggle)
eztrace 2.0%2Brepack-12
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 4,132 kB
  • sloc: ansic: 23,501; perl: 910; sh: 857; cpp: 771; makefile: 696; fortran: 327; f90: 320; python: 57
file content (90 lines) | stat: -rw-r--r-- 2,549 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# 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;
}
```