]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/nat/aarch64-linux.c
aarch64 multi-arch support (part 2): siginfo fixup
[thirdparty/binutils-gdb.git] / gdb / nat / aarch64-linux.c
1 /* Copyright (C) 2009-2015 Free Software Foundation, Inc.
2 Contributed by ARM Ltd.
3
4 This file is part of GDB.
5
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
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19 #include "common-defs.h"
20 #include "break-common.h"
21 #include "nat/linux-nat.h"
22 #include "nat/aarch64-linux-hw-point.h"
23 #include "nat/aarch64-linux.h"
24
25 /* Called when resuming a thread LWP.
26 The hardware debug registers are updated when there is any change. */
27
28 void
29 aarch64_linux_prepare_to_resume (struct lwp_info *lwp)
30 {
31 struct arch_lwp_info *info = lwp_arch_private_info (lwp);
32
33 /* NULL means this is the main thread still going through the shell,
34 or, no watchpoint has been set yet. In that case, there's
35 nothing to do. */
36 if (info == NULL)
37 return;
38
39 if (DR_HAS_CHANGED (info->dr_changed_bp)
40 || DR_HAS_CHANGED (info->dr_changed_wp))
41 {
42 ptid_t ptid = ptid_of_lwp (lwp);
43 int tid = ptid_get_lwp (ptid);
44 struct aarch64_debug_reg_state *state
45 = aarch64_get_debug_reg_state (ptid_get_pid (ptid));
46
47 if (show_debug_regs)
48 debug_printf ("prepare_to_resume thread %d\n", tid);
49
50 /* Watchpoints. */
51 if (DR_HAS_CHANGED (info->dr_changed_wp))
52 {
53 aarch64_linux_set_debug_regs (state, tid, 1);
54 DR_CLEAR_CHANGED (info->dr_changed_wp);
55 }
56
57 /* Breakpoints. */
58 if (DR_HAS_CHANGED (info->dr_changed_bp))
59 {
60 aarch64_linux_set_debug_regs (state, tid, 0);
61 DR_CLEAR_CHANGED (info->dr_changed_bp);
62 }
63 }
64 }
65
66 /* Function to call when a new thread is detected. */
67
68 void
69 aarch64_linux_new_thread (struct lwp_info *lwp)
70 {
71 struct arch_lwp_info *info = XNEW (struct arch_lwp_info);
72
73 /* Mark that all the hardware breakpoint/watchpoint register pairs
74 for this thread need to be initialized (with data from
75 aarch_process_info.debug_reg_state). */
76 DR_MARK_ALL_CHANGED (info->dr_changed_bp, aarch64_num_bp_regs);
77 DR_MARK_ALL_CHANGED (info->dr_changed_wp, aarch64_num_wp_regs);
78
79 lwp_set_arch_private_info (lwp, info);
80 }
81
82 /* Convert native siginfo FROM to the siginfo in the layout of the
83 inferior's architecture TO. */
84
85 void
86 aarch64_compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
87 {
88 memset (to, 0, sizeof (*to));
89
90 to->si_signo = from->si_signo;
91 to->si_errno = from->si_errno;
92 to->si_code = from->si_code;
93
94 if (to->si_code == SI_TIMER)
95 {
96 to->cpt_si_timerid = from->si_timerid;
97 to->cpt_si_overrun = from->si_overrun;
98 to->cpt_si_ptr = (intptr_t) from->si_ptr;
99 }
100 else if (to->si_code == SI_USER)
101 {
102 to->cpt_si_pid = from->si_pid;
103 to->cpt_si_uid = from->si_uid;
104 }
105 else if (to->si_code < 0)
106 {
107 to->cpt_si_pid = from->si_pid;
108 to->cpt_si_uid = from->si_uid;
109 to->cpt_si_ptr = (intptr_t) from->si_ptr;
110 }
111 else
112 {
113 switch (to->si_signo)
114 {
115 case SIGCHLD:
116 to->cpt_si_pid = from->si_pid;
117 to->cpt_si_uid = from->si_uid;
118 to->cpt_si_status = from->si_status;
119 to->cpt_si_utime = from->si_utime;
120 to->cpt_si_stime = from->si_stime;
121 break;
122 case SIGILL:
123 case SIGFPE:
124 case SIGSEGV:
125 case SIGBUS:
126 to->cpt_si_addr = (intptr_t) from->si_addr;
127 break;
128 case SIGPOLL:
129 to->cpt_si_band = from->si_band;
130 to->cpt_si_fd = from->si_fd;
131 break;
132 default:
133 to->cpt_si_pid = from->si_pid;
134 to->cpt_si_uid = from->si_uid;
135 to->cpt_si_ptr = (intptr_t) from->si_ptr;
136 break;
137 }
138 }
139 }
140
141 /* Convert inferior's architecture siginfo FROM to native siginfo TO. */
142
143 void
144 aarch64_siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
145 {
146 memset (to, 0, sizeof (*to));
147
148 to->si_signo = from->si_signo;
149 to->si_errno = from->si_errno;
150 to->si_code = from->si_code;
151
152 if (to->si_code == SI_TIMER)
153 {
154 to->si_timerid = from->cpt_si_timerid;
155 to->si_overrun = from->cpt_si_overrun;
156 to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
157 }
158 else if (to->si_code == SI_USER)
159 {
160 to->si_pid = from->cpt_si_pid;
161 to->si_uid = from->cpt_si_uid;
162 }
163 if (to->si_code < 0)
164 {
165 to->si_pid = from->cpt_si_pid;
166 to->si_uid = from->cpt_si_uid;
167 to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
168 }
169 else
170 {
171 switch (to->si_signo)
172 {
173 case SIGCHLD:
174 to->si_pid = from->cpt_si_pid;
175 to->si_uid = from->cpt_si_uid;
176 to->si_status = from->cpt_si_status;
177 to->si_utime = from->cpt_si_utime;
178 to->si_stime = from->cpt_si_stime;
179 break;
180 case SIGILL:
181 case SIGFPE:
182 case SIGSEGV:
183 case SIGBUS:
184 to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
185 break;
186 case SIGPOLL:
187 to->si_band = from->cpt_si_band;
188 to->si_fd = from->cpt_si_fd;
189 break;
190 default:
191 to->si_pid = from->cpt_si_pid;
192 to->si_uid = from->cpt_si_uid;
193 to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
194 break;
195 }
196 }
197 }