1 /* Target-dependent code for GNU/Linux UltraSPARC.
3 Copyright 2003, 2004 Free Software Foundation, Inc.
5 This file is part of GDB.
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 2 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
24 #include "frame-unwind.h"
27 #include "solib-svr4.h"
29 #include "trad-frame.h"
31 #include "gdb_assert.h"
32 #include "gdb_string.h"
34 #include "sparc64-tdep.h"
36 /* The instruction sequence for RT signals is
37 mov __NR_rt_sigreturn, %g1 ! hex: 0x82102065
38 ta 0x6d ! hex: 0x91d0206d
40 The effect is to call the system call rt_sigreturn.
41 Note that 64-bit binaries only use this RT signal return method. */
43 #define LINUX64_RT_SIGTRAMP_INSN0 0x82102065
44 #define LINUX64_RT_SIGTRAMP_INSN1 0x91d0206d
46 /* If PC is in a sigtramp routine consisting of the instructions
47 LINUX64_RT_SIGTRAMP_INSN0 and LINUX64_RT_SIGTRAMP_INSN1, return
48 the address of the start of the routine. Otherwise, return 0. */
51 sparc64_linux_sigtramp_start (struct frame_info
*next_frame
)
53 CORE_ADDR pc
= frame_pc_unwind (next_frame
);
54 ULONGEST word0
, word1
;
55 unsigned char buf
[8]; /* Two instructions. */
57 /* We only recognize a signal trampoline if PC is at the start of
58 one of the instructions. We optimize for finding the PC at the
59 start of the instruction sequence, as will be the case when the
60 trampoline is not the first frame on the stack. We assume that
61 in the case where the PC is not at the start of the instruction
62 sequence, there will be a few trailing readable bytes on the
65 if (!safe_frame_unwind_memory (next_frame
, pc
, buf
, sizeof buf
))
68 word0
= extract_unsigned_integer (buf
, 4);
69 if (word0
!= LINUX64_RT_SIGTRAMP_INSN0
)
71 if (word0
!= LINUX64_RT_SIGTRAMP_INSN1
)
75 if (!safe_frame_unwind_memory (next_frame
, pc
, buf
, sizeof buf
))
78 word0
= extract_unsigned_integer (buf
, 4);
81 word1
= extract_unsigned_integer (buf
+ 4, 4);
82 if (word0
!= LINUX64_RT_SIGTRAMP_INSN0
83 || word1
!= LINUX64_RT_SIGTRAMP_INSN1
)
90 sparc64_linux_sigtramp_p (struct frame_info
*next_frame
)
92 CORE_ADDR pc
= frame_pc_unwind (next_frame
);
95 find_pc_partial_function (pc
, &name
, NULL
, NULL
);
97 /* If we have NAME, we can optimize the search. The trampolines is
98 named __rt_sigreturn_stub. However, is isn't dynamically exported
99 from the shared C library, so the trampoline may appear to be part
100 of the preceding function. This should always be sigaction,
101 __sigaction, or __libc_sigaction (all aliases to the same function). */
102 if (name
== NULL
|| strstr (name
, "sigaction") != NULL
)
103 return (sparc64_linux_sigtramp_start (next_frame
) != 0);
105 return (strcmp ("__rt_sigreturn_stub", name
) == 0);
108 static struct sparc_frame_cache
*
109 sparc64_linux_sigtramp_frame_cache (struct frame_info
*next_frame
,
112 struct sparc_frame_cache
*cache
;
113 CORE_ADDR sigcontext_addr
, addr
;
119 cache
= sparc_frame_cache (next_frame
, this_cache
);
120 gdb_assert (cache
== *this_cache
);
122 regnum
= SPARC_SP_REGNUM
;
123 cache
->base
= frame_unwind_register_unsigned (next_frame
, regnum
);
127 regnum
= SPARC_O1_REGNUM
;
128 sigcontext_addr
= frame_unwind_register_unsigned (next_frame
, regnum
);
130 /* If this is a RT signal trampoline, adjust SIGCONTEXT_ADDR
132 addr
= sparc64_linux_sigtramp_start (next_frame
);
134 sigcontext_addr
+= 128;
136 addr
= frame_func_unwind (next_frame
);
140 cache
->saved_regs
= trad_frame_alloc_saved_regs (next_frame
);
142 /* Offsets from <bits/sigcontext.h> */
144 /* Since %g0 is always zero, keep the identity encoding. */
145 for (addr
= sigcontext_addr
+ 8, regnum
= SPARC_G1_REGNUM
;
146 regnum
<= SPARC_O7_REGNUM
; regnum
++, addr
+= 8)
147 cache
->saved_regs
[regnum
].addr
= addr
;
149 cache
->saved_regs
[SPARC64_STATE_REGNUM
].addr
= addr
+ 0;
150 cache
->saved_regs
[SPARC64_PC_REGNUM
].addr
= addr
+ 8;
151 cache
->saved_regs
[SPARC64_NPC_REGNUM
].addr
= addr
+ 16;
152 cache
->saved_regs
[SPARC64_Y_REGNUM
].addr
= addr
+ 24;
153 cache
->saved_regs
[SPARC64_FPRS_REGNUM
].addr
= addr
+ 28;
155 for (regnum
= SPARC_L0_REGNUM
, addr
= cache
->base
;
156 regnum
<= SPARC_I7_REGNUM
; regnum
++, addr
+= 8)
157 cache
->saved_regs
[regnum
].addr
= addr
;
163 sparc64_linux_sigtramp_frame_this_id (struct frame_info
*next_frame
,
165 struct frame_id
*this_id
)
167 struct sparc_frame_cache
*cache
=
168 sparc64_linux_sigtramp_frame_cache (next_frame
, this_cache
);
170 (*this_id
) = frame_id_build (cache
->base
, cache
->pc
);
174 sparc64_linux_sigtramp_frame_prev_register (struct frame_info
*next_frame
,
176 int regnum
, int *optimizedp
,
177 enum lval_type
*lvalp
,
179 int *realnump
, void *valuep
)
181 struct sparc_frame_cache
*cache
=
182 sparc64_linux_sigtramp_frame_cache (next_frame
, this_cache
);
184 trad_frame_get_prev_register (next_frame
, cache
->saved_regs
, regnum
,
185 optimizedp
, lvalp
, addrp
, realnump
, valuep
);
188 static const struct frame_unwind sparc64_linux_sigtramp_frame_unwind
=
191 sparc64_linux_sigtramp_frame_this_id
,
192 sparc64_linux_sigtramp_frame_prev_register
195 static const struct frame_unwind
*
196 sparc64_linux_sigtramp_frame_sniffer (struct frame_info
*next_frame
)
198 if (sparc64_linux_sigtramp_p (next_frame
))
199 return &sparc64_linux_sigtramp_frame_unwind
;
205 sparc64_linux_init_abi (struct gdbarch_info info
, struct gdbarch
*gdbarch
)
207 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
209 frame_unwind_append_sniffer (gdbarch
, sparc64_linux_sigtramp_frame_sniffer
);
211 /* GNU/Linux is very similar to Solaris ... */
212 sparc64_sol2_init_abi (info
, gdbarch
);
214 /* ... but doesn't have kernel-assisted single-stepping support. */
215 set_gdbarch_software_single_step (gdbarch
, sparc_software_single_step
);
217 /* Enable TLS support. */
218 set_gdbarch_fetch_tls_load_module_address (gdbarch
,
219 svr4_fetch_objfile_link_map
);
222 /* Provide a prototype to silence -Wmissing-prototypes. */
223 extern void _initialize_sparc64_linux_tdep (void);
226 _initialize_sparc64_linux_tdep (void)
228 gdbarch_register_osabi (bfd_arch_sparc
, bfd_mach_sparc_v9
,
229 GDB_OSABI_LINUX
, sparc64_linux_init_abi
);