1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2025-01-10 19:23:41 +01:00

Switch over to DWARF-based unwinder.

(Logical change 1.146)
This commit is contained in:
hp.com!davidm 2003-12-20 11:50:00 +00:00
parent 9fdd520e59
commit 468aaccf17
17 changed files with 806 additions and 335 deletions

View file

@ -45,7 +45,7 @@ extern "C" {
want to err on making it rather too big than too small. */
#define UNW_TDEP_CURSOR_LEN 127
typedef uint32_t unw_tdep_word_t;
typedef uint32_t unw_word_t;
typedef long double unw_tdep_fpreg_t;
@ -54,26 +54,91 @@ typedef enum
/* Note: general registers are expected to start with index 0.
This convention facilitates architecture-independent
implementation of the C++ exception handling ABI. See
_Unwind_SetGR() and _Unwind_GetGR() for details. */
UNW_X86_EAX,
UNW_X86_EBX,
UNW_X86_ECX,
UNW_X86_EDX,
UNW_X86_ESI,
UNW_X86_EDI,
UNW_X86_EBP,
UNW_X86_EIP,
UNW_X86_ESP,
_Unwind_SetGR() and _Unwind_GetGR() for details.
UNW_TDEP_LAST_REG = UNW_X86_ESP,
The described register usage convention is based on "System V
Application Binary Interface, Intel386 Architecture Processor
Supplement, Fourth Edition" at
http://www.linuxbase.org/spec/refspecs/elf/abi386-4.pdf
It would have been nice to use the same register numbering as
DWARF, but that doesn't work because the libunwind requires
that the exception argument registers be consecutive, which the
wouldn't be with the DWARF numbering. */
UNW_X86_EAX, /* scratch (exception argument 1) */
UNW_X86_EDX, /* scratch (exception argument 2) */
UNW_X86_ECX, /* preserved */
UNW_X86_EBX, /* preserved */
UNW_X86_ESI, /* preserved */
UNW_X86_EDI, /* preserved */
UNW_X86_EBP, /* (optional) frame-register */
UNW_X86_ESP, /* (optional) frame-register */
UNW_X86_EIP, /* frame-register */
UNW_X86_EFLAGS, /* scratch (except for "direction", which is fixed */
UNW_X86_TRAPNO, /* scratch */
/* MMX/stacked-fp registers */
UNW_X86_ST0, /* fp return value */
UNW_X86_ST1, /* scratch */
UNW_X86_ST2, /* scratch */
UNW_X86_ST3, /* scratch */
UNW_X86_ST4, /* scratch */
UNW_X86_ST5, /* scratch */
UNW_X86_ST6, /* scratch */
UNW_X86_ST7, /* scratch */
UNW_X86_FCW, /* scratch */
UNW_X86_FSW, /* scratch */
UNW_X86_FTW, /* scratch */
UNW_X86_FOP, /* scratch */
UNW_X86_FCS, /* scratch */
UNW_X86_FIP, /* scratch */
UNW_X86_FEA, /* scratch */
UNW_X86_FDS, /* scratch */
/* SSE registers */
UNW_X86_XMM0_lo, /* scratch */
UNW_X86_XMM0_hi, /* scratch */
UNW_X86_XMM1_lo, /* scratch */
UNW_X86_XMM1_hi, /* scratch */
UNW_X86_XMM2_lo, /* scratch */
UNW_X86_XMM2_hi, /* scratch */
UNW_X86_XMM3_lo, /* scratch */
UNW_X86_XMM3_hi, /* scratch */
UNW_X86_XMM4_lo, /* scratch */
UNW_X86_XMM4_hi, /* scratch */
UNW_X86_XMM5_lo, /* scratch */
UNW_X86_XMM5_hi, /* scratch */
UNW_X86_XMM6_lo, /* scratch */
UNW_X86_XMM6_hi, /* scratch */
UNW_X86_XMM7_lo, /* scratch */
UNW_X86_XMM7_hi, /* scratch */
UNW_X86_MXCSR, /* scratch */
/* segment registers */
UNW_X86_GS, /* special */
UNW_X86_FS, /* special */
UNW_X86_ES, /* special */
UNW_X86_DS, /* special */
UNW_X86_SS, /* special */
UNW_X86_CS, /* special */
UNW_X86_TSS, /* special */
UNW_X86_LDT, /* special */
/* frame info (read-only) */
UNW_X86_CFA,
UNW_TDEP_LAST_REG = UNW_X86_LDT,
UNW_TDEP_IP = UNW_X86_EIP,
UNW_TDEP_SP = UNW_X86_ESP,
UNW_TDEP_SP = UNW_X86_CFA,
UNW_TDEP_EH = UNW_X86_EAX
}
x86_regnum_t;
#define UNW_TDEP_NUM_EH_REGS 2 /* eax and ebx are exception args */
#define UNW_TDEP_NUM_EH_REGS 2 /* eax and edx are exception args */
typedef struct unw_tdep_save_loc
{
@ -93,6 +158,14 @@ typedef ucontext_t unw_tdep_context_t;
/* XXX fixme: */
#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_X86_FR) < 128)
#include "libunwind-dynamic.h"
typedef struct
{
unw_dyn_dwarf_fde_info_t dwarf_info;
}
unw_tdep_proc_info_t;
#include "libunwind-common.h"
#if defined(__cplusplus) || defined(c_plusplus)

View file

@ -1,5 +1,5 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2002 Hewlett-Packard Co
Copyright (C) 2002-2003 Hewlett-Packard Co
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of libunwind.
@ -33,19 +33,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include <libunwind.h>
#include "elf32.h"
enum x86_pregnum
{
X86_NUM_PREGS
};
struct x86_loc
{
unw_word_t val;
#ifndef UNW_LOCAL_ONLY
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
#endif
};
#include "dwarf.h"
struct unw_addr_space
{
@ -58,24 +46,118 @@ struct unw_addr_space
struct cursor
{
unw_addr_space_t as;
void *as_arg;
/* IP & SP cache: */
unw_word_t eip;
unw_word_t esp;
struct x86_loc eip_loc;
struct x86_loc ebp_loc;
struct dwarf_cursor dwarf; /* must be first */
};
#define DWARF_GET_LOC(l) ((l).val)
#ifdef UNW_LOCAL_ONLY
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
tdep_uc_addr((c)->as_arg, (r)), 0))
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
tdep_uc_addr((c)->as_arg, (r)), 0))
static inline int
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*val = *(unw_fpreg_t *) DWARF_GET_LOC (loc);
return 0;
}
static inline int
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*(unw_fpreg_t *) DWARF_GET_LOC (loc) = *val;
return 0;
}
static inline int
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*val = *(unw_word_t *) DWARF_GET_LOC (loc);
return 0;
}
static inline int
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*(unw_word_t *) DWARF_GET_LOC (loc) = val;
return 0;
}
#else /* !UNW_LOCAL_ONLY */
# define DWARF_LOC_TYPE_FP (1 << 0)
# define DWARF_LOC_TYPE_REG (1 << 1)
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
# define DWARF_IS_NULL_LOC(l) \
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
| DWARF_LOC_TYPE_FP))
static inline int
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
{
abort ();
}
static inline int
dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
{
abort ();
}
static inline int
dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
{
if (DWARF_IS_FP_LOC (loc))
abort ();
if (DWARF_IS_REG_LOC (loc))
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
0, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
0, c->as_arg);
}
static inline int
dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
{
if (DWARF_IS_FP_LOC (loc))
abort ();
if (DWARF_IS_REG_LOC (loc))
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
1, c->as_arg);
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
1, c->as_arg);
}
#endif /* !UNW_LOCAL_ONLY */
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
tdep_search_unwind_table. */
#define tdep_search_unwind_table(a,b,c,d,e,f) \
UNW_ARCH_OBJ(search_unwind_table) (a,b,c,d,e,f)
#define tdep_find_proc_info(as,ip,pi,n,a) \
UNW_ARCH_OBJ(find_proc_info) (as,ip,pi,n,a)
#define tdep_put_unwind_info(a,b,c) UNW_ARCH_OBJ(put_unwind_info)(a,b,c)
#define tdep_search_unwind_table dwarf_search_unwind_table
#define tdep_find_proc_info dwarf_find_proc_info
#define tdep_put_unwind_info dwarf_put_unwind_info
#define tdep_uc_addr(uc,reg) UNW_ARCH_OBJ(uc_addr)(uc,reg)
#define tdep_get_elf_image(a,b,c,d,e) UNW_ARCH_OBJ(get_elf_image) (a, b, c, \
d, e)
@ -84,9 +166,6 @@ struct cursor
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
unw_dyn_info_t *di, unw_proc_info_t *pi,
int need_unwind_info, void *arg);
extern int tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip,
unw_proc_info_t *pi, int need_unwind_info,
void *arg);
extern void tdep_put_unwind_info (unw_addr_space_t as,
unw_proc_info_t *pi, void *arg);
extern void *tdep_uc_addr (ucontext_t *uc, int reg);

View file

@ -1,5 +1,5 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2002 Hewlett-Packard Co
Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of libunwind.
@ -29,17 +29,17 @@ int
unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
{
struct cursor *c = (struct cursor *) cursor;
#if 0
int ret;
#endif
memset (pi, 0, sizeof (*pi));
pi->start_ip = c->eip;
pi->end_ip = c->eip + 1;
#if 0
if ((ret = ia64_make_proc_info (c)) < 0)
return ret;
#endif
if (dwarf_make_proc_info (&c->dwarf) < 0)
{
/* On x86, it's relatively common to be missing DWARF unwind
info. We don't want to fail in that case, because the
frame-chain still would let us do a backtrace at least. */
memset (pi, 0, sizeof (*pi));
pi->start_ip = c->dwarf.ip;
pi->end_ip = c->dwarf.ip + 1;
return 0;
}
*pi = c->dwarf.pi;
return 0;
}

View file

@ -31,5 +31,6 @@ unw_get_proc_name (unw_cursor_t *cursor, char *buf, size_t buf_len,
{
struct cursor *c = (struct cursor *) cursor;
return unwi_get_proc_name (c->as, c->eip, buf, buf_len, offp, c->as_arg);
return unwi_get_proc_name (c->dwarf.as, c->dwarf.ip, buf, buf_len,
offp, c->dwarf.as_arg);
}

View file

@ -99,13 +99,13 @@ access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
{
if (write)
{
debug (100, "%s: mem[%x] <- %x\n", __FUNCTION__, addr, *val);
Debug (16, "mem[%x] <- %x\n", addr, *val);
*(unw_word_t *) addr = *val;
}
else
{
*val = *(unw_word_t *) addr;
debug (100, "%s: mem[%x] -> %x\n", __FUNCTION__, addr, *val);
Debug (16, "mem[%x] -> %x\n", addr, *val);
}
return 0;
}
@ -129,17 +129,17 @@ access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
if (write)
{
*(unw_word_t *) addr = *val;
debug (100, "%s: %s <- %x\n", __FUNCTION__, unw_regname (reg), *val);
Debug (12, "%s <- %x\n", unw_regname (reg), *val);
}
else
{
*val = *(unw_word_t *) addr;
debug (100, "%s: %s -> %x\n", __FUNCTION__, unw_regname (reg), *val);
Debug (12, "%s -> %x\n", unw_regname (reg), *val);
}
return 0;
badreg:
debug (1, "%s: bad register number %u\n", __FUNCTION__, reg);
Debug (1, "bad register number %u\n", reg);
return -UNW_EBADREG;
}
@ -163,20 +163,20 @@ access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
if (write)
{
debug (100, "%s: %s <- %016lx.%016lx\n", __FUNCTION__,
Debug (12, "%s <- %016lx.%016lx\n",
unw_regname (reg), val->raw.bits[1], val->raw.bits[0]);
*(unw_fpreg_t *) addr = *val;
}
else
{
*val = *(unw_fpreg_t *) addr;
debug (100, "%s: %s -> %016lx.%016lx\n", __FUNCTION__,
Debug (12, "%s -> %016lx.%016lx\n",
unw_regname (reg), val->raw.bits[1], val->raw.bits[0]);
}
return 0;
badreg:
debug (1, "%s: bad register number %u\n", __FUNCTION__, reg);
Debug (1, "bad register number %u\n", reg);
/* attempt to access a non-preserved register */
return -UNW_EBADREG;
#endif
@ -195,7 +195,7 @@ x86_local_addr_space_init (void)
{
memset (&local_addr_space, 0, sizeof (local_addr_space));
local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
local_addr_space.acc.find_proc_info = UNW_ARCH_OBJ (find_proc_info);
local_addr_space.acc.find_proc_info = tdep_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
local_addr_space.acc.access_mem = access_mem;

View file

@ -0,0 +1,52 @@
/* libunwind - a platform-independent unwind library
Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of libunwind.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
#include "init.h"
#ifdef UNW_REMOTE_ONLY
int
unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
{
return -UNW_EINVAL;
}
#else /* !UNW_REMOTE_ONLY */
int
unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
{
struct cursor *c = (struct cursor *) cursor;
if (x86_needs_initialization)
x86_init ();
c->dwarf.as = unw_local_addr_space;
c->dwarf.as_arg = uc;
return common_init (c);
}
#endif /* !UNW_REMOTE_ONLY */

View file

@ -1,5 +1,5 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2003 Hewlett-Packard Co
Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of libunwind.
@ -35,13 +35,10 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
struct cursor *c = (struct cursor *) cursor;
if (x86_needs_initialization)
{
x86_needs_initialization = 0;
x86_init ();
}
x86_init ();
c->as = as;
c->as_arg = as_arg;
c->dwarf.as = as;
c->dwarf.as_arg = as_arg;
return common_init (c);
#endif /* !UNW_LOCAL_ONLY */
}

View file

@ -30,10 +30,16 @@ unw_is_signal_frame (unw_cursor_t *cursor)
{
#ifdef __linux__
struct cursor *c = (struct cursor *) cursor;
unw_accessors_t *a = unw_get_accessors (c->as);
unw_word_t w0, w1;
unw_word_t w0, w1, ip;
unw_addr_space_t as;
unw_accessors_t *a;
void *arg;
int ret;
as = c->dwarf.as;
a = unw_get_accessors (as);
arg = c->dwarf.as_arg;
/* Check if EIP points at sigreturn() sequence. On Linux, this is:
__restore:
@ -50,11 +56,14 @@ unw_is_signal_frame (unw_cursor_t *cursor)
if SA_SIGINFO is specified.
*/
if ((ret = (*a->access_mem) (c->as, c->eip, &w0, 0, c->as_arg)) < 0
|| (ret = (*a->access_mem) (c->as, c->eip + 4, &w1, 0, c->as_arg)) < 0)
ip = c->dwarf.ip;
if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
|| (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0)
return ret;
return (w0 == 0x0077b858 && w1 == 0x80cd0000)
|| (w0 == 0x0000adb8 && w1 == 0x9080cd00);
ret = ((w0 == 0x0077b858 && w1 == 0x80cd0000)
|| (w0 == 0x0000adb8 && w1 == 0x9080cd00));
Debug (16, "returning %d\n", ret);
return ret;
#else
printf ("%s: implement me\n", __FUNCTION__);
#endif

View file

@ -1,5 +1,5 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2002 Hewlett-Packard Co
Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of libunwind.
@ -29,29 +29,98 @@ HIDDEN int
x86_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
int write)
{
struct x86_loc loc = X86_LOC (0, 0);
struct dwarf_loc loc = DWARF_LOC (0, 0);
switch (reg)
{
case UNW_X86_EIP:
if (write)
c->eip = *valp; /* also update the EIP cache */
loc = c->eip_loc;
c->dwarf.ip = *valp; /* also update the EIP cache */
loc = c->dwarf.loc[EIP];
break;
case UNW_X86_ESP:
case UNW_X86_CFA:
if (write)
return -UNW_EREADONLYREG;
*valp = c->esp;
*valp = c->dwarf.cfa;
return 0;
case UNW_X86_EAX: loc = c->dwarf.loc[EAX]; break;
case UNW_X86_EBX: loc = c->dwarf.loc[EBX]; break;
case UNW_X86_ECX: loc = c->dwarf.loc[ECX]; break;
case UNW_X86_EDX: loc = c->dwarf.loc[EDX]; break;
case UNW_X86_ESI: loc = c->dwarf.loc[ESI]; break;
case UNW_X86_EDI: loc = c->dwarf.loc[EDI]; break;
case UNW_X86_EBP: loc = c->dwarf.loc[EBP]; break;
case UNW_X86_ESP: loc = c->dwarf.loc[ESP]; break;
#if 0
UNW_X86_EFLAGS
UNW_X86_TRAPNO
UNW_X86_FCW
UNW_X86_FSW
UNW_X86_FTW
UNW_X86_FOP
UNW_X86_FCS
UNW_X86_FIP
UNW_X86_FEA
UNW_X86_FDS
UNW_X86_MXCSR
UNW_X86_GS
UNW_X86_FS
UNW_X86_ES
UNW_X86_DS
UNW_X86_SS
UNW_X86_CS
UNW_X86_TSS
UNW_X86_LDT
#endif
default:
debug (1, "%s: bad register number %u\n", __FUNCTION__, reg);
Debug (1, "bad register number %u\n", reg);
return -UNW_EBADREG;
}
if (write)
return x86_put (c, loc, *valp);
return dwarf_put (&c->dwarf, loc, *valp);
else
return x86_get (c, loc, valp);
return dwarf_get (&c->dwarf, loc, valp);
}
HIDDEN int
x86_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
int write)
{
#if 0
/* MMX/stacked-fp registers */
UNW_X86_ST0, /* fp return value */
UNW_X86_ST1, /* scratch */
UNW_X86_ST2, /* scratch */
UNW_X86_ST3, /* scratch */
UNW_X86_ST4, /* scratch */
UNW_X86_ST5, /* scratch */
UNW_X86_ST6, /* scratch */
UNW_X86_ST7, /* scratch */
UNW_X86_XMM0_lo, /* scratch */
UNW_X86_XMM0_hi, /* scratch */
UNW_X86_XMM1_lo, /* scratch */
UNW_X86_XMM1_hi, /* scratch */
UNW_X86_XMM2_lo, /* scratch */
UNW_X86_XMM2_hi, /* scratch */
UNW_X86_XMM3_lo, /* scratch */
UNW_X86_XMM3_hi, /* scratch */
UNW_X86_XMM4_lo, /* scratch */
UNW_X86_XMM4_hi, /* scratch */
UNW_X86_XMM5_lo, /* scratch */
UNW_X86_XMM5_hi, /* scratch */
UNW_X86_XMM6_lo, /* scratch */
UNW_X86_XMM6_hi, /* scratch */
UNW_X86_XMM7_lo, /* scratch */
UNW_X86_XMM7_hi, /* scratch */
#endif
return -UNW_EINVAL;
}

View file

@ -0,0 +1,132 @@
/* libunwind - a platform-independent unwind library
Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of libunwind.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include <stdlib.h>
#include "unwind_i.h"
#ifndef UNW_REMOTE_ONLY
HIDDEN inline int
x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
{
#if 1
printf ("%s: implement me\n", __FUNCTION__);
return -UNW_EINVAL;
#else
struct cursor *c = (struct cursor *) cursor;
unw_fpreg_t fpval;
ucontext_t *uc = arg;
unw_word_t val, sol;
int i, ret;
# define SET_NAT(n) \
do \
{ \
ret = x86_access_reg (c, UNW_X86_NAT + (n), &val, 0); \
if (ret < 0) \
return ret; \
if (val) \
uc->uc_mcontext.sc_nat |= (unw_word_t) 1 << n; \
} \
while (0)
# define SET_REG(f, r) \
do \
{ \
ret = x86_get (c, c->r, &val); \
if (ret < 0) \
return ret; \
uc->uc_mcontext.f = val; \
} \
while (0)
# define SET_FPREG(f, r) \
do \
{ \
ret = x86_getfp (c, c->r, &fpval); \
if (ret < 0) \
return ret; \
uc->uc_mcontext.f.u.bits[0] = fpval.raw.bits[0]; \
uc->uc_mcontext.f.u.bits[1] = fpval.raw.bits[1]; \
} \
while (0)
/* ensure c->pi is up-to-date: */
if ((ret = x86_make_proc_info (c)) < 0)
return ret;
SET_REG (sc_ar_pfs, pfs_loc);
SET_REG (sc_br[0], ip_loc);
SET_REG (sc_pr, pr_loc);
SET_REG (sc_ar_rnat, rnat_loc);
SET_REG (sc_ar_lc, lc_loc);
SET_REG (sc_ar_fpsr, fpsr_loc);
SET_REG (sc_gr[4], r4_loc); SET_REG(sc_gr[5], r5_loc);
SET_REG (sc_gr[6], r6_loc); SET_REG(sc_gr[7], r7_loc);
uc->uc_mcontext.sc_nat = 0;
SET_NAT (4); SET_NAT(5);
SET_NAT (6); SET_NAT(7);
SET_REG (sc_br[1], b1_loc);
SET_REG (sc_br[2], b2_loc);
SET_REG (sc_br[3], b3_loc);
SET_REG (sc_br[4], b4_loc);
SET_REG (sc_br[5], b5_loc);
SET_FPREG (sc_fr[2], f2_loc);
SET_FPREG (sc_fr[3], f3_loc);
SET_FPREG (sc_fr[4], f4_loc);
SET_FPREG (sc_fr[5], f5_loc);
for (i = 16; i < 32; ++i)
SET_FPREG (sc_fr[i], fr_loc[i - 16]);
if (c->is_signal_frame)
abort (); /* XXX this needs to be fixed... */
/* Account for the fact that __x86_install_context() returns via
br.ret, which will decrement bsp by size-of-locals. */
sol = (uc->uc_mcontext.sc_ar_pfs >> 7) & 0x7f;
uc->uc_mcontext.sc_ar_bsp = x86_rse_skip_regs (c->bsp, sol);
uc->uc_mcontext.sc_flags = 0;
uc->uc_mcontext.sc_gr[1] = c->pi.gp;
uc->uc_mcontext.sc_gr[12] = c->psp;
__x86_install_context (uc, c->eh_args[0], c->eh_args[1], c->eh_args[2],
c->eh_args[3]);
#endif
}
#endif /* !UNW_REMOTE_ONLY */
int
unw_resume (unw_cursor_t *cursor)
{
struct cursor *c = (struct cursor *) cursor;
#ifdef UNW_LOCAL_ONLY
return x86_local_resume (c->dwarf.as, cursor, c->dwarf.as_arg);
#else
return (*c->dwarf.as->acc.resume) (c->dwarf.as, cursor, c->dwarf.as_arg);
#endif
}

View file

@ -26,161 +26,100 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
#include "offsets.h"
static inline int
update_frame_state (struct cursor *c)
{
#if 0
unw_word_t prev_ip, prev_sp, prev_bsp, ip, pr, num_regs, cfm;
int ret;
prev_ip = c->ip;
prev_sp = c->sp;
prev_bsp = c->bsp;
c->cfm_loc = c->pfs_loc;
num_regs = 0;
if (c->is_signal_frame)
{
ret = ia64_get (c, c->sp + 0x10 + SIGFRAME_ARG2_OFF, &c->sigcontext_loc);
debug (100, "%s: sigcontext_loc=%lx (ret=%d)\n",
__FUNCTION__, c->sigcontext_loc, ret);
if (ret < 0)
return ret;
if (c->ip_loc == c->sigcontext_loc + SIGCONTEXT_BR_OFF + 0*8)
{
/* Earlier kernels (before 2.4.19 and 2.5.10) had buggy
unwind info for sigtramp. Fix it up here. */
c->ip_loc = (c->sigcontext_loc + SIGCONTEXT_IP_OFF);
c->cfm_loc = (c->sigcontext_loc + SIGCONTEXT_CFM_OFF);
}
/* do what can't be described by unwind directives: */
c->pfs_loc = (c->sigcontext_loc + SIGCONTEXT_AR_PFS_OFF);
ret = ia64_get (c, c->cfm_loc, &cfm);
if (ret < 0)
return ret;
num_regs = cfm & 0x7f; /* size of frame */
}
else
{
ret = ia64_get (c, c->cfm_loc, &cfm);
if (ret < 0)
return ret;
num_regs = (cfm >> 7) & 0x7f; /* size of locals */
}
c->bsp = ia64_rse_skip_regs (c->bsp, -num_regs);
/* update the IP cache: */
ret = ia64_get (c, c->ip_loc, &ip);
if (ret < 0)
return ret;
c->ip = ip;
if ((ip & 0xc) != 0)
{
/* don't let obviously bad addresses pollute the cache */
debug (1, "%s: rejecting bad ip=0x%lx\n", __FUNCTION__, (long) c->ip);
return -UNW_EINVALIDIP;
}
if (ip == 0)
/* end of frame-chain reached */
return 0;
pr = c->pr;
c->sp = c->psp;
c->is_signal_frame = 0;
if (c->ip == prev_ip && c->sp == prev_sp && c->bsp == prev_bsp)
{
dprintf ("%s: ip, sp, and bsp unchanged; stopping here (ip=0x%lx)\n",
__FUNCTION__, (long) ip);
return -UNW_EBADFRAME;
}
/* as we unwind, the saved ar.unat becomes the primary unat: */
c->pri_unat_loc = c->unat_loc;
/* restore the predicates: */
ret = ia64_get (c, c->pr_loc, &c->pr);
if (ret < 0)
return ret;
c->pi_valid = 0;
#endif
return 0;
}
int
unw_step (unw_cursor_t *cursor)
{
struct cursor *c = (struct cursor *) cursor;
int ret;
int ret, i;
if (unw_is_signal_frame(cursor))
/* Try DWARF-based unwinding... */
ret = dwarf_step (&c->dwarf);
if (unlikely (ret < 0))
{
/* c->esp points at the arguments to the handler. Without
SA_SIGINFO, the arguments consist of a signal number followed
by a struct sigcontext. With SA_SIGINFO, the arguments
consist a signal number, a siginfo *, and a ucontext *. */
unw_word_t siginfo_ptr_addr = c->esp + 4;
unw_word_t sigcontext_ptr_addr = c->esp + 8;
unw_word_t siginfo_ptr, sigcontext_ptr;
struct x86_loc esp_loc, siginfo_ptr_loc, sigcontext_ptr_loc;
/* DWARF failed, let's see if we can follow the frame-chain
or skip over the signal trampoline. */
struct dwarf_loc ebp_loc, eip_loc;
siginfo_ptr_loc = X86_LOC (siginfo_ptr_addr, 0);
sigcontext_ptr_loc = X86_LOC (sigcontext_ptr_addr, 0);
ret = (x86_get (c, siginfo_ptr_loc, &siginfo_ptr)
| x86_get (c, sigcontext_ptr_loc, &sigcontext_ptr));
if (ret < 0)
return 0;
if (siginfo_ptr < c->esp || siginfo_ptr > c->esp + 256
|| sigcontext_ptr < c->esp || sigcontext_ptr > c->esp + 256)
{
/* Not plausible for SA_SIGINFO signal */
unw_word_t sigcontext_addr = c->esp + 4;
esp_loc = X86_LOC (sigcontext_addr + LINUX_SC_ESP_OFF, 0);
c->ebp_loc = X86_LOC (sigcontext_addr + LINUX_SC_EBP_OFF, 0);
c->eip_loc = X86_LOC (sigcontext_addr + LINUX_SC_EIP_OFF, 0);
}
Debug (14, "dwarf_step() failed (ret=%d), trying frame-chain\n",
ret);
if (unw_is_signal_frame(cursor))
{
/* XXX This code is Linux-specific! */
/* c->esp points at the arguments to the handler. Without
SA_SIGINFO, the arguments consist of a signal number
followed by a struct sigcontext. With SA_SIGINFO, the
arguments consist a signal number, a siginfo *, and a
ucontext *. */
unw_word_t siginfo_ptr_addr = c->dwarf.cfa + 4;
unw_word_t sigcontext_ptr_addr = c->dwarf.cfa + 8;
unw_word_t siginfo_ptr, sigcontext_ptr;
struct dwarf_loc esp_loc, siginfo_ptr_loc, sigcontext_ptr_loc;
siginfo_ptr_loc = DWARF_LOC (siginfo_ptr_addr, 0);
sigcontext_ptr_loc = DWARF_LOC (sigcontext_ptr_addr, 0);
ret = (dwarf_get (&c->dwarf, siginfo_ptr_loc, &siginfo_ptr)
| dwarf_get (&c->dwarf, sigcontext_ptr_loc, &sigcontext_ptr));
if (ret < 0)
return 0;
if (siginfo_ptr < c->dwarf.cfa
|| siginfo_ptr > c->dwarf.cfa + 256
|| sigcontext_ptr < c->dwarf.cfa
|| sigcontext_ptr > c->dwarf.cfa + 256)
{
/* Not plausible for SA_SIGINFO signal */
unw_word_t sigcontext_addr = c->dwarf.cfa + 4;
esp_loc = DWARF_LOC (sigcontext_addr + LINUX_SC_ESP_OFF, 0);
ebp_loc = DWARF_LOC (sigcontext_addr + LINUX_SC_EBP_OFF, 0);
eip_loc = DWARF_LOC (sigcontext_addr + LINUX_SC_EIP_OFF, 0);
}
else
{
/* If SA_SIGINFO were not specified, we actually read
various segment pointers instead. We believe that at
least fs and _fsh are always zero for linux, so it is
not just unlikely, but impossible that we would end
up here. */
esp_loc = DWARF_LOC (sigcontext_ptr + LINUX_UC_ESP_OFF, 0);
ebp_loc = DWARF_LOC (sigcontext_ptr + LINUX_UC_EBP_OFF, 0);
eip_loc = DWARF_LOC (sigcontext_ptr + LINUX_UC_EIP_OFF, 0);
}
ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa);
if (ret < 0)
return 0;
}
else
{
/* If SA_SIGINFO were not specified, we actually read
various segment pointers instead. We believe that at
least fs and _fsh are always zero for linux, so it is not
just unlikely, but impossible that we would end up
here. */
esp_loc = X86_LOC (sigcontext_ptr + LINUX_UC_ESP_OFF, 0);
c->ebp_loc = X86_LOC (sigcontext_ptr + LINUX_UC_EBP_OFF, 0);
c->eip_loc = X86_LOC (sigcontext_ptr + LINUX_UC_EIP_OFF, 0);
ret = dwarf_get (&c->dwarf, c->dwarf.loc[EBP], &c->dwarf.cfa);
if (ret < 0)
return ret;
Debug (14, "[EBP=0x%lx] = 0x%lx\n",
(long) DWARF_GET_LOC (c->dwarf.loc[EBP]),
(long) c->dwarf.cfa);
ebp_loc = DWARF_LOC (c->dwarf.cfa, 0);
eip_loc = DWARF_LOC (c->dwarf.cfa + 4, 0);
c->dwarf.cfa += 8;
}
ret = x86_get (c, esp_loc, &c->esp);
if (ret < 0)
return 0;
}
else
{
ret = x86_get (c, c->ebp_loc, &c->esp);
if (ret < 0)
return ret;
/* Mark all registers unsaved, since we don't know where they
are saved (if at all), except for the EBP and EIP. */
for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
c->dwarf.loc[i] = DWARF_NULL_LOC;
c->dwarf.loc[EBP] = ebp_loc;
c->dwarf.loc[EIP] = eip_loc;
c->dwarf.ret_addr_column = EIP;
c->ebp_loc = X86_LOC (c->esp, 0);
c->eip_loc = X86_LOC (c->esp + 4, 0);
c->esp += 8;
if (!DWARF_IS_NULL_LOC (c->dwarf.loc[EBP]))
{
ret = dwarf_get (&c->dwarf, c->dwarf.loc[EIP], &c->dwarf.ip);
if (ret < 0)
return ret;
}
else
c->dwarf.ip = 0;
}
if (X86_GET_LOC (c->ebp_loc))
{
ret = x86_get (c, c->eip_loc, &c->eip);
if (ret < 0)
return ret;
}
else
c->eip = 0;
return (c->eip == 0) ? 0 : 1;
return (c->dwarf.ip == 0) ? 0 : 1;
}

View file

@ -0,0 +1,45 @@
/* libunwind - a platform-independent unwind library
Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of libunwind.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "tdep.h"
void
unw_flush_cache (unw_addr_space_t as, unw_word_t lo, unw_word_t hi)
{
/* clear dyn_info_list_addr cache: */
as->dyn_info_list_addr = 0;
/* This lets us flush caches lazily. The implementation currently
ignores the flush range arguments (lo-hi). This is OK because
unw_flush_cache() is allowed to flush more than the requested
range. */
#ifdef HAVE_FETCH_AND_ADD1
fetch_and_add1 (&as->cache_generation);
#else
# warning unw_flush_cache(): need a way to atomically increment an integer.
++as->cache_generation;
#endif
}

View file

@ -0,0 +1,34 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2002 Hewlett-Packard Co
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of libunwind.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
unw_accessors_t *
unw_get_accessors (unw_addr_space_t as)
{
if (x86_needs_initialization)
x86_init ();
return &as->acc;
}

View file

@ -1,18 +1,74 @@
#include "unwind_i.h"
/* libunwind - a platform-independent unwind library
Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of libunwind.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
#include "dwarf-config.h"
HIDDEN pthread_mutex_t x86_lock = PTHREAD_MUTEX_INITIALIZER;
HIDDEN int x86_needs_initialization = 1;
#if UNW_DEBUG
HIDDEN int tdep_debug_level;
#endif
/* See comments for svr4_dbx_register_map[] in gcc/config/i386/i386.c. */
HIDDEN uint8_t dwarf_to_unw_regnum_map[19] =
{
UNW_X86_EAX, UNW_X86_ECX, UNW_X86_EDX, UNW_X86_EBX,
UNW_X86_ESP, UNW_X86_EBP, UNW_X86_ESI, UNW_X86_EDI,
UNW_X86_EIP, UNW_X86_EFLAGS, UNW_X86_TRAPNO,
UNW_X86_ST0, UNW_X86_ST1, UNW_X86_ST2, UNW_X86_ST3,
UNW_X86_ST4, UNW_X86_ST5, UNW_X86_ST6, UNW_X86_ST7
};
HIDDEN void
x86_init (void)
{
extern void _ULx86_local_addr_space_init (void);
sigset_t saved_sigmask;
mi_init();
sigfillset (&unwi_full_sigmask);
_Ux86_local_addr_space_init ();
_ULx86_local_addr_space_init ();
sigprocmask (SIG_SETMASK, &unwi_full_sigmask, &saved_sigmask);
mutex_lock (&x86_lock);
{
if (!x86_needs_initialization)
/* another thread else beat us to it... */
goto out;
mi_init ();
dwarf_init ();
_Ux86_local_addr_space_init ();
_ULx86_local_addr_space_init ();
x86_needs_initialization = 0; /* signal that we're initialized... */
}
out:
mutex_unlock (&x86_lock);
sigprocmask (SIG_SETMASK, &saved_sigmask, NULL);
}

View file

@ -0,0 +1,57 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2002 Hewlett-Packard Co
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of libunwind.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
static inline int
common_init (struct cursor *c)
{
int ret, i;
c->dwarf.loc[EAX] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EAX);
c->dwarf.loc[ECX] = DWARF_REG_LOC (&c->dwarf, UNW_X86_ECX);
c->dwarf.loc[EDX] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EDX);
c->dwarf.loc[EBX] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EBX);
c->dwarf.loc[ESP] = DWARF_REG_LOC (&c->dwarf, UNW_X86_ESP);
c->dwarf.loc[EBP] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EBP);
c->dwarf.loc[ESI] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EDI);
c->dwarf.loc[EDI] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EDI);
c->dwarf.loc[EIP] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EIP);
c->dwarf.loc[EFLAGS] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EFLAGS);
c->dwarf.loc[TRAPNO] = DWARF_REG_LOC (&c->dwarf, UNW_X86_TRAPNO);
c->dwarf.loc[ST0] = DWARF_REG_LOC (&c->dwarf, UNW_X86_ST0);
for (i = ST0 + 1; i < DWARF_NUM_PRESERVED_REGS; ++i)
c->dwarf.loc[i] = DWARF_NULL_LOC;
ret = dwarf_get (&c->dwarf, c->dwarf.loc[EIP], &c->dwarf.ip);
if (ret < 0)
return ret;
ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_X86_ESP),
&c->dwarf.cfa);
if (ret < 0)
return ret;
return 0;
}

View file

@ -2,7 +2,17 @@
static const char *regname[] =
{
"eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "eip", "esp"
"eax", "edx", "ecx", "ebx", "esi", "edi", "ebp", "esp", "eip",
"eflags", "trapno",
"st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7",
"fcw", "fsw", "ftw", "fop", "fcs", "fip", "fea", "fds",
"xmm0_lo", "xmm0_hi", "xmm1_lo", "xmm1_hi",
"xmm2_lo", "xmm2_hi", "xmm3_lo", "xmm3_hi",
"xmm4_lo", "xmm4_hi", "xmm5_lo", "xmm5_hi",
"xmm6_lo", "xmm6_hi", "xmm7_lo", "xmm7_hi",
"mxcsr",
"gs", "fs", "es", "ds", "ss", "cs",
"tss", "ldt"
};
const char *

View file

@ -34,103 +34,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "internal.h"
#include "tdep.h"
#define X86_GET_LOC(l) ((l).val)
#ifdef UNW_LOCAL_ONLY
# define X86_LOC(r, t) ((struct x86_loc) { .val = (r) })
# define X86_REG_LOC(c,r) (X86_LOC((unw_word_t) \
tdep_uc_addr((c)->as_arg, (r)), 0))
# define X86_FPREG_FLOC(c,r) (X86_LOC((unw_word_t) \
tdep_uc_addr((c)->as_arg, (r)), 0))
static inline int
x86_getfp (struct cursor *c, struct x86_loc loc, unw_fpreg_t *val)
{
if (!X86_GET_LOC (loc))
return -1;
*val = *(unw_fpreg_t *) X86_GET_LOC (loc);
return 0;
}
static inline int
x86_putfp (struct cursor *c, struct x86_loc loc, unw_fpreg_t *val)
{
if (!X86_GET_LOC (loc))
return -1;
*(unw_fpreg_t *) X86_GET_LOC (loc) = *val;
return 0;
}
static inline int
x86_get (struct cursor *c, struct x86_loc loc, unw_word_t *val)
{
if (!X86_GET_LOC (loc))
return -1;
*val = *(unw_word_t *) X86_GET_LOC (loc);
return 0;
}
static inline int
x86_put (struct cursor *c, struct x86_loc loc, unw_word_t val)
{
if (!X86_GET_LOC (loc))
return -1;
*(unw_word_t *) X86_GET_LOC (loc) = val;
return 0;
}
#else /* !UNW_LOCAL_ONLY */
# define X86_LOC_TYPE_FP (1 << 0)
# define X86_LOC_TYPE_REG (1 << 1)
# define X86_LOC(r, t) ((struct x86_loc) { .val = (r), .type = (t) })
# define X86_IS_REG_LOC(l) (((l).type & X86_LOC_TYPE_REG) != 0)
# define X86_IS_FP_LOC(l) (((l).type & X86_LOC_TYPE_FP) != 0)
# define X86_REG_LOC(c,r) X86_LOC((r), X86_LOC_TYPE_REG)
# define X86_FPREG_LOC(c,r) X86_LOC((r), (X86_LOC_TYPE_REG \
| X86_LOC_TYPE_FP))
static inline int
x86_getfp (struct cursor *c, struct x86_loc loc, unw_fpreg_t *val)
{
abort ();
}
static inline int
x86_putfp (struct cursor *c, struct x86_loc loc, unw_fpreg_t val)
{
abort ();
}
static inline int
x86_get (struct cursor *c, struct x86_loc loc, unw_word_t *val)
{
if (X86_IS_FP_LOC (loc))
abort ();
if (X86_IS_REG_LOC (loc))
return (*c->as->acc.access_reg)(c->as, X86_GET_LOC (loc), val, 0,
c->as_arg);
else
return (*c->as->acc.access_mem)(c->as, X86_GET_LOC (loc), val, 0,
c->as_arg);
}
static inline int
x86_put (struct cursor *c, struct x86_loc loc, unw_word_t val)
{
if (X86_IS_FP_LOC (loc))
abort ();
if (X86_IS_REG_LOC (loc))
return (*c->as->acc.access_reg)(c->as, X86_GET_LOC (loc), &val, 1,
c->as_arg);
else
return (*c->as->acc.access_mem)(c->as, X86_GET_LOC (loc), &val, 1,
c->as_arg);
}
#endif /* !UNW_LOCAL_ONLY */
/* DWARF column numbers: */
#define EAX 0
#define ECX 1
#define EDX 2
#define EBX 3
#define ESP 4
#define EBP 5
#define ESI 6
#define EDI 7
#define EIP 8
#define EFLAGS 9
#define TRAPNO 10
#define ST0 11
#define x86_lock UNW_ARCH_OBJ(lock)
#define x86_needs_initialization UNW_ARCH_OBJ(needs_initialization)
#define x86_init UNW_ARCH_OBJ(init)
#define x86_access_reg UNW_OBJ(access_reg)