ruby-usdt 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE.md ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (C) 2012 Kevin Chan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # ruby-usdt
2
+
3
+ Ruby bindings for [libusdt](https://github.com/chrisa/libusdt).
4
+
5
+ Applications, Libraries, and Frameworks can consume ruby-usdt to define USDT
6
+ providers at runtime for instrumentation and analysis by the DTrace
7
+ [DTrace](http://en.wikipedia.org/wiki/DTrace) framework.
8
+
9
+ ### Install
10
+
11
+ gem install ruby-usdt
12
+
13
+ ### Usage
14
+
15
+ # Provider.create <provider>, <module>
16
+ #
17
+ # Creates a probe
18
+ #
19
+ # returns USDT::Provider object
20
+ provider = USDT::Provider.create :ruby, :mymod
21
+
22
+ # Provider#probe *args
23
+ #
24
+ # args must be either :integer, or :string
25
+ # max 6 args (dtrace provides this many), additional args will be ignored
26
+ # returns USDT::Probe object
27
+ p = provider.probe("myfn", "probe", :string, :string, :integer)
28
+
29
+ # Provider#enable
30
+ # enables the probes defined with #probe
31
+ provider.enable
32
+
33
+ while true
34
+ if p.enabled
35
+ p.fire("omg", "probe!!", 12345)
36
+ end
37
+ sleep 0.5
38
+ end
39
+
40
+ # see the probes in action with:
41
+ # you should see continious output of the fire args above
42
+ sudo dtrace -n 'ruby*:mymod:myfn:probe { printf("%s %s %d",
43
+ copyinstr(arg0),
44
+ copyinstr(arg1),
45
+ args[2])
46
+ }'
47
+
48
+ ## Additional Resources
49
+
50
+ - [User-Level-Statically Defined Tracing](http://www.solarisinternals.com/wiki/index.php/DTrace_Topics_USDT#USDT)
51
+ - [DTrace Book](http://www.dtracebook.com/index.php/Main_Page)
52
+ - [Libusdt - Creating DTrace Providers at Runtime](http://chrisa.github.com/blog/2011/12/04/libusdt-runtime-dtrace-providers/)
53
+
54
+ ## License
55
+
56
+ The MIT License
57
+
58
+ Copyright (C) 2012 Kevin Chan
59
+
60
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
61
+ this software and associated documentation files (the "Software"), to deal in
62
+ the Software without restriction, including without limitation the rights to
63
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
64
+ the Software, and to permit persons to whom the Software is furnished to do so,
65
+ subject to the following conditions:
66
+
67
+ The above copyright notice and this permission notice shall be included in all
68
+ copies or substantial portions of the Software.
69
+
70
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
72
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
73
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
74
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
75
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,117 @@
1
+ UNAME=$(shell uname)
2
+ ARCH=$(shell uname -m)
3
+
4
+ MAC_BUILD=universal
5
+ CFLAGS= -g -O0 -Wall -Werror
6
+ CC=cc
7
+
8
+ ifeq ($(UNAME), SunOS)
9
+ PATH +=:/usr/perl5/5.10.0/bin
10
+ ifeq ($(ARCH), x86_64)
11
+ CFLAGS += -m64
12
+ endif
13
+ endif
14
+
15
+ ifeq ($(UNAME), FreeBSD)
16
+ CFLAGS += -Wno-error=unknown-pragmas -I/usr/src/sys/cddl/compat/opensolaris -I/usr/src/sys/cddl/contrib/opensolaris/uts/common
17
+ ifeq ($(ARCH), i386)
18
+ CFLAGS += -m32
19
+ endif
20
+ endif
21
+
22
+ objects = usdt.o usdt_dof_file.o usdt_tracepoints.o usdt_probe.o usdt_dof.o usdt_dof_sections.o
23
+ headers = usdt.h usdt_internal.h
24
+
25
+ .c.o: $(headers)
26
+
27
+ all: libusdt.a
28
+
29
+ ifeq ($(UNAME), Darwin)
30
+ ifeq ($(MAC_BUILD), universal)
31
+ CFLAGS+= -arch i386 -arch x86_64
32
+
33
+ usdt_tracepoints_i386.o: usdt_tracepoints_i386.s
34
+ as -arch i386 -o usdt_tracepoints_i386.o usdt_tracepoints_i386.s
35
+
36
+ usdt_tracepoints_x86_64.o: usdt_tracepoints_x86_64.s
37
+ as -arch x86_64 -o usdt_tracepoints_x86_64.o usdt_tracepoints_x86_64.s
38
+
39
+ usdt_tracepoints.o: usdt_tracepoints_i386.o usdt_tracepoints_x86_64.o
40
+ lipo -create -output usdt_tracepoints.o usdt_tracepoints_i386.o \
41
+ usdt_tracepoints_x86_64.o
42
+ else
43
+
44
+ ifeq ($(ARCH), x86_64)
45
+ usdt_tracepoints.o: usdt_tracepoints_x86_64.s
46
+ as -o usdt_tracepoints.o usdt_tracepoints_x86_64.s
47
+ else
48
+ usdt_tracepoints.o: usdt_tracepoints_i386.s
49
+ as -o usdt_tracepoints.o usdt_tracepoints_i386.s
50
+ endif
51
+
52
+ endif
53
+ endif
54
+
55
+ ifeq ($(UNAME), FreeBSD)
56
+ ifeq ($(ARCH), amd64)
57
+ usdt_tracepoints.o: usdt_tracepoints_x86_64.s
58
+ as --64 -o usdt_tracepoints.o usdt_tracepoints_x86_64.s
59
+ else
60
+ usdt_tracepoints.o: usdt_tracepoints_i386.s
61
+ as --32 -o usdt_tracepoints.o usdt_tracepoints_i386.s
62
+ endif
63
+ endif
64
+
65
+ ifeq ($(UNAME), SunOS)
66
+ ifeq ($(ARCH), x86_64)
67
+ usdt_tracepoints.o: usdt_tracepoints_x86_64.s
68
+ as --64 -o usdt_tracepoints.o usdt_tracepoints_x86_64.s
69
+ else
70
+ usdt_tracepoints.o: usdt_tracepoints_i386.s
71
+ as --32 -o usdt_tracepoints.o usdt_tracepoints_i386.s
72
+ endif
73
+ endif
74
+
75
+ libusdt.a: $(objects) $(headers)
76
+ ar cru libusdt.a $(objects)
77
+ ranlib libusdt.a
78
+
79
+ ifeq ($(UNAME), Darwin)
80
+ ifeq ($(MAC_BUILD), universal)
81
+ test_usdt64: libusdt.a test_usdt.o
82
+ $(CC) -arch x86_64 -o test_usdt64 test_usdt.o libusdt.a
83
+ test_usdt32: libusdt.a test_usdt.o
84
+ $(CC) -arch i386 -o test_usdt32 test_usdt.o libusdt.a
85
+ else
86
+ test_usdt: libusdt.a test_usdt.o
87
+ $(CC) $(CFLAGS) -o test_usdt test_usdt.o libusdt.a
88
+ endif
89
+ else
90
+ test_usdt: libusdt.a test_usdt.o
91
+ $(CC) $(CFLAGS) -o test_usdt test_usdt.o libusdt.a
92
+ endif
93
+
94
+ clean:
95
+ rm -f *.gch
96
+ rm -f *.o
97
+ rm -f libusdt.a
98
+ rm -f fat_libusdt.a
99
+ rm -f test_usdt
100
+ rm -f test_usdt32
101
+ rm -f test_usdt64
102
+
103
+ ifeq ($(UNAME), Darwin)
104
+ ifeq ($(MAC_BUILD), universal)
105
+ test: test_usdt32 test_usdt64
106
+ sudo prove test.pl :: 64
107
+ sudo prove test.pl :: 32
108
+ else
109
+ test: test_usdt
110
+ sudo prove test.pl
111
+ endif
112
+ else
113
+ test: test_usdt
114
+ sudo prove test.pl
115
+ endif
116
+
117
+ .PHONY: clean test
@@ -0,0 +1,59 @@
1
+ This is "libusdt", an extraction into a C library of the common parts
2
+ of ruby-dtrace[1], perl-dtrace[2] and node-dtrace-provider[3].
3
+
4
+ Those individual language-specific implementations will then become
5
+ bindings to this library, rather than containing their own
6
+ implementations of DOF generation and probe creation. Other dynamic
7
+ language bindings could then easily follow.
8
+
9
+ The idea here is to allow the specification of a DTrace provider
10
+ dynamically in code and then create the provider at runtime. This
11
+ allows providers to be specified in dynamic languages, given suitable
12
+ bindings.
13
+
14
+ The general approach is to create two stub functions for each probe,
15
+ one for the is-enabled check and one for the probe itself. These
16
+ contain the appropriate instruction sequences to appear to DTrace as
17
+ compiled-in tracepoints. A minimal DOF document is built describing
18
+ the provider and indicating these stub functions as the tracepoints,
19
+ then submitted to the kernel, creating the provider. The API then
20
+ exposes the stubs, through which the probes may be fired.
21
+
22
+ Status:
23
+
24
+ The implementation here works as shown in test_usdt.c on Mac OS X,
25
+ i386 and x86_64, on Solaris-like systems, i386 and x86_64 and on
26
+ FreeBSD, x86_64 only (so far).
27
+
28
+ Is-enabled probes are supported and exposed in the API.
29
+
30
+ There is a "test" target which runs a number of tests of the library,
31
+ for which perl is required.
32
+
33
+ OS X builds are Universal by default, and on Solaris, the ARCH
34
+ variable may be set to either i386 or x86_64 to force a particular
35
+ build.
36
+
37
+ FreeBSD builds suffer from broken argument handling; this is a known
38
+ issue with the current state of DTrace generally on FreeBSD: only the
39
+ first four arguments work reliably. See:
40
+
41
+ http://wiki.freebsd.org/DTraceTODO
42
+
43
+ To do:
44
+
45
+ Platform support:
46
+
47
+ * add support for FreeBSD 9.0 i386
48
+ * add support for Mac OS X PowerPC
49
+ * add support for Solaris SPARC
50
+
51
+ Features:
52
+
53
+ * add a "low level" API, allowing alternative provision of
54
+ tracepoints for closer integration with language VMs.
55
+
56
+ [1] https://github.com/chrisa/ruby-dtrace
57
+ [2] https://github.com/chrisa/perl-dtrace
58
+ [3] https://github.com/chrisa/node-dtrace-provider
59
+
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/perl
2
+ use strict;
3
+ use warnings;
4
+ use IPC::Open3;
5
+ use Symbol 'gensym';
6
+ use IO::Handle;
7
+ use Test::More qw/ no_plan /;
8
+
9
+ my $arch;
10
+ if (scalar @ARGV == 1) {
11
+ $arch = $ARGV[0];
12
+ }
13
+
14
+ run_tests('c', 'a');
15
+ run_tests('i', 1);
16
+
17
+ sub run_tests {
18
+ my ($type, $start_arg) = @_;
19
+
20
+ for my $i (0..6) {
21
+ my ($status, $output) = run_dtrace('func', 'name', split(//, $type x $i));
22
+ is($status, 0, 'dtrace exit status is 0');
23
+ like($output, qr/func:name/, 'function and name match');
24
+
25
+ my $arg = $start_arg;
26
+ for my $j (0..$i - 1) {
27
+ like($output, qr/arg$j:'$arg'/, "type '$type' arg $j is $arg");
28
+ $arg++;
29
+ }
30
+ }
31
+ }
32
+
33
+ # --------------------------------------------------------------------------
34
+
35
+ sub gen_d {
36
+ my (@types) = @_;
37
+
38
+ my $d = 'testlibusdt*:::{ ';
39
+ my $i = 0;
40
+ for my $type (@types) {
41
+ if ($type eq 'i') {
42
+ $d .= "printf(\"arg$i:'%i' \", arg$i); ";
43
+ }
44
+ if ($type eq 'c') {
45
+ $d .= "printf(\"arg$i:'%s' \", copyinstr(arg$i)); ";
46
+ }
47
+ $i++;
48
+ }
49
+ $d .= '}';
50
+
51
+ return $d;
52
+ }
53
+
54
+ sub run_dtrace {
55
+ my ($func, $name, @types) = @_;
56
+ my $d = gen_d(@types);
57
+
58
+ my $test;
59
+ if (defined $arch) {
60
+ $test = "./test_usdt$arch $func $name " . (join ' ', @types);
61
+ }
62
+ else {
63
+ $test = "./test_usdt $func $name " . (join ' ', @types);
64
+ }
65
+
66
+ my @cmd = ('dtrace', '-Zn', $d, '-c', $test);
67
+
68
+ my ($wtr, $rdr, $err);
69
+ $err = gensym;
70
+ my $pid = open3($wtr, $rdr, $err, @cmd);
71
+
72
+ waitpid( $pid, 0 );
73
+ my $status = $? >> 8;
74
+
75
+ if ($status > 0) {
76
+ while (!$err->eof) {
77
+ print STDERR $err->getline;
78
+ }
79
+ }
80
+
81
+ my ($header, $output) = ($rdr->getline, $rdr->getline);
82
+ return ($status, $output || '');
83
+ }
@@ -0,0 +1,60 @@
1
+ #include "usdt.h"
2
+
3
+ #include <stdio.h>
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+
7
+ int main(int argc, char **argv) {
8
+ usdt_provider_t *provider;
9
+ usdt_probedef_t *probedef;
10
+ char *char_argv[6] = { "a", "b", "c", "d", "e", "f" };
11
+ int int_argv[6] = { 1, 2, 3, 4, 5, 6 };
12
+ void **args;
13
+ int i;
14
+
15
+ if (argc < 3) {
16
+ fprintf(stderr, "usage: %s func name [types ...]\n", argv[0]);
17
+ return(1);
18
+ }
19
+
20
+ if (argc > 3) {
21
+ args = malloc((argc-3) * sizeof(void *));
22
+ }
23
+
24
+ for (i = 0; i < 6; i++) {
25
+ if (argv[i+3] != NULL && i+3 < argc) {
26
+ if (strncmp("c", argv[i+3], 1) == 0) {
27
+ args[i] = (void *)char_argv[i];
28
+ argv[i+3] = strdup("char *");
29
+ }
30
+ if (strncmp("i", argv[i+3], 1) == 0) {
31
+ args[i] = (void *)(long)int_argv[i];
32
+ argv[i+3] = strdup("int");
33
+ }
34
+ }
35
+ }
36
+
37
+ if ((provider = usdt_create_provider("testlibusdt", "modname")) == NULL) {
38
+ fprintf(stderr, "unable to create provider\n");
39
+ exit (1);
40
+ }
41
+ if ((probedef = usdt_create_probe((const char *)argv[1],
42
+ (const char *)argv[2],
43
+ (argc-3), (const char **)&argv[3])) == NULL)
44
+ {
45
+ fprintf(stderr, "unable to create probe\n");
46
+ exit (1);
47
+ }
48
+ usdt_provider_add_probe(provider, probedef);
49
+
50
+ if ((usdt_provider_enable(provider)) < 0) {
51
+ fprintf(stderr, "unable to enable provider: %s\n", usdt_errstr(provider));
52
+ exit (1);
53
+ }
54
+
55
+ if (usdt_is_enabled(probedef->probe)) {
56
+ usdt_fire_probe(probedef->probe, (argc-3), (void **)args);
57
+ }
58
+
59
+ return 0;
60
+ }
@@ -0,0 +1,198 @@
1
+ #include "usdt_internal.h"
2
+
3
+ #include <stdlib.h>
4
+ #include <stdarg.h>
5
+
6
+ char *usdt_errors[] = {
7
+ "failed to allocate memory",
8
+ "failed to allocate page-aligned memory",
9
+ "no probes defined",
10
+ "failed to load DOF"
11
+ };
12
+
13
+ usdt_provider_t *
14
+ usdt_create_provider(const char *name, const char *module)
15
+ {
16
+ usdt_provider_t *provider;
17
+
18
+ if ((provider = malloc(sizeof *provider)) == NULL)
19
+ return NULL;
20
+
21
+ provider->name = strdup(name);
22
+ provider->module = strdup(module);
23
+ provider->probedefs = NULL;
24
+
25
+ return provider;
26
+ }
27
+
28
+ usdt_probedef_t *
29
+ usdt_create_probe_varargs(const char *func, const char *name, ...)
30
+ {
31
+ va_list ap;
32
+ int i;
33
+ const char *type;
34
+ usdt_probedef_t *p;
35
+
36
+ if ((p = malloc(sizeof *p)) == NULL)
37
+ return (NULL);
38
+
39
+ p->function = strdup(func);
40
+ p->name = strdup(name);
41
+
42
+ va_start(ap, name);
43
+
44
+ for (i = 0; i < 6; i++) {
45
+ if ((type = va_arg(ap, const char *)) != NULL) {
46
+ if (strncmp("char *", type, 6)) {
47
+ p->types[i] = USDT_ARGTYPE_STRING;
48
+ }
49
+ if (strncmp("int", type, 3)) {
50
+ p->types[i] = USDT_ARGTYPE_INTEGER;
51
+ }
52
+ }
53
+ else {
54
+ p->types[i] = USDT_ARGTYPE_NONE;
55
+ }
56
+ }
57
+
58
+ return (p);
59
+ }
60
+
61
+ usdt_probedef_t *
62
+ usdt_create_probe(const char *func, const char *name, size_t argc, const char **types)
63
+ {
64
+ int i;
65
+ usdt_probedef_t *p;
66
+
67
+ if ((p = malloc(sizeof *p)) == NULL)
68
+ return (NULL);
69
+
70
+ p->function = strdup(func);
71
+ p->name = strdup(name);
72
+ p->argc = argc;
73
+
74
+ for (i = 0; i < 6; i++) {
75
+ if (i < argc && types[i] != NULL) {
76
+ if (strncmp("char *", types[i], 6) == 0)
77
+ p->types[i] = USDT_ARGTYPE_STRING;
78
+ if (strncmp("int", types[i], 3) == 0)
79
+ p->types[i] = USDT_ARGTYPE_INTEGER;
80
+ }
81
+ else {
82
+ p->types[i] = USDT_ARGTYPE_NONE;
83
+ }
84
+ }
85
+
86
+ return (p);
87
+ }
88
+
89
+ void
90
+ usdt_provider_add_probe(usdt_provider_t *provider, usdt_probedef_t *probedef)
91
+ {
92
+ usdt_probedef_t *pd;
93
+
94
+ probedef->next = NULL;
95
+ if (provider->probedefs == NULL)
96
+ provider->probedefs = probedef;
97
+ else {
98
+ for (pd = provider->probedefs; (pd->next != NULL); pd = pd->next) ;
99
+ pd->next = probedef;
100
+ }
101
+ }
102
+
103
+ uint8_t
104
+ usdt_probedef_argc(usdt_probedef_t *probedef)
105
+ {
106
+ uint8_t args = 0;
107
+ uint8_t i;
108
+
109
+ for (i = 0; probedef->types[i] != USDT_ARGTYPE_NONE && i < 6; i++)
110
+ args++;
111
+
112
+ return args;
113
+ }
114
+
115
+ int
116
+ usdt_provider_enable(usdt_provider_t *provider)
117
+ {
118
+ usdt_strtab_t strtab;
119
+ usdt_dof_file_t *file;
120
+ usdt_probedef_t *pd;
121
+ int i;
122
+ size_t size;
123
+ usdt_dof_section_t sects[5];
124
+
125
+ if (provider->probedefs == NULL) {
126
+ usdt_error(provider, USDT_ERROR_NOPROBES);
127
+ return (-1);
128
+ }
129
+
130
+ for (pd = provider->probedefs; pd != NULL; pd = pd->next) {
131
+ if ((pd->probe = malloc(sizeof(*pd->probe))) == NULL) {
132
+ usdt_error(provider, USDT_ERROR_MALLOC);
133
+ return (-1);
134
+ }
135
+ }
136
+
137
+ if ((usdt_strtab_init(&strtab, 0)) < 0) {
138
+ usdt_error(provider, USDT_ERROR_MALLOC);
139
+ return (-1);
140
+ }
141
+
142
+ if ((usdt_strtab_add(&strtab, provider->name)) < 0) {
143
+ usdt_error(provider, USDT_ERROR_MALLOC);
144
+ return (-1);
145
+ }
146
+
147
+ if ((usdt_dof_probes_sect(&sects[0], provider, &strtab)) < 0)
148
+ return (-1);
149
+ if ((usdt_dof_prargs_sect(&sects[1], provider)) < 0)
150
+ return (-1);
151
+
152
+ size = usdt_provider_dof_size(provider, &strtab);
153
+ if ((file = usdt_dof_file_init(provider, size)) == NULL)
154
+ return (-1);
155
+
156
+ if ((usdt_dof_proffs_sect(&sects[2], provider, file->dof)) < 0)
157
+ return (-1);
158
+ if ((usdt_dof_prenoffs_sect(&sects[3], provider, file->dof)) < 0)
159
+ return (-1);
160
+ if ((usdt_dof_provider_sect(&sects[4], provider)) < 0)
161
+ return (-1);
162
+
163
+ for (i = 0; i < 5; i++)
164
+ usdt_dof_file_append_section(file, &sects[i]);
165
+
166
+ usdt_dof_file_generate(file, &strtab);
167
+
168
+ if ((usdt_dof_file_load(file, provider->module)) < 0) {
169
+ usdt_error(provider, USDT_ERROR_LOADDOF);
170
+ return (-1);
171
+ }
172
+
173
+ return (0);
174
+ }
175
+
176
+ int
177
+ usdt_is_enabled(usdt_probe_t *probe)
178
+ {
179
+ return (*probe->isenabled_addr)();
180
+ }
181
+
182
+ void
183
+ usdt_fire_probe(usdt_probe_t *probe, size_t argc, void **nargv)
184
+ {
185
+ usdt_probe_args(probe->probe_addr, argc, nargv);
186
+ }
187
+
188
+ void
189
+ usdt_error(usdt_provider_t *provider, usdt_error_t error)
190
+ {
191
+ provider->error = usdt_errors[error];
192
+ }
193
+
194
+ char *
195
+ usdt_errstr(usdt_provider_t *provider)
196
+ {
197
+ return (provider->error);
198
+ }
@@ -0,0 +1,50 @@
1
+ #include <stdint.h>
2
+ #include <unistd.h>
3
+
4
+ typedef uint8_t usdt_argtype_t;
5
+ #define USDT_ARGTYPE_NONE 0
6
+ #define USDT_ARGTYPE_STRING 1
7
+ #define USDT_ARGTYPE_INTEGER 2
8
+
9
+ typedef enum usdt_error {
10
+ USDT_ERROR_MALLOC = 0,
11
+ USDT_ERROR_VALLOC,
12
+ USDT_ERROR_NOPROBES,
13
+ USDT_ERROR_LOADDOF
14
+ } usdt_error_t;
15
+
16
+ typedef struct usdt_probe {
17
+ int (*isenabled_addr)(void);
18
+ void *probe_addr;
19
+ } usdt_probe_t;
20
+
21
+ int usdt_is_enabled(usdt_probe_t *probe);
22
+ void usdt_fire_probe(usdt_probe_t *probe, size_t argc, void **argv);
23
+
24
+ typedef struct usdt_probedef {
25
+ const char *name;
26
+ const char *function;
27
+ size_t argc;
28
+ usdt_argtype_t types[6];
29
+ struct usdt_probe *probe;
30
+ struct usdt_probedef *next;
31
+ } usdt_probedef_t;
32
+
33
+ usdt_probedef_t *usdt_create_probe_varargs(const char *func, const char *name, ...);
34
+ usdt_probedef_t *usdt_create_probe(const char *func, const char *name,
35
+ size_t argc, const char **types);
36
+
37
+ typedef struct usdt_provider {
38
+ const char *name;
39
+ const char *module;
40
+ usdt_probedef_t *probedefs;
41
+ char *error;
42
+ } usdt_provider_t;
43
+
44
+ usdt_provider_t *usdt_create_provider(const char *name, const char *module);
45
+ void usdt_provider_add_probe(usdt_provider_t *provider, usdt_probedef_t *probedef);
46
+ int usdt_provider_enable(usdt_provider_t *provider);
47
+
48
+ void usdt_error(usdt_provider_t *provider, usdt_error_t error);
49
+ char *usdt_errstr(usdt_provider_t *provider);
50
+