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