GNU Binutils with patches for OS216
Révision | fc34faedba1aacec97bca094627e9c322049e68d (tree) |
---|---|
l'heure | 2003-03-05 08:15:24 |
Auteur | Andrew Cagney <cagney@redh...> |
Commiter | Andrew Cagney |
2003-03-04 Andrew Cagney <cagney@redhat.com>
* d10v-tdep.c (d10v_frame_unwind_cache): Update to work with
NEXT_FRAME and THIS_CACHE.
(d10v_frame_pc_unwind): Ditto.
(d10v_frame_id_unwind): Ditto.
(saved_regs_unwinder): Ditto.
(d10v_frame_register_unwind): Ditto.
* dummy-frame.c (dummy_frame_register_unwind): Ditto.
(dummy_frame_pc_unwind): Ditto.
(cached_find_dummy_frame): Ditto.
(dummy_frame_id_unwind): Ditto.
(dummy_frame_pop): Ditto.
* sentinel-frame.c (sentinel_frame_register_unwind): Ditto.
(sentinel_frame_pc_unwind): Ditto.
(sentinel_frame_id_unwind): Ditto.
(sentinel_frame_pop): Ditto.
* frame.c (frame_id_unwind): Reinstate function.
* frame.h (frame_id_unwind): Reinstate declaration.
* frame.c (frame_pc_unwind): Pass frame->next to the PC's unwind
method.
(frame_pop, frame_register_unwind): Ditto.
* frame-unwind.h (frame_unwind_id_ftype, frame_unwind_reg_ftype)
(frame_unwind_pc_ftype, frame_unwind_pop_ftype): Re-specify
behavior in terms of PREV_REGNUM, THIS_CACHE and NEXT_FRAME.
@@ -1,3 +1,29 @@ | ||
1 | +2003-03-04 Andrew Cagney <cagney@redhat.com> | |
2 | + | |
3 | + * d10v-tdep.c (d10v_frame_unwind_cache): Update to work with | |
4 | + NEXT_FRAME and THIS_CACHE. | |
5 | + (d10v_frame_pc_unwind): Ditto. | |
6 | + (d10v_frame_id_unwind): Ditto. | |
7 | + (saved_regs_unwinder): Ditto. | |
8 | + (d10v_frame_register_unwind): Ditto. | |
9 | + * dummy-frame.c (dummy_frame_register_unwind): Ditto. | |
10 | + (dummy_frame_pc_unwind): Ditto. | |
11 | + (cached_find_dummy_frame): Ditto. | |
12 | + (dummy_frame_id_unwind): Ditto. | |
13 | + (dummy_frame_pop): Ditto. | |
14 | + * sentinel-frame.c (sentinel_frame_register_unwind): Ditto. | |
15 | + (sentinel_frame_pc_unwind): Ditto. | |
16 | + (sentinel_frame_id_unwind): Ditto. | |
17 | + (sentinel_frame_pop): Ditto. | |
18 | + * frame.c (frame_id_unwind): Reinstate function. | |
19 | + * frame.h (frame_id_unwind): Reinstate declaration. | |
20 | + * frame.c (frame_pc_unwind): Pass frame->next to the PC's unwind | |
21 | + method. | |
22 | + (frame_pop, frame_register_unwind): Ditto. | |
23 | + * frame-unwind.h (frame_unwind_id_ftype, frame_unwind_reg_ftype) | |
24 | + (frame_unwind_pc_ftype, frame_unwind_pop_ftype): Re-specify | |
25 | + behavior in terms of PREV_REGNUM, THIS_CACHE and NEXT_FRAME. | |
26 | + | |
1 | 27 | 2003-03-03 Andrew Cagney <cagney@redhat.com> |
2 | 28 | |
3 | 29 | * frame.c (frame_id_unwind): Delete function. |
@@ -45,6 +45,14 @@ | ||
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 | + | |
48 | 56 | struct frame_extra_info |
49 | 57 | { |
50 | 58 | CORE_ADDR return_pc; |
@@ -616,7 +624,7 @@ d10v_skip_prologue (CORE_ADDR pc) | ||
616 | 624 | |
617 | 625 | struct d10v_unwind_cache |
618 | 626 | { |
619 | - CORE_ADDR return_pc; | |
627 | + CORE_ADDR base; | |
620 | 628 | int frameless; |
621 | 629 | int size; |
622 | 630 | CORE_ADDR *saved_regs; |
@@ -698,30 +706,30 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op, | ||
698 | 706 | for it IS the sp for the next frame. */ |
699 | 707 | |
700 | 708 | struct d10v_unwind_cache * |
701 | -d10v_frame_unwind_cache (struct frame_info *fi, | |
702 | - void **cache) | |
709 | +d10v_frame_unwind_cache (struct frame_info *next_frame, | |
710 | + void **this_cache) | |
703 | 711 | { |
704 | - CORE_ADDR fp, pc; | |
712 | + CORE_ADDR pc; | |
713 | + ULONGEST sp; | |
714 | + ULONGEST base; | |
705 | 715 | unsigned long op; |
706 | 716 | unsigned short op1, op2; |
707 | 717 | int i; |
708 | 718 | struct d10v_unwind_cache *info; |
709 | 719 | |
710 | - if ((*cache)) | |
711 | - return (*cache); | |
720 | + if ((*this_cache)) | |
721 | + return (*this_cache); | |
712 | 722 | |
713 | 723 | info = FRAME_OBSTACK_ZALLOC (struct d10v_unwind_cache); |
714 | - (*cache) = info; | |
724 | + (*this_cache) = info; | |
715 | 725 | info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS); |
716 | 726 | |
717 | 727 | info->frameless = 0; |
718 | 728 | info->size = 0; |
719 | - info->return_pc = 0; | |
720 | 729 | |
721 | - fp = get_frame_base (fi); | |
722 | 730 | info->next_addr = 0; |
723 | 731 | |
724 | - pc = get_pc_function_start (get_frame_pc (fi)); | |
732 | + pc = get_pc_function_start (frame_pc_unwind (next_frame)); | |
725 | 733 | |
726 | 734 | info->uses_frame = 0; |
727 | 735 | while (1) |
@@ -776,45 +784,40 @@ d10v_frame_unwind_cache (struct frame_info *fi, | ||
776 | 784 | |
777 | 785 | info->size = -info->next_addr; |
778 | 786 | |
779 | - if (!(fp & 0xffff)) | |
780 | - fp = d10v_read_sp (); | |
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); | |
781 | 790 | |
782 | 791 | for (i = 0; i < NUM_REGS - 1; i++) |
783 | 792 | if (info->saved_regs[i]) |
784 | 793 | { |
785 | - info->saved_regs[i] = fp - (info->next_addr - info->saved_regs[i]); | |
794 | + info->saved_regs[i] = sp - (info->next_addr - info->saved_regs[i]); | |
786 | 795 | } |
787 | 796 | |
788 | - if (info->saved_regs[LR_REGNUM]) | |
797 | + /* Compute the frame's base. */ | |
798 | + if (info->saved_regs[FP_REGNUM]) | |
789 | 799 | { |
790 | - CORE_ADDR return_pc | |
791 | - = read_memory_unsigned_integer (info->saved_regs[LR_REGNUM], | |
792 | - register_size (current_gdbarch, LR_REGNUM)); | |
793 | - info->return_pc = d10v_make_iaddr (return_pc); | |
800 | + /* The FP was saved, which means that the current FP is live. | |
801 | + Unwind its value from the NEXT frame. */ | |
802 | + frame_unwind_unsigned_register (next_frame, FP_REGNUM, &base); | |
794 | 803 | } |
795 | - else | |
804 | + else if (info->saved_regs[SP_REGNUM]) | |
796 | 805 | { |
797 | - ULONGEST return_pc; | |
798 | - frame_read_unsigned_register (fi, LR_REGNUM, &return_pc); | |
799 | - info->return_pc = d10v_make_iaddr (return_pc); | |
806 | + /* The SP was saved (this is very unusual), the frame base is | |
807 | + just the PREV's frame's TOP-OF-STACK. */ | |
808 | + base = read_memory_unsigned_integer (info->saved_regs[SP_REGNUM], | |
809 | + register_size (current_gdbarch, | |
810 | + SP_REGNUM)); | |
811 | + info->frameless = 1; | |
800 | 812 | } |
801 | - | |
802 | - /* The SP is not normally (ever?) saved, but check anyway */ | |
803 | - if (!info->saved_regs[SP_REGNUM]) | |
813 | + else | |
804 | 814 | { |
805 | - /* if the FP was saved, that means the current FP is valid, */ | |
806 | - /* otherwise, it isn't being used, so we use the SP instead */ | |
807 | - if (info->uses_frame) | |
808 | - info->saved_regs[SP_REGNUM] | |
809 | - = d10v_read_fp () + info->size; | |
810 | - else | |
811 | - { | |
812 | - info->saved_regs[SP_REGNUM] = fp + info->size; | |
813 | - info->frameless = 1; | |
814 | - info->saved_regs[FP_REGNUM] = 0; | |
815 | - } | |
815 | + /* Assume that the FP is this frame's SP but with that pushed | |
816 | + stack space added back. */ | |
817 | + frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base); | |
818 | + base += info->size; | |
816 | 819 | } |
817 | - | |
820 | + info->base = d10v_make_daddr (base); | |
818 | 821 | return info; |
819 | 822 | } |
820 | 823 |
@@ -1423,95 +1426,93 @@ display_trace (int low, int high) | ||
1423 | 1426 | |
1424 | 1427 | |
1425 | 1428 | static CORE_ADDR |
1426 | -d10v_frame_pc_unwind (struct frame_info *frame, | |
1427 | - void **cache) | |
1429 | +d10v_frame_pc_unwind (struct frame_info *next_frame, | |
1430 | + void **this_cache) | |
1428 | 1431 | { |
1429 | - struct d10v_unwind_cache *info = d10v_frame_unwind_cache (frame, cache); | |
1430 | - return info->return_pc; | |
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; | |
1439 | + 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); | |
1443 | + lr = extract_unsigned_integer (buffer, register_size (current_gdbarch, | |
1444 | + LR_REGNUM)); | |
1445 | + return d10v_make_iaddr (lr); | |
1446 | + | |
1431 | 1447 | } |
1432 | 1448 | |
1433 | -/* Given a GDB frame, determine the address of the calling function's | |
1449 | +/* Given the next frame, determine the address of this function's | |
1434 | 1450 | frame. This will be used to create a new GDB frame struct. */ |
1435 | 1451 | |
1436 | 1452 | static void |
1437 | -d10v_frame_id_unwind (struct frame_info *frame, | |
1438 | - void **cache, | |
1439 | - struct frame_id *id) | |
1453 | +d10v_frame_id_unwind (struct frame_info *next_frame, | |
1454 | + void **this_cache, | |
1455 | + struct frame_id *this_id) | |
1440 | 1456 | { |
1441 | - struct d10v_unwind_cache *info = d10v_frame_unwind_cache (frame, cache); | |
1442 | - CORE_ADDR addr; | |
1457 | + struct d10v_unwind_cache *info | |
1458 | + = d10v_frame_unwind_cache (next_frame, this_cache); | |
1459 | + CORE_ADDR base; | |
1460 | + CORE_ADDR pc; | |
1443 | 1461 | |
1444 | 1462 | /* Start with a NULL frame ID. */ |
1445 | - (*id) = null_frame_id; | |
1463 | + (*this_id) = null_frame_id; | |
1464 | + | |
1465 | + /* The PC is easy. */ | |
1466 | + pc = frame_pc_unwind (next_frame); | |
1446 | 1467 | |
1447 | - if (info->return_pc == IMEM_START | |
1448 | - || info->return_pc <= IMEM_START | |
1449 | - || inside_entry_file (info->return_pc)) | |
1468 | + /* This is meant to halt the backtrace at "_start". Make sure we | |
1469 | + don't halt it at a generic dummy frame. */ | |
1470 | + if (pc == IMEM_START || pc <= IMEM_START || inside_entry_file (pc)) | |
1450 | 1471 | { |
1451 | - /* This is meant to halt the backtrace at "_start". | |
1452 | - Make sure we don't halt it at a generic dummy frame. */ | |
1453 | 1472 | return; |
1454 | 1473 | } |
1455 | 1474 | |
1475 | +#if 0 | |
1456 | 1476 | if (!info->saved_regs[FP_REGNUM]) |
1457 | 1477 | { |
1458 | 1478 | if (!info->saved_regs[SP_REGNUM] |
1459 | 1479 | || info->saved_regs[SP_REGNUM] == STACK_START) |
1460 | 1480 | return; |
1461 | 1481 | |
1462 | - id->base = info->saved_regs[SP_REGNUM]; | |
1463 | - id->pc = info->return_pc; | |
1482 | + this_id->base = info->saved_regs[SP_REGNUM]; | |
1483 | + this_id->pc = info->return_pc; | |
1464 | 1484 | } |
1465 | 1485 | |
1466 | 1486 | addr = read_memory_unsigned_integer (info->saved_regs[FP_REGNUM], |
1467 | 1487 | register_size (current_gdbarch, FP_REGNUM)); |
1468 | 1488 | if (addr == 0) |
1469 | 1489 | return; |
1490 | +#endif | |
1470 | 1491 | |
1471 | - id->base = d10v_make_daddr (addr); | |
1472 | - id->pc = info->return_pc; | |
1492 | + /* Hopefully the prolog analysis has correctly determined the | |
1493 | + frame's base. */ | |
1494 | + this_id->base = info->base; | |
1495 | + this_id->pc = pc; | |
1473 | 1496 | } |
1474 | 1497 | |
1475 | 1498 | static void |
1476 | -saved_regs_unwinder (struct frame_info *frame, | |
1499 | +saved_regs_unwinder (struct frame_info *next_frame, | |
1477 | 1500 | CORE_ADDR *saved_regs, |
1478 | - int regnum, int *optimizedp, | |
1501 | + int prev_regnum, int *optimizedp, | |
1479 | 1502 | enum lval_type *lvalp, CORE_ADDR *addrp, |
1480 | 1503 | int *realnump, void *bufferp) |
1481 | 1504 | { |
1482 | - /* If we're using generic dummy frames, we'd better not be in a call | |
1483 | - dummy. (generic_call_dummy_register_unwind ought to have been called | |
1484 | - instead.) */ | |
1485 | - gdb_assert (!(DEPRECATED_USE_GENERIC_DUMMY_FRAMES | |
1486 | - && (get_frame_type (frame) == DUMMY_FRAME))); | |
1487 | - | |
1488 | - if (saved_regs[regnum] != 0) | |
1505 | + if (saved_regs[prev_regnum] != 0) | |
1489 | 1506 | { |
1490 | - if (regnum == SP_REGNUM) | |
1507 | + *optimizedp = 0; | |
1508 | + *lvalp = lval_memory; | |
1509 | + *addrp = saved_regs[prev_regnum]; | |
1510 | + *realnump = -1; | |
1511 | + if (bufferp != NULL) | |
1491 | 1512 | { |
1492 | - /* SP register treated specially. */ | |
1493 | - *optimizedp = 0; | |
1494 | - *lvalp = not_lval; | |
1495 | - *addrp = 0; | |
1496 | - *realnump = -1; | |
1497 | - if (bufferp != NULL) | |
1498 | - store_address (bufferp, register_size (current_gdbarch, regnum), | |
1499 | - saved_regs[regnum]); | |
1500 | - } | |
1501 | - else | |
1502 | - { | |
1503 | - /* Any other register is saved in memory, fetch it but cache | |
1504 | - a local copy of its value. */ | |
1505 | - *optimizedp = 0; | |
1506 | - *lvalp = lval_memory; | |
1507 | - *addrp = saved_regs[regnum]; | |
1508 | - *realnump = -1; | |
1509 | - if (bufferp != NULL) | |
1510 | - { | |
1511 | - /* Read the value in from memory. */ | |
1512 | - read_memory (saved_regs[regnum], bufferp, | |
1513 | - register_size (current_gdbarch, regnum)); | |
1514 | - } | |
1513 | + /* Read the value in from memory. */ | |
1514 | + read_memory (saved_regs[prev_regnum], bufferp, | |
1515 | + register_size (current_gdbarch, prev_regnum)); | |
1515 | 1516 | } |
1516 | 1517 | return; |
1517 | 1518 | } |
@@ -1520,20 +1521,23 @@ saved_regs_unwinder (struct frame_info *frame, | ||
1520 | 1521 | value. If a value is needed, pass the request on down the chain; |
1521 | 1522 | otherwise just return an indication that the value is in the same |
1522 | 1523 | register as the next frame. */ |
1523 | - frame_register (frame, regnum, optimizedp, lvalp, addrp, | |
1524 | - realnump, bufferp); | |
1524 | + frame_register_unwind (next_frame, prev_regnum, optimizedp, lvalp, addrp, | |
1525 | + realnump, bufferp); | |
1525 | 1526 | } |
1526 | 1527 | |
1527 | 1528 | |
1528 | 1529 | static void |
1529 | -d10v_frame_register_unwind (struct frame_info *frame, | |
1530 | - void **cache, | |
1531 | - int regnum, int *optimizedp, | |
1530 | +d10v_frame_register_unwind (struct frame_info *next_frame, | |
1531 | + void **this_cache, | |
1532 | + int prev_regnum, int *optimizedp, | |
1532 | 1533 | enum lval_type *lvalp, CORE_ADDR *addrp, |
1533 | 1534 | int *realnump, void *bufferp) |
1534 | 1535 | { |
1535 | - struct d10v_unwind_cache *info = d10v_frame_unwind_cache (frame, cache); | |
1536 | - saved_regs_unwinder (frame, info->saved_regs, regnum, optimizedp, | |
1536 | + struct d10v_unwind_cache *info | |
1537 | + = 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, | |
1537 | 1541 | lvalp, addrp, realnump, bufferp); |
1538 | 1542 | } |
1539 | 1543 |
@@ -105,11 +105,12 @@ find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp) | ||
105 | 105 | } |
106 | 106 | |
107 | 107 | struct dummy_frame * |
108 | -cached_find_dummy_frame (struct frame_info *frame, void **cache) | |
108 | +cached_find_dummy_frame (struct frame_info *next_frame, void **this_cache) | |
109 | 109 | { |
110 | - if ((*cache) == NULL) | |
111 | - (*cache) = find_dummy_frame (get_frame_pc (frame), get_frame_base (frame)); | |
112 | - return (*cache); | |
110 | + if ((*this_cache) == NULL) | |
111 | + (*this_cache) = find_dummy_frame (frame_pc_unwind (next_frame), | |
112 | + frame_id_unwind (next_frame).base); | |
113 | + return (*this_cache); | |
113 | 114 | } |
114 | 115 | |
115 | 116 | struct regcache * |
@@ -286,13 +287,13 @@ discard_innermost_dummy (struct dummy_frame **stack) | ||
286 | 287 | dummy stack frame. */ |
287 | 288 | |
288 | 289 | static void |
289 | -dummy_frame_pop (struct frame_info *fi, void **cache, | |
290 | +dummy_frame_pop (struct frame_info *next_frame, void **this_cache, | |
290 | 291 | struct regcache *regcache) |
291 | 292 | { |
292 | - struct dummy_frame *dummy = cached_find_dummy_frame (fi, cache); | |
293 | + struct dummy_frame *dummy = cached_find_dummy_frame (next_frame, this_cache); | |
293 | 294 | |
294 | 295 | /* If it isn't, what are we even doing here? */ |
295 | - gdb_assert (get_frame_type (fi) == DUMMY_FRAME); | |
296 | + /* gdb_assert (get_frame_type (fi) == DUMMY_FRAME); */ | |
296 | 297 | |
297 | 298 | if (dummy == NULL) |
298 | 299 | error ("Can't pop dummy frame!"); |
@@ -344,12 +345,12 @@ generic_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs, | ||
344 | 345 | register value is taken from the local copy of the register buffer. */ |
345 | 346 | |
346 | 347 | static void |
347 | -dummy_frame_register_unwind (struct frame_info *frame, void **cache, | |
348 | - int regnum, int *optimized, | |
348 | +dummy_frame_register_unwind (struct frame_info *next_frame, void **this_cache, | |
349 | + int prev_regnum, int *optimized, | |
349 | 350 | enum lval_type *lvalp, CORE_ADDR *addrp, |
350 | 351 | int *realnum, void *bufferp) |
351 | 352 | { |
352 | - struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache); | |
353 | + struct dummy_frame *dummy = cached_find_dummy_frame (next_frame, this_cache); | |
353 | 354 | gdb_assert (dummy != NULL); |
354 | 355 | |
355 | 356 | /* Describe the register's location. Generic dummy frames always |
@@ -366,7 +367,7 @@ dummy_frame_register_unwind (struct frame_info *frame, void **cache, | ||
366 | 367 | /* Use the regcache_cooked_read() method so that it, on the fly, |
367 | 368 | constructs either a raw or pseudo register from the raw |
368 | 369 | register cache. */ |
369 | - regcache_cooked_read (dummy->regcache, regnum, bufferp); | |
370 | + regcache_cooked_read (dummy->regcache, prev_regnum, bufferp); | |
370 | 371 | } |
371 | 372 | } |
372 | 373 |
@@ -374,10 +375,10 @@ dummy_frame_register_unwind (struct frame_info *frame, void **cache, | ||
374 | 375 | previous frame. */ |
375 | 376 | |
376 | 377 | static CORE_ADDR |
377 | -dummy_frame_pc_unwind (struct frame_info *frame, | |
378 | - void **cache) | |
378 | +dummy_frame_pc_unwind (struct frame_info *next_frame, | |
379 | + void **this_cache) | |
379 | 380 | { |
380 | - struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache); | |
381 | + struct dummy_frame *dummy = cached_find_dummy_frame (next_frame, this_cache); | |
381 | 382 | /* Oops! In a dummy-frame but can't find the stack dummy. Pretend |
382 | 383 | that the frame doesn't unwind. Should this function instead |
383 | 384 | return a has-no-caller indication? */ |
@@ -391,18 +392,18 @@ dummy_frame_pc_unwind (struct frame_info *frame, | ||
391 | 392 | (the frame that the dummy has the saved state of). */ |
392 | 393 | |
393 | 394 | static void |
394 | -dummy_frame_id_unwind (struct frame_info *frame, | |
395 | - void **cache, | |
396 | - struct frame_id *id) | |
395 | +dummy_frame_id_unwind (struct frame_info *next_frame, | |
396 | + void **this_cache, | |
397 | + struct frame_id *this_id) | |
397 | 398 | { |
398 | - struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache); | |
399 | + struct dummy_frame *dummy = cached_find_dummy_frame (next_frame, this_cache); | |
399 | 400 | /* Oops! In a dummy-frame but can't find the stack dummy. Pretend |
400 | 401 | that the frame doesn't unwind. Should this function instead |
401 | 402 | return a has-no-caller indication? */ |
402 | 403 | if (dummy == NULL) |
403 | - (*id) = null_frame_id; | |
404 | + (*this_id) = null_frame_id; | |
404 | 405 | else |
405 | - (*id) = dummy->id; | |
406 | + (*this_id) = dummy->id; | |
406 | 407 | } |
407 | 408 | |
408 | 409 | static struct frame_unwind dummy_frame_unwind = |
@@ -47,54 +47,102 @@ extern const struct frame_unwind *frame_unwind_find_by_pc (struct gdbarch | ||
47 | 47 | *gdbarch, |
48 | 48 | CORE_ADDR pc); |
49 | 49 | |
50 | -/* Return the location (and possibly value) of REGNUM for the previous | |
51 | - (older, up) frame. All parameters except VALUEP can be assumed to | |
52 | - be non NULL. When VALUEP is NULL, just the location of the | |
53 | - register should be returned. | |
54 | - | |
55 | - UNWIND_CACHE is provided as mechanism for implementing a per-frame | |
56 | - local cache. It's initial value being NULL. Memory for that cache | |
57 | - should be allocated using frame_obstack_zalloc(). | |
58 | - | |
59 | - Register window architectures (eg SPARC) should note that REGNUM | |
60 | - identifies the register for the previous frame. For instance, a | |
61 | - request for the value of "o1" for the previous frame would be found | |
62 | - in the register "i1" in this FRAME. */ | |
63 | - | |
64 | -typedef void (frame_unwind_reg_ftype) (struct frame_info * frame, | |
65 | - void **unwind_cache, | |
66 | - int regnum, | |
50 | +/* The following unwind functions all assume a frame chain like: | |
51 | + (outer) prev <-> this <-> next (inner); Even though some unwind to | |
52 | + THIS frame (frame ID) and others unwind the PREV frame, they are | |
53 | + all, consistently passed NEXT frame and THIS cache. | |
54 | + | |
55 | + The intent is to clarify the relationship between NEXT frame and | |
56 | + THIS cache. It is, of course, at the expense of confusing somewhat | |
57 | + the expected unwind behavior of PC/REG unwind VS ID unwind. Sigh. */ | |
58 | + | |
59 | +/* Assuming the frame chain: (outer) prev <-> this <-> next (inner); | |
60 | + use the NEXT frame, and its register unwind method, to determine | |
61 | + the frame ID of THIS frame. | |
62 | + | |
63 | + A frame ID provides an invariant that can be used to re-identify an | |
64 | + instance of a frame. It is a combination of the frame's `base' and | |
65 | + the frame's function's code. | |
66 | + | |
67 | + Traditionally, THIS frame's ID was determined by examining THIS | |
68 | + frame's function's prologue and identifying which register/offset | |
69 | + are being used as THIS frame's base. | |
70 | + | |
71 | + THIS_CACHE can be used to share any prolog analysis data with the | |
72 | + other unwind methods. Memory for that cache should be allocated | |
73 | + using frame_obstack_zalloc(). */ | |
74 | + | |
75 | +typedef void (frame_unwind_id_ftype) (struct frame_info *next_frame, | |
76 | + void **this_cache, | |
77 | + struct frame_id *this_id); | |
78 | + | |
79 | +/* Assuming the frame chain: (outer) prev <-> this <-> next (inner); | |
80 | + use the NEXT frame, and its register unwind method, to unwind THIS | |
81 | + frame's registers, returning the value of REGNUM in PREV frame. | |
82 | + | |
83 | + Traditionally, THIS frame's registers were unwound by examining | |
84 | + THIS frame's function's prologue and identifying which registers | |
85 | + that prolog code saved on the stack. | |
86 | + | |
87 | + Ex: Assuming THIS is a frameless function that has saved the return | |
88 | + address (to PREV) in R1, then: a request to unwind THIS's PC | |
89 | + (returning the value of PC in PREV), becomes a request for the | |
90 | + value of R1 in THIS (that is where the value was saved), which | |
91 | + becomes a request to unwind R1 from NEXT. | |
92 | + | |
93 | + THIS_CACHE can be used to share any prologue analysis data with the | |
94 | + other unwind methods. Memory for that cache should be allocated | |
95 | + using frame_obstack_zalloc(). */ | |
96 | + | |
97 | +typedef void (frame_unwind_reg_ftype) (struct frame_info *next_frame, | |
98 | + void **this_cache, | |
99 | + int prev_regnum, | |
67 | 100 | int *optimized, |
68 | 101 | enum lval_type * lvalp, |
69 | 102 | CORE_ADDR *addrp, |
70 | 103 | int *realnump, void *valuep); |
71 | 104 | |
72 | -/* Same as for registers above, but return the address at which the | |
73 | - calling frame would resume. */ | |
105 | +/* Assuming the frame chain: (outer) prev <-> this <-> next (inner); | |
106 | + use the NEXT frame, and its register unwind method, to unwind THIS | |
107 | + frame's PC, returning the value of PC (the return address) in PREV | |
108 | + frame. | |
74 | 109 | |
75 | -typedef CORE_ADDR (frame_unwind_pc_ftype) (struct frame_info * frame, | |
76 | - void **unwind_cache); | |
110 | + Traditionally, THIS frame's PC was unwound by examining THIS | |
111 | + frame's function prolog and identifying where (in a register or on | |
112 | + the stack) that return address was saved. | |
77 | 113 | |
78 | -/* Same as for registers above, but return the ID of the frame that | |
79 | - called this one. */ | |
114 | + Please note that this per-frame method may be superseeded by an | |
115 | + architecture specific method that determines the unwound PC (aka | |
116 | + return address) using just the register unwind methods. | |
80 | 117 | |
81 | -typedef void (frame_unwind_id_ftype) (struct frame_info * frame, | |
82 | - void **unwind_cache, | |
83 | - struct frame_id * id); | |
118 | + THIS_CACHE can be used to share any prologue analysis data with the | |
119 | + other unwind methods. Memory for that cache should be allocated | |
120 | + using frame_obstack_zalloc(). */ | |
84 | 121 | |
85 | -/* Discard the frame by restoring the registers (in regcache) back to | |
86 | - that of the caller. */ | |
87 | -/* NOTE: cagney/2003-01-19: While at present the callers all pop each | |
122 | +typedef CORE_ADDR (frame_unwind_pc_ftype) (struct frame_info *next_frame, | |
123 | + void **this_cache); | |
124 | + | |
125 | +/* Assuming the frame chain: (outer) prev <-> this <-> next (inner); | |
126 | + use the NEXT frame, and its register unwind method, to unwind THIS | |
127 | + frame's entire stack, writing PREV's frames register values into | |
128 | + REGCACHE. | |
129 | + | |
130 | + NOTE: cagney/2003-01-19: While at present the callers all pop each | |
88 | 131 | frame in turn, the implementor should try to code things so that |
89 | - any frame can be popped directly. */ | |
90 | -/* FIXME: cagney/2003-01-19: Since both FRAME and REGCACHE refer to a | |
132 | + any frame can be popped directly. | |
133 | + | |
134 | + FIXME: cagney/2003-01-19: Since both FRAME and REGCACHE refer to a | |
91 | 135 | common register cache, care must be taken when restoring the |
92 | 136 | registers. The `correct fix' is to first first save the registers |
93 | 137 | in a scratch cache, and second write that scratch cache back to to |
94 | - the real register cache. */ | |
138 | + the real register cache. | |
139 | + | |
140 | + FIXME: cagney/2003-03-04: Isn't this entire function redundant? | |
141 | + Shouldn't the code instead just iterate through the restore | |
142 | + reggroup unwinding those registers? */ | |
95 | 143 | |
96 | -typedef void (frame_unwind_pop_ftype) (struct frame_info *frame, | |
97 | - void **unwind_cache, | |
144 | +typedef void (frame_unwind_pop_ftype) (struct frame_info *next_frame, | |
145 | + void **this_cache, | |
98 | 146 | struct regcache *regcache); |
99 | 147 | |
100 | 148 | struct frame_unwind |
@@ -135,14 +135,27 @@ frame_find_by_id (struct frame_id id) | ||
135 | 135 | } |
136 | 136 | |
137 | 137 | CORE_ADDR |
138 | -frame_pc_unwind (struct frame_info *frame) | |
138 | +frame_pc_unwind (struct frame_info *this_frame) | |
139 | 139 | { |
140 | - if (!frame->pc_unwind_cache_p) | |
140 | + if (!this_frame->pc_unwind_cache_p) | |
141 | 141 | { |
142 | - frame->pc_unwind_cache = frame->unwind->pc (frame, &frame->unwind_cache); | |
143 | - frame->pc_unwind_cache_p = 1; | |
142 | + this_frame->pc_unwind_cache | |
143 | + = this_frame->unwind->pc (this_frame->next, &this_frame->unwind_cache); | |
144 | + this_frame->pc_unwind_cache_p = 1; | |
144 | 145 | } |
145 | - return frame->pc_unwind_cache; | |
146 | + return this_frame->pc_unwind_cache; | |
147 | +} | |
148 | + | |
149 | +struct frame_id | |
150 | +frame_id_unwind (struct frame_info *this_frame) | |
151 | +{ | |
152 | + if (!this_frame->id_unwind_cache_p) | |
153 | + { | |
154 | + this_frame->unwind->id (this_frame->next, &this_frame->unwind_cache, | |
155 | + &this_frame->id_unwind_cache); | |
156 | + this_frame->id_unwind_cache_p = 1; | |
157 | + } | |
158 | + return this_frame->id_unwind_cache; | |
146 | 159 | } |
147 | 160 | |
148 | 161 | void |
@@ -154,12 +167,12 @@ frame_pop (struct frame_info *frame) | ||
154 | 167 | values are needed to restore other registers. Instead, this code |
155 | 168 | should pass in a scratch cache and, as a second step, restore the |
156 | 169 | registers using that. */ |
157 | - frame->unwind->pop (frame, &frame->unwind_cache, current_regcache); | |
170 | + frame->unwind->pop (frame->next, &frame->unwind_cache, current_regcache); | |
158 | 171 | flush_cached_frames (); |
159 | 172 | } |
160 | 173 | |
161 | 174 | void |
162 | -frame_register_unwind (struct frame_info *frame, int regnum, | |
175 | +frame_register_unwind (struct frame_info *this_frame, int prev_regnum, | |
163 | 176 | int *optimizedp, enum lval_type *lvalp, |
164 | 177 | CORE_ADDR *addrp, int *realnump, void *bufferp) |
165 | 178 | { |
@@ -177,11 +190,13 @@ frame_register_unwind (struct frame_info *frame, int regnum, | ||
177 | 190 | is broken. There is always a frame. If there, for some reason, |
178 | 191 | isn't, there is some pretty busted code as it should have |
179 | 192 | detected the problem before calling here. */ |
180 | - gdb_assert (frame != NULL); | |
193 | + gdb_assert (this_frame != NULL && this_frame->next != NULL); | |
181 | 194 | |
182 | - /* Ask this frame to unwind its register. */ | |
183 | - frame->unwind->reg (frame, &frame->unwind_cache, regnum, | |
184 | - optimizedp, lvalp, addrp, realnump, bufferp); | |
195 | + /* Ask this frame's register unwinder to return the value of | |
196 | + PREV_REGNUM using register values unwound from the NEXT frame. */ | |
197 | + this_frame->unwind->reg (this_frame->next, &this_frame->unwind_cache, | |
198 | + prev_regnum, optimizedp, lvalp, addrp, realnump, | |
199 | + bufferp); | |
185 | 200 | } |
186 | 201 | |
187 | 202 | void |
@@ -1336,8 +1351,8 @@ get_prev_frame (struct frame_info *next_frame) | ||
1336 | 1351 | { |
1337 | 1352 | /* FIXME: cagney/2002-12-18: Instead of this hack, should just |
1338 | 1353 | save the frame ID directly. */ |
1339 | - struct frame_id id = prev_frame->unwind->id (next_frame, | |
1340 | - &prev_frame->unwind_cache); | |
1354 | + struct frame_id id; | |
1355 | + prev_frame->unwind->id (next_frame, &prev_frame->unwind_cache, &id); | |
1341 | 1356 | /* Check that the unwound ID is valid. As of 2003-02-24 the |
1342 | 1357 | x86-64 was returning an invalid frame ID when trying to do an |
1343 | 1358 | unwind a sentinel frame that belonged to a frame dummy. */ |
@@ -310,6 +310,10 @@ extern const char *frame_map_regnum_to_name (int regnum); | ||
310 | 310 | |
311 | 311 | extern CORE_ADDR frame_pc_unwind (struct frame_info *frame); |
312 | 312 | |
313 | +/* Unwind the frame ID. Return an ID that uniquely identifies the | |
314 | + caller's frame. */ | |
315 | +extern struct frame_id frame_id_unwind (struct frame_info *frame); | |
316 | + | |
313 | 317 | /* Discard the specified frame. Restoring the registers to the state |
314 | 318 | of the caller. */ |
315 | 319 | extern void frame_pop (struct frame_info *frame); |
@@ -45,19 +45,25 @@ sentinel_frame_cache (struct regcache *regcache) | ||
45 | 45 | /* Here the register value is taken direct from the register cache. */ |
46 | 46 | |
47 | 47 | void |
48 | -sentinel_frame_register_unwind (struct frame_info *frame, | |
49 | - void **unwind_cache, | |
50 | - int regnum, int *optimized, | |
48 | +sentinel_frame_register_unwind (struct frame_info *next_frame, | |
49 | + void **this_cache, | |
50 | + int prev_regnum, int *optimized, | |
51 | 51 | enum lval_type *lvalp, CORE_ADDR *addrp, |
52 | 52 | int *realnum, void *bufferp) |
53 | 53 | { |
54 | - struct frame_unwind_cache *cache = *unwind_cache; | |
54 | + /* Hey don't let on but, for the sentinel frame, next_frame->next == | |
55 | + next_frame. Fortunatly, that local knowledge isn't needed, | |
56 | + instead THIS_CACHE contains all the information needed to find | |
57 | + the frame's thread's REGCACHE and that REGCACHE is then accessed | |
58 | + directly. */ | |
59 | + struct frame_unwind_cache *cache = *this_cache; | |
60 | + | |
55 | 61 | /* Describe the register's location. A reg-frame maps all registers |
56 | 62 | onto the corresponding hardware register. */ |
57 | 63 | *optimized = 0; |
58 | 64 | *lvalp = lval_register; |
59 | - *addrp = REGISTER_BYTE (regnum); | |
60 | - *realnum = regnum; | |
65 | + *addrp = REGISTER_BYTE (prev_regnum); | |
66 | + *realnum = prev_regnum; | |
61 | 67 | |
62 | 68 | /* If needed, find and return the value of the register. */ |
63 | 69 | if (bufferp != NULL) |
@@ -66,13 +72,13 @@ sentinel_frame_register_unwind (struct frame_info *frame, | ||
66 | 72 | /* Use the regcache_cooked_read() method so that it, on the fly, |
67 | 73 | constructs either a raw or pseudo register from the raw |
68 | 74 | register cache. */ |
69 | - regcache_cooked_read (cache->regcache, regnum, bufferp); | |
75 | + regcache_cooked_read (cache->regcache, prev_regnum, bufferp); | |
70 | 76 | } |
71 | 77 | } |
72 | 78 | |
73 | 79 | CORE_ADDR |
74 | -sentinel_frame_pc_unwind (struct frame_info *frame, | |
75 | - void **cache) | |
80 | +sentinel_frame_pc_unwind (struct frame_info *next_frame, | |
81 | + void **this_cache) | |
76 | 82 | { |
77 | 83 | /* FIXME: cagney/2003-01-08: This should be using a per-architecture |
78 | 84 | method that doesn't suffer from DECR_PC_AFTER_BREAK problems. |
@@ -82,21 +88,16 @@ sentinel_frame_pc_unwind (struct frame_info *frame, | ||
82 | 88 | } |
83 | 89 | |
84 | 90 | void |
85 | -sentinel_frame_id_unwind (struct frame_info *frame, | |
86 | - void **cache, | |
87 | - struct frame_id *id) | |
91 | +sentinel_frame_id_unwind (struct frame_info *next_frame, | |
92 | + void **this_cache, | |
93 | + struct frame_id *this_id) | |
88 | 94 | { |
89 | - /* FIXME: cagney/2003-01-08: This should be using a per-architecture | |
90 | - method that doesn't suffer from DECR_PC_AFTER_BREAK problems. | |
91 | - Such a method would take unwind_cache, regcache and stop reason | |
92 | - parameters. */ | |
93 | - id->base = read_fp (); | |
94 | - id->pc = read_pc (); | |
95 | + internal_error (__FILE__, __LINE__, "sentinel_frame_id_unwind called"); | |
95 | 96 | } |
96 | 97 | |
97 | 98 | static void |
98 | -sentinel_frame_pop (struct frame_info *frame, | |
99 | - void **cache, | |
99 | +sentinel_frame_pop (struct frame_info *next_frame, | |
100 | + void **this_cache, | |
100 | 101 | struct regcache *regcache) |
101 | 102 | { |
102 | 103 | internal_error (__FILE__, __LINE__, "Function sentinal_frame_pop called"); |