This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [RFC] Take 2: Adding new files for Interix port
- From: Mark Kettenis <kettenis at chello dot nl>
- To: Joel Brobecker <brobecker at gnat dot com>
- Cc: gdb-patches at sources dot redhat dot com
- Date: 07 Sep 2002 18:17:51 +0200
- Subject: Re: [RFC] Take 2: Adding new files for Interix port
- References: <20020815194425.GB911@gnat.com>
Joel Brobecker <brobecker@gnat.com> writes:
> --BXVAT5kNtrzKuDFl
> Content-Type: text/plain; charset=us-ascii
> Content-Disposition: inline
>
> Thanks to Mark's very valuable comments, I think I have brought the
> interix-specific files to a much better state. I also fixed the ARI
> regressions (I had to hack a bit Andrew's script, so some regressions
> may have been left behind, but most of them should have been dealt
> with).
I'm sorry to be such a nitpicker, but there are several places where
the use of whitespace in and capitalization of comments is still
slightly wrong:
* Comments should be full sentences if possible.
* A full stop (that's a dot at the end of a sentence) should be
followed by two spaces, even at the end of a comment.
* There should only be a single space before the start of the text of
a comment.
> The nm- and xm- files contains macros that you have never seen so far.
> They are part of some changes that were made in common parts of the GDB
> source. They are probably temporary, all the more so as I understand
> that we want to get rid of these files in the long run anyway.
I don't think we're going to tolerate those changes in most of the
common parts of GDB. Therefore, what's the point of adding them now?
Anyway please use a uniform naming convention for these files; now you
have xm-i386interix.h and nm-interix.h, and you mention xm-interix.h
in your ChangeLog.
> One example of such macro is COFF_IMAGE_WITH_PE, which is used mostly
> in coffread to handle the little differences in the object format.
> There is probably a better way than using a macro, something like the
> procfs_ops vector, or the arch vector. I will take care of this macro
> at the same time I take of the changes in coffread.c.
>
> Same for macros like NONZERO_LINK_BASE, or NAME_OF_MALLOC.
>
> I am hoping that we are getting close to a state where I can check these
> files in, and work on the configury parts. Here is the ChangeLog:
>
> 2002-08-15 Joel Brobecker <brobecker@gnat.com>
>
> New interix-specific files:
> * config/i386/nm-interix.h: New file.
> * config/i386/xm-interix.h: New file.
> * config/i386/interix.mh: New file.
> * config/i386/interix.mt: New file.
> * i386-interix-nat.c: New file.
> * i386-interix-tdep.c: New file.
>
> Ok to apply?
>
> Thanks,
> --
> Joel
>
> --BXVAT5kNtrzKuDFl
> Content-Type: text/plain; charset=us-ascii
> Content-Description: nm-interix.h
> Content-Disposition: attachment; filename="nm-interix.h"
>
> /* Native-dependent definitions for Intel 386 running Interix, for GDB.
> Copyright 1986, 1987, 1989, 1992, 1996 Free Software Foundation, Inc.
>
> This file is part of GDB.
>
> This program is free software; you can redistribute it and/or modify
> it under the terms of the GNU General Public License as published by
> the Free Software Foundation; either version 2 of the License, or
> (at your option) any later version.
>
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU General Public License for more details.
>
> You should have received a copy of the GNU General Public License
> along with this program; if not, write to the Free Software
> Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
>
> #ifndef NM_INTERIX_H
> #define NM_INTERIX_H
>
> /* Be shared lib aware */
> #include "solib.h"
>
> /* submodes of USE_PROC_FS */
> #define UNIXWARE
>
> /* It's ALMOST coff; bfd does the same thing. Mostly used in coffread.c. */
> #define COFF_IMAGE_WITH_PE
>
> /* Turn on our own child_pid_to_exec_file. */
> #define CHILD_PID_TO_EXEC_FILE
>
> #endif /* NM_INTERIX_H */
>
> --BXVAT5kNtrzKuDFl
> Content-Type: text/plain; charset=us-ascii
> Content-Description: xm-i386interix.h
> Content-Disposition: attachment; filename="xm-i386interix.h"
>
> /* Host-dependent definitions for i386 running Interix.
> Copyright 2002 Free Software Foundation, Inc.
>
> This file is part of GDB.
>
> This program is free software; you can redistribute it and/or modify
> it under the terms of the GNU General Public License as published by
> the Free Software Foundation; either version 2 of the License, or
> (at your option) any later version.
>
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU General Public License for more details.
>
> You should have received a copy of the GNU General Public License
> along with this program; if not, write to the Free Software
> Foundation, Inc., 59 Temple Place - Suite 330,
> Boston, MA 02111-1307, USA. */
>
> #ifndef XM_I386INTERIX_H
> #define XM_I386INTERIX_H
>
> /* FIXME: This file is only temporary, and the final intent is to get
> rid of each macro defined here. This will be done later. */
>
> /* FIXME: configure should be taught about this. */
> #define PRINTF_HAS_LONG_LONG 1
> #ifdef __GNUC__
> #define BFD_HOST_64_BIT long long
> #define BFD_HOST_U_64_BIT unsigned long long
> #elif defined(_MSC_VER)
> #define BFD_HOST_64_BIT __int64
> #define BFD_HOST_U_64_BIT unsigned __int64
> #else
> #error... OK what compiler is this?
> #endif
>
> /* FIXME: configure should be taught about this. */
> #undef LONGEST
> #define LONGEST BFD_HOST_64_BIT
>
> /* FIXME: configure should be taught about this. */
> #undef ULONGEST
> #define ULONGEST BFD_HOST_U_64_BIT
This should really be addressed in BFD, not GDB. I suspect that with
this approach you'll encounter problems when you build a 64-bit
enabled BFD.
> /* Interix has a minimal sbrk() (but not what's wanted for this usage),
> and its relationship to environ[] is not what's usually expected
> (as in, there is no specific relationship at all). Just pretend we don't
> have an sbrk(). */
> #undef HAVE_SBRK
>
> /* Used in coffread.c to adjust the symbol offsets. */
> #define ADJUST_OBJFILE_OFFSETS(objfile, type) \
> pei_adjust_objfile_offsets(objfile, type)
>
> extern CORE_ADDR bfd_getImageBase(bfd *abfd);
> #define NONZERO_LINK_BASE(abfd) bfd_getImageBase(abfd)
>
> /* Used in valops.c, to change the name of the malloc function when
> trying to allocate memory in the inferior. On Interix, we need to
> call _malloc. Should this be added to the target vector? */
> #define NAME_OF_MALLOC "_malloc"
This doesn't belong here. Probably should be moved to your nm.h file.
> #endif /* XM_I386INTERIX_H */
>
>
> --BXVAT5kNtrzKuDFl
> Content-Type: text/plain; charset=us-ascii
> Content-Description: interix.mh
> Content-Disposition: attachment; filename="interix.mh"
>
> # Host: Intel 386 running Interix
> XDEPFILES=
> NATDEPFILES= corelow.o core-regset.o fork-child.o i386-interix-nat.o \
> procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o
> NAT_FILE= nm-interix.h
> XM_FILE= xm-i386interix.h
> # The below may be temporary; mmalloc relies on sbrk() at the moment
> MMALLOC=
> MMALLOC_CFLAGS=-DNO_MMALLOC
>
> --BXVAT5kNtrzKuDFl
> Content-Type: text/plain; charset=us-ascii
> Content-Description: interix.mt
> Content-Disposition: attachment; filename="interix.mt"
>
> # Target: Intel 386 running Interix
> TDEPFILES= i386-tdep.o i387-tdep.o i386-interix-tdep.o \
> solib.o solib-pei.o
> TM_FILE= tm-i386.h
>
> --BXVAT5kNtrzKuDFl
> Content-Type: text/plain; charset=us-ascii
> Content-Description: i386-interix-nat.c
> Content-Disposition: attachment; filename="i386-interix-nat.c"
>
> /* Native-dependent code for Interix running on i386's, for GDB.
> Copyright 2002 Free Software Foundation, Inc.
>
> This file is part of GDB.
>
> This program is free software; you can redistribute it and/or modify
> it under the terms of the GNU General Public License as published by
> the Free Software Foundation; either version 2 of the License, or
> (at your option) any later version.
>
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU General Public License for more details.
>
> You should have received a copy of the GNU General Public License
> along with this program; if not, write to the Free Software
> Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
>
> #include "defs.h"
>
> #include <sys/procfs.h>
> #include <inferior.h>
> #include <fcntl.h>
>
> #include <i386-tdep.h>
> #include "gdb_string.h"
> #include "gdbcore.h"
> #include "gregset.h"
>
> typedef unsigned long greg_t;
>
> /* This is a duplicate of the table in i386-linux-nat.c. */
>
> static int regmap[] = {
> EAX, ECX, EDX, EBX,
> UESP, EBP, ESI, EDI,
> EIP, EFL, CS, SS,
> DS, ES, FS, GS,
> };
>
> /* Forward declarations */
> extern void _initialize_core_interix (void);
> extern initialize_file_ftype _initialize_core_interix;
>
> /* Given a pointer to a general register set in /proc format (gregset_t *),
> unpack the register contents and supply them as gdb's idea of the current
> register values. */
>
> void
> supply_gregset (gregset_t *gregsetp)
> {
> int regi;
> greg_t *regp = (greg_t *) & gregsetp->gregs;
Indent gets this wrong :-(. Please remove the space after the ampersand.
> for (regi = 0; regi < I386_NUM_GREGS; regi++)
> {
> supply_register (regi, (char *) (regp + regmap[regi]));
> }
> }
>
> /* Store GDB's value for REGNO in *GREGSETP. If REGNO is -1, do all
> of them. */
>
> void
> fill_gregset (gregset_t *gregsetp, int regno)
> {
> int regi;
> greg_t *regp = (greg_t *) gregsetp->gregs;
>
> for (regi = 0; regi < I386_NUM_GREGS; regi++)
> if (regno == -1 || regi == regno)
> regcache_collect (regi, (void *) (regp + regmap[regi]));
> }
>
> /* Fill GDB's register file with the floating-point register values in
> *FPREGSETP. */
>
> void
> supply_fpregset (fpregset_t *fpregsetp)
> {
> i387_supply_fsave ((char *) fpregsetp);
> }
>
> /* Given a pointer to a floating point register set in (fpregset_t *)
> format, update all of the registers from gdb's idea of the current
> floating point register set. */
>
> void
> fill_fpregset (fpregset_t *fpregsetp, int regno)
> {
> i387_fill_fsave ((char *) fpregsetp, regno);
> }
>
> /* Read the values of either the general register set (WHICH equals 0)
> or the floating point register set (WHICH equals 2) from the core
> file data (pointed to by CORE_REG_SECT), and update gdb's idea of
> their current values. The CORE_REG_SIZE parameter is compared to
> the size of the gregset or fpgregset structures (as appropriate) to
> validate the size of the structure from the core file. The
> REG_ADDR parameter is ignored. */
>
> static void
> fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
> CORE_ADDR reg_addr)
> {
> gdb_gregset_t gregset;
> gdb_fpregset_t fpregset;
>
> if (which == 0)
> {
> if (core_reg_size != sizeof (gregset))
> {
> warning ("wrong size gregset struct in core file");
> }
> else
> {
> memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
> supply_gregset (&gregset);
> }
> }
> else if (which == 2)
> {
> if (core_reg_size != sizeof (fpregset))
> {
> warning ("wrong size fpregset struct in core file");
> }
> else
> {
> memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
> supply_fpregset (&fpregset);
> }
> }
> }
>
> #include <setjmp.h>
>
> static struct core_fns interix_core_fns = {
Please move the bracket on to the next line.
> bfd_target_coff_flavour, /* core_flavour (more or less) */
> default_check_format, /* check_format */
> default_core_sniffer, /* core_sniffer */
> fetch_core_registers, /* core_read_registers */
> NULL /* next */
> };
>
> void
> _initialize_core_interix (void)
> {
> add_core_fns (&interix_core_fns);
> }
>
> /* We don't have a /proc/pid/file or /proc/pid/exe to read a link from,
> so read it from the same place ps gets the name. */
>
> char *
> child_pid_to_exec_file (int pid)
> {
> char *path;
> char *buf;
> int fd, c;
> char *p;
>
> xasprintf (&path, "/proc/%d/stat", pid);
> buf = xcalloc (MAXPATHLEN + 1, sizeof (char));
> make_cleanup (xfree, path);
> make_cleanup (xfree, buf);
>
> fd = open (path, O_RDONLY);
>
> if (fd < 0)
> return NULL;
>
> /* Skip over "Argv0\t" */
> lseek (fd, 6, SEEK_SET);
>
> c = read (fd, buf, MAXPATHLEN);
> close (fd);
>
> if (c < 0)
> return NULL;
>
> buf[c] = '\0'; /* Ensure null termintion. */
> p = strchr (buf, '\n');
> if (p != NULL)
> *p = '\0';
>
> return buf;
> }
>
> --BXVAT5kNtrzKuDFl
> Content-Type: text/plain; charset=us-ascii
> Content-Description: i386-interix-tdep.c
> Content-Disposition: attachment; filename="i386-interix-tdep.c"
>
> /* Target-dependent code for Interix running on i386's, for GDB.
> Copyright 2002 Free Software Foundation, Inc.
>
> This file is part of GDB.
>
> This program is free software; you can redistribute it and/or modify
> it under the terms of the GNU General Public License as published by
> the Free Software Foundation; either version 2 of the License, or
> (at your option) any later version.
>
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU General Public License for more details.
>
> You should have received a copy of the GNU General Public License
> along with this program; if not, write to the Free Software
> Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
>
> #include "defs.h"
> #include "arch-utils.h"
>
> #include "frame.h"
> #include "gdb_string.h"
> #include "gdb-stabs.h"
> #include "gdbcore.h"
> #include "gdbtypes.h"
> #include "i386-tdep.h"
> #include "inferior.h"
> #include "libbfd.h"
> #include "objfiles.h"
> #include "osabi.h"
>
> /* offsetof (mcontext_t, gregs.gregs[EBP]) */
> static const int mcontext_EBP_greg_offset = 180;
>
> /* offsetof (mcontext_t, gregs.gregs[EIP]) */
> static const int mcontext_EIP_greg_offset = 184;
>
> /* offsetof (mcontext_t, gregs.gregs[UESP]) */
> static const int mcontext_UESP_greg_offset = 196;
>
> /* offsetof (mcontext_t, gregs.reserved[1]) */
> static const int mcontext_syscall_greg_offset = 4;
>
> /* offsetof (_JUMP_BUFFER, Eip) */
> static const int jump_buffer_Eip_offset = 20;
>
> /* See procfs.c and *interix*.h in config/[alpha,i386] */
> /* ??? These should be static, but this needs a bit of work before this
> can be done. */
> CORE_ADDR tramp_start;
> CORE_ADDR tramp_end;
> CORE_ADDR null_start;
> CORE_ADDR null_end;
> int winver; /* Windows NT version number */
>
> /* Forward declarations */
> extern void _initialize_i386_interix_tdep (void);
> extern initialize_file_ftype _initialize_i386_interix_tdep;
>
> /* Adjust the section offsets in an objfile structure so that it's correct
> for the type of symbols being read (or undo it with the _restore
> arguments).
>
> If main programs ever start showing up at other than the default Image
> Base, this is where that would likely be applied. */
>
> void
> pei_adjust_objfile_offsets (struct objfile *objfile,
> enum objfile_adjusts type)
> {
> int i;
> CORE_ADDR symbols_offset;
>
> switch (type)
> {
> case adjust_for_symtab:
> symbols_offset = NONZERO_LINK_BASE (objfile->obfd);
> break;
> case adjust_for_symtab_restore:
> symbols_offset = -NONZERO_LINK_BASE (objfile->obfd);
> break;
> case adjust_for_stabs:
> case adjust_for_stabs_restore:
> case adjust_for_dwarf:
> case adjust_for_dwarf_restore:
> default:
> return;
> }
>
> for (i = 0; i < SECT_OFF_MAX; i++)
> {
> (objfile->section_offsets)->offsets[i] += symbols_offset;
> }
> }
>
> static int
> i386_interix_pc_in_sigtramp (CORE_ADDR pc, char *name)
> {
> /* This is sufficient, where used, but is NOT a complete test; There
> is more in INIT_EXTRA_FRAME_INFO (a.k.a. interix_back_one_frame) */
> return (pc >= tramp_start && pc < tramp_end)
> || (pc >= null_start && pc < null_end);
Please use an extra pair of braces to get the indentation right.
> }
>
> static int
> i386_interix_in_solib_call_trampoline (CORE_ADDR pc, char *name)
> {
> return skip_trampoline_code (pc, name);
> }
Didn't you rename skip_trampoline_code?
> static CORE_ADDR
> i386_interix_skip_trampoline_code (CORE_ADDR pc)
> {
> return skip_trampoline_code (pc, 0);
> }
Likewise.
> static void
> i386_interix_init_frame_pc (int fromleaf, struct frame_info *prev)
> {
> /* Nothing to do on Interix */
> }
>
> static int
> i386_interix_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
> {
> /* In the context where this is used, we get the saved PC before we've
> successfully unwound far enough to be sure what we've got (it may
> be a signal handler caller). If we're dealing with a signal
> handler caller, this will return valid, which is fine. If not,
> it'll make the correct test. */
> return thisframe->signal_handler_caller
> || (chain != 0
> && !inside_entry_file (read_memory_integer (thisframe->frame + 4,
> 4)));
Again, please use an extra pair of braces.
> }
>
> /* We want to find the previous frame, which on Interix is tricky when signals
> are involved; set frame->frame appropriately, and also get the pc
> and tweak signal_handler_caller; this replaces a boatload of nested
> macros, as well. */
> static void
> i386_interix_back_one_frame (int fromleaf, struct frame_info *frame)
> {
> CORE_ADDR ra;
> CORE_ADDR fm;
> CORE_ADDR context;
> long t;
>
> if (frame == NULL)
> internal_error (__FILE__, __LINE__, "unexpected NULL frame");
>
> if (fromleaf)
> {
> frame->pc = SAVED_PC_AFTER_CALL (frame->next);
> return;
> }
>
> if (!frame->next)
> {
> frame->pc = read_pc ();
>
> /* part of the signal stuff... see below */
> if (stopped_by_random_signal)
> {
> /* we know we're in a system call mini-frame; was it
> NullApi or something else? */
> ra = SAVED_PC_AFTER_CALL (frame);
> if (ra >= null_start && ra < null_end)
> frame->signal_handler_caller = 1;
> /* There might also be an indirect call to the mini-frame,
> putting one more return address on the stack. (XP only,
> I think?) This can't (reasonably) return the address of the
> signal handler caller unless it's that situation, so this
> is safe. */
> ra =
> read_memory_unsigned_integer (read_register (SP_REGNUM) + 4, 4);
> if (ra >= null_start && ra < null_end)
> frame->signal_handler_caller = 1;
> }
> return;
> }
>
> if (!frame->next->signal_handler_caller)
> {
> frame->pc = read_memory_integer (frame->next->frame + 4, 4);
> return;
> }
>
> /* This is messy... (actually AWFUL) the "trampoline" might be 2, 3
> or all 5 entities on the frame.
>
> Chunk 1 will be present when we're actually in a signal handler.
> Chunk 2 will be present when an asynchronous signal (one that
> didn't come in with a system call) is present.
> We may not (yet) be in the handler, if we're just returning
> from the call.
> When we're actually in a handler taken from an asynchronous
> signal, both will be present.
>
> Chunk 1:
> PdxSignalDeliverer's frame
> + Context struct -- not accounted for in any frame
>
> Chunk 2:
> + PdxNullPosixApi's frame
> + PdxNullApiCaller's frame
> + Context struct = 0x230 not accounted for in any frame
>
> The symbol names come from examining objdumps of psxdll.dll;
> they don't appear in the runtime image.
>
> For gdb's purposes, we can pile all this into one frame.
> */
>
> ra = frame->next->pc;
> /* Are we already pointing at PdxNullPosixApi? We are if
> this is a signal frame, we're at next-to-top, and were stopped
> by a random signal. (If it wasn't the right address under
> these circumstances, we wouldn't be here at all by tests above
> on the prior frame.) */
> if (frame->next->next == NULL && stopped_by_random_signal)
> {
> /* We're pointing at the frame FOR PdxNullApi */
> fm = frame->frame;
> }
> else
> {
> /* No... we must be pointing at the frame that
> was called by PdxSignalDeliverer; back up across the
> whole mess */
>
> /* extract the frame for PdxSignalDeliverer; note...FRAME_CHAIN
> used the "old" frame pointer because we were a deliverer.
> Get the address of the context record that's on here frameless */
> context = read_memory_integer (frame->frame, 4); /* an Arg */
>
> /* Now extract the frame pointer contained in the context */
> fm = read_memory_integer (context + mcontext_EBP_greg_offset, 4);
>
> ra = read_memory_integer (context + mcontext_EIP_greg_offset, 4);
>
> /* We need to know if we're in a system call because we'll be
> in a syscall mini-frame, if so, and the rules are different. */
> t = (long) read_memory_integer (context + mcontext_syscall_greg_offset,
> 4);
> /* t contains 0 if running free, 1 if blocked on a system call,
> and 2 if blocked on an exception message (e.g. a trap);
> we don't expect to get here with a 2. */
> if (t != 1)
> {
> /* not at a system call, therefore it can't be NullApi */
> frame->pc = ra;
> frame->frame = fm;
> return;
> }
>
> /* It's a system call... mini frame, then look for NullApi */
> /* Get the RA (on the stack) associated with this... it's
> a system call mini-frame */
> ra = read_memory_integer (context + mcontext_UESP_greg_offset, 4);
>
> if (winver >= 51)
> {
> /* Newer versions of Windows NT interpose another return
> address (but no other "stack frame" stuff) that we need
> to simply ignore here. */
> ra += 4;
> }
>
> ra = read_memory_integer (ra, 4);
>
> /* We might be done (no Null API if so) */
> if (!(ra >= null_start && ra < null_end))
> {
> /* No Null API present; we're done */
> frame->pc = ra;
> frame->frame = fm;
> return;
> }
> }
> /* At this point, we're looking at the frame for PdxNullPosixApi,
> in either case.
>
> PdxNullPosixApi is called by PdxNullApiCaller (which in turn
> is called by _PdxNullApiCaller (note the _).)
> PdxNullPosixApiCaller (no _) is a frameless function.
>
> The saved frame pointer is as fm, but it's not of interest
> to us because it skips us over the saved context, which is
> the wrong thing to do, because it skips the interrrupted
> routine! PdxNullApiCaller takes as its only argument the
> address of the context of the interrupded function (which
> is really in no frame, but jammed on the stack by the system)
>
> So: fm+0: saved bp
> fm+4: return address to _PdxNullApiCaller
> fm+8: arg to PdxNullApiCaller pushed by _Pdx... */
>
> fm = read_memory_integer (fm + 0x8, 4);
>
> /* Extract the second context record */
>
> ra = read_memory_integer (fm + mcontext_EIP_greg_offset, 4);
> fm = read_memory_integer (fm + mcontext_EBP_greg_offset, 4);
>
> frame->frame = fm;
> frame->pc = ra;
>
> return;
> }
>
> static CORE_ADDR
> i386_interix_frame_saved_pc (struct frame_info *fi)
> {
> /* Assume that we've already unwound enough to have the caller's address
> if we're dealing with a signal handler caller. (And if that fails,
> return 0.) */
> if (fi->signal_handler_caller)
> return fi->next ? fi->next->pc : 0;
> else
> return read_memory_integer (fi->frame + 4, 4);
> }
>
> static void
> i386_interix_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> {
> struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>
> tdep->struct_return = reg_struct_return;
> tdep->jb_pc_offset = jump_buffer_Eip_offset;
>
> set_gdbarch_decr_pc_after_break (gdbarch, 0);
> set_gdbarch_pc_in_sigtramp (gdbarch, i386_interix_pc_in_sigtramp);
> set_gdbarch_in_solib_call_trampoline (gdbarch,
> i386_interix_in_solib_call_trampoline);
> set_gdbarch_skip_trampoline_code (gdbarch,
> i386_interix_skip_trampoline_code);
> set_gdbarch_init_extra_frame_info (gdbarch, i386_interix_back_one_frame);
> set_gdbarch_init_frame_pc (gdbarch, i386_interix_init_frame_pc);
> set_gdbarch_frame_chain_valid (gdbarch, i386_interix_frame_chain_valid);
> set_gdbarch_frame_saved_pc (gdbarch, i386_interix_frame_saved_pc);
> }
>
> static enum gdb_osabi
> i386_interix_osabi_sniffer (bfd * abfd)
> {
> char *target_name = bfd_get_target (abfd);
>
> if (strcmp (target_name, "pei-i386") == 0)
> return GDB_OSABI_INTERIX;
>
> return GDB_OSABI_UNKNOWN;
> }
>
> void
> _initialize_i386_interix_tdep (void)
> {
> gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
> i386_interix_osabi_sniffer);
>
> gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_INTERIX,
> i386_interix_init_abi);
> }
You'll have to add these GDB_OSABI constants to osabi.h first.