1 | /* libunwind - a platform-independent unwind library |
2 | Copyright (C) 2002-2004 Hewlett-Packard Co |
3 | Contributed by David Mosberger-Tang <davidm@hpl.hp.com> |
4 | |
5 | This file is part of libunwind. |
6 | |
7 | Permission is hereby granted, free of charge, to any person obtaining |
8 | a copy of this software and associated documentation files (the |
9 | "Software"), to deal in the Software without restriction, including |
10 | without limitation the rights to use, copy, modify, merge, publish, |
11 | distribute, sublicense, and/or sell copies of the Software, and to |
12 | permit persons to whom the Software is furnished to do so, subject to |
13 | the following conditions: |
14 | |
15 | The above copyright notice and this permission notice shall be |
16 | included in all copies or substantial portions of the Software. |
17 | |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
22 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
24 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
25 | |
26 | /* This file defines the runtime-support routines for dynamically |
27 | generated code. Even though it is implemented as part of libunwind, |
28 | it is logically separate from the interface to perform the actual |
29 | unwinding. In particular, this interface is always used in the |
30 | context of the unwind target, whereas the rest of the unwind API is |
31 | used in context of the process that is doing the unwind (which may be |
32 | a debugger running on another machine, for example). |
33 | |
34 | Note that the data-structures declared here server a dual purpose: |
35 | when a program registers a dynamically generated procedure, it uses |
36 | these structures directly. On the other hand, with remote-unwinding, |
37 | the data-structures are read from the remote process's memory and |
38 | translated into internalized versions. To facilitate remote-access, |
39 | the following rules should be followed in declaring these structures: |
40 | |
41 | (1) Declare a member as a pointer only if the the information the |
42 | member points to needs to be internalized as well (e.g., a |
43 | string representing a procedure name should be declared as |
44 | "const char *", but the instruction pointer should be declared |
45 | as unw_word_t). |
46 | |
47 | (2) Provide sufficient padding to ensure that no implicit padding |
48 | will be needed on any of the supported target architectures. For |
49 | the time being, padding data structures with the assumption that |
50 | sizeof (unw_word_t) == 8 should be sufficient. (Note: it's not |
51 | impossible to internalize structures with internal padding, but |
52 | it does make the process a bit harder). |
53 | |
54 | (3) Don't declare members that contain bitfields or floating-point |
55 | values. |
56 | |
57 | (4) Don't declare members with enumeration types. Declare them as |
58 | int32_t instead. */ |
59 | |
60 | typedef enum |
61 | { |
62 | UNW_DYN_STOP = 0, /* end-of-unwind-info marker */ |
63 | UNW_DYN_SAVE_REG, /* save register to another register */ |
64 | UNW_DYN_SPILL_FP_REL, /* frame-pointer-relative register spill */ |
65 | UNW_DYN_SPILL_SP_REL, /* stack-pointer-relative register spill */ |
66 | UNW_DYN_ADD, /* add constant value to a register */ |
67 | UNW_DYN_POP_FRAMES, /* drop one or more stack frames */ |
68 | UNW_DYN_LABEL_STATE, /* name the current state */ |
69 | UNW_DYN_COPY_STATE, /* set the region's entry-state */ |
70 | UNW_DYN_ALIAS /* get unwind info from an alias */ |
71 | } |
72 | unw_dyn_operation_t; |
73 | |
74 | typedef enum |
75 | { |
76 | UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */ |
77 | UNW_INFO_FORMAT_TABLE, /* unw_dyn_table_t */ |
78 | UNW_INFO_FORMAT_REMOTE_TABLE, /* unw_dyn_remote_table_t */ |
79 | UNW_INFO_FORMAT_ARM_EXIDX, /* ARM specific unwind info */ |
80 | UNW_INFO_FORMAT_IP_OFFSET, /* Like UNW_INFO_FORMAT_REMOTE_TABLE, but |
81 | table entries are considered |
82 | relative to di->start_ip, rather |
83 | than di->segbase */ |
84 | } |
85 | unw_dyn_info_format_t; |
86 | |
87 | typedef struct unw_dyn_op |
88 | { |
89 | int8_t tag; /* what operation? */ |
90 | int8_t qp; /* qualifying predicate register */ |
91 | int16_t reg; /* what register */ |
92 | int32_t when; /* when does it take effect? */ |
93 | unw_word_t val; /* auxiliary value */ |
94 | } |
95 | unw_dyn_op_t; |
96 | |
97 | typedef struct unw_dyn_region_info |
98 | { |
99 | struct unw_dyn_region_info *next; /* linked list of regions */ |
100 | int32_t insn_count; /* region length (# of instructions) */ |
101 | uint32_t op_count; /* length of op-array */ |
102 | unw_dyn_op_t op[1]; /* variable-length op-array */ |
103 | } |
104 | unw_dyn_region_info_t; |
105 | |
106 | typedef struct unw_dyn_proc_info |
107 | { |
108 | unw_word_t name_ptr; /* address of human-readable procedure name */ |
109 | unw_word_t handler; /* address of personality routine */ |
110 | uint32_t flags; |
111 | int32_t pad0; |
112 | unw_dyn_region_info_t *regions; |
113 | } |
114 | unw_dyn_proc_info_t; |
115 | |
116 | typedef struct unw_dyn_table_info |
117 | { |
118 | unw_word_t name_ptr; /* addr. of table name (e.g., library name) */ |
119 | unw_word_t segbase; /* segment base */ |
120 | unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */ |
121 | unw_word_t *table_data; |
122 | } |
123 | unw_dyn_table_info_t; |
124 | |
125 | typedef struct unw_dyn_remote_table_info |
126 | { |
127 | unw_word_t name_ptr; /* addr. of table name (e.g., library name) */ |
128 | unw_word_t segbase; /* segment base */ |
129 | unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */ |
130 | unw_word_t table_data; |
131 | } |
132 | unw_dyn_remote_table_info_t; |
133 | |
134 | typedef struct unw_dyn_info |
135 | { |
136 | /* doubly-linked list of dyn-info structures: */ |
137 | struct unw_dyn_info *next; |
138 | struct unw_dyn_info *prev; |
139 | unw_word_t start_ip; /* first IP covered by this entry */ |
140 | unw_word_t end_ip; /* first IP NOT covered by this entry */ |
141 | unw_word_t gp; /* global-pointer in effect for this entry */ |
142 | int32_t format; /* real type: unw_dyn_info_format_t */ |
143 | int32_t pad; |
144 | union |
145 | { |
146 | unw_dyn_proc_info_t pi; |
147 | unw_dyn_table_info_t ti; |
148 | unw_dyn_remote_table_info_t rti; |
149 | } |
150 | u; |
151 | } |
152 | unw_dyn_info_t; |
153 | |
154 | typedef struct unw_dyn_info_list |
155 | { |
156 | uint32_t version; |
157 | uint32_t generation; |
158 | unw_dyn_info_t *first; |
159 | } |
160 | unw_dyn_info_list_t; |
161 | |
162 | /* Return the size (in bytes) of an unw_dyn_region_info_t structure that can |
163 | hold OP_COUNT ops. */ |
164 | #define _U_dyn_region_info_size(op_count) \ |
165 | ((char *) (((unw_dyn_region_info_t *) NULL)->op + (op_count)) \ |
166 | - (char *) NULL) |
167 | |
168 | /* Register the unwind info for a single procedure. |
169 | This routine is NOT signal-safe. */ |
170 | extern void _U_dyn_register (unw_dyn_info_t *); |
171 | |
172 | /* Cancel the unwind info for a single procedure. |
173 | This routine is NOT signal-safe. */ |
174 | extern void _U_dyn_cancel (unw_dyn_info_t *); |
175 | |
176 | |
177 | /* Convenience routines. */ |
178 | |
179 | #define _U_dyn_op(_tag, _qp, _when, _reg, _val) \ |
180 | ((unw_dyn_op_t) { (_tag), (_qp), (_reg), (_when), (_val) }) |
181 | |
182 | #define _U_dyn_op_save_reg(op, qp, when, reg, dst) \ |
183 | (*(op) = _U_dyn_op (UNW_DYN_SAVE_REG, (qp), (when), (reg), (dst))) |
184 | |
185 | #define _U_dyn_op_spill_fp_rel(op, qp, when, reg, offset) \ |
186 | (*(op) = _U_dyn_op (UNW_DYN_SPILL_FP_REL, (qp), (when), (reg), \ |
187 | (offset))) |
188 | |
189 | #define _U_dyn_op_spill_sp_rel(op, qp, when, reg, offset) \ |
190 | (*(op) = _U_dyn_op (UNW_DYN_SPILL_SP_REL, (qp), (when), (reg), \ |
191 | (offset))) |
192 | |
193 | #define _U_dyn_op_add(op, qp, when, reg, value) \ |
194 | (*(op) = _U_dyn_op (UNW_DYN_ADD, (qp), (when), (reg), (value))) |
195 | |
196 | #define _U_dyn_op_pop_frames(op, qp, when, num_frames) \ |
197 | (*(op) = _U_dyn_op (UNW_DYN_POP_FRAMES, (qp), (when), 0, (num_frames))) |
198 | |
199 | #define _U_dyn_op_label_state(op, label) \ |
200 | (*(op) = _U_dyn_op (UNW_DYN_LABEL_STATE, _U_QP_TRUE, -1, 0, (label))) |
201 | |
202 | #define _U_dyn_op_copy_state(op, label) \ |
203 | (*(op) = _U_dyn_op (UNW_DYN_COPY_STATE, _U_QP_TRUE, -1, 0, (label))) |
204 | |
205 | #define _U_dyn_op_alias(op, qp, when, addr) \ |
206 | (*(op) = _U_dyn_op (UNW_DYN_ALIAS, (qp), (when), 0, (addr))) |
207 | |
208 | #define _U_dyn_op_stop(op) \ |
209 | (*(op) = _U_dyn_op (UNW_DYN_STOP, _U_QP_TRUE, -1, 0, 0)) |
210 | |
211 | /* The target-dependent qualifying predicate which is always TRUE. On |
212 | IA-64, that's p0 (0), on non-predicated architectures, the value is |
213 | ignored. */ |
214 | #define _U_QP_TRUE _U_TDEP_QP_TRUE |
215 | |