1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-12-23 03:53:43 +01:00

eh_elf: Implement step_cursor

This commit is contained in:
Théophile Bastian 2018-06-01 18:08:26 +02:00
parent 7f70295713
commit e0efd00acd
3 changed files with 85 additions and 9 deletions

View file

@ -0,0 +1,13 @@
#include <stdint.h>
typedef struct {
uintptr_t rip, rsp, rbp;
} unwind_context_t;
typedef uintptr_t (*deref_func_t)(uintptr_t);
typedef unwind_context_t (*_fde_func_t)(unwind_context_t, uintptr_t);
typedef unwind_context_t (*_fde_func_with_deref_t)(
unwind_context_t,
uintptr_t,
deref_func_t);

View file

@ -13,6 +13,10 @@
************************************************/
#include "eh_elf.h"
#include "context_struct.h"
#include "libunwind.h"
#include "memory_map.h"
#include "remote.h"
int eh_elf_init_local() {
return mmap_init_local();
@ -26,7 +30,70 @@ void eh_elf_clear() {
mmap_clear();
}
int eh_elf_step_cursor(struct cursor *cursor) {
// TODO implement
return 0;
static struct {
unw_addr_space_t addr_space;
unw_accessors_t *accessors;
void* arg;
} _fetch_state;
static uintptr_t fetchw_here(uintptr_t addr) {
uintptr_t out;
fetchw(_fetch_state.addr_space,
_fetch_state.accessors,
&addr,
&out,
_fetch_state.arg);
return out;
}
int eh_elf_step_cursor(struct cursor *cursor) {
uintptr_t ip = cursor->dwarf.ip;
// Retrieve memory map entry
mmap_entry_t* mmap_entry = mmap_get_entry(ip);
if(mmap_entry == NULL)
return -1;
// Retrieve a pointer to the eh_elf function
_fde_func_with_deref_t fde_func =
(_fde_func_t) (dlsym(mmap_entry->eh_elf, "_eh_elf"));
if(fde_func == NULL)
return -2;
// Setup an eh_elf context
unwind_context_t eh_elf_context;
eh_elf_context.rip = ip;
eh_elf_context.rsp = cursor->dwarf.loc[UNW_TDEP_SP].val;
eh_elf_context.rbp = cursor->dwarf.loc[UNW_TDEP_BP].val;
// Set _fetch_state before passing fetchw_here
_fetch_state.addr_space = cursor->dwarf.as;
_fetch_state.accessors = &cursor->dwarf.as->acc;
// Call fde_func
eh_elf_context = fde_func(
eh_elf_context,
ip - mmap_entry->offset,
fetchw_here);
// Check for the end of the call chain
if(eh_elf_context.rbp == 0 || eh_elf_context.rip + 1 == 0)
return 0;
// Push back the data into libunwind's structures
for (int i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
cursor->dwarf.loc[i] = DWARF_NULL_LOC;
cursor->dwarf.loc[UNW_TDEP_BP].val = eh_elf_context.rbp;
cursor->dwarf.loc[UNW_TDEP_SP].val = eh_elf_context.rsp;
cursor->dwarf.loc[UNW_TDEP_IP].val = eh_elf_context.rip;
cursor->dwarf.use_prev_instr = 1;
cursor->frame_info.frame_type = UNW_X86_64_FRAME_GUESSED;
cursor->frame_info.cfa_reg_rsp = 0;
cursor->frame_info.cfa_reg_offset = 16;
cursor->frame_info.rbp_cfa_offset = -16;
cursor->dwarf.cfa += 16;
return 1;
}

View file

@ -17,11 +17,6 @@
#include <sys/types.h>
#include "libunwind_i.h"
/// Store the necessary data for a single eh_elf
typedef struct {
// TODO
} eh_elf_handle_t;
/** Initialize everything for local memory analysis
* @return 0 on success, or a negative value upon failure
**/
@ -37,6 +32,7 @@ void eh_elf_clear();
/** Step the cursor using eh_elf mechanisms.
*
* Return 0 if everything went fine, otherwise, return a negative value.
* @return a positive value upon success, 0 if the frame before this unwinding
* was the last one, or a negative value upon failure.
**/
int eh_elf_step_cursor(struct cursor *cursor);