/* Definitions to target GDB to GNU/Linux on 386.
- Copyright 1992, 1993 Free Software Foundation, Inc.
+ Copyright 1992, 1993, 1995, 1996, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
This file is part of GDB.
#define TM_LINUX_H
#define I386_GNULINUX_TARGET
+#define HAVE_I387_REGS
+#ifdef HAVE_PTRACE_GETFPXREGS
+#define HAVE_SSE_REGS
+#endif
#include "i386/tm-i386.h"
+#include "tm-linux.h"
-/* Size of sigcontext, from <asm/sigcontext.h>. */
-#define LINUX_SIGCONTEXT_SIZE (88)
-
-/* Offset to saved PC in sigcontext, from <asm/sigcontext.h>. */
-#define LINUX_SIGCONTEXT_PC_OFFSET (56)
-
-/* Offset to saved SP in sigcontext, from <asm/sigcontext.h>. */
-#define LINUX_SIGCONTEXT_SP_OFFSET (28)
-
-/* We need this file for the SOLIB_TRAMPOLINE stuff. */
+/* Register number for the "orig_eax" pseudo-register. If this
+ pseudo-register contains a value >= 0 it is interpreted as the
+ system call number that the kernel is supposed to restart. */
+#define I386_LINUX_ORIG_EAX_REGNUM 41
-#include "tm-sysv4.h"
+/* Adjust a few macros to deal with this extra register. */
-/* copy of tm-cygwin32.h */
-#undef REGISTER_RAW_SIZE
-#undef REGISTER_VIRTUAL_SIZE
-#undef REGISTER_VIRTUAL_TYPE
-#undef REGISTER_NAMES
-#undef REGISTER_BYTES
-#undef REGISTER_BYTE
-#undef MAX_REGISTER_VIRTUAL_SIZE
#undef NUM_REGS
-#undef NUM_FREGS
-
-/* Number of machine registers */
-
-#define NUM_REGS 31
-#define NUM_FREGS 15
-
-/* Initializer for an array of names of registers.
- There should be NUM_REGS strings in this initializer. */
-
-/* the order of the first 8 registers must match the compiler's
- * numbering scheme (which is the same as the 386 scheme)
- * also, this table must match regmap in i386-pinsn.c.
- */
-
-#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
- "esp", "ebp", "esi", "edi", \
- "eip", "eflags","cs", "ss", \
- "ds", "es", "fs", "gs", \
- "cwd", "swd", "twd", "fip", \
- "fcs", "fopo", "fos", \
- "st", "st1", "st2", "st3", \
- "st4", "st5", "st6", "st7",}
-
-#define LOW_RETURN_REGNUM 0 /* holds low four bytes of result */
-#define HIGH_RETURN_REGNUM 2 /* holds high four bytes of result */
-
-#define FPSTART_REGNUM 16 /* start of FPU registers */
-#define FPCONTROL_REGNUM 16 /* FPU control register */
-#define FPSTATUS_REGNUM 17 /* FPU status register */
-#define FPTAG_REGNUM 18 /* FPU tag register */
-#define FPDATA_REGNUM 23 /* actual floating-point values */
-#define FPEND_REGNUM (FPSTART_REGNUM + 14) /* last FPU register */
-
-#define FPENV_BYTES (7 * 4)
+#define NUM_REGS (NUM_GREGS + NUM_FREGS + NUM_SSE_REGS + 1)
-#define FPREG_RAW_SIZE (10)
+#undef MAX_NUM_REGS
+#define MAX_NUM_REGS (16 + 16 + 9 + 1)
-/* Total amount of space needed to store our copies of the machine's
- FPU state. */
-
-#define FPREG_BYTES (FPENV_BYTES + 8 * FPREG_RAW_SIZE)
-
-/* Total amount of space needed to store our copies of the machine's
- register state, the array `registers'. */
-
-#define REGISTER_BYTES (FPSTART_REGNUM * 4 + FPREG_BYTES)
-
-/* Index within `registers' of the first byte of the space for
- register N. */
-
-#define REGISTER_BYTE(N) (((N) < FPDATA_REGNUM) ? \
- (N) * 4 : \
- (((N) - FPDATA_REGNUM) * FPREG_RAW_SIZE) \
- + (FPDATA_REGNUM * 4))
-
-/* Number of bytes of storage in the actual machine representation
- for register N. */
-
-#define REGISTER_RAW_SIZE(N) (((N) < FPDATA_REGNUM) ? 4 : FPREG_RAW_SIZE)
-
-/* Number of bytes of storage in the program's representation
- for register N. */
-
-#define REGISTER_VIRTUAL_SIZE(N) (((N) < FPDATA_REGNUM) ? 4 : FPREG_RAW_SIZE)
-
-/* Largest value REGISTER_RAW_SIZE can have. */
-
-#undef MAX_REGISTER_RAW_SIZE
-#define MAX_REGISTER_RAW_SIZE FPREG_RAW_SIZE
-
-/* Largest value REGISTER_VIRTUAL_SIZE can have. */
-
-#define MAX_REGISTER_VIRTUAL_SIZE FPREG_RAW_SIZE
-
-#if defined(HAVE_LONG_DOUBLE) && defined(HOST_I386)
-/* The host and target are i386 machines and the compiler supports
- long doubles. Long doubles on the host therefore have the same
- layout as a 387 FPU stack register. */
-#define LD_I387
-#endif
-
-#define TARGET_LONG_DOUBLE_BIT 80
-
-#ifdef LD_I387
-extern int i387_extract_floating (PTR addr, int len, long double *dretptr);
-extern int i387_store_floating (PTR addr, int len, long double val);
-
-#define TARGET_EXTRACT_FLOATING i387_extract_floating
-#define TARGET_STORE_FLOATING i387_store_floating
-
-#define TARGET_ANALYZE_FLOATING \
- do \
- { \
- unsigned expon; \
- \
- low = extract_unsigned_integer (valaddr, 4); \
- high = extract_unsigned_integer (valaddr + 4, 4); \
- expon = extract_unsigned_integer (valaddr + 8, 2); \
- \
- nonnegative = ((expon & 0x8000) == 0); \
- is_nan = ((expon & 0x7fff) == 0x7fff) \
- && ((high & 0x80000000) == 0x80000000) \
- && (((high & 0x7fffffff) | low) != 0); \
- } \
- while (0)
-#endif
-
-#ifndef LD_I387
-/* Nonzero if register N requires conversion
- from raw format to virtual format. */
-#define REGISTER_CONVERTIBLE(N) \
- ((N < FPDATA_REGNUM) ? 0 : 1)
-#endif
+#undef REGISTER_BYTES
+#define REGISTER_BYTES \
+ (SIZEOF_GREGS + SIZEOF_FPU_REGS + SIZEOF_FPU_CTRL_REGS + SIZEOF_SSE_REGS + 4)
-#ifdef LD_I387
-#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
-{ \
- long double val = *((long double *)FROM); \
- store_floating ((TO), TYPE_LENGTH (TYPE), val); \
-}
-#else
-/* Convert data from raw format for register REGNUM in buffer FROM
- to virtual format with type TYPE in buffer TO. */
-extern void
-i387_to_double PARAMS ((char *, char *));
-
-#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
-{ \
- double val; \
- i387_to_double ((FROM), (char *)&val); \
- store_floating ((TO), TYPE_LENGTH (TYPE), val); \
-}
-#endif
+#undef REGISTER_NAME
+#define REGISTER_NAME(reg) i386_linux_register_name ((reg))
+extern char *i386_linux_register_name (int reg);
-#ifdef LD_I387
-#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
-{ \
- long double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
- *((long double *)TO) = val; \
-}
-#else
-extern void
-double_to_i387 PARAMS ((char *, char *));
-
-#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
-{ \
- double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
- double_to_i387((char *)&val, (TO)); \
-}
-#endif
+#undef REGISTER_BYTE
+#define REGISTER_BYTE(reg) i386_linux_register_byte ((reg))
+extern int i386_linux_register_byte (int reg);
-/* Return the GDB type object for the "standard" data type
- of data in register N. */
-
-#ifdef LD_I387
-#define REGISTER_VIRTUAL_TYPE(N) \
- ((N < FPDATA_REGNUM) ? builtin_type_int : \
- builtin_type_long_double)
-#else
-#define REGISTER_VIRTUAL_TYPE(N) \
- ((N < FPDATA_REGNUM) ? builtin_type_int : \
- builtin_type_double)
-#endif
+#undef REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(reg) i386_linux_register_raw_size ((reg))
+extern int i386_linux_register_raw_size (int reg);
-/* end of copy */
+/* Linux/ELF uses stabs-in-ELF with the DWARF register numbering
+ scheme by default, so we must redefine STAB_REG_TO_REGNUM. This
+ messes up the floating-point registers for a.out, but there is not
+ much we can do about that. */
+#undef STAB_REG_TO_REGNUM
+#define STAB_REG_TO_REGNUM(reg) i386_dwarf_reg_to_regnum ((reg))
-extern void i387_float_info(void);
-#define FLOAT_INFO { i387_float_info (); }
+/* Use target_specific function to define link map offsets. */
+extern struct link_map_offsets *i386_linux_svr4_fetch_link_map_offsets (void);
+#define SVR4_FETCH_LINK_MAP_OFFSETS() i386_linux_svr4_fetch_link_map_offsets ()
/* The following works around a problem with /usr/include/sys/procfs.h */
#define sys_quotactl 1
-/* Define DO_REGISTERS_INFO() to do machine-specific formatting
- of register dumps. */
-
-#define DO_REGISTERS_INFO(_regnum, fp) i386_do_registers_info(_regnum, fp)
-extern void i386_do_registers_info PARAMS ((int, int));
-
-extern void i387_print_register PARAMS ((char *, int));
-
/* When the i386 Linux kernel calls a signal handler, the return
address points to a bit of code on the stack. These definitions
are used to identify this bit of code as a signal trampoline in
order to support backtracing through calls to signal handlers. */
-#define I386_LINUX_SIGTRAMP
-#define IN_SIGTRAMP(pc, name) ((name) == NULL && i386_linux_sigtramp (pc))
-
-extern int i386_linux_sigtramp PARAMS ((CORE_ADDR));
-
-/* We need our own version of sigtramp_saved_pc to get the saved PC in
- a sigtramp routine. */
-
-#define sigtramp_saved_pc i386_linux_sigtramp_saved_pc
-extern CORE_ADDR i386_linux_sigtramp_saved_pc PARAMS ((struct frame_info *));
-
-/* Signal trampolines don't have a meaningful frame. As in tm-i386.h,
- the frame pointer value we use is actually the frame pointer of the
- calling frame--that is, the frame which was in progress when the
- signal trampoline was entered. gdb mostly treats this frame
- pointer value as a magic cookie. We detect the case of a signal
- trampoline by looking at the SIGNAL_HANDLER_CALLER field, which is
- set based on IN_SIGTRAMP.
-
- When a signal trampoline is invoked from a frameless function, we
- essentially have two frameless functions in a row. In this case,
- we use the same magic cookie for three frames in a row. We detect
- this case by seeing whether the next frame has
- SIGNAL_HANDLER_CALLER set, and, if it does, checking whether the
- current frame is actually frameless. In this case, we need to get
- the PC by looking at the SP register value stored in the signal
- context.
-
- This should work in most cases except in horrible situations where
- a signal occurs just as we enter a function but before the frame
- has been set up. */
-
-#define FRAMELESS_SIGNAL(FRAME) \
- ((FRAME)->next != NULL \
- && (FRAME)->next->signal_handler_caller \
- && frameless_look_for_prologue (FRAME))
+#define IN_SIGTRAMP(pc, name) i386_linux_in_sigtramp (pc, name)
+extern int i386_linux_in_sigtramp (CORE_ADDR, char *);
#undef FRAME_CHAIN
-#define FRAME_CHAIN(FRAME) \
- ((FRAME)->signal_handler_caller \
- ? (FRAME)->frame \
- : (FRAMELESS_SIGNAL (FRAME) \
- ? (FRAME)->frame \
- : (!inside_entry_file ((FRAME)->pc) \
- ? read_memory_integer ((FRAME)->frame, 4) \
- : 0)))
+#define FRAME_CHAIN(frame) i386_linux_frame_chain (frame)
+extern CORE_ADDR i386_linux_frame_chain (struct frame_info *frame);
#undef FRAME_SAVED_PC
-#define FRAME_SAVED_PC(FRAME) \
- ((FRAME)->signal_handler_caller \
- ? sigtramp_saved_pc (FRAME) \
- : (FRAMELESS_SIGNAL (FRAME) \
- ? read_memory_integer (i386_linux_sigtramp_saved_sp ((FRAME)->next), 4) \
- : read_memory_integer ((FRAME)->frame + 4, 4)))
-
-extern CORE_ADDR i386_linux_sigtramp_saved_sp PARAMS ((struct frame_info *));
-
-/* Some versions of Linux have real-time signal support in the C library, and
- some don't. We have to include this file to find out. */
-#include <signal.h>
-
-#ifdef __SIGRTMIN
-#define REALTIME_LO __SIGRTMIN
-#define REALTIME_HI (__SIGRTMAX + 1)
-#else
-#define REALTIME_LO 32
-#define REALTIME_HI 64
-#endif
+#define FRAME_SAVED_PC(frame) i386_linux_frame_saved_pc (frame)
+extern CORE_ADDR i386_linux_frame_saved_pc (struct frame_info *frame);
+
+#undef SAVED_PC_AFTER_CALL
+#define SAVED_PC_AFTER_CALL(frame) i386_linux_saved_pc_after_call (frame)
+extern CORE_ADDR i386_linux_saved_pc_after_call (struct frame_info *);
+
+#define TARGET_WRITE_PC(pc, ptid) i386_linux_write_pc (pc, ptid)
+extern void i386_linux_write_pc (CORE_ADDR pc, ptid_t ptid);
/* When we call a function in a shared library, and the PLT sends us
into the dynamic linker to find the function's real address, we
/* N_FUN symbols in shared libaries have 0 for their values and need
to be relocated. */
#define SOFUN_ADDRESS_MAYBE_MISSING
+\f
-#endif /* #ifndef TM_LINUX_H */
+/* Support for longjmp. */
+
+/* Details about jmp_buf. It's supposed to be an array of integers. */
+
+#define JB_ELEMENT_SIZE 4 /* Size of elements in jmp_buf. */
+#define JB_PC 5 /* Array index of saved PC. */
+/* Figure out where the longjmp will land. Slurp the args out of the
+ stack. We expect the first arg to be a pointer to the jmp_buf
+ structure from which we extract the pc (JB_PC) that we will land
+ at. The pc is copied into ADDR. This routine returns true on
+ success. */
+
+#define GET_LONGJMP_TARGET(addr) get_longjmp_target (addr)
+extern int get_longjmp_target (CORE_ADDR *addr);
+
+#endif /* #ifndef TM_LINUX_H */