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