diff options
author | Mark Kettenis <kettenis@gnu.org> | 2002-06-14 19:42:20 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2002-06-14 19:42:20 +0000 |
commit | 8201327c4086d86bf1c16db4fd34bc55c2da53ef (patch) | |
tree | bdc313d28b682690e0b51a9017d48a88028e004d /gdb/i386-tdep.c | |
parent | e7e811813229598b44f7851121feddcffa911faa (diff) | |
download | gdb-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.c | 529 |
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); } |