1/* libunwind - a platform-independent unwind library
2 Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
3 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
29#include <libunwind.h>
30
31struct dwarf_cursor; /* forward-declaration */
32struct elf_dyn_info;
33
34#include "dwarf-config.h"
35
36#ifdef HAVE_CONFIG_H
37# include "config.h"
38#endif
39
40#ifndef UNW_REMOTE_ONLY
41 #if defined(HAVE_LINK_H)
42 #include <link.h>
43 #elif defined(HAVE_SYS_LINK_H)
44 #include <sys/link.h>
45 #else
46 #error Could not find <link.h>
47 #endif
48#endif
49
50#include <pthread.h>
51
52/* DWARF expression opcodes. */
53
54typedef enum
55 {
56 DW_OP_addr = 0x03,
57 DW_OP_deref = 0x06,
58 DW_OP_const1u = 0x08,
59 DW_OP_const1s = 0x09,
60 DW_OP_const2u = 0x0a,
61 DW_OP_const2s = 0x0b,
62 DW_OP_const4u = 0x0c,
63 DW_OP_const4s = 0x0d,
64 DW_OP_const8u = 0x0e,
65 DW_OP_const8s = 0x0f,
66 DW_OP_constu = 0x10,
67 DW_OP_consts = 0x11,
68 DW_OP_dup = 0x12,
69 DW_OP_drop = 0x13,
70 DW_OP_over = 0x14,
71 DW_OP_pick = 0x15,
72 DW_OP_swap = 0x16,
73 DW_OP_rot = 0x17,
74 DW_OP_xderef = 0x18,
75 DW_OP_abs = 0x19,
76 DW_OP_and = 0x1a,
77 DW_OP_div = 0x1b,
78 DW_OP_minus = 0x1c,
79 DW_OP_mod = 0x1d,
80 DW_OP_mul = 0x1e,
81 DW_OP_neg = 0x1f,
82 DW_OP_not = 0x20,
83 DW_OP_or = 0x21,
84 DW_OP_plus = 0x22,
85 DW_OP_plus_uconst = 0x23,
86 DW_OP_shl = 0x24,
87 DW_OP_shr = 0x25,
88 DW_OP_shra = 0x26,
89 DW_OP_xor = 0x27,
90 DW_OP_skip = 0x2f,
91 DW_OP_bra = 0x28,
92 DW_OP_eq = 0x29,
93 DW_OP_ge = 0x2a,
94 DW_OP_gt = 0x2b,
95 DW_OP_le = 0x2c,
96 DW_OP_lt = 0x2d,
97 DW_OP_ne = 0x2e,
98 DW_OP_lit0 = 0x30,
99 DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_lit4, DW_OP_lit5,
100 DW_OP_lit6, DW_OP_lit7, DW_OP_lit8, DW_OP_lit9, DW_OP_lit10,
101 DW_OP_lit11, DW_OP_lit12, DW_OP_lit13, DW_OP_lit14, DW_OP_lit15,
102 DW_OP_lit16, DW_OP_lit17, DW_OP_lit18, DW_OP_lit19, DW_OP_lit20,
103 DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24, DW_OP_lit25,
104 DW_OP_lit26, DW_OP_lit27, DW_OP_lit28, DW_OP_lit29, DW_OP_lit30,
105 DW_OP_lit31,
106 DW_OP_reg0 = 0x50,
107 DW_OP_reg1, DW_OP_reg2, DW_OP_reg3, DW_OP_reg4, DW_OP_reg5,
108 DW_OP_reg6, DW_OP_reg7, DW_OP_reg8, DW_OP_reg9, DW_OP_reg10,
109 DW_OP_reg11, DW_OP_reg12, DW_OP_reg13, DW_OP_reg14, DW_OP_reg15,
110 DW_OP_reg16, DW_OP_reg17, DW_OP_reg18, DW_OP_reg19, DW_OP_reg20,
111 DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24, DW_OP_reg25,
112 DW_OP_reg26, DW_OP_reg27, DW_OP_reg28, DW_OP_reg29, DW_OP_reg30,
113 DW_OP_reg31,
114 DW_OP_breg0 = 0x70,
115 DW_OP_breg1, DW_OP_breg2, DW_OP_breg3, DW_OP_breg4, DW_OP_breg5,
116 DW_OP_breg6, DW_OP_breg7, DW_OP_breg8, DW_OP_breg9, DW_OP_breg10,
117 DW_OP_breg11, DW_OP_breg12, DW_OP_breg13, DW_OP_breg14, DW_OP_breg15,
118 DW_OP_breg16, DW_OP_breg17, DW_OP_breg18, DW_OP_breg19, DW_OP_breg20,
119 DW_OP_breg21, DW_OP_breg22, DW_OP_breg23, DW_OP_breg24, DW_OP_breg25,
120 DW_OP_breg26, DW_OP_breg27, DW_OP_breg28, DW_OP_breg29, DW_OP_breg30,
121 DW_OP_breg31,
122 DW_OP_regx = 0x90,
123 DW_OP_fbreg = 0x91,
124 DW_OP_bregx = 0x92,
125 DW_OP_piece = 0x93,
126 DW_OP_deref_size = 0x94,
127 DW_OP_xderef_size = 0x95,
128 DW_OP_nop = 0x96,
129 DW_OP_push_object_address = 0x97,
130 DW_OP_call2 = 0x98,
131 DW_OP_call4 = 0x99,
132 DW_OP_call_ref = 0x9a,
133 DW_OP_lo_user = 0xe0,
134 DW_OP_hi_user = 0xff
135 }
136dwarf_expr_op_t;
137
138#define DWARF_CIE_VERSION 3
139#define DWARF_CIE_VERSION_MAX 4
140
141#define DWARF_CFA_OPCODE_MASK 0xc0
142#define DWARF_CFA_OPERAND_MASK 0x3f
143
144typedef enum
145 {
146 DW_CFA_advance_loc = 0x40,
147 DW_CFA_offset = 0x80,
148 DW_CFA_restore = 0xc0,
149 DW_CFA_nop = 0x00,
150 DW_CFA_set_loc = 0x01,
151 DW_CFA_advance_loc1 = 0x02,
152 DW_CFA_advance_loc2 = 0x03,
153 DW_CFA_advance_loc4 = 0x04,
154 DW_CFA_offset_extended = 0x05,
155 DW_CFA_restore_extended = 0x06,
156 DW_CFA_undefined = 0x07,
157 DW_CFA_same_value = 0x08,
158 DW_CFA_register = 0x09,
159 DW_CFA_remember_state = 0x0a,
160 DW_CFA_restore_state = 0x0b,
161 DW_CFA_def_cfa = 0x0c,
162 DW_CFA_def_cfa_register = 0x0d,
163 DW_CFA_def_cfa_offset = 0x0e,
164 DW_CFA_def_cfa_expression = 0x0f,
165 DW_CFA_expression = 0x10,
166 DW_CFA_offset_extended_sf = 0x11,
167 DW_CFA_def_cfa_sf = 0x12,
168 DW_CFA_def_cfa_offset_sf = 0x13,
169 DW_CFA_val_expression = 0x16,
170 DW_CFA_lo_user = 0x1c,
171 DW_CFA_MIPS_advance_loc8 = 0x1d,
172 DW_CFA_GNU_window_save = 0x2d,
173 DW_CFA_GNU_args_size = 0x2e,
174 DW_CFA_GNU_negative_offset_extended = 0x2f,
175 DW_CFA_hi_user = 0x3c
176 }
177dwarf_cfa_t;
178
179/* DWARF Pointer-Encoding (PEs).
180
181 Pointer-Encodings were invented for the GCC exception-handling
182 support for C++, but they represent a rather generic way of
183 describing the format in which an address/pointer is stored and
184 hence we include the definitions here, in the main dwarf.h file.
185 The Pointer-Encoding format is partially documented in Linux Base
186 Spec v1.3 (http://www.linuxbase.org/spec/). The rest is reverse
187 engineered from GCC.
188
189*/
190#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
191#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
192/* Flag bit. If set, the resulting pointer is the address of the word
193 that contains the final address. */
194#define DW_EH_PE_indirect 0x80
195
196/* Pointer-encoding formats: */
197#define DW_EH_PE_omit 0xff
198#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
199#define DW_EH_PE_uleb128 0x01 /* unsigned LE base-128 value */
200#define DW_EH_PE_udata2 0x02 /* unsigned 16-bit value */
201#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
202#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
203#define DW_EH_PE_sleb128 0x09 /* signed LE base-128 value */
204#define DW_EH_PE_sdata2 0x0a /* signed 16-bit value */
205#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
206#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
207
208/* Pointer-encoding application: */
209#define DW_EH_PE_absptr 0x00 /* absolute value */
210#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
211#define DW_EH_PE_textrel 0x20 /* text-relative (GCC-specific???) */
212#define DW_EH_PE_datarel 0x30 /* data-relative */
213/* The following are not documented by LSB v1.3, yet they are used by
214 GCC, presumably they aren't documented by LSB since they aren't
215 used on Linux: */
216#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
217#define DW_EH_PE_aligned 0x50 /* aligned pointer */
218
219extern struct mempool dwarf_reg_state_pool;
220extern struct mempool dwarf_cie_info_pool;
221
222typedef enum
223 {
224 DWARF_WHERE_UNDEF, /* register isn't saved at all */
225 DWARF_WHERE_SAME, /* register has same value as in prev. frame */
226 DWARF_WHERE_CFAREL, /* register saved at CFA-relative address */
227 DWARF_WHERE_REG, /* register saved in another register */
228 DWARF_WHERE_EXPR, /* register saved */
229 DWARF_WHERE_VAL_EXPR, /* register has computed value */
230 }
231dwarf_where_t;
232
233/* For uniformity, we'd like to treat the CFA save-location like any
234 other register save-location, but this doesn't quite work, because
235 the CFA can be expressed as a (REGISTER,OFFSET) pair. To handle
236 this, we use two dwarf_save_loc structures to describe the CFA.
237 The first one (CFA_REG_COLUMN), tells us where the CFA is saved.
238 In the case of DWARF_WHERE_EXPR, the CFA is defined by a DWARF
239 location expression whose address is given by member "val". In the
240 case of DWARF_WHERE_REG, member "val" gives the number of the
241 base-register and the "val" member of DWARF_CFA_OFF_COLUMN gives
242 the offset value. */
243#define DWARF_CFA_REG_COLUMN DWARF_NUM_PRESERVED_REGS
244#define DWARF_CFA_OFF_COLUMN (DWARF_NUM_PRESERVED_REGS + 1)
245
246typedef struct dwarf_reg_only_state
247 {
248 char where[DWARF_NUM_PRESERVED_REGS + 2]; /* how is the register saved? */
249 unw_word_t val[DWARF_NUM_PRESERVED_REGS + 2]; /* where it's saved */
250 }
251dwarf_reg_only_state_t;
252
253typedef struct dwarf_reg_state
254 {
255 unw_word_t ret_addr_column; /* which column in rule table represents return address */
256 dwarf_reg_only_state_t reg;
257 }
258dwarf_reg_state_t;
259
260typedef struct dwarf_stackable_reg_state
261 {
262 struct dwarf_stackable_reg_state *next; /* for rs_stack */
263 dwarf_reg_state_t state;
264 }
265dwarf_stackable_reg_state_t;
266
267typedef struct dwarf_reg_cache_entry
268 {
269 unw_word_t ip; /* ip this rs is for */
270 unsigned short coll_chain; /* used for hash collisions */
271 unsigned short hint; /* hint for next rs to try (or -1) */
272 unsigned short valid : 1; /* optional machine-dependent signal info */
273 unsigned short signal_frame : 1; /* optional machine-dependent signal info */
274 }
275dwarf_reg_cache_entry_t;
276
277typedef struct dwarf_cie_info
278 {
279 unw_word_t cie_instr_start; /* start addr. of CIE "initial_instructions" */
280 unw_word_t cie_instr_end; /* end addr. of CIE "initial_instructions" */
281 unw_word_t fde_instr_start; /* start addr. of FDE "instructions" */
282 unw_word_t fde_instr_end; /* end addr. of FDE "instructions" */
283 unw_word_t code_align; /* code-alignment factor */
284 unw_word_t data_align; /* data-alignment factor */
285 unw_word_t ret_addr_column; /* column of return-address register */
286 unw_word_t handler; /* address of personality-routine */
287 uint16_t abi;
288 uint16_t tag;
289 uint8_t fde_encoding;
290 uint8_t lsda_encoding;
291 unsigned int sized_augmentation : 1;
292 unsigned int have_abi_marker : 1;
293 unsigned int signal_frame : 1;
294 }
295dwarf_cie_info_t;
296
297typedef struct dwarf_state_record
298 {
299 unsigned char fde_encoding;
300 unw_word_t args_size;
301
302 dwarf_reg_state_t rs_initial; /* reg-state after CIE instructions */
303 dwarf_reg_state_t rs_current; /* current reg-state */
304 }
305dwarf_state_record_t;
306
307typedef struct dwarf_cursor
308 {
309 void *as_arg; /* argument to address-space callbacks */
310 unw_addr_space_t as; /* reference to per-address-space info */
311
312 unw_word_t cfa; /* canonical frame address; aka frame-/stack-pointer */
313 unw_word_t ip; /* instruction pointer */
314 unw_word_t args_size; /* size of arguments */
315 unw_word_t eh_args[UNW_TDEP_NUM_EH_REGS];
316 unsigned int eh_valid_mask;
317
318 dwarf_loc_t loc[DWARF_NUM_PRESERVED_REGS];
319
320 unsigned int stash_frames :1; /* stash frames for fast lookup */
321 unsigned int use_prev_instr :1; /* use previous (= call) or current (= signal) instruction? */
322 unsigned int pi_valid :1; /* is proc_info valid? */
323 unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
324 unw_proc_info_t pi; /* info about current procedure */
325
326 short hint; /* faster lookup of the rs cache */
327 short prev_rs;
328 }
329dwarf_cursor_t;
330
331#define DWARF_DEFAULT_LOG_UNW_CACHE_SIZE 7
332#define DWARF_DEFAULT_UNW_CACHE_SIZE (1 << DWARF_DEFAULT_LOG_UNW_CACHE_SIZE)
333
334#define DWARF_DEFAULT_LOG_UNW_HASH_SIZE (DWARF_DEFAULT_LOG_UNW_CACHE_SIZE + 1)
335#define DWARF_DEFAULT_UNW_HASH_SIZE (1 << DWARF_DEFAULT_LOG_UNW_HASH_SIZE)
336
337typedef unsigned char unw_hash_index_t;
338
339struct dwarf_rs_cache
340 {
341 pthread_mutex_t lock;
342 unsigned short rr_head; /* index of least-recently allocated rs */
343
344 unsigned short log_size;
345 unsigned short prev_log_size;
346
347 /* hash table that maps instruction pointer to rs index: */
348 unsigned short *hash;
349
350 uint32_t generation; /* generation number */
351
352 /* rs cache: */
353 dwarf_reg_state_t *buckets;
354 dwarf_reg_cache_entry_t *links;
355
356 /* default memory, loaded in BSS segment */
357 unsigned short default_hash[DWARF_DEFAULT_UNW_HASH_SIZE];
358 dwarf_reg_state_t default_buckets[DWARF_DEFAULT_UNW_CACHE_SIZE];
359 dwarf_reg_cache_entry_t default_links[DWARF_DEFAULT_UNW_CACHE_SIZE];
360 };
361
362/* A list of descriptors for loaded .debug_frame sections. */
363
364struct unw_debug_frame_list
365 {
366 /* The start (inclusive) and end (exclusive) of the described region. */
367 unw_word_t start;
368 unw_word_t end;
369 /* The debug frame itself. */
370 char *debug_frame;
371 size_t debug_frame_size;
372 /* Index (for binary search). */
373 struct table_entry *index;
374 size_t index_size;
375 /* Pointer to next descriptor. */
376 struct unw_debug_frame_list *next;
377 };
378
379/* Convenience macros: */
380#define dwarf_init UNW_ARCH_OBJ (dwarf_init)
381#define dwarf_callback UNW_OBJ (dwarf_callback)
382#define dwarf_find_proc_info UNW_OBJ (dwarf_find_proc_info)
383#define dwarf_find_debug_frame UNW_OBJ (dwarf_find_debug_frame)
384#define dwarf_search_unwind_table UNW_OBJ (dwarf_search_unwind_table)
385#define dwarf_find_unwind_table UNW_OBJ (dwarf_find_unwind_table)
386#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info)
387#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info)
388#define dwarf_eval_expr UNW_OBJ (dwarf_eval_expr)
389#define dwarf_stack_aligned UNW_OBJ (dwarf_stack_aligned)
390#define dwarf_extract_proc_info_from_fde \
391 UNW_OBJ (dwarf_extract_proc_info_from_fde)
392#define dwarf_find_save_locs UNW_OBJ (dwarf_find_save_locs)
393#define dwarf_make_proc_info UNW_OBJ (dwarf_make_proc_info)
394#define dwarf_apply_reg_state UNW_OBJ (dwarf_apply_reg_state)
395#define dwarf_reg_states_iterate UNW_OBJ (dwarf_reg_states_iterate)
396#define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer)
397#define dwarf_step UNW_OBJ (dwarf_step)
398#define dwarf_flush_rs_cache UNW_OBJ (dwarf_flush_rs_cache)
399
400extern int dwarf_init (void);
401#ifndef UNW_REMOTE_ONLY
402extern int dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr);
403extern int dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
404 unw_proc_info_t *pi,
405 int need_unwind_info, void *arg);
406#endif /* !UNW_REMOTE_ONLY */
407extern int dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug,
408 unw_word_t ip, unw_word_t segbase,
409 const char* obj_name, unw_word_t start,
410 unw_word_t end);
411extern int dwarf_search_unwind_table (unw_addr_space_t as,
412 unw_word_t ip,
413 unw_dyn_info_t *di,
414 unw_proc_info_t *pi,
415 int need_unwind_info, void *arg);
416
417extern int dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as,
418 char *path, unw_word_t segbase, unw_word_t mapoff,
419 unw_word_t ip);
420extern void dwarf_put_unwind_info (unw_addr_space_t as,
421 unw_proc_info_t *pi, void *arg);
422extern int dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr,
423 unw_word_t len, unw_word_t *valp,
424 int *is_register);
425extern int
426dwarf_stack_aligned(struct dwarf_cursor *c, unw_word_t cfa_addr,
427 unw_word_t rbp_addr, unw_word_t *offset);
428
429extern int dwarf_extract_proc_info_from_fde (unw_addr_space_t as,
430 unw_accessors_t *a,
431 unw_word_t *fde_addr,
432 unw_proc_info_t *pi,
433 unw_word_t base,
434 int need_unwind_info,
435 int is_debug_frame,
436 void *arg);
437extern int dwarf_find_save_locs (struct dwarf_cursor *c);
438extern int dwarf_make_proc_info (struct dwarf_cursor *c);
439extern int dwarf_apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs);
440extern int dwarf_reg_states_iterate (struct dwarf_cursor *c, unw_reg_states_callback cb, void *token);
441extern int dwarf_read_encoded_pointer (unw_addr_space_t as,
442 unw_accessors_t *a,
443 unw_word_t *addr,
444 unsigned char encoding,
445 const unw_proc_info_t *pi,
446 unw_word_t *valp, void *arg);
447extern int dwarf_step (struct dwarf_cursor *c);
448extern int dwarf_flush_rs_cache (struct dwarf_rs_cache *cache);
449
450#endif /* dwarf_h */
451