* 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.
This commit is contained in:
Mark Kettenis
2002-06-14 19:42:20 +00:00
parent e7e8118132
commit 8201327c40
22 changed files with 868 additions and 754 deletions

View File

@@ -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;
gdb_assert (sigtramp_saved_pc != NULL);
return sigtramp_saved_pc (frame);
}
return read_memory_unsigned_integer (frame->frame + 4, 4);
}
CORE_ADDR
i386go32_frame_saved_pc (struct frame_info *frame)
{
return read_memory_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;
/* 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;
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 (target_read_memory (sp + 4, buf, 4))
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))
jb_addr = extract_address (buf, 4);
if (target_read_memory (jb_addr + jb_pc_offset, buf, 4))
return 0;
*pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
*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
static void
process_note_sections (bfd *abfd, asection *sect, void *obj)
{
int *abi = obj;
const char *name;
unsigned int sectsize;
name = bfd_get_section_name (abfd, sect);
sectsize = bfd_section_size (abfd, sect);
if (strcmp (name, ".note.ABI-tag") == 0 && sectsize > 0)
{
unsigned int name_length, data_length, note_type;
char *note;
/* If the section is larger than this, it's probably not what we
are looking for. */
if (sectsize > 128)
sectsize = 128;
note = alloca (sectsize);
bfd_get_section_contents (abfd, sect, note,
(file_ptr) 0, (bfd_size_type) sectsize);
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);
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);
/* 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;
/* If the section is larger than this, it's probably not what we are
looking for. */
if (sectsize > 128)
sectsize = 128;
note = alloca (sectsize);
bfd_get_section_contents (abfd, sect, note,
(file_ptr) 0, (bfd_size_type) sectsize);
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);
if (name_length == 7 && desc_length == 4
&& note_type == NT_NETBSD_IDENT
&& strcmp (note + 12, "NetBSD") == 0)
*abi = ABI_TAG_OS_NETBSD;
}
}
/* System V Release 4 (SVR4). */
static int
i386_elf_abi_from_note (bfd *abfd)
i386_svr4_pc_in_sigtramp (CORE_ADDR pc, char *name)
{
enum i386_abi abi = I386_ABI_UNKNOWN;
bfd_map_over_sections (abfd, process_note_sections, &abi);
return abi;
return (name && (strcmp ("_sigreturn", name) == 0
|| strcmp ("_sigacthandler", name) == 0
|| strcmp ("sigvechandler", name) == 0));
}
static enum i386_abi
i386_elf_abi (bfd *abfd)
/* Get saved user PC for sigtramp from the pushed ucontext on the
stack for all three variants of SVR4 sigtramps. */
CORE_ADDR
i386_svr4_sigtramp_saved_pc (struct frame_info *frame)
{
int elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
CORE_ADDR saved_pc_offset = 4;
char *name = NULL;
/* 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)
find_pc_partial_function (frame->pc, &name, NULL, NULL);
if (name)
{
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;
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;
}
switch (elfosabi)
{
case ELFOSABI_NONE:
return I386_ABI_SVR4;
case ELFOSABI_FREEBSD:
return I386_ABI_FREEBSD;
}
return I386_ABI_UNKNOWN;
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);
}
struct i386_abi_handler
/* DJGPP. */
static int
i386_go32_pc_in_sigtramp (CORE_ADDR pc, char *name)
{
struct i386_abi_handler *next;
enum i386_abi abi;
void (*init_abi)(struct gdbarch_info, struct gdbarch *);
};
/* DJGPP doesn't have any special frames for signal handlers. */
return 0;
}
struct i386_abi_handler *i386_abi_handler_list = NULL;
/* Generic ELF. */
void
i386_gdbarch_register_os_abi (enum i386_abi abi,
void (*init_abi)(struct gdbarch_info,
struct gdbarch *))
i386_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct i386_abi_handler **handler_p;
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;
/* We typically use stabs-in-ELF with the DWARF register numbering. */
set_gdbarch_stab_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
}
/* System V Release 4 (SVR4). */
void
i386_svr4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* System V Release 4 uses ELF. */
i386_elf_init_abi (info, gdbarch);
/* FIXME: kettenis/20020511: Why do we override this function here? */
set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
set_gdbarch_pc_in_sigtramp (gdbarch, i386_svr4_pc_in_sigtramp);
tdep->sigtramp_saved_pc = i386_svr4_sigtramp_saved_pc;
tdep->jb_pc_offset = 20;
}
/* DJGPP. */
void
i386_go32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
set_gdbarch_pc_in_sigtramp (gdbarch, i386_go32_pc_in_sigtramp);
tdep->jb_pc_offset = 36;
}
/* NetWare. */
void
i386_nw_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* 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;
/* 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;
/* 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;
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_frame_chain_valid (gdbarch, file_frame_chain_valid);
set_gdbarch_use_struct_convention (gdbarch, i386_use_struct_convention);
/* 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);
/* 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);
/* 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);
}