This is the mail archive of the
gdb@sourceware.org
mailing list for the GDB project.
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