| OLD | NEW |
| 1 /* GNU/Linux/ARM specific low level interface, for the remote server for GDB. | 1 /* GNU/Linux/ARM specific low level interface, for the remote server for GDB. |
| 2 Copyright (C) 1995-1996, 1998-2012 Free Software Foundation, Inc. | 2 Copyright (C) 1995-1996, 1998-2012 Free Software Foundation, Inc. |
| 3 | 3 |
| 4 This file is part of GDB. | 4 This file is part of GDB. |
| 5 | 5 |
| 6 This program is free software; you can redistribute it and/or modify | 6 This program is free software; you can redistribute it and/or modify |
| 7 it under the terms of the GNU General Public License as published by | 7 it under the terms of the GNU General Public License as published by |
| 8 the Free Software Foundation; either version 3 of the License, or | 8 the Free Software Foundation; either version 3 of the License, or |
| 9 (at your option) any later version. | 9 (at your option) any later version. |
| 10 | 10 |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 /* Are two break-/watch-points equal? */ | 425 /* Are two break-/watch-points equal? */ |
| 426 static int | 426 static int |
| 427 arm_linux_hw_breakpoint_equal (const struct arm_linux_hw_breakpoint *p1, | 427 arm_linux_hw_breakpoint_equal (const struct arm_linux_hw_breakpoint *p1, |
| 428 const struct arm_linux_hw_breakpoint *p2) | 428 const struct arm_linux_hw_breakpoint *p2) |
| 429 { | 429 { |
| 430 return p1->address == p2->address && p1->control == p2->control; | 430 return p1->address == p2->address && p1->control == p2->control; |
| 431 } | 431 } |
| 432 | 432 |
| 433 /* Initialize the hardware breakpoint structure P for a breakpoint or | 433 /* Initialize the hardware breakpoint structure P for a breakpoint or |
| 434 watchpoint at ADDR to LEN. The type of watchpoint is given in TYPE. | 434 watchpoint at ADDR to LEN. The type of watchpoint is given in TYPE. |
| 435 Returns -1 if TYPE is unsupported, 0 if TYPE represents a breakpoint, | 435 Returns -1 if TYPE is unsupported, or -2 if the particular combination |
| 436 and 1 if type represents a watchpoint. */ | 436 of ADDR and LEN cannot be implemented. Otherwise, returns 0 if TYPE |
| 437 represents a breakpoint and 1 if type represents a watchpoint. */ |
| 437 static int | 438 static int |
| 438 arm_linux_hw_point_initialize (char type, CORE_ADDR addr, int len, | 439 arm_linux_hw_point_initialize (char type, CORE_ADDR addr, int len, |
| 439 struct arm_linux_hw_breakpoint *p) | 440 struct arm_linux_hw_breakpoint *p) |
| 440 { | 441 { |
| 441 arm_hwbp_type hwbp_type; | 442 arm_hwbp_type hwbp_type; |
| 442 unsigned mask; | 443 unsigned mask; |
| 443 | 444 |
| 444 /* Breakpoint/watchpoint types (GDB terminology): | 445 /* Breakpoint/watchpoint types (GDB terminology): |
| 445 0 = memory breakpoint for instructions | 446 0 = memory breakpoint for instructions |
| 446 (not supported; done via memory write instead) | 447 (not supported; done via memory write instead) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 467 return -1; | 468 return -1; |
| 468 } | 469 } |
| 469 | 470 |
| 470 if (hwbp_type == arm_hwbp_break) | 471 if (hwbp_type == arm_hwbp_break) |
| 471 { | 472 { |
| 472 /* For breakpoints, the length field encodes the mode. */ | 473 /* For breakpoints, the length field encodes the mode. */ |
| 473 switch (len) | 474 switch (len) |
| 474 { | 475 { |
| 475 case 2: /* 16-bit Thumb mode breakpoint */ | 476 case 2: /* 16-bit Thumb mode breakpoint */ |
| 476 case 3: /* 32-bit Thumb mode breakpoint */ | 477 case 3: /* 32-bit Thumb mode breakpoint */ |
| 477 » mask = 0x3 << (addr & 2); | 478 » mask = 0x3; |
| 479 » addr &= ~1; |
| 478 break; | 480 break; |
| 479 case 4: /* 32-bit ARM mode breakpoint */ | 481 case 4: /* 32-bit ARM mode breakpoint */ |
| 480 mask = 0xf; | 482 mask = 0xf; |
| 483 addr &= ~3; |
| 481 break; | 484 break; |
| 482 default: | 485 default: |
| 483 /* Unsupported. */ | 486 /* Unsupported. */ |
| 484 » return -1; | 487 » return -2; |
| 485 } | 488 } |
| 486 | |
| 487 addr &= ~3; | |
| 488 } | 489 } |
| 489 else | 490 else |
| 490 { | 491 { |
| 491 CORE_ADDR max_wp_length = arm_linux_get_hw_watchpoint_max_length (); | 492 CORE_ADDR max_wp_length = arm_linux_get_hw_watchpoint_max_length (); |
| 492 CORE_ADDR aligned_addr; | 493 CORE_ADDR aligned_addr; |
| 493 | 494 |
| 494 /* Can not set watchpoints for zero or negative lengths. */ | 495 /* Can not set watchpoints for zero or negative lengths. */ |
| 495 if (len <= 0) | 496 if (len <= 0) |
| 496 » return -1; | 497 » return -2; |
| 497 /* The current ptrace interface can only handle watchpoints that are a | 498 /* The current ptrace interface can only handle watchpoints that are a |
| 498 power of 2. */ | 499 power of 2. */ |
| 499 if ((len & (len - 1)) != 0) | 500 if ((len & (len - 1)) != 0) |
| 500 » return -1; | 501 » return -2; |
| 501 | 502 |
| 502 /* Test that the range [ADDR, ADDR + LEN) fits into the largest address | 503 /* Test that the range [ADDR, ADDR + LEN) fits into the largest address |
| 503 range covered by a watchpoint. */ | 504 range covered by a watchpoint. */ |
| 504 aligned_addr = addr & ~(max_wp_length - 1); | 505 aligned_addr = addr & ~(max_wp_length - 1); |
| 505 if (aligned_addr + max_wp_length < addr + len) | 506 if (aligned_addr + max_wp_length < addr + len) |
| 506 » return -1; | 507 » return -2; |
| 507 | 508 |
| 508 mask = (1 << len) - 1; | 509 mask = (1 << len) - 1; |
| 509 } | 510 } |
| 510 | 511 |
| 511 p->address = (unsigned int) addr; | 512 p->address = (unsigned int) addr; |
| 512 p->control = arm_hwbp_control_initialize (mask, hwbp_type, 1); | 513 p->control = arm_hwbp_control_initialize (mask, hwbp_type, 1); |
| 513 | 514 |
| 514 return hwbp_type != arm_hwbp_break; | 515 return hwbp_type != arm_hwbp_break; |
| 515 } | 516 } |
| 516 | 517 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 arm_insert_point (char type, CORE_ADDR addr, int len) | 554 arm_insert_point (char type, CORE_ADDR addr, int len) |
| 554 { | 555 { |
| 555 struct process_info *proc = current_process (); | 556 struct process_info *proc = current_process (); |
| 556 struct arm_linux_hw_breakpoint p, *pts; | 557 struct arm_linux_hw_breakpoint p, *pts; |
| 557 int watch, i, count; | 558 int watch, i, count; |
| 558 | 559 |
| 559 watch = arm_linux_hw_point_initialize (type, addr, len, &p); | 560 watch = arm_linux_hw_point_initialize (type, addr, len, &p); |
| 560 if (watch < 0) | 561 if (watch < 0) |
| 561 { | 562 { |
| 562 /* Unsupported. */ | 563 /* Unsupported. */ |
| 563 return 1; | 564 return watch == -1 ? 1 : -1; |
| 564 } | 565 } |
| 565 | 566 |
| 566 if (watch) | 567 if (watch) |
| 567 { | 568 { |
| 568 count = arm_linux_get_hw_watchpoint_count (); | 569 count = arm_linux_get_hw_watchpoint_count (); |
| 569 pts = proc->private->arch_private->wpts; | 570 pts = proc->private->arch_private->wpts; |
| 570 } | 571 } |
| 571 else | 572 else |
| 572 { | 573 { |
| 573 count = arm_linux_get_hw_breakpoint_count (); | 574 count = arm_linux_get_hw_breakpoint_count (); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 | 625 |
| 625 /* No watchpoint matched. */ | 626 /* No watchpoint matched. */ |
| 626 return -1; | 627 return -1; |
| 627 } | 628 } |
| 628 | 629 |
| 629 /* Return whether current thread is stopped due to a watchpoint. */ | 630 /* Return whether current thread is stopped due to a watchpoint. */ |
| 630 static int | 631 static int |
| 631 arm_stopped_by_watchpoint (void) | 632 arm_stopped_by_watchpoint (void) |
| 632 { | 633 { |
| 633 struct lwp_info *lwp = get_thread_lwp (current_inferior); | 634 struct lwp_info *lwp = get_thread_lwp (current_inferior); |
| 634 struct siginfo siginfo; | 635 siginfo_t siginfo; |
| 635 | 636 |
| 636 /* We must be able to set hardware watchpoints. */ | 637 /* We must be able to set hardware watchpoints. */ |
| 637 if (arm_linux_get_hw_watchpoint_count () == 0) | 638 if (arm_linux_get_hw_watchpoint_count () == 0) |
| 638 return 0; | 639 return 0; |
| 639 | 640 |
| 640 /* Retrieve siginfo. */ | 641 /* Retrieve siginfo. */ |
| 641 errno = 0; | 642 errno = 0; |
| 642 ptrace (PTRACE_GETSIGINFO, lwpid_of (lwp), 0, &siginfo); | 643 ptrace (PTRACE_GETSIGINFO, lwpid_of (lwp), 0, &siginfo); |
| 643 if (errno != 0) | 644 if (errno != 0) |
| 644 return 0; | 645 return 0; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 struct arch_process_info *proc_info = proc->private->arch_private; | 703 struct arch_process_info *proc_info = proc->private->arch_private; |
| 703 struct arch_lwp_info *lwp_info = lwp->arch_private; | 704 struct arch_lwp_info *lwp_info = lwp->arch_private; |
| 704 int i; | 705 int i; |
| 705 | 706 |
| 706 for (i = 0; i < arm_linux_get_hw_breakpoint_count (); i++) | 707 for (i = 0; i < arm_linux_get_hw_breakpoint_count (); i++) |
| 707 if (lwp_info->bpts_changed[i]) | 708 if (lwp_info->bpts_changed[i]) |
| 708 { | 709 { |
| 709 errno = 0; | 710 errno = 0; |
| 710 | 711 |
| 711 if (arm_hwbp_control_is_enabled (proc_info->bpts[i].control)) | 712 if (arm_hwbp_control_is_enabled (proc_info->bpts[i].control)) |
| 712 » if (ptrace (PTRACE_SETHBPREGS, pid, ((i << 1) + 1), | 713 » if (ptrace (PTRACE_SETHBPREGS, pid, |
| 713 » &proc_info->bpts[i].address) < 0) | 714 » » (PTRACE_ARG3_TYPE) ((i << 1) + 1), |
| 715 » » &proc_info->bpts[i].address) < 0) |
| 714 perror_with_name ("Unexpected error setting breakpoint address"); | 716 perror_with_name ("Unexpected error setting breakpoint address"); |
| 715 | 717 |
| 716 if (arm_hwbp_control_is_initialized (proc_info->bpts[i].control)) | 718 if (arm_hwbp_control_is_initialized (proc_info->bpts[i].control)) |
| 717 » if (ptrace (PTRACE_SETHBPREGS, pid, ((i << 1) + 2), | 719 » if (ptrace (PTRACE_SETHBPREGS, pid, |
| 718 » &proc_info->bpts[i].control) < 0) | 720 » » (PTRACE_ARG3_TYPE) ((i << 1) + 2), |
| 721 » » &proc_info->bpts[i].control) < 0) |
| 719 perror_with_name ("Unexpected error setting breakpoint"); | 722 perror_with_name ("Unexpected error setting breakpoint"); |
| 720 | 723 |
| 721 lwp_info->bpts_changed[i] = 0; | 724 lwp_info->bpts_changed[i] = 0; |
| 722 } | 725 } |
| 723 | 726 |
| 724 for (i = 0; i < arm_linux_get_hw_watchpoint_count (); i++) | 727 for (i = 0; i < arm_linux_get_hw_watchpoint_count (); i++) |
| 725 if (lwp_info->wpts_changed[i]) | 728 if (lwp_info->wpts_changed[i]) |
| 726 { | 729 { |
| 727 errno = 0; | 730 errno = 0; |
| 728 | 731 |
| 729 if (arm_hwbp_control_is_enabled (proc_info->wpts[i].control)) | 732 if (arm_hwbp_control_is_enabled (proc_info->wpts[i].control)) |
| 730 » if (ptrace (PTRACE_SETHBPREGS, pid, -((i << 1) + 1), | 733 » if (ptrace (PTRACE_SETHBPREGS, pid, |
| 731 » &proc_info->wpts[i].address) < 0) | 734 » » (PTRACE_ARG3_TYPE) -((i << 1) + 1), |
| 735 » » &proc_info->wpts[i].address) < 0) |
| 732 perror_with_name ("Unexpected error setting watchpoint address"); | 736 perror_with_name ("Unexpected error setting watchpoint address"); |
| 733 | 737 |
| 734 if (arm_hwbp_control_is_initialized (proc_info->wpts[i].control)) | 738 if (arm_hwbp_control_is_initialized (proc_info->wpts[i].control)) |
| 735 » if (ptrace (PTRACE_SETHBPREGS, pid, -((i << 1) + 2), | 739 » if (ptrace (PTRACE_SETHBPREGS, pid, |
| 736 » &proc_info->wpts[i].control) < 0) | 740 » » (PTRACE_ARG3_TYPE) -((i << 1) + 2), |
| 741 » » &proc_info->wpts[i].control) < 0) |
| 737 perror_with_name ("Unexpected error setting watchpoint"); | 742 perror_with_name ("Unexpected error setting watchpoint"); |
| 738 | 743 |
| 739 lwp_info->wpts_changed[i] = 0; | 744 lwp_info->wpts_changed[i] = 0; |
| 740 } | 745 } |
| 741 } | 746 } |
| 742 | 747 |
| 743 | 748 |
| 744 static int | 749 static int |
| 745 arm_get_hwcap (unsigned long *valp) | 750 arm_get_hwcap (unsigned long *valp) |
| 746 { | 751 { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 { PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 0, 32 * 8 + 4, | 832 { PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 0, 32 * 8 + 4, |
| 828 EXTENDED_REGS, | 833 EXTENDED_REGS, |
| 829 arm_fill_vfpregset, arm_store_vfpregset }, | 834 arm_fill_vfpregset, arm_store_vfpregset }, |
| 830 { 0, 0, 0, -1, -1, NULL, NULL } | 835 { 0, 0, 0, -1, -1, NULL, NULL } |
| 831 }; | 836 }; |
| 832 | 837 |
| 833 struct linux_target_ops the_low_target = { | 838 struct linux_target_ops the_low_target = { |
| 834 arm_arch_setup, | 839 arm_arch_setup, |
| 835 arm_num_regs, | 840 arm_num_regs, |
| 836 arm_regmap, | 841 arm_regmap, |
| 842 NULL, |
| 837 arm_cannot_fetch_register, | 843 arm_cannot_fetch_register, |
| 838 arm_cannot_store_register, | 844 arm_cannot_store_register, |
| 845 NULL, /* fetch_register */ |
| 839 arm_get_pc, | 846 arm_get_pc, |
| 840 arm_set_pc, | 847 arm_set_pc, |
| 841 | 848 |
| 842 /* Define an ARM-mode breakpoint; we only set breakpoints in the C | 849 /* Define an ARM-mode breakpoint; we only set breakpoints in the C |
| 843 library, which is most likely to be ARM. If the kernel supports | 850 library, which is most likely to be ARM. If the kernel supports |
| 844 clone events, we will never insert a breakpoint, so even a Thumb | 851 clone events, we will never insert a breakpoint, so even a Thumb |
| 845 C library will work; so will mixing EABI/non-EABI gdbserver and | 852 C library will work; so will mixing EABI/non-EABI gdbserver and |
| 846 application. */ | 853 application. */ |
| 847 #ifndef __ARM_EABI__ | 854 #ifndef __ARM_EABI__ |
| 848 (const unsigned char *) &arm_breakpoint, | 855 (const unsigned char *) &arm_breakpoint, |
| 849 #else | 856 #else |
| 850 (const unsigned char *) &arm_eabi_breakpoint, | 857 (const unsigned char *) &arm_eabi_breakpoint, |
| 851 #endif | 858 #endif |
| 852 arm_breakpoint_len, | 859 arm_breakpoint_len, |
| 853 arm_reinsert_addr, | 860 arm_reinsert_addr, |
| 854 0, | 861 0, |
| 855 arm_breakpoint_at, | 862 arm_breakpoint_at, |
| 856 arm_insert_point, | 863 arm_insert_point, |
| 857 arm_remove_point, | 864 arm_remove_point, |
| 858 arm_stopped_by_watchpoint, | 865 arm_stopped_by_watchpoint, |
| 859 arm_stopped_data_address, | 866 arm_stopped_data_address, |
| 860 NULL, /* collect_ptrace_register */ | 867 NULL, /* collect_ptrace_register */ |
| 861 NULL, /* supply_ptrace_register */ | 868 NULL, /* supply_ptrace_register */ |
| 862 NULL, /* siginfo_fixup */ | 869 NULL, /* siginfo_fixup */ |
| 863 arm_new_process, | 870 arm_new_process, |
| 864 arm_new_thread, | 871 arm_new_thread, |
| 865 arm_prepare_to_resume, | 872 arm_prepare_to_resume, |
| 866 }; | 873 }; |
| OLD | NEW |