aboutsummaryrefslogtreecommitdiff
path: root/gdb/i386-tdep.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2002-06-14 19:42:20 +0000
committerMark Kettenis <kettenis@gnu.org>2002-06-14 19:42:20 +0000
commit8201327c4086d86bf1c16db4fd34bc55c2da53ef (patch)
treebdc313d28b682690e0b51a9017d48a88028e004d /gdb/i386-tdep.c
parente7e811813229598b44f7851121feddcffa911faa (diff)
downloadgdb-8201327c4086d86bf1c16db4fd34bc55c2da53ef.zip
gdb-8201327c4086d86bf1c16db4fd34bc55c2da53ef.tar.gz
gdb-8201327c4086d86bf1c16db4fd34bc55c2da53ef.tar.bz2
* config/i386/i386sol2.mt (TDEPFILES): Add i386-sol2-tdep.o and
i386bsd-tdep.o. Remove solib.o, solib-svr4.o and solib-legacy.o. Move these to ... * config/i386/i386sol2.mh: ... here. * config/i386/tm-i386sol2.h (STAB_REG_TO_REGNUM): Remove define. (sigtramp_saved_pc, I386V4_SIGTRAMP_SAVED_PC): Don't #undef. (SIGCONTEXT_PC_OFFSET): Remove define. (IN_SIGTRAMP): Remove define. * i386-sol2-tdep.c: New file. * config/i386/i386nw.mt (TM_FILE): Change to tm-i386.h. * config/i386/tm-i386nw.h: Removed. * config/i386/tm-fbsd.h (STAB_REG_TO_REGNUM, USE_STRUCT_CONVENTION): Remove defines. (JB_ELEMENT_SIZE, JB_PC, GET_LONGJMP_TARGET): Remove defines. (get_longjmp_target): Remove prototype. (IN_SIGTRAMP): Remove define. (i386bsd_in_sigtramp): Remove prototype. (i386bsd_sigtramp_start, i386bsd_sigtramp_end): Turn into a function. Update comment accordingly (SIGTRAMP_START, SIGTRAMP): Adjust definition accordingly. (FRAME_SAVED_PC): Remove define. (i386bsd_frame_saved_pc): Remove prototype. * config/i386/tm-nbsd.h (JB_ELEMENT_SIZE, JB_PC, GET_LONGJMP_TARGET): Remove defines. (get_longjmp_target): Remove prototype. (IN_SIGTRAMP): Remove define. (i386bsd_in_sigtramp): Remove prototype. (i386bsd_sigtramp_start, i386bsd_sigtramp_end): Turn into a function. Update comment accordingly (SIGTRAMP_START, SIGTRAMP): Adjust definition accordingly. (FRAME_SAVED_PC): Remove define. (i386bsd_frame_saved_pc): Remove prototype. * config/i386/tm-nbsdaout.h (i386nbsd_aout_use_struct_convention): Remove prototype. (USE_STRUCT_CONVENTION): Remove prototype. * i386bsd-nat.c (i386bsd_sigcontext_pc_offset): Remove declaration. (_initialize_i386bsd_nat): Revise logic to determine some constants at compile time when compiling a native GDB. Warn if things don't match up with what we expect. * i386bsd-tdep.c (i386bsd_sigtramp_start, i386bsd_sigtramp_end): Remove variables. (i386bsd_in_sigtramp): Rename tp i386bsd_pc_in_sigtramp. Rewrite to use date stored in `struct gdbarch_tdep'. (i386bsd_sigcontext_offset): Remove varaible. (i386bsd_sigtramp_saved_pc): Make public. Rewrite to use data stored in `struct gdbarch_tdep'. (i386bsd_frame_saved_pc): Make static. (i386bsd_sigtramp_start, i386bsd_sigtramp_end): New functions. (i386bsd_sc_pc_offset, i386nbsd_sc_pc_offset, i386fbsd_sigtramp_start, i386fbsd_sigtramp_end, i386fbsd4_sc_pc_offset): New variables. (i386bsd_init_abi, i386nbsd_init_abi, i386nbsdelf_init_abi, i386fbsdaout_init_abi, i386fbsd_init_abi, i386fbsd4_init_abi): New functions. (i386bsd_aout_osabi_sniffer, _initialize_i386bsd_tdep): New functions. * i386fbsd-nat.c (_initialize_i386fbsd_nat): Fix type in comment. Modify the value of i386fbsd_sigtramp_start and i386fbsd_sigtramp_end instead of i386bsd_sigtramp_start and i386fbsd_sigtramp_end. * i386nbsd-tdep.c: (i386nbsd_aout_use_struct_convention): Remove function. * config/i386/tm-linux.h (I386_LINUX_ORIG_EAX_REGNUM): Move define to i386-linux-tdep.h. (NUM_REGS, MAX_NUM_REGS, REGISTER_BYTES, REGISTER_NAME, REGISTER_BYTE, REGISTER_RAW_SIZE, STAB_REG_TO_REGNUM): Remove defines. (i386_linux_register_name, i386_linux_register_byte, i386_linux_register_raw_size): Remove prototypes. (i386_linux_svr4_fetch_link_map_offsets): Remove prototype. (SVR4_FETCH_LINK_MAP_OFFSETS): Remove define. (IN_SIGTRAMP, FRAME_CHAIN, FRAME_SAVED_PC, SAVED_PC_AFTER_CALL, TARGET_WRITE_PC): Remove defines. (i386_linux_in_sigtramp, i386_linux_frame_chain, i386_linux_frame_saved_pc, i386_linux_saved_pc_after_call, i386_linux_write_pc): Remove prototypes. (JB_ELEMENT_SIZE, JB_PC, GET_LONGJMP_TARGET): Remove defines. (get_longjmp_target): Remove prototype. * i386-linux-tdep.h: New file. * i386-linux-nat.c: Include "i386-linux-tdep.h". * i386-linux-tdep.c: Include "i386-tdep.h" and "i386-linux-tdep.h". (i386_linux_register_name, i386_linux_register_byte, i386_linux_register_raw_size, i386_linux_in_sigtramp, i386_linux_write_pc, i386_linux_svr4_fetch_link_map_offsets): Make static. (i386_linux_init_abi): New function. (_initialize_i386_linux_tdep): New function. * config/i386/tm-i386.h (SAVED_PC_AFTER_CALL): Remove define. (i386_saved_pc_after_call): Remove prototype. (MAX_NUM_REGS): Increase to deal with Linux's orig_eax "register". (REGISTER_NAME, STAB_REG_TO_REGNUM, SDB_REG_TO_REGNUM, DWARF_REG_TO_REGNUM, DWARF2_REG_TO_REGNUM): Remove defines. (i386_register_name, i386_stab_reg_to_regnum, i386_dwarf_reg_to_regnum): Remove prototypes. (SIZEOF_GREGS, SIZEOF_FPU_REGS, SIZEOF_FPU_CTL_REGS, SIZEOF_SSE_REGS): Remove defines. (REGISTER_BYTES): Remove define. (REGISTER_BYTE, REGISTER_RAW_SIZE): Remove defines. (i386_register_byte, i386_register_raw_size): Remove prototypes. (FRAME_CHAIN, FRAME_SAVED_PC): Remove defines. (i386_frame_chain, i386_frame_saved_pc): Remove prototypes. * config/i386/tm-i386v4.h (FRAME_CHAIN_VALID): Remove define. (JB_ELEMENT_SIZE, JB_PC, JB_EBX, JB_ESI, JB_EDI, JB_EBP, JB_ESP, JB_EDX, GET_LONGJMP_TARGET): Remove defines. (get_longjmp_target): Remove prototype. (I386V4_SIGTRAMP_SAVED_PC, IN_SIGTRAMP): Remove defines. (sigtramp_saved_pc): Remove define. (i386v4_sigtramp_saved_pc): Remove prototype. * config/i386/tm-go32.h (FRAME_CHAIN, FRAMELESS_FUNCTION_INVOCATION, FRAME_SAVED_PC): Remove defines. (i386go32_frame_saved_pc): Remove prototype. (JB_ELEMENT_SIZE, JB_PC, GET_LONGJMP_TARGET): Remove defines. (get_longjmp_target): Remove prototype. * i386-tdep.h: Include "osabi.h". (enum i386_abi): Removed. (enum struct_return): New enum. (struct gdbarch_tdep): Remove abi member, add osabi, jb_pc_offset, struct_return, sigtramp_saved_pc, sigtramp_start, sigtramp_end and sc_pc_offset members. (i386_gdbarch_register_os_abi): Remove prototype. (I386_NUM_GREGS, I386_NUM_FREGS, I386_NUM_XREGS, I386_SSE_NUM_REGS): New defines. (I386_SIZEOF_GREGS, I386_SIZEOF_FREGS, I386_SIZEOF_XREGS, I386_SSE_SIZEOF_REGS): New defines. (i386_register_name, i386_register_byte, i386_register_raw_size): New prototypes. (i386_elf_init_abi, i386_svr4_init_abi): New prototypes. (i386bsd_sigtramp_saved_pc): New prototype. * i386-tdep.c: Don't include "elf-bfd.h". (i386_stab_reg_to_regnum, i386_dwarf_reg_to_regnum, i386_frame_chain, i386_saved_pc_after_call): Make static. (i386_frame_saved_pc): Rewrite to call architecture dependent function to deal with signal handlers. Make static. (i386go32_frame_saved_pc): Removed. [GET_LONGJMP_TARGET] (JB_PC, JB_ELEMENT_SIZE, get_longjmp_target): Removed. (i386_get_longjmp_target): New function. (default_struct_convention, pcc_struct_convention, reg_struct_convention, valid_conventions, struct_convention): New variables. (i386_use_struct_convention): New function. (i386v4_sigtramp_saved_pc): Renamed to i386_svr4_sigtramp_saved_pc. Made static. Moved. (i386_pc_in_sigtramp): New function. (i386_abi_names): Removed. (ABI_TAG_OS_GNU_LINUX, ABI_TAG_OS_GNU_HURD, ABI_TAG_OS_GNU_SOLARIS, ABI_TAG_OS_FREEBSD, ABI_TAG_OS_NETBSD): Removed. (process_note_sections, i386_elf_abi_from_note, i386_elf_abi, i386_gdbarch_register_os_abi): Removed. (struct i386_abi_handler): Removed. (i386_abi_handler_list): Removed. (i386_svr4_pc_in_sigtramp, i386_go32_pc_in_sigtramp): New functions. (i386_elf_init_abi, i386_svr4_init_abi, i386_go32_init_abi, i386_nw_init_abi): New functions. (i386_gdbarch_init): Rewritten to use generic OS ABI framework. Use set_gdbarch_xxx() calls instead of relying on macros for a number of calls. (i386_coff_osabi_sniffer, i386_nlm_osabi_sniffer): New functions. (_initialize_i386_tdep): Add new 'struct-convcention' command. Register the various architecture variants defined in this file.
Diffstat (limited to 'gdb/i386-tdep.c')
-rw-r--r--gdb/i386-tdep.c529
1 files changed, 235 insertions, 294 deletions
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 54746ee..ab52ba4 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -36,8 +36,6 @@
#include "value.h"
#include "gdb_assert.h"
-#include "elf-bfd.h"
-
#include "i386-tdep.h"
/* Names of the registers. The first 10 registers match the register
@@ -119,7 +117,7 @@ i386_register_virtual_size (int reg)
/* Convert stabs register number REG to the appropriate register
number used by GDB. */
-int
+static int
i386_stab_reg_to_regnum (int reg)
{
/* This implements what GCC calls the "default" register map. */
@@ -150,10 +148,10 @@ i386_stab_reg_to_regnum (int reg)
return NUM_REGS + NUM_PSEUDO_REGS;
}
-/* Convert Dwarf register number REG to the appropriate register
+/* Convert DWARF register number REG to the appropriate register
number used by GDB. */
-int
+static int
i386_dwarf_reg_to_regnum (int reg)
{
/* The DWARF register numbering includes %eip and %eflags, and
@@ -466,7 +464,7 @@ i386_get_frame_setup (CORE_ADDR pc)
frame's nominal address is the address of a 4-byte word containing
the calling frame's address. */
-CORE_ADDR
+static CORE_ADDR
i386_frame_chain (struct frame_info *frame)
{
if (frame->signal_handler_caller)
@@ -493,30 +491,24 @@ i386_frameless_function_invocation (struct frame_info *frame)
/* Return the saved program counter for FRAME. */
-CORE_ADDR
+static CORE_ADDR
i386_frame_saved_pc (struct frame_info *frame)
{
- /* FIXME: kettenis/2001-05-09: Conditionalizing the next bit of code
- on SIGCONTEXT_PC_OFFSET and I386V4_SIGTRAMP_SAVED_PC should be
- considered a temporary hack. I plan to come up with something
- better when we go multi-arch. */
-#if defined (SIGCONTEXT_PC_OFFSET) || defined (I386V4_SIGTRAMP_SAVED_PC)
if (frame->signal_handler_caller)
- return sigtramp_saved_pc (frame);
-#endif
+ {
+ CORE_ADDR (*sigtramp_saved_pc) (struct frame_info *);
+ sigtramp_saved_pc = gdbarch_tdep (current_gdbarch)->sigtramp_saved_pc;
- return read_memory_unsigned_integer (frame->frame + 4, 4);
-}
+ gdb_assert (sigtramp_saved_pc != NULL);
+ return sigtramp_saved_pc (frame);
+ }
-CORE_ADDR
-i386go32_frame_saved_pc (struct frame_info *frame)
-{
- return read_memory_integer (frame->frame + 4, 4);
+ return read_memory_unsigned_integer (frame->frame + 4, 4);
}
/* Immediately after a function call, return the saved pc. */
-CORE_ADDR
+static CORE_ADDR
i386_saved_pc_after_call (struct frame_info *frame)
{
return read_memory_unsigned_integer (read_register (SP_REGNUM), 4);
@@ -834,49 +826,35 @@ i386_pop_frame (void)
}
-#ifdef GET_LONGJMP_TARGET
-
-/* FIXME: Multi-arching does not set JB_PC and JB_ELEMENT_SIZE yet.
- Fill in with dummy value to enable compilation. */
-#ifndef JB_PC
-#define JB_PC 0
-#endif /* JB_PC */
-
-#ifndef JB_ELEMENT_SIZE
-#define JB_ELEMENT_SIZE 4
-#endif /* JB_ELEMENT_SIZE */
-
/* 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 PC. This routine returns true on
+ structure from which we extract the address that we will land at.
+ This address is copied into PC. This routine returns true on
success. */
-int
-get_longjmp_target (CORE_ADDR *pc)
+static int
+i386_get_longjmp_target (CORE_ADDR *pc)
{
- char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+ char buf[4];
CORE_ADDR sp, jb_addr;
+ int jb_pc_offset = gdbarch_tdep (current_gdbarch)->jb_pc_offset;
- sp = read_register (SP_REGNUM);
-
- if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack. */
- buf,
- TARGET_PTR_BIT / TARGET_CHAR_BIT))
+ /* If JB_PC_OFFSET is -1, we have no way to find out where the
+ longjmp will land. */
+ if (jb_pc_offset == -1)
return 0;
- jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
-
- if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
- TARGET_PTR_BIT / TARGET_CHAR_BIT))
+ sp = read_register (SP_REGNUM);
+ if (target_read_memory (sp + 4, buf, 4))
return 0;
- *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+ jb_addr = extract_address (buf, 4);
+ if (target_read_memory (jb_addr + jb_pc_offset, buf, 4))
+ return 0;
+ *pc = extract_address (buf, 4);
return 1;
}
-
-#endif /* GET_LONGJMP_TARGET */
CORE_ADDR
@@ -1044,6 +1022,37 @@ i386_extract_struct_value_address (char *regbuf)
}
+/* This is the variable that is set with "set struct-convention", and
+ its legitimate values. */
+static const char default_struct_convention[] = "default";
+static const char pcc_struct_convention[] = "pcc";
+static const char reg_struct_convention[] = "reg";
+static const char *valid_conventions[] =
+{
+ default_struct_convention,
+ pcc_struct_convention,
+ reg_struct_convention,
+ NULL
+};
+static const char *struct_convention = default_struct_convention;
+
+static int
+i386_use_struct_convention (int gcc_p, struct type *type)
+{
+ enum struct_return struct_return;
+
+ if (struct_convention == default_struct_convention)
+ struct_return = gdbarch_tdep (current_gdbarch)->struct_return;
+ else if (struct_convention == pcc_struct_convention)
+ struct_return = pcc_struct_return;
+ else
+ struct_return = reg_struct_return;
+
+ return generic_use_struct_convention (struct_return == reg_struct_return,
+ type);
+}
+
+
/* Return the GDB type object for the "standard" data type of data in
register REGNUM. Perhaps %esi and %edi should go here, but
potentially they could be used for things other than address. */
@@ -1122,34 +1131,6 @@ i386_register_convert_to_raw (struct type *type, int regnum,
}
-#ifdef I386V4_SIGTRAMP_SAVED_PC
-/* Get saved user PC for sigtramp from the pushed ucontext on the
- stack for all three variants of SVR4 sigtramps. */
-
-CORE_ADDR
-i386v4_sigtramp_saved_pc (struct frame_info *frame)
-{
- CORE_ADDR saved_pc_offset = 4;
- char *name = NULL;
-
- find_pc_partial_function (frame->pc, &name, NULL, NULL);
- if (name)
- {
- if (STREQ (name, "_sigreturn"))
- saved_pc_offset = 132 + 14 * 4;
- else if (STREQ (name, "_sigacthandler"))
- saved_pc_offset = 80 + 14 * 4;
- else if (STREQ (name, "sigvechandler"))
- saved_pc_offset = 120 + 14 * 4;
- }
-
- if (frame->next)
- return read_memory_integer (frame->next->frame + saved_pc_offset, 4);
- return read_memory_integer (read_register (SP_REGNUM) + saved_pc_offset, 4);
-}
-#endif /* I386V4_SIGTRAMP_SAVED_PC */
-
-
#ifdef STATIC_TRANSFORM_NAME
/* SunPRO encodes the static variables. This is not related to C++
mangling, it is done for C too. */
@@ -1199,6 +1180,16 @@ skip_trampoline_code (CORE_ADDR pc, char *name)
}
+/* Return non-zero if PC and NAME show that we are in a signal
+ trampoline. */
+
+static int
+i386_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+ return (name && strcmp ("_sigtramp", name) == 0);
+}
+
+
/* We have two flavours of disassembly. The machinery on this page
deals with switching between those. */
@@ -1213,229 +1204,132 @@ gdb_print_insn_i386 (bfd_vma memaddr, disassemble_info *info)
or intel_flavor. */
internal_error (__FILE__, __LINE__, "failed internal consistency check");
}
-
-/* This table matches the indices assigned to enum i386_abi. Keep
- them in sync. */
-static const char * const i386_abi_names[] =
-{
- "<unknown>",
- "SVR4",
- "NetBSD",
- "GNU/Linux",
- "GNU/Hurd",
- "Solaris",
- "FreeBSD",
- NULL
-};
+/* There are a few i386 architecture variants that differ only
+ slightly from the generic i386 target. For now, we don't give them
+ their own source file, but include them here. As a consequence,
+ they'll always be included. */
-#define ABI_TAG_OS_GNU_LINUX I386_ABI_LINUX
-#define ABI_TAG_OS_GNU_HURD I386_ABI_HURD
-#define ABI_TAG_OS_GNU_SOLARIS I386_ABI_INVALID
-#define ABI_TAG_OS_FREEBSD I386_ABI_FREEBSD
-#define ABI_TAG_OS_NETBSD I386_ABI_NETBSD
+/* System V Release 4 (SVR4). */
-static void
-process_note_sections (bfd *abfd, asection *sect, void *obj)
+static int
+i386_svr4_pc_in_sigtramp (CORE_ADDR pc, char *name)
{
- int *abi = obj;
- const char *name;
- unsigned int sectsize;
+ return (name && (strcmp ("_sigreturn", name) == 0
+ || strcmp ("_sigacthandler", name) == 0
+ || strcmp ("sigvechandler", name) == 0));
+}
- name = bfd_get_section_name (abfd, sect);
- sectsize = bfd_section_size (abfd, sect);
+/* Get saved user PC for sigtramp from the pushed ucontext on the
+ stack for all three variants of SVR4 sigtramps. */
- if (strcmp (name, ".note.ABI-tag") == 0 && sectsize > 0)
+CORE_ADDR
+i386_svr4_sigtramp_saved_pc (struct frame_info *frame)
+{
+ CORE_ADDR saved_pc_offset = 4;
+ char *name = NULL;
+
+ find_pc_partial_function (frame->pc, &name, NULL, NULL);
+ if (name)
{
- unsigned int name_length, data_length, note_type;
- char *note;
+ if (strcmp (name, "_sigreturn") == 0)
+ saved_pc_offset = 132 + 14 * 4;
+ else if (strcmp (name, "_sigacthandler") == 0)
+ saved_pc_offset = 80 + 14 * 4;
+ else if (strcmp (name, "sigvechandler") == 0)
+ saved_pc_offset = 120 + 14 * 4;
+ }
- /* If the section is larger than this, it's probably not what we
- are looking for. */
- if (sectsize > 128)
- sectsize = 128;
+ if (frame->next)
+ return read_memory_integer (frame->next->frame + saved_pc_offset, 4);
+ return read_memory_integer (read_register (SP_REGNUM) + saved_pc_offset, 4);
+}
+
- note = alloca (sectsize);
+/* DJGPP. */
- bfd_get_section_contents (abfd, sect, note,
- (file_ptr) 0, (bfd_size_type) sectsize);
+static int
+i386_go32_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+ /* DJGPP doesn't have any special frames for signal handlers. */
+ return 0;
+}
+
- name_length = bfd_h_get_32 (abfd, note);
- data_length = bfd_h_get_32 (abfd, note + 4);
- note_type = bfd_h_get_32 (abfd, note + 8);
+/* Generic ELF. */
- if (name_length == 4 && data_length == 16
- && note_type == NT_GNU_ABI_TAG
- && strcmp (note + 12, "GNU") == 0)
- {
- int abi_tag_os = bfd_h_get_32 (abfd, note + 16);
+void
+i386_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ /* We typically use stabs-in-ELF with the DWARF register numbering. */
+ set_gdbarch_stab_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
+}
- /* The case numbers are from abi-tags in glibc. */
- switch (abi_tag_os)
- {
- case GNU_ABI_TAG_LINUX:
- *abi = ABI_TAG_OS_GNU_LINUX;
- break;
-
- case GNU_ABI_TAG_HURD:
- *abi = ABI_TAG_OS_GNU_HURD;
- break;
-
- case GNU_ABI_TAG_SOLARIS:
- *abi = ABI_TAG_OS_GNU_SOLARIS;
- break;
-
- default:
- internal_error
- (__FILE__, __LINE__,
- "process_note_abi_sections: unknown ABI OS tag %d",
- abi_tag_os);
- break;
- }
- }
- else if (name_length == 8 && data_length == 4
- && note_type == NT_FREEBSD_ABI_TAG
- && strcmp (note + 12, "FreeBSD") == 0)
- *abi = ABI_TAG_OS_FREEBSD;
- }
- /* NetBSD uses a similar trick. */
- else if (strcmp (name, ".note.netbsd.ident") == 0 && sectsize > 0)
- {
- unsigned int name_length, desc_length, note_type;
- char *note;
+/* System V Release 4 (SVR4). */
- /* If the section is larger than this, it's probably not what we are
- looking for. */
- if (sectsize > 128)
- sectsize = 128;
+void
+i386_svr4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- note = alloca (sectsize);
+ /* System V Release 4 uses ELF. */
+ i386_elf_init_abi (info, gdbarch);
- bfd_get_section_contents (abfd, sect, note,
- (file_ptr) 0, (bfd_size_type) sectsize);
+ /* FIXME: kettenis/20020511: Why do we override this function here? */
+ set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
- name_length = bfd_h_get_32 (abfd, note);
- desc_length = bfd_h_get_32 (abfd, note + 4);
- note_type = bfd_h_get_32 (abfd, note + 8);
+ set_gdbarch_pc_in_sigtramp (gdbarch, i386_svr4_pc_in_sigtramp);
+ tdep->sigtramp_saved_pc = i386_svr4_sigtramp_saved_pc;
- if (name_length == 7 && desc_length == 4
- && note_type == NT_NETBSD_IDENT
- && strcmp (note + 12, "NetBSD") == 0)
- *abi = ABI_TAG_OS_NETBSD;
- }
+ tdep->jb_pc_offset = 20;
}
-static int
-i386_elf_abi_from_note (bfd *abfd)
-{
- enum i386_abi abi = I386_ABI_UNKNOWN;
-
- bfd_map_over_sections (abfd, process_note_sections, &abi);
-
- return abi;
-}
+/* DJGPP. */
-static enum i386_abi
-i386_elf_abi (bfd *abfd)
+void
+i386_go32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
- int elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
-
- /* The fact that the EI_OSABI byte is set to ELFOSABI_NONE doesn't
- necessarily mean that this is a System V ELF binary. To further
- distinguish between binaries for differens operating systems,
- check for vendor-specific note elements. */
- if (elfosabi == ELFOSABI_NONE)
- {
- enum i386_abi abi = i386_elf_abi_from_note (abfd);
-
- if (abi != I386_ABI_UNKNOWN)
- return abi;
-
- /* FreeBSD folks are naughty; they stored the string "FreeBSD"
- in the padding of the e_ident field of the ELF header. */
- if (strcmp (&elf_elfheader (abfd)->e_ident[8], "FreeBSD") == 0)
- return I386_ABI_FREEBSD;
- }
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- switch (elfosabi)
- {
- case ELFOSABI_NONE:
- return I386_ABI_SVR4;
- case ELFOSABI_FREEBSD:
- return I386_ABI_FREEBSD;
- }
+ set_gdbarch_pc_in_sigtramp (gdbarch, i386_go32_pc_in_sigtramp);
- return I386_ABI_UNKNOWN;
+ tdep->jb_pc_offset = 36;
}
-struct i386_abi_handler
-{
- struct i386_abi_handler *next;
- enum i386_abi abi;
- void (*init_abi)(struct gdbarch_info, struct gdbarch *);
-};
-
-struct i386_abi_handler *i386_abi_handler_list = NULL;
+/* NetWare. */
void
-i386_gdbarch_register_os_abi (enum i386_abi abi,
- void (*init_abi)(struct gdbarch_info,
- struct gdbarch *))
+i386_nw_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
- struct i386_abi_handler **handler_p;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- for (handler_p = &i386_abi_handler_list; *handler_p != NULL;
- handler_p = &(*handler_p)->next)
- {
- if ((*handler_p)->abi == abi)
- {
- internal_error
- (__FILE__, __LINE__,
- "i386_gdbarch_register_abi: A handler for this ABI variant "
- "(%d) has already been registered", (int) abi);
- /* If user wants to continue, override previous definition. */
- (*handler_p)->init_abi = init_abi;
- return;
- }
- }
- (*handler_p)
- = (struct i386_abi_handler *) xmalloc (sizeof (struct i386_abi_handler));
- (*handler_p)->next = NULL;
- (*handler_p)->abi = abi;
- (*handler_p)->init_abi = init_abi;
+ /* FIXME: kettenis/20020511: Why do we override this function here? */
+ set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
+
+ tdep->jb_pc_offset = 24;
}
+
struct gdbarch *
i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
struct gdbarch_tdep *tdep;
struct gdbarch *gdbarch;
- enum i386_abi abi = I386_ABI_UNKNOWN;
- struct i386_abi_handler *abi_handler;
+ enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
+ /* Try to determine the OS ABI of the object we're loading. */
if (info.abfd != NULL)
- {
- switch (bfd_get_flavour (info.abfd))
- {
- case bfd_target_elf_flavour:
- abi= i386_elf_abi (info.abfd);
- break;
-
- default:
- /* Not sure what to do here, leave the ABI as unknown. */
- break;
- }
- }
+ osabi = gdbarch_lookup_osabi (info.abfd);
/* Find a candidate among extant architectures. */
for (arches = gdbarch_list_lookup_by_info (arches, &info);
arches != NULL;
arches = gdbarch_list_lookup_by_info (arches->next, &info))
{
- /* Make sure the ABI selection matches. */
+ /* Make sure the OS ABI selection matches. */
tdep = gdbarch_tdep (arches->gdbarch);
- if (tdep && tdep->abi == abi)
+ if (tdep && tdep->osabi == osabi)
return arches->gdbarch;
}
@@ -1443,11 +1337,21 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep = XMALLOC (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
- tdep->abi = abi;
+ tdep->osabi = osabi;
+
+ /* The i386 default settings don't include the SSE registers.
+ FIXME: kettenis/20020509: They do include the FPU registers for
+ now, which is not quite right. */
+ tdep->num_xmm_regs = 0;
- /* FIXME: kettenis/2001-11-24: Although not all IA-32 processors
- have the SSE registers, it's easier to set the default to 8. */
- tdep->num_xmm_regs = 8;
+ tdep->jb_pc_offset = -1;
+ tdep->struct_return = pcc_struct_return;
+ tdep->sigtramp_saved_pc = NULL;
+ tdep->sigtramp_start = 0;
+ tdep->sigtramp_end = 0;
+ tdep->sc_pc_offset = -1;
+
+ set_gdbarch_get_longjmp_target (gdbarch, i386_get_longjmp_target);
set_gdbarch_use_generic_dummy_frames (gdbarch, 0);
@@ -1463,50 +1367,61 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
- /* NOTE: tm-i386nw.h and tm-i386v4.h override this. */
+ set_gdbarch_use_struct_convention (gdbarch, i386_use_struct_convention);
+
+ /* The following redefines make backtracing through sigtramp work.
+ They manufacture a fake sigtramp frame and obtain the saved pc in
+ sigtramp from the sigcontext structure which is pushed by the
+ kernel on the user stack, along with a pointer to it. */
+
+ set_gdbarch_frame_chain (gdbarch, i386_frame_chain);
set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
+ set_gdbarch_frame_saved_pc (gdbarch, i386_frame_saved_pc);
+ set_gdbarch_saved_pc_after_call (gdbarch, i386_saved_pc_after_call);
+ set_gdbarch_pc_in_sigtramp (gdbarch, i386_pc_in_sigtramp);
+
+ /* NOTE: tm-i386aix.h, tm-i386bsd.h, tm-i386os9k.h, tm-ptx.h,
+ tm-symmetry.h currently override this. Sigh. */
+ set_gdbarch_num_regs (gdbarch, I386_NUM_GREGS + I386_NUM_FREGS);
+
+ /* Use the "default" register numbering scheme for stabs and COFF. */
+ set_gdbarch_stab_reg_to_regnum (gdbarch, i386_stab_reg_to_regnum);
+ set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_stab_reg_to_regnum);
+
+ /* Use the DWARF register numbering scheme for DWARF and DWARF 2. */
+ set_gdbarch_dwarf_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
+ set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
- /* NOTE: tm-i386aix.h, tm-i386bsd.h, tm-i386os9k.h, tm-linux.h,
- tm-ptx.h, tm-symmetry.h currently override this. Sigh. */
- set_gdbarch_num_regs (gdbarch, NUM_GREGS + NUM_FREGS + NUM_SSE_REGS);
+ /* We don't define ECOFF_REG_TO_REGNUM, since ECOFF doesn't seem to
+ be in use on any of the supported i386 targets. */
+
+ set_gdbarch_register_bytes (gdbarch, I386_SIZEOF_GREGS + I386_SIZEOF_FREGS);
+ set_gdbarch_register_name (gdbarch, i386_register_name);
+ set_gdbarch_register_byte (gdbarch, i386_register_byte);
+ set_gdbarch_register_raw_size (gdbarch, i386_register_raw_size);
/* Hook in ABI-specific overrides, if they have been registered. */
- if (abi == I386_ABI_UNKNOWN)
- {
- /* Don't complain about not knowing the ABI variant if we don't
- have an inferior. */
- if (info.abfd)
- fprintf_filtered
- (gdb_stderr, "GDB doesn't recognize the ABI of the inferior. "
- "Attempting to continue with the default i386 settings");
- }
- else
- {
- for (abi_handler = i386_abi_handler_list; abi_handler != NULL;
- abi_handler = abi_handler->next)
- if (abi_handler->abi == abi)
- break;
+ gdbarch_init_osabi (info, gdbarch, osabi);
- if (abi_handler)
- abi_handler->init_abi (info, gdbarch);
- else
- {
- /* We assume that if GDB_MULTI_ARCH is less than
- GDB_MULTI_ARCH_TM that an ABI variant can be supported by
- overriding definitions in this file. */
- if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL)
- fprintf_filtered
- (gdb_stderr,
- "A handler for the ABI variant \"%s\" is not built into this "
- "configuration of GDB. "
- "Attempting to continue with the default i386 settings",
- i386_abi_names[abi]);
- }
- }
-
return gdbarch;
}
+static enum gdb_osabi
+i386_coff_osabi_sniffer (bfd *abfd)
+{
+ if (strcmp (bfd_get_target (abfd), "coff-go32-exe") == 0)
+ return GDB_OSABI_GO32;
+
+ return GDB_OSABI_UNKNOWN;
+}
+
+static enum gdb_osabi
+i386_nlm_osabi_sniffer (bfd *abfd)
+{
+ return GDB_OSABI_NETWARE;
+}
+
+
/* Provide a prototype to silence -Wmissing-prototypes. */
void _initialize_i386_tdep (void);
@@ -1544,4 +1459,30 @@ and the default value is \"att\".",
&setlist);
add_show_from_set (new_cmd, &showlist);
}
+
+ /* Add the variable that controls the convention for returning
+ structs. */
+ {
+ struct cmd_list_element *new_cmd;
+
+ new_cmd = add_set_enum_cmd ("struct-convention", no_class,
+ valid_conventions,
+ &struct_convention, "\
+Set the convention for returning small structs, valid values \
+are \"default\", \"pcc\" and \"reg\", and the default value is \"default\".",
+ &setlist);
+ add_show_from_set (new_cmd, &showlist);
+ }
+
+ gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
+ i386_coff_osabi_sniffer);
+ gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_nlm_flavour,
+ i386_nlm_osabi_sniffer);
+
+ gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_SVR4,
+ i386_svr4_init_abi);
+ gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_GO32,
+ i386_go32_init_abi);
+ gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_NETWARE,
+ i386_nw_init_abi);
}