This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: corelow and threads question


Pedro Alves wrote:
On Friday 05 June 2009 19:54:54, Aleksandar Ristovski wrote:

With corelow.c patched as proposed, on Neutrino I could do this:

For NTO, I "hijack" core_ops:
static void
init_nto_core_ops ()
{
   struct target_ops *core_ops;

core_ops = find_core_target ();
gdb_assert (core_ops && core_ops->to_shortname != NULL
&& !!"core_ops must be initialized first!");
original_core_ops = *core_ops;
core_ops->to_extra_thread_info = nto_target_extra_thread_info;
core_ops->to_open = nto_core_open;
core_ops->to_xfer_partial = nto_core_xfer_partial;
core_ops->to_pid_to_str = nto_pid_to_str;
}

As I mentioned in the other threads, this is fine as a local change, but not so to have in GDB proper, so it does go against your goal of pushing all your local changes. :-/

This is depending on the order of which the _initialize
routines are called, hence the gdb_assert.  I just cleaned
up the only left over target that was doing a similar hack
(sol-threads.c) a couple of months ago, to not do so.

Again, it's hard to come up with a better alternative
without knowing what you're doing in those overrides.  Maybe
what you need is a thread_stratum target sitting on top of
nto-procfs.c or corelow.c.  Maybe we need new gdbarch
callbacks.


Ok, I attached my nto-diff (work-in-progress) that compile with current gdb HEAD sources (with some tweaks in configure scripts). You will see all my hacks there.


I am inclined to think that core_ops is the right way to go; at which point should I do a "push_target" in that case?




-- Aleksandar Ristovski QNX Software Systems
Index: gdb/corelow.c
===================================================================
RCS file: /cvs/src/src/gdb/corelow.c,v
retrieving revision 1.86
diff -u -p -r1.86 corelow.c
--- gdb/corelow.c	5 Jun 2009 18:08:53 -0000	1.86
+++ gdb/corelow.c	5 Jun 2009 19:37:14 -0000
@@ -395,12 +395,6 @@ core_open (char *filename, int from_tty)
      previous session, and the frame cache being stale.  */
   registers_changed ();
 
-  /* Build up thread list from BFD sections, and possibly set the
-     current thread to the .reg/NN section matching the .reg
-     section. */
-  bfd_map_over_sections (core_bfd, add_to_thread_list,
-			 bfd_get_section_by_name (core_bfd, ".reg"));
-
   post_create_inferior (&core_ops, from_tty);
 
   /* Now go through the target stack looking for threads since there
@@ -748,6 +742,13 @@ core_pid_to_str (struct target_ops *ops,
   return buf;
 }
 
+static void
+core_find_new_threads (struct target_ops *ops)
+{
+  if (core_bfd)
+    bfd_map_over_sections (core_bfd, add_to_thread_list, NULL);
+}
+
 /* Fill in core_ops with its defined operations and properties.  */
 
 static void
@@ -775,6 +776,7 @@ init_core_ops (void)
   core_ops.to_has_stack = 1;
   core_ops.to_has_registers = 1;
   core_ops.to_magic = OPS_MAGIC;
+  core_ops.to_find_new_threads = core_find_new_threads;
 }
 
 void
Index: gdb/i386-nto-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-nto-tdep.c,v
retrieving revision 1.32
diff -u -p -r1.32 i386-nto-tdep.c
--- gdb/i386-nto-tdep.c	22 Feb 2009 01:02:17 -0000	1.32
+++ gdb/i386-nto-tdep.c	5 Jun 2009 19:37:14 -0000
@@ -33,9 +33,7 @@
 #include "nto-tdep.h"
 #include "solib.h"
 #include "solib-svr4.h"
-
-/* Target vector for QNX NTO x86.  */
-static struct nto_target_ops i386_nto_target;
+#include "elf-bfd.h"
 
 #ifndef X86_CPU_FXSR
 #define X86_CPU_FXSR (1L << 12)
@@ -126,6 +124,8 @@ i386nto_regset_id (int regno)
     return NTO_REG_GENERAL;
   else if (regno < I386_NUM_GREGS + I386_NUM_FREGS)
     return NTO_REG_FLOAT;
+  else if (regno < I386_SSE_NUM_REGS)
+    return NTO_REG_FLOAT; /* We store xmm registers in fxsave_area.  */
 
   return -1;			/* Error.  */
 }
@@ -134,6 +134,7 @@ static int
 i386nto_register_area (struct gdbarch *gdbarch,
 		       int regno, int regset, unsigned *off)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int len;
 
   *off = 0;
@@ -149,30 +150,98 @@ i386nto_register_area (struct gdbarch *g
     }
   else if (regset == NTO_REG_FLOAT)
     {
-      unsigned off_adjust, regsize, regset_size;
+      unsigned off_adjust, regsize, regset_size, regno_base;
+      /* The following are flags indicating number in our fxsave_area.  */
+      int first_four = (regno >= I387_FCTRL_REGNUM (tdep)
+			&& regno <= I387_FISEG_REGNUM (tdep));
+      int second_four = (regno > I387_FISEG_REGNUM (tdep)
+			 && regno <= I387_FOP_REGNUM (tdep));
+      int st_reg = (regno >= I387_ST0_REGNUM (tdep)
+		    && regno < I387_ST0_REGNUM (tdep) + 8);
+      int xmm_reg = (regno >= I387_XMM0_REGNUM (tdep)
+		     && regno < I387_MXCSR_REGNUM (tdep));
 
       if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
 	{
-	  off_adjust = 32;
-	  regsize = 16;
 	  regset_size = 512;
+	  /* fxsave_area structure.  */
+	  if (first_four)
+	    {
+	      /* fpu_control_word, fpu_status_word, fpu_tag_word, fpu_operand
+	         registers.  */
+	      regsize = 2; /* Two bytes each.  */
+	      off_adjust = 0;
+	      regno_base = I387_FCTRL_REGNUM (tdep);
+	    }
+	  else if (second_four)
+	    {
+	      /* fpu_ip, fpu_cs, fpu_op, fpu_ds registers.  */
+	      regsize = 4;
+	      off_adjust = 8;
+	      regno_base = I387_FISEG_REGNUM (tdep) + 1;
+	    }
+	  else if (st_reg)
+	    {
+	      /* ST registers.  */
+	      regsize = 16;
+	      off_adjust = 32;
+	      regno_base = I387_ST0_REGNUM (tdep);
+	    }
+	  else if (xmm_reg)
+	    {
+	      /* XMM registers.  */
+	      regsize = 16;
+	      off_adjust = 160;
+	      regno_base = I387_XMM0_REGNUM (tdep);
+	    }
+	  else if (regno == I387_MXCSR_REGNUM (tdep))
+	    {
+	      regsize = 4;
+	      off_adjust = 24;
+	      regno_base = I387_MXCSR_REGNUM (tdep);
+	    }
+	  else
+	    {
+	      /* Whole regset.  */
+	      gdb_assert (regno == -1);
+	      off_adjust = 0;
+	      regno_base = 0;
+	      regsize = regset_size;
+	    }
 	}
       else
 	{
-	  off_adjust = 28;
-	  regsize = 10;
-	  regset_size = 128;
+	  regset_size = 108;
+	  /* fsave_area structure.  */
+	  if (first_four || second_four)
+	    {
+	      /* fpu_control_word, ... , fpu_ds registers.  */
+	      regsize = 4;
+	      off_adjust = 0;
+	      regno_base = I387_FCTRL_REGNUM (tdep);
+	    }
+	  else if (st_reg)
+	    {
+	      /* One of ST registers.  */
+	      regsize = 10;
+	      off_adjust = 7 * 4;
+	      regno_base = I387_ST0_REGNUM (tdep);
+	    }
+	  else
+	    {
+	      /* Whole regset.  */
+	      gdb_assert (regno == -1);
+	      off_adjust = 0;
+	      regno_base = 0;
+	      regsize = regset_size;
+	    }
 	}
 
-      if (regno == -1)
-	return regset_size;
-
-      *off = (regno - gdbarch_fp0_regnum (gdbarch)) * regsize + off_adjust;
-      return 10;
-      /* Why 10 instead of regsize?  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.  */
+      if (regno != -1)
+	*off = off_adjust + (regno - regno_base) * regsize;
+      else
+	*off = 0;
+      return regsize;
     }
   return -1;
 }
@@ -217,8 +286,6 @@ i386nto_sigtramp_p (struct frame_info *t
   return name && strcmp ("__signalstub", name) == 0;
 }
 
-#define I386_NTO_SIGCONTEXT_OFFSET 136
-
 /* Assuming THIS_FRAME is a QNX Neutrino sigtramp routine, return the
    address of the associated sigcontext structure.  */
 
@@ -226,33 +293,34 @@ static CORE_ADDR
 i386nto_sigcontext_addr (struct frame_info *this_frame)
 {
   char buf[4];
-  CORE_ADDR sp;
+  CORE_ADDR ptrctx;
 
-  get_frame_register (this_frame, I386_ESP_REGNUM, buf);
-  sp = extract_unsigned_integer (buf, 4);
+  /* We store __ucontext_t addr in EDI register.  */
+  get_frame_register (this_frame, I386_EDI_REGNUM, buf);
+  ptrctx = extract_unsigned_integer (buf, 4);
+  ptrctx += 24 /* Context pointer is at this offset.  */;
 
-  return sp + I386_NTO_SIGCONTEXT_OFFSET;
+  return ptrctx;
 }
 
 static void
 init_i386nto_ops (void)
 {
-  i386_nto_target.regset_id = i386nto_regset_id;
-  i386_nto_target.supply_gregset = i386nto_supply_gregset;
-  i386_nto_target.supply_fpregset = i386nto_supply_fpregset;
-  i386_nto_target.supply_altregset = nto_dummy_supply_regset;
-  i386_nto_target.supply_regset = i386nto_supply_regset;
-  i386_nto_target.register_area = i386nto_register_area;
-  i386_nto_target.regset_fill = i386nto_regset_fill;
-  i386_nto_target.fetch_link_map_offsets =
-    svr4_ilp32_fetch_link_map_offsets;
+  nto_regset_id = i386nto_regset_id;
+  nto_supply_gregset = i386nto_supply_gregset;
+  nto_supply_fpregset = i386nto_supply_fpregset;
+  nto_supply_altregset = nto_dummy_supply_regset;
+  nto_supply_regset = i386nto_supply_regset;
+  nto_register_area = i386nto_register_area;
+  nto_regset_fill = i386nto_regset_fill;
+  nto_fetch_link_map_offsets = svr4_ilp32_fetch_link_map_offsets;
 }
 
+
 static void
 i386nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  static struct target_so_ops nto_svr4_so_ops;
 
   /* Deal with our strange signals.  */
   nto_initialize_signals ();
@@ -270,8 +338,8 @@ i386nto_init_abi (struct gdbarch_info in
 
   tdep->sigtramp_p = i386nto_sigtramp_p;
   tdep->sigcontext_addr = i386nto_sigcontext_addr;
-  tdep->sc_pc_offset = 56;
-  tdep->sc_sp_offset = 68;
+  tdep->sc_reg_offset = i386nto_gregset_reg_offset;
+  tdep->sc_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
 
   /* Setjmp()'s return PC saved in EDX (5).  */
   tdep->jb_pc_offset = 20;	/* 5x32 bit ints in.  */
@@ -279,31 +347,17 @@ i386nto_init_abi (struct gdbarch_info in
   set_solib_svr4_fetch_link_map_offsets
     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
 
-  /* Initialize this lazily, to avoid an initialization order
-     dependency on solib-svr4.c's _initialize routine.  */
-  if (nto_svr4_so_ops.in_dynsym_resolve_code == NULL)
-    {
-      nto_svr4_so_ops = svr4_so_ops;
+  /* Our loader handles solib relocations differently than svr4.  */
+  svr4_so_ops.relocate_section_addresses = nto_relocate_section_addresses;
 
-      /* Our loader handles solib relocations differently than svr4.  */
-      nto_svr4_so_ops.relocate_section_addresses
-        = nto_relocate_section_addresses;
-
-      /* Supply a nice function to find our solibs.  */
-      nto_svr4_so_ops.find_and_open_solib
-        = nto_find_and_open_solib;
-
-      /* Our linker code is in libc.  */
-      nto_svr4_so_ops.in_dynsym_resolve_code
-        = nto_in_dynsym_resolve_code;
-    }
-  set_solib_ops (gdbarch, &nto_svr4_so_ops);
+  /* Supply a nice function to find our solibs.  */
+  svr4_so_ops.find_and_open_solib = nto_find_and_open_solib;
 
-  nto_set_target (&i386_nto_target);
-}
+  /* Our linker code is in libc.  */
+  svr4_so_ops.in_dynsym_resolve_code = nto_in_dynsym_resolve_code;
 
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-extern initialize_file_ftype _initialize_i386nto_tdep;
+  set_solib_ops (gdbarch, &svr4_so_ops);
+}
 
 void
 _initialize_i386nto_tdep (void)
Index: gdb/nto-procfs.c
===================================================================
RCS file: /cvs/src/src/gdb/nto-procfs.c,v
retrieving revision 1.44
diff -u -p -r1.44 nto-procfs.c
--- gdb/nto-procfs.c	27 May 2009 18:28:31 -0000	1.44
+++ gdb/nto-procfs.c	5 Jun 2009 19:37:14 -0000
@@ -47,10 +47,19 @@
 #define _DEBUG_FLAG_TRACE	(_DEBUG_FLAG_TRACE_EXEC|_DEBUG_FLAG_TRACE_RD|\
 		_DEBUG_FLAG_TRACE_WR|_DEBUG_FLAG_TRACE_MODIFY)
 
+/* Typedefs, we use gdb specific type names... to be consistent,
+   we use them here too.  */
+typedef debug_thread_t nto_procfs_status;
+typedef debug_process_t nto_procfs_info;
+
+extern int nto_stopped_by_watchpoint (void);
+
 static struct target_ops procfs_ops;
 
 int ctl_fd;
 
+extern unsigned int nto_inferior_stopped_flags;
+
 static void (*ofunc) ();
 
 static procfs_run run;
@@ -63,8 +72,6 @@ static int procfs_xfer_memory (CORE_ADDR
 			       struct mem_attrib *attrib,
 			       struct target_ops *);
 
-static void notice_signals (void);
-
 static void init_procfs_ops (void);
 
 static ptid_t do_attach (ptid_t ptid);
@@ -75,7 +82,7 @@ static int procfs_insert_hw_watchpoint (
 
 static int procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type);
 
-static int procfs_stopped_by_watchpoint (void);
+static void procfs_notice_signals (ptid_t ptid);
 
 /* These two globals are only ever set in procfs_open(), but are
    referenced elsewhere.  'nto_procfs_node' is a flag used to say
@@ -103,12 +110,6 @@ nto_node (void)
   return (node);
 }
 
-static enum gdb_osabi
-procfs_is_nto_target (bfd *abfd)
-{
-  return GDB_OSABI_QNXNTO;
-}
-
 /* This is called when we call 'target procfs <arg>' from the (gdb) prompt.
    For QNX6 (nto), the only valid arg will be a QNX node string, 
    eg: "/net/some_node".  If arg is not a valid QNX node, we will
@@ -123,8 +124,6 @@ procfs_open (char *arg, int from_tty)
   procfs_sysinfo *sysinfo;
   struct cleanup *cleanups;
 
-  nto_is_nto_target = procfs_is_nto_target;
-
   /* Set the default node used for spawning to this one,
      and only override it if there is a valid arg.  */
 
@@ -220,11 +219,94 @@ static int
 procfs_thread_alive (struct target_ops *ops, ptid_t ptid)
 {
   pid_t tid;
+  pid_t pid;
+  procfs_status status;
+  int err;
 
   tid = ptid_get_tid (ptid);
-  if (devctl (ctl_fd, DCMD_PROC_CURTHREAD, &tid, sizeof (tid), 0) == EOK)
-    return 1;
-  return 0;
+  pid = ptid_get_pid (ptid);
+
+  if (kill (pid, 0) == -1)
+    return 0;
+
+  status.tid = tid;
+  if ((err = devctl (ctl_fd, DCMD_PROC_TIDSTATUS, 
+	      &status, sizeof (status), 0)) != EOK)
+    return 0;
+
+  /* Thread is alive or dead but not yet joined,
+     or dead and there is an alive (or dead unjoined) thread with
+     higher tid. We return tidinfo.  
+
+     Client should check if the tid is the same as 
+     requested; if not, requested tid is dead.  */
+  return (status.tid == tid) && (status.state != STATE_DEAD);
+}
+
+static void
+update_thread_private_data_name (struct thread_info *new_thread,
+				 const char *newname)
+{
+  int newnamelen;
+  struct private_thread_info *pti;
+  gdb_assert (newname != NULL);
+  gdb_assert (new_thread != NULL);
+
+  newnamelen = strlen (newname);
+
+  if (!new_thread->private)
+    {
+      new_thread->private = xmalloc (sizeof (struct private_thread_info)
+				     + newnamelen + 1);
+      memcpy (new_thread->private->name, newname, newnamelen + 1);
+    }
+  else if (strcmp (newname, new_thread->private->name) != 0)
+    {
+      /* Reallocate if neccessary.  */
+      int oldnamelen = strlen (new_thread->private->name);
+      if (oldnamelen < newnamelen)
+	new_thread->private = xrealloc (new_thread->private,
+					sizeof (struct private_thread_info)
+					+ newnamelen + 1);
+      memcpy (new_thread->private->name, newname, newnamelen + 1);
+    }
+}
+
+static void 
+update_thread_private_data (struct thread_info *new_thread, 
+			    pthread_t tid, int state, int flags)
+{
+  struct private_thread_info *pti;
+  procfs_info pidinfo;
+  struct _thread_name *tn;
+  procfs_threadctl tctl;
+#if _NTO_VERSION > 630
+  gdb_assert (new_thread != NULL);
+
+  if (devctl (ctl_fd, DCMD_PROC_INFO, &pidinfo,
+	      sizeof(pidinfo), 0) != EOK)
+    return;
+
+  memset (&tctl, 0, sizeof (tctl));
+  tctl.cmd = _NTO_TCTL_NAME;
+  tn = (struct _thread_name *) (&tctl.data);
+
+  /* Fetch name for the given thread.  */
+  tctl.tid = tid;
+  tn->name_buf_len = sizeof (tctl.data) - sizeof (*tn);
+  tn->new_name_len = -1; /* Getting, not setting.  */
+  if (devctl (ctl_fd, DCMD_PROC_THREADCTL, &tctl, sizeof (tctl), NULL) != EOK)
+    tn->name_buf[0] = '\0';
+
+  tn->name_buf[_NTO_THREAD_NAME_MAX] = '\0';
+
+  update_thread_private_data_name (new_thread, tn->name_buf);
+
+  pti = (struct private_thread_info *) new_thread->private;
+  pti->tid = tid;
+  pti->state = state;
+  pti->flags = flags;
+#endif /* _NTO_VERSION */
 }
 
 void
@@ -233,20 +315,37 @@ procfs_find_new_threads (struct target_o
   procfs_status status;
   pid_t pid;
   ptid_t ptid;
+  pthread_t tid;
+  struct thread_info *new_thread;
 
   if (ctl_fd == -1)
     return;
 
   pid = ptid_get_pid (inferior_ptid);
 
-  for (status.tid = 1;; ++status.tid)
+  status.tid = 1;
+
+  for (tid = 1;; ++tid)
     {
-      if (devctl (ctl_fd, DCMD_PROC_TIDSTATUS, &status, sizeof (status), 0)
-	  != EOK && status.tid != 0)
+      if (status.tid == tid 
+	  && (devctl (ctl_fd, DCMD_PROC_TIDSTATUS, &status, sizeof (status), 0)
+	      != EOK))
 	break;
-      ptid = ptid_build (pid, 0, status.tid);
-      if (!in_thread_list (ptid))
-	add_thread (ptid);
+      if (status.tid != tid)
+	{
+	/* The reason why this would not be equal is that devctl might have 
+	   returned different tid, meaning the requested tid no longer exists
+	   (e.g. thread exited).  */
+	  /* if (in_thread_list (ptid))
+	    delete_thread (ptid);  */
+	  continue;
+	}
+      ptid = ptid_build (pid, 0, tid);
+      new_thread = find_thread_ptid (ptid);
+      if (!new_thread)
+	new_thread = add_thread (ptid);
+      update_thread_private_data (new_thread, tid, status.state, 0);
+      status.tid++;
     }
   return;
 }
@@ -626,11 +725,11 @@ procfs_wait (struct target_ops *ops,
 	     ptid_t ptid, struct target_waitstatus *ourstatus, int options)
 {
   sigset_t set;
-  siginfo_t info;
   procfs_status status;
   static int exit_signo = 0;	/* To track signals that cause termination.  */
 
   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+  nto_inferior_stopped_flags = 0;
 
   if (ptid_equal (inferior_ptid, null_ptid))
     {
@@ -646,12 +745,19 @@ procfs_wait (struct target_ops *ops,
   devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
   while (!(status.flags & _DEBUG_FLAG_ISTOP))
     {
+      siginfo_t info;
+      sigset_t set;
+
+      sigemptyset (&set);
+      sigaddset (&set, SIGUSR1);
       ofunc = (void (*)()) signal (SIGINT, nto_interrupt);
       sigwaitinfo (&set, &info);
       signal (SIGINT, ofunc);
       devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
     }
 
+  nto_inferior_stopped_flags = status.flags;
+
   if (status.flags & _DEBUG_FLAG_SSTEP)
     {
       ourstatus->kind = TARGET_WAITKIND_STOPPED;
@@ -690,9 +796,6 @@ procfs_wait (struct target_ops *ops,
 
 	case _DEBUG_WHY_TERMINATED:
 	  {
-	    int waitval = 0;
-
-	    waitpid (PIDGET (inferior_ptid), &waitval, WNOHANG);
 	    if (exit_signo)
 	      {
 		/* Abnormal death.  */
@@ -703,7 +806,7 @@ procfs_wait (struct target_ops *ops,
 	      {
 		/* Normal death.  */
 		ourstatus->kind = TARGET_WAITKIND_EXITED;
-		ourstatus->value.integer = WEXITSTATUS (waitval);
+		ourstatus->value.integer = status.what; 
 	      }
 	    exit_signo = 0;
 	    break;
@@ -774,6 +877,39 @@ procfs_xfer_memory (CORE_ADDR memaddr, g
   return (nbytes);
 }
 
+static LONGEST
+procfs_xfer_partial (struct target_ops *ops, enum target_object object,
+		     const char *annex, gdb_byte *readbuf,
+		     const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+{
+  if (object == TARGET_OBJECT_AUXV
+      && readbuf)
+    {
+      int err;
+      CORE_ADDR initial_stack;
+      nto_procfs_info procinfo;
+
+      if (offset > 0)
+	return 0;
+
+      err = devctl (ctl_fd, DCMD_PROC_INFO, &procinfo, sizeof procinfo, 0);
+      if (err != EOK)
+	return -1;
+
+      /* Similar as in the case of a core file, we read auxv from
+         initial_stack.  */
+      initial_stack = procinfo.initial_stack;
+
+      /* procfs is always 'self-hosted', no byte-order manipulation. */
+      return nto_read_auxv_from_initial_stack (initial_stack, readbuf, len);
+    }
+
+  if (ops->beneath && ops->beneath->to_xfer_partial)
+    return ops->beneath->to_xfer_partial (ops, object, annex, readbuf,
+					  writebuf, offset, len);
+  return -1;
+}
+
 /* Take a program previously attached to and detaches it.
    The program resumes execution and will no longer stop
    on signals, etc.  We'd better not have left any breakpoints
@@ -882,14 +1018,17 @@ procfs_resume (struct target_ops *ops,
   run.flags |= _DEBUG_RUN_ARM;
 
   sigemptyset (&run.trace);
-  notice_signals ();
+  procfs_notice_signals (ptid_equal (ptid, minus_one_ptid) ? inferior_ptid :
+		         ptid);
   signal_to_pass = target_signal_to_host (signo);
 
   if (signal_to_pass)
     {
       devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
       signal_to_pass = target_signal_to_host (signo);
-      if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
+
+      if ((status.why == _DEBUG_WHY_REQUESTED) 
+	  || (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED)))
 	{
 	  if (signal_to_pass != status.info.si_signo)
 	    {
@@ -897,7 +1036,7 @@ procfs_resume (struct target_ops *ops,
 			  signal_to_pass, 0, 0);
 	      run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
 	    }
-	  else			/* Let it kill the program without telling us.  */
+	  else		/* Let it kill the program without telling us.  */
 	    sigdelset (&run.trace, signal_to_pass);
 	}
     }
@@ -1230,7 +1369,7 @@ procfs_store_registers (struct target_op
 }
 
 static void
-notice_signals (void)
+procfs_notice_signals (ptid_t ptid)
 {
   int signo;
 
@@ -1245,18 +1384,6 @@ notice_signals (void)
     }
 }
 
-/* When the user changes the state of gdb's signal handling via the
-   "handle" command, this function gets called to see if any change
-   in the /proc interface is required.  It is also called internally
-   by other /proc interface functions to initialize the state of
-   the traced signal set.  */
-static void
-procfs_notice_signals (ptid_t ptid)
-{
-  sigemptyset (&run.trace);
-  notice_signals ();
-}
-
 static struct tidinfo *
 procfs_thread_info (pid_t pid, short tid)
 {
@@ -1303,6 +1430,7 @@ init_procfs_ops (void)
   procfs_ops.to_store_registers = procfs_store_registers;
   procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
   procfs_ops.deprecated_xfer_memory = procfs_xfer_memory;
+  procfs_ops.to_xfer_partial = procfs_xfer_partial;
   procfs_ops.to_files_info = procfs_files_info;
   procfs_ops.to_insert_breakpoint = procfs_insert_breakpoint;
   procfs_ops.to_remove_breakpoint = procfs_remove_breakpoint;
@@ -1311,7 +1439,7 @@ init_procfs_ops (void)
   procfs_ops.to_remove_hw_breakpoint = procfs_remove_breakpoint;
   procfs_ops.to_insert_watchpoint = procfs_insert_hw_watchpoint;
   procfs_ops.to_remove_watchpoint = procfs_remove_hw_watchpoint;
-  procfs_ops.to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
+  procfs_ops.to_stopped_by_watchpoint = nto_stopped_by_watchpoint;
   procfs_ops.to_terminal_init = terminal_init_inferior;
   procfs_ops.to_terminal_inferior = terminal_inferior;
   procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
@@ -1334,6 +1462,7 @@ init_procfs_ops (void)
   procfs_ops.to_has_execution = 1;
   procfs_ops.to_magic = OPS_MAGIC;
   procfs_ops.to_have_continuable_watchpoint = 1;
+  procfs_ops.to_extra_thread_info = nto_target_extra_thread_info;
 }
 
 #define OSTYPE_NTO 1
@@ -1361,8 +1490,6 @@ _initialize_procfs (void)
 
   add_info ("pidlist", procfs_pidlist, _("pidlist"));
   add_info ("meminfo", procfs_meminfo, _("memory information"));
-
-  nto_is_nto_target = procfs_is_nto_target;
 }
 
 
Index: gdb/nto-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/nto-tdep.c,v
retrieving revision 1.32
diff -u -p -r1.32 nto-tdep.c
--- gdb/nto-tdep.c	22 May 2009 23:49:13 -0000	1.32
+++ gdb/nto-tdep.c	5 Jun 2009 19:37:15 -0000
@@ -34,22 +34,38 @@
 #include "gdbcore.h"
 #include "objfiles.h"
 
-#include <string.h>
+#include "gdbcmd.h"
+#include "safe-ctype.h"
+#include "gdb_assert.h"
+
+#include "observer.h"
+
+
+#include <sys/debug.h>
+#include <sys/elf_notes.h>
+#define __ELF_H_INCLUDED /* Needed for our link.h to avoid including elf.h.  */
+#include <sys/link.h>
+typedef debug_thread_t nto_procfs_status;
+typedef debug_process_t nto_procfs_info;
+
+#define QNX_NOTE_NAME	"QNX"
 
 #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
+
+/* The following define does a cast to const gdb_byte * type.  */
+
+#define EXTRACT_SIGNED_INTEGER(ptr, len) extract_signed_integer ((const gdb_byte *)(ptr), len)
+#define EXTRACT_UNSIGNED_INTEGER(ptr, len) extract_unsigned_integer ((const gdb_byte *)(ptr), len)
+
 static char default_nto_target[] = "";
-#endif
 
 struct nto_target_ops current_nto_target;
 
+unsigned int nto_inferior_stopped_flags;
+
 static char *
 nto_target (void)
 {
@@ -67,19 +83,6 @@ nto_target (void)
 #endif
 }
 
-void
-nto_set_target (struct nto_target_ops *targ)
-{
-  nto_regset_id = targ->regset_id;
-  nto_supply_gregset = targ->supply_gregset;
-  nto_supply_fpregset = targ->supply_fpregset;
-  nto_supply_altregset = targ->supply_altregset;
-  nto_supply_regset = targ->supply_regset;
-  nto_register_area = targ->register_area;
-  nto_regset_fill = targ->regset_fill;
-  nto_fetch_link_map_offsets = targ->fetch_link_map_offsets;
-}
-
 /* 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
@@ -98,13 +101,16 @@ nto_map_arch_to_cputype (const char *arc
   return CPUTYPE_UNKNOWN;
 }
 
-int
-nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
+/* Helper function, calculates architecture path, e.g.
+   /opt/qnx640/target/qnx6/ppcbe
+   It allocates string, callers must free the string using free.  */
+
+static char *
+nto_build_arch_path ()
 {
-  char *buf, *arch_path, *nto_root, *endian, *base;
-  const char *arch;
-  int ret;
-#define PATH_FMT "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
+  const char *nto_root, *arch, *endian;
+  char *arch_path;
+  const char *variant_suffix = "";
 
   nto_root = nto_target ();
   if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
@@ -127,16 +133,39 @@ nto_find_and_open_solib (char *solib, un
 	       == BFD_ENDIAN_BIG ? "be" : "le";
     }
 
+  if (strcmp (arch, "ppc") == 0)
+    {
+      struct bfd_arch_info const *info = 
+	gdbarch_bfd_arch_info (current_gdbarch);
+
+      if (info->mach == bfd_mach_ppc_e500)
+	variant_suffix = "-spe";
+    }
+
   /* In case nto_root is short, add strlen(solib)
      so we can reuse arch_path below.  */
   arch_path =
-    alloca (strlen (nto_root) + strlen (arch) + strlen (endian) + 2 +
-	    strlen (solib));
-  sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
+    malloc (strlen (nto_root) + strlen (arch) + strlen (endian) 
+	    + strlen (variant_suffix) +	2);
+  sprintf (arch_path, "%s/%s%s%s", nto_root, arch, endian, variant_suffix);
+  return arch_path;
+}
 
+int
+nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
+{
+  char *buf, *arch_path, *base;
+  const char *arch;
+  int ret;
+#define PATH_FMT "%s/lib%c%s/usr/lib%c%s/usr/photon/lib%c" \
+		 "%s/usr/photon/dll%c%s/lib/dll"
+
+  arch_path = nto_build_arch_path ();
   buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
-  sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
-	   arch_path);
+  sprintf (buf, PATH_FMT, arch_path, DIRNAME_SEPARATOR,
+	   arch_path, DIRNAME_SEPARATOR, arch_path, DIRNAME_SEPARATOR,
+	   arch_path, DIRNAME_SEPARATOR, arch_path);
+  free (arch_path);
 
   /* Don't assume basename() isn't destructive.  */
   base = strrchr (solib, '/');
@@ -148,51 +177,54 @@ nto_find_and_open_solib (char *solib, un
   ret = openp (buf, 1, base, o_flags, temp_pathname);
   if (ret < 0 && base != solib)
     {
-      sprintf (arch_path, "/%s", solib);
-      ret = open (arch_path, o_flags, 0);
+      sprintf (buf, "/%s", solib);
+      ret = open (buf, o_flags, 0);
       if (temp_pathname)
 	{
 	  if (ret >= 0)
-	    *temp_pathname = gdb_realpath (arch_path);
+	    *temp_pathname = gdb_realpath (buf);
 	  else
-	    **temp_pathname = '\0';
+	    *temp_pathname = NULL;
 	}
     }
   return ret;
 }
 
+/* The following two variables are defined in solib.c.  */
+extern char *gdb_sysroot; /* a.k.a solib-absolute-prefix  */
+
 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 (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
-    {
-      arch = "x86";
-      endian = "";
-    }
-  else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
-		   "rs6000") == 0
-	   || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
-		   "powerpc") == 0)
-    {
-      arch = "ppc";
-      endian = "be";
-    }
-  else
+  /* If it was nto_init_solib_absolute_prefix that set the path,
+     the following variable will be set to 1.  */
+  static int nto_set_gdb_sysroot;
+
+  char *buf, *arch_path;
+
+  arch_path = nto_build_arch_path ();
+
+  /* Do not change it if already set.  */
+  if ((!gdb_sysroot
+      || strlen (gdb_sysroot) == 0)
+      || nto_set_gdb_sysroot)
     {
-      arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
-      endian = gdbarch_byte_order (target_gdbarch)
-	       == BFD_ENDIAN_BIG ? "be" : "le";
+      buf = alloca (26 /* set solib-absolute-prefix */ 
+		    + strlen (arch_path) + 1);
+      if (gdb_sysroot == NULL || gdb_sysroot[0] == '\0')
+	{
+	  /* Initially, only set the string. We don't want any side effects. */
+	  xfree (gdb_sysroot);
+	  gdb_sysroot = xstrdup (arch_path);
+	}
+      else
+	{
+	  sprintf (buf, "set solib-absolute-prefix %s", arch_path);
+	  execute_command (buf, 0);
+	}
+      nto_set_gdb_sysroot = 1;
     }
-
-  sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
-
-  sprintf (buf, "set solib-absolute-prefix %s", arch_path);
-  execute_command (buf, 0);
+  free (arch_path);
 }
 
 char **
@@ -268,22 +300,20 @@ struct lm_info
        address changes, we may need a different offset, we want to
        warn about the difference and compute it only once.  */
     CORE_ADDR l_addr;
-
-    /* The target location of lm.  */
-    CORE_ADDR lm_addr;
   };
 
-
 static CORE_ADDR
-LM_ADDR (struct so_list *so)
+LM_ADDR_FROM_LINK_MAP (struct so_list *so)
 {
+  struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
+
   if (so->lm_info->l_addr == (CORE_ADDR)-1)
     {
-      struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
       struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
 
-      so->lm_info->l_addr =
-	extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
+      so->lm_info->l_addr = extract_typed_address (so->lm_info->lm 
+						   + lmo->l_addr_offset,
+						   ptr_type);
     }
   return so->lm_info->l_addr;
 }
@@ -326,8 +356,16 @@ nto_relocate_section_addresses (struct s
   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);
+  sec->addr = nto_truncate_ptr (sec->addr 
+			        + LM_ADDR_FROM_LINK_MAP (so)
+				- vaddr);
+  sec->endaddr = nto_truncate_ptr (sec->endaddr 
+				   + LM_ADDR_FROM_LINK_MAP (so)
+				   - vaddr);
+  if (so->addr_low == 0)
+    so->addr_low = LM_ADDR_FROM_LINK_MAP (so);
+  if (so->addr_high < sec->endaddr)
+    so->addr_high = sec->endaddr;
 }
 
 /* This is cheating a bit because our linker code is in libc.so.  If we
@@ -341,38 +379,95 @@ nto_in_dynsym_resolve_code (CORE_ADDR pc
 }
 
 void
-nto_generic_supply_gpregset (const struct regset *regset,
-			     struct regcache *regcache, int regnum,
-			     const void *gregs, size_t len)
+nto_dummy_supply_regset (struct regcache *regcache, char *regs)
 {
 }
 
-void
-nto_generic_supply_fpregset (const struct regset *regset,
-			     struct regcache *regcache, int regnum,
-			     const void *fpregs, size_t len)
+static void
+nto_sniff_abi_note_section (bfd *abfd, asection *sect, void *obj)
 {
-}
+  const char *sectname;
+  unsigned int sectsize;
+  char *note; // buffer holding the section contents
+  unsigned int namelen, type;
+  const char *name;
+
+  sectname = bfd_get_section_name (abfd, sect);
+  sectsize = bfd_section_size (abfd, sect);
+
+  /* TODO: limit the note size here, for now limit is 128 bytes
+     (enough to check the name and type).  */
+  if (sectsize > 128)
+    sectsize = 128;
 
-void
-nto_generic_supply_altregset (const struct regset *regset,
-			      struct regcache *regcache, int regnum,
-			      const void *altregs, size_t len)
-{
-}
+  if (sectname == strstr(sectname, "note")) 
+    {
+      note = alloca (sectsize); 
+      bfd_get_section_contents (abfd, sect, note, 0, sectsize);
+      namelen = (unsigned int) bfd_h_get_32 (abfd, note);
+      name = note + 12;
+
+      if (namelen != strlen (QNX_NOTE_NAME) + 1 
+	  || 0 != strcmp (name, QNX_NOTE_NAME)) 
+	goto not_ours;
+
+      type = (unsigned int) bfd_h_get_32 (abfd, note + 8);
+
+      switch (type)
+        {
+	  case QNT_NULL:
+	    gdb_assert (0);
+	    break;
+	  case QNT_CORE_SYSINFO:
+	    *(enum gdb_osabi *) obj = GDB_OSABI_QNXNTO;
+	    break;
+	  case QNT_CORE_INFO:
+	    break;
+        }
 
-void
-nto_dummy_supply_regset (struct regcache *regcache, char *regs)
-{
-  /* Do nothing.  */
+not_ours:
+       { /* We do nothing here.  */ } 
+    }
 }
 
 enum gdb_osabi
 nto_elf_osabi_sniffer (bfd *abfd)
 {
-  if (nto_is_nto_target)
-    return nto_is_nto_target (abfd);
-  return GDB_OSABI_UNKNOWN;
+  unsigned int elfosabi;
+  unsigned int elftype;
+  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
+
+  /* Note: if we ever get to sign our binaries, we should
+     really check if the OSABI matches. But untill then, just
+     hope the user knows what they are doing and are really opening
+     QNXNTO binary.  */
+
+  elftype = elf_elfheader (abfd)->e_type;
+
+  if (elftype == ET_CORE)
+      /* We do properly mark our core files, get the OSABI from
+         core note section.  */
+      bfd_map_over_sections (abfd,
+			     nto_sniff_abi_note_section, 
+			     &osabi);
+  else
+  /* Note: if we ever get to sign our binaries, we should
+     really check if the OSABI matches. But untill then, just
+     hope the user knows what they are doing and are really opening
+     QNXNTO binary.  */
+    osabi = GDB_OSABI_QNXNTO;
+
+  if (nto_internal_debugging)
+    gdb_assert (osabi == GDB_OSABI_QNXNTO);
+  return osabi;
+}
+
+char *
+nto_target_extra_thread_info (struct thread_info *ti)
+{
+  if (ti && ti->private && ti->private->name[0])
+    return ti->private->name;
+  return "";
 }
 
 void
@@ -398,12 +493,361 @@ nto_initialize_signals (void)
 #endif
 }
 
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-extern initialize_file_ftype _initialize_nto_tdep;
+static void
+show_nto_debug (struct ui_file *file, int from_tty,
+                struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("QNX NTO debug level is %d.\n"), nto_internal_debugging);
+}
+
+static int 
+nto_print_tidinfo_callback (struct thread_info *tp, void *data)
+{
+  char star = ' ';
+  int tid = 0;
+  int state = 0;
+  int flags = 0;
+
+  if (tp)
+    {
+      if (ptid_equal (tp->ptid, inferior_ptid))
+	star = '*';
+
+      if (tp->private)
+	{
+	  tid = tp->private->tid;
+	  state = tp->private->state;
+	  flags = tp->private->flags;
+	}
+      else
+	tid = ptid_get_tid (tp->ptid);
+
+      printf_filtered ("%c%d\t%d\t%d\n", star, tid, state, flags);
+    }
+
+  return 0;
+}
+
+static void 
+nto_info_tidinfo_command (char *args, int from_tty)
+{
+  char *execfile = get_exec_file (0);
+
+  target_find_new_threads ();
+  printf_filtered("Threads for pid %d (%s)\nTid:\tState:\tFlags:\n", 
+		  ptid_get_pid (inferior_ptid), execfile ? execfile : "");
+  
+  iterate_over_threads (nto_print_tidinfo_callback, NULL);
+}
+
+
+char *
+nto_pid_to_str (struct target_ops *ops, ptid_t ptid)
+{
+  static char buf[1024];
+  int pid, tid, n;
+  struct tidinfo *tip;
+
+  pid = ptid_get_pid (ptid);
+  tid = ptid_get_tid (ptid);
+
+  n = sprintf (buf, "process %d thread %d", pid, tid);
+
+  return buf;
+}
+
+
+/* NTO Core handling.  */
+
+extern struct gdbarch *core_gdbarch;
+
+/* Add thread status for the given gdb_thread_id.  */
+
+static void
+nto_core_add_thread_status_info (pid_t core_pid, int gdb_thread_id, const nto_procfs_status *ps)
+{
+  struct thread_info *ti;
+  ptid_t ptid;
+  struct private_thread_info *priv;
+  struct gdbarch *curr_gdbarch = current_gdbarch;
+ 
+  /* See corelow, function add_to_thread_list for details on pid.  */
+  ptid = ptid_build (core_pid, 0, gdb_thread_id);
+  ti = find_thread_ptid (ptid);
+  if (!ti)
+    ti = add_thread (ptid);
+  if(!ti)
+    {
+      warning ("Thread with gdb id %d not found.\n", gdb_thread_id);
+      return;
+    }
+  priv = malloc (sizeof (*priv));
+  if (priv == NULL)
+    {
+      warning ("Out of memory.\n");
+      return;
+    }
+  memset (priv, 0, sizeof (*priv));
+  ti->private = priv;
+  if (core_gdbarch != current_gdbarch)
+    /* Dirty hack - current_gdbarch is not the same, and we need
+       core_gdbarch for endiannes.  */
+    current_gdbarch = core_gdbarch;
+  priv->tid = EXTRACT_UNSIGNED_INTEGER (&ps->tid, sizeof (ps->tid));
+  priv->state = EXTRACT_UNSIGNED_INTEGER (&ps->state, sizeof (ps->state)); 
+  priv->flags = EXTRACT_UNSIGNED_INTEGER (&ps->flags, sizeof (ps->flags));
+  if (curr_gdbarch != current_gdbarch)
+    current_gdbarch = curr_gdbarch;
+}
+
+/* Add thread statuses read from qnx notes.  */
+static void
+nto_core_add_thread_private_data (bfd *abfd, asection *sect, void *notused)
+{
+  const char *sectname;
+  unsigned int sectsize;
+  const char qnx_core_status[] = ".qnx_core_status/";
+  const unsigned int qnx_sectnamelen = 17;/* strlen (qnx_core_status).  */
+  const char warning_msg[] = "Unable to read %s section from core.\n";
+  int gdb_thread_id;
+  int data_ofs;
+  nto_procfs_status status;
+  int len;
+
+  sectname = bfd_get_section_name (abfd, sect);
+  sectsize = bfd_section_size (abfd, sect);
+  if (sectsize > sizeof (status))
+    sectsize = sizeof (status);
+
+  if (strncmp (sectname, qnx_core_status, qnx_sectnamelen) != 0) 
+    return;
+
+  if (bfd_seek (abfd, sect->filepos, SEEK_SET) != 0)
+    {
+      warning (warning_msg, sectname);
+      return;
+    }
+  len = bfd_bread ((gdb_byte *)&status, sectsize, abfd);
+  if (len != sectsize)
+    {
+      warning (warning_msg, sectname);
+      return;
+    }
+  gdb_thread_id = atoi (sectname + qnx_sectnamelen);
+  nto_core_add_thread_status_info (elf_tdata (abfd)->core_pid, gdb_thread_id, &status);
+}
+
+struct target_ops original_core_ops;
+
+static void
+nto_core_solib_create_inferior_hook (void)
+{
+  /* Do nothing.  */
+}
+
+struct auxv_buf
+{
+  LONGEST len;
+  LONGEST len_read; /* For passing result. Can be len, 0, or -1  */
+  gdb_byte *readbuf;
+};
+
+/* Read AUXV from initial_stack.  */
+LONGEST
+nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack, gdb_byte *readbuf,
+				  LONGEST len)
+{
+  int data_ofs = 0;
+  int anint32;
+  LONGEST len_read = 0;
+  gdb_byte *panint32 = (gdb_byte*)&anint32;
+  gdb_byte *buff;
+
+  /* Skip over argc, argv and envp... (see comment in ldd.c)  */
+  if (target_read_memory (initial_stack + data_ofs, panint32, 4) != 0)
+    return 0;
+
+  anint32 = EXTRACT_UNSIGNED_INTEGER (panint32, sizeof (anint32));
+
+  /* Size of pointer is assumed to be 4 bytes (32 bit arch. ) */
+  data_ofs += (anint32 + 2) * 4; /* + 2 comes from argc itself and
+				    NULL terminating pointer in argv */
+
+  /* Now loop over env table:  */
+  while (target_read_memory (initial_stack + data_ofs, panint32, 4) == 0)
+    {
+      anint32 = EXTRACT_SIGNED_INTEGER (panint32, sizeof (anint32));
+      data_ofs += 4;
+      if (anint32 == 0)
+	break;
+    }
+  initial_stack += data_ofs;
+
+  memset (readbuf, 0, len);
+  buff = readbuf;
+  while (len_read <= len-8)
+    {
+      /* For 32-bit architecture, size of auxv_t is 8 bytes.  */
+
+      /* Search backwards until we have read AT_PHDR (num. 3),
+	 AT_PHENT (num 4), AT_PHNUM (num 5)  */
+      if (target_read_memory (initial_stack, buff, 8)
+	  == 0)
+	{
+	  int a_type = EXTRACT_SIGNED_INTEGER (buff, sizeof (a_type));
+	  if (a_type != AT_NULL)
+	    {
+	      buff += 8;
+	      len_read += 8;
+	    }
+	  if (a_type == AT_PHNUM) /* That's all we need.  */
+	    break;
+	  initial_stack += 8;
+	}
+      else
+	break;
+    }
+  return len_read;
+}
+
+/* Read AUXV from note.  */
+static void
+nto_core_read_auxv_from_note (bfd *abfd, asection *sect, void *pauxv_buf)
+{
+  struct auxv_buf *auxv_buf = (struct auxv_buf *)pauxv_buf;
+  const char *sectname;
+  unsigned int sectsize;
+  const char qnx_core_info[] = ".qnx_core_info/";
+  const unsigned int qnx_sectnamelen = 14;/* strlen (qnx_core_status).  */
+  const char warning_msg[] = "Unable to read %s section from core.\n";
+  int data_ofs;
+  nto_procfs_info info;
+  int len;
+  gdb_byte *buff; /* For skipping over argc, argv and envp-s */
+  int anint32;
+  CORE_ADDR initial_stack, base_address;
+
+  sectname = bfd_get_section_name (abfd, sect);
+  sectsize = bfd_section_size (abfd, sect);
+  if (sectsize > sizeof (info))
+    sectsize = sizeof (info);
+
+  if (strncmp (sectname, qnx_core_info, qnx_sectnamelen) != 0) 
+    return;
+
+  if (bfd_seek (abfd, sect->filepos, SEEK_SET) != 0)
+    {
+      warning (warning_msg, sectname);
+      return;
+    }
+  len = bfd_bread ((gdb_byte *)&info, sectsize, abfd);
+  if (len != sectsize)
+    {
+      warning (warning_msg, sectname);
+      return;
+    }
+  initial_stack = EXTRACT_UNSIGNED_INTEGER 
+    (&info.initial_stack, sizeof (info.initial_stack));
+  base_address = EXTRACT_UNSIGNED_INTEGER
+    (&info.base_address, sizeof (info.base_address));
+  buff = auxv_buf->readbuf;
+
+  auxv_buf->len_read = nto_read_auxv_from_initial_stack 
+    (initial_stack, auxv_buf->readbuf, auxv_buf->len);
+}
+
+static LONGEST
+nto_core_xfer_partial (struct target_ops *ops, enum target_object object,
+		       const char *annex, gdb_byte *readbuf,
+		       const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+{
+  if (object == TARGET_OBJECT_AUXV
+      && readbuf)
+    {
+      struct auxv_buf auxv_buf;
+
+      auxv_buf.len = len;
+      auxv_buf.len_read = 0;
+      auxv_buf.readbuf = readbuf;
+      
+      if (offset > 0)
+	return 0;
+
+      bfd_map_over_sections (core_bfd, nto_core_read_auxv_from_note, &auxv_buf);
+      if (auxv_buf.len_read > 0)
+	return auxv_buf.len_read;
+    }
+
+  /* In any other case, try default code.  */
+  return original_core_ops.to_xfer_partial (ops, object, annex, readbuf,
+					    writebuf, offset, len);
+} 
+
+static void
+nto_core_open (char *filename, int from_tty)
+{
+  original_core_ops.to_open (filename, from_tty);
+}
+
+
+static void
+nto_find_new_threads_in_core (struct target_ops *ops)
+{
+  if (core_bfd)
+    bfd_map_over_sections (core_bfd, nto_core_add_thread_private_data, NULL);
+}
+
+
+static void
+init_nto_core_ops ()
+{
+  struct target_ops *core_ops;
+
+  core_ops = find_core_target ();
+  gdb_assert (core_ops && core_ops->to_shortname != NULL 
+	      && !!"core_ops must be initialized first!");
+  original_core_ops = *core_ops;
+  core_ops->to_extra_thread_info = nto_target_extra_thread_info;
+  core_ops->to_open = nto_core_open;
+  core_ops->to_xfer_partial = nto_core_xfer_partial;
+  core_ops->to_pid_to_str = nto_pid_to_str;
+  core_ops->to_find_new_threads = nto_find_new_threads_in_core;
+}
+
+int
+nto_stopped_by_watchpoint (void)
+{
+  /* NOTE: nto_stopped_by_watchpoint will be called ONLY while we are 
+     stopped due to a SIGTRAP.  This assumes gdb works in 'all-stop' mode;
+     future gdb versions will likely run in 'non-stop' mode in which case 
+     we will have to store/examine statuses per thread in question.  
+     Until then, this will work fine.  */
+
+  return nto_inferior_stopped_flags 
+	 & (_DEBUG_FLAG_TRACE_RD
+	    | _DEBUG_FLAG_TRACE_WR
+	    | _DEBUG_FLAG_TRACE_MODIFY);
+}
+
+
+static void
+nto_architecture_changed_listener (struct gdbarch *newarch)
+{
+  nto_init_solib_absolute_prefix ();
+}
+
+
+/* Prevent corelow.c from adding core_ops target. We will do it
+   after overriding some of the default functions. See comment in
+   corelow.c for details.  */
+int coreops_suppress_target = 1;
+
 
 void
 _initialize_nto_tdep (void)
 {
+  init_nto_core_ops ();
+
   add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
 			    &nto_internal_debugging, _("\
 Set QNX NTO internal debugging."), _("\
@@ -412,6 +856,13 @@ When non-zero, nto specific debug info i
 displayed. Different information is displayed\n\
 for different positive values."),
 			    NULL,
-			    NULL, /* FIXME: i18n: QNX NTO internal debugging is %s.  */
-			    &setdebuglist, &showdebuglist);
+			    show_nto_debug,
+			    &setdebuglist,
+			    &showdebuglist);
+
+  add_info ("tidinfo", nto_info_tidinfo_command, "List threads for current process." );
+  nto_fetch_link_map_offsets = svr4_ilp32_fetch_link_map_offsets;
+  nto_is_nto_target = nto_elf_osabi_sniffer;
+
+  observer_attach_architecture_changed (nto_architecture_changed_listener);
 }
Index: gdb/nto-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/nto-tdep.h,v
retrieving revision 1.13
diff -u -p -r1.13 nto-tdep.h
--- gdb/nto-tdep.h	22 May 2009 23:49:13 -0000	1.13
+++ gdb/nto-tdep.h	5 Jun 2009 19:37:15 -0000
@@ -25,6 +25,7 @@
 #include "solist.h"
 #include "osabi.h"
 #include "regset.h"
+#include "gdbthread.h"
 
 /* Target operations defined for Neutrino targets (<target>-nto-tdep.c).  */
 
@@ -103,6 +104,10 @@ extern struct nto_target_ops current_nto
 
 #define nto_is_nto_target (current_nto_target.is_nto_target)
 
+#define NTO_ALL_REGS (-1)
+#define RAW_SUPPLY_IF_NEEDED(regcache, whichreg, dataptr) \
+  {if (!(NTO_ALL_REGS == regno || regno == (whichreg))) {} \
+    else regcache_raw_supply (regcache, whichreg, dataptr); }
 /* Keep this consistant with neutrino syspage.h.  */
 enum
 {
@@ -138,12 +143,18 @@ typedef struct _debug_regs
   qnx_reg64 padding[1024];
 } nto_regset_t;
 
+/* Used by gdbthread.h.  Same as struct tidinfo in pdebug protocol */
+struct private_thread_info {
+  short tid;
+  unsigned char state;
+  unsigned char flags;
+  char name[1];
+};
+
 /* Generic functions in nto-tdep.c.  */
 
 void nto_init_solib_absolute_prefix (void);
 
-void nto_set_target(struct nto_target_ops *);
-
 char **nto_parse_redirection (char *start_argv[], const char **in,
 			      const char **out, const char **err);
 
@@ -160,19 +171,28 @@ enum gdb_osabi nto_elf_osabi_sniffer (bf
 
 void nto_initialize_signals (void);
 
-void nto_generic_supply_gpregset (const struct regset *, struct regcache *,
-				  int, const void *, size_t);
-
-void nto_generic_supply_fpregset (const struct regset *, struct regcache *,
-				  int, const void *, size_t);
-
-void nto_generic_supply_altregset (const struct regset *, struct regcache *,
-				   int, const void *, size_t);
-
 /* Dummy function for initializing nto_target_ops on targets which do
    not define a particular regset.  */
 void nto_dummy_supply_regset (struct regcache *regcache, char *regs);
 
 int nto_in_dynsym_resolve_code (CORE_ADDR pc);
 
+char *nto_target_extra_thread_info (struct thread_info *);
+
+struct link_map_offsets* nto_generic_svr4_fetch_link_map_offsets (void);
+
+/* needed for remote protocol and for core files */
+enum target_signal target_signal_from_nto (struct gdbarch *, int sig);
+int target_signal_to_nto(struct gdbarch *, enum target_signal sig);
+
+int qnx_filename_cmp (const char *s1, const char *s2);
+
+LONGEST nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack, 
+					  gdb_byte *readbuf,
+					  LONGEST len);
+
+char *nto_pid_to_str (struct target_ops *, ptid_t);
+
+
+
 #endif

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]