ruby-usdt 0.2.0 → 0.2.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.
- checksums.yaml +4 -4
- data/ext/libusdt/LICENCE +21 -0
- data/ext/libusdt/Makefile +148 -0
- data/ext/libusdt/README.md +81 -0
- data/ext/libusdt/test.pl +112 -0
- data/ext/libusdt/test_mem_usage.c +77 -0
- data/ext/libusdt/test_usdt.c +87 -0
- data/ext/libusdt/usdt.c +296 -0
- data/ext/libusdt/usdt.h +66 -0
- data/ext/libusdt/usdt_dof.c +128 -0
- data/ext/libusdt/usdt_dof_file.c +277 -0
- data/ext/libusdt/usdt_dof_sections.c +190 -0
- data/ext/libusdt/usdt_internal.h +95 -0
- data/ext/libusdt/usdt_probe.c +74 -0
- data/ext/libusdt/usdt_tracepoints_i386.s +69 -0
- data/ext/libusdt/usdt_tracepoints_x86_64.s +123 -0
- data/lib/usdt/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 465f1aa47fc3e1464824f95cec1bfc9ffab8fd29
|
4
|
+
data.tar.gz: af101a5e965a3aa2f235b5fe7f95eff573e6d622
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 836df20d76b44ae9e03952af0016e08bd1fbfbb46ca72624e29a9f73120499c59785b700eb900a33f8d45aa625772f9f6bb376aa7858c5a896cea8e193ace051
|
7
|
+
data.tar.gz: 6844f06f4be41aa88d9b3901f3fd0b2cfe1e9ceb4e021d4edd240183512f8110239fe4d84a8dd620f89e33b4a7382bd88725824f4483e9858835422d5b669650
|
data/ext/libusdt/LICENCE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright 2012 Chris Andrews. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are
|
4
|
+
permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
1. Redistributions of source code must retain the above copyright notice, this list of
|
7
|
+
conditions and the following disclaimer.
|
8
|
+
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list
|
10
|
+
of conditions and the following disclaimer in the documentation and/or other materials
|
11
|
+
provided with the distribution.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY CHRIS ANDREWS ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
14
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CHRIS ANDREWS OR
|
16
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
17
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
18
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
19
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
20
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
21
|
+
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@@ -0,0 +1,148 @@
|
|
1
|
+
CC = gcc
|
2
|
+
CFLAGS = -O2
|
3
|
+
|
4
|
+
# MAC_BUILD - set this to "universal" to build a 2-way fat library
|
5
|
+
MAC_BUILD = universal
|
6
|
+
|
7
|
+
# if ARCH set, disable universal build on the mac
|
8
|
+
ifdef ARCH
|
9
|
+
MAC_BUILD =
|
10
|
+
else
|
11
|
+
ARCH = $(shell uname -m)
|
12
|
+
endif
|
13
|
+
|
14
|
+
UNAME = $(shell uname -s)
|
15
|
+
|
16
|
+
ifeq ($(UNAME), SunOS)
|
17
|
+
RANLIB=/bin/true
|
18
|
+
PATH +=:/usr/perl5/5.10.0/bin:/usr/perl5/5.12/bin
|
19
|
+
CFLAGS += -fPIC
|
20
|
+
|
21
|
+
ifeq ($(ARCH), i86pc)
|
22
|
+
ARCH = $(shell isainfo -k)
|
23
|
+
ifeq ($(ARCH), amd64)
|
24
|
+
ARCH = x86_64
|
25
|
+
else
|
26
|
+
ARCH = i386
|
27
|
+
endif
|
28
|
+
endif
|
29
|
+
ifeq ($(ARCH), x86_64)
|
30
|
+
CFLAGS += -m64
|
31
|
+
endif
|
32
|
+
endif
|
33
|
+
|
34
|
+
ifeq ($(UNAME), FreeBSD)
|
35
|
+
RANLIB=ranlib
|
36
|
+
CFLAGS += -Wno-error=unknown-pragmas -I/usr/src/sys/cddl/compat/opensolaris -I/usr/src/sys/cddl/contrib/opensolaris/uts/common
|
37
|
+
ifeq ($(ARCH), i386)
|
38
|
+
CFLAGS += -m32
|
39
|
+
endif
|
40
|
+
endif
|
41
|
+
|
42
|
+
ifeq ($(UNAME), Darwin)
|
43
|
+
RANLIB=ranlib
|
44
|
+
ifeq ($(MAC_BUILD), universal)
|
45
|
+
CFLAGS += -arch i386 -arch x86_64
|
46
|
+
else
|
47
|
+
CFLAGS += -arch $(ARCH)
|
48
|
+
endif
|
49
|
+
endif
|
50
|
+
|
51
|
+
# main library build
|
52
|
+
objects = usdt.o usdt_dof_file.o usdt_tracepoints.o usdt_probe.o usdt_dof.o usdt_dof_sections.o
|
53
|
+
headers = usdt.h usdt_internal.h
|
54
|
+
|
55
|
+
.c.o: $(headers)
|
56
|
+
|
57
|
+
all: libusdt.a
|
58
|
+
|
59
|
+
libusdt.a: $(objects) $(headers)
|
60
|
+
rm -f libusdt.a
|
61
|
+
$(AR) cru libusdt.a $(objects)
|
62
|
+
$(RANLIB) libusdt.a
|
63
|
+
|
64
|
+
# Tracepoints build.
|
65
|
+
#
|
66
|
+
# If on Darwin and building a universal library, manually assemble a
|
67
|
+
# two-way fat object file from both the 32 and 64 bit tracepoint asm
|
68
|
+
# files.
|
69
|
+
#
|
70
|
+
# Otherwise, just choose the appropriate asm file based on the build
|
71
|
+
# architecture.
|
72
|
+
|
73
|
+
ifeq ($(UNAME), Darwin)
|
74
|
+
ifeq ($(MAC_BUILD), universal)
|
75
|
+
|
76
|
+
usdt_tracepoints_i386.o: usdt_tracepoints_i386.s
|
77
|
+
$(CC) -arch i386 -o usdt_tracepoints_i386.o -c usdt_tracepoints_i386.s
|
78
|
+
|
79
|
+
usdt_tracepoints_x86_64.o: usdt_tracepoints_x86_64.s
|
80
|
+
$(CC) -arch x86_64 -o usdt_tracepoints_x86_64.o -c usdt_tracepoints_x86_64.s
|
81
|
+
|
82
|
+
usdt_tracepoints.o: usdt_tracepoints_i386.o usdt_tracepoints_x86_64.o
|
83
|
+
lipo -create -output usdt_tracepoints.o usdt_tracepoints_i386.o \
|
84
|
+
usdt_tracepoints_x86_64.o
|
85
|
+
|
86
|
+
else # Darwin, not universal
|
87
|
+
usdt_tracepoints.o: usdt_tracepoints_$(ARCH).s
|
88
|
+
$(CC) -arch $(ARCH) -o usdt_tracepoints.o -c usdt_tracepoints_$(ARCH).s
|
89
|
+
endif
|
90
|
+
|
91
|
+
else # not Darwin; FreeBSD and Illumos
|
92
|
+
|
93
|
+
ifeq ($(ARCH), x86_64)
|
94
|
+
usdt_tracepoints.o: usdt_tracepoints_x86_64.s
|
95
|
+
$(CC) $(CFLAGS) -o usdt_tracepoints.o -c usdt_tracepoints_x86_64.s
|
96
|
+
endif
|
97
|
+
ifeq ($(ARCH), i386)
|
98
|
+
usdt_tracepoints.o: usdt_tracepoints_i386.s
|
99
|
+
$(CC) $(CFLAGS) -o usdt_tracepoints.o -c usdt_tracepoints_i386.s
|
100
|
+
endif
|
101
|
+
|
102
|
+
endif
|
103
|
+
|
104
|
+
clean:
|
105
|
+
rm -f *.gch
|
106
|
+
rm -f *.o
|
107
|
+
rm -f libusdt.a
|
108
|
+
rm -f test_usdt
|
109
|
+
rm -f test_usdt32
|
110
|
+
rm -f test_usdt64
|
111
|
+
rm -f test_mem_usage
|
112
|
+
|
113
|
+
.PHONY: clean test
|
114
|
+
|
115
|
+
# testing
|
116
|
+
|
117
|
+
test_mem_usage: libusdt.a test_mem_usage.o
|
118
|
+
$(CC) $(CFLAGS) -o test_mem_usage test_mem_usage.o libusdt.a
|
119
|
+
|
120
|
+
ifeq ($(UNAME), Darwin)
|
121
|
+
ifeq ($(MAC_BUILD), universal)
|
122
|
+
test_usdt64: libusdt.a test_usdt.o
|
123
|
+
$(CC) -arch x86_64 -o test_usdt64 test_usdt.o libusdt.a
|
124
|
+
test_usdt32: libusdt.a test_usdt.o
|
125
|
+
$(CC) -arch i386 -o test_usdt32 test_usdt.o libusdt.a
|
126
|
+
else
|
127
|
+
test_usdt: libusdt.a test_usdt.o
|
128
|
+
$(CC) $(CFLAGS) -o test_usdt test_usdt.o libusdt.a
|
129
|
+
endif
|
130
|
+
else
|
131
|
+
test_usdt: libusdt.a test_usdt.o
|
132
|
+
$(CC) $(CFLAGS) -o test_usdt test_usdt.o libusdt.a
|
133
|
+
endif
|
134
|
+
|
135
|
+
ifeq ($(UNAME), Darwin)
|
136
|
+
ifeq ($(MAC_BUILD), universal)
|
137
|
+
test: test_usdt32 test_usdt64
|
138
|
+
sudo prove test.pl :: 64
|
139
|
+
sudo prove test.pl :: 32
|
140
|
+
else
|
141
|
+
test: test_usdt
|
142
|
+
sudo prove test.pl
|
143
|
+
endif
|
144
|
+
else
|
145
|
+
test: test_usdt
|
146
|
+
sudo prove test.pl
|
147
|
+
endif
|
148
|
+
|
@@ -0,0 +1,81 @@
|
|
1
|
+
libusdt
|
2
|
+
=======
|
3
|
+
|
4
|
+
This is "libusdt", an extraction into a C library of the common parts
|
5
|
+
of ruby-dtrace[1], perl-dtrace[2] and node-dtrace-provider[3].
|
6
|
+
|
7
|
+
Those individual language-specific implementations will then become
|
8
|
+
bindings to this library, rather than containing their own
|
9
|
+
implementations of DOF generation and probe creation. Other dynamic
|
10
|
+
language bindings could then easily follow.
|
11
|
+
|
12
|
+
The idea here is to allow the specification of a DTrace provider
|
13
|
+
dynamically in code and then create the provider at runtime. This
|
14
|
+
allows providers to be specified in dynamic languages, given suitable
|
15
|
+
bindings.
|
16
|
+
|
17
|
+
The general approach is to create two stub functions for each probe,
|
18
|
+
one for the is-enabled check and one for the probe itself. These
|
19
|
+
contain the appropriate instruction sequences to appear to DTrace as
|
20
|
+
compiled-in tracepoints. A minimal DOF document is built describing
|
21
|
+
the provider and indicating these stub functions as the tracepoints,
|
22
|
+
then submitted to the kernel, creating the provider. The API then
|
23
|
+
exposes the stubs, through which the probes may be fired.
|
24
|
+
|
25
|
+
Status
|
26
|
+
------
|
27
|
+
|
28
|
+
The implementation here works as shown in test_usdt.c on Mac OS X,
|
29
|
+
i386 and x86_64, on Solaris-like systems, i386 and x86_64 and on
|
30
|
+
FreeBSD, x86_64 only (so far).
|
31
|
+
|
32
|
+
Is-enabled probes are supported and exposed in the API.
|
33
|
+
|
34
|
+
There is a "test" target which runs a number of tests of the library,
|
35
|
+
for which perl is required.
|
36
|
+
|
37
|
+
OS X builds are Universal by default, and on Solaris, the ARCH
|
38
|
+
variable may be set to either i386 or x86_64 to force a particular
|
39
|
+
build.
|
40
|
+
|
41
|
+
FreeBSD builds suffer from broken argument handling; this is a known
|
42
|
+
issue with the current state of DTrace generally on FreeBSD: only the
|
43
|
+
first four arguments work reliably. See:
|
44
|
+
|
45
|
+
http://wiki.freebsd.org/DTraceTODO
|
46
|
+
|
47
|
+
See Also
|
48
|
+
--------
|
49
|
+
|
50
|
+
There are experimental Lua bindings available, which are a thin
|
51
|
+
layer over this library, and should serve as an example of typical use
|
52
|
+
as a dynamic language extension:
|
53
|
+
|
54
|
+
https://github.com/chrisa/lua-usdt
|
55
|
+
|
56
|
+
There are also Ruby bindings by Kevin Chan, replacing the provider
|
57
|
+
implementation in ruby-dtrace:
|
58
|
+
|
59
|
+
https://github.com/kevinykchan/ruby-usdt
|
60
|
+
|
61
|
+
To Do
|
62
|
+
-----
|
63
|
+
|
64
|
+
Platform support:
|
65
|
+
|
66
|
+
* add support for FreeBSD 9.0 i386
|
67
|
+
* add support for Mac OS X PowerPC
|
68
|
+
* add support for Solaris SPARC
|
69
|
+
|
70
|
+
Features:
|
71
|
+
|
72
|
+
* add a "low level" API, allowing alternative provision of
|
73
|
+
tracepoints for closer integration with language VMs.
|
74
|
+
|
75
|
+
* support structured types, with close integration with the host
|
76
|
+
DTrace system.
|
77
|
+
|
78
|
+
|
79
|
+
[1] https://github.com/chrisa/ruby-dtrace
|
80
|
+
[2] https://github.com/chrisa/perl-dtrace
|
81
|
+
[3] https://github.com/chrisa/node-dtrace-provider
|
data/ext/libusdt/test.pl
ADDED
@@ -0,0 +1,112 @@
|
|
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 $USDT_ARG_MAX = 32;
|
10
|
+
|
11
|
+
my $arch;
|
12
|
+
if (scalar @ARGV == 1) {
|
13
|
+
$arch = $ARGV[0];
|
14
|
+
}
|
15
|
+
|
16
|
+
my $user_t = ($^O eq 'solaris') ? 'uintptr_t' : 'user_addr_t';
|
17
|
+
|
18
|
+
run_tests('c', 'A');
|
19
|
+
run_tests('i', 1);
|
20
|
+
|
21
|
+
sub run_tests {
|
22
|
+
my ($type, $start_arg) = @_;
|
23
|
+
|
24
|
+
for my $i (0..$USDT_ARG_MAX) {
|
25
|
+
my ($t_status, $d_status, $output) = run_dtrace('func', 'name', split(//, $type x $i));
|
26
|
+
is($t_status, 0, 'test exit status is 0');
|
27
|
+
is($d_status, 0, 'dtrace exit status is 0');
|
28
|
+
like($output, qr/func:name/, 'function and name match');
|
29
|
+
|
30
|
+
my $arg = $start_arg;
|
31
|
+
for my $j (0..$i - 1) {
|
32
|
+
like($output, qr/arg$j:'\Q$arg\E'/, "type '$type' arg $j is $arg");
|
33
|
+
if ($type eq 'i') {
|
34
|
+
$arg++;
|
35
|
+
}
|
36
|
+
else {
|
37
|
+
$arg = chr(ord($arg) + 1);
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
# --------------------------------------------------------------------------
|
44
|
+
|
45
|
+
sub gen_d {
|
46
|
+
my (@types) = @_;
|
47
|
+
|
48
|
+
my $d = 'testlibusdt*:::{ ';
|
49
|
+
my $i = 0;
|
50
|
+
for my $type (@types) {
|
51
|
+
if ($type eq 'i') {
|
52
|
+
$d .= "printf(\"arg$i:'%i' \", args[$i]); ";
|
53
|
+
}
|
54
|
+
if ($type eq 'c') {
|
55
|
+
$d .= "printf(\"arg$i:'%s' \", copyinstr(($user_t)args[$i])); ";
|
56
|
+
}
|
57
|
+
$i++;
|
58
|
+
}
|
59
|
+
$d .= '}';
|
60
|
+
|
61
|
+
return $d;
|
62
|
+
}
|
63
|
+
|
64
|
+
sub run_dtrace {
|
65
|
+
my ($func, $name, @types) = @_;
|
66
|
+
my $d = gen_d(@types);
|
67
|
+
|
68
|
+
my @t_cmd;
|
69
|
+
if (defined $arch) {
|
70
|
+
@t_cmd = ("./test_usdt$arch", $func, $name, @types);
|
71
|
+
}
|
72
|
+
else {
|
73
|
+
@t_cmd = ("./test_usdt", $func, $name, @types);
|
74
|
+
}
|
75
|
+
|
76
|
+
my ($d_wtr, $d_rdr, $d_err);
|
77
|
+
my ($t_wtr, $t_rdr, $t_err);
|
78
|
+
|
79
|
+
$d_err = gensym;
|
80
|
+
$t_err = gensym;
|
81
|
+
|
82
|
+
#diag(join(' ', @t_cmd));
|
83
|
+
my $t_pid = open3($t_wtr, $t_rdr, $t_err, @t_cmd);
|
84
|
+
my $enabled = $t_rdr->getline;
|
85
|
+
|
86
|
+
my @d_cmd = ('/usr/sbin/dtrace', '-p', $t_pid, '-n', $d);
|
87
|
+
|
88
|
+
#diag(join(' ', @d_cmd));
|
89
|
+
my $d_pid = open3($d_wtr, $d_rdr, $d_err, @d_cmd);
|
90
|
+
my $matched = $d_err->getline; # expect "matched 1 probe"
|
91
|
+
|
92
|
+
$t_wtr->print("go\n");
|
93
|
+
$t_wtr->flush;
|
94
|
+
waitpid( $t_pid, 0 );
|
95
|
+
my $t_status = $? >> 8;
|
96
|
+
|
97
|
+
my ($header, $output) = ($d_rdr->getline, $d_rdr->getline);
|
98
|
+
chomp $header;
|
99
|
+
chomp $output;
|
100
|
+
#diag("DTrace header: $header\n");
|
101
|
+
#diag("DTrace output: $output\n");
|
102
|
+
waitpid( $d_pid, 0 );
|
103
|
+
|
104
|
+
my $d_status = $? >> 8;
|
105
|
+
while (!$d_err->eof) {
|
106
|
+
my $error = $d_err->getline;
|
107
|
+
chomp $error;
|
108
|
+
#diag "DTrace error: $error";
|
109
|
+
}
|
110
|
+
|
111
|
+
return ($t_status, $d_status, $output || '');
|
112
|
+
}
|
@@ -0,0 +1,77 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2012, Chris Andrews. All rights reserved.
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "usdt.h"
|
6
|
+
|
7
|
+
#include <stdio.h>
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <string.h>
|
10
|
+
|
11
|
+
static void
|
12
|
+
create_and_free_provider(int argc, char **argv)
|
13
|
+
{
|
14
|
+
usdt_provider_t *provider;
|
15
|
+
usdt_probedef_t *probedef;
|
16
|
+
|
17
|
+
if ((provider = usdt_create_provider("testlibusdt", "modname")) == NULL) {
|
18
|
+
fprintf(stderr, "unable to create provider\n");
|
19
|
+
exit (1);
|
20
|
+
}
|
21
|
+
if ((probedef = usdt_create_probe((const char *)argv[1],
|
22
|
+
(const char *)argv[2],
|
23
|
+
(argc-3), (const char **)&argv[3])) == NULL)
|
24
|
+
{
|
25
|
+
fprintf(stderr, "unable to create probe\n");
|
26
|
+
exit (1);
|
27
|
+
}
|
28
|
+
usdt_provider_add_probe(provider, probedef);
|
29
|
+
|
30
|
+
if ((usdt_provider_enable(provider)) < 0) {
|
31
|
+
fprintf(stderr, "unable to enable provider: %s\n", usdt_errstr(provider));
|
32
|
+
exit (1);
|
33
|
+
}
|
34
|
+
|
35
|
+
if ((usdt_provider_disable(provider)) < 0) {
|
36
|
+
fprintf(stderr, "unable to disable provider: %s\n", usdt_errstr(provider));
|
37
|
+
exit (1);
|
38
|
+
}
|
39
|
+
|
40
|
+
usdt_probe_release(probedef);
|
41
|
+
usdt_provider_free(provider);
|
42
|
+
}
|
43
|
+
|
44
|
+
int
|
45
|
+
main(int argc, char **argv)
|
46
|
+
{
|
47
|
+
char char_argv[USDT_ARG_MAX];
|
48
|
+
int int_argv[USDT_ARG_MAX * 2];
|
49
|
+
int i;
|
50
|
+
char buf[255];
|
51
|
+
|
52
|
+
for (i = 0; i < USDT_ARG_MAX; i++)
|
53
|
+
int_argv[i] = i + 1;
|
54
|
+
for (i = 0; i < USDT_ARG_MAX; i++)
|
55
|
+
char_argv[i] = (char) i + 65;
|
56
|
+
|
57
|
+
if (argc < 3) {
|
58
|
+
fprintf(stderr, "usage: %s func name [types ...]\n", argv[0]);
|
59
|
+
return(1);
|
60
|
+
}
|
61
|
+
|
62
|
+
for (i = 0; i < USDT_ARG_MAX; i++) {
|
63
|
+
if (argv[i+3] != NULL && i+3 < argc) {
|
64
|
+
if (strncmp("c", argv[i+3], 1) == 0) {
|
65
|
+
argv[i+3] = strdup("char *");
|
66
|
+
}
|
67
|
+
if (strncmp("i", argv[i+3], 1) == 0) {
|
68
|
+
argv[i+3] = strdup("int");
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
for (i = 0; i < 100000; i++)
|
74
|
+
create_and_free_provider(argc, argv);
|
75
|
+
|
76
|
+
return 0;
|
77
|
+
}
|