]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/sparc64-linux-tdep.c
373dfb69a262ccef41fdb7e981f2d9054cb25696
[thirdparty/binutils-gdb.git] / gdb / sparc64-linux-tdep.c
1 /* Target-dependent code for GNU/Linux UltraSPARC.
2
3 Copyright (C) 2003-2025 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
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
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
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/>. */
19
20 #include "extract-store-integer.h"
21 #include "frame.h"
22 #include "frame-unwind.h"
23 #include "dwarf2/frame.h"
24 #include "regset.h"
25 #include "regcache.h"
26 #include "gdbarch.h"
27 #include "gdbcore.h"
28 #include "osabi.h"
29 #include "solib-svr4.h"
30 #include "symtab.h"
31 #include "trad-frame.h"
32 #include "tramp-frame.h"
33 #include "xml-syscall.h"
34 #include "linux-tdep.h"
35 #include "solib-svr4-linux.h"
36
37 /* ADI specific si_code */
38 #ifndef SEGV_ACCADI
39 #define SEGV_ACCADI 3
40 #endif
41 #ifndef SEGV_ADIDERR
42 #define SEGV_ADIDERR 4
43 #endif
44 #ifndef SEGV_ADIPERR
45 #define SEGV_ADIPERR 5
46 #endif
47
48 /* The syscall's XML filename for sparc 64-bit. */
49 #define XML_SYSCALL_FILENAME_SPARC64 "syscalls/sparc64-linux.xml"
50
51 #include "sparc64-tdep.h"
52
53 /* Signal trampoline support. */
54
55 static void sparc64_linux_sigframe_init (const struct tramp_frame *self,
56 const frame_info_ptr &this_frame,
57 struct trad_frame_cache *this_cache,
58 CORE_ADDR func);
59
60 /* See sparc-linux-tdep.c for details. Note that 64-bit binaries only
61 use RT signals. */
62
63 static const struct tramp_frame sparc64_linux_rt_sigframe =
64 {
65 SIGTRAMP_FRAME,
66 4,
67 {
68 { 0x82102065, ULONGEST_MAX }, /* mov __NR_rt_sigreturn, %g1 */
69 { 0x91d0206d, ULONGEST_MAX }, /* ta 0x6d */
70 { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
71 },
72 sparc64_linux_sigframe_init
73 };
74
75 static void
76 sparc64_linux_sigframe_init (const struct tramp_frame *self,
77 const frame_info_ptr &this_frame,
78 struct trad_frame_cache *this_cache,
79 CORE_ADDR func)
80 {
81 CORE_ADDR base, addr, sp_addr;
82 int regnum;
83
84 base = get_frame_register_unsigned (this_frame, SPARC_O1_REGNUM);
85 base += 128;
86
87 /* Offsets from <bits/sigcontext.h>. */
88
89 /* Since %g0 is always zero, keep the identity encoding. */
90 addr = base + 8;
91 sp_addr = base + ((SPARC_SP_REGNUM - SPARC_G0_REGNUM) * 8);
92 for (regnum = SPARC_G1_REGNUM; regnum <= SPARC_O7_REGNUM; regnum++)
93 {
94 trad_frame_set_reg_addr (this_cache, regnum, addr);
95 addr += 8;
96 }
97
98 trad_frame_set_reg_addr (this_cache, SPARC64_STATE_REGNUM, addr + 0);
99 trad_frame_set_reg_addr (this_cache, SPARC64_PC_REGNUM, addr + 8);
100 trad_frame_set_reg_addr (this_cache, SPARC64_NPC_REGNUM, addr + 16);
101 trad_frame_set_reg_addr (this_cache, SPARC64_Y_REGNUM, addr + 24);
102 trad_frame_set_reg_addr (this_cache, SPARC64_FPRS_REGNUM, addr + 28);
103
104 base = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
105 if (base & 1)
106 base += BIAS;
107
108 addr = get_frame_memory_unsigned (this_frame, sp_addr, 8);
109 if (addr & 1)
110 addr += BIAS;
111
112 for (regnum = SPARC_L0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
113 {
114 trad_frame_set_reg_addr (this_cache, regnum, addr);
115 addr += 8;
116 }
117 trad_frame_set_id (this_cache, frame_id_build (base, func));
118 }
119
120 /* sparc64 GNU/Linux implementation of the report_signal_info
121 gdbarch hook.
122 Displays information related to ADI memory corruptions. */
123
124 static void
125 sparc64_linux_report_signal_info (struct gdbarch *gdbarch, struct ui_out *uiout,
126 enum gdb_signal siggnal)
127 {
128 if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word != 64
129 || siggnal != GDB_SIGNAL_SEGV)
130 return;
131
132 CORE_ADDR addr = 0;
133 long si_code = 0;
134
135 try
136 {
137 /* Evaluate si_code to see if the segfault is ADI related. */
138 si_code = parse_and_eval_long ("$_siginfo.si_code\n");
139
140 if (si_code >= SEGV_ACCADI && si_code <= SEGV_ADIPERR)
141 addr = parse_and_eval_long ("$_siginfo._sifields._sigfault.si_addr");
142 }
143 catch (const gdb_exception_error &exception)
144 {
145 return;
146 }
147
148 /* Print out ADI event based on sig_code value */
149 switch (si_code)
150 {
151 case SEGV_ACCADI: /* adi not enabled */
152 uiout->text ("\n");
153 uiout->field_string ("sigcode-meaning", _("ADI disabled"));
154 uiout->text (_(" while accessing address "));
155 uiout->field_core_addr ("bound-access", gdbarch, addr);
156 break;
157 case SEGV_ADIDERR: /* disrupting mismatch */
158 uiout->text ("\n");
159 uiout->field_string ("sigcode-meaning", _("ADI deferred mismatch"));
160 uiout->text (_(" while accessing address "));
161 uiout->field_core_addr ("bound-access", gdbarch, addr);
162 break;
163 case SEGV_ADIPERR: /* precise mismatch */
164 uiout->text ("\n");
165 uiout->field_string ("sigcode-meaning", _("ADI precise mismatch"));
166 uiout->text (_(" while accessing address "));
167 uiout->field_core_addr ("bound-access", gdbarch, addr);
168 break;
169 default:
170 break;
171 }
172
173 }
174
175 \f
176 /* Return the address of a system call's alternative return
177 address. */
178
179 static CORE_ADDR
180 sparc64_linux_step_trap (const frame_info_ptr &frame, unsigned long insn)
181 {
182 /* __NR_rt_sigreturn is 101 */
183 if ((insn == 0x91d0206d)
184 && (get_frame_register_unsigned (frame, SPARC_G1_REGNUM) == 101))
185 {
186 struct gdbarch *gdbarch = get_frame_arch (frame);
187 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
188
189 ULONGEST sp = get_frame_register_unsigned (frame, SPARC_SP_REGNUM);
190 if (sp & 1)
191 sp += BIAS;
192
193 /* The kernel puts the sigreturn registers on the stack,
194 and this is where the signal unwinding state is take from
195 when returning from a signal.
196
197 A siginfo_t sits 192 bytes from the base of the stack. This
198 siginfo_t is 128 bytes, and is followed by the sigreturn
199 register save area. The saved PC sits at a 136 byte offset
200 into there. */
201
202 return read_memory_unsigned_integer (sp + 192 + 128 + 136,
203 8, byte_order);
204 }
205
206 return 0;
207 }
208 \f
209
210 const struct sparc_gregmap sparc64_linux_core_gregmap =
211 {
212 32 * 8, /* %tstate */
213 33 * 8, /* %tpc */
214 34 * 8, /* %tnpc */
215 35 * 8, /* %y */
216 -1, /* %wim */
217 -1, /* %tbr */
218 1 * 8, /* %g1 */
219 16 * 8, /* %l0 */
220 8, /* y size */
221 };
222 \f
223
224 static void
225 sparc64_linux_supply_core_gregset (const struct regset *regset,
226 struct regcache *regcache,
227 int regnum, const void *gregs, size_t len)
228 {
229 sparc64_supply_gregset (&sparc64_linux_core_gregmap,
230 regcache, regnum, gregs);
231 }
232
233 static void
234 sparc64_linux_collect_core_gregset (const struct regset *regset,
235 const struct regcache *regcache,
236 int regnum, void *gregs, size_t len)
237 {
238 sparc64_collect_gregset (&sparc64_linux_core_gregmap,
239 regcache, regnum, gregs);
240 }
241
242 static void
243 sparc64_linux_supply_core_fpregset (const struct regset *regset,
244 struct regcache *regcache,
245 int regnum, const void *fpregs, size_t len)
246 {
247 sparc64_supply_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs);
248 }
249
250 static void
251 sparc64_linux_collect_core_fpregset (const struct regset *regset,
252 const struct regcache *regcache,
253 int regnum, void *fpregs, size_t len)
254 {
255 sparc64_collect_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs);
256 }
257
258 /* Set the program counter for process PTID to PC. */
259
260 #define TSTATE_SYSCALL 0x0000000000000020ULL
261
262 static void
263 sparc64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
264 {
265 gdbarch *arch = regcache->arch ();
266 sparc_gdbarch_tdep *tdep = gdbarch_tdep<sparc_gdbarch_tdep> (arch);
267 ULONGEST state;
268
269 regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
270 regcache_cooked_write_unsigned (regcache, tdep->npc_regnum, pc + 4);
271
272 /* Clear the "in syscall" bit to prevent the kernel from
273 messing with the PCs we just installed, if we happen to be
274 within an interrupted system call that the kernel wants to
275 restart.
276
277 Note that after we return from the dummy call, the TSTATE et al.
278 registers will be automatically restored, and the kernel
279 continues to restart the system call at this point. */
280 regcache_cooked_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state);
281 state &= ~TSTATE_SYSCALL;
282 regcache_cooked_write_unsigned (regcache, SPARC64_STATE_REGNUM, state);
283 }
284
285 static LONGEST
286 sparc64_linux_get_syscall_number (struct gdbarch *gdbarch,
287 thread_info *thread)
288 {
289 struct regcache *regcache = get_thread_regcache (thread);
290 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
291 /* The content of a register. */
292 gdb_byte buf[8];
293 /* The result. */
294 LONGEST ret;
295
296 /* Getting the system call number from the register.
297 When dealing with the sparc architecture, this information
298 is stored at the %g1 register. */
299 regcache->cooked_read (SPARC_G1_REGNUM, buf);
300
301 ret = extract_signed_integer (buf, 8, byte_order);
302
303 return ret;
304 }
305
306 \f
307 /* Implement the "get_longjmp_target" gdbarch method. */
308
309 static int
310 sparc64_linux_get_longjmp_target (const frame_info_ptr &frame, CORE_ADDR *pc)
311 {
312 struct gdbarch *gdbarch = get_frame_arch (frame);
313 CORE_ADDR jb_addr;
314 gdb_byte buf[8];
315
316 jb_addr = get_frame_register_unsigned (frame, SPARC_O0_REGNUM);
317
318 /* setjmp and longjmp in SPARC64 are implemented in glibc using the
319 setcontext and getcontext system calls respectively. These
320 system calls operate on ucontext_t structures, which happen to
321 partially have the same structure than jmp_buf. However the
322 ucontext returned by getcontext, and thus the jmp_buf structure
323 returned by setjmp, contains the context of the trap instruction
324 in the glibc __[sig]setjmp wrapper, not the context of the user
325 code calling setjmp.
326
327 %o7 in the jmp_buf structure is stored at offset 18*8 in the
328 mc_gregs array, which is itself located at offset 32 into
329 jmp_buf. See bits/setjmp.h. This register contains the address
330 of the 'call setjmp' instruction in user code.
331
332 In order to determine the longjmp target address in the
333 initiating frame we need to examine the call instruction itself,
334 in particular whether the annul bit is set. If it is not set
335 then we need to jump over the instruction at the delay slot. */
336
337 if (target_read_memory (jb_addr + 32 + (18 * 8), buf, 8))
338 return 0;
339
340 *pc = extract_unsigned_integer (buf, 8, gdbarch_byte_order (gdbarch));
341
342 if (!sparc_is_annulled_branch_insn (*pc))
343 *pc += 4; /* delay slot insn */
344 *pc += 4; /* call insn */
345
346 return 1;
347 }
348
349 \f
350
351 static const struct regset sparc64_linux_gregset =
352 {
353 NULL,
354 sparc64_linux_supply_core_gregset,
355 sparc64_linux_collect_core_gregset
356 };
357
358 static const struct regset sparc64_linux_fpregset =
359 {
360 NULL,
361 sparc64_linux_supply_core_fpregset,
362 sparc64_linux_collect_core_fpregset
363 };
364
365 static void
366 sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
367 {
368 sparc_gdbarch_tdep *tdep = gdbarch_tdep<sparc_gdbarch_tdep> (gdbarch);
369
370 linux_init_abi (info, gdbarch, 0);
371
372 tdep->gregset = &sparc64_linux_gregset;
373 tdep->sizeof_gregset = 288;
374
375 tdep->fpregset = &sparc64_linux_fpregset;
376 tdep->sizeof_fpregset = 280;
377
378 tramp_frame_prepend_unwinder (gdbarch, &sparc64_linux_rt_sigframe);
379
380 /* Hook in the DWARF CFI frame unwinder. */
381 dwarf2_append_unwinders (gdbarch);
382
383 sparc64_init_abi (info, gdbarch);
384
385 /* GNU/Linux has SVR4-style shared libraries... */
386 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
387 set_solib_svr4_ops (gdbarch, make_linux_lp64_svr4_solib_ops);
388
389 /* ...which means that we need some special handling when doing
390 prologue analysis. */
391 tdep->plt_entry_size = 16;
392
393 /* Enable TLS support. */
394 set_gdbarch_fetch_tls_load_module_address (gdbarch,
395 svr4_fetch_objfile_link_map);
396
397 /* Make sure we can single-step over signal return system calls. */
398 tdep->step_trap = sparc64_linux_step_trap;
399
400 /* Make sure we can single-step over longjmp calls. */
401 set_gdbarch_get_longjmp_target (gdbarch, sparc64_linux_get_longjmp_target);
402
403 set_gdbarch_write_pc (gdbarch, sparc64_linux_write_pc);
404
405 /* Functions for 'catch syscall'. */
406 set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_SPARC64);
407 set_gdbarch_get_syscall_number (gdbarch,
408 sparc64_linux_get_syscall_number);
409 set_gdbarch_report_signal_info (gdbarch, sparc64_linux_report_signal_info);
410 }
411
412 INIT_GDB_FILE (sparc64_linux_tdep)
413 {
414 gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
415 GDB_OSABI_LINUX, sparc64_linux_init_abi);
416 }