Performs the unwind of a function */
| 493 | |
| 494 | /* Performs the unwind of a function */ |
| 495 | static int |
| 496 | unwind_tab(struct unwind_state *state) |
| 497 | { |
| 498 | uint32_t entry; |
| 499 | |
| 500 | /* Set PC to a known value */ |
| 501 | state->registers[PC] = 0; |
| 502 | |
| 503 | /* Read the personality */ |
| 504 | entry = *state->insn & ENTRY_MASK; |
| 505 | |
| 506 | if (entry == ENTRY_ARM_SU16) { |
| 507 | state->byte = 2; |
| 508 | state->entries = 1; |
| 509 | } else if (entry == ENTRY_ARM_LU16) { |
| 510 | state->byte = 1; |
| 511 | state->entries = ((*state->insn >> 16) & 0xFF) + 1; |
| 512 | } else { |
| 513 | #if 0 |
| 514 | db_printf("Unknown entry: %x\n", entry); |
| 515 | #endif |
| 516 | return 1; |
| 517 | } |
| 518 | |
| 519 | while (state->entries > 0) { |
| 520 | if (unwind_exec_insn(state) != 0) |
| 521 | return 1; |
| 522 | } |
| 523 | |
| 524 | /* |
| 525 | * The program counter was not updated, load it from the link register. |
| 526 | */ |
| 527 | if (state->registers[PC] == 0) { |
| 528 | state->registers[PC] = state->registers[LR]; |
| 529 | |
| 530 | /* |
| 531 | * If the program counter changed, flag it in the update mask. |
| 532 | */ |
| 533 | if (state->start_pc != state->registers[PC]) |
| 534 | state->update_mask |= 1 << PC; |
| 535 | } |
| 536 | |
| 537 | return 0; |
| 538 | } |
| 539 | |
| 540 | /* |
| 541 | * Unwind a single stack frame. |
no test coverage detected