ruby-static-tracing 0.0.2 → 0.0.3

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.
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
+ }