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