Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFC] Take 2: Adding new files for Interix port
@ 2002-08-15 12:44 Joel Brobecker
  2002-09-07  9:18 ` Mark Kettenis
  0 siblings, 1 reply; 3+ messages in thread
From: Joel Brobecker @ 2002-08-15 12:44 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1468 bytes --]

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).

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.

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

[-- Attachment #2: nm-interix.h --]
[-- Type: text/plain, Size: 1201 bytes --]

/* 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 */

[-- Attachment #3: xm-i386interix.h --]
[-- Type: text/plain, Size: 2352 bytes --]

/* 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

/* 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"

#endif /* XM_I386INTERIX_H */


[-- Attachment #4: interix.mh --]
[-- Type: text/plain, Size: 331 bytes --]

# 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

[-- Attachment #5: interix.mt --]
[-- Type: text/plain, Size: 140 bytes --]

# 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

[-- Attachment #6: i386-interix-nat.c --]
[-- Type: text/plain, Size: 4752 bytes --]

/* 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;

  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 = {
  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;
}

[-- Attachment #7: i386-interix-tdep.c --]
[-- Type: text/plain, Size: 11638 bytes --]

/* 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);
}

static int
i386_interix_in_solib_call_trampoline (CORE_ADDR pc, char *name)
{
  return skip_trampoline_code (pc, name);
}

static CORE_ADDR
i386_interix_skip_trampoline_code (CORE_ADDR pc)
{
  return skip_trampoline_code (pc, 0);
}

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)));
}

/* 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);
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC] Take 2: Adding new files for Interix port
  2002-08-15 12:44 [RFC] Take 2: Adding new files for Interix port Joel Brobecker
@ 2002-09-07  9:18 ` Mark Kettenis
  2002-09-08 15:49   ` Joel Brobecker
  0 siblings, 1 reply; 3+ messages in thread
From: Mark Kettenis @ 2002-09-07  9:18 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

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.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC] Take 2: Adding new files for Interix port
  2002-09-07  9:18 ` Mark Kettenis
@ 2002-09-08 15:49   ` Joel Brobecker
  0 siblings, 0 replies; 3+ messages in thread
From: Joel Brobecker @ 2002-09-08 15:49 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

> 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:

Please don't be sorry. It's me who feels bad for still leaving some of
these style errors. I thought I fixed them all, I'll fix the remaining
ones.

> > 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?

It would make my life simpler: the current interix port still needs some
rework to bring it to a point where all the changes would be acceptable
for integration (albeit with some minor edits, based on the GDB
developers feedback).

But if this is not acceptable, then I will check-in the part that is
approved, and keep this changes localy until I can finally get rid of
them...

> 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.

Ok, will do.

> > /* 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.

That makes sense. Will do.

Regarding the xm- file:
> > /* 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.

Just to make sure I understand which macros you refer to, would you mind
clarifying for me?
  - HAVE_SBRK  (I assume leaving it in the xm- file is ok, since this
    is where you recommended in a previous message where to put it)
  - ADJUST_OBJFILE_OFFSETS? 
  - NONZERO_LINK_BASE?
  - NAME_OF_MALLOC? I would actually think that this macro should
    be in the -tdep file, since it is the name of function to call
    in the inferior, which lives on the target. What do you think?
    Should it really be in the nm.h file?

> > 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.

Thanks, fixed.

> > #include <setjmp.h>
> > 
> > static struct core_fns interix_core_fns = {
> 
> Please move the bracket on to the next line.

Thanks, fixed.

> > 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.

argh, added.

> > 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?

Yes, I did. And I actually resync'ed  my version of the sources. So
this is already fixed.

> >   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.

Braces added.

> >   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.

Ok.

I will start devoting more time working on bfd, to at least get the
BFD-related comments above solved. I'll then add this GDB_OSABI, and
then resubmit these files, with hopefully all your comments addressed.

Thanks again for the review,
-- 
Joel


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2002-09-08 22:49 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-08-15 12:44 [RFC] Take 2: Adding new files for Interix port Joel Brobecker
2002-09-07  9:18 ` Mark Kettenis
2002-09-08 15:49   ` Joel Brobecker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox