Commit fead16ad authored by Yonghong Song's avatar Yonghong Song

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 <pid> 'u:<binary_path>:probe'
```
will count `probe` occurances for all binary paths in `pid`, not just
`<binary_path>`. The command
```
argdist -p <pid> 'u:<binary_path>: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 <pid> '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: default avatarYonghong Song <yhs@fb.com>
parent 24894573
......@@ -22,7 +22,7 @@ extern "C" {
#include <stdint.h>
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);
......
......@@ -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);
}
......
......@@ -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<int> pid() const { return pid_; }
......
......@@ -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;
......
......@@ -179,7 +179,7 @@ lib.bcc_symcache_refresh.restype = None
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]
......
......@@ -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:
......
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