Commit 54a5b4d1 authored by yonghong-song's avatar yonghong-song Committed by GitHub

Merge pull request #1382 from palmtenor/vdso

Support resolve vDSO symbols
parents 5b08d385 1670d338
......@@ -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,51 +79,42 @@ 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,
void *payload) {
char procmap_filename[128];
FILE *procmap;
int ret;
snprintf(procmap_filename, sizeof(procmap_filename), "/proc/%ld/maps",
(long)pid);
procmap = fopen(procmap_filename, "r");
if (!procmap)
return -1;
do {
char endline[4096];
char perm[8], dev[8];
long long begin, end, offset, inode;
ret = fscanf(procmap, "%llx-%llx %s %llx %s %lld", &begin, &end, perm,
&offset, dev, &inode);
if (!fgets(endline, sizeof(endline), procmap))
char buf[PATH_MAX + 1], perm[5], dev[8];
char *name;
uint64_t begin, end, inode;
unsigned long long offset;
while (true) {
buf[0] = '\0';
// From fs/proc/task_mmu.c:show_map_vma
if (fscanf(procmap, "%lx-%lx %s %llx %s %lu%[^\n]", &begin, &end, perm,
&offset, dev, &inode, buf) != 7)
break;
if (ret == 6) {
char *mapname = endline;
char *newline = strchr(endline, '\n');
if (newline)
newline[0] = '\0';
if (perm[2] != 'x')
continue;
while (isspace(mapname[0]))
mapname++;
name = buf;
while (isspace(*name))
name++;
if (!bcc_mapping_is_file_backed(name))
continue;
if (strchr(perm, 'x') && bcc_mapping_is_file_backed(mapname)) {
if (callback(mapname, (uint64_t)begin, (uint64_t)end, (uint64_t)offset,
true, payload) < 0)
break;
}
}
} while (ret && ret != EOF);
if (callback(name, begin, end, (uint64_t)offset, true, payload) < 0)
break;
}
fclose(procmap);
......
......@@ -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