Hello community,
here is the log from the commit of package bcc for openSUSE:Factory checked in at 2017-03-12 20:05:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/bcc (Old)
and /work/SRC/openSUSE:Factory/.bcc.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "bcc"
Sun Mar 12 20:05:02 2017 rev:5 rq:478085 version:0.3.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/bcc/bcc.changes 2017-03-03 17:55:02.428090760 +0100
+++ /work/SRC/openSUSE:Factory/.bcc.new/bcc.changes 2017-03-12 20:05:04.992560381 +0100
@@ -1,0 +2,18 @@
+Fri Mar 10 02:20:39 UTC 2017 - glin@suse.com
+
+- Update to 0.3.0
+ + Added s390x support. Needs 4.10 Kernel
+ + Restrict rewrite of unary operators to dereference operator
+ + cmake: Explicitly mark static libraries as such
+ + Fix bpf_dins_pkt rewrite in BinaryOperator
+ + cc: Symbol resolution with multiple executable regions per
+ module
+ + cc: Fix assertion for debug builds
+ + cc: Don't parse the same module multiple times for USDT probes
+ + add XDP return values to python interface
+ + python: handle null module in BPF.sym
+ + filetop: support specifying sort column via cmdline argument
+ + cc: Retry symbol resolution using perfmap
+ + cc: Handle nested functions correctly when resolving symbols
+
+-------------------------------------------------------------------
Old:
----
bcc-v0.2.0+git1488325605.4d0d430.tar.xz
New:
----
bcc-v0.3.0.tar.xz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ bcc.spec ++++++
--- /var/tmp/diff_new_pack.9e1EsI/_old 2017-03-12 20:05:05.948425124 +0100
+++ /var/tmp/diff_new_pack.9e1EsI/_new 2017-03-12 20:05:05.948425124 +0100
@@ -16,7 +16,7 @@
#
-%define libversion 0.2.0
+%define libversion 0.3.0
%ifarch ppc64 aarch64 ppc64le
%{!?with_lua: %global with_lua 0}
%else
@@ -24,7 +24,7 @@
%endif
Name: bcc
-Version: 0.2.0+git1488325605.4d0d430
+Version: 0.3.0
Release: 0
Summary: BPF Compiler Collection (BCC)
License: Apache-2.0
++++++ bcc-v0.2.0+git1488325605.4d0d430.tar.xz -> bcc-v0.3.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/.travis.yml new/bcc-v0.3.0/.travis.yml
--- old/bcc-v0.2.0+git1488325605.4d0d430/.travis.yml 1970-01-01 01:00:00.000000000 +0100
+++ new/bcc-v0.3.0/.travis.yml 2017-03-10 03:07:20.000000000 +0100
@@ -0,0 +1,6 @@
+language: generic
+install:
+ - sudo apt-get install -y python-pip
+ - sudo pip install pep8
+script:
+ - find tools/ -type f -name "*.py" | xargs pep8 -r --show-source --ignore=E123,E125,E126,E127,E128,E302
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/debian/changelog new/bcc-v0.3.0/debian/changelog
--- old/bcc-v0.2.0+git1488325605.4d0d430/debian/changelog 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/debian/changelog 2017-03-10 03:07:20.000000000 +0100
@@ -1,3 +1,16 @@
+bcc (0.3.0-1) unstable; urgency=low
+
+ * Many bugfixes
+ * Many tools converted to perf ring buffer
+ * New utilities in tools/
+ * capable, cpuunclaimed, dbslower, dbstat, deadlock_detector, llcstat,
+ mountsnoop, runqlen, slabratetop, syscount, tcplife, tcptop, ttysnoop,
+ ucalls, uflow, ugc, uobjnew, ustat, uthreads
+ * New C++ API
+ * Support for kernel up to 4.10
+
+ -- Brenden Blanco Thu, 09 Mar 2017 19:08:08 +0000
+
bcc (0.2.0-1) unstable; urgency=low
* Add many new utilities in tools/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/debian/rules new/bcc-v0.3.0/debian/rules
--- old/bcc-v0.2.0+git1488325605.4d0d430/debian/rules 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/debian/rules 2017-03-10 03:07:20.000000000 +0100
@@ -11,6 +11,10 @@
%:
dh $@ --buildsystem=cmake --parallel
+# tests cannot be run in parallel
+override_dh_auto_test:
+ dh_auto_test -O--buildsystem=cmake -O--no-parallel
+
# FIXME: LLVM_DEFINITIONS is broken somehow in LLVM cmake upstream
override_dh_auto_configure:
dh_auto_configure -- -DREVISION_LAST=$(UPSTREAM_VERSION) -DREVISION=$(UPSTREAM_VERSION) -DLLVM_DEFINITIONS="-D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/docs/tutorial_bcc_python_developer.md new/bcc-v0.3.0/docs/tutorial_bcc_python_developer.md
--- old/bcc-v0.2.0+git1488325605.4d0d430/docs/tutorial_bcc_python_developer.md 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/docs/tutorial_bcc_python_developer.md 2017-03-10 03:07:20.000000000 +0100
@@ -96,7 +96,7 @@
1. ```b.attach_kprobe(event="sys_clone", fn_name="hello")```: Creates a kprobe for the sys_clone() kernel function, which will execute our defined hello() function. You can call attach_kprobe() more than once, and attach your C function to multiple kernel functions.
-1. ```b.trace_fields()```: Returns a fixed set of fields from trace_pipe. Simalar to trace_print(), this is handy for hacking, but for real tooling we should switch to BPF_PERF_OUTPUT().
+1. ```b.trace_fields()```: Returns a fixed set of fields from trace_pipe. Similar to trace_print(), this is handy for hacking, but for real tooling we should switch to BPF_PERF_OUTPUT().
### Lesson 4. sync_timing.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/man/man8/filetop.8 new/bcc-v0.3.0/man/man8/filetop.8
--- old/bcc-v0.2.0+git1488325605.4d0d430/man/man8/filetop.8 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/man/man8/filetop.8 2017-03-10 03:07:20.000000000 +0100
@@ -2,14 +2,15 @@
.SH NAME
filetop \- File reads and writes by filename and process. Top for files.
.SH SYNOPSIS
-.B filetop [\-h] [\-C] [\-r MAXROWS] [\-p PID] [interval] [count]
+.B filetop [\-h] [\-C] [\-r MAXROWS] [\-s {reads,writes,rbytes,wbytes}] [\-p PID] [interval] [count]
.SH DESCRIPTION
This is top for files.
-This traces file reads and writes, and prints a per-file summary every
-interval (by default, 1 second). The summary is sorted on the highest read
-throughput (Kbytes). By default only IO on regular files is shown. The -a
-option will list all file types (sokets, FIFOs, etc).
+This traces file reads and writes, and prints a per-file summary every interval
+(by default, 1 second). By default the summary is sorted on the highest read
+throughput (Kbytes). Sorting order can be changed via -s option. By default only
+IO on regular files is shown. The -a option will list all file types (sokets,
+FIFOs, etc).
This uses in-kernel eBPF maps to store per process summaries for efficiency.
@@ -39,6 +40,9 @@
\-r MAXROWS
Maximum number of rows to print. Default is 20.
.TP
+\-s {reads,writes,rbytes,wbytes}
+Sort column. Default is rbytes (read throughput).
+.TP
\-p PID
Trace this PID only.
.TP
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/CMakeLists.txt new/bcc-v0.3.0/src/cc/CMakeLists.txt
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/CMakeLists.txt 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/cc/CMakeLists.txt 2017-03-10 03:07:20.000000000 +0100
@@ -39,7 +39,7 @@
set_target_properties(bcc-shared PROPERTIES VERSION ${REVISION_LAST} SOVERSION 0)
set_target_properties(bcc-shared PROPERTIES OUTPUT_NAME bcc)
-add_library(bcc-loader-static libbpf.c perf_reader.c bcc_elf.c bcc_perf_map.c bcc_proc.c)
+add_library(bcc-loader-static STATIC libbpf.c perf_reader.c bcc_elf.c bcc_perf_map.c bcc_proc.c)
add_library(bcc-static STATIC bpf_common.cc bpf_module.cc shared_table.cc exported_files.cc bcc_syms.cc usdt_args.cc usdt.cc common.cc BPF.cc BPFTable.cc)
set_target_properties(bcc-static PROPERTIES OUTPUT_NAME bcc)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/bcc_syms.cc new/bcc-v0.3.0/src/cc/bcc_syms.cc
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/bcc_syms.cc 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/cc/bcc_syms.cc 2017-03-10 03:07:20.000000000 +0100
@@ -101,7 +101,11 @@
int ProcSyms::_add_module(const char *modname, uint64_t start, uint64_t end,
void *payload) {
ProcSyms *ps = static_cast(payload);
- ps->modules_.emplace_back(modname, start, end);
+ auto it = std::find_if(ps->modules_.begin(), ps->modules_.end(),
+ [=](const ProcSyms::Module &m) { return m.name_ == modname; });
+ if (it == ps->modules_.end())
+ it = ps->modules_.insert(ps->modules_.end(), modname);
+ it->ranges_.push_back(ProcSyms::Module::Range(start, end));
return 0;
}
@@ -114,15 +118,30 @@
sym->demangle_name = nullptr;
sym->offset = 0x0;
+ const char *original_module = nullptr;
for (Module &mod : modules_) {
- if (addr >= mod.start_ && addr < mod.end_) {
+ if (mod.contains(addr)) {
bool res = mod.find_addr(addr, sym);
if (sym->name) {
sym->demangle_name = abi::__cxa_demangle(sym->name, nullptr, nullptr, nullptr);
if (!sym->demangle_name)
sym->demangle_name = sym->name;
}
- return res;
+ // If we have a match, return right away. But if we don't have a match in
+ // this module, we might have a match in the perf map (even though the
+ // module itself doesn't have symbols). Wait until we see the perf map if
+ // any, but keep the original module name for reporting.
+ if (res) {
+ // If we have already seen this module, report the original name rather
+ // than the perf map name:
+ if (original_module)
+ sym->module = original_module;
+ return res;
+ } else {
+ // Record the module to which this symbol belongs, so that even if it's
+ // later found using a perf map, we still report the right module name.
+ original_module = mod.name_.c_str();
+ }
}
}
return false;
@@ -140,8 +159,8 @@
return false;
}
-ProcSyms::Module::Module(const char *name, uint64_t start, uint64_t end)
- : name_(name), start_(start), end_(end) {
+ProcSyms::Module::Module(const char *name)
+ : name_(name) {
is_so_ = bcc_elf_is_shared_obj(name) == 1;
}
@@ -169,12 +188,20 @@
std::sort(syms_.begin(), syms_.end());
}
+bool ProcSyms::Module::contains(uint64_t addr) const {
+ for (const auto &range : ranges_) {
+ if (addr >= range.start && addr < range.end)
+ return true;
+ }
+ return false;
+}
+
bool ProcSyms::Module::find_name(const char *symname, uint64_t *addr) {
load_sym_table();
for (Symbol &s : syms_) {
if (*(s.name) == symname) {
- *addr = is_so() ? start_ + s.start : s.start;
+ *addr = is_so() ? start() + s.start : s.start;
return true;
}
}
@@ -182,7 +209,7 @@
}
bool ProcSyms::Module::find_addr(uint64_t addr, struct bcc_symbol *sym) {
- uint64_t offset = is_so() ? (addr - start_) : addr;
+ uint64_t offset = is_so() ? (addr - start()) : addr;
load_sym_table();
@@ -190,16 +217,34 @@
sym->offset = offset;
auto it = std::upper_bound(syms_.begin(), syms_.end(), Symbol(nullptr, offset, 0));
- if (it != syms_.begin())
- --it;
- else
- it = syms_.end();
+ if (it == syms_.begin())
+ return false;
- if (it != syms_.end()
- && offset >= it->start && offset < it->start + it->size) {
- sym->name = it->name->c_str();
- sym->offset = (offset - it->start);
- return true;
+ // 'it' points to the symbol whose start address is strictly greater than
+ // the address we're looking for. Start stepping backwards as long as the
+ // current symbol is still below the desired address, and see if the end
+ // of the current symbol (start + size) is above the desired address. Once
+ // we have a matching symbol, return it. Note that simply looking at '--it'
+ // is not enough, because symbols can be nested. For example, we could be
+ // looking for offset 0x12 with the following symbols available:
+ // SYMBOL START SIZE END
+ // goo 0x0 0x6 0x0 + 0x6 = 0x6
+ // foo 0x6 0x10 0x6 + 0x10 = 0x16
+ // bar 0x8 0x4 0x8 + 0x4 = 0xc
+ // baz 0x16 0x10 0x16 + 0x10 = 0x26
+ // The upper_bound lookup will return baz, and then going one symbol back
+ // brings us to bar, which does not contain offset 0x12 and is nested inside
+ // foo. Going back one more symbol brings us to foo, which contains 0x12
+ // and is a match.
+ for (--it; offset >= it->start; --it) {
+ if (offset < it->start + it->size) {
+ sym->name = it->name->c_str();
+ sym->offset = (offset - it->start);
+ return true;
+ }
+ // But don't step beyond begin()!
+ if (it == syms_.begin())
+ break;
}
return false;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/export/helpers.h new/bcc-v0.3.0/src/cc/export/helpers.h
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/export/helpers.h 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/cc/export/helpers.h 2017-03-10 03:07:20.000000000 +0100
@@ -468,6 +468,17 @@
#define PT_REGS_RC(ctx) ((ctx)->gpr[3])
#define PT_REGS_IP(ctx) ((ctx)->nip)
#define PT_REGS_SP(ctx) ((ctx)->sp)
+#elif defined(__s390x__)
+#define PT_REGS_PARM1(x) ((x)->gprs[2])
+#define PT_REGS_PARM2(x) ((x)->gprs[3])
+#define PT_REGS_PARM3(x) ((x)->gprs[4])
+#define PT_REGS_PARM4(x) ((x)->gprs[5])
+#define PT_REGS_PARM5(x) ((x)->gprs[6])
+#define PT_REGS_RET(x) ((x)->gprs[14])
+#define PT_REGS_FP(x) ((x)->gprs[11]) /* Works only with CONFIG_FRAME_POINTER */
+#define PT_REGS_RC(x) ((x)->gprs[2])
+#define PT_REGS_SP(x) ((x)->gprs[15])
+#define PT_REGS_IP(x) ((x)->psw.addr)
#elif defined(__x86_64__)
#define PT_REGS_PARM1(ctx) ((ctx)->di)
#define PT_REGS_PARM2(ctx) ((ctx)->si)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/frontends/b/CMakeLists.txt new/bcc-v0.3.0/src/cc/frontends/b/CMakeLists.txt
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/frontends/b/CMakeLists.txt 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/cc/frontends/b/CMakeLists.txt 2017-03-10 03:07:20.000000000 +0100
@@ -11,5 +11,5 @@
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/lexer.ll.cc PROPERTIES COMPILE_FLAGS "-Wno-deprecated-register")
endif()
-add_library(b_frontend loader.cc codegen_llvm.cc node.cc parser.cc printer.cc
+add_library(b_frontend STATIC loader.cc codegen_llvm.cc node.cc parser.cc printer.cc
type_check.cc ${BISON_Parser_OUTPUTS} ${FLEX_Lexer_OUTPUTS})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/frontends/clang/CMakeLists.txt new/bcc-v0.3.0/src/cc/frontends/clang/CMakeLists.txt
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/frontends/clang/CMakeLists.txt 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/cc/frontends/clang/CMakeLists.txt 2017-03-10 03:07:20.000000000 +0100
@@ -2,4 +2,4 @@
# Licensed under the Apache License, Version 2.0 (the "License")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DKERNEL_MODULES_DIR='\"${BCC_KERNEL_MODULES_DIR}\"'")
-add_library(clang_frontend loader.cc b_frontend_action.cc tp_frontend_action.cc kbuild_helper.cc ../../common.cc)
+add_library(clang_frontend STATIC loader.cc b_frontend_action.cc tp_frontend_action.cc kbuild_helper.cc ../../common.cc)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/frontends/clang/b_frontend_action.cc new/bcc-v0.3.0/src/cc/frontends/clang/b_frontend_action.cc
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/frontends/clang/b_frontend_action.cc 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/cc/frontends/clang/b_frontend_action.cc 2017-03-10 03:07:20.000000000 +0100
@@ -39,11 +39,17 @@
};
const char *calling_conv_regs_ppc[] = {"gpr[3]", "gpr[4]", "gpr[5]",
"gpr[6]", "gpr[7]", "gpr[8]"};
+
+const char *calling_conv_regs_s390x[] = {"gprs[2]", "gprs[3]", "gprs[4]",
+ "gprs[5]", "gprs[6]" };
+
const char *calling_conv_regs_arm64[] = {"regs[0]", "regs[1]", "regs[2]",
"regs[3]", "regs[4]", "regs[5]"};
// todo: support more archs
#if defined(__powerpc__)
const char **calling_conv_regs = calling_conv_regs_ppc;
+#elif defined(__s390x__)
+const char **calling_conv_regs = calling_conv_regs_s390x;
#elif defined(__aarch64__)
const char **calling_conv_regs = calling_conv_regs_arm64;
#else
@@ -200,7 +206,7 @@
return true;
}
bool ProbeVisitor::VisitUnaryOperator(UnaryOperator *E) {
- if (E->getOpcode() == UO_AddrOf)
+ if (E->getOpcode() != UO_Deref)
return true;
if (memb_visited_.find(E) != memb_visited_.end())
return true;
@@ -521,7 +527,6 @@
if (!E->isAssignmentOp())
return true;
Expr *LHS = E->getLHS()->IgnoreImplicit();
- Expr *RHS = E->getRHS()->IgnoreImplicit();
if (MemberExpr *Memb = dyn_cast<MemberExpr>(LHS)) {
if (DeclRefExpr *Base = dyn_cast<DeclRefExpr>(Memb->getBase()->IgnoreImplicit())) {
if (DeprecatedAttr *A = Base->getDecl()->getAttr<DeprecatedAttr>()) {
@@ -534,10 +539,10 @@
uint64_t ofs = C.getFieldOffset(F);
uint64_t sz = F->isBitField() ? F->getBitWidthValue(C) : C.getTypeSize(F->getType());
string base = rewriter_.getRewrittenText(expansionRange(Base->getSourceRange()));
- string rhs = rewriter_.getRewrittenText(expansionRange(RHS->getSourceRange()));
string text = "bpf_dins_pkt(" + fn_args_[0]->getName().str() + ", (u64)" + base + "+" + to_string(ofs >> 3)
- + ", " + to_string(ofs & 0x7) + ", " + to_string(sz) + ", " + rhs + ")";
- rewriter_.ReplaceText(expansionRange(E->getSourceRange()), text);
+ + ", " + to_string(ofs & 0x7) + ", " + to_string(sz) + ",";
+ rewriter_.ReplaceText(expansionRange(SourceRange(E->getLocStart(), E->getOperatorLoc())), text);
+ rewriter_.InsertTextAfterToken(E->getLocEnd(), ")");
}
}
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/frontends/clang/loader.cc new/bcc-v0.3.0/src/cc/frontends/clang/loader.cc
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/frontends/clang/loader.cc 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/cc/frontends/clang/loader.cc 2017-03-10 03:07:20.000000000 +0100
@@ -172,6 +172,8 @@
#else
driver::Driver drv("", "powerpc64-unknown-linux-gnu", diags);
#endif
+#elif defined(__s390x__)
+ driver::Driver drv("", "s390x-ibm-linux-gnu", diags);
#elif defined(__aarch64__)
driver::Driver drv("", "aarch64-unknown-linux-gnu", diags);
#else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/libbpf.c new/bcc-v0.3.0/src/cc/libbpf.c
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/libbpf.c 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/cc/libbpf.c 2017-03-10 03:07:20.000000000 +0100
@@ -46,6 +46,8 @@
#ifndef __NR_bpf
#if defined(__powerpc64__)
#define __NR_bpf 361
+#elif defined(__s390x__)
+#define __NR_bpf 351
#elif defined(__aarch64__)
#define __NR_bpf 280
#else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/syms.h new/bcc-v0.3.0/src/cc/syms.h
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/syms.h 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/cc/syms.h 2017-03-10 03:07:20.000000000 +0100
@@ -79,15 +79,22 @@
};
struct Module {
- Module(const char *name, uint64_t start, uint64_t end);
+ struct Range {
+ uint64_t start;
+ uint64_t end;
+ Range(uint64_t s, uint64_t e) : start(s), end(e) {}
+ };
+
+ Module(const char *name);
std::string name_;
- uint64_t start_;
- uint64_t end_;
+ std::vector<Range> ranges_;
bool is_so_;
std::unordered_setstd::string symnames_;
std::vector<Symbol> syms_;
void load_sym_table();
+ bool contains(uint64_t addr) const;
+ uint64_t start() const { return ranges_.begin()->start; }
bool find_addr(uint64_t addr, struct bcc_symbol *sym);
bool find_name(const char *symname, uint64_t *addr);
bool is_so() const { return is_so_; }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/usdt.cc new/bcc-v0.3.0/src/cc/usdt.cc
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/usdt.cc 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/cc/usdt.cc 2017-03-10 03:07:20.000000000 +0100
@@ -63,7 +63,7 @@
}
bool Probe::add_to_semaphore(int16_t val) {
- assert(pid_ && attached_semaphore_);
+ assert(pid_);
if (!attached_semaphore_) {
uint64_t addr;
@@ -200,7 +200,13 @@
}
int Context::_each_module(const char *modpath, uint64_t, uint64_t, void *p) {
- bcc_elf_foreach_usdt(modpath, _each_probe, p);
+ Context *ctx = static_cast(p);
+ // Modules may be reported multiple times if they contain more than one
+ // executable region. We are going to parse the ELF on disk anyway, so we
+ // don't need these duplicates.
+ if (ctx->modules_.insert(modpath).second /*inserted new?*/) {
+ bcc_elf_foreach_usdt(modpath, _each_probe, p);
+ }
return 0;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/usdt.h new/bcc-v0.3.0/src/cc/usdt.h
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/cc/usdt.h 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/cc/usdt.h 2017-03-10 03:07:20.000000000 +0100
@@ -191,6 +191,7 @@
class Context {
std::vector probes_;
+ std::unordered_setstd::string modules_;
optional<int> pid_;
optional<ProcStat> pid_stat_;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/python/bcc/__init__.py new/bcc-v0.3.0/src/python/bcc/__init__.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/python/bcc/__init__.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/python/bcc/__init__.py 2017-03-10 03:07:20.000000000 +0100
@@ -118,6 +118,12 @@
XDP = 6
PERF_EVENT = 7
+ # from xdp_action uapi/linux/bpf.h
+ XDP_ABORTED = 0
+ XDP_DROP = 1
+ XDP_PASS = 2
+ XDP_TX = 3
+
_probe_repl = re.compile("[^a-zA-Z0-9_]")
_sym_caches = {}
@@ -989,12 +995,12 @@
returned. When show_module is True, the module name is also included.
When show_offset is True, the instruction offset as a hexadecimal
number is also included in the string.
-
+
A pid of less than zero will access the kernel symbol cache.
Example output when both show_module and show_offset are True:
"start_thread+0x202 [libpthread-2.24.so]"
-
+
Example output when both show_module and show_offset are False:
"start_thread"
"""
@@ -1002,7 +1008,8 @@
offset = "+0x%x" % offset if show_offset and name is not None else ""
name = name or "[unknown]"
name = name + offset
- module = " [%s]" % os.path.basename(module) if show_module else ""
+ module = " [%s]" % os.path.basename(module) \
+ if show_module and module is not None else ""
return name + module
@staticmethod
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/src/python/bcc/usdt.py new/bcc-v0.3.0/src/python/bcc/usdt.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/src/python/bcc/usdt.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/src/python/bcc/usdt.py 2017-03-10 03:07:20.000000000 +0100
@@ -130,7 +130,7 @@
raise USDTException("USDT failed to instrument PID %d" % pid)
elif path:
self.path = path
- self.context = lib.bcc_usdt_new_frompath(path)
+ self.context = lib.bcc_usdt_new_frompath(path.encode('ascii'))
if self.context == None:
raise USDTException("USDT failed to instrument path %s" % path)
else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tests/python/test_clang.py new/bcc-v0.3.0/tests/python/test_clang.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tests/python/test_clang.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tests/python/test_clang.py 2017-03-10 03:07:20.000000000 +0100
@@ -392,5 +392,35 @@
t = b["act"]
self.assertEquals(len(t), 32);
+ def test_bpf_dins_pkt_rewrite(self):
+ text = """
+#include
+int dns_test(struct __sk_buff *skb) {
+ u8 *cursor = 0;
+ struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
+ if(ethernet->type == ETH_P_IP) {
+ struct ip_t *ip = cursor_advance(cursor, sizeof(*ip));
+ ip->src = ip->dst;
+ return 0;
+ }
+ return -1;
+}
+ """
+ b = BPF(text=text)
+
+ def test_unary_operator(self):
+ text = """
+#include
+#include
+int trace_read_entry(struct pt_regs *ctx, struct file *file) {
+ return !file->f_op->read_iter;
+}
+ """
+ b = BPF(text=text)
+ b.attach_kprobe(event="__vfs_read", fn_name="trace_read_entry")
+
if __name__ == "__main__":
main()
+
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/argdist.py new/bcc-v0.3.0/tools/argdist.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/argdist.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/argdist.py 2017-03-10 03:07:20.000000000 +0100
@@ -200,7 +200,7 @@
elif self.probe_type == "u":
self.library = parts[1]
self.probe_func_name = self._make_valid_identifier(
- "%s_probe%d" % \
+ "%s_probe%d" %
(self.function, Probe.next_probe_index))
self._enable_usdt_probe()
else:
@@ -238,10 +238,10 @@
(any(map(check, self.exprs)) or check(self.filter))
self.probe_func_name = self._make_valid_identifier(
- "%s_probe%d" % \
+ "%s_probe%d" %
(self.function, Probe.next_probe_index))
self.probe_hash_name = self._make_valid_identifier(
- "%s_hash%d" % \
+ "%s_hash%d" %
(self.function, Probe.next_probe_index))
Probe.next_probe_index += 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/cpuunclaimed.py new/bcc-v0.3.0/tools/cpuunclaimed.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/cpuunclaimed.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/cpuunclaimed.py 2017-03-10 03:07:20.000000000 +0100
@@ -169,10 +169,10 @@
if args.timestamp:
print("TIME", end=",")
print("TIMESTAMP_ns", end=",")
- print(",".join("CPU" + str(c) for c in xrange(ncpu)), end="")
+ print(",".join("CPU" + str(c) for c in range(ncpu)), end="")
if args.fullcsv:
print(",", end="")
- print(",".join("OFFSET_ns_CPU" + str(c) for c in xrange(ncpu)), end="")
+ print(",".join("OFFSET_ns_CPU" + str(c) for c in range(ncpu)), end="")
print()
else:
print(("Sampling run queues... Output every %s seconds. " +
@@ -255,10 +255,10 @@
if args.timestamp:
print("%-8s" % strftime("%H:%M:%S"), end=",")
print("%d" % g_time, end=",")
- print(",".join(str(lens[c]) for c in xrange(ncpu)), end="")
+ print(",".join(str(lens[c]) for c in range(ncpu)), end="")
if args.fullcsv:
print(",", end="")
- print(",".join(str(offs[c]) for c in xrange(ncpu)))
+ print(",".join(str(offs[c]) for c in range(ncpu)))
else:
print()
else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/dbslower.py new/bcc-v0.3.0/tools/dbslower.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/dbslower.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/dbslower.py 2017-03-10 03:07:20.000000000 +0100
@@ -13,7 +13,7 @@
#
# Strongly inspired by Brendan Gregg's work on the mysqld_qslower script.
#
-# Copyright 2017, Sasha Goldshtein
+# Copyright 2017, Sasha Goldshtein
# Licensed under the Apache License, Version 2.0
#
# 15-Feb-2017 Sasha Goldshtein Created this.
@@ -27,7 +27,7 @@
dbslower postgres # trace PostgreSQL queries slower than 1ms
dbslower postgres -p 188 322 # trace specific PostgreSQL processes
dbslower mysql -p 480 -m 30 # trace MySQL queries slower than 30ms
- dbslower mysql -p 480 -v # trace MySQL queries and print the BPF program
+ dbslower mysql -p 480 -v # trace MySQL queries & print the BPF program
"""
parser = argparse.ArgumentParser(
description="",
@@ -134,4 +134,3 @@
bpf["events"].open_perf_buffer(print_event, page_cnt=64)
while True:
bpf.kprobe_poll()
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/dbstat.py new/bcc-v0.3.0/tools/dbstat.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/dbstat.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/dbstat.py 2017-03-10 03:07:20.000000000 +0100
@@ -8,7 +8,7 @@
# This tool uses USDT probes, which means it needs MySQL and PostgreSQL built
# with USDT (DTrace) support.
#
-# Copyright 2017, Sasha Goldshtein
+# Copyright 2017, Sasha Goldshtein
# Licensed under the Apache License, Version 2.0
#
# 15-Feb-2017 Sasha Goldshtein Created this.
@@ -80,7 +80,7 @@
}
"""
program = program.replace("SCALE", str(1000 if args.microseconds else 1000000))
-program = program.replace("FILTER", "" if args.threshold == 0 else \
+program = program.replace("FILTER", "" if args.threshold == 0 else
"if (delta / 1000000 < %d) { return 0; }" % args.threshold)
usdts = map(lambda pid: USDT(pid=pid), args.pids)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/filetop.py new/bcc-v0.3.0/tools/filetop.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/filetop.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/filetop.py 2017-03-10 03:07:20.000000000 +0100
@@ -38,6 +38,9 @@
help="don't clear the screen")
parser.add_argument("-r", "--maxrows", default=20,
help="maximum rows to print, default 20")
+parser.add_argument("-s", "--sort", default="rbytes",
+ choices=["reads", "writes", "rbytes", "wbytes"],
+ help="sort column, default rbytes")
parser.add_argument("-p", "--pid", type=int, metavar="PID", dest="tgid",
help="trace this PID only")
parser.add_argument("interval", nargs="?", default=1,
@@ -184,7 +187,8 @@
counts = b.get_table("counts")
line = 0
for k, v in reversed(sorted(counts.items(),
- key=lambda counts: counts[1].rbytes)):
+ key=lambda counts:
+ getattr(counts[1], args.sort))):
name = k.name.decode()
if k.name_len > DNAME_INLINE_LEN:
name = name[:-3] + "..."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/filetop_example.txt new/bcc-v0.3.0/tools/filetop_example.txt
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/filetop_example.txt 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/filetop_example.txt 2017-03-10 03:07:20.000000000 +0100
@@ -29,10 +29,11 @@
26628 ld 12 0 52 0 R swap.o
[...]
-This shows various files read and written during a Linux kernel build. The
-output is sorted by the total read size in Kbytes (R_Kb). This is instrumenting
-at the VFS interface, so this is reads and writes that may return entirely
-from the file system cache (page cache).
+This shows various files read and written during a Linux kernel build. By
+default the output is sorted by the total read size in Kbytes (R_Kb). Sorting
+order can be changed via -s option. This is instrumenting at the VFS interface,
+so this is reads and writes that may return entirely from the file system cache
+(page cache).
While not printed, the average read and write size can be calculated by
dividing R_Kb by READS, and the same for writes.
@@ -146,6 +147,8 @@
-C, --noclear don't clear the screen
-r MAXROWS, --maxrows MAXROWS
maximum rows to print, default 20
+ -s {reads,writes,rbytes,wbytes}, --sort {reads,writes,rbytes,wbytes}
+ sort column, default rbytes
-p PID, --pid PID trace this PID only
examples:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/funclatency.py new/bcc-v0.3.0/tools/funclatency.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/funclatency.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/funclatency.py 2017-03-10 03:07:20.000000000 +0100
@@ -90,7 +90,6 @@
# define BPF program
bpf_text = """
#include
-#include
typedef struct ip_pid {
u64 ip;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/old/memleak.py new/bcc-v0.3.0/tools/old/memleak.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/old/memleak.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/old/memleak.py 2017-03-10 03:07:20.000000000 +0100
@@ -186,8 +186,9 @@
allocs.update(&address, &info);
if (SHOULD_PRINT) {
- bpf_trace_printk("alloc exited, size = %lu, result = %lx, frames = %d\\n",
- info.size, address, info.num_frames);
+ bpf_trace_printk("alloc exited, size = %lu, result = %lx,"
+ "frames = %d\\n", info.size, address,
+ info.num_frames);
}
return 0;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/old/offwaketime.py new/bcc-v0.3.0/tools/old/offwaketime.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/old/offwaketime.py 1970-01-01 01:00:00.000000000 +0100
+++ new/bcc-v0.3.0/tools/old/offwaketime.py 2017-03-10 03:07:20.000000000 +0100
@@ -0,0 +1,284 @@
+#!/usr/bin/python
+#
+# offwaketime Summarize blocked time by kernel off-CPU stack + waker stack
+# For Linux, uses BCC, eBPF.
+#
+# USAGE: offwaketime [-h] [-u] [-p PID] [-T] [duration]
+#
+# The current implementation uses an unrolled loop for x86_64, and was written
+# as a proof of concept. This implementation should be replaced in the future
+# with an appropriate bpf_ call, when available.
+#
+# The Off-CPU stack is currently limited to a stack trace depth of 20
+# (maxtdepth), and the waker stack limited to 10 (maxwdepth). This is also
+# limited to kernel stacks, and x86_64 only. Check for future versions, where
+# these limitations should be removed.
+#
+# Copyright 2016 Netflix, Inc.
+# Licensed under the Apache License, Version 2.0 (the "License")
+#
+# 20-Jan-2016 Brendan Gregg Created this.
+
+from __future__ import print_function
+from bcc import BPF
+from time import sleep
+import argparse
+import signal
+
+# arguments
+examples = """examples:
+ ./offwaketime # trace off-CPU + waker stack time until Ctrl-C
+ ./offwaketime 5 # trace for 5 seconds only
+ ./offwaketime -f 5 # 5 seconds, and output in folded format
+ ./offwaketime -u # don't include kernel threads (user only)
+ ./offwaketime -p 185 # trace fo PID 185 only
+"""
+parser = argparse.ArgumentParser(
+ description="Summarize blocked time by kernel stack trace + waker stack",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog=examples)
+parser.add_argument("-u", "--useronly", action="store_true",
+ help="user threads only (no kernel threads)")
+parser.add_argument("-p", "--pid",
+ help="trace this PID only")
+parser.add_argument("-v", "--verbose", action="store_true",
+ help="show raw addresses")
+parser.add_argument("-f", "--folded", action="store_true",
+ help="output folded format")
+parser.add_argument("duration", nargs="?", default=99999999,
+ help="duration of trace, in seconds")
+args = parser.parse_args()
+folded = args.folded
+duration = int(args.duration)
+debug = 0
+maxwdepth = 10 # and MAXWDEPTH
+maxtdepth = 20 # and MAXTDEPTH
+if args.pid and args.useronly:
+ print("ERROR: use either -p or -u.")
+ exit()
+
+# signal handler
+def signal_ignore(signal, frame):
+ print()
+
+# define BPF program
+bpf_text = """
+#include
+#include
+
+#define MAXWDEPTH 10
+#define MAXTDEPTH 20
+#define MINBLOCK_US 1
+
+struct key_t {
+ char waker[TASK_COMM_LEN];
+ char target[TASK_COMM_LEN];
+ u64 wret[MAXWDEPTH];
+ u64 tret[MAXTDEPTH];
+};
+BPF_HASH(counts, struct key_t);
+BPF_HASH(start, u32);
+struct wokeby_t {
+ char name[TASK_COMM_LEN];
+ u64 ret[MAXWDEPTH];
+};
+BPF_HASH(wokeby, u32, struct wokeby_t);
+
+static u64 get_frame(u64 *bp) {
+ if (*bp) {
+ // The following stack walker is x86_64 specific
+ u64 ret = 0;
+ if (bpf_probe_read(&ret, sizeof(ret), (void *)(*bp+8)))
+ return 0;
+ if (bpf_probe_read(bp, sizeof(*bp), (void *)*bp))
+ *bp = 0;
+ if (ret < __START_KERNEL_map)
+ return 0;
+ return ret;
+ }
+ return 0;
+}
+
+int waker(struct pt_regs *ctx, struct task_struct *p) {
+ u32 pid = p->pid;
+
+ if (!(FILTER))
+ return 0;
+
+ u64 bp = 0;
+ struct wokeby_t woke = {};
+ int depth = 0;
+ bpf_get_current_comm(&woke.name, sizeof(woke.name));
+ bp = ctx->bp;
+
+ // unrolled loop (MAXWDEPTH):
+ if (!(woke.ret[depth++] = get_frame(&bp))) goto out;
+ if (!(woke.ret[depth++] = get_frame(&bp))) goto out;
+ if (!(woke.ret[depth++] = get_frame(&bp))) goto out;
+ if (!(woke.ret[depth++] = get_frame(&bp))) goto out;
+ if (!(woke.ret[depth++] = get_frame(&bp))) goto out;
+ if (!(woke.ret[depth++] = get_frame(&bp))) goto out;
+ if (!(woke.ret[depth++] = get_frame(&bp))) goto out;
+ if (!(woke.ret[depth++] = get_frame(&bp))) goto out;
+ if (!(woke.ret[depth++] = get_frame(&bp))) goto out;
+ woke.ret[depth] = get_frame(&bp);
+
+out:
+ wokeby.update(&pid, &woke);
+ return 0;
+}
+
+int oncpu(struct pt_regs *ctx, struct task_struct *p) {
+ u32 pid = p->pid;
+ u64 ts, *tsp;
+
+ // record previous thread sleep time
+ if (FILTER) {
+ ts = bpf_ktime_get_ns();
+ start.update(&pid, &ts);
+ }
+
+ // calculate current thread's delta time
+ pid = bpf_get_current_pid_tgid();
+ tsp = start.lookup(&pid);
+ if (tsp == 0)
+ return 0; // missed start or filtered
+ u64 delta = bpf_ktime_get_ns() - *tsp;
+ start.delete(&pid);
+ delta = delta / 1000;
+ if (delta < MINBLOCK_US)
+ return 0;
+
+ // create map key
+ u64 zero = 0, *val, bp = 0;
+ int depth = 0;
+ struct key_t key = {};
+ struct wokeby_t *woke;
+ bpf_get_current_comm(&key.target, sizeof(key.target));
+ bp = ctx->bp;
+
+ // unrolled loop (MAXTDEPTH):
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ if (!(key.tret[depth++] = get_frame(&bp))) goto out;
+ key.tret[depth] = get_frame(&bp);
+
+out:
+ woke = wokeby.lookup(&pid);
+ if (woke) {
+ __builtin_memcpy(&key.wret, woke->ret, sizeof(key.wret));
+ __builtin_memcpy(&key.waker, woke->name, TASK_COMM_LEN);
+ wokeby.delete(&pid);
+ }
+
+ val = counts.lookup_or_init(&key, &zero);
+ (*val) += delta;
+ return 0;
+}
+"""
+if args.pid:
+ filter = 'pid == %s' % args.pid
+elif args.useronly:
+ filter = '!(p->flags & PF_KTHREAD)'
+else:
+ filter = '1'
+bpf_text = bpf_text.replace('FILTER', filter)
+if debug:
+ print(bpf_text)
+
+# initialize BPF
+b = BPF(text=bpf_text)
+b.attach_kprobe(event="finish_task_switch", fn_name="oncpu")
+b.attach_kprobe(event="try_to_wake_up", fn_name="waker")
+matched = b.num_open_kprobes()
+if matched == 0:
+ print("0 functions traced. Exiting.")
+ exit()
+
+# header
+if not folded:
+ print("Tracing blocked time (us) by kernel off-CPU and waker stack",
+ end="")
+ if duration < 99999999:
+ print(" for %d secs." % duration)
+ else:
+ print("... Hit Ctrl-C to end.")
+
+# output
+while (1):
+ try:
+ sleep(duration)
+ except KeyboardInterrupt:
+ # as cleanup can take many seconds, trap Ctrl-C:
+ signal.signal(signal.SIGINT, signal_ignore)
+
+ if not folded:
+ print()
+ counts = b.get_table("counts")
+ for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
+ if folded:
+ # fold target stack
+ line = k.target + ";"
+ for i in reversed(range(0, maxtdepth)):
+ if k.tret[i] == 0:
+ continue
+ line = line + b.ksym(k.tret[i])
+ if i != 0:
+ line = line + ";"
+
+ # add delimiter
+ line = line + ";-"
+
+ # fold waker stack
+ for i in range(0, maxwdepth):
+ line = line + ";"
+ if k.wret[i] == 0:
+ break
+ line = line + b.ksym(k.wret[i])
+ if i != 0:
+ line = line + ";" + k.waker
+
+ # print as a line
+ print("%s %d" % (line, v.value))
+ else:
+ # print wakeup name then stack in reverse order
+ print(" %-16s %s" % ("waker:", k.waker))
+ for i in reversed(range(0, maxwdepth)):
+ if k.wret[i] == 0:
+ continue
+ print(" %-16x %s" % (k.wret[i],
+ b.ksym(k.wret[i])))
+
+ # print delimiter
+ print(" %-16s %s" % ("-", "-"))
+
+ # print default multi-line stack output
+ for i in range(0, maxtdepth):
+ if k.tret[i] == 0:
+ break
+ print(" %-16x %s" % (k.tret[i],
+ b.ksym(k.tret[i])))
+ print(" %-16s %s" % ("target:", k.target))
+ print(" %d\n" % v.value)
+ counts.clear()
+
+ if not folded:
+ print("Detaching...")
+ exit()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/syscount.py new/bcc-v0.3.0/tools/syscount.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/syscount.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/syscount.py 2017-03-10 03:07:20.000000000 +0100
@@ -23,7 +23,8 @@
# cat syscallent.h | awk -F, '{ gsub(/[ \t"}]/, "", $4);
# gsub(/[ \t/*]/, "", $5);
# print " "$5": \""$4"\","; }
-# BEGIN { print "syscalls = {" } END { print "}" }'
+# BEGIN { print "syscalls = {" }
+# END { print "}" }'
#
syscalls = {
0: "read",
@@ -459,7 +460,7 @@
def agg_colval(key):
if args.process:
- return "%-6d %-15s" % (key.value, comm_for_pid(key.value))
+ return "%-6d %-15s" % (key.value, comm_for_pid(key.value))
else:
return syscalls.get(key.value, "[unknown: %d]" % key.value)
@@ -478,7 +479,8 @@
data = bpf["data"]
print("[%s]" % strftime("%H:%M:%S"))
print("%-22s %8s %16s" % (agg_colname, "COUNT", time_colname))
- for k, v in sorted(data.items(), key=lambda kv: -kv[1].total_ns)[:args.top]:
+ for k, v in sorted(data.items(),
+ key=lambda kv: -kv[1].total_ns)[:args.top]:
if k.value == 0xFFFFFFFF:
continue # happens occasionally, we don't need it
print(("%-22s %8d " + ("%16.6f" if args.milliseconds else "%16.3f")) %
@@ -497,4 +499,3 @@
if not args.interval:
print_stats()
break
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/tplist.py new/bcc-v0.3.0/tools/tplist.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/tplist.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/tplist.py 2017-03-10 03:07:20.000000000 +0100
@@ -64,17 +64,17 @@
print_tpoint(category, event)
def print_usdt_argument_details(location):
- for idx in xrange(0, location.num_arguments):
+ for idx in range(0, location.num_arguments):
arg = location.get_argument(idx)
- print(" argument #%d %s" % (idx+1, arg))
+ print(" argument #%d %s" % (idx + 1, arg))
def print_usdt_details(probe):
if args.verbosity > 0:
print(probe)
if args.verbosity > 1:
- for idx in xrange(0, probe.num_locations):
+ for idx in range(0, probe.num_locations):
loc = probe.get_location(idx)
- print(" location #%d %s" % (idx+1, loc))
+ print(" location #%d %s" % (idx + 1, loc))
print_usdt_argument_details(loc)
else:
print(" %d location(s)" % probe.num_locations)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/trace.py new/bcc-v0.3.0/tools/trace.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/trace.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/trace.py 2017-03-10 03:07:20.000000000 +0100
@@ -53,7 +53,8 @@
self.probe_num = Probe.probe_count
self.probe_name = "probe_%s_%d" % \
(self._display_function(), self.probe_num)
- self.probe_name = re.sub(r'[^A-Za-z0-9_]', '_', self.probe_name)
+ self.probe_name = re.sub(r'[^A-Za-z0-9_]', '_',
+ self.probe_name)
def __str__(self):
return "%s:%s:%s FLT=%s ACT=%s/%s" % (self.probe_type,
@@ -81,7 +82,8 @@
text).groups()
self._parse_spec(spec)
- self.signature = sig[1:-1] if sig else None # remove the parens
+ # Remove the parens
+ self.signature = sig[1:-1] if sig else None
if self.signature and self.probe_type in ['u', 't']:
self._bail("USDT and tracepoint probes can't have " +
"a function signature; use arg1, arg2, " +
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/ucalls.py new/bcc-v0.3.0/tools/ucalls.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/ucalls.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/ucalls.py 2017-03-10 03:07:20.000000000 +0100
@@ -257,7 +257,8 @@
bpf["systimes"].items())
data.extend(syscalls)
else:
- syscalls = map(lambda kv: (bpf.ksym(kv[0].value), (kv[1].value, 0)),
+ syscalls = map(lambda kv: (bpf.ksym(kv[0].value),
+ (kv[1].value, 0)),
bpf["syscounts"].items())
data.extend(syscalls)
@@ -294,8 +295,8 @@
data = data[-args.top:]
for key, value in data:
if args.latency:
- time = value[1]/1000000.0 if args.milliseconds else \
- value[1]/1000.0
+ time = value[1] / 1000000.0 if args.milliseconds else \
+ value[1] / 1000.0
print("%-50s %8d %6.2f" % (key, value[0], time))
else:
print("%-50s %8d" % (key, value[0]))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/uflow.py new/bcc-v0.3.0/tools/uflow.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/uflow.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/uflow.py 2017-03-10 03:07:20.000000000 +0100
@@ -97,7 +97,7 @@
def enable_probe(probe_name, func_name, read_class, read_method, is_return):
global program, trace_template, usdt
depth = "*depth + 1" if not is_return else "*depth | (1ULL << 63)"
- update = "++(*depth);" if not is_return else "if (*depth) --(*depth);"
+ update = "++(*depth);" if not is_return else "if (*depth) --(*depth);"
filter_class = "if (!prefix_class(data.clazz)) { return 0; }" \
if args.clazz else ""
filter_method = "if (!prefix_method(data.method)) { return 0; }" \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/ugc.py new/bcc-v0.3.0/tools/ugc.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/ugc.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/ugc.py 2017-03-10 03:07:20.000000000 +0100
@@ -134,8 +134,10 @@
bpf_probe_read(&event.string1, sizeof(event.string1), (void *)manager);
bpf_probe_read(&event.string2, sizeof(event.string2), (void *)pool);
"""
- formatter = lambda e: "%s %s used=%d->%d max=%d->%d" % \
- (e.string1, e.string2, e.field1, e.field3, e.field2, e.field4)
+
+ def formatter(e):
+ "%s %s used=%d->%d max=%d->%d" % \
+ (e.string1, e.string2, e.field1, e.field3, e.field2, e.field4)
probes.append(Probe("mem__pool__gc__begin", "mem__pool__gc__end",
begin_save, end_save, formatter))
probes.append(Probe("gc__begin", "gc__end",
@@ -155,8 +157,10 @@
event.field1 = e->field1;
event.field2 = objs;
"""
- formatter = lambda event: "gen %d GC collected %d objects" % \
- (event.field1, event.field2)
+
+ def formatter(event):
+ "gen %d GC collected %d objects" % \
+ (event.field1, event.field2)
probes.append(Probe("gc__start", "gc__done",
begin_save, end_save, formatter))
#
@@ -214,10 +218,10 @@
def print_event(cpu, data, size):
event = ct.cast(data, ct.POINTER(GCEvent)).contents
- elapsed = event.elapsed_ns/1000000 if args.milliseconds else \
- event.elapsed_ns/1000
+ elapsed = event.elapsed_ns / 1000000 if args.milliseconds else \
+ event.elapsed_ns / 1000
description = probes[event.probe_index].format(event)
- if args.filter and not args.filter in description:
+ if args.filter and args.filter not in description:
return
print("%-8.3f %-8.2f %s" % (time.time() - start_ts, elapsed, description))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/uobjnew.py new/bcc-v0.3.0/tools/uobjnew.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/uobjnew.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/uobjnew.py 2017-03-10 03:07:20.000000000 +0100
@@ -110,7 +110,8 @@
usdt.enable_probe_or_bail("object__create", "object_alloc_entry")
for thing in ["string", "hash", "array"]:
program += create_template.replace("THETHING", thing)
- usdt.enable_probe_or_bail("%s__create" % thing, "%s_alloc_entry" % thing)
+ usdt.enable_probe_or_bail("%s__create" % thing,
+ "%s_alloc_entry" % thing)
#
# C
#
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bcc-v0.2.0+git1488325605.4d0d430/tools/ustat.py new/bcc-v0.3.0/tools/ustat.py
--- old/bcc-v0.2.0+git1488325605.4d0d430/tools/ustat.py 2017-03-01 00:46:45.000000000 +0100
+++ new/bcc-v0.3.0/tools/ustat.py 2017-03-10 03:07:20.000000000 +0100
@@ -244,8 +244,9 @@
counts.update(probe.get_counts(self.bpf))
targets.update(probe.targets)
if self.args.sort:
- counts = sorted(counts.items(), key=lambda kv:
- -kv[1].get(self.args.sort.upper(), 0))
+ sort_field = self.args.sort.upper()
+ counts = sorted(counts.items(),
+ key=lambda kv: -kv[1].get(sort_field, 0))
else:
counts = sorted(counts.items(), key=lambda kv: kv[0])
for pid, stats in counts: