Commit 4a57f4dd authored by 4ast's avatar 4ast Committed by GitHub

Merge pull request #928 from goldshtn/tp-data-loc

Support for __data_loc tracepoint fields
parents b77915df 3ea6eee8
......@@ -499,5 +499,18 @@ int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("l
#define TRACEPOINT_PROBE(category, event) \
int tracepoint__##category##__##event(struct tracepoint__##category##__##event *args)
#define TP_DATA_LOC_READ_CONST(dst, field, length) \
do { \
short __offset = args->data_loc_##field & 0xFFFF; \
bpf_probe_read((void *)dst, length, (char *)args + __offset); \
} while (0);
#define TP_DATA_LOC_READ(dst, field) \
do { \
short __offset = args->data_loc_##field & 0xFFFF; \
short __length = args->data_loc_##field >> 16; \
bpf_probe_read((void *)dst, __length, (char *)args + __offset); \
} while (0);
#endif
)********"
......@@ -48,35 +48,42 @@ TracepointTypeVisitor::TracepointTypeVisitor(ASTContext &C, Rewriter &rewriter)
: C(C), diag_(C.getDiagnostics()), rewriter_(rewriter), out_(llvm::errs()) {
}
static inline bool _is_valid_field(string const& line,
string& field_type,
string& field_name) {
enum class field_kind_t {
common,
data_loc,
regular,
invalid
};
static inline field_kind_t _get_field_kind(string const& line,
string& field_type,
string& field_name) {
auto field_pos = line.find("field:");
if (field_pos == string::npos)
return false;
return field_kind_t::invalid;
auto semi_pos = line.find(';', field_pos);
if (semi_pos == string::npos)
return false;
return field_kind_t::invalid;
auto size_pos = line.find("size:", semi_pos);
if (size_pos == string::npos)
return false;
return field_kind_t::invalid;
auto field = line.substr(field_pos + 6/*"field:"*/,
semi_pos - field_pos - 6);
auto pos = field.find_last_of("\t ");
if (pos == string::npos)
return false;
return field_kind_t::invalid;
field_type = field.substr(0, pos);
field_name = field.substr(pos + 1);
if (field_type.find("__data_loc") != string::npos)
return false;
return field_kind_t::data_loc;
if (field_name.find("common_") == 0)
return false;
return field_kind_t::common;
return true;
return field_kind_t::regular;
}
string TracepointTypeVisitor::GenerateTracepointStruct(
......@@ -91,9 +98,17 @@ string TracepointTypeVisitor::GenerateTracepointStruct(
tp_struct += "\tu64 __do_not_use__;\n";
for (string line; getline(input, line); ) {
string field_type, field_name;
if (!_is_valid_field(line, field_type, field_name))
continue;
tp_struct += "\t" + field_type + " " + field_name + ";\n";
switch (_get_field_kind(line, field_type, field_name)) {
case field_kind_t::invalid:
case field_kind_t::common:
continue;
case field_kind_t::data_loc:
tp_struct += "\tint data_loc_" + field_name + ";\n";
break;
case field_kind_t::regular:
tp_struct += "\t" + field_type + " " + field_name + ";\n";
break;
}
}
tp_struct += "};\n";
......
......@@ -7,6 +7,7 @@ import unittest
from time import sleep
import distutils.version
import os
import subprocess
def kernel_version_ge(major, minor):
# True if running kernel is >= X.Y
......@@ -39,5 +40,31 @@ class TestTracepoint(unittest.TestCase):
total_switches += v.value
self.assertNotEqual(0, total_switches)
@unittest.skipUnless(kernel_version_ge(4,7), "requires kernel >= 4.7")
class TestTracepointDataLoc(unittest.TestCase):
def test_tracepoint_data_loc(self):
text = """
struct value_t {
char filename[64];
};
BPF_HASH(execs, u32, struct value_t);
TRACEPOINT_PROBE(sched, sched_process_exec) {
struct value_t val = {0};
char fn[64];
u32 pid = args->pid;
struct value_t *existing = execs.lookup_or_init(&pid, &val);
TP_DATA_LOC_READ_CONST(fn, filename, 64);
__builtin_memcpy(existing->filename, fn, 64);
return 0;
}
"""
b = bcc.BPF(text=text)
subprocess.check_output(["/bin/ls"])
sleep(1)
found = False
for k, v in b["execs"].items():
found = "ls" in v.filename
self.assertTrue(found, "'ls' was not found in map")
if __name__ == "__main__":
unittest.main()
......@@ -42,8 +42,6 @@ def print_tpoint_format(category, event):
parts = match.group(1).split()
field_name = parts[-1:][0]
field_type = " ".join(parts[:-1])
if "__data_loc" in field_type:
continue
if field_name.startswith("common_"):
continue
print(" %s %s;" % (field_type, field_name))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment