123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- /* libunwind - a platform-independent unwind library
- Copyright (C) 2002-2004 Hewlett-Packard Co
- Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
- This file is part of libunwind.
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
- /* This file defines the runtime-support routines for dynamically
- generated code. Even though it is implemented as part of libunwind,
- it is logically separate from the interface to perform the actual
- unwinding. In particular, this interface is always used in the
- context of the unwind target, whereas the rest of the unwind API is
- used in context of the process that is doing the unwind (which may be
- a debugger running on another machine, for example).
- Note that the data-structures declared here server a dual purpose:
- when a program registers a dynamically generated procedure, it uses
- these structures directly. On the other hand, with remote-unwinding,
- the data-structures are read from the remote process's memory and
- translated into internalized versions. To facilitate remote-access,
- the following rules should be followed in declaring these structures:
- (1) Declare a member as a pointer only if the the information the
- member points to needs to be internalized as well (e.g., a
- string representing a procedure name should be declared as
- "const char *", but the instruction pointer should be declared
- as unw_word_t).
- (2) Provide sufficient padding to ensure that no implicit padding
- will be needed on any of the supported target architectures. For
- the time being, padding data structures with the assumption that
- sizeof (unw_word_t) == 8 should be sufficient. (Note: it's not
- impossible to internalize structures with internal padding, but
- it does make the process a bit harder).
- (3) Don't declare members that contain bitfields or floating-point
- values.
- (4) Don't declare members with enumeration types. Declare them as
- int32_t instead. */
- typedef enum
- {
- UNW_DYN_STOP = 0, /* end-of-unwind-info marker */
- UNW_DYN_SAVE_REG, /* save register to another register */
- UNW_DYN_SPILL_FP_REL, /* frame-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_POP_FRAMES, /* drop one or more stack frames */
- UNW_DYN_LABEL_STATE, /* name the current state */
- UNW_DYN_COPY_STATE, /* set the region's entry-state */
- UNW_DYN_ALIAS /* get unwind info from an alias */
- }
- unw_dyn_operation_t;
- typedef enum
- {
- UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */
- UNW_INFO_FORMAT_TABLE, /* unw_dyn_table_t */
- UNW_INFO_FORMAT_REMOTE_TABLE, /* unw_dyn_remote_table_t */
- UNW_INFO_FORMAT_ARM_EXIDX /* ARM specific unwind info */
- }
- unw_dyn_info_format_t;
- typedef struct unw_dyn_op
- {
- int8_t tag; /* what operation? */
- int8_t qp; /* qualifying predicate register */
- int16_t reg; /* what register */
- int32_t when; /* when does it take effect? */
- unw_word_t val; /* auxiliary value */
- }
- unw_dyn_op_t;
- typedef struct unw_dyn_region_info
- {
- struct unw_dyn_region_info *next; /* linked list of regions */
- int32_t insn_count; /* region length (# of instructions) */
- uint32_t op_count; /* length of op-array */
- unw_dyn_op_t op[1]; /* variable-length op-array */
- }
- unw_dyn_region_info_t;
- typedef struct unw_dyn_proc_info
- {
- unw_word_t name_ptr; /* address of human-readable procedure name */
- unw_word_t handler; /* address of personality routine */
- uint32_t flags;
- int32_t pad0;
- unw_dyn_region_info_t *regions;
- }
- unw_dyn_proc_info_t;
- typedef struct unw_dyn_table_info
- {
- unw_word_t name_ptr; /* addr. of table name (e.g., library name) */
- unw_word_t segbase; /* segment base */
- unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */
- unw_word_t *table_data;
- }
- unw_dyn_table_info_t;
- typedef struct unw_dyn_remote_table_info
- {
- unw_word_t name_ptr; /* addr. of table name (e.g., library name) */
- unw_word_t segbase; /* segment base */
- unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */
- unw_word_t table_data;
- }
- unw_dyn_remote_table_info_t;
- typedef struct unw_dyn_info
- {
- /* doubly-linked list of dyn-info structures: */
- struct unw_dyn_info *next;
- struct unw_dyn_info *prev;
- 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 gp; /* global-pointer in effect for this entry */
- int32_t format; /* real type: unw_dyn_info_format_t */
- int32_t pad;
- union
- {
- unw_dyn_proc_info_t pi;
- unw_dyn_table_info_t ti;
- unw_dyn_remote_table_info_t rti;
- }
- u;
- }
- unw_dyn_info_t;
- typedef struct unw_dyn_info_list
- {
- uint32_t version;
- uint32_t generation;
- unw_dyn_info_t *first;
- }
- unw_dyn_info_list_t;
- /* Return the size (in bytes) of an unw_dyn_region_info_t structure that can
- hold OP_COUNT ops. */
- #define _U_dyn_region_info_size(op_count) \
- ((char *) (((unw_dyn_region_info_t *) NULL)->op + (op_count)) \
- - (char *) NULL)
- /* Register the unwind info for a single procedure.
- This routine is NOT signal-safe. */
- extern void _U_dyn_register (unw_dyn_info_t *);
- /* Cancel the unwind info for a single procedure.
- This routine is NOT signal-safe. */
- extern void _U_dyn_cancel (unw_dyn_info_t *);
- /* Convenience routines. */
- #define _U_dyn_op(_tag, _qp, _when, _reg, _val) \
- ((unw_dyn_op_t) { (_tag), (_qp), (_reg), (_when), (_val) })
- #define _U_dyn_op_save_reg(op, 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) \
- (*(op) = _U_dyn_op (UNW_DYN_SPILL_FP_REL, (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), \
- (offset)))
- #define _U_dyn_op_add(op, 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) \
- (*(op) = _U_dyn_op (UNW_DYN_POP_FRAMES, (qp), (when), 0, (num_frames)))
- #define _U_dyn_op_label_state(op, label) \
- (*(op) = _U_dyn_op (UNW_DYN_LABEL_STATE, _U_QP_TRUE, -1, 0, (label)))
- #define _U_dyn_op_copy_state(op, label) \
- (*(op) = _U_dyn_op (UNW_DYN_COPY_STATE, _U_QP_TRUE, -1, 0, (label)))
- #define _U_dyn_op_alias(op, qp, when, addr) \
- (*(op) = _U_dyn_op (UNW_DYN_ALIAS, (qp), (when), 0, (addr)))
- #define _U_dyn_op_stop(op) \
- (*(op) = _U_dyn_op (UNW_DYN_STOP, _U_QP_TRUE, -1, 0, 0))
- /* The target-dependent qualifying predicate which is always TRUE. On
- IA-64, that's p0 (0), on non-predicated architectures, the value is
- ignored. */
- #define _U_QP_TRUE _U_TDEP_QP_TRUE
|