From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28791 invoked by alias); 7 Sep 2002 16:18:14 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 28776 invoked from network); 7 Sep 2002 16:18:11 -0000 Received: from unknown (HELO walton.kettenis.dyndns.org) (62.163.169.250) by sources.redhat.com with SMTP; 7 Sep 2002 16:18:11 -0000 Received: from elgar.kettenis.dyndns.org (elgar.kettenis.dyndns.org [192.168.0.2]) by walton.kettenis.dyndns.org (8.12.5/8.12.5) with ESMTP id g87GI5oR000322; Sat, 7 Sep 2002 18:18:05 +0200 (CEST) (envelope-from kettenis@elgar.kettenis.dyndns.org) Received: from elgar.kettenis.dyndns.org (localhost [127.0.0.1]) by elgar.kettenis.dyndns.org (8.12.5/8.12.5) with ESMTP id g87GI0KH000318; Sat, 7 Sep 2002 18:18:00 +0200 (CEST) (envelope-from kettenis@elgar.kettenis.dyndns.org) Received: (from kettenis@localhost) by elgar.kettenis.dyndns.org (8.12.5/8.12.5/Submit) id g87GHqPG000313; Sat, 7 Sep 2002 18:17:52 +0200 (CEST) To: Joel Brobecker Cc: gdb-patches@sources.redhat.com Subject: Re: [RFC] Take 2: Adding new files for Interix port References: <20020815194425.GB911@gnat.com> From: Mark Kettenis Date: Sat, 07 Sep 2002 09:18:00 -0000 In-Reply-To: Joel Brobecker's message of "Thu, 15 Aug 2002 12:44:25 -0700" Message-ID: <86sn0l4vv4.fsf@elgar.kettenis.dyndns.org> X-SW-Source: 2002-09/txt/msg00106.txt.bz2 Joel Brobecker 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 > > 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 > #include > #include > > #include > #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 > > 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.