From fead16addb28582d21f8fcd6f175d46f06ae31f9 Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Wed, 10 Jan 2018 10:43:28 -0800 Subject: [PATCH] usdt: permit to enable probes from a pid and a particular binary Currently, for usdt, the commands where both a pid and a binary path are specified are not well supported. For example, ``` funccount -p 'u::probe' ``` will count `probe` occurances for all binary paths in `pid`, not just ``. The command ``` argdist -p 'u::probe():s64:arg1' ``` will also count `probe` occurances for all binary paths in `pid` with my previous patch. Furthermore, suppose user want to trace linker `setjmp` probe point with command ``` trace.py -p 'u:/usr/lib64/ld-2.17.so:setjmp' ``` Without my previous patch, user will have incorrect results as both `libc:setjmp` and `rtld:setjmp` exists and the bcc just picks the first one which is `libc:setjmp`. My last patch will cause `enable_probe` failures if in the same usdt context, two probes have the same probe_name but different provider name. To fix all these issues, this patch passes additional binary path to the pid-based usdt context, so that only probes from that particular binary will be added to the context. This solved all the above mentioned issues. Signed-off-by: Yonghong Song --- src/cc/bcc_usdt.h | 2 +- src/cc/link_all.cc | 2 +- src/cc/usdt.h | 1 + src/cc/usdt/usdt.cc | 25 +++++++++++++++++++++++-- src/python/bcc/libbcc.py | 2 +- src/python/bcc/usdt.py | 5 ++++- 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/cc/bcc_usdt.h b/src/cc/bcc_usdt.h index 57515d1d3183..a031bc6ab2c7 100644 --- a/src/cc/bcc_usdt.h +++ b/src/cc/bcc_usdt.h @@ -22,7 +22,7 @@ extern "C" { #include -void *bcc_usdt_new_frompid(int pid); +void *bcc_usdt_new_frompid(int pid, const char *path); void *bcc_usdt_new_frompath(const char *path); void bcc_usdt_close(void *usdt); diff --git a/src/cc/link_all.cc b/src/cc/link_all.cc index 11057766e179..e03ea76cf6d8 100644 --- a/src/cc/link_all.cc +++ b/src/cc/link_all.cc @@ -13,7 +13,7 @@ namespace { if (::getenv("bar") != (char *)-1) return; - (void)bcc_usdt_new_frompid(-1); + (void)bcc_usdt_new_frompid(-1, nullptr); (void)bcc_usdt_new_frompath(nullptr); (void)bcc_usdt_close(nullptr); } diff --git a/src/cc/usdt.h b/src/cc/usdt.h index 5932890de516..33878bcf97c4 100644 --- a/src/cc/usdt.h +++ b/src/cc/usdt.h @@ -249,6 +249,7 @@ class Context { public: Context(const std::string &bin_path); Context(int pid); + Context(int pid, const std::string &bin_path); ~Context(); optional pid() const { return pid_; } diff --git a/src/cc/usdt/usdt.cc b/src/cc/usdt/usdt.cc index 72d38fe9d3e3..49ff3abc4fe5 100644 --- a/src/cc/usdt/usdt.cc +++ b/src/cc/usdt/usdt.cc @@ -365,6 +365,22 @@ Context::Context(int pid) : pid_(pid), pid_stat_(pid), probe->finalize_locations(); } +Context::Context(int pid, const std::string &bin_path) + : pid_(pid), pid_stat_(pid), + mount_ns_instance_(new ProcMountNS(pid)), loaded_(false) { + std::string full_path = resolve_bin_path(bin_path); + if (!full_path.empty()) { + if (bcc_elf_foreach_usdt(full_path.c_str(), _each_probe, this) == 0) { + cmd_bin_path_ = ebpf::get_pid_exe(pid); + if (cmd_bin_path_.empty()) + return; + loaded_ = true; + } + } + for (const auto &probe : probes_) + probe->finalize_locations(); +} + Context::~Context() { if (pid_stat_ && !pid_stat_->is_stale()) { for (auto &p : probes_) p->disable(); @@ -374,8 +390,13 @@ Context::~Context() { extern "C" { -void *bcc_usdt_new_frompid(int pid) { - USDT::Context *ctx = new USDT::Context(pid); +void *bcc_usdt_new_frompid(int pid, const char *path) { + USDT::Context *ctx; + + if (!path) + ctx = new USDT::Context(pid); + else + ctx = new USDT::Context(pid, path); if (!ctx->loaded()) { delete ctx; return nullptr; diff --git a/src/python/bcc/libbcc.py b/src/python/bcc/libbcc.py index d94fa6e7dcd9..2f857624b682 100644 --- a/src/python/bcc/libbcc.py +++ b/src/python/bcc/libbcc.py @@ -179,7 +179,7 @@ class bcc_symbol_option(ct.Structure): lib.bcc_symcache_refresh.argtypes = [ct.c_void_p] lib.bcc_usdt_new_frompid.restype = ct.c_void_p -lib.bcc_usdt_new_frompid.argtypes = [ct.c_int] +lib.bcc_usdt_new_frompid.argtypes = [ct.c_int, ct.c_char_p] lib.bcc_usdt_new_frompath.restype = ct.c_void_p lib.bcc_usdt_new_frompath.argtypes = [ct.c_char_p] diff --git a/src/python/bcc/usdt.py b/src/python/bcc/usdt.py index feb5e2e83d23..8b113ce3fa41 100644 --- a/src/python/bcc/usdt.py +++ b/src/python/bcc/usdt.py @@ -127,7 +127,10 @@ class USDT(object): def __init__(self, pid=None, path=None): if pid and pid != -1: self.pid = pid - self.context = lib.bcc_usdt_new_frompid(pid) + if path: + self.context = lib.bcc_usdt_new_frompid(pid, path.encode('ascii')) + else: + self.context = lib.bcc_usdt_new_frompid(pid, ct.c_char_p(0)) if self.context == None: raise USDTException("USDT failed to instrument PID %d" % pid) elif path: