GNU Binutils with patches for OS216
Revision | fdd93b8b10a297196af99279086ddc214f3d9bb6 (tree) |
---|---|
Zeit | 2003-03-05 14:00:04 |
Autor | Andrew Cagney <cagney@redh...> |
Commiter | Andrew Cagney |
2003-03-04 Andrew Cagney <cagney@redhat.com>
* d10v-tdep.c (struct d10v_unwind_cache): Add field "r11_addr",
change type of "next_addr" to LONGEST. Delete member "frameless".
(prologue_find_regs): Parse "st rn, @r11", save r11's offset.
(d10v_frame_unwind_cache): Compute both the frame base and the
previous stack pointer. Store the previous SP's value in the
saved_regs array.
(d10v_frame_id_unwind): Remove commented out code. Check for
circular stack.
(saved_regs_unwinder): When SP_REGNUM, extract the value from the
saved_regs array.
(d10v_unwind_dummy_id): New function.
(d10v_gdbarch_init): Initialize d10v_unwind_dummy_id and
save_dummy_frame_tos.
(struct frame_extra_info): Delete.
(saved_regs_unwind): New function.
(d10v_frame_pop): Update to match current code.
(d10v_frame_register_unwind): Don't unwind LR_REGNUM. Unwind the
PC_REGNUM by returning the saved LR_REGNUM.
* frame.c (get_prev_frame): Store this frame's ID in the next
frame's unwound ID cache.
(deprecated_update_frame_pc_hack): Update the cached value in NEXT
as well.
2003-02-27 Andrew Cagney <cagney@redhat.com>
* frame.c (get_prev_frame): Rewrite the frame ID unwind code to
use unwind_dummy_id when available.
* gdbarch.sh (get_dummy_frame_id): New multi-arch method with
predicate.
* gdbarch.h, gdbarch.c: Regneerate.
@@ -1,5 +1,37 @@ | ||
1 | 1 | 2003-03-04 Andrew Cagney <cagney@redhat.com> |
2 | 2 | |
3 | + * d10v-tdep.c (struct d10v_unwind_cache): Add field "r11_addr", | |
4 | + change type of "next_addr" to LONGEST. Delete member "frameless". | |
5 | + (prologue_find_regs): Parse "st rn, @r11", save r11's offset. | |
6 | + (d10v_frame_unwind_cache): Compute both the frame base and the | |
7 | + previous stack pointer. Store the previous SP's value in the | |
8 | + saved_regs array. | |
9 | + (d10v_frame_id_unwind): Remove commented out code. Check for | |
10 | + circular stack. | |
11 | + (saved_regs_unwinder): When SP_REGNUM, extract the value from the | |
12 | + saved_regs array. | |
13 | + (d10v_unwind_dummy_id): New function. | |
14 | + (d10v_gdbarch_init): Initialize d10v_unwind_dummy_id and | |
15 | + save_dummy_frame_tos. | |
16 | + (struct frame_extra_info): Delete. | |
17 | + (saved_regs_unwind): New function. | |
18 | + (d10v_frame_pop): Update to match current code. | |
19 | + (d10v_frame_register_unwind): Don't unwind LR_REGNUM. Unwind the | |
20 | + PC_REGNUM by returning the saved LR_REGNUM. | |
21 | + * frame.c (get_prev_frame): Store this frame's ID in the next | |
22 | + frame's unwound ID cache. | |
23 | + (deprecated_update_frame_pc_hack): Update the cached value in NEXT | |
24 | + as well. | |
25 | + | |
26 | + 2003-02-27 Andrew Cagney <cagney@redhat.com> | |
27 | + * frame.c (get_prev_frame): Rewrite the frame ID unwind code to | |
28 | + use unwind_dummy_id when available. | |
29 | + * gdbarch.sh (get_dummy_frame_id): New multi-arch method with | |
30 | + predicate. | |
31 | + * gdbarch.h, gdbarch.c: Regneerate. | |
32 | + | |
33 | +2003-03-04 Andrew Cagney <cagney@redhat.com> | |
34 | + | |
3 | 35 | * d10v-tdep.c (d10v_frame_unwind_cache): Update to work with |
4 | 36 | NEXT_FRAME and THIS_CACHE. |
5 | 37 | (d10v_frame_pc_unwind): Ditto. |
@@ -45,20 +45,9 @@ | ||
45 | 45 | |
46 | 46 | #include "gdb_assert.h" |
47 | 47 | |
48 | -static void d10v_frame_register_unwind (struct frame_info *next_frame, | |
49 | - void **this_cache, | |
50 | - int prev_regnum, int *optimizedp, | |
51 | - enum lval_type *lvalp, | |
52 | - CORE_ADDR *addrp, | |
53 | - int *realnump, void *bufferp); | |
54 | - | |
55 | - | |
56 | -struct frame_extra_info | |
57 | - { | |
58 | - CORE_ADDR return_pc; | |
59 | - int frameless; | |
60 | - int size; | |
61 | - }; | |
48 | +static void saved_regs_unwind (struct frame_info *next_frame, | |
49 | + CORE_ADDR *saved_regs, int prev_regnum, | |
50 | + void *bufferp); | |
62 | 51 | |
63 | 52 | struct gdbarch_tdep |
64 | 53 | { |
@@ -625,10 +614,10 @@ d10v_skip_prologue (CORE_ADDR pc) | ||
625 | 614 | struct d10v_unwind_cache |
626 | 615 | { |
627 | 616 | CORE_ADDR base; |
628 | - int frameless; | |
629 | 617 | int size; |
630 | 618 | CORE_ADDR *saved_regs; |
631 | - CORE_ADDR next_addr; | |
619 | + LONGEST next_addr; | |
620 | + LONGEST r11_addr; | |
632 | 621 | int uses_frame; |
633 | 622 | void **regs; |
634 | 623 | }; |
@@ -672,6 +661,15 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op, | ||
672 | 661 | if (op == 0x417E) |
673 | 662 | { |
674 | 663 | info->uses_frame = 1; |
664 | + info->r11_addr = info->next_addr; | |
665 | + return 1; | |
666 | + } | |
667 | + | |
668 | + /* st rn, @r11 */ | |
669 | + if ((op & 0x7E1F) == 0x6816) | |
670 | + { | |
671 | + n = (op & 0x1E0) >> 5; | |
672 | + info->saved_regs[n] = info->r11_addr; | |
675 | 673 | return 1; |
676 | 674 | } |
677 | 675 |
@@ -724,7 +722,6 @@ d10v_frame_unwind_cache (struct frame_info *next_frame, | ||
724 | 722 | (*this_cache) = info; |
725 | 723 | info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS); |
726 | 724 | |
727 | - info->frameless = 0; | |
728 | 725 | info->size = 0; |
729 | 726 | |
730 | 727 | info->next_addr = 0; |
@@ -784,40 +781,51 @@ d10v_frame_unwind_cache (struct frame_info *next_frame, | ||
784 | 781 | |
785 | 782 | info->size = -info->next_addr; |
786 | 783 | |
787 | - /* Start out with the frame's stack top. */ | |
788 | - frame_unwind_unsigned_register (next_frame, SP_REGNUM, &sp); | |
789 | - sp = d10v_make_daddr (sp); | |
790 | - | |
791 | - for (i = 0; i < NUM_REGS - 1; i++) | |
792 | - if (info->saved_regs[i]) | |
793 | - { | |
794 | - info->saved_regs[i] = sp - (info->next_addr - info->saved_regs[i]); | |
795 | - } | |
796 | - | |
797 | 784 | /* Compute the frame's base. */ |
798 | - if (info->saved_regs[FP_REGNUM]) | |
785 | + if (info->uses_frame) | |
799 | 786 | { |
800 | - /* The FP was saved, which means that the current FP is live. | |
801 | - Unwind its value from the NEXT frame. */ | |
787 | + /* The SP was moved into the FP. This indicates that a new | |
788 | + frame was created. Get THIS frame's FP value by unwinding it | |
789 | + from the next frame. */ | |
802 | 790 | frame_unwind_unsigned_register (next_frame, FP_REGNUM, &base); |
791 | + /* The FP points at the last saved register. Adjust the FP back | |
792 | + to before the first saved register giving the SP. */ | |
793 | + sp = base + info->size; | |
803 | 794 | } |
804 | 795 | else if (info->saved_regs[SP_REGNUM]) |
805 | 796 | { |
806 | - /* The SP was saved (this is very unusual), the frame base is | |
797 | + /* The SP was saved (which is very unusual), the frame base is | |
807 | 798 | just the PREV's frame's TOP-OF-STACK. */ |
808 | 799 | base = read_memory_unsigned_integer (info->saved_regs[SP_REGNUM], |
809 | 800 | register_size (current_gdbarch, |
810 | 801 | SP_REGNUM)); |
811 | - info->frameless = 1; | |
802 | + sp = base; | |
812 | 803 | } |
813 | 804 | else |
814 | 805 | { |
815 | 806 | /* Assume that the FP is this frame's SP but with that pushed |
816 | 807 | stack space added back. */ |
817 | 808 | frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base); |
818 | - base += info->size; | |
809 | + sp = base + info->size; | |
819 | 810 | } |
811 | + | |
820 | 812 | info->base = d10v_make_daddr (base); |
813 | + sp = d10v_make_daddr (sp); | |
814 | + | |
815 | + /* Adjust all the saved registers so that they contain addresses and | |
816 | + not offsets. */ | |
817 | + for (i = 0; i < NUM_REGS - 1; i++) | |
818 | + { | |
819 | + if (info->saved_regs[i]) | |
820 | + { | |
821 | + info->saved_regs[i] = (sp + info->saved_regs[i]); | |
822 | + } | |
823 | + } | |
824 | + | |
825 | + /* The SP_REGNUM is special. Instead of the address of the SP, the | |
826 | + previous frame's SP value is saved. */ | |
827 | + info->saved_regs[SP_REGNUM] = sp; | |
828 | + | |
821 | 829 | return info; |
822 | 830 | } |
823 | 831 |
@@ -1429,17 +1437,13 @@ static CORE_ADDR | ||
1429 | 1437 | d10v_frame_pc_unwind (struct frame_info *next_frame, |
1430 | 1438 | void **this_cache) |
1431 | 1439 | { |
1432 | - /* FIXME: This shouldn't be needed. Instead a per-architecture | |
1433 | - method should be called. */ | |
1434 | - int optimized; | |
1435 | - enum lval_type lval; | |
1436 | - CORE_ADDR addr; | |
1437 | - int realnum; | |
1438 | - ULONGEST lr; | |
1440 | + /* FIXME: This shouldn't be needed. Instead single per-architecture | |
1441 | + method should be called for all frames. */ | |
1442 | + CORE_ADDR lr; | |
1443 | + struct d10v_unwind_cache *info | |
1444 | + = d10v_frame_unwind_cache (next_frame, this_cache); | |
1439 | 1445 | void *buffer = alloca (max_register_size (current_gdbarch)); |
1440 | - d10v_frame_register_unwind (next_frame, this_cache, LR_REGNUM, | |
1441 | - &optimized, &lval, &addr, &realnum, | |
1442 | - buffer); | |
1446 | + saved_regs_unwind (next_frame, info->saved_regs, LR_REGNUM, buffer); | |
1443 | 1447 | lr = extract_unsigned_integer (buffer, register_size (current_gdbarch, |
1444 | 1448 | LR_REGNUM)); |
1445 | 1449 | return d10v_make_iaddr (lr); |
@@ -1472,26 +1476,24 @@ d10v_frame_id_unwind (struct frame_info *next_frame, | ||
1472 | 1476 | return; |
1473 | 1477 | } |
1474 | 1478 | |
1475 | -#if 0 | |
1476 | - if (!info->saved_regs[FP_REGNUM]) | |
1477 | - { | |
1478 | - if (!info->saved_regs[SP_REGNUM] | |
1479 | - || info->saved_regs[SP_REGNUM] == STACK_START) | |
1480 | - return; | |
1481 | - | |
1482 | - this_id->base = info->saved_regs[SP_REGNUM]; | |
1483 | - this_id->pc = info->return_pc; | |
1484 | - } | |
1479 | + /* Hopefully the prologue analysis either correctly determined the | |
1480 | + frame's base (which is the SP from the previous frame), or set | |
1481 | + that base to "NULL". */ | |
1482 | + base = info->base; | |
1483 | + if (base == STACK_START || base == 0) | |
1484 | + return; | |
1485 | 1485 | |
1486 | - addr = read_memory_unsigned_integer (info->saved_regs[FP_REGNUM], | |
1487 | - register_size (current_gdbarch, FP_REGNUM)); | |
1488 | - if (addr == 0) | |
1486 | + /* Check that we're not going round in circles on the same frame ID. | |
1487 | + Be careful to avoid applying the test to sentinel frames (which | |
1488 | + do go round in circles). Can't use ID_EQ as that doesn't yet | |
1489 | + compare PC values. */ | |
1490 | + if (frame_relative_level (next_frame) >= 0 | |
1491 | + && get_frame_type (next_frame) != DUMMY_FRAME | |
1492 | + && get_frame_id (next_frame).pc == pc | |
1493 | + && get_frame_id (next_frame).base == base) | |
1489 | 1494 | return; |
1490 | -#endif | |
1491 | 1495 | |
1492 | - /* Hopefully the prolog analysis has correctly determined the | |
1493 | - frame's base. */ | |
1494 | - this_id->base = info->base; | |
1496 | + this_id->base = base; | |
1495 | 1497 | this_id->pc = pc; |
1496 | 1498 | } |
1497 | 1499 |
@@ -1504,15 +1506,30 @@ saved_regs_unwinder (struct frame_info *next_frame, | ||
1504 | 1506 | { |
1505 | 1507 | if (saved_regs[prev_regnum] != 0) |
1506 | 1508 | { |
1507 | - *optimizedp = 0; | |
1508 | - *lvalp = lval_memory; | |
1509 | - *addrp = saved_regs[prev_regnum]; | |
1510 | - *realnump = -1; | |
1511 | - if (bufferp != NULL) | |
1509 | + if (prev_regnum == SP_REGNUM) | |
1510 | + { | |
1511 | + /* SP register treated specially. */ | |
1512 | + *optimizedp = 0; | |
1513 | + *lvalp = not_lval; | |
1514 | + *addrp = 0; | |
1515 | + *realnump = -1; | |
1516 | + if (bufferp != NULL) | |
1517 | + store_address (bufferp, | |
1518 | + register_size (current_gdbarch, SP_REGNUM), | |
1519 | + saved_regs[SP_REGNUM]); | |
1520 | + } | |
1521 | + else | |
1512 | 1522 | { |
1513 | - /* Read the value in from memory. */ | |
1514 | - read_memory (saved_regs[prev_regnum], bufferp, | |
1515 | - register_size (current_gdbarch, prev_regnum)); | |
1523 | + *optimizedp = 0; | |
1524 | + *lvalp = lval_memory; | |
1525 | + *addrp = saved_regs[prev_regnum]; | |
1526 | + *realnump = -1; | |
1527 | + if (bufferp != NULL) | |
1528 | + { | |
1529 | + /* Read the value in from memory. */ | |
1530 | + read_memory (saved_regs[prev_regnum], bufferp, | |
1531 | + register_size (current_gdbarch, prev_regnum)); | |
1532 | + } | |
1516 | 1533 | } |
1517 | 1534 | return; |
1518 | 1535 | } |
@@ -1525,6 +1542,20 @@ saved_regs_unwinder (struct frame_info *next_frame, | ||
1525 | 1542 | realnump, bufferp); |
1526 | 1543 | } |
1527 | 1544 | |
1545 | +/* Wrapper so that local code can unwind register values. */ | |
1546 | + | |
1547 | +static void | |
1548 | +saved_regs_unwind (struct frame_info *next_frame, CORE_ADDR *saved_regs, | |
1549 | + int prev_regnum, void *bufferp) | |
1550 | +{ | |
1551 | + int optimized; | |
1552 | + enum lval_type lval; | |
1553 | + CORE_ADDR addr; | |
1554 | + int realnum; | |
1555 | + saved_regs_unwinder (next_frame, saved_regs, prev_regnum, | |
1556 | + &optimized, &lval, &addr, &realnum, bufferp); | |
1557 | +} | |
1558 | + | |
1528 | 1559 | |
1529 | 1560 | static void |
1530 | 1561 | d10v_frame_register_unwind (struct frame_info *next_frame, |
@@ -1535,44 +1566,67 @@ d10v_frame_register_unwind (struct frame_info *next_frame, | ||
1535 | 1566 | { |
1536 | 1567 | struct d10v_unwind_cache *info |
1537 | 1568 | = d10v_frame_unwind_cache (next_frame, this_cache); |
1538 | - if (prev_regnum == PC_REGNUM) | |
1539 | - prev_regnum = LR_REGNUM; | |
1540 | - saved_regs_unwinder (next_frame, info->saved_regs, prev_regnum, optimizedp, | |
1541 | - lvalp, addrp, realnump, bufferp); | |
1569 | + if (prev_regnum == LR_REGNUM) | |
1570 | + /* Unwinding the LR isn't possible. It's value is trashed by the | |
1571 | + call instruction. Mark the value as optimized away. */ | |
1572 | + { | |
1573 | + *optimizedp = 1; | |
1574 | + *lvalp = lval_register; | |
1575 | + *addrp = 0; | |
1576 | + *realnump = LR_REGNUM; | |
1577 | + if (bufferp != NULL) | |
1578 | + memset (bufferp, 0, register_size (current_gdbarch, LR_REGNUM)); | |
1579 | + } | |
1580 | + else if (prev_regnum == PC_REGNUM) | |
1581 | + /* The caller's PC is saved in LR_REGNUM. Find/return the | |
1582 | + LR_REGNUM. */ | |
1583 | + saved_regs_unwinder (next_frame, info->saved_regs, LR_REGNUM, optimizedp, | |
1584 | + lvalp, addrp, realnump, bufferp); | |
1585 | + else | |
1586 | + saved_regs_unwinder (next_frame, info->saved_regs, prev_regnum, optimizedp, | |
1587 | + lvalp, addrp, realnump, bufferp); | |
1542 | 1588 | } |
1543 | 1589 | |
1544 | 1590 | |
1591 | +static struct frame_id | |
1592 | +d10v_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) | |
1593 | +{ | |
1594 | + ULONGEST base; | |
1595 | + struct frame_id id; | |
1596 | + id.pc = frame_pc_unwind (next_frame); | |
1597 | + frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base); | |
1598 | + id.base = d10v_make_daddr (base); | |
1599 | + return id; | |
1600 | +} | |
1601 | + | |
1545 | 1602 | static void |
1546 | -d10v_frame_pop (struct frame_info *fi, void **unwind_cache, | |
1603 | +d10v_frame_pop (struct frame_info *next_frame, void **this_cache, | |
1547 | 1604 | struct regcache *regcache) |
1548 | 1605 | { |
1549 | - struct d10v_unwind_cache *info = d10v_frame_unwind_cache (fi, unwind_cache); | |
1606 | + struct d10v_unwind_cache *info | |
1607 | + = d10v_frame_unwind_cache (next_frame, this_cache); | |
1550 | 1608 | CORE_ADDR fp; |
1551 | 1609 | int regnum; |
1552 | 1610 | char raw_buffer[8]; |
1553 | 1611 | |
1554 | - fp = get_frame_base (fi); | |
1555 | - | |
1556 | 1612 | /* now update the current registers with the old values */ |
1557 | 1613 | for (regnum = A0_REGNUM; regnum < A0_REGNUM + NR_A_REGS; regnum++) |
1558 | 1614 | { |
1559 | - frame_unwind_register (fi, regnum, raw_buffer); | |
1615 | + saved_regs_unwind (next_frame, info->saved_regs, regnum, raw_buffer); | |
1560 | 1616 | regcache_cooked_write (regcache, regnum, raw_buffer); |
1561 | 1617 | } |
1562 | 1618 | for (regnum = 0; regnum < SP_REGNUM; regnum++) |
1563 | 1619 | { |
1564 | - frame_unwind_register (fi, regnum, raw_buffer); | |
1620 | + saved_regs_unwind (next_frame, info->saved_regs, regnum, raw_buffer); | |
1565 | 1621 | regcache_cooked_write (regcache, regnum, raw_buffer); |
1566 | 1622 | } |
1567 | - frame_unwind_register (fi, PSW_REGNUM, raw_buffer); | |
1623 | + saved_regs_unwind (next_frame, info->saved_regs, PSW_REGNUM, raw_buffer); | |
1568 | 1624 | regcache_cooked_write (regcache, PSW_REGNUM, raw_buffer); |
1569 | 1625 | |
1570 | - frame_unwind_register (fi, LR_REGNUM, raw_buffer); | |
1626 | + saved_regs_unwind (next_frame, info->saved_regs, LR_REGNUM, raw_buffer); | |
1571 | 1627 | regcache_cooked_write (regcache, PC_REGNUM, raw_buffer); |
1572 | 1628 | |
1573 | - store_unsigned_integer (raw_buffer, | |
1574 | - register_size (current_gdbarch, SP_REGNUM), | |
1575 | - fp + info->size); | |
1629 | + saved_regs_unwind (next_frame, info->saved_regs, SP_REGNUM, raw_buffer); | |
1576 | 1630 | regcache_cooked_write (regcache, SP_REGNUM, raw_buffer); |
1577 | 1631 | |
1578 | 1632 | target_store_registers (-1); |
@@ -1728,6 +1782,8 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | ||
1728 | 1782 | set_gdbarch_print_registers_info (gdbarch, d10v_print_registers_info); |
1729 | 1783 | |
1730 | 1784 | frame_unwind_append_predicate (gdbarch, d10v_frame_p); |
1785 | + set_gdbarch_unwind_dummy_id (gdbarch, d10v_unwind_dummy_id); | |
1786 | + set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos); | |
1731 | 1787 | |
1732 | 1788 | return gdbarch; |
1733 | 1789 | } |
@@ -1,3 +1,10 @@ | ||
1 | +2003-03-04 Andrew Cagney <cagney@redhat.com> | |
2 | + | |
3 | + 2003-02-27 Andrew Cagney <cagney@redhat.com> | |
4 | + * gdbint.texinfo (Target Architecture Definition): Document | |
5 | + unwind_dummy_id. Cross reference unwind_dummy_id and | |
6 | + SAVE_DUMMY_FRAME_TOS. | |
7 | + | |
1 | 8 | 2003-03-02 Daniel Jacobowitz <drow@mvista.com> |
2 | 9 | |
3 | 10 | * Makefile.in (distclean): Remove config.log. |
@@ -3691,10 +3691,11 @@ rather than directly. | ||
3691 | 3691 | |
3692 | 3692 | @item SAVE_DUMMY_FRAME_TOS (@var{sp}) |
3693 | 3693 | @findex SAVE_DUMMY_FRAME_TOS |
3694 | -Used in @samp{call_function_by_hand} to notify the target dependent code | |
3695 | -of the top-of-stack value that will be passed to the the inferior code. | |
3696 | -This is the value of the @code{SP} after both the dummy frame and space | |
3697 | -for parameters/results have been allocated on the stack. | |
3694 | +@anchor{SAVE_DUMMY_FRAME_TOS} Used in @samp{call_function_by_hand} to | |
3695 | +notify the target dependent code of the top-of-stack value that will be | |
3696 | +passed to the the inferior code. This is the value of the @code{SP} | |
3697 | +after both the dummy frame and space for parameters/results have been | |
3698 | +allocated on the stack. @xref{unwind_dummy_id}. | |
3698 | 3699 | |
3699 | 3700 | @item SDB_REG_TO_REGNUM |
3700 | 3701 | @findex SDB_REG_TO_REGNUM |
@@ -3878,6 +3879,14 @@ Libraries, ,Opcodes}). @var{info} is a structure (of type | ||
3878 | 3879 | @code{disassemble_info}) defined in @file{include/dis-asm.h} used to |
3879 | 3880 | pass information to the instruction decoding routine. |
3880 | 3881 | |
3882 | +@item struct frame_id unwind_dummy_id (struct frame_info *@var{frame}) | |
3883 | +@findex unwind_dummy_id | |
3884 | +@anchor{unwind_dummy_id} Given @var{frame} return a @code{struct | |
3885 | +frame_id} that uniquely identifies an inferior function call's dummy | |
3886 | +frame. The value returned must match the dummy frame stack value | |
3887 | +previously saved using @code{SAVE_DUMMY_FRAME_TOS}. | |
3888 | +@xref{SAVE_DUMMY_FRAME_TOS}. | |
3889 | + | |
3881 | 3890 | @item USE_STRUCT_CONVENTION (@var{gcc_p}, @var{type}) |
3882 | 3891 | @findex USE_STRUCT_CONVENTION |
3883 | 3892 | If defined, this must be an expression that is nonzero if a value of the |
@@ -1345,39 +1345,83 @@ get_prev_frame (struct frame_info *next_frame) | ||
1345 | 1345 | prev_frame->unwind = frame_unwind_find_by_pc (current_gdbarch, |
1346 | 1346 | prev_frame->pc); |
1347 | 1347 | |
1348 | - /* FIXME: cagney/2003-01-13: A dummy frame doesn't need to unwind | |
1349 | - the frame ID because the frame ID comes from the previous frame. | |
1350 | - The other frames do though. True? */ | |
1348 | + /* Find the prev's frame's ID. */ | |
1351 | 1349 | { |
1352 | - /* FIXME: cagney/2002-12-18: Instead of this hack, should just | |
1353 | - save the frame ID directly. */ | |
1354 | - struct frame_id id; | |
1355 | - prev_frame->unwind->id (next_frame, &prev_frame->unwind_cache, &id); | |
1356 | - /* Check that the unwound ID is valid. As of 2003-02-24 the | |
1357 | - x86-64 was returning an invalid frame ID when trying to do an | |
1358 | - unwind a sentinel frame that belonged to a frame dummy. */ | |
1359 | - if (!frame_id_p (id)) | |
1350 | + switch (prev_frame->type) | |
1360 | 1351 | { |
1361 | - if (frame_debug) | |
1362 | - fprintf_unfiltered (gdb_stdlog, | |
1363 | - "Outermost frame - unwound frame ID invalid\n"); | |
1364 | - return NULL; | |
1352 | + case DUMMY_FRAME: | |
1353 | + /* A dummy doesn't have anything resembling either a sane | |
1354 | + frame or PC. The PC is sitting in the entry code and the | |
1355 | + stack, which has nothing to do with that entry address, is | |
1356 | + a down right mess. Trying to use the standard frame ID | |
1357 | + unwind code to get the previous frame ID is just asking for | |
1358 | + trouble. */ | |
1359 | + if (gdbarch_unwind_dummy_id_p (current_gdbarch)) | |
1360 | + { | |
1361 | + /* Assume hand_function_call(), via SAVE_DUMMY_FRAME_TOS, | |
1362 | + previously saved the dummy ID that is being obtained | |
1363 | + here. Things only work if the two match. */ | |
1364 | + gdb_assert (SAVE_DUMMY_FRAME_TOS_P ()); | |
1365 | + /* Use an architecture specific method to extract the | |
1366 | + prev's dummy ID from the next frame. Note that this | |
1367 | + method typically uses frame_register_unwind to obtain | |
1368 | + register values needed to determine the dummy ID. */ | |
1369 | + next_frame->id_unwind_cache = | |
1370 | + gdbarch_unwind_dummy_id (current_gdbarch, next_frame); | |
1371 | + } | |
1372 | + else if (next_frame->level == 0) | |
1373 | + { | |
1374 | + /* We're `unwinding' the sentinel frame. Just fake up the | |
1375 | + ID the same way that the traditional hacks did it. */ | |
1376 | + next_frame->id_unwind_cache.pc = read_pc (); | |
1377 | + next_frame->id_unwind_cache.pc = read_fp (); | |
1378 | + } | |
1379 | + else | |
1380 | + { | |
1381 | + /* Outch! We're not on the innermost frame yet we're | |
1382 | + trying to unwind to a dummy. The architecture must | |
1383 | + provide the unwind_dummy_id() method. */ | |
1384 | + internal_error (__FILE__, __LINE__, | |
1385 | + "Missing unwind_dummy_id architecture method"); | |
1386 | + } | |
1387 | + break; | |
1388 | + case NORMAL_FRAME: | |
1389 | + case SIGTRAMP_FRAME: | |
1390 | + prev_frame->unwind->id (next_frame, &prev_frame->unwind_cache, | |
1391 | + &next_frame->id_unwind_cache); | |
1392 | + /* Check that the unwound ID is valid. */ | |
1393 | + if (!frame_id_p (next_frame->id_unwind_cache)) | |
1394 | + { | |
1395 | + if (frame_debug) | |
1396 | + fprintf_unfiltered (gdb_stdlog, | |
1397 | + "Outermost frame - unwound frame ID invalid\n"); | |
1398 | + return NULL; | |
1399 | + } | |
1400 | + /* Check that the new frame isn't inner to (younger, below, | |
1401 | + next) the old frame. If that happens the frame unwind is | |
1402 | + going backwards. */ | |
1403 | + /* FIXME: cagney/2003-02-25: Ignore the sentinel frame since | |
1404 | + that doesn't have a valid frame ID. Should instead set the | |
1405 | + sentinel frame's frame ID to a `sentinel'. Leave it until | |
1406 | + after the switch to storing the frame ID, instead of the | |
1407 | + frame base, in the frame object. */ | |
1408 | + if (next_frame->level >= 0 | |
1409 | + && frame_id_inner (next_frame->id_unwind_cache, | |
1410 | + get_frame_id (next_frame))) | |
1411 | + error ("Unwound frame inner-to selected frame (corrupt stack?)"); | |
1412 | + /* Note that, due to frameless functions, the stronger test of | |
1413 | + the new frame being outer to the old frame can't be used - | |
1414 | + frameless functions differ by only their PC value. */ | |
1415 | + break; | |
1416 | + default: | |
1417 | + internal_error (__FILE__, __LINE__, "bad switch"); | |
1365 | 1418 | } |
1366 | - /* Check that the new frame isn't inner to (younger, below, next) | |
1367 | - the old frame. If that happens the frame unwind is going | |
1368 | - backwards. */ | |
1369 | - /* FIXME: cagney/2003-02-25: Ignore the sentinel frame since that | |
1370 | - doesn't have a valid frame ID. Should instead set the sentinel | |
1371 | - frame's frame ID to a `sentinel'. Leave it until after the | |
1372 | - switch to storing the frame ID, instead of the frame base, in | |
1373 | - the frame object. */ | |
1374 | - if (next_frame->level >= 0 | |
1375 | - && frame_id_inner (id, get_frame_id (next_frame))) | |
1376 | - error ("Unwound frame inner-to selected frame (corrupt stack?)"); | |
1377 | - /* Note that, due to frameless functions, the stronger test of the | |
1378 | - new frame being outer to the old frame can't be used - | |
1379 | - frameless functions differ by only their PC value. */ | |
1380 | - prev_frame->frame = id.base; | |
1419 | + /* FIXME: cagney/2002-12-18: Instead of this hack, the frame ID | |
1420 | + should be directly stored in the `struct frame_info'. | |
1421 | + Unfortunatly, GDB isn't quite ready for this, need to get HP/UX | |
1422 | + multi-arch and make 'struct frame_info' opaque. */ | |
1423 | + next_frame->id_unwind_cache_p = 1; | |
1424 | + prev_frame->frame = next_frame->id_unwind_cache.base; | |
1381 | 1425 | } |
1382 | 1426 | |
1383 | 1427 | /* Link it in. */ |
@@ -1514,7 +1558,12 @@ deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc) | ||
1514 | 1558 | { |
1515 | 1559 | /* See comment in "frame.h". */ |
1516 | 1560 | gdb_assert (frame->next != NULL); |
1561 | + /* Fix up this PC's value. */ | |
1517 | 1562 | frame->pc = pc; |
1563 | + /* While we're at it, also update the cache, in NEXT, that also | |
1564 | + contains that value. */ | |
1565 | + frame->next->pc_unwind_cache = pc; | |
1566 | + frame->next->pc_unwind_cache_p = 1; | |
1518 | 1567 | } |
1519 | 1568 | |
1520 | 1569 | void |
@@ -251,6 +251,7 @@ struct gdbarch | ||
251 | 251 | int extra_stack_alignment_needed; |
252 | 252 | gdbarch_reg_struct_has_addr_ftype *reg_struct_has_addr; |
253 | 253 | gdbarch_save_dummy_frame_tos_ftype *save_dummy_frame_tos; |
254 | + gdbarch_unwind_dummy_id_ftype *unwind_dummy_id; | |
254 | 255 | int parm_boundary; |
255 | 256 | const struct floatformat * float_format; |
256 | 257 | const struct floatformat * double_format; |
@@ -431,6 +432,7 @@ struct gdbarch startup_gdbarch = | ||
431 | 432 | 0, |
432 | 433 | 0, |
433 | 434 | 0, |
435 | + 0, | |
434 | 436 | generic_in_function_epilogue_p, |
435 | 437 | construct_inferior_arguments, |
436 | 438 | 0, |
@@ -770,6 +772,7 @@ verify_gdbarch (struct gdbarch *gdbarch) | ||
770 | 772 | /* Skip verify of extra_stack_alignment_needed, invalid_p == 0 */ |
771 | 773 | /* Skip verify of reg_struct_has_addr, has predicate */ |
772 | 774 | /* Skip verify of save_dummy_frame_tos, has predicate */ |
775 | + /* Skip verify of unwind_dummy_id, has predicate */ | |
773 | 776 | if (gdbarch->float_format == 0) |
774 | 777 | gdbarch->float_format = default_float_format (gdbarch); |
775 | 778 | if (gdbarch->double_format == 0) |
@@ -2567,6 +2570,14 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) | ||
2567 | 2570 | (long) current_gdbarch->write_sp |
2568 | 2571 | /*TARGET_WRITE_SP ()*/); |
2569 | 2572 | #endif |
2573 | + if (GDB_MULTI_ARCH) | |
2574 | + fprintf_unfiltered (file, | |
2575 | + "gdbarch_dump: gdbarch_unwind_dummy_id_p() = %d\n", | |
2576 | + gdbarch_unwind_dummy_id_p (current_gdbarch)); | |
2577 | + if (GDB_MULTI_ARCH) | |
2578 | + fprintf_unfiltered (file, | |
2579 | + "gdbarch_dump: unwind_dummy_id = 0x%08lx\n", | |
2580 | + (long) current_gdbarch->unwind_dummy_id); | |
2570 | 2581 | #ifdef USE_STRUCT_CONVENTION |
2571 | 2582 | fprintf_unfiltered (file, |
2572 | 2583 | "gdbarch_dump: %s # %s\n", |
@@ -5032,6 +5043,32 @@ set_gdbarch_save_dummy_frame_tos (struct gdbarch *gdbarch, | ||
5032 | 5043 | } |
5033 | 5044 | |
5034 | 5045 | int |
5046 | +gdbarch_unwind_dummy_id_p (struct gdbarch *gdbarch) | |
5047 | +{ | |
5048 | + gdb_assert (gdbarch != NULL); | |
5049 | + return gdbarch->unwind_dummy_id != 0; | |
5050 | +} | |
5051 | + | |
5052 | +struct frame_id | |
5053 | +gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *info) | |
5054 | +{ | |
5055 | + gdb_assert (gdbarch != NULL); | |
5056 | + if (gdbarch->unwind_dummy_id == 0) | |
5057 | + internal_error (__FILE__, __LINE__, | |
5058 | + "gdbarch: gdbarch_unwind_dummy_id invalid"); | |
5059 | + if (gdbarch_debug >= 2) | |
5060 | + fprintf_unfiltered (gdb_stdlog, "gdbarch_unwind_dummy_id called\n"); | |
5061 | + return gdbarch->unwind_dummy_id (gdbarch, info); | |
5062 | +} | |
5063 | + | |
5064 | +void | |
5065 | +set_gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, | |
5066 | + gdbarch_unwind_dummy_id_ftype unwind_dummy_id) | |
5067 | +{ | |
5068 | + gdbarch->unwind_dummy_id = unwind_dummy_id; | |
5069 | +} | |
5070 | + | |
5071 | +int | |
5035 | 5072 | gdbarch_parm_boundary (struct gdbarch *gdbarch) |
5036 | 5073 | { |
5037 | 5074 | gdb_assert (gdbarch != NULL); |
@@ -2458,6 +2458,12 @@ extern void set_gdbarch_save_dummy_frame_tos (struct gdbarch *gdbarch, gdbarch_s | ||
2458 | 2458 | #endif |
2459 | 2459 | #endif |
2460 | 2460 | |
2461 | +extern int gdbarch_unwind_dummy_id_p (struct gdbarch *gdbarch); | |
2462 | + | |
2463 | +typedef struct frame_id (gdbarch_unwind_dummy_id_ftype) (struct gdbarch *gdbarch, struct frame_info *info); | |
2464 | +extern struct frame_id gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *info); | |
2465 | +extern void set_gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, gdbarch_unwind_dummy_id_ftype *unwind_dummy_id); | |
2466 | + | |
2461 | 2467 | extern int gdbarch_parm_boundary (struct gdbarch *gdbarch); |
2462 | 2468 | extern void set_gdbarch_parm_boundary (struct gdbarch *gdbarch, int parm_boundary); |
2463 | 2469 | #if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (PARM_BOUNDARY) |
@@ -602,6 +602,7 @@ M:::CORE_ADDR:frame_align:CORE_ADDR address:address | ||
602 | 602 | v:2:EXTRA_STACK_ALIGNMENT_NEEDED:int:extra_stack_alignment_needed::::0:1::0::: |
603 | 603 | F:2:REG_STRUCT_HAS_ADDR:int:reg_struct_has_addr:int gcc_p, struct type *type:gcc_p, type::0:0 |
604 | 604 | F:2:SAVE_DUMMY_FRAME_TOS:void:save_dummy_frame_tos:CORE_ADDR sp:sp::0:0 |
605 | +M::UNWIND_DUMMY_ID:struct frame_id:unwind_dummy_id:struct frame_info *info:info::0:0 | |
605 | 606 | v:2:PARM_BOUNDARY:int:parm_boundary |
606 | 607 | # |
607 | 608 | v:2:TARGET_FLOAT_FORMAT:const struct floatformat *:float_format::::::default_float_format (gdbarch)::%s:(TARGET_FLOAT_FORMAT)->name |