Gparser.c revision d7089547e2d13c2ae5f9ad896dc4bc5dc796fb0b
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#include <stddef.h> 27#include "dwarf_i.h" 28#include "libunwind_i.h" 29 30#define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool)) 31#define free_reg_state(rs) (mempool_free (&dwarf_reg_state_pool, rs)) 32 33static inline int 34read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, 35 unw_word_t *valp, void *arg) 36{ 37 int ret; 38 39 if ((ret = dwarf_read_uleb128 (as, a, addr, valp, arg)) < 0) 40 return ret; 41 42 if (*valp >= DWARF_NUM_PRESERVED_REGS) 43 { 44 Debug (1, "Invalid register number %u\n", (unsigned int) *valp); 45 return -UNW_EBADREG; 46 } 47 return 0; 48} 49 50static inline void 51set_reg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where, 52 unw_word_t val) 53{ 54 sr->rs_current.reg[regnum].where = where; 55 sr->rs_current.reg[regnum].val = val; 56} 57 58/* Run a CFI program to update the register state. */ 59static int 60run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr, 61 unw_word_t ip, unw_word_t *addr, unw_word_t end_addr, 62 struct dwarf_cie_info *dci) 63{ 64 unw_word_t curr_ip, operand = 0, regnum, val, len, fde_encoding; 65 dwarf_reg_state_t *rs_stack = NULL, *new_rs, *old_rs; 66 unw_addr_space_t as; 67 unw_accessors_t *a; 68 uint8_t u8, op; 69 uint16_t u16; 70 uint32_t u32; 71 void *arg; 72 int ret; 73 74 as = c->as; 75 arg = c->as_arg; 76 a = unw_get_accessors (as); 77 curr_ip = c->pi.start_ip; 78 79 while (curr_ip < ip && *addr < end_addr) 80 { 81 if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0) 82 return ret; 83 84 if (op & DWARF_CFA_OPCODE_MASK) 85 { 86 operand = op & DWARF_CFA_OPERAND_MASK; 87 op &= ~DWARF_CFA_OPERAND_MASK; 88 } 89 switch ((dwarf_cfa_t) op) 90 { 91 case DW_CFA_advance_loc: 92 curr_ip += operand * dci->code_align; 93 Debug (15, "CFA_advance_loc to 0x%lx\n", (long) curr_ip); 94 break; 95 96 case DW_CFA_advance_loc1: 97 if ((ret = dwarf_readu8 (as, a, addr, &u8, arg)) < 0) 98 goto fail; 99 curr_ip += u8 * dci->code_align; 100 Debug (15, "CFA_advance_loc1 to 0x%lx\n", (long) curr_ip); 101 break; 102 103 case DW_CFA_advance_loc2: 104 if ((ret = dwarf_readu16 (as, a, addr, &u16, arg)) < 0) 105 goto fail; 106 curr_ip += u16 * dci->code_align; 107 Debug (15, "CFA_advance_loc2 to 0x%lx\n", (long) curr_ip); 108 break; 109 110 case DW_CFA_advance_loc4: 111 if ((ret = dwarf_readu32 (as, a, addr, &u32, arg)) < 0) 112 goto fail; 113 curr_ip += u32 * dci->code_align; 114 Debug (15, "CFA_advance_loc4 to 0x%lx\n", (long) curr_ip); 115 break; 116 117 case DW_CFA_MIPS_advance_loc8: 118#ifdef UNW_TARGET_MIPS 119 { 120 uint64_t u64; 121 122 if ((ret = dwarf_readu64 (as, a, addr, &u64, arg)) < 0) 123 goto fail; 124 curr_ip += u64 * dci->code_align; 125 Debug (15, "CFA_MIPS_advance_loc8\n"); 126 break; 127 } 128#else 129 Debug (1, "DW_CFA_MIPS_advance_loc8 on non-MIPS target\n"); 130 ret = -UNW_EINVAL; 131 goto fail; 132#endif 133 134 case DW_CFA_offset: 135 regnum = operand; 136 if (regnum >= DWARF_NUM_PRESERVED_REGS) 137 { 138 Debug (1, "Invalid register number %u in DW_cfa_OFFSET\n", 139 (unsigned int) regnum); 140 ret = -UNW_EBADREG; 141 goto fail; 142 } 143 if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) 144 goto fail; 145 set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); 146 Debug (15, "CFA_offset r%lu at cfa+0x%lx\n", 147 (long) regnum, (long) (val * dci->data_align)); 148 break; 149 150 case DW_CFA_offset_extended: 151 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 152 || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) 153 goto fail; 154 set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); 155 Debug (15, "CFA_offset_extended r%lu at cf+0x%lx\n", 156 (long) regnum, (long) (val * dci->data_align)); 157 break; 158 159 case DW_CFA_offset_extended_sf: 160 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 161 || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)) 162 goto fail; 163 set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); 164 Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n", 165 (long) regnum, (long) (val * dci->data_align)); 166 break; 167 168 case DW_CFA_restore: 169 regnum = operand; 170 if (regnum >= DWARF_NUM_PRESERVED_REGS) 171 { 172 Debug (1, "Invalid register number %u in DW_CFA_restore\n", 173 (unsigned int) regnum); 174 ret = -UNW_EINVAL; 175 goto fail; 176 } 177 sr->rs_current.reg[regnum] = sr->rs_initial.reg[regnum]; 178 Debug (15, "CFA_restore r%lu\n", (long) regnum); 179 break; 180 181 case DW_CFA_restore_extended: 182 if ((ret = dwarf_read_uleb128 (as, a, addr, ®num, arg)) < 0) 183 goto fail; 184 if (regnum >= DWARF_NUM_PRESERVED_REGS) 185 { 186 Debug (1, "Invalid register number %u in " 187 "DW_CFA_restore_extended\n", (unsigned int) regnum); 188 ret = -UNW_EINVAL; 189 goto fail; 190 } 191 sr->rs_current.reg[regnum] = sr->rs_initial.reg[regnum]; 192 Debug (15, "CFA_restore_extended r%lu\n", (long) regnum); 193 break; 194 195 case DW_CFA_nop: 196 break; 197 198 case DW_CFA_set_loc: 199 fde_encoding = dci->fde_encoding; 200 if ((ret = dwarf_read_encoded_pointer (as, a, addr, fde_encoding, 201 &c->pi, &curr_ip, 202 arg)) < 0) 203 goto fail; 204 Debug (15, "CFA_set_loc to 0x%lx\n", (long) curr_ip); 205 break; 206 207 case DW_CFA_undefined: 208 if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 209 goto fail; 210 set_reg (sr, regnum, DWARF_WHERE_UNDEF, 0); 211 Debug (15, "CFA_undefined r%lu\n", (long) regnum); 212 break; 213 214 case DW_CFA_same_value: 215 if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 216 goto fail; 217 set_reg (sr, regnum, DWARF_WHERE_SAME, 0); 218 Debug (15, "CFA_same_value r%lu\n", (long) regnum); 219 break; 220 221 case DW_CFA_register: 222 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 223 || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) 224 goto fail; 225 set_reg (sr, regnum, DWARF_WHERE_REG, val); 226 Debug (15, "CFA_register r%lu to r%lu\n", (long) regnum, (long) val); 227 break; 228 229 case DW_CFA_remember_state: 230 new_rs = alloc_reg_state (); 231 if (!new_rs) 232 { 233 Debug (1, "Out of memory in DW_CFA_remember_state\n"); 234 ret = -UNW_ENOMEM; 235 goto fail; 236 } 237 238 memcpy (new_rs->reg, sr->rs_current.reg, sizeof (new_rs->reg)); 239 new_rs->next = rs_stack; 240 rs_stack = new_rs; 241 Debug (15, "CFA_remember_state\n"); 242 break; 243 244 case DW_CFA_restore_state: 245 if (!rs_stack) 246 { 247 Debug (1, "register-state stack underflow\n"); 248 ret = -UNW_EINVAL; 249 goto fail; 250 } 251 memcpy (&sr->rs_current.reg, &rs_stack->reg, sizeof (rs_stack->reg)); 252 old_rs = rs_stack; 253 rs_stack = rs_stack->next; 254 free_reg_state (old_rs); 255 Debug (15, "CFA_restore_state\n"); 256 break; 257 258 case DW_CFA_def_cfa: 259 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 260 || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) 261 goto fail; 262 set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum); 263 set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */ 264 Debug (15, "CFA_def_cfa r%lu+0x%lx\n", (long) regnum, (long) val); 265 break; 266 267 case DW_CFA_def_cfa_sf: 268 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 269 || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)) 270 goto fail; 271 set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum); 272 set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, 273 val * dci->data_align); /* factored! */ 274 Debug (15, "CFA_def_cfa_sf r%lu+0x%lx\n", 275 (long) regnum, (long) (val * dci->data_align)); 276 break; 277 278 case DW_CFA_def_cfa_register: 279 if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 280 goto fail; 281 set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum); 282 Debug (15, "CFA_def_cfa_register r%lu\n", (long) regnum); 283 break; 284 285 case DW_CFA_def_cfa_offset: 286 if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) 287 goto fail; 288 set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */ 289 Debug (15, "CFA_def_cfa_offset 0x%lx\n", (long) val); 290 break; 291 292 case DW_CFA_def_cfa_offset_sf: 293 if ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0) 294 goto fail; 295 set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, 296 val * dci->data_align); /* factored! */ 297 Debug (15, "CFA_def_cfa_offset_sf 0x%lx\n", 298 (long) (val * dci->data_align)); 299 break; 300 301 case DW_CFA_def_cfa_expression: 302 /* Save the address of the DW_FORM_block for later evaluation. */ 303 set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_EXPR, *addr); 304 305 if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0) 306 goto fail; 307 308 Debug (15, "CFA_def_cfa_expr @ 0x%lx [%lu bytes]\n", 309 (long) *addr, (long) len); 310 *addr += len; 311 break; 312 313 case DW_CFA_expression: 314 if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 315 goto fail; 316 317 /* Save the address of the DW_FORM_block for later evaluation. */ 318 set_reg (sr, regnum, DWARF_WHERE_EXPR, *addr); 319 320 if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0) 321 goto fail; 322 323 Debug (15, "CFA_expression r%lu @ 0x%lx [%lu bytes]\n", 324 (long) regnum, (long) addr, (long) len); 325 *addr += len; 326 break; 327 328 case DW_CFA_GNU_args_size: 329 if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) 330 goto fail; 331 sr->args_size = val; 332 Debug (15, "CFA_GNU_args_size %lu\n", (long) val); 333 break; 334 335 case DW_CFA_GNU_negative_offset_extended: 336 /* A comment in GCC says that this is obsoleted by 337 DW_CFA_offset_extended_sf, but that it's used by older 338 PowerPC code. */ 339 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 340 || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) 341 goto fail; 342 set_reg (sr, regnum, DWARF_WHERE_CFAREL, -(val * dci->data_align)); 343 Debug (15, "CFA_GNU_negative_offset_extended cfa+0x%lx\n", 344 (long) -(val * dci->data_align)); 345 break; 346 347 case DW_CFA_GNU_window_save: 348#ifdef UNW_TARGET_SPARC 349 /* This is a special CFA to handle all 16 windowed registers 350 on SPARC. */ 351 for (regnum = 16; regnum < 32; ++regnum) 352 set_reg (sr, regnum, DWARF_WHERE_CFAREL, 353 (regnum - 16) * sizeof (unw_word_t)); 354 Debug (15, "CFA_GNU_window_save\n"); 355 break; 356#else 357 /* FALL THROUGH */ 358#endif 359 case DW_CFA_lo_user: 360 case DW_CFA_hi_user: 361 Debug (1, "Unexpected CFA opcode 0x%x\n", op); 362 ret = -UNW_EINVAL; 363 goto fail; 364 } 365 } 366 ret = 0; 367 368 fail: 369 /* Free the register-state stack, if not empty already. */ 370 while (rs_stack) 371 { 372 old_rs = rs_stack; 373 rs_stack = rs_stack->next; 374 free_reg_state (old_rs); 375 } 376 return ret; 377} 378 379static int 380fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info) 381{ 382 int ret, dynamic = 1; 383 384 --ip; 385 386 if (c->pi_valid && !need_unwind_info) 387 return 0; 388 389 memset (&c->pi, 0, sizeof (c->pi)); 390 391 /* check dynamic info first --- it overrides everything else */ 392 ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info, 393 c->as_arg); 394 if (ret == -UNW_ENOINFO) 395 { 396 dynamic = 0; 397 if ((ret = tdep_find_proc_info (c, ip, need_unwind_info)) < 0) 398 return ret; 399 } 400 401 c->pi_valid = 1; 402 c->pi_is_dynamic = dynamic; 403 return ret; 404} 405 406static int 407parse_dynamic (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr) 408{ 409 Debug (1, "Not yet implemented\n"); 410#if 0 411 /* Don't forget to set the ret_addr_column! */ 412 c->ret_addr_column = XXX; 413#endif 414 return -UNW_ENOINFO; 415} 416 417static inline void 418put_unwind_info (struct dwarf_cursor *c, unw_proc_info_t *pi) 419{ 420 if (!c->pi_valid) 421 return; 422 423 if (c->pi_is_dynamic) 424 unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg); 425 else if (pi->unwind_info); 426 { 427 mempool_free (&dwarf_cie_info_pool, pi->unwind_info); 428 pi->unwind_info = NULL; 429 } 430} 431 432static inline int 433parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr) 434{ 435 struct dwarf_cie_info *dci; 436 unw_word_t addr; 437 int ret; 438 439 dci = c->pi.unwind_info; 440 c->ret_addr_column = dci->ret_addr_column; 441 442 addr = dci->cie_instr_start; 443 if ((ret = run_cfi_program (c, sr, ~(unw_word_t) 0, &addr, 444 dci->cie_instr_end, dci)) < 0) 445 return ret; 446 447 memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial)); 448 449 addr = dci->fde_instr_start; 450 if ((ret = run_cfi_program (c, sr, ip, &addr, dci->fde_instr_end, dci)) < 0) 451 return ret; 452 453 return 0; 454} 455 456static inline void 457flush_rs_cache (struct dwarf_rs_cache *cache) 458{ 459 int i; 460 461 cache->lru_head = DWARF_UNW_CACHE_SIZE - 1; 462 cache->lru_tail = 0; 463 464 for (i = 0; i < DWARF_UNW_CACHE_SIZE; ++i) 465 { 466 if (i > 0) 467 cache->buckets[i].lru_chain = (i - 1); 468 cache->buckets[i].coll_chain = -1; 469 cache->buckets[i].ip = 0; 470 } 471 for (i = 0; i<DWARF_UNW_HASH_SIZE; ++i) 472 cache->hash[i] = -1; 473} 474 475static inline struct dwarf_rs_cache * 476get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp) 477{ 478 struct dwarf_rs_cache *cache = &as->global_cache; 479 unw_caching_policy_t caching = as->caching_policy; 480 481 if (caching == UNW_CACHE_NONE) 482 return NULL; 483 484 if (likely (caching == UNW_CACHE_GLOBAL)) 485 { 486 Debug (16, "%s: acquiring lock\n", __FUNCTION__); 487 lock_acquire (&cache->lock, *saved_maskp); 488 } 489 490 if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation)) 491 { 492 flush_rs_cache (cache); 493 cache->generation = as->cache_generation; 494 } 495 496 return cache; 497} 498 499static inline void 500put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache, 501 intrmask_t *saved_maskp) 502{ 503 assert (as->caching_policy != UNW_CACHE_NONE); 504 505 Debug (16, "unmasking signals/interrupts and releasing lock\n"); 506 if (likely (as->caching_policy == UNW_CACHE_GLOBAL)) 507 lock_release (&cache->lock, *saved_maskp); 508} 509 510static inline unw_hash_index_t 511hash (unw_word_t ip) 512{ 513 /* based on (sqrt(5)/2-1)*2^64 */ 514# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL) 515 516 return ip * magic >> ((sizeof(unw_word_t) * 8) - DWARF_LOG_UNW_HASH_SIZE); 517} 518 519static inline long 520cache_match (dwarf_reg_state_t *rs, unw_word_t ip) 521{ 522 if (ip == rs->ip) 523 return 1; 524 return 0; 525} 526 527static dwarf_reg_state_t * 528rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c) 529{ 530 dwarf_reg_state_t *rs = cache->buckets + c->hint; 531 unsigned short index; 532 unw_word_t ip; 533 534 ip = c->ip; 535 536 if (cache_match (rs, ip)) 537 return rs; 538 539 index = cache->hash[hash (ip)]; 540 if (index >= DWARF_UNW_CACHE_SIZE) 541 return 0; 542 543 rs = cache->buckets + index; 544 while (1) 545 { 546 if (cache_match (rs, ip)) 547 { 548 /* update hint; no locking needed: single-word writes are atomic */ 549 c->hint = cache->buckets[c->prev_rs].hint = 550 (rs - cache->buckets); 551 return rs; 552 } 553 if (rs->coll_chain >= DWARF_UNW_HASH_SIZE) 554 return 0; 555 rs = cache->buckets + rs->coll_chain; 556 } 557} 558 559static inline dwarf_reg_state_t * 560rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c) 561{ 562 dwarf_reg_state_t *rs, *prev, *tmp; 563 unw_hash_index_t index; 564 unsigned short head; 565 566 head = cache->lru_head; 567 rs = cache->buckets + head; 568 cache->lru_head = rs->lru_chain; 569 570 /* re-insert rs at the tail of the LRU chain: */ 571 cache->buckets[cache->lru_tail].lru_chain = head; 572 cache->lru_tail = head; 573 574 /* remove the old rs from the hash table (if it's there): */ 575 if (rs->ip) 576 { 577 index = hash (rs->ip); 578 tmp = cache->buckets + cache->hash[index]; 579 prev = 0; 580 while (1) 581 { 582 if (tmp == rs) 583 { 584 if (prev) 585 prev->coll_chain = tmp->coll_chain; 586 else 587 cache->hash[index] = tmp->coll_chain; 588 break; 589 } 590 else 591 prev = tmp; 592 if (tmp->coll_chain >= DWARF_UNW_CACHE_SIZE) 593 /* old rs wasn't in the hash-table */ 594 break; 595 tmp = cache->buckets + tmp->coll_chain; 596 } 597 } 598 599 /* enter new rs in the hash table */ 600 index = hash (c->ip); 601 rs->coll_chain = cache->hash[index]; 602 cache->hash[index] = rs - cache->buckets; 603 604 rs->hint = 0; 605 rs->ip = c->ip; 606 rs->ret_addr_column = c->ret_addr_column; 607 608 return rs; 609} 610 611static int 612create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr, 613 unw_word_t ip) 614{ 615 int i, ret; 616 617 assert (c->pi_valid); 618 619 memset (sr, 0, sizeof (*sr)); 620 for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i) 621 set_reg (sr, i, DWARF_WHERE_SAME, 0); 622 623 switch (c->pi.format) 624 { 625 case UNW_INFO_FORMAT_TABLE: 626 case UNW_INFO_FORMAT_REMOTE_TABLE: 627 ret = parse_fde (c, ip, sr); 628 break; 629 630 case UNW_INFO_FORMAT_DYNAMIC: 631 ret = parse_dynamic (c, ip, sr); 632 break; 633 634 default: 635 Debug (1, "Unexpected unwind-info format %d\n", c->pi.format); 636 ret = -UNW_EINVAL; 637 } 638 return ret; 639} 640 641static inline int 642eval_location_expr (struct dwarf_cursor *c, unw_addr_space_t as, 643 unw_accessors_t *a, unw_word_t addr, 644 dwarf_loc_t *locp, void *arg) 645{ 646 int ret, is_register; 647 unw_word_t len, val; 648 649 /* read the length of the expression: */ 650 if ((ret = dwarf_read_uleb128 (as, a, &addr, &len, arg)) < 0) 651 return ret; 652 653 /* evaluate the expression: */ 654 if ((ret = dwarf_eval_expr (c, &addr, len, &val, &is_register)) < 0) 655 return ret; 656 657 if (is_register) 658 *locp = DWARF_REG_LOC (c, dwarf_to_unw_regnum (val)); 659 else 660 *locp = DWARF_MEM_LOC (c, val); 661 662 return 0; 663} 664 665static int 666apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) 667{ 668 unw_word_t regnum, addr, cfa, ip; 669 unw_word_t prev_ip, prev_cfa; 670 unw_addr_space_t as; 671 dwarf_loc_t cfa_loc; 672 unw_accessors_t *a; 673 int i, ret; 674 void *arg; 675 676 prev_ip = c->ip; 677 prev_cfa = c->cfa; 678 679 as = c->as; 680 arg = c->as_arg; 681 a = unw_get_accessors (as); 682 683 /* Evaluate the CFA first, because it may be referred to by other 684 expressions. */ 685 686 if (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG) 687 { 688 /* CFA is equal to [reg] + offset: */ 689 690 /* As a special-case, if the stack-pointer is the CFA and the 691 stack-pointer wasn't saved, popping the CFA implicitly pops 692 the stack-pointer as well. */ 693 if ((rs->reg[DWARF_CFA_REG_COLUMN].val == UNW_TDEP_SP) 694 && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg)) 695 && (rs->reg[UNW_TDEP_SP].where == DWARF_WHERE_SAME)) 696 cfa = c->cfa; 697 else 698 { 699 regnum = dwarf_to_unw_regnum (rs->reg[DWARF_CFA_REG_COLUMN].val); 700 if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0) 701 return ret; 702 } 703 cfa += rs->reg[DWARF_CFA_OFF_COLUMN].val; 704 } 705 else 706 { 707 /* CFA is equal to EXPR: */ 708 709 assert (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_EXPR); 710 711 addr = rs->reg[DWARF_CFA_REG_COLUMN].val; 712 if ((ret = eval_location_expr (c, as, a, addr, &cfa_loc, arg)) < 0) 713 return ret; 714 /* the returned location better be a memory location... */ 715 if (DWARF_IS_REG_LOC (cfa_loc)) 716 return -UNW_EBADFRAME; 717 cfa = DWARF_GET_LOC (cfa_loc); 718 } 719 720 for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) 721 { 722 switch ((dwarf_where_t) rs->reg[i].where) 723 { 724 case DWARF_WHERE_UNDEF: 725 c->loc[i] = DWARF_NULL_LOC; 726 break; 727 728 case DWARF_WHERE_SAME: 729 break; 730 731 case DWARF_WHERE_CFAREL: 732 c->loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg[i].val); 733 break; 734 735 case DWARF_WHERE_REG: 736 c->loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg[i].val)); 737 break; 738 739 case DWARF_WHERE_EXPR: 740 addr = rs->reg[i].val; 741 if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) , 0) 742 return ret; 743 break; 744 } 745 } 746 c->cfa = cfa; 747 ret = dwarf_get (c, c->loc[c->ret_addr_column], &ip); 748 if (ret < 0) 749 return ret; 750 c->ip = ip; 751 /* XXX: check for ip to be code_aligned */ 752 753 if (c->ip == prev_ip && c->cfa == prev_cfa) 754 { 755 Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n", 756 __FUNCTION__, (long) c->ip); 757 return -UNW_EBADFRAME; 758 } 759 return 0; 760} 761 762static int 763uncached_dwarf_find_save_locs (struct dwarf_cursor *c) 764{ 765 dwarf_state_record_t sr; 766 int ret; 767 768 if ((ret = fetch_proc_info (c, c->ip, 1)) < 0) 769 return ret; 770 771 if ((ret = create_state_record_for (c, &sr, c->ip)) < 0) 772 return ret; 773 774 if ((ret = apply_reg_state (c, &sr.rs_current)) < 0) 775 return ret; 776 777 put_unwind_info (c, &c->pi); 778 return 0; 779} 780 781/* The function finds the saved locations and applies the register 782 state as well. */ 783HIDDEN int 784dwarf_find_save_locs (struct dwarf_cursor *c) 785{ 786 dwarf_state_record_t sr; 787 dwarf_reg_state_t *rs, *rs1; 788 struct dwarf_rs_cache *cache; 789 int ret = 0; 790 intrmask_t saved_mask; 791 792 if (c->as->caching_policy == UNW_CACHE_NONE) 793 return uncached_dwarf_find_save_locs (c); 794 795 cache = get_rs_cache(c->as, &saved_mask); 796 if (!cache) 797 return -UNW_ENOINFO; /* cache is busy */ 798 rs = rs_lookup(cache, c); 799 800 if (rs) 801 { 802 c->ret_addr_column = rs->ret_addr_column; 803 goto apply; 804 } 805 806 if ((ret = fetch_proc_info (c, c->ip, 1)) < 0) 807 goto out; 808 809 if ((ret = create_state_record_for (c, &sr, c->ip)) < 0) 810 goto out; 811 812 rs1 = &sr.rs_current; 813 if (rs1) 814 { 815 rs = rs_new (cache, c); 816 memcpy(rs, rs1, offsetof(struct dwarf_reg_state, ip)); 817 if (!rs) 818 { 819 Dprintf ("%s: failed to create unwind rs\n", __FUNCTION__); 820 ret = -UNW_EUNSPEC; 821 goto out; 822 } 823 } 824 cache->buckets[c->prev_rs].hint = rs - cache->buckets; 825 826 c->hint = rs->hint; 827 c->prev_rs = rs - cache->buckets; 828 829 put_unwind_info (c, &c->pi); 830 ret = apply_reg_state (c, rs); 831 832out: 833 put_rs_cache (c->as, cache, &saved_mask); 834 return ret; 835 836apply: 837 put_rs_cache (c->as, cache, &saved_mask); 838 if ((ret = apply_reg_state (c, rs)) < 0) 839 return ret; 840 841 return 0; 842} 843 844/* The proc-info must be valid for IP before this routine can be 845 called. */ 846HIDDEN int 847dwarf_create_state_record (struct dwarf_cursor *c, dwarf_state_record_t *sr) 848{ 849 return create_state_record_for (c, sr, c->ip); 850} 851 852HIDDEN int 853dwarf_make_proc_info (struct dwarf_cursor *c) 854{ 855#if 0 856 if (c->as->caching_policy == UNW_CACHE_NONE 857 || get_cached_proc_info (c) < 0) 858#endif 859 /* Lookup it up the slow way... */ 860 return fetch_proc_info (c, c->ip, 0); 861 return 0; 862} 863