Commit 1670d338 authored by Teng Qin's avatar Teng Qin

Allow BCC to parse vDSO symbols

parent a9e5f535
......@@ -16,6 +16,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
......@@ -26,21 +27,29 @@
#include <gelf.h>
#include "bcc_elf.h"
#include "bcc_proc.h"
#include "bcc_syms.h"
#define NT_STAPSDT 3
#define ELF_ST_TYPE(x) (((uint32_t) x) & 0xf)
static int openelf(const char *path, Elf **elf_out, int *fd_out) {
static int openelf_fd(int fd, Elf **elf_out) {
if (elf_version(EV_CURRENT) == EV_NONE)
return -1;
*elf_out = elf_begin(fd, ELF_C_READ, 0);
if (*elf_out == NULL)
return -1;
return 0;
}
static int openelf(const char *path, Elf **elf_out, int *fd_out) {
*fd_out = open(path, O_RDONLY);
if (*fd_out < 0)
return -1;
*elf_out = elf_begin(*fd_out, ELF_C_READ, 0);
if (*elf_out == 0) {
if (openelf_fd(*fd_out, elf_out) == -1) {
close(*fd_out);
return -1;
}
......@@ -532,6 +541,72 @@ int bcc_elf_is_shared_obj(const char *path) {
return bcc_elf_get_type(path) == ET_DYN;
}
int bcc_elf_is_vdso(const char *name) {
return strcmp(name, "[vdso]") == 0;
}
// -2: Failed
// -1: Not initialized
// >0: Initialized
static int vdso_image_fd = -1;
static int find_vdso(const char *name, uint64_t st, uint64_t en,
uint64_t offset, bool enter_ns, void *payload) {
int fd;
char tmpfile[128];
if (!bcc_elf_is_vdso(name))
return 0;
void *image = malloc(en - st);
if (!image)
goto on_error;
memcpy(image, (void *)st, en - st);
snprintf(tmpfile, sizeof(tmpfile), "/tmp/bcc_%d_vdso_image_XXXXXX", getpid());
fd = mkostemp(tmpfile, O_CLOEXEC);
if (fd < 0) {
fprintf(stderr, "Unable to create temp file: %s\n", strerror(errno));
goto on_error;
}
// Unlink the file to avoid leaking
if (unlink(tmpfile) == -1)
fprintf(stderr, "Unlink %s failed: %s\n", tmpfile, strerror(errno));
if (write(fd, image, en - st) == -1) {
fprintf(stderr, "Failed to write to vDSO image: %s\n", strerror(errno));
close(fd);
goto on_error;
}
vdso_image_fd = fd;
on_error:
if (image)
free(image);
// Always stop the iteration
return -1;
}
int bcc_elf_foreach_vdso_sym(bcc_elf_symcb callback, void *payload) {
Elf *elf;
static struct bcc_symbol_option default_option = {
.use_debug_file = 0,
.check_debug_file_crc = 0,
.use_symbol_type = (1 << STT_FUNC) | (1 << STT_GNU_IFUNC)
};
if (vdso_image_fd == -1) {
vdso_image_fd = -2;
bcc_procutils_each_module(getpid(), &find_vdso, NULL);
}
if (vdso_image_fd == -2)
return -1;
if (openelf_fd(vdso_image_fd, &elf) == -1)
return -1;
return listsymbols(elf, callback, payload, &default_option);
}
#if 0
#include <stdio.h>
......
......@@ -57,10 +57,14 @@ int bcc_elf_foreach_load_section(const char *path,
// Returns -1 on error, and 0 on success or stopped by callback
int bcc_elf_foreach_sym(const char *path, bcc_elf_symcb callback, void *option,
void *payload);
// Iterate over all symbols from current system's vDSO
// Returns -1 on error, and 0 on success or stopped by callback
int bcc_elf_foreach_vdso_sym(bcc_elf_symcb callback, void *payload);
int bcc_elf_get_type(const char *path);
int bcc_elf_is_shared_obj(const char *path);
int bcc_elf_is_exe(const char *path);
int bcc_elf_is_vdso(const char *name);
#ifdef __cplusplus
}
......
......@@ -79,8 +79,7 @@ int bcc_mapping_is_file_backed(const char *mapname) {
STARTS_WITH(mapname, "[stack") ||
STARTS_WITH(mapname, "/SYSV") ||
STARTS_WITH(mapname, "[heap]") ||
STARTS_WITH(mapname, "[vsyscall]") ||
STARTS_WITH(mapname, "[vdso]"));
STARTS_WITH(mapname, "[vsyscall]"));
}
int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback,
......
......@@ -23,6 +23,7 @@ extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
// Module name, start address, end address, file_offset,
// whether to check mount namespace, payload
......
......@@ -255,6 +255,11 @@ bool ProcSyms::Module::init() {
type_ = ModuleType::PERF_MAP;
return true;
}
if (bcc_elf_is_vdso(name_.c_str()) == 1) {
type_ = ModuleType::VDSO;
return true;
}
return false;
}
......@@ -278,6 +283,8 @@ void ProcSyms::Module::load_sym_table() {
bcc_perf_map_foreach_sym(name_.c_str(), _add_symbol, this);
if (type_ == ModuleType::EXEC || type_ == ModuleType::SO)
bcc_elf_foreach_sym(name_.c_str(), _add_symbol, symbol_option_, this);
if (type_ == ModuleType::VDSO)
bcc_elf_foreach_vdso_sym(_add_symbol, this);
std::sort(syms_.begin(), syms_.end());
}
......@@ -285,7 +292,7 @@ void ProcSyms::Module::load_sym_table() {
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)
offset = (type_ == ModuleType::SO || type_ == ModuleType::VDSO)
? (addr - range.start + range.file_offset)
: addr;
return true;
......
......@@ -85,7 +85,8 @@ class ProcSyms : SymbolCache {
UNKNOWN,
EXEC,
SO,
PERF_MAP
PERF_MAP,
VDSO
};
struct Module {
......
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