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,
FILE *procmap;
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");
if (!procmap)
......@@ -90,10 +91,10 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback,
do {
char endline[4096];
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,
&size, dev, &inode);
&offset, dev, &inode);
if (!fgets(endline, sizeof(endline), procmap))
break;
......@@ -105,10 +106,12 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback,
if (newline)
newline[0] = '\0';
while (isspace(mapname[0])) mapname++;
while (isspace(mapname[0]))
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;
}
}
......@@ -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,
// in case it is generated by the process itself.
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
// by other Process. Avoid checking mount namespace for this.
int res = snprintf(map_path, 4096, "/tmp/perf-%d.map", pid);
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;
}
......
......@@ -24,14 +24,21 @@ extern "C" {
#include <stdint.h>
// Module name, start address, end address, whether to check mount namespace, payload
typedef int (*bcc_procutils_modulecb)(const char *, uint64_t, uint64_t, bool, void *);
// Module name, start address, end address, file_offset,
// 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
typedef void (*bcc_procutils_ksymcb)(const char *, uint64_t, void *);
char *bcc_procutils_which_so(const char *libname, int pid);
char *bcc_procutils_which(const char *binpath);
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,
void *payload);
int bcc_procutils_each_ksym(bcc_procutils_ksymcb callback, void *payload);
......
......@@ -14,7 +14,6 @@
* limitations under the License.
*/
#include <algorithm>
#include <cxxabi.h>
#include <cstring>
#include <fcntl.h>
......@@ -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,
uint64_t file_offset, void *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;
}
......@@ -148,7 +147,7 @@ void ProcSyms::refresh() {
}
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);
auto it = std::find_if(
ps->modules_.begin(), ps->modules_.end(),
......@@ -162,7 +161,11 @@ int ProcSyms::_add_module(const char *modname, uint64_t start, uint64_t end,
else
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;
}
......@@ -275,21 +278,12 @@ void ProcSyms::Module::load_sym_table() {
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 {
for (const auto &range : ranges_)
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 false;
......@@ -401,13 +395,15 @@ void bcc_symcache_refresh(void *resolver) {
struct mod_st {
const char *name;
uint64_t start;
uint64_t file_offset;
};
static int _find_module(const char *modname, uint64_t start, uint64_t end, bool,
void *p) {
static int _find_module(const char *modname, uint64_t start, uint64_t end,
uint64_t offset, bool, void *p) {
struct mod_st *mod = (struct mod_st *)p;
if (!strcmp(modname, mod->name)) {
mod->start = start;
mod->file_offset = offset;
return -1;
}
return 0;
......@@ -420,7 +416,7 @@ int bcc_resolve_global_addr(int pid, const char *module, const uint64_t address,
mod.start == 0x0)
return -1;
*global = mod.start + address;
*global = mod.start + mod.file_offset + address;
return 0;
}
......
......@@ -92,10 +92,12 @@ class ProcSyms : SymbolCache {
struct Range {
uint64_t start;
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);
bool init();
......@@ -111,7 +113,6 @@ class ProcSyms : SymbolCache {
void load_sym_table();
void add_range(uint64_t st, uint64_t en);
bool contains(uint64_t addr, uint64_t &offset) const;
uint64_t start() const { return ranges_.begin()->start; }
......@@ -130,7 +131,8 @@ class ProcSyms : SymbolCache {
static int _add_load_sections(uint64_t v_addr, uint64_t mem_sz,
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_modules();
......
......@@ -207,7 +207,8 @@ class Context {
static void _each_probe(const char *binpath, const struct bcc_elf_usdt *probe,
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);
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,
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);
// 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
......
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