GNU Binutils with patches for OS216
Revision | 9712a26d7d2b502a43eda619bce184d065420697 (tree) |
---|---|
Time | 2003-03-18 01:17:56 |
Author | Andrew Cagney <cagney@redh...> |
Commiter | Andrew Cagney |
2003-03-17 Andrew Cagney <cagney@redhat.com>
* frame.c (get_frame_id): If the frame's ID isn't valid, get it.
(get_prev_frame): Validate THIS frame's ID before trying to unwind
to prev frame. Don't compute PREV's frame's ID.
(get_frame_base): Force the update of frame ID before returning
the frame.
* frame.h (struct frame_info): Add "id_p".
@@ -1,5 +1,14 @@ | ||
1 | 1 | 2003-03-17 Andrew Cagney <cagney@redhat.com> |
2 | 2 | |
3 | + * frame.c (get_frame_id): If the frame's ID isn't valid, get it. | |
4 | + (get_prev_frame): Validate THIS frame's ID before trying to unwind | |
5 | + to prev frame. Don't compute PREV's frame's ID. | |
6 | + (get_frame_base): Force the update of frame ID before returning | |
7 | + the frame. | |
8 | + * frame.h (struct frame_info): Add "id_p". | |
9 | + | |
10 | +2003-03-17 Andrew Cagney <cagney@redhat.com> | |
11 | + | |
3 | 12 | Fix frame off-by-one bug. |
4 | 13 | * frame-unwind.h (frame_this_id_ftype): Replace |
5 | 14 | frame_unwind_id_ftype. |
@@ -53,17 +53,50 @@ static int backtrace_below_main; | ||
53 | 53 | struct frame_id |
54 | 54 | get_frame_id (struct frame_info *fi) |
55 | 55 | { |
56 | + struct frame_id id; | |
56 | 57 | if (fi == NULL) |
57 | 58 | { |
59 | + /* Should never happen! */ | |
58 | 60 | return null_frame_id; |
59 | 61 | } |
60 | - else | |
62 | + if (!fi->id_p) | |
61 | 63 | { |
62 | - struct frame_id id; | |
63 | - id.base = fi->frame; | |
64 | - id.pc = fi->pc; | |
65 | - return id; | |
64 | + gdb_assert (!legacy_frame_p (current_gdbarch)); | |
65 | + | |
66 | + /* Find THIS frame's ID. */ | |
67 | + fi->unwind->this_id (fi->next, &fi->prologue_cache, &fi->id); | |
68 | + fi->id_p = 1; | |
69 | + | |
70 | + /* Check that the unwound ID is valid. */ | |
71 | + if (!frame_id_p (fi->id) && frame_debug) | |
72 | + fprintf_unfiltered (gdb_stdlog, | |
73 | + "Unwound frame ID invalid\n"); | |
74 | + | |
75 | + /* Check that the new frame isn't inner to (younger, below, next) | |
76 | + the old frame. If that happens the frame unwind is going | |
77 | + backwards. */ | |
78 | + /* FIXME: cagney/2003-02-25: Ignore the sentinel frame since | |
79 | + that doesn't have a valid frame ID. Should instead set the | |
80 | + sentinel frame's frame ID to a true `sentinel'. Leave it | |
81 | + until after the switch to storing the frame ID, instead of | |
82 | + the frame base, in the frame object. */ | |
83 | + if (fi->level >= 0 && frame_id_p (fi->id) && fi->next->id_p | |
84 | + && frame_id_inner (fi->id, get_frame_id (fi->next))) | |
85 | + error ("Unwound frame inner-to selected frame (corrupt stack?)"); | |
86 | + | |
87 | + /* Note that, due to frameless functions, the stronger test of | |
88 | + the new frame being outer to the old frame can't be used - | |
89 | + frameless functions differ by only their PC value. */ | |
90 | + | |
91 | + /* FIXME: cagney/2002-12-18: Instead of this hack, should only | |
92 | + store the frame ID in PREV_FRAME. Unfortunatly, some | |
93 | + architectures (HP/UX) still reply on EXTRA_FRAME_INFO and, | |
94 | + hence, still poke at the "struct frame_info" object directly. */ | |
95 | + fi->frame = fi->id.base; | |
66 | 96 | } |
97 | + id.base = fi->frame; | |
98 | + id.pc = fi->pc; | |
99 | + return id; | |
67 | 100 | } |
68 | 101 | |
69 | 102 | const struct frame_id null_frame_id; /* All zeros. */ |
@@ -1452,6 +1485,39 @@ get_prev_frame (struct frame_info *this_frame) | ||
1452 | 1485 | return NULL; |
1453 | 1486 | } |
1454 | 1487 | |
1488 | + /* If THIS frame ended up with a NULL frame ID, don't bother trying | |
1489 | + to unwind it. */ | |
1490 | + if (this_frame->level >= 0 && !frame_id_p (get_frame_id (this_frame))) | |
1491 | + { | |
1492 | + if (frame_debug) | |
1493 | + fprintf_filtered (gdb_stdlog, | |
1494 | + "Outermost frame - next ID is NULL\n"); | |
1495 | + return NULL; | |
1496 | + } | |
1497 | + | |
1498 | + /* Check that THIS frame isn't inner to (younger, below, next) the | |
1499 | + NEXT frame. If that happens the frame unwind went backwards. */ | |
1500 | + /* FIXME: cagney/2003-02-25: Instead of ignoring the sentinel frame | |
1501 | + (since that doesn't have a valid frame ID), the code should set | |
1502 | + the sentinel frame's frame ID to a true `sentinel'. Leave it | |
1503 | + until after the switch to storing the frame ID, instead of the | |
1504 | + frame base, in the frame object. */ | |
1505 | + if (this_frame->level > 0 | |
1506 | + && frame_id_inner (get_frame_id (this_frame), | |
1507 | + get_frame_id (this_frame->next))) | |
1508 | + error ("This frame inner-to next frame (corrupt stack?)"); | |
1509 | + | |
1510 | + /* Check that THIS and NEXT frame are different. If they are not, | |
1511 | + there is most likely a stack cycle. */ | |
1512 | + /* FIXME: cagney/2003-03-17: Can't yet do this check. The | |
1513 | + frame_id_eq() method doesn't yet use function addresses when | |
1514 | + comparing IDs. */ | |
1515 | + if (0 | |
1516 | + && this_frame->level > 0 | |
1517 | + && frame_id_eq (get_frame_id (this_frame), | |
1518 | + get_frame_id (this_frame->next))) | |
1519 | + error ("This frame identical to next frame (corrupt stack?)"); | |
1520 | + | |
1455 | 1521 | /* If any of the old frame initialization methods are around, use |
1456 | 1522 | the legacy get_prev_frame method. */ |
1457 | 1523 | if (legacy_frame_p (current_gdbarch)) |
@@ -1509,63 +1575,7 @@ get_prev_frame (struct frame_info *this_frame) | ||
1509 | 1575 | prev_frame->unwind = frame_unwind_find_by_pc (current_gdbarch, |
1510 | 1576 | prev_frame->pc); |
1511 | 1577 | |
1512 | - /* Find the prev's frame's ID. */ | |
1513 | - | |
1514 | - /* The callee expects to be invoked with: | |
1515 | - | |
1516 | - this->unwind->this_id (this->next, &this->cache, &this->id); | |
1517 | - | |
1518 | - The below is carefully shifted one frame `to the left' so that | |
1519 | - both the unwind->this_id and unwind->prev_register methods are | |
1520 | - consistently invoked with NEXT_FRAME and THIS_PROLOGUE_CACHE. | |
1521 | - | |
1522 | - Also note that, while the PC for this new previous frame was | |
1523 | - unwound first (see above), the below is the first call that | |
1524 | - [potentially] requires analysis of the new previous frame's | |
1525 | - prologue. Consequently, it is this call, that typically ends up | |
1526 | - initializing the previous frame's prologue cache. */ | |
1527 | - prev_frame->unwind->this_id (this_frame, | |
1528 | - &prev_frame->prologue_cache, | |
1529 | - &prev_frame->id); | |
1530 | - | |
1531 | - /* Check that the unwound ID is valid. */ | |
1532 | - if (!frame_id_p (prev_frame->id)) | |
1533 | - { | |
1534 | - if (frame_debug) | |
1535 | - fprintf_unfiltered (gdb_stdlog, | |
1536 | - "Outermost frame - unwound frame ID invalid\n"); | |
1537 | - return NULL; | |
1538 | - } | |
1539 | - | |
1540 | - /* Check that the new frame isn't inner to (younger, below, next) | |
1541 | - the old frame. If that happens the frame unwind is going | |
1542 | - backwards. */ | |
1543 | - /* FIXME: cagney/2003-02-25: Ignore the sentinel frame since that | |
1544 | - doesn't have a valid frame ID. Should instead set the sentinel | |
1545 | - frame's frame ID to a true `sentinel'. Leave it until after the | |
1546 | - switch to storing the frame ID, instead of the frame base, in the | |
1547 | - frame object. */ | |
1548 | - if (this_frame->level >= 0 | |
1549 | - && frame_id_inner (prev_frame->id, get_frame_id (this_frame))) | |
1550 | - error ("Unwound frame inner-to selected frame (corrupt stack?)"); | |
1551 | - | |
1552 | - /* FIXME: cagney/2003-03-14: Should check that this and next frame's | |
1553 | - IDs are different (i.e., !frame_id_eq()). Can't yet do that as | |
1554 | - the EQ function doesn't yet compare PC values. */ | |
1555 | - | |
1556 | - /* FIXME: cagney/2003-03-14: Should delay the evaluation of the | |
1557 | - frame ID until when it is needed. That way the inner most frame | |
1558 | - can be created without needing to do prologue analysis. */ | |
1559 | - | |
1560 | - /* Note that, due to frameless functions, the stronger test of the | |
1561 | - new frame being outer to the old frame can't be used - frameless | |
1562 | - functions differ by only their PC value. */ | |
1563 | - | |
1564 | - /* FIXME: cagney/2002-12-18: Instead of this hack, should only store | |
1565 | - the frame ID in PREV_FRAME. Unfortunatly, some architectures | |
1566 | - (HP/UX) still reply on EXTRA_FRAME_INFO and, hence, still poke at | |
1567 | - the "struct frame_info" object directly. */ | |
1568 | - prev_frame->frame = prev_frame->id.base; | |
1578 | + /* The PREV's frame ID is computed on-demand in get_frame_id(). */ | |
1569 | 1579 | |
1570 | 1580 | /* Link it in. */ |
1571 | 1581 | this_frame->prev = prev_frame; |
@@ -1608,6 +1618,12 @@ find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal) | ||
1608 | 1618 | CORE_ADDR |
1609 | 1619 | get_frame_base (struct frame_info *fi) |
1610 | 1620 | { |
1621 | + if (!fi->id_p) | |
1622 | + { | |
1623 | + /* Force the ID code to (indirectly) initialize the ->frame | |
1624 | + pointer. */ | |
1625 | + get_frame_id (fi); | |
1626 | + } | |
1611 | 1627 | return fi->frame; |
1612 | 1628 | } |
1613 | 1629 |
@@ -410,8 +410,10 @@ struct frame_info | ||
410 | 410 | CORE_ADDR pc_unwind_cache; |
411 | 411 | |
412 | 412 | /* This frame's ID. Note that the frame's ID, base and PC contain |
413 | - redundant information. */ | |
413 | + redundant information. If id_p is non-zero, the ID is assumed | |
414 | + to be valid. */ | |
414 | 415 | struct frame_id id; |
416 | + int id_p; | |
415 | 417 | |
416 | 418 | /* Pointers to the next (down, inner, younger) and previous (up, |
417 | 419 | outer, older) frame_info's in the frame cache. */ |