StackWalker: multiple fixes

Includes adding a few failsafe guards, translating the instruction
pointer before handing it to the eh_elf.so, a few cosmetic changes, ...
This commit is contained in:
Théophile Bastian 2018-04-27 17:31:53 +02:00
parent f00ec34b4e
commit 4595bb48fb
2 changed files with 29 additions and 13 deletions

View file

@ -1,6 +1,6 @@
CXX=g++
CXXLIBS=-ldl
CXXFLAGS=-O0 -g -fPIC -Wall -Wextra
CXXFLAGS=-O2 -fPIC -Wall -Wextra
TARGET=libstack_walker.so
OBJS=stack_walker.o

View file

@ -45,10 +45,8 @@ std::string readlink_rec(const char* path) {
do {
int rc = readlink(buf[parity], buf[1-parity], 1024);
parity = 1 - parity;
if(rc < 0) {
if(errno == EINVAL)
break;
}
if(rc < 0)
break;
} while(true);
return std::string(buf[1 - parity]);
@ -150,15 +148,14 @@ unwind_context_t get_context() {
out.rsp = uctx.uc_mcontext.gregs[REG_RSP];
out.rbp = uctx.uc_mcontext.gregs[REG_RBP];
unwind_context(out);
if(!unwind_context(out)) {
memset(&out, 0, sizeof(unwind_context_t));
return out;
}
return out;
}
/** Get the `fde_func_t` function handling the given program counter — it may
* be by calling a lookup function, or by directly looking into the ELF
* symbols, depending on the state of the experiment. This is an abstraction
* function. */
_fde_func_t fde_handler_for_pc(uintptr_t pc) {
MemoryMapEntry* get_mmap_entry(uintptr_t pc) {
// Get the memory_map entry
auto mmap_entry_it = memory_map.lower_bound(pc);
if(mmap_entry_it == memory_map.end()) {
@ -168,26 +165,45 @@ _fde_func_t fde_handler_for_pc(uintptr_t pc) {
if(!(mmap_entry.beg <= pc && pc <= mmap_entry.end))
return nullptr;
return &mmap_entry;
}
/** Get the `fde_func_t` function handling the given program counter — it may
* be by calling a lookup function, or by directly looking into the ELF
* symbols, depending on the state of the experiment. This is an abstraction
* function. */
_fde_func_t fde_handler_for_pc(uintptr_t pc, MemoryMapEntry& mmap_entry) {
// Get the lookup function
_fde_func_t (*lookup)(uintptr_t) =
(_fde_func_t (*)(uintptr_t)) (
dlsym(mmap_entry.eh_dl_handle, "_fde_lookup"));
if(lookup == nullptr)
return nullptr;
// Get the translated pc
uintptr_t tr_pc = pc - mmap_entry.beg;
// Get the actual function
_fde_func_t rfunc = lookup(tr_pc);
if(rfunc == nullptr)
return nullptr;
return rfunc;
}
bool unwind_context(unwind_context_t& ctx) {
_fde_func_t fde_func = fde_handler_for_pc(ctx.rip);
MemoryMapEntry* mmap_entry = get_mmap_entry(ctx.rip);
if(mmap_entry == nullptr)
return false;
_fde_func_t fde_func = fde_handler_for_pc(ctx.rip, *mmap_entry);
if(fde_func == nullptr)
return false;
ctx = fde_func(ctx, ctx.rip);
uintptr_t tr_pc = ctx.rip - mmap_entry->beg;
ctx = fde_func(ctx, tr_pc);
return true;
}