Commit 1df0f883 authored by Teng Qin's avatar Teng Qin

Fix Module display for unreadable Modules

parent f609af25
...@@ -25,9 +25,11 @@ ...@@ -25,9 +25,11 @@
bool bcc_is_perf_map(const char *path) { bool bcc_is_perf_map(const char *path) {
char* pos = strstr(path, ".map"); char* pos = strstr(path, ".map");
// Path ends with ".map" // Path ends with ".map"
if (pos == NULL || *(pos + 4) != 0) return (pos != NULL) && (*(pos + 4)== 0);
return false; }
return access(path, R_OK) == 0;
bool bcc_is_valid_perf_map(const char *path) {
return bcc_is_perf_map(path) && (access(path, R_OK) == 0);
} }
int bcc_perf_map_nstgid(int pid) { int bcc_perf_map_nstgid(int pid) {
......
...@@ -28,6 +28,7 @@ extern "C" { ...@@ -28,6 +28,7 @@ extern "C" {
typedef int (*bcc_perf_map_symcb)(const char *, uint64_t, uint64_t, void *); typedef int (*bcc_perf_map_symcb)(const char *, uint64_t, uint64_t, void *);
bool bcc_is_perf_map(const char *path); bool bcc_is_perf_map(const char *path);
bool bcc_is_valid_perf_map(const char *path);
int bcc_perf_map_nstgid(int pid); int bcc_perf_map_nstgid(int pid);
bool bcc_perf_map_path(char *map_path, size_t map_len, int pid); bool bcc_perf_map_path(char *map_path, size_t map_len, int pid);
......
...@@ -125,8 +125,6 @@ void ProcSyms::load_exe() { ...@@ -125,8 +125,6 @@ void ProcSyms::load_exe() {
std::string exe = ebpf::get_pid_exe(pid_); std::string exe = ebpf::get_pid_exe(pid_);
Module module(exe.c_str(), mount_ns_instance_.get(), &symbol_option_); Module module(exe.c_str(), mount_ns_instance_.get(), &symbol_option_);
if (!module.init())
return;
if (module.type_ != ModuleType::EXEC) if (module.type_ != ModuleType::EXEC)
return; return;
...@@ -160,7 +158,10 @@ int ProcSyms::_add_module(const char *modname, uint64_t start, uint64_t end, ...@@ -160,7 +158,10 @@ int ProcSyms::_add_module(const char *modname, uint64_t start, uint64_t end,
auto module = Module( auto module = Module(
modname, check_mount_ns ? ps->mount_ns_instance_.get() : nullptr, modname, check_mount_ns ? ps->mount_ns_instance_.get() : nullptr,
&ps->symbol_option_); &ps->symbol_option_);
if (module.init()) if (!bcc_is_perf_map(modname) || module.type_ != ModuleType::UNKNOWN)
// Always add the module even if we can't read it, so that we could
// report correct module name. Unless it's a perf map that we only
// add readable ones.
it = ps->modules_.insert(ps->modules_.end(), std::move(module)); it = ps->modules_.insert(ps->modules_.end(), std::move(module));
else else
return 0; return 0;
...@@ -179,16 +180,16 @@ bool ProcSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym, ...@@ -179,16 +180,16 @@ bool ProcSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym,
if (procstat_.is_stale()) if (procstat_.is_stale())
refresh(); refresh();
sym->module = nullptr; memset(sym, 0, sizeof(struct bcc_symbol));
sym->name = nullptr;
sym->demangle_name = nullptr;
sym->offset = 0x0;
const char *original_module = nullptr; const char *original_module = nullptr;
uint64_t offset; uint64_t offset;
bool only_perf_map = false;
for (Module &mod : modules_) { for (Module &mod : modules_) {
if (only_perf_map && (mod.type_ != ModuleType::PERF_MAP))
continue;
if (mod.contains(addr, offset)) { if (mod.contains(addr, offset)) {
bool res = mod.find_addr(offset, sym); if (mod.find_addr(offset, sym)) {
if (demangle) { if (demangle) {
if (sym->name) if (sym->name)
sym->demangle_name = sym->demangle_name =
...@@ -196,23 +197,23 @@ bool ProcSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym, ...@@ -196,23 +197,23 @@ bool ProcSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym,
if (!sym->demangle_name) if (!sym->demangle_name)
sym->demangle_name = sym->name; sym->demangle_name = sym->name;
} }
// If we have a match, return right away. But if we don't have a match in return true;
// 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 if (mod.type_ != ModuleType::PERF_MAP) { } else if (mod.type_ != ModuleType::PERF_MAP) {
// Record the module to which this symbol belongs, so that even if it's // In this case, we found the address in the range of a module, but
// later found using a perf map, we still report the right module name. // not able to find a symbol of that address in the module.
// Thus, we would try to find the address in perf map, and
// save the module's name in case we will need it later.
original_module = mod.name_.c_str(); original_module = mod.name_.c_str();
only_perf_map = true;
} }
} }
} }
// If we didn't find the symbol anywhere, the module name is probably
// set to be the perf map's name as it would be the last we tried.
// In this case, if we have found the address previously in a module,
// report the saved original module name instead.
if (original_module)
sym->module = original_module;
return false; return false;
} }
...@@ -234,34 +235,22 @@ ProcSyms::Module::Module(const char *name, ProcMountNS *mount_ns, ...@@ -234,34 +235,22 @@ ProcSyms::Module::Module(const char *name, ProcMountNS *mount_ns,
loaded_(false), loaded_(false),
mount_ns_(mount_ns), mount_ns_(mount_ns),
symbol_option_(option), symbol_option_(option),
type_(ModuleType::UNKNOWN) {} type_(ModuleType::UNKNOWN) {
bool ProcSyms::Module::init() {
ProcMountNSGuard g(mount_ns_); ProcMountNSGuard g(mount_ns_);
int elf_type = bcc_elf_get_type(name_.c_str()); int elf_type = bcc_elf_get_type(name_.c_str());
// The Module is an ELF file
if (elf_type >= 0) { if (elf_type >= 0) {
if (elf_type == ET_EXEC) { if (elf_type == ET_EXEC)
type_ = ModuleType::EXEC; type_ = ModuleType::EXEC;
return true; else if (elf_type == ET_DYN)
}
if (elf_type == ET_DYN) {
type_ = ModuleType::SO; type_ = ModuleType::SO;
return true; return;
}
return false;
} }
// Other symbol files
if (bcc_is_perf_map(name_.c_str()) == 1) { if (bcc_is_valid_perf_map(name_.c_str()) == 1)
type_ = ModuleType::PERF_MAP; type_ = ModuleType::PERF_MAP;
return true; else if (bcc_elf_is_vdso(name_.c_str()) == 1)
}
if (bcc_elf_is_vdso(name_.c_str()) == 1) {
type_ = ModuleType::VDSO; type_ = ModuleType::VDSO;
return true;
}
return false;
} }
int ProcSyms::Module::_add_symbol(const char *symname, uint64_t start, int ProcSyms::Module::_add_symbol(const char *symname, uint64_t start,
...@@ -277,6 +266,9 @@ void ProcSyms::Module::load_sym_table() { ...@@ -277,6 +266,9 @@ void ProcSyms::Module::load_sym_table() {
return; return;
loaded_ = true; loaded_ = true;
if (type_ == ModuleType::UNKNOWN)
return;
ProcMountNSGuard g(mount_ns_); ProcMountNSGuard g(mount_ns_);
if (type_ == ModuleType::PERF_MAP) if (type_ == ModuleType::PERF_MAP)
......
...@@ -100,7 +100,6 @@ class ProcSyms : SymbolCache { ...@@ -100,7 +100,6 @@ class ProcSyms : SymbolCache {
Module(const char *name, ProcMountNS *mount_ns, Module(const char *name, ProcMountNS *mount_ns,
struct bcc_symbol_option *option); struct bcc_symbol_option *option);
bool init();
std::string name_; std::string name_;
std::vector<Range> ranges_; std::vector<Range> ranges_;
......
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