Skip to content

Commit

Permalink
Merge pull request iovisor#1358 from palmtenor/load_exe
Browse files Browse the repository at this point in the history
Use ELF load sections in address -> symbol resolution
  • Loading branch information
yonghong-song committed Sep 26, 2017
2 parents 649e7f0 + 5db9d37 commit 0daa912
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 15 deletions.
46 changes: 42 additions & 4 deletions src/cc/bcc_syms.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

#include <algorithm>
#include <cxxabi.h>
#include <cstring>
#include <fcntl.h>
Expand All @@ -28,9 +29,10 @@
#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"

ino_t ProcStat::getinode_() {
struct stat s;
Expand Down Expand Up @@ -109,8 +111,33 @@ ProcSyms::ProcSyms(int pid, struct bcc_symbol_option *option)
load_modules();
}

bool ProcSyms::load_modules() {
return bcc_procutils_each_module(pid_, _add_module, this) == 0;
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);
return 0;
}

void ProcSyms::load_exe() {
std::string exe = ebpf::get_pid_exe(pid_);
Module module(exe.c_str(), mount_ns_instance_.get(), &symbol_option_);

if (!module.init())
return;
if (module.type_ != ModuleType::EXEC)
return;

ProcMountNSGuard g(mount_ns_instance_.get());

bcc_elf_foreach_load_section(exe.c_str(), &_add_load_sections, &module);

if (!module.ranges_.empty())
modules_.emplace_back(std::move(module));
}

void ProcSyms::load_modules() {
load_exe();
bcc_procutils_each_module(pid_, _add_module, this);
}

void ProcSyms::refresh() {
Expand All @@ -135,7 +162,7 @@ int ProcSyms::_add_module(const char *modname, uint64_t start, uint64_t end,
else
return 0;
}
it->ranges_.emplace_back(start, end);
it->add_range(start, end);

return 0;
}
Expand Down Expand Up @@ -248,6 +275,17 @@ 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) {
Expand Down
13 changes: 13 additions & 0 deletions src/cc/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <sstream>

#include "common.h"
#include "vendor/tinyformat.hpp"

namespace ebpf {

Expand Down Expand Up @@ -48,4 +49,16 @@ std::vector<int> get_possible_cpus() {
return read_cpu_range("/sys/devices/system/cpu/possible");
}

std::string get_pid_exe(pid_t pid) {
char exe_path[4096];
int res;

std::string exe_link = tfm::format("/proc/%d/exe", pid);
res = readlink(exe_link.c_str(), exe_path, sizeof(exe_path));
if (res == -1)
return "";
exe_path[res] = '\0';
return std::string(exe_path);
}

} // namespace ebpf
4 changes: 4 additions & 0 deletions src/cc/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#pragma once

#include <memory>
#include <string>
#include <unistd.h>
#include <vector>

namespace ebpf {
Expand All @@ -31,4 +33,6 @@ std::vector<int> get_online_cpus();

std::vector<int> get_possible_cpus();

std::string get_pid_exe(pid_t pid);

} // namespace ebpf
8 changes: 7 additions & 1 deletion src/cc/syms.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,11 @@ class ProcSyms : SymbolCache {
std::vector<Symbol> syms_;

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; }

bool find_addr(uint64_t offset, struct bcc_symbol *sym);
bool find_name(const char *symname, uint64_t *addr);

Expand All @@ -125,8 +128,11 @@ class ProcSyms : SymbolCache {
std::unique_ptr<ProcMountNS> mount_ns_instance_;
bcc_symbol_option symbol_option_;

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 *);
bool load_modules();
void load_exe();
void load_modules();

public:
ProcSyms(int pid, struct bcc_symbol_option *option = nullptr);
Expand Down
13 changes: 3 additions & 10 deletions src/cc/usdt/usdt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "bcc_elf.h"
#include "bcc_proc.h"
#include "common.h"
#include "usdt.h"
#include "vendor/tinyformat.hpp"
#include "bcc_usdt.h"
Expand Down Expand Up @@ -314,17 +315,9 @@ Context::Context(const std::string &bin_path)
Context::Context(int pid) : pid_(pid), pid_stat_(pid),
mount_ns_instance_(new ProcMountNS(pid)), loaded_(false) {
if (bcc_procutils_each_module(pid, _each_module, this) == 0) {
// get exe command from /proc/<pid>/exe
// assume the maximum path length 4096, which should be
// sufficiently large to cover all use cases
char source[64];
char cmd_buf[4096];
snprintf(source, sizeof(source), "/proc/%d/exe", pid);
ssize_t cmd_len = readlink(source, cmd_buf, sizeof(cmd_buf) - 1);
if (cmd_len == -1)
cmd_bin_path_ = ebpf::get_pid_exe(pid);
if (cmd_bin_path_.empty())
return;
cmd_buf[cmd_len] = '\0';
cmd_bin_path_.assign(cmd_buf, cmd_len + 1);

loaded_ = true;
}
Expand Down

0 comments on commit 0daa912

Please sign in to comment.