Merge pull request #1555 from myreg/trace-addr
Add option to print virtual address to trace.py
diff --git a/docs/kernel-versions.md b/docs/kernel-versions.md
index 554847c..9514944 100644
--- a/docs/kernel-versions.md
+++ b/docs/kernel-versions.md
@@ -123,6 +123,7 @@
`BPF_FUNC_get_socket_cookie()` | 4.12 | [91b8270f2a4d](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=91b8270f2a4d1d9b268de90451cdca63a70052d6)
`BPF_FUNC_get_socket_uid()` | 4.12 | [6acc5c291068](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=6acc5c2910689fc6ee181bf63085c5efff6a42bd)
`BPF_FUNC_get_stackid()` | 4.6 | [d5a3b1f69186](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=d5a3b1f691865be576c2bffa708549b8cdccda19)
+`BPF_FUNC_getsockopt()` | 4.15 | [cd86d1fd2102](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=cd86d1fd21025fdd6daf23d1288da405e7ad0ec6)
`BPF_FUNC_ktime_get_ns()` | 4.1 | [d9847d310ab4](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=d9847d310ab4003725e6ed1822682e24bd406908)
`BPF_FUNC_l3_csum_replace()` | 4.1 | [91bc4822c3d6](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=91bc4822c3d61b9bb7ef66d3b77948a4f9177954)
`BPF_FUNC_l4_csum_replace()` | 4.1 | [91bc4822c3d6](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=91bc4822c3d61b9bb7ef66d3b77948a4f9177954)
diff --git a/docs/reference_guide.md b/docs/reference_guide.md
index d88eec7..b89d140 100644
--- a/docs/reference_guide.md
+++ b/docs/reference_guide.md
@@ -21,7 +21,8 @@
- [4. bpf_get_current_pid_tgid()](#4-bpf_get_current_pid_tgid)
- [5. bpf_get_current_uid_gid()](#5-bpf_get_current_uid_gid)
- [6. bpf_get_current_comm()](#6-bpf_get_current_comm)
- - [7. bpf_log2l()](#7-bpflog2l)
+ - [7. bpf_get_current_task()](#7-bpf_get_current_task)
+ - [8. bpf_log2l()](#8-bpflog2l)
- [Debugging](#debugging)
- [1. bpf_override_return()](#1-bpf_override_return)
- [Output](#output)
@@ -316,7 +317,30 @@
[search /examples](https://github.com/iovisor/bcc/search?q=bpf_get_current_comm+path%3Aexamples&type=Code),
[search /tools](https://github.com/iovisor/bcc/search?q=bpf_get_current_comm+path%3Atools&type=Code)
-### 7. bpf_log2l()
+### 7. bpf_get_current_task()
+
+Syntax: ```bpf_get_current_task()```
+
+Return: current task as a pointer to struct task_struct.
+
+Returns a pointer to the current task's task_struct object. This helper can be used to compute the on-CPU time for a process, identify kernel threads, get the current CPU's run queue, or retrieve many other pieces of information.
+
+With Linux 4.13, due to issues with field randomization, you may need two #define directives before the includes:
+```C
+#define randomized_struct_fields_start struct {
+#define randomized_struct_fields_end };
+#include <linux/sched.h>
+
+int do_trace(void *ctx) {
+ struct task_struct *t = (struct task_struct *)bpf_get_current_task();
+[...]
+```
+
+Examples in situ:
+[search /examples](https://github.com/iovisor/bcc/search?q=bpf_get_current_task+path%3Aexamples&type=Code),
+[search /tools](https://github.com/iovisor/bcc/search?q=bpf_get_current_task+path%3Atools&type=Code)
+
+### 8. bpf_log2l()
Syntax: ```unsigned int bpf_log2l(unsigned long v)```
diff --git a/man/man8/funccount.8 b/man/man8/funccount.8
index 6c1623a..9039ab3 100644
--- a/man/man8/funccount.8
+++ b/man/man8/funccount.8
@@ -2,7 +2,7 @@
.SH NAME
funccount \- Count function, tracepoint, and USDT probe calls matching a pattern. Uses Linux eBPF/bcc.
.SH SYNOPSIS
-.B funccount [\-h] [\-p PID] [\-i INTERVAL] [\-T] [\-r] [\-d] pattern
+.B funccount [\-h] [\-p PID] [\-i INTERVAL] [\-d DURATION] [\-T] [\-r] [\-D] pattern
.SH DESCRIPTION
This tool is a quick way to determine which functions are being called,
and at what rate. It uses in-kernel eBPF maps to count function calls.
@@ -36,7 +36,7 @@
\-r
Use regular expressions for the search pattern.
.TP
-\-d
+\-D
Print the BPF program before starting (for debugging purposes).
.SH EXAMPLES
.TP
diff --git a/src/cc/export/helpers.h b/src/cc/export/helpers.h
index 1d25c6e..1fa4a64 100644
--- a/src/cc/export/helpers.h
+++ b/src/cc/export/helpers.h
@@ -250,6 +250,30 @@
(void *) BPF_FUNC_perf_event_read_value;
static int (*bpf_perf_prog_read_value)(void *ctx, void *buf, u32 buf_size) =
(void *) BPF_FUNC_perf_prog_read_value;
+static int (*bpf_current_task_under_cgroup)(void *map, int index) =
+ (void *) BPF_FUNC_current_task_under_cgroup;
+static u32 (*bpf_get_socket_cookie)(void *ctx) =
+ (void *) BPF_FUNC_get_socket_cookie;
+static u64 (*bpf_get_socket_uid)(void *ctx) =
+ (void *) BPF_FUNC_get_socket_uid;
+static int (*bpf_getsockopt)(void *ctx, int level, int optname, void *optval, int optlen) =
+ (void *) BPF_FUNC_getsockopt;
+static int (*bpf_redirect_map)(void *map, int key, int flags) =
+ (void *) BPF_FUNC_redirect_map;
+static int (*bpf_set_hash)(void *ctx, u32 hash) =
+ (void *) BPF_FUNC_set_hash;
+static int (*bpf_setsockopt)(void *ctx, int level, int optname, void *optval, int optlen) =
+ (void *) BPF_FUNC_setsockopt;
+static int (*bpf_skb_adjust_room)(void *ctx, int len_diff, u32 mode, u64 flags) =
+ (void *) BPF_FUNC_skb_adjust_room;
+static int (*bpf_skb_under_cgroup)(void *ctx, void *map, int index) =
+ (void *) BPF_FUNC_skb_under_cgroup;
+static int (*bpf_sk_redirect_map)(void *ctx, void *map, int key, int flags) =
+ (void *) BPF_FUNC_sk_redirect_map;
+static int (*bpf_sock_map_update)(void *map, void *key, void *value, unsigned long long flags) =
+ (void *) BPF_FUNC_sock_map_update;
+static int (*bpf_xdp_adjust_meta)(void *ctx, int offset) =
+ (void *) BPF_FUNC_xdp_adjust_meta;
/* bcc_get_stackid will return a negative value in the case of an error
*
diff --git a/src/cc/frontends/clang/CMakeLists.txt b/src/cc/frontends/clang/CMakeLists.txt
index a6228fc..105278c 100644
--- a/src/cc/frontends/clang/CMakeLists.txt
+++ b/src/cc/frontends/clang/CMakeLists.txt
@@ -10,3 +10,4 @@
endif()
add_library(clang_frontend STATIC loader.cc b_frontend_action.cc tp_frontend_action.cc kbuild_helper.cc ../../common.cc)
+target_link_libraries(clang_frontend bcc-static)
diff --git a/src/cc/frontends/clang/b_frontend_action.cc b/src/cc/frontends/clang/b_frontend_action.cc
index c42fb62..257167e 100644
--- a/src/cc/frontends/clang/b_frontend_action.cc
+++ b/src/cc/frontends/clang/b_frontend_action.cc
@@ -778,7 +778,8 @@
return false;
}
- fe_.table_storage().VisitMapType(table, C, key_type, leaf_type);
+ if (!table.is_extern)
+ fe_.table_storage().VisitMapType(table, C, key_type, leaf_type);
fe_.table_storage().Insert(local_path, move(table));
} else if (const PointerType *P = Decl->getType()->getAs<PointerType>()) {
// if var is a pointer to a packet type, clone the annotation into the var
diff --git a/src/cc/libbpf.c b/src/cc/libbpf.c
index 6e24ccf..41f1560 100644
--- a/src/cc/libbpf.c
+++ b/src/cc/libbpf.c
@@ -84,6 +84,72 @@
#define min(x, y) ((x) < (y) ? (x) : (y))
+struct bpf_helper {
+ char *name;
+ char *required_version;
+};
+
+static struct bpf_helper helpers[] = {
+ {"map_lookup_elem", "3.19"},
+ {"map_update_elem", "3.19"},
+ {"map_delete_elem", "3.19"},
+ {"probe_read", "4.1"},
+ {"ktime_get_ns", "4.1"},
+ {"trace_printk", "4.1"},
+ {"get_prandom_u32", "4.1"},
+ {"get_smp_processor_id", "4.1"},
+ {"skb_store_bytes", "4.1"},
+ {"l3_csum_replace", "4.1"},
+ {"l4_csum_replace", "4.1"},
+ {"tail_call", "4.2"},
+ {"clone_redirect", "4.2"},
+ {"get_current_pid_tgid", "4.2"},
+ {"get_current_uid_gid", "4.2"},
+ {"get_current_comm", "4.2"},
+ {"get_cgroup_classid", "4.3"},
+ {"skb_vlan_push", "4.3"},
+ {"skb_vlan_pop", "4.3"},
+ {"skb_get_tunnel_key", "4.3"},
+ {"skb_set_tunnel_key", "4.3"},
+ {"perf_event_read", "4.3"},
+ {"redirect", "4.4"},
+ {"get_route_realm", "4.4"},
+ {"perf_event_output", "4.4"},
+ {"skb_load_bytes", "4.5"},
+ {"get_stackid", "4.6"},
+ {"csum_diff", "4.6"},
+ {"skb_get_tunnel_opt", "4.6"},
+ {"skb_set_tunnel_opt", "4.6"},
+ {"skb_change_proto", "4.8"},
+ {"skb_change_type", "4.8"},
+ {"skb_under_cgroup", "4.8"},
+ {"get_hash_recalc", "4.8"},
+ {"get_current_task", "4.8"},
+ {"probe_write_user", "4.8"},
+ {"current_task_under_cgroup", "4.9"},
+ {"skb_change_tail", "4.9"},
+ {"skb_pull_data", "4.9"},
+ {"csum_update", "4.9"},
+ {"set_hash_invalid", "4.9"},
+ {"get_numa_node_id", "4.10"},
+ {"skb_change_head", "4.10"},
+ {"xdp_adjust_head", "4.10"},
+ {"probe_read_str", "4.11"},
+ {"get_socket_cookie", "4.12"},
+ {"get_socket_uid", "4.12"},
+ {"set_hash", "4.13"},
+ {"setsockopt", "4.13"},
+ {"skb_adjust_room", "4.13"},
+ {"redirect_map", "4.14"},
+ {"sk_redirect_map", "4.14"},
+ {"sock_map_update", "4.14"},
+ {"xdp_adjust_meta", "4.15"},
+ {"perf_event_read_value", "4.15"},
+ {"perf_prog_read_value", "4.15"},
+ {"getsockopt", "4.15"},
+ {"override_return", "4.16"},
+};
+
static int probe_perf_reader_page_cnt = 8;
static uint64_t ptr_to_u64(void *ptr)
@@ -245,6 +311,22 @@
"bpf_probe_read is automatic by the bcc rewriter, other times "
"you'll need to be explicit.\n\n");
}
+
+ // helper function not found in kernel
+ char *helper_str = strstr(log, "invalid func ");
+ if (helper_str != NULL) {
+ helper_str += strlen("invalid func ");
+ char *str = strchr(helper_str, '#');
+ if (str != NULL) {
+ helper_str = str + 1;
+ }
+ int helper_id = atoi(helper_str);
+ if (helper_id && helper_id < sizeof(helpers) / sizeof(struct bpf_helper)) {
+ struct bpf_helper helper = helpers[helper_id - 1];
+ fprintf(stderr, "HINT: bpf_%s missing (added in Linux %s).\n\n",
+ helper.name, helper.required_version);
+ }
+ }
}
#define ROUND_UP(x, n) (((x) + (n) - 1u) & ~((n) - 1u))
diff --git a/src/python/bcc/table.py b/src/python/bcc/table.py
index aa037f6..d88b402 100644
--- a/src/python/bcc/table.py
+++ b/src/python/bcc/table.py
@@ -205,6 +205,11 @@
errstr = os.strerror(ct.get_errno())
raise Exception("Could not update table: %s" % errstr)
+ def __delitem__(self, key):
+ res = lib.bpf_delete_elem(self.map_fd, ct.byref(key))
+ if res < 0:
+ raise KeyError
+
# override the MutableMapping's implementation of these since they
# don't handle KeyError nicely
def itervalues(self):
@@ -391,11 +396,6 @@
for k in self: i += 1
return i
- def __delitem__(self, key):
- res = lib.bpf_delete_elem(self.map_fd, ct.byref(key))
- if res < 0:
- raise KeyError
-
class LruHash(HashTable):
def __init__(self, *args, **kwargs):
super(LruHash, self).__init__(*args, **kwargs)
@@ -430,11 +430,12 @@
def __delitem__(self, key):
key = self._normalize_key(key)
- # Deleting from array type maps does not have an effect, so
- # zero out the entry instead.
+ super(ArrayBase, self).__delitem__(key)
+
+ def clearitem(self, key):
+ key = self._normalize_key(key)
leaf = self.Leaf()
- res = lib.bpf_update_elem(self.map_fd, ct.byref(key), ct.byref(leaf),
- 0)
+ res = lib.bpf_update_elem(self.map_fd, ct.byref(key), ct.byref(leaf), 0)
if res < 0:
raise Exception("Could not clear item")
@@ -461,6 +462,9 @@
def __init__(self, *args, **kwargs):
super(Array, self).__init__(*args, **kwargs)
+ def __delitem__(self, key):
+ # Delete in Array type does not have an effect, so zero out instead
+ self.clearitem(key)
class ProgArray(ArrayBase):
def __init__(self, *args, **kwargs):
@@ -473,12 +477,6 @@
leaf = self.Leaf(leaf.fd)
super(ProgArray, self).__setitem__(key, leaf)
- def __delitem__(self, key):
- key = self._normalize_key(key)
- res = lib.bpf_delete_elem(self.map_fd, ct.byref(key))
- if res < 0:
- raise Exception("Could not delete item")
-
class PerfEventArray(ArrayBase):
def __init__(self, *args, **kwargs):
@@ -494,8 +492,7 @@
if key not in self._open_key_fds:
return
# Delete entry from the array
- c_key = self._normalize_key(key)
- lib.bpf_delete_elem(self.map_fd, ct.byref(c_key))
+ super(PerfEventArray, self).__delitem__(key)
key_id = (id(self), key)
if key_id in self.bpf.open_kprobes:
# The key is opened for perf ring buffer
@@ -665,6 +662,10 @@
def __setitem__(self, key, leaf):
super(PerCpuArray, self).__setitem__(key, leaf)
+ def __delitem__(self, key):
+ # Delete in this type does not have an effect, so zero out instead
+ self.clearitem(key)
+
def sum(self, key):
if isinstance(self.Leaf(), ct.Structure):
raise IndexError("Leaf must be an integer type for default sum functions")
@@ -728,10 +729,5 @@
for k in self: i += 1
return i
- def __delitem__(self, key):
- res = lib.bpf_delete_elem(self.map_fd, ct.byref(key))
- if res < 0:
- raise KeyError
-
def clear(self):
pass
diff --git a/tests/python/test_clang.py b/tests/python/test_clang.py
index ba8c02f..58c808e 100755
--- a/tests/python/test_clang.py
+++ b/tests/python/test_clang.py
@@ -400,6 +400,7 @@
def test_exported_maps(self):
b1 = BPF(text="""BPF_TABLE_PUBLIC("hash", int, int, table1, 10);""")
b2 = BPF(text="""BPF_TABLE("extern", int, int, table1, 10);""")
+ t = b2["table1"]
def test_syntax_error(self):
with self.assertRaises(Exception):
diff --git a/tools/opensnoop.py b/tools/opensnoop.py
index 112c56a..6d011e9 100755
--- a/tools/opensnoop.py
+++ b/tools/opensnoop.py
@@ -68,7 +68,7 @@
BPF_HASH(infotmp, u64, struct val_t);
BPF_PERF_OUTPUT(events);
-int trace_entry(struct pt_regs *ctx, const char __user *filename)
+int trace_entry(struct pt_regs *ctx, int dfd, const char __user *filename)
{
struct val_t val = {};
u64 id = bpf_get_current_pid_tgid();
@@ -124,8 +124,8 @@
# initialize BPF
b = BPF(text=bpf_text)
-b.attach_kprobe(event="sys_open", fn_name="trace_entry")
-b.attach_kretprobe(event="sys_open", fn_name="trace_return")
+b.attach_kprobe(event="do_sys_open", fn_name="trace_entry")
+b.attach_kretprobe(event="do_sys_open", fn_name="trace_return")
TASK_COMM_LEN = 16 # linux/sched.h
NAME_MAX = 255 # linux/limits.h