ruby-dtrace 0.2.8 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }