mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-21 23:27:39 +01:00
One time whitespace fixup.
for f in $(find src include -name '*.[ch]'); do expand -t 8 $f > $tmp; mv $tmp $f; done
This commit is contained in:
parent
06e608d043
commit
781d5d5263
275 changed files with 7649 additions and 7649 deletions
|
@ -1,7 +1,7 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2001-2005 Hewlett-Packard Co
|
Copyright (C) 2001-2005 Hewlett-Packard Co
|
||||||
Copyright (C) 2007 David Mosberger-Tang
|
Copyright (C) 2007 David Mosberger-Tang
|
||||||
Contributed by David Mosberger-Tang <dmosberger@gmail.com>
|
Contributed by David Mosberger-Tang <dmosberger@gmail.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -31,28 +31,28 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#define COMPILER_H
|
#define COMPILER_H
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# define ALIGNED(x) __attribute__((aligned(x)))
|
# define ALIGNED(x) __attribute__((aligned(x)))
|
||||||
# define CONST_ATTR __attribute__((__const__))
|
# define CONST_ATTR __attribute__((__const__))
|
||||||
# define UNUSED __attribute__((unused))
|
# define UNUSED __attribute__((unused))
|
||||||
# define NOINLINE __attribute__((noinline))
|
# define NOINLINE __attribute__((noinline))
|
||||||
# define NORETURN __attribute__((noreturn))
|
# define NORETURN __attribute__((noreturn))
|
||||||
# define ALIAS(name) __attribute__((alias (#name)))
|
# define ALIAS(name) __attribute__((alias (#name)))
|
||||||
# if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
|
# if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
|
||||||
# define ALWAYS_INLINE inline __attribute__((always_inline))
|
# define ALWAYS_INLINE inline __attribute__((always_inline))
|
||||||
# define HIDDEN __attribute__((visibility ("hidden")))
|
# define HIDDEN __attribute__((visibility ("hidden")))
|
||||||
# define PROTECTED __attribute__((visibility ("protected")))
|
# define PROTECTED __attribute__((visibility ("protected")))
|
||||||
# else
|
# else
|
||||||
# define ALWAYS_INLINE
|
# define ALWAYS_INLINE
|
||||||
# define HIDDEN
|
# define HIDDEN
|
||||||
# define PROTECTED
|
# define PROTECTED
|
||||||
# endif
|
# endif
|
||||||
# define WEAK __attribute__((weak))
|
# define WEAK __attribute__((weak))
|
||||||
# if (__GNUC__ >= 3)
|
# if (__GNUC__ >= 3)
|
||||||
# define likely(x) __builtin_expect ((x), 1)
|
# define likely(x) __builtin_expect ((x), 1)
|
||||||
# define unlikely(x) __builtin_expect ((x), 0)
|
# define unlikely(x) __builtin_expect ((x), 0)
|
||||||
# else
|
# else
|
||||||
# define likely(x) (x)
|
# define likely(x) (x)
|
||||||
# define unlikely(x) (x)
|
# define unlikely(x) (x)
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
# define ALIGNED(x)
|
# define ALIGNED(x)
|
||||||
|
@ -65,10 +65,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
# define HIDDEN
|
# define HIDDEN
|
||||||
# define PROTECTED
|
# define PROTECTED
|
||||||
# define WEAK
|
# define WEAK
|
||||||
# define likely(x) (x)
|
# define likely(x) (x)
|
||||||
# define unlikely(x) (x)
|
# define unlikely(x) (x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
|
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
|
||||||
|
|
||||||
#endif /* COMPILER_H */
|
#endif /* COMPILER_H */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
|
Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -58,9 +58,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
string:
|
string:
|
||||||
|
|
||||||
'z': The operand for this character is a uleb128 value that gives the
|
'z': The operand for this character is a uleb128 value that gives the
|
||||||
length of the CIE augmentation body, not counting the length
|
length of the CIE augmentation body, not counting the length
|
||||||
of the uleb128 operand itself. If present, this code must
|
of the uleb128 operand itself. If present, this code must
|
||||||
appear as the first character in the augmentation body.
|
appear as the first character in the augmentation body.
|
||||||
|
|
||||||
'L': Indicates that the FDE's augmentation body contains an LSDA
|
'L': Indicates that the FDE's augmentation body contains an LSDA
|
||||||
pointer. The operand for this character is a single byte
|
pointer. The operand for this character is a single byte
|
||||||
|
@ -73,13 +73,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
operand for this character is a single byte that specifies
|
operand for this character is a single byte that specifies
|
||||||
the pointer-encoding (PE) that is used for the
|
the pointer-encoding (PE) that is used for the
|
||||||
code-pointers. Note: the "address_range" member is always
|
code-pointers. Note: the "address_range" member is always
|
||||||
encoded as an absolute value. Apart from that, the specified
|
encoded as an absolute value. Apart from that, the specified
|
||||||
FDE pointer-encoding applies.
|
FDE pointer-encoding applies.
|
||||||
|
|
||||||
'P': Indicates the presence of a personality routine (handler).
|
'P': Indicates the presence of a personality routine (handler).
|
||||||
The first operand for this character specifies the
|
The first operand for this character specifies the
|
||||||
pointer-encoding (PE) that is used for the second operand,
|
pointer-encoding (PE) that is used for the second operand,
|
||||||
which specifies the address of the personality routine.
|
which specifies the address of the personality routine.
|
||||||
|
|
||||||
If the augmentation string contains any other characters, the
|
If the augmentation string contains any other characters, the
|
||||||
remainder of the augmentation string should be ignored.
|
remainder of the augmentation string should be ignored.
|
||||||
|
@ -104,7 +104,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DW_EH_VERSION 1 /* The version we're implementing */
|
#define DW_EH_VERSION 1 /* The version we're implementing */
|
||||||
|
|
||||||
struct dwarf_eh_frame_hdr
|
struct dwarf_eh_frame_hdr
|
||||||
{
|
{
|
||||||
|
@ -115,14 +115,14 @@ struct dwarf_eh_frame_hdr
|
||||||
/* The rest of the header is variable-length and consists of the
|
/* The rest of the header is variable-length and consists of the
|
||||||
following members:
|
following members:
|
||||||
|
|
||||||
encoded_t eh_frame_ptr;
|
encoded_t eh_frame_ptr;
|
||||||
encoded_t fde_count;
|
encoded_t fde_count;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
encoded_t start_ip; // first address covered by this FDE
|
encoded_t start_ip; // first address covered by this FDE
|
||||||
encoded_t fde_addr; // address of the FDE
|
encoded_t fde_addr; // address of the FDE
|
||||||
}
|
}
|
||||||
binary_search_table[fde_count]; */
|
binary_search_table[fde_count]; */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* dwarf_eh_h */
|
#endif /* dwarf_eh_h */
|
||||||
|
|
396
include/dwarf.h
396
include/dwarf.h
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
|
Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
#include <libunwind.h>
|
#include <libunwind.h>
|
||||||
|
|
||||||
struct dwarf_cursor; /* forward-declaration */
|
struct dwarf_cursor; /* forward-declaration */
|
||||||
struct elf_dyn_info;
|
struct elf_dyn_info;
|
||||||
|
|
||||||
#include "dwarf-config.h"
|
#include "dwarf-config.h"
|
||||||
|
@ -53,49 +53,49 @@ struct elf_dyn_info;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
DW_OP_addr = 0x03,
|
DW_OP_addr = 0x03,
|
||||||
DW_OP_deref = 0x06,
|
DW_OP_deref = 0x06,
|
||||||
DW_OP_const1u = 0x08,
|
DW_OP_const1u = 0x08,
|
||||||
DW_OP_const1s = 0x09,
|
DW_OP_const1s = 0x09,
|
||||||
DW_OP_const2u = 0x0a,
|
DW_OP_const2u = 0x0a,
|
||||||
DW_OP_const2s = 0x0b,
|
DW_OP_const2s = 0x0b,
|
||||||
DW_OP_const4u = 0x0c,
|
DW_OP_const4u = 0x0c,
|
||||||
DW_OP_const4s = 0x0d,
|
DW_OP_const4s = 0x0d,
|
||||||
DW_OP_const8u = 0x0e,
|
DW_OP_const8u = 0x0e,
|
||||||
DW_OP_const8s = 0x0f,
|
DW_OP_const8s = 0x0f,
|
||||||
DW_OP_constu = 0x10,
|
DW_OP_constu = 0x10,
|
||||||
DW_OP_consts = 0x11,
|
DW_OP_consts = 0x11,
|
||||||
DW_OP_dup = 0x12,
|
DW_OP_dup = 0x12,
|
||||||
DW_OP_drop = 0x13,
|
DW_OP_drop = 0x13,
|
||||||
DW_OP_over = 0x14,
|
DW_OP_over = 0x14,
|
||||||
DW_OP_pick = 0x15,
|
DW_OP_pick = 0x15,
|
||||||
DW_OP_swap = 0x16,
|
DW_OP_swap = 0x16,
|
||||||
DW_OP_rot = 0x17,
|
DW_OP_rot = 0x17,
|
||||||
DW_OP_xderef = 0x18,
|
DW_OP_xderef = 0x18,
|
||||||
DW_OP_abs = 0x19,
|
DW_OP_abs = 0x19,
|
||||||
DW_OP_and = 0x1a,
|
DW_OP_and = 0x1a,
|
||||||
DW_OP_div = 0x1b,
|
DW_OP_div = 0x1b,
|
||||||
DW_OP_minus = 0x1c,
|
DW_OP_minus = 0x1c,
|
||||||
DW_OP_mod = 0x1d,
|
DW_OP_mod = 0x1d,
|
||||||
DW_OP_mul = 0x1e,
|
DW_OP_mul = 0x1e,
|
||||||
DW_OP_neg = 0x1f,
|
DW_OP_neg = 0x1f,
|
||||||
DW_OP_not = 0x20,
|
DW_OP_not = 0x20,
|
||||||
DW_OP_or = 0x21,
|
DW_OP_or = 0x21,
|
||||||
DW_OP_plus = 0x22,
|
DW_OP_plus = 0x22,
|
||||||
DW_OP_plus_uconst = 0x23,
|
DW_OP_plus_uconst = 0x23,
|
||||||
DW_OP_shl = 0x24,
|
DW_OP_shl = 0x24,
|
||||||
DW_OP_shr = 0x25,
|
DW_OP_shr = 0x25,
|
||||||
DW_OP_shra = 0x26,
|
DW_OP_shra = 0x26,
|
||||||
DW_OP_xor = 0x27,
|
DW_OP_xor = 0x27,
|
||||||
DW_OP_skip = 0x2f,
|
DW_OP_skip = 0x2f,
|
||||||
DW_OP_bra = 0x28,
|
DW_OP_bra = 0x28,
|
||||||
DW_OP_eq = 0x29,
|
DW_OP_eq = 0x29,
|
||||||
DW_OP_ge = 0x2a,
|
DW_OP_ge = 0x2a,
|
||||||
DW_OP_gt = 0x2b,
|
DW_OP_gt = 0x2b,
|
||||||
DW_OP_le = 0x2c,
|
DW_OP_le = 0x2c,
|
||||||
DW_OP_lt = 0x2d,
|
DW_OP_lt = 0x2d,
|
||||||
DW_OP_ne = 0x2e,
|
DW_OP_ne = 0x2e,
|
||||||
DW_OP_lit0 = 0x30,
|
DW_OP_lit0 = 0x30,
|
||||||
DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_lit4, DW_OP_lit5,
|
DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_lit4, DW_OP_lit5,
|
||||||
DW_OP_lit6, DW_OP_lit7, DW_OP_lit8, DW_OP_lit9, DW_OP_lit10,
|
DW_OP_lit6, DW_OP_lit7, DW_OP_lit8, DW_OP_lit9, DW_OP_lit10,
|
||||||
DW_OP_lit11, DW_OP_lit12, DW_OP_lit13, DW_OP_lit14, DW_OP_lit15,
|
DW_OP_lit11, DW_OP_lit12, DW_OP_lit13, DW_OP_lit14, DW_OP_lit15,
|
||||||
|
@ -103,7 +103,7 @@ typedef enum
|
||||||
DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24, DW_OP_lit25,
|
DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24, DW_OP_lit25,
|
||||||
DW_OP_lit26, DW_OP_lit27, DW_OP_lit28, DW_OP_lit29, DW_OP_lit30,
|
DW_OP_lit26, DW_OP_lit27, DW_OP_lit28, DW_OP_lit29, DW_OP_lit30,
|
||||||
DW_OP_lit31,
|
DW_OP_lit31,
|
||||||
DW_OP_reg0 = 0x50,
|
DW_OP_reg0 = 0x50,
|
||||||
DW_OP_reg1, DW_OP_reg2, DW_OP_reg3, DW_OP_reg4, DW_OP_reg5,
|
DW_OP_reg1, DW_OP_reg2, DW_OP_reg3, DW_OP_reg4, DW_OP_reg5,
|
||||||
DW_OP_reg6, DW_OP_reg7, DW_OP_reg8, DW_OP_reg9, DW_OP_reg10,
|
DW_OP_reg6, DW_OP_reg7, DW_OP_reg8, DW_OP_reg9, DW_OP_reg10,
|
||||||
DW_OP_reg11, DW_OP_reg12, DW_OP_reg13, DW_OP_reg14, DW_OP_reg15,
|
DW_OP_reg11, DW_OP_reg12, DW_OP_reg13, DW_OP_reg14, DW_OP_reg15,
|
||||||
|
@ -111,7 +111,7 @@ typedef enum
|
||||||
DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24, DW_OP_reg25,
|
DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24, DW_OP_reg25,
|
||||||
DW_OP_reg26, DW_OP_reg27, DW_OP_reg28, DW_OP_reg29, DW_OP_reg30,
|
DW_OP_reg26, DW_OP_reg27, DW_OP_reg28, DW_OP_reg29, DW_OP_reg30,
|
||||||
DW_OP_reg31,
|
DW_OP_reg31,
|
||||||
DW_OP_breg0 = 0x70,
|
DW_OP_breg0 = 0x70,
|
||||||
DW_OP_breg1, DW_OP_breg2, DW_OP_breg3, DW_OP_breg4, DW_OP_breg5,
|
DW_OP_breg1, DW_OP_breg2, DW_OP_breg3, DW_OP_breg4, DW_OP_breg5,
|
||||||
DW_OP_breg6, DW_OP_breg7, DW_OP_breg8, DW_OP_breg9, DW_OP_breg10,
|
DW_OP_breg6, DW_OP_breg7, DW_OP_breg8, DW_OP_breg9, DW_OP_breg10,
|
||||||
DW_OP_breg11, DW_OP_breg12, DW_OP_breg13, DW_OP_breg14, DW_OP_breg15,
|
DW_OP_breg11, DW_OP_breg12, DW_OP_breg13, DW_OP_breg14, DW_OP_breg15,
|
||||||
|
@ -119,59 +119,59 @@ typedef enum
|
||||||
DW_OP_breg21, DW_OP_breg22, DW_OP_breg23, DW_OP_breg24, DW_OP_breg25,
|
DW_OP_breg21, DW_OP_breg22, DW_OP_breg23, DW_OP_breg24, DW_OP_breg25,
|
||||||
DW_OP_breg26, DW_OP_breg27, DW_OP_breg28, DW_OP_breg29, DW_OP_breg30,
|
DW_OP_breg26, DW_OP_breg27, DW_OP_breg28, DW_OP_breg29, DW_OP_breg30,
|
||||||
DW_OP_breg31,
|
DW_OP_breg31,
|
||||||
DW_OP_regx = 0x90,
|
DW_OP_regx = 0x90,
|
||||||
DW_OP_fbreg = 0x91,
|
DW_OP_fbreg = 0x91,
|
||||||
DW_OP_bregx = 0x92,
|
DW_OP_bregx = 0x92,
|
||||||
DW_OP_piece = 0x93,
|
DW_OP_piece = 0x93,
|
||||||
DW_OP_deref_size = 0x94,
|
DW_OP_deref_size = 0x94,
|
||||||
DW_OP_xderef_size = 0x95,
|
DW_OP_xderef_size = 0x95,
|
||||||
DW_OP_nop = 0x96,
|
DW_OP_nop = 0x96,
|
||||||
DW_OP_push_object_address = 0x97,
|
DW_OP_push_object_address = 0x97,
|
||||||
DW_OP_call2 = 0x98,
|
DW_OP_call2 = 0x98,
|
||||||
DW_OP_call4 = 0x99,
|
DW_OP_call4 = 0x99,
|
||||||
DW_OP_call_ref = 0x9a,
|
DW_OP_call_ref = 0x9a,
|
||||||
DW_OP_lo_user = 0xe0,
|
DW_OP_lo_user = 0xe0,
|
||||||
DW_OP_hi_user = 0xff
|
DW_OP_hi_user = 0xff
|
||||||
}
|
}
|
||||||
dwarf_expr_op_t;
|
dwarf_expr_op_t;
|
||||||
|
|
||||||
#define DWARF_CIE_VERSION 3 /* GCC emits version 1??? */
|
#define DWARF_CIE_VERSION 3 /* GCC emits version 1??? */
|
||||||
|
|
||||||
#define DWARF_CFA_OPCODE_MASK 0xc0
|
#define DWARF_CFA_OPCODE_MASK 0xc0
|
||||||
#define DWARF_CFA_OPERAND_MASK 0x3f
|
#define DWARF_CFA_OPERAND_MASK 0x3f
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
DW_CFA_advance_loc = 0x40,
|
DW_CFA_advance_loc = 0x40,
|
||||||
DW_CFA_offset = 0x80,
|
DW_CFA_offset = 0x80,
|
||||||
DW_CFA_restore = 0xc0,
|
DW_CFA_restore = 0xc0,
|
||||||
DW_CFA_nop = 0x00,
|
DW_CFA_nop = 0x00,
|
||||||
DW_CFA_set_loc = 0x01,
|
DW_CFA_set_loc = 0x01,
|
||||||
DW_CFA_advance_loc1 = 0x02,
|
DW_CFA_advance_loc1 = 0x02,
|
||||||
DW_CFA_advance_loc2 = 0x03,
|
DW_CFA_advance_loc2 = 0x03,
|
||||||
DW_CFA_advance_loc4 = 0x04,
|
DW_CFA_advance_loc4 = 0x04,
|
||||||
DW_CFA_offset_extended = 0x05,
|
DW_CFA_offset_extended = 0x05,
|
||||||
DW_CFA_restore_extended = 0x06,
|
DW_CFA_restore_extended = 0x06,
|
||||||
DW_CFA_undefined = 0x07,
|
DW_CFA_undefined = 0x07,
|
||||||
DW_CFA_same_value = 0x08,
|
DW_CFA_same_value = 0x08,
|
||||||
DW_CFA_register = 0x09,
|
DW_CFA_register = 0x09,
|
||||||
DW_CFA_remember_state = 0x0a,
|
DW_CFA_remember_state = 0x0a,
|
||||||
DW_CFA_restore_state = 0x0b,
|
DW_CFA_restore_state = 0x0b,
|
||||||
DW_CFA_def_cfa = 0x0c,
|
DW_CFA_def_cfa = 0x0c,
|
||||||
DW_CFA_def_cfa_register = 0x0d,
|
DW_CFA_def_cfa_register = 0x0d,
|
||||||
DW_CFA_def_cfa_offset = 0x0e,
|
DW_CFA_def_cfa_offset = 0x0e,
|
||||||
DW_CFA_def_cfa_expression = 0x0f,
|
DW_CFA_def_cfa_expression = 0x0f,
|
||||||
DW_CFA_expression = 0x10,
|
DW_CFA_expression = 0x10,
|
||||||
DW_CFA_offset_extended_sf = 0x11,
|
DW_CFA_offset_extended_sf = 0x11,
|
||||||
DW_CFA_def_cfa_sf = 0x12,
|
DW_CFA_def_cfa_sf = 0x12,
|
||||||
DW_CFA_def_cfa_offset_sf = 0x13,
|
DW_CFA_def_cfa_offset_sf = 0x13,
|
||||||
DW_CFA_val_expression = 0x16,
|
DW_CFA_val_expression = 0x16,
|
||||||
DW_CFA_lo_user = 0x1c,
|
DW_CFA_lo_user = 0x1c,
|
||||||
DW_CFA_MIPS_advance_loc8 = 0x1d,
|
DW_CFA_MIPS_advance_loc8 = 0x1d,
|
||||||
DW_CFA_GNU_window_save = 0x2d,
|
DW_CFA_GNU_window_save = 0x2d,
|
||||||
DW_CFA_GNU_args_size = 0x2e,
|
DW_CFA_GNU_args_size = 0x2e,
|
||||||
DW_CFA_GNU_negative_offset_extended = 0x2f,
|
DW_CFA_GNU_negative_offset_extended = 0x2f,
|
||||||
DW_CFA_hi_user = 0x3c
|
DW_CFA_hi_user = 0x3c
|
||||||
}
|
}
|
||||||
dwarf_cfa_t;
|
dwarf_cfa_t;
|
||||||
|
|
||||||
|
@ -186,53 +186,53 @@ dwarf_cfa_t;
|
||||||
engineered from GCC.
|
engineered from GCC.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
|
#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
|
||||||
#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
|
#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
|
||||||
/* Flag bit. If set, the resulting pointer is the address of the word
|
/* Flag bit. If set, the resulting pointer is the address of the word
|
||||||
that contains the final address. */
|
that contains the final address. */
|
||||||
#define DW_EH_PE_indirect 0x80
|
#define DW_EH_PE_indirect 0x80
|
||||||
|
|
||||||
/* Pointer-encoding formats: */
|
/* Pointer-encoding formats: */
|
||||||
#define DW_EH_PE_omit 0xff
|
#define DW_EH_PE_omit 0xff
|
||||||
#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
|
#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
|
||||||
#define DW_EH_PE_uleb128 0x01 /* unsigned LE base-128 value */
|
#define DW_EH_PE_uleb128 0x01 /* unsigned LE base-128 value */
|
||||||
#define DW_EH_PE_udata2 0x02 /* unsigned 16-bit value */
|
#define DW_EH_PE_udata2 0x02 /* unsigned 16-bit value */
|
||||||
#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
|
#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
|
||||||
#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
|
#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
|
||||||
#define DW_EH_PE_sleb128 0x09 /* signed LE base-128 value */
|
#define DW_EH_PE_sleb128 0x09 /* signed LE base-128 value */
|
||||||
#define DW_EH_PE_sdata2 0x0a /* signed 16-bit value */
|
#define DW_EH_PE_sdata2 0x0a /* signed 16-bit value */
|
||||||
#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
|
#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
|
||||||
#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
|
#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
|
||||||
|
|
||||||
/* Pointer-encoding application: */
|
/* Pointer-encoding application: */
|
||||||
#define DW_EH_PE_absptr 0x00 /* absolute value */
|
#define DW_EH_PE_absptr 0x00 /* absolute value */
|
||||||
#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
|
#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
|
||||||
#define DW_EH_PE_textrel 0x20 /* text-relative (GCC-specific???) */
|
#define DW_EH_PE_textrel 0x20 /* text-relative (GCC-specific???) */
|
||||||
#define DW_EH_PE_datarel 0x30 /* data-relative */
|
#define DW_EH_PE_datarel 0x30 /* data-relative */
|
||||||
/* The following are not documented by LSB v1.3, yet they are used by
|
/* The following are not documented by LSB v1.3, yet they are used by
|
||||||
GCC, presumably they aren't documented by LSB since they aren't
|
GCC, presumably they aren't documented by LSB since they aren't
|
||||||
used on Linux: */
|
used on Linux: */
|
||||||
#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
|
#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
|
||||||
#define DW_EH_PE_aligned 0x50 /* aligned pointer */
|
#define DW_EH_PE_aligned 0x50 /* aligned pointer */
|
||||||
|
|
||||||
extern struct mempool dwarf_reg_state_pool;
|
extern struct mempool dwarf_reg_state_pool;
|
||||||
extern struct mempool dwarf_cie_info_pool;
|
extern struct mempool dwarf_cie_info_pool;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
DWARF_WHERE_UNDEF, /* register isn't saved at all */
|
DWARF_WHERE_UNDEF, /* register isn't saved at all */
|
||||||
DWARF_WHERE_SAME, /* register has same value as in prev. frame */
|
DWARF_WHERE_SAME, /* register has same value as in prev. frame */
|
||||||
DWARF_WHERE_CFAREL, /* register saved at CFA-relative address */
|
DWARF_WHERE_CFAREL, /* register saved at CFA-relative address */
|
||||||
DWARF_WHERE_REG, /* register saved in another register */
|
DWARF_WHERE_REG, /* register saved in another register */
|
||||||
DWARF_WHERE_EXPR, /* register saved */
|
DWARF_WHERE_EXPR, /* register saved */
|
||||||
DWARF_WHERE_VAL_EXPR, /* register has computed value */
|
DWARF_WHERE_VAL_EXPR, /* register has computed value */
|
||||||
}
|
}
|
||||||
dwarf_where_t;
|
dwarf_where_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
dwarf_where_t where; /* how is the register saved? */
|
dwarf_where_t where; /* how is the register saved? */
|
||||||
unw_word_t val; /* where it's saved */
|
unw_word_t val; /* where it's saved */
|
||||||
}
|
}
|
||||||
dwarf_save_loc_t;
|
dwarf_save_loc_t;
|
||||||
|
|
||||||
|
@ -246,18 +246,18 @@ dwarf_save_loc_t;
|
||||||
case of DWARF_WHERE_REG, member "val" gives the number of the
|
case of DWARF_WHERE_REG, member "val" gives the number of the
|
||||||
base-register and the "val" member of DWARF_CFA_OFF_COLUMN gives
|
base-register and the "val" member of DWARF_CFA_OFF_COLUMN gives
|
||||||
the offset value. */
|
the offset value. */
|
||||||
#define DWARF_CFA_REG_COLUMN DWARF_NUM_PRESERVED_REGS
|
#define DWARF_CFA_REG_COLUMN DWARF_NUM_PRESERVED_REGS
|
||||||
#define DWARF_CFA_OFF_COLUMN (DWARF_NUM_PRESERVED_REGS + 1)
|
#define DWARF_CFA_OFF_COLUMN (DWARF_NUM_PRESERVED_REGS + 1)
|
||||||
|
|
||||||
typedef struct dwarf_reg_state
|
typedef struct dwarf_reg_state
|
||||||
{
|
{
|
||||||
struct dwarf_reg_state *next; /* for rs_stack */
|
struct dwarf_reg_state *next; /* for rs_stack */
|
||||||
dwarf_save_loc_t reg[DWARF_NUM_PRESERVED_REGS + 2];
|
dwarf_save_loc_t reg[DWARF_NUM_PRESERVED_REGS + 2];
|
||||||
unw_word_t ip; /* ip this rs is for */
|
unw_word_t ip; /* ip this rs is for */
|
||||||
unw_word_t ret_addr_column; /* indicates which column in the rule table represents return address */
|
unw_word_t ret_addr_column; /* indicates which column in the rule table represents return address */
|
||||||
unsigned short lru_chain; /* used for least-recently-used chain */
|
unsigned short lru_chain; /* used for least-recently-used chain */
|
||||||
unsigned short coll_chain; /* used for hash collisions */
|
unsigned short coll_chain; /* used for hash collisions */
|
||||||
unsigned short hint; /* hint for next rs to try (or -1) */
|
unsigned short hint; /* hint for next rs to try (or -1) */
|
||||||
unsigned short valid : 1; /* optional machine-dependent signal info */
|
unsigned short valid : 1; /* optional machine-dependent signal info */
|
||||||
unsigned short signal_frame : 1; /* optional machine-dependent signal info */
|
unsigned short signal_frame : 1; /* optional machine-dependent signal info */
|
||||||
}
|
}
|
||||||
|
@ -265,14 +265,14 @@ dwarf_reg_state_t;
|
||||||
|
|
||||||
typedef struct dwarf_cie_info
|
typedef struct dwarf_cie_info
|
||||||
{
|
{
|
||||||
unw_word_t cie_instr_start; /* start addr. of CIE "initial_instructions" */
|
unw_word_t cie_instr_start; /* start addr. of CIE "initial_instructions" */
|
||||||
unw_word_t cie_instr_end; /* end addr. of CIE "initial_instructions" */
|
unw_word_t cie_instr_end; /* end addr. of CIE "initial_instructions" */
|
||||||
unw_word_t fde_instr_start; /* start addr. of FDE "instructions" */
|
unw_word_t fde_instr_start; /* start addr. of FDE "instructions" */
|
||||||
unw_word_t fde_instr_end; /* end addr. of FDE "instructions" */
|
unw_word_t fde_instr_end; /* end addr. of FDE "instructions" */
|
||||||
unw_word_t code_align; /* code-alignment factor */
|
unw_word_t code_align; /* code-alignment factor */
|
||||||
unw_word_t data_align; /* data-alignment factor */
|
unw_word_t data_align; /* data-alignment factor */
|
||||||
unw_word_t ret_addr_column; /* column of return-address register */
|
unw_word_t ret_addr_column; /* column of return-address register */
|
||||||
unw_word_t handler; /* address of personality-routine */
|
unw_word_t handler; /* address of personality-routine */
|
||||||
uint16_t abi;
|
uint16_t abi;
|
||||||
uint16_t tag;
|
uint16_t tag;
|
||||||
uint8_t fde_encoding;
|
uint8_t fde_encoding;
|
||||||
|
@ -288,20 +288,20 @@ typedef struct dwarf_state_record
|
||||||
unsigned char fde_encoding;
|
unsigned char fde_encoding;
|
||||||
unw_word_t args_size;
|
unw_word_t args_size;
|
||||||
|
|
||||||
dwarf_reg_state_t rs_initial; /* reg-state after CIE instructions */
|
dwarf_reg_state_t rs_initial; /* reg-state after CIE instructions */
|
||||||
dwarf_reg_state_t rs_current; /* current reg-state */
|
dwarf_reg_state_t rs_current; /* current reg-state */
|
||||||
}
|
}
|
||||||
dwarf_state_record_t;
|
dwarf_state_record_t;
|
||||||
|
|
||||||
typedef struct dwarf_cursor
|
typedef struct dwarf_cursor
|
||||||
{
|
{
|
||||||
void *as_arg; /* argument to address-space callbacks */
|
void *as_arg; /* argument to address-space callbacks */
|
||||||
unw_addr_space_t as; /* reference to per-address-space info */
|
unw_addr_space_t as; /* reference to per-address-space info */
|
||||||
|
|
||||||
unw_word_t cfa; /* canonical frame address; aka frame-/stack-pointer */
|
unw_word_t cfa; /* canonical frame address; aka frame-/stack-pointer */
|
||||||
unw_word_t ip; /* instruction pointer */
|
unw_word_t ip; /* instruction pointer */
|
||||||
unw_word_t args_size; /* size of arguments */
|
unw_word_t args_size; /* size of arguments */
|
||||||
unw_word_t ret_addr_column; /* column for return-address */
|
unw_word_t ret_addr_column; /* column for return-address */
|
||||||
unw_word_t eh_args[UNW_TDEP_NUM_EH_REGS];
|
unw_word_t eh_args[UNW_TDEP_NUM_EH_REGS];
|
||||||
unsigned int eh_valid_mask;
|
unsigned int eh_valid_mask;
|
||||||
|
|
||||||
|
@ -309,33 +309,33 @@ typedef struct dwarf_cursor
|
||||||
|
|
||||||
unsigned int stash_frames :1; /* stash frames for fast lookup */
|
unsigned int stash_frames :1; /* stash frames for fast lookup */
|
||||||
unsigned int use_prev_instr :1; /* use previous (= call) or current (= signal) instruction? */
|
unsigned int use_prev_instr :1; /* use previous (= call) or current (= signal) instruction? */
|
||||||
unsigned int pi_valid :1; /* is proc_info valid? */
|
unsigned int pi_valid :1; /* is proc_info valid? */
|
||||||
unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
|
unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
|
||||||
unw_proc_info_t pi; /* info about current procedure */
|
unw_proc_info_t pi; /* info about current procedure */
|
||||||
|
|
||||||
short hint; /* faster lookup of the rs cache */
|
short hint; /* faster lookup of the rs cache */
|
||||||
short prev_rs;
|
short prev_rs;
|
||||||
}
|
}
|
||||||
dwarf_cursor_t;
|
dwarf_cursor_t;
|
||||||
|
|
||||||
#define DWARF_LOG_UNW_CACHE_SIZE 7
|
#define DWARF_LOG_UNW_CACHE_SIZE 7
|
||||||
#define DWARF_UNW_CACHE_SIZE (1 << DWARF_LOG_UNW_CACHE_SIZE)
|
#define DWARF_UNW_CACHE_SIZE (1 << DWARF_LOG_UNW_CACHE_SIZE)
|
||||||
|
|
||||||
#define DWARF_LOG_UNW_HASH_SIZE (DWARF_LOG_UNW_CACHE_SIZE + 1)
|
#define DWARF_LOG_UNW_HASH_SIZE (DWARF_LOG_UNW_CACHE_SIZE + 1)
|
||||||
#define DWARF_UNW_HASH_SIZE (1 << DWARF_LOG_UNW_HASH_SIZE)
|
#define DWARF_UNW_HASH_SIZE (1 << DWARF_LOG_UNW_HASH_SIZE)
|
||||||
|
|
||||||
typedef unsigned char unw_hash_index_t;
|
typedef unsigned char unw_hash_index_t;
|
||||||
|
|
||||||
struct dwarf_rs_cache
|
struct dwarf_rs_cache
|
||||||
{
|
{
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
unsigned short lru_head; /* index of lead-recently used rs */
|
unsigned short lru_head; /* index of lead-recently used rs */
|
||||||
unsigned short lru_tail; /* index of most-recently used rs */
|
unsigned short lru_tail; /* index of most-recently used rs */
|
||||||
|
|
||||||
/* hash table that maps instruction pointer to rs index: */
|
/* hash table that maps instruction pointer to rs index: */
|
||||||
unsigned short hash[DWARF_UNW_HASH_SIZE];
|
unsigned short hash[DWARF_UNW_HASH_SIZE];
|
||||||
|
|
||||||
uint32_t generation; /* generation number */
|
uint32_t generation; /* generation number */
|
||||||
|
|
||||||
/* rs cache: */
|
/* rs cache: */
|
||||||
dwarf_reg_state_t buckets[DWARF_UNW_CACHE_SIZE];
|
dwarf_reg_state_t buckets[DWARF_UNW_CACHE_SIZE];
|
||||||
|
@ -361,74 +361,74 @@ struct unw_debug_frame_list
|
||||||
struct dwarf_callback_data
|
struct dwarf_callback_data
|
||||||
{
|
{
|
||||||
/* in: */
|
/* in: */
|
||||||
unw_word_t ip; /* instruction-pointer we're looking for */
|
unw_word_t ip; /* instruction-pointer we're looking for */
|
||||||
unw_proc_info_t *pi; /* proc-info pointer */
|
unw_proc_info_t *pi; /* proc-info pointer */
|
||||||
int need_unwind_info;
|
int need_unwind_info;
|
||||||
/* out: */
|
/* out: */
|
||||||
int single_fde; /* did we find a single FDE? (vs. a table) */
|
int single_fde; /* did we find a single FDE? (vs. a table) */
|
||||||
unw_dyn_info_t di; /* table info (if single_fde is false) */
|
unw_dyn_info_t di; /* table info (if single_fde is false) */
|
||||||
unw_dyn_info_t di_debug; /* additional table info for .debug_frame */
|
unw_dyn_info_t di_debug; /* additional table info for .debug_frame */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Convenience macros: */
|
/* Convenience macros: */
|
||||||
#define dwarf_init UNW_ARCH_OBJ (dwarf_init)
|
#define dwarf_init UNW_ARCH_OBJ (dwarf_init)
|
||||||
#define dwarf_callback UNW_OBJ (dwarf_callback)
|
#define dwarf_callback UNW_OBJ (dwarf_callback)
|
||||||
#define dwarf_find_proc_info UNW_OBJ (dwarf_find_proc_info)
|
#define dwarf_find_proc_info UNW_OBJ (dwarf_find_proc_info)
|
||||||
#define dwarf_find_debug_frame UNW_OBJ (dwarf_find_debug_frame)
|
#define dwarf_find_debug_frame UNW_OBJ (dwarf_find_debug_frame)
|
||||||
#define dwarf_search_unwind_table UNW_OBJ (dwarf_search_unwind_table)
|
#define dwarf_search_unwind_table UNW_OBJ (dwarf_search_unwind_table)
|
||||||
#define dwarf_find_unwind_table UNW_OBJ (dwarf_find_unwind_table)
|
#define dwarf_find_unwind_table UNW_OBJ (dwarf_find_unwind_table)
|
||||||
#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info)
|
#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info)
|
||||||
#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info)
|
#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info)
|
||||||
#define dwarf_eval_expr UNW_OBJ (dwarf_eval_expr)
|
#define dwarf_eval_expr UNW_OBJ (dwarf_eval_expr)
|
||||||
#define dwarf_extract_proc_info_from_fde \
|
#define dwarf_extract_proc_info_from_fde \
|
||||||
UNW_OBJ (dwarf_extract_proc_info_from_fde)
|
UNW_OBJ (dwarf_extract_proc_info_from_fde)
|
||||||
#define dwarf_find_save_locs UNW_OBJ (dwarf_find_save_locs)
|
#define dwarf_find_save_locs UNW_OBJ (dwarf_find_save_locs)
|
||||||
#define dwarf_create_state_record UNW_OBJ (dwarf_create_state_record)
|
#define dwarf_create_state_record UNW_OBJ (dwarf_create_state_record)
|
||||||
#define dwarf_make_proc_info UNW_OBJ (dwarf_make_proc_info)
|
#define dwarf_make_proc_info UNW_OBJ (dwarf_make_proc_info)
|
||||||
#define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer)
|
#define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer)
|
||||||
#define dwarf_step UNW_OBJ (dwarf_step)
|
#define dwarf_step UNW_OBJ (dwarf_step)
|
||||||
|
|
||||||
extern int dwarf_init (void);
|
extern int dwarf_init (void);
|
||||||
#ifndef UNW_REMOTE_ONLY
|
#ifndef UNW_REMOTE_ONLY
|
||||||
extern int dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr);
|
extern int dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr);
|
||||||
extern int dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
extern int dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||||
unw_proc_info_t *pi,
|
unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg);
|
int need_unwind_info, void *arg);
|
||||||
#endif /* !UNW_REMOTE_ONLY */
|
#endif /* !UNW_REMOTE_ONLY */
|
||||||
extern int dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug,
|
extern int dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug,
|
||||||
unw_word_t ip, unw_word_t segbase,
|
unw_word_t ip, unw_word_t segbase,
|
||||||
const char* obj_name, unw_word_t start,
|
const char* obj_name, unw_word_t start,
|
||||||
unw_word_t end);
|
unw_word_t end);
|
||||||
extern int dwarf_search_unwind_table (unw_addr_space_t as,
|
extern int dwarf_search_unwind_table (unw_addr_space_t as,
|
||||||
unw_word_t ip,
|
unw_word_t ip,
|
||||||
unw_dyn_info_t *di,
|
unw_dyn_info_t *di,
|
||||||
unw_proc_info_t *pi,
|
unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg);
|
int need_unwind_info, void *arg);
|
||||||
extern int dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
|
extern int dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
|
||||||
char *path, unw_word_t segbase, unw_word_t mapoff,
|
char *path, unw_word_t segbase, unw_word_t mapoff,
|
||||||
unw_word_t ip);
|
unw_word_t ip);
|
||||||
extern void dwarf_put_unwind_info (unw_addr_space_t as,
|
extern void dwarf_put_unwind_info (unw_addr_space_t as,
|
||||||
unw_proc_info_t *pi, void *arg);
|
unw_proc_info_t *pi, void *arg);
|
||||||
extern int dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr,
|
extern int dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr,
|
||||||
unw_word_t len, unw_word_t *valp,
|
unw_word_t len, unw_word_t *valp,
|
||||||
int *is_register);
|
int *is_register);
|
||||||
extern int dwarf_extract_proc_info_from_fde (unw_addr_space_t as,
|
extern int dwarf_extract_proc_info_from_fde (unw_addr_space_t as,
|
||||||
unw_accessors_t *a,
|
unw_accessors_t *a,
|
||||||
unw_word_t *fde_addr,
|
unw_word_t *fde_addr,
|
||||||
unw_proc_info_t *pi,
|
unw_proc_info_t *pi,
|
||||||
int need_unwind_info,
|
int need_unwind_info,
|
||||||
unw_word_t base,
|
unw_word_t base,
|
||||||
void *arg);
|
void *arg);
|
||||||
extern int dwarf_find_save_locs (struct dwarf_cursor *c);
|
extern int dwarf_find_save_locs (struct dwarf_cursor *c);
|
||||||
extern int dwarf_create_state_record (struct dwarf_cursor *c,
|
extern int dwarf_create_state_record (struct dwarf_cursor *c,
|
||||||
dwarf_state_record_t *sr);
|
dwarf_state_record_t *sr);
|
||||||
extern int dwarf_make_proc_info (struct dwarf_cursor *c);
|
extern int dwarf_make_proc_info (struct dwarf_cursor *c);
|
||||||
extern int dwarf_read_encoded_pointer (unw_addr_space_t as,
|
extern int dwarf_read_encoded_pointer (unw_addr_space_t as,
|
||||||
unw_accessors_t *a,
|
unw_accessors_t *a,
|
||||||
unw_word_t *addr,
|
unw_word_t *addr,
|
||||||
unsigned char encoding,
|
unsigned char encoding,
|
||||||
const unw_proc_info_t *pi,
|
const unw_proc_info_t *pi,
|
||||||
unw_word_t *valp, void *arg);
|
unw_word_t *valp, void *arg);
|
||||||
extern int dwarf_step (struct dwarf_cursor *c);
|
extern int dwarf_step (struct dwarf_cursor *c);
|
||||||
|
|
||||||
#endif /* dwarf_h */
|
#endif /* dwarf_h */
|
||||||
|
|
|
@ -16,10 +16,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef dwarf_to_unw_regnum
|
#ifndef dwarf_to_unw_regnum
|
||||||
# define dwarf_to_unw_regnum_map UNW_OBJ (dwarf_to_unw_regnum_map)
|
# define dwarf_to_unw_regnum_map UNW_OBJ (dwarf_to_unw_regnum_map)
|
||||||
extern const uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH];
|
extern const uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH];
|
||||||
/* REG is evaluated multiple times; it better be side-effects free! */
|
/* REG is evaluated multiple times; it better be side-effects free! */
|
||||||
# define dwarf_to_unw_regnum(reg) \
|
# define dwarf_to_unw_regnum(reg) \
|
||||||
(((reg) <= DWARF_REGNUM_MAP_LENGTH) ? dwarf_to_unw_regnum_map[reg] : 0)
|
(((reg) <= DWARF_REGNUM_MAP_LENGTH) ? dwarf_to_unw_regnum_map[reg] : 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ dwarf_misaligned_value_t;
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
int8_t *val, void *arg)
|
int8_t *val, void *arg)
|
||||||
{
|
{
|
||||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
int16_t *val, void *arg)
|
int16_t *val, void *arg)
|
||||||
{
|
{
|
||||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
int32_t *val, void *arg)
|
int32_t *val, void *arg)
|
||||||
{
|
{
|
||||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
int64_t *val, void *arg)
|
int64_t *val, void *arg)
|
||||||
{
|
{
|
||||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
uint8_t *val, void *arg)
|
uint8_t *val, void *arg)
|
||||||
{
|
{
|
||||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
uint16_t *val, void *arg)
|
uint16_t *val, void *arg)
|
||||||
{
|
{
|
||||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
uint32_t *val, void *arg)
|
uint32_t *val, void *arg)
|
||||||
{
|
{
|
||||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
uint64_t *val, void *arg)
|
uint64_t *val, void *arg)
|
||||||
{
|
{
|
||||||
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr;
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
uint8_t *valp, void *arg)
|
uint8_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
unw_word_t val, aligned_addr = *addr & -sizeof (unw_word_t);
|
unw_word_t val, aligned_addr = *addr & -sizeof (unw_word_t);
|
||||||
unw_word_t off = *addr - aligned_addr;
|
unw_word_t off = *addr - aligned_addr;
|
||||||
|
@ -153,7 +153,7 @@ dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
uint16_t *val, void *arg)
|
uint16_t *val, void *arg)
|
||||||
{
|
{
|
||||||
uint8_t v0, v1;
|
uint8_t v0, v1;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -171,7 +171,7 @@ dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
uint32_t *val, void *arg)
|
uint32_t *val, void *arg)
|
||||||
{
|
{
|
||||||
uint16_t v0, v1;
|
uint16_t v0, v1;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -189,7 +189,7 @@ dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
uint64_t *val, void *arg)
|
uint64_t *val, void *arg)
|
||||||
{
|
{
|
||||||
uint32_t v0, v1;
|
uint32_t v0, v1;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -207,7 +207,7 @@ dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
int8_t *val, void *arg)
|
int8_t *val, void *arg)
|
||||||
{
|
{
|
||||||
uint8_t uval;
|
uint8_t uval;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -220,7 +220,7 @@ dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
int16_t *val, void *arg)
|
int16_t *val, void *arg)
|
||||||
{
|
{
|
||||||
uint16_t uval;
|
uint16_t uval;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -233,7 +233,7 @@ dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
int32_t *val, void *arg)
|
int32_t *val, void *arg)
|
||||||
{
|
{
|
||||||
uint32_t uval;
|
uint32_t uval;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -246,7 +246,7 @@ dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
int64_t *val, void *arg)
|
int64_t *val, void *arg)
|
||||||
{
|
{
|
||||||
uint64_t uval;
|
uint64_t uval;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -261,7 +261,7 @@ dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
unw_word_t *val, void *arg)
|
unw_word_t *val, void *arg)
|
||||||
{
|
{
|
||||||
uint32_t u32;
|
uint32_t u32;
|
||||||
uint64_t u64;
|
uint64_t u64;
|
||||||
|
@ -272,14 +272,14 @@ dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
case 4:
|
case 4:
|
||||||
ret = dwarf_readu32 (as, a, addr, &u32, arg);
|
ret = dwarf_readu32 (as, a, addr, &u32, arg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
*val = u32;
|
*val = u32;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
ret = dwarf_readu64 (as, a, addr, &u64, arg);
|
ret = dwarf_readu64 (as, a, addr, &u64, arg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
*val = u64;
|
*val = u64;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_read_uleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_read_uleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
unw_word_t *valp, void *arg)
|
unw_word_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
unw_word_t val = 0, shift = 0;
|
unw_word_t val = 0, shift = 0;
|
||||||
unsigned char byte;
|
unsigned char byte;
|
||||||
|
@ -302,7 +302,7 @@ dwarf_read_uleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
val |= ((unw_word_t) byte & 0x7f) << shift;
|
val |= ((unw_word_t) byte & 0x7f) << shift;
|
||||||
shift += 7;
|
shift += 7;
|
||||||
|
@ -318,7 +318,7 @@ dwarf_read_uleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
unw_word_t *valp, void *arg)
|
unw_word_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
unw_word_t val = 0, shift = 0;
|
unw_word_t val = 0, shift = 0;
|
||||||
unsigned char byte;
|
unsigned char byte;
|
||||||
|
@ -327,7 +327,7 @@ dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
val |= ((unw_word_t) byte & 0x7f) << shift;
|
val |= ((unw_word_t) byte & 0x7f) << shift;
|
||||||
shift += 7;
|
shift += 7;
|
||||||
|
@ -344,9 +344,9 @@ dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static ALWAYS_INLINE int
|
static ALWAYS_INLINE int
|
||||||
dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
|
dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_word_t *addr, unsigned char encoding,
|
unw_word_t *addr, unsigned char encoding,
|
||||||
const unw_proc_info_t *pi,
|
const unw_proc_info_t *pi,
|
||||||
unw_word_t *valp, void *arg)
|
unw_word_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
unw_word_t val, initial_addr = *addr;
|
unw_word_t val, initial_addr = *addr;
|
||||||
uint16_t uval16;
|
uint16_t uval16;
|
||||||
|
@ -375,58 +375,58 @@ dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
{
|
{
|
||||||
case DW_EH_PE_ptr:
|
case DW_EH_PE_ptr:
|
||||||
if ((ret = dwarf_readw (as, a, addr, &val, arg)) < 0)
|
if ((ret = dwarf_readw (as, a, addr, &val, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_EH_PE_uleb128:
|
case DW_EH_PE_uleb128:
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
|
if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_EH_PE_udata2:
|
case DW_EH_PE_udata2:
|
||||||
if ((ret = dwarf_readu16 (as, a, addr, &uval16, arg)) < 0)
|
if ((ret = dwarf_readu16 (as, a, addr, &uval16, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
val = uval16;
|
val = uval16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_EH_PE_udata4:
|
case DW_EH_PE_udata4:
|
||||||
if ((ret = dwarf_readu32 (as, a, addr, &uval32, arg)) < 0)
|
if ((ret = dwarf_readu32 (as, a, addr, &uval32, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
val = uval32;
|
val = uval32;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_EH_PE_udata8:
|
case DW_EH_PE_udata8:
|
||||||
if ((ret = dwarf_readu64 (as, a, addr, &uval64, arg)) < 0)
|
if ((ret = dwarf_readu64 (as, a, addr, &uval64, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
val = uval64;
|
val = uval64;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_EH_PE_sleb128:
|
case DW_EH_PE_sleb128:
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
|
if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_EH_PE_sdata2:
|
case DW_EH_PE_sdata2:
|
||||||
if ((ret = dwarf_reads16 (as, a, addr, &sval16, arg)) < 0)
|
if ((ret = dwarf_reads16 (as, a, addr, &sval16, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
val = sval16;
|
val = sval16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_EH_PE_sdata4:
|
case DW_EH_PE_sdata4:
|
||||||
if ((ret = dwarf_reads32 (as, a, addr, &sval32, arg)) < 0)
|
if ((ret = dwarf_reads32 (as, a, addr, &sval32, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
val = sval32;
|
val = sval32;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_EH_PE_sdata8:
|
case DW_EH_PE_sdata8:
|
||||||
if ((ret = dwarf_reads64 (as, a, addr, &sval64, arg)) < 0)
|
if ((ret = dwarf_reads64 (as, a, addr, &sval64, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
val = sval64;
|
val = sval64;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Debug (1, "unexpected encoding format 0x%x\n",
|
Debug (1, "unexpected encoding format 0x%x\n",
|
||||||
encoding & DW_EH_PE_FORMAT_MASK);
|
encoding & DW_EH_PE_FORMAT_MASK);
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,7 +462,7 @@ dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
"segbase" member to unw_proc_info_t. */
|
"segbase" member to unw_proc_info_t. */
|
||||||
default:
|
default:
|
||||||
Debug (1, "unexpected application type 0x%x\n",
|
Debug (1, "unexpected application type 0x%x\n",
|
||||||
encoding & DW_EH_PE_APPL_MASK);
|
encoding & DW_EH_PE_APPL_MASK);
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,7 +480,7 @@ dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_word_t indirect_addr = val;
|
unw_word_t indirect_addr = val;
|
||||||
|
|
||||||
if ((ret = dwarf_readw (as, a, &indirect_addr, &val, arg)) < 0)
|
if ((ret = dwarf_readw (as, a, &indirect_addr, &val, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
*valp = val;
|
*valp = val;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2001-2004 Hewlett-Packard Co
|
Copyright (C) 2001-2004 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
Copyright (C) 2013 Linaro Limited
|
Copyright (C) 2013 Linaro Limited
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
@ -35,10 +35,10 @@ extern "C" {
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
|
|
||||||
#define UNW_TARGET aarch64
|
#define UNW_TARGET aarch64
|
||||||
#define UNW_TARGET_AARCH64 1
|
#define UNW_TARGET_AARCH64 1
|
||||||
|
|
||||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||||
|
|
||||||
/* This needs to be big enough to accommodate "struct cursor", while
|
/* This needs to be big enough to accommodate "struct cursor", while
|
||||||
leaving some slack for future expansion. Changing this value will
|
leaving some slack for future expansion. Changing this value will
|
||||||
|
@ -46,7 +46,7 @@ extern "C" {
|
||||||
relatively cheap and unwind-state copying is relatively rare, so we
|
relatively cheap and unwind-state copying is relatively rare, so we
|
||||||
want to err on making it rather too big than too small. */
|
want to err on making it rather too big than too small. */
|
||||||
|
|
||||||
#define UNW_TDEP_CURSOR_LEN 4096
|
#define UNW_TDEP_CURSOR_LEN 4096
|
||||||
|
|
||||||
typedef uint64_t unw_word_t;
|
typedef uint64_t unw_word_t;
|
||||||
typedef int64_t unw_sword_t;
|
typedef int64_t unw_sword_t;
|
||||||
|
@ -160,7 +160,7 @@ typedef enum
|
||||||
aarch64_regnum_t;
|
aarch64_regnum_t;
|
||||||
|
|
||||||
/* Use R0 through R3 to pass exception handling information. */
|
/* Use R0 through R3 to pass exception handling information. */
|
||||||
#define UNW_TDEP_NUM_EH_REGS 4
|
#define UNW_TDEP_NUM_EH_REGS 4
|
||||||
|
|
||||||
typedef struct unw_tdep_save_loc
|
typedef struct unw_tdep_save_loc
|
||||||
{
|
{
|
||||||
|
@ -176,7 +176,7 @@ typedef ucontext_t unw_tdep_context_t;
|
||||||
#include "libunwind-dynamic.h"
|
#include "libunwind-dynamic.h"
|
||||||
|
|
||||||
#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
|
#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
|
||||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||||
|
|
||||||
extern int unw_tdep_is_fpreg (int);
|
extern int unw_tdep_is_fpreg (int);
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,10 @@ extern "C" {
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define UNW_TARGET arm
|
#define UNW_TARGET arm
|
||||||
#define UNW_TARGET_ARM 1
|
#define UNW_TARGET_ARM 1
|
||||||
|
|
||||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||||
|
|
||||||
/* This needs to be big enough to accommodate "struct cursor", while
|
/* This needs to be big enough to accommodate "struct cursor", while
|
||||||
leaving some slack for future expansion. Changing this value will
|
leaving some slack for future expansion. Changing this value will
|
||||||
|
@ -44,7 +44,7 @@ extern "C" {
|
||||||
want to err on making it rather too big than too small. */
|
want to err on making it rather too big than too small. */
|
||||||
|
|
||||||
/* FIXME for ARM. Too big? What do other things use for similar tasks? */
|
/* FIXME for ARM. Too big? What do other things use for similar tasks? */
|
||||||
#define UNW_TDEP_CURSOR_LEN 4096
|
#define UNW_TDEP_CURSOR_LEN 4096
|
||||||
|
|
||||||
typedef uint32_t unw_word_t;
|
typedef uint32_t unw_word_t;
|
||||||
typedef int32_t unw_sword_t;
|
typedef int32_t unw_sword_t;
|
||||||
|
@ -242,7 +242,7 @@ typedef enum
|
||||||
}
|
}
|
||||||
arm_regnum_t;
|
arm_regnum_t;
|
||||||
|
|
||||||
#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for ARM. */
|
#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for ARM. */
|
||||||
|
|
||||||
typedef struct unw_tdep_save_loc
|
typedef struct unw_tdep_save_loc
|
||||||
{
|
{
|
||||||
|
@ -263,22 +263,22 @@ unw_tdep_context_t;
|
||||||
registers. FIXME: Not ideal, may not be sufficient for all libunwind
|
registers. FIXME: Not ideal, may not be sufficient for all libunwind
|
||||||
use cases. Stores pc+8, which is only approximately correct, really. */
|
use cases. Stores pc+8, which is only approximately correct, really. */
|
||||||
#ifndef __thumb__
|
#ifndef __thumb__
|
||||||
#define unw_tdep_getcontext(uc) (({ \
|
#define unw_tdep_getcontext(uc) (({ \
|
||||||
unw_tdep_context_t *unw_ctx = (uc); \
|
unw_tdep_context_t *unw_ctx = (uc); \
|
||||||
register unsigned long *unw_base asm ("r0") = unw_ctx->regs; \
|
register unsigned long *unw_base asm ("r0") = unw_ctx->regs; \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
"stmia %[base], {r0-r15}" \
|
"stmia %[base], {r0-r15}" \
|
||||||
: : [base] "r" (unw_base) : "memory"); \
|
: : [base] "r" (unw_base) : "memory"); \
|
||||||
}), 0)
|
}), 0)
|
||||||
#else /* __thumb__ */
|
#else /* __thumb__ */
|
||||||
#define unw_tdep_getcontext(uc) (({ \
|
#define unw_tdep_getcontext(uc) (({ \
|
||||||
unw_tdep_context_t *unw_ctx = (uc); \
|
unw_tdep_context_t *unw_ctx = (uc); \
|
||||||
register unsigned long *unw_base asm ("r0") = unw_ctx->regs; \
|
register unsigned long *unw_base asm ("r0") = unw_ctx->regs; \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
".align 2\nbx pc\nnop\n.code 32\n" \
|
".align 2\nbx pc\nnop\n.code 32\n" \
|
||||||
"stmia %[base], {r0-r15}\n" \
|
"stmia %[base], {r0-r15}\n" \
|
||||||
"orr %[base], pc, #1\nbx %[base]" \
|
"orr %[base], pc, #1\nbx %[base]" \
|
||||||
: [base] "+r" (unw_base) : : "memory", "cc"); \
|
: [base] "+r" (unw_base) : : "memory", "cc"); \
|
||||||
}), 0)
|
}), 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ unw_tdep_proc_info_t;
|
||||||
|
|
||||||
#include "libunwind-common.h"
|
#include "libunwind-common.h"
|
||||||
|
|
||||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||||
extern int unw_tdep_is_fpreg (int);
|
extern int unw_tdep_is_fpreg (int);
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
|
|
|
@ -46,22 +46,22 @@ extern pid_t _UCD_get_pid(struct UCD_info *);
|
||||||
extern int _UCD_get_cursig(struct UCD_info *);
|
extern int _UCD_get_cursig(struct UCD_info *);
|
||||||
extern int _UCD_add_backing_file_at_segment(struct UCD_info *, int phdr_no, const char *filename);
|
extern int _UCD_add_backing_file_at_segment(struct UCD_info *, int phdr_no, const char *filename);
|
||||||
extern int _UCD_add_backing_file_at_vaddr(struct UCD_info *,
|
extern int _UCD_add_backing_file_at_vaddr(struct UCD_info *,
|
||||||
unsigned long vaddr,
|
unsigned long vaddr,
|
||||||
const char *filename);
|
const char *filename);
|
||||||
|
|
||||||
extern int _UCD_find_proc_info (unw_addr_space_t, unw_word_t,
|
extern int _UCD_find_proc_info (unw_addr_space_t, unw_word_t,
|
||||||
unw_proc_info_t *, int, void *);
|
unw_proc_info_t *, int, void *);
|
||||||
extern void _UCD_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *);
|
extern void _UCD_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *);
|
||||||
extern int _UCD_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *,
|
extern int _UCD_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *,
|
||||||
void *);
|
void *);
|
||||||
extern int _UCD_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int,
|
extern int _UCD_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int,
|
||||||
void *);
|
void *);
|
||||||
extern int _UCD_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *,
|
extern int _UCD_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *,
|
||||||
int, void *);
|
int, void *);
|
||||||
extern int _UCD_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
|
extern int _UCD_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
|
||||||
int, void *);
|
int, void *);
|
||||||
extern int _UCD_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t,
|
extern int _UCD_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t,
|
||||||
unw_word_t *, void *);
|
unw_word_t *, void *);
|
||||||
extern int _UCD_resume (unw_addr_space_t, unw_cursor_t *, void *);
|
extern int _UCD_resume (unw_addr_space_t, unw_cursor_t *, void *);
|
||||||
extern unw_accessors_t _UCD_accessors;
|
extern unw_accessors_t _UCD_accessors;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2002-2004 Hewlett-Packard Co
|
Copyright (C) 2002-2004 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -59,50 +59,50 @@ the following rules should be followed in declaring these structures:
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
UNW_DYN_STOP = 0, /* end-of-unwind-info marker */
|
UNW_DYN_STOP = 0, /* end-of-unwind-info marker */
|
||||||
UNW_DYN_SAVE_REG, /* save register to another register */
|
UNW_DYN_SAVE_REG, /* save register to another register */
|
||||||
UNW_DYN_SPILL_FP_REL, /* frame-pointer-relative register spill */
|
UNW_DYN_SPILL_FP_REL, /* frame-pointer-relative register spill */
|
||||||
UNW_DYN_SPILL_SP_REL, /* stack-pointer-relative register spill */
|
UNW_DYN_SPILL_SP_REL, /* stack-pointer-relative register spill */
|
||||||
UNW_DYN_ADD, /* add constant value to a register */
|
UNW_DYN_ADD, /* add constant value to a register */
|
||||||
UNW_DYN_POP_FRAMES, /* drop one or more stack frames */
|
UNW_DYN_POP_FRAMES, /* drop one or more stack frames */
|
||||||
UNW_DYN_LABEL_STATE, /* name the current state */
|
UNW_DYN_LABEL_STATE, /* name the current state */
|
||||||
UNW_DYN_COPY_STATE, /* set the region's entry-state */
|
UNW_DYN_COPY_STATE, /* set the region's entry-state */
|
||||||
UNW_DYN_ALIAS /* get unwind info from an alias */
|
UNW_DYN_ALIAS /* get unwind info from an alias */
|
||||||
}
|
}
|
||||||
unw_dyn_operation_t;
|
unw_dyn_operation_t;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */
|
UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */
|
||||||
UNW_INFO_FORMAT_TABLE, /* unw_dyn_table_t */
|
UNW_INFO_FORMAT_TABLE, /* unw_dyn_table_t */
|
||||||
UNW_INFO_FORMAT_REMOTE_TABLE, /* unw_dyn_remote_table_t */
|
UNW_INFO_FORMAT_REMOTE_TABLE, /* unw_dyn_remote_table_t */
|
||||||
UNW_INFO_FORMAT_ARM_EXIDX /* ARM specific unwind info */
|
UNW_INFO_FORMAT_ARM_EXIDX /* ARM specific unwind info */
|
||||||
}
|
}
|
||||||
unw_dyn_info_format_t;
|
unw_dyn_info_format_t;
|
||||||
|
|
||||||
typedef struct unw_dyn_op
|
typedef struct unw_dyn_op
|
||||||
{
|
{
|
||||||
int8_t tag; /* what operation? */
|
int8_t tag; /* what operation? */
|
||||||
int8_t qp; /* qualifying predicate register */
|
int8_t qp; /* qualifying predicate register */
|
||||||
int16_t reg; /* what register */
|
int16_t reg; /* what register */
|
||||||
int32_t when; /* when does it take effect? */
|
int32_t when; /* when does it take effect? */
|
||||||
unw_word_t val; /* auxiliary value */
|
unw_word_t val; /* auxiliary value */
|
||||||
}
|
}
|
||||||
unw_dyn_op_t;
|
unw_dyn_op_t;
|
||||||
|
|
||||||
typedef struct unw_dyn_region_info
|
typedef struct unw_dyn_region_info
|
||||||
{
|
{
|
||||||
struct unw_dyn_region_info *next; /* linked list of regions */
|
struct unw_dyn_region_info *next; /* linked list of regions */
|
||||||
int32_t insn_count; /* region length (# of instructions) */
|
int32_t insn_count; /* region length (# of instructions) */
|
||||||
uint32_t op_count; /* length of op-array */
|
uint32_t op_count; /* length of op-array */
|
||||||
unw_dyn_op_t op[1]; /* variable-length op-array */
|
unw_dyn_op_t op[1]; /* variable-length op-array */
|
||||||
}
|
}
|
||||||
unw_dyn_region_info_t;
|
unw_dyn_region_info_t;
|
||||||
|
|
||||||
typedef struct unw_dyn_proc_info
|
typedef struct unw_dyn_proc_info
|
||||||
{
|
{
|
||||||
unw_word_t name_ptr; /* address of human-readable procedure name */
|
unw_word_t name_ptr; /* address of human-readable procedure name */
|
||||||
unw_word_t handler; /* address of personality routine */
|
unw_word_t handler; /* address of personality routine */
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
int32_t pad0;
|
int32_t pad0;
|
||||||
unw_dyn_region_info_t *regions;
|
unw_dyn_region_info_t *regions;
|
||||||
|
@ -111,18 +111,18 @@ unw_dyn_proc_info_t;
|
||||||
|
|
||||||
typedef struct unw_dyn_table_info
|
typedef struct unw_dyn_table_info
|
||||||
{
|
{
|
||||||
unw_word_t name_ptr; /* addr. of table name (e.g., library name) */
|
unw_word_t name_ptr; /* addr. of table name (e.g., library name) */
|
||||||
unw_word_t segbase; /* segment base */
|
unw_word_t segbase; /* segment base */
|
||||||
unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */
|
unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */
|
||||||
unw_word_t *table_data;
|
unw_word_t *table_data;
|
||||||
}
|
}
|
||||||
unw_dyn_table_info_t;
|
unw_dyn_table_info_t;
|
||||||
|
|
||||||
typedef struct unw_dyn_remote_table_info
|
typedef struct unw_dyn_remote_table_info
|
||||||
{
|
{
|
||||||
unw_word_t name_ptr; /* addr. of table name (e.g., library name) */
|
unw_word_t name_ptr; /* addr. of table name (e.g., library name) */
|
||||||
unw_word_t segbase; /* segment base */
|
unw_word_t segbase; /* segment base */
|
||||||
unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */
|
unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */
|
||||||
unw_word_t table_data;
|
unw_word_t table_data;
|
||||||
}
|
}
|
||||||
unw_dyn_remote_table_info_t;
|
unw_dyn_remote_table_info_t;
|
||||||
|
@ -132,16 +132,16 @@ typedef struct unw_dyn_info
|
||||||
/* doubly-linked list of dyn-info structures: */
|
/* doubly-linked list of dyn-info structures: */
|
||||||
struct unw_dyn_info *next;
|
struct unw_dyn_info *next;
|
||||||
struct unw_dyn_info *prev;
|
struct unw_dyn_info *prev;
|
||||||
unw_word_t start_ip; /* first IP covered by this entry */
|
unw_word_t start_ip; /* first IP covered by this entry */
|
||||||
unw_word_t end_ip; /* first IP NOT covered by this entry */
|
unw_word_t end_ip; /* first IP NOT covered by this entry */
|
||||||
unw_word_t gp; /* global-pointer in effect for this entry */
|
unw_word_t gp; /* global-pointer in effect for this entry */
|
||||||
int32_t format; /* real type: unw_dyn_info_format_t */
|
int32_t format; /* real type: unw_dyn_info_format_t */
|
||||||
int32_t pad;
|
int32_t pad;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
unw_dyn_proc_info_t pi;
|
unw_dyn_proc_info_t pi;
|
||||||
unw_dyn_table_info_t ti;
|
unw_dyn_table_info_t ti;
|
||||||
unw_dyn_remote_table_info_t rti;
|
unw_dyn_remote_table_info_t rti;
|
||||||
}
|
}
|
||||||
u;
|
u;
|
||||||
}
|
}
|
||||||
|
@ -157,9 +157,9 @@ unw_dyn_info_list_t;
|
||||||
|
|
||||||
/* Return the size (in bytes) of an unw_dyn_region_info_t structure that can
|
/* Return the size (in bytes) of an unw_dyn_region_info_t structure that can
|
||||||
hold OP_COUNT ops. */
|
hold OP_COUNT ops. */
|
||||||
#define _U_dyn_region_info_size(op_count) \
|
#define _U_dyn_region_info_size(op_count) \
|
||||||
((char *) (((unw_dyn_region_info_t *) NULL)->op + (op_count)) \
|
((char *) (((unw_dyn_region_info_t *) NULL)->op + (op_count)) \
|
||||||
- (char *) NULL)
|
- (char *) NULL)
|
||||||
|
|
||||||
/* Register the unwind info for a single procedure.
|
/* Register the unwind info for a single procedure.
|
||||||
This routine is NOT signal-safe. */
|
This routine is NOT signal-safe. */
|
||||||
|
@ -172,39 +172,39 @@ extern void _U_dyn_cancel (unw_dyn_info_t *);
|
||||||
|
|
||||||
/* Convenience routines. */
|
/* Convenience routines. */
|
||||||
|
|
||||||
#define _U_dyn_op(_tag, _qp, _when, _reg, _val) \
|
#define _U_dyn_op(_tag, _qp, _when, _reg, _val) \
|
||||||
((unw_dyn_op_t) { (_tag), (_qp), (_reg), (_when), (_val) })
|
((unw_dyn_op_t) { (_tag), (_qp), (_reg), (_when), (_val) })
|
||||||
|
|
||||||
#define _U_dyn_op_save_reg(op, qp, when, reg, dst) \
|
#define _U_dyn_op_save_reg(op, qp, when, reg, dst) \
|
||||||
(*(op) = _U_dyn_op (UNW_DYN_SAVE_REG, (qp), (when), (reg), (dst)))
|
(*(op) = _U_dyn_op (UNW_DYN_SAVE_REG, (qp), (when), (reg), (dst)))
|
||||||
|
|
||||||
#define _U_dyn_op_spill_fp_rel(op, qp, when, reg, offset) \
|
#define _U_dyn_op_spill_fp_rel(op, qp, when, reg, offset) \
|
||||||
(*(op) = _U_dyn_op (UNW_DYN_SPILL_FP_REL, (qp), (when), (reg), \
|
(*(op) = _U_dyn_op (UNW_DYN_SPILL_FP_REL, (qp), (when), (reg), \
|
||||||
(offset)))
|
(offset)))
|
||||||
|
|
||||||
#define _U_dyn_op_spill_sp_rel(op, qp, when, reg, offset) \
|
#define _U_dyn_op_spill_sp_rel(op, qp, when, reg, offset) \
|
||||||
(*(op) = _U_dyn_op (UNW_DYN_SPILL_SP_REL, (qp), (when), (reg), \
|
(*(op) = _U_dyn_op (UNW_DYN_SPILL_SP_REL, (qp), (when), (reg), \
|
||||||
(offset)))
|
(offset)))
|
||||||
|
|
||||||
#define _U_dyn_op_add(op, qp, when, reg, value) \
|
#define _U_dyn_op_add(op, qp, when, reg, value) \
|
||||||
(*(op) = _U_dyn_op (UNW_DYN_ADD, (qp), (when), (reg), (value)))
|
(*(op) = _U_dyn_op (UNW_DYN_ADD, (qp), (when), (reg), (value)))
|
||||||
|
|
||||||
#define _U_dyn_op_pop_frames(op, qp, when, num_frames) \
|
#define _U_dyn_op_pop_frames(op, qp, when, num_frames) \
|
||||||
(*(op) = _U_dyn_op (UNW_DYN_POP_FRAMES, (qp), (when), 0, (num_frames)))
|
(*(op) = _U_dyn_op (UNW_DYN_POP_FRAMES, (qp), (when), 0, (num_frames)))
|
||||||
|
|
||||||
#define _U_dyn_op_label_state(op, label) \
|
#define _U_dyn_op_label_state(op, label) \
|
||||||
(*(op) = _U_dyn_op (UNW_DYN_LABEL_STATE, _U_QP_TRUE, -1, 0, (label)))
|
(*(op) = _U_dyn_op (UNW_DYN_LABEL_STATE, _U_QP_TRUE, -1, 0, (label)))
|
||||||
|
|
||||||
#define _U_dyn_op_copy_state(op, label) \
|
#define _U_dyn_op_copy_state(op, label) \
|
||||||
(*(op) = _U_dyn_op (UNW_DYN_COPY_STATE, _U_QP_TRUE, -1, 0, (label)))
|
(*(op) = _U_dyn_op (UNW_DYN_COPY_STATE, _U_QP_TRUE, -1, 0, (label)))
|
||||||
|
|
||||||
#define _U_dyn_op_alias(op, qp, when, addr) \
|
#define _U_dyn_op_alias(op, qp, when, addr) \
|
||||||
(*(op) = _U_dyn_op (UNW_DYN_ALIAS, (qp), (when), 0, (addr)))
|
(*(op) = _U_dyn_op (UNW_DYN_ALIAS, (qp), (when), 0, (addr)))
|
||||||
|
|
||||||
#define _U_dyn_op_stop(op) \
|
#define _U_dyn_op_stop(op) \
|
||||||
(*(op) = _U_dyn_op (UNW_DYN_STOP, _U_QP_TRUE, -1, 0, 0))
|
(*(op) = _U_dyn_op (UNW_DYN_STOP, _U_QP_TRUE, -1, 0, 0))
|
||||||
|
|
||||||
/* The target-dependent qualifying predicate which is always TRUE. On
|
/* The target-dependent qualifying predicate which is always TRUE. On
|
||||||
IA-64, that's p0 (0), on non-predicated architectures, the value is
|
IA-64, that's p0 (0), on non-predicated architectures, the value is
|
||||||
ignored. */
|
ignored. */
|
||||||
#define _U_QP_TRUE _U_TDEP_QP_TRUE
|
#define _U_QP_TRUE _U_TDEP_QP_TRUE
|
||||||
|
|
|
@ -32,17 +32,17 @@ extern "C" {
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
|
|
||||||
#define UNW_TARGET hppa
|
#define UNW_TARGET hppa
|
||||||
#define UNW_TARGET_HPPA 1
|
#define UNW_TARGET_HPPA 1
|
||||||
|
|
||||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||||
|
|
||||||
/* This needs to be big enough to accommodate "struct cursor", while
|
/* This needs to be big enough to accommodate "struct cursor", while
|
||||||
leaving some slack for future expansion. Changing this value will
|
leaving some slack for future expansion. Changing this value will
|
||||||
require recompiling all users of this library. Stack allocation is
|
require recompiling all users of this library. Stack allocation is
|
||||||
relatively cheap and unwind-state copying is relatively rare, so we
|
relatively cheap and unwind-state copying is relatively rare, so we
|
||||||
want to err on making it rather too big than too small. */
|
want to err on making it rather too big than too small. */
|
||||||
#define UNW_TDEP_CURSOR_LEN 511
|
#define UNW_TDEP_CURSOR_LEN 511
|
||||||
|
|
||||||
typedef uint32_t unw_word_t;
|
typedef uint32_t unw_word_t;
|
||||||
typedef int32_t unw_sword_t;
|
typedef int32_t unw_sword_t;
|
||||||
|
@ -61,13 +61,13 @@ typedef enum
|
||||||
implementation of the C++ exception handling ABI. See
|
implementation of the C++ exception handling ABI. See
|
||||||
_Unwind_SetGR() and _Unwind_GetGR() for details. */
|
_Unwind_SetGR() and _Unwind_GetGR() for details. */
|
||||||
UNW_HPPA_GR = 0,
|
UNW_HPPA_GR = 0,
|
||||||
UNW_HPPA_RP = 2, /* return pointer */
|
UNW_HPPA_RP = 2, /* return pointer */
|
||||||
UNW_HPPA_FP = 3, /* frame pointer */
|
UNW_HPPA_FP = 3, /* frame pointer */
|
||||||
UNW_HPPA_SP = UNW_HPPA_GR + 30,
|
UNW_HPPA_SP = UNW_HPPA_GR + 30,
|
||||||
|
|
||||||
UNW_HPPA_FR = UNW_HPPA_GR + 32,
|
UNW_HPPA_FR = UNW_HPPA_GR + 32,
|
||||||
|
|
||||||
UNW_HPPA_IP = UNW_HPPA_FR + 32, /* instruction pointer */
|
UNW_HPPA_IP = UNW_HPPA_FR + 32, /* instruction pointer */
|
||||||
|
|
||||||
/* other "preserved" registers (fpsr etc.)... */
|
/* other "preserved" registers (fpsr etc.)... */
|
||||||
|
|
||||||
|
@ -76,10 +76,10 @@ typedef enum
|
||||||
exception-handling registers which we then alias to the actual
|
exception-handling registers which we then alias to the actual
|
||||||
physical register. */
|
physical register. */
|
||||||
|
|
||||||
UNW_HPPA_EH0 = UNW_HPPA_IP + 1, /* alias for UNW_HPPA_GR + 20 */
|
UNW_HPPA_EH0 = UNW_HPPA_IP + 1, /* alias for UNW_HPPA_GR + 20 */
|
||||||
UNW_HPPA_EH1 = UNW_HPPA_EH0 + 1, /* alias for UNW_HPPA_GR + 21 */
|
UNW_HPPA_EH1 = UNW_HPPA_EH0 + 1, /* alias for UNW_HPPA_GR + 21 */
|
||||||
UNW_HPPA_EH2 = UNW_HPPA_EH1 + 1, /* alias for UNW_HPPA_GR + 22 */
|
UNW_HPPA_EH2 = UNW_HPPA_EH1 + 1, /* alias for UNW_HPPA_GR + 22 */
|
||||||
UNW_HPPA_EH3 = UNW_HPPA_EH2 + 1, /* alias for UNW_HPPA_GR + 31 */
|
UNW_HPPA_EH3 = UNW_HPPA_EH2 + 1, /* alias for UNW_HPPA_GR + 31 */
|
||||||
|
|
||||||
/* frame info (read-only) */
|
/* frame info (read-only) */
|
||||||
UNW_HPPA_CFA,
|
UNW_HPPA_CFA,
|
||||||
|
@ -92,7 +92,7 @@ typedef enum
|
||||||
}
|
}
|
||||||
hppa_regnum_t;
|
hppa_regnum_t;
|
||||||
|
|
||||||
#define UNW_TDEP_NUM_EH_REGS 4
|
#define UNW_TDEP_NUM_EH_REGS 4
|
||||||
|
|
||||||
typedef struct unw_tdep_save_loc
|
typedef struct unw_tdep_save_loc
|
||||||
{
|
{
|
||||||
|
@ -103,7 +103,7 @@ unw_tdep_save_loc_t;
|
||||||
/* On PA-RISC, we can directly use ucontext_t as the unwind context. */
|
/* On PA-RISC, we can directly use ucontext_t as the unwind context. */
|
||||||
typedef ucontext_t unw_tdep_context_t;
|
typedef ucontext_t unw_tdep_context_t;
|
||||||
|
|
||||||
#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_HPPA_FR) < 32)
|
#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_HPPA_FR) < 32)
|
||||||
|
|
||||||
#include "libunwind-dynamic.h"
|
#include "libunwind-dynamic.h"
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ unw_tdep_proc_info_t;
|
||||||
|
|
||||||
#include "libunwind-common.h"
|
#include "libunwind-common.h"
|
||||||
|
|
||||||
#define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext)
|
#define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext)
|
||||||
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2001-2004 Hewlett-Packard Co
|
Copyright (C) 2001-2004 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -47,24 +47,24 @@ extern "C" {
|
||||||
# define UNW_GENERIC_ONLY
|
# define UNW_GENERIC_ONLY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define UNW_TARGET ia64
|
#define UNW_TARGET ia64
|
||||||
#define UNW_TARGET_IA64 1
|
#define UNW_TARGET_IA64 1
|
||||||
|
|
||||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||||
|
|
||||||
/* This needs to be big enough to accommodate "struct cursor", while
|
/* This needs to be big enough to accommodate "struct cursor", while
|
||||||
leaving some slack for future expansion. Changing this value will
|
leaving some slack for future expansion. Changing this value will
|
||||||
require recompiling all users of this library. Stack allocation is
|
require recompiling all users of this library. Stack allocation is
|
||||||
relatively cheap and unwind-state copying is relatively rare, so we
|
relatively cheap and unwind-state copying is relatively rare, so we
|
||||||
want to err on making it rather too big than too small. */
|
want to err on making it rather too big than too small. */
|
||||||
#define UNW_TDEP_CURSOR_LEN 511
|
#define UNW_TDEP_CURSOR_LEN 511
|
||||||
|
|
||||||
/* If this bit is it indicates that the procedure saved all of ar.bsp,
|
/* If this bit is it indicates that the procedure saved all of ar.bsp,
|
||||||
ar.bspstore, and ar.rnat. If, additionally, ar.bsp != saved ar.bsp,
|
ar.bspstore, and ar.rnat. If, additionally, ar.bsp != saved ar.bsp,
|
||||||
then this procedure has performed a register-backing-store switch. */
|
then this procedure has performed a register-backing-store switch. */
|
||||||
#define UNW_PI_FLAG_IA64_RBS_SWITCH_BIT (UNW_PI_FLAG_FIRST_TDEP_BIT + 0)
|
#define UNW_PI_FLAG_IA64_RBS_SWITCH_BIT (UNW_PI_FLAG_FIRST_TDEP_BIT + 0)
|
||||||
|
|
||||||
#define UNW_PI_FLAG_IA64_RBS_SWITCH (1 << UNW_PI_FLAG_IA64_RBS_SWITCH_BIT)
|
#define UNW_PI_FLAG_IA64_RBS_SWITCH (1 << UNW_PI_FLAG_IA64_RBS_SWITCH_BIT)
|
||||||
|
|
||||||
typedef uint64_t unw_word_t;
|
typedef uint64_t unw_word_t;
|
||||||
typedef int64_t unw_sword_t;
|
typedef int64_t unw_sword_t;
|
||||||
|
@ -76,7 +76,7 @@ typedef int64_t unw_sword_t;
|
||||||
typedef union
|
typedef union
|
||||||
{
|
{
|
||||||
struct { unw_word_t bits[2]; } raw;
|
struct { unw_word_t bits[2]; } raw;
|
||||||
long double dummy; /* dummy to force 16-byte alignment */
|
long double dummy; /* dummy to force 16-byte alignment */
|
||||||
}
|
}
|
||||||
unw_tdep_fpreg_t;
|
unw_tdep_fpreg_t;
|
||||||
|
|
||||||
|
@ -92,15 +92,15 @@ typedef enum
|
||||||
This convention facilitates architecture-independent
|
This convention facilitates architecture-independent
|
||||||
implementation of the C++ exception handling ABI. See
|
implementation of the C++ exception handling ABI. See
|
||||||
_Unwind_SetGR() and _Unwind_GetGR() for details. */
|
_Unwind_SetGR() and _Unwind_GetGR() for details. */
|
||||||
UNW_IA64_GR = 0, /* general registers (r0..r127) */
|
UNW_IA64_GR = 0, /* general registers (r0..r127) */
|
||||||
UNW_IA64_GP = UNW_IA64_GR + 1,
|
UNW_IA64_GP = UNW_IA64_GR + 1,
|
||||||
UNW_IA64_TP = UNW_IA64_GR + 13,
|
UNW_IA64_TP = UNW_IA64_GR + 13,
|
||||||
|
|
||||||
UNW_IA64_NAT = UNW_IA64_GR + 128, /* NaT registers (nat0..nat127) */
|
UNW_IA64_NAT = UNW_IA64_GR + 128, /* NaT registers (nat0..nat127) */
|
||||||
|
|
||||||
UNW_IA64_FR = UNW_IA64_NAT + 128, /* fp registers (f0..f127) */
|
UNW_IA64_FR = UNW_IA64_NAT + 128, /* fp registers (f0..f127) */
|
||||||
|
|
||||||
UNW_IA64_AR = UNW_IA64_FR + 128, /* application registers (ar0..r127) */
|
UNW_IA64_AR = UNW_IA64_FR + 128, /* application registers (ar0..r127) */
|
||||||
UNW_IA64_AR_RSC = UNW_IA64_AR + 16,
|
UNW_IA64_AR_RSC = UNW_IA64_AR + 16,
|
||||||
UNW_IA64_AR_BSP = UNW_IA64_AR + 17,
|
UNW_IA64_AR_BSP = UNW_IA64_AR + 17,
|
||||||
UNW_IA64_AR_BSPSTORE = UNW_IA64_AR + 18,
|
UNW_IA64_AR_BSPSTORE = UNW_IA64_AR + 18,
|
||||||
|
@ -115,9 +115,9 @@ typedef enum
|
||||||
UNW_IA64_AR_LC = UNW_IA64_AR + 65,
|
UNW_IA64_AR_LC = UNW_IA64_AR + 65,
|
||||||
UNW_IA64_AR_EC = UNW_IA64_AR + 66,
|
UNW_IA64_AR_EC = UNW_IA64_AR + 66,
|
||||||
|
|
||||||
UNW_IA64_BR = UNW_IA64_AR + 128, /* branch registers (b0..p7) */
|
UNW_IA64_BR = UNW_IA64_AR + 128, /* branch registers (b0..p7) */
|
||||||
UNW_IA64_RP = UNW_IA64_BR + 0, /* return pointer (rp) */
|
UNW_IA64_RP = UNW_IA64_BR + 0, /* return pointer (rp) */
|
||||||
UNW_IA64_PR = UNW_IA64_BR + 8, /* predicate registers (p0..p63) */
|
UNW_IA64_PR = UNW_IA64_BR + 8, /* predicate registers (p0..p63) */
|
||||||
UNW_IA64_CFM,
|
UNW_IA64_CFM,
|
||||||
|
|
||||||
/* frame info: */
|
/* frame info: */
|
||||||
|
@ -133,7 +133,7 @@ typedef enum
|
||||||
}
|
}
|
||||||
ia64_regnum_t;
|
ia64_regnum_t;
|
||||||
|
|
||||||
#define UNW_TDEP_NUM_EH_REGS 4 /* r15-r18 are exception args */
|
#define UNW_TDEP_NUM_EH_REGS 4 /* r15-r18 are exception args */
|
||||||
|
|
||||||
typedef struct unw_tdep_save_loc
|
typedef struct unw_tdep_save_loc
|
||||||
{
|
{
|
||||||
|
@ -150,7 +150,7 @@ unw_tdep_save_loc_t;
|
||||||
/* On IA-64, we can directly use ucontext_t as the unwind context. */
|
/* On IA-64, we can directly use ucontext_t as the unwind context. */
|
||||||
typedef ucontext_t unw_tdep_context_t;
|
typedef ucontext_t unw_tdep_context_t;
|
||||||
|
|
||||||
#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_IA64_FR) < 128)
|
#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_IA64_FR) < 128)
|
||||||
|
|
||||||
#include "libunwind-dynamic.h"
|
#include "libunwind-dynamic.h"
|
||||||
#include "libunwind-common.h"
|
#include "libunwind-common.h"
|
||||||
|
@ -159,9 +159,9 @@ typedef ucontext_t unw_tdep_context_t;
|
||||||
/* In theory, we could use _Uia64_getcontext() on HP-UX as well, but
|
/* In theory, we could use _Uia64_getcontext() on HP-UX as well, but
|
||||||
the benefit of doing so would be marginal given that it can't
|
the benefit of doing so would be marginal given that it can't
|
||||||
support UNW_LOCAL_ONLY. */
|
support UNW_LOCAL_ONLY. */
|
||||||
# define unw_tdep_getcontext getcontext
|
# define unw_tdep_getcontext getcontext
|
||||||
#else
|
#else
|
||||||
# define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext)
|
# define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext)
|
||||||
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -171,17 +171,17 @@ typedef ucontext_t unw_tdep_context_t;
|
||||||
with malloc(), and should be free()d during the put_unwind_info()
|
with malloc(), and should be free()d during the put_unwind_info()
|
||||||
callback. This routine is signal-safe for the local-address-space
|
callback. This routine is signal-safe for the local-address-space
|
||||||
case ONLY. */
|
case ONLY. */
|
||||||
#define unw_search_ia64_unwind_table UNW_OBJ(search_unwind_table)
|
#define unw_search_ia64_unwind_table UNW_OBJ(search_unwind_table)
|
||||||
extern int unw_search_ia64_unwind_table (unw_addr_space_t, unw_word_t,
|
extern int unw_search_ia64_unwind_table (unw_addr_space_t, unw_word_t,
|
||||||
unw_dyn_info_t *, unw_proc_info_t *,
|
unw_dyn_info_t *, unw_proc_info_t *,
|
||||||
int, void *);
|
int, void *);
|
||||||
|
|
||||||
/* This is a helper routine which the get_dyn_info_list_addr()
|
/* This is a helper routine which the get_dyn_info_list_addr()
|
||||||
callback can use to locate the special dynamic-info list entry in
|
callback can use to locate the special dynamic-info list entry in
|
||||||
an IA-64 unwind table. If the entry exists in the table, the
|
an IA-64 unwind table. If the entry exists in the table, the
|
||||||
list-address is returned. In all other cases, 0 is returned. */
|
list-address is returned. In all other cases, 0 is returned. */
|
||||||
extern unw_word_t _Uia64_find_dyn_list (unw_addr_space_t, unw_dyn_info_t *,
|
extern unw_word_t _Uia64_find_dyn_list (unw_addr_space_t, unw_dyn_info_t *,
|
||||||
void *);
|
void *);
|
||||||
|
|
||||||
/* This is a helper routine to obtain the kernel-unwind info. It is
|
/* This is a helper routine to obtain the kernel-unwind info. It is
|
||||||
signal-safe. */
|
signal-safe. */
|
||||||
|
|
|
@ -36,10 +36,10 @@ extern "C" {
|
||||||
# undef mips
|
# undef mips
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define UNW_TARGET mips
|
#define UNW_TARGET mips
|
||||||
#define UNW_TARGET_MIPS 1
|
#define UNW_TARGET_MIPS 1
|
||||||
|
|
||||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||||
|
|
||||||
/* This needs to be big enough to accommodate "struct cursor", while
|
/* This needs to be big enough to accommodate "struct cursor", while
|
||||||
leaving some slack for future expansion. Changing this value will
|
leaving some slack for future expansion. Changing this value will
|
||||||
|
@ -48,7 +48,7 @@ extern "C" {
|
||||||
want to err on making it rather too big than too small. */
|
want to err on making it rather too big than too small. */
|
||||||
|
|
||||||
/* FIXME for MIPS. Too big? What do other things use for similar tasks? */
|
/* FIXME for MIPS. Too big? What do other things use for similar tasks? */
|
||||||
#define UNW_TDEP_CURSOR_LEN 4096
|
#define UNW_TDEP_CURSOR_LEN 4096
|
||||||
|
|
||||||
/* The size of a "word" varies on MIPS. This type is used for memory
|
/* The size of a "word" varies on MIPS. This type is used for memory
|
||||||
addresses and register values. To allow a single library to support
|
addresses and register values. To allow a single library to support
|
||||||
|
@ -119,7 +119,7 @@ typedef enum
|
||||||
}
|
}
|
||||||
mips_abi_t;
|
mips_abi_t;
|
||||||
|
|
||||||
#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for MIPS. */
|
#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for MIPS. */
|
||||||
|
|
||||||
typedef struct unw_tdep_save_loc
|
typedef struct unw_tdep_save_loc
|
||||||
{
|
{
|
||||||
|
@ -147,7 +147,7 @@ unw_tdep_proc_info_t;
|
||||||
#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
|
#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
|
||||||
extern int unw_tdep_getcontext (ucontext_t *uc);
|
extern int unw_tdep_getcontext (ucontext_t *uc);
|
||||||
|
|
||||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||||
extern int unw_tdep_is_fpreg (int);
|
extern int unw_tdep_is_fpreg (int);
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
|
|
|
@ -39,10 +39,10 @@ extern "C" {
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
|
|
||||||
#define UNW_TARGET ppc32
|
#define UNW_TARGET ppc32
|
||||||
#define UNW_TARGET_PPC32 1
|
#define UNW_TARGET_PPC32 1
|
||||||
|
|
||||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This needs to be big enough to accommodate "struct cursor", while
|
* This needs to be big enough to accommodate "struct cursor", while
|
||||||
|
@ -170,7 +170,7 @@ ppc32_regnum_t;
|
||||||
* passing parameters to exception handlers.
|
* passing parameters to exception handlers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define UNW_TDEP_NUM_EH_REGS 4
|
#define UNW_TDEP_NUM_EH_REGS 4
|
||||||
|
|
||||||
typedef struct unw_tdep_save_loc
|
typedef struct unw_tdep_save_loc
|
||||||
{
|
{
|
||||||
|
@ -185,7 +185,7 @@ typedef ucontext_t unw_tdep_context_t;
|
||||||
using the "getcontext" name just because it's using libunwind. We
|
using the "getcontext" name just because it's using libunwind. We
|
||||||
can't just use __getcontext() either, because that isn't exported
|
can't just use __getcontext() either, because that isn't exported
|
||||||
by glibc... */
|
by glibc... */
|
||||||
#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
|
#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
|
||||||
|
|
||||||
#include "libunwind-dynamic.h"
|
#include "libunwind-dynamic.h"
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ unw_tdep_proc_info_t;
|
||||||
|
|
||||||
#include "libunwind-common.h"
|
#include "libunwind-common.h"
|
||||||
|
|
||||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||||
extern int unw_tdep_is_fpreg (int);
|
extern int unw_tdep_is_fpreg (int);
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
|
|
|
@ -39,10 +39,10 @@ extern "C" {
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
|
|
||||||
#define UNW_TARGET ppc64
|
#define UNW_TARGET ppc64
|
||||||
#define UNW_TARGET_PPC64 1
|
#define UNW_TARGET_PPC64 1
|
||||||
|
|
||||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This needs to be big enough to accommodate "struct cursor", while
|
* This needs to be big enough to accommodate "struct cursor", while
|
||||||
|
@ -234,7 +234,7 @@ ppc64_abi_t;
|
||||||
* passing parameters to exception handlers.
|
* passing parameters to exception handlers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define UNW_TDEP_NUM_EH_REGS 4
|
#define UNW_TDEP_NUM_EH_REGS 4
|
||||||
|
|
||||||
typedef struct unw_tdep_save_loc
|
typedef struct unw_tdep_save_loc
|
||||||
{
|
{
|
||||||
|
@ -249,7 +249,7 @@ typedef ucontext_t unw_tdep_context_t;
|
||||||
using the "getcontext" name just because it's using libunwind. We
|
using the "getcontext" name just because it's using libunwind. We
|
||||||
can't just use __getcontext() either, because that isn't exported
|
can't just use __getcontext() either, because that isn't exported
|
||||||
by glibc... */
|
by glibc... */
|
||||||
#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
|
#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
|
||||||
|
|
||||||
#include "libunwind-dynamic.h"
|
#include "libunwind-dynamic.h"
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ unw_tdep_proc_info_t;
|
||||||
|
|
||||||
#include "libunwind-common.h"
|
#include "libunwind-common.h"
|
||||||
|
|
||||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||||
extern int unw_tdep_is_fpreg (int);
|
extern int unw_tdep_is_fpreg (int);
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2004 Hewlett-Packard Co
|
Copyright (C) 2004 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -40,18 +40,18 @@ extern "C" {
|
||||||
extern void *_UPT_create (pid_t);
|
extern void *_UPT_create (pid_t);
|
||||||
extern void _UPT_destroy (void *);
|
extern void _UPT_destroy (void *);
|
||||||
extern int _UPT_find_proc_info (unw_addr_space_t, unw_word_t,
|
extern int _UPT_find_proc_info (unw_addr_space_t, unw_word_t,
|
||||||
unw_proc_info_t *, int, void *);
|
unw_proc_info_t *, int, void *);
|
||||||
extern void _UPT_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *);
|
extern void _UPT_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *);
|
||||||
extern int _UPT_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *,
|
extern int _UPT_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *,
|
||||||
void *);
|
void *);
|
||||||
extern int _UPT_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int,
|
extern int _UPT_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int,
|
||||||
void *);
|
void *);
|
||||||
extern int _UPT_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *,
|
extern int _UPT_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *,
|
||||||
int, void *);
|
int, void *);
|
||||||
extern int _UPT_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
|
extern int _UPT_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
|
||||||
int, void *);
|
int, void *);
|
||||||
extern int _UPT_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t,
|
extern int _UPT_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t,
|
||||||
unw_word_t *, void *);
|
unw_word_t *, void *);
|
||||||
extern int _UPT_resume (unw_addr_space_t, unw_cursor_t *, void *);
|
extern int _UPT_resume (unw_addr_space_t, unw_cursor_t *, void *);
|
||||||
extern unw_accessors_t _UPT_accessors;
|
extern unw_accessors_t _UPT_accessors;
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,10 @@ extern "C" {
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
|
|
||||||
#define UNW_TARGET sh
|
#define UNW_TARGET sh
|
||||||
#define UNW_TARGET_SH 1
|
#define UNW_TARGET_SH 1
|
||||||
|
|
||||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||||
|
|
||||||
/* This needs to be big enough to accommodate "struct cursor", while
|
/* This needs to be big enough to accommodate "struct cursor", while
|
||||||
leaving some slack for future expansion. Changing this value will
|
leaving some slack for future expansion. Changing this value will
|
||||||
|
@ -45,7 +45,7 @@ extern "C" {
|
||||||
relatively cheap and unwind-state copying is relatively rare, so we
|
relatively cheap and unwind-state copying is relatively rare, so we
|
||||||
want to err on making it rather too big than too small. */
|
want to err on making it rather too big than too small. */
|
||||||
|
|
||||||
#define UNW_TDEP_CURSOR_LEN 4096
|
#define UNW_TDEP_CURSOR_LEN 4096
|
||||||
|
|
||||||
typedef uint32_t unw_word_t;
|
typedef uint32_t unw_word_t;
|
||||||
typedef int32_t unw_sword_t;
|
typedef int32_t unw_sword_t;
|
||||||
|
@ -82,11 +82,11 @@ typedef enum
|
||||||
}
|
}
|
||||||
sh_regnum_t;
|
sh_regnum_t;
|
||||||
|
|
||||||
#define UNW_TDEP_NUM_EH_REGS 2
|
#define UNW_TDEP_NUM_EH_REGS 2
|
||||||
|
|
||||||
typedef ucontext_t unw_tdep_context_t;
|
typedef ucontext_t unw_tdep_context_t;
|
||||||
|
|
||||||
#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
|
#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
|
||||||
|
|
||||||
typedef struct unw_tdep_save_loc
|
typedef struct unw_tdep_save_loc
|
||||||
{
|
{
|
||||||
|
@ -104,7 +104,7 @@ unw_tdep_proc_info_t;
|
||||||
|
|
||||||
#include "libunwind-common.h"
|
#include "libunwind-common.h"
|
||||||
|
|
||||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||||
extern int unw_tdep_is_fpreg (int);
|
extern int unw_tdep_is_fpreg (int);
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2002-2004 Hewlett-Packard Co
|
Copyright (C) 2002-2004 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -34,17 +34,17 @@ extern "C" {
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
|
|
||||||
#define UNW_TARGET x86
|
#define UNW_TARGET x86
|
||||||
#define UNW_TARGET_X86 1
|
#define UNW_TARGET_X86 1
|
||||||
|
|
||||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||||
|
|
||||||
/* This needs to be big enough to accommodate "struct cursor", while
|
/* This needs to be big enough to accommodate "struct cursor", while
|
||||||
leaving some slack for future expansion. Changing this value will
|
leaving some slack for future expansion. Changing this value will
|
||||||
require recompiling all users of this library. Stack allocation is
|
require recompiling all users of this library. Stack allocation is
|
||||||
relatively cheap and unwind-state copying is relatively rare, so we
|
relatively cheap and unwind-state copying is relatively rare, so we
|
||||||
want to err on making it rather too big than too small. */
|
want to err on making it rather too big than too small. */
|
||||||
#define UNW_TDEP_CURSOR_LEN 127
|
#define UNW_TDEP_CURSOR_LEN 127
|
||||||
|
|
||||||
typedef uint32_t unw_word_t;
|
typedef uint32_t unw_word_t;
|
||||||
typedef int32_t unw_sword_t;
|
typedef int32_t unw_sword_t;
|
||||||
|
@ -72,78 +72,78 @@ typedef enum
|
||||||
DWARF, but that doesn't work because the libunwind requires
|
DWARF, but that doesn't work because the libunwind requires
|
||||||
that the exception argument registers be consecutive, which the
|
that the exception argument registers be consecutive, which the
|
||||||
wouldn't be with the DWARF numbering. */
|
wouldn't be with the DWARF numbering. */
|
||||||
UNW_X86_EAX, /* scratch (exception argument 1) */
|
UNW_X86_EAX, /* scratch (exception argument 1) */
|
||||||
UNW_X86_EDX, /* scratch (exception argument 2) */
|
UNW_X86_EDX, /* scratch (exception argument 2) */
|
||||||
UNW_X86_ECX, /* scratch */
|
UNW_X86_ECX, /* scratch */
|
||||||
UNW_X86_EBX, /* preserved */
|
UNW_X86_EBX, /* preserved */
|
||||||
UNW_X86_ESI, /* preserved */
|
UNW_X86_ESI, /* preserved */
|
||||||
UNW_X86_EDI, /* preserved */
|
UNW_X86_EDI, /* preserved */
|
||||||
UNW_X86_EBP, /* (optional) frame-register */
|
UNW_X86_EBP, /* (optional) frame-register */
|
||||||
UNW_X86_ESP, /* (optional) frame-register */
|
UNW_X86_ESP, /* (optional) frame-register */
|
||||||
UNW_X86_EIP, /* frame-register */
|
UNW_X86_EIP, /* frame-register */
|
||||||
UNW_X86_EFLAGS, /* scratch (except for "direction", which is fixed */
|
UNW_X86_EFLAGS, /* scratch (except for "direction", which is fixed */
|
||||||
UNW_X86_TRAPNO, /* scratch */
|
UNW_X86_TRAPNO, /* scratch */
|
||||||
|
|
||||||
/* MMX/stacked-fp registers */
|
/* MMX/stacked-fp registers */
|
||||||
UNW_X86_ST0, /* fp return value */
|
UNW_X86_ST0, /* fp return value */
|
||||||
UNW_X86_ST1, /* scratch */
|
UNW_X86_ST1, /* scratch */
|
||||||
UNW_X86_ST2, /* scratch */
|
UNW_X86_ST2, /* scratch */
|
||||||
UNW_X86_ST3, /* scratch */
|
UNW_X86_ST3, /* scratch */
|
||||||
UNW_X86_ST4, /* scratch */
|
UNW_X86_ST4, /* scratch */
|
||||||
UNW_X86_ST5, /* scratch */
|
UNW_X86_ST5, /* scratch */
|
||||||
UNW_X86_ST6, /* scratch */
|
UNW_X86_ST6, /* scratch */
|
||||||
UNW_X86_ST7, /* scratch */
|
UNW_X86_ST7, /* scratch */
|
||||||
|
|
||||||
UNW_X86_FCW, /* scratch */
|
UNW_X86_FCW, /* scratch */
|
||||||
UNW_X86_FSW, /* scratch */
|
UNW_X86_FSW, /* scratch */
|
||||||
UNW_X86_FTW, /* scratch */
|
UNW_X86_FTW, /* scratch */
|
||||||
UNW_X86_FOP, /* scratch */
|
UNW_X86_FOP, /* scratch */
|
||||||
UNW_X86_FCS, /* scratch */
|
UNW_X86_FCS, /* scratch */
|
||||||
UNW_X86_FIP, /* scratch */
|
UNW_X86_FIP, /* scratch */
|
||||||
UNW_X86_FEA, /* scratch */
|
UNW_X86_FEA, /* scratch */
|
||||||
UNW_X86_FDS, /* scratch */
|
UNW_X86_FDS, /* scratch */
|
||||||
|
|
||||||
/* SSE registers */
|
/* SSE registers */
|
||||||
UNW_X86_XMM0_lo, /* scratch */
|
UNW_X86_XMM0_lo, /* scratch */
|
||||||
UNW_X86_XMM0_hi, /* scratch */
|
UNW_X86_XMM0_hi, /* scratch */
|
||||||
UNW_X86_XMM1_lo, /* scratch */
|
UNW_X86_XMM1_lo, /* scratch */
|
||||||
UNW_X86_XMM1_hi, /* scratch */
|
UNW_X86_XMM1_hi, /* scratch */
|
||||||
UNW_X86_XMM2_lo, /* scratch */
|
UNW_X86_XMM2_lo, /* scratch */
|
||||||
UNW_X86_XMM2_hi, /* scratch */
|
UNW_X86_XMM2_hi, /* scratch */
|
||||||
UNW_X86_XMM3_lo, /* scratch */
|
UNW_X86_XMM3_lo, /* scratch */
|
||||||
UNW_X86_XMM3_hi, /* scratch */
|
UNW_X86_XMM3_hi, /* scratch */
|
||||||
UNW_X86_XMM4_lo, /* scratch */
|
UNW_X86_XMM4_lo, /* scratch */
|
||||||
UNW_X86_XMM4_hi, /* scratch */
|
UNW_X86_XMM4_hi, /* scratch */
|
||||||
UNW_X86_XMM5_lo, /* scratch */
|
UNW_X86_XMM5_lo, /* scratch */
|
||||||
UNW_X86_XMM5_hi, /* scratch */
|
UNW_X86_XMM5_hi, /* scratch */
|
||||||
UNW_X86_XMM6_lo, /* scratch */
|
UNW_X86_XMM6_lo, /* scratch */
|
||||||
UNW_X86_XMM6_hi, /* scratch */
|
UNW_X86_XMM6_hi, /* scratch */
|
||||||
UNW_X86_XMM7_lo, /* scratch */
|
UNW_X86_XMM7_lo, /* scratch */
|
||||||
UNW_X86_XMM7_hi, /* scratch */
|
UNW_X86_XMM7_hi, /* scratch */
|
||||||
|
|
||||||
UNW_X86_MXCSR, /* scratch */
|
UNW_X86_MXCSR, /* scratch */
|
||||||
|
|
||||||
/* segment registers */
|
/* segment registers */
|
||||||
UNW_X86_GS, /* special */
|
UNW_X86_GS, /* special */
|
||||||
UNW_X86_FS, /* special */
|
UNW_X86_FS, /* special */
|
||||||
UNW_X86_ES, /* special */
|
UNW_X86_ES, /* special */
|
||||||
UNW_X86_DS, /* special */
|
UNW_X86_DS, /* special */
|
||||||
UNW_X86_SS, /* special */
|
UNW_X86_SS, /* special */
|
||||||
UNW_X86_CS, /* special */
|
UNW_X86_CS, /* special */
|
||||||
UNW_X86_TSS, /* special */
|
UNW_X86_TSS, /* special */
|
||||||
UNW_X86_LDT, /* special */
|
UNW_X86_LDT, /* special */
|
||||||
|
|
||||||
/* frame info (read-only) */
|
/* frame info (read-only) */
|
||||||
UNW_X86_CFA,
|
UNW_X86_CFA,
|
||||||
|
|
||||||
UNW_X86_XMM0, /* scratch */
|
UNW_X86_XMM0, /* scratch */
|
||||||
UNW_X86_XMM1, /* scratch */
|
UNW_X86_XMM1, /* scratch */
|
||||||
UNW_X86_XMM2, /* scratch */
|
UNW_X86_XMM2, /* scratch */
|
||||||
UNW_X86_XMM3, /* scratch */
|
UNW_X86_XMM3, /* scratch */
|
||||||
UNW_X86_XMM4, /* scratch */
|
UNW_X86_XMM4, /* scratch */
|
||||||
UNW_X86_XMM5, /* scratch */
|
UNW_X86_XMM5, /* scratch */
|
||||||
UNW_X86_XMM6, /* scratch */
|
UNW_X86_XMM6, /* scratch */
|
||||||
UNW_X86_XMM7, /* scratch */
|
UNW_X86_XMM7, /* scratch */
|
||||||
|
|
||||||
UNW_TDEP_LAST_REG = UNW_X86_XMM7,
|
UNW_TDEP_LAST_REG = UNW_X86_XMM7,
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ typedef enum
|
||||||
}
|
}
|
||||||
x86_regnum_t;
|
x86_regnum_t;
|
||||||
|
|
||||||
#define UNW_TDEP_NUM_EH_REGS 2 /* eax and edx are exception args */
|
#define UNW_TDEP_NUM_EH_REGS 2 /* eax and edx are exception args */
|
||||||
|
|
||||||
typedef struct unw_tdep_save_loc
|
typedef struct unw_tdep_save_loc
|
||||||
{
|
{
|
||||||
|
@ -174,10 +174,10 @@ unw_tdep_proc_info_t;
|
||||||
|
|
||||||
#include "libunwind-common.h"
|
#include "libunwind-common.h"
|
||||||
|
|
||||||
#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
|
#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
|
||||||
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
||||||
|
|
||||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||||
extern int unw_tdep_is_fpreg (int);
|
extern int unw_tdep_is_fpreg (int);
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2002-2004 Hewlett-Packard Co
|
Copyright (C) 2002-2004 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
|
Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
|
||||||
|
|
||||||
|
@ -36,17 +36,17 @@ extern "C" {
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
|
|
||||||
#define UNW_TARGET x86_64
|
#define UNW_TARGET x86_64
|
||||||
#define UNW_TARGET_X86_64 1
|
#define UNW_TARGET_X86_64 1
|
||||||
|
|
||||||
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
|
||||||
|
|
||||||
/* This needs to be big enough to accommodate "struct cursor", while
|
/* This needs to be big enough to accommodate "struct cursor", while
|
||||||
leaving some slack for future expansion. Changing this value will
|
leaving some slack for future expansion. Changing this value will
|
||||||
require recompiling all users of this library. Stack allocation is
|
require recompiling all users of this library. Stack allocation is
|
||||||
relatively cheap and unwind-state copying is relatively rare, so we
|
relatively cheap and unwind-state copying is relatively rare, so we
|
||||||
want to err on making it rather too big than too small. */
|
want to err on making it rather too big than too small. */
|
||||||
#define UNW_TDEP_CURSOR_LEN 127
|
#define UNW_TDEP_CURSOR_LEN 127
|
||||||
|
|
||||||
typedef uint64_t unw_word_t;
|
typedef uint64_t unw_word_t;
|
||||||
typedef int64_t unw_sword_t;
|
typedef int64_t unw_sword_t;
|
||||||
|
@ -106,7 +106,7 @@ typedef enum
|
||||||
}
|
}
|
||||||
x86_64_regnum_t;
|
x86_64_regnum_t;
|
||||||
|
|
||||||
#define UNW_TDEP_NUM_EH_REGS 2 /* XXX Not sure what this means */
|
#define UNW_TDEP_NUM_EH_REGS 2 /* XXX Not sure what this means */
|
||||||
|
|
||||||
typedef struct unw_tdep_save_loc
|
typedef struct unw_tdep_save_loc
|
||||||
{
|
{
|
||||||
|
@ -128,8 +128,8 @@ unw_tdep_proc_info_t;
|
||||||
#include "libunwind-dynamic.h"
|
#include "libunwind-dynamic.h"
|
||||||
#include "libunwind-common.h"
|
#include "libunwind-common.h"
|
||||||
|
|
||||||
#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
|
#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
|
||||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||||
|
|
||||||
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
||||||
extern int unw_tdep_is_fpreg (int);
|
extern int unw_tdep_is_fpreg (int);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2001-2005 Hewlett-Packard Co
|
Copyright (C) 2001-2005 Hewlett-Packard Co
|
||||||
Copyright (C) 2007 David Mosberger-Tang
|
Copyright (C) 2007 David Mosberger-Tang
|
||||||
Contributed by David Mosberger-Tang <dmosberger@gmail.com>
|
Contributed by David Mosberger-Tang <dmosberger@gmail.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* Platform-independent libunwind-internal declarations. */
|
/* Platform-independent libunwind-internal declarations. */
|
||||||
|
|
||||||
#include <sys/types.h> /* HP-UX needs this before include of pthread.h */
|
#include <sys/types.h> /* HP-UX needs this before include of pthread.h */
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <libunwind.h>
|
#include <libunwind.h>
|
||||||
|
@ -70,8 +70,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#elif defined(HAVE_SYS_ENDIAN_H)
|
#elif defined(HAVE_SYS_ENDIAN_H)
|
||||||
# include <sys/endian.h>
|
# include <sys/endian.h>
|
||||||
#else
|
#else
|
||||||
# define __LITTLE_ENDIAN 1234
|
# define __LITTLE_ENDIAN 1234
|
||||||
# define __BIG_ENDIAN 4321
|
# define __BIG_ENDIAN 4321
|
||||||
# if defined(__hpux)
|
# if defined(__hpux)
|
||||||
# define __BYTE_ORDER __BIG_ENDIAN
|
# define __BYTE_ORDER __BIG_ENDIAN
|
||||||
# elif defined(__QNX__)
|
# elif defined(__QNX__)
|
||||||
|
@ -94,9 +94,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
# define UNW_DEBUG 1
|
# define UNW_DEBUG 1
|
||||||
#else
|
#else
|
||||||
# define UNW_DEBUG 0
|
# define UNW_DEBUG 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Make it easy to write thread-safe code which may or may not be
|
/* Make it easy to write thread-safe code which may or may not be
|
||||||
|
@ -108,12 +108,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#pragma weak pthread_mutex_lock
|
#pragma weak pthread_mutex_lock
|
||||||
#pragma weak pthread_mutex_unlock
|
#pragma weak pthread_mutex_unlock
|
||||||
|
|
||||||
#define mutex_init(l) \
|
#define mutex_init(l) \
|
||||||
(pthread_mutex_init != NULL ? pthread_mutex_init ((l), NULL) : 0)
|
(pthread_mutex_init != NULL ? pthread_mutex_init ((l), NULL) : 0)
|
||||||
#define mutex_lock(l) \
|
#define mutex_lock(l) \
|
||||||
(pthread_mutex_lock != NULL ? pthread_mutex_lock (l) : 0)
|
(pthread_mutex_lock != NULL ? pthread_mutex_lock (l) : 0)
|
||||||
#define mutex_unlock(l) \
|
#define mutex_unlock(l) \
|
||||||
(pthread_mutex_unlock != NULL ? pthread_mutex_unlock (l) : 0)
|
(pthread_mutex_unlock != NULL ? pthread_mutex_unlock (l) : 0)
|
||||||
|
|
||||||
#ifdef HAVE_ATOMIC_OPS_H
|
#ifdef HAVE_ATOMIC_OPS_H
|
||||||
# include <atomic_ops.h>
|
# include <atomic_ops.h>
|
||||||
|
@ -130,8 +130,8 @@ cmpxchg_ptr (void *addr, void *old, void *new)
|
||||||
u.vp = addr;
|
u.vp = addr;
|
||||||
return AO_compare_and_swap(u.aop, (AO_t) old, (AO_t) new);
|
return AO_compare_and_swap(u.aop, (AO_t) old, (AO_t) new);
|
||||||
}
|
}
|
||||||
# define fetch_and_add1(_ptr) AO_fetch_and_add1(_ptr)
|
# define fetch_and_add1(_ptr) AO_fetch_and_add1(_ptr)
|
||||||
# define fetch_and_add(_ptr, value) AO_fetch_and_add(_ptr, value)
|
# define fetch_and_add(_ptr, value) AO_fetch_and_add(_ptr, value)
|
||||||
/* GCC 3.2.0 on HP-UX crashes on cmpxchg_ptr() */
|
/* GCC 3.2.0 on HP-UX crashes on cmpxchg_ptr() */
|
||||||
# if !(defined(__hpux) && __GNUC__ == 3 && __GNUC_MINOR__ == 2)
|
# if !(defined(__hpux) && __GNUC__ == 3 && __GNUC_MINOR__ == 2)
|
||||||
# define HAVE_CMPXCHG
|
# define HAVE_CMPXCHG
|
||||||
|
@ -154,14 +154,14 @@ cmpxchg_ptr (void *addr, void *old, void *new)
|
||||||
u.vp = addr;
|
u.vp = addr;
|
||||||
return __sync_bool_compare_and_swap(u.vlp, (long) old, (long) new);
|
return __sync_bool_compare_and_swap(u.vlp, (long) old, (long) new);
|
||||||
}
|
}
|
||||||
# define fetch_and_add1(_ptr) __sync_fetch_and_add(_ptr, 1)
|
# define fetch_and_add1(_ptr) __sync_fetch_and_add(_ptr, 1)
|
||||||
# define fetch_and_add(_ptr, value) __sync_fetch_and_add(_ptr, value)
|
# define fetch_and_add(_ptr, value) __sync_fetch_and_add(_ptr, value)
|
||||||
# define HAVE_CMPXCHG
|
# define HAVE_CMPXCHG
|
||||||
# define HAVE_FETCH_AND_ADD
|
# define HAVE_FETCH_AND_ADD
|
||||||
#endif
|
#endif
|
||||||
#define atomic_read(ptr) (*(ptr))
|
#define atomic_read(ptr) (*(ptr))
|
||||||
|
|
||||||
#define UNWI_OBJ(fn) UNW_PASTE(UNW_PREFIX,UNW_PASTE(I,fn))
|
#define UNWI_OBJ(fn) UNW_PASTE(UNW_PREFIX,UNW_PASTE(I,fn))
|
||||||
#define UNWI_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_UI,UNW_TARGET),_), fn)
|
#define UNWI_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_UI,UNW_TARGET),_), fn)
|
||||||
|
|
||||||
#define unwi_full_mask UNWI_ARCH_OBJ(full_mask)
|
#define unwi_full_mask UNWI_ARCH_OBJ(full_mask)
|
||||||
|
@ -195,85 +195,85 @@ static inline void mark_as_used(void *v UNUSED) {
|
||||||
|
|
||||||
#define define_lock(name) \
|
#define define_lock(name) \
|
||||||
pthread_mutex_t name = UNW_PTHREAD_MUTEX_INITIALIZER
|
pthread_mutex_t name = UNW_PTHREAD_MUTEX_INITIALIZER
|
||||||
#define lock_init(l) mutex_init (l)
|
#define lock_init(l) mutex_init (l)
|
||||||
#define lock_acquire(l,m) \
|
#define lock_acquire(l,m) \
|
||||||
do { \
|
do { \
|
||||||
SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &(m)); \
|
SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &(m)); \
|
||||||
mutex_lock (l); \
|
mutex_lock (l); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define lock_release(l,m) \
|
#define lock_release(l,m) \
|
||||||
do { \
|
do { \
|
||||||
mutex_unlock (l); \
|
mutex_unlock (l); \
|
||||||
SIGPROCMASK (SIG_SETMASK, &(m), NULL); \
|
SIGPROCMASK (SIG_SETMASK, &(m), NULL); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define SOS_MEMORY_SIZE 16384 /* see src/mi/mempool.c */
|
#define SOS_MEMORY_SIZE 16384 /* see src/mi/mempool.c */
|
||||||
|
|
||||||
#ifndef MAP_ANONYMOUS
|
#ifndef MAP_ANONYMOUS
|
||||||
# define MAP_ANONYMOUS MAP_ANON
|
# define MAP_ANONYMOUS MAP_ANON
|
||||||
#endif
|
#endif
|
||||||
#define GET_MEMORY(mem, size) \
|
#define GET_MEMORY(mem, size) \
|
||||||
do { \
|
do { \
|
||||||
/* Hopefully, mmap() goes straight through to a system call stub... */ \
|
/* Hopefully, mmap() goes straight through to a system call stub... */ \
|
||||||
mem = mmap (NULL, size, PROT_READ | PROT_WRITE, \
|
mem = mmap (NULL, size, PROT_READ | PROT_WRITE, \
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \
|
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \
|
||||||
if (mem == MAP_FAILED) \
|
if (mem == MAP_FAILED) \
|
||||||
mem = NULL; \
|
mem = NULL; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define unwi_find_dynamic_proc_info UNWI_OBJ(find_dynamic_proc_info)
|
#define unwi_find_dynamic_proc_info UNWI_OBJ(find_dynamic_proc_info)
|
||||||
#define unwi_extract_dynamic_proc_info UNWI_OBJ(extract_dynamic_proc_info)
|
#define unwi_extract_dynamic_proc_info UNWI_OBJ(extract_dynamic_proc_info)
|
||||||
#define unwi_put_dynamic_unwind_info UNWI_OBJ(put_dynamic_unwind_info)
|
#define unwi_put_dynamic_unwind_info UNWI_OBJ(put_dynamic_unwind_info)
|
||||||
#define unwi_dyn_remote_find_proc_info UNWI_OBJ(dyn_remote_find_proc_info)
|
#define unwi_dyn_remote_find_proc_info UNWI_OBJ(dyn_remote_find_proc_info)
|
||||||
#define unwi_dyn_remote_put_unwind_info UNWI_OBJ(dyn_remote_put_unwind_info)
|
#define unwi_dyn_remote_put_unwind_info UNWI_OBJ(dyn_remote_put_unwind_info)
|
||||||
#define unwi_dyn_validate_cache UNWI_OBJ(dyn_validate_cache)
|
#define unwi_dyn_validate_cache UNWI_OBJ(dyn_validate_cache)
|
||||||
|
|
||||||
extern int unwi_find_dynamic_proc_info (unw_addr_space_t as,
|
extern int unwi_find_dynamic_proc_info (unw_addr_space_t as,
|
||||||
unw_word_t ip,
|
unw_word_t ip,
|
||||||
unw_proc_info_t *pi,
|
unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg);
|
int need_unwind_info, void *arg);
|
||||||
extern int unwi_extract_dynamic_proc_info (unw_addr_space_t as,
|
extern int unwi_extract_dynamic_proc_info (unw_addr_space_t as,
|
||||||
unw_word_t ip,
|
unw_word_t ip,
|
||||||
unw_proc_info_t *pi,
|
unw_proc_info_t *pi,
|
||||||
unw_dyn_info_t *di,
|
unw_dyn_info_t *di,
|
||||||
int need_unwind_info,
|
int need_unwind_info,
|
||||||
void *arg);
|
void *arg);
|
||||||
extern void unwi_put_dynamic_unwind_info (unw_addr_space_t as,
|
extern void unwi_put_dynamic_unwind_info (unw_addr_space_t as,
|
||||||
unw_proc_info_t *pi, void *arg);
|
unw_proc_info_t *pi, void *arg);
|
||||||
|
|
||||||
/* These handle the remote (cross-address-space) case of accessing
|
/* These handle the remote (cross-address-space) case of accessing
|
||||||
dynamic unwind info. */
|
dynamic unwind info. */
|
||||||
|
|
||||||
extern int unwi_dyn_remote_find_proc_info (unw_addr_space_t as,
|
extern int unwi_dyn_remote_find_proc_info (unw_addr_space_t as,
|
||||||
unw_word_t ip,
|
unw_word_t ip,
|
||||||
unw_proc_info_t *pi,
|
unw_proc_info_t *pi,
|
||||||
int need_unwind_info,
|
int need_unwind_info,
|
||||||
void *arg);
|
void *arg);
|
||||||
extern void unwi_dyn_remote_put_unwind_info (unw_addr_space_t as,
|
extern void unwi_dyn_remote_put_unwind_info (unw_addr_space_t as,
|
||||||
unw_proc_info_t *pi,
|
unw_proc_info_t *pi,
|
||||||
void *arg);
|
void *arg);
|
||||||
extern int unwi_dyn_validate_cache (unw_addr_space_t as, void *arg);
|
extern int unwi_dyn_validate_cache (unw_addr_space_t as, void *arg);
|
||||||
|
|
||||||
extern unw_dyn_info_list_t _U_dyn_info_list;
|
extern unw_dyn_info_list_t _U_dyn_info_list;
|
||||||
extern pthread_mutex_t _U_dyn_info_list_lock;
|
extern pthread_mutex_t _U_dyn_info_list_lock;
|
||||||
|
|
||||||
#if UNW_DEBUG
|
#if UNW_DEBUG
|
||||||
#define unwi_debug_level UNWI_ARCH_OBJ(debug_level)
|
#define unwi_debug_level UNWI_ARCH_OBJ(debug_level)
|
||||||
extern long unwi_debug_level;
|
extern long unwi_debug_level;
|
||||||
|
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# define Debug(level,format...) \
|
# define Debug(level,format...) \
|
||||||
do { \
|
do { \
|
||||||
if (unwi_debug_level >= level) \
|
if (unwi_debug_level >= level) \
|
||||||
{ \
|
{ \
|
||||||
int _n = level; \
|
int _n = level; \
|
||||||
if (_n > 16) \
|
if (_n > 16) \
|
||||||
_n = 16; \
|
_n = 16; \
|
||||||
fprintf (stderr, "%*c>%s: ", _n, ' ', __FUNCTION__); \
|
fprintf (stderr, "%*c>%s: ", _n, ' ', __FUNCTION__); \
|
||||||
fprintf (stderr, format); \
|
fprintf (stderr, format); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
# define Dprintf(format...) fprintf (stderr, format)
|
# define Dprintf(format...) fprintf (stderr, format)
|
||||||
#else
|
#else
|
||||||
# define Debug(level,format...)
|
# define Debug(level,format...)
|
||||||
# define Dprintf(format...)
|
# define Dprintf(format...)
|
||||||
|
@ -285,17 +285,17 @@ print_error (const char *string)
|
||||||
return write (2, string, strlen (string));
|
return write (2, string, strlen (string));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define mi_init UNWI_ARCH_OBJ(mi_init)
|
#define mi_init UNWI_ARCH_OBJ(mi_init)
|
||||||
|
|
||||||
extern void mi_init (void); /* machine-independent initializations */
|
extern void mi_init (void); /* machine-independent initializations */
|
||||||
extern unw_word_t _U_dyn_info_list_addr (void);
|
extern unw_word_t _U_dyn_info_list_addr (void);
|
||||||
|
|
||||||
/* This is needed/used by ELF targets only. */
|
/* This is needed/used by ELF targets only. */
|
||||||
|
|
||||||
struct elf_image
|
struct elf_image
|
||||||
{
|
{
|
||||||
void *image; /* pointer to mmap'd image */
|
void *image; /* pointer to mmap'd image */
|
||||||
size_t size; /* (file-) size of the image */
|
size_t size; /* (file-) size of the image */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct elf_dyn_info
|
struct elf_dyn_info
|
||||||
|
@ -335,21 +335,21 @@ static inline void invalidate_edi (struct elf_dyn_info *edi)
|
||||||
/* Define GNU and processor specific values for the Phdr p_type field in case
|
/* Define GNU and processor specific values for the Phdr p_type field in case
|
||||||
they aren't defined by <elf.h>. */
|
they aren't defined by <elf.h>. */
|
||||||
#ifndef PT_GNU_EH_FRAME
|
#ifndef PT_GNU_EH_FRAME
|
||||||
# define PT_GNU_EH_FRAME 0x6474e550
|
# define PT_GNU_EH_FRAME 0x6474e550
|
||||||
#endif /* !PT_GNU_EH_FRAME */
|
#endif /* !PT_GNU_EH_FRAME */
|
||||||
#ifndef PT_ARM_EXIDX
|
#ifndef PT_ARM_EXIDX
|
||||||
# define PT_ARM_EXIDX 0x70000001 /* ARM unwind segment */
|
# define PT_ARM_EXIDX 0x70000001 /* ARM unwind segment */
|
||||||
#endif /* !PT_ARM_EXIDX */
|
#endif /* !PT_ARM_EXIDX */
|
||||||
|
|
||||||
#include "tdep/libunwind_i.h"
|
#include "tdep/libunwind_i.h"
|
||||||
|
|
||||||
#ifndef tdep_get_func_addr
|
#ifndef tdep_get_func_addr
|
||||||
# define tdep_get_func_addr(as,addr,v) (*(v) = addr, 0)
|
# define tdep_get_func_addr(as,addr,v) (*(v) = addr, 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DWARF_VAL_LOC
|
#ifndef DWARF_VAL_LOC
|
||||||
# define DWARF_IS_VAL_LOC(l) 0
|
# define DWARF_IS_VAL_LOC(l) 0
|
||||||
# define DWARF_VAL_LOC(c,v) DWARF_NULL_LOC
|
# define DWARF_VAL_LOC(c,v) DWARF_NULL_LOC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define UNW_ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL))
|
#define UNW_ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2002-2003 Hewlett-Packard Co
|
Copyright (C) 2002-2003 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -51,23 +51,23 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
#include "libunwind_i.h"
|
#include "libunwind_i.h"
|
||||||
|
|
||||||
#define sos_alloc(s) UNWI_ARCH_OBJ(_sos_alloc)(s)
|
#define sos_alloc(s) UNWI_ARCH_OBJ(_sos_alloc)(s)
|
||||||
#define mempool_init(p,s,r) UNWI_ARCH_OBJ(_mempool_init)(p,s,r)
|
#define mempool_init(p,s,r) UNWI_ARCH_OBJ(_mempool_init)(p,s,r)
|
||||||
#define mempool_alloc(p) UNWI_ARCH_OBJ(_mempool_alloc)(p)
|
#define mempool_alloc(p) UNWI_ARCH_OBJ(_mempool_alloc)(p)
|
||||||
#define mempool_free(p,o) UNWI_ARCH_OBJ(_mempool_free)(p,o)
|
#define mempool_free(p,o) UNWI_ARCH_OBJ(_mempool_free)(p,o)
|
||||||
|
|
||||||
/* The mempool structure should be treated as an opaque object. It's
|
/* The mempool structure should be treated as an opaque object. It's
|
||||||
declared here only to enable static allocation of mempools. */
|
declared here only to enable static allocation of mempools. */
|
||||||
struct mempool
|
struct mempool
|
||||||
{
|
{
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
size_t obj_size; /* object size (rounded up for alignment) */
|
size_t obj_size; /* object size (rounded up for alignment) */
|
||||||
size_t chunk_size; /* allocation granularity */
|
size_t chunk_size; /* allocation granularity */
|
||||||
unsigned int reserve; /* minimum (desired) size of the free-list */
|
unsigned int reserve; /* minimum (desired) size of the free-list */
|
||||||
unsigned int num_free; /* number of objects on the free-list */
|
unsigned int num_free; /* number of objects on the free-list */
|
||||||
struct object
|
struct object
|
||||||
{
|
{
|
||||||
struct object *next;
|
struct object *next;
|
||||||
}
|
}
|
||||||
*free_list;
|
*free_list;
|
||||||
};
|
};
|
||||||
|
@ -82,7 +82,7 @@ extern void *sos_alloc (size_t size);
|
||||||
tight memory situations. If it is zero, mempool attempts to pick a
|
tight memory situations. If it is zero, mempool attempts to pick a
|
||||||
reasonable default value. */
|
reasonable default value. */
|
||||||
extern void mempool_init (struct mempool *pool,
|
extern void mempool_init (struct mempool *pool,
|
||||||
size_t obj_size, size_t reserve);
|
size_t obj_size, size_t reserve);
|
||||||
extern void *mempool_alloc (struct mempool *pool);
|
extern void *mempool_alloc (struct mempool *pool);
|
||||||
extern void mempool_free (struct mempool *pool, void *object);
|
extern void mempool_free (struct mempool *pool, void *object);
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
fetch8 (unw_addr_space_t as, unw_accessors_t *a,
|
fetch8 (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_word_t *addr, int8_t *valp, void *arg)
|
unw_word_t *addr, int8_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
*valp = *(int8_t *) (uintptr_t) *addr;
|
*valp = *(int8_t *) (uintptr_t) *addr;
|
||||||
*addr += 1;
|
*addr += 1;
|
||||||
|
@ -18,7 +18,7 @@ fetch8 (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
fetch16 (unw_addr_space_t as, unw_accessors_t *a,
|
fetch16 (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_word_t *addr, int16_t *valp, void *arg)
|
unw_word_t *addr, int16_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
*valp = *(int16_t *) (uintptr_t) *addr;
|
*valp = *(int16_t *) (uintptr_t) *addr;
|
||||||
*addr += 2;
|
*addr += 2;
|
||||||
|
@ -27,7 +27,7 @@ fetch16 (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
fetch32 (unw_addr_space_t as, unw_accessors_t *a,
|
fetch32 (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_word_t *addr, int32_t *valp, void *arg)
|
unw_word_t *addr, int32_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
*valp = *(int32_t *) (uintptr_t) *addr;
|
*valp = *(int32_t *) (uintptr_t) *addr;
|
||||||
*addr += 4;
|
*addr += 4;
|
||||||
|
@ -36,7 +36,7 @@ fetch32 (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
fetchw (unw_addr_space_t as, unw_accessors_t *a,
|
fetchw (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_word_t *addr, unw_word_t *valp, void *arg)
|
unw_word_t *addr, unw_word_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
*valp = *(unw_word_t *) (uintptr_t) *addr;
|
*valp = *(unw_word_t *) (uintptr_t) *addr;
|
||||||
*addr += sizeof (unw_word_t);
|
*addr += sizeof (unw_word_t);
|
||||||
|
@ -45,11 +45,11 @@ fetchw (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
|
|
||||||
#else /* !UNW_LOCAL_ONLY */
|
#else /* !UNW_LOCAL_ONLY */
|
||||||
|
|
||||||
#define WSIZE (sizeof (unw_word_t))
|
#define WSIZE (sizeof (unw_word_t))
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
fetch8 (unw_addr_space_t as, unw_accessors_t *a,
|
fetch8 (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_word_t *addr, int8_t *valp, void *arg)
|
unw_word_t *addr, int8_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
|
unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -69,7 +69,7 @@ fetch8 (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
fetch16 (unw_addr_space_t as, unw_accessors_t *a,
|
fetch16 (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_word_t *addr, int16_t *valp, void *arg)
|
unw_word_t *addr, int16_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
|
unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -91,7 +91,7 @@ fetch16 (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
fetch32 (unw_addr_space_t as, unw_accessors_t *a,
|
fetch32 (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_word_t *addr, int32_t *valp, void *arg)
|
unw_word_t *addr, int32_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
|
unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -113,7 +113,7 @@ fetch32 (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
fetchw (unw_addr_space_t as, unw_accessors_t *a,
|
fetchw (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_word_t *addr, unw_word_t *valp, void *arg)
|
unw_word_t *addr, unw_word_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|
|
@ -29,22 +29,22 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* This matches the value udes by GCC (see
|
/* This matches the value udes by GCC (see
|
||||||
gcc/config/aarch64/aarch64.h:DWARF_FRAME_REGISTERS. */
|
gcc/config/aarch64/aarch64.h:DWARF_FRAME_REGISTERS. */
|
||||||
#define DWARF_NUM_PRESERVED_REGS 97
|
#define DWARF_NUM_PRESERVED_REGS 97
|
||||||
|
|
||||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||||
#define dwarf_is_big_endian(addr_space) 0
|
#define dwarf_is_big_endian(addr_space) 0
|
||||||
|
|
||||||
#define dwarf_to_unw_regnum(reg) (((reg) <= UNW_AARCH64_V31) ? (reg) : 0)
|
#define dwarf_to_unw_regnum(reg) (((reg) <= UNW_AARCH64_V31) ? (reg) : 0)
|
||||||
|
|
||||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||||
unw_cursor_t. */
|
unw_cursor_t. */
|
||||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||||
|
|
||||||
typedef struct dwarf_loc
|
typedef struct dwarf_loc
|
||||||
{
|
{
|
||||||
unw_word_t val;
|
unw_word_t val;
|
||||||
#ifndef UNW_LOCAL_ONLY
|
#ifndef UNW_LOCAL_ONLY
|
||||||
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
dwarf_loc_t;
|
dwarf_loc_t;
|
||||||
|
|
|
@ -27,7 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* FIXME for AArch64 */
|
/* FIXME for AArch64 */
|
||||||
|
|
||||||
#define JB_SP 13
|
#define JB_SP 13
|
||||||
#define JB_RP 14
|
#define JB_RP 14
|
||||||
#define JB_MASK_SAVED 15
|
#define JB_MASK_SAVED 15
|
||||||
#define JB_MASK 16
|
#define JB_MASK 16
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2001-2005 Hewlett-Packard Co
|
Copyright (C) 2001-2005 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
Copyright (C) 2013 Linaro Limited
|
Copyright (C) 2013 Linaro Limited
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
@ -84,7 +84,7 @@ struct unw_addr_space
|
||||||
uint32_t cache_generation;
|
uint32_t cache_generation;
|
||||||
#endif
|
#endif
|
||||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||||
struct dwarf_rs_cache global_cache;
|
struct dwarf_rs_cache global_cache;
|
||||||
struct unw_debug_frame_list *debug_frames;
|
struct unw_debug_frame_list *debug_frames;
|
||||||
};
|
};
|
||||||
|
@ -93,7 +93,7 @@ struct cursor
|
||||||
{
|
{
|
||||||
struct dwarf_cursor dwarf; /* must be first */
|
struct dwarf_cursor dwarf; /* must be first */
|
||||||
|
|
||||||
unw_tdep_frame_t frame_info; /* quick tracing assist info */
|
unw_tdep_frame_t frame_info; /* quick tracing assist info */
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -261,21 +261,21 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
|
|
||||||
|
|
||||||
#define tdep_getcontext_trace UNW_ARCH_OBJ(getcontext_trace)
|
#define tdep_getcontext_trace UNW_ARCH_OBJ(getcontext_trace)
|
||||||
#define tdep_init_done UNW_OBJ(init_done)
|
#define tdep_init_done UNW_OBJ(init_done)
|
||||||
#define tdep_init UNW_OBJ(init)
|
#define tdep_init UNW_OBJ(init)
|
||||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||||
tdep_search_unwind_table. */
|
tdep_search_unwind_table. */
|
||||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||||
#define tdep_uc_addr UNW_OBJ(uc_addr)
|
#define tdep_uc_addr UNW_OBJ(uc_addr)
|
||||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||||
#define tdep_cache_frame(c,rs) do {} while(0)
|
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||||
#define tdep_stash_frame UNW_OBJ(tdep_stash_frame)
|
#define tdep_stash_frame UNW_OBJ(tdep_stash_frame)
|
||||||
#define tdep_trace UNW_OBJ(tdep_trace)
|
#define tdep_trace UNW_OBJ(tdep_trace)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
|
@ -300,19 +300,19 @@ extern int tdep_init_done;
|
||||||
|
|
||||||
extern void tdep_init (void);
|
extern void tdep_init (void);
|
||||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
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,
|
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg);
|
int need_unwind_info, void *arg);
|
||||||
extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
|
extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
|
||||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||||
unsigned long *segbase, unsigned long *mapoff,
|
unsigned long *segbase, unsigned long *mapoff,
|
||||||
char *path, size_t pathlen);
|
char *path, size_t pathlen);
|
||||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_word_t *valp, int write);
|
unw_word_t *valp, int write);
|
||||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_fpreg_t *valp, int write);
|
unw_fpreg_t *valp, int write);
|
||||||
extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
|
extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
|
||||||
extern void tdep_stash_frame (struct dwarf_cursor *c,
|
extern void tdep_stash_frame (struct dwarf_cursor *c,
|
||||||
struct dwarf_reg_state *rs);
|
struct dwarf_reg_state *rs);
|
||||||
extern int tdep_getcontext_trace (unw_tdep_context_t *);
|
extern int tdep_getcontext_trace (unw_tdep_context_t *);
|
||||||
|
|
||||||
#endif /* AARCH64_LIBUNWIND_I_H */
|
#endif /* AARCH64_LIBUNWIND_I_H */
|
||||||
|
|
|
@ -28,22 +28,22 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
|
/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
|
||||||
explicitly defined. */
|
explicitly defined. */
|
||||||
#define DWARF_NUM_PRESERVED_REGS 128
|
#define DWARF_NUM_PRESERVED_REGS 128
|
||||||
|
|
||||||
#define dwarf_to_unw_regnum(reg) (((reg) < 16) ? (reg) : 0)
|
#define dwarf_to_unw_regnum(reg) (((reg) < 16) ? (reg) : 0)
|
||||||
|
|
||||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||||
#define dwarf_is_big_endian(addr_space) 0
|
#define dwarf_is_big_endian(addr_space) 0
|
||||||
|
|
||||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||||
unw_cursor_t. */
|
unw_cursor_t. */
|
||||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||||
|
|
||||||
typedef struct dwarf_loc
|
typedef struct dwarf_loc
|
||||||
{
|
{
|
||||||
unw_word_t val;
|
unw_word_t val;
|
||||||
#ifndef UNW_LOCAL_ONLY
|
#ifndef UNW_LOCAL_ONLY
|
||||||
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
dwarf_loc_t;
|
dwarf_loc_t;
|
||||||
|
|
|
@ -44,9 +44,9 @@ struct arm_exbuf_data
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define arm_exidx_extract UNW_OBJ(arm_exidx_extract)
|
#define arm_exidx_extract UNW_OBJ(arm_exidx_extract)
|
||||||
#define arm_exidx_decode UNW_OBJ(arm_exidx_decode)
|
#define arm_exidx_decode UNW_OBJ(arm_exidx_decode)
|
||||||
#define arm_exidx_apply_cmd UNW_OBJ(arm_exidx_apply_cmd)
|
#define arm_exidx_apply_cmd UNW_OBJ(arm_exidx_apply_cmd)
|
||||||
|
|
||||||
int arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf);
|
int arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf);
|
||||||
int arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c);
|
int arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c);
|
||||||
|
|
|
@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* FIXME for ARM! */
|
/* FIXME for ARM! */
|
||||||
|
|
||||||
#define JB_SP 4
|
#define JB_SP 4
|
||||||
#define JB_RP 5
|
#define JB_RP 5
|
||||||
#define JB_MASK_SAVED 6
|
#define JB_MASK_SAVED 6
|
||||||
#define JB_MASK 7
|
#define JB_MASK 7
|
||||||
|
|
|
@ -68,17 +68,17 @@ struct unw_addr_space
|
||||||
#else
|
#else
|
||||||
uint32_t cache_generation;
|
uint32_t cache_generation;
|
||||||
#endif
|
#endif
|
||||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||||
struct dwarf_rs_cache global_cache;
|
struct dwarf_rs_cache global_cache;
|
||||||
struct unw_debug_frame_list *debug_frames;
|
struct unw_debug_frame_list *debug_frames;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cursor
|
struct cursor
|
||||||
{
|
{
|
||||||
struct dwarf_cursor dwarf; /* must be first */
|
struct dwarf_cursor dwarf; /* must be first */
|
||||||
|
|
||||||
unw_tdep_frame_t frame_info; /* quick tracing assist info */
|
unw_tdep_frame_t frame_info; /* quick tracing assist info */
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -95,18 +95,18 @@ struct cursor
|
||||||
int validate;
|
int validate;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DWARF_GET_LOC(l) ((l).val)
|
#define DWARF_GET_LOC(l) ((l).val)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||||
# define DWARF_IS_REG_LOC(l) 0
|
# define DWARF_IS_REG_LOC(l) 0
|
||||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
@ -145,18 +145,18 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !UNW_LOCAL_ONLY */
|
#else /* !UNW_LOCAL_ONLY */
|
||||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) \
|
# define DWARF_IS_NULL_LOC(l) \
|
||||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
({ 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_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_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_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_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||||
| DWARF_LOC_TYPE_FP))
|
| DWARF_LOC_TYPE_FP))
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
@ -170,15 +170,15 @@ dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
val, 0, c->as_arg);
|
val, 0, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||||
0, c->as_arg)) < 0)
|
0, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
||||||
c->as_arg);
|
c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -193,15 +193,15 @@ dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
&val, 1, c->as_arg);
|
&val, 1, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||||
1, c->as_arg)) < 0)
|
1, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -218,10 +218,10 @@ dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -238,74 +238,74 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !UNW_LOCAL_ONLY */
|
#endif /* !UNW_LOCAL_ONLY */
|
||||||
|
|
||||||
#define tdep_getcontext_trace unw_getcontext
|
#define tdep_getcontext_trace unw_getcontext
|
||||||
#define tdep_init_done UNW_OBJ(init_done)
|
#define tdep_init_done UNW_OBJ(init_done)
|
||||||
#define tdep_init UNW_OBJ(init)
|
#define tdep_init UNW_OBJ(init)
|
||||||
#define arm_find_proc_info UNW_OBJ(find_proc_info)
|
#define arm_find_proc_info UNW_OBJ(find_proc_info)
|
||||||
#define arm_put_unwind_info UNW_OBJ(put_unwind_info)
|
#define arm_put_unwind_info UNW_OBJ(put_unwind_info)
|
||||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||||
tdep_search_unwind_table. */
|
tdep_search_unwind_table. */
|
||||||
#define tdep_search_unwind_table UNW_OBJ(search_unwind_table)
|
#define tdep_search_unwind_table UNW_OBJ(search_unwind_table)
|
||||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||||
#define tdep_cache_frame(c,rs) do {} while(0)
|
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||||
#define tdep_stash_frame UNW_OBJ(tdep_stash_frame)
|
#define tdep_stash_frame UNW_OBJ(tdep_stash_frame)
|
||||||
#define tdep_trace UNW_OBJ(tdep_trace)
|
#define tdep_trace UNW_OBJ(tdep_trace)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
arm_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
arm_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
arm_put_unwind_info((as), (pi), (arg))
|
arm_put_unwind_info((as), (pi), (arg))
|
||||||
#else
|
#else
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||||
#define tdep_big_endian(as) ((as)->big_endian)
|
#define tdep_big_endian(as) ((as)->big_endian)
|
||||||
|
|
||||||
extern int tdep_init_done;
|
extern int tdep_init_done;
|
||||||
|
|
||||||
extern void tdep_init (void);
|
extern void tdep_init (void);
|
||||||
extern int arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
extern int arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||||
unw_proc_info_t *pi, int need_unwind_info,
|
unw_proc_info_t *pi, int need_unwind_info,
|
||||||
void *arg);
|
void *arg);
|
||||||
extern void arm_put_unwind_info (unw_addr_space_t as,
|
extern void arm_put_unwind_info (unw_addr_space_t as,
|
||||||
unw_proc_info_t *pi, void *arg);
|
unw_proc_info_t *pi, void *arg);
|
||||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
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,
|
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg);
|
int need_unwind_info, void *arg);
|
||||||
extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
|
extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
|
||||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||||
unsigned long *segbase, unsigned long *mapoff,
|
unsigned long *segbase, unsigned long *mapoff,
|
||||||
char *path, size_t pathlen);
|
char *path, size_t pathlen);
|
||||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_word_t *valp, int write);
|
unw_word_t *valp, int write);
|
||||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_fpreg_t *valp, int write);
|
unw_fpreg_t *valp, int write);
|
||||||
extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
|
extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
|
||||||
extern void tdep_stash_frame (struct dwarf_cursor *c,
|
extern void tdep_stash_frame (struct dwarf_cursor *c,
|
||||||
struct dwarf_reg_state *rs);
|
struct dwarf_reg_state *rs);
|
||||||
|
|
||||||
/* unwinding method selection support */
|
/* unwinding method selection support */
|
||||||
#define UNW_ARM_METHOD_ALL 0xFF
|
#define UNW_ARM_METHOD_ALL 0xFF
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
|
Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -27,26 +27,26 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#define dwarf_config_h
|
#define dwarf_config_h
|
||||||
|
|
||||||
/* See DWARF_FRAME_REGNUM() macro in gcc/config/pa/pa32-regs.h: */
|
/* See DWARF_FRAME_REGNUM() macro in gcc/config/pa/pa32-regs.h: */
|
||||||
#define dwarf_to_unw_regnum(reg) \
|
#define dwarf_to_unw_regnum(reg) \
|
||||||
(((reg) < DWARF_NUM_PRESERVED_REGS) ? (reg) : 0)
|
(((reg) < DWARF_NUM_PRESERVED_REGS) ? (reg) : 0)
|
||||||
|
|
||||||
/* This matches the value used by GCC (see
|
/* This matches the value used by GCC (see
|
||||||
gcc/config/pa/pa32-regs.h:FIRST_PSEUDO_REGISTER), which leaves
|
gcc/config/pa/pa32-regs.h:FIRST_PSEUDO_REGISTER), which leaves
|
||||||
plenty of room for expansion. */
|
plenty of room for expansion. */
|
||||||
#define DWARF_NUM_PRESERVED_REGS 89
|
#define DWARF_NUM_PRESERVED_REGS 89
|
||||||
|
|
||||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||||
#define dwarf_is_big_endian(addr_space) 1
|
#define dwarf_is_big_endian(addr_space) 1
|
||||||
|
|
||||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||||
unw_cursor_t. */
|
unw_cursor_t. */
|
||||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||||
|
|
||||||
typedef struct dwarf_loc
|
typedef struct dwarf_loc
|
||||||
{
|
{
|
||||||
unw_word_t val;
|
unw_word_t val;
|
||||||
#ifndef UNW_LOCAL_ONLY
|
#ifndef UNW_LOCAL_ONLY
|
||||||
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
dwarf_loc_t;
|
dwarf_loc_t;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2004 Hewlett-Packard Co
|
Copyright (C) 2004 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||||
|
|
||||||
#ifndef JB_SP
|
#ifndef JB_SP
|
||||||
# define JB_SP 19
|
# define JB_SP 19
|
||||||
#endif
|
#endif
|
||||||
#define JB_RP 20
|
#define JB_RP 20
|
||||||
#define JB_MASK_SAVED 21
|
#define JB_MASK_SAVED 21
|
||||||
#define JB_MASK 22
|
#define JB_MASK 22
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2003-2005 Hewlett-Packard Co
|
Copyright (C) 2003-2005 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -51,39 +51,39 @@ struct unw_addr_space
|
||||||
#else
|
#else
|
||||||
uint32_t cache_generation;
|
uint32_t cache_generation;
|
||||||
#endif
|
#endif
|
||||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||||
struct dwarf_rs_cache global_cache;
|
struct dwarf_rs_cache global_cache;
|
||||||
struct unw_debug_frame_list *debug_frames;
|
struct unw_debug_frame_list *debug_frames;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cursor
|
struct cursor
|
||||||
{
|
{
|
||||||
struct dwarf_cursor dwarf; /* must be first */
|
struct dwarf_cursor dwarf; /* must be first */
|
||||||
|
|
||||||
/* Format of sigcontext structure and address at which it is
|
/* Format of sigcontext structure and address at which it is
|
||||||
stored: */
|
stored: */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
HPPA_SCF_NONE, /* no signal frame encountered */
|
HPPA_SCF_NONE, /* no signal frame encountered */
|
||||||
HPPA_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
|
HPPA_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
|
||||||
}
|
}
|
||||||
sigcontext_format;
|
sigcontext_format;
|
||||||
unw_word_t sigcontext_addr;
|
unw_word_t sigcontext_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DWARF_GET_LOC(l) ((l).val)
|
#define DWARF_GET_LOC(l) ((l).val)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||||
# define DWARF_IS_REG_LOC(l) 0
|
# define DWARF_IS_REG_LOC(l) 0
|
||||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
@ -122,18 +122,18 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !UNW_LOCAL_ONLY */
|
#else /* !UNW_LOCAL_ONLY */
|
||||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) \
|
# define DWARF_IS_NULL_LOC(l) \
|
||||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
({ 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_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_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_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_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||||
| DWARF_LOC_TYPE_FP))
|
| DWARF_LOC_TYPE_FP))
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
@ -147,15 +147,15 @@ dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
val, 0, c->as_arg);
|
val, 0, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||||
0, c->as_arg)) < 0)
|
0, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
||||||
c->as_arg);
|
c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -170,15 +170,15 @@ dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
&val, 1, c->as_arg);
|
&val, 1, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||||
1, c->as_arg)) < 0)
|
1, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -195,10 +195,10 @@ dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -215,63 +215,63 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !UNW_LOCAL_ONLY */
|
#endif /* !UNW_LOCAL_ONLY */
|
||||||
|
|
||||||
#define tdep_getcontext_trace unw_getcontext
|
#define tdep_getcontext_trace unw_getcontext
|
||||||
#define tdep_init_done UNW_OBJ(init_done)
|
#define tdep_init_done UNW_OBJ(init_done)
|
||||||
#define tdep_init UNW_OBJ(init)
|
#define tdep_init UNW_OBJ(init)
|
||||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||||
tdep_search_unwind_table. */
|
tdep_search_unwind_table. */
|
||||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||||
#define tdep_cache_frame(c,rs) do {} while(0)
|
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
dwarf_put_unwind_info((as), (pi), (arg))
|
dwarf_put_unwind_info((as), (pi), (arg))
|
||||||
#else
|
#else
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||||
#define tdep_big_endian(as) 1
|
#define tdep_big_endian(as) 1
|
||||||
|
|
||||||
extern int tdep_init_done;
|
extern int tdep_init_done;
|
||||||
|
|
||||||
extern void tdep_init (void);
|
extern void tdep_init (void);
|
||||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
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,
|
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg);
|
int need_unwind_info, void *arg);
|
||||||
extern void *tdep_uc_addr (ucontext_t *uc, int reg);
|
extern void *tdep_uc_addr (ucontext_t *uc, int reg);
|
||||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||||
unsigned long *segbase, unsigned long *mapoff,
|
unsigned long *segbase, unsigned long *mapoff,
|
||||||
char *path, size_t pathlen);
|
char *path, size_t pathlen);
|
||||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_word_t *valp, int write);
|
unw_word_t *valp, int write);
|
||||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_fpreg_t *valp, int write);
|
unw_fpreg_t *valp, int write);
|
||||||
|
|
||||||
#endif /* HPPA_LIBUNWIND_I_H */
|
#endif /* HPPA_LIBUNWIND_I_H */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2004 Hewlett-Packard Co
|
Copyright (C) 2004 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP and BSP: */
|
/* Use glibc's jump-buffer indices; NPTL peeks at SP and BSP: */
|
||||||
|
|
||||||
#define JB_SP 0
|
#define JB_SP 0
|
||||||
#define JB_RP 8
|
#define JB_RP 8
|
||||||
#define JB_BSP 17
|
#define JB_BSP 17
|
||||||
#define JB_MASK_SAVED 70
|
#define JB_MASK_SAVED 70
|
||||||
#define JB_MASK 71
|
#define JB_MASK 71
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2001-2005 Hewlett-Packard Co
|
Copyright (C) 2001-2005 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -45,11 +45,11 @@ enum ia64_pregnum
|
||||||
IA64_REG_PRI_UNAT_MEM,
|
IA64_REG_PRI_UNAT_MEM,
|
||||||
|
|
||||||
/* memory stack (order matters: see build_script() */
|
/* memory stack (order matters: see build_script() */
|
||||||
IA64_REG_PSP, /* previous memory stack pointer */
|
IA64_REG_PSP, /* previous memory stack pointer */
|
||||||
/* register stack */
|
/* register stack */
|
||||||
IA64_REG_BSP, /* register stack pointer */
|
IA64_REG_BSP, /* register stack pointer */
|
||||||
IA64_REG_BSPSTORE,
|
IA64_REG_BSPSTORE,
|
||||||
IA64_REG_PFS, /* previous function state */
|
IA64_REG_PFS, /* previous function state */
|
||||||
IA64_REG_RNAT,
|
IA64_REG_RNAT,
|
||||||
/* instruction pointer: */
|
/* instruction pointer: */
|
||||||
IA64_REG_IP,
|
IA64_REG_IP,
|
||||||
|
@ -83,19 +83,19 @@ ia64_loc_t;
|
||||||
|
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
|
|
||||||
#define ABI_UNKNOWN 0
|
#define ABI_UNKNOWN 0
|
||||||
#define ABI_LINUX 1
|
#define ABI_LINUX 1
|
||||||
#define ABI_HPUX 2
|
#define ABI_HPUX 2
|
||||||
#define ABI_FREEBSD 3
|
#define ABI_FREEBSD 3
|
||||||
#define ABI_OPENVMS 4
|
#define ABI_OPENVMS 4
|
||||||
#define ABI_NSK 5 /* Tandem/HP Non-Stop Kernel */
|
#define ABI_NSK 5 /* Tandem/HP Non-Stop Kernel */
|
||||||
#define ABI_WINDOWS 6
|
#define ABI_WINDOWS 6
|
||||||
|
|
||||||
struct unw_addr_space
|
struct unw_addr_space
|
||||||
{
|
{
|
||||||
struct unw_accessors acc;
|
struct unw_accessors acc;
|
||||||
int big_endian;
|
int big_endian;
|
||||||
int abi; /* abi < 0 => unknown, 0 => SysV, 1 => HP-UX, 2 => Windows */
|
int abi; /* abi < 0 => unknown, 0 => SysV, 1 => HP-UX, 2 => Windows */
|
||||||
unw_caching_policy_t caching_policy;
|
unw_caching_policy_t caching_policy;
|
||||||
#ifdef HAVE_ATOMIC_OPS_H
|
#ifdef HAVE_ATOMIC_OPS_H
|
||||||
AO_t cache_generation;
|
AO_t cache_generation;
|
||||||
|
@ -103,7 +103,7 @@ struct unw_addr_space
|
||||||
uint32_t cache_generation;
|
uint32_t cache_generation;
|
||||||
#endif
|
#endif
|
||||||
unw_word_t dyn_generation;
|
unw_word_t dyn_generation;
|
||||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||||
#ifndef UNW_REMOTE_ONLY
|
#ifndef UNW_REMOTE_ONLY
|
||||||
unsigned long long shared_object_removals;
|
unsigned long long shared_object_removals;
|
||||||
#endif
|
#endif
|
||||||
|
@ -113,47 +113,47 @@ struct unw_addr_space
|
||||||
|
|
||||||
/* Note: The ABI numbers in the ABI-markers (.unwabi directive) are
|
/* Note: The ABI numbers in the ABI-markers (.unwabi directive) are
|
||||||
not the same as the above ABI numbers. */
|
not the same as the above ABI numbers. */
|
||||||
#define ABI_MARKER_OLD_LINUX_SIGTRAMP ((0 << 8) | 's')
|
#define ABI_MARKER_OLD_LINUX_SIGTRAMP ((0 << 8) | 's')
|
||||||
#define ABI_MARKER_OLD_LINUX_INTERRUPT ((0 << 8) | 'i')
|
#define ABI_MARKER_OLD_LINUX_INTERRUPT ((0 << 8) | 'i')
|
||||||
#define ABI_MARKER_HP_UX_SIGTRAMP ((1 << 8) | 1)
|
#define ABI_MARKER_HP_UX_SIGTRAMP ((1 << 8) | 1)
|
||||||
#define ABI_MARKER_LINUX_SIGTRAMP ((3 << 8) | 's')
|
#define ABI_MARKER_LINUX_SIGTRAMP ((3 << 8) | 's')
|
||||||
#define ABI_MARKER_LINUX_INTERRUPT ((3 << 8) | 'i')
|
#define ABI_MARKER_LINUX_INTERRUPT ((3 << 8) | 'i')
|
||||||
|
|
||||||
struct cursor
|
struct cursor
|
||||||
{
|
{
|
||||||
void *as_arg; /* argument to address-space callbacks */
|
void *as_arg; /* argument to address-space callbacks */
|
||||||
unw_addr_space_t as; /* reference to per-address-space info */
|
unw_addr_space_t as; /* reference to per-address-space info */
|
||||||
|
|
||||||
/* IP, CFM, and predicate cache (these are always equal to the
|
/* IP, CFM, and predicate cache (these are always equal to the
|
||||||
values stored in ip_loc, cfm_loc, and pr_loc,
|
values stored in ip_loc, cfm_loc, and pr_loc,
|
||||||
respectively). */
|
respectively). */
|
||||||
unw_word_t ip; /* instruction pointer value */
|
unw_word_t ip; /* instruction pointer value */
|
||||||
unw_word_t cfm; /* current frame mask */
|
unw_word_t cfm; /* current frame mask */
|
||||||
unw_word_t pr; /* current predicate values */
|
unw_word_t pr; /* current predicate values */
|
||||||
|
|
||||||
/* current frame info: */
|
/* current frame info: */
|
||||||
unw_word_t bsp; /* backing store pointer value */
|
unw_word_t bsp; /* backing store pointer value */
|
||||||
unw_word_t sp; /* stack pointer value */
|
unw_word_t sp; /* stack pointer value */
|
||||||
unw_word_t psp; /* previous sp value */
|
unw_word_t psp; /* previous sp value */
|
||||||
ia64_loc_t cfm_loc; /* cfm save location (or NULL) */
|
ia64_loc_t cfm_loc; /* cfm save location (or NULL) */
|
||||||
ia64_loc_t ec_loc; /* ar.ec save location (usually cfm_loc) */
|
ia64_loc_t ec_loc; /* ar.ec save location (usually cfm_loc) */
|
||||||
ia64_loc_t loc[IA64_NUM_PREGS];
|
ia64_loc_t loc[IA64_NUM_PREGS];
|
||||||
|
|
||||||
unw_word_t eh_args[4]; /* exception handler arguments */
|
unw_word_t eh_args[4]; /* exception handler arguments */
|
||||||
unw_word_t sigcontext_addr; /* address of sigcontext or 0 */
|
unw_word_t sigcontext_addr; /* address of sigcontext or 0 */
|
||||||
unw_word_t sigcontext_off; /* sigcontext-offset relative to signal sp */
|
unw_word_t sigcontext_off; /* sigcontext-offset relative to signal sp */
|
||||||
|
|
||||||
short hint;
|
short hint;
|
||||||
short prev_script;
|
short prev_script;
|
||||||
|
|
||||||
uint8_t nat_bitnr[4]; /* NaT bit numbers for r4-r7 */
|
uint8_t nat_bitnr[4]; /* NaT bit numbers for r4-r7 */
|
||||||
uint16_t abi_marker; /* abi_marker for current frame (if any) */
|
uint16_t abi_marker; /* abi_marker for current frame (if any) */
|
||||||
uint16_t last_abi_marker; /* last abi_marker encountered so far */
|
uint16_t last_abi_marker; /* last abi_marker encountered so far */
|
||||||
uint8_t eh_valid_mask;
|
uint8_t eh_valid_mask;
|
||||||
|
|
||||||
unsigned int pi_valid :1; /* is proc_info valid? */
|
unsigned int pi_valid :1; /* is proc_info valid? */
|
||||||
unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
|
unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
|
||||||
unw_proc_info_t pi; /* info about current procedure */
|
unw_proc_info_t pi; /* info about current procedure */
|
||||||
|
|
||||||
/* In case of stack-discontiguities, such as those introduced by
|
/* In case of stack-discontiguities, such as those introduced by
|
||||||
signal-delivery on an alternate signal-stack (see
|
signal-delivery on an alternate signal-stack (see
|
||||||
|
@ -171,20 +171,20 @@ struct cursor
|
||||||
register may not have gotten spilled until much later, when a
|
register may not have gotten spilled until much later, when a
|
||||||
possibly different rbs-area might have been in effect
|
possibly different rbs-area might have been in effect
|
||||||
already. */
|
already. */
|
||||||
uint8_t rbs_curr; /* index of curr. rbs-area (contains c->bsp) */
|
uint8_t rbs_curr; /* index of curr. rbs-area (contains c->bsp) */
|
||||||
uint8_t rbs_left_edge; /* index of inner-most valid rbs-area */
|
uint8_t rbs_left_edge; /* index of inner-most valid rbs-area */
|
||||||
struct rbs_area
|
struct rbs_area
|
||||||
{
|
{
|
||||||
unw_word_t end;
|
unw_word_t end;
|
||||||
unw_word_t size;
|
unw_word_t size;
|
||||||
ia64_loc_t rnat_loc;
|
ia64_loc_t rnat_loc;
|
||||||
}
|
}
|
||||||
rbs_area[96 + 2]; /* 96 stacked regs + 1 extra stack on each side... */
|
rbs_area[96 + 2]; /* 96 stacked regs + 1 extra stack on each side... */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ia64_global_unwind_state
|
struct ia64_global_unwind_state
|
||||||
{
|
{
|
||||||
pthread_mutex_t lock; /* global data lock */
|
pthread_mutex_t lock; /* global data lock */
|
||||||
|
|
||||||
volatile char init_done;
|
volatile char init_done;
|
||||||
|
|
||||||
|
@ -200,9 +200,9 @@ struct ia64_global_unwind_state
|
||||||
*/
|
*/
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unw_word_t r0; /* r0 is byte-order neutral */
|
unw_word_t r0; /* r0 is byte-order neutral */
|
||||||
unw_fpreg_t f0; /* f0 is byte-order neutral */
|
unw_fpreg_t f0; /* f0 is byte-order neutral */
|
||||||
unw_fpreg_t f1_le, f1_be; /* f1 is byte-order dependent */
|
unw_fpreg_t f1_le, f1_be; /* f1 is byte-order dependent */
|
||||||
}
|
}
|
||||||
read_only;
|
read_only;
|
||||||
unw_fpreg_t nat_val_le, nat_val_be;
|
unw_fpreg_t nat_val_le, nat_val_be;
|
||||||
|
@ -217,63 +217,63 @@ struct ia64_global_unwind_state
|
||||||
};
|
};
|
||||||
|
|
||||||
#define tdep_getcontext_trace unw_getcontext
|
#define tdep_getcontext_trace unw_getcontext
|
||||||
#define tdep_init_done unw.init_done
|
#define tdep_init_done unw.init_done
|
||||||
#define tdep_init UNW_OBJ(init)
|
#define tdep_init UNW_OBJ(init)
|
||||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||||
tdep_search_unwind_table. */
|
tdep_search_unwind_table. */
|
||||||
#define tdep_search_unwind_table unw_search_ia64_unwind_table
|
#define tdep_search_unwind_table unw_search_ia64_unwind_table
|
||||||
#define tdep_find_unwind_table ia64_find_unwind_table
|
#define tdep_find_unwind_table ia64_find_unwind_table
|
||||||
#define tdep_find_proc_info UNW_OBJ(find_proc_info)
|
#define tdep_find_proc_info UNW_OBJ(find_proc_info)
|
||||||
#define tdep_uc_addr UNW_OBJ(uc_addr)
|
#define tdep_uc_addr UNW_OBJ(uc_addr)
|
||||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||||
#define tdep_cache_frame(c,rs) do {} while(0)
|
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||||
#define tdep_get_as(c) ((c)->as)
|
#define tdep_get_as(c) ((c)->as)
|
||||||
#define tdep_get_as_arg(c) ((c)->as_arg)
|
#define tdep_get_as_arg(c) ((c)->as_arg)
|
||||||
#define tdep_get_ip(c) ((c)->ip)
|
#define tdep_get_ip(c) ((c)->ip)
|
||||||
#define tdep_big_endian(as) ((c)->as->big_endian != 0)
|
#define tdep_big_endian(as) ((c)->as->big_endian != 0)
|
||||||
|
|
||||||
#ifndef UNW_LOCAL_ONLY
|
#ifndef UNW_LOCAL_ONLY
|
||||||
# define tdep_put_unwind_info UNW_OBJ(put_unwind_info)
|
# define tdep_put_unwind_info UNW_OBJ(put_unwind_info)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This can't be an UNW_ARCH_OBJ() because we need separate
|
/* This can't be an UNW_ARCH_OBJ() because we need separate
|
||||||
unw.initialized flags for the local-only and generic versions of
|
unw.initialized flags for the local-only and generic versions of
|
||||||
the library. Also, if we wanted to have a single, shared global
|
the library. Also, if we wanted to have a single, shared global
|
||||||
data structure, we couldn't declare "unw" as HIDDEN/PROTECTED. */
|
data structure, we couldn't declare "unw" as HIDDEN/PROTECTED. */
|
||||||
#define unw UNW_OBJ(data)
|
#define unw UNW_OBJ(data)
|
||||||
|
|
||||||
extern void tdep_init (void);
|
extern void tdep_init (void);
|
||||||
extern int tdep_find_unwind_table (struct elf_dyn_info *edi,
|
extern int tdep_find_unwind_table (struct elf_dyn_info *edi,
|
||||||
unw_addr_space_t as, char *path,
|
unw_addr_space_t as, char *path,
|
||||||
unw_word_t segbase, unw_word_t mapoff,
|
unw_word_t segbase, unw_word_t mapoff,
|
||||||
unw_word_t ip);
|
unw_word_t ip);
|
||||||
extern int tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
extern int tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||||
unw_proc_info_t *pi, int need_unwind_info,
|
unw_proc_info_t *pi, int need_unwind_info,
|
||||||
void *arg);
|
void *arg);
|
||||||
extern void tdep_put_unwind_info (unw_addr_space_t as,
|
extern void tdep_put_unwind_info (unw_addr_space_t as,
|
||||||
unw_proc_info_t *pi, void *arg);
|
unw_proc_info_t *pi, void *arg);
|
||||||
extern void *tdep_uc_addr (ucontext_t *uc, unw_regnum_t regnum,
|
extern void *tdep_uc_addr (ucontext_t *uc, unw_regnum_t regnum,
|
||||||
uint8_t *nat_bitnr);
|
uint8_t *nat_bitnr);
|
||||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||||
unsigned long *segbase, unsigned long *mapoff,
|
unsigned long *segbase, unsigned long *mapoff,
|
||||||
char *path, size_t pathlen);
|
char *path, size_t pathlen);
|
||||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_word_t *valp, int write);
|
unw_word_t *valp, int write);
|
||||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_fpreg_t *valp, int write);
|
unw_fpreg_t *valp, int write);
|
||||||
|
|
||||||
extern struct ia64_global_unwind_state unw;
|
extern struct ia64_global_unwind_state unw;
|
||||||
|
|
||||||
/* In user-level, we have no reasonable way of determining the base of
|
/* In user-level, we have no reasonable way of determining the base of
|
||||||
an arbitrary backing-store. We default to half the
|
an arbitrary backing-store. We default to half the
|
||||||
address-space. */
|
address-space. */
|
||||||
#define rbs_get_base(c,bspstore,rbs_basep) \
|
#define rbs_get_base(c,bspstore,rbs_basep) \
|
||||||
(*(rbs_basep) = (bspstore) - (((unw_word_t) 1) << 63), 0)
|
(*(rbs_basep) = (bspstore) - (((unw_word_t) 1) << 63), 0)
|
||||||
|
|
||||||
#endif /* IA64_LIBUNWIND_I_H */
|
#endif /* IA64_LIBUNWIND_I_H */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 1998, 1999, 2002, 2003, 2005 Hewlett-Packard Co
|
* Copyright (C) 1998, 1999, 2002, 2003, 2005 Hewlett-Packard Co
|
||||||
* David Mosberger-Tang <davidm@hpl.hp.com>
|
* David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
*
|
*
|
||||||
* Register stack engine related helper functions. This file may be
|
* Register stack engine related helper functions. This file may be
|
||||||
* used in applications, so be careful about the name-space and give
|
* used in applications, so be careful about the name-space and give
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
static inline uint64_t
|
static inline uint64_t
|
||||||
rse_slot_num (uint64_t addr)
|
rse_slot_num (uint64_t addr)
|
||||||
{
|
{
|
||||||
return (addr >> 3) & 0x3f;
|
return (addr >> 3) & 0x3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -24,7 +24,7 @@ rse_slot_num (uint64_t addr)
|
||||||
static inline uint64_t
|
static inline uint64_t
|
||||||
rse_is_rnat_slot (uint64_t addr)
|
rse_is_rnat_slot (uint64_t addr)
|
||||||
{
|
{
|
||||||
return rse_slot_num (addr) == 0x3f;
|
return rse_slot_num (addr) == 0x3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -34,7 +34,7 @@ rse_is_rnat_slot (uint64_t addr)
|
||||||
static inline uint64_t
|
static inline uint64_t
|
||||||
rse_rnat_addr (uint64_t slot_addr)
|
rse_rnat_addr (uint64_t slot_addr)
|
||||||
{
|
{
|
||||||
return slot_addr | (0x3f << 3);
|
return slot_addr | (0x3f << 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -45,9 +45,9 @@ rse_rnat_addr (uint64_t slot_addr)
|
||||||
static inline uint64_t
|
static inline uint64_t
|
||||||
rse_num_regs (uint64_t bspstore, uint64_t bsp)
|
rse_num_regs (uint64_t bspstore, uint64_t bsp)
|
||||||
{
|
{
|
||||||
uint64_t slots = (bsp - bspstore) >> 3;
|
uint64_t slots = (bsp - bspstore) >> 3;
|
||||||
|
|
||||||
return slots - (rse_slot_num(bspstore) + slots)/0x40;
|
return slots - (rse_slot_num(bspstore) + slots)/0x40;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -57,11 +57,11 @@ rse_num_regs (uint64_t bspstore, uint64_t bsp)
|
||||||
static inline uint64_t
|
static inline uint64_t
|
||||||
rse_skip_regs (uint64_t addr, long num_regs)
|
rse_skip_regs (uint64_t addr, long num_regs)
|
||||||
{
|
{
|
||||||
long delta = rse_slot_num(addr) + num_regs;
|
long delta = rse_slot_num(addr) + num_regs;
|
||||||
|
|
||||||
if (num_regs < 0)
|
if (num_regs < 0)
|
||||||
delta -= 0x3e;
|
delta -= 0x3e;
|
||||||
return addr + ((num_regs + delta/0x3f) << 3);
|
return addr + ((num_regs + delta/0x3f) << 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* RSE_H */
|
#endif /* RSE_H */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2001-2002 Hewlett-Packard Co
|
Copyright (C) 2001-2002 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -23,17 +23,17 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
#define IA64_LOG_UNW_CACHE_SIZE 7
|
#define IA64_LOG_UNW_CACHE_SIZE 7
|
||||||
#define IA64_UNW_CACHE_SIZE (1 << IA64_LOG_UNW_CACHE_SIZE)
|
#define IA64_UNW_CACHE_SIZE (1 << IA64_LOG_UNW_CACHE_SIZE)
|
||||||
|
|
||||||
#define IA64_LOG_UNW_HASH_SIZE (IA64_LOG_UNW_CACHE_SIZE + 1)
|
#define IA64_LOG_UNW_HASH_SIZE (IA64_LOG_UNW_CACHE_SIZE + 1)
|
||||||
#define IA64_UNW_HASH_SIZE (1 << IA64_LOG_UNW_HASH_SIZE)
|
#define IA64_UNW_HASH_SIZE (1 << IA64_LOG_UNW_HASH_SIZE)
|
||||||
|
|
||||||
typedef unsigned char unw_hash_index_t;
|
typedef unsigned char unw_hash_index_t;
|
||||||
|
|
||||||
struct ia64_script_insn
|
struct ia64_script_insn
|
||||||
{
|
{
|
||||||
unsigned int opc; /* see enum ia64_script_insn_opcode */
|
unsigned int opc; /* see enum ia64_script_insn_opcode */
|
||||||
unsigned int dst;
|
unsigned int dst;
|
||||||
unw_word_t val;
|
unw_word_t val;
|
||||||
};
|
};
|
||||||
|
@ -41,18 +41,18 @@ struct ia64_script_insn
|
||||||
/* Updating each preserved register may result in one script
|
/* Updating each preserved register may result in one script
|
||||||
instruction each. At the end of the script, psp gets popped,
|
instruction each. At the end of the script, psp gets popped,
|
||||||
accounting for one more instruction. */
|
accounting for one more instruction. */
|
||||||
#define IA64_MAX_SCRIPT_LEN (IA64_NUM_PREGS + 1)
|
#define IA64_MAX_SCRIPT_LEN (IA64_NUM_PREGS + 1)
|
||||||
|
|
||||||
struct ia64_script
|
struct ia64_script
|
||||||
{
|
{
|
||||||
unw_word_t ip; /* ip this script is for */
|
unw_word_t ip; /* ip this script is for */
|
||||||
unw_word_t pr_mask; /* mask of predicates script depends on */
|
unw_word_t pr_mask; /* mask of predicates script depends on */
|
||||||
unw_word_t pr_val; /* predicate values this script is for */
|
unw_word_t pr_val; /* predicate values this script is for */
|
||||||
unw_proc_info_t pi; /* info about underlying procedure */
|
unw_proc_info_t pi; /* info about underlying procedure */
|
||||||
unsigned short lru_chain; /* used for least-recently-used chain */
|
unsigned short lru_chain; /* used for least-recently-used chain */
|
||||||
unsigned short coll_chain; /* used for hash collisions */
|
unsigned short coll_chain; /* used for hash collisions */
|
||||||
unsigned short hint; /* hint for next script to try (or -1) */
|
unsigned short hint; /* hint for next script to try (or -1) */
|
||||||
unsigned short count; /* number of instructions in script */
|
unsigned short count; /* number of instructions in script */
|
||||||
unsigned short abi_marker;
|
unsigned short abi_marker;
|
||||||
struct ia64_script_insn insn[IA64_MAX_SCRIPT_LEN];
|
struct ia64_script_insn insn[IA64_MAX_SCRIPT_LEN];
|
||||||
};
|
};
|
||||||
|
@ -60,26 +60,26 @@ struct ia64_script
|
||||||
struct ia64_script_cache
|
struct ia64_script_cache
|
||||||
{
|
{
|
||||||
#ifdef HAVE_ATOMIC_OPS_H
|
#ifdef HAVE_ATOMIC_OPS_H
|
||||||
AO_TS_t busy; /* is the script-cache busy? */
|
AO_TS_t busy; /* is the script-cache busy? */
|
||||||
#else
|
#else
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
#endif
|
#endif
|
||||||
unsigned short lru_head; /* index of lead-recently used script */
|
unsigned short lru_head; /* index of lead-recently used script */
|
||||||
unsigned short lru_tail; /* index of most-recently used script */
|
unsigned short lru_tail; /* index of most-recently used script */
|
||||||
|
|
||||||
/* hash table that maps instruction pointer to script index: */
|
/* hash table that maps instruction pointer to script index: */
|
||||||
unsigned short hash[IA64_UNW_HASH_SIZE];
|
unsigned short hash[IA64_UNW_HASH_SIZE];
|
||||||
|
|
||||||
uint32_t generation; /* generation number */
|
uint32_t generation; /* generation number */
|
||||||
|
|
||||||
/* script cache: */
|
/* script cache: */
|
||||||
struct ia64_script buckets[IA64_UNW_CACHE_SIZE];
|
struct ia64_script buckets[IA64_UNW_CACHE_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ia64_cache_proc_info UNW_OBJ(cache_proc_info)
|
#define ia64_cache_proc_info UNW_OBJ(cache_proc_info)
|
||||||
#define ia64_get_cached_proc_info UNW_OBJ(get_cached_proc_info)
|
#define ia64_get_cached_proc_info UNW_OBJ(get_cached_proc_info)
|
||||||
|
|
||||||
struct cursor; /* forward declaration */
|
struct cursor; /* forward declaration */
|
||||||
|
|
||||||
extern int ia64_cache_proc_info (struct cursor *c);
|
extern int ia64_cache_proc_info (struct cursor *c);
|
||||||
extern int ia64_get_cached_proc_info (struct cursor *c);
|
extern int ia64_get_cached_proc_info (struct cursor *c);
|
||||||
|
|
|
@ -28,25 +28,25 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
|
/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not
|
||||||
explicitly defined. */
|
explicitly defined. */
|
||||||
#define DWARF_NUM_PRESERVED_REGS 188
|
#define DWARF_NUM_PRESERVED_REGS 188
|
||||||
|
|
||||||
#define dwarf_to_unw_regnum(reg) (((reg) < 32) ? (reg) : 0)
|
#define dwarf_to_unw_regnum(reg) (((reg) < 32) ? (reg) : 0)
|
||||||
|
|
||||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||||
#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
|
#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
|
||||||
|
|
||||||
/* Return the size of an address, for DWARF purposes. */
|
/* Return the size of an address, for DWARF purposes. */
|
||||||
#define dwarf_addr_size(addr_space) ((addr_space)->addr_size)
|
#define dwarf_addr_size(addr_space) ((addr_space)->addr_size)
|
||||||
|
|
||||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||||
unw_cursor_t. */
|
unw_cursor_t. */
|
||||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||||
|
|
||||||
typedef struct dwarf_loc
|
typedef struct dwarf_loc
|
||||||
{
|
{
|
||||||
unw_word_t val;
|
unw_word_t val;
|
||||||
#ifndef UNW_LOCAL_ONLY
|
#ifndef UNW_LOCAL_ONLY
|
||||||
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
dwarf_loc_t;
|
dwarf_loc_t;
|
||||||
|
|
|
@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* FIXME for MIPS! */
|
/* FIXME for MIPS! */
|
||||||
|
|
||||||
#define JB_SP 4
|
#define JB_SP 4
|
||||||
#define JB_RP 5
|
#define JB_RP 5
|
||||||
#define JB_MASK_SAVED 6
|
#define JB_MASK_SAVED 6
|
||||||
#define JB_MASK 7
|
#define JB_MASK 7
|
||||||
|
|
|
@ -59,21 +59,21 @@ struct unw_addr_space
|
||||||
#else
|
#else
|
||||||
uint32_t cache_generation;
|
uint32_t cache_generation;
|
||||||
#endif
|
#endif
|
||||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||||
struct dwarf_rs_cache global_cache;
|
struct dwarf_rs_cache global_cache;
|
||||||
struct unw_debug_frame_list *debug_frames;
|
struct unw_debug_frame_list *debug_frames;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define tdep_big_endian(as) ((as)->big_endian)
|
#define tdep_big_endian(as) ((as)->big_endian)
|
||||||
|
|
||||||
struct cursor
|
struct cursor
|
||||||
{
|
{
|
||||||
struct dwarf_cursor dwarf; /* must be first */
|
struct dwarf_cursor dwarf; /* must be first */
|
||||||
unw_word_t sigcontext_addr;
|
unw_word_t sigcontext_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DWARF_GET_LOC(l) ((l).val)
|
#define DWARF_GET_LOC(l) ((l).val)
|
||||||
|
|
||||||
#ifndef UNW_REMOTE_ONLY
|
#ifndef UNW_REMOTE_ONLY
|
||||||
# if _MIPS_SIM == _ABIN32
|
# if _MIPS_SIM == _ABIN32
|
||||||
|
@ -84,15 +84,15 @@ typedef long mips_reg_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||||
# define DWARF_IS_REG_LOC(l) 0
|
# define DWARF_IS_REG_LOC(l) 0
|
||||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \
|
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \
|
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
|
|
||||||
/* FIXME: Implement these for the MIPS FPU. */
|
/* FIXME: Implement these for the MIPS FPU. */
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -132,18 +132,18 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !UNW_LOCAL_ONLY */
|
#else /* !UNW_LOCAL_ONLY */
|
||||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) \
|
# define DWARF_IS_NULL_LOC(l) \
|
||||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
({ 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_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_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_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_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||||
| DWARF_LOC_TYPE_FP))
|
| DWARF_LOC_TYPE_FP))
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
read_s32 (struct dwarf_cursor *c, unw_word_t addr, unw_word_t *val)
|
read_s32 (struct dwarf_cursor *c, unw_word_t addr, unw_word_t *val)
|
||||||
|
@ -196,15 +196,15 @@ dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
val, 0, c->as_arg);
|
val, 0, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||||
0, c->as_arg)) < 0)
|
0, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
||||||
c->as_arg);
|
c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -219,15 +219,15 @@ dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
&val, 1, c->as_arg);
|
&val, 1, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||||
1, c->as_arg)) < 0)
|
1, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -244,12 +244,12 @@ dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
else if (c->as->abi == UNW_MIPS_ABI_O32)
|
else if (c->as->abi == UNW_MIPS_ABI_O32)
|
||||||
return read_s32 (c, DWARF_GET_LOC (loc), val);
|
return read_s32 (c, DWARF_GET_LOC (loc), val);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -266,64 +266,64 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
else if (c->as->abi == UNW_MIPS_ABI_O32)
|
else if (c->as->abi == UNW_MIPS_ABI_O32)
|
||||||
return write_s32 (c, DWARF_GET_LOC (loc), &val);
|
return write_s32 (c, DWARF_GET_LOC (loc), &val);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !UNW_LOCAL_ONLY */
|
#endif /* !UNW_LOCAL_ONLY */
|
||||||
|
|
||||||
#define tdep_getcontext_trace unw_getcontext
|
#define tdep_getcontext_trace unw_getcontext
|
||||||
#define tdep_init_done UNW_OBJ(init_done)
|
#define tdep_init_done UNW_OBJ(init_done)
|
||||||
#define tdep_init UNW_OBJ(init)
|
#define tdep_init UNW_OBJ(init)
|
||||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||||
tdep_search_unwind_table. */
|
tdep_search_unwind_table. */
|
||||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||||
#define tdep_cache_frame(c,rs) do {} while(0)
|
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
dwarf_put_unwind_info((as), (pi), (arg))
|
dwarf_put_unwind_info((as), (pi), (arg))
|
||||||
#else
|
#else
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||||
|
|
||||||
extern int tdep_init_done;
|
extern int tdep_init_done;
|
||||||
|
|
||||||
extern void tdep_init (void);
|
extern void tdep_init (void);
|
||||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
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,
|
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg);
|
int need_unwind_info, void *arg);
|
||||||
extern void *tdep_uc_addr (ucontext_t *uc, int reg);
|
extern void *tdep_uc_addr (ucontext_t *uc, int reg);
|
||||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||||
unsigned long *segbase, unsigned long *mapoff,
|
unsigned long *segbase, unsigned long *mapoff,
|
||||||
char *path, size_t pathlen);
|
char *path, size_t pathlen);
|
||||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_word_t *valp, int write);
|
unw_word_t *valp, int write);
|
||||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_fpreg_t *valp, int write);
|
unw_fpreg_t *valp, int write);
|
||||||
|
|
||||||
#endif /* MIPS_LIBUNWIND_I_H */
|
#endif /* MIPS_LIBUNWIND_I_H */
|
||||||
|
|
|
@ -33,22 +33,22 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#define dwarf_config_h
|
#define dwarf_config_h
|
||||||
|
|
||||||
/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */
|
/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */
|
||||||
#define DWARF_NUM_PRESERVED_REGS 115
|
#define DWARF_NUM_PRESERVED_REGS 115
|
||||||
|
|
||||||
#define DWARF_REGNUM_MAP_LENGTH 115
|
#define DWARF_REGNUM_MAP_LENGTH 115
|
||||||
|
|
||||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||||
#define dwarf_is_big_endian(addr_space) 1
|
#define dwarf_is_big_endian(addr_space) 1
|
||||||
|
|
||||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||||
unw_cursor_t. */
|
unw_cursor_t. */
|
||||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||||
|
|
||||||
typedef struct dwarf_loc
|
typedef struct dwarf_loc
|
||||||
{
|
{
|
||||||
unw_word_t val;
|
unw_word_t val;
|
||||||
#ifndef UNW_LOCAL_ONLY
|
#ifndef UNW_LOCAL_ONLY
|
||||||
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
dwarf_loc_t;
|
dwarf_loc_t;
|
||||||
|
|
|
@ -31,7 +31,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||||
|
|
||||||
#define JB_SP 6
|
#define JB_SP 6
|
||||||
#define JB_RP 7
|
#define JB_RP 7
|
||||||
#define JB_MASK_SAVED 8
|
#define JB_MASK_SAVED 8
|
||||||
#define JB_MASK 9
|
#define JB_MASK 9
|
||||||
|
|
|
@ -57,8 +57,8 @@ struct unw_addr_space
|
||||||
#else
|
#else
|
||||||
uint32_t cache_generation;
|
uint32_t cache_generation;
|
||||||
#endif
|
#endif
|
||||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||||
struct dwarf_rs_cache global_cache;
|
struct dwarf_rs_cache global_cache;
|
||||||
struct unw_debug_frame_list *debug_frames;
|
struct unw_debug_frame_list *debug_frames;
|
||||||
int validate;
|
int validate;
|
||||||
|
@ -66,53 +66,53 @@ struct unw_addr_space
|
||||||
|
|
||||||
struct cursor
|
struct cursor
|
||||||
{
|
{
|
||||||
struct dwarf_cursor dwarf; /* must be first */
|
struct dwarf_cursor dwarf; /* must be first */
|
||||||
|
|
||||||
/* Format of sigcontext structure and address at which it is
|
/* Format of sigcontext structure and address at which it is
|
||||||
stored: */
|
stored: */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PPC_SCF_NONE, /* no signal frame encountered */
|
PPC_SCF_NONE, /* no signal frame encountered */
|
||||||
PPC_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
|
PPC_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
|
||||||
}
|
}
|
||||||
sigcontext_format;
|
sigcontext_format;
|
||||||
unw_word_t sigcontext_addr;
|
unw_word_t sigcontext_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DWARF_GET_LOC(l) ((l).val)
|
#define DWARF_GET_LOC(l) ((l).val)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||||
# define DWARF_IS_REG_LOC(l) 0
|
# define DWARF_IS_REG_LOC(l) 0
|
||||||
# define DWARF_IS_FP_LOC(l) 0
|
# define DWARF_IS_FP_LOC(l) 0
|
||||||
# define DWARF_IS_V_LOC(l) 0
|
# define DWARF_IS_V_LOC(l) 0
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
# define DWARF_VREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_VREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
#else /* !UNW_LOCAL_ONLY */
|
#else /* !UNW_LOCAL_ONLY */
|
||||||
|
|
||||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||||
# define DWARF_LOC_TYPE_V (1 << 2)
|
# define DWARF_LOC_TYPE_V (1 << 2)
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) \
|
# define DWARF_IS_NULL_LOC(l) \
|
||||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
({ 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_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_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_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||||
# define DWARF_IS_V_LOC(l) (((l).type & DWARF_LOC_TYPE_V) != 0)
|
# define DWARF_IS_V_LOC(l) (((l).type & DWARF_LOC_TYPE_V) != 0)
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||||
| DWARF_LOC_TYPE_FP))
|
| DWARF_LOC_TYPE_FP))
|
||||||
# define DWARF_VREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
# define DWARF_VREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||||
| DWARF_LOC_TYPE_V))
|
| DWARF_LOC_TYPE_V))
|
||||||
|
|
||||||
#endif /* !UNW_LOCAL_ONLY */
|
#endif /* !UNW_LOCAL_ONLY */
|
||||||
|
|
||||||
|
@ -131,12 +131,12 @@ dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
val, 0, c->as_arg);
|
val, 0, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
|
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
|
||||||
0, c->as_arg)) < 0)
|
0, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 0, c->as_arg);
|
return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 0, c->as_arg);
|
||||||
|
@ -157,11 +157,11 @@ dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
&val, 1, c->as_arg);
|
&val, 1, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
|
||||||
1, c->as_arg)) < 0)
|
1, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 1, c->as_arg);
|
return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 1, c->as_arg);
|
||||||
|
@ -181,7 +181,7 @@ dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
val, 0, c->as_arg);
|
val, 0, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 0, c->as_arg);
|
return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 0, c->as_arg);
|
||||||
|
@ -202,7 +202,7 @@ dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
&val, 1, c->as_arg);
|
&val, 1, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
|
|
||||||
|
@ -224,10 +224,10 @@ dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t * val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -245,68 +245,68 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define tdep_getcontext_trace unw_getcontext
|
#define tdep_getcontext_trace unw_getcontext
|
||||||
#define tdep_init_done UNW_OBJ(init_done)
|
#define tdep_init_done UNW_OBJ(init_done)
|
||||||
#define tdep_init UNW_OBJ(init)
|
#define tdep_init UNW_OBJ(init)
|
||||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||||
tdep_search_unwind_table. */
|
tdep_search_unwind_table. */
|
||||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||||
#define tdep_cache_frame(c,rs) do {} while(0)
|
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||||
#define tdep_get_func_addr UNW_OBJ(get_func_addr)
|
#define tdep_get_func_addr UNW_OBJ(get_func_addr)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
dwarf_put_unwind_info((as), (pi), (arg))
|
dwarf_put_unwind_info((as), (pi), (arg))
|
||||||
#else
|
#else
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int tdep_fetch_proc_info_post (struct dwarf_cursor *c, unw_word_t ip,
|
extern int tdep_fetch_proc_info_post (struct dwarf_cursor *c, unw_word_t ip,
|
||||||
int need_unwind_info);
|
int need_unwind_info);
|
||||||
|
|
||||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||||
#define tdep_big_endian(as) 1
|
#define tdep_big_endian(as) 1
|
||||||
|
|
||||||
extern int tdep_init_done;
|
extern int tdep_init_done;
|
||||||
|
|
||||||
extern void tdep_init (void);
|
extern void tdep_init (void);
|
||||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||||
unw_dyn_info_t * di,
|
unw_dyn_info_t * di,
|
||||||
unw_proc_info_t * pi,
|
unw_proc_info_t * pi,
|
||||||
int need_unwind_info, void *arg);
|
int need_unwind_info, void *arg);
|
||||||
extern void *tdep_uc_addr (ucontext_t * uc, int reg);
|
extern void *tdep_uc_addr (ucontext_t * uc, int reg);
|
||||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||||
unsigned long *segbase, unsigned long *mapoff,
|
unsigned long *segbase, unsigned long *mapoff,
|
||||||
char *path, size_t pathlen);
|
char *path, size_t pathlen);
|
||||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_word_t * valp, int write);
|
unw_word_t * valp, int write);
|
||||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_fpreg_t * valp, int write);
|
unw_fpreg_t * valp, int write);
|
||||||
extern int tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr,
|
extern int tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr,
|
||||||
unw_word_t *entry_point);
|
unw_word_t *entry_point);
|
||||||
|
|
||||||
#endif /* PPC64_LIBUNWIND_I_H */
|
#endif /* PPC64_LIBUNWIND_I_H */
|
||||||
|
|
|
@ -33,22 +33,22 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#define dwarf_config_h
|
#define dwarf_config_h
|
||||||
|
|
||||||
/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */
|
/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */
|
||||||
#define DWARF_NUM_PRESERVED_REGS 115
|
#define DWARF_NUM_PRESERVED_REGS 115
|
||||||
|
|
||||||
#define DWARF_REGNUM_MAP_LENGTH 115
|
#define DWARF_REGNUM_MAP_LENGTH 115
|
||||||
|
|
||||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||||
#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
|
#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
|
||||||
|
|
||||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||||
unw_cursor_t. */
|
unw_cursor_t. */
|
||||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||||
|
|
||||||
typedef struct dwarf_loc
|
typedef struct dwarf_loc
|
||||||
{
|
{
|
||||||
unw_word_t val;
|
unw_word_t val;
|
||||||
#ifndef UNW_LOCAL_ONLY
|
#ifndef UNW_LOCAL_ONLY
|
||||||
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
dwarf_loc_t;
|
dwarf_loc_t;
|
||||||
|
|
|
@ -31,7 +31,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||||
|
|
||||||
#define JB_SP 6
|
#define JB_SP 6
|
||||||
#define JB_RP 7
|
#define JB_RP 7
|
||||||
#define JB_MASK_SAVED 8
|
#define JB_MASK_SAVED 8
|
||||||
#define JB_MASK 9
|
#define JB_MASK 9
|
||||||
|
|
|
@ -59,8 +59,8 @@ struct unw_addr_space
|
||||||
#else
|
#else
|
||||||
uint32_t cache_generation;
|
uint32_t cache_generation;
|
||||||
#endif
|
#endif
|
||||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||||
struct dwarf_rs_cache global_cache;
|
struct dwarf_rs_cache global_cache;
|
||||||
struct unw_debug_frame_list *debug_frames;
|
struct unw_debug_frame_list *debug_frames;
|
||||||
int validate;
|
int validate;
|
||||||
|
@ -68,53 +68,53 @@ struct unw_addr_space
|
||||||
|
|
||||||
struct cursor
|
struct cursor
|
||||||
{
|
{
|
||||||
struct dwarf_cursor dwarf; /* must be first */
|
struct dwarf_cursor dwarf; /* must be first */
|
||||||
|
|
||||||
/* Format of sigcontext structure and address at which it is
|
/* Format of sigcontext structure and address at which it is
|
||||||
stored: */
|
stored: */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PPC_SCF_NONE, /* no signal frame encountered */
|
PPC_SCF_NONE, /* no signal frame encountered */
|
||||||
PPC_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
|
PPC_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
|
||||||
}
|
}
|
||||||
sigcontext_format;
|
sigcontext_format;
|
||||||
unw_word_t sigcontext_addr;
|
unw_word_t sigcontext_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DWARF_GET_LOC(l) ((l).val)
|
#define DWARF_GET_LOC(l) ((l).val)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||||
# define DWARF_IS_REG_LOC(l) 0
|
# define DWARF_IS_REG_LOC(l) 0
|
||||||
# define DWARF_IS_FP_LOC(l) 0
|
# define DWARF_IS_FP_LOC(l) 0
|
||||||
# define DWARF_IS_V_LOC(l) 0
|
# define DWARF_IS_V_LOC(l) 0
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
# define DWARF_VREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_VREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
#else /* !UNW_LOCAL_ONLY */
|
#else /* !UNW_LOCAL_ONLY */
|
||||||
|
|
||||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||||
# define DWARF_LOC_TYPE_V (1 << 2)
|
# define DWARF_LOC_TYPE_V (1 << 2)
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) \
|
# define DWARF_IS_NULL_LOC(l) \
|
||||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
({ 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_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_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_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||||
# define DWARF_IS_V_LOC(l) (((l).type & DWARF_LOC_TYPE_V) != 0)
|
# define DWARF_IS_V_LOC(l) (((l).type & DWARF_LOC_TYPE_V) != 0)
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||||
| DWARF_LOC_TYPE_FP))
|
| DWARF_LOC_TYPE_FP))
|
||||||
# define DWARF_VREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
# define DWARF_VREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||||
| DWARF_LOC_TYPE_V))
|
| DWARF_LOC_TYPE_V))
|
||||||
|
|
||||||
#endif /* !UNW_LOCAL_ONLY */
|
#endif /* !UNW_LOCAL_ONLY */
|
||||||
|
|
||||||
|
@ -133,12 +133,12 @@ dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
val, 0, c->as_arg);
|
val, 0, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
|
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
|
||||||
0, c->as_arg)) < 0)
|
0, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 0, c->as_arg);
|
return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 0, c->as_arg);
|
||||||
|
@ -159,11 +159,11 @@ dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
&val, 1, c->as_arg);
|
&val, 1, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
|
||||||
1, c->as_arg)) < 0)
|
1, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 1, c->as_arg);
|
return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 1, c->as_arg);
|
||||||
|
@ -183,7 +183,7 @@ dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
val, 0, c->as_arg);
|
val, 0, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 0, c->as_arg);
|
return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 0, c->as_arg);
|
||||||
|
@ -204,7 +204,7 @@ dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
&val, 1, c->as_arg);
|
&val, 1, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
|
|
||||||
|
@ -226,10 +226,10 @@ dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t * val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -247,68 +247,68 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define tdep_getcontext_trace unw_getcontext
|
#define tdep_getcontext_trace unw_getcontext
|
||||||
#define tdep_init_done UNW_OBJ(init_done)
|
#define tdep_init_done UNW_OBJ(init_done)
|
||||||
#define tdep_init UNW_OBJ(init)
|
#define tdep_init UNW_OBJ(init)
|
||||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||||
tdep_search_unwind_table. */
|
tdep_search_unwind_table. */
|
||||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||||
#define tdep_cache_frame(c,rs) do {} while(0)
|
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||||
#define tdep_get_func_addr UNW_OBJ(get_func_addr)
|
#define tdep_get_func_addr UNW_OBJ(get_func_addr)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
dwarf_put_unwind_info((as), (pi), (arg))
|
dwarf_put_unwind_info((as), (pi), (arg))
|
||||||
#else
|
#else
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int tdep_fetch_proc_info_post (struct dwarf_cursor *c, unw_word_t ip,
|
extern int tdep_fetch_proc_info_post (struct dwarf_cursor *c, unw_word_t ip,
|
||||||
int need_unwind_info);
|
int need_unwind_info);
|
||||||
|
|
||||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||||
#define tdep_big_endian(as) ((as)->big_endian)
|
#define tdep_big_endian(as) ((as)->big_endian)
|
||||||
|
|
||||||
extern int tdep_init_done;
|
extern int tdep_init_done;
|
||||||
|
|
||||||
extern void tdep_init (void);
|
extern void tdep_init (void);
|
||||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||||
unw_dyn_info_t * di,
|
unw_dyn_info_t * di,
|
||||||
unw_proc_info_t * pi,
|
unw_proc_info_t * pi,
|
||||||
int need_unwind_info, void *arg);
|
int need_unwind_info, void *arg);
|
||||||
extern void *tdep_uc_addr (ucontext_t * uc, int reg);
|
extern void *tdep_uc_addr (ucontext_t * uc, int reg);
|
||||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||||
unsigned long *segbase, unsigned long *mapoff,
|
unsigned long *segbase, unsigned long *mapoff,
|
||||||
char *path, size_t pathlen);
|
char *path, size_t pathlen);
|
||||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_word_t * valp, int write);
|
unw_word_t * valp, int write);
|
||||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_fpreg_t * valp, int write);
|
unw_fpreg_t * valp, int write);
|
||||||
extern int tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr,
|
extern int tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr,
|
||||||
unw_word_t *entry_point);
|
unw_word_t *entry_point);
|
||||||
|
|
||||||
#endif /* PPC64_LIBUNWIND_I_H */
|
#endif /* PPC64_LIBUNWIND_I_H */
|
||||||
|
|
|
@ -26,22 +26,22 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#ifndef dwarf_config_h
|
#ifndef dwarf_config_h
|
||||||
#define dwarf_config_h
|
#define dwarf_config_h
|
||||||
|
|
||||||
#define DWARF_NUM_PRESERVED_REGS 18
|
#define DWARF_NUM_PRESERVED_REGS 18
|
||||||
|
|
||||||
#define dwarf_to_unw_regnum(reg) (((reg) <= UNW_SH_PR) ? (reg) : 0)
|
#define dwarf_to_unw_regnum(reg) (((reg) <= UNW_SH_PR) ? (reg) : 0)
|
||||||
|
|
||||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||||
#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
|
#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian)
|
||||||
|
|
||||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||||
unw_cursor_t. */
|
unw_cursor_t. */
|
||||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||||
|
|
||||||
typedef struct dwarf_loc
|
typedef struct dwarf_loc
|
||||||
{
|
{
|
||||||
unw_word_t val;
|
unw_word_t val;
|
||||||
#ifndef UNW_LOCAL_ONLY
|
#ifndef UNW_LOCAL_ONLY
|
||||||
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
dwarf_loc_t;
|
dwarf_loc_t;
|
||||||
|
|
|
@ -42,7 +42,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
* 14. fr15
|
* 14. fr15
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define JB_SP 7
|
#define JB_SP 7
|
||||||
#define JB_RP 8
|
#define JB_RP 8
|
||||||
#define JB_MASK_SAVED 15
|
#define JB_MASK_SAVED 15
|
||||||
#define JB_MASK 16
|
#define JB_MASK 16
|
||||||
|
|
|
@ -52,15 +52,15 @@ struct unw_addr_space
|
||||||
#else
|
#else
|
||||||
uint32_t cache_generation;
|
uint32_t cache_generation;
|
||||||
#endif
|
#endif
|
||||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||||
struct dwarf_rs_cache global_cache;
|
struct dwarf_rs_cache global_cache;
|
||||||
struct unw_debug_frame_list *debug_frames;
|
struct unw_debug_frame_list *debug_frames;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cursor
|
struct cursor
|
||||||
{
|
{
|
||||||
struct dwarf_cursor dwarf; /* must be first */
|
struct dwarf_cursor dwarf; /* must be first */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SH_SCF_NONE, /* no signal frame */
|
SH_SCF_NONE, /* no signal frame */
|
||||||
|
@ -73,18 +73,18 @@ struct cursor
|
||||||
unw_word_t sigcontext_pc;
|
unw_word_t sigcontext_pc;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DWARF_GET_LOC(l) ((l).val)
|
#define DWARF_GET_LOC(l) ((l).val)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||||
# define DWARF_IS_REG_LOC(l) 0
|
# define DWARF_IS_REG_LOC(l) 0
|
||||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr((c)->as_arg, (r)), 0))
|
tdep_uc_addr((c)->as_arg, (r)), 0))
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
@ -123,18 +123,18 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !UNW_LOCAL_ONLY */
|
#else /* !UNW_LOCAL_ONLY */
|
||||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) \
|
# define DWARF_IS_NULL_LOC(l) \
|
||||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
({ 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_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_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_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_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||||
| DWARF_LOC_TYPE_FP))
|
| DWARF_LOC_TYPE_FP))
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
@ -148,15 +148,15 @@ dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
val, 0, c->as_arg);
|
val, 0, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||||
0, c->as_arg)) < 0)
|
0, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
||||||
c->as_arg);
|
c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -171,15 +171,15 @@ dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
&val, 1, c->as_arg);
|
&val, 1, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||||
1, c->as_arg)) < 0)
|
1, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -196,10 +196,10 @@ dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -216,63 +216,63 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !UNW_LOCAL_ONLY */
|
#endif /* !UNW_LOCAL_ONLY */
|
||||||
|
|
||||||
#define tdep_getcontext_trace unw_getcontext
|
#define tdep_getcontext_trace unw_getcontext
|
||||||
#define tdep_init_done UNW_OBJ(init_done)
|
#define tdep_init_done UNW_OBJ(init_done)
|
||||||
#define tdep_init UNW_OBJ(init)
|
#define tdep_init UNW_OBJ(init)
|
||||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||||
tdep_search_unwind_table. */
|
tdep_search_unwind_table. */
|
||||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||||
#define tdep_cache_frame(c,rs) do {} while(0)
|
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
dwarf_put_unwind_info((as), (pi), (arg))
|
dwarf_put_unwind_info((as), (pi), (arg))
|
||||||
#else
|
#else
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||||
#define tdep_big_endian(as) ((as)->big_endian)
|
#define tdep_big_endian(as) ((as)->big_endian)
|
||||||
|
|
||||||
extern int tdep_init_done;
|
extern int tdep_init_done;
|
||||||
|
|
||||||
extern void tdep_init (void);
|
extern void tdep_init (void);
|
||||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
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,
|
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg);
|
int need_unwind_info, void *arg);
|
||||||
extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
|
extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
|
||||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||||
unsigned long *segbase, unsigned long *mapoff,
|
unsigned long *segbase, unsigned long *mapoff,
|
||||||
char *path, size_t pathlen);
|
char *path, size_t pathlen);
|
||||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_word_t *valp, int write);
|
unw_word_t *valp, int write);
|
||||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_fpreg_t *valp, int write);
|
unw_fpreg_t *valp, int write);
|
||||||
|
|
||||||
#endif /* SH_LIBUNWIND_I_H */
|
#endif /* SH_LIBUNWIND_I_H */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
|
Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -29,22 +29,22 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/* This matches the value used by GCC (see
|
/* This matches the value used by GCC (see
|
||||||
gcc/config/i386.h:DWARF_FRAME_REGISTERS), which leaves plenty of
|
gcc/config/i386.h:DWARF_FRAME_REGISTERS), which leaves plenty of
|
||||||
room for expansion. */
|
room for expansion. */
|
||||||
#define DWARF_NUM_PRESERVED_REGS 17
|
#define DWARF_NUM_PRESERVED_REGS 17
|
||||||
|
|
||||||
#define DWARF_REGNUM_MAP_LENGTH 19
|
#define DWARF_REGNUM_MAP_LENGTH 19
|
||||||
|
|
||||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||||
#define dwarf_is_big_endian(addr_space) 0
|
#define dwarf_is_big_endian(addr_space) 0
|
||||||
|
|
||||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||||
unw_cursor_t. */
|
unw_cursor_t. */
|
||||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||||
|
|
||||||
typedef struct dwarf_loc
|
typedef struct dwarf_loc
|
||||||
{
|
{
|
||||||
unw_word_t val;
|
unw_word_t val;
|
||||||
#ifndef UNW_LOCAL_ONLY
|
#ifndef UNW_LOCAL_ONLY
|
||||||
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
dwarf_loc_t;
|
dwarf_loc_t;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2004 Hewlett-Packard Co
|
Copyright (C) 2004 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -27,16 +27,16 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
#if defined __linux__
|
#if defined __linux__
|
||||||
|
|
||||||
#define JB_SP 4
|
#define JB_SP 4
|
||||||
#define JB_RP 5
|
#define JB_RP 5
|
||||||
#define JB_MASK_SAVED 6
|
#define JB_MASK_SAVED 6
|
||||||
#define JB_MASK 7
|
#define JB_MASK 7
|
||||||
|
|
||||||
#elif defined __FreeBSD__
|
#elif defined __FreeBSD__
|
||||||
|
|
||||||
#define JB_SP 2
|
#define JB_SP 2
|
||||||
#define JB_RP 0
|
#define JB_RP 0
|
||||||
#define JB_MASK_SAVED 11
|
#define JB_MASK_SAVED 11
|
||||||
#define JB_MASK 7
|
#define JB_MASK 7
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2002-2005 Hewlett-Packard Co
|
Copyright (C) 2002-2005 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -51,27 +51,27 @@ struct unw_addr_space
|
||||||
#else
|
#else
|
||||||
uint32_t cache_generation;
|
uint32_t cache_generation;
|
||||||
#endif
|
#endif
|
||||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||||
struct dwarf_rs_cache global_cache;
|
struct dwarf_rs_cache global_cache;
|
||||||
struct unw_debug_frame_list *debug_frames;
|
struct unw_debug_frame_list *debug_frames;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cursor
|
struct cursor
|
||||||
{
|
{
|
||||||
struct dwarf_cursor dwarf; /* must be first */
|
struct dwarf_cursor dwarf; /* must be first */
|
||||||
|
|
||||||
/* Format of sigcontext structure and address at which it is
|
/* Format of sigcontext structure and address at which it is
|
||||||
stored: */
|
stored: */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
X86_SCF_NONE, /* no signal frame encountered */
|
X86_SCF_NONE, /* no signal frame encountered */
|
||||||
X86_SCF_LINUX_SIGFRAME, /* Linux x86 sigcontext */
|
X86_SCF_LINUX_SIGFRAME, /* Linux x86 sigcontext */
|
||||||
X86_SCF_LINUX_RT_SIGFRAME, /* POSIX ucontext_t */
|
X86_SCF_LINUX_RT_SIGFRAME, /* POSIX ucontext_t */
|
||||||
X86_SCF_FREEBSD_SIGFRAME, /* FreeBSD x86 sigcontext */
|
X86_SCF_FREEBSD_SIGFRAME, /* FreeBSD x86 sigcontext */
|
||||||
X86_SCF_FREEBSD_SIGFRAME4, /* FreeBSD 4.x x86 sigcontext */
|
X86_SCF_FREEBSD_SIGFRAME4, /* FreeBSD 4.x x86 sigcontext */
|
||||||
X86_SCF_FREEBSD_OSIGFRAME, /* FreeBSD pre-4.x x86 sigcontext */
|
X86_SCF_FREEBSD_OSIGFRAME, /* FreeBSD pre-4.x x86 sigcontext */
|
||||||
X86_SCF_FREEBSD_SYSCALL, /* FreeBSD x86 syscall */
|
X86_SCF_FREEBSD_SYSCALL, /* FreeBSD x86 syscall */
|
||||||
}
|
}
|
||||||
sigcontext_format;
|
sigcontext_format;
|
||||||
unw_word_t sigcontext_addr;
|
unw_word_t sigcontext_addr;
|
||||||
|
@ -86,18 +86,18 @@ dwarf_get_uc(const struct dwarf_cursor *cursor)
|
||||||
return c->uc;
|
return c->uc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DWARF_GET_LOC(l) ((l).val)
|
#define DWARF_GET_LOC(l) ((l).val)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||||
# define DWARF_IS_REG_LOC(l) 0
|
# define DWARF_IS_REG_LOC(l) 0
|
||||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr(dwarf_get_uc(c), (r)), 0))
|
tdep_uc_addr(dwarf_get_uc(c), (r)), 0))
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
tdep_uc_addr(dwarf_get_uc(c), (r)), 0))
|
tdep_uc_addr(dwarf_get_uc(c), (r)), 0))
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
@ -123,7 +123,7 @@ dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||||
if (!DWARF_GET_LOC (loc))
|
if (!DWARF_GET_LOC (loc))
|
||||||
return -1;
|
return -1;
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -132,22 +132,22 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
if (!DWARF_GET_LOC (loc))
|
if (!DWARF_GET_LOC (loc))
|
||||||
return -1;
|
return -1;
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !UNW_LOCAL_ONLY */
|
#else /* !UNW_LOCAL_ONLY */
|
||||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) \
|
# define DWARF_IS_NULL_LOC(l) \
|
||||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
({ 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_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_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_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_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||||
| DWARF_LOC_TYPE_FP))
|
| DWARF_LOC_TYPE_FP))
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
@ -161,15 +161,15 @@ dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
val, 0, c->as_arg);
|
val, 0, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||||
0, c->as_arg)) < 0)
|
0, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
|
||||||
c->as_arg);
|
c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -184,15 +184,15 @@ dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
|
||||||
&val, 1, c->as_arg);
|
&val, 1, c->as_arg);
|
||||||
|
|
||||||
addr = DWARF_GET_LOC (loc);
|
addr = DWARF_GET_LOC (loc);
|
||||||
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
|
||||||
1, c->as_arg)) < 0)
|
1, c->as_arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -209,10 +209,10 @@ dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -229,63 +229,63 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !UNW_LOCAL_ONLY */
|
#endif /* !UNW_LOCAL_ONLY */
|
||||||
|
|
||||||
#define tdep_getcontext_trace unw_getcontext
|
#define tdep_getcontext_trace unw_getcontext
|
||||||
#define tdep_init_done UNW_OBJ(init_done)
|
#define tdep_init_done UNW_OBJ(init_done)
|
||||||
#define tdep_init UNW_OBJ(init)
|
#define tdep_init UNW_OBJ(init)
|
||||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||||
tdep_search_unwind_table. */
|
tdep_search_unwind_table. */
|
||||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||||
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr)
|
||||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||||
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
#define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||||
#define tdep_cache_frame(c,rs) do {} while(0)
|
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
dwarf_put_unwind_info((as), (pi), (arg))
|
dwarf_put_unwind_info((as), (pi), (arg))
|
||||||
#else
|
#else
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||||
#define tdep_big_endian(as) 0
|
#define tdep_big_endian(as) 0
|
||||||
|
|
||||||
extern int tdep_init_done;
|
extern int tdep_init_done;
|
||||||
|
|
||||||
extern void tdep_init (void);
|
extern void tdep_init (void);
|
||||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
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,
|
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg);
|
int need_unwind_info, void *arg);
|
||||||
extern void *tdep_uc_addr (ucontext_t *uc, int reg);
|
extern void *tdep_uc_addr (ucontext_t *uc, int reg);
|
||||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||||
unsigned long *segbase, unsigned long *mapoff,
|
unsigned long *segbase, unsigned long *mapoff,
|
||||||
char *path, size_t pathlen);
|
char *path, size_t pathlen);
|
||||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_word_t *valp, int write);
|
unw_word_t *valp, int write);
|
||||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_fpreg_t *valp, int write);
|
unw_fpreg_t *valp, int write);
|
||||||
|
|
||||||
#endif /* X86_LIBUNWIND_I_H */
|
#endif /* X86_LIBUNWIND_I_H */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
|
Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
|
Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
|
||||||
|
|
||||||
|
@ -33,25 +33,25 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* XXX need to verify if this value is correct */
|
/* XXX need to verify if this value is correct */
|
||||||
#ifdef CONFIG_MSABI_SUPPORT
|
#ifdef CONFIG_MSABI_SUPPORT
|
||||||
#define DWARF_NUM_PRESERVED_REGS 33
|
#define DWARF_NUM_PRESERVED_REGS 33
|
||||||
#else
|
#else
|
||||||
#define DWARF_NUM_PRESERVED_REGS 17
|
#define DWARF_NUM_PRESERVED_REGS 17
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DWARF_REGNUM_MAP_LENGTH DWARF_NUM_PRESERVED_REGS
|
#define DWARF_REGNUM_MAP_LENGTH DWARF_NUM_PRESERVED_REGS
|
||||||
|
|
||||||
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */
|
||||||
#define dwarf_is_big_endian(addr_space) 0
|
#define dwarf_is_big_endian(addr_space) 0
|
||||||
|
|
||||||
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
/* Convert a pointer to a dwarf_cursor structure to a pointer to
|
||||||
unw_cursor_t. */
|
unw_cursor_t. */
|
||||||
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
#define dwarf_to_cursor(c) ((unw_cursor_t *) (c))
|
||||||
|
|
||||||
typedef struct dwarf_loc
|
typedef struct dwarf_loc
|
||||||
{
|
{
|
||||||
unw_word_t val;
|
unw_word_t val;
|
||||||
#ifndef UNW_LOCAL_ONLY
|
#ifndef UNW_LOCAL_ONLY
|
||||||
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
unw_word_t type; /* see X86_LOC_TYPE_* macros. */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
dwarf_loc_t;
|
dwarf_loc_t;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2004 Hewlett-Packard Co
|
Copyright (C) 2004 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -27,17 +27,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||||
|
|
||||||
#define JB_SP 6
|
#define JB_SP 6
|
||||||
#define JB_RP 7
|
#define JB_RP 7
|
||||||
#define JB_MASK_SAVED 8
|
#define JB_MASK_SAVED 8
|
||||||
#define JB_MASK 9
|
#define JB_MASK 9
|
||||||
|
|
||||||
#elif defined __FreeBSD__
|
#elif defined __FreeBSD__
|
||||||
|
|
||||||
#define JB_SP 2
|
#define JB_SP 2
|
||||||
#define JB_RP 0
|
#define JB_RP 0
|
||||||
/* Pretend the ip cannot be 0 and mask is always saved */
|
/* Pretend the ip cannot be 0 and mask is always saved */
|
||||||
#define JB_MASK_SAVED 0
|
#define JB_MASK_SAVED 0
|
||||||
#define JB_MASK 9
|
#define JB_MASK 9
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2002-2005 Hewlett-Packard Co
|
Copyright (C) 2002-2005 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
|
Modified for x86_64 by Max Asbock <masbock@us.ibm.com>
|
||||||
|
|
||||||
|
@ -68,26 +68,26 @@ struct unw_addr_space
|
||||||
#else
|
#else
|
||||||
uint32_t cache_generation;
|
uint32_t cache_generation;
|
||||||
#endif
|
#endif
|
||||||
unw_word_t dyn_generation; /* see dyn-common.h */
|
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||||
struct dwarf_rs_cache global_cache;
|
struct dwarf_rs_cache global_cache;
|
||||||
struct unw_debug_frame_list *debug_frames;
|
struct unw_debug_frame_list *debug_frames;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cursor
|
struct cursor
|
||||||
{
|
{
|
||||||
struct dwarf_cursor dwarf; /* must be first */
|
struct dwarf_cursor dwarf; /* must be first */
|
||||||
|
|
||||||
unw_tdep_frame_t frame_info; /* quick tracing assist info */
|
unw_tdep_frame_t frame_info; /* quick tracing assist info */
|
||||||
|
|
||||||
/* Format of sigcontext structure and address at which it is
|
/* Format of sigcontext structure and address at which it is
|
||||||
stored: */
|
stored: */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
X86_64_SCF_NONE, /* no signal frame encountered */
|
X86_64_SCF_NONE, /* no signal frame encountered */
|
||||||
X86_64_SCF_LINUX_RT_SIGFRAME, /* Linux ucontext_t */
|
X86_64_SCF_LINUX_RT_SIGFRAME, /* Linux ucontext_t */
|
||||||
X86_64_SCF_FREEBSD_SIGFRAME, /* FreeBSD signal frame */
|
X86_64_SCF_FREEBSD_SIGFRAME, /* FreeBSD signal frame */
|
||||||
X86_64_SCF_FREEBSD_SYSCALL, /* FreeBSD syscall */
|
X86_64_SCF_FREEBSD_SYSCALL, /* FreeBSD syscall */
|
||||||
}
|
}
|
||||||
sigcontext_format;
|
sigcontext_format;
|
||||||
unw_word_t sigcontext_addr;
|
unw_word_t sigcontext_addr;
|
||||||
|
@ -102,40 +102,40 @@ dwarf_get_uc(const struct dwarf_cursor *cursor)
|
||||||
return c->uc;
|
return c->uc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DWARF_GET_LOC(l) ((l).val)
|
#define DWARF_GET_LOC(l) ((l).val)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0)
|
||||||
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
|
||||||
# define DWARF_IS_REG_LOC(l) 0
|
# define DWARF_IS_REG_LOC(l) 0
|
||||||
# define DWARF_IS_MEM_LOC(l) 1
|
# define DWARF_IS_MEM_LOC(l) 1
|
||||||
# define DWARF_IS_VAL_LOC(l) 0
|
# define DWARF_IS_VAL_LOC(l) 0
|
||||||
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
x86_64_r_uc_addr(dwarf_get_uc(c), (r)), 0))
|
x86_64_r_uc_addr(dwarf_get_uc(c), (r)), 0))
|
||||||
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
|
||||||
x86_64_r_uc_addr(dwarf_get_uc(c), (r)), 0))
|
x86_64_r_uc_addr(dwarf_get_uc(c), (r)), 0))
|
||||||
# define DWARF_VAL_LOC(c,v) DWARF_NULL_LOC
|
# define DWARF_VAL_LOC(c,v) DWARF_NULL_LOC
|
||||||
|
|
||||||
#else /* !UNW_LOCAL_ONLY */
|
#else /* !UNW_LOCAL_ONLY */
|
||||||
|
|
||||||
# define DWARF_LOC_TYPE_FP (1 << 0)
|
# define DWARF_LOC_TYPE_FP (1 << 0)
|
||||||
# define DWARF_LOC_TYPE_REG (1 << 1)
|
# define DWARF_LOC_TYPE_REG (1 << 1)
|
||||||
# define DWARF_LOC_TYPE_VAL (1 << 2)
|
# define DWARF_LOC_TYPE_VAL (1 << 2)
|
||||||
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
|
||||||
# define DWARF_IS_NULL_LOC(l) \
|
# define DWARF_IS_NULL_LOC(l) \
|
||||||
({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
|
({ 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_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_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_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
|
||||||
# define DWARF_IS_MEM_LOC(l) ((l).type == 0)
|
# define DWARF_IS_MEM_LOC(l) ((l).type == 0)
|
||||||
# define DWARF_IS_VAL_LOC(l) (((l).type & DWARF_LOC_TYPE_VAL) != 0)
|
# define DWARF_IS_VAL_LOC(l) (((l).type & DWARF_LOC_TYPE_VAL) != 0)
|
||||||
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
|
# 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_MEM_LOC(c,m) DWARF_LOC ((m), 0)
|
||||||
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
|
||||||
| DWARF_LOC_TYPE_FP))
|
| DWARF_LOC_TYPE_FP))
|
||||||
# define DWARF_VAL_LOC(c,v) DWARF_LOC ((v), DWARF_LOC_TYPE_VAL)
|
# define DWARF_VAL_LOC(c,v) DWARF_LOC ((v), DWARF_LOC_TYPE_VAL)
|
||||||
|
|
||||||
#endif /* !UNW_LOCAL_ONLY */
|
#endif /* !UNW_LOCAL_ONLY */
|
||||||
|
|
||||||
|
@ -165,10 +165,10 @@ dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
if (DWARF_IS_MEM_LOC (loc))
|
if (DWARF_IS_MEM_LOC (loc))
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
|
||||||
0, c->as_arg);
|
0, c->as_arg);
|
||||||
assert(DWARF_IS_VAL_LOC (loc));
|
assert(DWARF_IS_VAL_LOC (loc));
|
||||||
*val = DWARF_GET_LOC (loc);
|
*val = DWARF_GET_LOC (loc);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -184,79 +184,79 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
||||||
|
|
||||||
if (DWARF_IS_REG_LOC (loc))
|
if (DWARF_IS_REG_LOC (loc))
|
||||||
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
else
|
else
|
||||||
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
|
||||||
1, c->as_arg);
|
1, c->as_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define tdep_getcontext_trace UNW_ARCH_OBJ(getcontext_trace)
|
#define tdep_getcontext_trace UNW_ARCH_OBJ(getcontext_trace)
|
||||||
#define tdep_init_done UNW_OBJ(init_done)
|
#define tdep_init_done UNW_OBJ(init_done)
|
||||||
#define tdep_init_mem_validate UNW_OBJ(init_mem_validate)
|
#define tdep_init_mem_validate UNW_OBJ(init_mem_validate)
|
||||||
#define tdep_init UNW_OBJ(init)
|
#define tdep_init UNW_OBJ(init)
|
||||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||||
tdep_search_unwind_table. */
|
tdep_search_unwind_table. */
|
||||||
#define tdep_search_unwind_table dwarf_search_unwind_table
|
#define tdep_search_unwind_table dwarf_search_unwind_table
|
||||||
#define tdep_find_unwind_table dwarf_find_unwind_table
|
#define tdep_find_unwind_table dwarf_find_unwind_table
|
||||||
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
|
||||||
#define tdep_access_reg UNW_OBJ(access_reg)
|
#define tdep_access_reg UNW_OBJ(access_reg)
|
||||||
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
|
||||||
#if __linux__
|
#if __linux__
|
||||||
# define tdep_fetch_frame UNW_OBJ(fetch_frame)
|
# define tdep_fetch_frame UNW_OBJ(fetch_frame)
|
||||||
# define tdep_cache_frame UNW_OBJ(cache_frame)
|
# define tdep_cache_frame UNW_OBJ(cache_frame)
|
||||||
# define tdep_reuse_frame UNW_OBJ(reuse_frame)
|
# define tdep_reuse_frame UNW_OBJ(reuse_frame)
|
||||||
#else
|
#else
|
||||||
# define tdep_fetch_frame(c,ip,n) do {} while(0)
|
# define tdep_fetch_frame(c,ip,n) do {} while(0)
|
||||||
# define tdep_cache_frame(c,rs) do {} while(0)
|
# define tdep_cache_frame(c,rs) do {} while(0)
|
||||||
# define tdep_reuse_frame(c,rs) do {} while(0)
|
# define tdep_reuse_frame(c,rs) do {} while(0)
|
||||||
#endif
|
#endif
|
||||||
#define tdep_stash_frame UNW_OBJ(stash_frame)
|
#define tdep_stash_frame UNW_OBJ(stash_frame)
|
||||||
#define tdep_trace UNW_OBJ(tdep_trace)
|
#define tdep_trace UNW_OBJ(tdep_trace)
|
||||||
#define x86_64_r_uc_addr UNW_OBJ(r_uc_addr)
|
#define x86_64_r_uc_addr UNW_OBJ(r_uc_addr)
|
||||||
|
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
dwarf_put_unwind_info((as), (pi), (arg))
|
dwarf_put_unwind_info((as), (pi), (arg))
|
||||||
#else
|
#else
|
||||||
# define tdep_find_proc_info(c,ip,n) \
|
# define tdep_find_proc_info(c,ip,n) \
|
||||||
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \
|
||||||
(c)->as_arg)
|
(c)->as_arg)
|
||||||
# define tdep_put_unwind_info(as,pi,arg) \
|
# define tdep_put_unwind_info(as,pi,arg) \
|
||||||
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
(*(as)->acc.put_unwind_info)((as), (pi), (arg))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define tdep_get_as(c) ((c)->dwarf.as)
|
#define tdep_get_as(c) ((c)->dwarf.as)
|
||||||
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
#define tdep_get_as_arg(c) ((c)->dwarf.as_arg)
|
||||||
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
#define tdep_get_ip(c) ((c)->dwarf.ip)
|
||||||
#define tdep_big_endian(as) 0
|
#define tdep_big_endian(as) 0
|
||||||
|
|
||||||
extern int tdep_init_done;
|
extern int tdep_init_done;
|
||||||
|
|
||||||
extern void tdep_init (void);
|
extern void tdep_init (void);
|
||||||
extern void tdep_init_mem_validate (void);
|
extern void tdep_init_mem_validate (void);
|
||||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
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,
|
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg);
|
int need_unwind_info, void *arg);
|
||||||
extern void *x86_64_r_uc_addr (ucontext_t *uc, int reg);
|
extern void *x86_64_r_uc_addr (ucontext_t *uc, int reg);
|
||||||
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||||
unsigned long *segbase, unsigned long *mapoff,
|
unsigned long *segbase, unsigned long *mapoff,
|
||||||
char *path, size_t pathlen);
|
char *path, size_t pathlen);
|
||||||
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_word_t *valp, int write);
|
unw_word_t *valp, int write);
|
||||||
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
|
||||||
unw_fpreg_t *valp, int write);
|
unw_fpreg_t *valp, int write);
|
||||||
#if __linux__
|
#if __linux__
|
||||||
extern void tdep_fetch_frame (struct dwarf_cursor *c, unw_word_t ip,
|
extern void tdep_fetch_frame (struct dwarf_cursor *c, unw_word_t ip,
|
||||||
int need_unwind_info);
|
int need_unwind_info);
|
||||||
extern void tdep_cache_frame (struct dwarf_cursor *c,
|
extern void tdep_cache_frame (struct dwarf_cursor *c,
|
||||||
struct dwarf_reg_state *rs);
|
struct dwarf_reg_state *rs);
|
||||||
extern void tdep_reuse_frame (struct dwarf_cursor *c,
|
extern void tdep_reuse_frame (struct dwarf_cursor *c,
|
||||||
struct dwarf_reg_state *rs);
|
struct dwarf_reg_state *rs);
|
||||||
extern void tdep_stash_frame (struct dwarf_cursor *c,
|
extern void tdep_stash_frame (struct dwarf_cursor *c,
|
||||||
struct dwarf_reg_state *rs);
|
struct dwarf_reg_state *rs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int tdep_getcontext_trace (unw_tdep_context_t *);
|
extern int tdep_getcontext_trace (unw_tdep_context_t *);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2003 Hewlett-Packard Co
|
Copyright (C) 2003 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ extern "C" {
|
||||||
|
|
||||||
/* Minimal interface as per C++ ABI draft standard:
|
/* Minimal interface as per C++ ABI draft standard:
|
||||||
|
|
||||||
http://www.codesourcery.com/cxx-abi/abi-eh.html */
|
http://www.codesourcery.com/cxx-abi/abi-eh.html */
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -53,22 +53,22 @@ _Unwind_Reason_Code;
|
||||||
|
|
||||||
typedef int _Unwind_Action;
|
typedef int _Unwind_Action;
|
||||||
|
|
||||||
#define _UA_SEARCH_PHASE 1
|
#define _UA_SEARCH_PHASE 1
|
||||||
#define _UA_CLEANUP_PHASE 2
|
#define _UA_CLEANUP_PHASE 2
|
||||||
#define _UA_HANDLER_FRAME 4
|
#define _UA_HANDLER_FRAME 4
|
||||||
#define _UA_FORCE_UNWIND 8
|
#define _UA_FORCE_UNWIND 8
|
||||||
|
|
||||||
struct _Unwind_Context; /* opaque data-structure */
|
struct _Unwind_Context; /* opaque data-structure */
|
||||||
struct _Unwind_Exception; /* forward-declaration */
|
struct _Unwind_Exception; /* forward-declaration */
|
||||||
|
|
||||||
typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
|
typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
|
||||||
struct _Unwind_Exception *);
|
struct _Unwind_Exception *);
|
||||||
|
|
||||||
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) (int, _Unwind_Action,
|
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) (int, _Unwind_Action,
|
||||||
uint64_t,
|
uint64_t,
|
||||||
struct _Unwind_Exception *,
|
struct _Unwind_Exception *,
|
||||||
struct _Unwind_Context *,
|
struct _Unwind_Context *,
|
||||||
void *);
|
void *);
|
||||||
|
|
||||||
/* The C++ ABI requires exception_class, private_1, and private_2 to
|
/* The C++ ABI requires exception_class, private_1, and private_2 to
|
||||||
be of type uint64 and the entire structure to be
|
be of type uint64 and the entire structure to be
|
||||||
|
@ -84,7 +84,7 @@ struct _Unwind_Exception
|
||||||
|
|
||||||
extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *);
|
extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *);
|
||||||
extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *,
|
extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *,
|
||||||
_Unwind_Stop_Fn, void *);
|
_Unwind_Stop_Fn, void *);
|
||||||
extern void _Unwind_Resume (struct _Unwind_Exception *);
|
extern void _Unwind_Resume (struct _Unwind_Exception *);
|
||||||
extern void _Unwind_DeleteException (struct _Unwind_Exception *);
|
extern void _Unwind_DeleteException (struct _Unwind_Exception *);
|
||||||
extern unsigned long _Unwind_GetGR (struct _Unwind_Context *, int);
|
extern unsigned long _Unwind_GetGR (struct _Unwind_Context *, int);
|
||||||
|
@ -100,17 +100,17 @@ extern unsigned long _Unwind_GetRegionStart (struct _Unwind_Context *);
|
||||||
/* Callback for _Unwind_Backtrace(). The backtrace stops immediately
|
/* Callback for _Unwind_Backtrace(). The backtrace stops immediately
|
||||||
if the callback returns any value other than _URC_NO_REASON. */
|
if the callback returns any value other than _URC_NO_REASON. */
|
||||||
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *,
|
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *,
|
||||||
void *);
|
void *);
|
||||||
|
|
||||||
/* See http://gcc.gnu.org/ml/gcc-patches/2001-09/msg00082.html for why
|
/* See http://gcc.gnu.org/ml/gcc-patches/2001-09/msg00082.html for why
|
||||||
_UA_END_OF_STACK exists. */
|
_UA_END_OF_STACK exists. */
|
||||||
# define _UA_END_OF_STACK 16
|
# define _UA_END_OF_STACK 16
|
||||||
|
|
||||||
/* If the unwind was initiated due to a forced unwind, resume that
|
/* If the unwind was initiated due to a forced unwind, resume that
|
||||||
operation, else re-raise the exception. This is used by
|
operation, else re-raise the exception. This is used by
|
||||||
__cxa_rethrow(). */
|
__cxa_rethrow(). */
|
||||||
extern _Unwind_Reason_Code
|
extern _Unwind_Reason_Code
|
||||||
_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *);
|
_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *);
|
||||||
|
|
||||||
/* See http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00154.html for why
|
/* See http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00154.html for why
|
||||||
_Unwind_GetBSP() exists. */
|
_Unwind_GetBSP() exists. */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2004 Hewlett-Packard Co
|
Copyright (C) 2004 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
/* Use glibc's jump-buffer indices; NPTL peeks at SP: */
|
||||||
|
|
||||||
#define JB_SP 4
|
#define JB_SP 4
|
||||||
#define JB_RP 5
|
#define JB_RP 5
|
||||||
#define JB_MASK_SAVED 6
|
#define JB_MASK_SAVED 6
|
||||||
#define JB_MASK 7
|
#define JB_MASK 7
|
||||||
|
|
|
@ -72,7 +72,7 @@ unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
loc = DWARF_NULL_LOC; /* default to "not saved" */
|
loc = DWARF_NULL_LOC; /* default to "not saved" */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ tdep_init (void)
|
||||||
#ifndef UNW_REMOTE_ONLY
|
#ifndef UNW_REMOTE_ONLY
|
||||||
aarch64_local_addr_space_init ();
|
aarch64_local_addr_space_init ();
|
||||||
#endif
|
#endif
|
||||||
tdep_init_done = 1; /* signal that we're initialized... */
|
tdep_init_done = 1; /* signal that we're initialized... */
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
lock_release (&aarch64_lock, saved_mask);
|
lock_release (&aarch64_lock, saved_mask);
|
||||||
|
|
|
@ -74,7 +74,7 @@ put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
|
get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
*dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
|
*dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -82,7 +82,7 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
|
access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
if (write)
|
if (write)
|
||||||
{
|
{
|
||||||
|
@ -99,7 +99,7 @@ access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
|
access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
unw_word_t *addr;
|
unw_word_t *addr;
|
||||||
ucontext_t *uc = arg;
|
ucontext_t *uc = arg;
|
||||||
|
@ -129,7 +129,7 @@ access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
|
access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
|
||||||
int write, void *arg)
|
int write, void *arg)
|
||||||
{
|
{
|
||||||
ucontext_t *uc = arg;
|
ucontext_t *uc = arg;
|
||||||
unw_fpreg_t *addr;
|
unw_fpreg_t *addr;
|
||||||
|
@ -143,14 +143,14 @@ access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
|
||||||
if (write)
|
if (write)
|
||||||
{
|
{
|
||||||
Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
|
Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
|
||||||
((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
|
((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
|
||||||
*(unw_fpreg_t *) addr = *val;
|
*(unw_fpreg_t *) addr = *val;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*val = *(unw_fpreg_t *) addr;
|
*val = *(unw_fpreg_t *) addr;
|
||||||
Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
|
Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
|
||||||
((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
|
((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -162,8 +162,8 @@ access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
|
get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
|
||||||
char *buf, size_t buf_len, unw_word_t *offp,
|
char *buf, size_t buf_len, unw_word_t *offp,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
|
return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
HIDDEN int
|
HIDDEN int
|
||||||
tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
|
tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
|
||||||
int write)
|
int write)
|
||||||
{
|
{
|
||||||
dwarf_loc_t loc = DWARF_NULL_LOC;
|
dwarf_loc_t loc = DWARF_NULL_LOC;
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
|
@ -106,7 +106,7 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
|
||||||
|
|
||||||
HIDDEN int
|
HIDDEN int
|
||||||
tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
|
tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
|
||||||
int write)
|
int write)
|
||||||
{
|
{
|
||||||
Debug (1, "bad register number %u\n", reg);
|
Debug (1, "bad register number %u\n", reg);
|
||||||
return -UNW_EBADREG;
|
return -UNW_EBADREG;
|
||||||
|
|
|
@ -39,7 +39,7 @@ aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
|
||||||
if (c->sigcontext_format == AARCH64_SCF_NONE)
|
if (c->sigcontext_format == AARCH64_SCF_NONE)
|
||||||
{
|
{
|
||||||
/* Since there are no signals involved here we restore the non scratch
|
/* Since there are no signals involved here we restore the non scratch
|
||||||
registers only. */
|
registers only. */
|
||||||
unsigned long regs[11];
|
unsigned long regs[11];
|
||||||
regs[0] = uc->uc_mcontext.regs[19];
|
regs[0] = uc->uc_mcontext.regs[19];
|
||||||
regs[1] = uc->uc_mcontext.regs[20];
|
regs[1] = uc->uc_mcontext.regs[20];
|
||||||
|
@ -143,15 +143,15 @@ establish_machine_state (struct cursor *c)
|
||||||
{
|
{
|
||||||
Debug (16, "copying %s %d\n", unw_regname (reg), reg);
|
Debug (16, "copying %s %d\n", unw_regname (reg), reg);
|
||||||
if (unw_is_fpreg (reg))
|
if (unw_is_fpreg (reg))
|
||||||
{
|
{
|
||||||
if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
|
if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
|
||||||
as->acc.access_fpreg (as, reg, &fpval, 1, arg);
|
as->acc.access_fpreg (as, reg, &fpval, 1, arg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (tdep_access_reg (c, reg, &val, 0) >= 0)
|
if (tdep_access_reg (c, reg, &val, 0) >= 0)
|
||||||
as->acc.access_reg (as, reg, &val, 1, arg);
|
as->acc.access_reg (as, reg, &val, 1, arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ unw_resume (unw_cursor_t *cursor)
|
||||||
if (!c->dwarf.ip)
|
if (!c->dwarf.ip)
|
||||||
{
|
{
|
||||||
/* This can happen easily when the frame-chain gets truncated
|
/* This can happen easily when the frame-chain gets truncated
|
||||||
due to bad or missing unwind-info. */
|
due to bad or missing unwind-info. */
|
||||||
Debug (1, "refusing to resume execution at address 0\n");
|
Debug (1, "refusing to resume execution at address 0\n");
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -173,5 +173,5 @@ unw_resume (unw_cursor_t *cursor)
|
||||||
establish_machine_state (c);
|
establish_machine_state (c);
|
||||||
|
|
||||||
return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
|
return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
|
||||||
c->dwarf.as_arg);
|
c->dwarf.as_arg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
|
Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
|
||||||
Copyright (C) 2014 CERN and Aalto University
|
Copyright (C) 2014 CERN and Aalto University
|
||||||
Contributed by Filip Nyback
|
Contributed by Filip Nyback
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -33,16 +33,16 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
|
||||||
unw_tdep_frame_t *f = &c->frame_info;
|
unw_tdep_frame_t *f = &c->frame_info;
|
||||||
|
|
||||||
Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld"
|
Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld"
|
||||||
" ra=0x%lx fp [where=%d val=%ld @0x%lx] lr [where=%d val=%ld @0x%lx] "
|
" ra=0x%lx fp [where=%d val=%ld @0x%lx] lr [where=%d val=%ld @0x%lx] "
|
||||||
"sp [where=%d val=%ld @0x%lx]\n",
|
"sp [where=%d val=%ld @0x%lx]\n",
|
||||||
d->ip, d->cfa, f->frame_type,
|
d->ip, d->cfa, f->frame_type,
|
||||||
rs->reg[DWARF_CFA_REG_COLUMN].where,
|
rs->reg[DWARF_CFA_REG_COLUMN].where,
|
||||||
rs->reg[DWARF_CFA_REG_COLUMN].val,
|
rs->reg[DWARF_CFA_REG_COLUMN].val,
|
||||||
rs->reg[DWARF_CFA_OFF_COLUMN].val,
|
rs->reg[DWARF_CFA_OFF_COLUMN].val,
|
||||||
DWARF_GET_LOC(d->loc[d->ret_addr_column]),
|
DWARF_GET_LOC(d->loc[d->ret_addr_column]),
|
||||||
rs->reg[FP].where, rs->reg[FP].val, DWARF_GET_LOC(d->loc[FP]),
|
rs->reg[FP].where, rs->reg[FP].val, DWARF_GET_LOC(d->loc[FP]),
|
||||||
rs->reg[LR].where, rs->reg[LR].val, DWARF_GET_LOC(d->loc[LR]),
|
rs->reg[LR].where, rs->reg[LR].val, DWARF_GET_LOC(d->loc[LR]),
|
||||||
rs->reg[SP].where, rs->reg[SP].val, DWARF_GET_LOC(d->loc[SP]));
|
rs->reg[SP].where, rs->reg[SP].val, DWARF_GET_LOC(d->loc[SP]));
|
||||||
|
|
||||||
/* A standard frame is defined as:
|
/* A standard frame is defined as:
|
||||||
- CFA is register-relative offset off FP or SP;
|
- CFA is register-relative offset off FP or SP;
|
||||||
|
@ -53,24 +53,24 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
|
||||||
if (f->frame_type == UNW_AARCH64_FRAME_OTHER
|
if (f->frame_type == UNW_AARCH64_FRAME_OTHER
|
||||||
&& (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG)
|
&& (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG)
|
||||||
&& (rs->reg[DWARF_CFA_REG_COLUMN].val == FP
|
&& (rs->reg[DWARF_CFA_REG_COLUMN].val == FP
|
||||||
|| rs->reg[DWARF_CFA_REG_COLUMN].val == SP)
|
|| rs->reg[DWARF_CFA_REG_COLUMN].val == SP)
|
||||||
&& labs(rs->reg[DWARF_CFA_OFF_COLUMN].val) < (1 << 29)
|
&& labs(rs->reg[DWARF_CFA_OFF_COLUMN].val) < (1 << 29)
|
||||||
&& d->ret_addr_column == LR
|
&& d->ret_addr_column == LR
|
||||||
&& (rs->reg[FP].where == DWARF_WHERE_UNDEF
|
&& (rs->reg[FP].where == DWARF_WHERE_UNDEF
|
||||||
|| rs->reg[FP].where == DWARF_WHERE_SAME
|
|| rs->reg[FP].where == DWARF_WHERE_SAME
|
||||||
|| (rs->reg[FP].where == DWARF_WHERE_CFAREL
|
|| (rs->reg[FP].where == DWARF_WHERE_CFAREL
|
||||||
&& labs(rs->reg[FP].val) < (1 << 29)
|
&& labs(rs->reg[FP].val) < (1 << 29)
|
||||||
&& rs->reg[FP].val+1 != 0))
|
&& rs->reg[FP].val+1 != 0))
|
||||||
&& (rs->reg[LR].where == DWARF_WHERE_UNDEF
|
&& (rs->reg[LR].where == DWARF_WHERE_UNDEF
|
||||||
|| rs->reg[LR].where == DWARF_WHERE_SAME
|
|| rs->reg[LR].where == DWARF_WHERE_SAME
|
||||||
|| (rs->reg[LR].where == DWARF_WHERE_CFAREL
|
|| (rs->reg[LR].where == DWARF_WHERE_CFAREL
|
||||||
&& labs(rs->reg[LR].val) < (1 << 29)
|
&& labs(rs->reg[LR].val) < (1 << 29)
|
||||||
&& rs->reg[LR].val+1 != 0))
|
&& rs->reg[LR].val+1 != 0))
|
||||||
&& (rs->reg[SP].where == DWARF_WHERE_UNDEF
|
&& (rs->reg[SP].where == DWARF_WHERE_UNDEF
|
||||||
|| rs->reg[SP].where == DWARF_WHERE_SAME
|
|| rs->reg[SP].where == DWARF_WHERE_SAME
|
||||||
|| (rs->reg[SP].where == DWARF_WHERE_CFAREL
|
|| (rs->reg[SP].where == DWARF_WHERE_CFAREL
|
||||||
&& labs(rs->reg[SP].val) < (1 << 29)
|
&& labs(rs->reg[SP].val) < (1 << 29)
|
||||||
&& rs->reg[SP].val+1 != 0)))
|
&& rs->reg[SP].val+1 != 0)))
|
||||||
{
|
{
|
||||||
/* Save information for a standard frame. */
|
/* Save information for a standard frame. */
|
||||||
f->frame_type = UNW_AARCH64_FRAME_STANDARD;
|
f->frame_type = UNW_AARCH64_FRAME_STANDARD;
|
||||||
|
|
|
@ -112,7 +112,7 @@ unw_step (unw_cursor_t *cursor)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx))\n",
|
Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx))\n",
|
||||||
c, c->dwarf.ip, c->dwarf.cfa);
|
c, c->dwarf.ip, c->dwarf.cfa);
|
||||||
|
|
||||||
/* Check if this is a signal frame. */
|
/* Check if this is a signal frame. */
|
||||||
if (unw_is_signal_frame (cursor))
|
if (unw_is_signal_frame (cursor))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
|
Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
|
||||||
Copyright (C) 2014 CERN and Aalto University
|
Copyright (C) 2014 CERN and Aalto University
|
||||||
Contributed by Filip Nyback
|
Contributed by Filip Nyback
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ typedef struct
|
||||||
size_t log_size;
|
size_t log_size;
|
||||||
size_t used;
|
size_t used;
|
||||||
size_t dtor_count; /* Counts how many times our destructor has already
|
size_t dtor_count; /* Counts how many times our destructor has already
|
||||||
been called. */
|
been called. */
|
||||||
} unw_trace_cache_t;
|
} unw_trace_cache_t;
|
||||||
|
|
||||||
static const unw_tdep_frame_t empty_frame = { 0, UNW_AARCH64_FRAME_OTHER, -1, -1, 0, -1, -1, -1 };
|
static const unw_tdep_frame_t empty_frame = { 0, UNW_AARCH64_FRAME_OTHER, -1, -1, 0, -1, -1, -1 };
|
||||||
|
@ -65,7 +65,7 @@ trace_cache_free (void *arg)
|
||||||
/* Not yet our turn to get destroyed. Re-install ourselves into the key. */
|
/* Not yet our turn to get destroyed. Re-install ourselves into the key. */
|
||||||
pthread_setspecific(trace_cache_key, cache);
|
pthread_setspecific(trace_cache_key, cache);
|
||||||
Debug(5, "delayed freeing cache %p (%zx to go)\n", cache,
|
Debug(5, "delayed freeing cache %p (%zx to go)\n", cache,
|
||||||
PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count);
|
PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tls_cache_destroyed = 1;
|
tls_cache_destroyed = 1;
|
||||||
|
@ -111,7 +111,7 @@ trace_cache_create (void)
|
||||||
/* The current thread is in the process of exiting. Don't recreate
|
/* The current thread is in the process of exiting. Don't recreate
|
||||||
cache, as we wouldn't have another chance to free it. */
|
cache, as we wouldn't have another chance to free it. */
|
||||||
Debug(5, "refusing to reallocate cache: "
|
Debug(5, "refusing to reallocate cache: "
|
||||||
"thread-locals are being deallocated\n");
|
"thread-locals are being deallocated\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,11 +214,11 @@ trace_cache_get (void)
|
||||||
highly unusual unwind info which uses these creatively. */
|
highly unusual unwind info which uses these creatively. */
|
||||||
static unw_tdep_frame_t *
|
static unw_tdep_frame_t *
|
||||||
trace_init_addr (unw_tdep_frame_t *f,
|
trace_init_addr (unw_tdep_frame_t *f,
|
||||||
unw_cursor_t *cursor,
|
unw_cursor_t *cursor,
|
||||||
unw_word_t cfa,
|
unw_word_t cfa,
|
||||||
unw_word_t pc,
|
unw_word_t pc,
|
||||||
unw_word_t fp,
|
unw_word_t fp,
|
||||||
unw_word_t sp)
|
unw_word_t sp)
|
||||||
{
|
{
|
||||||
struct cursor *c = (struct cursor *) cursor;
|
struct cursor *c = (struct cursor *) cursor;
|
||||||
struct dwarf_cursor *d = &c->dwarf;
|
struct dwarf_cursor *d = &c->dwarf;
|
||||||
|
@ -261,9 +261,9 @@ trace_init_addr (unw_tdep_frame_t *f,
|
||||||
f->last_frame = -1;
|
f->last_frame = -1;
|
||||||
|
|
||||||
Debug (3, "frame va %lx type %d last %d cfa %s+%d fp @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n",
|
Debug (3, "frame va %lx type %d last %d cfa %s+%d fp @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n",
|
||||||
f->virtual_address, f->frame_type, f->last_frame,
|
f->virtual_address, f->frame_type, f->last_frame,
|
||||||
f->cfa_reg_sp ? "sp" : "fp", f->cfa_reg_offset,
|
f->cfa_reg_sp ? "sp" : "fp", f->cfa_reg_offset,
|
||||||
f->fp_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset);
|
f->fp_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset);
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
@ -274,11 +274,11 @@ trace_init_addr (unw_tdep_frame_t *f,
|
||||||
frame cache slot which describes RIP. */
|
frame cache slot which describes RIP. */
|
||||||
static unw_tdep_frame_t *
|
static unw_tdep_frame_t *
|
||||||
trace_lookup (unw_cursor_t *cursor,
|
trace_lookup (unw_cursor_t *cursor,
|
||||||
unw_trace_cache_t *cache,
|
unw_trace_cache_t *cache,
|
||||||
unw_word_t cfa,
|
unw_word_t cfa,
|
||||||
unw_word_t pc,
|
unw_word_t pc,
|
||||||
unw_word_t fp,
|
unw_word_t fp,
|
||||||
unw_word_t sp)
|
unw_word_t sp)
|
||||||
{
|
{
|
||||||
/* First look up for previously cached information using cache as
|
/* First look up for previously cached information using cache as
|
||||||
linear probing hash table with probe step of 1. Majority of
|
linear probing hash table with probe step of 1. Majority of
|
||||||
|
@ -441,7 +441,7 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
||||||
{
|
{
|
||||||
pc -= d->use_prev_instr;
|
pc -= d->use_prev_instr;
|
||||||
Debug (2, "depth %d cfa 0x%lx pc 0x%lx sp 0x%lx fp 0x%lx\n",
|
Debug (2, "depth %d cfa 0x%lx pc 0x%lx sp 0x%lx fp 0x%lx\n",
|
||||||
depth, cfa, pc, sp, fp);
|
depth, cfa, pc, sp, fp);
|
||||||
|
|
||||||
/* See if we have this address cached. If not, evaluate enough of
|
/* See if we have this address cached. If not, evaluate enough of
|
||||||
the dwarf unwind information to fill the cache line data, or to
|
the dwarf unwind information to fill the cache line data, or to
|
||||||
|
@ -483,7 +483,7 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
||||||
/* Advance standard traceable frame. */
|
/* Advance standard traceable frame. */
|
||||||
cfa = (f->cfa_reg_sp ? sp : fp) + f->cfa_reg_offset;
|
cfa = (f->cfa_reg_sp ? sp : fp) + f->cfa_reg_offset;
|
||||||
if (likely(f->lr_cfa_offset != -1))
|
if (likely(f->lr_cfa_offset != -1))
|
||||||
ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->lr_cfa_offset, pc);
|
ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->lr_cfa_offset, pc);
|
||||||
else if (lr != 0)
|
else if (lr != 0)
|
||||||
{
|
{
|
||||||
/* Use the saved link register as the new pc. */
|
/* Use the saved link register as the new pc. */
|
||||||
|
@ -491,7 +491,7 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
||||||
lr = 0;
|
lr = 0;
|
||||||
}
|
}
|
||||||
if (likely(ret >= 0) && likely(f->fp_cfa_offset != -1))
|
if (likely(ret >= 0) && likely(f->fp_cfa_offset != -1))
|
||||||
ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->fp_cfa_offset, fp);
|
ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->fp_cfa_offset, fp);
|
||||||
|
|
||||||
/* Don't bother reading SP from DWARF, CFA becomes new SP. */
|
/* Don't bother reading SP from DWARF, CFA becomes new SP. */
|
||||||
sp = cfa;
|
sp = cfa;
|
||||||
|
@ -523,14 +523,14 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* We cannot trace through this frame, give up and tell the
|
/* We cannot trace through this frame, give up and tell the
|
||||||
caller we had to stop. Data collected so far may still be
|
caller we had to stop. Data collected so far may still be
|
||||||
useful to the caller, so let it know how far we got. */
|
useful to the caller, so let it know how far we got. */
|
||||||
ret = -UNW_ESTOPUNWIND;
|
ret = -UNW_ESTOPUNWIND;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug (4, "new cfa 0x%lx pc 0x%lx sp 0x%lx fp 0x%lx\n",
|
Debug (4, "new cfa 0x%lx pc 0x%lx sp 0x%lx fp 0x%lx\n",
|
||||||
cfa, pc, sp, fp);
|
cfa, pc, sp, fp);
|
||||||
|
|
||||||
/* If we failed or ended up somewhere bogus, stop. */
|
/* If we failed or ended up somewhere bogus, stop. */
|
||||||
if (unlikely(ret < 0 || pc < 0x4000))
|
if (unlikely(ret < 0 || pc < 0x4000))
|
||||||
|
|
|
@ -4,46 +4,46 @@
|
||||||
|
|
||||||
/* Offsets for AArch64 Linux "ucontext_t": */
|
/* Offsets for AArch64 Linux "ucontext_t": */
|
||||||
|
|
||||||
#define LINUX_UC_FLAGS_OFF 0x0
|
#define LINUX_UC_FLAGS_OFF 0x0
|
||||||
#define LINUX_UC_LINK_OFF 0x8
|
#define LINUX_UC_LINK_OFF 0x8
|
||||||
#define LINUX_UC_STACK_OFF 0x10
|
#define LINUX_UC_STACK_OFF 0x10
|
||||||
#define LINUX_UC_SIGMASK_OFF 0x28
|
#define LINUX_UC_SIGMASK_OFF 0x28
|
||||||
#define LINUX_UC_MCONTEXT_OFF 0xb0
|
#define LINUX_UC_MCONTEXT_OFF 0xb0
|
||||||
|
|
||||||
/* Offsets for AArch64 Linux "struct sigcontext": */
|
/* Offsets for AArch64 Linux "struct sigcontext": */
|
||||||
|
|
||||||
#define LINUX_SC_FAULTADDRESS_OFF 0x00
|
#define LINUX_SC_FAULTADDRESS_OFF 0x00
|
||||||
#define LINUX_SC_X0_OFF 0x008
|
#define LINUX_SC_X0_OFF 0x008
|
||||||
#define LINUX_SC_X1_OFF 0x010
|
#define LINUX_SC_X1_OFF 0x010
|
||||||
#define LINUX_SC_X2_OFF 0x018
|
#define LINUX_SC_X2_OFF 0x018
|
||||||
#define LINUX_SC_X3_OFF 0x020
|
#define LINUX_SC_X3_OFF 0x020
|
||||||
#define LINUX_SC_X4_OFF 0x028
|
#define LINUX_SC_X4_OFF 0x028
|
||||||
#define LINUX_SC_X5_OFF 0x030
|
#define LINUX_SC_X5_OFF 0x030
|
||||||
#define LINUX_SC_X6_OFF 0x038
|
#define LINUX_SC_X6_OFF 0x038
|
||||||
#define LINUX_SC_X7_OFF 0x040
|
#define LINUX_SC_X7_OFF 0x040
|
||||||
#define LINUX_SC_X8_OFF 0x048
|
#define LINUX_SC_X8_OFF 0x048
|
||||||
#define LINUX_SC_X9_OFF 0x050
|
#define LINUX_SC_X9_OFF 0x050
|
||||||
#define LINUX_SC_X10_OFF 0x058
|
#define LINUX_SC_X10_OFF 0x058
|
||||||
#define LINUX_SC_X11_OFF 0x060
|
#define LINUX_SC_X11_OFF 0x060
|
||||||
#define LINUX_SC_X12_OFF 0x068
|
#define LINUX_SC_X12_OFF 0x068
|
||||||
#define LINUX_SC_X13_OFF 0x070
|
#define LINUX_SC_X13_OFF 0x070
|
||||||
#define LINUX_SC_X14_OFF 0x078
|
#define LINUX_SC_X14_OFF 0x078
|
||||||
#define LINUX_SC_X15_OFF 0x080
|
#define LINUX_SC_X15_OFF 0x080
|
||||||
#define LINUX_SC_X16_OFF 0x088
|
#define LINUX_SC_X16_OFF 0x088
|
||||||
#define LINUX_SC_X17_OFF 0x090
|
#define LINUX_SC_X17_OFF 0x090
|
||||||
#define LINUX_SC_X18_OFF 0x098
|
#define LINUX_SC_X18_OFF 0x098
|
||||||
#define LINUX_SC_X19_OFF 0x0a0
|
#define LINUX_SC_X19_OFF 0x0a0
|
||||||
#define LINUX_SC_X20_OFF 0x0a8
|
#define LINUX_SC_X20_OFF 0x0a8
|
||||||
#define LINUX_SC_X21_OFF 0x0b0
|
#define LINUX_SC_X21_OFF 0x0b0
|
||||||
#define LINUX_SC_X22_OFF 0x0b8
|
#define LINUX_SC_X22_OFF 0x0b8
|
||||||
#define LINUX_SC_X23_OFF 0x0c0
|
#define LINUX_SC_X23_OFF 0x0c0
|
||||||
#define LINUX_SC_X24_OFF 0x0c8
|
#define LINUX_SC_X24_OFF 0x0c8
|
||||||
#define LINUX_SC_X25_OFF 0x0d0
|
#define LINUX_SC_X25_OFF 0x0d0
|
||||||
#define LINUX_SC_X26_OFF 0x0d8
|
#define LINUX_SC_X26_OFF 0x0d8
|
||||||
#define LINUX_SC_X27_OFF 0x0e0
|
#define LINUX_SC_X27_OFF 0x0e0
|
||||||
#define LINUX_SC_X28_OFF 0x0e8
|
#define LINUX_SC_X28_OFF 0x0e8
|
||||||
#define LINUX_SC_X29_OFF 0x0f0
|
#define LINUX_SC_X29_OFF 0x0f0
|
||||||
#define LINUX_SC_X30_OFF 0x0f8
|
#define LINUX_SC_X30_OFF 0x0f8
|
||||||
#define LINUX_SC_SP_OFF 0x100
|
#define LINUX_SC_SP_OFF 0x100
|
||||||
#define LINUX_SC_PC_OFF 0x108
|
#define LINUX_SC_PC_OFF 0x108
|
||||||
#define LINUX_SC_PSTATE_OFF 0x110
|
#define LINUX_SC_PSTATE_OFF 0x110
|
||||||
|
|
|
@ -33,19 +33,19 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#include "libunwind_i.h"
|
#include "libunwind_i.h"
|
||||||
|
|
||||||
/* DWARF column numbers for AArch64: */
|
/* DWARF column numbers for AArch64: */
|
||||||
#define X29 29
|
#define X29 29
|
||||||
#define FP 29
|
#define FP 29
|
||||||
#define X30 30
|
#define X30 30
|
||||||
#define LR 30
|
#define LR 30
|
||||||
#define SP 31
|
#define SP 31
|
||||||
|
|
||||||
#define aarch64_lock UNW_OBJ(lock)
|
#define aarch64_lock UNW_OBJ(lock)
|
||||||
#define aarch64_local_resume UNW_OBJ(local_resume)
|
#define aarch64_local_resume UNW_OBJ(local_resume)
|
||||||
#define aarch64_local_addr_space_init UNW_OBJ(local_addr_space_init)
|
#define aarch64_local_addr_space_init UNW_OBJ(local_addr_space_init)
|
||||||
|
|
||||||
extern void aarch64_local_addr_space_init (void);
|
extern void aarch64_local_addr_space_init (void);
|
||||||
extern int aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
|
extern int aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
|
||||||
void *arg);
|
void *arg);
|
||||||
|
|
||||||
/* By-pass calls to access_mem() when known to be safe. */
|
/* By-pass calls to access_mem() when known to be safe. */
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
|
|
|
@ -30,14 +30,14 @@ http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
|
||||||
|
|
||||||
#include "libunwind_i.h"
|
#include "libunwind_i.h"
|
||||||
|
|
||||||
#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f)
|
#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f)
|
||||||
#define ARM_EXBUF_COUNT(x) ((x) & 0x0f)
|
#define ARM_EXBUF_COUNT(x) ((x) & 0x0f)
|
||||||
#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
|
#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
|
||||||
|
|
||||||
#define ARM_EXIDX_CANT_UNWIND 0x00000001
|
#define ARM_EXIDX_CANT_UNWIND 0x00000001
|
||||||
#define ARM_EXIDX_COMPACT 0x80000000
|
#define ARM_EXIDX_COMPACT 0x80000000
|
||||||
|
|
||||||
#define ARM_EXTBL_OP_FINISH 0xb0
|
#define ARM_EXTBL_OP_FINISH 0xb0
|
||||||
|
|
||||||
enum arm_exbuf_cmd_flags {
|
enum arm_exbuf_cmd_flags {
|
||||||
ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
|
ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
|
||||||
|
@ -61,7 +61,7 @@ prel31_read (uint32_t prel31)
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
prel31_to_addr (unw_addr_space_t as, void *arg, unw_word_t prel31,
|
prel31_to_addr (unw_addr_space_t as, void *arg, unw_word_t prel31,
|
||||||
unw_word_t *val)
|
unw_word_t *val)
|
||||||
{
|
{
|
||||||
unw_word_t offset;
|
unw_word_t offset;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c)
|
||||||
case ARM_EXIDX_CMD_FINISH:
|
case ARM_EXIDX_CMD_FINISH:
|
||||||
/* Set LR to PC if not set already. */
|
/* Set LR to PC if not set already. */
|
||||||
if (DWARF_IS_NULL_LOC (c->loc[UNW_ARM_R15]))
|
if (DWARF_IS_NULL_LOC (c->loc[UNW_ARM_R15]))
|
||||||
c->loc[UNW_ARM_R15] = c->loc[UNW_ARM_R14];
|
c->loc[UNW_ARM_R15] = c->loc[UNW_ARM_R14];
|
||||||
/* Set IP. */
|
/* Set IP. */
|
||||||
dwarf_get (c, c->loc[UNW_ARM_R15], &c->ip);
|
dwarf_get (c, c->loc[UNW_ARM_R15], &c->ip);
|
||||||
break;
|
break;
|
||||||
|
@ -102,15 +102,15 @@ arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c)
|
||||||
break;
|
break;
|
||||||
case ARM_EXIDX_CMD_REG_POP:
|
case ARM_EXIDX_CMD_REG_POP:
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++)
|
||||||
if (edata->data & (1 << i))
|
if (edata->data & (1 << i))
|
||||||
{
|
{
|
||||||
Debug (2, "pop {r%d}\n", i);
|
Debug (2, "pop {r%d}\n", i);
|
||||||
c->loc[UNW_ARM_R0 + i] = DWARF_LOC (c->cfa, 0);
|
c->loc[UNW_ARM_R0 + i] = DWARF_LOC (c->cfa, 0);
|
||||||
c->cfa += 4;
|
c->cfa += 4;
|
||||||
}
|
}
|
||||||
/* Set cfa in case the SP got popped. */
|
/* Set cfa in case the SP got popped. */
|
||||||
if (edata->data & (1 << 13))
|
if (edata->data & (1 << 13))
|
||||||
dwarf_get (c, c->loc[UNW_ARM_R13], &c->cfa);
|
dwarf_get (c, c->loc[UNW_ARM_R13], &c->cfa);
|
||||||
break;
|
break;
|
||||||
case ARM_EXIDX_CMD_REG_TO_SP:
|
case ARM_EXIDX_CMD_REG_TO_SP:
|
||||||
assert (edata->data < 16);
|
assert (edata->data < 16);
|
||||||
|
@ -121,20 +121,20 @@ arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c)
|
||||||
case ARM_EXIDX_CMD_VFP_POP:
|
case ARM_EXIDX_CMD_VFP_POP:
|
||||||
/* Skip VFP registers, but be sure to adjust stack */
|
/* Skip VFP registers, but be sure to adjust stack */
|
||||||
for (i = ARM_EXBUF_START (edata->data); i <= ARM_EXBUF_END (edata->data);
|
for (i = ARM_EXBUF_START (edata->data); i <= ARM_EXBUF_END (edata->data);
|
||||||
i++)
|
i++)
|
||||||
c->cfa += 8;
|
c->cfa += 8;
|
||||||
if (!(edata->data & ARM_EXIDX_VFP_DOUBLE))
|
if (!(edata->data & ARM_EXIDX_VFP_DOUBLE))
|
||||||
c->cfa += 4;
|
c->cfa += 4;
|
||||||
break;
|
break;
|
||||||
case ARM_EXIDX_CMD_WREG_POP:
|
case ARM_EXIDX_CMD_WREG_POP:
|
||||||
for (i = ARM_EXBUF_START (edata->data); i <= ARM_EXBUF_END (edata->data);
|
for (i = ARM_EXBUF_START (edata->data); i <= ARM_EXBUF_END (edata->data);
|
||||||
i++)
|
i++)
|
||||||
c->cfa += 8;
|
c->cfa += 8;
|
||||||
break;
|
break;
|
||||||
case ARM_EXIDX_CMD_WCGR_POP:
|
case ARM_EXIDX_CMD_WCGR_POP:
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
if (edata->data & (1 << i))
|
if (edata->data & (1 << i))
|
||||||
c->cfa += 4;
|
c->cfa += 4;
|
||||||
break;
|
break;
|
||||||
case ARM_EXIDX_CMD_REFUSED:
|
case ARM_EXIDX_CMD_REFUSED:
|
||||||
case ARM_EXIDX_CMD_RESERVED:
|
case ARM_EXIDX_CMD_RESERVED:
|
||||||
|
@ -163,119 +163,119 @@ arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c)
|
||||||
{
|
{
|
||||||
uint8_t op = READ_OP ();
|
uint8_t op = READ_OP ();
|
||||||
if ((op & 0xc0) == 0x00)
|
if ((op & 0xc0) == 0x00)
|
||||||
{
|
{
|
||||||
edata.cmd = ARM_EXIDX_CMD_DATA_POP;
|
edata.cmd = ARM_EXIDX_CMD_DATA_POP;
|
||||||
edata.data = (((int)op & 0x3f) << 2) + 4;
|
edata.data = (((int)op & 0x3f) << 2) + 4;
|
||||||
}
|
}
|
||||||
else if ((op & 0xc0) == 0x40)
|
else if ((op & 0xc0) == 0x40)
|
||||||
{
|
{
|
||||||
edata.cmd = ARM_EXIDX_CMD_DATA_PUSH;
|
edata.cmd = ARM_EXIDX_CMD_DATA_PUSH;
|
||||||
edata.data = (((int)op & 0x3f) << 2) + 4;
|
edata.data = (((int)op & 0x3f) << 2) + 4;
|
||||||
}
|
}
|
||||||
else if ((op & 0xf0) == 0x80)
|
else if ((op & 0xf0) == 0x80)
|
||||||
{
|
{
|
||||||
uint8_t op2 = READ_OP ();
|
uint8_t op2 = READ_OP ();
|
||||||
if (op == 0x80 && op2 == 0x00)
|
if (op == 0x80 && op2 == 0x00)
|
||||||
edata.cmd = ARM_EXIDX_CMD_REFUSED;
|
edata.cmd = ARM_EXIDX_CMD_REFUSED;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
edata.cmd = ARM_EXIDX_CMD_REG_POP;
|
edata.cmd = ARM_EXIDX_CMD_REG_POP;
|
||||||
edata.data = ((op & 0xf) << 8) | op2;
|
edata.data = ((op & 0xf) << 8) | op2;
|
||||||
edata.data = edata.data << 4;
|
edata.data = edata.data << 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((op & 0xf0) == 0x90)
|
else if ((op & 0xf0) == 0x90)
|
||||||
{
|
{
|
||||||
if (op == 0x9d || op == 0x9f)
|
if (op == 0x9d || op == 0x9f)
|
||||||
edata.cmd = ARM_EXIDX_CMD_RESERVED;
|
edata.cmd = ARM_EXIDX_CMD_RESERVED;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
edata.cmd = ARM_EXIDX_CMD_REG_TO_SP;
|
edata.cmd = ARM_EXIDX_CMD_REG_TO_SP;
|
||||||
edata.data = op & 0x0f;
|
edata.data = op & 0x0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((op & 0xf0) == 0xa0)
|
else if ((op & 0xf0) == 0xa0)
|
||||||
{
|
{
|
||||||
unsigned end = (op & 0x07);
|
unsigned end = (op & 0x07);
|
||||||
edata.data = (1 << (end + 1)) - 1;
|
edata.data = (1 << (end + 1)) - 1;
|
||||||
edata.data = edata.data << 4;
|
edata.data = edata.data << 4;
|
||||||
if (op & 0x08)
|
if (op & 0x08)
|
||||||
edata.data |= 1 << 14;
|
edata.data |= 1 << 14;
|
||||||
edata.cmd = ARM_EXIDX_CMD_REG_POP;
|
edata.cmd = ARM_EXIDX_CMD_REG_POP;
|
||||||
}
|
}
|
||||||
else if (op == ARM_EXTBL_OP_FINISH)
|
else if (op == ARM_EXTBL_OP_FINISH)
|
||||||
{
|
{
|
||||||
edata.cmd = ARM_EXIDX_CMD_FINISH;
|
edata.cmd = ARM_EXIDX_CMD_FINISH;
|
||||||
buf = end;
|
buf = end;
|
||||||
}
|
}
|
||||||
else if (op == 0xb1)
|
else if (op == 0xb1)
|
||||||
{
|
{
|
||||||
uint8_t op2 = READ_OP ();
|
uint8_t op2 = READ_OP ();
|
||||||
if (op2 == 0 || (op2 & 0xf0))
|
if (op2 == 0 || (op2 & 0xf0))
|
||||||
edata.cmd = ARM_EXIDX_CMD_RESERVED;
|
edata.cmd = ARM_EXIDX_CMD_RESERVED;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
edata.cmd = ARM_EXIDX_CMD_REG_POP;
|
edata.cmd = ARM_EXIDX_CMD_REG_POP;
|
||||||
edata.data = op2 & 0x0f;
|
edata.data = op2 & 0x0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (op == 0xb2)
|
else if (op == 0xb2)
|
||||||
{
|
{
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
uint8_t byte, shift = 0;
|
uint8_t byte, shift = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
byte = READ_OP ();
|
byte = READ_OP ();
|
||||||
offset |= (byte & 0x7f) << shift;
|
offset |= (byte & 0x7f) << shift;
|
||||||
shift += 7;
|
shift += 7;
|
||||||
}
|
}
|
||||||
while (byte & 0x80);
|
while (byte & 0x80);
|
||||||
edata.data = offset * 4 + 0x204;
|
edata.data = offset * 4 + 0x204;
|
||||||
edata.cmd = ARM_EXIDX_CMD_DATA_POP;
|
edata.cmd = ARM_EXIDX_CMD_DATA_POP;
|
||||||
}
|
}
|
||||||
else if (op == 0xb3 || op == 0xc8 || op == 0xc9)
|
else if (op == 0xb3 || op == 0xc8 || op == 0xc9)
|
||||||
{
|
{
|
||||||
edata.cmd = ARM_EXIDX_CMD_VFP_POP;
|
edata.cmd = ARM_EXIDX_CMD_VFP_POP;
|
||||||
edata.data = READ_OP ();
|
edata.data = READ_OP ();
|
||||||
if (op == 0xc8)
|
if (op == 0xc8)
|
||||||
edata.data |= ARM_EXIDX_VFP_SHIFT_16;
|
edata.data |= ARM_EXIDX_VFP_SHIFT_16;
|
||||||
if (op != 0xb3)
|
if (op != 0xb3)
|
||||||
edata.data |= ARM_EXIDX_VFP_DOUBLE;
|
edata.data |= ARM_EXIDX_VFP_DOUBLE;
|
||||||
}
|
}
|
||||||
else if ((op & 0xf8) == 0xb8 || (op & 0xf8) == 0xd0)
|
else if ((op & 0xf8) == 0xb8 || (op & 0xf8) == 0xd0)
|
||||||
{
|
{
|
||||||
edata.cmd = ARM_EXIDX_CMD_VFP_POP;
|
edata.cmd = ARM_EXIDX_CMD_VFP_POP;
|
||||||
edata.data = 0x80 | (op & 0x07);
|
edata.data = 0x80 | (op & 0x07);
|
||||||
if ((op & 0xf8) == 0xd0)
|
if ((op & 0xf8) == 0xd0)
|
||||||
edata.data |= ARM_EXIDX_VFP_DOUBLE;
|
edata.data |= ARM_EXIDX_VFP_DOUBLE;
|
||||||
}
|
}
|
||||||
else if (op >= 0xc0 && op <= 0xc5)
|
else if (op >= 0xc0 && op <= 0xc5)
|
||||||
{
|
{
|
||||||
edata.cmd = ARM_EXIDX_CMD_WREG_POP;
|
edata.cmd = ARM_EXIDX_CMD_WREG_POP;
|
||||||
edata.data = 0xa0 | (op & 0x07);
|
edata.data = 0xa0 | (op & 0x07);
|
||||||
}
|
}
|
||||||
else if (op == 0xc6)
|
else if (op == 0xc6)
|
||||||
{
|
{
|
||||||
edata.cmd = ARM_EXIDX_CMD_WREG_POP;
|
edata.cmd = ARM_EXIDX_CMD_WREG_POP;
|
||||||
edata.data = READ_OP ();
|
edata.data = READ_OP ();
|
||||||
}
|
}
|
||||||
else if (op == 0xc7)
|
else if (op == 0xc7)
|
||||||
{
|
{
|
||||||
uint8_t op2 = READ_OP ();
|
uint8_t op2 = READ_OP ();
|
||||||
if (op2 == 0 || (op2 & 0xf0))
|
if (op2 == 0 || (op2 & 0xf0))
|
||||||
edata.cmd = ARM_EXIDX_CMD_RESERVED;
|
edata.cmd = ARM_EXIDX_CMD_RESERVED;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
edata.cmd = ARM_EXIDX_CMD_WCGR_POP;
|
edata.cmd = ARM_EXIDX_CMD_WCGR_POP;
|
||||||
edata.data = op2 & 0x0f;
|
edata.data = op2 & 0x0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
edata.cmd = ARM_EXIDX_CMD_RESERVED;
|
edata.cmd = ARM_EXIDX_CMD_RESERVED;
|
||||||
|
|
||||||
ret = arm_exidx_apply_cmd (&edata, c);
|
ret = arm_exidx_apply_cmd (&edata, c);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -299,7 +299,7 @@ arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf)
|
||||||
* if set to 0x1: the function cannot be unwound (EXIDX_CANTUNWIND)
|
* if set to 0x1: the function cannot be unwound (EXIDX_CANTUNWIND)
|
||||||
* if bit 31 is one: this is a table entry itself (ARM_EXIDX_COMPACT)
|
* if bit 31 is one: this is a table entry itself (ARM_EXIDX_COMPACT)
|
||||||
* if bit 31 is zero: this is a prel31 offset of the start of the
|
* if bit 31 is zero: this is a prel31 offset of the start of the
|
||||||
table entry for this function */
|
table entry for this function */
|
||||||
if (prel31_to_addr(c->as, c->as_arg, entry, &addr) < 0)
|
if (prel31_to_addr(c->as, c->as_arg, entry, &addr) < 0)
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
|
|
||||||
|
@ -314,7 +314,7 @@ arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf)
|
||||||
else if (data & ARM_EXIDX_COMPACT)
|
else if (data & ARM_EXIDX_COMPACT)
|
||||||
{
|
{
|
||||||
Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr,
|
Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr,
|
||||||
(data >> 24) & 0x7f, data);
|
(data >> 24) & 0x7f, data);
|
||||||
buf[nbuf++] = data >> 16;
|
buf[nbuf++] = data >> 16;
|
||||||
buf[nbuf++] = data >> 8;
|
buf[nbuf++] = data >> 8;
|
||||||
buf[nbuf++] = data;
|
buf[nbuf++] = data;
|
||||||
|
@ -328,51 +328,51 @@ arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf)
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
|
|
||||||
if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0, c->as_arg) < 0)
|
if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0, c->as_arg) < 0)
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
|
|
||||||
if (data & ARM_EXIDX_COMPACT)
|
if (data & ARM_EXIDX_COMPACT)
|
||||||
{
|
{
|
||||||
int pers = (data >> 24) & 0x0f;
|
int pers = (data >> 24) & 0x0f;
|
||||||
Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr, pers, data);
|
Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr, pers, data);
|
||||||
if (pers == 1 || pers == 2)
|
if (pers == 1 || pers == 2)
|
||||||
{
|
{
|
||||||
n_table_words = (data >> 16) & 0xff;
|
n_table_words = (data >> 16) & 0xff;
|
||||||
extbl_data += 4;
|
extbl_data += 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
buf[nbuf++] = data >> 16;
|
buf[nbuf++] = data >> 16;
|
||||||
buf[nbuf++] = data >> 8;
|
buf[nbuf++] = data >> 8;
|
||||||
buf[nbuf++] = data;
|
buf[nbuf++] = data;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unw_word_t pers;
|
unw_word_t pers;
|
||||||
if (prel31_to_addr (c->as, c->as_arg, extbl_data, &pers) < 0)
|
if (prel31_to_addr (c->as, c->as_arg, extbl_data, &pers) < 0)
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
Debug (2, "%p Personality routine: %8p\n", (void *)addr,
|
Debug (2, "%p Personality routine: %8p\n", (void *)addr,
|
||||||
(void *)pers);
|
(void *)pers);
|
||||||
if ((*c->as->acc.access_mem)(c->as, extbl_data + 4, &data, 0,
|
if ((*c->as->acc.access_mem)(c->as, extbl_data + 4, &data, 0,
|
||||||
c->as_arg) < 0)
|
c->as_arg) < 0)
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
n_table_words = data >> 24;
|
n_table_words = data >> 24;
|
||||||
buf[nbuf++] = data >> 16;
|
buf[nbuf++] = data >> 16;
|
||||||
buf[nbuf++] = data >> 8;
|
buf[nbuf++] = data >> 8;
|
||||||
buf[nbuf++] = data;
|
buf[nbuf++] = data;
|
||||||
extbl_data += 8;
|
extbl_data += 8;
|
||||||
}
|
}
|
||||||
assert (n_table_words <= 5);
|
assert (n_table_words <= 5);
|
||||||
unsigned j;
|
unsigned j;
|
||||||
for (j = 0; j < n_table_words; j++)
|
for (j = 0; j < n_table_words; j++)
|
||||||
{
|
{
|
||||||
if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0,
|
if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0,
|
||||||
c->as_arg) < 0)
|
c->as_arg) < 0)
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
extbl_data += 4;
|
extbl_data += 4;
|
||||||
buf[nbuf++] = data >> 24;
|
buf[nbuf++] = data >> 24;
|
||||||
buf[nbuf++] = data >> 16;
|
buf[nbuf++] = data >> 16;
|
||||||
buf[nbuf++] = data >> 8;
|
buf[nbuf++] = data >> 8;
|
||||||
buf[nbuf++] = data >> 0;
|
buf[nbuf++] = data >> 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbuf > 0 && buf[nbuf - 1] != ARM_EXTBL_OP_FINISH)
|
if (nbuf > 0 && buf[nbuf - 1] != ARM_EXTBL_OP_FINISH)
|
||||||
|
@ -383,71 +383,71 @@ arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf)
|
||||||
|
|
||||||
PROTECTED int
|
PROTECTED int
|
||||||
tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||||
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg)
|
int need_unwind_info, void *arg)
|
||||||
{
|
{
|
||||||
if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)
|
if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)
|
||||||
&& di->format == UNW_INFO_FORMAT_ARM_EXIDX)
|
&& di->format == UNW_INFO_FORMAT_ARM_EXIDX)
|
||||||
{
|
{
|
||||||
/* The .ARM.exidx section contains a sorted list of key-value pairs -
|
/* The .ARM.exidx section contains a sorted list of key-value pairs -
|
||||||
the unwind entries. The 'key' is a prel31 offset to the start of a
|
the unwind entries. The 'key' is a prel31 offset to the start of a
|
||||||
function. We binary search this section in order to find the
|
function. We binary search this section in order to find the
|
||||||
appropriate unwind entry. */
|
appropriate unwind entry. */
|
||||||
unw_word_t first = di->u.rti.table_data;
|
unw_word_t first = di->u.rti.table_data;
|
||||||
unw_word_t last = di->u.rti.table_data + di->u.rti.table_len - 8;
|
unw_word_t last = di->u.rti.table_data + di->u.rti.table_len - 8;
|
||||||
unw_word_t entry, val;
|
unw_word_t entry, val;
|
||||||
|
|
||||||
if (prel31_to_addr (as, arg, first, &val) < 0 || ip < val)
|
if (prel31_to_addr (as, arg, first, &val) < 0 || ip < val)
|
||||||
return -UNW_ENOINFO;
|
return -UNW_ENOINFO;
|
||||||
|
|
||||||
if (prel31_to_addr (as, arg, last, &val) < 0)
|
if (prel31_to_addr (as, arg, last, &val) < 0)
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
|
|
||||||
if (ip >= val)
|
if (ip >= val)
|
||||||
{
|
{
|
||||||
entry = last;
|
entry = last;
|
||||||
|
|
||||||
if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0)
|
if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0)
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
|
|
||||||
pi->end_ip = di->end_ip -1;
|
pi->end_ip = di->end_ip -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (first < last - 8)
|
while (first < last - 8)
|
||||||
{
|
{
|
||||||
entry = first + (((last - first) / 8 + 1) >> 1) * 8;
|
entry = first + (((last - first) / 8 + 1) >> 1) * 8;
|
||||||
|
|
||||||
if (prel31_to_addr (as, arg, entry, &val) < 0)
|
if (prel31_to_addr (as, arg, entry, &val) < 0)
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
|
|
||||||
if (ip < val)
|
if (ip < val)
|
||||||
last = entry;
|
last = entry;
|
||||||
else
|
else
|
||||||
first = entry;
|
first = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = first;
|
entry = first;
|
||||||
|
|
||||||
if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0)
|
if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0)
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
|
|
||||||
if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0)
|
if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0)
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
|
|
||||||
pi->end_ip--;
|
pi->end_ip--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_unwind_info)
|
if (need_unwind_info)
|
||||||
{
|
{
|
||||||
pi->unwind_info_size = 8;
|
pi->unwind_info_size = 8;
|
||||||
pi->unwind_info = (void *) entry;
|
pi->unwind_info = (void *) entry;
|
||||||
pi->format = UNW_INFO_FORMAT_ARM_EXIDX;
|
pi->format = UNW_INFO_FORMAT_ARM_EXIDX;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)
|
else if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)
|
||||||
&& di->format != UNW_INFO_FORMAT_ARM_EXIDX)
|
&& di->format != UNW_INFO_FORMAT_ARM_EXIDX)
|
||||||
return dwarf_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
|
return dwarf_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
|
||||||
|
|
||||||
return -UNW_ENOINFO;
|
return -UNW_ENOINFO;
|
||||||
|
@ -469,20 +469,20 @@ arm_phdr_cb (struct dl_phdr_info *info, size_t size, void *data)
|
||||||
for (n = info->dlpi_phnum; --n >= 0; phdr++)
|
for (n = info->dlpi_phnum; --n >= 0; phdr++)
|
||||||
{
|
{
|
||||||
switch (phdr->p_type)
|
switch (phdr->p_type)
|
||||||
{
|
{
|
||||||
case PT_LOAD:
|
case PT_LOAD:
|
||||||
if (cb_data->ip >= phdr->p_vaddr + info->dlpi_addr &&
|
if (cb_data->ip >= phdr->p_vaddr + info->dlpi_addr &&
|
||||||
cb_data->ip < phdr->p_vaddr + info->dlpi_addr + phdr->p_memsz)
|
cb_data->ip < phdr->p_vaddr + info->dlpi_addr + phdr->p_memsz)
|
||||||
p_text = phdr;
|
p_text = phdr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_ARM_EXIDX:
|
case PT_ARM_EXIDX:
|
||||||
p_arm_exidx = phdr;
|
p_arm_exidx = phdr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_text && p_arm_exidx)
|
if (p_text && p_arm_exidx)
|
||||||
|
@ -501,7 +501,7 @@ arm_phdr_cb (struct dl_phdr_info *info, size_t size, void *data)
|
||||||
|
|
||||||
HIDDEN int
|
HIDDEN int
|
||||||
arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||||
unw_proc_info_t *pi, int need_unwind_info, void *arg)
|
unw_proc_info_t *pi, int need_unwind_info, void *arg)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
intrmask_t saved_mask;
|
intrmask_t saved_mask;
|
||||||
|
@ -524,14 +524,14 @@ arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||||
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
|
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
|
||||||
|
|
||||||
if (cb_data.single_fde)
|
if (cb_data.single_fde)
|
||||||
/* already got the result in *pi */
|
/* already got the result in *pi */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (cb_data.di_debug.format != -1)
|
if (cb_data.di_debug.format != -1)
|
||||||
ret = tdep_search_unwind_table (as, ip, &cb_data.di_debug, pi,
|
ret = tdep_search_unwind_table (as, ip, &cb_data.di_debug, pi,
|
||||||
need_unwind_info, arg);
|
need_unwind_info, arg);
|
||||||
else
|
else
|
||||||
ret = -UNW_ENOINFO;
|
ret = -UNW_ENOINFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX))
|
if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX))
|
||||||
|
@ -548,10 +548,10 @@ arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||||
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
|
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
|
||||||
|
|
||||||
if (cb_data.di.format != -1)
|
if (cb_data.di.format != -1)
|
||||||
ret = tdep_search_unwind_table (as, ip, &cb_data.di, pi,
|
ret = tdep_search_unwind_table (as, ip, &cb_data.di, pi,
|
||||||
need_unwind_info, arg);
|
need_unwind_info, arg);
|
||||||
else
|
else
|
||||||
ret = -UNW_ENOINFO;
|
ret = -UNW_ENOINFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
|
@ -30,7 +30,7 @@ unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc)
|
||||||
struct cursor *c = (struct cursor *) cursor;
|
struct cursor *c = (struct cursor *) cursor;
|
||||||
dwarf_loc_t loc;
|
dwarf_loc_t loc;
|
||||||
|
|
||||||
loc = DWARF_NULL_LOC; /* default to "not saved" */
|
loc = DWARF_NULL_LOC; /* default to "not saved" */
|
||||||
|
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,7 +58,7 @@ tdep_init (void)
|
||||||
#ifndef UNW_REMOTE_ONLY
|
#ifndef UNW_REMOTE_ONLY
|
||||||
arm_local_addr_space_init ();
|
arm_local_addr_space_init ();
|
||||||
#endif
|
#endif
|
||||||
tdep_init_done = 1; /* signal that we're initialized... */
|
tdep_init_done = 1; /* signal that we're initialized... */
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
lock_release (&arm_lock, saved_mask);
|
lock_release (&arm_lock, saved_mask);
|
||||||
|
|
|
@ -66,7 +66,7 @@ HIDDEN unw_dyn_info_list_t _U_dyn_info_list;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
|
get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
*dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
|
*dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -74,7 +74,7 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
|
access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
if (write)
|
if (write)
|
||||||
{
|
{
|
||||||
|
@ -91,7 +91,7 @@ access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
|
access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
unw_word_t *addr;
|
unw_word_t *addr;
|
||||||
unw_tdep_context_t *uc = arg;
|
unw_tdep_context_t *uc = arg;
|
||||||
|
@ -122,7 +122,7 @@ Debug (16, "reg = %s\n", unw_regname (reg));
|
||||||
|
|
||||||
static int
|
static int
|
||||||
access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
|
access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
|
||||||
int write, void *arg)
|
int write, void *arg)
|
||||||
{
|
{
|
||||||
unw_tdep_context_t *uc = arg;
|
unw_tdep_context_t *uc = arg;
|
||||||
unw_fpreg_t *addr;
|
unw_fpreg_t *addr;
|
||||||
|
@ -136,14 +136,14 @@ access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
|
||||||
if (write)
|
if (write)
|
||||||
{
|
{
|
||||||
Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
|
Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
|
||||||
((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
|
((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
|
||||||
*(unw_fpreg_t *) addr = *val;
|
*(unw_fpreg_t *) addr = *val;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*val = *(unw_fpreg_t *) addr;
|
*val = *(unw_fpreg_t *) addr;
|
||||||
Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
|
Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
|
||||||
((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
|
((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -155,8 +155,8 @@ access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
|
get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
|
||||||
char *buf, size_t buf_len, unw_word_t *offp,
|
char *buf, size_t buf_len, unw_word_t *offp,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
|
return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
HIDDEN int
|
HIDDEN int
|
||||||
tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
|
tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
|
||||||
int write)
|
int write)
|
||||||
{
|
{
|
||||||
dwarf_loc_t loc = DWARF_NULL_LOC;
|
dwarf_loc_t loc = DWARF_NULL_LOC;
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
|
||||||
|
|
||||||
HIDDEN int
|
HIDDEN int
|
||||||
tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
|
tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
|
||||||
int write)
|
int write)
|
||||||
{
|
{
|
||||||
Debug (1, "bad register number %u\n", reg);
|
Debug (1, "bad register number %u\n", reg);
|
||||||
return -UNW_EBADREG;
|
return -UNW_EBADREG;
|
||||||
|
|
|
@ -39,7 +39,7 @@ arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
|
||||||
if (c->sigcontext_format == ARM_SCF_NONE)
|
if (c->sigcontext_format == ARM_SCF_NONE)
|
||||||
{
|
{
|
||||||
/* Since there are no signals involved here we restore the non scratch
|
/* Since there are no signals involved here we restore the non scratch
|
||||||
registers only. */
|
registers only. */
|
||||||
unsigned long regs[10];
|
unsigned long regs[10];
|
||||||
regs[0] = uc->regs[4];
|
regs[0] = uc->regs[4];
|
||||||
regs[1] = uc->regs[5];
|
regs[1] = uc->regs[5];
|
||||||
|
@ -53,21 +53,21 @@ arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
|
||||||
regs[9] = uc->regs[14]; /* LR */
|
regs[9] = uc->regs[14]; /* LR */
|
||||||
|
|
||||||
struct regs_overlay {
|
struct regs_overlay {
|
||||||
char x[sizeof(regs)];
|
char x[sizeof(regs)];
|
||||||
};
|
};
|
||||||
|
|
||||||
asm __volatile__ (
|
asm __volatile__ (
|
||||||
"ldmia %0, {r4-r12, lr}\n"
|
"ldmia %0, {r4-r12, lr}\n"
|
||||||
"mov sp, r12\n"
|
"mov sp, r12\n"
|
||||||
"bx lr\n"
|
"bx lr\n"
|
||||||
: : "r" (regs),
|
: : "r" (regs),
|
||||||
"m" (*(struct regs_overlay *)regs)
|
"m" (*(struct regs_overlay *)regs)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* In case a signal frame is involved, we're using its trampoline which
|
/* In case a signal frame is involved, we're using its trampoline which
|
||||||
calls sigreturn. */
|
calls sigreturn. */
|
||||||
struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
|
struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
|
||||||
sc->arm_r0 = uc->regs[0];
|
sc->arm_r0 = uc->regs[0];
|
||||||
sc->arm_r1 = uc->regs[1];
|
sc->arm_r1 = uc->regs[1];
|
||||||
|
@ -89,11 +89,11 @@ arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
|
||||||
sc->arm_cpsr &= 0xf9ff03ffUL;
|
sc->arm_cpsr &= 0xf9ff03ffUL;
|
||||||
|
|
||||||
/* Set the SP and the PC in order to continue execution at the modified
|
/* Set the SP and the PC in order to continue execution at the modified
|
||||||
trampoline which restores the signal mask and the registers. */
|
trampoline which restores the signal mask and the registers. */
|
||||||
asm __volatile__ (
|
asm __volatile__ (
|
||||||
"mov sp, %0\n"
|
"mov sp, %0\n"
|
||||||
"bx %1\n"
|
"bx %1\n"
|
||||||
: : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc)
|
: : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
unreachable();
|
unreachable();
|
||||||
|
@ -120,15 +120,15 @@ establish_machine_state (struct cursor *c)
|
||||||
{
|
{
|
||||||
Debug (16, "copying %s %d\n", unw_regname (reg), reg);
|
Debug (16, "copying %s %d\n", unw_regname (reg), reg);
|
||||||
if (unw_is_fpreg (reg))
|
if (unw_is_fpreg (reg))
|
||||||
{
|
{
|
||||||
if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
|
if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
|
||||||
as->acc.access_fpreg (as, reg, &fpval, 1, arg);
|
as->acc.access_fpreg (as, reg, &fpval, 1, arg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (tdep_access_reg (c, reg, &val, 0) >= 0)
|
if (tdep_access_reg (c, reg, &val, 0) >= 0)
|
||||||
as->acc.access_reg (as, reg, &val, 1, arg);
|
as->acc.access_reg (as, reg, &val, 1, arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ unw_resume (unw_cursor_t *cursor)
|
||||||
if (!c->dwarf.ip)
|
if (!c->dwarf.ip)
|
||||||
{
|
{
|
||||||
/* This can happen easily when the frame-chain gets truncated
|
/* This can happen easily when the frame-chain gets truncated
|
||||||
due to bad or missing unwind-info. */
|
due to bad or missing unwind-info. */
|
||||||
Debug (1, "refusing to resume execution at address 0\n");
|
Debug (1, "refusing to resume execution at address 0\n");
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -150,5 +150,5 @@ unw_resume (unw_cursor_t *cursor)
|
||||||
establish_machine_state (c);
|
establish_machine_state (c);
|
||||||
|
|
||||||
return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
|
return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
|
||||||
c->dwarf.as_arg);
|
c->dwarf.as_arg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
|
Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
|
||||||
Copyright (C) 2014 CERN and Aalto University
|
Copyright (C) 2014 CERN and Aalto University
|
||||||
Contributed by Filip Nyback
|
Contributed by Filip Nyback
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -33,16 +33,16 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
|
||||||
unw_tdep_frame_t *f = &c->frame_info;
|
unw_tdep_frame_t *f = &c->frame_info;
|
||||||
|
|
||||||
Debug (4, "ip=0x%x cfa=0x%x type %d cfa [where=%d val=%d] cfaoff=%d"
|
Debug (4, "ip=0x%x cfa=0x%x type %d cfa [where=%d val=%d] cfaoff=%d"
|
||||||
" ra=0x%x r7 [where=%d val=%d @0x%x] lr [where=%d val=%d @0x%x] "
|
" ra=0x%x r7 [where=%d val=%d @0x%x] lr [where=%d val=%d @0x%x] "
|
||||||
"sp [where=%d val=%d @0x%x]\n",
|
"sp [where=%d val=%d @0x%x]\n",
|
||||||
d->ip, d->cfa, f->frame_type,
|
d->ip, d->cfa, f->frame_type,
|
||||||
rs->reg[DWARF_CFA_REG_COLUMN].where,
|
rs->reg[DWARF_CFA_REG_COLUMN].where,
|
||||||
rs->reg[DWARF_CFA_REG_COLUMN].val,
|
rs->reg[DWARF_CFA_REG_COLUMN].val,
|
||||||
rs->reg[DWARF_CFA_OFF_COLUMN].val,
|
rs->reg[DWARF_CFA_OFF_COLUMN].val,
|
||||||
DWARF_GET_LOC(d->loc[d->ret_addr_column]),
|
DWARF_GET_LOC(d->loc[d->ret_addr_column]),
|
||||||
rs->reg[R7].where, rs->reg[R7].val, DWARF_GET_LOC(d->loc[R7]),
|
rs->reg[R7].where, rs->reg[R7].val, DWARF_GET_LOC(d->loc[R7]),
|
||||||
rs->reg[LR].where, rs->reg[LR].val, DWARF_GET_LOC(d->loc[LR]),
|
rs->reg[LR].where, rs->reg[LR].val, DWARF_GET_LOC(d->loc[LR]),
|
||||||
rs->reg[SP].where, rs->reg[SP].val, DWARF_GET_LOC(d->loc[SP]));
|
rs->reg[SP].where, rs->reg[SP].val, DWARF_GET_LOC(d->loc[SP]));
|
||||||
|
|
||||||
/* A standard frame is defined as:
|
/* A standard frame is defined as:
|
||||||
- CFA is register-relative offset off R7 or SP;
|
- CFA is register-relative offset off R7 or SP;
|
||||||
|
@ -53,24 +53,24 @@ tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
|
||||||
if (f->frame_type == UNW_ARM_FRAME_OTHER
|
if (f->frame_type == UNW_ARM_FRAME_OTHER
|
||||||
&& (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG)
|
&& (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG)
|
||||||
&& (rs->reg[DWARF_CFA_REG_COLUMN].val == R7
|
&& (rs->reg[DWARF_CFA_REG_COLUMN].val == R7
|
||||||
|| rs->reg[DWARF_CFA_REG_COLUMN].val == SP)
|
|| rs->reg[DWARF_CFA_REG_COLUMN].val == SP)
|
||||||
&& labs(rs->reg[DWARF_CFA_OFF_COLUMN].val) < (1 << 29)
|
&& labs(rs->reg[DWARF_CFA_OFF_COLUMN].val) < (1 << 29)
|
||||||
&& d->ret_addr_column == LR
|
&& d->ret_addr_column == LR
|
||||||
&& (rs->reg[R7].where == DWARF_WHERE_UNDEF
|
&& (rs->reg[R7].where == DWARF_WHERE_UNDEF
|
||||||
|| rs->reg[R7].where == DWARF_WHERE_SAME
|
|| rs->reg[R7].where == DWARF_WHERE_SAME
|
||||||
|| (rs->reg[R7].where == DWARF_WHERE_CFAREL
|
|| (rs->reg[R7].where == DWARF_WHERE_CFAREL
|
||||||
&& labs(rs->reg[R7].val) < (1 << 29)
|
&& labs(rs->reg[R7].val) < (1 << 29)
|
||||||
&& rs->reg[R7].val+1 != 0))
|
&& rs->reg[R7].val+1 != 0))
|
||||||
&& (rs->reg[LR].where == DWARF_WHERE_UNDEF
|
&& (rs->reg[LR].where == DWARF_WHERE_UNDEF
|
||||||
|| rs->reg[LR].where == DWARF_WHERE_SAME
|
|| rs->reg[LR].where == DWARF_WHERE_SAME
|
||||||
|| (rs->reg[LR].where == DWARF_WHERE_CFAREL
|
|| (rs->reg[LR].where == DWARF_WHERE_CFAREL
|
||||||
&& labs(rs->reg[LR].val) < (1 << 29)
|
&& labs(rs->reg[LR].val) < (1 << 29)
|
||||||
&& rs->reg[LR].val+1 != 0))
|
&& rs->reg[LR].val+1 != 0))
|
||||||
&& (rs->reg[SP].where == DWARF_WHERE_UNDEF
|
&& (rs->reg[SP].where == DWARF_WHERE_UNDEF
|
||||||
|| rs->reg[SP].where == DWARF_WHERE_SAME
|
|| rs->reg[SP].where == DWARF_WHERE_SAME
|
||||||
|| (rs->reg[SP].where == DWARF_WHERE_CFAREL
|
|| (rs->reg[SP].where == DWARF_WHERE_CFAREL
|
||||||
&& labs(rs->reg[SP].val) < (1 << 29)
|
&& labs(rs->reg[SP].val) < (1 << 29)
|
||||||
&& rs->reg[SP].val+1 != 0)))
|
&& rs->reg[SP].val+1 != 0)))
|
||||||
{
|
{
|
||||||
/* Save information for a standard frame. */
|
/* Save information for a standard frame. */
|
||||||
f->frame_type = UNW_ARM_FRAME_STANDARD;
|
f->frame_type = UNW_ARM_FRAME_STANDARD;
|
||||||
|
|
|
@ -30,7 +30,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#define arm_exidx_step UNW_OBJ(arm_exidx_step)
|
#define arm_exidx_step UNW_OBJ(arm_exidx_step)
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
arm_exidx_step (struct cursor *c)
|
arm_exidx_step (struct cursor *c)
|
||||||
|
@ -64,7 +64,7 @@ arm_exidx_step (struct cursor *c)
|
||||||
if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa)
|
if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa)
|
||||||
{
|
{
|
||||||
Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
|
Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
|
||||||
__FUNCTION__, (long) c->dwarf.ip);
|
__FUNCTION__, (long) c->dwarf.ip);
|
||||||
return -UNW_EBADFRAME;
|
return -UNW_EBADFRAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,32 +103,32 @@ unw_handle_signal_frame (unw_cursor_t *cursor)
|
||||||
if (ret == 1)
|
if (ret == 1)
|
||||||
{
|
{
|
||||||
/* Handle non-RT signal frames. Check if the first word on the stack
|
/* Handle non-RT signal frames. Check if the first word on the stack
|
||||||
is the magic number. */
|
is the magic number. */
|
||||||
if (sp == 0x5ac3c35a)
|
if (sp == 0x5ac3c35a)
|
||||||
{
|
{
|
||||||
c->sigcontext_format = ARM_SCF_LINUX_SIGFRAME;
|
c->sigcontext_format = ARM_SCF_LINUX_SIGFRAME;
|
||||||
sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF;
|
sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
c->sigcontext_format = ARM_SCF_LINUX_OLD_SIGFRAME;
|
c->sigcontext_format = ARM_SCF_LINUX_OLD_SIGFRAME;
|
||||||
sc_addr = sp_addr;
|
sc_addr = sp_addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ret == 2)
|
else if (ret == 2)
|
||||||
{
|
{
|
||||||
/* Handle RT signal frames. Check if the first word on the stack is a
|
/* Handle RT signal frames. Check if the first word on the stack is a
|
||||||
pointer to the siginfo structure. */
|
pointer to the siginfo structure. */
|
||||||
if (sp == sp_addr + 8)
|
if (sp == sp_addr + 8)
|
||||||
{
|
{
|
||||||
c->sigcontext_format = ARM_SCF_LINUX_OLD_RT_SIGFRAME;
|
c->sigcontext_format = ARM_SCF_LINUX_OLD_RT_SIGFRAME;
|
||||||
sc_addr = sp_addr + 8 + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
|
sc_addr = sp_addr + 8 + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
c->sigcontext_format = ARM_SCF_LINUX_RT_SIGFRAME;
|
c->sigcontext_format = ARM_SCF_LINUX_RT_SIGFRAME;
|
||||||
sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
|
sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -UNW_EUNSPEC;
|
return -UNW_EUNSPEC;
|
||||||
|
@ -186,9 +186,9 @@ unw_step (unw_cursor_t *cursor)
|
||||||
Debug(1, "dwarf_step()=%d\n", ret);
|
Debug(1, "dwarf_step()=%d\n", ret);
|
||||||
|
|
||||||
if (likely (ret > 0))
|
if (likely (ret > 0))
|
||||||
return 1;
|
return 1;
|
||||||
else if (unlikely (ret == -UNW_ESTOPUNWIND))
|
else if (unlikely (ret == -UNW_ESTOPUNWIND))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (ret < 0 && ret != -UNW_ENOINFO)
|
if (ret < 0 && ret != -UNW_ENOINFO)
|
||||||
{
|
{
|
||||||
|
@ -203,9 +203,9 @@ unw_step (unw_cursor_t *cursor)
|
||||||
{
|
{
|
||||||
ret = arm_exidx_step (c);
|
ret = arm_exidx_step (c);
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
return 1;
|
return 1;
|
||||||
if (ret == -UNW_ESTOPUNWIND || ret == 0)
|
if (ret == -UNW_ESTOPUNWIND || ret == 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fall back on APCS frame parsing.
|
/* Fall back on APCS frame parsing.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
|
Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
|
||||||
Copyright (C) 2014 CERN and Aalto University
|
Copyright (C) 2014 CERN and Aalto University
|
||||||
Contributed by Filip Nyback
|
Contributed by Filip Nyback
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ typedef struct
|
||||||
size_t log_size;
|
size_t log_size;
|
||||||
size_t used;
|
size_t used;
|
||||||
size_t dtor_count; /* Counts how many times our destructor has already
|
size_t dtor_count; /* Counts how many times our destructor has already
|
||||||
been called. */
|
been called. */
|
||||||
} unw_trace_cache_t;
|
} unw_trace_cache_t;
|
||||||
|
|
||||||
static const unw_tdep_frame_t empty_frame = { 0, UNW_ARM_FRAME_OTHER, -1, -1, 0, -1, -1, -1 };
|
static const unw_tdep_frame_t empty_frame = { 0, UNW_ARM_FRAME_OTHER, -1, -1, 0, -1, -1, -1 };
|
||||||
|
@ -65,7 +65,7 @@ trace_cache_free (void *arg)
|
||||||
/* Not yet our turn to get destroyed. Re-install ourselves into the key. */
|
/* Not yet our turn to get destroyed. Re-install ourselves into the key. */
|
||||||
pthread_setspecific(trace_cache_key, cache);
|
pthread_setspecific(trace_cache_key, cache);
|
||||||
Debug(5, "delayed freeing cache %p (%zx to go)\n", cache,
|
Debug(5, "delayed freeing cache %p (%zx to go)\n", cache,
|
||||||
PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count);
|
PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tls_cache_destroyed = 1;
|
tls_cache_destroyed = 1;
|
||||||
|
@ -111,7 +111,7 @@ trace_cache_create (void)
|
||||||
/* The current thread is in the process of exiting. Don't recreate
|
/* The current thread is in the process of exiting. Don't recreate
|
||||||
cache, as we wouldn't have another chance to free it. */
|
cache, as we wouldn't have another chance to free it. */
|
||||||
Debug(5, "refusing to reallocate cache: "
|
Debug(5, "refusing to reallocate cache: "
|
||||||
"thread-locals are being deallocated\n");
|
"thread-locals are being deallocated\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,11 +215,11 @@ trace_cache_get (void)
|
||||||
highly unusual unwind info which uses these creatively. */
|
highly unusual unwind info which uses these creatively. */
|
||||||
static unw_tdep_frame_t *
|
static unw_tdep_frame_t *
|
||||||
trace_init_addr (unw_tdep_frame_t *f,
|
trace_init_addr (unw_tdep_frame_t *f,
|
||||||
unw_cursor_t *cursor,
|
unw_cursor_t *cursor,
|
||||||
unw_word_t cfa,
|
unw_word_t cfa,
|
||||||
unw_word_t pc,
|
unw_word_t pc,
|
||||||
unw_word_t r7,
|
unw_word_t r7,
|
||||||
unw_word_t sp)
|
unw_word_t sp)
|
||||||
{
|
{
|
||||||
struct cursor *c = (struct cursor *) cursor;
|
struct cursor *c = (struct cursor *) cursor;
|
||||||
struct dwarf_cursor *d = &c->dwarf;
|
struct dwarf_cursor *d = &c->dwarf;
|
||||||
|
@ -262,9 +262,9 @@ trace_init_addr (unw_tdep_frame_t *f,
|
||||||
f->last_frame = -1;
|
f->last_frame = -1;
|
||||||
|
|
||||||
Debug (3, "frame va %x type %d last %d cfa %s+%d r7 @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n",
|
Debug (3, "frame va %x type %d last %d cfa %s+%d r7 @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n",
|
||||||
f->virtual_address, f->frame_type, f->last_frame,
|
f->virtual_address, f->frame_type, f->last_frame,
|
||||||
f->cfa_reg_sp ? "sp" : "r7", f->cfa_reg_offset,
|
f->cfa_reg_sp ? "sp" : "r7", f->cfa_reg_offset,
|
||||||
f->r7_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset);
|
f->r7_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset);
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
@ -275,11 +275,11 @@ trace_init_addr (unw_tdep_frame_t *f,
|
||||||
frame cache slot which describes RIP. */
|
frame cache slot which describes RIP. */
|
||||||
static unw_tdep_frame_t *
|
static unw_tdep_frame_t *
|
||||||
trace_lookup (unw_cursor_t *cursor,
|
trace_lookup (unw_cursor_t *cursor,
|
||||||
unw_trace_cache_t *cache,
|
unw_trace_cache_t *cache,
|
||||||
unw_word_t cfa,
|
unw_word_t cfa,
|
||||||
unw_word_t pc,
|
unw_word_t pc,
|
||||||
unw_word_t r7,
|
unw_word_t r7,
|
||||||
unw_word_t sp)
|
unw_word_t sp)
|
||||||
{
|
{
|
||||||
/* First look up for previously cached information using cache as
|
/* First look up for previously cached information using cache as
|
||||||
linear probing hash table with probe step of 1. Majority of
|
linear probing hash table with probe step of 1. Majority of
|
||||||
|
@ -442,7 +442,7 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
||||||
{
|
{
|
||||||
pc -= d->use_prev_instr;
|
pc -= d->use_prev_instr;
|
||||||
Debug (2, "depth %d cfa 0x%x pc 0x%x sp 0x%x r7 0x%x\n",
|
Debug (2, "depth %d cfa 0x%x pc 0x%x sp 0x%x r7 0x%x\n",
|
||||||
depth, cfa, pc, sp, r7);
|
depth, cfa, pc, sp, r7);
|
||||||
|
|
||||||
/* See if we have this address cached. If not, evaluate enough of
|
/* See if we have this address cached. If not, evaluate enough of
|
||||||
the dwarf unwind information to fill the cache line data, or to
|
the dwarf unwind information to fill the cache line data, or to
|
||||||
|
@ -484,7 +484,7 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
||||||
/* Advance standard traceable frame. */
|
/* Advance standard traceable frame. */
|
||||||
cfa = (f->cfa_reg_sp ? sp : r7) + f->cfa_reg_offset;
|
cfa = (f->cfa_reg_sp ? sp : r7) + f->cfa_reg_offset;
|
||||||
if (likely(f->lr_cfa_offset != -1))
|
if (likely(f->lr_cfa_offset != -1))
|
||||||
ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->lr_cfa_offset, pc);
|
ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->lr_cfa_offset, pc);
|
||||||
else if (lr != 0)
|
else if (lr != 0)
|
||||||
{
|
{
|
||||||
/* Use the saved link register as the new pc. */
|
/* Use the saved link register as the new pc. */
|
||||||
|
@ -492,7 +492,7 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
||||||
lr = 0;
|
lr = 0;
|
||||||
}
|
}
|
||||||
if (likely(ret >= 0) && likely(f->r7_cfa_offset != -1))
|
if (likely(ret >= 0) && likely(f->r7_cfa_offset != -1))
|
||||||
ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->r7_cfa_offset, r7);
|
ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->r7_cfa_offset, r7);
|
||||||
|
|
||||||
/* Don't bother reading SP from DWARF, CFA becomes new SP. */
|
/* Don't bother reading SP from DWARF, CFA becomes new SP. */
|
||||||
sp = cfa;
|
sp = cfa;
|
||||||
|
@ -524,14 +524,14 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* We cannot trace through this frame, give up and tell the
|
/* We cannot trace through this frame, give up and tell the
|
||||||
caller we had to stop. Data collected so far may still be
|
caller we had to stop. Data collected so far may still be
|
||||||
useful to the caller, so let it know how far we got. */
|
useful to the caller, so let it know how far we got. */
|
||||||
ret = -UNW_ESTOPUNWIND;
|
ret = -UNW_ESTOPUNWIND;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug (4, "new cfa 0x%x pc 0x%x sp 0x%x r7 0x%x\n",
|
Debug (4, "new cfa 0x%x pc 0x%x sp 0x%x r7 0x%x\n",
|
||||||
cfa, pc, sp, r7);
|
cfa, pc, sp, r7);
|
||||||
|
|
||||||
/* If we failed or ended up somewhere bogus, stop. */
|
/* If we failed or ended up somewhere bogus, stop. */
|
||||||
if (unlikely(ret < 0 || pc < 0x4000))
|
if (unlikely(ret < 0 || pc < 0x4000))
|
||||||
|
|
|
@ -54,7 +54,7 @@ common_init (struct cursor *c, unsigned use_prev_instr)
|
||||||
|
|
||||||
/* FIXME: correct for ARM? */
|
/* FIXME: correct for ARM? */
|
||||||
ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13),
|
ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13),
|
||||||
&c->dwarf.cfa);
|
&c->dwarf.cfa);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,9 @@ PROTECTED int
|
||||||
unw_is_fpreg (int regnum)
|
unw_is_fpreg (int regnum)
|
||||||
{
|
{
|
||||||
return ((regnum >= UNW_ARM_S0 && regnum <= UNW_ARM_S31)
|
return ((regnum >= UNW_ARM_S0 && regnum <= UNW_ARM_S31)
|
||||||
|| (regnum >= UNW_ARM_F0 && regnum <= UNW_ARM_F7)
|
|| (regnum >= UNW_ARM_F0 && regnum <= UNW_ARM_F7)
|
||||||
|| (regnum >= UNW_ARM_wCGR0 && regnum <= UNW_ARM_wCGR7)
|
|| (regnum >= UNW_ARM_wCGR0 && regnum <= UNW_ARM_wCGR7)
|
||||||
|| (regnum >= UNW_ARM_wR0 && regnum <= UNW_ARM_wR15)
|
|| (regnum >= UNW_ARM_wR0 && regnum <= UNW_ARM_wR15)
|
||||||
|| (regnum >= UNW_ARM_wC0 && regnum <= UNW_ARM_wC7)
|
|| (regnum >= UNW_ARM_wC0 && regnum <= UNW_ARM_wC7)
|
||||||
|| (regnum >= UNW_ARM_D0 && regnum <= UNW_ARM_D31));
|
|| (regnum >= UNW_ARM_D0 && regnum <= UNW_ARM_D31));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,33 +4,33 @@
|
||||||
|
|
||||||
/* Offsets for ARM Linux "ucontext_t": */
|
/* Offsets for ARM Linux "ucontext_t": */
|
||||||
|
|
||||||
#define LINUX_UC_FLAGS_OFF 0x00
|
#define LINUX_UC_FLAGS_OFF 0x00
|
||||||
#define LINUX_UC_LINK_OFF 0x04
|
#define LINUX_UC_LINK_OFF 0x04
|
||||||
#define LINUX_UC_STACK_OFF 0x08
|
#define LINUX_UC_STACK_OFF 0x08
|
||||||
#define LINUX_UC_MCONTEXT_OFF 0x14
|
#define LINUX_UC_MCONTEXT_OFF 0x14
|
||||||
#define LINUX_UC_SIGMASK_OFF 0x68
|
#define LINUX_UC_SIGMASK_OFF 0x68
|
||||||
#define LINUX_UC_REGSPACE_OFF 0xE8
|
#define LINUX_UC_REGSPACE_OFF 0xE8
|
||||||
|
|
||||||
/* Offsets for ARM Linux "struct sigcontext": */
|
/* Offsets for ARM Linux "struct sigcontext": */
|
||||||
|
|
||||||
#define LINUX_SC_TRAPNO_OFF 0x00
|
#define LINUX_SC_TRAPNO_OFF 0x00
|
||||||
#define LINUX_SC_ERRORCODE_OFF 0x04
|
#define LINUX_SC_ERRORCODE_OFF 0x04
|
||||||
#define LINUX_SC_OLDMASK_OFF 0x08
|
#define LINUX_SC_OLDMASK_OFF 0x08
|
||||||
#define LINUX_SC_R0_OFF 0x0C
|
#define LINUX_SC_R0_OFF 0x0C
|
||||||
#define LINUX_SC_R1_OFF 0x10
|
#define LINUX_SC_R1_OFF 0x10
|
||||||
#define LINUX_SC_R2_OFF 0x14
|
#define LINUX_SC_R2_OFF 0x14
|
||||||
#define LINUX_SC_R3_OFF 0x18
|
#define LINUX_SC_R3_OFF 0x18
|
||||||
#define LINUX_SC_R4_OFF 0x1C
|
#define LINUX_SC_R4_OFF 0x1C
|
||||||
#define LINUX_SC_R5_OFF 0x20
|
#define LINUX_SC_R5_OFF 0x20
|
||||||
#define LINUX_SC_R6_OFF 0x24
|
#define LINUX_SC_R6_OFF 0x24
|
||||||
#define LINUX_SC_R7_OFF 0x28
|
#define LINUX_SC_R7_OFF 0x28
|
||||||
#define LINUX_SC_R8_OFF 0x2C
|
#define LINUX_SC_R8_OFF 0x2C
|
||||||
#define LINUX_SC_R9_OFF 0x30
|
#define LINUX_SC_R9_OFF 0x30
|
||||||
#define LINUX_SC_R10_OFF 0x34
|
#define LINUX_SC_R10_OFF 0x34
|
||||||
#define LINUX_SC_FP_OFF 0x38
|
#define LINUX_SC_FP_OFF 0x38
|
||||||
#define LINUX_SC_IP_OFF 0x3C
|
#define LINUX_SC_IP_OFF 0x3C
|
||||||
#define LINUX_SC_SP_OFF 0x40
|
#define LINUX_SC_SP_OFF 0x40
|
||||||
#define LINUX_SC_LR_OFF 0x44
|
#define LINUX_SC_LR_OFF 0x44
|
||||||
#define LINUX_SC_PC_OFF 0x48
|
#define LINUX_SC_PC_OFF 0x48
|
||||||
#define LINUX_SC_CPSR_OFF 0x4C
|
#define LINUX_SC_CPSR_OFF 0x4C
|
||||||
#define LINUX_SC_FAULTADDR_OFF 0x50
|
#define LINUX_SC_FAULTADDR_OFF 0x50
|
||||||
|
|
|
@ -32,18 +32,18 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#include "libunwind_i.h"
|
#include "libunwind_i.h"
|
||||||
|
|
||||||
/* DWARF column numbers for ARM: */
|
/* DWARF column numbers for ARM: */
|
||||||
#define R7 7
|
#define R7 7
|
||||||
#define SP 13
|
#define SP 13
|
||||||
#define LR 14
|
#define LR 14
|
||||||
#define PC 15
|
#define PC 15
|
||||||
|
|
||||||
#define arm_lock UNW_OBJ(lock)
|
#define arm_lock UNW_OBJ(lock)
|
||||||
#define arm_local_resume UNW_OBJ(local_resume)
|
#define arm_local_resume UNW_OBJ(local_resume)
|
||||||
#define arm_local_addr_space_init UNW_OBJ(local_addr_space_init)
|
#define arm_local_addr_space_init UNW_OBJ(local_addr_space_init)
|
||||||
|
|
||||||
extern void arm_local_addr_space_init (void);
|
extern void arm_local_addr_space_init (void);
|
||||||
extern int arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
|
extern int arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
|
||||||
void *arg);
|
void *arg);
|
||||||
/* By-pass calls to access_mem() when known to be safe. */
|
/* By-pass calls to access_mem() when known to be safe. */
|
||||||
#ifdef UNW_LOCAL_ONLY
|
#ifdef UNW_LOCAL_ONLY
|
||||||
# undef ACCESS_MEM_FAST
|
# undef ACCESS_MEM_FAST
|
||||||
|
|
|
@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
int
|
int
|
||||||
_UCD_access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
|
_UCD_access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
|
||||||
int write, void *arg)
|
int write, void *arg)
|
||||||
{
|
{
|
||||||
if (write)
|
if (write)
|
||||||
{
|
{
|
||||||
|
@ -43,9 +43,9 @@ _UCD_access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
|
||||||
{
|
{
|
||||||
phdr = &ui->phdrs[i];
|
phdr = &ui->phdrs[i];
|
||||||
if (phdr->p_vaddr <= addr && addr_last < phdr->p_vaddr + phdr->p_memsz)
|
if (phdr->p_vaddr <= addr && addr_last < phdr->p_vaddr + phdr->p_memsz)
|
||||||
{
|
{
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Debug(1, "addr 0x%llx is unmapped\n", (unsigned long long)addr);
|
Debug(1, "addr 0x%llx is unmapped\n", (unsigned long long)addr);
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
|
@ -62,8 +62,8 @@ _UCD_access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
|
||||||
if (phdr->backing_fd < 0)
|
if (phdr->backing_fd < 0)
|
||||||
{
|
{
|
||||||
Debug(1, "access to not-present data in phdr[%d]: addr:0x%llx\n",
|
Debug(1, "access to not-present data in phdr[%d]: addr:0x%llx\n",
|
||||||
i, (unsigned long long)addr
|
i, (unsigned long long)addr
|
||||||
);
|
);
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
}
|
}
|
||||||
filename = phdr->backing_filename;
|
filename = phdr->backing_filename;
|
||||||
|
@ -82,17 +82,17 @@ _UCD_access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
|
||||||
goto read_error;
|
goto read_error;
|
||||||
|
|
||||||
Debug(1, "0x%llx <- [addr:0x%llx fileofs:0x%llx]\n",
|
Debug(1, "0x%llx <- [addr:0x%llx fileofs:0x%llx]\n",
|
||||||
(unsigned long long)(*val),
|
(unsigned long long)(*val),
|
||||||
(unsigned long long)addr,
|
(unsigned long long)addr,
|
||||||
(unsigned long long)fileofs
|
(unsigned long long)fileofs
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
read_error:
|
read_error:
|
||||||
Debug(1, "access out of file: addr:0x%llx fileofs:%llx file:'%s'\n",
|
Debug(1, "access out of file: addr:0x%llx fileofs:%llx file:'%s'\n",
|
||||||
(unsigned long long)addr,
|
(unsigned long long)addr,
|
||||||
(unsigned long long)fileofs,
|
(unsigned long long)fileofs,
|
||||||
filename
|
filename
|
||||||
);
|
);
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,8 +130,8 @@ _UCD_access_reg (unw_addr_space_t as,
|
||||||
* image.
|
* image.
|
||||||
*/
|
*/
|
||||||
Debug(1, "pr_reg[%d]:%ld (0x%lx)\n", regnum,
|
Debug(1, "pr_reg[%d]:%ld (0x%lx)\n", regnum,
|
||||||
(long)ui->prstatus->pr_reg[regnum],
|
(long)ui->prstatus->pr_reg[regnum],
|
||||||
(long)ui->prstatus->pr_reg[regnum]
|
(long)ui->prstatus->pr_reg[regnum]
|
||||||
);
|
);
|
||||||
*valp = ui->prstatus->pr_reg[regnum];
|
*valp = ui->prstatus->pr_reg[regnum];
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
PROTECTED unw_accessors_t _UCD_accessors =
|
PROTECTED unw_accessors_t _UCD_accessors =
|
||||||
{
|
{
|
||||||
.find_proc_info = _UCD_find_proc_info,
|
.find_proc_info = _UCD_find_proc_info,
|
||||||
.put_unwind_info = _UCD_put_unwind_info,
|
.put_unwind_info = _UCD_put_unwind_info,
|
||||||
.get_dyn_info_list_addr = _UCD_get_dyn_info_list_addr,
|
.get_dyn_info_list_addr = _UCD_get_dyn_info_list_addr,
|
||||||
.access_mem = _UCD_access_mem,
|
.access_mem = _UCD_access_mem,
|
||||||
.access_reg = _UCD_access_reg,
|
.access_reg = _UCD_access_reg,
|
||||||
.access_fpreg = _UCD_access_fpreg,
|
.access_fpreg = _UCD_access_fpreg,
|
||||||
.resume = _UCD_resume,
|
.resume = _UCD_resume,
|
||||||
.get_proc_name = _UCD_get_proc_name
|
.get_proc_name = _UCD_get_proc_name
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,17 +40,17 @@ CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr)
|
||||||
/* addr, length, prot, flags, fd, fd_offset */
|
/* addr, length, prot, flags, fd, fd_offset */
|
||||||
ei->image = mmap(NULL, phdr->p_memsz, PROT_READ, MAP_PRIVATE, ui->coredump_fd, phdr->p_offset);
|
ei->image = mmap(NULL, phdr->p_memsz, PROT_READ, MAP_PRIVATE, ui->coredump_fd, phdr->p_offset);
|
||||||
if (ei->image == MAP_FAILED)
|
if (ei->image == MAP_FAILED)
|
||||||
{
|
{
|
||||||
ei->image = NULL;
|
ei->image = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ei->size = phdr->p_filesz;
|
ei->size = phdr->p_filesz;
|
||||||
size_t remainder_len = phdr->p_memsz - phdr->p_filesz;
|
size_t remainder_len = phdr->p_memsz - phdr->p_filesz;
|
||||||
if (remainder_len > 0)
|
if (remainder_len > 0)
|
||||||
{
|
{
|
||||||
void *remainder_base = (char*) ei->image + phdr->p_filesz;
|
void *remainder_base = (char*) ei->image + phdr->p_filesz;
|
||||||
munmap(remainder_base, remainder_len);
|
munmap(remainder_base, remainder_len);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* We have a backing file for this segment.
|
/* We have a backing file for this segment.
|
||||||
* This file is always longer than phdr->p_memsz,
|
* This file is always longer than phdr->p_memsz,
|
||||||
|
@ -62,10 +62,10 @@ CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr)
|
||||||
/* addr, length, prot, flags, fd, fd_offset */
|
/* addr, length, prot, flags, fd, fd_offset */
|
||||||
ei->image = mmap(NULL, phdr->backing_filesize, PROT_READ, MAP_PRIVATE, phdr->backing_fd, 0);
|
ei->image = mmap(NULL, phdr->backing_filesize, PROT_READ, MAP_PRIVATE, phdr->backing_fd, 0);
|
||||||
if (ei->image == MAP_FAILED)
|
if (ei->image == MAP_FAILED)
|
||||||
{
|
{
|
||||||
ei->image = NULL;
|
ei->image = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ei->size = phdr->backing_filesize;
|
ei->size = phdr->backing_filesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,10 +89,10 @@ _UCD_get_elf_image(struct UCD_info *ui, unw_word_t ip)
|
||||||
{
|
{
|
||||||
coredump_phdr_t *phdr = &ui->phdrs[i];
|
coredump_phdr_t *phdr = &ui->phdrs[i];
|
||||||
if (phdr->p_vaddr <= ip && ip < phdr->p_vaddr + phdr->p_memsz)
|
if (phdr->p_vaddr <= ip && ip < phdr->p_vaddr + phdr->p_memsz)
|
||||||
{
|
{
|
||||||
phdr = CD_elf_map_image(ui, phdr);
|
phdr = CD_elf_map_image(ui, phdr);
|
||||||
return phdr;
|
return phdr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ get_unwind_info(struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip)
|
||||||
|
|
||||||
int
|
int
|
||||||
_UCD_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
|
_UCD_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg)
|
int need_unwind_info, void *arg)
|
||||||
{
|
{
|
||||||
struct UCD_info *ui = arg;
|
struct UCD_info *ui = arg;
|
||||||
|
|
||||||
|
@ -119,33 +119,33 @@ _UCD_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
|
||||||
if (ui->edi.ktab.format != -1)
|
if (ui->edi.ktab.format != -1)
|
||||||
{
|
{
|
||||||
/* The kernel unwind table resides in local memory, so we have
|
/* The kernel unwind table resides in local memory, so we have
|
||||||
to use the local address space to search it. Since
|
to use the local address space to search it. Since
|
||||||
_UCD_put_unwind_info() has no easy way of detecting this
|
_UCD_put_unwind_info() has no easy way of detecting this
|
||||||
case, we simply make a copy of the unwind-info, so
|
case, we simply make a copy of the unwind-info, so
|
||||||
_UCD_put_unwind_info() can always free() the unwind-info
|
_UCD_put_unwind_info() can always free() the unwind-info
|
||||||
without ill effects. */
|
without ill effects. */
|
||||||
ret = tdep_search_unwind_table (unw_local_addr_space, ip, &ui->edi.ktab, pi,
|
ret = tdep_search_unwind_table (unw_local_addr_space, ip, &ui->edi.ktab, pi,
|
||||||
need_unwind_info, arg);
|
need_unwind_info, arg);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
{
|
{
|
||||||
if (!need_unwind_info)
|
if (!need_unwind_info)
|
||||||
pi->unwind_info = NULL;
|
pi->unwind_info = NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
void *mem = malloc (pi->unwind_info_size);
|
void *mem = malloc (pi->unwind_info_size);
|
||||||
|
|
||||||
if (!mem)
|
if (!mem)
|
||||||
return -UNW_ENOMEM;
|
return -UNW_ENOMEM;
|
||||||
memcpy (mem, pi->unwind_info, pi->unwind_info_size);
|
memcpy (mem, pi->unwind_info, pi->unwind_info_size);
|
||||||
pi->unwind_info = mem;
|
pi->unwind_info = mem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ret == -UNW_ENOINFO && ui->edi.di_cache.format != -1)
|
if (ret == -UNW_ENOINFO && ui->edi.di_cache.format != -1)
|
||||||
ret = tdep_search_unwind_table (as, ip, &ui->edi.di_cache,
|
ret = tdep_search_unwind_table (as, ip, &ui->edi.di_cache,
|
||||||
pi, need_unwind_info, arg);
|
pi, need_unwind_info, arg);
|
||||||
|
|
||||||
#if UNW_TARGET_ARM
|
#if UNW_TARGET_ARM
|
||||||
if (ret == -UNW_ENOINFO && ui->edi.di_arm.format != -1)
|
if (ret == -UNW_ENOINFO && ui->edi.di_arm.format != -1)
|
||||||
|
@ -155,7 +155,7 @@ _UCD_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
|
||||||
|
|
||||||
if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1)
|
if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1)
|
||||||
ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi,
|
ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi,
|
||||||
need_unwind_info, arg);
|
need_unwind_info, arg);
|
||||||
|
|
||||||
Debug(1, "returns %d\n", ret);
|
Debug(1, "returns %d\n", ret);
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
sensitive to the performance of this routine, why bother... */
|
sensitive to the performance of this routine, why bother... */
|
||||||
static int
|
static int
|
||||||
elf_w (CD_get_proc_name) (struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip,
|
elf_w (CD_get_proc_name) (struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip,
|
||||||
char *buf, size_t buf_len, unw_word_t *offp)
|
char *buf, size_t buf_len, unw_word_t *offp)
|
||||||
{
|
{
|
||||||
unsigned long segbase, mapoff;
|
unsigned long segbase, mapoff;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -56,7 +56,7 @@ elf_w (CD_get_proc_name) (struct UCD_info *ui, unw_addr_space_t as, unw_word_t i
|
||||||
|
|
||||||
int
|
int
|
||||||
_UCD_get_proc_name (unw_addr_space_t as, unw_word_t ip,
|
_UCD_get_proc_name (unw_addr_space_t as, unw_word_t ip,
|
||||||
char *buf, size_t buf_len, unw_word_t *offp, void *arg)
|
char *buf, size_t buf_len, unw_word_t *offp, void *arg)
|
||||||
{
|
{
|
||||||
struct UCD_info *ui = arg;
|
struct UCD_info *ui = arg;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
int
|
int
|
||||||
_UCD_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
|
_UCD_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
|
||||||
int write, void *arg)
|
int write, void *arg)
|
||||||
{
|
{
|
||||||
print_error (__func__);
|
print_error (__func__);
|
||||||
print_error (" not implemented\n");
|
print_error (" not implemented\n");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* We need to get a separate copy of the ELF-code into
|
/* We need to get a separate copy of the ELF-code into
|
||||||
libunwind-coredump since it cannot (and must not) have any ELF
|
libunwind-coredump since it cannot (and must not) have any ELF
|
||||||
dependencies on libunwind. */
|
dependencies on libunwind. */
|
||||||
#include "libunwind_i.h" /* get ELFCLASS defined */
|
#include "libunwind_i.h" /* get ELFCLASS defined */
|
||||||
#include "../elfxx.c"
|
#include "../elfxx.c"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2003-2005 Hewlett-Packard Co
|
Copyright (C) 2003-2005 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
|
get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
|
||||||
int *countp)
|
int *countp)
|
||||||
{
|
{
|
||||||
unsigned long lo, hi, off;
|
unsigned long lo, hi, off;
|
||||||
struct UPT_info *ui = arg;
|
struct UPT_info *ui = arg;
|
||||||
|
@ -46,26 +46,26 @@ get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
|
||||||
while (maps_next (&mi, &lo, &hi, &off))
|
while (maps_next (&mi, &lo, &hi, &off))
|
||||||
{
|
{
|
||||||
if (off)
|
if (off)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
invalidate_edi (&ui->edi);
|
invalidate_edi (&ui->edi);
|
||||||
|
|
||||||
if (elf_map_image (&ui->ei, path) < 0)
|
if (elf_map_image (&ui->ei, path) < 0)
|
||||||
/* ignore unmappable stuff like "/SYSV00001b58 (deleted)" */
|
/* ignore unmappable stuff like "/SYSV00001b58 (deleted)" */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Debug (16, "checking object %s\n", path);
|
Debug (16, "checking object %s\n", path);
|
||||||
|
|
||||||
di = tdep_find_unwind_table (&ui->edi, as, path, lo, off);
|
di = tdep_find_unwind_table (&ui->edi, as, path, lo, off);
|
||||||
if (di)
|
if (di)
|
||||||
{
|
{
|
||||||
res = _Uia64_find_dyn_list (as, di, arg);
|
res = _Uia64_find_dyn_list (as, di, arg);
|
||||||
if (res && count++ == 0)
|
if (res && count++ == 0)
|
||||||
{
|
{
|
||||||
Debug (12, "dyn_info_list_addr = 0x%lx\n", (long) res);
|
Debug (12, "dyn_info_list_addr = 0x%lx\n", (long) res);
|
||||||
*dil_addr = res;
|
*dil_addr = res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maps_close (&mi);
|
maps_close (&mi);
|
||||||
*countp = count;
|
*countp = count;
|
||||||
|
@ -76,7 +76,7 @@ get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
|
get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
|
||||||
int *countp)
|
int *countp)
|
||||||
{
|
{
|
||||||
# warning Implement get_list_addr(), please.
|
# warning Implement get_list_addr(), please.
|
||||||
*countp = 0;
|
*countp = 0;
|
||||||
|
@ -87,7 +87,7 @@ get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg,
|
||||||
|
|
||||||
int
|
int
|
||||||
_UCD_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr,
|
_UCD_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
int count, ret;
|
int count, ret;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2003 Hewlett-Packard Co
|
Copyright (C) 2003 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2003 Hewlett-Packard Co
|
Copyright (C) 2003 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
190
src/dwarf/Gfde.c
190
src/dwarf/Gfde.c
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
|
Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ is_cie_id (unw_word_t val, int is_debug_frame)
|
||||||
repeated. */
|
repeated. */
|
||||||
static inline int
|
static inline int
|
||||||
parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
||||||
const unw_proc_info_t *pi, struct dwarf_cie_info *dci,
|
const unw_proc_info_t *pi, struct dwarf_cie_info *dci,
|
||||||
unw_word_t base, void *arg)
|
unw_word_t base, void *arg)
|
||||||
{
|
{
|
||||||
uint8_t version, ch, augstr[5], fde_encoding, handler_encoding;
|
uint8_t version, ch, augstr[5], fde_encoding, handler_encoding;
|
||||||
unw_word_t len, cie_end_addr, aug_size;
|
unw_word_t len, cie_end_addr, aug_size;
|
||||||
|
@ -53,8 +53,8 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
||||||
uint64_t u64val;
|
uint64_t u64val;
|
||||||
size_t i;
|
size_t i;
|
||||||
int ret;
|
int ret;
|
||||||
# define STR2(x) #x
|
# define STR2(x) #x
|
||||||
# define STR(x) STR2(x)
|
# define STR(x) STR2(x)
|
||||||
|
|
||||||
/* Pick appropriate default for FDE-encoding. DWARF spec says
|
/* Pick appropriate default for FDE-encoding. DWARF spec says
|
||||||
start-IP (initial_location) and the code-size (address_range) are
|
start-IP (initial_location) and the code-size (address_range) are
|
||||||
|
@ -63,9 +63,9 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
||||||
for fde_encoding. */
|
for fde_encoding. */
|
||||||
switch (dwarf_addr_size (as))
|
switch (dwarf_addr_size (as))
|
||||||
{
|
{
|
||||||
case 4: fde_encoding = DW_EH_PE_udata4; break;
|
case 4: fde_encoding = DW_EH_PE_udata4; break;
|
||||||
case 8: fde_encoding = DW_EH_PE_udata8; break;
|
case 8: fde_encoding = DW_EH_PE_udata8; break;
|
||||||
default: fde_encoding = DW_EH_PE_omit; break;
|
default: fde_encoding = DW_EH_PE_omit; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dci->lsda_encoding = DW_EH_PE_omit;
|
dci->lsda_encoding = DW_EH_PE_omit;
|
||||||
|
@ -84,32 +84,32 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
||||||
len = u32val;
|
len = u32val;
|
||||||
cie_end_addr = addr + len;
|
cie_end_addr = addr + len;
|
||||||
if ((ret = dwarf_readu32 (as, a, &addr, &cie_id, arg)) < 0)
|
if ((ret = dwarf_readu32 (as, a, &addr, &cie_id, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if (cie_id != expected_id)
|
if (cie_id != expected_id)
|
||||||
{
|
{
|
||||||
Debug (1, "Unexpected CIE id %x\n", cie_id);
|
Debug (1, "Unexpected CIE id %x\n", cie_id);
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* the CIE is in the 64-bit DWARF format */
|
/* the CIE is in the 64-bit DWARF format */
|
||||||
uint64_t cie_id;
|
uint64_t cie_id;
|
||||||
/* DWARF says CIE id should be 0xffffffffffffffff, but in
|
/* DWARF says CIE id should be 0xffffffffffffffff, but in
|
||||||
.eh_frame, it's 0 */
|
.eh_frame, it's 0 */
|
||||||
const uint64_t expected_id = (base) ? 0xffffffffffffffffull : 0;
|
const uint64_t expected_id = (base) ? 0xffffffffffffffffull : 0;
|
||||||
|
|
||||||
if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0)
|
if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
len = u64val;
|
len = u64val;
|
||||||
cie_end_addr = addr + len;
|
cie_end_addr = addr + len;
|
||||||
if ((ret = dwarf_readu64 (as, a, &addr, &cie_id, arg)) < 0)
|
if ((ret = dwarf_readu64 (as, a, &addr, &cie_id, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if (cie_id != expected_id)
|
if (cie_id != expected_id)
|
||||||
{
|
{
|
||||||
Debug (1, "Unexpected CIE id %llx\n", (long long) cie_id);
|
Debug (1, "Unexpected CIE id %llx\n", (long long) cie_id);
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dci->cie_instr_end = cie_end_addr;
|
dci->cie_instr_end = cie_end_addr;
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
||||||
if (version != 1 && version != DWARF_CIE_VERSION)
|
if (version != 1 && version != DWARF_CIE_VERSION)
|
||||||
{
|
{
|
||||||
Debug (1, "Got CIE version %u, expected version 1 or "
|
Debug (1, "Got CIE version %u, expected version 1 or "
|
||||||
STR (DWARF_CIE_VERSION) "\n", version);
|
STR (DWARF_CIE_VERSION) "\n", version);
|
||||||
return -UNW_EBADVERSION;
|
return -UNW_EBADVERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,13 +128,13 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
||||||
for (i = 0;;)
|
for (i = 0;;)
|
||||||
{
|
{
|
||||||
if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!ch)
|
if (!ch)
|
||||||
break; /* end of augmentation string */
|
break; /* end of augmentation string */
|
||||||
|
|
||||||
if (i < sizeof (augstr) - 1)
|
if (i < sizeof (augstr) - 1)
|
||||||
augstr[i++] = ch;
|
augstr[i++] = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->code_align, arg)) < 0
|
if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->code_align, arg)) < 0
|
||||||
|
@ -145,11 +145,11 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
||||||
if (version == 1)
|
if (version == 1)
|
||||||
{
|
{
|
||||||
if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
dci->ret_addr_column = ch;
|
dci->ret_addr_column = ch;
|
||||||
}
|
}
|
||||||
else if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->ret_addr_column,
|
else if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->ret_addr_column,
|
||||||
arg)) < 0)
|
arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -157,7 +157,7 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
||||||
{
|
{
|
||||||
dci->sized_augmentation = 1;
|
dci->sized_augmentation = 1;
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0)
|
if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,50 +165,50 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
||||||
switch (augstr[i])
|
switch (augstr[i])
|
||||||
{
|
{
|
||||||
case 'L':
|
case 'L':
|
||||||
/* read the LSDA pointer-encoding format. */
|
/* read the LSDA pointer-encoding format. */
|
||||||
if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
dci->lsda_encoding = ch;
|
dci->lsda_encoding = ch;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'R':
|
case 'R':
|
||||||
/* read the FDE pointer-encoding format. */
|
/* read the FDE pointer-encoding format. */
|
||||||
if ((ret = dwarf_readu8 (as, a, &addr, &fde_encoding, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, &addr, &fde_encoding, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
/* read the personality-routine pointer-encoding format. */
|
/* read the personality-routine pointer-encoding format. */
|
||||||
if ((ret = dwarf_readu8 (as, a, &addr, &handler_encoding, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, &addr, &handler_encoding, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = dwarf_read_encoded_pointer (as, a, &addr, handler_encoding,
|
if ((ret = dwarf_read_encoded_pointer (as, a, &addr, handler_encoding,
|
||||||
pi, &dci->handler, arg)) < 0)
|
pi, &dci->handler, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
/* This is a signal frame. */
|
/* This is a signal frame. */
|
||||||
dci->signal_frame = 1;
|
dci->signal_frame = 1;
|
||||||
|
|
||||||
/* Temporarily set it to one so dwarf_parse_fde() knows that
|
/* Temporarily set it to one so dwarf_parse_fde() knows that
|
||||||
it should fetch the actual ABI/TAG pair from the FDE. */
|
it should fetch the actual ABI/TAG pair from the FDE. */
|
||||||
dci->have_abi_marker = 1;
|
dci->have_abi_marker = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Debug (1, "Unexpected augmentation string `%s'\n", augstr);
|
Debug (1, "Unexpected augmentation string `%s'\n", augstr);
|
||||||
if (dci->sized_augmentation)
|
if (dci->sized_augmentation)
|
||||||
/* If we have the size of the augmentation body, we can skip
|
/* If we have the size of the augmentation body, we can skip
|
||||||
over the parts that we don't understand, so we're OK. */
|
over the parts that we don't understand, so we're OK. */
|
||||||
goto done;
|
goto done;
|
||||||
else
|
else
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
dci->fde_encoding = fde_encoding;
|
dci->fde_encoding = fde_encoding;
|
||||||
dci->cie_instr_start = addr;
|
dci->cie_instr_start = addr;
|
||||||
Debug (15, "CIE parsed OK, augmentation = \"%s\", handler=0x%lx\n",
|
Debug (15, "CIE parsed OK, augmentation = \"%s\", handler=0x%lx\n",
|
||||||
augstr, (long) dci->handler);
|
augstr, (long) dci->handler);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,9 +219,9 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
||||||
|
|
||||||
HIDDEN int
|
HIDDEN int
|
||||||
dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_word_t *addrp, unw_proc_info_t *pi,
|
unw_word_t *addrp, unw_proc_info_t *pi,
|
||||||
int need_unwind_info, unw_word_t base,
|
int need_unwind_info, unw_word_t base,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
unw_word_t fde_end_addr, cie_addr, cie_offset_addr, aug_end_addr = 0;
|
unw_word_t fde_end_addr, cie_addr, cie_offset_addr, aug_end_addr = 0;
|
||||||
unw_word_t start_ip, ip_range, aug_size, addr = *addrp;
|
unw_word_t start_ip, ip_range, aug_size, addr = *addrp;
|
||||||
|
@ -242,9 +242,9 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
int32_t cie_offset;
|
int32_t cie_offset;
|
||||||
|
|
||||||
/* In some configurations, an FDE with a 0 length indicates the
|
/* In some configurations, an FDE with a 0 length indicates the
|
||||||
end of the FDE-table. */
|
end of the FDE-table. */
|
||||||
if (u32val == 0)
|
if (u32val == 0)
|
||||||
return -UNW_ENOINFO;
|
return -UNW_ENOINFO;
|
||||||
|
|
||||||
/* the FDE is in the 32-bit DWARF format */
|
/* the FDE is in the 32-bit DWARF format */
|
||||||
|
|
||||||
|
@ -252,20 +252,20 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
cie_offset_addr = addr;
|
cie_offset_addr = addr;
|
||||||
|
|
||||||
if ((ret = dwarf_reads32 (as, a, &addr, &cie_offset, arg)) < 0)
|
if ((ret = dwarf_reads32 (as, a, &addr, &cie_offset, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (is_cie_id (cie_offset, base != 0))
|
if (is_cie_id (cie_offset, base != 0))
|
||||||
/* ignore CIEs (happens during linear searches) */
|
/* ignore CIEs (happens during linear searches) */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (base != 0)
|
if (base != 0)
|
||||||
cie_addr = base + cie_offset;
|
cie_addr = base + cie_offset;
|
||||||
else
|
else
|
||||||
/* DWARF says that the CIE_pointer in the FDE is a
|
/* DWARF says that the CIE_pointer in the FDE is a
|
||||||
.debug_frame-relative offset, but the GCC-generated .eh_frame
|
.debug_frame-relative offset, but the GCC-generated .eh_frame
|
||||||
sections instead store a "pcrelative" offset, which is just
|
sections instead store a "pcrelative" offset, which is just
|
||||||
as fine as it's self-contained. */
|
as fine as it's self-contained. */
|
||||||
cie_addr = cie_offset_addr - cie_offset;
|
cie_addr = cie_offset_addr - cie_offset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -274,26 +274,26 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
/* the FDE is in the 64-bit DWARF format */
|
/* the FDE is in the 64-bit DWARF format */
|
||||||
|
|
||||||
if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0)
|
if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
*addrp = fde_end_addr = addr + u64val;
|
*addrp = fde_end_addr = addr + u64val;
|
||||||
cie_offset_addr = addr;
|
cie_offset_addr = addr;
|
||||||
|
|
||||||
if ((ret = dwarf_reads64 (as, a, &addr, &cie_offset, arg)) < 0)
|
if ((ret = dwarf_reads64 (as, a, &addr, &cie_offset, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (is_cie_id (cie_offset, base != 0))
|
if (is_cie_id (cie_offset, base != 0))
|
||||||
/* ignore CIEs (happens during linear searches) */
|
/* ignore CIEs (happens during linear searches) */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (base != 0)
|
if (base != 0)
|
||||||
cie_addr = base + cie_offset;
|
cie_addr = base + cie_offset;
|
||||||
else
|
else
|
||||||
/* DWARF says that the CIE_pointer in the FDE is a
|
/* DWARF says that the CIE_pointer in the FDE is a
|
||||||
.debug_frame-relative offset, but the GCC-generated .eh_frame
|
.debug_frame-relative offset, but the GCC-generated .eh_frame
|
||||||
sections instead store a "pcrelative" offset, which is just
|
sections instead store a "pcrelative" offset, which is just
|
||||||
as fine as it's self-contained. */
|
as fine as it's self-contained. */
|
||||||
cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
|
cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug (15, "looking for CIE at address %lx\n", (long) cie_addr);
|
Debug (15, "looking for CIE at address %lx\n", (long) cie_addr);
|
||||||
|
@ -306,9 +306,9 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
ip_range_encoding = dci.fde_encoding & DW_EH_PE_FORMAT_MASK;
|
ip_range_encoding = dci.fde_encoding & DW_EH_PE_FORMAT_MASK;
|
||||||
|
|
||||||
if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.fde_encoding,
|
if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.fde_encoding,
|
||||||
pi, &start_ip, arg)) < 0
|
pi, &start_ip, arg)) < 0
|
||||||
|| (ret = dwarf_read_encoded_pointer (as, a, &addr, ip_range_encoding,
|
|| (ret = dwarf_read_encoded_pointer (as, a, &addr, ip_range_encoding,
|
||||||
pi, &ip_range, arg)) < 0)
|
pi, &ip_range, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
pi->start_ip = start_ip;
|
pi->start_ip = start_ip;
|
||||||
pi->end_ip = start_ip + ip_range;
|
pi->end_ip = start_ip + ip_range;
|
||||||
|
@ -317,16 +317,16 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
if (dci.sized_augmentation)
|
if (dci.sized_augmentation)
|
||||||
{
|
{
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0)
|
if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
aug_end_addr = addr + aug_size;
|
aug_end_addr = addr + aug_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.lsda_encoding,
|
if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.lsda_encoding,
|
||||||
pi, &pi->lsda, arg)) < 0)
|
pi, &pi->lsda, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
Debug (15, "FDE covers IP 0x%lx-0x%lx, LSDA=0x%lx\n",
|
Debug (15, "FDE covers IP 0x%lx-0x%lx, LSDA=0x%lx\n",
|
||||||
(long) pi->start_ip, (long) pi->end_ip, (long) pi->lsda);
|
(long) pi->start_ip, (long) pi->end_ip, (long) pi->lsda);
|
||||||
|
|
||||||
if (need_unwind_info)
|
if (need_unwind_info)
|
||||||
{
|
{
|
||||||
|
@ -334,21 +334,21 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
pi->unwind_info_size = sizeof (dci);
|
pi->unwind_info_size = sizeof (dci);
|
||||||
pi->unwind_info = mempool_alloc (&dwarf_cie_info_pool);
|
pi->unwind_info = mempool_alloc (&dwarf_cie_info_pool);
|
||||||
if (!pi->unwind_info)
|
if (!pi->unwind_info)
|
||||||
return -UNW_ENOMEM;
|
return -UNW_ENOMEM;
|
||||||
|
|
||||||
if (dci.have_abi_marker)
|
if (dci.have_abi_marker)
|
||||||
{
|
{
|
||||||
if ((ret = dwarf_readu16 (as, a, &addr, &dci.abi, arg)) < 0
|
if ((ret = dwarf_readu16 (as, a, &addr, &dci.abi, arg)) < 0
|
||||||
|| (ret = dwarf_readu16 (as, a, &addr, &dci.tag, arg)) < 0)
|
|| (ret = dwarf_readu16 (as, a, &addr, &dci.tag, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
Debug (13, "Found ABI marker = (abi=%u, tag=%u)\n",
|
Debug (13, "Found ABI marker = (abi=%u, tag=%u)\n",
|
||||||
dci.abi, dci.tag);
|
dci.abi, dci.tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dci.sized_augmentation)
|
if (dci.sized_augmentation)
|
||||||
dci.fde_instr_start = aug_end_addr;
|
dci.fde_instr_start = aug_end_addr;
|
||||||
else
|
else
|
||||||
dci.fde_instr_start = addr;
|
dci.fde_instr_start = addr;
|
||||||
dci.fde_instr_end = fde_end_addr;
|
dci.fde_instr_end = fde_end_addr;
|
||||||
|
|
||||||
memcpy (pi->unwind_info, &dci, sizeof (dci));
|
memcpy (pi->unwind_info, &dci, sizeof (dci));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
|
Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -48,9 +48,9 @@ struct table_entry
|
||||||
|
|
||||||
static int
|
static int
|
||||||
linear_search (unw_addr_space_t as, unw_word_t ip,
|
linear_search (unw_addr_space_t as, unw_word_t ip,
|
||||||
unw_word_t eh_frame_start, unw_word_t eh_frame_end,
|
unw_word_t eh_frame_start, unw_word_t eh_frame_end,
|
||||||
unw_word_t fde_count,
|
unw_word_t fde_count,
|
||||||
unw_proc_info_t *pi, int need_unwind_info, void *arg)
|
unw_proc_info_t *pi, int need_unwind_info, void *arg)
|
||||||
{
|
{
|
||||||
unw_accessors_t *a = unw_get_accessors (unw_local_addr_space);
|
unw_accessors_t *a = unw_get_accessors (unw_local_addr_space);
|
||||||
unw_word_t i = 0, fde_addr, addr = eh_frame_start;
|
unw_word_t i = 0, fde_addr, addr = eh_frame_start;
|
||||||
|
@ -60,21 +60,21 @@ linear_search (unw_addr_space_t as, unw_word_t ip,
|
||||||
{
|
{
|
||||||
fde_addr = addr;
|
fde_addr = addr;
|
||||||
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, 0, 0, arg))
|
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, 0, 0, arg))
|
||||||
< 0)
|
< 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (ip >= pi->start_ip && ip < pi->end_ip)
|
if (ip >= pi->start_ip && ip < pi->end_ip)
|
||||||
{
|
{
|
||||||
if (!need_unwind_info)
|
if (!need_unwind_info)
|
||||||
return 1;
|
return 1;
|
||||||
addr = fde_addr;
|
addr = fde_addr;
|
||||||
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
|
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
|
||||||
need_unwind_info, 0,
|
need_unwind_info, 0,
|
||||||
arg))
|
arg))
|
||||||
< 0)
|
< 0)
|
||||||
return ret;
|
return ret;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -UNW_ENOINFO;
|
return -UNW_ENOINFO;
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local)
|
||||||
goto file_error;
|
goto file_error;
|
||||||
|
|
||||||
Debug (4, "loading string table of size %zd\n",
|
Debug (4, "loading string table of size %zd\n",
|
||||||
sec_hdrs[shstrndx].sh_size);
|
sec_hdrs[shstrndx].sh_size);
|
||||||
stringtab = malloc (sec_hdrs[shstrndx].sh_size);
|
stringtab = malloc (sec_hdrs[shstrndx].sh_size);
|
||||||
fseek (f, sec_hdrs[shstrndx].sh_offset, SEEK_SET);
|
fseek (f, sec_hdrs[shstrndx].sh_offset, SEEK_SET);
|
||||||
if (fread (stringtab, 1, sec_hdrs[shstrndx].sh_size, f) != sec_hdrs[shstrndx].sh_size)
|
if (fread (stringtab, 1, sec_hdrs[shstrndx].sh_size, f) != sec_hdrs[shstrndx].sh_size)
|
||||||
|
@ -136,28 +136,28 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local)
|
||||||
|
|
||||||
if (strcmp (secname, ".debug_frame") == 0)
|
if (strcmp (secname, ".debug_frame") == 0)
|
||||||
{
|
{
|
||||||
*bufsize = sec_hdrs[i].sh_size;
|
*bufsize = sec_hdrs[i].sh_size;
|
||||||
*buf = malloc (*bufsize);
|
*buf = malloc (*bufsize);
|
||||||
|
|
||||||
fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
|
fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
|
||||||
if (fread (*buf, 1, *bufsize, f) != *bufsize)
|
if (fread (*buf, 1, *bufsize, f) != *bufsize)
|
||||||
goto file_error;
|
goto file_error;
|
||||||
|
|
||||||
Debug (4, "read %zd bytes of .debug_frame from offset %zd\n",
|
Debug (4, "read %zd bytes of .debug_frame from offset %zd\n",
|
||||||
*bufsize, sec_hdrs[i].sh_offset);
|
*bufsize, sec_hdrs[i].sh_offset);
|
||||||
}
|
}
|
||||||
else if (strcmp (secname, ".gnu_debuglink") == 0)
|
else if (strcmp (secname, ".gnu_debuglink") == 0)
|
||||||
{
|
{
|
||||||
linksize = sec_hdrs[i].sh_size;
|
linksize = sec_hdrs[i].sh_size;
|
||||||
linkbuf = malloc (linksize);
|
linkbuf = malloc (linksize);
|
||||||
|
|
||||||
fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
|
fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
|
||||||
if (fread (linkbuf, 1, linksize, f) != linksize)
|
if (fread (linkbuf, 1, linksize, f) != linksize)
|
||||||
goto file_error;
|
goto file_error;
|
||||||
|
|
||||||
Debug (4, "read %zd bytes of .gnu_debuglink from offset %zd\n",
|
Debug (4, "read %zd bytes of .gnu_debuglink from offset %zd\n",
|
||||||
linksize, sec_hdrs[i].sh_offset);
|
linksize, sec_hdrs[i].sh_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free (stringtab);
|
free (stringtab);
|
||||||
|
@ -181,16 +181,16 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local)
|
||||||
/* XXX: Don't bother with the checksum; just search for the file. */
|
/* XXX: Don't bother with the checksum; just search for the file. */
|
||||||
basedir = malloc (strlen (file) + 1);
|
basedir = malloc (strlen (file) + 1);
|
||||||
newname = malloc (strlen (linkbuf) + strlen (debugdir)
|
newname = malloc (strlen (linkbuf) + strlen (debugdir)
|
||||||
+ strlen (file) + 9);
|
+ strlen (file) + 9);
|
||||||
|
|
||||||
p = strrchr (file, '/');
|
p = strrchr (file, '/');
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
{
|
{
|
||||||
memcpy (basedir, file, p - file);
|
memcpy (basedir, file, p - file);
|
||||||
basedir[p - file] = '\0';
|
basedir[p - file] = '\0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
basedir[0] = 0;
|
basedir[0] = 0;
|
||||||
|
|
||||||
strcpy (newname, basedir);
|
strcpy (newname, basedir);
|
||||||
strcat (newname, "/");
|
strcat (newname, "/");
|
||||||
|
@ -198,21 +198,21 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local)
|
||||||
ret = load_debug_frame (newname, buf, bufsize, -1);
|
ret = load_debug_frame (newname, buf, bufsize, -1);
|
||||||
|
|
||||||
if (ret == 1)
|
if (ret == 1)
|
||||||
{
|
{
|
||||||
strcpy (newname, basedir);
|
strcpy (newname, basedir);
|
||||||
strcat (newname, "/.debug/");
|
strcat (newname, "/.debug/");
|
||||||
strcat (newname, linkbuf);
|
strcat (newname, linkbuf);
|
||||||
ret = load_debug_frame (newname, buf, bufsize, -1);
|
ret = load_debug_frame (newname, buf, bufsize, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 1 && is_local == 1)
|
if (ret == 1 && is_local == 1)
|
||||||
{
|
{
|
||||||
strcpy (newname, debugdir);
|
strcpy (newname, debugdir);
|
||||||
strcat (newname, basedir);
|
strcat (newname, basedir);
|
||||||
strcat (newname, "/");
|
strcat (newname, "/");
|
||||||
strcat (newname, linkbuf);
|
strcat (newname, linkbuf);
|
||||||
ret = load_debug_frame (newname, buf, bufsize, -1);
|
ret = load_debug_frame (newname, buf, bufsize, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
free (basedir);
|
free (basedir);
|
||||||
free (newname);
|
free (newname);
|
||||||
|
@ -248,14 +248,14 @@ find_binary_for_address (unw_word_t ip, char *name, size_t name_size)
|
||||||
while (maps_next (&mi, &segbase, &hi, &mapoff))
|
while (maps_next (&mi, &segbase, &hi, &mapoff))
|
||||||
if (ip >= segbase && ip < hi)
|
if (ip >= segbase && ip < hi)
|
||||||
{
|
{
|
||||||
size_t len = strlen (mi.path);
|
size_t len = strlen (mi.path);
|
||||||
|
|
||||||
if (len + 1 <= name_size)
|
if (len + 1 <= name_size)
|
||||||
{
|
{
|
||||||
memcpy (name, mi.path, len + 1);
|
memcpy (name, mi.path, len + 1);
|
||||||
found = 1;
|
found = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
maps_close (&mi);
|
maps_close (&mi);
|
||||||
return !found;
|
return !found;
|
||||||
|
@ -269,7 +269,7 @@ find_binary_for_address (unw_word_t ip, char *name, size_t name_size)
|
||||||
|
|
||||||
static struct unw_debug_frame_list *
|
static struct unw_debug_frame_list *
|
||||||
locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
|
locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
|
||||||
unw_word_t start, unw_word_t end)
|
unw_word_t start, unw_word_t end)
|
||||||
{
|
{
|
||||||
struct unw_debug_frame_list *w, *fdesc = 0;
|
struct unw_debug_frame_list *w, *fdesc = 0;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
@ -284,7 +284,7 @@ locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
|
||||||
{
|
{
|
||||||
Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end);
|
Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end);
|
||||||
if (addr >= w->start && addr < w->end)
|
if (addr >= w->start && addr < w->end)
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the object name we receive is blank, there's still a chance of locating
|
/* If the object name we receive is blank, there's still a chance of locating
|
||||||
|
@ -295,10 +295,10 @@ locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
|
||||||
err = find_binary_for_address (addr, name, sizeof(path));
|
err = find_binary_for_address (addr, name, sizeof(path));
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n",
|
Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n",
|
||||||
(uint64_t) addr);
|
(uint64_t) addr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
name = (char*) dlname;
|
name = (char*) dlname;
|
||||||
|
@ -331,7 +331,7 @@ struct debug_frame_tab
|
||||||
|
|
||||||
static void
|
static void
|
||||||
debug_frame_tab_append (struct debug_frame_tab *tab,
|
debug_frame_tab_append (struct debug_frame_tab *tab,
|
||||||
unw_word_t fde_offset, unw_word_t start_ip)
|
unw_word_t fde_offset, unw_word_t start_ip)
|
||||||
{
|
{
|
||||||
unsigned int length = tab->length;
|
unsigned int length = tab->length;
|
||||||
|
|
||||||
|
@ -372,8 +372,8 @@ debug_frame_tab_compare (const void *a, const void *b)
|
||||||
|
|
||||||
PROTECTED int
|
PROTECTED int
|
||||||
dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
|
dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
|
||||||
unw_word_t segbase, const char* obj_name,
|
unw_word_t segbase, const char* obj_name,
|
||||||
unw_word_t start, unw_word_t end)
|
unw_word_t start, unw_word_t end)
|
||||||
{
|
{
|
||||||
unw_dyn_info_t *di;
|
unw_dyn_info_t *di;
|
||||||
struct unw_debug_frame_list *fdesc = 0;
|
struct unw_debug_frame_list *fdesc = 0;
|
||||||
|
@ -546,11 +546,11 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||||
|
|
||||||
/* Make sure struct dl_phdr_info is at least as big as we need. */
|
/* Make sure struct dl_phdr_info is at least as big as we need. */
|
||||||
if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
|
if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
|
||||||
+ sizeof (info->dlpi_phnum))
|
+ sizeof (info->dlpi_phnum))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
Debug (15, "checking %s, base=0x%lx)\n",
|
Debug (15, "checking %s, base=0x%lx)\n",
|
||||||
info->dlpi_name, (long) info->dlpi_addr);
|
info->dlpi_name, (long) info->dlpi_addr);
|
||||||
|
|
||||||
phdr = info->dlpi_phdr;
|
phdr = info->dlpi_phdr;
|
||||||
load_base = info->dlpi_addr;
|
load_base = info->dlpi_addr;
|
||||||
|
@ -563,19 +563,19 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||||
for (n = info->dlpi_phnum; --n >= 0; phdr++)
|
for (n = info->dlpi_phnum; --n >= 0; phdr++)
|
||||||
{
|
{
|
||||||
if (phdr->p_type == PT_LOAD)
|
if (phdr->p_type == PT_LOAD)
|
||||||
{
|
{
|
||||||
Elf_W(Addr) vaddr = phdr->p_vaddr + load_base;
|
Elf_W(Addr) vaddr = phdr->p_vaddr + load_base;
|
||||||
|
|
||||||
if (ip >= vaddr && ip < vaddr + phdr->p_memsz)
|
if (ip >= vaddr && ip < vaddr + phdr->p_memsz)
|
||||||
p_text = phdr;
|
p_text = phdr;
|
||||||
|
|
||||||
if (vaddr + phdr->p_filesz > max_load_addr)
|
if (vaddr + phdr->p_filesz > max_load_addr)
|
||||||
max_load_addr = vaddr + phdr->p_filesz;
|
max_load_addr = vaddr + phdr->p_filesz;
|
||||||
}
|
}
|
||||||
else if (phdr->p_type == PT_GNU_EH_FRAME)
|
else if (phdr->p_type == PT_GNU_EH_FRAME)
|
||||||
p_eh_hdr = phdr;
|
p_eh_hdr = phdr;
|
||||||
else if (phdr->p_type == PT_DYNAMIC)
|
else if (phdr->p_type == PT_DYNAMIC)
|
||||||
p_dynamic = phdr;
|
p_dynamic = phdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p_text)
|
if (!p_text)
|
||||||
|
@ -584,97 +584,97 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||||
if (p_eh_hdr)
|
if (p_eh_hdr)
|
||||||
{
|
{
|
||||||
if (p_dynamic)
|
if (p_dynamic)
|
||||||
{
|
{
|
||||||
/* For dynamicly linked executables and shared libraries,
|
/* For dynamicly linked executables and shared libraries,
|
||||||
DT_PLTGOT is the value that data-relative addresses are
|
DT_PLTGOT is the value that data-relative addresses are
|
||||||
relative to for that object. We call this the "gp". */
|
relative to for that object. We call this the "gp". */
|
||||||
Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base);
|
Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base);
|
||||||
for (; dyn->d_tag != DT_NULL; ++dyn)
|
for (; dyn->d_tag != DT_NULL; ++dyn)
|
||||||
if (dyn->d_tag == DT_PLTGOT)
|
if (dyn->d_tag == DT_PLTGOT)
|
||||||
{
|
{
|
||||||
/* Assume that _DYNAMIC is writable and GLIBC has
|
/* Assume that _DYNAMIC is writable and GLIBC has
|
||||||
relocated it (true for x86 at least). */
|
relocated it (true for x86 at least). */
|
||||||
di->gp = dyn->d_un.d_ptr;
|
di->gp = dyn->d_un.d_ptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Otherwise this is a static executable with no _DYNAMIC. Assume
|
/* Otherwise this is a static executable with no _DYNAMIC. Assume
|
||||||
that data-relative addresses are relative to 0, i.e.,
|
that data-relative addresses are relative to 0, i.e.,
|
||||||
absolute. */
|
absolute. */
|
||||||
di->gp = 0;
|
di->gp = 0;
|
||||||
pi->gp = di->gp;
|
pi->gp = di->gp;
|
||||||
|
|
||||||
hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base);
|
hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base);
|
||||||
if (hdr->version != DW_EH_VERSION)
|
if (hdr->version != DW_EH_VERSION)
|
||||||
{
|
{
|
||||||
Debug (1, "table `%s' has unexpected version %d\n",
|
Debug (1, "table `%s' has unexpected version %d\n",
|
||||||
info->dlpi_name, hdr->version);
|
info->dlpi_name, hdr->version);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
a = unw_get_accessors (unw_local_addr_space);
|
a = unw_get_accessors (unw_local_addr_space);
|
||||||
addr = (unw_word_t) (uintptr_t) (hdr + 1);
|
addr = (unw_word_t) (uintptr_t) (hdr + 1);
|
||||||
|
|
||||||
/* (Optionally) read eh_frame_ptr: */
|
/* (Optionally) read eh_frame_ptr: */
|
||||||
if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
|
if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
|
||||||
&addr, hdr->eh_frame_ptr_enc, pi,
|
&addr, hdr->eh_frame_ptr_enc, pi,
|
||||||
&eh_frame_start, NULL)) < 0)
|
&eh_frame_start, NULL)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* (Optionally) read fde_count: */
|
/* (Optionally) read fde_count: */
|
||||||
if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
|
if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
|
||||||
&addr, hdr->fde_count_enc, pi,
|
&addr, hdr->fde_count_enc, pi,
|
||||||
&fde_count, NULL)) < 0)
|
&fde_count, NULL)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
|
if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
|
||||||
{
|
{
|
||||||
/* If there is no search table or it has an unsupported
|
/* If there is no search table or it has an unsupported
|
||||||
encoding, fall back on linear search. */
|
encoding, fall back on linear search. */
|
||||||
if (hdr->table_enc == DW_EH_PE_omit)
|
if (hdr->table_enc == DW_EH_PE_omit)
|
||||||
Debug (4, "table `%s' lacks search table; doing linear search\n",
|
Debug (4, "table `%s' lacks search table; doing linear search\n",
|
||||||
info->dlpi_name);
|
info->dlpi_name);
|
||||||
else
|
else
|
||||||
Debug (4, "table `%s' has encoding 0x%x; doing linear search\n",
|
Debug (4, "table `%s' has encoding 0x%x; doing linear search\n",
|
||||||
info->dlpi_name, hdr->table_enc);
|
info->dlpi_name, hdr->table_enc);
|
||||||
|
|
||||||
eh_frame_end = max_load_addr; /* XXX can we do better? */
|
eh_frame_end = max_load_addr; /* XXX can we do better? */
|
||||||
|
|
||||||
if (hdr->fde_count_enc == DW_EH_PE_omit)
|
if (hdr->fde_count_enc == DW_EH_PE_omit)
|
||||||
fde_count = ~0UL;
|
fde_count = ~0UL;
|
||||||
if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit)
|
if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
/* XXX we know how to build a local binary search table for
|
/* XXX we know how to build a local binary search table for
|
||||||
.debug_frame, so we could do that here too. */
|
.debug_frame, so we could do that here too. */
|
||||||
cb_data->single_fde = 1;
|
cb_data->single_fde = 1;
|
||||||
found = linear_search (unw_local_addr_space, ip,
|
found = linear_search (unw_local_addr_space, ip,
|
||||||
eh_frame_start, eh_frame_end, fde_count,
|
eh_frame_start, eh_frame_end, fde_count,
|
||||||
pi, need_unwind_info, NULL);
|
pi, need_unwind_info, NULL);
|
||||||
if (found != 1)
|
if (found != 1)
|
||||||
found = 0;
|
found = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
di->format = UNW_INFO_FORMAT_REMOTE_TABLE;
|
di->format = UNW_INFO_FORMAT_REMOTE_TABLE;
|
||||||
di->start_ip = p_text->p_vaddr + load_base;
|
di->start_ip = p_text->p_vaddr + load_base;
|
||||||
di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz;
|
di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz;
|
||||||
di->u.rti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name;
|
di->u.rti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name;
|
||||||
di->u.rti.table_data = addr;
|
di->u.rti.table_data = addr;
|
||||||
assert (sizeof (struct table_entry) % sizeof (unw_word_t) == 0);
|
assert (sizeof (struct table_entry) % sizeof (unw_word_t) == 0);
|
||||||
di->u.rti.table_len = (fde_count * sizeof (struct table_entry)
|
di->u.rti.table_len = (fde_count * sizeof (struct table_entry)
|
||||||
/ sizeof (unw_word_t));
|
/ sizeof (unw_word_t));
|
||||||
/* For the binary-search table in the eh_frame_hdr, data-relative
|
/* For the binary-search table in the eh_frame_hdr, data-relative
|
||||||
means relative to the start of that section... */
|
means relative to the start of that section... */
|
||||||
di->u.rti.segbase = (unw_word_t) (uintptr_t) hdr;
|
di->u.rti.segbase = (unw_word_t) (uintptr_t) hdr;
|
||||||
|
|
||||||
found = 1;
|
found = 1;
|
||||||
Debug (15, "found table `%s': segbase=0x%lx, len=%lu, gp=0x%lx, "
|
Debug (15, "found table `%s': segbase=0x%lx, len=%lu, gp=0x%lx, "
|
||||||
"table_data=0x%lx\n", (char *) (uintptr_t) di->u.rti.name_ptr,
|
"table_data=0x%lx\n", (char *) (uintptr_t) di->u.rti.name_ptr,
|
||||||
(long) di->u.rti.segbase, (long) di->u.rti.table_len,
|
(long) di->u.rti.segbase, (long) di->u.rti.table_len,
|
||||||
(long) di->gp, (long) di->u.rti.table_data);
|
(long) di->gp, (long) di->u.rti.table_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FRAME
|
#ifdef CONFIG_DEBUG_FRAME
|
||||||
|
@ -687,20 +687,20 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||||
{
|
{
|
||||||
if (info->dlpi_phdr[n].p_type == PT_LOAD)
|
if (info->dlpi_phdr[n].p_type == PT_LOAD)
|
||||||
{
|
{
|
||||||
unw_word_t seg_start = info->dlpi_addr + info->dlpi_phdr[n].p_vaddr;
|
unw_word_t seg_start = info->dlpi_addr + info->dlpi_phdr[n].p_vaddr;
|
||||||
unw_word_t seg_end = seg_start + info->dlpi_phdr[n].p_memsz;
|
unw_word_t seg_end = seg_start + info->dlpi_phdr[n].p_memsz;
|
||||||
|
|
||||||
if (seg_start < start)
|
if (seg_start < start)
|
||||||
start = seg_start;
|
start = seg_start;
|
||||||
|
|
||||||
if (seg_end > end)
|
if (seg_end > end)
|
||||||
end = seg_end;
|
end = seg_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
found = dwarf_find_debug_frame (found, &cb_data->di_debug, ip,
|
found = dwarf_find_debug_frame (found, &cb_data->di_debug, ip,
|
||||||
info->dlpi_addr, info->dlpi_name, start,
|
info->dlpi_addr, info->dlpi_name, start,
|
||||||
end);
|
end);
|
||||||
#endif /* CONFIG_DEBUG_FRAME */
|
#endif /* CONFIG_DEBUG_FRAME */
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
|
@ -708,7 +708,7 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
|
||||||
|
|
||||||
HIDDEN int
|
HIDDEN int
|
||||||
dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||||
unw_proc_info_t *pi, int need_unwind_info, void *arg)
|
unw_proc_info_t *pi, int need_unwind_info, void *arg)
|
||||||
{
|
{
|
||||||
struct dwarf_callback_data cb_data;
|
struct dwarf_callback_data cb_data;
|
||||||
intrmask_t saved_mask;
|
intrmask_t saved_mask;
|
||||||
|
@ -740,13 +740,13 @@ dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||||
/* search the table: */
|
/* search the table: */
|
||||||
if (cb_data.di.format != -1)
|
if (cb_data.di.format != -1)
|
||||||
ret = dwarf_search_unwind_table (as, ip, &cb_data.di,
|
ret = dwarf_search_unwind_table (as, ip, &cb_data.di,
|
||||||
pi, need_unwind_info, arg);
|
pi, need_unwind_info, arg);
|
||||||
else
|
else
|
||||||
ret = -UNW_ENOINFO;
|
ret = -UNW_ENOINFO;
|
||||||
|
|
||||||
if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1)
|
if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1)
|
||||||
ret = dwarf_search_unwind_table (as, ip, &cb_data.di_debug, pi,
|
ret = dwarf_search_unwind_table (as, ip, &cb_data.di_debug, pi,
|
||||||
need_unwind_info, arg);
|
need_unwind_info, arg);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -764,12 +764,12 @@ lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip)
|
||||||
e = table + mid;
|
e = table + mid;
|
||||||
Debug (15, "e->start_ip_offset = %lx\n", (long) e->start_ip_offset);
|
Debug (15, "e->start_ip_offset = %lx\n", (long) e->start_ip_offset);
|
||||||
if (rel_ip < e->start_ip_offset)
|
if (rel_ip < e->start_ip_offset)
|
||||||
hi = mid;
|
hi = mid;
|
||||||
else
|
else
|
||||||
lo = mid + 1;
|
lo = mid + 1;
|
||||||
}
|
}
|
||||||
if (hi <= 0)
|
if (hi <= 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
e = table + hi - 1;
|
e = table + hi - 1;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -783,8 +783,8 @@ lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip)
|
||||||
occurred reading remote memory. */
|
occurred reading remote memory. */
|
||||||
static int
|
static int
|
||||||
remote_lookup (unw_addr_space_t as,
|
remote_lookup (unw_addr_space_t as,
|
||||||
unw_word_t table, size_t table_size, int32_t rel_ip,
|
unw_word_t table, size_t table_size, int32_t rel_ip,
|
||||||
struct table_entry *e, void *arg)
|
struct table_entry *e, void *arg)
|
||||||
{
|
{
|
||||||
unsigned long table_len = table_size / sizeof (struct table_entry);
|
unsigned long table_len = table_size / sizeof (struct table_entry);
|
||||||
unw_accessors_t *a = unw_get_accessors (as);
|
unw_accessors_t *a = unw_get_accessors (as);
|
||||||
|
@ -799,12 +799,12 @@ remote_lookup (unw_addr_space_t as,
|
||||||
mid = (lo + hi) / 2;
|
mid = (lo + hi) / 2;
|
||||||
e_addr = table + mid * sizeof (struct table_entry);
|
e_addr = table + mid * sizeof (struct table_entry);
|
||||||
if ((ret = dwarf_reads32 (as, a, &e_addr, &start, arg)) < 0)
|
if ((ret = dwarf_reads32 (as, a, &e_addr, &start, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (rel_ip < start)
|
if (rel_ip < start)
|
||||||
hi = mid;
|
hi = mid;
|
||||||
else
|
else
|
||||||
lo = mid + 1;
|
lo = mid + 1;
|
||||||
}
|
}
|
||||||
if (hi <= 0)
|
if (hi <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -819,8 +819,8 @@ remote_lookup (unw_addr_space_t as,
|
||||||
|
|
||||||
PROTECTED int
|
PROTECTED int
|
||||||
dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||||
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||||
int need_unwind_info, void *arg)
|
int need_unwind_info, void *arg)
|
||||||
{
|
{
|
||||||
const struct table_entry *e = NULL, *table;
|
const struct table_entry *e = NULL, *table;
|
||||||
unw_word_t segbase = 0, fde_addr;
|
unw_word_t segbase = 0, fde_addr;
|
||||||
|
@ -836,7 +836,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||||
assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE);
|
assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE);
|
||||||
#else
|
#else
|
||||||
assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE
|
assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE
|
||||||
|| di->format == UNW_INFO_FORMAT_TABLE);
|
|| di->format == UNW_INFO_FORMAT_TABLE);
|
||||||
#endif
|
#endif
|
||||||
assert (ip >= di->start_ip && ip < di->end_ip);
|
assert (ip >= di->start_ip && ip < di->end_ip);
|
||||||
|
|
||||||
|
@ -876,34 +876,34 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||||
#ifndef UNW_LOCAL_ONLY
|
#ifndef UNW_LOCAL_ONLY
|
||||||
segbase = di->u.rti.segbase;
|
segbase = di->u.rti.segbase;
|
||||||
if ((ret = remote_lookup (as, (uintptr_t) table, table_len,
|
if ((ret = remote_lookup (as, (uintptr_t) table, table_len,
|
||||||
ip - segbase, &ent, arg)) < 0)
|
ip - segbase, &ent, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if (ret)
|
if (ret)
|
||||||
e = &ent;
|
e = &ent;
|
||||||
else
|
else
|
||||||
e = NULL; /* no info found */
|
e = NULL; /* no info found */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (!e)
|
if (!e)
|
||||||
{
|
{
|
||||||
Debug (1, "IP %lx inside range %lx-%lx, but no explicit unwind info found\n",
|
Debug (1, "IP %lx inside range %lx-%lx, but no explicit unwind info found\n",
|
||||||
(long) ip, (long) di->start_ip, (long) di->end_ip);
|
(long) ip, (long) di->start_ip, (long) di->end_ip);
|
||||||
/* IP is inside this table's range, but there is no explicit
|
/* IP is inside this table's range, but there is no explicit
|
||||||
unwind info. */
|
unwind info. */
|
||||||
return -UNW_ENOINFO;
|
return -UNW_ENOINFO;
|
||||||
}
|
}
|
||||||
Debug (15, "ip=0x%lx, start_ip=0x%lx\n",
|
Debug (15, "ip=0x%lx, start_ip=0x%lx\n",
|
||||||
(long) ip, (long) (e->start_ip_offset));
|
(long) ip, (long) (e->start_ip_offset));
|
||||||
if (debug_frame_base)
|
if (debug_frame_base)
|
||||||
fde_addr = e->fde_offset + debug_frame_base;
|
fde_addr = e->fde_offset + debug_frame_base;
|
||||||
else
|
else
|
||||||
fde_addr = e->fde_offset + segbase;
|
fde_addr = e->fde_offset + segbase;
|
||||||
Debug (1, "e->fde_offset = %lx, segbase = %lx, debug_frame_base = %lx, "
|
Debug (1, "e->fde_offset = %lx, segbase = %lx, debug_frame_base = %lx, "
|
||||||
"fde_addr = %lx\n", (long) e->fde_offset, (long) segbase,
|
"fde_addr = %lx\n", (long) e->fde_offset, (long) segbase,
|
||||||
(long) debug_frame_base, (long) fde_addr);
|
(long) debug_frame_base, (long) fde_addr);
|
||||||
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi,
|
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi,
|
||||||
need_unwind_info,
|
need_unwind_info,
|
||||||
debug_frame_base, arg)) < 0)
|
debug_frame_base, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* .debug_frame uses an absolute encoding that does not know about any
|
/* .debug_frame uses an absolute encoding that does not know about any
|
||||||
|
@ -924,5 +924,5 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||||
HIDDEN void
|
HIDDEN void
|
||||||
dwarf_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
|
dwarf_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
|
||||||
{
|
{
|
||||||
return; /* always a nop */
|
return; /* always a nop */
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2003-2004 Hewlett-Packard Co
|
Copyright (C) 2003-2004 Hewlett-Packard Co
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
int
|
int
|
||||||
dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
|
dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
|
||||||
char *path, unw_word_t segbase, unw_word_t mapoff,
|
char *path, unw_word_t segbase, unw_word_t mapoff,
|
||||||
unw_word_t ip)
|
unw_word_t ip)
|
||||||
{
|
{
|
||||||
Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL;
|
Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL;
|
||||||
unw_word_t addr, eh_frame_start, fde_count, load_base;
|
unw_word_t addr, eh_frame_start, fde_count, load_base;
|
||||||
|
@ -63,37 +63,37 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
|
||||||
for (i = 0; i < ehdr->e_phnum; ++i)
|
for (i = 0; i < ehdr->e_phnum; ++i)
|
||||||
{
|
{
|
||||||
switch (phdr[i].p_type)
|
switch (phdr[i].p_type)
|
||||||
{
|
{
|
||||||
case PT_LOAD:
|
case PT_LOAD:
|
||||||
if (phdr[i].p_vaddr < start_ip)
|
if (phdr[i].p_vaddr < start_ip)
|
||||||
start_ip = phdr[i].p_vaddr;
|
start_ip = phdr[i].p_vaddr;
|
||||||
|
|
||||||
if (phdr[i].p_vaddr + phdr[i].p_memsz > end_ip)
|
if (phdr[i].p_vaddr + phdr[i].p_memsz > end_ip)
|
||||||
end_ip = phdr[i].p_vaddr + phdr[i].p_memsz;
|
end_ip = phdr[i].p_vaddr + phdr[i].p_memsz;
|
||||||
|
|
||||||
if (phdr[i].p_offset == mapoff)
|
if (phdr[i].p_offset == mapoff)
|
||||||
ptxt = phdr + i;
|
ptxt = phdr + i;
|
||||||
if ((uintptr_t) edi->ei.image + phdr->p_filesz > max_load_addr)
|
if ((uintptr_t) edi->ei.image + phdr->p_filesz > max_load_addr)
|
||||||
max_load_addr = (uintptr_t) edi->ei.image + phdr->p_filesz;
|
max_load_addr = (uintptr_t) edi->ei.image + phdr->p_filesz;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_GNU_EH_FRAME:
|
case PT_GNU_EH_FRAME:
|
||||||
peh_hdr = phdr + i;
|
peh_hdr = phdr + i;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_DYNAMIC:
|
case PT_DYNAMIC:
|
||||||
pdyn = phdr + i;
|
pdyn = phdr + i;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if UNW_TARGET_ARM
|
#if UNW_TARGET_ARM
|
||||||
case PT_ARM_EXIDX:
|
case PT_ARM_EXIDX:
|
||||||
parm_exidx = phdr + i;
|
parm_exidx = phdr + i;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ptxt)
|
if (!ptxt)
|
||||||
|
@ -106,85 +106,85 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
|
||||||
if (peh_hdr)
|
if (peh_hdr)
|
||||||
{
|
{
|
||||||
if (pdyn)
|
if (pdyn)
|
||||||
{
|
{
|
||||||
/* For dynamicly linked executables and shared libraries,
|
/* For dynamicly linked executables and shared libraries,
|
||||||
DT_PLTGOT is the value that data-relative addresses are
|
DT_PLTGOT is the value that data-relative addresses are
|
||||||
relative to for that object. We call this the "gp". */
|
relative to for that object. We call this the "gp". */
|
||||||
Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(pdyn->p_offset
|
Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(pdyn->p_offset
|
||||||
+ (char *) edi->ei.image);
|
+ (char *) edi->ei.image);
|
||||||
for (; dyn->d_tag != DT_NULL; ++dyn)
|
for (; dyn->d_tag != DT_NULL; ++dyn)
|
||||||
if (dyn->d_tag == DT_PLTGOT)
|
if (dyn->d_tag == DT_PLTGOT)
|
||||||
{
|
{
|
||||||
/* Assume that _DYNAMIC is writable and GLIBC has
|
/* Assume that _DYNAMIC is writable and GLIBC has
|
||||||
relocated it (true for x86 at least). */
|
relocated it (true for x86 at least). */
|
||||||
edi->di_cache.gp = dyn->d_un.d_ptr;
|
edi->di_cache.gp = dyn->d_un.d_ptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Otherwise this is a static executable with no _DYNAMIC. Assume
|
/* Otherwise this is a static executable with no _DYNAMIC. Assume
|
||||||
that data-relative addresses are relative to 0, i.e.,
|
that data-relative addresses are relative to 0, i.e.,
|
||||||
absolute. */
|
absolute. */
|
||||||
edi->di_cache.gp = 0;
|
edi->di_cache.gp = 0;
|
||||||
|
|
||||||
hdr = (struct dwarf_eh_frame_hdr *) (peh_hdr->p_offset
|
hdr = (struct dwarf_eh_frame_hdr *) (peh_hdr->p_offset
|
||||||
+ (char *) edi->ei.image);
|
+ (char *) edi->ei.image);
|
||||||
if (hdr->version != DW_EH_VERSION)
|
if (hdr->version != DW_EH_VERSION)
|
||||||
{
|
{
|
||||||
Debug (1, "table `%s' has unexpected version %d\n",
|
Debug (1, "table `%s' has unexpected version %d\n",
|
||||||
path, hdr->version);
|
path, hdr->version);
|
||||||
return -UNW_ENOINFO;
|
return -UNW_ENOINFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
a = unw_get_accessors (unw_local_addr_space);
|
a = unw_get_accessors (unw_local_addr_space);
|
||||||
addr = (unw_word_t) (hdr + 1);
|
addr = (unw_word_t) (hdr + 1);
|
||||||
|
|
||||||
/* Fill in a dummy proc_info structure. We just need to fill in
|
/* Fill in a dummy proc_info structure. We just need to fill in
|
||||||
enough to ensure that dwarf_read_encoded_pointer() can do it's
|
enough to ensure that dwarf_read_encoded_pointer() can do it's
|
||||||
job. Since we don't have a procedure-context at this point, all
|
job. Since we don't have a procedure-context at this point, all
|
||||||
we have to do is fill in the global-pointer. */
|
we have to do is fill in the global-pointer. */
|
||||||
memset (&pi, 0, sizeof (pi));
|
memset (&pi, 0, sizeof (pi));
|
||||||
pi.gp = edi->di_cache.gp;
|
pi.gp = edi->di_cache.gp;
|
||||||
|
|
||||||
/* (Optionally) read eh_frame_ptr: */
|
/* (Optionally) read eh_frame_ptr: */
|
||||||
if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
|
if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
|
||||||
&addr, hdr->eh_frame_ptr_enc, &pi,
|
&addr, hdr->eh_frame_ptr_enc, &pi,
|
||||||
&eh_frame_start, NULL)) < 0)
|
&eh_frame_start, NULL)) < 0)
|
||||||
return -UNW_ENOINFO;
|
return -UNW_ENOINFO;
|
||||||
|
|
||||||
/* (Optionally) read fde_count: */
|
/* (Optionally) read fde_count: */
|
||||||
if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
|
if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
|
||||||
&addr, hdr->fde_count_enc, &pi,
|
&addr, hdr->fde_count_enc, &pi,
|
||||||
&fde_count, NULL)) < 0)
|
&fde_count, NULL)) < 0)
|
||||||
return -UNW_ENOINFO;
|
return -UNW_ENOINFO;
|
||||||
|
|
||||||
if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
|
if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
abort ();
|
abort ();
|
||||||
#else
|
#else
|
||||||
unw_word_t eh_frame_end;
|
unw_word_t eh_frame_end;
|
||||||
|
|
||||||
/* If there is no search table or it has an unsupported
|
/* If there is no search table or it has an unsupported
|
||||||
encoding, fall back on linear search. */
|
encoding, fall back on linear search. */
|
||||||
if (hdr->table_enc == DW_EH_PE_omit)
|
if (hdr->table_enc == DW_EH_PE_omit)
|
||||||
Debug (4, "EH lacks search table; doing linear search\n");
|
Debug (4, "EH lacks search table; doing linear search\n");
|
||||||
else
|
else
|
||||||
Debug (4, "EH table has encoding 0x%x; doing linear search\n",
|
Debug (4, "EH table has encoding 0x%x; doing linear search\n",
|
||||||
hdr->table_enc);
|
hdr->table_enc);
|
||||||
|
|
||||||
eh_frame_end = max_load_addr; /* XXX can we do better? */
|
eh_frame_end = max_load_addr; /* XXX can we do better? */
|
||||||
|
|
||||||
if (hdr->fde_count_enc == DW_EH_PE_omit)
|
if (hdr->fde_count_enc == DW_EH_PE_omit)
|
||||||
fde_count = ~0UL;
|
fde_count = ~0UL;
|
||||||
if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit)
|
if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
return linear_search (unw_local_addr_space, ip,
|
return linear_search (unw_local_addr_space, ip,
|
||||||
eh_frame_start, eh_frame_end, fde_count,
|
eh_frame_start, eh_frame_end, fde_count,
|
||||||
pi, need_unwind_info, NULL);
|
pi, need_unwind_info, NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
edi->di_cache.start_ip = start_ip;
|
edi->di_cache.start_ip = start_ip;
|
||||||
edi->di_cache.end_ip = end_ip;
|
edi->di_cache.end_ip = end_ip;
|
||||||
|
@ -193,14 +193,14 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
|
||||||
/* two 32-bit values (ip_offset/fde_offset) per table-entry: */
|
/* two 32-bit values (ip_offset/fde_offset) per table-entry: */
|
||||||
edi->di_cache.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t);
|
edi->di_cache.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t);
|
||||||
edi->di_cache.u.rti.table_data = ((load_base + peh_hdr->p_vaddr)
|
edi->di_cache.u.rti.table_data = ((load_base + peh_hdr->p_vaddr)
|
||||||
+ (addr - (unw_word_t) edi->ei.image
|
+ (addr - (unw_word_t) edi->ei.image
|
||||||
- peh_hdr->p_offset));
|
- peh_hdr->p_offset));
|
||||||
|
|
||||||
/* For the binary-search table in the eh_frame_hdr, data-relative
|
/* For the binary-search table in the eh_frame_hdr, data-relative
|
||||||
means relative to the start of that section... */
|
means relative to the start of that section... */
|
||||||
edi->di_cache.u.rti.segbase = ((load_base + peh_hdr->p_vaddr)
|
edi->di_cache.u.rti.segbase = ((load_base + peh_hdr->p_vaddr)
|
||||||
+ ((unw_word_t) hdr - (unw_word_t) edi->ei.image
|
+ ((unw_word_t) hdr - (unw_word_t) edi->ei.image
|
||||||
- peh_hdr->p_offset));
|
- peh_hdr->p_offset));
|
||||||
found = 1;
|
found = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
|
||||||
#ifdef CONFIG_DEBUG_FRAME
|
#ifdef CONFIG_DEBUG_FRAME
|
||||||
/* Try .debug_frame. */
|
/* Try .debug_frame. */
|
||||||
found = dwarf_find_debug_frame (found, &edi->di_debug, ip, load_base, path,
|
found = dwarf_find_debug_frame (found, &edi->di_debug, ip, load_base, path,
|
||||||
start_ip, end_ip);
|
start_ip, end_ip);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
|
Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -27,12 +27,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#include "dwarf_i.h"
|
#include "dwarf_i.h"
|
||||||
#include "libunwind_i.h"
|
#include "libunwind_i.h"
|
||||||
|
|
||||||
#define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool))
|
#define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool))
|
||||||
#define free_reg_state(rs) (mempool_free (&dwarf_reg_state_pool, rs))
|
#define free_reg_state(rs) (mempool_free (&dwarf_reg_state_pool, rs))
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
unw_word_t *valp, void *arg)
|
unw_word_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
set_reg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where,
|
set_reg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where,
|
||||||
unw_word_t val)
|
unw_word_t val)
|
||||||
{
|
{
|
||||||
sr->rs_current.reg[regnum].where = where;
|
sr->rs_current.reg[regnum].where = where;
|
||||||
sr->rs_current.reg[regnum].val = val;
|
sr->rs_current.reg[regnum].val = val;
|
||||||
|
@ -58,8 +58,8 @@ set_reg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where,
|
||||||
/* Run a CFI program to update the register state. */
|
/* Run a CFI program to update the register state. */
|
||||||
static int
|
static int
|
||||||
run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
|
run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
|
||||||
unw_word_t ip, unw_word_t *addr, unw_word_t end_addr,
|
unw_word_t ip, unw_word_t *addr, unw_word_t end_addr,
|
||||||
struct dwarf_cie_info *dci)
|
struct dwarf_cie_info *dci)
|
||||||
{
|
{
|
||||||
unw_word_t curr_ip, operand = 0, regnum, val, len, fde_encoding;
|
unw_word_t curr_ip, operand = 0, regnum, val, len, fde_encoding;
|
||||||
dwarf_reg_state_t *rs_stack = NULL, *new_rs, *old_rs;
|
dwarf_reg_state_t *rs_stack = NULL, *new_rs, *old_rs;
|
||||||
|
@ -88,251 +88,251 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
|
||||||
while (curr_ip <= ip && *addr < end_addr)
|
while (curr_ip <= ip && *addr < end_addr)
|
||||||
{
|
{
|
||||||
if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (op & DWARF_CFA_OPCODE_MASK)
|
if (op & DWARF_CFA_OPCODE_MASK)
|
||||||
{
|
{
|
||||||
operand = op & DWARF_CFA_OPERAND_MASK;
|
operand = op & DWARF_CFA_OPERAND_MASK;
|
||||||
op &= ~DWARF_CFA_OPERAND_MASK;
|
op &= ~DWARF_CFA_OPERAND_MASK;
|
||||||
}
|
}
|
||||||
switch ((dwarf_cfa_t) op)
|
switch ((dwarf_cfa_t) op)
|
||||||
{
|
{
|
||||||
case DW_CFA_advance_loc:
|
case DW_CFA_advance_loc:
|
||||||
curr_ip += operand * dci->code_align;
|
curr_ip += operand * dci->code_align;
|
||||||
Debug (15, "CFA_advance_loc to 0x%lx\n", (long) curr_ip);
|
Debug (15, "CFA_advance_loc to 0x%lx\n", (long) curr_ip);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_advance_loc1:
|
case DW_CFA_advance_loc1:
|
||||||
if ((ret = dwarf_readu8 (as, a, addr, &u8, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, addr, &u8, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
curr_ip += u8 * dci->code_align;
|
curr_ip += u8 * dci->code_align;
|
||||||
Debug (15, "CFA_advance_loc1 to 0x%lx\n", (long) curr_ip);
|
Debug (15, "CFA_advance_loc1 to 0x%lx\n", (long) curr_ip);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_advance_loc2:
|
case DW_CFA_advance_loc2:
|
||||||
if ((ret = dwarf_readu16 (as, a, addr, &u16, arg)) < 0)
|
if ((ret = dwarf_readu16 (as, a, addr, &u16, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
curr_ip += u16 * dci->code_align;
|
curr_ip += u16 * dci->code_align;
|
||||||
Debug (15, "CFA_advance_loc2 to 0x%lx\n", (long) curr_ip);
|
Debug (15, "CFA_advance_loc2 to 0x%lx\n", (long) curr_ip);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_advance_loc4:
|
case DW_CFA_advance_loc4:
|
||||||
if ((ret = dwarf_readu32 (as, a, addr, &u32, arg)) < 0)
|
if ((ret = dwarf_readu32 (as, a, addr, &u32, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
curr_ip += u32 * dci->code_align;
|
curr_ip += u32 * dci->code_align;
|
||||||
Debug (15, "CFA_advance_loc4 to 0x%lx\n", (long) curr_ip);
|
Debug (15, "CFA_advance_loc4 to 0x%lx\n", (long) curr_ip);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_MIPS_advance_loc8:
|
case DW_CFA_MIPS_advance_loc8:
|
||||||
#ifdef UNW_TARGET_MIPS
|
#ifdef UNW_TARGET_MIPS
|
||||||
{
|
{
|
||||||
uint64_t u64;
|
uint64_t u64;
|
||||||
|
|
||||||
if ((ret = dwarf_readu64 (as, a, addr, &u64, arg)) < 0)
|
if ((ret = dwarf_readu64 (as, a, addr, &u64, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
curr_ip += u64 * dci->code_align;
|
curr_ip += u64 * dci->code_align;
|
||||||
Debug (15, "CFA_MIPS_advance_loc8\n");
|
Debug (15, "CFA_MIPS_advance_loc8\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
Debug (1, "DW_CFA_MIPS_advance_loc8 on non-MIPS target\n");
|
Debug (1, "DW_CFA_MIPS_advance_loc8 on non-MIPS target\n");
|
||||||
ret = -UNW_EINVAL;
|
ret = -UNW_EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case DW_CFA_offset:
|
case DW_CFA_offset:
|
||||||
regnum = operand;
|
regnum = operand;
|
||||||
if (regnum >= DWARF_NUM_PRESERVED_REGS)
|
if (regnum >= DWARF_NUM_PRESERVED_REGS)
|
||||||
{
|
{
|
||||||
Debug (1, "Invalid register number %u in DW_cfa_OFFSET\n",
|
Debug (1, "Invalid register number %u in DW_cfa_OFFSET\n",
|
||||||
(unsigned int) regnum);
|
(unsigned int) regnum);
|
||||||
ret = -UNW_EBADREG;
|
ret = -UNW_EBADREG;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
|
if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
|
set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
|
||||||
Debug (15, "CFA_offset r%lu at cfa+0x%lx\n",
|
Debug (15, "CFA_offset r%lu at cfa+0x%lx\n",
|
||||||
(long) regnum, (long) (val * dci->data_align));
|
(long) regnum, (long) (val * dci->data_align));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_offset_extended:
|
case DW_CFA_offset_extended:
|
||||||
if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
||||||
|| ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
|
|| ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
|
set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
|
||||||
Debug (15, "CFA_offset_extended r%lu at cf+0x%lx\n",
|
Debug (15, "CFA_offset_extended r%lu at cf+0x%lx\n",
|
||||||
(long) regnum, (long) (val * dci->data_align));
|
(long) regnum, (long) (val * dci->data_align));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_offset_extended_sf:
|
case DW_CFA_offset_extended_sf:
|
||||||
if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
||||||
|| ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
|
|| ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
|
set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
|
||||||
Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n",
|
Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n",
|
||||||
(long) regnum, (long) (val * dci->data_align));
|
(long) regnum, (long) (val * dci->data_align));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_restore:
|
case DW_CFA_restore:
|
||||||
regnum = operand;
|
regnum = operand;
|
||||||
if (regnum >= DWARF_NUM_PRESERVED_REGS)
|
if (regnum >= DWARF_NUM_PRESERVED_REGS)
|
||||||
{
|
{
|
||||||
Debug (1, "Invalid register number %u in DW_CFA_restore\n",
|
Debug (1, "Invalid register number %u in DW_CFA_restore\n",
|
||||||
(unsigned int) regnum);
|
(unsigned int) regnum);
|
||||||
ret = -UNW_EINVAL;
|
ret = -UNW_EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
sr->rs_current.reg[regnum] = sr->rs_initial.reg[regnum];
|
sr->rs_current.reg[regnum] = sr->rs_initial.reg[regnum];
|
||||||
Debug (15, "CFA_restore r%lu\n", (long) regnum);
|
Debug (15, "CFA_restore r%lu\n", (long) regnum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_restore_extended:
|
case DW_CFA_restore_extended:
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, addr, ®num, arg)) < 0)
|
if ((ret = dwarf_read_uleb128 (as, a, addr, ®num, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
if (regnum >= DWARF_NUM_PRESERVED_REGS)
|
if (regnum >= DWARF_NUM_PRESERVED_REGS)
|
||||||
{
|
{
|
||||||
Debug (1, "Invalid register number %u in "
|
Debug (1, "Invalid register number %u in "
|
||||||
"DW_CFA_restore_extended\n", (unsigned int) regnum);
|
"DW_CFA_restore_extended\n", (unsigned int) regnum);
|
||||||
ret = -UNW_EINVAL;
|
ret = -UNW_EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
sr->rs_current.reg[regnum] = sr->rs_initial.reg[regnum];
|
sr->rs_current.reg[regnum] = sr->rs_initial.reg[regnum];
|
||||||
Debug (15, "CFA_restore_extended r%lu\n", (long) regnum);
|
Debug (15, "CFA_restore_extended r%lu\n", (long) regnum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_nop:
|
case DW_CFA_nop:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_set_loc:
|
case DW_CFA_set_loc:
|
||||||
fde_encoding = dci->fde_encoding;
|
fde_encoding = dci->fde_encoding;
|
||||||
if ((ret = dwarf_read_encoded_pointer (as, a, addr, fde_encoding,
|
if ((ret = dwarf_read_encoded_pointer (as, a, addr, fde_encoding,
|
||||||
&c->pi, &curr_ip,
|
&c->pi, &curr_ip,
|
||||||
arg)) < 0)
|
arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
Debug (15, "CFA_set_loc to 0x%lx\n", (long) curr_ip);
|
Debug (15, "CFA_set_loc to 0x%lx\n", (long) curr_ip);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_undefined:
|
case DW_CFA_undefined:
|
||||||
if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg (sr, regnum, DWARF_WHERE_UNDEF, 0);
|
set_reg (sr, regnum, DWARF_WHERE_UNDEF, 0);
|
||||||
Debug (15, "CFA_undefined r%lu\n", (long) regnum);
|
Debug (15, "CFA_undefined r%lu\n", (long) regnum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_same_value:
|
case DW_CFA_same_value:
|
||||||
if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg (sr, regnum, DWARF_WHERE_SAME, 0);
|
set_reg (sr, regnum, DWARF_WHERE_SAME, 0);
|
||||||
Debug (15, "CFA_same_value r%lu\n", (long) regnum);
|
Debug (15, "CFA_same_value r%lu\n", (long) regnum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_register:
|
case DW_CFA_register:
|
||||||
if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
||||||
|| ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
|
|| ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg (sr, regnum, DWARF_WHERE_REG, val);
|
set_reg (sr, regnum, DWARF_WHERE_REG, val);
|
||||||
Debug (15, "CFA_register r%lu to r%lu\n", (long) regnum, (long) val);
|
Debug (15, "CFA_register r%lu to r%lu\n", (long) regnum, (long) val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_remember_state:
|
case DW_CFA_remember_state:
|
||||||
new_rs = alloc_reg_state ();
|
new_rs = alloc_reg_state ();
|
||||||
if (!new_rs)
|
if (!new_rs)
|
||||||
{
|
{
|
||||||
Debug (1, "Out of memory in DW_CFA_remember_state\n");
|
Debug (1, "Out of memory in DW_CFA_remember_state\n");
|
||||||
ret = -UNW_ENOMEM;
|
ret = -UNW_ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (new_rs->reg, sr->rs_current.reg, sizeof (new_rs->reg));
|
memcpy (new_rs->reg, sr->rs_current.reg, sizeof (new_rs->reg));
|
||||||
new_rs->next = rs_stack;
|
new_rs->next = rs_stack;
|
||||||
rs_stack = new_rs;
|
rs_stack = new_rs;
|
||||||
Debug (15, "CFA_remember_state\n");
|
Debug (15, "CFA_remember_state\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_restore_state:
|
case DW_CFA_restore_state:
|
||||||
if (!rs_stack)
|
if (!rs_stack)
|
||||||
{
|
{
|
||||||
Debug (1, "register-state stack underflow\n");
|
Debug (1, "register-state stack underflow\n");
|
||||||
ret = -UNW_EINVAL;
|
ret = -UNW_EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
memcpy (&sr->rs_current.reg, &rs_stack->reg, sizeof (rs_stack->reg));
|
memcpy (&sr->rs_current.reg, &rs_stack->reg, sizeof (rs_stack->reg));
|
||||||
old_rs = rs_stack;
|
old_rs = rs_stack;
|
||||||
rs_stack = rs_stack->next;
|
rs_stack = rs_stack->next;
|
||||||
free_reg_state (old_rs);
|
free_reg_state (old_rs);
|
||||||
Debug (15, "CFA_restore_state\n");
|
Debug (15, "CFA_restore_state\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_def_cfa:
|
case DW_CFA_def_cfa:
|
||||||
if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
||||||
|| ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
|
|| ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
|
set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
|
||||||
set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */
|
set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */
|
||||||
Debug (15, "CFA_def_cfa r%lu+0x%lx\n", (long) regnum, (long) val);
|
Debug (15, "CFA_def_cfa r%lu+0x%lx\n", (long) regnum, (long) val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_def_cfa_sf:
|
case DW_CFA_def_cfa_sf:
|
||||||
if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
||||||
|| ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
|
|| ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
|
set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
|
||||||
set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
|
set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
|
||||||
val * dci->data_align); /* factored! */
|
val * dci->data_align); /* factored! */
|
||||||
Debug (15, "CFA_def_cfa_sf r%lu+0x%lx\n",
|
Debug (15, "CFA_def_cfa_sf r%lu+0x%lx\n",
|
||||||
(long) regnum, (long) (val * dci->data_align));
|
(long) regnum, (long) (val * dci->data_align));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_def_cfa_register:
|
case DW_CFA_def_cfa_register:
|
||||||
if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
|
set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
|
||||||
Debug (15, "CFA_def_cfa_register r%lu\n", (long) regnum);
|
Debug (15, "CFA_def_cfa_register r%lu\n", (long) regnum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_def_cfa_offset:
|
case DW_CFA_def_cfa_offset:
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
|
if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */
|
set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */
|
||||||
Debug (15, "CFA_def_cfa_offset 0x%lx\n", (long) val);
|
Debug (15, "CFA_def_cfa_offset 0x%lx\n", (long) val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_def_cfa_offset_sf:
|
case DW_CFA_def_cfa_offset_sf:
|
||||||
if ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)
|
if ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
|
set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
|
||||||
val * dci->data_align); /* factored! */
|
val * dci->data_align); /* factored! */
|
||||||
Debug (15, "CFA_def_cfa_offset_sf 0x%lx\n",
|
Debug (15, "CFA_def_cfa_offset_sf 0x%lx\n",
|
||||||
(long) (val * dci->data_align));
|
(long) (val * dci->data_align));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_def_cfa_expression:
|
case DW_CFA_def_cfa_expression:
|
||||||
/* Save the address of the DW_FORM_block for later evaluation. */
|
/* Save the address of the DW_FORM_block for later evaluation. */
|
||||||
set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_EXPR, *addr);
|
set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_EXPR, *addr);
|
||||||
|
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
|
if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
Debug (15, "CFA_def_cfa_expr @ 0x%lx [%lu bytes]\n",
|
Debug (15, "CFA_def_cfa_expr @ 0x%lx [%lu bytes]\n",
|
||||||
(long) *addr, (long) len);
|
(long) *addr, (long) len);
|
||||||
*addr += len;
|
*addr += len;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_expression:
|
case DW_CFA_expression:
|
||||||
if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* Save the address of the DW_FORM_block for later evaluation. */
|
/* Save the address of the DW_FORM_block for later evaluation. */
|
||||||
set_reg (sr, regnum, DWARF_WHERE_EXPR, *addr);
|
set_reg (sr, regnum, DWARF_WHERE_EXPR, *addr);
|
||||||
|
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
|
if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
Debug (15, "CFA_expression r%lu @ 0x%lx [%lu bytes]\n",
|
Debug (15, "CFA_expression r%lu @ 0x%lx [%lu bytes]\n",
|
||||||
(long) regnum, (long) addr, (long) len);
|
(long) regnum, (long) addr, (long) len);
|
||||||
*addr += len;
|
*addr += len;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_val_expression:
|
case DW_CFA_val_expression:
|
||||||
if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
||||||
|
@ -350,42 +350,42 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_GNU_args_size:
|
case DW_CFA_GNU_args_size:
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
|
if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
sr->args_size = val;
|
sr->args_size = val;
|
||||||
Debug (15, "CFA_GNU_args_size %lu\n", (long) val);
|
Debug (15, "CFA_GNU_args_size %lu\n", (long) val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_GNU_negative_offset_extended:
|
case DW_CFA_GNU_negative_offset_extended:
|
||||||
/* A comment in GCC says that this is obsoleted by
|
/* A comment in GCC says that this is obsoleted by
|
||||||
DW_CFA_offset_extended_sf, but that it's used by older
|
DW_CFA_offset_extended_sf, but that it's used by older
|
||||||
PowerPC code. */
|
PowerPC code. */
|
||||||
if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
|
||||||
|| ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
|
|| ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg (sr, regnum, DWARF_WHERE_CFAREL, -(val * dci->data_align));
|
set_reg (sr, regnum, DWARF_WHERE_CFAREL, -(val * dci->data_align));
|
||||||
Debug (15, "CFA_GNU_negative_offset_extended cfa+0x%lx\n",
|
Debug (15, "CFA_GNU_negative_offset_extended cfa+0x%lx\n",
|
||||||
(long) -(val * dci->data_align));
|
(long) -(val * dci->data_align));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_GNU_window_save:
|
case DW_CFA_GNU_window_save:
|
||||||
#ifdef UNW_TARGET_SPARC
|
#ifdef UNW_TARGET_SPARC
|
||||||
/* This is a special CFA to handle all 16 windowed registers
|
/* This is a special CFA to handle all 16 windowed registers
|
||||||
on SPARC. */
|
on SPARC. */
|
||||||
for (regnum = 16; regnum < 32; ++regnum)
|
for (regnum = 16; regnum < 32; ++regnum)
|
||||||
set_reg (sr, regnum, DWARF_WHERE_CFAREL,
|
set_reg (sr, regnum, DWARF_WHERE_CFAREL,
|
||||||
(regnum - 16) * sizeof (unw_word_t));
|
(regnum - 16) * sizeof (unw_word_t));
|
||||||
Debug (15, "CFA_GNU_window_save\n");
|
Debug (15, "CFA_GNU_window_save\n");
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
#endif
|
#endif
|
||||||
case DW_CFA_lo_user:
|
case DW_CFA_lo_user:
|
||||||
case DW_CFA_hi_user:
|
case DW_CFA_hi_user:
|
||||||
Debug (1, "Unexpected CFA opcode 0x%x\n", op);
|
Debug (1, "Unexpected CFA opcode 0x%x\n", op);
|
||||||
ret = -UNW_EINVAL;
|
ret = -UNW_EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
@ -430,12 +430,12 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info)
|
||||||
|
|
||||||
/* check dynamic info first --- it overrides everything else */
|
/* check dynamic info first --- it overrides everything else */
|
||||||
ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info,
|
ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info,
|
||||||
c->as_arg);
|
c->as_arg);
|
||||||
if (ret == -UNW_ENOINFO)
|
if (ret == -UNW_ENOINFO)
|
||||||
{
|
{
|
||||||
dynamic = 0;
|
dynamic = 0;
|
||||||
if ((ret = tdep_find_proc_info (c, ip, need_unwind_info)) < 0)
|
if ((ret = tdep_find_proc_info (c, ip, need_unwind_info)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->pi.format != UNW_INFO_FORMAT_DYNAMIC
|
if (c->pi.format != UNW_INFO_FORMAT_DYNAMIC
|
||||||
|
@ -496,7 +496,7 @@ parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
|
||||||
|
|
||||||
addr = dci->cie_instr_start;
|
addr = dci->cie_instr_start;
|
||||||
if ((ret = run_cfi_program (c, sr, ~(unw_word_t) 0, &addr,
|
if ((ret = run_cfi_program (c, sr, ~(unw_word_t) 0, &addr,
|
||||||
dci->cie_instr_end, dci)) < 0)
|
dci->cie_instr_end, dci)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial));
|
memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial));
|
||||||
|
@ -519,7 +519,7 @@ flush_rs_cache (struct dwarf_rs_cache *cache)
|
||||||
for (i = 0; i < DWARF_UNW_CACHE_SIZE; ++i)
|
for (i = 0; i < DWARF_UNW_CACHE_SIZE; ++i)
|
||||||
{
|
{
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
cache->buckets[i].lru_chain = (i - 1);
|
cache->buckets[i].lru_chain = (i - 1);
|
||||||
cache->buckets[i].coll_chain = -1;
|
cache->buckets[i].coll_chain = -1;
|
||||||
cache->buckets[i].ip = 0;
|
cache->buckets[i].ip = 0;
|
||||||
cache->buckets[i].valid = 0;
|
cache->buckets[i].valid = 0;
|
||||||
|
@ -554,7 +554,7 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache,
|
put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache,
|
||||||
intrmask_t *saved_maskp)
|
intrmask_t *saved_maskp)
|
||||||
{
|
{
|
||||||
assert (as->caching_policy != UNW_CACHE_NONE);
|
assert (as->caching_policy != UNW_CACHE_NONE);
|
||||||
|
|
||||||
|
@ -567,7 +567,7 @@ static inline unw_hash_index_t CONST_ATTR
|
||||||
hash (unw_word_t ip)
|
hash (unw_word_t ip)
|
||||||
{
|
{
|
||||||
/* based on (sqrt(5)/2-1)*2^64 */
|
/* based on (sqrt(5)/2-1)*2^64 */
|
||||||
# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL)
|
# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL)
|
||||||
|
|
||||||
return ip * magic >> ((sizeof(unw_word_t) * 8) - DWARF_LOG_UNW_HASH_SIZE);
|
return ip * magic >> ((sizeof(unw_word_t) * 8) - DWARF_LOG_UNW_HASH_SIZE);
|
||||||
}
|
}
|
||||||
|
@ -634,22 +634,22 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
|
||||||
tmp = cache->buckets + cache->hash[index];
|
tmp = cache->buckets + cache->hash[index];
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (tmp == rs)
|
if (tmp == rs)
|
||||||
{
|
{
|
||||||
if (prev)
|
if (prev)
|
||||||
prev->coll_chain = tmp->coll_chain;
|
prev->coll_chain = tmp->coll_chain;
|
||||||
else
|
else
|
||||||
cache->hash[index] = tmp->coll_chain;
|
cache->hash[index] = tmp->coll_chain;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
prev = tmp;
|
prev = tmp;
|
||||||
if (tmp->coll_chain >= DWARF_UNW_CACHE_SIZE)
|
if (tmp->coll_chain >= DWARF_UNW_CACHE_SIZE)
|
||||||
/* old rs wasn't in the hash-table */
|
/* old rs wasn't in the hash-table */
|
||||||
break;
|
break;
|
||||||
tmp = cache->buckets + tmp->coll_chain;
|
tmp = cache->buckets + tmp->coll_chain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enter new rs in the hash table */
|
/* enter new rs in the hash table */
|
||||||
|
@ -669,7 +669,7 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr,
|
create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr,
|
||||||
unw_word_t ip)
|
unw_word_t ip)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
|
@ -699,8 +699,8 @@ create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
eval_location_expr (struct dwarf_cursor *c, unw_addr_space_t as,
|
eval_location_expr (struct dwarf_cursor *c, unw_addr_space_t as,
|
||||||
unw_accessors_t *a, unw_word_t addr,
|
unw_accessors_t *a, unw_word_t addr,
|
||||||
dwarf_loc_t *locp, void *arg)
|
dwarf_loc_t *locp, void *arg)
|
||||||
{
|
{
|
||||||
int ret, is_register;
|
int ret, is_register;
|
||||||
unw_word_t len, val;
|
unw_word_t len, val;
|
||||||
|
@ -747,18 +747,18 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
|
||||||
/* CFA is equal to [reg] + offset: */
|
/* CFA is equal to [reg] + offset: */
|
||||||
|
|
||||||
/* As a special-case, if the stack-pointer is the CFA and the
|
/* As a special-case, if the stack-pointer is the CFA and the
|
||||||
stack-pointer wasn't saved, popping the CFA implicitly pops
|
stack-pointer wasn't saved, popping the CFA implicitly pops
|
||||||
the stack-pointer as well. */
|
the stack-pointer as well. */
|
||||||
if ((rs->reg[DWARF_CFA_REG_COLUMN].val == UNW_TDEP_SP)
|
if ((rs->reg[DWARF_CFA_REG_COLUMN].val == UNW_TDEP_SP)
|
||||||
&& (UNW_TDEP_SP < ARRAY_SIZE(rs->reg))
|
&& (UNW_TDEP_SP < ARRAY_SIZE(rs->reg))
|
||||||
&& (rs->reg[UNW_TDEP_SP].where == DWARF_WHERE_SAME))
|
&& (rs->reg[UNW_TDEP_SP].where == DWARF_WHERE_SAME))
|
||||||
cfa = c->cfa;
|
cfa = c->cfa;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
regnum = dwarf_to_unw_regnum (rs->reg[DWARF_CFA_REG_COLUMN].val);
|
regnum = dwarf_to_unw_regnum (rs->reg[DWARF_CFA_REG_COLUMN].val);
|
||||||
if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0)
|
if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
cfa += rs->reg[DWARF_CFA_OFF_COLUMN].val;
|
cfa += rs->reg[DWARF_CFA_OFF_COLUMN].val;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -769,37 +769,37 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
|
||||||
|
|
||||||
addr = rs->reg[DWARF_CFA_REG_COLUMN].val;
|
addr = rs->reg[DWARF_CFA_REG_COLUMN].val;
|
||||||
if ((ret = eval_location_expr (c, as, a, addr, &cfa_loc, arg)) < 0)
|
if ((ret = eval_location_expr (c, as, a, addr, &cfa_loc, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
/* the returned location better be a memory location... */
|
/* the returned location better be a memory location... */
|
||||||
if (DWARF_IS_REG_LOC (cfa_loc))
|
if (DWARF_IS_REG_LOC (cfa_loc))
|
||||||
return -UNW_EBADFRAME;
|
return -UNW_EBADFRAME;
|
||||||
cfa = DWARF_GET_LOC (cfa_loc);
|
cfa = DWARF_GET_LOC (cfa_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
|
for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
|
||||||
{
|
{
|
||||||
switch ((dwarf_where_t) rs->reg[i].where)
|
switch ((dwarf_where_t) rs->reg[i].where)
|
||||||
{
|
{
|
||||||
case DWARF_WHERE_UNDEF:
|
case DWARF_WHERE_UNDEF:
|
||||||
c->loc[i] = DWARF_NULL_LOC;
|
c->loc[i] = DWARF_NULL_LOC;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DWARF_WHERE_SAME:
|
case DWARF_WHERE_SAME:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DWARF_WHERE_CFAREL:
|
case DWARF_WHERE_CFAREL:
|
||||||
c->loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg[i].val);
|
c->loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg[i].val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DWARF_WHERE_REG:
|
case DWARF_WHERE_REG:
|
||||||
c->loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg[i].val));
|
c->loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg[i].val));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DWARF_WHERE_EXPR:
|
case DWARF_WHERE_EXPR:
|
||||||
addr = rs->reg[i].val;
|
addr = rs->reg[i].val;
|
||||||
if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0)
|
if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DWARF_WHERE_VAL_EXPR:
|
case DWARF_WHERE_VAL_EXPR:
|
||||||
addr = rs->reg[i].val;
|
addr = rs->reg[i].val;
|
||||||
|
@ -807,7 +807,7 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
|
||||||
return ret;
|
return ret;
|
||||||
c->loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (c->loc[i]));
|
c->loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (c->loc[i]));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c->cfa = cfa;
|
c->cfa = cfa;
|
||||||
|
@ -826,7 +826,7 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
|
||||||
if (c->ip == prev_ip && c->cfa == prev_cfa)
|
if (c->ip == prev_ip && c->cfa == prev_cfa)
|
||||||
{
|
{
|
||||||
Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
|
Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
|
||||||
__FUNCTION__, (long) c->ip);
|
__FUNCTION__, (long) c->ip);
|
||||||
return -UNW_EBADFRAME;
|
return -UNW_EBADFRAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,12 +883,12 @@ dwarf_find_save_locs (struct dwarf_cursor *c)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((ret = fetch_proc_info (c, c->ip, 1)) < 0 ||
|
if ((ret = fetch_proc_info (c, c->ip, 1)) < 0 ||
|
||||||
(ret = create_state_record_for (c, &sr, c->ip)) < 0)
|
(ret = create_state_record_for (c, &sr, c->ip)) < 0)
|
||||||
{
|
{
|
||||||
put_rs_cache (c->as, cache, &saved_mask);
|
put_rs_cache (c->as, cache, &saved_mask);
|
||||||
put_unwind_info (c, &c->pi);
|
put_unwind_info (c, &c->pi);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
rs = rs_new (cache, c);
|
rs = rs_new (cache, c);
|
||||||
memcpy(rs, &sr.rs_current, offsetof(struct dwarf_reg_state, ip));
|
memcpy(rs, &sr.rs_current, offsetof(struct dwarf_reg_state, ip));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
|
Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -30,10 +30,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
HIDDEN int
|
HIDDEN int
|
||||||
dwarf_read_encoded_pointer (unw_addr_space_t as, unw_accessors_t *a,
|
dwarf_read_encoded_pointer (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_word_t *addr, unsigned char encoding,
|
unw_word_t *addr, unsigned char encoding,
|
||||||
const unw_proc_info_t *pi,
|
const unw_proc_info_t *pi,
|
||||||
unw_word_t *valp, void *arg)
|
unw_word_t *valp, void *arg)
|
||||||
{
|
{
|
||||||
return dwarf_read_encoded_pointer_inlined (as, a, addr, encoding,
|
return dwarf_read_encoded_pointer_inlined (as, a, addr, encoding,
|
||||||
pi, valp, arg);
|
pi, valp, arg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
|
Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P.
|
Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P.
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define elf32_h
|
#define elf32_h
|
||||||
|
|
||||||
#ifndef ELF_CLASS
|
#ifndef ELF_CLASS
|
||||||
#define ELF_CLASS ELFCLASS32
|
#define ELF_CLASS ELFCLASS32
|
||||||
#endif
|
#endif
|
||||||
#include "elfxx.h"
|
#include "elfxx.h"
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define elf64_h
|
#define elf64_h
|
||||||
|
|
||||||
#ifndef ELF_CLASS
|
#ifndef ELF_CLASS
|
||||||
#define ELF_CLASS ELFCLASS64
|
#define ELF_CLASS ELFCLASS64
|
||||||
#endif
|
#endif
|
||||||
#include "elfxx.h"
|
#include "elfxx.h"
|
||||||
|
|
||||||
|
|
160
src/elfxx.c
160
src/elfxx.c
|
@ -1,7 +1,7 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2003-2005 Hewlett-Packard Co
|
Copyright (C) 2003-2005 Hewlett-Packard Co
|
||||||
Copyright (C) 2007 David Mosberger-Tang
|
Copyright (C) 2007 David Mosberger-Tang
|
||||||
Contributed by David Mosberger-Tang <dmosberger@gmail.com>
|
Contributed by David Mosberger-Tang <dmosberger@gmail.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@ elf_w (section_table) (struct elf_image *ei)
|
||||||
if (soff + ehdr->e_shnum * ehdr->e_shentsize > ei->size)
|
if (soff + ehdr->e_shnum * ehdr->e_shentsize > ei->size)
|
||||||
{
|
{
|
||||||
Debug (1, "section table outside of image? (%lu > %lu)\n",
|
Debug (1, "section table outside of image? (%lu > %lu)\n",
|
||||||
(unsigned long) (soff + ehdr->e_shnum * ehdr->e_shentsize),
|
(unsigned long) (soff + ehdr->e_shnum * ehdr->e_shentsize),
|
||||||
(unsigned long) ei->size);
|
(unsigned long) ei->size);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,8 +65,8 @@ elf_w (string_table) (struct elf_image *ei, int section)
|
||||||
if (str_soff + ehdr->e_shentsize > ei->size)
|
if (str_soff + ehdr->e_shentsize > ei->size)
|
||||||
{
|
{
|
||||||
Debug (1, "string shdr table outside of image? (%lu > %lu)\n",
|
Debug (1, "string shdr table outside of image? (%lu > %lu)\n",
|
||||||
(unsigned long) (str_soff + ehdr->e_shentsize),
|
(unsigned long) (str_soff + ehdr->e_shentsize),
|
||||||
(unsigned long) ei->size);
|
(unsigned long) ei->size);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
str_shdr = (Elf_W (Shdr) *) ((char *) ei->image + str_soff);
|
str_shdr = (Elf_W (Shdr) *) ((char *) ei->image + str_soff);
|
||||||
|
@ -74,8 +74,8 @@ elf_w (string_table) (struct elf_image *ei, int section)
|
||||||
if (str_shdr->sh_offset + str_shdr->sh_size > ei->size)
|
if (str_shdr->sh_offset + str_shdr->sh_size > ei->size)
|
||||||
{
|
{
|
||||||
Debug (1, "string table outside of image? (%lu > %lu)\n",
|
Debug (1, "string table outside of image? (%lu > %lu)\n",
|
||||||
(unsigned long) (str_shdr->sh_offset + str_shdr->sh_size),
|
(unsigned long) (str_shdr->sh_offset + str_shdr->sh_size),
|
||||||
(unsigned long) ei->size);
|
(unsigned long) ei->size);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +85,9 @@ elf_w (string_table) (struct elf_image *ei, int section)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
elf_w (lookup_symbol) (unw_addr_space_t as,
|
elf_w (lookup_symbol) (unw_addr_space_t as,
|
||||||
unw_word_t ip, struct elf_image *ei,
|
unw_word_t ip, struct elf_image *ei,
|
||||||
Elf_W (Addr) load_offset,
|
Elf_W (Addr) load_offset,
|
||||||
char *buf, size_t buf_len, Elf_W (Addr) *min_dist)
|
char *buf, size_t buf_len, Elf_W (Addr) *min_dist)
|
||||||
{
|
{
|
||||||
size_t syment_size;
|
size_t syment_size;
|
||||||
Elf_W (Ehdr) *ehdr = ei->image;
|
Elf_W (Ehdr) *ehdr = ei->image;
|
||||||
|
@ -107,50 +107,50 @@ elf_w (lookup_symbol) (unw_addr_space_t as,
|
||||||
for (i = 0; i < ehdr->e_shnum; ++i)
|
for (i = 0; i < ehdr->e_shnum; ++i)
|
||||||
{
|
{
|
||||||
switch (shdr->sh_type)
|
switch (shdr->sh_type)
|
||||||
{
|
{
|
||||||
case SHT_SYMTAB:
|
case SHT_SYMTAB:
|
||||||
case SHT_DYNSYM:
|
case SHT_DYNSYM:
|
||||||
symtab = (Elf_W (Sym) *) ((char *) ei->image + shdr->sh_offset);
|
symtab = (Elf_W (Sym) *) ((char *) ei->image + shdr->sh_offset);
|
||||||
symtab_end = (Elf_W (Sym) *) ((char *) symtab + shdr->sh_size);
|
symtab_end = (Elf_W (Sym) *) ((char *) symtab + shdr->sh_size);
|
||||||
syment_size = shdr->sh_entsize;
|
syment_size = shdr->sh_entsize;
|
||||||
|
|
||||||
strtab = elf_w (string_table) (ei, shdr->sh_link);
|
strtab = elf_w (string_table) (ei, shdr->sh_link);
|
||||||
if (!strtab)
|
if (!strtab)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Debug (16, "symtab=0x%lx[%d]\n",
|
Debug (16, "symtab=0x%lx[%d]\n",
|
||||||
(long) shdr->sh_offset, shdr->sh_type);
|
(long) shdr->sh_offset, shdr->sh_type);
|
||||||
|
|
||||||
for (sym = symtab;
|
for (sym = symtab;
|
||||||
sym < symtab_end;
|
sym < symtab_end;
|
||||||
sym = (Elf_W (Sym) *) ((char *) sym + syment_size))
|
sym = (Elf_W (Sym) *) ((char *) sym + syment_size))
|
||||||
{
|
{
|
||||||
if (ELF_W (ST_TYPE) (sym->st_info) == STT_FUNC
|
if (ELF_W (ST_TYPE) (sym->st_info) == STT_FUNC
|
||||||
&& sym->st_shndx != SHN_UNDEF)
|
&& sym->st_shndx != SHN_UNDEF)
|
||||||
{
|
{
|
||||||
val = sym->st_value;
|
val = sym->st_value;
|
||||||
if (sym->st_shndx != SHN_ABS)
|
if (sym->st_shndx != SHN_ABS)
|
||||||
val += load_offset;
|
val += load_offset;
|
||||||
if (tdep_get_func_addr (as, val, &val) < 0)
|
if (tdep_get_func_addr (as, val, &val) < 0)
|
||||||
continue;
|
continue;
|
||||||
Debug (16, "0x%016lx info=0x%02x %s\n",
|
Debug (16, "0x%016lx info=0x%02x %s\n",
|
||||||
(long) val, sym->st_info, strtab + sym->st_name);
|
(long) val, sym->st_info, strtab + sym->st_name);
|
||||||
|
|
||||||
if ((Elf_W (Addr)) (ip - val) < *min_dist)
|
if ((Elf_W (Addr)) (ip - val) < *min_dist)
|
||||||
{
|
{
|
||||||
*min_dist = (Elf_W (Addr)) (ip - val);
|
*min_dist = (Elf_W (Addr)) (ip - val);
|
||||||
strncpy (buf, strtab + sym->st_name, buf_len);
|
strncpy (buf, strtab + sym->st_name, buf_len);
|
||||||
buf[buf_len - 1] = '\0';
|
buf[buf_len - 1] = '\0';
|
||||||
ret = (strlen (strtab + sym->st_name) >= buf_len
|
ret = (strlen (strtab + sym->st_name) >= buf_len
|
||||||
? -UNW_ENOMEM : 0);
|
? -UNW_ENOMEM : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize);
|
shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -158,7 +158,7 @@ elf_w (lookup_symbol) (unw_addr_space_t as,
|
||||||
|
|
||||||
static Elf_W (Addr)
|
static Elf_W (Addr)
|
||||||
elf_w (get_load_offset) (struct elf_image *ei, unsigned long segbase,
|
elf_w (get_load_offset) (struct elf_image *ei, unsigned long segbase,
|
||||||
unsigned long mapoff)
|
unsigned long mapoff)
|
||||||
{
|
{
|
||||||
Elf_W (Addr) offset = 0;
|
Elf_W (Addr) offset = 0;
|
||||||
Elf_W (Ehdr) *ehdr;
|
Elf_W (Ehdr) *ehdr;
|
||||||
|
@ -171,8 +171,8 @@ elf_w (get_load_offset) (struct elf_image *ei, unsigned long segbase,
|
||||||
for (i = 0; i < ehdr->e_phnum; ++i)
|
for (i = 0; i < ehdr->e_phnum; ++i)
|
||||||
if (phdr[i].p_type == PT_LOAD && phdr[i].p_offset == mapoff)
|
if (phdr[i].p_type == PT_LOAD && phdr[i].p_offset == mapoff)
|
||||||
{
|
{
|
||||||
offset = segbase - phdr[i].p_vaddr;
|
offset = segbase - phdr[i].p_vaddr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
|
@ -199,7 +199,7 @@ xz_uncompressed_size (uint8_t *compressed, size_t length)
|
||||||
|
|
||||||
uint8_t *indexdata = footer - options.backward_size;
|
uint8_t *indexdata = footer - options.backward_size;
|
||||||
if (lzma_index_buffer_decode (&index, &memlimit, NULL, indexdata,
|
if (lzma_index_buffer_decode (&index, &memlimit, NULL, indexdata,
|
||||||
&pos, options.backward_size) != LZMA_OK)
|
&pos, options.backward_size) != LZMA_OK)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (lzma_index_size (index) == options.backward_size)
|
if (lzma_index_size (index) == options.backward_size)
|
||||||
|
@ -236,21 +236,21 @@ elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi)
|
||||||
for (i = 0; i < ehdr->e_shnum; ++i)
|
for (i = 0; i < ehdr->e_shnum; ++i)
|
||||||
{
|
{
|
||||||
if (strcmp (strtab + shdr->sh_name, ".gnu_debugdata") == 0)
|
if (strcmp (strtab + shdr->sh_name, ".gnu_debugdata") == 0)
|
||||||
{
|
{
|
||||||
if (shdr->sh_offset + shdr->sh_size > ei->size)
|
if (shdr->sh_offset + shdr->sh_size > ei->size)
|
||||||
{
|
{
|
||||||
Debug (1, ".gnu_debugdata outside image? (0x%lu > 0x%lu)\n",
|
Debug (1, ".gnu_debugdata outside image? (0x%lu > 0x%lu)\n",
|
||||||
(unsigned long) shdr->sh_offset + shdr->sh_size,
|
(unsigned long) shdr->sh_offset + shdr->sh_size,
|
||||||
(unsigned long) ei->size);
|
(unsigned long) ei->size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug (16, "found .gnu_debugdata at 0x%lx\n",
|
Debug (16, "found .gnu_debugdata at 0x%lx\n",
|
||||||
(unsigned long) shdr->sh_offset);
|
(unsigned long) shdr->sh_offset);
|
||||||
compressed = ((uint8_t *) ei->image) + shdr->sh_offset;
|
compressed = ((uint8_t *) ei->image) + shdr->sh_offset;
|
||||||
compressed_len = shdr->sh_size;
|
compressed_len = shdr->sh_size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize);
|
shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize);
|
||||||
}
|
}
|
||||||
|
@ -268,7 +268,7 @@ elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi)
|
||||||
|
|
||||||
mdi->size = uncompressed_len;
|
mdi->size = uncompressed_len;
|
||||||
mdi->image = mmap (NULL, uncompressed_len, PROT_READ|PROT_WRITE,
|
mdi->image = mmap (NULL, uncompressed_len, PROT_READ|PROT_WRITE,
|
||||||
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||||
|
|
||||||
if (mdi->image == MAP_FAILED)
|
if (mdi->image == MAP_FAILED)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -276,8 +276,8 @@ elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi)
|
||||||
size_t in_pos = 0, out_pos = 0;
|
size_t in_pos = 0, out_pos = 0;
|
||||||
lzma_ret lret;
|
lzma_ret lret;
|
||||||
lret = lzma_stream_buffer_decode (&memlimit, 0, NULL,
|
lret = lzma_stream_buffer_decode (&memlimit, 0, NULL,
|
||||||
compressed, &in_pos, compressed_len,
|
compressed, &in_pos, compressed_len,
|
||||||
mdi->image, &out_pos, mdi->size);
|
mdi->image, &out_pos, mdi->size);
|
||||||
if (lret != LZMA_OK)
|
if (lret != LZMA_OK)
|
||||||
{
|
{
|
||||||
Debug (1, "LZMA decompression failed: %d\n", lret);
|
Debug (1, "LZMA decompression failed: %d\n", lret);
|
||||||
|
@ -302,10 +302,10 @@ elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi)
|
||||||
|
|
||||||
HIDDEN int
|
HIDDEN int
|
||||||
elf_w (get_proc_name_in_image) (unw_addr_space_t as, struct elf_image *ei,
|
elf_w (get_proc_name_in_image) (unw_addr_space_t as, struct elf_image *ei,
|
||||||
unsigned long segbase,
|
unsigned long segbase,
|
||||||
unsigned long mapoff,
|
unsigned long mapoff,
|
||||||
unw_word_t ip,
|
unw_word_t ip,
|
||||||
char *buf, size_t buf_len, unw_word_t *offp)
|
char *buf, size_t buf_len, unw_word_t *offp)
|
||||||
{
|
{
|
||||||
Elf_W (Addr) load_offset;
|
Elf_W (Addr) load_offset;
|
||||||
Elf_W (Addr) min_dist = ~(Elf_W (Addr))0;
|
Elf_W (Addr) min_dist = ~(Elf_W (Addr))0;
|
||||||
|
@ -320,19 +320,19 @@ elf_w (get_proc_name_in_image) (unw_addr_space_t as, struct elf_image *ei,
|
||||||
if (elf_w (extract_minidebuginfo) (ei, &mdi))
|
if (elf_w (extract_minidebuginfo) (ei, &mdi))
|
||||||
{
|
{
|
||||||
int ret_mdi = elf_w (lookup_symbol) (as, ip, &mdi, load_offset, buf,
|
int ret_mdi = elf_w (lookup_symbol) (as, ip, &mdi, load_offset, buf,
|
||||||
buf_len, &min_dist);
|
buf_len, &min_dist);
|
||||||
|
|
||||||
/* Closer symbol was found (possibly truncated). */
|
/* Closer symbol was found (possibly truncated). */
|
||||||
if (ret_mdi == 0 || ret_mdi == -UNW_ENOMEM)
|
if (ret_mdi == 0 || ret_mdi == -UNW_ENOMEM)
|
||||||
{
|
{
|
||||||
ret = ret_mdi;
|
ret = ret_mdi;
|
||||||
}
|
}
|
||||||
|
|
||||||
munmap (mdi.image, mdi.size);
|
munmap (mdi.image, mdi.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (min_dist >= ei->size)
|
if (min_dist >= ei->size)
|
||||||
return -UNW_ENOINFO; /* not found */
|
return -UNW_ENOINFO; /* not found */
|
||||||
if (offp)
|
if (offp)
|
||||||
*offp = min_dist;
|
*offp = min_dist;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -340,7 +340,7 @@ elf_w (get_proc_name_in_image) (unw_addr_space_t as, struct elf_image *ei,
|
||||||
|
|
||||||
HIDDEN int
|
HIDDEN int
|
||||||
elf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, unw_word_t ip,
|
elf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, unw_word_t ip,
|
||||||
char *buf, size_t buf_len, unw_word_t *offp)
|
char *buf, size_t buf_len, unw_word_t *offp)
|
||||||
{
|
{
|
||||||
unsigned long segbase, mapoff;
|
unsigned long segbase, mapoff;
|
||||||
struct elf_image ei;
|
struct elf_image ei;
|
||||||
|
|
36
src/elfxx.h
36
src/elfxx.h
|
@ -1,7 +1,7 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2003, 2005 Hewlett-Packard Co
|
Copyright (C) 2003, 2005 Hewlett-Packard Co
|
||||||
Copyright (C) 2007 David Mosberger-Tang
|
Copyright (C) 2007 David Mosberger-Tang
|
||||||
Contributed by David Mosberger-Tang <dmosberger@gmail.com>
|
Contributed by David Mosberger-Tang <dmosberger@gmail.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -33,26 +33,26 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#include "libunwind_i.h"
|
#include "libunwind_i.h"
|
||||||
|
|
||||||
#if ELF_CLASS == ELFCLASS32
|
#if ELF_CLASS == ELFCLASS32
|
||||||
# define ELF_W(x) ELF32_##x
|
# define ELF_W(x) ELF32_##x
|
||||||
# define Elf_W(x) Elf32_##x
|
# define Elf_W(x) Elf32_##x
|
||||||
# define elf_w(x) _Uelf32_##x
|
# define elf_w(x) _Uelf32_##x
|
||||||
#else
|
#else
|
||||||
# define ELF_W(x) ELF64_##x
|
# define ELF_W(x) ELF64_##x
|
||||||
# define Elf_W(x) Elf64_##x
|
# define Elf_W(x) Elf64_##x
|
||||||
# define elf_w(x) _Uelf64_##x
|
# define elf_w(x) _Uelf64_##x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int elf_w (get_proc_name) (unw_addr_space_t as,
|
extern int elf_w (get_proc_name) (unw_addr_space_t as,
|
||||||
pid_t pid, unw_word_t ip,
|
pid_t pid, unw_word_t ip,
|
||||||
char *buf, size_t len,
|
char *buf, size_t len,
|
||||||
unw_word_t *offp);
|
unw_word_t *offp);
|
||||||
|
|
||||||
extern int elf_w (get_proc_name_in_image) (unw_addr_space_t as,
|
extern int elf_w (get_proc_name_in_image) (unw_addr_space_t as,
|
||||||
struct elf_image *ei,
|
struct elf_image *ei,
|
||||||
unsigned long segbase,
|
unsigned long segbase,
|
||||||
unsigned long mapoff,
|
unsigned long mapoff,
|
||||||
unw_word_t ip,
|
unw_word_t ip,
|
||||||
char *buf, size_t buf_len, unw_word_t *offp);
|
char *buf, size_t buf_len, unw_word_t *offp);
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
elf_w (valid_object) (struct elf_image *ei)
|
elf_w (valid_object) (struct elf_image *ei)
|
||||||
|
@ -61,9 +61,9 @@ elf_w (valid_object) (struct elf_image *ei)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return (memcmp (ei->image, ELFMAG, SELFMAG) == 0
|
return (memcmp (ei->image, ELFMAG, SELFMAG) == 0
|
||||||
&& ((uint8_t *) ei->image)[EI_CLASS] == ELF_CLASS
|
&& ((uint8_t *) ei->image)[EI_CLASS] == ELF_CLASS
|
||||||
&& ((uint8_t *) ei->image)[EI_VERSION] != EV_NONE
|
&& ((uint8_t *) ei->image)[EI_VERSION] != EV_NONE
|
||||||
&& ((uint8_t *) ei->image)[EI_VERSION] <= EV_CURRENT);
|
&& ((uint8_t *) ei->image)[EI_VERSION] <= EV_CURRENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue