1 /* Target-dependent code for GNU/Linux x86-64.
3 Copyright 2001, 2003, 2004 Free Software Foundation, Inc.
4 Contributed by Jiri Smid, SuSE Labs.
6 This file is part of GDB.
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 2 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
29 #include "gdb_string.h"
31 #include "amd64-tdep.h"
32 #include "solib-svr4.h"
34 /* Mapping between the general-purpose registers in `struct user'
35 format and GDB's register cache layout. */
37 /* From <sys/reg.h>. */
38 static int amd64_linux_gregset_reg_offset
[] =
67 /* Support for signal handlers. */
69 #define LINUX_SIGTRAMP_INSN0 0x48 /* mov $NNNNNNNN, %rax */
70 #define LINUX_SIGTRAMP_OFFSET0 0
71 #define LINUX_SIGTRAMP_INSN1 0x0f /* syscall */
72 #define LINUX_SIGTRAMP_OFFSET1 7
74 static const unsigned char linux_sigtramp_code
[] =
76 /* mov $__NR_rt_sigreturn, %rax */
77 LINUX_SIGTRAMP_INSN0
, 0xc7, 0xc0, 0x0f, 0x00, 0x00, 0x00,
79 LINUX_SIGTRAMP_INSN1
, 0x05
82 #define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
84 /* If PC is in a sigtramp routine, return the address of the start of
85 the routine. Otherwise, return 0. */
88 amd64_linux_sigtramp_start (CORE_ADDR pc
)
90 unsigned char buf
[LINUX_SIGTRAMP_LEN
];
92 /* We only recognize a signal trampoline if PC is at the start of
93 one of the two instructions. We optimize for finding the PC at
94 the start, as will be the case when the trampoline is not the
95 first frame on the stack. We assume that in the case where the
96 PC is not at the start of the instruction sequence, there will be
97 a few trailing readable bytes on the stack. */
99 if (read_memory_nobpt (pc
, (char *) buf
, LINUX_SIGTRAMP_LEN
) != 0)
102 if (buf
[0] != LINUX_SIGTRAMP_INSN0
)
104 if (buf
[0] != LINUX_SIGTRAMP_INSN1
)
107 pc
-= LINUX_SIGTRAMP_OFFSET1
;
109 if (read_memory_nobpt (pc
, (char *) buf
, LINUX_SIGTRAMP_LEN
) != 0)
113 if (memcmp (buf
, linux_sigtramp_code
, LINUX_SIGTRAMP_LEN
) != 0)
119 /* Return whether PC is in a GNU/Linux sigtramp routine. */
122 amd64_linux_pc_in_sigtramp (CORE_ADDR pc
, char *name
)
124 /* If we have NAME, we can optimize the search. The trampoline is
125 named __restore_rt. However, it isn't dynamically exported from
126 the shared C library, so the trampoline may appear to be part of
127 the preceding function. This should always be sigaction,
128 __sigaction, or __libc_sigaction (all aliases to the same
130 if (name
== NULL
|| strstr (name
, "sigaction") != NULL
)
131 return (amd64_linux_sigtramp_start (pc
) != 0);
133 return (strcmp ("__restore_rt", name
) == 0);
136 /* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */
137 #define AMD64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 40
139 /* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
140 routine, return the address of the associated sigcontext structure. */
143 amd64_linux_sigcontext_addr (struct frame_info
*next_frame
)
148 frame_unwind_register (next_frame
, SP_REGNUM
, buf
);
149 sp
= extract_unsigned_integer (buf
, 8);
151 /* The sigcontext structure is part of the user context. A pointer
152 to the user context is passed as the third argument to the signal
153 handler, i.e. in %rdx. Unfortunately %rdx isn't preserved across
154 function calls so we can't use it. Fortunately the user context
155 is part of the signal frame and the unwound %rsp directly points
157 return sp
+ AMD64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET
;
161 /* From <asm/sigcontext.h>. */
162 static int amd64_linux_sc_reg_offset
[] =
181 17 * 8, /* %eflags */
183 /* FIXME: kettenis/2002030531: The registers %cs, %fs and %gs are
184 available in `struct sigcontext'. However, they only occupy two
185 bytes instead of four, which makes using them here rather
186 difficult. Leave them out for now. */
196 amd64_linux_init_abi (struct gdbarch_info info
, struct gdbarch
*gdbarch
)
198 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
200 tdep
->gregset_reg_offset
= amd64_linux_gregset_reg_offset
;
201 tdep
->gregset_num_regs
= ARRAY_SIZE (amd64_linux_gregset_reg_offset
);
202 tdep
->sizeof_gregset
= 27 * 8;
204 amd64_init_abi (info
, gdbarch
);
206 set_gdbarch_pc_in_sigtramp (gdbarch
, amd64_linux_pc_in_sigtramp
);
207 tdep
->sigcontext_addr
= amd64_linux_sigcontext_addr
;
208 tdep
->sc_reg_offset
= amd64_linux_sc_reg_offset
;
209 tdep
->sc_num_regs
= ARRAY_SIZE (amd64_linux_sc_reg_offset
);
211 /* GNU/Linux uses SVR4-style shared libraries. */
212 set_solib_svr4_fetch_link_map_offsets
213 (gdbarch
, svr4_lp64_fetch_link_map_offsets
);
217 /* Provide a prototype to silence -Wmissing-prototypes. */
218 extern void _initialize_amd64_linux_tdep (void);
221 _initialize_amd64_linux_tdep (void)
223 gdbarch_register_osabi (bfd_arch_i386
, bfd_mach_x86_64
,
224 GDB_OSABI_LINUX
, amd64_linux_init_abi
);