Home | History | Annotate | Line # | Download | only in unwind
      1 /*	$NetBSD: stackframe.h,v 1.4 2016/07/31 19:33:18 dholland Exp $	*/
      2 
      3 /*
      4  * Contributed to the NetBSD foundation by Cherry G. Mathew
      5  */
      6 
      7 #define UNW_VER(x)           ((x) >> 48)
      8 #define UNW_FLAG_MASK        0x0000ffff00000000L
      9 #define UNW_FLAG_OSMASK      0x0000f00000000000L
     10 #define UNW_FLAG_EHANDLER(x) ((x) & 0x0000000100000000L)
     11 #define UNW_FLAG_UHANDLER(x) ((x) & 0x0000000200000000L)
     12 #define UNW_LENGTH(x)        ((x) & 0x00000000ffffffffL)
     13 
     14 /* Unwind table entry. */
     15 struct uwtable_ent {
     16 	uint64_t start;
     17 	uint64_t end;
     18 	char *infoptr;
     19 };
     20 
     21 
     22 enum regrecord_type{
     23 	/* Register contents live ( and therefore untouched ). */
     24 	UNSAVED,
     25 	/* .offset field is the saved content. */
     26 	IMMED,
     27 	/* Register saved in one of the Branch Registers. */
     28 	BRREL,
     29 	/*
     30 	 * Register saved in one of the Stacked GRs
     31 	 * regstate.offset contains GR number (usually >= 32)
     32 	 */
     33 	GRREL,
     34 	/*
     35 	 * Register saved on the memory stack frame.
     36 	 * regstate.offset is in words; ie; location == (sp + 4 * spoff).
     37 	 */
     38 	SPREL,
     39 	/*
     40 	 * Register saved on the memory stack frame but offseted via psp
     41 	 * regstate.offset is in words; ie,
     42 	 * location == (psp + 16  4 * pspoff)
     43 	 */
     44 	PSPREL
     45 };
     46 
     47 
     48 struct regstate {
     49 	enum regrecord_type where;
     50 	uint64_t when;
     51 
     52 #define INVALID -1UL	/* Indicates uninitialised offset value. */
     53 	uint64_t offset;
     54 };
     55 
     56 
     57 /* A staterecord contains the net state of
     58  * sequentially parsing unwind descriptors.
     59  * The entry state of the current prologue region
     60  * is the exit state of the previous region.
     61  * We record info about registers we care about
     62  * ie; just enough to re-construct an unwind frame,
     63  * and ignore the rest.
     64  * Initial state is where = UNSAVED for all .where fields.
     65  */
     66 
     67 struct staterecord {
     68 	struct regstate bsp;
     69    	struct regstate psp;
     70  	struct regstate rp;
     71  	struct regstate pfs;
     72 };
     73 
     74 /* The unwind frame is a simpler version of the trap frame
     75  * and contains a subset of preserved registers, which are
     76  * useful in unwinding an ia64 stack frame.
     77  * Keep this in sync with the staterecord. See: stackframe.c:updateregs()
     78  */
     79 
     80 struct unwind_frame {
     81 	uint64_t		bsp;	/* Base of the RSE. */
     82 				    /* !!! XXX: Stack Frame discontinuities */
     83 	uint64_t		psp;	/* Mem stack (variable size) base. */
     84 	uint64_t		rp;	/* Return Pointer */
     85 	uint64_t		pfs;	/* Previous Frame size info */
     86 
     87 	/* Don't mirror anything below this line with struct staterecord */
     88 	uint64_t		sp;
     89 };
     90 
     91 
     92 void buildrecordchain(uint64_t, struct recordchain *);
     93 void initrecord(struct staterecord *);
     94 void modifyrecord(struct staterecord *, struct recordchain *, uint64_t);
     95 void pushrecord(struct staterecord *);
     96 void poprecord(struct staterecord *, int);
     97 void dump_staterecord(struct staterecord *);
     98 void clonerecordstack(u_int);
     99 void switchrecordstack(u_int);
    100 
    101 struct uwtable_ent *get_unwind_table_entry(uint64_t);
    102 void patchunwindframe(struct unwind_frame *, uint64_t, uint64_t);
    103 void updateregs(struct unwind_frame *uwf, struct staterecord *, uint64_t);
    104 struct uwtable_ent * get_unwind_table_entry(uint64_t ip);
    105 
    106 struct staterecord *buildrecordstack(struct recordchain *, uint64_t);
    107 void dump_recordchain(struct recordchain *);
    108 
    109 /* Convenience macros to decompose CFM & ar.pfs. */
    110 #define	IA64_CFM_SOF(x)		((x) & 0x7f)
    111 #define	IA64_CFM_SOL(x)		(((x) >> 7) & 0x7f)
    112 #define	IA64_CFM_SOR(x)		(((x) >> 14) & 0x0f)
    113 #define	IA64_CFM_RRB_GR(x)	(((x) >> 18) & 0x7f)
    114 #define	IA64_CFM_RRB_FR(x)	(((x) >> 25) & 0x7f)
    115 #define	IA64_CFM_RRB_PR(x)	(((x) >> 32) & 0x3f)
    116 
    117 #define IA64_RNATINDEX(x)	(((x) & 0x1f8) >> 3)
    118 
    119 /* Obeys Table 6:2 RSE Operation Instructions and State Modification */
    120 
    121 /* These functions adjust for RSE rnat saves to bsp in the forward and
    122  * reverse directions respectively.
    123  */
    124 #define ia64_rnat_adjust ia64_bsp_adjust_call
    125 
    126 static __inline uint64_t
    127 ia64_bsp_adjust_call(uint64_t bsp, int sol)
    128 {
    129 	bsp += ((sol + (IA64_RNATINDEX(bsp) + sol) / 63) << 3);
    130 	return bsp;
    131 }
    132 
    133 static __inline uint64_t
    134 ia64_bsp_adjust_ret(uint64_t bsp, int sol)
    135 {
    136 	bsp -= ((sol + (62 - IA64_RNATINDEX(bsp) + sol) / 63) << 3);
    137 	return bsp;
    138 }
    139 
    140 static __inline uint64_t
    141 ia64_getrse_gr(uint64_t bsp, uint64_t gr)
    142 {
    143 	bsp = ia64_bsp_adjust_call(bsp, gr);
    144 	return *(uint64_t *) bsp;
    145 }
    146