1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Public interface for AMD64 Unwind context
29  */
30 
31 #ifndef _UNWIND_CONTEXT_H
32 #define	_UNWIND_CONTEXT_H
33 
34 /*
35  * implementation of context structure
36  *
37  * Register arrays are indexed as specified in reg_num.h
38  */
39 struct _Unwind_Context {
40 	uint64_t	entry_regs[16];
41 	uint64_t	current_regs[16];
42 	uint64_t	cfa;
43 	uint64_t	pc;
44 	uint64_t	ra;
45 	void		*fde;
46 	_Unwind_Personality_Fn	pfn;
47 	uint64_t	func;
48 	void		*lsda;
49 	uint64_t	range;
50 };
51 
52 enum register_rule {
53 	undefined_rule,
54 	same_value_rule,	/* target_reg = target_reg */
55 	offset_rule,		/* target_reg = *(offset + CFA) */
56 	is_offset_rule,		/* target_reg = offset + CFA */
57 	register_rule,		/* target_reg = offset + source_reg */
58 	constant_rule,		/* target_reg = offset */
59 	indirect_rule		/* target_reg = *(offset + source_reg) */
60 };
61 
62 struct register_state {
63 	uint64_t	offset;
64 	enum register_rule	rule;
65 	unsigned char	source_reg;
66 };
67 
68 struct eh_frame_fields {
69 	void		*cie_ops;
70 	void		*cie_ops_end;
71 	ptrdiff_t	cie_reloc;
72 	int		code_align;
73 	int		data_align;
74 	int		code_enc;
75 	void		*fde_ops;
76 	void		*fde_ops_end;
77 	ptrdiff_t	fde_reloc;
78 };
79 
80 _Unwind_Reason_Code
81 _Unw_very_boring_personality(int version, int actions, uint64_t exclass,
82 		struct _Unwind_Exception *exception_object,
83 		struct _Unwind_Context *ctx);
84 /*
85  * Starting withe an initialized context (from a ucontext)
86  * the following routines are sufficient to implement a non-destructive
87  * stack walk if modified to access the target processes memory. These
88  * routines refer to the local address of an item using names containing
89  * `data' names containing `reloc' give the correction to get target
90  * process location.
91  */
92 
93 /* ================== find function ====================== */
94 
95 /*
96  * Computes the func and fde fields using pc as the lookup key.
97  * Return is 0 or address of fde
98  *
99  * This is the only function that look into .eh_frame_hdr
100  */
101 void *_Unw_EhfhLookup(struct _Unwind_Context *ctx);
102 
103 /* =================== analyze function ================== */
104 
105 /*
106  * Fills in personality_fn and lsda fields of the context based
107  * the fde entry which must be valid and also partially unpacks
108  * fde and cie into *f
109  *
110  * This is one of two functions that look inside fde's
111  */
112 struct eh_frame_fields *_Unw_Decode_FDE(struct eh_frame_fields *f,
113 		struct _Unwind_Context *ctx);
114 
115 /*
116  * Computes register values at entry to function based on current
117  * register values, pc and fde values in a context
118  *
119  * This is the other function which looks inside fde's and
120  * the only one to look at CFA operations
121  *
122  * If 'f' is NULL (because no fde was found), a default calculation
123  * assuming an FP is done.
124  */
125 uint64_t _Unw_Rollback_Registers(struct eh_frame_fields *f,
126 		struct _Unwind_Context *ctx);
127 
128 /* ================= register propagation =============== */
129 
130 /*
131  * Fills in the current register context for the caller
132  * based on computed at-entry state of callee
133  */
134 void
135 _Unw_Propagate_Registers(struct _Unwind_Context *old_ctx,
136 		struct _Unwind_Context *new_ctx);
137 
138 /* ================================================= */
139 enum operand_desc {
140 	NO_OPR,
141 	ULEB128_FAC,
142 	ULEB128,
143 	ULEB128_SREG,
144 	SLEB128,
145 	SLEB128_FAC,
146 	ADDR,
147 	SIZE,
148 	ZTSTRING,
149 	UNUM6,
150 	UNUM6_CFAC,
151 	UNUM8,
152 	UNUM8_CFAC,
153 	UNUM16,
154 	UNUM16_CFAC,
155 	UNUM32,
156 	UNUM32_CFAC,
157 	UNUM64,
158 	SNUM8,
159 	SNUM16,
160 	SNUM32,
161 	SNUM64,
162 	BLOCK
163 };
164 
165 uint64_t _Unw_get_val(void **datap, ptrdiff_t reloc,
166 		enum operand_desc opr,
167 		int daf, int caf, int enc);
168 
169 #endif	/* _UNWIND_CONTEXT_H */
170