summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc/amd64/unwind/unwind_context.h
blob: 9ec0eefc8c7ab4305a1a1f8d5c72d88026e25eb8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Public interface for AMD64 Unwind context
 */

#ifndef _UNWIND_CONTEXT_H
#define	_UNWIND_CONTEXT_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

/*
 * implementation of context structure
 *
 * Register arrays are indexed as specified in reg_num.h
 */
struct _Unwind_Context {
	uint64_t	entry_regs[16];
	uint64_t	current_regs[16];
	uint64_t	cfa;
	uint64_t	pc;
	uint64_t	ra;
	void		*fde;
	_Unwind_Personality_Fn	pfn;
	uint64_t	func;
	void		*lsda;
	uint64_t	range;
};

enum register_rule {
	undefined_rule,
	same_value_rule,	/* target_reg = target_reg */
	offset_rule,		/* target_reg = *(offset + CFA) */
	is_offset_rule,		/* target_reg = offset + CFA */
	register_rule,		/* target_reg = offset + source_reg */
	constant_rule,		/* target_reg = offset */
	indirect_rule		/* target_reg = *(offset + source_reg) */
};

struct register_state {
	uint64_t	offset;
	enum register_rule	rule;
	unsigned char	source_reg;
};

struct eh_frame_fields {
	void		*cie_ops;
	void		*cie_ops_end;
	ptrdiff_t	cie_reloc;
	int		code_align;
	int		data_align;
	int		code_enc;
	void		*fde_ops;
	void		*fde_ops_end;
	ptrdiff_t	fde_reloc;
};

_Unwind_Reason_Code
_Unw_very_boring_personality(int version, int actions, uint64_t exclass,
		struct _Unwind_Exception *exception_object,
		struct _Unwind_Context *ctx);
/*
 * Starting withe an initialized context (from a ucontext)
 * the following routines are sufficient to implement a non-destructive
 * stack walk if modified to access the target processes memory. These
 * routines refer to the local address of an item using names containing
 * `data' names containing `reloc' give the correction to get target
 * process location.
 */

/* ================== find function ====================== */

/*
 * Computes the func and fde fields using pc as the lookup key.
 * Return is 0 or address of fde
 *
 * This is the only function that look into .eh_frame_hdr
 */
void *_Unw_EhfhLookup(struct _Unwind_Context *ctx);

/* =================== analyze function ================== */

/*
 * Fills in personality_fn and lsda fields of the context based
 * the fde entry which must be valid and also partially unpacks
 * fde and cie into *f
 *
 * This is one of two functions that look inside fde's
 */
struct eh_frame_fields *_Unw_Decode_FDE(struct eh_frame_fields *f,
		struct _Unwind_Context *ctx);

/*
 * Computes register values at entry to function based on current
 * register values, pc and fde values in a context
 *
 * This is the other function which looks inside fde's and
 * the only one to look at CFA operations
 *
 * If 'f' is NULL (because no fde was found), a default calculation
 * assuming an FP is done.
 */
uint64_t _Unw_Rollback_Registers(struct eh_frame_fields *f,
		struct _Unwind_Context *ctx);

/* ================= register propagation =============== */

/*
 * Fills in the current register context for the caller
 * based on computed at-entry state of callee
 */
void
_Unw_Propagate_Registers(struct _Unwind_Context *old_ctx,
		struct _Unwind_Context *new_ctx);

/* ================================================= */
enum operand_desc {
	NO_OPR,
	ULEB128_FAC,
	ULEB128,
	ULEB128_SREG,
	SLEB128,
	SLEB128_FAC,
	ADDR,
	SIZE,
	ZTSTRING,
	UNUM6,
	UNUM6_CFAC,
	UNUM8,
	UNUM8_CFAC,
	UNUM16,
	UNUM16_CFAC,
	UNUM32,
	UNUM32_CFAC,
	UNUM64,
	SNUM8,
	SNUM16,
	SNUM32,
	SNUM64,
	BLOCK
};

uint64_t _Unw_get_val(void **datap, ptrdiff_t reloc,
		enum operand_desc opr,
		int daf, int caf, int enc);

#endif	/* _UNWIND_CONTEXT_H */