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,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