OLD | NEW |
1 /* Process record and replay target for GDB, the GNU debugger. | 1 /* Process record and replay target for GDB, the GNU debugger. |
2 | 2 |
3 Copyright (C) 2008-2012 Free Software Foundation, Inc. | 3 Copyright (C) 2008-2012 Free Software Foundation, Inc. |
4 | 4 |
5 This file is part of GDB. | 5 This file is part of GDB. |
6 | 6 |
7 This program is free software; you can redistribute it and/or modify | 7 This program is free software; you can redistribute it and/or modify |
8 it under the terms of the GNU General Public License as published by | 8 it under the terms of the GNU General Public License as published by |
9 the Free Software Foundation; either version 3 of the License, or | 9 the Free Software Foundation; either version 3 of the License, or |
10 (at your option) any later version. | 10 (at your option) any later version. |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 unsigned short len; | 93 unsigned short len; |
94 union | 94 union |
95 { | 95 { |
96 gdb_byte *ptr; | 96 gdb_byte *ptr; |
97 gdb_byte buf[2 * sizeof (gdb_byte *)]; | 97 gdb_byte buf[2 * sizeof (gdb_byte *)]; |
98 } u; | 98 } u; |
99 }; | 99 }; |
100 | 100 |
101 struct record_end_entry | 101 struct record_end_entry |
102 { | 102 { |
103 enum target_signal sigval; | 103 enum gdb_signal sigval; |
104 ULONGEST insn_num; | 104 ULONGEST insn_num; |
105 }; | 105 }; |
106 | 106 |
107 enum record_type | 107 enum record_type |
108 { | 108 { |
109 record_end = 0, | 109 record_end = 0, |
110 record_reg, | 110 record_reg, |
111 record_mem | 111 record_mem |
112 }; | 112 }; |
113 | 113 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 than count of insns presently in execution log). */ | 202 than count of insns presently in execution log). */ |
203 static ULONGEST record_insn_count; | 203 static ULONGEST record_insn_count; |
204 | 204 |
205 /* The target_ops of process record. */ | 205 /* The target_ops of process record. */ |
206 static struct target_ops record_ops; | 206 static struct target_ops record_ops; |
207 static struct target_ops record_core_ops; | 207 static struct target_ops record_core_ops; |
208 | 208 |
209 /* The beneath function pointers. */ | 209 /* The beneath function pointers. */ |
210 static struct target_ops *record_beneath_to_resume_ops; | 210 static struct target_ops *record_beneath_to_resume_ops; |
211 static void (*record_beneath_to_resume) (struct target_ops *, ptid_t, int, | 211 static void (*record_beneath_to_resume) (struct target_ops *, ptid_t, int, |
212 enum target_signal); | 212 enum gdb_signal); |
213 static struct target_ops *record_beneath_to_wait_ops; | 213 static struct target_ops *record_beneath_to_wait_ops; |
214 static ptid_t (*record_beneath_to_wait) (struct target_ops *, ptid_t, | 214 static ptid_t (*record_beneath_to_wait) (struct target_ops *, ptid_t, |
215 struct target_waitstatus *, | 215 struct target_waitstatus *, |
216 int); | 216 int); |
217 static struct target_ops *record_beneath_to_store_registers_ops; | 217 static struct target_ops *record_beneath_to_store_registers_ops; |
218 static void (*record_beneath_to_store_registers) (struct target_ops *, | 218 static void (*record_beneath_to_store_registers) (struct target_ops *, |
219 struct regcache *, | 219 struct regcache *, |
220 int regno); | 220 int regno); |
221 static struct target_ops *record_beneath_to_xfer_partial_ops; | 221 static struct target_ops *record_beneath_to_xfer_partial_ops; |
222 static LONGEST (*record_beneath_to_xfer_partial) (struct target_ops *ops, | 222 static LONGEST (*record_beneath_to_xfer_partial) (struct target_ops *ops, |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 int | 524 int |
525 record_arch_list_add_end (void) | 525 record_arch_list_add_end (void) |
526 { | 526 { |
527 struct record_entry *rec; | 527 struct record_entry *rec; |
528 | 528 |
529 if (record_debug > 1) | 529 if (record_debug > 1) |
530 fprintf_unfiltered (gdb_stdlog, | 530 fprintf_unfiltered (gdb_stdlog, |
531 "Process record: add end to arch list.\n"); | 531 "Process record: add end to arch list.\n"); |
532 | 532 |
533 rec = record_end_alloc (); | 533 rec = record_end_alloc (); |
534 rec->u.end.sigval = TARGET_SIGNAL_0; | 534 rec->u.end.sigval = GDB_SIGNAL_0; |
535 rec->u.end.insn_num = ++record_insn_count; | 535 rec->u.end.insn_num = ++record_insn_count; |
536 | 536 |
537 record_arch_list_add (rec); | 537 record_arch_list_add (rec); |
538 | 538 |
539 return 0; | 539 return 0; |
540 } | 540 } |
541 | 541 |
542 static void | 542 static void |
543 record_check_insn_num (int set_terminal) | 543 record_check_insn_num (int set_terminal) |
544 { | 544 { |
(...skipping 29 matching lines...) Expand all Loading... |
574 record_list_release (record_arch_list_tail); | 574 record_list_release (record_arch_list_tail); |
575 } | 575 } |
576 | 576 |
577 /* Before inferior step (when GDB record the running message, inferior | 577 /* Before inferior step (when GDB record the running message, inferior |
578 only can step), GDB will call this function to record the values to | 578 only can step), GDB will call this function to record the values to |
579 record_list. This function will call gdbarch_process_record to | 579 record_list. This function will call gdbarch_process_record to |
580 record the running message of inferior and set them to | 580 record the running message of inferior and set them to |
581 record_arch_list, and add it to record_list. */ | 581 record_arch_list, and add it to record_list. */ |
582 | 582 |
583 static int | 583 static int |
584 record_message (struct regcache *regcache, enum target_signal signal) | 584 record_message (struct regcache *regcache, enum gdb_signal signal) |
585 { | 585 { |
586 int ret; | 586 int ret; |
587 struct gdbarch *gdbarch = get_regcache_arch (regcache); | 587 struct gdbarch *gdbarch = get_regcache_arch (regcache); |
588 struct cleanup *old_cleanups = make_cleanup (record_arch_list_cleanups, 0); | 588 struct cleanup *old_cleanups = make_cleanup (record_arch_list_cleanups, 0); |
589 | 589 |
590 record_arch_list_head = NULL; | 590 record_arch_list_head = NULL; |
591 record_arch_list_tail = NULL; | 591 record_arch_list_tail = NULL; |
592 | 592 |
593 /* Check record_insn_num. */ | 593 /* Check record_insn_num. */ |
594 record_check_insn_num (1); | 594 record_check_insn_num (1); |
(...skipping 19 matching lines...) Expand all Loading... |
614 | 614 |
615 But we should still deliver the signal to gdb during the replay, | 615 But we should still deliver the signal to gdb during the replay, |
616 if we delivered it during the recording. Therefore we should | 616 if we delivered it during the recording. Therefore we should |
617 record the signal during record_wait, not record_resume. */ | 617 record the signal during record_wait, not record_resume. */ |
618 if (record_list != &record_first) /* FIXME better way to check */ | 618 if (record_list != &record_first) /* FIXME better way to check */ |
619 { | 619 { |
620 gdb_assert (record_list->type == record_end); | 620 gdb_assert (record_list->type == record_end); |
621 record_list->u.end.sigval = signal; | 621 record_list->u.end.sigval = signal; |
622 } | 622 } |
623 | 623 |
624 if (signal == TARGET_SIGNAL_0 | 624 if (signal == GDB_SIGNAL_0 |
625 || !gdbarch_process_record_signal_p (gdbarch)) | 625 || !gdbarch_process_record_signal_p (gdbarch)) |
626 ret = gdbarch_process_record (gdbarch, | 626 ret = gdbarch_process_record (gdbarch, |
627 regcache, | 627 regcache, |
628 regcache_read_pc (regcache)); | 628 regcache_read_pc (regcache)); |
629 else | 629 else |
630 ret = gdbarch_process_record_signal (gdbarch, | 630 ret = gdbarch_process_record_signal (gdbarch, |
631 regcache, | 631 regcache, |
632 signal); | 632 signal); |
633 | 633 |
634 if (ret > 0) | 634 if (ret > 0) |
(...skipping 10 matching lines...) Expand all Loading... |
645 if (record_insn_num == record_insn_max_num && record_insn_max_num) | 645 if (record_insn_num == record_insn_max_num && record_insn_max_num) |
646 record_list_release_first (); | 646 record_list_release_first (); |
647 else | 647 else |
648 record_insn_num++; | 648 record_insn_num++; |
649 | 649 |
650 return 1; | 650 return 1; |
651 } | 651 } |
652 | 652 |
653 struct record_message_args { | 653 struct record_message_args { |
654 struct regcache *regcache; | 654 struct regcache *regcache; |
655 enum target_signal signal; | 655 enum gdb_signal signal; |
656 }; | 656 }; |
657 | 657 |
658 static int | 658 static int |
659 record_message_wrapper (void *args) | 659 record_message_wrapper (void *args) |
660 { | 660 { |
661 struct record_message_args *record_args = args; | 661 struct record_message_args *record_args = args; |
662 | 662 |
663 return record_message (record_args->regcache, record_args->signal); | 663 return record_message (record_args->regcache, record_args->signal); |
664 } | 664 } |
665 | 665 |
666 static int | 666 static int |
667 record_message_wrapper_safe (struct regcache *regcache, | 667 record_message_wrapper_safe (struct regcache *regcache, |
668 enum target_signal signal) | 668 enum gdb_signal signal) |
669 { | 669 { |
670 struct record_message_args args; | 670 struct record_message_args args; |
671 | 671 |
672 args.regcache = regcache; | 672 args.regcache = regcache; |
673 args.signal = signal; | 673 args.signal = signal; |
674 | 674 |
675 return catch_errors (record_message_wrapper, &args, NULL, RETURN_MASK_ALL); | 675 return catch_errors (record_message_wrapper, &args, NULL, RETURN_MASK_ALL); |
676 } | 676 } |
677 | 677 |
678 /* Set to 1 if record_store_registers and record_xfer_partial | 678 /* Set to 1 if record_store_registers and record_xfer_partial |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 } | 779 } |
780 } | 780 } |
781 } | 781 } |
782 } | 782 } |
783 break; | 783 break; |
784 } | 784 } |
785 } | 785 } |
786 | 786 |
787 static struct target_ops *tmp_to_resume_ops; | 787 static struct target_ops *tmp_to_resume_ops; |
788 static void (*tmp_to_resume) (struct target_ops *, ptid_t, int, | 788 static void (*tmp_to_resume) (struct target_ops *, ptid_t, int, |
789 » » » enum target_signal); | 789 » » » enum gdb_signal); |
790 static struct target_ops *tmp_to_wait_ops; | 790 static struct target_ops *tmp_to_wait_ops; |
791 static ptid_t (*tmp_to_wait) (struct target_ops *, ptid_t, | 791 static ptid_t (*tmp_to_wait) (struct target_ops *, ptid_t, |
792 struct target_waitstatus *, | 792 struct target_waitstatus *, |
793 int); | 793 int); |
794 static struct target_ops *tmp_to_store_registers_ops; | 794 static struct target_ops *tmp_to_store_registers_ops; |
795 static void (*tmp_to_store_registers) (struct target_ops *, | 795 static void (*tmp_to_store_registers) (struct target_ops *, |
796 struct regcache *, | 796 struct regcache *, |
797 int regno); | 797 int regno); |
798 static struct target_ops *tmp_to_xfer_partial_ops; | 798 static struct target_ops *tmp_to_xfer_partial_ops; |
799 static LONGEST (*tmp_to_xfer_partial) (struct target_ops *ops, | 799 static LONGEST (*tmp_to_xfer_partial) (struct target_ops *ops, |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
889 if (!tmp_to_stopped_by_watchpoint) | 889 if (!tmp_to_stopped_by_watchpoint) |
890 error (_("Could not find 'to_stopped_by_watchpoint' " | 890 error (_("Could not find 'to_stopped_by_watchpoint' " |
891 "method on the target stack.")); | 891 "method on the target stack.")); |
892 if (!tmp_to_stopped_data_address) | 892 if (!tmp_to_stopped_data_address) |
893 error (_("Could not find 'to_stopped_data_address' " | 893 error (_("Could not find 'to_stopped_data_address' " |
894 "method on the target stack.")); | 894 "method on the target stack.")); |
895 | 895 |
896 push_target (&record_ops); | 896 push_target (&record_ops); |
897 } | 897 } |
898 | 898 |
| 899 static void record_init_record_breakpoints (void); |
| 900 |
899 /* "to_open" target method. Open the process record target. */ | 901 /* "to_open" target method. Open the process record target. */ |
900 | 902 |
901 static void | 903 static void |
902 record_open (char *name, int from_tty) | 904 record_open (char *name, int from_tty) |
903 { | 905 { |
904 struct target_ops *t; | 906 struct target_ops *t; |
905 | 907 |
906 if (record_debug) | 908 if (record_debug) |
907 fprintf_unfiltered (gdb_stdlog, "Process record: record_open\n"); | 909 fprintf_unfiltered (gdb_stdlog, "Process record: record_open\n"); |
908 | 910 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 | 988 |
987 if (core_bfd) | 989 if (core_bfd) |
988 record_core_open_1 (name, from_tty); | 990 record_core_open_1 (name, from_tty); |
989 else | 991 else |
990 record_open_1 (name, from_tty); | 992 record_open_1 (name, from_tty); |
991 | 993 |
992 /* Register extra event sources in the event loop. */ | 994 /* Register extra event sources in the event loop. */ |
993 record_async_inferior_event_token | 995 record_async_inferior_event_token |
994 = create_async_event_handler (record_async_inferior_event_handler, | 996 = create_async_event_handler (record_async_inferior_event_handler, |
995 NULL); | 997 NULL); |
| 998 |
| 999 record_init_record_breakpoints (); |
996 } | 1000 } |
997 | 1001 |
998 /* "to_close" target method. Close the process record target. */ | 1002 /* "to_close" target method. Close the process record target. */ |
999 | 1003 |
1000 static void | 1004 static void |
1001 record_close (int quitting) | 1005 record_close (int quitting) |
1002 { | 1006 { |
1003 struct record_core_buf_entry *entry; | 1007 struct record_core_buf_entry *entry; |
1004 | 1008 |
1005 if (record_debug) | 1009 if (record_debug) |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1049 the global execution direction accordingly (to reverse) | 1053 the global execution direction accordingly (to reverse) |
1050 7. infrun polls an event out of the record target, and handles it | 1054 7. infrun polls an event out of the record target, and handles it |
1051 8. GDB goes back to the event loop, and goto #4. | 1055 8. GDB goes back to the event loop, and goto #4. |
1052 */ | 1056 */ |
1053 static enum exec_direction_kind record_execution_dir = EXEC_FORWARD; | 1057 static enum exec_direction_kind record_execution_dir = EXEC_FORWARD; |
1054 | 1058 |
1055 /* "to_resume" target method. Resume the process record target. */ | 1059 /* "to_resume" target method. Resume the process record target. */ |
1056 | 1060 |
1057 static void | 1061 static void |
1058 record_resume (struct target_ops *ops, ptid_t ptid, int step, | 1062 record_resume (struct target_ops *ops, ptid_t ptid, int step, |
1059 enum target_signal signal) | 1063 enum gdb_signal signal) |
1060 { | 1064 { |
1061 record_resume_step = step; | 1065 record_resume_step = step; |
1062 record_resumed = 1; | 1066 record_resumed = 1; |
1063 record_execution_dir = execution_direction; | 1067 record_execution_dir = execution_direction; |
1064 | 1068 |
1065 if (!RECORD_IS_REPLAY) | 1069 if (!RECORD_IS_REPLAY) |
1066 { | 1070 { |
1067 struct gdbarch *gdbarch = target_thread_architecture (ptid); | 1071 struct gdbarch *gdbarch = target_thread_architecture (ptid); |
1068 | 1072 |
1069 record_message (get_current_regcache (), signal); | 1073 record_message (get_current_regcache (), signal); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1212 } | 1216 } |
1213 | 1217 |
1214 if (single_step_breakpoints_inserted ()) | 1218 if (single_step_breakpoints_inserted ()) |
1215 remove_single_step_breakpoints (); | 1219 remove_single_step_breakpoints (); |
1216 | 1220 |
1217 if (record_resume_step) | 1221 if (record_resume_step) |
1218 return ret; | 1222 return ret; |
1219 | 1223 |
1220 /* Is this a SIGTRAP? */ | 1224 /* Is this a SIGTRAP? */ |
1221 if (status->kind == TARGET_WAITKIND_STOPPED | 1225 if (status->kind == TARGET_WAITKIND_STOPPED |
1222 » » && status->value.sig == TARGET_SIGNAL_TRAP) | 1226 » » && status->value.sig == GDB_SIGNAL_TRAP) |
1223 { | 1227 { |
1224 struct regcache *regcache; | 1228 struct regcache *regcache; |
1225 struct address_space *aspace; | 1229 struct address_space *aspace; |
1226 | 1230 |
1227 /* Yes -- this is likely our single-step finishing, | 1231 /* Yes -- this is likely our single-step finishing, |
1228 but check if there's any reason the core would be | 1232 but check if there's any reason the core would be |
1229 interested in the event. */ | 1233 interested in the event. */ |
1230 | 1234 |
1231 registers_changed (); | 1235 registers_changed (); |
1232 regcache = get_current_regcache (); | 1236 regcache = get_current_regcache (); |
(...skipping 21 matching lines...) Expand all Loading... |
1254 } | 1258 } |
1255 else | 1259 else |
1256 { | 1260 { |
1257 /* This is a single-step trap. Record the | 1261 /* This is a single-step trap. Record the |
1258 insn and issue another step. | 1262 insn and issue another step. |
1259 FIXME: this part can be a random SIGTRAP too. | 1263 FIXME: this part can be a random SIGTRAP too. |
1260 But GDB cannot handle it. */ | 1264 But GDB cannot handle it. */ |
1261 int step = 1; | 1265 int step = 1; |
1262 | 1266 |
1263 if (!record_message_wrapper_safe (regcache, | 1267 if (!record_message_wrapper_safe (regcache, |
1264 TARGET_SIGNAL_0)) | 1268 GDB_SIGNAL_0)) |
1265 { | 1269 { |
1266 status->kind = TARGET_WAITKIND_STOPPED; | 1270 status->kind = TARGET_WAITKIND_STOPPED; |
1267 status->value.sig = TARGET_SIGNAL_0; | 1271 status->value.sig = GDB_SIGNAL_0; |
1268 break; | 1272 break; |
1269 } | 1273 } |
1270 | 1274 |
1271 if (gdbarch_software_single_step_p (gdbarch)) | 1275 if (gdbarch_software_single_step_p (gdbarch)) |
1272 { | 1276 { |
1273 /* Try to insert the software single step breakpoint. | 1277 /* Try to insert the software single step breakpoint. |
1274 If insert success, set step to 0. */ | 1278 If insert success, set step to 0. */ |
1275 set_executing (inferior_ptid, 0); | 1279 set_executing (inferior_ptid, 0); |
1276 reinit_frame_cache (); | 1280 reinit_frame_cache (); |
1277 if (gdbarch_software_single_step (gdbarch, | 1281 if (gdbarch_software_single_step (gdbarch, |
1278 get_current_frame ()
)) | 1282 get_current_frame ()
)) |
1279 step = 0; | 1283 step = 0; |
1280 set_executing (inferior_ptid, 1); | 1284 set_executing (inferior_ptid, 1); |
1281 } | 1285 } |
1282 | 1286 |
1283 if (record_debug) | 1287 if (record_debug) |
1284 fprintf_unfiltered (gdb_stdlog, | 1288 fprintf_unfiltered (gdb_stdlog, |
1285 "Process record: record_wait " | 1289 "Process record: record_wait " |
1286 "issuing one more step in the target
beneath\n"); | 1290 "issuing one more step in the target
beneath\n"); |
1287 record_beneath_to_resume (record_beneath_to_resume_ops, | 1291 record_beneath_to_resume (record_beneath_to_resume_ops, |
1288 ptid, step, | 1292 ptid, step, |
1289 » » » » » » TARGET_SIGNAL_0); | 1293 » » » » » » GDB_SIGNAL_0); |
1290 continue; | 1294 continue; |
1291 } | 1295 } |
1292 } | 1296 } |
1293 | 1297 |
1294 /* The inferior is broken by a breakpoint or a signal. */ | 1298 /* The inferior is broken by a breakpoint or a signal. */ |
1295 break; | 1299 break; |
1296 } | 1300 } |
1297 | 1301 |
1298 return ret; | 1302 return ret; |
1299 } | 1303 } |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1418 | 1422 |
1419 if (record_hw_watchpoint) | 1423 if (record_hw_watchpoint) |
1420 { | 1424 { |
1421 if (record_debug) | 1425 if (record_debug) |
1422 fprintf_unfiltered (gdb_stdlog, | 1426 fprintf_unfiltered (gdb_stdlog, |
1423 "Process record: hit hw " | 1427 "Process record: hit hw " |
1424 "watchpoint.\n"); | 1428 "watchpoint.\n"); |
1425 continue_flag = 0; | 1429 continue_flag = 0; |
1426 } | 1430 } |
1427 /* Check target signal */ | 1431 /* Check target signal */ |
1428 » » if (record_list->u.end.sigval != TARGET_SIGNAL_0) | 1432 » » if (record_list->u.end.sigval != GDB_SIGNAL_0) |
1429 /* FIXME: better way to check */ | 1433 /* FIXME: better way to check */ |
1430 continue_flag = 0; | 1434 continue_flag = 0; |
1431 } | 1435 } |
1432 } | 1436 } |
1433 | 1437 |
1434 if (continue_flag) | 1438 if (continue_flag) |
1435 { | 1439 { |
1436 if (execution_direction == EXEC_REVERSE) | 1440 if (execution_direction == EXEC_REVERSE) |
1437 { | 1441 { |
1438 if (record_list->prev) | 1442 if (record_list->prev) |
1439 record_list = record_list->prev; | 1443 record_list = record_list->prev; |
1440 } | 1444 } |
1441 else | 1445 else |
1442 { | 1446 { |
1443 if (record_list->next) | 1447 if (record_list->next) |
1444 record_list = record_list->next; | 1448 record_list = record_list->next; |
1445 } | 1449 } |
1446 } | 1450 } |
1447 } | 1451 } |
1448 while (continue_flag); | 1452 while (continue_flag); |
1449 | 1453 |
1450 replay_out: | 1454 replay_out: |
1451 if (record_get_sig) | 1455 if (record_get_sig) |
1452 » status->value.sig = TARGET_SIGNAL_INT; | 1456 » status->value.sig = GDB_SIGNAL_INT; |
1453 else if (record_list->u.end.sigval != TARGET_SIGNAL_0) | 1457 else if (record_list->u.end.sigval != GDB_SIGNAL_0) |
1454 /* FIXME: better way to check */ | 1458 /* FIXME: better way to check */ |
1455 status->value.sig = record_list->u.end.sigval; | 1459 status->value.sig = record_list->u.end.sigval; |
1456 else | 1460 else |
1457 » status->value.sig = TARGET_SIGNAL_TRAP; | 1461 » status->value.sig = GDB_SIGNAL_TRAP; |
1458 | 1462 |
1459 discard_cleanups (old_cleanups); | 1463 discard_cleanups (old_cleanups); |
1460 } | 1464 } |
1461 | 1465 |
1462 signal (SIGINT, handle_sigint); | 1466 signal (SIGINT, handle_sigint); |
1463 | 1467 |
1464 do_cleanups (set_cleanups); | 1468 do_cleanups (set_cleanups); |
1465 return inferior_ptid; | 1469 return inferior_ptid; |
1466 } | 1470 } |
1467 | 1471 |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1711 record_list_release_first (); | 1715 record_list_release_first (); |
1712 else | 1716 else |
1713 record_insn_num++; | 1717 record_insn_num++; |
1714 } | 1718 } |
1715 | 1719 |
1716 return record_beneath_to_xfer_partial (record_beneath_to_xfer_partial_ops, | 1720 return record_beneath_to_xfer_partial (record_beneath_to_xfer_partial_ops, |
1717 object, annex, readbuf, writebuf, | 1721 object, annex, readbuf, writebuf, |
1718 offset, len); | 1722 offset, len); |
1719 } | 1723 } |
1720 | 1724 |
1721 /* Behavior is conditional on RECORD_IS_REPLAY. | 1725 /* This structure represents a breakpoint inserted while the record |
1722 We will not actually insert or remove breakpoints when replaying, | 1726 target is active. We use this to know when to install/remove |
1723 nor when recording. */ | 1727 breakpoints in/from the target beneath. For example, a breakpoint |
| 1728 may be inserted while recording, but removed when not replaying nor |
| 1729 recording. In that case, the breakpoint had not been inserted on |
| 1730 the target beneath, so we should not try to remove it there. */ |
| 1731 |
| 1732 struct record_breakpoint |
| 1733 { |
| 1734 /* The address and address space the breakpoint was set at. */ |
| 1735 struct address_space *address_space; |
| 1736 CORE_ADDR addr; |
| 1737 |
| 1738 /* True when the breakpoint has been also installed in the target |
| 1739 beneath. This will be false for breakpoints set during replay or |
| 1740 when recording. */ |
| 1741 int in_target_beneath; |
| 1742 }; |
| 1743 |
| 1744 typedef struct record_breakpoint *record_breakpoint_p; |
| 1745 DEF_VEC_P(record_breakpoint_p); |
| 1746 |
| 1747 /* The list of breakpoints inserted while the record target is |
| 1748 active. */ |
| 1749 VEC(record_breakpoint_p) *record_breakpoints = NULL; |
| 1750 |
| 1751 static void |
| 1752 record_sync_record_breakpoints (struct bp_location *loc, void *data) |
| 1753 { |
| 1754 if (loc->loc_type != bp_loc_software_breakpoint) |
| 1755 return; |
| 1756 |
| 1757 if (loc->inserted) |
| 1758 { |
| 1759 struct record_breakpoint *bp = XNEW (struct record_breakpoint); |
| 1760 |
| 1761 bp->addr = loc->target_info.placed_address; |
| 1762 bp->address_space = loc->target_info.placed_address_space; |
| 1763 |
| 1764 bp->in_target_beneath = 1; |
| 1765 |
| 1766 VEC_safe_push (record_breakpoint_p, record_breakpoints, bp); |
| 1767 } |
| 1768 } |
| 1769 |
| 1770 /* Sync existing breakpoints to record_breakpoints. */ |
| 1771 |
| 1772 static void |
| 1773 record_init_record_breakpoints (void) |
| 1774 { |
| 1775 VEC_free (record_breakpoint_p, record_breakpoints); |
| 1776 |
| 1777 iterate_over_bp_locations (record_sync_record_breakpoints); |
| 1778 } |
| 1779 |
| 1780 /* Behavior is conditional on RECORD_IS_REPLAY. We will not actually |
| 1781 insert or remove breakpoints in the real target when replaying, nor |
| 1782 when recording. */ |
1724 | 1783 |
1725 static int | 1784 static int |
1726 record_insert_breakpoint (struct gdbarch *gdbarch, | 1785 record_insert_breakpoint (struct gdbarch *gdbarch, |
1727 struct bp_target_info *bp_tgt) | 1786 struct bp_target_info *bp_tgt) |
1728 { | 1787 { |
| 1788 struct record_breakpoint *bp; |
| 1789 int in_target_beneath = 0; |
| 1790 |
1729 if (!RECORD_IS_REPLAY) | 1791 if (!RECORD_IS_REPLAY) |
1730 { | 1792 { |
1731 struct cleanup *old_cleanups = record_gdb_operation_disable_set (); | 1793 /* When recording, we currently always single-step, so we don't |
1732 int ret = record_beneath_to_insert_breakpoint (gdbarch, bp_tgt); | 1794 » really need to install regular breakpoints in the inferior. |
| 1795 » However, we do have to insert software single-step |
| 1796 » breakpoints, in case the target can't hardware step. To keep |
| 1797 » things single, we always insert. */ |
| 1798 struct cleanup *old_cleanups; |
| 1799 int ret; |
1733 | 1800 |
| 1801 old_cleanups = record_gdb_operation_disable_set (); |
| 1802 ret = record_beneath_to_insert_breakpoint (gdbarch, bp_tgt); |
1734 do_cleanups (old_cleanups); | 1803 do_cleanups (old_cleanups); |
1735 | 1804 |
1736 return ret; | 1805 if (ret != 0) |
| 1806 » return ret; |
| 1807 |
| 1808 in_target_beneath = 1; |
1737 } | 1809 } |
1738 | 1810 |
| 1811 bp = XNEW (struct record_breakpoint); |
| 1812 bp->addr = bp_tgt->placed_address; |
| 1813 bp->address_space = bp_tgt->placed_address_space; |
| 1814 bp->in_target_beneath = in_target_beneath; |
| 1815 VEC_safe_push (record_breakpoint_p, record_breakpoints, bp); |
1739 return 0; | 1816 return 0; |
1740 } | 1817 } |
1741 | 1818 |
1742 /* "to_remove_breakpoint" method for process record target. */ | 1819 /* "to_remove_breakpoint" method for process record target. */ |
1743 | 1820 |
1744 static int | 1821 static int |
1745 record_remove_breakpoint (struct gdbarch *gdbarch, | 1822 record_remove_breakpoint (struct gdbarch *gdbarch, |
1746 struct bp_target_info *bp_tgt) | 1823 struct bp_target_info *bp_tgt) |
1747 { | 1824 { |
1748 if (!RECORD_IS_REPLAY) | 1825 struct record_breakpoint *bp; |
| 1826 int ix; |
| 1827 |
| 1828 for (ix = 0; |
| 1829 VEC_iterate (record_breakpoint_p, record_breakpoints, ix, bp); |
| 1830 ++ix) |
1749 { | 1831 { |
1750 struct cleanup *old_cleanups = record_gdb_operation_disable_set (); | 1832 if (bp->addr == bp_tgt->placed_address |
1751 int ret = record_beneath_to_remove_breakpoint (gdbarch, bp_tgt); | 1833 » && bp->address_space == bp_tgt->placed_address_space) |
| 1834 » { |
| 1835 » if (bp->in_target_beneath) |
| 1836 » { |
| 1837 » struct cleanup *old_cleanups; |
| 1838 » int ret; |
1752 | 1839 |
1753 do_cleanups (old_cleanups); | 1840 » old_cleanups = record_gdb_operation_disable_set (); |
| 1841 » ret = record_beneath_to_remove_breakpoint (gdbarch, bp_tgt); |
| 1842 » do_cleanups (old_cleanups); |
1754 | 1843 |
1755 return ret; | 1844 » if (ret != 0) |
| 1845 » » return ret; |
| 1846 » } |
| 1847 |
| 1848 » VEC_unordered_remove (record_breakpoint_p, record_breakpoints, ix); |
| 1849 » return 0; |
| 1850 » } |
1756 } | 1851 } |
1757 | 1852 |
1758 return 0; | 1853 gdb_assert_not_reached ("removing unknown breakpoint"); |
1759 } | 1854 } |
1760 | 1855 |
1761 /* "to_can_execute_reverse" method for process record target. */ | 1856 /* "to_can_execute_reverse" method for process record target. */ |
1762 | 1857 |
1763 static int | 1858 static int |
1764 record_can_execute_reverse (void) | 1859 record_can_execute_reverse (void) |
1765 { | 1860 { |
1766 return 1; | 1861 return 1; |
1767 } | 1862 } |
1768 | 1863 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1879 record_ops.to_can_async_p = record_can_async_p; | 1974 record_ops.to_can_async_p = record_can_async_p; |
1880 record_ops.to_is_async_p = record_is_async_p; | 1975 record_ops.to_is_async_p = record_is_async_p; |
1881 record_ops.to_execution_direction = record_execution_direction; | 1976 record_ops.to_execution_direction = record_execution_direction; |
1882 record_ops.to_magic = OPS_MAGIC; | 1977 record_ops.to_magic = OPS_MAGIC; |
1883 } | 1978 } |
1884 | 1979 |
1885 /* "to_resume" method for prec over corefile. */ | 1980 /* "to_resume" method for prec over corefile. */ |
1886 | 1981 |
1887 static void | 1982 static void |
1888 record_core_resume (struct target_ops *ops, ptid_t ptid, int step, | 1983 record_core_resume (struct target_ops *ops, ptid_t ptid, int step, |
1889 enum target_signal signal) | 1984 enum gdb_signal signal) |
1890 { | 1985 { |
1891 record_resume_step = step; | 1986 record_resume_step = step; |
1892 record_resumed = 1; | 1987 record_resumed = 1; |
1893 record_execution_dir = execution_direction; | 1988 record_execution_dir = execution_direction; |
1894 | 1989 |
1895 /* We are about to start executing the inferior (or simulate it), | 1990 /* We are about to start executing the inferior (or simulate it), |
1896 let's register it with the event loop. */ | 1991 let's register it with the event loop. */ |
1897 if (target_can_async_p ()) | 1992 if (target_can_async_p ()) |
1898 { | 1993 { |
1899 target_async (inferior_event_handler, 0); | 1994 target_async (inferior_event_handler, 0); |
(...skipping 955 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2855 { | 2950 { |
2856 printf_filtered (_("Go backward to insn number %s\n"), | 2951 printf_filtered (_("Go backward to insn number %s\n"), |
2857 pulongest (target_insn)); | 2952 pulongest (target_insn)); |
2858 record_goto_insn (p, EXEC_REVERSE); | 2953 record_goto_insn (p, EXEC_REVERSE); |
2859 } | 2954 } |
2860 registers_changed (); | 2955 registers_changed (); |
2861 reinit_frame_cache (); | 2956 reinit_frame_cache (); |
2862 print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); | 2957 print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); |
2863 } | 2958 } |
2864 | 2959 |
| 2960 /* Provide a prototype to silence -Wmissing-prototypes. */ |
| 2961 extern initialize_file_ftype _initialize_record; |
| 2962 |
2865 void | 2963 void |
2866 _initialize_record (void) | 2964 _initialize_record (void) |
2867 { | 2965 { |
2868 struct cmd_list_element *c; | 2966 struct cmd_list_element *c; |
2869 | 2967 |
2870 /* Init record_first. */ | 2968 /* Init record_first. */ |
2871 record_first.prev = NULL; | 2969 record_first.prev = NULL; |
2872 record_first.next = NULL; | 2970 record_first.next = NULL; |
2873 record_first.type = record_end; | 2971 record_first.type = record_end; |
2874 | 2972 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2958 Set whether query if PREC cannot record memory change of next instruction."), | 3056 Set whether query if PREC cannot record memory change of next instruction."), |
2959 _("\ | 3057 _("\ |
2960 Show whether query if PREC cannot record memory change of next instruction."), | 3058 Show whether query if PREC cannot record memory change of next instruction."), |
2961 _("\ | 3059 _("\ |
2962 Default is OFF.\n\ | 3060 Default is OFF.\n\ |
2963 When ON, query if PREC cannot record memory change of next instruction."), | 3061 When ON, query if PREC cannot record memory change of next instruction."), |
2964 NULL, NULL, | 3062 NULL, NULL, |
2965 &set_record_cmdlist, &show_record_cmdlist); | 3063 &set_record_cmdlist, &show_record_cmdlist); |
2966 | 3064 |
2967 } | 3065 } |
OLD | NEW |