Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Side by Side Diff: gdb/aarch64-linux-tdep.c

Issue 124383005: GDB 7.6.50 (Closed) Base URL: http://git.chromium.org/native_client/nacl-gdb.git@upstream
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gdb/aarch64-linux-tdep.h ('k') | gdb/aarch64-newlib-tdep.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* Target-dependent code for GNU/Linux AArch64.
2
3 Copyright (C) 2009-2013 Free Software Foundation, Inc.
4 Contributed by ARM Ltd.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include "defs.h"
22
23 #include "gdbarch.h"
24 #include "glibc-tdep.h"
25 #include "linux-tdep.h"
26 #include "aarch64-tdep.h"
27 #include "aarch64-linux-tdep.h"
28 #include "osabi.h"
29 #include "solib-svr4.h"
30 #include "symtab.h"
31 #include "tramp-frame.h"
32 #include "trad-frame.h"
33
34 #include "inferior.h"
35 #include "regcache.h"
36 #include "regset.h"
37
38 /* The general-purpose regset consists of 31 X registers, plus SP, PC,
39 and PSTATE registers, as defined in the AArch64 port of the Linux
40 kernel. */
41 #define AARCH64_LINUX_SIZEOF_GREGSET (34 * X_REGISTER_SIZE)
42
43 /* The fp regset consists of 32 V registers, plus FPCR and FPSR which
44 are 4 bytes wide each, and the whole structure is padded to 128 bit
45 alignment. */
46 #define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
47
48 /* Signal frame handling.
49
50 +----------+ ^
51 | saved lr | |
52 +->| saved fp |--+
53 | | |
54 | | |
55 | +----------+
56 | | saved lr |
57 +--| saved fp |
58 ^ | |
59 | | |
60 | +----------+
61 ^ | |
62 | | signal |
63 | | |
64 | | saved lr |-->interrupted_function_pc
65 +--| saved fp |
66 | +----------+
67 | | saved lr |--> default_restorer (movz x8, NR_sys_rt_sigreturn; svc 0)
68 +--| saved fp |<- FP
69 | |
70 | |<- SP
71 +----------+
72
73 On signal delivery, the kernel will create a signal handler stack
74 frame and setup the return address in LR to point at restorer stub.
75 The signal stack frame is defined by:
76
77 struct rt_sigframe
78 {
79 siginfo_t info;
80 struct ucontext uc;
81 };
82
83 typedef struct
84 {
85 ... 128 bytes
86 } siginfo_t;
87
88 The ucontext has the following form:
89 struct ucontext
90 {
91 unsigned long uc_flags;
92 struct ucontext *uc_link;
93 stack_t uc_stack;
94 sigset_t uc_sigmask;
95 struct sigcontext uc_mcontext;
96 };
97
98 typedef struct sigaltstack
99 {
100 void *ss_sp;
101 int ss_flags;
102 size_t ss_size;
103 } stack_t;
104
105 struct sigcontext
106 {
107 unsigned long fault_address;
108 unsigned long regs[31];
109 unsigned long sp; / * 31 * /
110 unsigned long pc; / * 32 * /
111 unsigned long pstate; / * 33 * /
112 __u8 __reserved[4096]
113 };
114
115 The restorer stub will always have the form:
116
117 d28015a8 movz x8, #0xad
118 d4000001 svc #0x0
119
120 We detect signal frames by snooping the return code for the restorer
121 instruction sequence.
122
123 The handler then needs to recover the saved register set from
124 ucontext.uc_mcontext. */
125
126 /* These magic numbers need to reflect the layout of the kernel
127 defined struct rt_sigframe and ucontext. */
128 #define AARCH64_SIGCONTEXT_REG_SIZE 8
129 #define AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET 128
130 #define AARCH64_UCONTEXT_SIGCONTEXT_OFFSET 176
131 #define AARCH64_SIGCONTEXT_XO_OFFSET 8
132
133 /* Implement the "init" method of struct tramp_frame. */
134
135 static void
136 aarch64_linux_sigframe_init (const struct tramp_frame *self,
137 struct frame_info *this_frame,
138 struct trad_frame_cache *this_cache,
139 CORE_ADDR func)
140 {
141 struct gdbarch *gdbarch = get_frame_arch (this_frame);
142 CORE_ADDR sp = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM);
143 CORE_ADDR fp = get_frame_register_unsigned (this_frame, AARCH64_FP_REGNUM);
144 CORE_ADDR sigcontext_addr =
145 sp
146 + AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET
147 + AARCH64_UCONTEXT_SIGCONTEXT_OFFSET;
148 int i;
149
150 for (i = 0; i < 31; i++)
151 {
152 trad_frame_set_reg_addr (this_cache,
153 AARCH64_X0_REGNUM + i,
154 sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
155 + i * AARCH64_SIGCONTEXT_REG_SIZE);
156 }
157
158 trad_frame_set_reg_addr (this_cache, AARCH64_FP_REGNUM, fp);
159 trad_frame_set_reg_addr (this_cache, AARCH64_LR_REGNUM, fp + 8);
160 trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM, fp + 8);
161
162 trad_frame_set_id (this_cache, frame_id_build (fp, func));
163 }
164
165 static const struct tramp_frame aarch64_linux_rt_sigframe =
166 {
167 SIGTRAMP_FRAME,
168 4,
169 {
170 /* movz x8, 0x8b (S=1,o=10,h=0,i=0x8b,r=8)
171 Soo1 0010 1hhi iiii iiii iiii iiir rrrr */
172 {0xd2801168, -1},
173
174 /* svc 0x0 (o=0, l=1)
175 1101 0100 oooi iiii iiii iiii iii0 00ll */
176 {0xd4000001, -1},
177 {TRAMP_SENTINEL_INSN, -1}
178 },
179 aarch64_linux_sigframe_init
180 };
181
182 /* Fill GDB's register array with the general-purpose register values
183 in the buffer pointed by GREGS_BUF. */
184
185 void
186 aarch64_linux_supply_gregset (struct regcache *regcache,
187 const gdb_byte *gregs_buf)
188 {
189 int regno;
190
191 for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_CPSR_REGNUM; regno++)
192 regcache_raw_supply (regcache, regno,
193 gregs_buf + X_REGISTER_SIZE
194 * (regno - AARCH64_X0_REGNUM));
195 }
196
197 /* The "supply_regset" function for the general-purpose register set. */
198
199 static void
200 supply_gregset_from_core (const struct regset *regset,
201 struct regcache *regcache,
202 int regnum, const void *regbuf, size_t len)
203 {
204 aarch64_linux_supply_gregset (regcache, (const gdb_byte *) regbuf);
205 }
206
207 /* Fill GDB's register array with the floating-point register values
208 in the buffer pointed by FPREGS_BUF. */
209
210 void
211 aarch64_linux_supply_fpregset (struct regcache *regcache,
212 const gdb_byte *fpregs_buf)
213 {
214 int regno;
215
216 for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
217 regcache_raw_supply (regcache, regno,
218 fpregs_buf + V_REGISTER_SIZE
219 * (regno - AARCH64_V0_REGNUM));
220
221 regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM,
222 fpregs_buf + V_REGISTER_SIZE * 32);
223 regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM,
224 fpregs_buf + V_REGISTER_SIZE * 32 + 4);
225 }
226
227 /* The "supply_regset" function for the floating-point register set. */
228
229 static void
230 supply_fpregset_from_core (const struct regset *regset,
231 struct regcache *regcache,
232 int regnum, const void *regbuf, size_t len)
233 {
234 aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) regbuf);
235 }
236
237 /* Implement the "regset_from_core_section" gdbarch method. */
238
239 static const struct regset *
240 aarch64_linux_regset_from_core_section (struct gdbarch *gdbarch,
241 const char *sect_name,
242 size_t sect_size)
243 {
244 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
245
246 if (strcmp (sect_name, ".reg") == 0
247 && sect_size == AARCH64_LINUX_SIZEOF_GREGSET)
248 {
249 if (tdep->gregset == NULL)
250 tdep->gregset = regset_alloc (gdbarch, supply_gregset_from_core,
251 NULL);
252 return tdep->gregset;
253 }
254
255 if (strcmp (sect_name, ".reg2") == 0
256 && sect_size == AARCH64_LINUX_SIZEOF_FPREGSET)
257 {
258 if (tdep->fpregset == NULL)
259 tdep->fpregset = regset_alloc (gdbarch, supply_fpregset_from_core,
260 NULL);
261 return tdep->fpregset;
262 }
263 return NULL;
264 }
265
266 static void
267 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
268 {
269 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
270
271 tdep->lowest_pc = 0x8000;
272
273 linux_init_abi (info, gdbarch);
274
275 set_solib_svr4_fetch_link_map_offsets (gdbarch,
276 svr4_lp64_fetch_link_map_offsets);
277
278 /* Enable TLS support. */
279 set_gdbarch_fetch_tls_load_module_address (gdbarch,
280 svr4_fetch_objfile_link_map);
281
282 /* Shared library handling. */
283 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
284
285 set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
286 tramp_frame_prepend_unwinder (gdbarch, &aarch64_linux_rt_sigframe);
287
288 /* Enable longjmp. */
289 tdep->jb_pc = 11;
290
291 set_gdbarch_regset_from_core_section (gdbarch,
292 aarch64_linux_regset_from_core_section);
293 }
294
295 /* Provide a prototype to silence -Wmissing-prototypes. */
296 extern initialize_file_ftype _initialize_aarch64_linux_tdep;
297
298 void
299 _initialize_aarch64_linux_tdep (void)
300 {
301 gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_LINUX,
302 aarch64_linux_init_abi);
303 }
OLDNEW
« no previous file with comments | « gdb/aarch64-linux-tdep.h ('k') | gdb/aarch64-newlib-tdep.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698