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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
35 
36 /*
37  * implementation of context structure
38  *
39  * Register arrays are indexed as specified in reg_num.h
40  */
41 struct _Unwind_Context {
42 	uint64_t	entry_regs[16];
43 	uint64_t	current_regs[16];
44 	uint64_t	cfa;
45 	uint64_t	pc;
46 	uint64_t	ra;
47 	void		*fde;
48 	_Unwind_Personality_Fn	pfn;
49 	uint64_t	func;
50 	void		*lsda;
51 	uint64_t	range;
52 };
53 
54 enum register_rule {
55 	undefined_rule,
56 	same_value_rule,	/* target_reg = target_reg */
57 	offset_rule,		/* target_reg = *(offset + CFA) */
58 	is_offset_rule,		/* target_reg = offset + CFA */
59 	register_rule,		/* target_reg = offset + source_reg */
60 	constant_rule,		/* target_reg = offset */
61 	indirect_rule		/* target_reg = *(offset + source_reg) */
62 };
63 
64 struct register_state {
65 	uint64_t	offset;
66 	enum register_rule	rule;
67 	unsigned char	source_reg;
68 };
69 
70 struct eh_frame_fields {
71 	void		*cie_ops;
72 	void		*cie_ops_end;
73 	ptrdiff_t	cie_reloc;
74 	int		code_align;
75 	int		data_align;
76 	int		code_enc;
77 	void		*fde_ops;
78 	void		*fde_ops_end;
79 	ptrdiff_t	fde_reloc;
80 };
81 
82 _Unwind_Reason_Code
83 _Unw_very_boring_personality(int version, int actions, uint64_t exclass,
84 		struct _Unwind_Exception *exception_object,
85 		struct _Unwind_Context *ctx);
86 /*
87  * Starting withe an initialized context (from a ucontext)
88  * the following routines are sufficient to implement a non-destructive
89  * stack walk if modified to access the target processes memory. These
90  * routines refer to the local address of an item using names containing
91  * `data' names containing `reloc' give the correction to get target
92  * process location.
93  */
94 
95 /* ================== find function ====================== */
96 
97 /*
98  * Computes the func and fde fields using pc as the lookup key.
99  * Return is 0 or address of fde
100  *
101  * This is the only function that look into .eh_frame_hdr
102  */
103 void *_Unw_EhfhLookup(struct _Unwind_Context *ctx);
104 
105 /* =================== analyze function ================== */
106 
107 /*
108  * Fills in personality_fn and lsda fields of the context based
109  * the fde entry which must be valid and also partially unpacks
110  * fde and cie into *f
111  *
112  * This is one of two functions that look inside fde's
113  */
114 struct eh_frame_fields *_Unw_Decode_FDE(struct eh_frame_fields *f,
115 		struct _Unwind_Context *ctx);
116 
117 /*
118  * Computes register values at entry to function based on current
119  * register values, pc and fde values in a context
120  *
121  * This is the other function which looks inside fde's and
122  * the only one to look at CFA operations
123  *
124  * If 'f' is NULL (because no fde was found), a default calculation
125  * assuming an FP is done.
126  */
127 uint64_t _Unw_Rollback_Registers(struct eh_frame_fields *f,
128 		struct _Unwind_Context *ctx);
129 
130 /* ================= register propagation =============== */
131 
132 /*
133  * Fills in the current register context for the caller
134  * based on computed at-entry state of callee
135  */
136 void
137 _Unw_Propagate_Registers(struct _Unwind_Context *old_ctx,
138 		struct _Unwind_Context *new_ctx);
139 
140 /* ================================================= */
141 enum operand_desc {
142 	NO_OPR,
143 	ULEB128_FAC,
144 	ULEB128,
145 	ULEB128_SREG,
146 	SLEB128,
147 	SLEB128_FAC,
148 	ADDR,
149 	SIZE,
150 	ZTSTRING,
151 	UNUM6,
152 	UNUM6_CFAC,
153 	UNUM8,
154 	UNUM8_CFAC,
155 	UNUM16,
156 	UNUM16_CFAC,
157 	UNUM32,
158 	UNUM32_CFAC,
159 	UNUM64,
160 	SNUM8,
161 	SNUM16,
162 	SNUM32,
163 	SNUM64,
164 	BLOCK
165 };
166 
167 uint64_t _Unw_get_val(void **datap, ptrdiff_t reloc,
168 		enum operand_desc opr,
169 		int daf, int caf, int enc);
170 
171 #endif	/* _UNWIND_CONTEXT_H */
172