| @@ -1,162 +1,162 @@ | | | @@ -1,162 +1,162 @@ |
1 | /* Native-dependent code for X86 BSD's. | | 1 | /* Native-dependent code for X86 BSD's. |
2 | | | 2 | |
3 | Copyright (C) 2003-2017 Free Software Foundation, Inc. | | 3 | Copyright (C) 2003-2017 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. |
11 | | | 11 | |
12 | This program is distributed in the hope that it will be useful, | | 12 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | | 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. | | 15 | GNU General Public License for more details. |
16 | | | 16 | |
17 | You should have received a copy of the GNU General Public License | | 17 | You should have received a copy of the GNU General Public License |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
19 | | | 19 | |
20 | #include "defs.h" | | 20 | #include "defs.h" |
21 | #include "inferior.h" | | 21 | #include "inferior.h" |
22 | #include "gdbthread.h" | | 22 | #include "gdbthread.h" |
23 | | | 23 | |
24 | /* We include <signal.h> to make sure `struct fxsave64' is defined on | | 24 | /* We include <signal.h> to make sure `struct fxsave64' is defined on |
25 | NetBSD, since NetBSD's <machine/reg.h> needs it. */ | | 25 | NetBSD, since NetBSD's <machine/reg.h> needs it. */ |
26 | #include <signal.h> | | 26 | #include <signal.h> |
27 | #include <sys/types.h> | | 27 | #include <sys/types.h> |
28 | #include <sys/ptrace.h> | | 28 | #include <sys/ptrace.h> |
29 | #include <machine/reg.h> | | 29 | #include <machine/reg.h> |
30 | | | 30 | |
31 | #include "x86-nat.h" | | 31 | #include "x86-nat.h" |
32 | #include "x86-bsd-nat.h" | | 32 | #include "x86-bsd-nat.h" |
33 | #include "inf-ptrace.h" | | 33 | #include "inf-ptrace.h" |
34 | | | 34 | |
35 | | | 35 | |
36 | #ifdef PT_GETXSTATE_INFO | | 36 | #ifdef PT_GETXSTATE_INFO |
37 | size_t x86bsd_xsave_len; | | 37 | size_t x86bsd_xsave_len; |
38 | #endif | | 38 | #endif |
39 | | | 39 | |
40 | /* Support for debug registers. */ | | 40 | /* Support for debug registers. */ |
41 | | | 41 | |
42 | #ifdef HAVE_PT_GETDBREGS | | 42 | #ifdef HAVE_PT_GETDBREGS |
43 | static void (*super_mourn_inferior) (struct target_ops *ops); | | 43 | static void (*super_mourn_inferior) (struct target_ops *ops); |
44 | | | 44 | |
45 | /* Implement the "to_mourn_inferior" target_ops method. */ | | 45 | /* Implement the "to_mourn_inferior" target_ops method. */ |
46 | | | 46 | |
47 | static void | | 47 | static void |
48 | x86bsd_mourn_inferior (struct target_ops *ops) | | 48 | x86bsd_mourn_inferior (struct target_ops *ops) |
49 | { | | 49 | { |
50 | x86_cleanup_dregs (); | | 50 | x86_cleanup_dregs (); |
51 | super_mourn_inferior (ops); | | 51 | super_mourn_inferior (ops); |
52 | } | | 52 | } |
53 | | | 53 | |
54 | /* Not all versions of FreeBSD/i386 that support the debug registers | | 54 | /* Not all versions of FreeBSD/i386 that support the debug registers |
55 | have this macro. */ | | 55 | have this macro. */ |
56 | #ifndef DBREG_DRX | | 56 | #ifndef DBREG_DRX |
57 | # if defined(__NetBSD__) | | 57 | # if defined(__NetBSD__) |
58 | # define DBREG_DRX(d, x) (((unsigned long *)&d->dr)[x]) | | 58 | # define DBREG_DRX(d, x) (((unsigned long *)&d->dr)[x]) |
59 | # elif defined(__FreeBSD__) | | 59 | # elif defined(__FreeBSD__) |
60 | # define DBREG_DRX(d, x) ((&d->dr0)[x]) | | 60 | # define DBREG_DRX(d, x) ((&d->dr0)[x]) |
61 | # else | | 61 | # else |
62 | # error "No drx macro" | | 62 | # error "No drx macro" |
63 | # endif | | 63 | # endif |
64 | #endif | | 64 | #endif |
65 | | | 65 | |
66 | static unsigned long | | 66 | static unsigned long |
67 | x86bsd_dr_get (ptid_t ptid, int regnum) | | 67 | x86bsd_dr_get (ptid_t ptid, int regnum) |
68 | { | | 68 | { |
69 | struct dbreg dbregs; | | 69 | struct dbreg dbregs; |
70 | | | 70 | |
71 | if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid), | | 71 | if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid), |
72 | (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) | | 72 | (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) |
73 | perror_with_name (_("Couldn't read debug registers")); | | 73 | perror_with_name (_("Couldn't read debug registers")); |
74 | | | 74 | |
75 | return DBREG_DRX ((&dbregs), regnum); | | 75 | return DBREG_DRX ((&dbregs), regnum); |
76 | } | | 76 | } |
77 | | | 77 | |
78 | static void | | 78 | static void |
79 | x86bsd_dr_set (int regnum, unsigned long value) | | 79 | x86bsd_dr_set (int regnum, unsigned long value) |
80 | { | | 80 | { |
81 | struct thread_info *thread; | | 81 | struct thread_info *thread; |
82 | struct dbreg dbregs; | | 82 | struct dbreg dbregs; |
83 | | | 83 | |
84 | if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid), | | 84 | if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid), |
85 | (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) | | 85 | (PTRACE_TYPE_ARG3) &dbregs, ptid_get_lwp (inferior_ptid)) == -1) |
86 | perror_with_name (_("Couldn't get debug registers")); | | 86 | perror_with_name (_("Couldn't get debug registers")); |
87 | | | 87 | |
88 | /* For some mysterious reason, some of the reserved bits in the | | 88 | /* For some mysterious reason, some of the reserved bits in the |
89 | debug control register get set. Mask these off, otherwise the | | 89 | debug control register get set. Mask these off, otherwise the |
90 | ptrace call below will fail. */ | | 90 | ptrace call below will fail. */ |
91 | DBREG_DRX ((&dbregs), 7) &= ~(0xffffffff0000fc00); | | 91 | DBREG_DRX ((&dbregs), 7) &= ~(0xffffffff0000fc00); |
92 | | | 92 | |
93 | DBREG_DRX ((&dbregs), regnum) = value; | | 93 | DBREG_DRX ((&dbregs), regnum) = value; |
94 | | | 94 | |
95 | ALL_NON_EXITED_THREADS (thread) | | 95 | ALL_NON_EXITED_THREADS (thread) |
96 | if (thread->inf == current_inferior ()) | | 96 | if (thread->inf == current_inferior ()) |
97 | { | | 97 | { |
98 | if (ptrace (PT_SETDBREGS, get_ptrace_pid (thread->ptid), | | 98 | if (ptrace (PT_SETDBREGS, get_ptrace_pid (thread->ptid), |
99 | (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) | | 99 | (PTRACE_TYPE_ARG3) &dbregs, ptid_get_lwp (inferior_ptid)) == -1) |
100 | perror_with_name (_("Couldn't write debug registers")); | | 100 | perror_with_name (_("Couldn't write debug registers")); |
101 | } | | 101 | } |
102 | } | | 102 | } |
103 | | | 103 | |
104 | static void | | 104 | static void |
105 | x86bsd_dr_set_control (unsigned long control) | | 105 | x86bsd_dr_set_control (unsigned long control) |
106 | { | | 106 | { |
107 | x86bsd_dr_set (7, control); | | 107 | x86bsd_dr_set (7, control); |
108 | } | | 108 | } |
109 | | | 109 | |
110 | static void | | 110 | static void |
111 | x86bsd_dr_set_addr (int regnum, CORE_ADDR addr) | | 111 | x86bsd_dr_set_addr (int regnum, CORE_ADDR addr) |
112 | { | | 112 | { |
113 | gdb_assert (regnum >= 0 && regnum <= 4); | | 113 | gdb_assert (regnum >= 0 && regnum <= 4); |
114 | | | 114 | |
115 | x86bsd_dr_set (regnum, addr); | | 115 | x86bsd_dr_set (regnum, addr); |
116 | } | | 116 | } |
117 | | | 117 | |
118 | static CORE_ADDR | | 118 | static CORE_ADDR |
119 | x86bsd_dr_get_addr (int regnum) | | 119 | x86bsd_dr_get_addr (int regnum) |
120 | { | | 120 | { |
121 | return x86bsd_dr_get (inferior_ptid, regnum); | | 121 | return x86bsd_dr_get (inferior_ptid, regnum); |
122 | } | | 122 | } |
123 | | | 123 | |
124 | static unsigned long | | 124 | static unsigned long |
125 | x86bsd_dr_get_status (void) | | 125 | x86bsd_dr_get_status (void) |
126 | { | | 126 | { |
127 | return x86bsd_dr_get (inferior_ptid, 6); | | 127 | return x86bsd_dr_get (inferior_ptid, 6); |
128 | } | | 128 | } |
129 | | | 129 | |
130 | static unsigned long | | 130 | static unsigned long |
131 | x86bsd_dr_get_control (void) | | 131 | x86bsd_dr_get_control (void) |
132 | { | | 132 | { |
133 | return x86bsd_dr_get (inferior_ptid, 7); | | 133 | return x86bsd_dr_get (inferior_ptid, 7); |
134 | } | | 134 | } |
135 | | | 135 | |
136 | #endif /* PT_GETDBREGS */ | | 136 | #endif /* PT_GETDBREGS */ |
137 | | | 137 | |
138 | /* Create a prototype *BSD/x86 target. The client can override it | | 138 | /* Create a prototype *BSD/x86 target. The client can override it |
139 | with local methods. */ | | 139 | with local methods. */ |
140 | | | 140 | |
141 | struct target_ops * | | 141 | struct target_ops * |
142 | x86bsd_target (void) | | 142 | x86bsd_target (void) |
143 | { | | 143 | { |
144 | struct target_ops *t; | | 144 | struct target_ops *t; |
145 | | | 145 | |
146 | t = inf_ptrace_target (); | | 146 | t = inf_ptrace_target (); |
147 | | | 147 | |
148 | #ifdef HAVE_PT_GETDBREGS | | 148 | #ifdef HAVE_PT_GETDBREGS |
149 | x86_use_watchpoints (t); | | 149 | x86_use_watchpoints (t); |
150 | | | 150 | |
151 | x86_dr_low.set_control = x86bsd_dr_set_control; | | 151 | x86_dr_low.set_control = x86bsd_dr_set_control; |
152 | x86_dr_low.set_addr = x86bsd_dr_set_addr; | | 152 | x86_dr_low.set_addr = x86bsd_dr_set_addr; |
153 | x86_dr_low.get_addr = x86bsd_dr_get_addr; | | 153 | x86_dr_low.get_addr = x86bsd_dr_get_addr; |
154 | x86_dr_low.get_status = x86bsd_dr_get_status; | | 154 | x86_dr_low.get_status = x86bsd_dr_get_status; |
155 | x86_dr_low.get_control = x86bsd_dr_get_control; | | 155 | x86_dr_low.get_control = x86bsd_dr_get_control; |
156 | x86_set_debug_register_length (sizeof (void *)); | | 156 | x86_set_debug_register_length (sizeof (void *)); |
157 | super_mourn_inferior = t->to_mourn_inferior; | | 157 | super_mourn_inferior = t->to_mourn_inferior; |
158 | t->to_mourn_inferior = x86bsd_mourn_inferior; | | 158 | t->to_mourn_inferior = x86bsd_mourn_inferior; |
159 | #endif /* HAVE_PT_GETDBREGS */ | | 159 | #endif /* HAVE_PT_GETDBREGS */ |
160 | | | 160 | |
161 | return t; | | 161 | return t; |
162 | } | | 162 | } |