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:
parent
f00ec34b4e
commit
4595bb48fb
2 changed files with 29 additions and 13 deletions
|
@ -1,6 +1,6 @@
|
||||||
CXX=g++
|
CXX=g++
|
||||||
CXXLIBS=-ldl
|
CXXLIBS=-ldl
|
||||||
CXXFLAGS=-O0 -g -fPIC -Wall -Wextra
|
CXXFLAGS=-O2 -fPIC -Wall -Wextra
|
||||||
|
|
||||||
TARGET=libstack_walker.so
|
TARGET=libstack_walker.so
|
||||||
OBJS=stack_walker.o
|
OBJS=stack_walker.o
|
||||||
|
|
|
@ -45,10 +45,8 @@ std::string readlink_rec(const char* path) {
|
||||||
do {
|
do {
|
||||||
int rc = readlink(buf[parity], buf[1-parity], 1024);
|
int rc = readlink(buf[parity], buf[1-parity], 1024);
|
||||||
parity = 1 - parity;
|
parity = 1 - parity;
|
||||||
if(rc < 0) {
|
if(rc < 0)
|
||||||
if(errno == EINVAL)
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while(true);
|
} while(true);
|
||||||
|
|
||||||
return std::string(buf[1 - parity]);
|
return std::string(buf[1 - parity]);
|
||||||
|
@ -150,15 +148,14 @@ unwind_context_t get_context() {
|
||||||
out.rsp = uctx.uc_mcontext.gregs[REG_RSP];
|
out.rsp = uctx.uc_mcontext.gregs[REG_RSP];
|
||||||
out.rbp = uctx.uc_mcontext.gregs[REG_RBP];
|
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;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the `fde_func_t` function handling the given program counter — it may
|
MemoryMapEntry* get_mmap_entry(uintptr_t pc) {
|
||||||
* 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) {
|
|
||||||
// Get the memory_map entry
|
// Get the memory_map entry
|
||||||
auto mmap_entry_it = memory_map.lower_bound(pc);
|
auto mmap_entry_it = memory_map.lower_bound(pc);
|
||||||
if(mmap_entry_it == memory_map.end()) {
|
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))
|
if(!(mmap_entry.beg <= pc && pc <= mmap_entry.end))
|
||||||
return nullptr;
|
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
|
// Get the lookup function
|
||||||
_fde_func_t (*lookup)(uintptr_t) =
|
_fde_func_t (*lookup)(uintptr_t) =
|
||||||
(_fde_func_t (*)(uintptr_t)) (
|
(_fde_func_t (*)(uintptr_t)) (
|
||||||
dlsym(mmap_entry.eh_dl_handle, "_fde_lookup"));
|
dlsym(mmap_entry.eh_dl_handle, "_fde_lookup"));
|
||||||
|
|
||||||
|
if(lookup == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
// Get the translated pc
|
// Get the translated pc
|
||||||
uintptr_t tr_pc = pc - mmap_entry.beg;
|
uintptr_t tr_pc = pc - mmap_entry.beg;
|
||||||
|
|
||||||
// Get the actual function
|
// Get the actual function
|
||||||
_fde_func_t rfunc = lookup(tr_pc);
|
_fde_func_t rfunc = lookup(tr_pc);
|
||||||
|
|
||||||
|
if(rfunc == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
return rfunc;
|
return rfunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool unwind_context(unwind_context_t& ctx) {
|
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)
|
if(fde_func == nullptr)
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue