mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-12-23 12:03:41 +01:00
eh_elf: Implement step_cursor
This commit is contained in:
parent
7f70295713
commit
e0efd00acd
3 changed files with 85 additions and 9 deletions
13
src/eh_elf/context_struct.h
Normal file
13
src/eh_elf/context_struct.h
Normal 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);
|
|
@ -13,6 +13,10 @@
|
||||||
************************************************/
|
************************************************/
|
||||||
|
|
||||||
#include "eh_elf.h"
|
#include "eh_elf.h"
|
||||||
|
#include "context_struct.h"
|
||||||
|
#include "libunwind.h"
|
||||||
|
#include "memory_map.h"
|
||||||
|
#include "remote.h"
|
||||||
|
|
||||||
int eh_elf_init_local() {
|
int eh_elf_init_local() {
|
||||||
return mmap_init_local();
|
return mmap_init_local();
|
||||||
|
@ -26,7 +30,70 @@ void eh_elf_clear() {
|
||||||
mmap_clear();
|
mmap_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int eh_elf_step_cursor(struct cursor *cursor) {
|
static struct {
|
||||||
// TODO implement
|
unw_addr_space_t addr_space;
|
||||||
return 0;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,6 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include "libunwind_i.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
|
/** Initialize everything for local memory analysis
|
||||||
* @return 0 on success, or a negative value upon failure
|
* @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.
|
/** 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);
|
int eh_elf_step_cursor(struct cursor *cursor);
|
||||||
|
|
Loading…
Reference in a new issue