bpfql 0.1.0 → 0.2.0
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/README.md +7 -3
 - data/examples/read-simple.rb +9 -0
 - data/lib/bpfql.rb +1 -0
 - data/lib/bpfql/cli.rb +10 -2
 - data/lib/bpfql/dsl.rb +71 -0
 - data/lib/bpfql/query.rb +1 -1
 - data/lib/bpfql/runner.rb +64 -1
 - data/lib/bpfql/version.rb +1 -1
 - metadata +4 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: b134a056eb4c5c02472903a1f49c68ebd9c3a9af551ce8024c681ac4113581ae
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: e0d3921a0b4861c7edd9c392f4117470ae4d6165b40298d0a9bd06bc3d232f56
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: a27deed2b4d0bcef159899d388fee10cfcdf7ba40c2f21f6f2226ddba29df53f2348ef0f09db321d5338f2b6cb3357d4d7b9f73cccad2b5af2aac0100353a59a
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: c62284c1237a94a3b1831d5320cff0240838ab1efbcc47ee4bec56a21754ee5149da1d711a604b8d0dad917dfc9aa2ded4000b2d4c159985e2641de6f4e2c3d1
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,5 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # BPFQL
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            [](https://badge.fury.io/rb/bpfql)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
       3 
5 
     | 
    
         
             
            eBPF query runner. Choose a format in:
         
     | 
| 
       4 
6 
     | 
    
         | 
| 
       5 
7 
     | 
    
         
             
            * Ruby DSL
         
     | 
| 
         @@ -36,7 +38,7 @@ end 
     | 
|
| 
       36 
38 
     | 
    
         
             
            ```ruby
         
     | 
| 
       37 
39 
     | 
    
         
             
            BPFQL do
         
     | 
| 
       38 
40 
     | 
    
         
             
              select "count()"
         
     | 
| 
       39 
     | 
    
         
            -
              from "tracepoint:syscalls: 
     | 
| 
      
 41 
     | 
    
         
            +
              from "tracepoint:syscalls:sys_enter_clone"
         
     | 
| 
       40 
42 
     | 
    
         
             
              group_by "comm"
         
     | 
| 
       41 
43 
     | 
    
         
             
              interval "15s"
         
     | 
| 
       42 
44 
     | 
    
         
             
            end
         
     | 
| 
         @@ -47,7 +49,7 @@ end 
     | 
|
| 
       47 
49 
     | 
    
         
             
            ```yaml
         
     | 
| 
       48 
50 
     | 
    
         
             
            BPFQL:
         
     | 
| 
       49 
51 
     | 
    
         
             
            - select: count()
         
     | 
| 
       50 
     | 
    
         
            -
              from: tracepoint:syscalls: 
     | 
| 
      
 52 
     | 
    
         
            +
              from: tracepoint:syscalls:sys_enter_clone
         
     | 
| 
       51 
53 
     | 
    
         
             
              group_by: comm
         
     | 
| 
       52 
54 
     | 
    
         
             
              stop_after: "30s"
         
     | 
| 
       53 
55 
     | 
    
         
             
            ```
         
     | 
| 
         @@ -55,12 +57,14 @@ BPFQL: 
     | 
|
| 
       55 
57 
     | 
    
         
             
            ```yaml
         
     | 
| 
       56 
58 
     | 
    
         
             
            BPFQL:
         
     | 
| 
       57 
59 
     | 
    
         
             
            - select: count()
         
     | 
| 
       58 
     | 
    
         
            -
              from: tracepoint:syscalls: 
     | 
| 
      
 60 
     | 
    
         
            +
              from: tracepoint:syscalls:sys_enter_clone
         
     | 
| 
       59 
61 
     | 
    
         
             
              where:
         
     | 
| 
       60 
62 
     | 
    
         
             
                - comm is "ruby"
         
     | 
| 
       61 
63 
     | 
    
         
             
                - pid is 12345
         
     | 
| 
       62 
64 
     | 
    
         
             
            ```
         
     | 
| 
       63 
65 
     | 
    
         | 
| 
      
 66 
     | 
    
         
            +
            * See [examples/](examples/) to find working examples.
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
       64 
68 
     | 
    
         
             
            ## Development
         
     | 
| 
       65 
69 
     | 
    
         | 
| 
       66 
70 
     | 
    
         
             
            After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
         
     | 
    
        data/lib/bpfql.rb
    CHANGED
    
    
    
        data/lib/bpfql/cli.rb
    CHANGED
    
    | 
         @@ -14,8 +14,16 @@ module Bpfql 
     | 
|
| 
       14 
14 
     | 
    
         
             
                    exit 1
         
     | 
| 
       15 
15 
     | 
    
         
             
                  end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                   
     | 
| 
       18 
     | 
    
         
            -
                  q =  
     | 
| 
      
 17 
     | 
    
         
            +
                  file = argv[0]
         
     | 
| 
      
 18 
     | 
    
         
            +
                  q = nil
         
     | 
| 
      
 19 
     | 
    
         
            +
                  case File.extname(file)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  when ".rb", ".bpfql"
         
     | 
| 
      
 21 
     | 
    
         
            +
                    dsl = File.read(file)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    q = [eval(dsl)]
         
     | 
| 
      
 23 
     | 
    
         
            +
                  when ".yml", ".yaml"
         
     | 
| 
      
 24 
     | 
    
         
            +
                    q = Bpfql::Query.parse_yaml(File.read file)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
       19 
27 
     | 
    
         
             
                  r = Bpfql::Runner.new(q[0])
         
     | 
| 
       20 
28 
     | 
    
         
             
                  r.run
         
     | 
| 
       21 
29 
     | 
    
         
             
                end
         
     | 
    
        data/lib/bpfql/dsl.rb
    ADDED
    
    | 
         @@ -0,0 +1,71 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'bpfql/query'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Bpfql
         
     | 
| 
      
 4 
     | 
    
         
            +
              class DSL
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(qb)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @builder = qb
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @_where_continue = false
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader :builder
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def select(*members)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  builder.select = Query::SelectOption.new(members)
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def from(probe)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  builder.from = Query::ProbeOption.new(probe)
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def where(*filter, **options)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  builder.where = []
         
     | 
| 
      
 21 
     | 
    
         
            +
                  builder.where << eval_where(*filter, **options)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @_where_continue = true
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def _and(*filter, **options)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  if @_where_continue
         
     | 
| 
      
 27 
     | 
    
         
            +
                    builder.where << eval_where(*filter, **options)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  else
         
     | 
| 
      
 29 
     | 
    
         
            +
                    raise ArgumentError, "Cannot invoke _and() before where()"
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def group_by(var)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  builder.group_by = var
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def interval(timing)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  builder.interval = timing
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                def stop_after(timing)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  builder.stop = Query::StopOption.new(:after, timing)
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                private
         
     | 
| 
      
 46 
     | 
    
         
            +
                def eval_where(*filter, **options)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  case filter.size
         
     | 
| 
      
 48 
     | 
    
         
            +
                  when 1
         
     | 
| 
      
 49 
     | 
    
         
            +
                    if (options.keys & %i(is not lt gt lteq gteq)).empty?
         
     | 
| 
      
 50 
     | 
    
         
            +
                      raise ArgumentError, "Invalid parameter: #{filter}, #{options}"
         
     | 
| 
      
 51 
     | 
    
         
            +
                    end
         
     | 
| 
      
 52 
     | 
    
         
            +
                    %i(is not lt gt lteq gteq).each do |ope|
         
     | 
| 
      
 53 
     | 
    
         
            +
                      if options.has_key?(ope)
         
     | 
| 
      
 54 
     | 
    
         
            +
                        return Query::FilterOption.new(filter[0], ope.to_s, options[ope])
         
     | 
| 
      
 55 
     | 
    
         
            +
                      end
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                  when 3
         
     | 
| 
      
 58 
     | 
    
         
            +
                    return Query::FilterOption.new(*filter)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  else
         
     | 
| 
      
 60 
     | 
    
         
            +
                    raise ArgumentError, "Invalid parameter: #{filter}, #{options}"
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
            end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            def BPFQL(&b)
         
     | 
| 
      
 67 
     | 
    
         
            +
              query = Bpfql::Query.new
         
     | 
| 
      
 68 
     | 
    
         
            +
              evaluator = Bpfql::DSL.new(query)
         
     | 
| 
      
 69 
     | 
    
         
            +
              evaluator.instance_eval(&b)
         
     | 
| 
      
 70 
     | 
    
         
            +
              query
         
     | 
| 
      
 71 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/bpfql/query.rb
    CHANGED
    
    
    
        data/lib/bpfql/runner.rb
    CHANGED
    
    | 
         @@ -10,6 +10,7 @@ module Bpfql 
     | 
|
| 
       10 
10 
     | 
    
         
             
                end
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                def run
         
     | 
| 
      
 13 
     | 
    
         
            +
                  $stderr.puts bpf_source if ENV['BPFQL_DEBUG']
         
     | 
| 
       13 
14 
     | 
    
         
             
                  @module = RbBCC::BCC.new(text: bpf_source)
         
     | 
| 
       14 
15 
     | 
    
         
             
                  puts(@fmt.gsub(/(\.\d+f|d)/, 's') % tracepoint_fields_sorted.map(&:upcase))
         
     | 
| 
       15 
16 
     | 
    
         | 
| 
         @@ -83,12 +84,16 @@ module Bpfql 
     | 
|
| 
       83 
84 
     | 
    
         
             
                    src = <<~FUNCTION
         
     | 
| 
       84 
85 
     | 
    
         
             
                      TRACEPOINT_PROBE(#{qb.probe.arg1}, #{qb.probe.arg2}) {
         
     | 
| 
       85 
86 
     | 
    
         
             
                        struct data_t data = {};
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
       86 
88 
     | 
    
         
             
                        __ASSIGN_PID__
         
     | 
| 
       87 
89 
     | 
    
         
             
                        __ASSIGN_TS__
         
     | 
| 
       88 
90 
     | 
    
         
             
                        __ASSIGN_COMM__
         
     | 
| 
       89 
91 
     | 
    
         | 
| 
       90 
92 
     | 
    
         
             
                        __ASSIGN_FIELDS__
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                        __FILTER__
         
     | 
| 
      
 95 
     | 
    
         
            +
                          events.perf_submit(args, &data, sizeof(data));
         
     | 
| 
      
 96 
     | 
    
         
            +
                        __FILTER_END__
         
     | 
| 
       92 
97 
     | 
    
         
             
                        return 0;
         
     | 
| 
       93 
98 
     | 
    
         
             
                      }
         
     | 
| 
       94 
99 
     | 
    
         
             
                    FUNCTION
         
     | 
| 
         @@ -104,12 +109,70 @@ module Bpfql 
     | 
|
| 
       104 
109 
     | 
    
         
             
                      }.join("\n")
         
     | 
| 
       105 
110 
     | 
    
         
             
                      src.sub!('__ASSIGN_FIELDS__', assigner)
         
     | 
| 
       106 
111 
     | 
    
         
             
                    end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                    if qb.where && !qb.where.empty?
         
     | 
| 
      
 114 
     | 
    
         
            +
                      src.sub!('__FILTER__', filter_clause)
         
     | 
| 
      
 115 
     | 
    
         
            +
                      src.sub!('__FILTER_END__', filter_end_clause)
         
     | 
| 
      
 116 
     | 
    
         
            +
                    else
         
     | 
| 
      
 117 
     | 
    
         
            +
                      src.sub!('__FILTER__', "")
         
     | 
| 
      
 118 
     | 
    
         
            +
                      src.sub!('__FILTER_END__', "")
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
       107 
120 
     | 
    
         
             
                    src
         
     | 
| 
       108 
121 
     | 
    
         
             
                  else
         
     | 
| 
       109 
122 
     | 
    
         
             
                    raise NotImplementedError, "unsupported probe: #{qb.probe.to_s}"
         
     | 
| 
       110 
123 
     | 
    
         
             
                  end
         
     | 
| 
       111 
124 
     | 
    
         
             
                end
         
     | 
| 
       112 
125 
     | 
    
         | 
| 
      
 126 
     | 
    
         
            +
                def filter_clause
         
     | 
| 
      
 127 
     | 
    
         
            +
                  conds = []
         
     | 
| 
      
 128 
     | 
    
         
            +
                  needle_section = ""
         
     | 
| 
      
 129 
     | 
    
         
            +
                  qb.where.each do |filter|
         
     | 
| 
      
 130 
     | 
    
         
            +
                    if filter[0] == "comm" # || field_maps[filter[0]] =~ /^const char \* #{filter[0]}$/
         
     | 
| 
      
 131 
     | 
    
         
            +
                      ope = case filter[1].to_s
         
     | 
| 
      
 132 
     | 
    
         
            +
                            when "is"; ""
         
     | 
| 
      
 133 
     | 
    
         
            +
                            when "not"; "!"
         
     | 
| 
      
 134 
     | 
    
         
            +
                            else
         
     | 
| 
      
 135 
     | 
    
         
            +
                              raise "String comparation supports only == or !=; You put: #{filter}"
         
     | 
| 
      
 136 
     | 
    
         
            +
                            end
         
     | 
| 
      
 137 
     | 
    
         
            +
                      filter_string = %Q<"#{filter[2]}">
         
     | 
| 
      
 138 
     | 
    
         
            +
                      needle_section = <<~NEEDLE
         
     | 
| 
      
 139 
     | 
    
         
            +
                        bool matched   = true;
         
     | 
| 
      
 140 
     | 
    
         
            +
                        char needle[] = #{filter_string};
         
     | 
| 
      
 141 
     | 
    
         
            +
                        char haystack[sizeof(needle)] = {};
         
     | 
| 
      
 142 
     | 
    
         
            +
                        bpf_probe_read(&haystack, sizeof(haystack), (void*)data.#{filter[0]});
         
     | 
| 
      
 143 
     | 
    
         
            +
                        for (int i = 0; i < sizeof(needle) - 1; ++i) {
         
     | 
| 
      
 144 
     | 
    
         
            +
                          if (needle[i] != haystack[i]) {
         
     | 
| 
      
 145 
     | 
    
         
            +
                            matched = false;
         
     | 
| 
      
 146 
     | 
    
         
            +
                          }
         
     | 
| 
      
 147 
     | 
    
         
            +
                        }
         
     | 
| 
      
 148 
     | 
    
         
            +
                      NEEDLE
         
     | 
| 
      
 149 
     | 
    
         
            +
                      conds << %Q<#{ope}matched>
         
     | 
| 
      
 150 
     | 
    
         
            +
                    else
         
     | 
| 
      
 151 
     | 
    
         
            +
                      lhs = "data.#{filter[0]}"
         
     | 
| 
      
 152 
     | 
    
         
            +
                      ope = case filter[1].to_s
         
     | 
| 
      
 153 
     | 
    
         
            +
                            when "is"; "=="
         
     | 
| 
      
 154 
     | 
    
         
            +
                            when "not"; "!="
         
     | 
| 
      
 155 
     | 
    
         
            +
                            when "lt"; "<"
         
     | 
| 
      
 156 
     | 
    
         
            +
                            when "gt"; ">"
         
     | 
| 
      
 157 
     | 
    
         
            +
                            when "lteq"; "<="
         
     | 
| 
      
 158 
     | 
    
         
            +
                            when "gteq"; ">="
         
     | 
| 
      
 159 
     | 
    
         
            +
                            else
         
     | 
| 
      
 160 
     | 
    
         
            +
                              raise "[BPFQL BUG] Cannot evaluate ope: #{filter}; This may be a bug"
         
     | 
| 
      
 161 
     | 
    
         
            +
                            end
         
     | 
| 
      
 162 
     | 
    
         
            +
                      rhs = filter[2]
         
     | 
| 
      
 163 
     | 
    
         
            +
                    conds << [lhs, ope, rhs].join(" ")
         
     | 
| 
      
 164 
     | 
    
         
            +
                    end
         
     | 
| 
      
 165 
     | 
    
         
            +
                  end
         
     | 
| 
      
 166 
     | 
    
         
            +
                  return <<~FILTER
         
     | 
| 
      
 167 
     | 
    
         
            +
                    #{needle_section}
         
     | 
| 
      
 168 
     | 
    
         
            +
                    if (#{conds.join("&&")}) {
         
     | 
| 
      
 169 
     | 
    
         
            +
                  FILTER
         
     | 
| 
      
 170 
     | 
    
         
            +
                end
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                def filter_end_clause
         
     | 
| 
      
 173 
     | 
    
         
            +
                  return "}"
         
     | 
| 
      
 174 
     | 
    
         
            +
                end
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
       113 
176 
     | 
    
         
             
                def tracepoint_fields
         
     | 
| 
       114 
177 
     | 
    
         
             
                  @fields ||= begin
         
     | 
| 
       115 
178 
     | 
    
         
             
                                if qb.select.members[0] == '*'
         
     | 
    
        data/lib/bpfql/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: bpfql
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.2.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Uchio Kondo
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2020-03- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2020-03-05 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rbbcc
         
     | 
| 
         @@ -42,9 +42,11 @@ files: 
     | 
|
| 
       42 
42 
     | 
    
         
             
            - bin/setup
         
     | 
| 
       43 
43 
     | 
    
         
             
            - bpfql.gemspec
         
     | 
| 
       44 
44 
     | 
    
         
             
            - examples/random-simple.yml
         
     | 
| 
      
 45 
     | 
    
         
            +
            - examples/read-simple.rb
         
     | 
| 
       45 
46 
     | 
    
         
             
            - exe/bpfql
         
     | 
| 
       46 
47 
     | 
    
         
             
            - lib/bpfql.rb
         
     | 
| 
       47 
48 
     | 
    
         
             
            - lib/bpfql/cli.rb
         
     | 
| 
      
 49 
     | 
    
         
            +
            - lib/bpfql/dsl.rb
         
     | 
| 
       48 
50 
     | 
    
         
             
            - lib/bpfql/query.rb
         
     | 
| 
       49 
51 
     | 
    
         
             
            - lib/bpfql/runner.rb
         
     | 
| 
       50 
52 
     | 
    
         
             
            - lib/bpfql/version.rb
         
     |