Commit fca66074 authored by yonghong-song's avatar yonghong-song Committed by GitHub

Merge pull request #1364 from palmtenor/multi_section_so

Fix shared library loaded into multiple sections
parents 0daa9124 67fa222c
...@@ -81,7 +81,8 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, ...@@ -81,7 +81,8 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback,
FILE *procmap; FILE *procmap;
int ret; int ret;
snprintf(procmap_filename, sizeof(procmap_filename), "/proc/%ld/maps", (long)pid); snprintf(procmap_filename, sizeof(procmap_filename), "/proc/%ld/maps",
(long)pid);
procmap = fopen(procmap_filename, "r"); procmap = fopen(procmap_filename, "r");
if (!procmap) if (!procmap)
...@@ -90,10 +91,10 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, ...@@ -90,10 +91,10 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback,
do { do {
char endline[4096]; char endline[4096];
char perm[8], dev[8]; char perm[8], dev[8];
long long begin, end, size, inode; long long begin, end, offset, inode;
ret = fscanf(procmap, "%llx-%llx %s %llx %s %lld", &begin, &end, perm, ret = fscanf(procmap, "%llx-%llx %s %llx %s %lld", &begin, &end, perm,
&size, dev, &inode); &offset, dev, &inode);
if (!fgets(endline, sizeof(endline), procmap)) if (!fgets(endline, sizeof(endline), procmap))
break; break;
...@@ -105,10 +106,12 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, ...@@ -105,10 +106,12 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback,
if (newline) if (newline)
newline[0] = '\0'; newline[0] = '\0';
while (isspace(mapname[0])) mapname++; while (isspace(mapname[0]))
mapname++;
if (strchr(perm, 'x') && bcc_mapping_is_file_backed(mapname)) { if (strchr(perm, 'x') && bcc_mapping_is_file_backed(mapname)) {
if (callback(mapname, (uint64_t)begin, (uint64_t)end, true, payload) < 0) if (callback(mapname, (uint64_t)begin, (uint64_t)end, (uint64_t)offset,
true, payload) < 0)
break; break;
} }
} }
...@@ -122,12 +125,15 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, ...@@ -122,12 +125,15 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback,
// Try perf-<PID>.map path with process's mount namespace, chroot and NSPID, // Try perf-<PID>.map path with process's mount namespace, chroot and NSPID,
// in case it is generated by the process itself. // in case it is generated by the process itself.
if (bcc_perf_map_path(map_path, sizeof(map_path), pid)) if (bcc_perf_map_path(map_path, sizeof(map_path), pid))
callback(map_path, 0, -1, true, payload); if (callback(map_path, 0, -1, 0, true, payload) < 0)
return 0;
// Try perf-<PID>.map path with global root and PID, in case it is generated // Try perf-<PID>.map path with global root and PID, in case it is generated
// by other Process. Avoid checking mount namespace for this. // by other Process. Avoid checking mount namespace for this.
int res = snprintf(map_path, 4096, "/tmp/perf-%d.map", pid); int res = snprintf(map_path, 4096, "/tmp/perf-%d.map", pid);
if (res > 0 && res < 4096) if (res > 0 && res < 4096)
callback(map_path, 0, -1, false, payload); if (callback(map_path, 0, -1, 0, false, payload) < 0)
return 0;
return 0; return 0;
} }
......
...@@ -24,14 +24,21 @@ extern "C" { ...@@ -24,14 +24,21 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
// Module name, start address, end address, whether to check mount namespace, payload // Module name, start address, end address, file_offset,
typedef int (*bcc_procutils_modulecb)(const char *, uint64_t, uint64_t, bool, void *); // whether to check mount namespace, payload
// Callback returning a negative value indicates to stop the iteration
typedef int (*bcc_procutils_modulecb)(const char *, uint64_t, uint64_t,
uint64_t, bool, void *);
// Symbol name, address, payload // Symbol name, address, payload
typedef void (*bcc_procutils_ksymcb)(const char *, uint64_t, void *); typedef void (*bcc_procutils_ksymcb)(const char *, uint64_t, void *);
char *bcc_procutils_which_so(const char *libname, int pid); char *bcc_procutils_which_so(const char *libname, int pid);
char *bcc_procutils_which(const char *binpath); char *bcc_procutils_which(const char *binpath);
int bcc_mapping_is_file_backed(const char *mapname); int bcc_mapping_is_file_backed(const char *mapname);
// Iterate over all executable memory mapping sections of a Process.
// All anonymous and non-file-backed mapping sections, namely those
// listed in bcc_mapping_is_file_backed, will be ignored.
// Returns -1 on error, and 0 on success
int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback,
void *payload); void *payload);
int bcc_procutils_each_ksym(bcc_procutils_ksymcb callback, void *payload); int bcc_procutils_each_ksym(bcc_procutils_ksymcb callback, void *payload);
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
#include <algorithm>
#include <cxxabi.h> #include <cxxabi.h>
#include <cstring> #include <cstring>
#include <fcntl.h> #include <fcntl.h>
...@@ -114,7 +113,7 @@ ProcSyms::ProcSyms(int pid, struct bcc_symbol_option *option) ...@@ -114,7 +113,7 @@ ProcSyms::ProcSyms(int pid, struct bcc_symbol_option *option)
int ProcSyms::_add_load_sections(uint64_t v_addr, uint64_t mem_sz, int ProcSyms::_add_load_sections(uint64_t v_addr, uint64_t mem_sz,
uint64_t file_offset, void *payload) { uint64_t file_offset, void *payload) {
auto module = static_cast<Module *>(payload); auto module = static_cast<Module *>(payload);
module->add_range(v_addr, v_addr + mem_sz); module->ranges_.emplace_back(v_addr, v_addr + mem_sz, file_offset);
return 0; return 0;
} }
...@@ -148,7 +147,7 @@ void ProcSyms::refresh() { ...@@ -148,7 +147,7 @@ void ProcSyms::refresh() {
} }
int ProcSyms::_add_module(const char *modname, uint64_t start, uint64_t end, int ProcSyms::_add_module(const char *modname, uint64_t start, uint64_t end,
bool check_mount_ns, void *payload) { uint64_t offset, bool check_mount_ns, void *payload) {
ProcSyms *ps = static_cast<ProcSyms *>(payload); ProcSyms *ps = static_cast<ProcSyms *>(payload);
auto it = std::find_if( auto it = std::find_if(
ps->modules_.begin(), ps->modules_.end(), ps->modules_.begin(), ps->modules_.end(),
...@@ -162,7 +161,11 @@ int ProcSyms::_add_module(const char *modname, uint64_t start, uint64_t end, ...@@ -162,7 +161,11 @@ int ProcSyms::_add_module(const char *modname, uint64_t start, uint64_t end,
else else
return 0; return 0;
} }
it->add_range(start, end); it->ranges_.emplace_back(start, end, offset);
// perf-PID map is added last. We try both inside the Process's mount
// namespace + chroot, and in global /tmp. Make sure we only add one.
if (it->type_ == ModuleType::PERF_MAP)
return -1;
return 0; return 0;
} }
...@@ -275,21 +278,12 @@ void ProcSyms::Module::load_sym_table() { ...@@ -275,21 +278,12 @@ void ProcSyms::Module::load_sym_table() {
std::sort(syms_.begin(), syms_.end()); std::sort(syms_.begin(), syms_.end());
} }
void ProcSyms::Module::add_range(uint64_t st, uint64_t en) {
if (!ranges_.empty()) {
Range &last = ranges_.back();
if (st >= last.start && st <= last.end) {
last.end = std::max(en, last.end);
return;
}
}
ranges_.emplace_back(st, en);
}
bool ProcSyms::Module::contains(uint64_t addr, uint64_t &offset) const { bool ProcSyms::Module::contains(uint64_t addr, uint64_t &offset) const {
for (const auto &range : ranges_) for (const auto &range : ranges_)
if (addr >= range.start && addr < range.end) { if (addr >= range.start && addr < range.end) {
offset = type_ == ModuleType::SO ? addr - range.start : addr; offset = (type_ == ModuleType::SO)
? (addr - range.start + range.file_offset)
: addr;
return true; return true;
} }
return false; return false;
...@@ -401,13 +395,15 @@ void bcc_symcache_refresh(void *resolver) { ...@@ -401,13 +395,15 @@ void bcc_symcache_refresh(void *resolver) {
struct mod_st { struct mod_st {
const char *name; const char *name;
uint64_t start; uint64_t start;
uint64_t file_offset;
}; };
static int _find_module(const char *modname, uint64_t start, uint64_t end, bool, static int _find_module(const char *modname, uint64_t start, uint64_t end,
void *p) { uint64_t offset, bool, void *p) {
struct mod_st *mod = (struct mod_st *)p; struct mod_st *mod = (struct mod_st *)p;
if (!strcmp(modname, mod->name)) { if (!strcmp(modname, mod->name)) {
mod->start = start; mod->start = start;
mod->file_offset = offset;
return -1; return -1;
} }
return 0; return 0;
...@@ -420,7 +416,7 @@ int bcc_resolve_global_addr(int pid, const char *module, const uint64_t address, ...@@ -420,7 +416,7 @@ int bcc_resolve_global_addr(int pid, const char *module, const uint64_t address,
mod.start == 0x0) mod.start == 0x0)
return -1; return -1;
*global = mod.start + address; *global = mod.start + mod.file_offset + address;
return 0; return 0;
} }
......
...@@ -92,10 +92,12 @@ class ProcSyms : SymbolCache { ...@@ -92,10 +92,12 @@ class ProcSyms : SymbolCache {
struct Range { struct Range {
uint64_t start; uint64_t start;
uint64_t end; uint64_t end;
Range(uint64_t s, uint64_t e) : start(s), end(e) {} uint64_t file_offset;
Range(uint64_t s, uint64_t e, uint64_t f)
: start(s), end(e), file_offset(f) {}
}; };
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(); bool init();
...@@ -111,7 +113,6 @@ class ProcSyms : SymbolCache { ...@@ -111,7 +113,6 @@ class ProcSyms : SymbolCache {
void load_sym_table(); void load_sym_table();
void add_range(uint64_t st, uint64_t en);
bool contains(uint64_t addr, uint64_t &offset) const; bool contains(uint64_t addr, uint64_t &offset) const;
uint64_t start() const { return ranges_.begin()->start; } uint64_t start() const { return ranges_.begin()->start; }
...@@ -130,7 +131,8 @@ class ProcSyms : SymbolCache { ...@@ -130,7 +131,8 @@ class ProcSyms : SymbolCache {
static int _add_load_sections(uint64_t v_addr, uint64_t mem_sz, static int _add_load_sections(uint64_t v_addr, uint64_t mem_sz,
uint64_t file_offset, void *payload); uint64_t file_offset, void *payload);
static int _add_module(const char *, uint64_t, uint64_t, bool, void *); static int _add_module(const char *, uint64_t, uint64_t, uint64_t, bool,
void *);
void load_exe(); void load_exe();
void load_modules(); void load_modules();
......
...@@ -207,7 +207,8 @@ class Context { ...@@ -207,7 +207,8 @@ class Context {
static void _each_probe(const char *binpath, const struct bcc_elf_usdt *probe, static void _each_probe(const char *binpath, const struct bcc_elf_usdt *probe,
void *p); void *p);
static int _each_module(const char *modpath, uint64_t, uint64_t, bool, void *p); static int _each_module(const char *modpath, uint64_t, uint64_t, uint64_t,
bool, void *p);
void add_probe(const char *binpath, const struct bcc_elf_usdt *probe); void add_probe(const char *binpath, const struct bcc_elf_usdt *probe);
std::string resolve_bin_path(const std::string &bin_path); std::string resolve_bin_path(const std::string &bin_path);
......
...@@ -217,7 +217,8 @@ void Context::_each_probe(const char *binpath, const struct bcc_elf_usdt *probe, ...@@ -217,7 +217,8 @@ void Context::_each_probe(const char *binpath, const struct bcc_elf_usdt *probe,
ctx->add_probe(binpath, probe); ctx->add_probe(binpath, probe);
} }
int Context::_each_module(const char *modpath, uint64_t, uint64_t, bool, void *p) { int Context::_each_module(const char *modpath, uint64_t, uint64_t, uint64_t,
bool, void *p) {
Context *ctx = static_cast<Context *>(p); Context *ctx = static_cast<Context *>(p);
// Modules may be reported multiple times if they contain more than one // Modules may be reported multiple times if they contain more than one
// executable region. We are going to parse the ELF on disk anyway, so we // executable region. We are going to parse the ELF on disk anyway, so we
......
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