blob: 6f2fab81394dc977d6563ae3f39a38a54460b4dd [file] [log] [blame]
hp.com!davidmeb51b422003-12-20 11:43:08 +00001/* libunwind - a platform-independent unwind library
hp.com!davidmf9b7af52005-05-20 09:48:08 +00002 Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
hp.com!davidmeb51b422003-12-20 11:43:08 +00003 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5This file is part of libunwind.
6
7Permission is hereby granted, free of charge, to any person obtaining
8a copy of this software and associated documentation files (the
9"Software"), to deal in the Software without restriction, including
10without limitation the rights to use, copy, modify, merge, publish,
11distribute, sublicense, and/or sell copies of the Software, and to
12permit persons to whom the Software is furnished to do so, subject to
13the following conditions:
14
15The above copyright notice and this permission notice shall be
16included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
25
26#ifndef dwarf_h
27#define dwarf_h
28
hp.com!davidmf9b7af52005-05-20 09:48:08 +000029#include <libunwind.h>
hp.com!davidmeb51b422003-12-20 11:43:08 +000030
31struct dwarf_cursor; /* forward-declaration */
32
33#include "dwarf-config.h"
34
35/* DWARF expression opcodes. */
36
37typedef enum
38 {
39 DW_OP_addr = 0x03,
40 DW_OP_deref = 0x06,
41 DW_OP_const1u = 0x08,
42 DW_OP_const1s = 0x09,
43 DW_OP_const2u = 0x0a,
44 DW_OP_const2s = 0x0b,
45 DW_OP_const4u = 0x0c,
46 DW_OP_const4s = 0x0d,
47 DW_OP_const8u = 0x0e,
48 DW_OP_const8s = 0x0f,
49 DW_OP_constu = 0x10,
50 DW_OP_consts = 0x11,
51 DW_OP_dup = 0x12,
52 DW_OP_drop = 0x13,
53 DW_OP_over = 0x14,
54 DW_OP_pick = 0x15,
55 DW_OP_swap = 0x16,
56 DW_OP_rot = 0x17,
57 DW_OP_xderef = 0x18,
58 DW_OP_abs = 0x19,
59 DW_OP_and = 0x1a,
60 DW_OP_div = 0x1b,
61 DW_OP_minus = 0x1c,
62 DW_OP_mod = 0x1d,
63 DW_OP_mul = 0x1e,
64 DW_OP_neg = 0x1f,
65 DW_OP_not = 0x20,
66 DW_OP_or = 0x21,
67 DW_OP_plus = 0x22,
68 DW_OP_plus_uconst = 0x23,
69 DW_OP_shl = 0x24,
70 DW_OP_shr = 0x25,
71 DW_OP_shra = 0x26,
72 DW_OP_xor = 0x27,
73 DW_OP_skip = 0x2f,
74 DW_OP_bra = 0x28,
75 DW_OP_eq = 0x29,
76 DW_OP_ge = 0x2a,
77 DW_OP_gt = 0x2b,
78 DW_OP_le = 0x2c,
79 DW_OP_lt = 0x2d,
80 DW_OP_ne = 0x2e,
81 DW_OP_lit0 = 0x30,
82 DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_lit4, DW_OP_lit5,
83 DW_OP_lit6, DW_OP_lit7, DW_OP_lit8, DW_OP_lit9, DW_OP_lit10,
84 DW_OP_lit11, DW_OP_lit12, DW_OP_lit13, DW_OP_lit14, DW_OP_lit15,
85 DW_OP_lit16, DW_OP_lit17, DW_OP_lit18, DW_OP_lit19, DW_OP_lit20,
86 DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24, DW_OP_lit25,
87 DW_OP_lit26, DW_OP_lit27, DW_OP_lit28, DW_OP_lit29, DW_OP_lit30,
88 DW_OP_lit31,
89 DW_OP_reg0 = 0x50,
90 DW_OP_reg1, DW_OP_reg2, DW_OP_reg3, DW_OP_reg4, DW_OP_reg5,
91 DW_OP_reg6, DW_OP_reg7, DW_OP_reg8, DW_OP_reg9, DW_OP_reg10,
92 DW_OP_reg11, DW_OP_reg12, DW_OP_reg13, DW_OP_reg14, DW_OP_reg15,
93 DW_OP_reg16, DW_OP_reg17, DW_OP_reg18, DW_OP_reg19, DW_OP_reg20,
94 DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24, DW_OP_reg25,
95 DW_OP_reg26, DW_OP_reg27, DW_OP_reg28, DW_OP_reg29, DW_OP_reg30,
96 DW_OP_reg31,
97 DW_OP_breg0 = 0x70,
98 DW_OP_breg1, DW_OP_breg2, DW_OP_breg3, DW_OP_breg4, DW_OP_breg5,
99 DW_OP_breg6, DW_OP_breg7, DW_OP_breg8, DW_OP_breg9, DW_OP_breg10,
100 DW_OP_breg11, DW_OP_breg12, DW_OP_breg13, DW_OP_breg14, DW_OP_breg15,
101 DW_OP_breg16, DW_OP_breg17, DW_OP_breg18, DW_OP_breg19, DW_OP_breg20,
102 DW_OP_breg21, DW_OP_breg22, DW_OP_breg23, DW_OP_breg24, DW_OP_breg25,
103 DW_OP_breg26, DW_OP_breg27, DW_OP_breg28, DW_OP_breg29, DW_OP_breg30,
104 DW_OP_breg31,
105 DW_OP_regx = 0x90,
106 DW_OP_fbreg = 0x91,
107 DW_OP_bregx = 0x92,
108 DW_OP_piece = 0x93,
109 DW_OP_deref_size = 0x94,
110 DW_OP_xderef_size = 0x95,
111 DW_OP_nop = 0x96,
112 DW_OP_push_object_address = 0x97,
113 DW_OP_call2 = 0x98,
114 DW_OP_call4 = 0x99,
115 DW_OP_call_ref = 0x9a,
116 DW_OP_lo_user = 0xe0,
117 DW_OP_hi_user = 0xff
118 }
119dwarf_expr_op_t;
120
121#define DWARF_CIE_VERSION 3 /* GCC emits version 1??? */
122
123#define DWARF_CFA_OPCODE_MASK 0xc0
124#define DWARF_CFA_OPERAND_MASK 0x3f
125
126typedef enum
127 {
128 DW_CFA_advance_loc = 0x40,
129 DW_CFA_offset = 0x80,
130 DW_CFA_restore = 0xc0,
131 DW_CFA_nop = 0x00,
132 DW_CFA_set_loc = 0x01,
133 DW_CFA_advance_loc1 = 0x02,
134 DW_CFA_advance_loc2 = 0x03,
135 DW_CFA_advance_loc4 = 0x04,
136 DW_CFA_offset_extended = 0x05,
137 DW_CFA_restore_extended = 0x06,
138 DW_CFA_undefined = 0x07,
139 DW_CFA_same_value = 0x08,
140 DW_CFA_register = 0x09,
141 DW_CFA_remember_state = 0x0a,
142 DW_CFA_restore_state = 0x0b,
143 DW_CFA_def_cfa = 0x0c,
144 DW_CFA_def_cfa_register = 0x0d,
145 DW_CFA_def_cfa_offset = 0x0e,
146 DW_CFA_def_cfa_expression = 0x0f,
mostang.com!davidmadeb9b52005-05-03 09:13:17 +0000147 DW_CFA_expression = 0x10,
hp.com!davidmeb51b422003-12-20 11:43:08 +0000148 DW_CFA_offset_extended_sf = 0x11,
149 DW_CFA_def_cfa_sf = 0x12,
150 DW_CFA_def_cfa_offset_sf = 0x13,
151 DW_CFA_lo_user = 0x1c,
152 DW_CFA_MIPS_advance_loc8 = 0x1d,
153 DW_CFA_GNU_window_save = 0x2d,
154 DW_CFA_GNU_args_size = 0x2e,
155 DW_CFA_GNU_negative_offset_extended = 0x2f,
156 DW_CFA_hi_user = 0x3c
157 }
158dwarf_cfa_t;
159
160/* DWARF Pointer-Encoding (PEs).
161
162 Pointer-Encodings were invented for the GCC exception-handling
163 support for C++, but they represent a rather generic way of
164 describing the format in which an address/pointer is stored and
165 hence we include the definitions here, in the main dwarf.h file.
166 The Pointer-Encoding format is partially documented in Linux Base
167 Spec v1.3 (http://www.linuxbase.org/spec/). The rest is reverse
168 engineered from GCC.
169
170*/
171#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
172#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
173/* Flag bit. If set, the resulting pointer is the address of the word
174 that contains the final address. */
175#define DW_EH_PE_indirect 0x80
176
177/* Pointer-encoding formats: */
178#define DW_EH_PE_omit 0xff
179#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
180#define DW_EH_PE_uleb128 0x01 /* unsigned LE base-128 value */
181#define DW_EH_PE_udata2 0x02 /* unsigned 16-bit value */
182#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
183#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
184#define DW_EH_PE_sleb128 0x09 /* signed LE base-128 value */
185#define DW_EH_PE_sdata2 0x0a /* signed 16-bit value */
186#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
187#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
188
189/* Pointer-encoding application: */
190#define DW_EH_PE_absptr 0x00 /* absolute value */
191#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
192#define DW_EH_PE_textrel 0x20 /* text-relative (GCC-specific???) */
193#define DW_EH_PE_datarel 0x30 /* data-relative */
194/* The following are not documented by LSB v1.3, yet they are used by
195 GCC, presumably they aren't documented by LSB since they aren't
196 used on Linux: */
197#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
198#define DW_EH_PE_aligned 0x50 /* aligned pointer */
199
hp.com!davidmeb51b422003-12-20 11:43:08 +0000200typedef enum
201 {
202 DWARF_WHERE_UNDEF, /* register isn't saved at all */
203 DWARF_WHERE_SAME, /* register has same value as in prev. frame */
204 DWARF_WHERE_CFAREL, /* register saved at CFA-relative address */
205 DWARF_WHERE_REG, /* register saved in another register */
206 DWARF_WHERE_EXPR, /* register saved */
207 }
208dwarf_where_t;
209
210typedef struct
211 {
212 dwarf_where_t where; /* how is the register saved? */
213 unw_word_t val; /* where it's saved */
214 }
215dwarf_save_loc_t;
216
217/* For uniformity, we'd like to treat the CFA save-location like any
218 other register save-location, but this doesn't quite work, because
219 the CFA can be expressed as a (REGISTER,OFFSET) pair. To handle
220 this, we use two dwarf_save_loc structures to describe the CFA.
221 The first one (CFA_REG_COLUMN), tells us where the CFA is saved.
222 In the case of DWARF_WHERE_EXPR, the CFA is defined by a DWARF
223 location expression whose address is given by member "val". In the
224 case of DWARF_WHERE_REG, member "val" gives the number of the
225 base-register and the "val" member of DWARF_CFA_OFF_COLUMN gives
226 the offset value. */
227#define DWARF_CFA_REG_COLUMN DWARF_NUM_PRESERVED_REGS
228#define DWARF_CFA_OFF_COLUMN (DWARF_NUM_PRESERVED_REGS + 1)
229
230typedef struct dwarf_reg_state
231 {
232 struct dwarf_reg_state *next; /* for rs_stack */
233 dwarf_save_loc_t reg[DWARF_NUM_PRESERVED_REGS + 2];
234 }
235dwarf_reg_state_t;
236
mostang.com!davidmadeb9b52005-05-03 09:13:17 +0000237typedef struct dwarf_cie_info
238 {
239 unw_word_t cie_instr_start; /* start addr. of CIE "initial_instructions" */
240 unw_word_t cie_instr_end; /* end addr. of CIE "initial_instructions" */
241 unw_word_t fde_instr_start; /* start addr. of FDE "instructions" */
242 unw_word_t fde_instr_end; /* end addr. of FDE "instructions" */
243 unw_word_t code_align; /* code-alignment factor */
244 unw_word_t data_align; /* data-alignment factor */
245 unw_word_t ret_addr_column; /* column of return-address register */
246 unw_word_t handler; /* address of personality-routine */
247 uint16_t abi;
248 uint16_t tag;
249 uint8_t fde_encoding;
250 uint8_t lsda_encoding;
251 unsigned int sized_augmentation : 1;
252 unsigned int have_abi_marker : 1;
253 }
254dwarf_cie_info_t;
255
hp.com!davidmeb51b422003-12-20 11:43:08 +0000256typedef struct dwarf_state_record
257 {
258 unsigned char fde_encoding;
259 unw_word_t args_size;
260
261 dwarf_reg_state_t rs_initial; /* reg-state after CIE instructions */
262 dwarf_reg_state_t rs_current; /* current reg-state */
263 }
264dwarf_state_record_t;
265
266typedef struct dwarf_cursor
267 {
268 void *as_arg; /* argument to address-space callbacks */
269 unw_addr_space_t as; /* reference to per-address-space info */
270
271 unw_word_t cfa; /* canonical frame address; aka frame-/stack-pointer */
272 unw_word_t ip; /* instruction pointer */
273 unw_word_t args_size; /* size of arguments */
274 unw_word_t ret_addr_column; /* column for return-address */
mostang.com!davidmadeb9b52005-05-03 09:13:17 +0000275 unw_word_t eh_args[UNW_TDEP_NUM_EH_REGS];
276 unsigned int eh_valid_mask;
hp.com!davidmeb51b422003-12-20 11:43:08 +0000277
278 dwarf_loc_t loc[DWARF_NUM_PRESERVED_REGS];
279
280 unsigned int pi_valid :1; /* is proc_info valid? */
281 unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
282 unw_proc_info_t pi; /* info about current procedure */
283 }
284dwarf_cursor_t;
285
286/* Convenience macros: */
287#define dwarf_init UNW_ARCH_OBJ (dwarf_init)
288#define dwarf_find_proc_info UNW_OBJ (dwarf_find_proc_info)
289#define dwarf_search_unwind_table UNW_OBJ (dwarf_search_unwind_table)
290#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info)
291#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info)
292#define dwarf_eval_expr UNW_OBJ (dwarf_eval_expr)
mostang.com!davidmadeb9b52005-05-03 09:13:17 +0000293#define dwarf_extract_proc_info_from_fde \
294 UNW_OBJ (dwarf_extract_proc_info_from_fde)
hp.com!davidmeb51b422003-12-20 11:43:08 +0000295#define dwarf_find_save_locs UNW_OBJ (dwarf_find_save_locs)
296#define dwarf_create_state_record UNW_OBJ (dwarf_create_state_record)
297#define dwarf_make_proc_info UNW_OBJ (dwarf_make_proc_info)
298#define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer)
299#define dwarf_step UNW_OBJ (dwarf_step)
300
mostang.com!davidmb9d2cc72003-12-21 07:57:42 +0000301extern int dwarf_init (void);
302extern int dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
303 unw_proc_info_t *pi,
304 int need_unwind_info, void *arg);
305extern int dwarf_search_unwind_table (unw_addr_space_t as,
306 unw_word_t ip,
307 unw_dyn_info_t *di,
308 unw_proc_info_t *pi,
309 int need_unwind_info, void *arg);
310extern void dwarf_put_unwind_info (unw_addr_space_t as,
311 unw_proc_info_t *pi, void *arg);
312extern int dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr,
313 unw_word_t len, unw_word_t *valp,
314 int *is_register);
mostang.com!davidmadeb9b52005-05-03 09:13:17 +0000315extern int dwarf_extract_proc_info_from_fde (unw_addr_space_t as,
316 unw_accessors_t *a,
317 unw_word_t *fde_addr,
318 unw_proc_info_t *pi,
319 int need_unwind_info,
320 void *arg);
mostang.com!davidmb9d2cc72003-12-21 07:57:42 +0000321extern int dwarf_find_save_locs (struct dwarf_cursor *c);
322extern int dwarf_create_state_record (struct dwarf_cursor *c,
323 dwarf_state_record_t *sr);
324extern int dwarf_make_proc_info (struct dwarf_cursor *c);
325extern int dwarf_read_encoded_pointer (unw_addr_space_t as,
326 unw_accessors_t *a,
327 unw_word_t *addr,
328 unsigned char encoding,
mostang.com!davidmadeb9b52005-05-03 09:13:17 +0000329 const unw_proc_info_t *pi,
mostang.com!davidmb9d2cc72003-12-21 07:57:42 +0000330 unw_word_t *valp, void *arg);
331extern int dwarf_step (struct dwarf_cursor *c);
hp.com!davidmeb51b422003-12-20 11:43:08 +0000332
333#endif /* dwarf_h */