From bba251cf133764001410b2688c93053dbbe90706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophile=20Bastian?= Date: Sun, 9 Jun 2019 03:42:28 +0200 Subject: [PATCH] eh_elf: tolerate slightly out-of-bound mem access Recover from slightly out-of-bounds wrt. %rsp memory accesses. When we're unwinding the first frame of a chain, and we start from, eg. a `pop %rbx` at the end of the function, the DWARF can be out of sync and still state that eg. `%rbx` is saved at something that simplifies to `%rsp-8`. Which might not be accessibe through the `access_mem` abstraction, eg. if we're running perf and it didn't capture the stack below `%rsp` --- src/eh_elf/eh_elf.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/eh_elf/eh_elf.c b/src/eh_elf/eh_elf.c index 442ff54a..1c4e4087 100644 --- a/src/eh_elf/eh_elf.c +++ b/src/eh_elf/eh_elf.c @@ -39,6 +39,7 @@ void eh_elf_clear() { static struct { struct cursor* cursor; int last_rc; + uintptr_t cur_rsp; } _fetch_state; static uintptr_t fetchw_here(uintptr_t addr) { @@ -51,7 +52,24 @@ static uintptr_t fetchw_here(uintptr_t addr) { _fetch_state.cursor->dwarf.as_arg); if(rv != 0) { - Debug(1, "dwarf_get error %d\n", rv); + /* + Recover from slightly out-of-sync DWARF + ==== + + When we're unwinding the first frame of a chain, and we start from, + eg. a `pop %rbx` at the end of the function, the DWARF can be out + of sync and still state that eg. `%rbx` is saved at something that + simplifies to `%rsp-8`. Which might not be accessibe through the + `access_mem` abstraction, eg. if we're running perf and it didn't + capture the stack below `%rsp` + */ + if(_fetch_state.cur_rsp - addr < 128) { + Debug(3, "dwarf_get warning: tried to access %lX (%lX below rsp)\n", + addr, _fetch_state.cur_rsp - addr); + return 0; // hope that nothing bad will happen. + } + Debug(1, "dwarf_get error %d (addr %lX, sp %lX)\n", + rv, addr, _fetch_state.cur_rsp); _fetch_state.last_rc = rv; } @@ -112,6 +130,7 @@ int eh_elf_step_cursor(struct cursor *cursor) { // Set _fetch_state before passing fetchw_here _fetch_state.cursor = cursor; _fetch_state.last_rc = 0; + _fetch_state.cur_rsp = cursor->dwarf.cfa; Debug(4, "Unwinding in mmap entry %s at position 0x%lx (sp=%016lx)\n", mmap_entry->object_name,