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