ruby-dtrace 0.2.8 → 0.3.0

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.
@@ -1,3 +1,9 @@
1
+ == 0.3.0 / 2011-01-31
2
+
3
+ * Fix build on Ruby 1.8.7 (thanks to Laust Rud Jacobsen)
4
+ * Add x86_64 ports for Solaris and Mac OS X 10.6
5
+ * Add Universal build for Mac OS X /usr/bin/ruby
6
+
1
7
  == 0.2.8 / 2009-07-23
2
8
 
3
9
  * Replace string-eval provider class creation
data/README.txt CHANGED
@@ -63,12 +63,11 @@ Probes: see Dtrace::Provider
63
63
  == REQUIREMENTS
64
64
 
65
65
  * For the consumer API, platform with DTrace support (OpenSolaris, Mac
66
- OS X 10.5 Leopard tested, possibly also FreeBSD).
66
+ OS X 10.5 Leopard and 10.6 Snow Leopard tested, possibly also FreeBSD).
67
67
 
68
68
  * For the probe API, a platform with DTrace support (as for the
69
- consumer API), with a 32 bit Ruby build - i386, PowerPC (for OS X)
70
- and SPARC (for Solaris) are all supported. 64 bit builds are not,
71
- yet.
69
+ consumer API), with a 32 bit or 64 bit Ruby build - i386/x86_64,
70
+ PowerPC (for OS X) and SPARC (for Solaris) are all supported.
72
71
 
73
72
  * root, or some/all of the dtrace privileges on Solaris: dtrace_user,
74
73
  dtrace_proc and dtrace_kernel.
@@ -79,7 +78,7 @@ Probes: see Dtrace::Provider
79
78
 
80
79
  == LICENSE
81
80
 
82
- Copyright (c) 2008, 2009 Chris Andrews <chris@nodnol.org>
81
+ Copyright (c) 2008, 2009, 2011 Chris Andrews <chris@nodnol.org>
83
82
 
84
83
  Permission is hereby granted, free of charge, to any person obtaining
85
84
  a copy of this software and associated documentation files (the
File without changes
@@ -4,63 +4,65 @@ SHELL = /bin/sh
4
4
  #### Start of system configuration section. ####
5
5
 
6
6
  srcdir = .
7
- topdir = /opt/local/lib/ruby/1.8/i686-darwin9.7.0
7
+ topdir = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0
8
8
  hdrdir = $(topdir)
9
9
  VPATH = $(srcdir):$(topdir):$(hdrdir)
10
- prefix = $(DESTDIR)/opt/local
11
10
  exec_prefix = $(prefix)
12
- sitedir = $(prefix)/lib/ruby/site_ruby
13
- rubylibdir = $(libdir)/ruby/$(ruby_version)
14
- docdir = $(datarootdir)/doc/$(PACKAGE)
15
- dvidir = $(docdir)
16
- datarootdir = $(prefix)/share
17
- archdir = $(rubylibdir)/$(arch)
18
- sbindir = $(exec_prefix)/sbin
11
+ prefix = $(DESTDIR)/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr
12
+ sharedstatedir = $(prefix)/com
13
+ mandir = $(DESTDIR)/usr/share/man
19
14
  psdir = $(docdir)
20
- vendordir = $(prefix)/lib/ruby/vendor_ruby
15
+ oldincludedir = $(DESTDIR)/usr/include
21
16
  localedir = $(datarootdir)/locale
17
+ bindir = $(exec_prefix)/bin
18
+ libexecdir = $(exec_prefix)/libexec
19
+ sitedir = $(DESTDIR)/Library/Ruby/Site
22
20
  htmldir = $(docdir)
23
- datadir = $(datarootdir)
21
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
24
22
  includedir = $(prefix)/include
25
- infodir = $(datarootdir)/info
23
+ infodir = $(DESTDIR)/usr/share/info
24
+ vendorlibdir = $(vendordir)/$(ruby_version)
26
25
  sysconfdir = $(prefix)/etc
27
26
  libdir = $(exec_prefix)/lib
28
- mandir = $(DESTDIR)/opt/local/share/man
29
- sharedstatedir = $(prefix)/com
30
- oldincludedir = $(DESTDIR)/usr/include
27
+ sbindir = $(exec_prefix)/sbin
28
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
29
+ docdir = $(datarootdir)/doc/$(PACKAGE)
30
+ dvidir = $(docdir)
31
+ vendordir = $(libdir)/ruby/vendor_ruby
32
+ datarootdir = $(prefix)/share
31
33
  pdfdir = $(docdir)
34
+ archdir = $(rubylibdir)/$(arch)
32
35
  sitearchdir = $(sitelibdir)/$(sitearch)
33
- vendorarchdir = $(vendorlibdir)/$(vendorarch)
36
+ datadir = $(datarootdir)
34
37
  localstatedir = $(prefix)/var
35
- bindir = $(exec_prefix)/bin
36
- vendorlibdir = $(vendordir)/$(ruby_version)
37
38
  sitelibdir = $(sitedir)/$(ruby_version)
38
- libexecdir = $(exec_prefix)/libexec
39
39
 
40
- CC = /usr/bin/gcc-4.0
40
+ CC = gcc
41
41
  LIBRUBY = $(LIBRUBY_SO)
42
42
  LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
43
43
  LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
44
- LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
44
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)
45
45
 
46
46
  RUBY_EXTCONF_H =
47
- CFLAGS = -fno-common -O2 -fno-common -pipe -fno-common -D_LONGLONG_TYPE -g
47
+ CFLAGS = -fno-common -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common $(cflags) -D_LONGLONG_TYPE -g
48
48
  INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
49
49
  DEFS =
50
- CPPFLAGS = -DHAVE_SYS_DTRACE_H -I/opt/local/include $(DEFS)
50
+ CPPFLAGS = -DHAVE_SYS_DTRACE_H -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags)
51
51
  CXXFLAGS = $(CFLAGS)
52
- DLDFLAGS = -L. -L/opt/local/lib
53
- LDSHARED = cc -dynamic -bundle -undefined suppress -flat_namespace
52
+ ldflags = -L. -arch i386 -arch x86_64
53
+ dldflags =
54
+ archflag =
55
+ DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
56
+ LDSHARED = cc -arch i386 -arch x86_64 -pipe -bundle -undefined dynamic_lookup
54
57
  AR = ar
55
58
  EXEEXT =
56
59
 
57
60
  RUBY_INSTALL_NAME = ruby
58
61
  RUBY_SO_NAME = ruby
59
- arch = i686-darwin9.7.0
60
- sitearch = i686-darwin9.7.0
61
- vendorarch = i686-darwin9.7.0
62
+ arch = universal-darwin10.0
63
+ sitearch = universal-darwin10.0
62
64
  ruby_version = 1.8
63
- ruby = /opt/local/bin/ruby
65
+ ruby = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
64
66
  RUBY = $(ruby)
65
67
  RM = rm -f
66
68
  MAKEDIRS = mkdir -p
@@ -84,7 +86,7 @@ extout =
84
86
  extout_prefix =
85
87
  target_prefix =
86
88
  LOCAL_LIBS =
87
- LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl -lobjc
89
+ LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl
88
90
  SRCS = constants.c dof_api.c dof_helper.c file.c generator.c header.c parser.c section.c
89
91
  OBJS = constants.o dof_api.o dof_helper.o file.o generator.o header.o parser.o section.o
90
92
  TARGET = dof_api
@@ -92,6 +94,7 @@ DLLIB = $(TARGET).bundle
92
94
  EXTSTATIC =
93
95
  STATIC_LIB =
94
96
 
97
+ BINDIR = $(bindir)
95
98
  RUBYCOMMONDIR = $(sitedir)$(target_prefix)
96
99
  RUBYLIBDIR = $(sitelibdir)$(target_prefix)
97
100
  RUBYARCHDIR = $(sitearchdir)$(target_prefix)
@@ -145,7 +148,7 @@ site-install-rb: install-rb
145
148
  .c.o:
146
149
  $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
147
150
 
148
- $(DLLIB): $(OBJS) Makefile
151
+ $(DLLIB): $(OBJS)
149
152
  @-$(RM) $@
150
153
  $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
151
154
 
@@ -145,7 +145,7 @@ _dof_parse_dof_probe_t_array(VALUE self, char *dof, dof_sec_t *sec)
145
145
  count++;
146
146
 
147
147
  probe_data = rb_hash_new();
148
- sprintf(addr_str, "%p", probe.dofpr_addr);
148
+ sprintf(addr_str, "%p", (void *)probe.dofpr_addr);
149
149
  rb_hash_aset(probe_data, ID2SYM(rb_intern("addr")), rb_str_new2(addr_str));
150
150
  rb_hash_aset(probe_data, ID2SYM(rb_intern("func")), rb_hash_aref(strtab, INT2FIX(probe.dofpr_func)));
151
151
  rb_hash_aset(probe_data, ID2SYM(rb_intern("name")), rb_hash_aref(strtab, INT2FIX(probe.dofpr_name)));
@@ -69,12 +69,12 @@ VALUE dof_generate_probes(VALUE self) {
69
69
  dof_probe_t p;
70
70
  memset(&p, 0, sizeof(p));
71
71
 
72
- p.dofpr_addr = (uint64_t)FIX2INT(rb_hash_aref(probe, ID2SYM(rb_intern("addr"))));
72
+ p.dofpr_addr = (uint64_t)NUM2LL(rb_hash_aref(probe, ID2SYM(rb_intern("addr"))));
73
73
  p.dofpr_func = (dof_stridx_t)FIX2INT(rb_hash_aref(probe, ID2SYM(rb_intern("func"))));
74
74
  p.dofpr_name = (dof_stridx_t)FIX2INT(rb_hash_aref(probe, ID2SYM(rb_intern("name"))));
75
75
  p.dofpr_nargv = (dof_stridx_t)FIX2INT(rb_hash_aref(probe, ID2SYM(rb_intern("nargv"))));
76
76
  p.dofpr_xargv = (dof_stridx_t)FIX2INT(rb_hash_aref(probe, ID2SYM(rb_intern("xargv"))));
77
-
77
+
78
78
  p.dofpr_argidx = (uint32_t)FIX2INT(rb_hash_aref(probe, ID2SYM(rb_intern("argidx"))));
79
79
  p.dofpr_offidx = (uint32_t)FIX2INT(rb_hash_aref(probe, ID2SYM(rb_intern("offidx"))));
80
80
  p.dofpr_nargc = (uint8_t)FIX2INT(rb_hash_aref(probe, ID2SYM(rb_intern("nargc"))));
@@ -77,7 +77,7 @@ VALUE dtrace_hdl_alloc(VALUE klass)
77
77
  return obj;
78
78
  }
79
79
  else {
80
- rb_raise(eDtraceException, "unable to open dtrace (not root?)");
80
+ rb_raise(eDtraceException, "unable to open dtrace: %s (not root?)", strerror(err));
81
81
  }
82
82
  }
83
83
 
@@ -440,7 +440,10 @@ VALUE dtrace_hdl_work(int argc, VALUE *argv, VALUE self)
440
440
  handlers.rec = rec_consumer;
441
441
  handlers.handle = self;
442
442
 
443
- status = dtrace_work(handle->hdl, NULL, _probe_consumer, _rec_consumer, &handlers);
443
+ FILE *devnull = fopen("/dev/null", "w");
444
+ status = dtrace_work(handle->hdl, devnull, _probe_consumer, _rec_consumer, &handlers);
445
+ fclose(devnull);
446
+
444
447
  if (status < 0)
445
448
  rb_raise(eDtraceException, (dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl))));
446
449
 
@@ -0,0 +1,10 @@
1
+ /* Ruby-Dtrace
2
+ * (c) 2008-2011 Chris Andrews <chris@nodnol.org>
3
+ */
4
+
5
+ /*
6
+ * dtrace_probe.c is built for the target architecture from one of the
7
+ * variants in the per-arch subdirectories. See extconf.rb for build
8
+ * details.
9
+ *
10
+ */
@@ -1,29 +1,72 @@
1
1
  require 'mkmf'
2
2
  require 'rbconfig'
3
3
 
4
- def symlink(old, new)
5
- begin
6
- File.symlink(old, new)
7
- rescue Errno::EEXIST
8
- File.unlink(new)
9
- retry
10
- end
11
- end
4
+ $CFLAGS += " -D_LONGLONG_TYPE"
12
5
 
13
- $CFLAGS += " -D_LONGLONG_TYPE -g"
14
- have_library("dtrace", "dtrace_open")
6
+ # Need to specify full path to dtrace.h or we'll pick up ruby's
7
+ # dtrace.h on Solaris or other builds with the runtime probes included.
8
+ have_library("dtrace", "dtrace_open", "/usr/include/dtrace.h")
15
9
 
16
- # Update machine-dependent symlinks in the source, based on $Config::CONFIG and `uname -p`
10
+ # Figure out target platform
17
11
  os = Config::CONFIG['target_os']
18
12
  os.gsub! /[0-9.]+$/, ''
19
13
 
20
- # On OSX, this is "powerpc", even on Intel...
21
- #cpu = Config::CONFIG['target_cpu']
14
+ # Snow Leopard handling: detect Universal build and invoke dual build of dtrace_probe.c
22
15
  cpu = `uname -p`.chomp
16
+ if cpu == "i386"
17
+ ldflags = Config::CONFIG['LDFLAGS']
18
+ if ldflags =~ /i386/ && ldflags =~ /x86_64/
19
+ puts "Universal build detected"
20
+ apple_universal = true
21
+ end
22
+ end
23
+
24
+ arch = "#{cpu}-#{os}"
23
25
 
24
- dir = "#{cpu}-#{os}"
25
- symlink "#{dir}/dtrace_probe.c", "dtrace_probe.c"
26
+ # Set up generated Makefile to build everything except dtrace_probe.c
27
+ $srcs = %w{ dtrace_aggdata.c
28
+ dtrace_dropdata.c
29
+ dtrace_process.c
30
+ dtrace_recdesc.c
31
+ dtrace_api.c
32
+ dtrace_errdata.c
33
+ dtrace_probedata.c
34
+ dtrace_program.c
35
+ dtrace_util.c
36
+ dtrace_bufdata.c
37
+ dtrace_hdl.c
38
+ dtrace_probedesc.c
39
+ dtrace_programinfo.c
40
+ }
41
+
42
+ $objs = []
43
+ for f in $srcs
44
+ obj = File.basename(f, ".*") << ".o"
45
+ $objs.push(obj)
46
+ end
47
+
48
+ $objs.push "dtrace_probe.o"
26
49
 
27
50
  # Create makefile in the usual way
28
51
  create_makefile("dtrace_api")
29
52
 
53
+ # Then append rule(s) to create dtrace_probe.c
54
+ begin
55
+ mfile = open("Makefile", "ab")
56
+ mfile.puts
57
+
58
+ if apple_universal
59
+ # create i386 .o and x86_64.o
60
+ mfile.print "dtrace_probe_i386-darwin.o:\n\t$(CC) $(INCFLAGS) -arch i386 -o dtrace_probe_i386-darwin.o -c i386-darwin/dtrace_probe.c\n\n"
61
+ mfile.print "dtrace_probe_x86_64-darwin.o:\n\t$(CC) $(INCFLAGS) -arch x86_64 -o dtrace_probe_x86_64-darwin.o -c x86_64-darwin/dtrace_probe.c\n\n"
62
+
63
+ # link those into a universal dtrace_probe.o
64
+ mfile.print "dtrace_probe.o: dtrace_probe_i386-darwin.o dtrace_probe_x86_64-darwin.o\n" +
65
+ "\tlipo -create -output dtrace_probe.o dtrace_probe_x86_64-darwin.o dtrace_probe_i386-darwin.o"
66
+ else
67
+ # just selected arch
68
+ mfile.print "dtrace_probe.o:\n\t$(CC) $(INCFLAGS) $(CXXFLAGS) -c #{arch}/dtrace_probe.c\n\n"
69
+ end
70
+ ensure
71
+ mfile.close
72
+ end
@@ -250,8 +250,8 @@ VALUE dtraceprobe_probe_offset(VALUE self, VALUE file_addr, VALUE argc)
250
250
  {
251
251
  void *probe_addr;
252
252
  int offset;
253
- probe_addr = (void *)FIX2INT(rb_funcall(self, rb_intern("addr"), 0));
254
- switch FIX2INT(argc) {
253
+ probe_addr = (void *)FIX2UINT(rb_funcall(self, rb_intern("addr"), 0));
254
+ switch (FIX2INT(argc)) {
255
255
  case 0:
256
256
  offset = 40; /* 32 + 6 + 2 */
257
257
  break;
@@ -262,7 +262,7 @@ VALUE dtraceprobe_probe_offset(VALUE self, VALUE file_addr, VALUE argc)
262
262
  offset = 46 + (FIX2INT(argc)-1) * 7; /* 32 + 6 + 6 + 7 per subsequent arg + 2 */
263
263
  break;
264
264
  }
265
- return INT2FIX((int)probe_addr - (int)FIX2INT(file_addr) + offset);
265
+ return INT2FIX((uint32_t)probe_addr - (uint32_t)FIX2UINT(file_addr) + offset);
266
266
  }
267
267
 
268
268
  /*
@@ -0,0 +1,470 @@
1
+ /* Ruby-Dtrace
2
+ * (c) 2008 Chris Andrews <chris@nodnol.org>
3
+ */
4
+
5
+ #include "dtrace_api.h"
6
+
7
+ #include <errno.h>
8
+ #include <stdlib.h>
9
+ #include <sys/mman.h>
10
+
11
+ RUBY_EXTERN VALUE eDtraceException;
12
+
13
+ #define FUNC_SIZE 256
14
+ #define IS_ENABLED_FUNC_LEN 32
15
+
16
+ void install_insns(uint8_t *probe_insns, uint8_t *insns, int count)
17
+ {
18
+ int i,j;
19
+ uint8_t *ip;
20
+ ip = insns;
21
+ for (j = 1; j <= count; j++) {
22
+ for (i = 0; i < 4; i++) {
23
+ *ip++ = *probe_insns++;
24
+ }
25
+ }
26
+ }
27
+
28
+ /* :nodoc: */
29
+ VALUE dtraceprobe_init(VALUE self, VALUE rargc)
30
+ {
31
+ dtrace_probe_t *probe;
32
+ uint8_t *ip;
33
+ int i;
34
+ int argc = FIX2INT(rargc);
35
+ uint8_t probe_insns[FUNC_SIZE];
36
+
37
+ Data_Get_Struct(self, dtrace_probe_t, probe);
38
+
39
+ /* First initialise the is_enabled tracepoint */
40
+ uint8_t insns[FUNC_SIZE] = {
41
+ /* stmw r30,0xfff8(r1) */
42
+ 0xbf, 0xc1, 0xff, 0xf8,
43
+ /* stwu r1,0xffd0(r1) */
44
+ 0x94, 0x21, 0xff, 0xd0,
45
+ /* or r30,r1,r1 */
46
+ 0x7c, 0x3e, 0x0b, 0x78,
47
+ /* li r0,0x0 */
48
+ 0x38, 0x00, 0x00, 0x00,
49
+ /* or r3,r0,r0 */
50
+ 0x7c, 0x03, 0x03, 0x78,
51
+ /* lwz r1,0x0(r1) */
52
+ 0x80, 0x21, 0x00, 0x00,
53
+ /* lmw r30,0xfff8(r1) */
54
+ 0xbb, 0xc1, 0xff, 0xf8,
55
+ /* blr */
56
+ 0x4e, 0x80, 0x00, 0x20
57
+ };
58
+
59
+ /* Now build probe tracepoint */
60
+ switch (argc) {
61
+
62
+ case 0:
63
+ {
64
+ uint8_t probe_insns[FUNC_SIZE] = {
65
+ /* stmw r30,0xfff8(r1) */
66
+ 0xbf, 0xc1, 0xff, 0xf8,
67
+ /* stwu r1,0xffd0(r1) */
68
+ 0x94, 0x21, 0xff, 0xd0,
69
+ /* or r30,r1,r1 */
70
+ 0x7c, 0x3e, 0x0b, 0x78,
71
+ /* lwz r1,0x0(r1) */
72
+ 0x80, 0x21, 0x00, 0x00,
73
+ /* lmw r30,0xfff8(r1) */
74
+ 0xbb, 0xc1, 0xff, 0xf8,
75
+ /* blr */
76
+ 0x4e, 0x80, 0x00, 0x20
77
+ };
78
+ install_insns(probe_insns, &insns[IS_ENABLED_FUNC_LEN], 6);
79
+ }
80
+ break;
81
+
82
+ case 1:
83
+ {
84
+ uint8_t probe_insns[FUNC_SIZE] = {
85
+ /* stmw r30,0xfff8(r1) */
86
+ 0xbf, 0xc1, 0xff, 0xf8,
87
+ /* stwu r1,0xffd0(r1) */
88
+ 0x94, 0x21, 0xff, 0xd0,
89
+ /* or r30,r1,r1 */
90
+ 0x7c, 0x3e, 0x0b, 0x78,
91
+ /* stw r3,0x48(r30) */
92
+ 0x90, 0x7e, 0x00, 0x48,
93
+ /* lwz r1,0x0(r1) */
94
+ 0x80, 0x21, 0x00, 0x00,
95
+ /* lmw r30,0xfff8(r1) */
96
+ 0xbb, 0xc1, 0xff, 0xf8,
97
+ /* blr */
98
+ 0x4e, 0x80, 0x00, 0x20
99
+ };
100
+ install_insns(probe_insns, &insns[IS_ENABLED_FUNC_LEN], 7);
101
+ }
102
+ break;
103
+
104
+ case 2:
105
+ {
106
+ uint8_t probe_insns[FUNC_SIZE] = {
107
+ /* stmw r30,0xfff8(r1) */
108
+ 0xbf, 0xc1, 0xff, 0xf8,
109
+ /* stwu r1,0xffd0(r1) */
110
+ 0x94, 0x21, 0xff, 0xd0,
111
+ /* or r30,r1,r1 */
112
+ 0x7c, 0x3e, 0x0b, 0x78,
113
+ /* stw r3,0x48(r30) */
114
+ 0x90, 0x7e, 0x00, 0x48,
115
+ /* stw r4,0x4c(r30) */
116
+ 0x90, 0x9e, 0x00, 0x4c,
117
+ /* lwz r1,0x0(r1) */
118
+ 0x80, 0x21, 0x00, 0x00,
119
+ /* lmw r30,0xfff8(r1) */
120
+ 0xbb, 0xc1, 0xff, 0xf8,
121
+ /* blr */
122
+ 0x4e, 0x80, 0x00, 0x20
123
+ };
124
+ install_insns(probe_insns, &insns[IS_ENABLED_FUNC_LEN], 8);
125
+ }
126
+ break;
127
+
128
+ case 3:
129
+ {
130
+ uint8_t probe_insns[FUNC_SIZE] = {
131
+ /* stmw r30,0xfff8(r1) */
132
+ 0xbf, 0xc1, 0xff, 0xf8,
133
+ /* stwu r1,0xffd0(r1) */
134
+ 0x94, 0x21, 0xff, 0xd0,
135
+ /* or r30,r1,r1 */
136
+ 0x7c, 0x3e, 0x0b, 0x78,
137
+ /* stw r3,0x48(r30) */
138
+ 0x90, 0x7e, 0x00, 0x48,
139
+ /* stw r4,0x4c(r30) */
140
+ 0x90, 0x9e, 0x00, 0x4c,
141
+ /* stw r5,0x50(r30) */
142
+ 0x90, 0xbe, 0x00, 0x50,
143
+ /* lwz r1,0x0(r1) */
144
+ 0x80, 0x21, 0x00, 0x00,
145
+ /* lmw r30,0xfff8(r1) */
146
+ 0xbb, 0xc1, 0xff, 0xf8,
147
+ /* blr */
148
+ 0x4e, 0x80, 0x00, 0x20
149
+ };
150
+ install_insns(probe_insns, &insns[IS_ENABLED_FUNC_LEN], 9);
151
+ }
152
+ break;
153
+
154
+ case 4:
155
+ {
156
+ uint8_t probe_insns[FUNC_SIZE] = {
157
+ /* stmw r30,0xfff8(r1) */
158
+ 0xbf, 0xc1, 0xff, 0xf8,
159
+ /* stwu r1,0xffd0(r1) */
160
+ 0x94, 0x21, 0xff, 0xd0,
161
+ /* or r30,r1,r1 */
162
+ 0x7c, 0x3e, 0x0b, 0x78,
163
+ /* stw r3,0x48(r30) */
164
+ 0x90, 0x7e, 0x00, 0x48,
165
+ /* stw r4,0x4c(r30) */
166
+ 0x90, 0x9e, 0x00, 0x4c,
167
+ /* stw r5,0x50(r30) */
168
+ 0x90, 0xbe, 0x00, 0x50,
169
+ /* stw r5,0x50(r30) */
170
+ 0x90, 0xde, 0x00, 0x54,
171
+ /* lwz r1,0x0(r1) */
172
+ 0x80, 0x21, 0x00, 0x00,
173
+ /* lmw r30,0xfff8(r1) */
174
+ 0xbb, 0xc1, 0xff, 0xf8,
175
+ /* blr */
176
+ 0x4e, 0x80, 0x00, 0x20
177
+ };
178
+ install_insns(probe_insns, &insns[IS_ENABLED_FUNC_LEN], 10);
179
+ }
180
+ break;
181
+
182
+ case 5:
183
+ {
184
+ uint8_t probe_insns[FUNC_SIZE] = {
185
+ /* stmw r30,0xfff8(r1) */
186
+ 0xbf, 0xc1, 0xff, 0xf8,
187
+ /* stwu r1,0xffd0(r1) */
188
+ 0x94, 0x21, 0xff, 0xd0,
189
+ /* or r30,r1,r1 */
190
+ 0x7c, 0x3e, 0x0b, 0x78,
191
+ /* stw r3,0x48(r30) */
192
+ 0x90, 0x7e, 0x00, 0x48,
193
+ /* stw r4,0x4c(r30) */
194
+ 0x90, 0x9e, 0x00, 0x4c,
195
+ /* stw r5,0x50(r30) */
196
+ 0x90, 0xbe, 0x00, 0x50,
197
+ /* stw r6,0x54(r30) */
198
+ 0x90, 0xde, 0x00, 0x54,
199
+ /* stw r7,0x58(r30) */
200
+ 0x90, 0xfe, 0x00, 0x58,
201
+ /* lwz r1,0x0(r1) */
202
+ 0x80, 0x21, 0x00, 0x00,
203
+ /* lmw r30,0xfff8(r1) */
204
+ 0xbb, 0xc1, 0xff, 0xf8,
205
+ /* blr */
206
+ 0x4e, 0x80, 0x00, 0x20
207
+ };
208
+ install_insns(probe_insns, &insns[IS_ENABLED_FUNC_LEN], 11);
209
+ }
210
+ break;
211
+
212
+ case 6:
213
+ {
214
+ uint8_t probe_insns[FUNC_SIZE] = {
215
+ /* stmw r30,0xfff8(r1) */
216
+ 0xbf, 0xc1, 0xff, 0xf8,
217
+ /* stwu r1,0xffd0(r1) */
218
+ 0x94, 0x21, 0xff, 0xd0,
219
+ /* or r30,r1,r1 */
220
+ 0x7c, 0x3e, 0x0b, 0x78,
221
+ /* stw r3,0x48(r30) */
222
+ 0x90, 0x7e, 0x00, 0x48,
223
+ /* stw r4,0x4c(r30) */
224
+ 0x90, 0x9e, 0x00, 0x4c,
225
+ /* stw r5,0x50(r30) */
226
+ 0x90, 0xbe, 0x00, 0x50,
227
+ /* stw r6,0x54(r30) */
228
+ 0x90, 0xde, 0x00, 0x54,
229
+ /* stw r7,0x58(r30) */
230
+ 0x90, 0xfe, 0x00, 0x58,
231
+ /* stw r8,0x5c(r30) */
232
+ 0x91, 0x1e, 0x00, 0x5c,
233
+ /* lwz r1,0x0(r1) */
234
+ 0x80, 0x21, 0x00, 0x00,
235
+ /* lmw r30,0xfff8(r1) */
236
+ 0xbb, 0xc1, 0xff, 0xf8,
237
+ /* blr */
238
+ 0x4e, 0x80, 0x00, 0x20
239
+ };
240
+ install_insns(probe_insns, &insns[IS_ENABLED_FUNC_LEN], 12);
241
+ }
242
+ break;
243
+
244
+ case 7:
245
+ {
246
+ uint8_t probe_insns[FUNC_SIZE] = {
247
+ /* stmw r30,0xfff8(r1) */
248
+ 0xbf, 0xc1, 0xff, 0xf8,
249
+ /* stwu r1,0xffd0(r1) */
250
+ 0x94, 0x21, 0xff, 0xd0,
251
+ /* or r30,r1,r1 */
252
+ 0x7c, 0x3e, 0x0b, 0x78,
253
+ /* stw r3,0x48(r30) */
254
+ 0x90, 0x7e, 0x00, 0x48,
255
+ /* stw r4,0x4c(r30) */
256
+ 0x90, 0x9e, 0x00, 0x4c,
257
+ /* stw r5,0x50(r30) */
258
+ 0x90, 0xbe, 0x00, 0x50,
259
+ /* stw r6,0x54(r30) */
260
+ 0x90, 0xde, 0x00, 0x54,
261
+ /* stw r7,0x58(r30) */
262
+ 0x90, 0xfe, 0x00, 0x58,
263
+ /* stw r8,0x5c(r30) */
264
+ 0x91, 0x1e, 0x00, 0x5c,
265
+ /* stw r9,0x60(r30) */
266
+ 0x91, 0x3e, 0x00, 0x60,
267
+ /* lwz r1,0x0(r1) */
268
+ 0x80, 0x21, 0x00, 0x00,
269
+ /* lmw r30,0xfff8(r1) */
270
+ 0xbb, 0xc1, 0xff, 0xf8,
271
+ /* blr */
272
+ 0x4e, 0x80, 0x00, 0x20
273
+ };
274
+ install_insns(probe_insns, &insns[IS_ENABLED_FUNC_LEN], 13);
275
+ }
276
+ break;
277
+
278
+ case 8:
279
+ {
280
+ uint8_t probe_insns[FUNC_SIZE] = {
281
+ /* stmw r30,0xfff8(r1) */
282
+ 0xbf, 0xc1, 0xff, 0xf8,
283
+ /* stwu r1,0xffd0(r1) */
284
+ 0x94, 0x21, 0xff, 0xd0,
285
+ /* or r30,r1,r1 */
286
+ 0x7c, 0x3e, 0x0b, 0x78,
287
+ /* stw r3,0x48(r30) */
288
+ 0x90, 0x7e, 0x00, 0x48,
289
+ /* stw r4,0x4c(r30) */
290
+ 0x90, 0x9e, 0x00, 0x4c,
291
+ /* stw r5,0x50(r30) */
292
+ 0x90, 0xbe, 0x00, 0x50,
293
+ /* stw r6,0x54(r30) */
294
+ 0x90, 0xde, 0x00, 0x54,
295
+ /* stw r7,0x58(r30) */
296
+ 0x90, 0xfe, 0x00, 0x58,
297
+ /* stw r8,0x5c(r30) */
298
+ 0x91, 0x1e, 0x00, 0x5c,
299
+ /* stw r9,0x60(r30) */
300
+ 0x91, 0x3e, 0x00, 0x60,
301
+ /* stw r10,0x64(r30) */
302
+ 0x91, 0x5e, 0x00, 0x64,
303
+ /* lwz r1,0x0(r1) */
304
+ 0x80, 0x21, 0x00, 0x00,
305
+ /* lmw r30,0xfff8(r1) */
306
+ 0xbb, 0xc1, 0xff, 0xf8,
307
+ /* blr */
308
+ 0x4e, 0x80, 0x00, 0x20
309
+ };
310
+ install_insns(probe_insns, &insns[IS_ENABLED_FUNC_LEN], 14);
311
+ }
312
+ break;
313
+
314
+ default:
315
+ rb_raise(eDtraceException, "probe argc max is 8");
316
+ return Qnil;
317
+ break;
318
+ }
319
+
320
+ /* allocate memory on a page boundary, for mprotect */
321
+ probe->func = (void *)valloc(FUNC_SIZE);
322
+ if (probe->func < 0) {
323
+ rb_raise(eDtraceException, "malloc failed: %s\n", strerror(errno));
324
+ return Qnil;
325
+ }
326
+
327
+ if ((mprotect((void *)probe->func, FUNC_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC)) < 0) {
328
+ rb_raise(eDtraceException, "mprotect failed: %s\n", strerror(errno));
329
+ return Qnil;
330
+ }
331
+
332
+ if ((memcpy(probe->func, insns, FUNC_SIZE)) < 0) {
333
+ rb_raise(eDtraceException, "memcpy failed: %s\n", strerror(errno));
334
+ return Qnil;
335
+ }
336
+
337
+ return self;
338
+ }
339
+
340
+ VALUE dtraceprobe_free(void *arg)
341
+ {
342
+ dtrace_probe_t *probe = (dtrace_probe_t *)arg;
343
+
344
+ if (probe) {
345
+ free(probe);
346
+ }
347
+ }
348
+
349
+ VALUE dtraceprobe_alloc(VALUE klass)
350
+ {
351
+ VALUE obj;
352
+ dtrace_probe_t *probe;
353
+
354
+ probe = ALLOC(dtrace_probe_t);
355
+ if (!probe) {
356
+ rb_raise(eDtraceException, "alloc failed");
357
+ return Qnil;
358
+ }
359
+
360
+ /* no mark function: no ruby objects hung off this struct */
361
+ obj = Data_Wrap_Struct(klass, NULL, dtraceprobe_free, probe);
362
+ return obj;
363
+ }
364
+
365
+ VALUE dtraceprobe_addr(VALUE self)
366
+ {
367
+ dtrace_probe_t *probe;
368
+
369
+ Data_Get_Struct(self, dtrace_probe_t, probe);
370
+ return INT2FIX(probe->func);
371
+ }
372
+
373
+ VALUE dtraceprobe_is_enabled(VALUE self)
374
+ {
375
+ dtrace_probe_t *probe;
376
+
377
+ Data_Get_Struct(self, dtrace_probe_t, probe);
378
+ return ((int)(*probe->func)()) ? Qtrue : Qfalse;
379
+ }
380
+
381
+ VALUE dtraceprobe_fire(int argc, VALUE *ruby_argv, VALUE self) {
382
+ dtrace_probe_t *probe;
383
+ int i;
384
+ void *argv[8]; // probe argc max for now.
385
+ void (*func)();
386
+
387
+ Data_Get_Struct(self, dtrace_probe_t, probe);
388
+
389
+ /* munge Ruby values to either char *s or ints. */
390
+ for (i = 0; i < argc; i++) {
391
+ switch (TYPE(ruby_argv[i])) {
392
+ case T_STRING:
393
+ argv[i] = (void *)RSTRING(ruby_argv[i])->ptr;
394
+ break;
395
+ case T_FIXNUM:
396
+ argv[i] = (void *)FIX2INT(ruby_argv[i]);
397
+ break;
398
+ default:
399
+ rb_raise(eDtraceException, "type of arg[%d] is not string or fixnum", i);
400
+ break;
401
+ }
402
+ }
403
+
404
+ func = (void (*)())(probe->func + IS_ENABLED_FUNC_LEN);
405
+
406
+ switch (argc) {
407
+ case 0:
408
+ (void)(*func)();
409
+ break;
410
+ case 1:
411
+ (void)(*func)(argv[0]);
412
+ break;
413
+ case 2:
414
+ (void)(*func)(argv[0], argv[1]);
415
+ break;
416
+ case 3:
417
+ (void)(*func)(argv[0], argv[1], argv[2]);
418
+ break;
419
+ case 4:
420
+ (void)(*func)(argv[0], argv[1], argv[2], argv[3]);
421
+ break;
422
+ case 5:
423
+ (void)(*func)(argv[0], argv[1], argv[2], argv[3],
424
+ argv[4]);
425
+ break;
426
+ case 6:
427
+ (void)(*func)(argv[0], argv[1], argv[2], argv[3],
428
+ argv[4], argv[5]);
429
+ break;
430
+ case 7:
431
+ (void)(*func)(argv[0], argv[1], argv[2], argv[3],
432
+ argv[4], argv[5], argv[6]);
433
+ break;
434
+ case 8:
435
+ (void)(*func)(argv[0], argv[1], argv[2], argv[3],
436
+ argv[4], argv[5], argv[6], argv[7]);
437
+ break;
438
+ default:
439
+ rb_raise(eDtraceException, "probe argc max is 8");
440
+ break;
441
+ }
442
+
443
+ return Qnil;
444
+ }
445
+
446
+
447
+ /*
448
+ * Returns the offset for this probe in the PROFFS section, based on
449
+ * the location of the DOF, and the location of this probe.
450
+ */
451
+ VALUE dtraceprobe_probe_offset(VALUE self, VALUE file_addr, VALUE argc)
452
+ {
453
+ void *probe_addr;
454
+ int offset;
455
+ probe_addr = (void *)FIX2INT(rb_funcall(self, rb_intern("addr"), 0));
456
+ offset = IS_ENABLED_FUNC_LEN + 8 + (FIX2INT(argc) * 4);
457
+ return INT2FIX((int)probe_addr - (int)FIX2INT(file_addr) + offset);
458
+ }
459
+
460
+ /*
461
+ * Returns the offset for this probe's is-enabled tracepoint in the
462
+ * PRENOFFS section, based on the location of the DOF, and the
463
+ * location of this probe.
464
+ */
465
+ VALUE dtraceprobe_is_enabled_offset(VALUE self, VALUE file_addr)
466
+ {
467
+ void *probe_addr;
468
+ probe_addr = (void *)FIX2INT(rb_funcall(self, rb_intern("addr"), 0));
469
+ return INT2FIX((int)probe_addr - (int)FIX2INT(file_addr) + 12);
470
+ }