From cc441778d1b77ee0b206751180046fb385f9c9fc Mon Sep 17 00:00:00 2001 From: Tomas Glozar Date: Mon, 3 Oct 2022 10:38:50 +0200 Subject: [PATCH] Use absolute module file path when possible Follow symlink in /proc/.../root and prepend it to module filename instead of prepending /proc/.../root. This allows the file to be found when doing symbol resolution even when the process has already exited by that time. The symlink value is stored in ProcStat::root_ and is checked for changes in ProcStat::is_stale, its change triggering reloading modules to get the correct path. If the symlink reading fails, ProcStat::root_ is set to /proc/.../root. --- src/cc/bcc_syms.cc | 37 +++++++++++++++++++++++++++++-------- src/cc/syms.h | 4 ++++ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/cc/bcc_syms.cc b/src/cc/bcc_syms.cc index fdacfe77d9e0..5968ad8a1b45 100644 --- a/src/cc/bcc_syms.cc +++ b/src/cc/bcc_syms.cc @@ -14,25 +14,27 @@ * limitations under the License. */ +#include "bcc_syms.h" + #include -#include #include +#include #include #include #include #include #include #include + #include +#include #include "bcc_elf.h" #include "bcc_perf_map.h" #include "bcc_proc.h" -#include "bcc_syms.h" #include "common.h" -#include "vendor/tinyformat.hpp" - #include "syms.h" +#include "vendor/tinyformat.hpp" bool ProcStat::getinode_(ino_t &inode) { struct stat s; @@ -44,13 +46,31 @@ bool ProcStat::getinode_(ino_t &inode) { } } +bool ProcStat::refresh_root() { + char ns_root[PATH_MAX]; + std::string original_root = root_; + int readlink_read = readlink(root_symlink_.c_str(), ns_root, PATH_MAX); + if (readlink_read >= 0 && readlink_read < PATH_MAX) { + // readlink succeded, save link target to root_ + ns_root[readlink_read] = 0; + root_ = std::string(ns_root); + return original_root != root_; + } + // readlink failed, keep old value of root_ + return false; +} + bool ProcStat::is_stale() { ino_t cur_inode; - return getinode_(cur_inode) && (cur_inode != inode_); + return getinode_(cur_inode) && (cur_inode != inode_) && refresh_root(); } -ProcStat::ProcStat(int pid) : procfs_(tfm::format("/proc/%d/exe", pid)) { +ProcStat::ProcStat(int pid) + : procfs_(tfm::format("/proc/%d/exe", pid)), + root_symlink_(tfm::format("/proc/%d/root", pid)), + root_(root_symlink_) { getinode_(inode_); + refresh_root(); } void KSyms::_add_symbol(const char *symname, const char *modname, uint64_t addr, void *p) { @@ -134,8 +154,9 @@ void ProcSyms::refresh() { int ProcSyms::_add_module(mod_info *mod, int enter_ns, void *payload) { ProcSyms *ps = static_cast(payload); - std::string ns_relative_path = tfm::format("/proc/%d/root%s", ps->pid_, mod->name); - const char *modpath = enter_ns && ps->pid_ != -1 ? ns_relative_path.c_str() : mod->name; + std::string ns_modpath = ps->procstat_.get_root() + mod->name; + const char *modpath = + enter_ns && ps->pid_ != -1 ? ns_modpath.c_str() : mod->name; auto it = std::find_if( ps->modules_.begin(), ps->modules_.end(), [=](const ProcSyms::Module &m) { return m.name_ == mod->name; }); diff --git a/src/cc/syms.h b/src/cc/syms.h index 86e84e221cdf..f61537dd8482 100644 --- a/src/cc/syms.h +++ b/src/cc/syms.h @@ -29,11 +29,15 @@ class ProcStat { std::string procfs_; + std::string root_symlink_; + std::string root_; ino_t inode_; bool getinode_(ino_t &inode); public: ProcStat(int pid); + bool refresh_root(); + const std::string &get_root() { return root_; } bool is_stale(); void reset() { getinode_(inode_); } };