diff --git a/.bcc.metadata b/.bcc.metadata new file mode 100644 index 0000000..71269e3 --- /dev/null +++ b/.bcc.metadata @@ -0,0 +1 @@ +34cd5c38225fedc75417f55108a306d6cbc198dd SOURCES/bcc-0.6.1.tar.gz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7c6148e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/bcc-0.6.1.tar.gz diff --git a/README.md b/README.md deleted file mode 100644 index 98f42b4..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/Disable-tests-cc.patch b/SOURCES/Disable-tests-cc.patch new file mode 100644 index 0000000..8661bf3 --- /dev/null +++ b/SOURCES/Disable-tests-cc.patch @@ -0,0 +1,28 @@ +From b3faa19c61a5a5385899a80bdd0d6a3052f1415a Mon Sep 17 00:00:00 2001 +From: Jerome Marchand +Date: Thu, 24 May 2018 16:11:30 +0200 +Subject: [PATCH] Disable tests/cc + +Some files in tests/cc/ don't compile on s390x. We can just disable +them until a better fix is available: the build target are not +installed anyway. + +--- + tests/CMakeLists.txt | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt +index 86abec9..48e9029 100644 +--- a/tests/CMakeLists.txt ++++ b/tests/CMakeLists.txt +@@ -8,7 +8,6 @@ add_test(NAME style-check COMMAND ${CMAKE_SOURCE_DIR}/scripts/style-check.sh) + set_tests_properties(style-check PROPERTIES PASS_REGULAR_EXPRESSION ".*") + + if(ENABLE_CLANG_JIT) +-add_subdirectory(cc) + add_subdirectory(python) + add_subdirectory(lua) + endif() +-- +2.13.6 + diff --git a/SOURCES/Fix-tools-for-RHEL-7.patch b/SOURCES/Fix-tools-for-RHEL-7.patch new file mode 100644 index 0000000..be136bb --- /dev/null +++ b/SOURCES/Fix-tools-for-RHEL-7.patch @@ -0,0 +1,559 @@ +From c28fdc2ad6c6acbd6c61dc78a6c6e114572357a5 Mon Sep 17 00:00:00 2001 +From: Jerome Marchand +Date: Thu, 16 Aug 2018 14:58:56 +0200 +Subject: [PATCH] Fix tools for RHEL 7 + +There some differences on RHEL 7 that make some tools fail. This patch +fixes the following: + - missing /sys/kernel/debug/kprobes/blacklist file + - missing __vfs_read() function + - aio_read/write methods replaced by read/write_iter in file_operations + - changes in mnt_namespace structure + - change in finish_task_switch() argument list + - changes in sock_common struct + - missing TCP_NEW_SYN_RECV TCP state + - mm_page_alloc tracepoint returns page struct instead of PFN + - iocb argument removed from tcp_sendmsg() +--- + src/python/bcc/__init__.py | 7 +++++-- + tools/btrfsdist.py | 13 +++++++------ + tools/btrfsslower.py | 13 +++++++------ + tools/cpudist.py | 4 +++- + tools/ext4dist.py | 11 ++++++----- + tools/ext4slower.py | 13 +++++++------ + tools/fileslower.py | 13 +++++++++---- + tools/memleak.py | 12 ++++++++++-- + tools/mountsnoop.py | 9 ++++----- + tools/nfsslower.py | 1 + + tools/offcputime.py | 4 +++- + tools/offwaketime.py | 4 +++- + tools/runqlat.py | 2 +- + tools/runqslower.py | 2 +- + tools/solisten.py | 2 +- + tools/tcpsubnet.py | 4 ++-- + tools/tcptracer.py | 9 ++++----- + tools/xfsdist.py | 8 ++++---- + tools/xfsslower.py | 11 ++++++----- + 19 files changed, 84 insertions(+), 58 deletions(-) + +diff --git a/src/python/bcc/__init__.py b/src/python/bcc/__init__.py +index 8f793aa..470ac49 100644 +--- a/src/python/bcc/__init__.py ++++ b/src/python/bcc/__init__.py +@@ -500,8 +500,11 @@ DEBUG_BPF_REGISTER_STATE = 0x10 + + @staticmethod + def get_kprobe_functions(event_re): +- with open("%s/../kprobes/blacklist" % TRACEFS, "rb") as blacklist_f: +- blacklist = set([line.rstrip().split()[1] for line in blacklist_f]) ++ try: ++ with open("%s/../kprobes/blacklist" % TRACEFS, "rb") as blacklist_f: ++ blacklist = set([line.rstrip().split()[1] for line in blacklist_f]) ++ except: ++ blacklist = set() + fns = [] + + in_init_section = 0 +diff --git a/tools/btrfsdist.py b/tools/btrfsdist.py +index 4659ab4..3326b67 100755 +--- a/tools/btrfsdist.py ++++ b/tools/btrfsdist.py +@@ -60,6 +60,7 @@ debug = 0 + bpf_text = """ + #include + #include ++#include + #include + + #define OP_NAME_LEN 8 +@@ -81,7 +82,7 @@ int trace_entry(struct pt_regs *ctx) + return 0; + } + +-// The current btrfs (Linux 4.5) uses generic_file_read_iter() instead of it's ++// btrfs uses generic_file_aio_read() instead of it's + // own read function. So we need to trace that and then filter on btrfs, which + // I do by checking file->f_op. + int trace_read_entry(struct pt_regs *ctx, struct kiocb *iocb) +@@ -193,13 +194,13 @@ bpf_text = bpf_text.replace('FACTOR', str(factor)) + # load BPF program + b = BPF(text=bpf_text) + +-# Common file functions. See earlier comment about generic_file_read_iter(). +-b.attach_kprobe(event="generic_file_read_iter", fn_name="trace_read_entry") +-b.attach_kprobe(event="btrfs_file_write_iter", fn_name="trace_entry") ++# Common file functions. See earlier comment about generic_file_aio_read(). ++b.attach_kprobe(event="generic_file_aio_read", fn_name="trace_read_entry") ++b.attach_kprobe(event="btrfs_file_aio_write", fn_name="trace_entry") + b.attach_kprobe(event="generic_file_open", fn_name="trace_open_entry") + b.attach_kprobe(event="btrfs_sync_file", fn_name="trace_entry") +-b.attach_kretprobe(event="generic_file_read_iter", fn_name="trace_read_return") +-b.attach_kretprobe(event="btrfs_file_write_iter", fn_name="trace_write_return") ++b.attach_kretprobe(event="generic_file_aio_read", fn_name="trace_read_return") ++b.attach_kretprobe(event="btrfs_file_aio_write", fn_name="trace_write_return") + b.attach_kretprobe(event="generic_file_open", fn_name="trace_open_return") + b.attach_kretprobe(event="btrfs_sync_file", fn_name="trace_fsync_return") + +diff --git a/tools/btrfsslower.py b/tools/btrfsslower.py +index 644cb22..a720396 100755 +--- a/tools/btrfsslower.py ++++ b/tools/btrfsslower.py +@@ -63,6 +63,7 @@ debug = 0 + bpf_text = """ + #include + #include ++#include + #include + #include + +@@ -97,7 +98,7 @@ BPF_PERF_OUTPUT(events); + // Store timestamp and size on entry + // + +-// The current btrfs (Linux 4.5) uses generic_file_read_iter() instead of it's ++// btrfs uses generic_file_aio_read() instead of it's + // own read function. So we need to trace that and then filter on btrfs, which + // I do by checking file->f_op. + int trace_read_entry(struct pt_regs *ctx, struct kiocb *iocb) +@@ -124,7 +125,7 @@ int trace_read_entry(struct pt_regs *ctx, struct kiocb *iocb) + return 0; + } + +-// btrfs_file_write_iter(): ++// btrfs_file_aio_write(): + int trace_write_entry(struct pt_regs *ctx, struct kiocb *iocb) + { + u64 id = bpf_get_current_pid_tgid(); +@@ -327,12 +328,12 @@ TASK_COMM_LEN = 16 # linux/sched.h + b = BPF(text=bpf_text) + + # Common file functions. See earlier comment about generic_*(). +-b.attach_kprobe(event="generic_file_read_iter", fn_name="trace_read_entry") +-b.attach_kprobe(event="btrfs_file_write_iter", fn_name="trace_write_entry") ++b.attach_kprobe(event="generic_file_aio_read", fn_name="trace_read_entry") ++b.attach_kprobe(event="btrfs_file_aio_write", fn_name="trace_write_entry") + b.attach_kprobe(event="generic_file_open", fn_name="trace_open_entry") + b.attach_kprobe(event="btrfs_sync_file", fn_name="trace_fsync_entry") +-b.attach_kretprobe(event="generic_file_read_iter", fn_name="trace_read_return") +-b.attach_kretprobe(event="btrfs_file_write_iter", fn_name="trace_write_return") ++b.attach_kretprobe(event="generic_file_aio_read", fn_name="trace_read_return") ++b.attach_kretprobe(event="btrfs_file_aio_write", fn_name="trace_write_return") + b.attach_kretprobe(event="generic_file_open", fn_name="trace_open_return") + b.attach_kretprobe(event="btrfs_sync_file", fn_name="trace_fsync_return") + +diff --git a/tools/cpudist.py b/tools/cpudist.py +index 4d7c9eb..ddb675e 100755 +--- a/tools/cpudist.py ++++ b/tools/cpudist.py +@@ -94,7 +94,9 @@ static inline void update_hist(u32 tgid, u32 pid, u64 ts) + STORE + } + +-int sched_switch(struct pt_regs *ctx, struct task_struct *prev) ++struct rq; ++ ++int sched_switch(struct pt_regs *ctx, struct rq *rq, struct task_struct *prev) + { + u64 ts = bpf_ktime_get_ns(); + u64 pid_tgid = bpf_get_current_pid_tgid(); +diff --git a/tools/ext4dist.py b/tools/ext4dist.py +index 227c138..f57cda8 100755 +--- a/tools/ext4dist.py ++++ b/tools/ext4dist.py +@@ -60,6 +60,7 @@ debug = 0 + bpf_text = """ + #include + #include ++#include + #include + + #define OP_NAME_LEN 8 +@@ -81,7 +82,7 @@ int trace_entry(struct pt_regs *ctx) + return 0; + } + +-// The current ext4 (Linux 4.5) uses generic_file_read_iter(), instead of it's ++// ext4 uses generic_file_aio_read(), instead of it's + // own function, for reads. So we need to trace that and then filter on ext4, + // which I do by checking file->f_op. + int trace_read_entry(struct pt_regs *ctx, struct kiocb *iocb) +@@ -183,12 +184,12 @@ b = BPF(text=bpf_text) + if BPF.get_kprobe_functions('ext4_file_read_iter'): + b.attach_kprobe(event="ext4_file_read_iter", fn_name="trace_entry") + else: +- b.attach_kprobe(event="generic_file_read_iter", fn_name="trace_read_entry") +-b.attach_kprobe(event="ext4_file_write_iter", fn_name="trace_entry") ++ b.attach_kprobe(event="generic_file_aio_read", fn_name="trace_read_entry") ++b.attach_kprobe(event="ext4_file_write", fn_name="trace_entry") + b.attach_kprobe(event="ext4_file_open", fn_name="trace_entry") + b.attach_kprobe(event="ext4_sync_file", fn_name="trace_entry") +-b.attach_kretprobe(event="generic_file_read_iter", fn_name="trace_read_return") +-b.attach_kretprobe(event="ext4_file_write_iter", fn_name="trace_write_return") ++b.attach_kretprobe(event="generic_file_aio_read", fn_name="trace_read_return") ++b.attach_kretprobe(event="ext4_file_write", fn_name="trace_write_return") + b.attach_kretprobe(event="ext4_file_open", fn_name="trace_open_return") + b.attach_kretprobe(event="ext4_sync_file", fn_name="trace_fsync_return") + +diff --git a/tools/ext4slower.py b/tools/ext4slower.py +index eb6430e..276123f 100755 +--- a/tools/ext4slower.py ++++ b/tools/ext4slower.py +@@ -64,6 +64,7 @@ debug = 0 + bpf_text = """ + #include + #include ++#include + #include + #include + +@@ -98,7 +99,7 @@ BPF_PERF_OUTPUT(events); + // Store timestamp and size on entry + // + +-// The current ext4 (Linux 4.5) uses generic_file_read_iter(), instead of it's ++// ext4 uses generic_file_aio_read(), instead of it's + // own function, for reads. So we need to trace that and then filter on ext4, + // which I do by checking file->f_op. + // The new Linux version (since form 4.10) uses ext4_file_read_iter(), And if the 'CONFIG_FS_DAX' +@@ -128,7 +129,7 @@ int trace_read_entry(struct pt_regs *ctx, struct kiocb *iocb) + return 0; + } + +-// ext4_file_write_iter(): ++// ext4_file_write(): + int trace_write_entry(struct pt_regs *ctx, struct kiocb *iocb) + { + u64 id = bpf_get_current_pid_tgid(); +@@ -328,15 +329,15 @@ b = BPF(text=bpf_text) + if BPF.get_kprobe_functions(b'ext4_file_read_iter'): + b.attach_kprobe(event="ext4_file_read_iter", fn_name="trace_read_entry") + else: +- b.attach_kprobe(event="generic_file_read_iter", fn_name="trace_read_entry") +-b.attach_kprobe(event="ext4_file_write_iter", fn_name="trace_write_entry") ++ b.attach_kprobe(event="generic_file_aio_read", fn_name="trace_read_entry") ++b.attach_kprobe(event="ext4_file_write", fn_name="trace_write_entry") + b.attach_kprobe(event="ext4_file_open", fn_name="trace_open_entry") + b.attach_kprobe(event="ext4_sync_file", fn_name="trace_fsync_entry") + if BPF.get_kprobe_functions(b'ext4_file_read_iter'): + b.attach_kretprobe(event="ext4_file_read_iter", fn_name="trace_read_return") + else: +- b.attach_kretprobe(event="generic_file_read_iter", fn_name="trace_read_return") +-b.attach_kretprobe(event="ext4_file_write_iter", fn_name="trace_write_return") ++ b.attach_kretprobe(event="generic_file_aio_read", fn_name="trace_read_return") ++b.attach_kretprobe(event="ext4_file_write", fn_name="trace_write_return") + b.attach_kretprobe(event="ext4_file_open", fn_name="trace_open_return") + b.attach_kretprobe(event="ext4_sync_file", fn_name="trace_fsync_return") + +diff --git a/tools/fileslower.py b/tools/fileslower.py +index 5caa4ca..6af91af 100755 +--- a/tools/fileslower.py ++++ b/tools/fileslower.py +@@ -124,7 +124,7 @@ int trace_read_entry(struct pt_regs *ctx, struct file *file, + char __user *buf, size_t count) + { + // skip non-sync I/O; see kernel code for __vfs_read() +- if (!(file->f_op->read_iter)) ++ if (!(file->f_op->aio_read)) + return 0; + return trace_rw_entry(ctx, file, buf, count); + } +@@ -133,7 +133,7 @@ int trace_write_entry(struct pt_regs *ctx, struct file *file, + char __user *buf, size_t count) + { + // skip non-sync I/O; see kernel code for __vfs_write() +- if (!(file->f_op->write_iter)) ++ if (!(file->f_op->aio_write)) + return 0; + return trace_rw_entry(ctx, file, buf, count); + } +@@ -200,8 +200,13 @@ b = BPF(text=bpf_text) + # do_sync_read/do_sync_write), but those became static. So trace these from + # the parent functions, at the cost of more overhead, instead. + # Ultimately, we should be using [V]FS tracepoints. +-b.attach_kprobe(event="__vfs_read", fn_name="trace_read_entry") +-b.attach_kretprobe(event="__vfs_read", fn_name="trace_read_return") ++try: ++ b.attach_kprobe(event="__vfs_read", fn_name="trace_read_entry") ++ b.attach_kretprobe(event="__vfs_read", fn_name="trace_read_return") ++except: ++ # older kernels don't have __vfs_read so try vfs_read instead ++ b.attach_kprobe(event="vfs_read", fn_name="trace_read_entry") ++ b.attach_kretprobe(event="vfs_read", fn_name="trace_read_return") + try: + b.attach_kprobe(event="__vfs_write", fn_name="trace_write_entry") + b.attach_kretprobe(event="__vfs_write", fn_name="trace_write_return") +diff --git a/tools/memleak.py b/tools/memleak.py +index 5d69538..3cf9ee0 100755 +--- a/tools/memleak.py ++++ b/tools/memleak.py +@@ -354,13 +354,21 @@ TRACEPOINT_PROBE(kmem, kmem_cache_free) { + return gen_free_enter((struct pt_regs *)args, (void *)args->ptr); + } + ++/* ++ * Upstream reads the PFN here, but on RHEL7 kernel this is not available ++ * and the address of the pages struct is returned instead. This value is ++ * used as the key in a hash to identify each allocation. No other allocation ++ * should return an address belonging to mem_map, so there's no risk of ++ * colision ++ */ ++ + TRACEPOINT_PROBE(kmem, mm_page_alloc) { + gen_alloc_enter((struct pt_regs *)args, PAGE_SIZE << args->order); +- return gen_alloc_exit2((struct pt_regs *)args, args->pfn); ++ return gen_alloc_exit2((struct pt_regs *)args, (size_t)args->page); + } + + TRACEPOINT_PROBE(kmem, mm_page_free) { +- return gen_free_enter((struct pt_regs *)args, (void *)args->pfn); ++ return gen_free_enter((struct pt_regs *)args, (void *)args->page); + } + """ + +diff --git a/tools/mountsnoop.py b/tools/mountsnoop.py +index 2d0fa1a..bec8993 100755 +--- a/tools/mountsnoop.py ++++ b/tools/mountsnoop.py +@@ -24,7 +24,6 @@ bpf_text = r""" + #include + + #include +-#include + + /* + * XXX: struct mnt_namespace is defined in fs/mount.h, which is private to the +@@ -34,7 +33,7 @@ bpf_text = r""" + */ + struct mnt_namespace { + atomic_t count; +- struct ns_common ns; ++ unsigned int proc_inum; + }; + + /* +@@ -69,7 +68,7 @@ struct data_t { + union { + /* EVENT_MOUNT, EVENT_UMOUNT */ + struct { +- /* current->nsproxy->mnt_ns->ns.inum */ ++ /* current->nsproxy->proc_inum */ + unsigned int mnt_ns; + char comm[TASK_COMM_LEN]; + unsigned long flags; +@@ -106,7 +105,7 @@ int syscall__mount(struct pt_regs *ctx, char __user *source, + task = (struct task_struct *)bpf_get_current_task(); + nsproxy = task->nsproxy; + mnt_ns = nsproxy->mnt_ns; +- event.enter.mnt_ns = mnt_ns->ns.inum; ++ event.enter.mnt_ns = mnt_ns->proc_inum; + events.perf_submit(ctx, &event, sizeof(event)); + + event.type = EVENT_MOUNT_SOURCE; +@@ -161,7 +160,7 @@ int syscall__umount(struct pt_regs *ctx, char __user *target, int flags) + task = (struct task_struct *)bpf_get_current_task(); + nsproxy = task->nsproxy; + mnt_ns = nsproxy->mnt_ns; +- event.enter.mnt_ns = mnt_ns->ns.inum; ++ event.enter.mnt_ns = mnt_ns->proc_inum; + events.perf_submit(ctx, &event, sizeof(event)); + + event.type = EVENT_UMOUNT_TARGET; +diff --git a/tools/nfsslower.py b/tools/nfsslower.py +index 0f836af..a7018cb 100755 +--- a/tools/nfsslower.py ++++ b/tools/nfsslower.py +@@ -65,6 +65,7 @@ bpf_text = """ + + #include + #include ++#include + #include + #include + +diff --git a/tools/offcputime.py b/tools/offcputime.py +index e1f3af9..802fbfd 100755 +--- a/tools/offcputime.py ++++ b/tools/offcputime.py +@@ -128,7 +128,9 @@ BPF_HASH(counts, struct key_t); + BPF_HASH(start, u32); + BPF_STACK_TRACE(stack_traces, STACK_STORAGE_SIZE); + +-int oncpu(struct pt_regs *ctx, struct task_struct *prev) { ++struct rq; ++ ++int oncpu(struct pt_regs *ctx, struct rq *rq, struct task_struct *prev) { + u32 pid = prev->pid; + u32 tgid = prev->tgid; + u64 ts, *tsp; +diff --git a/tools/offwaketime.py b/tools/offwaketime.py +index 2b78c89..83838c9 100755 +--- a/tools/offwaketime.py ++++ b/tools/offwaketime.py +@@ -163,7 +163,9 @@ int waker(struct pt_regs *ctx, struct task_struct *p) { + return 0; + } + +-int oncpu(struct pt_regs *ctx, struct task_struct *p) { ++struct rq; ++ ++int oncpu(struct pt_regs *ctx, struct rq *rq, struct task_struct *p) { + // PID and TGID of the previous Process (Process going into waiting) + u32 pid = p->pid; + u32 tgid = p->tgid; +diff --git a/tools/runqlat.py b/tools/runqlat.py +index 9fd4064..0c9bb1c 100755 +--- a/tools/runqlat.py ++++ b/tools/runqlat.py +@@ -111,7 +111,7 @@ int trace_ttwu_do_wakeup(struct pt_regs *ctx, struct rq *rq, struct task_struct + } + + // calculate latency +-int trace_run(struct pt_regs *ctx, struct task_struct *prev) ++int trace_run(struct pt_regs *ctx, struct rq *rq, struct task_struct *prev) + { + u32 pid, tgid; + +diff --git a/tools/runqslower.py b/tools/runqslower.py +index 7a1869c..b3e3fac 100755 +--- a/tools/runqslower.py ++++ b/tools/runqslower.py +@@ -98,7 +98,7 @@ int trace_ttwu_do_wakeup(struct pt_regs *ctx, struct rq *rq, struct task_struct + } + + // calculate latency +-int trace_run(struct pt_regs *ctx, struct task_struct *prev) ++int trace_run(struct pt_regs *ctx, struct rq *rq, struct task_struct *prev) + { + u32 pid, tgid; + +diff --git a/tools/solisten.py b/tools/solisten.py +index 6a35f82..a9e8722 100755 +--- a/tools/solisten.py ++++ b/tools/solisten.py +@@ -100,7 +100,7 @@ int kprobe__inet_listen(struct pt_regs *ctx, struct socket *sock, int backlog) + + // Get network namespace id, if kernel supports it + #ifdef CONFIG_NET_NS +- evt.netns = sk->__sk_common.skc_net.net->ns.inum; ++ evt.netns = sk->__sk_common.skc_net->proc_inum; + #else + evt.netns = 0; + #endif +diff --git a/tools/tcpsubnet.py b/tools/tcpsubnet.py +index 2779276..f47eea7 100755 +--- a/tools/tcpsubnet.py ++++ b/tools/tcpsubnet.py +@@ -110,8 +110,8 @@ struct index_key_t { + + BPF_HASH(ipv4_send_bytes, struct index_key_t); + +-int kprobe__tcp_sendmsg(struct pt_regs *ctx, struct sock *sk, +- struct msghdr *msg, size_t size) ++int kprobe__tcp_sendmsg(struct pt_regs *ctx, struct kiocb *iocb, ++ struct sock *sk, struct msghdr *msg, size_t size) + { + u16 family = sk->__sk_common.skc_family; + u64 *val, zero = 0; +diff --git a/tools/tcptracer.py b/tools/tcptracer.py +index 5e97ee6..177e860 100755 +--- a/tools/tcptracer.py ++++ b/tools/tcptracer.py +@@ -116,7 +116,7 @@ static int read_ipv4_tuple(struct ipv4_tuple_t *tuple, struct sock *skp) + u16 sport = sockp->inet_sport; + u16 dport = skp->__sk_common.skc_dport; + #ifdef CONFIG_NET_NS +- net_ns_inum = skp->__sk_common.skc_net.net->ns.inum; ++ net_ns_inum = skp->__sk_common.skc_net->proc_inum; + #endif + + ##FILTER_NETNS## +@@ -143,7 +143,7 @@ static int read_ipv6_tuple(struct ipv6_tuple_t *tuple, struct sock *skp) + u16 sport = sockp->inet_sport; + u16 dport = skp->__sk_common.skc_dport; + #ifdef CONFIG_NET_NS +- net_ns_inum = skp->__sk_common.skc_net.net->ns.inum; ++ net_ns_inum = skp->__sk_common.skc_net->proc_inum; + #endif + bpf_probe_read(&saddr, sizeof(saddr), + skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); +@@ -361,8 +361,7 @@ int trace_close_entry(struct pt_regs *ctx, struct sock *skp) + // Don't generate close events for connections that were never + // established in the first place. + if (oldstate == TCP_SYN_SENT || +- oldstate == TCP_SYN_RECV || +- oldstate == TCP_NEW_SYN_RECV) ++ oldstate == TCP_SYN_RECV ) + return 0; + + u8 ipver = 0; +@@ -433,7 +432,7 @@ int trace_accept_return(struct pt_regs *ctx) + + // Get network namespace id, if kernel supports it + #ifdef CONFIG_NET_NS +- net_ns_inum = newsk->__sk_common.skc_net.net->ns.inum; ++ net_ns_inum = newsk->__sk_common.skc_net->proc_inum; + #endif + + ##FILTER_NETNS## +diff --git a/tools/xfsdist.py b/tools/xfsdist.py +index f409f90..2976f9e 100755 +--- a/tools/xfsdist.py ++++ b/tools/xfsdist.py +@@ -137,12 +137,12 @@ bpf_text = bpf_text.replace('FACTOR', str(factor)) + b = BPF(text=bpf_text) + + # common file functions +-b.attach_kprobe(event="xfs_file_read_iter", fn_name="trace_entry") +-b.attach_kprobe(event="xfs_file_write_iter", fn_name="trace_entry") ++b.attach_kprobe(event="xfs_file_aio_read", fn_name="trace_entry") ++b.attach_kprobe(event="xfs_file_aio_write", fn_name="trace_entry") + b.attach_kprobe(event="xfs_file_open", fn_name="trace_entry") + b.attach_kprobe(event="xfs_file_fsync", fn_name="trace_entry") +-b.attach_kretprobe(event="xfs_file_read_iter", fn_name="trace_read_return") +-b.attach_kretprobe(event="xfs_file_write_iter", fn_name="trace_write_return") ++b.attach_kretprobe(event="xfs_file_aio_read", fn_name="trace_read_return") ++b.attach_kretprobe(event="xfs_file_aio_write", fn_name="trace_write_return") + b.attach_kretprobe(event="xfs_file_open", fn_name="trace_open_return") + b.attach_kretprobe(event="xfs_file_fsync", fn_name="trace_fsync_return") + +diff --git a/tools/xfsslower.py b/tools/xfsslower.py +index da70c57..4320284 100755 +--- a/tools/xfsslower.py ++++ b/tools/xfsslower.py +@@ -60,6 +60,7 @@ debug = 0 + bpf_text = """ + #include + #include ++#include + #include + #include + +@@ -94,7 +95,7 @@ BPF_PERF_OUTPUT(events); + // Store timestamp and size on entry + // + +-// xfs_file_read_iter(), xfs_file_write_iter(): ++// xfs_file_aio_read(), xfs_file_aio_write(): + int trace_rw_entry(struct pt_regs *ctx, struct kiocb *iocb) + { + u64 id = bpf_get_current_pid_tgid(); +@@ -273,12 +274,12 @@ TASK_COMM_LEN = 16 # linux/sched.h + b = BPF(text=bpf_text) + + # common file functions +-b.attach_kprobe(event="xfs_file_read_iter", fn_name="trace_rw_entry") +-b.attach_kprobe(event="xfs_file_write_iter", fn_name="trace_rw_entry") ++b.attach_kprobe(event="xfs_file_aio_read", fn_name="trace_rw_entry") ++b.attach_kprobe(event="xfs_file_aio_write", fn_name="trace_rw_entry") + b.attach_kprobe(event="xfs_file_open", fn_name="trace_open_entry") + b.attach_kprobe(event="xfs_file_fsync", fn_name="trace_fsync_entry") +-b.attach_kretprobe(event="xfs_file_read_iter", fn_name="trace_read_return") +-b.attach_kretprobe(event="xfs_file_write_iter", fn_name="trace_write_return") ++b.attach_kretprobe(event="xfs_file_aio_read", fn_name="trace_read_return") ++b.attach_kretprobe(event="xfs_file_aio_write", fn_name="trace_write_return") + b.attach_kretprobe(event="xfs_file_open", fn_name="trace_open_return") + b.attach_kretprobe(event="xfs_file_fsync", fn_name="trace_fsync_return") + +-- +2.17.1 + diff --git a/SOURCES/Miscellaneous-fixes-1914.patch b/SOURCES/Miscellaneous-fixes-1914.patch new file mode 100644 index 0000000..20eba8c --- /dev/null +++ b/SOURCES/Miscellaneous-fixes-1914.patch @@ -0,0 +1,127 @@ +From b84714a47a3a1ec646bbd489442b305c84b35e15 Mon Sep 17 00:00:00 2001 +From: jeromemarchand <38073585+jeromemarchand@users.noreply.github.com> +Date: Wed, 8 Aug 2018 18:09:44 +0200 +Subject: [PATCH] Miscellaneous fixes (#1914) + +* Fix multiple memory access errors + +Fixes a buffer overflow in get_pid_exe(), a use-after-free error in +bcc_usdt_get_probe_argctype() and a possible NULL pointer dereference +in find_debug_via_debuglink(). + +* Fix multiple ressource leaks + +Leaked file descriptors in bpf_attach_uprobe() and verify_checksum(). +Memory leaks in Parser::func_add() and bcc_procutils_language(). + +* fixup! Fix multiple ressource leaks +--- + src/cc/bcc_elf.c | 6 ++++-- + src/cc/bcc_proc.c | 4 +++- + src/cc/common.cc | 2 ++ + src/cc/frontends/b/parser.cc | 4 +++- + src/cc/libbpf.c | 1 + + src/cc/usdt/usdt.cc | 5 +++-- + 6 files changed, 16 insertions(+), 6 deletions(-) + +diff --git a/src/cc/bcc_elf.c b/src/cc/bcc_elf.c +index e848912..c425db6 100644 +--- a/src/cc/bcc_elf.c ++++ b/src/cc/bcc_elf.c +@@ -377,8 +377,10 @@ static int verify_checksum(const char *file, unsigned int crc) { + if (fd < 0) + return 0; + +- if (fstat(fd, &st) < 0) ++ if (fstat(fd, &st) < 0) { ++ close(fd); + return 0; ++ } + + buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (!buf) { +@@ -433,7 +435,7 @@ static char *find_debug_via_debuglink(Elf *e, const char *binpath, + + DONE: + free(bindir); +- if (check_crc && !verify_checksum(res, crc)) ++ if (res && check_crc && !verify_checksum(res, crc)) + return NULL; + return res; + } +diff --git a/src/cc/bcc_proc.c b/src/cc/bcc_proc.c +index 14ee18e..6fe11a0 100644 +--- a/src/cc/bcc_proc.c ++++ b/src/cc/bcc_proc.c +@@ -446,8 +446,10 @@ const char *bcc_procutils_language(int pid) { + while (isspace(mapname[0])) mapname++; + for (i = 0; i < nb_languages; i++) { + snprintf(pathname, sizeof(pathname), "/lib%s", languages[i]); +- if (strstr(mapname, pathname)) ++ if (strstr(mapname, pathname)) { ++ fclose(procfile); + return languages[i]; ++ } + if ((str = strstr(mapname, "libc")) && + (str[4] == '-' || str[4] == '.')) + libc = true; +diff --git a/src/cc/common.cc b/src/cc/common.cc +index 1cfe91a..c8370a3 100644 +--- a/src/cc/common.cc ++++ b/src/cc/common.cc +@@ -57,6 +57,8 @@ std::string get_pid_exe(pid_t pid) { + res = readlink(exe_link.c_str(), exe_path, sizeof(exe_path)); + if (res == -1) + return ""; ++ if (res >= sizeof(exe_path)) ++ res = sizeof(exe_path) - 1; + exe_path[res] = '\0'; + return std::string(exe_path); + } +diff --git a/src/cc/frontends/b/parser.cc b/src/cc/frontends/b/parser.cc +index 9e61346..8a5e149 100644 +--- a/src/cc/frontends/b/parser.cc ++++ b/src/cc/frontends/b/parser.cc +@@ -199,8 +199,10 @@ StmtNode * Parser::func_add(vector *types, Scopes::StateScope *scope, + auto cur_scope = scopes_->current_var(); + scopes_->set_current(scope); + for (auto it = formals->begin(); it != formals->end(); ++it) +- if (!variable_add(nullptr, it->get())) ++ if (!variable_add(nullptr, it->get())) { ++ delete decl; + return nullptr; ++ } + scopes_->set_current(cur_scope); + decl->scope_ = scope; + scopes_->top_func()->add(id->name_, decl); +diff --git a/src/cc/libbpf.c b/src/cc/libbpf.c +index c23030e..acfbc5e 100644 +--- a/src/cc/libbpf.c ++++ b/src/cc/libbpf.c +@@ -925,6 +925,7 @@ static void exit_mount_ns(int fd) { + + if (setns(fd, CLONE_NEWNS)) + perror("setns"); ++ close(fd); + } + + int bpf_attach_uprobe(int progfd, enum bpf_probe_attach_type attach_type, +diff --git a/src/cc/usdt/usdt.cc b/src/cc/usdt/usdt.cc +index 2992593..2010520 100644 +--- a/src/cc/usdt/usdt.cc ++++ b/src/cc/usdt/usdt.cc +@@ -478,8 +478,9 @@ const char *bcc_usdt_get_probe_argctype( + void *ctx, const char* probe_name, const int arg_index + ) { + USDT::Probe *p = static_cast(ctx)->get(probe_name); +- std::string res = p ? p->get_arg_ctype(arg_index) : ""; +- return res.c_str(); ++ if (p) ++ return p->get_arg_ctype(arg_index).c_str(); ++ return ""; + } + + void bcc_usdt_foreach(void *usdt, bcc_usdt_cb callback) { +-- +2.17.1 + diff --git a/SOURCES/link-against-libLLVM.so-instead-of-static-libs.patch b/SOURCES/link-against-libLLVM.so-instead-of-static-libs.patch new file mode 100644 index 0000000..c39e643 --- /dev/null +++ b/SOURCES/link-against-libLLVM.so-instead-of-static-libs.patch @@ -0,0 +1,30 @@ +From ddbdaef40b7db8259f7728a64839b9ff38fbfd76 Mon Sep 17 00:00:00 2001 +From: Jerome Marchand +Date: Fri, 15 Jun 2018 11:41:47 +0200 +Subject: [PATCH] Link against libLLVM.so instead of static libs + +--- + src/cc/CMakeLists.txt | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/cc/CMakeLists.txt b/src/cc/CMakeLists.txt +index 8ddfd8f..0c3d7df 100644 +--- a/src/cc/CMakeLists.txt ++++ b/src/cc/CMakeLists.txt +@@ -62,11 +62,11 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${llvm_lib_exclude_f + # bcc_common_libs_for_a for archive libraries + # bcc_common_libs_for_s for shared libraries + set(bcc_common_libs_for_a b_frontend clang_frontend bpf-static +- -Wl,--whole-archive ${clang_libs} ${llvm_libs} -Wl,--no-whole-archive ++ -Wl,--whole-archive ${clang_libs} libLLVM-6.0-rhel.so -Wl,--no-whole-archive + ${LIBELF_LIBRARIES}) + set(bcc_common_libs_for_s ${bcc_common_libs_for_a}) + set(bcc_common_libs_for_lua b_frontend clang_frontend bpf-static +- ${clang_libs} ${llvm_libs} ${LIBELF_LIBRARIES}) ++ ${clang_libs} libLLVM-6.0-rhel.so ${LIBELF_LIBRARIES}) + + if(ENABLE_CPP_API) + add_subdirectory(api) +-- +2.17.1 + diff --git a/SOURCES/llcstat-print-a-nicer-error-message-when-hardware-ev.patch b/SOURCES/llcstat-print-a-nicer-error-message-when-hardware-ev.patch new file mode 100644 index 0000000..bec257c --- /dev/null +++ b/SOURCES/llcstat-print-a-nicer-error-message-when-hardware-ev.patch @@ -0,0 +1,43 @@ +From d274b66f58d59d97543c8b64e9f88449581e4299 Mon Sep 17 00:00:00 2001 +From: Jerome Marchand +Date: Tue, 7 Aug 2018 17:24:31 +0200 +Subject: [PATCH] llcstat: print a nicer error message when hardware events are + missing + +Hardware events such as CACHE_MISSES and CACHE_REFERENCES are usually +not available on virtual machine. Print a more useful message when +this happen. +--- + tools/llcstat.py | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/tools/llcstat.py b/tools/llcstat.py +index e59f9a8..fe8bdd9 100755 +--- a/tools/llcstat.py ++++ b/tools/llcstat.py +@@ -78,12 +78,16 @@ int on_cache_ref(struct bpf_perf_event_data *ctx) { + exit() + + b = BPF(text=bpf_text) +-b.attach_perf_event( +- ev_type=PerfType.HARDWARE, ev_config=PerfHWConfig.CACHE_MISSES, +- fn_name="on_cache_miss", sample_period=args.sample_period) +-b.attach_perf_event( +- ev_type=PerfType.HARDWARE, ev_config=PerfHWConfig.CACHE_REFERENCES, +- fn_name="on_cache_ref", sample_period=args.sample_period) ++try: ++ b.attach_perf_event( ++ ev_type=PerfType.HARDWARE, ev_config=PerfHWConfig.CACHE_MISSES, ++ fn_name="on_cache_miss", sample_period=args.sample_period) ++ b.attach_perf_event( ++ ev_type=PerfType.HARDWARE, ev_config=PerfHWConfig.CACHE_REFERENCES, ++ fn_name="on_cache_ref", sample_period=args.sample_period) ++except: ++ print("Failed to attach to a hardware event. Is this a virtual machine?") ++ exit() + + print("Running for {} seconds or hit Ctrl-C to end.".format(args.duration)) + +-- +2.17.1 + diff --git a/SOURCES/sslsniff-add-NSS-support-1908.patch b/SOURCES/sslsniff-add-NSS-support-1908.patch new file mode 100644 index 0000000..fc1c74d --- /dev/null +++ b/SOURCES/sslsniff-add-NSS-support-1908.patch @@ -0,0 +1,185 @@ +From 8b17dc3472a9c11139d0058bbf8b42eae66022b8 Mon Sep 17 00:00:00 2001 +From: jeromemarchand <38073585+jeromemarchand@users.noreply.github.com> +Date: Sat, 4 Aug 2018 07:09:36 +0200 +Subject: [PATCH] sslsniff: add NSS support (#1908) + +* sslsniff: add NSS support + +* sslsniff: update documentation +--- + man/man8/sslsniff.8 | 18 +++++++++--------- + tools/sslsniff.py | 21 +++++++++++++++++++-- + tools/sslsniff_example.txt | 16 +++++++++------- + 3 files changed, 37 insertions(+), 18 deletions(-) + +diff --git a/man/man8/sslsniff.8 b/man/man8/sslsniff.8 +index e20e28a..72836e2 100644 +--- a/man/man8/sslsniff.8 ++++ b/man/man8/sslsniff.8 +@@ -1,12 +1,12 @@ + .TH sslsniff 8 "2016-08-16" "USER COMMANDS" + .SH NAME +-sslsniff \- Print data passed to OpenSSL. Uses Linux eBPF/bcc. ++sslsniff \- Print data passed to OpenSSL, GnuTLS or NSS. Uses Linux eBPF/bcc. + .SH SYNOPSIS +-.B sslsniff ++.B sslsniff [-h] [-p PID] [-c COMM] [-o] [-g] [-n] [-d] + .SH DESCRIPTION +-sslsniff prints data sent to SSL_write and SSL_read OpenSSL functions, allowing +-us to read plain text content before encryption (when writing) and after +-decryption (when reading). ++sslsniff prints data sent to write/send and read/recv functions of ++OpenSSL, GnuTLS and NSS, allowing us to read plain text content before ++encryption (when writing) and after decryption (when reading). + + This works reading the second parameter of both functions (*buf). + +@@ -15,13 +15,13 @@ Since this uses BPF, only the root user can use this tool. + CONFIG_BPF and bcc. + .SH EXAMPLES + .TP +-Print all calls to SSL_write and SSL_read system-wide: ++Print all calls to SSL write/send and read/recv system-wide: + # + .B sslsniff + .SH FIELDS + .TP + FUNC +-Which function is being called (SSL_write or SSL_read) ++Which function is being called (write/send or read/recv) + .TP + TIME + Time of the command, in seconds. +@@ -30,10 +30,10 @@ COMM + Entered command. + .TP + PID +-Process ID calling OpenSSL. ++Process ID calling SSL. + .TP + LEN +-Bytes written or read by OpenSSL functions. ++Bytes written or read by SSL functions. + .SH SOURCE + This is from bcc. + .IP +diff --git a/tools/sslsniff.py b/tools/sslsniff.py +index 174577b..2e74fba 100755 +--- a/tools/sslsniff.py ++++ b/tools/sslsniff.py +@@ -1,7 +1,7 @@ + #!/usr/bin/python + # +-# sslsniff Captures data on read/recv or write/send functions of OpenSSL and +-# GnuTLS ++# sslsniff Captures data on read/recv or write/send functions of OpenSSL, ++# GnuTLS and NSS + # For Linux, uses BCC, eBPF. + # + # USAGE: sslsniff.py [-h] [-p PID] [-c COMM] [-o] [-g] [-d] +@@ -25,6 +25,7 @@ import argparse + ./sslsniff -c curl # sniff curl command only + ./sslsniff --no-openssl # don't show OpenSSL calls + ./sslsniff --no-gnutls # don't show GnuTLS calls ++ ./sslsniff --no-nss # don't show NSS calls + """ + parser = argparse.ArgumentParser( + description="Sniff SSL data", +@@ -37,6 +38,8 @@ parser.add_argument("-o", "--no-openssl", action="store_false", dest="openssl", + help="do not show OpenSSL calls.") + parser.add_argument("-g", "--no-gnutls", action="store_false", dest="gnutls", + help="do not show GnuTLS calls.") ++parser.add_argument("-n", "--no-nss", action="store_false", dest="nss", ++ help="do not show NSS calls.") + parser.add_argument('-d', '--debug', dest='debug', action='count', default=0, + help='debug mode.') + parser.add_argument("--ebpf", action="store_true", +@@ -149,6 +152,20 @@ b = BPF(text=prog) + b.attach_uretprobe(name="gnutls", sym="gnutls_record_recv", + fn_name="probe_SSL_read_exit", pid=args.pid or -1) + ++if args.nss: ++ b.attach_uprobe(name="nspr4", sym="PR_Write", fn_name="probe_SSL_write", ++ pid=args.pid or -1) ++ b.attach_uprobe(name="nspr4", sym="PR_Send", fn_name="probe_SSL_write", ++ pid=args.pid or -1) ++ b.attach_uprobe(name="nspr4", sym="PR_Read", fn_name="probe_SSL_read_enter", ++ pid=args.pid or -1) ++ b.attach_uretprobe(name="nspr4", sym="PR_Read", ++ fn_name="probe_SSL_read_exit", pid=args.pid or -1) ++ b.attach_uprobe(name="nspr4", sym="PR_Recv", fn_name="probe_SSL_read_enter", ++ pid=args.pid or -1) ++ b.attach_uretprobe(name="nspr4", sym="PR_Recv", ++ fn_name="probe_SSL_read_exit", pid=args.pid or -1) ++ + # define output data structure in Python + TASK_COMM_LEN = 16 # linux/sched.h + MAX_BUF_SIZE = 464 # Limited by the BPF stack +diff --git a/tools/sslsniff_example.txt b/tools/sslsniff_example.txt +index c16b572..8c51722 100644 +--- a/tools/sslsniff_example.txt ++++ b/tools/sslsniff_example.txt +@@ -1,16 +1,16 @@ + Demonstrations of sslsniff.py + + +-This tool traces the OpenSSL functions SSL_READ and SSL_WRITE. +-Data passed to this functions is printed as plain text. +-Useful, for example, to sniff HTTP before encrypted with SSL. ++This tool traces the write/send and read/recv functions of OpenSSL, ++GnuTLS and NSS. Data passed to this functions is printed as plain ++text. Useful, for example, to sniff HTTP before encrypted with SSL. + + + Output of tool executing in other shell "curl https://example.com" + + % sudo python sslsniff.py + FUNC TIME(s) COMM PID LEN +-SSL_WRITE 0.000000000 curl 12915 75 ++WRITE/SEND 0.000000000 curl 12915 75 + ----- DATA ----- + GET / HTTP/1.1 + Host: example.com +@@ -20,7 +20,7 @@ Accept: */* + + ----- END DATA ----- + +-SSL_READ 0.127144585 curl 12915 333 ++READ/RECV 0.127144585 curl 12915 333 + ----- DATA ----- + HTTP/1.1 200 OK + Cache-Control: max-age=604800 +@@ -38,7 +38,7 @@ Content-Length: 1270 + + ----- END DATA ----- + +-SSL_READ 0.129967972 curl 12915 1270 ++READ/RECV 0.129967972 curl 12915 1270 + ----- DATA ----- + + +@@ -65,7 +65,7 @@ SSL_READ 0.129967972 curl 12915 1270 + + USAGE message: + +-usage: sslsniff.py [-h] [-p PID] [-c COMM] [-o] [-g] [-d] ++usage: sslsniff.py [-h] [-p PID] [-c COMM] [-o] [-g] [-n] [-d] + + Sniff SSL data + +@@ -75,6 +75,7 @@ Sniff SSL data + -c COMM, --comm COMM sniff only commands matching string. + -o, --no-openssl do not show OpenSSL calls. + -g, --no-gnutls do not show GnuTLS calls. ++ -n, --no-nss do not show NSS calls. + -d, --debug debug mode. + + examples: +@@ -83,3 +84,4 @@ Sniff SSL data + ./sslsniff -c curl # sniff curl command only + ./sslsniff --no-openssl # don't show OpenSSL calls + ./sslsniff --no-gnutls # don't show GnuTLS calls ++ ./sslsniff --no-nss # don't show NSS calls +-- +2.17.1 + diff --git a/SPECS/bcc.spec b/SPECS/bcc.spec new file mode 100644 index 0000000..885c385 --- /dev/null +++ b/SPECS/bcc.spec @@ -0,0 +1,262 @@ +# luajit is not available for some architectures and not at all on RHEL7 +%if 0%{?rhel} <= 7 +%bcond_with lua +%else +%ifarch ppc64 ppc64le s390x +%bcond_with lua +%else +%bcond_without lua +%endif +%endif + +Name: bcc +Version: 0.6.1 +Release: 2%{?dist} +Summary: BPF Compiler Collection (BCC) +License: ASL 2.0 +URL: https://github.com/iovisor/bcc +Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz +Patch0: link-against-libLLVM.so-instead-of-static-libs.patch +Patch1: Fix-tools-for-RHEL-7.patch +Patch2: sslsniff-add-NSS-support-1908.patch +Patch3: llcstat-print-a-nicer-error-message-when-hardware-ev.patch +Patch4: Miscellaneous-fixes-1914.patch +# tests/cc doesn't compile on s390x, so disable it until we have a better fix +Patch10: Disable-tests-cc.patch + +# Arches will be included as upstream support is added and dependencies are +# satisfied in the respective arches +ExcludeArch: i686 ppc s390 + +BuildRequires: bison, cmake >= 2.8.7, flex, libxml2-devel +BuildRequires: python-devel +BuildRequires: elfutils-libelf-devel +BuildRequires: ncurses-devel +%if %{with lua} +BuildRequires: pkgconfig(luajit) +%endif +BuildRequires: llvm-private-devel >= 6.0.1-0.3 + +Requires: %{name}-tools = %{version}-%{release} +Requires: llvm-private >= 6.0.1-0.3 + +%description +BCC is a toolkit for creating efficient kernel tracing and manipulation +programs, and includes several useful tools and examples. It makes use of +extended BPF (Berkeley Packet Filters), formally known as eBPF, a new feature +that was first added to Linux 3.15. BCC makes BPF programs easier to write, +with kernel instrumentation in C (and includes a C wrapper around LLVM), and +front-ends in Python and lua. It is suited for many tasks, including +performance analysis and network traffic control. + + +%package devel +Summary: Shared library for BPF Compiler Collection (BCC) +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +The %{name}-devel package contains libraries and header files for developing +application that use BPF Compiler Collection (BCC). + + +%package doc +Summary: Examples for BPF Compiler Collection (BCC) +BuildArch: noarch + +%description doc +Examples for BPF Compiler Collection (BCC) + + +%package -n python-%{name} +Summary: Python bindings for BPF Compiler Collection (BCC) +Requires: %{name}%{?_isa} = %{version}-%{release} +%{?python_provide:%python_provide python-%{srcname}} + +%description -n python-%{name} +Python bindings for BPF Compiler Collection (BCC) + + +%if %{with lua} +%package lua +Summary: Standalone tool to run BCC tracers written in Lua +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description lua +Standalone tool to run BCC tracers written in Lua +%endif + + +%package tools +Summary: Command line tools for BPF Compiler Collection (BCC) +Requires: python-%{name} = %{version}-%{release} +Requires: python-netaddr +Requires: kernel-devel + +%description tools +Command line tools for BPF Compiler Collection (BCC) + +%prep +%setup +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 + +%ifarch s390x +%patch10 -p1 +%endif + +%build +%cmake . \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo\ + -DCMAKE_CXX_FLAGS='-std=c++11 -I/usr/include/llvm-private/'\ + -DREVISION_LAST=%{version} -DREVISION=%{version}\ + -DCMAKE_LIBRARY_PATH=/usr/lib64/clang-private/\ + -DCMAKE_INSTALL_RPATH=/usr/lib64/clang-private/ +%make_build + +%install +%make_install + +# Move man pages to the right location +mkdir -p %{buildroot}%{_mandir} +mv %{buildroot}%{_datadir}/%{name}/man/* %{buildroot}%{_mandir}/ +# Avoid conflict with other manpages +# https://bugzilla.redhat.com/show_bug.cgi?id=1517408 +for i in `find %{buildroot}%{_mandir} -name "*.gz"`; do + tname=$(basename $i) + rename $tname %{name}-$tname $i +done +# Fix the symlink too +for i in `find %{buildroot}%{_mandir} -lname \*.gz` ; do + target=`readlink $i`; + ln -sf bcc-$target $i; +done +mkdir -p %{buildroot}%{_docdir}/%{name} +mv %{buildroot}%{_datadir}/%{name}/examples %{buildroot}%{_docdir}/%{name}/ + +# We cannot run the test suit since it requires root and it makes changes to +# the machine (e.g, IP address) +#%check + +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig + +%files +%doc README.md +%license LICENSE.txt +%{_libdir}/lib%{name}.so.* +%{_libdir}/libbpf.so.* + +%files devel +%{_libdir}/lib%{name}.so +%{_libdir}/libbpf.so +%{_libdir}/pkgconfig/lib%{name}.pc +%{_includedir}/%{name}/ + +%files -n python-%{name} +%{python_sitelib}/%{name}* + +%files doc +%dir %{_docdir}/%{name} +%doc %{_docdir}/%{name}/examples/ + +%files tools +%dir %{_datadir}/%{name} +%dir %{_datadir}/%{name}/tools +%dir %{_datadir}/%{name}/introspection +%{_datadir}/%{name}/tools/* +%{_datadir}/%{name}/introspection/* +%exclude %{_datadir}/%{name}/tools/old/ +# inject relies on BPF_KPROBE_OVERRIDE which is absent on RHEL 7 +%exclude %{_datadir}/%{name}/tools/inject +# ZFS isn't available on RHEL +%exclude %{_datadir}/%{name}/tools/zfs* +%{_mandir}/man8/* + +%if %{with lua} +%files lua +%{_bindir}/bcc-lua +%endif + + +%changelog +* Fri Sep 21 2018 Jerome Marchand - 0.6.1-2 +- Set a minimal version for llvm-private(-devel) + +* Thu Aug 16 2018 Jerome Marchand - 0.6.1-1 +- Rebase on v0.6.1 +- Fix tcpsubnet +- Reinstate llcstat tool +- Remove inject tool +- Add NSS support to sslsniff +- Fixes miscellaneous error uncovered by covscan + +* Wed Jul 04 2018 Jerome Marchand - 0.6.0-3 +- Fix tools on RHEL 7 +- Remove llcstat and ZFS tools. + +* Tue Jun 26 2018 Jerome Marchand - 0.6.0-2 +- Add llvm-private requirement +- Fix manpages symlinks + +* Tue Jun 19 2018 Jerome Marchand - 0.6.0-1 +- Rebase on bcc-0.6.0 + +* Thu Jun 07 2018 Jerome Marchand - 0.5.0-6 +- Enables build on RHEL 7 + +* Thu May 24 2018 Jerome Marchand - 0.5.0-5 +- Enables build on ppc64(le) and s390x arches + +* Thu Apr 05 2018 Rafael Santos - 0.5.0-4 +- Resolves #1555627 - fix compilation error with latest llvm/clang + +* Wed Feb 07 2018 Fedora Release Engineering - 0.5.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Fri Feb 02 2018 Igor Gnatenko - 0.5.0-2 +- Switch to %%ldconfig_scriptlets + +* Wed Jan 03 2018 Rafael Santos - 0.5.0-1 +- Rebase to new released version + +* Thu Nov 16 2017 Rafael Santos - 0.4.0-4 +- Resolves #1517408 - avoid conflict with other manpages + +* Thu Nov 02 2017 Rafael Santos - 0.4.0-3 +- Use weak deps to not require lua subpkg on ppc64(le) + +* Wed Nov 01 2017 Igor Gnatenko - 0.4.0-2 +- Rebuild for LLVM5 + +* Wed Nov 01 2017 Rafael Fonseca - 0.4.0-1 +- Resolves #1460482 - rebase to new release +- Resolves #1505506 - add support for LLVM 5.0 +- Resolves #1460482 - BPF module compilation issue +- Partially address #1479990 - location of man pages +- Enable ppc64(le) support without lua +- Soname versioning for libbpf by ignatenkobrain + +* Wed Aug 02 2017 Fedora Release Engineering - 0.3.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 0.3.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Thu Mar 30 2017 Igor Gnatenko - 0.3.0-2 +- Rebuild for LLVM4 +- Trivial fixes in spec + +* Fri Mar 10 2017 Rafael Fonseca - 0.3.0-1 +- Rebase to new release. + +* Fri Feb 10 2017 Fedora Release Engineering - 0.2.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Tue Jan 10 2017 Rafael Fonseca - 0.2.0-2 +- Fix typo + +* Tue Nov 29 2016 Rafael Fonseca - 0.2.0-1 +- Initial import