Skip to content

Commit

Permalink
Use absolute module file path when possible
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
lenticularis39 authored and yonghong-song committed Oct 8, 2022
1 parent 12e5312 commit cc44177
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 8 deletions.
37 changes: 29 additions & 8 deletions src/cc/bcc_syms.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,27 @@
* limitations under the License.
*/

#include "bcc_syms.h"

#include <cxxabi.h>
#include <cstring>
#include <fcntl.h>
#include <limits.h>
#include <linux/elf.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <unistd.h>

#include <cstdio>
#include <cstring>

#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;
Expand All @@ -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) {
Expand Down Expand Up @@ -134,8 +154,9 @@ void ProcSyms::refresh() {

int ProcSyms::_add_module(mod_info *mod, int enter_ns, void *payload) {
ProcSyms *ps = static_cast<ProcSyms *>(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; });
Expand Down
4 changes: 4 additions & 0 deletions src/cc/syms.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_); }
};
Expand Down

0 comments on commit cc44177

Please sign in to comment.