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,46 @@
1
+ #ifndef _SHARED_LIB_H
2
+ #define _SHARED_LIB_H
3
+
4
+ #include "section.h"
5
+ #include "string-table.h"
6
+ #include "sdtnote.h"
7
+ #include "dynamic-symbols.h"
8
+
9
+ typedef struct {
10
+ Section
11
+ *hash,
12
+ *dynSym,
13
+ *dynStr,
14
+ *text,
15
+ *sdtBase,
16
+ *ehFrame,
17
+ *dynamic,
18
+ *sdtNote,
19
+ *shStrTab;
20
+ } SectionsList;
21
+
22
+ typedef struct {
23
+ Elf *elf;
24
+ Elf64_Ehdr *ehdr;
25
+ Elf64_Phdr *phdrLoad1, *phdrLoad2, *phdrDyn, *phdrStack;
26
+
27
+ StringTable *stringTable;
28
+ StringTable *dynamicString;
29
+
30
+ DynamicSymbolTable *dynamicSymbols;
31
+
32
+ SDTNoteList_t *sdtNotes;
33
+ size_t sdtNotesCount;
34
+
35
+ SectionsList sections;
36
+ } DynElf;
37
+
38
+ DynElf *dynElfInit();
39
+
40
+ int dynElfAddProbe(DynElf *dynElf, SDTProbe_t *probe);
41
+
42
+ int dynElfSave(DynElf *dynElf);
43
+
44
+ void dynElfClose(DynElf *dynElf);
45
+
46
+ #endif
@@ -0,0 +1,67 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+
4
+ #include "string-table.h"
5
+
6
+ StringTable *stringTableInit() {
7
+ StringTable *stringTable = (StringTable *)calloc(sizeof(StringTable), 1);
8
+ stringTable->count = 1;
9
+ stringTable->size = 1;
10
+
11
+ stringTable->first = (StringTableNode *)calloc(sizeof(StringTableNode), 1);
12
+
13
+ stringTable->first->index = 0;
14
+ stringTable->first->size = 1;
15
+ stringTable->first->str = (char *)calloc(sizeof(char), 1);
16
+ stringTable->first->str[0] = '\0';
17
+ stringTable->first->next = NULL;
18
+
19
+ return stringTable;
20
+ }
21
+
22
+ StringTableNode *stringTableAdd(StringTable *stringTable, char *str) {
23
+ StringTableNode *current;
24
+
25
+ for (current = stringTable->first; current->next != NULL;
26
+ current = current->next) {
27
+ }
28
+
29
+ current->next = (StringTableNode *)calloc(sizeof(StringTableNode), 1);
30
+ current->next->index = current->index + current->size;
31
+
32
+ current = current->next;
33
+ current->size = strlen(str) + 1;
34
+
35
+ current->str = (char *)calloc(current->size, 1);
36
+ memcpy(current->str, str, current->size);
37
+ current->next = NULL;
38
+
39
+ stringTable->count += 1;
40
+ stringTable->size += current->size;
41
+
42
+ return current;
43
+ }
44
+
45
+ char *stringTableToBuffer(StringTable *stringTable) {
46
+ int offset;
47
+ StringTableNode *current;
48
+ char *buffer = (char *)calloc(stringTable->size, 1);
49
+
50
+ for (current = stringTable->first, offset = 0; current != NULL;
51
+ offset += current->size, current = current->next) {
52
+ memcpy(&buffer[offset], current->str, current->size);
53
+ }
54
+
55
+ return buffer;
56
+ }
57
+
58
+ void stringTableFree(StringTable *table) {
59
+ StringTableNode *node=NULL, *next=NULL;
60
+ for(node=table->first; node!=NULL; node=next) {
61
+ free(node->str);
62
+
63
+ next=node->next;
64
+ free(node);
65
+ }
66
+ free(table);
67
+ }
@@ -0,0 +1,28 @@
1
+ #ifndef _STRING_TABLE_H
2
+ #define _STRING_TABLE_H
3
+
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+
7
+ typedef struct StringTableNode_ {
8
+ int index;
9
+ int size;
10
+ char *str;
11
+ struct StringTableNode_ *next;
12
+ } StringTableNode;
13
+
14
+ typedef struct {
15
+ int count;
16
+ size_t size;
17
+ StringTableNode *first;
18
+ } StringTable;
19
+
20
+ StringTable *stringTableInit();
21
+
22
+ StringTableNode *stringTableAdd(StringTable *stringTable, char *str);
23
+
24
+ char *stringTableToBuffer(StringTable *stringTable);
25
+
26
+ void stringTableFree(StringTable *stringTable);
27
+
28
+ #endif
@@ -0,0 +1,12 @@
1
+ int roundUp(int numToRound, int multiple) {
2
+ if (multiple == 0) {
3
+ return numToRound;
4
+ }
5
+
6
+ int remainder = numToRound % multiple;
7
+ if (remainder == 0) {
8
+ return numToRound;
9
+ }
10
+
11
+ return numToRound + multiple - remainder;
12
+ }
@@ -0,0 +1,6 @@
1
+ #ifndef _UTIL_H
2
+ #define _UTIL_H
3
+
4
+ int roundUp(int numToRound, int multiple);
5
+
6
+ #endif
@@ -0,0 +1,77 @@
1
+ #include "libstapsdt.h"
2
+ #include <stdio.h>
3
+ #include <unistd.h>
4
+ #include <dlfcn.h>
5
+
6
+ int testElfCreationError() {
7
+ // TODO (mmarchini) write test case for elf creation error
8
+ return 1;
9
+ }
10
+
11
+ int testTmpCreationError() {
12
+ SDTProvider_t *provider;
13
+ SDTError_t errno;
14
+ provider = providerInit("test/probe/creation/error");
15
+ if(providerLoad(provider) == 0) {
16
+ return 0;
17
+ }
18
+ printf("[testTmpCreationError] Error message: %s\n", provider->error);
19
+ errno = provider->errno;
20
+ providerDestroy(provider);
21
+ return errno == tmpCreationError;
22
+ }
23
+
24
+ int testSharedLibraryOpenError() {
25
+ // TODO (mmarchini) write test case for shared library loading error
26
+ return 1;
27
+ }
28
+
29
+ int testSymbolLoadingError() {
30
+ // TODO (mmarchini) write test case for symbol loading error
31
+ return 1;
32
+ }
33
+
34
+ int testSharedLibraryCloseError() {
35
+ SDTProvider_t *provider;
36
+ SDTError_t errno;
37
+ provider = providerInit("test-error");
38
+ providerLoad(provider);
39
+ dlclose(provider->_handle);
40
+ if(providerUnload(provider) == 0) {
41
+ return 0;
42
+ }
43
+ errno = provider->errno;
44
+ printf("[testSharedLibraryCloseError] Error message: %s\n", provider->error);
45
+ providerDestroy(provider);
46
+ return errno == sharedLibraryCloseError;
47
+ }
48
+
49
+ int main() {
50
+ if (!testElfCreationError()) {
51
+ printf("Test case failed: testElfCreationError\n");
52
+ return -1;
53
+ }
54
+
55
+ if (!testTmpCreationError()) {
56
+ printf("Test case failed: testTmpCreationError\n");
57
+ return -2;
58
+ }
59
+
60
+ if (!testSharedLibraryOpenError()) {
61
+ printf("Test case failed: testSharedLibraryOpenError\n");
62
+ return -3;
63
+ }
64
+
65
+ if (!testSymbolLoadingError()) {
66
+ printf("Test case failed: testSymbolLoadingError\n");
67
+ return -4;
68
+ }
69
+
70
+ if (!testSharedLibraryCloseError()) {
71
+ printf("Test case failed: testSharedLibraryCloseError\n");
72
+ return -5;
73
+ }
74
+
75
+
76
+ return 0;
77
+ }
@@ -0,0 +1,25 @@
1
+ #include <stdio.h>
2
+ #include <unistd.h>
3
+ #include <libstapsdt.h>
4
+
5
+ int main( int argc, char *argv[] ) {
6
+ SDTProvider_t *provider;
7
+ SDTProbe_t *probe1, *probe2;
8
+
9
+ provider = providerInit("testProvider");
10
+ probe1 = providerAddProbe(provider, "testProbe1", 4, int8, uint8, int64, uint64);
11
+ probe2 = providerAddProbe(provider, "testProbe2", 2, int8, uint8);
12
+
13
+ if(providerLoad(provider) == -1) {
14
+ printf("Something went wrong...\n");
15
+ return -1;
16
+ }
17
+
18
+ probeFire(probe1, 1, 2, 3, 4);
19
+ probeFire(probe2, -3, 8);
20
+
21
+ providerUnload(provider);
22
+ providerDestroy(provider);
23
+
24
+ return 0;
25
+ }
@@ -0,0 +1,37 @@
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
+ # Linux is a noop
10
+ if StaticTracing::Platform.linux?
11
+ File.write "Makefile", <<MAKEFILE
12
+ all:
13
+ touch post.so
14
+ clean:
15
+ install:
16
+ MAKEFILE
17
+ exit
18
+ # We'll build libusdt and install and update linker info
19
+ elsif StaticTracing::Platform.darwin?
20
+ # This is done to ensure that the bundle will look in its local directory for the library
21
+ File.write "Makefile", <<MAKEFILE
22
+ all:
23
+ touch post.bundle
24
+ install_name_tool -change libusdt.dylib @loader_path/../ruby-static-tracing/libusdt.dylib #{File.join(LIB_DIR, 'ruby_static_tracing.bundle')}
25
+ clean:
26
+ install:
27
+ MAKEFILE
28
+ exit
29
+ else
30
+ # - Stub, for other platforms that we don't support, we write an empty makefile
31
+ File.write "Makefile", <<MAKEFILE
32
+ all:
33
+ clean:
34
+ install:
35
+ MAKEFILE
36
+ exit
37
+ end
@@ -19,7 +19,7 @@ provider_initialize(VALUE self, VALUE name)
19
19
  // Check and cast arguments
20
20
  c_name_str = check_name_arg(name);
21
21
 
22
- // Build semian resource structure
22
+ // Build provider structure
23
23
  TypedData_Get_Struct(self, static_tracing_provider_t, &static_tracing_provider_type, res);
24
24
  res->sdt_provider = providerInit(c_name_str);
25
25
  return self;
@@ -1,16 +1,11 @@
1
- /*
2
- For core static tracing functions exposed directly to ruby.
3
- Functions here are associated with rubyland operations.
4
- */
5
1
  #ifndef STATIC_TRACING_PROVIDER_H
6
2
  #define STATIC_TRACING_PROVIDER_H
7
3
 
8
- #include <ruby.h>
9
4
  // Include libstapsdt.h to wrap
10
- #include <libstapsdt.h>
5
+ #include <libstapsdt.h> // FIXME use local
11
6
 
7
+ #include "types.h"
12
8
  #include "ruby_static_tracing.h"
13
- #include "tracepoint.h"
14
9
 
15
10
  typedef struct {
16
11
  char *name;
@@ -1,5 +1,6 @@
1
- #include "provider.h"
2
- #include "tracepoint.h"
1
+ #include "ruby_static_tracing.h"
2
+
3
+ VALUE eUSDT, eInternal;
3
4
 
4
5
  void Init_ruby_static_tracing()
5
6
  {
@@ -41,7 +42,7 @@ void Init_ruby_static_tracing()
41
42
 
42
43
  rb_define_alloc_func(cTracepoint, static_tracing_tracepoint_alloc);
43
44
  rb_define_method(cTracepoint, "tracepoint_initialize", tracepoint_initialize, 3);
44
- rb_define_method(cTracepoint, "fire_tracepoint", tracepoint_fire, 1);
45
+ rb_define_method(cTracepoint, "_fire_tracepoint", tracepoint_fire, 1);
45
46
  rb_define_method(cTracepoint, "enabled?", tracepoint_enabled, 0);
46
47
  }
47
48
 
@@ -1,5 +1,4 @@
1
1
  #include "tracepoint.h"
2
- #include "provider.h"
3
2
 
4
3
  static const rb_data_type_t
5
4
  static_tracing_tracepoint_type;
@@ -1,16 +1,12 @@
1
- /*
2
- For core static tracing functions exposed directly to ruby.
3
- Functions here are associated with rubyland operations.
4
- */
5
1
  #ifndef STATIC_TRACING_TRACEPOINT_H
6
2
  #define STATIC_TRACING_TRACEPOINT_H
7
3
 
8
4
  #include <ruby.h>
9
5
  // Include libstapsdt.h to wrap
10
6
  #include <libstapsdt.h>
11
- // Probably need to include provider.h to be able to initialize self
12
7
 
13
8
  #include "ruby_static_tracing.h"
9
+ #include "types.h"
14
10
 
15
11
  typedef union {
16
12
  unsigned long long intval;
@@ -0,0 +1,11 @@
1
+ #ifndef STATIC_TRACING_TYPES_H
2
+ #define STATIC_TRACING_TYPES_H
3
+
4
+ #include <libstapsdt.h>
5
+
6
+ typedef enum TRACEPOINT_ARG_TYPES_ENUM {
7
+ Integer = int64, // STAP enum type -8
8
+ String = uint64, // STAP enum type 8
9
+ } Tracepoint_arg_types;
10
+
11
+ #endif // STATIC_TRACING_TYPEs_H
@@ -6,6 +6,7 @@ require 'ruby-static-tracing/version'
6
6
  require 'ruby-static-tracing/platform'
7
7
  require 'ruby-static-tracing/provider'
8
8
  require 'ruby-static-tracing/tracepoint'
9
+ require 'ruby-static-tracing/tracepoints'
9
10
  require 'ruby-static-tracing/configuration'
10
11
  require 'ruby-static-tracing/tracers'
11
12
 
@@ -45,12 +46,15 @@ module StaticTracing
45
46
  # with a wrapped version that has tracing enabled
46
47
  def enable!
47
48
  tracers.each(&:enable!)
49
+ StaticTracing::Provider.enable!
48
50
  @enabled = true
49
51
  end
50
52
 
51
53
  # Overwrite the definition of all functions to their original definition,
52
54
  # no longer wrapping them
53
55
  def disable!
56
+ tracers.each(&:disable!)
57
+ StaticTracing::Provider.disable!
54
58
  @enabled = false
55
59
  end
56
60
 
@@ -72,10 +76,4 @@ module StaticTracing
72
76
  end
73
77
  end
74
78
 
75
- # FIXME add signal handlers to enable-disable on specific process signals
76
- # within a trap handler.
77
- # Specify default signals, but allow these to be overidden for easier integration
78
-
79
- # This loads the actual C extension, we might want to guard it
80
- # for cases where the extension isn't yet built
81
- require 'ruby-static-tracing/ruby_static_tracing' if StaticTracing::Platform.linux?
79
+ require 'ruby-static-tracing/ruby_static_tracing' if StaticTracing::Platform.linux? || StaticTracing::Platform.darwin?
@@ -3,9 +3,57 @@
3
3
  module StaticTracing
4
4
  module Platform
5
5
  extend self
6
+ UNSUPPORTED_POST_INSTALL_MESSAGE = %(
7
+ WARNING: You have installed this on an unsupported platform, somehow.
8
+
9
+ You should verify for yourself that the behavior on your platform is safe.
10
+ )
11
+
12
+ LINUX_POST_INSTALL_MESSAGE = %(
13
+ WARNING: you will need a new kernel (4.14+) that supports eBPF.
14
+
15
+ You should use the newest possible version of bpftrace
16
+ ).freeze
17
+
18
+ DARWIN_POST_INSTALL_MESSAGE = %(
19
+ WARNING: tracing with dtrace will not work with SIP enabled.
20
+
21
+ SIP is enabled by default on recent versions of OSX. You can
22
+ check if SIP is enabled with:
23
+
24
+ csrutil status
25
+
26
+ If you want to test your probes out locally, you will need to at
27
+ least allow dtrace. To do this, you must reboot into recovery mode
28
+ by holding CMD + R while your Mac is booting. Once it has booted,
29
+ open a terminal and type:
30
+
31
+ csrutil clear
32
+ csrutil enable --without-dtrace
33
+
34
+ After this, you should be able to use dtrace on the tracepoints you
35
+ define here. If it still doesn't work, you can disable SIP entirely
36
+ but this is not recommended for security purposes.
37
+ ).freeze
6
38
 
7
39
  def linux?
8
40
  /linux/.match(RUBY_PLATFORM)
9
41
  end
42
+
43
+ def darwin?
44
+ /darwin/.match(RUBY_PLATFORM)
45
+ end
46
+
47
+ def post_install_message
48
+ message = begin
49
+ if linux?
50
+ LINUX_POST_INSTALL_MESSAGE
51
+ elsif darwin?
52
+ DARWIN_POST_INSTALL_MESSAGE
53
+ else
54
+ UNSUPPORTED_POST_INSTALL_MESSAGE
55
+ end
56
+ end
57
+ end
10
58
  end
11
59
  end