Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFC] QNX Neutrino/i386 support
@ 2003-03-08 13:45 Mark Kettenis
  2003-03-08 15:02 ` Kris Warkentin
  2003-03-08 15:19 ` Kris Warkentin
  0 siblings, 2 replies; 11+ messages in thread
From: Mark Kettenis @ 2003-03-08 13:45 UTC (permalink / raw)
  To: Kris Warkentin; +Cc: gdb-patches

Kris,

Here is a sort-of minimal patch to add the QNX Neutroni/i386 target
stuff into GDB.  I left out all the controversial bits for now, and
some bits I don't understand yet.  I also left out the bits dealing
with the special NTO remote protocol.  As I wrote to you before, I'd
rather not have those bits in i386-nto-tdep.c.

I'm still struggling with the shared library stuff.  There's something
fishy in there, but it seems that the comment in nto-tdep.c is wrong,
or at least outdated.

Anyway, this should be enough to do some basic debugging via the
standard GDB remote protocol if it were supported on NTO.  My proposal
is to check this in, and work from there.

Mark

Index: configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.98
diff -u -p -r1.98 configure.tgt
--- configure.tgt 5 Feb 2003 23:14:47 -0000 1.98
+++ configure.tgt 8 Mar 2003 13:25:19 -0000
@@ -90,6 +90,7 @@ i[3456]86-*-netbsd*)	gdb_target=nbsd ;;
 i[3456]86-*-openbsd*)	gdb_target=obsd ;;
 i[3456]86-*-go32*)	gdb_target=i386aout ;;
 i[3456]86-*-msdosdjgpp*) gdb_target=go32 ;;
+i[3456]86-*-nto* | x86-*-nto*)	gdb_target=nto ;;
 i[3456]86-*-lynxos*)	gdb_target=i386lynx ;;
 i[3456]86-*-solaris*)	gdb_target=i386sol2 ;;
 i[3456]86-*-sco*)	gdb_target=i386v ;;
@@ -280,5 +281,6 @@ esac
 case "${target}" in
 *-*-linux*)	gdb_osabi=GDB_OSABI_LINUX ;;
 *-*-gnu*)	gdb_osabi=GDB_OSABI_HURD ;;
+*-*-nto*)	gdb_osabi=GDB_OSABI_QNXNTO ;;
 *-*-solaris*)	gdb_osabi=GDB_OSABI_SOLARIS ;;
 esac
--- /dev/null	Sat Mar  8 14:22:37 2003
+++ config/i386/tm-nto.h	Sat Mar  1 20:33:57 2003
@@ -0,0 +1,27 @@
+/* Target-dependent definitions for QNX Neutrino/i386.
+   Copyright 2003 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 TM_NTO_H
+#define TM_NTO_H
+
+#include "i386/tm-i386.h"
+#include "solib.h"
+
+#endif /* TM_NTO_H */
--- /dev/null	Sat Mar  8 14:22:37 2003
+++ config/i386/nto.mt	Sat Mar  1 20:37:46 2003
@@ -0,0 +1,4 @@
+# Target: Intel 386 running QNX
+TDEPFILES= i386-tdep.o i387-tdep.o i386-nto-tdep.o \
+	solib.o solib-svr4.o
+TM_FILE= tm-nto.h
--- /dev/null	Sat Mar  8 14:22:37 2003
+++ i386-nto-tdep.c	Sat Mar  1 20:31:29 2003
@@ -0,0 +1,125 @@
+/* Target-dependent code for NTO.
+   Copyright 2003 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 "frame.h"
+#include "symtab.h"
+#include "objfiles.h"
+#include "osabi.h"
+#include "regcache.h"
+
+#include "i386-tdep.h"
+
+#include "solib-svr4.h"
+
+static int
+i386_nto_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+  return (name && strcmp ("__signalstub", name) == 0);
+}
+
+#define I386_NTO_SIGCONTEXT_OFFSET	136
+
+static CORE_ADDR
+i386_nto_sigcontext_addr (struct frame_info *frame)
+{
+  struct frame_info *next = get_next_frame (frame);
+
+  if (next)
+    return get_frame_base (next) + I386_NTO_SIGCONTEXT_OFFSET;
+
+  return read_register (SP_REGNUM) + I386_NTO_SIGCONTEXT_OFFSET;
+}
+
+/* Fetch (and possibly build) an appropriate link_map_offsets
+   structure for native x86 targets using the struct offsets defined
+   in link.h (but without actual reference to that file).
+
+   This makes it possible to access x86 shared libraries from a GDB
+   that was not built on an x86 host (for cross debugging).  */
+
+static struct link_map_offsets *
+i386_nto_svr4_fetch_link_map_offsets (void)
+{
+  static struct link_map_offsets lmo;
+  static struct link_map_offsets *lmp = NULL;
+
+  if (lmp == NULL)
+    {
+      lmp = &lmo;
+
+      lmo.r_debug_size = 8;	/* The actual size is larger, but this
+                                   is all we need.  */
+      lmo.r_map_offset = 4;
+      lmo.r_map_size = 4;
+
+      lmo.link_map_size = 20;	/* The actual size is larger bytes,
+				   but this is all we need.  */
+      lmo.l_addr_offset = 0;
+      lmo.l_addr_size = 4;
+
+      lmo.l_name_offset = 4;
+      lmo.l_name_size = 4;
+
+      lmo.l_next_offset = 12;
+      lmo.l_next_size = 4;
+
+      lmo.l_prev_offset = 16;
+      lmo.l_prev_size = 4;
+    }
+
+  return lmp;
+}
+
+/* QNX Neutrino (NTO).  */
+
+static void
+i386_nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* NTO uses ELF.  */
+  i386_elf_init_abi (info, gdbarch);
+
+  /* NTO has shared libraries.  */
+  set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
+  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+
+  set_gdbarch_pc_in_sigtramp (gdbarch, i386_nto_pc_in_sigtramp);
+  tdep->sigcontext_addr = i386_nto_sigcontext_addr;
+  tdep->sc_pc_offset = 56;
+  tdep->sc_sp_offset = 68;
+
+  tdep->jb_pc_offset = 20;
+
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+					 i386_nto_svr4_fetch_link_map_offsets);
+}
+\f
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_i386_nto_tdep (void);
+
+void
+_initialize_i386_nto_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
+			  i386_nto_init_abi);
+}


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

* Re: [RFC] QNX Neutrino/i386 support
  2003-03-08 13:45 [RFC] QNX Neutrino/i386 support Mark Kettenis
@ 2003-03-08 15:02 ` Kris Warkentin
  2003-03-08 23:49   ` Mark Kettenis
  2003-03-09  0:14   ` Mark Kettenis
  2003-03-08 15:19 ` Kris Warkentin
  1 sibling, 2 replies; 11+ messages in thread
From: Kris Warkentin @ 2003-03-08 15:02 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

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

That's great Mark but what about the native procfs stuff?  The most recent
patch that I had submitted was a native only version.  The only stuff in the
i386-nto-tdep.c that was even vaguely related to the remote protocol was
stuffing the regset type in the register area.  This is also used by
nto-procfs.c so I refactored the regset numbers to be defines that can be
used by both.

The file you have reduced to here is completely useless for any form of
debugging on Neutrino.  We don't currently support the standard gdb debug
protocol although it's on our to-do list.  Our i386 registers are in a
different order that gdb so we need to do the mapping.  I have already
applied patches to solib.c to do a special lookup of target solibs.  Without
that support, libs won't be found properly.

BTW, the OSABI stuff is already committed (they gave me write-after approval
for cvs) - the only stuff left is the addition of new files.  I would like
to get the config dir stuff, the tdep files, the nto-share headers and
nto-procfs.c committed.

What we have currently is something that works perfectly for us.  I really
don't want to start with something completely broken and make additions
until it works.  I want to add the working stuff and then cut away any fat
that we can prove that we don't need.  I don't mind doing major refactoring
but I want to have working code in CVS at all times.  That is something that
the GDB project strives for and I would like to do for our target as well.

I've attached a tarball with the files in it.  I think that it's pretty much
the same as what you have with the changes for the remote defines.  I
appreciate the time you're putting into this and I really want our port to
be as clean as it can be.  I know that there's lots of work to be done but
I'd really rather start from a working version and clean from there.  This
is one of my highest priority projects so I have lots of cycles available to
do the work but I want to be able to point our customers to the head branch
and have it work for them.

cheers,

Kris

----- Original Message -----
From: "Mark Kettenis" <kettenis@chello.nl>
To: "Kris Warkentin" <kewarken@qnx.com>
Cc: <gdb-patches@sources.redhat.com>
Sent: Saturday, March 08, 2003 8:44 AM
Subject: [RFC] QNX Neutrino/i386 support


> Kris,
>
> Here is a sort-of minimal patch to add the QNX Neutroni/i386 target
> stuff into GDB.  I left out all the controversial bits for now, and
> some bits I don't understand yet.  I also left out the bits dealing
> with the special NTO remote protocol.  As I wrote to you before, I'd
> rather not have those bits in i386-nto-tdep.c.
>
> I'm still struggling with the shared library stuff.  There's something
> fishy in there, but it seems that the comment in nto-tdep.c is wrong,
> or at least outdated.
>
> Anyway, this should be enough to do some basic debugging via the
> standard GDB remote protocol if it were supported on NTO.  My proposal
> is to check this in, and work from there.
>
> Mark
>
> Index: configure.tgt
> ===================================================================
> RCS file: /cvs/src/src/gdb/configure.tgt,v
> retrieving revision 1.98
> diff -u -p -r1.98 configure.tgt
> --- configure.tgt 5 Feb 2003 23:14:47 -0000 1.98
> +++ configure.tgt 8 Mar 2003 13:25:19 -0000
> @@ -90,6 +90,7 @@ i[3456]86-*-netbsd*) gdb_target=nbsd ;;
>  i[3456]86-*-openbsd*) gdb_target=obsd ;;
>  i[3456]86-*-go32*) gdb_target=i386aout ;;
>  i[3456]86-*-msdosdjgpp*) gdb_target=go32 ;;
> +i[3456]86-*-nto* | x86-*-nto*) gdb_target=nto ;;
>  i[3456]86-*-lynxos*) gdb_target=i386lynx ;;
>  i[3456]86-*-solaris*) gdb_target=i386sol2 ;;
>  i[3456]86-*-sco*) gdb_target=i386v ;;
> @@ -280,5 +281,6 @@ esac
>  case "${target}" in
>  *-*-linux*) gdb_osabi=GDB_OSABI_LINUX ;;
>  *-*-gnu*) gdb_osabi=GDB_OSABI_HURD ;;
> +*-*-nto*) gdb_osabi=GDB_OSABI_QNXNTO ;;
>  *-*-solaris*) gdb_osabi=GDB_OSABI_SOLARIS ;;
>  esac
> --- /dev/null Sat Mar  8 14:22:37 2003
> +++ config/i386/tm-nto.h Sat Mar  1 20:33:57 2003
> @@ -0,0 +1,27 @@
> +/* Target-dependent definitions for QNX Neutrino/i386.
> +   Copyright 2003 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 TM_NTO_H
> +#define TM_NTO_H
> +
> +#include "i386/tm-i386.h"
> +#include "solib.h"
> +
> +#endif /* TM_NTO_H */
> --- /dev/null Sat Mar  8 14:22:37 2003
> +++ config/i386/nto.mt Sat Mar  1 20:37:46 2003
> @@ -0,0 +1,4 @@
> +# Target: Intel 386 running QNX
> +TDEPFILES= i386-tdep.o i387-tdep.o i386-nto-tdep.o \
> + solib.o solib-svr4.o
> +TM_FILE= tm-nto.h
> --- /dev/null Sat Mar  8 14:22:37 2003
> +++ i386-nto-tdep.c Sat Mar  1 20:31:29 2003
> @@ -0,0 +1,125 @@
> +/* Target-dependent code for NTO.
> +   Copyright 2003 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 "frame.h"
> +#include "symtab.h"
> +#include "objfiles.h"
> +#include "osabi.h"
> +#include "regcache.h"
> +
> +#include "i386-tdep.h"
> +
> +#include "solib-svr4.h"
> +
> +static int
> +i386_nto_pc_in_sigtramp (CORE_ADDR pc, char *name)
> +{
> +  return (name && strcmp ("__signalstub", name) == 0);
> +}
> +
> +#define I386_NTO_SIGCONTEXT_OFFSET 136
> +
> +static CORE_ADDR
> +i386_nto_sigcontext_addr (struct frame_info *frame)
> +{
> +  struct frame_info *next = get_next_frame (frame);
> +
> +  if (next)
> +    return get_frame_base (next) + I386_NTO_SIGCONTEXT_OFFSET;
> +
> +  return read_register (SP_REGNUM) + I386_NTO_SIGCONTEXT_OFFSET;
> +}
> +
> +/* Fetch (and possibly build) an appropriate link_map_offsets
> +   structure for native x86 targets using the struct offsets defined
> +   in link.h (but without actual reference to that file).
> +
> +   This makes it possible to access x86 shared libraries from a GDB
> +   that was not built on an x86 host (for cross debugging).  */
> +
> +static struct link_map_offsets *
> +i386_nto_svr4_fetch_link_map_offsets (void)
> +{
> +  static struct link_map_offsets lmo;
> +  static struct link_map_offsets *lmp = NULL;
> +
> +  if (lmp == NULL)
> +    {
> +      lmp = &lmo;
> +
> +      lmo.r_debug_size = 8; /* The actual size is larger, but this
> +                                   is all we need.  */
> +      lmo.r_map_offset = 4;
> +      lmo.r_map_size = 4;
> +
> +      lmo.link_map_size = 20; /* The actual size is larger bytes,
> +    but this is all we need.  */
> +      lmo.l_addr_offset = 0;
> +      lmo.l_addr_size = 4;
> +
> +      lmo.l_name_offset = 4;
> +      lmo.l_name_size = 4;
> +
> +      lmo.l_next_offset = 12;
> +      lmo.l_next_size = 4;
> +
> +      lmo.l_prev_offset = 16;
> +      lmo.l_prev_size = 4;
> +    }
> +
> +  return lmp;
> +}
> +
> +/* QNX Neutrino (NTO).  */
> +
> +static void
> +i386_nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +
> +  /* NTO uses ELF.  */
> +  i386_elf_init_abi (info, gdbarch);
> +
> +  /* NTO has shared libraries.  */
> +  set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
> +  set_gdbarch_skip_trampoline_code (gdbarch,
find_solib_trampoline_target);
> +
> +  set_gdbarch_pc_in_sigtramp (gdbarch, i386_nto_pc_in_sigtramp);
> +  tdep->sigcontext_addr = i386_nto_sigcontext_addr;
> +  tdep->sc_pc_offset = 56;
> +  tdep->sc_sp_offset = 68;
> +
> +  tdep->jb_pc_offset = 20;
> +
> +  set_solib_svr4_fetch_link_map_offsets (gdbarch,
> + i386_nto_svr4_fetch_link_map_offsets);
> +}
> +
> +
> +/* Provide a prototype to silence -Wmissing-prototypes.  */
> +void _initialize_i386_nto_tdep (void);
> +
> +void
> +_initialize_i386_nto_tdep (void)
> +{
> +  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
> +   i386_nto_init_abi);
> +}
>

[-- Attachment #2: qnx_files.tgz --]
[-- Type: application/x-compressed, Size: 24848 bytes --]

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

* Re: [RFC] QNX Neutrino/i386 support
  2003-03-08 13:45 [RFC] QNX Neutrino/i386 support Mark Kettenis
  2003-03-08 15:02 ` Kris Warkentin
@ 2003-03-08 15:19 ` Kris Warkentin
  2003-03-08 15:22   ` Kris Warkentin
  1 sibling, 1 reply; 11+ messages in thread
From: Kris Warkentin @ 2003-03-08 15:19 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

> I'm still struggling with the shared library stuff.  There's something
> fishy in there, but it seems that the comment in nto-tdep.c is wrong,
> or at least outdated.

There have been some fairly long thread on the mailing list about the solib
issue.  Look for threads 'relocation of shared libs not based at 0' starting
back in November/December and some more recently.  You may be right about
the comment - I should take a look at it again but the long and the short of
it is that we have a slightly different interpretation of the way
relocations are done.  Our chief architect can explain it better but it's
possible that neither interpretation is wrong - one treats two base
addresses as the same, the other doesn't.  Either way, the override of
relocate_section_addresses is ABSOLUTELY required.  If this is not done,
global data in shared objects will be off by a page.

cheers,

Kris


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

* Re: [RFC] QNX Neutrino/i386 support
  2003-03-08 15:19 ` Kris Warkentin
@ 2003-03-08 15:22   ` Kris Warkentin
  0 siblings, 0 replies; 11+ messages in thread
From: Kris Warkentin @ 2003-03-08 15:22 UTC (permalink / raw)
  To: Kris Warkentin, Mark Kettenis; +Cc: gdb-patches

> > I'm still struggling with the shared library stuff.  There's something
> > fishy in there, but it seems that the comment in nto-tdep.c is wrong,
> > or at least outdated.
>
> There have been some fairly long thread on the mailing list about the
solib
> issue.  Look for threads 'relocation of shared libs not based at 0'
starting
> back in November/December and some more recently.  You may be right about
> the comment - I should take a look at it again but the long and the short
of
> it is that we have a slightly different interpretation of the way
> relocations are done.  Our chief architect can explain it better but it's
> possible that neither interpretation is wrong - one treats two base
> addresses as the same, the other doesn't.  Either way, the override of
> relocate_section_addresses is ABSOLUTELY required.  If this is not done,
> global data in shared objects will be off by a page.

Aha.  Found relevant explanation from our chief architect.

http://sources.redhat.com/ml/gdb/2003-02/msg00202.html

cheers,

Kris


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

* Re: [RFC] QNX Neutrino/i386 support
  2003-03-08 15:02 ` Kris Warkentin
@ 2003-03-08 23:49   ` Mark Kettenis
  2003-03-09  0:14   ` Mark Kettenis
  1 sibling, 0 replies; 11+ messages in thread
From: Mark Kettenis @ 2003-03-08 23:49 UTC (permalink / raw)
  To: kewarken; +Cc: gdb-patches

   From: "Kris Warkentin" <kewarken@qnx.com>
   Date: Sat, 8 Mar 2003 10:06:49 -0500

   That's great Mark but what about the native procfs stuff?

Sorry but the native procfs stuff is beyond my maintainership, and I
don't feel confident enough to approve that stuff based on my global
maintainership.

   The most recent patch that I had submitted was a native only
   version.  The only stuff in the i386-nto-tdep.c that was even
   vaguely related to the remote protocol was stuffing the regset type
   in the register area.  This is also used by nto-procfs.c so I
   refactored the regset numbers to be defines that can be used by
   both.

The i386-nto-tdep.c (and the nto-tdep.c for that matter) should only
contain ISA/ABI related code.  You'll probably need some register
mapping functions in there (for interpreting core files), but I fail
to see how the code that's in your proposed i386-nto-tdep.c file is
related to the rest of the stuff.  There just seem to be too many
interdependencies between all the different files.

   The file you have reduced to here is completely useless for any
   form of debugging on Neutrino.  We don't currently support the
   standard gdb debug protocol although it's on our to-do list.  Our
   i386 registers are in a different order that gdb so we need to do
   the mapping.  I have already applied patches to solib.c to do a
   special lookup of target solibs.  Without that support, libs won't
   be found properly.

I understand that, and I'm not asking you to implement the standard
GDB remote protocol before we can add this to GDB.

   BTW, the OSABI stuff is already committed (they gave me write-after
   approval for cvs) - the only stuff left is the addition of new
   files.  I would like to get the config dir stuff, the tdep files,
   the nto-share headers and nto-procfs.c committed.

But I hope you can understand that you can't just drop in those new
files.  Dropping in large chunks of code makes it difficult to get
approval.  If you can split things up in smaller chunks that don't
need approval of several people, you're much more likely to get
approval.  As a benefit you'll probably get code that's structure more
like the way we'd like GDB to evolve.  That's the main reason why I
(and Andrew before me) have asked you to seperate the target-dependent
bits from the native and remote support and ask approval for those
bits seperately.

   What we have currently is something that works perfectly for us.  I
   really don't want to start with something completely broken and
   make additions until it works.  I want to add the working stuff and
   then cut away any fat that we can prove that we don't need.  I
   don't mind doing major refactoring but I want to have working code
   in CVS at all times.  That is something that the GDB project
   strives for and I would like to do for our target as well.

   I've attached a tarball with the files in it.  I think that it's
   pretty much the same as what you have with the changes for the
   remote defines.  I appreciate the time you're putting into this and
   I really want our port to be as clean as it can be.  I know that
   there's lots of work to be done but I'd really rather start from a
   working version and clean from there.  This is one of my highest
   priority projects so I have lots of cycles available to do the work
   but I want to be able to point our customers to the head branch and
   have it work for them.

We have seen in the past that such cleanups hardly ever happen.  Would
it be acceptable for you to check the new files in on a branch and
merge it in bit by bit from there?

Mark


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

* Re: [RFC] QNX Neutrino/i386 support
  2003-03-08 15:02 ` Kris Warkentin
  2003-03-08 23:49   ` Mark Kettenis
@ 2003-03-09  0:14   ` Mark Kettenis
  2003-03-09  4:34     ` Kris Warkentin
  2003-03-09 17:51     ` Kris Warkentin
  1 sibling, 2 replies; 11+ messages in thread
From: Mark Kettenis @ 2003-03-09  0:14 UTC (permalink / raw)
  To: kewarken; +Cc: gdb-patches

Kris,

Here are my comments about the i386-nto-tdep.c file.  Some general
stuff first (which probably applies to the other files as well):

* Please review the GNU and GDB coding standards, there are quite a
  few violations in the QNX files, most notably:

  - Always make comments full sentences.  Start with a capital, end
    with a full stop, and always use two spaces after it, even if its
    the last sentence of the comment.  Format the comments according
    to the GNU coding standards.

  - Use ISO function declarations.

  - Don't use the register keyword.

* Your files should include the blurb about the GPL.  Look at the
  files that are already part of GDB.

My file-specific comments are given below intertwined with bits from
the file itself.  Search for >>> to get at my comments:

/* i386-nto-tdep.c - i386 specific functionality for QNX Neutrino */

/* Copyright 2003 Free Software Foundation */

/* This code was donated by QNX Software Systems Ltd. */

>>> Other files in GDB say "Contributed by XYZ, Inc.", so please
>>> consider using the same style.

#include "defs.h"
#include "gdb_string.h"
#include <fcntl.h>
#include "frame.h"
#include "inferior.h"
#include "bfd.h"
#include "symfile.h"
#include "target.h"
#include "gdb_wait.h"
#include "gdbcmd.h"
#include "objfiles.h"
#include "gdb-stabs.h"
#include "gdbthread.h"
#include "regcache.h"
#include "solib-svr4.h"
#include "dcache.h"
#include "i386-tdep.h"
#include "nto-tdep.h"
#include "osabi.h"

>>> That's a while lot of includes.  I really doubt whether you need
>>> them all.  Please trim.

#ifdef USG
#include <sys/types.h>
#endif

>>> We shouldn't introduce any new uses of the USG define.

#include <signal.h>
#include "serial.h"

#include "nto-share/debug.h"

/* Prototypes for i387_supply_fsave etc.  */
#include "i387-tdep.h"

#ifndef FPC_REGNUM
#define FPC_REGNUM (FP0_REGNUM + 8)
#endif

>>> FPC is already defined by i386-tdep.h.

#define NUM_GPREGS 13
static int gdb_to_nto[NUM_GPREGS] =
  { 7, 6, 5, 4, 11, 2, 1, 0, 8, 10, 9, 12, -1 };

#define GDB_TO_OS(x)	((x >= 0 && x < NUM_GPREGS) ? gdb_to_nto[x] : -1)

#ifndef X86_CPU_FXSR
#define X86_CPU_FXSR (1L << 12)
#endif

extern unsigned nto_cpuinfo_flags;
extern int nto_cpuinfo_valid;
extern int nto_ostype, nto_cputype;

>>> Are these global variables really needed?  If they are, they
>>> probably belong in a header file of some sort, and they would
>>> deserve a comment.


/*
	Given a register return an id that represents the Neutrino regset it came from
	if reg == -1 update all regsets
	$MJC
 */

enum QNX_REGS
{
  QNX_REGS_GP = 0,
  QNX_REGS_FP = 1,
  QNX_REGS_END = 2
};

unsigned
nto_get_regset_id (int regno)
{
  unsigned regset;
  if (regno == -1)
    {				/* return size so we can enumerate */
      regset = 2;
    }
  else if (regno < FP0_REGNUM)
    {
      regset = 0;
    }
  else if (regno < FPC_REGNUM)
    {
      regset = 1;
    }
  else
    {
      regset = -1;		/* error */
    }
  return regset;
}

>>> Personally, I would leave out the braces here.

/* Tell GDB about the regset contained in the 'data' buffer  */
static void
gp_regset_fetch (char *data)
{
  unsigned first_regno;
  for (first_regno = 0; first_regno < FP0_REGNUM; first_regno++)
    {
      int regno = GDB_TO_OS (first_regno);
      int const minusone = -1;

      if (data == NULL || regno == -1)
	{
	  supply_register (first_regno, (char *) &minusone);

>>> GDB's convention is to fill registers with zero instead of -1.  At
>>> least that's what all the other i386 targets do.

	}
      else
	{
	  supply_register (first_regno, &data[regno * 4]);
	}
    }
}

/* get 8087 data */
static void
fp_regset_fetch (char *data)
{
  if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
    i387_supply_fxsave (data);
  else
    i387_supply_fsave (data);
}

void
nto_cpu_regset_fetch (int endian, int regset, void *data)
{
  endian = endian;		/* x86, don't care about endian */

  switch (regset)
    {
    case QNX_REGS_GP:		/* QNX has different ordering of GP regs GDB */
      gp_regset_fetch ((char *) data);
      break;
    case QNX_REGS_FP:
      fp_regset_fetch ((char *) data);
      break;
    }
}

/* get regset characteristics */
unsigned
nto_get_regset_area (unsigned regset, char *subcmd)
{
  unsigned length = 0;
  switch (regset)
    {
    case QNX_REGS_GP:
      *subcmd = NTO_REG_GENERAL;
      length = NUM_GPREGS * sizeof (unsigned);
      break;
    case QNX_REGS_FP:
      *subcmd = NTO_REG_FLOAT;
      /* FIXME: should we calculate based on fxsave/fsave? */
      length = 512;
      break;
    default:
      length = 0;
    }
  return length;
}

/*-
	Given the first and last register number, figure out the size/len
	of the Neutrino register save area to ask for/tell about. Also set
	the register set that's being dealt with in *subcmd. Watch out for
	the range crossing a register set boundry.
 */

unsigned
nto_cpu_register_area (first_regno, last_regno, subcmd, off, len)
     unsigned first_regno;
     unsigned last_regno;
     unsigned char *subcmd;
     unsigned *off;
     unsigned *len;
{
  int regno = -1;

  if (first_regno < FP0_REGNUM)
    {
      if (last_regno >= FP0_REGNUM)
	last_regno = FP0_REGNUM - 1;
      *subcmd = NTO_REG_GENERAL;
      regno = GDB_TO_OS (first_regno);
      *off = regno * sizeof (unsigned);
      if (regno == -1)
	*len = 0;
      else
	*len = (last_regno - first_regno + 1) * sizeof (unsigned);
    }
  else if (first_regno == FP_REGNUM)
    {
      /* Frame Pointer Psuedo-register */
      *off = SP_REGNUM * sizeof (unsigned);
      *len = sizeof (unsigned);
      return FP_REGNUM;
    }
  else if (first_regno >= FP0_REGNUM && first_regno < FPC_REGNUM)
    {
      unsigned off_adjust, regsize;

      if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
	{
	  off_adjust = 32;
	  regsize = 16;
	}
      else
	{
	  off_adjust = 28;
	  regsize = 10;
	}

      if (last_regno >= FPC_REGNUM)
	last_regno = FPC_REGNUM - 1;
      *subcmd = NTO_REG_FLOAT;
      *off = (first_regno - FP0_REGNUM) * regsize + off_adjust;
      *len = (last_regno - first_regno + 1) * 10;
      /* Why 10?  GDB only stores 10 bytes per FP register so if we're
       * sending a register back to the target, we only want pdebug to write
       * 10 bytes so as not to clobber the reserved 6 bytes in the fxsave
       * structure.  The astute reader will note that this will fail if we
       * try to send a range of fpregs rather than 1 at a time but, as far
       * as I know, there is no way to send more than one fpreg at a time
       * anyway.  If this turns out to be wrong, we may need to put more code
       * in pdebug to deal with this - perhaps by masking off part of the
       * register when it writes it in.*/
    }
  else
    {
      *len = 0;
      return last_regno;
    }
  return last_regno;
}

/* Tell GDB about the registers contained in the 'data' buffer  */

void
nto_cpu_register_fetch (endian, first_regno, last_regno, data)
     int endian;
     unsigned first_regno;
     unsigned last_regno;
     void *data;
{
  fprintf_unfiltered (gdb_stderr, "warning: nto_cpu_register_fetch called \
			in remote-nto-i386.c.  This shouldn't happen\n");
  /* If remote-nto-i386.c calls nto_supply_register in remote-nto.c,
   * then remote-nto.c calls nto_cpu_register_fetch.  Since this never
   * happens, this function is left unimplemented. */
}

>>> This comment references remote-i386-nto.c.  There is no such file
>>> in your patch.

/* Build the Neutrino register set info into the 'data' buffer */

int
nto_cpu_register_store (endian, first_regno, last_regno, data)
     int endian;
     unsigned first_regno;
     unsigned last_regno;
     void *data;
{
  /* Mostly (always?) you're only storing one at a time */
  if (first_regno == last_regno)
    {
      regcache_collect (first_regno, data);
      return 1;
    }
  /* Floating point is the same for gdb and target */
  if (first_regno >= FP0_REGNUM)
    {
      for (; first_regno <= last_regno; first_regno++)
	{
	  regcache_collect (first_regno, data);
	  (char *) data += REGISTER_RAW_SIZE (first_regno);
	}
      return 1;
    }
  /* GP registers are mapped differently for NTO than GDB */
  for (; first_regno <= last_regno; first_regno++)
    {
      int regnum = GDB_TO_OS (first_regno);
      if (regnum == -1)
	continue;
      regcache_collect (first_regno,
			(char *) data + sizeof (unsigned) * regnum);
    }
  return 1;
}

/* nto_supply_* are used by nto_procfs.c and nto_core-regset.c */
void
nto_supply_gregset (gregsetp)
     nto_gregset_t *gregsetp;
{
  register int regi, i = 0;
  register unsigned *regp = (unsigned *) gregsetp;

  for (regi = 0; regi < (NUM_REGS - FP0_REGNUM); regi++)
    {
      i = GDB_TO_OS (regi);
      supply_register (regi, (char *) &regp[i]);
    }
}

void
nto_supply_fpregset (fpregsetp)
     nto_fpregset_t *fpregsetp;
{
  if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
    i387_supply_fxsave ((char *) fpregsetp);
  else
    i387_supply_fsave ((char *) fpregsetp);
}

/* Fetch (and possibly build) an appropriate link_map_offsets
   structure for native x86 targets using the struct offsets
   defined in link.h (but without actual reference to that file).

   This makes it possible to access x86 shared libraries from a GDB
   that was not built on an x86 host (for cross debugging).  */

static struct link_map_offsets *
i386_nto_svr4_fetch_link_map_offsets (void)
{
  static struct link_map_offsets lmo;
  static struct link_map_offsets *lmp = NULL;

  if (lmp == NULL)
    {
      lmp = &lmo;

      lmo.r_debug_size = 8;	/* The actual size is 20 bytes, but
				   this is all we need.  */
      lmo.r_map_offset = 4;
      lmo.r_map_size = 4;

      lmo.link_map_size = 20;	/* The actual size is 552 bytes, but
				   this is all we need.  */
      lmo.l_addr_offset = 0;
      lmo.l_addr_size = 4;

      lmo.l_name_offset = 4;
      lmo.l_name_size = 4;

      lmo.l_next_offset = 12;
      lmo.l_next_size = 4;

      lmo.l_prev_offset = 16;
      lmo.l_prev_size = 4;
    }

  return lmp;
}

struct link_map_offsets *
nto_fetch_link_map_offsets (void)
{
  return i386_nto_svr4_fetch_link_map_offsets ();
}

static int
i386_nto_pc_in_sigtramp (CORE_ADDR pc, char *name)
{
  return name && strcmp ("__signalstub", name) == 0;
}

static CORE_ADDR
i386_nto_sigcontext_addr (struct frame_info *frame)
{
  int sigcontext_offset = 136;

  if (get_next_frame (frame))
    return get_frame_base (get_next_frame (frame)) + sigcontext_offset;

  return read_register (SP_REGNUM) + sigcontext_offset;
}

static void
i386_nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  /* NTO uses ELF.  */
  i386_elf_init_abi (info, gdbarch);

  /* neutrino rewinds to look more normal */
  set_gdbarch_decr_pc_after_break (gdbarch, 0);

  /* NTO has shared libraries.  */
  set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);

  set_gdbarch_pc_in_sigtramp (gdbarch, i386_nto_pc_in_sigtramp);
  tdep->sigcontext_addr = i386_nto_sigcontext_addr;
  tdep->sc_pc_offset = 56;
  tdep->sc_sp_offset = 68;

  /* setjmp()'s return PC saved in EDX (5) */
  tdep->jb_pc_offset = 5 * sizeof (int);

>>> You cannot use sizeof(int) here, since that might very well differ
>>> from 4 on other systems.

  set_solib_svr4_fetch_link_map_offsets (gdbarch,
					 i386_nto_svr4_fetch_link_map_offsets);

  /* Our loader handles solib relocations slightly differently than svr4 */
  TARGET_SO_RELOCATE_SECTION_ADDRESSES = nto_relocate_section_addresses;

  /* Supply a nice function to find our solibs */
  TARGET_SO_FIND_AND_OPEN_SOLIB = nto_find_and_open_solib;

/* After a watchpoint trap, the PC points to the instruction after
   the one that caused the trap.  Therefore we don't need to step over it.
   But we do need to reset the status register to avoid another trap.  */
  HAVE_CONTINUABLE_WATCHPOINT = 1;

>>> This HAVE_CONTINUABLE_WATCHPOINT stuff has been moved to the
>>> target vector, so that's where you should provide the appropriate
>>> definition.

}

void
_initialize_i386_nto_tdep (void)
{
  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
			  i386_nto_init_abi);

  /* read our extra gdbinit file */
  nto_source_extra_gdbinit (".ntox86-gdbinit");

>>> This extra-gdbinit-stuff doesn't belong here.  We have had a
>>> discussion about these target-dependent init files recently, and I
>>> believe the outcome was that if they were wanted, some general
>>> mechanism should be added rather than these kind of ad-hoc hacks.

}


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

* Re: [RFC] QNX Neutrino/i386 support
  2003-03-09  0:14   ` Mark Kettenis
@ 2003-03-09  4:34     ` Kris Warkentin
  2003-03-09 17:51     ` Kris Warkentin
  1 sibling, 0 replies; 11+ messages in thread
From: Kris Warkentin @ 2003-03-09  4:34 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

> * Your files should include the blurb about the GPL.  Look at the
>   files that are already part of GDB.

I had just looked at the vxworks files.  I should have looked at a few
others.

> #ifdef USG
> #include <sys/types.h>
> #endif
>
> >>> We shouldn't introduce any new uses of the USG define.

What should I check for?  Is there a HAVE_SYS_TYPES define or some such?

> extern unsigned nto_cpuinfo_flags;
> extern int nto_cpuinfo_valid;
> extern int nto_ostype, nto_cputype;
>
> >>> Are these global variables really needed?  If they are, they
> >>> probably belong in a header file of some sort, and they would
> >>> deserve a comment.

Actually, they're in nto-tdep.h.  I just missed removing the externs.  As
far as whether they're needed, they just help us work around a few ugly
issues like whether the remote supports fxsave or not.  Also used to figure
out remote targets when using qnet, our "transparent" networking protocol
where you could do something like 'target procfs /net/some_machine'.  There
are probably better ways of doing these things.  That's where you guys come
in - to help me remove hacks. ;-)  I'll definitely make some comments.

>   else
>     {
>       regset = -1; /* error */
>     }
>   return regset;
> }
>
> >>> Personally, I would leave out the braces here.

Eew.  Good thing I didn't write that function. ;-)  There have been many
fingers in these pies and clean up is not fun.  You should see our mips and
sh support....

>   supply_register (first_regno, (char *) &minusone);
>
> >>> GDB's convention is to fill registers with zero instead of -1.  At
> >>> least that's what all the other i386 targets do.

I think that the -1 might have been from a long long time ago.  These files
were originally from gdb 4.17 or earlier.

>   /* If remote-nto-i386.c calls nto_supply_register in remote-nto.c,
>    * then remote-nto.c calls nto_cpu_register_fetch.  Since this never
>    * happens, this function is left unimplemented. */

> >>> This comment references remote-i386-nto.c.  There is no such file
> >>> in your patch.

My register refactoring eliminated this function last week.  The register
refactoring is on our head branch which I need to port to my FSF submission
branch....some of it also needs to be back ported to our previous release
branch....  Arghh....too many trees make Kris go crazy....

>   /* setjmp()'s return PC saved in EDX (5) */
>   tdep->jb_pc_offset = 5 * sizeof (int);
>
> >>> You cannot use sizeof(int) here, since that might very well differ
> >>> from 4 on other systems.

Ooh...good catch.  That might spank me on sparc64.

> /* After a watchpoint trap, the PC points to the instruction after
>    the one that caused the trap.  Therefore we don't need to step over it.
>    But we do need to reset the status register to avoid another trap.  */
>   HAVE_CONTINUABLE_WATCHPOINT = 1;
>
> >>> This HAVE_CONTINUABLE_WATCHPOINT stuff has been moved to the
> >>> target vector, so that's where you should provide the appropriate
> >>> definition.

I did the target vector patch but I guess I don't know where this should
have gone...Help?

>   /* read our extra gdbinit file */
>   nto_source_extra_gdbinit (".ntox86-gdbinit");
>
> >>> This extra-gdbinit-stuff doesn't belong here.  We have had a
> >>> discussion about these target-dependent init files recently, and I
> >>> believe the outcome was that if they were wanted, some general
> >>> mechanism should be added rather than these kind of ad-hoc hacks.

This is not a critical feature and can be removed for an FSF submission
pending a better way of doing it.  I could volunteer to try and find one.

Thanks for the commentary Mark.  I'm on semi-vacation next week (AFK Monday,
Wednesday, Friday) but I'll try to keep this flowing.

cheers,

Kris


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

* Re: [RFC] QNX Neutrino/i386 support
  2003-03-09  0:14   ` Mark Kettenis
  2003-03-09  4:34     ` Kris Warkentin
@ 2003-03-09 17:51     ` Kris Warkentin
  2003-03-19 18:19       ` Kris Warkentin
  1 sibling, 1 reply; 11+ messages in thread
From: Kris Warkentin @ 2003-03-09 17:51 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

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

> Here are my comments about the i386-nto-tdep.c file.  Some general
> stuff first (which probably applies to the other files as well):

Hi Mark,

I've done the cleaning that you proposed and attached the revised files.
I'm not really fond of the branch and merging idea so if you really don't
want to put all of this stuff in, we'll rip everything out, start with the
minimum and work up from there.

Kris

[-- Attachment #2: nto-tdep.c --]
[-- Type: application/octet-stream, Size: 8792 bytes --]

/* nto-tdep.c - general QNX Neutrino target functionality */

/* Copyright 2003 Free Software Foundation */

/* Contributed by QNX Software Systems Ltd. */

#include <sys/stat.h>
#include "nto-tdep.h"
#include "top.h"
#include "cli/cli-decode.h"
#include "cli/cli-cmds.h"
#include "inferior.h"
#include "gdbarch.h"
#include "bfd.h"
#include "elf-bfd.h"
#include "solib-svr4.h"
#include "gdbcore.h"

#ifdef __CYGWIN__
#include <sys/cygwin.h>
#endif

#ifdef __CYGWIN__
static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
#elif defined(__sun__) || defined(linux)
static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
#else
static char default_nto_target[] = "";
#endif

/* Maintenance debugging flag */
int nto_internal_debugging;

/* Filled in cpu info structure and flag to indicate its validity. 
 * This is initialized in procfs_attach or nto_start_remote depending on
 * our host/target.  It would only be invalid if we were talking to an
 * older pdebug which didn't support the cpuinfo message. */
unsigned nto_cpuinfo_flags;
int nto_cpuinfo_valid;

static char *
nto_target (void)
{
  char *p = getenv ("QNX_TARGET");

#ifdef __CYGWIN__
  static char buf[PATH_MAX];
  if (p)
    cygwin_conv_to_posix_path (p, buf);
  else
    cygwin_conv_to_posix_path (default_nto_target, buf);
  return buf;
#else
  return p ? p : default_nto_target;
#endif
}

/* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86,
   CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h. */
int
nto_map_arch_to_cputype(const char *arch)
{
  if(!strcmp(arch, "i386") || !strcmp(arch, "x86"))
    return CPUTYPE_X86;
  if(!strcmp(arch, "rs6000") || !strcmp(arch, "ppc"))
    return CPUTYPE_PPC;
  if(!strcmp(arch, "mips"))
    return CPUTYPE_MIPS;
  if(!strcmp(arch, "arm"))
    return CPUTYPE_ARM;
  if(!strcmp(arch, "sh"))
    return CPUTYPE_SH;
  return CPUTYPE_UNKNOWN;
}

int
nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
{
  char *buf, arch_path[PATH_MAX], *nto_root, *endian;
  const char *arch;
  char *path_fmt = "%s/lib:%s/usr/lib:%s/usr/photon/lib\
:%s/usr/photon/dll:%s/lib/dll";

  nto_root = nto_target ();
  if (strcmp (TARGET_ARCHITECTURE->arch_name, "i386") == 0)
    {
      arch = "x86";
      endian = "";
    }
  else if (strcmp (TARGET_ARCHITECTURE->arch_name, "rs6000") == 0)
    {
      arch = "ppc";
      endian = "be";
    }
  else
    {
      arch = TARGET_ARCHITECTURE->arch_name;
      endian = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "be" : "le";
    }

  sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);

  buf = alloca (strlen(path_fmt) + strlen(arch_path) * 5 + 1);
  sprintf (buf, path_fmt, arch_path, arch_path, arch_path, arch_path, arch_path);

  return openp(buf, 1, solib, o_flags, 0, temp_pathname);
}

void
nto_init_solib_absolute_prefix (void)
{
  char buf[PATH_MAX * 2], arch_path[PATH_MAX];
  char *nto_root, *endian;
  const char *arch;

  nto_root = nto_target ();
  if (strcmp (TARGET_ARCHITECTURE->arch_name, "i386") == 0)
    {
      arch = "x86";
      endian = "";
    }
  else if (strcmp (TARGET_ARCHITECTURE->arch_name, "rs6000") == 0)
    {
      arch = "ppc";
      endian = "be";
    }
  else
    {
      arch = TARGET_ARCHITECTURE->arch_name;
      endian = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "be" : "le";
    }

  sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);

  sprintf (buf, "set solib-absolute-prefix %s", arch_path);
  execute_command (buf, 0);
}

char **
nto_parse_redirection (char *pargv[], char **pin, char **pout, char **perr)
{
  char **argv;
  char *in, *out, *err, *p;
  int argc, i, n;

  for (n = 0; pargv[n]; n++);
  if (n == 0)
    return NULL;
  in = "";
  out = "";
  err = "";

  argv = xcalloc (n + 1, sizeof argv[0]);
  argc = n;
  for (i = 0, n = 0; n < argc; n++)
    {
      p = pargv[n];
      if (*p == '>')
	{
	  p++;
	  if (*p)
	    out = p;
	  else
	    out = pargv[++n];
	}
      else if (*p == '<')
	{
	  p++;
	  if (*p)
	    in = p;
	  else
	    in = pargv[++n];
	}
      else if (*p++ == '2' && *p++ == '>')
	{
	  if (*p == '&' && *(p + 1) == '1')
	    err = out;
	  else if (*p)
	    err = p;
	  else
	    err = pargv[++n];
	}
      else
	argv[i++] = pargv[n];
    }
  *pin = in;
  *pout = out;
  *perr = err;
  return argv;
}

void
nto_source_extra_gdbinit (char *file)
{
  char *homedir, *homeinit;
  struct stat statbuf;

  homedir = getenv ("HOME");

  if (homedir && !inhibit_gdbinit)
    {
      homeinit = (char *) alloca (strlen (homedir) + strlen (file) + 10);
      sprintf (homeinit, "%s/%s", homedir, file);
      if (stat (homeinit, &statbuf) == 0)
	catch_command_errors (source_command, homeinit, 0, RETURN_MASK_ALL);
    }
}

/* struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from
   solib-svr4.c to support nto_relocate_section_addresses
   which is different from the svr4 version. */

struct lm_info
{
  /* Pointer to copy of link map from inferior.  The type is char *
     rather than void *, so that we may use byte offsets to find the
     various fields without the need for a cast.  */
  char *lm;
};

static CORE_ADDR
LM_ADDR (struct so_list *so)
{
  struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();

  return (CORE_ADDR) extract_signed_integer (so->lm_info->lm +
					     lmo->l_addr_offset,
					     lmo->l_addr_size);
}

static CORE_ADDR
nto_truncate_ptr (CORE_ADDR addr)
{
  if (TARGET_PTR_BIT == sizeof (CORE_ADDR) * 8)
    /* We don't need to truncate anything, and the bit twiddling below
       will fail due to overflow problems.  */
    return addr;
  else
    return addr & (((CORE_ADDR) 1 << TARGET_PTR_BIT) - 1);
}

Elf_Internal_Phdr *
find_load_phdr (bfd *abfd)
{
  Elf_Internal_Phdr *phdr;
  unsigned int i;

  if (!elf_tdata (abfd))
    return NULL;

  phdr = elf_tdata (abfd)->phdr;
  for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
    {
      if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
	return phdr;
    }
  return NULL;
}

void
nto_relocate_section_addresses (struct so_list *so, struct section_table *sec)
{
  /* Neutrino treats the l_addr base address field in link.h as different than
     the base address in the System V ABI and so the offset needs to be
     calculated and applied to relocations.  */
  Elf_Internal_Phdr *phdr = find_load_phdr (sec->bfd);
  unsigned vaddr = phdr ? phdr->p_vaddr : 0;

  sec->addr = nto_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
  sec->endaddr = nto_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
}

static void
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
  int which, CORE_ADDR reg_addr)
{
  nto_gregset_t gregset;
  nto_fpregset_t fpregset;

  nto_init_solib_absolute_prefix ();

  if (which == 0)
    {
      memcpy ((char *) &gregset, core_reg_sect,
	      min (core_reg_size, sizeof (gregset)));
      nto_supply_gregset (&gregset);
    }
  else if (which == 2)
    {
      memcpy ((char *) &fpregset, core_reg_sect,
	      min (core_reg_size, sizeof (fpregset)));
      nto_supply_fpregset (&fpregset);
    }
}

/* Register that we are able to handle ELF file formats using standard
   procfs "regset" structures.  */

static struct core_fns regset_core_fns = {
  bfd_target_elf_flavour,	/* core_flavour */
  default_check_format,		/* check_format */
  default_core_sniffer,		/* core_sniffer */
  fetch_core_registers,		/* core_read_registers */
  NULL				/* next */
};

void
_initialize_nto_tdep ()
{
  add_show_from_set (add_set_cmd ("nto-debug", class_maintenance, var_zinteger, (char *) &nto_internal_debugging, "Set QNX NTO internal debugging.\n\
When non-zero, nto specific debug info is\n\
displayed. Different information is displayed\n\
for different positive values.", &setdebuglist),
		     &showdebuglist);

  /* We use SIG45 for pulses, or something, so nostop, noprint
     and pass them. */
  signal_stop_update (target_signal_from_name ("SIG45"), 0);
  signal_print_update (target_signal_from_name ("SIG45"), 0);
  signal_pass_update (target_signal_from_name ("SIG45"), 1);

  /* By default we don't want to stop on these two, but we do want to pass. */
#if defined(SIGSELECT)
  signal_stop_update (SIGSELECT, 0);
  signal_print_update (SIGSELECT, 0);
  signal_pass_update (SIGSELECT, 1);
#endif

#if defined(SIGPHOTON)
  signal_stop_update (SIGPHOTON, 0);
  signal_print_update (SIGPHOTON, 0);
  signal_pass_update (SIGPHOTON, 1);
#endif

  /* Register core file support. */
  add_core_fns (&regset_core_fns);
}

[-- Attachment #3: nto-tdep.h --]
[-- Type: application/octet-stream, Size: 1894 bytes --]

/* nto-tdep.h - QNX Neutrino target header */

/* Copyright 2003 Free Software Foundation */

/* Contributed by QNX Software Systems Ltd. */

#ifndef _NTO_TDEP_H
#define _NTO_TDEP_H

#include "defs.h"
#include "nto-share/debug.h"
#include "solist.h"

/* Generic functions in nto-tdep.c. */

extern void nto_init_solib_absolute_prefix PARAMS ((void));

char **nto_parse_redirection
PARAMS ((char *start_argv[], char **in, char **out, char **err));

int proc_iterate_over_mappings PARAMS ((int (*func) (int, CORE_ADDR)));

void nto_source_extra_gdbinit PARAMS ((char *));

void nto_relocate_section_addresses
PARAMS ((struct so_list *, struct section_table *));

int nto_map_arch_to_cputype PARAMS((const char *));

int nto_find_and_open_solib PARAMS((char *, unsigned, char **));

/* Functions exported from all Neutrino targets (<target>-nto-tdep.c). */

unsigned nto_get_regset_id PARAMS ((int regno));

void nto_cpu_regset_fetch PARAMS ((int endian, int regset, void *data));

unsigned nto_get_regset_area PARAMS ((unsigned regset, char *subcmd));

unsigned nto_cpu_register_area
PARAMS ((unsigned first_regno, unsigned last_regno, unsigned char *subcmd,
	 unsigned *off, unsigned *len));

int nto_cpu_register_store
PARAMS ((int endian, unsigned first_regno, unsigned last_regno, void *data));

void nto_supply_gregset PARAMS ((union _debug_gregs *));

void nto_supply_fpregset PARAMS ((union _debug_fpregs *));

struct link_map_offsets *nto_fetch_link_map_offsets PARAMS ((void));

/* Globals. */

/* For 'maintenance debug nto-debug' command. */
extern int nto_internal_debugging;

/* The CPUINFO flags from the remote.  Currently used by
   i386 for fxsave but future proofing other hosts */
extern unsigned nto_cpuinfo_flags;

/* True if successfully retrieved cpuinfo from remote */
extern int nto_cpuinfo_valid;

#endif

[-- Attachment #4: i386-nto-tdep.c --]
[-- Type: application/octet-stream, Size: 9401 bytes --]

/* i386-nto-tdep.c - i386 specific functionality for QNX Neutrino */

/* Copyright 2003 Free Software Foundation */

/* Contributed by QNX Software Systems Ltd. */

#include "defs.h"
#include "frame.h"
#include "target.h"
#include "regcache.h"
#include "solib-svr4.h"
#include "i386-tdep.h"
#include "nto-tdep.h"
#include "osabi.h"
#include "nto-share/debug.h"
#include "i387-tdep.h"

#define NUM_GPREGS 13
static int gdb_to_nto[NUM_GPREGS] =
  { 7, 6, 5, 4, 11, 2, 1, 0, 8, 10, 9, 12, -1 };

#define GDB_TO_OS(x)	((x >= 0 && x < NUM_GPREGS) ? gdb_to_nto[x] : -1)

#ifndef X86_CPU_FXSR
#define X86_CPU_FXSR (1L << 12)
#endif

enum QNX_REGS
{
  QNX_REGS_GP = 0,
  QNX_REGS_FP = 1,
  QNX_REGS_END = 2
};

/* Given a register, return an id that represents the Neutrino
   regset it came from.  If reg == -1 update all regsets.  */
unsigned
nto_get_regset_id (int regno)
{
  if (regno == -1)
    return QNX_REGS_END;
  else if (regno < FP0_REGNUM)
    return QNX_REGS_GP;
  else if (regno < FPC_REGNUM)
    return QNX_REGS_FP;

  return -1; /* error */
}

/* Tell GDB about the regset contained in the 'data' buffer.  */
static void
gp_regset_fetch (char *data)
{
  unsigned first_regno;

  for (first_regno = 0; first_regno < FP0_REGNUM; first_regno++)
    {
      int regno = GDB_TO_OS (first_regno);
      int const blank = 0;

      if (data == NULL || regno == -1)
	  supply_register (first_regno, (char *) &blank);
      else
	  supply_register (first_regno, &data[regno * 4]);
    }
}

/* Get 8087 data.  */
static void
fp_regset_fetch (char *data)
{
  if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
    i387_supply_fxsave (data);
  else
    i387_supply_fsave (data);
}

void
nto_cpu_regset_fetch (int endian, int regset, void *data)
{
  endian = endian;  /* For i386, we don't care about endian. */

  switch (regset)
    {
    case QNX_REGS_GP:  /* QNX has different ordering of GP regs than GDB. */
      gp_regset_fetch ((char *) data);
      break;
    case QNX_REGS_FP:
      fp_regset_fetch ((char *) data);
      break;
    }
}

/* Get regset characteristics. */
unsigned
nto_get_regset_area (unsigned regset, char *subcmd)
{
  unsigned length = 0;
  switch (regset)
    {
    case QNX_REGS_GP:
      *subcmd = NTO_REG_GENERAL;
      length = NUM_GPREGS * sizeof (unsigned);
      break;
    case QNX_REGS_FP:
      *subcmd = NTO_REG_FLOAT;
      /* FIXME: should we calculate based on fxsave/fsave? */
      length = 512;
      break;
    default:
      length = 0;
    }
  return length;
}

/* Given the first and last register number, figure out the size/len
   of the Neutrino register save area to ask for/tell about.  Also set
   the register set that's being dealt with in *subcmd.  Watch out for
   the range crossing a register set boundry.  */
unsigned
nto_cpu_register_area (unsigned first_regno, unsigned last_regno, 
  unsigned char *subcmd, unsigned *off, unsigned *len)
{
  int regno = -1;

  if (first_regno < FP0_REGNUM)
    {
      if (last_regno >= FP0_REGNUM)
	last_regno = FP0_REGNUM - 1;
      *subcmd = NTO_REG_GENERAL;
      regno = GDB_TO_OS (first_regno);
      *off = regno * sizeof (unsigned);
      if (regno == -1)
	*len = 0;
      else
	*len = (last_regno - first_regno + 1) * sizeof (unsigned);
    }
  else if (first_regno == FP_REGNUM)
    {
      /* Frame Pointer Psuedo-register */
      *off = SP_REGNUM * sizeof (unsigned);
      *len = sizeof (unsigned);
      return FP_REGNUM;
    }
  else if (first_regno >= FP0_REGNUM && first_regno < FPC_REGNUM)
    {
      unsigned off_adjust, regsize;

      if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
	{
	  off_adjust = 32;
	  regsize = 16;
	}
      else
	{
	  off_adjust = 28;
	  regsize = 10;
	}

      if (last_regno >= FPC_REGNUM)
	last_regno = FPC_REGNUM - 1;
      *subcmd = NTO_REG_FLOAT;
      *off = (first_regno - FP0_REGNUM) * regsize + off_adjust;
      *len = (last_regno - first_regno + 1) * 10;
      /* Why 10?  GDB only stores 10 bytes per FP register so if we're
         sending a register back to the target, we only want pdebug to write
         10 bytes so as not to clobber the reserved 6 bytes in the fxsave
         structure.  The astute reader will note that this will fail if we
         try to send a range of fpregs rather than 1 at a time but, as far
         as I know, there is no way to send more than one fpreg at a time
         anyway.  If this turns out to be wrong, we may need to put more code
         in pdebug to deal with this - perhaps by masking off part of the
         register when it writes it in.*/
    }
  else
    {
      *len = 0;
      return last_regno;
    }
  return last_regno;
}

/* Build the Neutrino register set info into the 'data' buffer. */
int
nto_cpu_register_store (int endian, unsigned first_regno,
  unsigned last_regno, void *data)
{
  /* Mostly (always?) you're only storing one at a time. */
  if (first_regno == last_regno)
    {
      regcache_collect (first_regno, data);
      return 1;
    }
  /* Floating point is the same for gdb and target */
  if (first_regno >= FP0_REGNUM)
    {
      for (; first_regno <= last_regno; first_regno++)
	{
	  regcache_collect (first_regno, data);
	  (char *) data += REGISTER_RAW_SIZE (first_regno);
	}
      return 1;
    }
  /* GP registers are mapped differently for NTO than GDB */
  for (; first_regno <= last_regno; first_regno++)
    {
      int regnum = GDB_TO_OS (first_regno);
      if (regnum == -1)
	continue;
      regcache_collect (first_regno,
			(char *) data + sizeof (unsigned) * regnum);
    }
  return 1;
}

void
nto_supply_gregset (nto_gregset_t *gregsetp)
{
  int regi, i = 0;
  unsigned *regp = (unsigned *) gregsetp;

  for (regi = 0; regi < (NUM_REGS - FP0_REGNUM); regi++)
    {
      i = GDB_TO_OS (regi);
      supply_register (regi, (char *) &regp[i]);
    }
}

void
nto_supply_fpregset (nto_fpregset_t *fpregsetp)
{
  if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
    i387_supply_fxsave ((char *) fpregsetp);
  else
    i387_supply_fsave ((char *) fpregsetp);
}

/* Fetch (and possibly build) an appropriate link_map_offsets
   structure for native x86 targets using the struct offsets
   defined in link.h (but without actual reference to that file).

   This makes it possible to access x86 shared libraries from a GDB
   that was not built on an x86 host (for cross debugging).  */

static struct link_map_offsets *
i386_nto_svr4_fetch_link_map_offsets (void)
{
  static struct link_map_offsets lmo;
  static struct link_map_offsets *lmp = NULL;

  if (lmp == NULL)
    {
      lmp = &lmo;

      lmo.r_debug_size = 8;	/* The actual size is 20 bytes, but
				   this is all we need.  */
      lmo.r_map_offset = 4;
      lmo.r_map_size = 4;

      lmo.link_map_size = 20;	/* The actual size is 552 bytes, but
				   this is all we need.  */
      lmo.l_addr_offset = 0;
      lmo.l_addr_size = 4;

      lmo.l_name_offset = 4;
      lmo.l_name_size = 4;

      lmo.l_next_offset = 12;
      lmo.l_next_size = 4;

      lmo.l_prev_offset = 16;
      lmo.l_prev_size = 4;
    }

  return lmp;
}

struct link_map_offsets *
nto_fetch_link_map_offsets (void)
{
  return i386_nto_svr4_fetch_link_map_offsets ();
}

static int
i386_nto_pc_in_sigtramp (CORE_ADDR pc, char *name)
{
  return name && strcmp ("__signalstub", name) == 0;
}

static CORE_ADDR
i386_nto_sigcontext_addr (struct frame_info *frame)
{
  int sigcontext_offset = 136;

  if (get_next_frame (frame))
    return get_frame_base (get_next_frame (frame)) + sigcontext_offset;

  return read_register (SP_REGNUM) + sigcontext_offset;
}

static void
i386_nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  /* NTO uses ELF.  */
  i386_elf_init_abi (info, gdbarch);

  /* neutrino rewinds to look more normal */
  set_gdbarch_decr_pc_after_break (gdbarch, 0);

  /* NTO has shared libraries.  */
  set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);

  set_gdbarch_pc_in_sigtramp (gdbarch, i386_nto_pc_in_sigtramp);
  tdep->sigcontext_addr = i386_nto_sigcontext_addr;
  tdep->sc_pc_offset = 56;
  tdep->sc_sp_offset = 68;

  /* setjmp()'s return PC saved in EDX (5) */
  tdep->jb_pc_offset = 20; /* 5x32 bit ints in. */

  set_solib_svr4_fetch_link_map_offsets (gdbarch,
					 i386_nto_svr4_fetch_link_map_offsets);

  /* Our loader handles solib relocations slightly differently than svr4 */
  TARGET_SO_RELOCATE_SECTION_ADDRESSES = nto_relocate_section_addresses;

  /* Supply a nice function to find our solibs */
  TARGET_SO_FIND_AND_OPEN_SOLIB = nto_find_and_open_solib;

/* After a watchpoint trap, the PC points to the instruction after
   the one that caused the trap.  Therefore we don't need to step over it.
   But we do need to reset the status register to avoid another trap.  */
  HAVE_CONTINUABLE_WATCHPOINT = 1;
}

void
_initialize_i386_nto_tdep (void)
{
  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
			  i386_nto_init_abi);
}

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

* Re: [RFC] QNX Neutrino/i386 support
  2003-03-09 17:51     ` Kris Warkentin
@ 2003-03-19 18:19       ` Kris Warkentin
  2003-03-19 18:27         ` Mark Kettenis
  0 siblings, 1 reply; 11+ messages in thread
From: Kris Warkentin @ 2003-03-19 18:19 UTC (permalink / raw)
  To: Kris Warkentin, Mark Kettenis; +Cc: gdb-patches

> > Here are my comments about the i386-nto-tdep.c file.  Some general
> > stuff first (which probably applies to the other files as well):
>
> Hi Mark,
>
> I've done the cleaning that you proposed and attached the revised files.
> I'm not really fond of the branch and merging idea so if you really don't
> want to put all of this stuff in, we'll rip everything out, start with the
> minimum and work up from there.

Ping?


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

* Re: [RFC] QNX Neutrino/i386 support
  2003-03-19 18:19       ` Kris Warkentin
@ 2003-03-19 18:27         ` Mark Kettenis
  0 siblings, 0 replies; 11+ messages in thread
From: Mark Kettenis @ 2003-03-19 18:27 UTC (permalink / raw)
  To: kewarken; +Cc: kewarken, gdb-patches

   From: "Kris Warkentin" <kewarken@qnx.com>
   Cc: <gdb-patches@sources.redhat.com>
   Date: Wed, 19 Mar 2003 13:19:23 -0500
   Content-Type: text/plain;
	   charset="iso-8859-1"
   X-Priority: 3
   X-MSMail-Priority: Normal
   X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106

   > > Here are my comments about the i386-nto-tdep.c file.  Some general
   > > stuff first (which probably applies to the other files as well):
   >
   > Hi Mark,
   >
   > I've done the cleaning that you proposed and attached the revised files.
   > I'm not really fond of the branch and merging idea so if you really don't
   > want to put all of this stuff in, we'll rip everything out, start with the
   > minimum and work up from there.

   Ping?

Sorry Kris, I'm extremely busy right now (there are still too many
notes in Bruckner's 6th symphony that I can't play yet :().  I won't
be able to do any serious work on GDB done in the next two weeks.

I hope I'll be able to look into things after April 5.

Mark


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

* Re: [RFC] QNX Neutrino/i386 support
@ 2003-03-09 14:54 Kris Warkentin
  0 siblings, 0 replies; 11+ messages in thread
From: Kris Warkentin @ 2003-03-09 14:54 UTC (permalink / raw)
  To: gdb-patches

> Sorry but the native procfs stuff is beyond my maintainership, and I
> don't feel confident enough to approve that stuff based on my global
> maintainership.

Okay.  I guess I'll have to wait for someone else to pipe up.

> The i386-nto-tdep.c (and the nto-tdep.c for that matter) should only
> contain ISA/ABI related code.  You'll probably need some register
> mapping functions in there (for interpreting core files), but I fail
> to see how the code that's in your proposed i386-nto-tdep.c file is
> related to the rest of the stuff.  There just seem to be too many
> interdependencies between all the different files.

Okay, I can see that.  One of the things I've been working on is untying all
our register stuff (in our own tree) because it bounces back and forth
between files so I can relate to how nasty that gets.  All there is in
i386-nto-tdep.c however is the link map stuff and the register fetch/store
functions which many tdep files have.  I just happen to do a little extra
calculating to report back regset numbers and sizes, etc. that are handy for
nto-procfs and remote-nto to know.

My plan was to have all the generic stuff in nto-tdep.c and then have hooks
for register store/fetch in the <arch>-nto-tdep.c files.  This way
nto-procfs.c and remote-nto.c get to take advantage of the same files.
Forgive my bad ascii art but we have:

nto-procfs.c__                  _i386-nto-tdep.c
              \_nto-tdep.[ch]__/_sh-nto-tdep.c
remote-nto.c__/                \_mips-nto-tdep.c, arm, ppc, ...

Where the nto-tdep.h is the interface to the arch specific back ends.

> That's the main reason why I
> (and Andrew before me) have asked you to seperate the target-dependent
> bits from the native and remote support and ask approval for those
> bits seperately.

Alright.  I had understood that you wanted me to separate the native from
the remote but perhaps I misunderstood.  If you would like to do it this
way, it's fine by me.

> We have seen in the past that such cleanups hardly ever happen.  Would
> it be acceptable for you to check the new files in on a branch and
> merge it in bit by bit from there?

I hope that I will eventually earn your trust but I can see your point.
Tell you what, how about you add the file as you presented it to me and then
I will start submitting additions to you.  Trust is a two way street so I
will trust you to do the right thing and help me get our support in and
working.

cheers,

Kris


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

end of thread, other threads:[~2003-03-19 18:27 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-03-08 13:45 [RFC] QNX Neutrino/i386 support Mark Kettenis
2003-03-08 15:02 ` Kris Warkentin
2003-03-08 23:49   ` Mark Kettenis
2003-03-09  0:14   ` Mark Kettenis
2003-03-09  4:34     ` Kris Warkentin
2003-03-09 17:51     ` Kris Warkentin
2003-03-19 18:19       ` Kris Warkentin
2003-03-19 18:27         ` Mark Kettenis
2003-03-08 15:19 ` Kris Warkentin
2003-03-08 15:22   ` Kris Warkentin
2003-03-09 14:54 Kris Warkentin

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