rbbcc 0.4.1 → 0.4.2
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 +4 -4
- data/Gemfile.lock +1 -1
- data/examples/ruby_usdt.rb +105 -0
- data/examples/sbrk_trace.rb +204 -0
- data/lib/rbbcc/bcc.rb +9 -7
- data/lib/rbbcc/clib.rb +2 -1
- data/lib/rbbcc/debug.rb +17 -0
- data/lib/rbbcc/usdt.rb +21 -4
- data/lib/rbbcc/version.rb +1 -1
- metadata +5 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 403f2664a61a40bce19ee3ca85f9637822b2172fb8123e7758f49342e022725f
         | 
| 4 | 
            +
              data.tar.gz: 81f005eeb8d5c53faedffe8b01874b952faff8d81cda3b5319bc3fdde0044d6d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 1ea74e38ea3bf6668c6d17b2907e7fe08497c913eff17776b77194cbb2285a79b9259f6412564ae5ec16c4979a321abcdf299d7735f363c5304ce0f665465e09
         | 
| 7 | 
            +
              data.tar.gz: 46e964f12ddce367941db82c6efd33dbcf0ad6c396b51e39c4ea0e2ebc26dd0568558ebc44794144104f0b30def56d5ebae7173a9fe78fa883e7579226a0f588
         | 
    
        data/Gemfile.lock
    CHANGED
    
    
| @@ -0,0 +1,105 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            # To run this example, please build the target ruby with an `--enable-dtrace` option in advance.
         | 
| 3 | 
            +
            # To build via rbenv, sample command is:
         | 
| 4 | 
            +
            #     $ RUBY_CONFIGURE_OPTS='--enable-dtrace' rbenv install 2.7.0
         | 
| 5 | 
            +
            #
         | 
| 6 | 
            +
            # Example autput:
         | 
| 7 | 
            +
            #     # bundle exec ruby examples/ruby_usdt.rb $(pidof irb)
         | 
| 8 | 
            +
            #     TIME(s)            COMM   KLASS                    PATH
         | 
| 9 | 
            +
            #     0.000000000        irb    Struct::Key              /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/reline.rb
         | 
| 10 | 
            +
            #     0.000055206        irb    Array                    /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/reline/line_editor.rb
         | 
| 11 | 
            +
            #     0.000088588        irb    Ripper::Lexer            /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 12 | 
            +
            #     0.000117740        irb    Ripper::Lexer::Elem      /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 13 | 
            +
            #     0.000126697        irb    Ripper::Lexer::State     /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 14 | 
            +
            #     0.000213388        irb    Array                    /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/reline/line_editor.rb
         | 
| 15 | 
            +
            #     0.000225678        irb    Ripper::Lexer            /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 16 | 
            +
            #     0.000243638        irb    Array                    /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/reline/line_editor.rb
         | 
| 17 | 
            +
            #     0.000254680        irb    Range                    /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/irb/ruby-lex.rb
         | 
| 18 | 
            +
            #     0.000264707        irb    Ripper::Lexer            /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 19 | 
            +
            #     0.000275579        irb    Ripper::Lexer::Elem      /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 20 | 
            +
            #     0.000282438        irb    Ripper::Lexer::State     /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 21 | 
            +
            #     0.000326136        irb    String                   /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/irb.rb
         | 
| 22 | 
            +
            #     0.001353621        irb    Array                    /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/reline/line_editor.rb
         | 
| 23 | 
            +
            #     0.001385320        irb    IRB::Color::SymbolState  /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/irb/color.rb
         | 
| 24 | 
            +
            #     0.001397043        irb    Ripper::Lexer            /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/irb/color.rb
         | 
| 25 | 
            +
            #     0.001416420        irb    Ripper::Lexer::Elem      /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 26 | 
            +
            #     0.001423861        irb    Ripper::Lexer::State     /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 27 | 
            +
            #     0.001462010        irb    Ripper::Lexer::State     /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 28 | 
            +
            #     0.001478995        irb    Array                    /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/reline/line_editor.rb
         | 
| 29 | 
            +
            #     0.001487499        irb    Range                    /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/irb/ruby-lex.rb
         | 
| 30 | 
            +
            #     0.001496666        irb    Ripper::Lexer            /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 31 | 
            +
            #     0.001508224        irb    Ripper::Lexer::Elem      /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 32 | 
            +
            #     0.001515143        irb    Ripper::Lexer::State     /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/ripper/lexer.rb
         | 
| 33 | 
            +
            #     0.001556170        irb    String                   /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/irb.rb
         | 
| 34 | 
            +
            #     0.001726273        irb    String                   /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/reline/line_editor.rb
         | 
| 35 | 
            +
            #     0.001946948        irb    Array                    /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/reline/line_editor.rb
         | 
| 36 | 
            +
            #     0.001956585        irb    String                   /root/.rbenv/versions/2.7.0/lib/ruby/2.7.0/reline.rb
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            require 'rbbcc'
         | 
| 39 | 
            +
            include RbBCC
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            pid = ARGV[0] || begin
         | 
| 42 | 
            +
              puts("USAGE: #{$0} PID")
         | 
| 43 | 
            +
              exit()
         | 
| 44 | 
            +
            end
         | 
| 45 | 
            +
            debug = !!ENV['DEBUG']
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            bpf_text = <<BPF
         | 
| 48 | 
            +
            #include <uapi/linux/ptrace.h>
         | 
| 49 | 
            +
            #include <linux/sched.h>
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            struct data_t {
         | 
| 52 | 
            +
                u64 ts;
         | 
| 53 | 
            +
                char comm[TASK_COMM_LEN];
         | 
| 54 | 
            +
                char klass[64];
         | 
| 55 | 
            +
                char path[256];
         | 
| 56 | 
            +
            };
         | 
| 57 | 
            +
            BPF_PERF_OUTPUT(events);
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            int do_trace_create_object(struct pt_regs *ctx) {
         | 
| 60 | 
            +
                struct data_t data = {};
         | 
| 61 | 
            +
                uint64_t addr, addr2;
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                data.ts = bpf_ktime_get_ns();
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                bpf_get_current_comm(&data.comm, sizeof(data.comm));
         | 
| 66 | 
            +
                bpf_usdt_readarg_p(1, ctx, &data.klass, sizeof(data.klass));
         | 
| 67 | 
            +
                bpf_usdt_readarg_p(2, ctx, &data.path, sizeof(data.path));
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                events.perf_submit(ctx, &data, sizeof(data));
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                return 0;
         | 
| 72 | 
            +
            };
         | 
| 73 | 
            +
            BPF
         | 
| 74 | 
            +
             | 
| 75 | 
            +
            u = USDT.new(pid: pid.to_i)
         | 
| 76 | 
            +
            u.enable_probe(probe: "object__create", fn_name: "do_trace_create_object")
         | 
| 77 | 
            +
            if debug
         | 
| 78 | 
            +
              puts(u.get_text)
         | 
| 79 | 
            +
              puts(bpf_text)
         | 
| 80 | 
            +
            end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            # initialize BPF
         | 
| 83 | 
            +
            b = BCC.new(text: bpf_text, usdt_contexts: [u])
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            puts("%-18s %-6s %-24s %s" % ["TIME(s)", "COMM", "KLASS", "PATH"])
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            # process event
         | 
| 88 | 
            +
            start = 0
         | 
| 89 | 
            +
            b["events"].open_perf_buffer do |cpu, data, size|
         | 
| 90 | 
            +
              event = b["events"].event(data)
         | 
| 91 | 
            +
              if start == 0
         | 
| 92 | 
            +
                start = event.ts
         | 
| 93 | 
            +
              end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
              time_s = ((event.ts - start).to_f) / 1000000000
         | 
| 96 | 
            +
              puts(
         | 
| 97 | 
            +
                "%-18.9f %-6s %-24s %s" %
         | 
| 98 | 
            +
                [time_s, event.comm, event.klass, event.path]
         | 
| 99 | 
            +
              )
         | 
| 100 | 
            +
            end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
            Signal.trap(:INT) { puts "\nDone."; exit }
         | 
| 103 | 
            +
            loop do
         | 
| 104 | 
            +
              b.perf_buffer_poll()
         | 
| 105 | 
            +
            end
         | 
| @@ -0,0 +1,204 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            # Trace example for libc's USDT:
         | 
| 3 | 
            +
            # - memory_sbrk_more
         | 
| 4 | 
            +
            # - memory_sbrk_less
         | 
| 5 | 
            +
            # - memory_mallopt_free_dyn_thresholds
         | 
| 6 | 
            +
            # Description is here: https://www.gnu.org/software/libc/manual/html_node/Memory-Allocation-Probes.html
         | 
| 7 | 
            +
            #
         | 
| 8 | 
            +
            # Example output:
         | 
| 9 | 
            +
            # bundle exec ruby examples/sbrk_trace.rb -c ruby
         | 
| 10 | 
            +
            # !! Trace start.
         | 
| 11 | 
            +
            # [       0.000000000] pid=32756 comm=ruby probe=memory_sbrk_more addr=0x55f34b979000 size=135168
         | 
| 12 | 
            +
            # [       0.036549804] pid=32756 comm=ruby probe=memory_sbrk_more addr=0x557fd9760000 size=135168
         | 
| 13 | 
            +
            # [       0.036804183] pid=32756 comm=ruby probe=memory_sbrk_more addr=0x557fd9781000 size=143360
         | 
| 14 | 
            +
            # [       0.036855378] pid=32756 comm=ruby probe=memory_sbrk_less addr=0x557fd97a0000 size=16384
         | 
| 15 | 
            +
            # [       0.036931376] pid=32756 comm=ruby probe=memory_sbrk_more addr=0x557fd97a0000 size=147456
         | 
| 16 | 
            +
            # [       0.036940382] pid=32756 comm=ruby probe=memory_sbrk_less addr=0x557fd97c0000 size=16384
         | 
| 17 | 
            +
            # [       0.037022971] pid=32756 comm=ruby probe=memory_sbrk_more addr=0x557fd97c0000 size=151552
         | 
| 18 | 
            +
            # [       0.038602464] pid=32756 comm=ruby probe=memory_sbrk_more addr=0x557fd97e5000 size=204800
         | 
| 19 | 
            +
            # [       0.039398297] pid=32756 comm=ruby probe=memory_sbrk_more addr=0x557fd9817000 size=135168
         | 
| 20 | 
            +
            # [       0.039909594] pid=32756 comm=ruby probe=memory_sbrk_more addr=0x557fd9838000 size=135168
         | 
| 21 | 
            +
            # [       0.040536005] pid=32756 comm=ruby probe=memory_sbrk_more addr=0x557fd9859000 size=163840
         | 
| 22 | 
            +
            # ...
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            require 'rbbcc'
         | 
| 25 | 
            +
            include RbBCC
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            def usage
         | 
| 28 | 
            +
              puts("USAGE: #{$0} [-p PID|-c COMM]")
         | 
| 29 | 
            +
              exit()
         | 
| 30 | 
            +
            end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            def find_libc_location
         | 
| 33 | 
            +
              if File.exist?('/lib/x86_64-linux-gnu/libc.so.6')
         | 
| 34 | 
            +
                '/lib/x86_64-linux-gnu/libc.so.6'
         | 
| 35 | 
            +
              else
         | 
| 36 | 
            +
                `find /lib -name 'libc.so*' | grep -v musl | head -1`.chomp
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            usage if ARGV.size != 0 && ARGV.size != 2
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            pid = comm = nil
         | 
| 43 | 
            +
            path = find_libc_location
         | 
| 44 | 
            +
            case ARGV[0]
         | 
| 45 | 
            +
            when '-p', '--pid'
         | 
| 46 | 
            +
              pid = ARGV[1].to_i
         | 
| 47 | 
            +
            when '-c', '--comm'
         | 
| 48 | 
            +
              comm = ARGV[1]
         | 
| 49 | 
            +
            when nil
         | 
| 50 | 
            +
              # nop
         | 
| 51 | 
            +
            else
         | 
| 52 | 
            +
              usage
         | 
| 53 | 
            +
            end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            debug = !!ENV['DEBUG']
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            bpf_text = <<BPF
         | 
| 58 | 
            +
            #include <uapi/linux/ptrace.h>
         | 
| 59 | 
            +
            #include <linux/sched.h>
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            struct data_t {
         | 
| 62 | 
            +
                u32 type;
         | 
| 63 | 
            +
                u64 ts;
         | 
| 64 | 
            +
                u32 pid;
         | 
| 65 | 
            +
                char comm[TASK_COMM_LEN];
         | 
| 66 | 
            +
                u64 addr;
         | 
| 67 | 
            +
                u32 sbrk_size;
         | 
| 68 | 
            +
                u32 adjusted_mmap;
         | 
| 69 | 
            +
                u32 trim_thresholds;
         | 
| 70 | 
            +
            };
         | 
| 71 | 
            +
            BPF_PERF_OUTPUT(events);
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            static inline bool streq(uintptr_t str) {
         | 
| 74 | 
            +
                char needle[] = "{{NEEDLE}}";
         | 
| 75 | 
            +
                char haystack[sizeof(needle)];
         | 
| 76 | 
            +
                bpf_probe_read(&haystack, sizeof(haystack), (void *)str);
         | 
| 77 | 
            +
                for (int i = 0; i < sizeof(needle) - 1; ++i) {
         | 
| 78 | 
            +
                    if (needle[i] != haystack[i]) {
         | 
| 79 | 
            +
                        return false;
         | 
| 80 | 
            +
                    }
         | 
| 81 | 
            +
                }
         | 
| 82 | 
            +
                return true;
         | 
| 83 | 
            +
            }
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            #define PROBE_TYPE_more 1
         | 
| 86 | 
            +
            #define PROBE_TYPE_less 2
         | 
| 87 | 
            +
            #define PROBE_TYPE_free 3
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            {{FUNC_MORE}}
         | 
| 90 | 
            +
             | 
| 91 | 
            +
            {{FUNC_LESS}}
         | 
| 92 | 
            +
             | 
| 93 | 
            +
            int trace_memory_free(struct pt_regs *ctx) {
         | 
| 94 | 
            +
                struct data_t data = {};
         | 
| 95 | 
            +
                long buf;
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                data.type = PROBE_TYPE_free;
         | 
| 98 | 
            +
                data.ts = bpf_ktime_get_ns();
         | 
| 99 | 
            +
                data.pid = bpf_get_current_pid_tgid();
         | 
| 100 | 
            +
                bpf_get_current_comm(&data.comm, sizeof(data.comm));
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                {{NEEDLE_START}}
         | 
| 103 | 
            +
                bpf_usdt_readarg(1, ctx, &buf);
         | 
| 104 | 
            +
                data.adjusted_mmap = buf;
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                bpf_usdt_readarg(2, ctx, &buf);
         | 
| 107 | 
            +
                data.trim_thresholds = buf;
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                events.perf_submit(ctx, &data, sizeof(data));
         | 
| 110 | 
            +
                {{NEEDLE_END}}
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                return 0;
         | 
| 113 | 
            +
            };
         | 
| 114 | 
            +
             | 
| 115 | 
            +
            BPF
         | 
| 116 | 
            +
             | 
| 117 | 
            +
            trace_fun_sbrk = <<FUNC
         | 
| 118 | 
            +
            int trace_memory_sbrk_{{TYPE}}(struct pt_regs *ctx) {
         | 
| 119 | 
            +
                struct data_t data = {};
         | 
| 120 | 
            +
                long buf;
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                data.type = PROBE_TYPE_{{TYPE}};
         | 
| 123 | 
            +
                data.ts = bpf_ktime_get_ns();
         | 
| 124 | 
            +
                data.pid = bpf_get_current_pid_tgid();
         | 
| 125 | 
            +
                bpf_get_current_comm(&data.comm, sizeof(data.comm));
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                {{NEEDLE_START}}
         | 
| 128 | 
            +
                bpf_usdt_readarg(1, ctx, &buf);
         | 
| 129 | 
            +
                data.addr = buf;
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                bpf_usdt_readarg(2, ctx, &buf);
         | 
| 132 | 
            +
                data.sbrk_size = buf;
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                events.perf_submit(ctx, &data, sizeof(data));
         | 
| 135 | 
            +
                {{NEEDLE_END}}
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                return 0;
         | 
| 138 | 
            +
            };
         | 
| 139 | 
            +
            FUNC
         | 
| 140 | 
            +
             | 
| 141 | 
            +
            PROBE_TYPE_more = 1
         | 
| 142 | 
            +
            PROBE_TYPE_less = 2
         | 
| 143 | 
            +
            PROBE_TYPE_free = 3
         | 
| 144 | 
            +
            PROBE_MAP = {
         | 
| 145 | 
            +
              PROBE_TYPE_more => 'memory_sbrk_more',
         | 
| 146 | 
            +
              PROBE_TYPE_less => 'memory_sbrk_less',
         | 
| 147 | 
            +
              PROBE_TYPE_free => 'memory_mallopt_free_dyn_thresholds'
         | 
| 148 | 
            +
            }
         | 
| 149 | 
            +
             | 
| 150 | 
            +
            bpf_text.sub!('{{FUNC_MORE}}', trace_fun_sbrk.gsub('{{TYPE}}', 'more'))
         | 
| 151 | 
            +
            bpf_text.sub!('{{FUNC_LESS}}', trace_fun_sbrk.gsub('{{TYPE}}', 'less'))
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            if comm
         | 
| 154 | 
            +
              bpf_text.sub!('{{NEEDLE}}', comm)
         | 
| 155 | 
            +
              bpf_text.gsub!('{{NEEDLE_START}}', "if(streq((uintptr_t)data.comm)) {")
         | 
| 156 | 
            +
              bpf_text.gsub!('{{NEEDLE_END}}', "}")
         | 
| 157 | 
            +
            else
         | 
| 158 | 
            +
              bpf_text.sub!('{{NEEDLE}}', "")
         | 
| 159 | 
            +
              bpf_text.gsub!('{{NEEDLE_START}}', "")
         | 
| 160 | 
            +
              bpf_text.gsub!('{{NEEDLE_END}}', "")
         | 
| 161 | 
            +
            end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
            u = USDT.new(pid: pid, path: path)
         | 
| 164 | 
            +
            u.enable_probe(probe: "memory_sbrk_more", fn_name: "trace_memory_sbrk_more")
         | 
| 165 | 
            +
            u.enable_probe(probe: "memory_sbrk_less", fn_name: "trace_memory_sbrk_less")
         | 
| 166 | 
            +
            if pid
         | 
| 167 | 
            +
              # FIXME: Only available when PID is specified
         | 
| 168 | 
            +
              # otherwise got an error:
         | 
| 169 | 
            +
              #     bpf: Failed to load program: Invalid argument
         | 
| 170 | 
            +
              #     last insn is not an exit or jmp
         | 
| 171 | 
            +
              # It seems libbcc won't generate proper readarg helper
         | 
| 172 | 
            +
              u.enable_probe(probe: "memory_mallopt_free_dyn_thresholds", fn_name: "trace_memory_free")
         | 
| 173 | 
            +
            end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
            # initialize BPF
         | 
| 176 | 
            +
            b = BCC.new(text: bpf_text, usdt_contexts: [u])
         | 
| 177 | 
            +
             | 
| 178 | 
            +
            puts "!! Trace start."
         | 
| 179 | 
            +
            # process event
         | 
| 180 | 
            +
            start = 0
         | 
| 181 | 
            +
            b["events"].open_perf_buffer do |cpu, data, size|
         | 
| 182 | 
            +
              event = b["events"].event(data)
         | 
| 183 | 
            +
              if start == 0
         | 
| 184 | 
            +
                start = event.ts
         | 
| 185 | 
            +
              end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
              time_s = ((event.ts - start).to_f) / 1000000000
         | 
| 188 | 
            +
              if [PROBE_TYPE_more, PROBE_TYPE_less].include?(event.type)
         | 
| 189 | 
            +
                puts(
         | 
| 190 | 
            +
                  "[%18.9f] pid=%d comm=%s probe=%s addr=%#x size=%d" %
         | 
| 191 | 
            +
                  [time_s, event.pid, event.comm, PROBE_MAP[event.type], event.addr, event.sbrk_size]
         | 
| 192 | 
            +
                )
         | 
| 193 | 
            +
              else
         | 
| 194 | 
            +
                puts(
         | 
| 195 | 
            +
                  "[%18.9f] pid=%d comm=%s probe=%s adjusted_mmap=%d trim_thresholds=%d" %
         | 
| 196 | 
            +
                  [time_s, event.pid, event.comm, PROBE_MAP[event.type], event.adjusted_mmap, event.trim_thresholds]
         | 
| 197 | 
            +
                )
         | 
| 198 | 
            +
              end
         | 
| 199 | 
            +
            end
         | 
| 200 | 
            +
             | 
| 201 | 
            +
            Signal.trap(:INT) { puts "\n!! Done."; exit }
         | 
| 202 | 
            +
            loop do
         | 
| 203 | 
            +
              b.perf_buffer_poll()
         | 
| 204 | 
            +
            end
         | 
    
        data/lib/rbbcc/bcc.rb
    CHANGED
    
    | @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            require 'rbbcc/consts'
         | 
| 2 2 | 
             
            require 'rbbcc/table'
         | 
| 3 3 | 
             
            require 'rbbcc/symbol_cache'
         | 
| 4 | 
            +
            require 'rbbcc/debug'
         | 
| 4 5 |  | 
| 5 6 | 
             
            module RbBCC
         | 
| 6 7 | 
             
              SYSCALL_PREFIXES = [
         | 
| @@ -217,6 +218,7 @@ module RbBCC | |
| 217 218 | 
             
                      text = code + text
         | 
| 218 219 | 
             
                    end
         | 
| 219 220 |  | 
| 221 | 
            +
                    # Util.debug text
         | 
| 220 222 | 
             
                    @module = Clib.bpf_module_create_c_from_string(
         | 
| 221 223 | 
             
                      text,
         | 
| 222 224 | 
             
                      debug,
         | 
| @@ -282,7 +284,7 @@ module RbBCC | |
| 282 284 | 
             
                  if fd < 0
         | 
| 283 285 | 
             
                    raise SystemCallError.new("Failed to attach BPF program #{fn_name} to tracepoint #{tp}", Fiddle.last_error)
         | 
| 284 286 | 
             
                  end
         | 
| 285 | 
            -
                   | 
| 287 | 
            +
                  Util.debug "Attach: #{tp}"
         | 
| 286 288 | 
             
                  @tracepoint_fds[tp] = fd
         | 
| 287 289 | 
             
                  self
         | 
| 288 290 | 
             
                end
         | 
| @@ -297,7 +299,7 @@ module RbBCC | |
| 297 299 | 
             
                  if fd < 0
         | 
| 298 300 | 
             
                    raise SystemCallError.new("Failed to attach BPF program #{fn_name} to raw tracepoint #{tp}", Fiddle.last_error)
         | 
| 299 301 | 
             
                  end
         | 
| 300 | 
            -
                   | 
| 302 | 
            +
                  Util.debug "Attach: #{tp}"
         | 
| 301 303 | 
             
                  @raw_tracepoint_fds[tp] = fd
         | 
| 302 304 | 
             
                  self
         | 
| 303 305 | 
             
                end
         | 
| @@ -309,7 +311,7 @@ module RbBCC | |
| 309 311 | 
             
                  if fd < 0
         | 
| 310 312 | 
             
                    raise SystemCallError.new("Failed to attach BPF program #{fn_name} to kprobe #{event}", Fiddle.last_error)
         | 
| 311 313 | 
             
                  end
         | 
| 312 | 
            -
                   | 
| 314 | 
            +
                  Util.debug "Attach: #{ev_name}"
         | 
| 313 315 | 
             
                  @kprobe_fds[ev_name] = fd
         | 
| 314 316 | 
             
                  [ev_name, fd]
         | 
| 315 317 | 
             
                end
         | 
| @@ -322,7 +324,7 @@ module RbBCC | |
| 322 324 | 
             
                  if fd < 0
         | 
| 323 325 | 
             
                    raise SystemCallError.new("Failed to attach BPF program #{fn_name} to kretprobe #{event}", Fiddle.last_error)
         | 
| 324 326 | 
             
                  end
         | 
| 325 | 
            -
                   | 
| 327 | 
            +
                  Util.debug "Attach: #{ev_name}"
         | 
| 326 328 | 
             
                  @kprobe_fds[ev_name] = fd
         | 
| 327 329 | 
             
                  [ev_name, fd]
         | 
| 328 330 | 
             
                end
         | 
| @@ -336,7 +338,7 @@ module RbBCC | |
| 336 338 | 
             
                  if fd < 0
         | 
| 337 339 | 
             
                    raise SystemCallError.new(Fiddle.last_error)
         | 
| 338 340 | 
             
                  end
         | 
| 339 | 
            -
                   | 
| 341 | 
            +
                  Util.debug "Attach: #{ev_name}"
         | 
| 340 342 |  | 
| 341 343 | 
             
                  @uprobe_fds[ev_name] = fd
         | 
| 342 344 | 
             
                  [ev_name, fd]
         | 
| @@ -351,7 +353,7 @@ module RbBCC | |
| 351 353 | 
             
                  if fd < 0
         | 
| 352 354 | 
             
                    raise SystemCallError.new(Fiddle.last_error)
         | 
| 353 355 | 
             
                  end
         | 
| 354 | 
            -
                   | 
| 356 | 
            +
                  Util.debug "Attach: #{ev_name}"
         | 
| 355 357 |  | 
| 356 358 | 
             
                  @uprobe_fds[ev_name] = fd
         | 
| 357 359 | 
             
                  [ev_name, fd]
         | 
| @@ -552,7 +554,7 @@ module RbBCC | |
| 552 554 | 
             
                    else
         | 
| 553 555 | 
             
                      next
         | 
| 554 556 | 
             
                    end
         | 
| 555 | 
            -
                     | 
| 557 | 
            +
                    Util.debug "Found fnc: #{func_name}"
         | 
| 556 558 | 
             
                    if func_name.start_with?("kprobe__")
         | 
| 557 559 | 
             
                      fn = load_func(func_name, BPF::KPROBE)
         | 
| 558 560 | 
             
                      attach_kprobe(
         | 
    
        data/lib/rbbcc/clib.rb
    CHANGED
    
    | @@ -120,10 +120,11 @@ module RbBCC | |
| 120 120 | 
             
                extern 'char * bpf_perf_event_field(void *program, const char *event, size_t i)'
         | 
| 121 121 |  | 
| 122 122 | 
             
                extern 'void * bcc_usdt_new_frompid(int, char *)'
         | 
| 123 | 
            +
                extern 'void * bcc_usdt_new_frompath(char *path)'
         | 
| 123 124 | 
             
                extern 'int bcc_usdt_enable_probe(void *, char *, char *)'
         | 
| 124 125 | 
             
                extern 'char * bcc_usdt_genargs(void **, int)'
         | 
| 125 126 | 
             
                extern 'void bcc_usdt_foreach_uprobe(void *, void *)'
         | 
| 126 | 
            -
             | 
| 127 | 
            +
                extern 'void bcc_usdt_close(void *usdt)'
         | 
| 127 128 | 
             
                BCCSymbol = struct([
         | 
| 128 129 | 
             
                                     "const char *name",
         | 
| 129 130 | 
             
                                     "const char *demangle_name",
         | 
    
        data/lib/rbbcc/debug.rb
    ADDED
    
    
    
        data/lib/rbbcc/usdt.rb
    CHANGED
    
    | @@ -4,15 +4,21 @@ module RbBCC | |
| 4 4 | 
             
              USDTProbe = Struct.new(:binpath, :fn_name, :addr, :pid)
         | 
| 5 5 |  | 
| 6 6 | 
             
              class USDT
         | 
| 7 | 
            -
                 | 
| 8 | 
            -
                def initialize(pid:)
         | 
| 7 | 
            +
                def initialize(pid: nil, path: nil)
         | 
| 9 8 | 
             
                  @pid = pid
         | 
| 10 | 
            -
                  @ | 
| 9 | 
            +
                  @path = path
         | 
| 10 | 
            +
                  if pid
         | 
| 11 | 
            +
                    @context = Clib.bcc_usdt_new_frompid(pid, path)
         | 
| 12 | 
            +
                  elsif path
         | 
| 13 | 
            +
                    @context = Clib.bcc_usdt_new_frompath(path)
         | 
| 14 | 
            +
                  else
         | 
| 15 | 
            +
                    raise "Either a pid or a binary path must be specified"
         | 
| 16 | 
            +
                  end
         | 
| 11 17 | 
             
                  if !@context || @context.null?
         | 
| 12 18 | 
             
                    raise SystemCallError.new(Fiddle.last_error)
         | 
| 13 19 | 
             
                  end
         | 
| 14 20 | 
             
                end
         | 
| 15 | 
            -
                attr_reader :pid, :context
         | 
| 21 | 
            +
                attr_reader :pid, :path, :context
         | 
| 16 22 |  | 
| 17 23 | 
             
                def enable_probe(probe:, fn_name:)
         | 
| 18 24 | 
             
                  ret = Clib.bcc_usdt_enable_probe(@context, probe, fn_name)
         | 
| @@ -33,5 +39,16 @@ module RbBCC | |
| 33 39 |  | 
| 34 40 | 
             
                  return probes
         | 
| 35 41 | 
             
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                private
         | 
| 44 | 
            +
                def __del__
         | 
| 45 | 
            +
                  lambda { Clib.bcc_usdt_close(@context); Util.debug("USDT GC'ed.") }
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            at_exit do
         | 
| 51 | 
            +
              ObjectSpace.each_object(RbBCC::USDT) do |o|
         | 
| 52 | 
            +
                o.send(:__del__).call
         | 
| 36 53 | 
             
              end
         | 
| 37 54 | 
             
            end
         | 
    
        data/lib/rbbcc/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: rbbcc
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.4. | 
| 4 | 
            +
              version: 0.4.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Uchio Kondo
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2020-03- | 
| 11 | 
            +
            date: 2020-03-26 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -123,6 +123,8 @@ files: | |
| 123 123 | 
             
            - examples/mallocstack.rb
         | 
| 124 124 | 
             
            - examples/networking/http_filter/http-parse-simple.c
         | 
| 125 125 | 
             
            - examples/networking/http_filter/http-parse-simple.rb
         | 
| 126 | 
            +
            - examples/ruby_usdt.rb
         | 
| 127 | 
            +
            - examples/sbrk_trace.rb
         | 
| 126 128 | 
             
            - examples/tools/execsnoop.rb
         | 
| 127 129 | 
             
            - examples/tools/runqlat.rb
         | 
| 128 130 | 
             
            - examples/urandomread-explicit.rb
         | 
| @@ -134,6 +136,7 @@ files: | |
| 134 136 | 
             
            - lib/rbbcc/clib.rb
         | 
| 135 137 | 
             
            - lib/rbbcc/consts.rb
         | 
| 136 138 | 
             
            - lib/rbbcc/cpu_helper.rb
         | 
| 139 | 
            +
            - lib/rbbcc/debug.rb
         | 
| 137 140 | 
             
            - lib/rbbcc/disp_helper.rb
         | 
| 138 141 | 
             
            - lib/rbbcc/fiddle_ext.rb
         | 
| 139 142 | 
             
            - lib/rbbcc/symbol_cache.rb
         |