acme@redhat.com |
---|
# pfunct --prototype tests/prometheus/main | grep -w counter void vendor/golang.org/x/crypto/chacha20.(*Cipher).SetCounter(vendor/golang.org/x/crypto/chacha20.Cipher *s, uint32 counter); void crypto/cipher.(*gcm).deriveCounter(crypto/cipher.gcm *g, uint8 *counter, struct []uint8 nonce); void crypto/cipher.(*gcm).counterCrypt(crypto/cipher.gcm *g, struct []uint8 out, struct []uint8 in, uint8 *counter); void github.com/prometheus/client_golang/prometheus.(*counter).Describe(chan<- *github.com/prometheus/client_golang/prometheus.Desc ch); void github.com/prometheus/client_golang/prometheus.(*counter).Collect(chan<- github.com/prometheus/client_golang/prometheus.Metric ch); void github.com/prometheus/client_golang/prometheus.(*counter).Inc(github.com/prometheus/client_golang/prometheus.counter *c); void github.com/prometheus/client_golang/prometheus.(*counter).get(github.com/prometheus/client_golang/prometheus.counter *c); void github.com/prometheus/client_golang/prometheus.(*counter).Add(github.com/prometheus/client_golang/prometheus.counter *c, float64 v); #
# perf probe -x tests/prometheus/main -F *Inc* crypto/x509.IncorrectPasswordError github.com/prometheus/client_golang/prometheus.(*counter).Inc github.com/prometheus/client_golang/prometheus.(*gauge).Inc github.com/prometheus/client_golang/prometheus.errInconsistentCardinality github.com/prometheus/common/expfmt.NegotiateIncludingOpenMetrics vendor/golang.org/x/crypto/chacha20poly1305.avx2IncMask vendor/golang.org/x/crypto/chacha20poly1305.sseIncMask vendor/golang.org/x/text/transform.errInconsistentByteCount #
# pahole tests/prometheus/main -C github.com/prometheus/client_golang/prometheus.counter struct github.com/prometheus/client_golang/prometheus.counter { uint64 valBits; /* 0 8 */ uint64 valInt; /* 8 8 */ github.com/prometheus/client_golang/prometheus.selfCollector selfCollector; /* 16 16 */ github.com/prometheus/client_golang/prometheus.Desc * desc; /* 32 8 */ struct []*github.com/prometheus/client_model/go.LabelPair labelPairs; /* 40 24 */ /* --- cacheline 1 boundary (64 bytes) --- */ sync/atomic.Value exemplar; /* 64 16 */ func() time.Time now; /* 80 8 */ /* size: 88, cachelines: 2, members: 7 */ /* last cacheline: 24 bytes */ }; #
# perf probe -L kfree
<kfree@/usr/src/debug/kernel-6.4.10/linux-6.4.10-200.fc38.x86_64/mm/slab_common.c:0> 0 void kfree(const void *object) { 2 struct folio *folio; struct slab *slab; struct kmem_cache *s; trace_kfree(_RET_IP_, object); 8 if (unlikely(ZERO_OR_NULL_PTR(object))) return; 11 folio = virt_to_folio(object); 12 if (unlikely(!folio_test_slab(folio))) { 13 free_large_kmalloc(folio, (void *)object); return; } 17 slab = folio_slab(folio); s = slab->slab_cache; 19 __kmem_cache_free(s, (void *)object, _RET_IP_); } EXPORT_SYMBOL(kfree); #
# perf probe -x prometheusnoop -L prometheusnoop_bpf__open_opts
0 prometheusnoop_bpf__open_opts(const struct bpf_object_open_opts *opts) { struct prometheusnoop_bpf *obj; int err; 5 obj = (struct prometheusnoop_bpf *)calloc(1, sizeof(*obj)); 6 if (!obj) { 7 errno = ENOMEM; 8 return NULL; } 11 err = prometheusnoop_bpf__create_skeleton(obj); 12 if (err) 13 goto err_out; 15 err = bpf_object__open_skeleton(obj->skeleton, opts); 16 if (err) 17 goto err_out; 19 return obj; err_out: 21 prometheusnoop_bpf__destroy(obj); 22 errno = -err; 23 return NULL; 24 } static inline struct prometheusnoop_bpf * prometheusnoop_bpf__open(void) #
# perf probe -x /lib64/libc.so.6 -V malloc
Available variables at malloc @<__libc_malloc+0> char* __PRETTY_FUNCTION__ size_t bytes #
# perf probe -x /lib64/libc.so.6 __libc_malloc bytes Added new event: probe_libc:__libc_malloc (on __libc_malloc in /usr/lib64/libc.so.6 with bytes) You can now use it in all perf tools, such as: perf record -e probe_libc:__libc_malloc -aR sleep 1 #
# perf trace -e probe_libc:__libc_malloc/max-stack=8/ --max-events=2
0.000 gnome-control-/405742 probe_libc:__libc_malloc(__probe_ip: 139765834955664, bytes: 16) malloc (/usr/lib64/libc.so.6) g_slice_alloc (/usr/lib64/libglib-2.0.so.0.7600.5) g_object_notify_queue_freeze.lto_priv.0 (/usr/lib64/libgobject-2.0.so.0.7600.5) g_object_freeze_notify (/usr/lib64/libgobject-2.0.so.0.7600.5) gtk_window_set_default_size_internal (/usr/lib64/libgtk-4.so.1.1000.5) toplevel_compute_size (/usr/lib64/libgtk-4.so.1.1000.5) g_closure_invoke (/usr/lib64/libgobject-2.0.so.0.7600.5) signal_emit_unlocked_R.isra.0 (/usr/lib64/libgobject-2.0.so.0.7600.5)
0.014 gnome-control-/405742 probe_libc:__libc_malloc(__probe_ip: 139765834955664, bytes: 48) malloc (/usr/lib64/libc.so.6) g_slice_alloc (/usr/lib64/libglib-2.0.so.0.7600.5) g_source_new (/usr/lib64/libglib-2.0.so.0.7600.5) timeout_add_full.constprop.0 (/usr/lib64/libglib-2.0.so.0.7600.5) maybe_start_idle (/usr/lib64/libgtk-4.so.1.1000.5) gdk_frame_clock_paint_idle (/usr/lib64/libgtk-4.so.1.1000.5) g_timeout_dispatch (/usr/lib64/libglib-2.0.so.0.7600.5) g_main_context_dispatch (/usr/lib64/libglib-2.0.so.0.7600.5) #
# perf probe -x tests/prometheus/main -L 'github.com/prometheus/client_golang/prometheus.(*counter).Inc' Debuginfo analysis failed. Error: Failed to show lines. #
# perf probe -x tests/prometheus/main \ 'counter_inc=github.com/prometheus/client_golang/prometheus.(*counter).Inc' Added new event: probe_main:counter_inc (on github.com/prometheus/client_golang/prometheus.(*counter).Inc in /home/acme/git/libbpf-bootstrap/examples/c/tests/prometheus/main) You can now use it in all perf tools, such as: perf record -e probe_main:counter_inc -aR sleep 1 #
# perf probe -l probe_main:counter_inc (on github.com/prometheus/client_golang/prometheus.(*counter).Inc in /home/acme/git/libbpf-bootstrap/examples/c/tests/prometheus/main) #
# perf trace -e probe_main:counter_inc/max-stack=8/ --max-events=2 0.000 main/502040 probe_main:counter_inc(__probe_ip: 8072576) github.com/prometheus/client_golang/prometheus.(*counter).Inc (/home/acme/git/libbpf-bootstrap/examples/c/tests/prometheus/main) runtime.goexit.abi0 (/home/acme/git/libbpf-bootstrap/examples/c/tests/prometheus/main) 0.033 main/502040 probe_main:counter_inc(__probe_ip: 8072576) github.com/prometheus/client_golang/prometheus.(*counter).Inc (/home/acme/git/libbpf-bootstrap/examples/c/tests/prometheus/main) runtime.goexit.abi0 (/home/acme/git/libbpf-bootstrap/examples/c/tests/prometheus/main) #
# perf trace -e probe_main:counter_inc,connect 0.000 (0.064 ms): DNS Resolver #/7247 connect(fd: 94, uservaddr: { family: LOCAL, path: /run/systemd/resolve/io.systemd.Resolve }, addrlen: 42) = 0 2.344 (0.058 ms): DNS Resolver #/7247 connect(fd: 94, uservaddr: { family: INET6, port: 0, addr: 2800:3f0:4004:809::200e }, addrlen: 28) = -1 ENETUNREACH (Network is unreachable) 2.418 (0.012 ms): DNS Resolver #/7247 connect(fd: 94, uservaddr: { family: UNSPEC }, addrlen: 16) = 0 2.443 (0.029 ms): DNS Resolver #/7247 connect(fd: 94, uservaddr: { family: INET, port: 0, addr: 142.251.135.142 }, addrlen: 16) = 0 9.020 (0.057 ms): DNS Resolver #/7254 connect(fd: 94, uservaddr: { family: LOCAL, path: /run/systemd/resolve/io.systemd.Resolve }, addrlen: 42) = 0 11.064 (0.044 ms): DNS Resolver #/7254 connect(fd: 94, uservaddr: { family: INET6, port: 0, addr: 2800:3f0:4004:809::200e }, addrlen: 28) = -1 ENETUNREACH (Network is unreachable) 11.121 (0.011 ms): DNS Resolver #/7254 connect(fd: 94, uservaddr: { family: UNSPEC }, addrlen: 16) = 0 11.141 (0.019 ms): DNS Resolver #/7254 connect(fd: 94, uservaddr: { family: INET, port: 0, addr: 142.251.135.142 }, addrlen: 16) = 0 485.958 ( ): main/502042 probe_main:counter_inc(__probe_ip: 8072576) 486.006 ( ): main/502042 probe_main:counter_inc(__probe_ip: 8072576) 1485.959 ( ): main/502042 probe_main:counter_inc(__probe_ip: 8072576) ^C#
# bpftrace -e 'uprobe:tests/prometheus/main:github.com/prometheus/client_golang/prometheus.(*counter).Inc { printf("in here\n"); }' stdin:1:1-78: ERROR: syntax error, unexpected (, expecting { uprobe:tests/prometheus/main:github.com/prometheus/client_golang/prometheus.(*counter).Inc { printf("in here\n"); } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# bpftrace -e 'uprobe:tests/prometheus/main:github.com/prometheus/client_golang/prometheus*Inc { printf("in here\n"); }' Attaching 2 probes... in here in here in here in here in here in here ^C #
var fake_counter = prometheus.NewCounter(prometheus.CounterOpts{ Name: "fake_counter", Help: "Increments at every second", })
go func() { for { select { case <-ticker.C: fake_counter.Inc() } } }()
$ tests/prometheus/main Prometheus demo I0908 12:21:38.448655 495592 main.go:64] Starting metrics server at 127.0.0.1:8080
^C# ./prometheusnoop --include_description --binary tests/prometheus/main TIME EVENT(Object) PID 12:21:39 (0xc00021e3c0) 495592 : desc: "another_fake_gauge" value: 0.000000 12:21:39 (0xc00021e440) 495592 : desc: "sub_fake_gauge" value: 0.000000 12:21:39 (0xc00021e400) 495592 : desc: "dec_fake_gauge" value: 0.000000 12:21:40 (0xc0002000c0) 495592 : desc: "fake_counter" value: 0 12:21:41 (0xc000200120) 495592 : desc: "another_fake_counter" value: 0 12:21:41 (0xc000200120) 495592 : desc: "another_fake_counter" value: 1 12:21:42 (0xc00021e380) 495592 : desc: "fake_gauge" value: 0.000000 12:21:43 (0xc00021e3c0) 495592 : desc: "another_fake_gauge" value: 5.000000 12:21:43 (0xc00021e440) 495592 : desc: "sub_fake_gauge" value: -7.000000 12:21:43 (0xc00021e400) 495592 : desc: "dec_fake_gauge" value: -1.000000 12:21:44 (0xc0002000c0) 495592 : desc: "fake_counter" value: 1 ^C#
# pahole -C github.com/prometheus/client_golang/prometheus.counter tests/prometheus/main struct github.com/prometheus/client_golang/prometheus.counter { uint64 valBits; /* 0 8 */ uint64 valInt; /* 8 8 */ github.com/prometheus/client_golang/prometheus.selfCollector selfCollector; /* 16 16 */ github.com/prometheus/client_golang/prometheus.Desc * desc; /* 32 8 */ struct []*github.com/prometheus/client_model/go.LabelPair labelPairs; /* 40 24 */ /* --- cacheline 1 boundary (64 bytes) --- */ sync/atomic.Value exemplar; /* 64 16 */ func() time.Time now; /* 80 8 */ /* size: 88, cachelines: 2, members: 7 */ /* last cacheline: 24 bytes */ };
# pahole -C github.com/prometheus/client_golang/prometheus.Desc tests/prometheus/main struct github.com/prometheus/client_golang/prometheus.Desc { struct string fqName; /* 0 16 */ struct string help; /* 16 16 */ struct []*github.com/prometheus/client_model/go.LabelPair constLabelPairs; /* 32 24 */ struct []string variableLabels; /* 56 24 */ /* --- cacheline 1 boundary (64 bytes) was 16 bytes ago --- */ uint64 id; /* 80 8 */ uint64 dimHash; /* 88 8 */ error err; /* 96 16 */ /* size: 112, cachelines: 2, members: 7 */ /* last cacheline: 48 bytes */ };
# pahole -C string tests/prometheus/main struct string { uint8 * str; /* 0 8 */ int len; /* 8 8 */ /* size: 16, cachelines: 1, members: 2 */ /* last cacheline: 16 bytes */ };
$ objdump -S --disassemble='github.com/prometheus/client_golang/prometheus.(*gauge).Add' \ tests/prometheus/main | head -30 tests/prometheus/main: file format elf64-x86-64 000000000079dec0: func (g *gauge) Dec() { g.Add(-1) } func (g *gauge) Add(val float64) { for { 79dec0: eb 03 jmp 79dec5 <github.com/prometheus/client_golang/prometheus.(*gauge).Add+0x5> oldBits := atomic.LoadUint64(&g.valBits) 79dec2: 48 89 d8 mov %rbx,%rax 79dec5: 48 8b 08 mov (%rax),%rcx // Float64frombits returns the floating-point number corresponding // to the IEEE 754 binary representation b, with the sign bit of b // and the result in the same bit position. // Float64frombits(Float64bits(x)) == x. func Float64frombits(b uint64) float64 { return *(*float64)(unsafe.Pointer(&b)) } 79dec8: 66 48 0f 6e c9 movq %rcx,%xmm1 newBits := math.Float64bits(math.Float64frombits(oldBits) + val) 79decd: f2 0f 58 c8 addsd %xmm0,%xmm1 func Float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) } 79ded1: 66 48 0f 7e ca movq %xmm1,%rdx func (g *gauge) Add(val float64) { 79ded6: 48 89 c3 mov %rax,%rbx $
BPF_CALL_1(bpf_read_64bit_xmm_register, u32, regindex) { u64 ret; asm volatile("movq %%xmm0, %0" : "=r" (ret)); return ret; }
const struct bpf_func_proto bpf_read_64bit_xmm_register_proto = { .func = bpf_read_64bit_xmm_register, .gpl_only = false, .might_sleep = false, .ret_type = RET_INTEGER, .arg1_type = ARG_ANYTHING, };
var sub_fake_gauge = prometheus.NewGauge(prometheus.GaugeOpts{ Name: "sub_fake_gauge", Help: "Subtracts 5 at every second", }) <SNIP> go func() { for { select { case <-ticker.C: another_fake_gauge.Add(5) sub_fake_gauge.Sub(7) dec_fake_gauge.Dec() } } }()
# ./prometheusnoop --include_description -b tests/prometheus/main TIME EVENT(Object) PID 11:12:18 (0xc00021a3c0) 2431 : desc: "another_fake_gauge" value: 0.000000 inc: 5.000000 11:12:18 (0xc00021a440) 2431 : desc: "sub_fake_gauge" value: 0.000000 inc: 7.000000 11:12:18 (0xc00021a400) 2431 : desc: "dec_fake_gauge" value: 0.000000 inc: -7.000000 11:12:19 (0xc000218060) 2431 : desc: "fake_counter" value: 0 11:12:20 (0xc0002180c0) 2431 : desc: "another_fake_counter" value: 0 11:12:20 (0xc0002180c0) 2431 : desc: "another_fake_counter" value: 1 11:12:21 (0xc00021a380) 2431 : desc: "fake_gauge" value: 0.000000 11:12:22 (0xc00021a3c0) 2431 : desc: "another_fake_gauge" value: 5.000000 inc: 5.000000 11:12:22 (0xc00021a440) 2431 : desc: "sub_fake_gauge" value: -7.000000 inc: 7.000000 11:12:22 (0xc00021a400) 2431 : desc: "dec_fake_gauge" value: -1.000000 inc: -7.000000 11:12:23 (0xc000218060) 2431 : desc: "fake_counter" value: 1 11:12:24 (0xc0002180c0) 2431 : desc: "another_fake_counter" value: 2 11:12:24 (0xc0002180c0) 2431 : desc: "another_fake_counter" value: 3 11:12:25 (0xc00021a380) 2431 : desc: "fake_gauge" value: 1.000000 11:12:26 (0xc00021a3c0) 2431 : desc: "another_fake_gauge" value: 10.000000 inc: 5.000000 11:12:26 (0xc00021a440) 2431 : desc: "sub_fake_gauge" value: -14.000000 inc: 7.000000 11:12:26 (0xc00021a400) 2431 : desc: "dec_fake_gauge" value: -2.000000 inc: -7.000000 11:12:27 (0xc000218060) 2431 : desc: "fake_counter" value: 2 11:12:28 (0xc0002180c0) 2431 : desc: "another_fake_counter" value: 4 11:12:28 (0xc0002180c0) 2431 : desc: "another_fake_counter" value: 5 11:12:29 (0xc00021a380) 2431 : desc: "fake_gauge" value: 2.000000 11:12:30 (0xc00021a3c0) 2431 : desc: "another_fake_gauge" value: 15.000000 inc: 5.000000 11:12:30 (0xc00021a440) 2431 : desc: "sub_fake_gauge" value: -21.000000 inc: 7.000000 11:12:30 (0xc00021a400) 2431 : desc: "dec_fake_gauge" value: -3.000000 inc: -7.000000 ^C#
# perf bench uprobe # List of available benchmarks for collection 'uprobe': baseline: Baseline libc usleep(1000) call empty: Attach empty BPF prog to uprobe on usleep, system wide trace_printk: Attach trace_printk BPF prog to uprobe on usleep syswide #
# grep -m1 'model name' /proc/cpuinfo model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
# perf bench uprobe all # Running uprobe/baseline benchmark... # Executed 1,000 usleep(1000) calls Total time: 1,145,049 usecs 1,145.049 usecs/op
# Running uprobe/empty benchmark... # Executed 1,000 usleep(1000) calls Total time: 1,168,813 usecs +23,764 to baseline 1,168.813 usecs/op 23.764 usecs/op to baseline
# Running uprobe/trace_printk benchmark... # Executed 1,000 usleep(1000) calls Total time: 1,173,868 usecs +28,819 to baseline +5,055 to previous 1,173.868 usecs/op 28.819 usecs/op to baseline 5.055 usecs/op to previous #
$ perf probe -L rust_begin_unwind0 fn panic(info: &core::panic::PanicInfo<'_>) -> ! { 1 pr_emerg!("{}\n", info); // SAFETY: FFI call. 3 unsafe { bindings::BUG() }; } #
# perf probe rust_begin_unwind Failed to write event: Invalid argument Error: Failed to add events. #
# dmesg | tail -1 [ 9771.947668] trace_kprobe: Could not probe notrace function _text #
# pahole rust/alloc.o -C \&str die__process_class: tag not supported 0x33 (variant_part)! die__process_function: tag not supported 0x2f (template_type_parameter)! struct &str { u8 * data_ptr __attribute__((__aligned__(8))); /* 0 8 */ usize length __attribute__((__aligned__(8))); /* 8 8 */ /* size: 16, cachelines: 1, members: 2 */ /* forced alignments: 2 */ /* last cacheline: 16 bytes */ } __attribute__((__aligned__(8))); #
<1>: Abbrev Number: 8 (DW_TAG_structure_type) DW_AT_name : (indirect string, offset: 0x840): &str DW_AT_byte_size : 16 DW_AT_alignment : 8 <2> : Abbrev Number: 4 (DW_TAG_member) DW_AT_name : (indirect string, offset: 0x830): data_ptr DW_AT_type : <0xbe6> DW_AT_alignment : 8 DW_AT_data_member_location: 0 <2> : Abbrev Number: 4 (DW_TAG_member) DW_AT_name : (indirect string, offset: 0x839): length DW_AT_type : <0x89> DW_AT_alignment : 8 DW_AT_data_member_location: 8