linux64.h revision 107590
190075Sobrien/* Definitions for AMD x86-64 running Linux-based GNU systems with ELF format.
296263Sobrien   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
390075Sobrien   Contributed by Jan Hubicka <jh@suse.cz>, based on linux.h.
490075Sobrien
590075SobrienThis file is part of GNU CC.
690075Sobrien
790075SobrienGNU CC is free software; you can redistribute it and/or modify
890075Sobrienit under the terms of the GNU General Public License as published by
990075Sobrienthe Free Software Foundation; either version 2, or (at your option)
1090075Sobrienany later version.
1190075Sobrien
1290075SobrienGNU CC is distributed in the hope that it will be useful,
1390075Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1490075SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1590075SobrienGNU General Public License for more details.
1690075Sobrien
1790075SobrienYou should have received a copy of the GNU General Public License
1890075Sobrienalong with GNU CC; see the file COPYING.  If not, write to
1990075Sobrienthe Free Software Foundation, 59 Temple Place - Suite 330,
2090075SobrienBoston, MA 02111-1307, USA.  */
2190075Sobrien
2290075Sobrien#define LINUX_DEFAULT_ELF
2390075Sobrien
2490075Sobrien#undef TARGET_VERSION
2590075Sobrien#define TARGET_VERSION fprintf (stderr, " (x86-64 Linux/ELF)");
2690075Sobrien
2790075Sobrien#undef CPP_PREDEFINES
2896263Sobrien#define CPP_PREDEFINES "-D__ELF__ -Dunix -D__gnu_linux__ -Dlinux -Asystem(posix)"
2990075Sobrien
3090075Sobrien#undef CPP_SPEC
3190075Sobrien#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT} %{!m32:-D__LONG_MAX__=9223372036854775807L}"
3290075Sobrien
33107590Sobrien/* The svr4 ABI for the i386 says that records and unions are returned
34107590Sobrien   in memory.  In the 64bit compilation we will turn this flag off in
35107590Sobrien   override_options, as we never do pcc_struct_return scheme on this target.  */
36107590Sobrien#undef DEFAULT_PCC_STRUCT_RETURN
37107590Sobrien#define DEFAULT_PCC_STRUCT_RETURN 1
38107590Sobrien
3990075Sobrien/* Provide a LINK_SPEC.  Here we provide support for the special GCC
4090075Sobrien   options -static and -shared, which allow us to link things in one
4190075Sobrien   of these three modes by applying the appropriate combinations of
4290075Sobrien   options at link-time.
4390075Sobrien
4490075Sobrien   When the -shared link option is used a final link is not being
4590075Sobrien   done.  */
4690075Sobrien
4790075Sobrien#undef	LINK_SPEC
4896263Sobrien#define LINK_SPEC "%{!m32:-m elf_x86_64 -Y P,/usr/lib64} %{m32:-m elf_i386} \
4996263Sobrien  %{shared:-shared} \
5090075Sobrien  %{!shared: \
5190075Sobrien    %{!static: \
5290075Sobrien      %{rdynamic:-export-dynamic} \
5396263Sobrien      %{m32:%{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
5496263Sobrien      %{!m32:%{!dynamic-linker:-dynamic-linker /lib64/ld-linux-x86-64.so.2}}} \
5596263Sobrien    %{static:-static}}"
5690075Sobrien
5796263Sobrien#undef  STARTFILE_SPEC
5896263Sobrien#define STARTFILE_SPEC \
59104752Skan  "%{!shared: \
60104752Skan     %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
61104752Skan     %{!p:%{profile:gcrt1.o%s} %{!profile:crt1.o%s}}}} \
62104752Skan   crti.o%s %{static:crtbeginT.o%s} \
63104752Skan   %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
6496263Sobrien
6596263Sobrien#undef  ENDFILE_SPEC
66104752Skan#define ENDFILE_SPEC "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
6796263Sobrien
6896263Sobrien#define MULTILIB_DEFAULTS { "m64" }
6996263Sobrien
7096263Sobrien/* Do code reading to identify a signal frame, and set the frame
71102780Skan   state data appropriately.  See unwind-dw2.c for the structs.
72102780Skan   Don't use this at all if inhibit_libc is used.  */
7396263Sobrien
74102780Skan#ifndef inhibit_libc
7596263Sobrien#ifdef IN_LIBGCC2
7696263Sobrien#include <signal.h>
7796263Sobrien#include <sys/ucontext.h>
7896263Sobrien#endif
7996263Sobrien
80102780Skan#ifdef __x86_64__
8196263Sobrien#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)		\
8296263Sobrien  do {									\
8396263Sobrien    unsigned char *pc_ = (CONTEXT)->ra;					\
8496263Sobrien    struct sigcontext *sc_;						\
8596263Sobrien    long new_cfa_;							\
8696263Sobrien									\
8796263Sobrien    /* movq __NR_rt_sigreturn, %rax ; syscall  */			\
8896263Sobrien    if (*(unsigned char *)(pc_+0) == 0x48				\
8996263Sobrien	&& *(unsigned long *)(pc_+1) == 0x050f0000000fc0c7)		\
9096263Sobrien      {									\
9196263Sobrien	struct ucontext *uc_ = (CONTEXT)->cfa;				\
9296263Sobrien	sc_ = (struct sigcontext *) &uc_->uc_mcontext;			\
9396263Sobrien      }									\
9496263Sobrien    else								\
9596263Sobrien      break;								\
9696263Sobrien									\
9796263Sobrien    new_cfa_ = sc_->rsp;						\
9896263Sobrien    (FS)->cfa_how = CFA_REG_OFFSET;					\
9996263Sobrien    /* Register 7 is rsp  */						\
10096263Sobrien    (FS)->cfa_reg = 7;							\
10196263Sobrien    (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa;		\
10296263Sobrien									\
10396263Sobrien    /* The SVR4 register numbering macros aren't usable in libgcc.  */	\
10496263Sobrien    (FS)->regs.reg[0].how = REG_SAVED_OFFSET;				\
10596263Sobrien    (FS)->regs.reg[0].loc.offset = (long)&sc_->rax - new_cfa_;		\
10696263Sobrien    (FS)->regs.reg[1].how = REG_SAVED_OFFSET;				\
10796263Sobrien    (FS)->regs.reg[1].loc.offset = (long)&sc_->rbx - new_cfa_;		\
10896263Sobrien    (FS)->regs.reg[2].how = REG_SAVED_OFFSET;				\
10996263Sobrien    (FS)->regs.reg[2].loc.offset = (long)&sc_->rcx - new_cfa_;		\
11096263Sobrien    (FS)->regs.reg[3].how = REG_SAVED_OFFSET;				\
11196263Sobrien    (FS)->regs.reg[3].loc.offset = (long)&sc_->rdx - new_cfa_;		\
11296263Sobrien    (FS)->regs.reg[4].how = REG_SAVED_OFFSET;				\
11396263Sobrien    (FS)->regs.reg[4].loc.offset = (long)&sc_->rbp - new_cfa_;		\
11496263Sobrien    (FS)->regs.reg[5].how = REG_SAVED_OFFSET;				\
11596263Sobrien    (FS)->regs.reg[5].loc.offset = (long)&sc_->rsi - new_cfa_;		\
11696263Sobrien    (FS)->regs.reg[6].how = REG_SAVED_OFFSET;				\
11796263Sobrien    (FS)->regs.reg[6].loc.offset = (long)&sc_->rdi - new_cfa_;		\
11896263Sobrien    (FS)->regs.reg[8].how = REG_SAVED_OFFSET;				\
11996263Sobrien    (FS)->regs.reg[8].loc.offset = (long)&sc_->r8 - new_cfa_;		\
12096263Sobrien    (FS)->regs.reg[9].how = REG_SAVED_OFFSET;				\
12196263Sobrien    (FS)->regs.reg[9].loc.offset = (long)&sc_->r9 - new_cfa_;		\
12296263Sobrien    (FS)->regs.reg[10].how = REG_SAVED_OFFSET;				\
12396263Sobrien    (FS)->regs.reg[10].loc.offset = (long)&sc_->r10 - new_cfa_;		\
12496263Sobrien    (FS)->regs.reg[11].how = REG_SAVED_OFFSET;				\
12596263Sobrien    (FS)->regs.reg[11].loc.offset = (long)&sc_->r11 - new_cfa_;		\
12696263Sobrien    (FS)->regs.reg[12].how = REG_SAVED_OFFSET;				\
12796263Sobrien    (FS)->regs.reg[12].loc.offset = (long)&sc_->r12 - new_cfa_;		\
12896263Sobrien    (FS)->regs.reg[13].how = REG_SAVED_OFFSET;				\
12996263Sobrien    (FS)->regs.reg[13].loc.offset = (long)&sc_->r13 - new_cfa_;		\
13096263Sobrien    (FS)->regs.reg[14].how = REG_SAVED_OFFSET;				\
13196263Sobrien    (FS)->regs.reg[14].loc.offset = (long)&sc_->r14 - new_cfa_;		\
13296263Sobrien    (FS)->regs.reg[15].how = REG_SAVED_OFFSET;				\
13396263Sobrien    (FS)->regs.reg[15].loc.offset = (long)&sc_->r15 - new_cfa_;		\
13496263Sobrien    (FS)->retaddr_column = 16;						\
13596263Sobrien    goto SUCCESS;							\
13696263Sobrien  } while (0)
137102780Skan#else /* ifdef __x86_64__  */
138102780Skan#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)		\
139102780Skan  do {									\
140102780Skan    unsigned char *pc_ = (CONTEXT)->ra;					\
141102780Skan    struct sigcontext *sc_;						\
142102780Skan    long new_cfa_;							\
143102780Skan									\
144102780Skan    /* popl %eax ; movl $__NR_sigreturn,%eax ; int $0x80  */		\
145102780Skan    if (*(unsigned short *)(pc_+0) == 0xb858				\
146102780Skan	&& *(unsigned int *)(pc_+2) == 119				\
147102780Skan	&& *(unsigned short *)(pc_+6) == 0x80cd)			\
148102780Skan      sc_ = (CONTEXT)->cfa + 4;						\
149102780Skan    /* movl $__NR_rt_sigreturn,%eax ; int $0x80  */			\
150102780Skan    else if (*(unsigned char *)(pc_+0) == 0xb8				\
151102780Skan	     && *(unsigned int *)(pc_+1) == 173				\
152102780Skan	     && *(unsigned short *)(pc_+5) == 0x80cd)			\
153102780Skan      {									\
154102780Skan	struct rt_sigframe {						\
155102780Skan	  int sig;							\
156102780Skan	  struct siginfo *pinfo;					\
157102780Skan	  void *puc;							\
158102780Skan	  struct siginfo info;						\
159102780Skan	  struct ucontext uc;						\
160102780Skan	} *rt_ = (CONTEXT)->cfa;					\
161102780Skan	sc_ = (struct sigcontext *) &rt_->uc.uc_mcontext;		\
162102780Skan      }									\
163102780Skan    else								\
164102780Skan      break;								\
165102780Skan									\
166102780Skan    new_cfa_ = sc_->esp;						\
167102780Skan    (FS)->cfa_how = CFA_REG_OFFSET;					\
168102780Skan    (FS)->cfa_reg = 4;							\
169102780Skan    (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa;		\
170102780Skan									\
171102780Skan    /* The SVR4 register numbering macros aren't usable in libgcc.  */	\
172102780Skan    (FS)->regs.reg[0].how = REG_SAVED_OFFSET;				\
173102780Skan    (FS)->regs.reg[0].loc.offset = (long)&sc_->eax - new_cfa_;		\
174102780Skan    (FS)->regs.reg[3].how = REG_SAVED_OFFSET;				\
175102780Skan    (FS)->regs.reg[3].loc.offset = (long)&sc_->ebx - new_cfa_;		\
176102780Skan    (FS)->regs.reg[1].how = REG_SAVED_OFFSET;				\
177102780Skan    (FS)->regs.reg[1].loc.offset = (long)&sc_->ecx - new_cfa_;		\
178102780Skan    (FS)->regs.reg[2].how = REG_SAVED_OFFSET;				\
179102780Skan    (FS)->regs.reg[2].loc.offset = (long)&sc_->edx - new_cfa_;		\
180102780Skan    (FS)->regs.reg[6].how = REG_SAVED_OFFSET;				\
181102780Skan    (FS)->regs.reg[6].loc.offset = (long)&sc_->esi - new_cfa_;		\
182102780Skan    (FS)->regs.reg[7].how = REG_SAVED_OFFSET;				\
183102780Skan    (FS)->regs.reg[7].loc.offset = (long)&sc_->edi - new_cfa_;		\
184102780Skan    (FS)->regs.reg[5].how = REG_SAVED_OFFSET;				\
185102780Skan    (FS)->regs.reg[5].loc.offset = (long)&sc_->ebp - new_cfa_;		\
186102780Skan    (FS)->regs.reg[8].how = REG_SAVED_OFFSET;				\
187102780Skan    (FS)->regs.reg[8].loc.offset = (long)&sc_->eip - new_cfa_;		\
188102780Skan    (FS)->retaddr_column = 8;						\
189102780Skan    goto SUCCESS;							\
190102780Skan  } while (0)
191102780Skan#endif /* ifdef __x86_64__  */
192102780Skan#endif /* ifdef inhibit_libc  */
193