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.
- checksums.yaml +5 -5
- data/ext/ruby-static-tracing/darwin/provider.c +128 -0
- data/ext/ruby-static-tracing/darwin/provider.h +62 -0
- data/ext/ruby-static-tracing/darwin/ruby_static_tracing.c +48 -0
- data/ext/ruby-static-tracing/darwin/tracepoint.c +231 -0
- data/ext/ruby-static-tracing/darwin/tracepoint.h +52 -0
- data/ext/ruby-static-tracing/extconf.rb +45 -5
- data/ext/ruby-static-tracing/{linux → include}/ruby_static_tracing.h +3 -6
- data/ext/ruby-static-tracing/lib/deps-extconf.rb +47 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/example/demo.c +42 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/dynamic-symbols.c +41 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/dynamic-symbols.h +34 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/errors.c +30 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/errors.h +8 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/hash-table.c +27 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/hash-table.h +3 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/libstapsdt.c +208 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/libstapsdt.h +66 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/sdtnote.c +176 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/sdtnote.h +46 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/section.c +30 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/section.h +21 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/shared-lib.c +563 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/shared-lib.h +46 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/string-table.c +67 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/string-table.h +28 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/util.c +12 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/src/util.h +6 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/tests/test-errors.c +77 -0
- data/ext/ruby-static-tracing/lib/libstapsdt/tests/test-memory-leaks.c +25 -0
- data/ext/ruby-static-tracing/lib/post-extconf.rb +37 -0
- data/ext/ruby-static-tracing/linux/provider.c +1 -1
- data/ext/ruby-static-tracing/linux/provider.h +2 -7
- data/ext/ruby-static-tracing/linux/ruby_static_tracing.c +4 -3
- data/ext/ruby-static-tracing/linux/tracepoint.c +0 -1
- data/ext/ruby-static-tracing/linux/tracepoint.h +1 -5
- data/ext/ruby-static-tracing/linux/types.h +11 -0
- data/lib/ruby-static-tracing.rb +5 -7
- data/lib/ruby-static-tracing/platform.rb +48 -0
- data/lib/ruby-static-tracing/provider.rb +18 -1
- data/lib/ruby-static-tracing/tracepoint.rb +15 -3
- data/lib/ruby-static-tracing/tracepoints.rb +36 -0
- data/lib/ruby-static-tracing/tracers.rb +1 -0
- data/lib/ruby-static-tracing/tracers/base.rb +68 -0
- data/lib/ruby-static-tracing/tracers/helpers.rb +17 -0
- data/lib/ruby-static-tracing/tracers/latency_tracer.rb +13 -60
- data/lib/ruby-static-tracing/tracers/stack_tracer.rb +19 -0
- data/lib/ruby-static-tracing/version.rb +1 -1
- 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(
|
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
|
-
|
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,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,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
|
+
}
|