ruby-static-tracing 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/ext/ruby-static-tracing/darwin/provider.c +128 -0
  3. data/ext/ruby-static-tracing/darwin/provider.h +62 -0
  4. data/ext/ruby-static-tracing/darwin/ruby_static_tracing.c +48 -0
  5. data/ext/ruby-static-tracing/darwin/tracepoint.c +231 -0
  6. data/ext/ruby-static-tracing/darwin/tracepoint.h +52 -0
  7. data/ext/ruby-static-tracing/extconf.rb +45 -5
  8. data/ext/ruby-static-tracing/{linux → include}/ruby_static_tracing.h +3 -6
  9. data/ext/ruby-static-tracing/lib/deps-extconf.rb +47 -0
  10. data/ext/ruby-static-tracing/lib/libstapsdt/example/demo.c +42 -0
  11. data/ext/ruby-static-tracing/lib/libstapsdt/src/dynamic-symbols.c +41 -0
  12. data/ext/ruby-static-tracing/lib/libstapsdt/src/dynamic-symbols.h +34 -0
  13. data/ext/ruby-static-tracing/lib/libstapsdt/src/errors.c +30 -0
  14. data/ext/ruby-static-tracing/lib/libstapsdt/src/errors.h +8 -0
  15. data/ext/ruby-static-tracing/lib/libstapsdt/src/hash-table.c +27 -0
  16. data/ext/ruby-static-tracing/lib/libstapsdt/src/hash-table.h +3 -0
  17. data/ext/ruby-static-tracing/lib/libstapsdt/src/libstapsdt.c +208 -0
  18. data/ext/ruby-static-tracing/lib/libstapsdt/src/libstapsdt.h +66 -0
  19. data/ext/ruby-static-tracing/lib/libstapsdt/src/sdtnote.c +176 -0
  20. data/ext/ruby-static-tracing/lib/libstapsdt/src/sdtnote.h +46 -0
  21. data/ext/ruby-static-tracing/lib/libstapsdt/src/section.c +30 -0
  22. data/ext/ruby-static-tracing/lib/libstapsdt/src/section.h +21 -0
  23. data/ext/ruby-static-tracing/lib/libstapsdt/src/shared-lib.c +563 -0
  24. data/ext/ruby-static-tracing/lib/libstapsdt/src/shared-lib.h +46 -0
  25. data/ext/ruby-static-tracing/lib/libstapsdt/src/string-table.c +67 -0
  26. data/ext/ruby-static-tracing/lib/libstapsdt/src/string-table.h +28 -0
  27. data/ext/ruby-static-tracing/lib/libstapsdt/src/util.c +12 -0
  28. data/ext/ruby-static-tracing/lib/libstapsdt/src/util.h +6 -0
  29. data/ext/ruby-static-tracing/lib/libstapsdt/tests/test-errors.c +77 -0
  30. data/ext/ruby-static-tracing/lib/libstapsdt/tests/test-memory-leaks.c +25 -0
  31. data/ext/ruby-static-tracing/lib/post-extconf.rb +37 -0
  32. data/ext/ruby-static-tracing/linux/provider.c +1 -1
  33. data/ext/ruby-static-tracing/linux/provider.h +2 -7
  34. data/ext/ruby-static-tracing/linux/ruby_static_tracing.c +4 -3
  35. data/ext/ruby-static-tracing/linux/tracepoint.c +0 -1
  36. data/ext/ruby-static-tracing/linux/tracepoint.h +1 -5
  37. data/ext/ruby-static-tracing/linux/types.h +11 -0
  38. data/lib/ruby-static-tracing.rb +5 -7
  39. data/lib/ruby-static-tracing/platform.rb +48 -0
  40. data/lib/ruby-static-tracing/provider.rb +18 -1
  41. data/lib/ruby-static-tracing/tracepoint.rb +15 -3
  42. data/lib/ruby-static-tracing/tracepoints.rb +36 -0
  43. data/lib/ruby-static-tracing/tracers.rb +1 -0
  44. data/lib/ruby-static-tracing/tracers/base.rb +68 -0
  45. data/lib/ruby-static-tracing/tracers/helpers.rb +17 -0
  46. data/lib/ruby-static-tracing/tracers/latency_tracer.rb +13 -60
  47. data/lib/ruby-static-tracing/tracers/stack_tracer.rb +19 -0
  48. data/lib/ruby-static-tracing/version.rb +1 -1
  49. metadata +41 -5
@@ -0,0 +1,52 @@
1
+ #ifndef STATIC_TRACING_TRACEPOINT_H
2
+ #define STATIC_TRACING_TRACEPOINT_H
3
+
4
+ #include "usdt.h"
5
+
6
+ #include "ruby_static_tracing.h"
7
+
8
+ // FIXME move this to shared header
9
+ typedef union {
10
+ unsigned long long intval;
11
+ char * strval;
12
+ } Tracepoint_fire_arg;
13
+
14
+ typedef struct {
15
+ char *name;
16
+ usdt_probedef_t *usdt_tracepoint_def;
17
+ usdt_probe_t *usdt_tracepoint;
18
+ //Tracepoint_arg_types *args;
19
+ } static_tracing_tracepoint_t;
20
+
21
+ /*
22
+ * call-seq:
23
+ * StaticTracing::Tracepoint.new(provider, id, *vargs) -> tracepoint
24
+ *
25
+ * Creates a new tracepoint on a provider
26
+ */
27
+ VALUE
28
+ tracepoint_initialize(VALUE self, VALUE provider, VALUE id, VALUE vargs);
29
+
30
+ /*
31
+ * call-seq:
32
+ * tracepoint.fire(*vargs) -> true
33
+ *
34
+ * Fires data for the tracepoint to be probed
35
+ */
36
+ VALUE
37
+ tracepoint_fire(VALUE self, VALUE vargs);
38
+
39
+ /*
40
+ * call-seq:
41
+ * tracepoint.enabled? -> true
42
+ *
43
+ * Checks if the tracepoint is enabled, indicating it is being traced
44
+ */
45
+ VALUE
46
+ tracepoint_enabled(VALUE self);
47
+
48
+ // Allocate a static_tracing_tracepoint_type struct for ruby memory management
49
+ VALUE
50
+ static_tracing_tracepoint_alloc(VALUE klass);
51
+
52
+ #endif //STATIC_TRACING_TRACEPOINT_H
@@ -3,13 +3,31 @@ $LOAD_PATH.unshift File.expand_path("../../../lib", __FILE__)
3
3
  require 'mkmf'
4
4
  require 'ruby-static-tracing/platform'
5
5
 
6
+ BASE_DIR=File.expand_path(File.dirname(__FILE__))
7
+ LIB_DIR = File.expand_path('../../../lib/ruby-static-tracing', __FILE__)
8
+
9
+ MKMF_TARGET='ruby-static-tracing/ruby_static_tracing'
10
+
6
11
  def platform_dir(platform)
7
12
  File.expand_path("../../../ext/ruby-static-tracing/#{platform}/", __FILE__)
8
13
  end
9
14
 
15
+ def lib_dir
16
+ File.expand_path("../../../lib/ruby-static-tracing/", __FILE__)
17
+ end
18
+ # - Linux, via libstapsdt
10
19
  if StaticTracing::Platform.linux?
11
20
  abort 'libstapsdt.h is missing, please install libstapsdt' unless find_header('libstapsdt.h')
12
21
 
22
+ LIB_DIRS = [LIB_DIR, RbConfig::CONFIG['libdir']]
23
+ HEADER_DIRS = [
24
+ File.join(BASE_DIR, 'include'),
25
+ File.join(BASE_DIR, 'lib', 'libstapsdt'),
26
+ RbConfig::CONFIG['includedir']
27
+ ]
28
+
29
+ dir_config(MKMF_TARGET, HEADER_DIRS, LIB_DIRS)
30
+
13
31
  have_header 'libstapsdt.h'
14
32
 
15
33
  unless have_library('stapsdt')
@@ -23,12 +41,34 @@ if StaticTracing::Platform.linux?
23
41
  $CFLAGS << "-O3"
24
42
  end
25
43
 
26
- create_makefile('ruby-static-tracing/ruby_static_tracing', platform_dir("linux"))
44
+ create_makefile(MKMF_TARGET, platform_dir("linux"))
45
+
46
+ # - Darwin/BSD and other dtrace platforms, via libusdt
47
+ elsif StaticTracing::Platform.darwin?
48
+ abort 'dtrace is missing, this platform is not supported' unless have_library("dtrace", "dtrace_open")
49
+
50
+ LIB_DIRS = [LIB_DIR, RbConfig::CONFIG['libdir']]
51
+ puts LIB_DIRS.inspect
52
+ HEADER_DIRS = [
53
+ File.join(BASE_DIR, 'include'),
54
+ File.join(BASE_DIR, 'lib', 'libusdt'),
55
+ RbConfig::CONFIG['includedir']
56
+ ]
57
+
58
+ dir_config(MKMF_TARGET, HEADER_DIRS, LIB_DIRS)
59
+
60
+ have_header('usdt.h')
61
+ abort "ERROR: libusdt is required. It is included, so this failure is an error." unless have_library('usdt')
62
+
63
+ $CFLAGS = "-D_GNU_SOURCE -Wall " # -Werror complaining
64
+ if ENV.key?('DEBUG')
65
+ $CFLAGS << "-O0 -g -DDEBUG"
66
+ else
67
+ $CFLAGS << "-O3"
68
+ end
69
+
70
+ create_makefile(MKMF_TARGET, platform_dir('darwin'))
27
71
  else
28
- # FIXME properly stub this.
29
- # Should have 3 cases:
30
- # - Linux, via libstapsdt
31
- # - BSD and other dtrace platforms, via libusdt
32
72
  # - Stub, for other platforms that support neither
33
73
  # for now, we will yolo stub this to leave room to handle platforms
34
74
  # that support properly support conventional dtrace
@@ -6,14 +6,11 @@ Implements Init_ruby_static_tracing, which is used as C/Ruby entrypoint.
6
6
  #ifndef RUBY_STATIC_TRACING_H
7
7
  #define RUBY_STATIC_TRACING_H
8
8
 
9
- typedef enum TRACEPOINT_ARG_TYPES_ENUM {
10
- Integer = int64, // STAP enum type -8
11
- String = uint64, // STAP enum type 8
12
- } Tracepoint_arg_types;
13
-
9
+ #include "ruby.h"
14
10
  #include "provider.h"
11
+ #include "tracepoint.h"
15
12
 
16
13
  void Init_ruby_static_tracing();
17
- VALUE eUSDT, eInternal;
14
+ extern VALUE eUSDT, eInternal;
18
15
 
19
16
  #endif //RUBY_STATIC_TRACING_H
@@ -0,0 +1,47 @@
1
+ $LOAD_PATH.unshift File.expand_path("../../../lib", __FILE__)
2
+
3
+ require 'mkmf'
4
+ require 'ruby-static-tracing/platform'
5
+
6
+ BASE_DIR = File.expand_path(File.dirname(__FILE__))
7
+ LIB_DIR = File.expand_path('../../../../lib/ruby-static-tracing', __FILE__)
8
+
9
+ # FIXME have this install libstapsdt
10
+ if StaticTracing::Platform.linux?
11
+ # This is a bit of a hack to compile libstapsdt.so
12
+ # and "trick" extconf into thinking it's just another .so
13
+ File.write "Makefile", <<MAKEFILE
14
+ all:
15
+ cd #{File.join(BASE_DIR, 'libstapsdt')} && make
16
+ touch deps.so # HACK
17
+ cp #{File.join(BASE_DIR, 'libstapsdt', 'out/libstapsdt.so.0')} #{LIB_DIR}
18
+ clean:
19
+ cd #{File.join(BASE_DIR, 'libstapsdt')} && make clean
20
+ install:
21
+ MAKEFILE
22
+ exit
23
+ # We'll build libusdt and install and update linker info
24
+ elsif StaticTracing::Platform.darwin?
25
+ # This is a bit of a hack to compile libusdt.dylib
26
+ # and "trick" extconf into thinking it's just another .bundle
27
+ # After installing it (in post-extconf), we forcefully update the load path for
28
+ # ruby_static_tracing.bundle to find it in the same directory
29
+ File.write "Makefile", <<MAKEFILE
30
+ all:
31
+ cd #{File.join(BASE_DIR, 'libusdt')} && make libusdt.dylib
32
+ touch deps.bundle # HACK
33
+ cp #{File.join(BASE_DIR, 'libusdt', 'libusdt.dylib')} #{LIB_DIR}
34
+ clean:
35
+ cd #{File.join(BASE_DIR, 'libusdt')} && make clean
36
+ install:
37
+ MAKEFILE
38
+ exit
39
+ else
40
+ # - Stub, for other platforms that we don't support, we write an empty makefile
41
+ File.write "Makefile", <<MAKEFILE
42
+ all:
43
+ clean:
44
+ install:
45
+ MAKEFILE
46
+ exit
47
+ end
@@ -0,0 +1,42 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <unistd.h>
4
+ #include <libstapsdt.h>
5
+
6
+ int main( int argc, char *argv[] ) {
7
+ SDTProvider_t *provider;
8
+ SDTProbe_t **probes;
9
+ int probesCount = 0;
10
+ unsigned long long i=0;
11
+ int j=0;
12
+
13
+ if(argc < 3) {
14
+ printf("usage: demo PROVIDER PROBE\n");
15
+ return -1;
16
+ }
17
+
18
+ probesCount = argc - 2;
19
+ probes = calloc(sizeof(SDTProvider_t *), probesCount);
20
+
21
+ provider = providerInit(argv[1]);
22
+ for (int idx = 0; idx < (probesCount); idx++) {
23
+ probes[idx] = providerAddProbe(provider, argv[idx + 2], 2, uint64, int64);
24
+ }
25
+
26
+ if(providerLoad(provider) == -1) {
27
+ printf("Something went wrong: %s\n", provider->error);
28
+ return -1;
29
+ }
30
+
31
+ while(1) {
32
+ printf("Firing probes...\n");
33
+ for (int idx = 0; idx < probesCount; idx++) {
34
+ printf("Firing probe [%d]...\n", idx);
35
+ probeFire(probes[idx], i++, j--);
36
+ }
37
+ printf("Probe fired!\n");
38
+ sleep(3);
39
+ }
40
+
41
+ return 0;
42
+ }
@@ -0,0 +1,41 @@
1
+ #include "dynamic-symbols.h"
2
+ #include "string-table.h"
3
+ #include <libelf.h>
4
+
5
+ DynamicSymbolTable *dynamicSymbolTableInit(StringTable *dynamicString) {
6
+ DynamicSymbolTable *dynSymTab =
7
+ (DynamicSymbolTable *)calloc(sizeof(DynamicSymbolTable), 1);
8
+
9
+ dynSymTab->stringTable = dynamicString;
10
+
11
+ dynSymTab->bssStart.string = stringTableAdd(dynamicString, "__bss_start");
12
+ dynSymTab->eData.string = stringTableAdd(dynamicString, "_edata");
13
+ dynSymTab->end.string = stringTableAdd(dynamicString, "_end");
14
+
15
+ dynSymTab->count = 0;
16
+ dynSymTab->symbols = NULL;
17
+
18
+ return dynSymTab;
19
+ }
20
+
21
+ DynamicSymbol *dynamicSymbolTableAdd(DynamicSymbolTable *table,
22
+ char *symbolName) {
23
+ DynamicSymbolList *symbol = (DynamicSymbolList *)calloc(sizeof(DynamicSymbolList), 1);
24
+
25
+ symbol->symbol.string = stringTableAdd(table->stringTable, symbolName);
26
+
27
+ symbol->next = table->symbols;
28
+ table->symbols = symbol;
29
+ table->count += 1;
30
+
31
+ return &(symbol->symbol);
32
+ }
33
+
34
+ void dynamicSymbolTableFree(DynamicSymbolTable *table) {
35
+ DynamicSymbolList *node=NULL, *next=NULL;
36
+ for(node=table->symbols; node!=NULL; node=next) {
37
+ next=node->next;
38
+ free(node);
39
+ }
40
+ free(table);
41
+ }
@@ -0,0 +1,34 @@
1
+ #ifndef _DYNAMIC_SYMBOLS_
2
+ #define _DYNAMIC_SYMBOLS_
3
+
4
+ #include "string-table.h"
5
+ #include <libelf.h>
6
+
7
+ typedef struct {
8
+ StringTableNode *string;
9
+ Elf64_Sym *symbol;
10
+ } DynamicSymbol;
11
+
12
+ typedef struct DynamicSymbolList_ {
13
+ DynamicSymbol symbol;
14
+ struct DynamicSymbolList_ *next;
15
+ } DynamicSymbolList;
16
+
17
+ typedef struct {
18
+ StringTable *stringTable;
19
+
20
+ DynamicSymbol bssStart;
21
+ DynamicSymbol eData;
22
+ DynamicSymbol end;
23
+
24
+ size_t count;
25
+ DynamicSymbolList *symbols;
26
+ } DynamicSymbolTable;
27
+
28
+ DynamicSymbolTable *dynamicSymbolTableInit(StringTable *dynamicString);
29
+ DynamicSymbol *dynamicSymbolTableAdd(DynamicSymbolTable *table,
30
+ char *symbolName);
31
+
32
+ void dynamicSymbolTableFree(DynamicSymbolTable *table);
33
+
34
+ #endif
@@ -0,0 +1,30 @@
1
+
2
+ #include <stdarg.h>
3
+ #define _GNU_SOURCE
4
+ #include <stdlib.h>
5
+ #include <stdio.h>
6
+
7
+ #include "errors.h"
8
+
9
+ const char *sdtErrors[] = {
10
+ "failed to create Elf shared library for provider '%s'",
11
+ "failed to create temporary file '%s'",
12
+ "failed to open shared library '%s': %s",
13
+ "failed to load symbol '%s' for shared library '%s': %s",
14
+ "failed to close shared library '%s' for provider '%s': %s",
15
+ };
16
+
17
+ void sdtSetError(SDTProvider_t *provider, SDTError_t error, ...) {
18
+ va_list argp;
19
+
20
+ if(provider->error != NULL) {
21
+ free(provider->error);
22
+ provider->error = NULL;
23
+ provider->errno = noError;
24
+ }
25
+
26
+ va_start(argp, error);
27
+ provider->errno = error;
28
+ (void)vasprintf(&provider->error, sdtErrors[error], argp);
29
+ va_end(argp);
30
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef _ERRORS_H
2
+ #define _ERRORS_H
3
+
4
+ #include "libstapsdt.h"
5
+
6
+ void sdtSetError(SDTProvider_t *provider, SDTError_t error, ...);
7
+
8
+ #endif
@@ -0,0 +1,27 @@
1
+ #include <stdio.h>
2
+ #include "dynamic-symbols.h"
3
+
4
+ size_t hashTableFromSymbolTable(DynamicSymbolTable *table, uint32_t **hashTable) {
5
+ DynamicSymbolList *current;
6
+ uint32_t nBuckets = table->count + 3, // + 3, to count bss, end, and eData symbols
7
+ nChains = table->count + 3;
8
+ size_t hashTableSize = (nBuckets + nChains + 2);
9
+
10
+ uint32_t *hashTable_ = (uint32_t *)calloc(sizeof(uint32_t), hashTableSize);
11
+ uint32_t *buckets = &(hashTable_[2]);
12
+ uint32_t *chains = &(buckets[nBuckets]);
13
+ int idx, stringIdx=2;
14
+
15
+ hashTable_[0] = nBuckets;
16
+ hashTable_[1] = nChains;
17
+
18
+ for(current=table->symbols; current!=NULL; current=current->next) {
19
+ idx = elf_hash(current->symbol.string->str) % nBuckets;
20
+ chains[stringIdx] = buckets[idx];
21
+ buckets[idx] = stringIdx;
22
+ stringIdx++;
23
+ }
24
+
25
+ *hashTable = hashTable_;
26
+ return hashTableSize * sizeof(uint32_t);
27
+ }
@@ -0,0 +1,3 @@
1
+ #include "dynamic-symbols.h"
2
+
3
+ size_t hashTableFromSymbolTable(DynamicSymbolTable *table, uint32_t **hashTable);
@@ -0,0 +1,208 @@
1
+ #include <stdarg.h>
2
+ #include <dlfcn.h>
3
+ #include <err.h>
4
+ #include <fcntl.h>
5
+ #include <libelf.h>
6
+ #include <stdio.h>
7
+ #include <stdlib.h>
8
+ #include <string.h>
9
+ #include <sys/types.h>
10
+ #include <unistd.h>
11
+
12
+ #include "dynamic-symbols.h"
13
+ #include "sdtnote.h"
14
+ #include "section.h"
15
+ #include "string-table.h"
16
+ #include "shared-lib.h"
17
+ #include "util.h"
18
+ #include "libstapsdt.h"
19
+ #include "errors.h"
20
+
21
+ int createSharedLibrary(int fd, SDTProvider_t *provider) {
22
+ DynElf *dynElf = dynElfInit(fd);
23
+
24
+ for(SDTProbeList_t *node=provider->probes; node != NULL; node = node->next) {
25
+ dynElfAddProbe(dynElf, &(node->probe));
26
+ }
27
+
28
+ if(dynElfSave(dynElf) == -1) {
29
+ sdtSetError(provider, elfCreationError, provider->name);
30
+ return -1;
31
+ }
32
+
33
+ dynElfClose(dynElf);
34
+
35
+ return 0;
36
+ }
37
+
38
+ SDTProvider_t *providerInit(const char *name) {
39
+ SDTProvider_t *provider = (SDTProvider_t *) calloc(sizeof(SDTProvider_t), 1);
40
+ provider->error = NULL;
41
+ provider->errno = noError;
42
+ provider->probes = NULL;
43
+ provider->_handle = NULL;
44
+ provider->_filename = NULL;
45
+
46
+ provider->name = (char *) calloc(sizeof(char), strlen(name) + 1);
47
+ memcpy(provider->name, name, sizeof(char) * strlen(name) + 1);
48
+
49
+ return provider;
50
+ }
51
+
52
+ SDTProbe_t *providerAddProbe(SDTProvider_t *provider, const char *name, int argCount, ...) {
53
+ int i;
54
+ va_list vl;
55
+ ArgType_t arg;
56
+ va_start(vl, argCount);
57
+
58
+ SDTProbeList_t *probeList = (SDTProbeList_t *) calloc(sizeof(SDTProbeList_t), 1);
59
+ probeList->probe._fire = NULL;
60
+
61
+ probeList->probe.name = (char *) calloc(sizeof(char), strlen(name) + 1);
62
+ memcpy(probeList->probe.name, name, sizeof(char) * strlen(name) + 1);
63
+
64
+ probeList->next = provider->probes;
65
+ provider->probes = probeList;
66
+
67
+ probeList->probe.argCount = argCount;
68
+
69
+ for(i=0; i < argCount; i++) {
70
+ arg = va_arg(vl, ArgType_t);
71
+ probeList->probe.argFmt[i] = arg;
72
+ }
73
+
74
+ for(; i<MAX_ARGUMENTS; i++) {
75
+ probeList->probe.argFmt[i] = noarg;
76
+ }
77
+
78
+ probeList->probe.provider = provider;
79
+
80
+ return &(probeList->probe);
81
+ }
82
+
83
+ int providerLoad(SDTProvider_t *provider) {
84
+ int fd;
85
+ void *fireProbe;
86
+ char *filename = calloc(sizeof(char), strlen("/tmp/-XXXXXX.so") + strlen(provider->name) + 1);
87
+ char *error;
88
+
89
+ sprintf(filename, "/tmp/%s-XXXXXX.so", provider->name);
90
+
91
+ if ((fd = mkstemps(filename, 3)) < 0) {
92
+ sdtSetError(provider, tmpCreationError, filename);
93
+ free(filename);
94
+ return -1;
95
+ }
96
+ provider->_filename = filename;
97
+
98
+ if(createSharedLibrary(fd, provider) != 0) {
99
+ (void)close(fd);
100
+ return -1;
101
+ }
102
+ (void)close(fd);
103
+
104
+ provider->_handle = dlopen(filename, RTLD_LAZY);
105
+ if (!provider->_handle) {
106
+ sdtSetError(provider, sharedLibraryOpenError, filename, dlerror());
107
+ return -1;
108
+ }
109
+
110
+ for(SDTProbeList_t *node=provider->probes; node != NULL; node = node->next) {
111
+ fireProbe = dlsym(provider->_handle, node->probe.name);
112
+
113
+ // TODO (mmarchini) handle errors better when a symbol fails to load
114
+ if ((error = dlerror()) != NULL) {
115
+ sdtSetError(provider, sharedLibraryOpenError, filename, node->probe.name, error);
116
+ return -1;
117
+ }
118
+
119
+ node->probe._fire = fireProbe;
120
+ }
121
+
122
+
123
+ return 0;
124
+ }
125
+
126
+ int providerUnload(SDTProvider_t *provider) {
127
+ if(provider->_handle == NULL) {
128
+ return 0;
129
+ }
130
+ if(dlclose(provider->_handle) != 0) {
131
+ sdtSetError(provider, sharedLibraryCloseError, provider->_filename, provider->name, dlerror());
132
+ return -1;
133
+ }
134
+ provider->_handle = NULL;
135
+
136
+ for(SDTProbeList_t *node=provider->probes; node != NULL; node = node->next) {
137
+ node->probe._fire = NULL;
138
+ }
139
+
140
+ unlink(provider->_filename);
141
+ free(provider->_filename);
142
+
143
+ return 0;
144
+ }
145
+
146
+ void probeFire(SDTProbe_t *probe, ...) {
147
+ if(probe->_fire == NULL) {
148
+ return;
149
+ }
150
+ va_list vl;
151
+ va_start(vl, probe);
152
+ uint64_t arg[6] = {0};
153
+ for(int i=0; i < probe->argCount; i++) {
154
+ arg[i] = va_arg(vl, uint64_t);
155
+ }
156
+
157
+ switch(probe->argCount) {
158
+ case 0:
159
+ ((void (*)())probe->_fire) ();
160
+ return;
161
+ case 1:
162
+ ((void (*)())probe->_fire) (arg[0]);
163
+ return;
164
+ case 2:
165
+ ((void (*)())probe->_fire) (arg[0], arg[1]);
166
+ return;
167
+ case 3:
168
+ ((void (*)())probe->_fire) (arg[0], arg[1], arg[2]);
169
+ return;
170
+ case 4:
171
+ ((void (*)())probe->_fire) (arg[0], arg[1], arg[2], arg[3]);
172
+ return;
173
+ case 5:
174
+ ((void (*)())probe->_fire) (arg[0], arg[1], arg[2], arg[3], arg[4]);
175
+ return;
176
+ case 6:
177
+ ((void (*)())probe->_fire) (arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
178
+ return;
179
+ default:
180
+ ((void (*)())probe->_fire) ();
181
+ return;
182
+ }
183
+ }
184
+
185
+ int probeIsEnabled(SDTProbe_t *probe) {
186
+ if(probe->_fire == NULL) {
187
+ return 0;
188
+ }
189
+ if(((*(char *)probe->_fire) & 0x90) == 0x90) {
190
+ return 0;
191
+ }
192
+ return 1;
193
+ }
194
+
195
+ void providerDestroy(SDTProvider_t *provider) {
196
+ SDTProbeList_t *node=NULL, *next=NULL;
197
+
198
+ for(node=provider->probes; node!=NULL; node=next) {
199
+ free(node->probe.name);
200
+ next=node->next;
201
+ free(node);
202
+ }
203
+ free(provider->name);
204
+ if(provider->error != NULL) {
205
+ free(provider->error);
206
+ }
207
+ free(provider);
208
+ }