Mirror of the gdb mailing list
 help / color / mirror / Atom feed
* corelow and threads question
@ 2009-06-05 18:55 Aleksandar Ristovski
  2009-06-05 19:03 ` Daniel Jacobowitz
  2009-06-05 19:24 ` Pedro Alves
  0 siblings, 2 replies; 10+ messages in thread
From: Aleksandar Ristovski @ 2009-06-05 18:55 UTC (permalink / raw)
  To: gdb

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

Hello,

Since: 
http://sourceware.org/ml/gdb-patches/2009-06/msg00101.html 
diverged from original intention, I would like to ask a 
question regarding core_ops and possible solution to my problem.

Right now, we are treating core_ops somewhat specially since 
we add threads before calling target_find_new_threads in 
core_open; but why don't we let target_find_new_threads add 
the threads instead of adding them in core_open?

Wouldn't that actually be the right solution?

(attached is diff for corelow.c that illustrates what I am 
talking about).



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

I can provide to_find_new_threads there:

static void
nto_find_new_threads_in_core (void)
{
   if (core_bfd)
     bfd_map_over_sections (core_bfd, 
nto_core_add_thread_private_data, NULL);
}

where I add_thread and also add thread private data. All 
works well.


Thoughts?

-- 
Aleksandar Ristovski
QNX Software Systems

[-- Attachment #2: corelow.c.diff --]
[-- Type: text/x-patch, Size: 1322 bytes --]

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 18:51:03 -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

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

* Re: corelow and threads question
  2009-06-05 18:55 corelow and threads question Aleksandar Ristovski
@ 2009-06-05 19:03 ` Daniel Jacobowitz
  2009-06-05 19:20   ` Aleksandar Ristovski
  2009-06-05 19:24 ` Pedro Alves
  1 sibling, 1 reply; 10+ messages in thread
From: Daniel Jacobowitz @ 2009-06-05 19:03 UTC (permalink / raw)
  To: Aleksandar Ristovski; +Cc: gdb

On Fri, Jun 05, 2009 at 02:54:54PM -0400, Aleksandar Ristovski wrote:
> Hello,
>
> Since: http://sourceware.org/ml/gdb-patches/2009-06/msg00101.html  
> diverged from original intention, I would like to ask a question regarding 
> core_ops and possible solution to my problem.
>
> Right now, we are treating core_ops somewhat specially since we add 
> threads before calling target_find_new_threads in core_open; but why don't 
> we let target_find_new_threads add the threads instead of adding them in 
> core_open?
>
> Wouldn't that actually be the right solution?

I think the version you have now will cause "info threads" to
duplicate threads every time you type it.  The current version
reflects that threads are only added when the target is opened.

That said, I think either way is fine - but you'll have to detect
already-added threads.

-- 
Daniel Jacobowitz
CodeSourcery


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

* Re: corelow and threads question
  2009-06-05 19:03 ` Daniel Jacobowitz
@ 2009-06-05 19:20   ` Aleksandar Ristovski
  0 siblings, 0 replies; 10+ messages in thread
From: Aleksandar Ristovski @ 2009-06-05 19:20 UTC (permalink / raw)
  To: gdb

Daniel Jacobowitz wrote:
> On Fri, Jun 05, 2009 at 02:54:54PM -0400, Aleksandar Ristovski wrote:
>> Hello,
>>
>> Since: http://sourceware.org/ml/gdb-patches/2009-06/msg00101.html  
>> diverged from original intention, I would like to ask a question regarding 
>> core_ops and possible solution to my problem.
>>
>> Right now, we are treating core_ops somewhat specially since we add 
>> threads before calling target_find_new_threads in core_open; but why don't 
>> we let target_find_new_threads add the threads instead of adding them in 
>> core_open?
>>
>> Wouldn't that actually be the right solution?
> 
> I think the version you have now will cause "info threads" to
> duplicate threads every time you type it.  The current version
> reflects that threads are only added when the target is opened.

I missed to add to the example code that I set
core_ops->to_find_new_threads = nto_find_new_threads_in_core;

I tested on neutrino, it doesn't duplicate threads: notice I 
removed snippet with bfd_map_over_sections from core_open 
and moved it into new core_find_new_threads which represents 
default to_find_new_threads; then I override it in nto-tdep.c

> 
> That said, I think either way is fine - but you'll have to detect
> already-added threads.
> 

I don't think there would be any already added threads? If 
core_open doesn't add them, but defers that to 
target_find_new_threads, I believe (and my test with 
neutrino shows that) we wouldn't have any threads at 
"find_new_threads" time.

However, I am still unclear on whether overriding core_ops 
the way I implemented it is the right way, or should I 
somewhere do a "push_target (&nto_core_ops)"?

-- 
Aleksandar Ristovski
QNX Software Systems


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

* Re: corelow and threads question
  2009-06-05 18:55 corelow and threads question Aleksandar Ristovski
  2009-06-05 19:03 ` Daniel Jacobowitz
@ 2009-06-05 19:24 ` Pedro Alves
  2009-06-05 19:41   ` Aleksandar Ristovski
  1 sibling, 1 reply; 10+ messages in thread
From: Pedro Alves @ 2009-06-05 19:24 UTC (permalink / raw)
  To: gdb; +Cc: Aleksandar Ristovski

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.

-- 
Pedro Alves


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

* Re: corelow and threads question
  2009-06-05 19:24 ` Pedro Alves
@ 2009-06-05 19:41   ` Aleksandar Ristovski
  2009-06-06  0:01     ` Pedro Alves
  2009-06-06  0:27     ` Pedro Alves
  0 siblings, 2 replies; 10+ messages in thread
From: Aleksandar Ristovski @ 2009-06-05 19:41 UTC (permalink / raw)
  To: gdb

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

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

[-- Attachment #2: nto.diff --]
[-- Type: text/x-patch, Size: 46511 bytes --]

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

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

* Re: corelow and threads question
  2009-06-05 19:41   ` Aleksandar Ristovski
@ 2009-06-06  0:01     ` Pedro Alves
  2009-06-06  0:27     ` Pedro Alves
  1 sibling, 0 replies; 10+ messages in thread
From: Pedro Alves @ 2009-06-06  0:01 UTC (permalink / raw)
  To: gdb; +Cc: Aleksandar Ristovski

On Friday 05 June 2009 20:40:23, Aleksandar Ristovski wrote:

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

It is not the "right" way to go.  It will work for a native
nto gdb, but it is not acceptable for mainline.  The core debugging
support should work on cross configurations too.  If you have
anything core support related that depends on the host where gdb was
configured, you have a design bug.  With such a hack, a
multi-arch nto gdb breaks when debugging cores from other
architectures (your core_ops overrides will kick in, although
the core being debugged isn't nto).  A multi-arch gdb
(e.g., --enable-targets=all) on e.g., a linux host, wouldn't
be  able to cross debug nto cores the same as a native
nto gdb, as it would miss the overrides.

-- 
Pedro Alves


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

* Re: corelow and threads question
  2009-06-05 19:41   ` Aleksandar Ristovski
  2009-06-06  0:01     ` Pedro Alves
@ 2009-06-06  0:27     ` Pedro Alves
  2009-06-09 16:10       ` Aleksandar Ristovski
  1 sibling, 1 reply; 10+ messages in thread
From: Pedro Alves @ 2009-06-06  0:27 UTC (permalink / raw)
  To: gdb; +Cc: Aleksandar Ristovski

On Friday 05 June 2009 20:40:23, Aleksandar Ristovski wrote:

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

You don't really need this.  Fix bfd/elf.c to grok the note, and export
a .auxv section, just like corelow.c expects, and other archs do.

> +  core_ops->to_extra_thread_info = nto_target_extra_thread_info;

Looks like one of two things would be possible here:
 - a gdbarch callback so that cores can customize this, move the
   needed code into a nto-tdep.c file, and register the callback.
 - come up with new fake bfd sections like e.g., ".thrextrainfo/TID"
   (named similarly to to .reg/TID), whose contents would simply be the
   string GDB should display, in target_extra_thread_info.  Implement support
   for that in bfd and corelow.c.

> +  core_ops->to_xfer_partial = nto_core_xfer_partial;

This isn't needed, as explained.

> +  core_ops->to_pid_to_str = nto_pid_to_str;

There's already a gdbarch callback for this.

> +  core_ops->to_find_new_threads = nto_find_new_threads_in_core;

Then you'd not have a need for this.  Do any extra needed processing
lazilly in to_extra_thread_info if you must.

-- 
Pedro Alves


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

* Re: corelow and threads question
  2009-06-06  0:27     ` Pedro Alves
@ 2009-06-09 16:10       ` Aleksandar Ristovski
  2009-06-10 16:49         ` Pedro Alves
  0 siblings, 1 reply; 10+ messages in thread
From: Aleksandar Ristovski @ 2009-06-09 16:10 UTC (permalink / raw)
  To: gdb

Hello Pedro,

Thanks for your comments.

Pedro Alves wrote:
> On Friday 05 June 2009 20:40:23, Aleksandar Ristovski wrote:
> 
>> +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)
>> +    {
...
> 
> You don't really need this.  Fix bfd/elf.c to grok the note, and export
> a .auxv section, just like corelow.c expects, and other archs do.

I agree, however, my problem is, we do not really dump auxv 
in a note, I have to retrieve auxv from initial stack; I 
only read status from the note (and from status initial 
stack), then have to read target memory to fetch auxv.

> 
>> +  core_ops->to_extra_thread_info = nto_target_extra_thread_info;
> 
> Looks like one of two things would be possible here:
>  - a gdbarch callback so that cores can customize this, move the
>    needed code into a nto-tdep.c file, and register the callback.
>  - come up with new fake bfd sections like e.g., ".thrextrainfo/TID"
>    (named similarly to to .reg/TID), whose contents would simply be the
>    string GDB should display, in target_extra_thread_info.  Implement support
>    for that in bfd and corelow.c.

The main purpose of fetching extra thread info is to fetch 
thread statuses.

> 
>> +  core_ops->to_xfer_partial = nto_core_xfer_partial;
> 
> This isn't needed, as explained.
> 
>> +  core_ops->to_pid_to_str = nto_pid_to_str;
> 
> There's already a gdbarch callback  for this.

Ok, thanks.

> 
>> +  core_ops->to_find_new_threads = nto_find_new_threads_in_core;
> 
> Then you'd not have a need for this.  Do any extra needed processing
> lazilly in to_extra_thread_info if you must.
> 

But I do not have my to_extra_thread_info active?

I think this is going back to my initial question (pardon my 
ignorance): how do I "install" my to_extra_thread_info? I 
don't see a clean way of pushing my core_ops on top of 
default ones (and I thought that would be a clean way).

I think letting architecture push its customization on top 
of default provided _ops would be very useful. In the 
core_ops example, maybe we could have arch. callback for 
that, and have the callback be called from core_open just 
after core_open pushes core_ops?  That would definitely 
solve all the problems I have in a generic way.


Thanks,

-- 
Aleksandar Ristovski
QNX Software Systems


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

* Re: corelow and threads question
  2009-06-09 16:10       ` Aleksandar Ristovski
@ 2009-06-10 16:49         ` Pedro Alves
  2009-06-10 20:38           ` Aleksandar Ristovski
  0 siblings, 1 reply; 10+ messages in thread
From: Pedro Alves @ 2009-06-10 16:49 UTC (permalink / raw)
  To: gdb; +Cc: Aleksandar Ristovski

On Tuesday 09 June 2009 17:10:09, Aleksandar Ristovski wrote:

> I agree, however, my problem is, we do not really dump auxv 
> in a note, I have to retrieve auxv from initial stack; I 
> only read status from the note (and from status initial 
> stack), then have to read target memory to fetch auxv.

Ok, then a new gdbarch callback would help you here?

> >> +  core_ops->to_extra_thread_info = nto_target_extra_thread_info;
> > 
> > Looks like one of two things would be possible here:
> >  - a gdbarch callback so that cores can customize this, move the
> >    needed code into a nto-tdep.c file, and register the callback.
> >  - come up with new fake bfd sections like e.g., ".thrextrainfo/TID"
> >    (named similarly to to .reg/TID), whose contents would simply be the
> >    string GDB should display, in target_extra_thread_info.  Implement support
> >    for that in bfd and corelow.c.
> 

> >> +  core_ops->to_find_new_threads = nto_find_new_threads_in_core;
> > 

> > Then you'd not have a need for this.  Do any extra needed processing
> > lazilly in to_extra_thread_info if you must.
> > 
> 
> But I do not have my to_extra_thread_info active?

If you do need this, then doesn't the first option I
gave fit?  That would be a new gdbarch_core_extra_thread_info,
for example.

> I think letting architecture push its customization on top 
> of default provided _ops would be very useful. In the 
> core_ops example, maybe we could have arch. callback for 
> that, and have the callback be called from core_open just 
> after core_open pushes core_ops?  That would definitely 
> solve all the problems I have in a generic way.

I don't see that much different from having finer
grained gdbarch callbacks, which can have similar
interfaces to the target_ops methods, thus avoiding
issues with target stack/ops management (as I mentioned before,
think of a a single gdb binary that can debug both native linux
and cross nto: you'd have to undo your changes to core_ops
when you close your core).  Really, to get things done
right, I suggest you build your gdb on a linux host,
with --enable-targets=nto, and hack on your core support
until it can debug cores in that configuration.  :-)

-- 
Pedro Alves


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

* Re: corelow and threads question
  2009-06-10 16:49         ` Pedro Alves
@ 2009-06-10 20:38           ` Aleksandar Ristovski
  0 siblings, 0 replies; 10+ messages in thread
From: Aleksandar Ristovski @ 2009-06-10 20:38 UTC (permalink / raw)
  To: gdb

Thanks for replying.

Ok, then I think what you wanted to commit works for me (I 
am talking about: 
http://sourceware.org/ml/gdb-patches/2009-06/msg00112.html).

As for extra thread info, I guess if we have 
"core_pid_to_str" to be a thing of architecture, then extra 
thread info from core fits there too.


But I am still not happy about having to expand gdbarch 
whenever I have something specific to my architecture for a 
particular stratum - maybe it does belong there but the 
target stack mechanism seems attractive for using in 
"fine-tuning" existing targets ("strata").  This will really 
lead us to having target_ops functions per each predefined 
strata in gdbarch (i.e. customization for core, for process, 
for thread...)


I was playing (in my head) with idea of defining new 
"gdbarch_stratum" that would be used on top of other 
strata... for example, having one gdbarch_stratum per 
defined stratum (i.e. gdbarch_stratum+file_stratum - to 
allow gdbarch customize file_stratum, gdbarch_stratum + 
core_stratum for customizing core stuff, etc...); we would 
have to "spread" stratums in "strata" enum and insert 
gdbarch_ versions above correspoinding strata... that way I 
could really customize each of the strata for my 
architecture only by overriding corresponding _ops functions 
without having to add new function to gdbarch interface and 
regenerating gdbarch files.

Something like this (just an illustration):

enum strata
   {
     dumm_stratum = 0,
     gdbarch_stratum = 1,
     file_stratum = 2,
     core_stratum = 4,
     process_stratum = 6,
     thread_stratum = 8,
     record_stratum = 10
   };


Then I would be able to "inject" my:

...
   nto_core_ops.to_stratum = gdbarch_stratum + core_stratum;

/* But NO add_target(&nto_core_ops); */
...

Then, somewhere in core_open:


/* insert gdbarch specific core stratum just above 
core_stratum */
if (gdbarch_has_stratum (gdbarch_stratum + core_stratum))
     push_target (gdbarch_stratum (gdbarch_stratum + 
core_stratum));



Thanks,


-- 
Aleksandar Ristovski
QNX Software Systems


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

end of thread, other threads:[~2009-06-10 20:38 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-05 18:55 corelow and threads question Aleksandar Ristovski
2009-06-05 19:03 ` Daniel Jacobowitz
2009-06-05 19:20   ` Aleksandar Ristovski
2009-06-05 19:24 ` Pedro Alves
2009-06-05 19:41   ` Aleksandar Ristovski
2009-06-06  0:01     ` Pedro Alves
2009-06-06  0:27     ` Pedro Alves
2009-06-09 16:10       ` Aleksandar Ristovski
2009-06-10 16:49         ` Pedro Alves
2009-06-10 20:38           ` Aleksandar Ristovski

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