diff -upN -x CVS -x '.*' -x '*.bak' ../../../srcclean/gdb/gdbserver/configure.srv ./configure.srv --- ../../../srcclean/gdb/gdbserver/configure.srv 2009-05-26 09:56:20.000000000 -0400 +++ ./configure.srv 2009-06-17 10:39:25.000000000 -0400 @@ -74,6 +74,10 @@ case "${target}" in srv_tgtobj="win32-low.o win32-i386-low.o" srv_mingw=yes ;; + i[34567]86-*-nto*) srv_regobj=reg-i386.o + srv_tgtobj="nto-low.o nto-x86-low.o" + extra_srv_libs=-lsocket + ;; ia64-*-linux*) srv_regobj=reg-ia64.o srv_tgtobj="linux-low.o linux-ia64-low.o" srv_linux_usrregs=yes diff -upN -x CVS -x '.*' -x '*.bak' ../../../srcclean/gdb/gdbserver/nto-low.c ./nto-low.c --- ../../../srcclean/gdb/gdbserver/nto-low.c 1969-12-31 19:00:00.000000000 -0500 +++ ./nto-low.c 2009-06-19 15:42:47.000000000 -0400 @@ -0,0 +1,766 @@ +/* QNX Neutrino specific low level interface, for the remote server + for GDB. + Copyright (C) 2009 + Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include "server.h" +#include "nto-low.h" + +#include +#include +#include +#include +#include +#include +#include + +#define _DEBUG_FLAG_TRACE (_DEBUG_FLAG_TRACE_EXEC|_DEBUG_FLAG_TRACE_RD|\ + _DEBUG_FLAG_TRACE_WR|_DEBUG_FLAG_TRACE_MODIFY) + + +extern int using_threads; +int using_threads = 1; + +static void +nto_trace (const char *fmt, ...) +{ + va_list arg_list; + + if (debug_threads == 0) + return; + fprintf (stderr, "nto:"); + va_start (arg_list, fmt); + vfprintf (stderr, fmt, arg_list); + va_end (arg_list); +} + +#define TRACE nto_trace + +struct nto_inferior +{ + char nto_procfs_path[PATH_MAX]; + int ctl_fd; +}; + +static struct nto_inferior nto_inferior; + +static void +do_detach () +{ + if (nto_inferior.ctl_fd != -1) + { + nto_trace ("Closing fd\n"); + close (nto_inferior.ctl_fd); + nto_inferior.ctl_fd = -1; + } +} + +/* Given pid, open procfs path. Return ptid built from pid,0,tid. */ + +static pid_t +do_attach (pid_t pid) +{ + procfs_status status; + struct sigevent event; + + if (nto_inferior.ctl_fd != -1) + { + close (nto_inferior.ctl_fd); + nto_inferior.ctl_fd = -1; + } + snprintf (nto_inferior.nto_procfs_path, PATH_MAX - 1, "/proc/%d/as", pid); + nto_inferior.ctl_fd = open (nto_inferior.nto_procfs_path, O_RDWR); + if (nto_inferior.ctl_fd == -1) + { + TRACE ("Failed to open %s\n", nto_inferior.nto_procfs_path); + return -1; + } + if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, &status, sizeof (status), 0) + != EOK) + { + do_detach (); + return -1; + } + /* Define a sigevent for process stopped notification. */ + event.sigev_notify = SIGEV_SIGNAL_THREAD; + event.sigev_signo = SIGUSR1; + event.sigev_code = 0; + event.sigev_value.sival_ptr = NULL; + event.sigev_priority = -1; + devctl (nto_inferior.ctl_fd, DCMD_PROC_EVENT, &event, sizeof (event), 0); + + if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), + 0) == EOK + && (status.flags & _DEBUG_FLAG_STOPPED)) + { + ptid_t ptid; + + kill (pid, SIGCONT); + ptid = ptid_build (status.pid, status.tid, 0); + the_low_target.arch_setup (); + add_process (status.pid, 1); + TRACE ("Adding thread: pid=%d tid=%ld\n", status.pid, + ptid_get_lwp (ptid)); + add_thread (ptid, NULL); + } + else + { + do_detach (); + return -1; + } + + return pid; +} + +static void +nto_set_thread (ptid_t ptid) +{ + pid_t tid; + + TRACE ("%s pid: %d tid: %ld\n", __func__, ptid_get_pid (ptid), + ptid_get_lwp (ptid)); + + if (nto_inferior.ctl_fd != -1) + { + tid = ptid_get_lwp (ptid); + if (EOK != devctl (nto_inferior.ctl_fd, DCMD_PROC_CURTHREAD, &tid, + sizeof (tid), 0)) + TRACE ("ERROR: setting current thread\n"); + } +} + +static int +nto_xfer_memory (off_t memaddr, unsigned char *myaddr, int len, + int dowrite) +{ + int nbytes = 0; + + if (lseek (nto_inferior.ctl_fd, memaddr, SEEK_SET) == memaddr) + { + if (dowrite) + nbytes = write (nto_inferior.ctl_fd, myaddr, len); + else + nbytes = read (nto_inferior.ctl_fd, myaddr, len); + if (nbytes < 0) + nbytes = 0; + } + if (nbytes == 0) + { + int e = errno; + TRACE ("Error in %s : errno=%d (%s)\n", __func__, e, strerror (e)); + } + return (nbytes); +} + +static int +nto_breakpoint (CORE_ADDR addr, int type, int size) +{ + procfs_break brk; + + brk.type = type; + brk.addr = addr; + brk.size = size; + errno = devctl (nto_inferior.ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0); + if (errno != EOK) + return 1; + return 0; +} + +/* Read AUXV from initial_stack. */ +static int +nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack, + unsigned char *myaddr, + unsigned int len) +{ + int data_ofs = 0; + int anint; + unsigned int len_read = 0; + + /* Skip over argc, argv and envp... (see comment in ldd.c) */ + if (nto_xfer_memory (initial_stack, (unsigned char *)&anint, + sizeof (anint), 0) != sizeof (anint)) + return 0; + + /* Size of pointer is assumed to be 4 bytes (32 bit arch. ) */ + data_ofs += (anint + 2) * sizeof (void *); /* + 2 comes from argc itself and + NULL terminating pointer in + argv. */ + + /* Now loop over env table: */ + while (nto_xfer_memory (initial_stack + data_ofs, + (unsigned char *)&anint, sizeof (anint), 0) + == sizeof (anint)) + { + data_ofs += sizeof (anint); + if (anint == 0) + break; + } + initial_stack += data_ofs; + + memset (myaddr, 0, len); + while (len_read <= len - sizeof (auxv_t)) + { + auxv_t *auxv = (auxv_t *)myaddr; + + /* Search backwards until we have read AT_PHDR (num. 3), + AT_PHENT (num 4), AT_PHNUM (num 5) */ + if (nto_xfer_memory (initial_stack, (unsigned char *)auxv, + sizeof (auxv_t), 0) == sizeof (auxv_t)) + { + if (auxv->a_type != AT_NULL) + { + auxv++; + len_read += sizeof (auxv_t); + } + if (auxv->a_type == AT_PHNUM) /* That's all we need. */ + break; + initial_stack += sizeof (auxv_t); + } + else + break; + } + TRACE ("auxv: len_read: %d\n", len_read); + return len_read; +} + +/* Start inferior specified by PROGRAM passing arguments ALLARGS. */ + +static int +nto_create_inferior (char *program, char **allargs) +{ + struct inheritance inherit; + pid_t pid; + sigset_t set; + + TRACE ("%s %s\n", __func__, program); + /* Clear any pending SIGUSR1's but keep the behavior the same. */ + signal (SIGUSR1, signal (SIGUSR1, SIG_IGN)); + + sigemptyset (&set); + sigaddset (&set, SIGUSR1); + sigprocmask (SIG_UNBLOCK, &set, NULL); + + memset (&inherit, 0, sizeof (inherit)); + inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD; + inherit.pgroup = SPAWN_NEWPGROUP; + pid = spawnp (program, 0, NULL, &inherit, allargs, 0); + sigprocmask (SIG_BLOCK, &set, NULL); + + if (pid == -1) + return -1; + + if (do_attach (pid) != pid) + return -1; + + return pid; +} + +static int +nto_attach (unsigned long pid) +{ + TRACE ("%s %ld\n", __func__, pid); + if (do_attach (pid) != pid) + error ("Unable to attach to %ld\n", pid); + return 0; +} + +static int +nto_kill (int pid) +{ + TRACE ("%s %d\n", __func__, pid); + kill (pid, SIGKILL); + do_detach (); + return 0; +} + +static int +nto_detach (int pid) +{ + TRACE ("%s %d\n", __func__, pid); + do_detach (); + return 0; +} + +static int +nto_thread_alive (ptid_t ptid) +{ + pid_t tid; + + tid = ptid_get_lwp (ptid); + TRACE ("%s %d\n", __func__, tid); + if (devctl (nto_inferior.ctl_fd, DCMD_PROC_CURTHREAD, &tid, sizeof (tid), 0) + == EOK) + return 1; + return 0; +} + +static void +nto_resume (struct thread_resume *resume_info, size_t n) +{ + /* We can only work in all-stop mode. */ + procfs_status status; + procfs_run run; + int err; + + TRACE ("%s\n", __func__); + /* Workaround for aliasing rules violation. */ + sigset_t *run_fault = (sigset_t *) (void *) &run.fault; + nto_set_thread (resume_info->thread); + + run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE; + if (resume_info->kind == resume_step) + run.flags |= _DEBUG_RUN_STEP; + run.flags |= _DEBUG_RUN_ARM; + + sigemptyset (run_fault); + sigaddset (run_fault, FLTBPT); + sigaddset (run_fault, FLTTRACE); + sigaddset (run_fault, FLTILL); + sigaddset (run_fault, FLTPRIV); + sigaddset (run_fault, FLTBOUNDS); + sigaddset (run_fault, FLTIOVF); + sigaddset (run_fault, FLTIZDIV); + sigaddset (run_fault, FLTFPE); + sigaddset (run_fault, FLTPAGE); + + sigemptyset (&run.trace); + if (resume_info->sig) + { + int signal_to_pass; + + devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), + 0); + signal_to_pass = resume_info->sig; + if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED)) + { + if (signal_to_pass != status.info.si_signo) + { + kill (status.pid, signal_to_pass); + run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG; + } + else /* Let it kill the program without telling us. */ + sigdelset (&run.trace, signal_to_pass); + } + } + else + run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT; + + regcache_invalidate (); + + err = devctl (nto_inferior.ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0); + if (err != EOK) + TRACE ("Error: %d \"%s\"\n", err); +} + +static ptid_t +nto_wait (ptid_t ptid, + struct target_waitstatus *ourstatus, int target_options) +{ + sigset_t set; + siginfo_t info; + procfs_status status; + static int exit_signo = 0; /* For tracking exit status. */ + + TRACE ("%s\n", __func__); + + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + + + sigemptyset (&set); + sigaddset (&set, SIGUSR1); + + devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0); + while (!(status.flags & _DEBUG_FLAG_ISTOP)) + { + sigwaitinfo (&set, &info); + devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), + 0); + } + + if (status.flags & _DEBUG_FLAG_SSTEP) + { + TRACE ("SSTEP\n"); + ourstatus->kind = TARGET_WAITKIND_STOPPED; + ourstatus->value.sig = TARGET_SIGNAL_TRAP; + } + /* Was it a breakpoint? */ + else if (status.flags & _DEBUG_FLAG_TRACE) + { + TRACE ("STOPPED\n"); + ourstatus->kind = TARGET_WAITKIND_STOPPED; + ourstatus->value.sig = TARGET_SIGNAL_TRAP; + } + else if (status.flags & _DEBUG_FLAG_ISTOP) + { + TRACE ("ISTOP\n"); + switch (status.why) + { + case _DEBUG_WHY_SIGNALLED: + TRACE (" SIGNALLED\n"); + ourstatus->kind = TARGET_WAITKIND_STOPPED; + ourstatus->value.sig = + target_signal_from_host (status.info.si_signo); + exit_signo = 0; + break; + case _DEBUG_WHY_FAULTED: + TRACE (" FAULTED\n"); + ourstatus->kind = TARGET_WAITKIND_STOPPED; + if (status.info.si_signo == SIGTRAP) + { + ourstatus->value.sig = 0; + exit_signo = 0; + } + else + { + ourstatus->value.sig = + target_signal_from_host (status.info.si_signo); + exit_signo = ourstatus->value.sig; + } + break; + + case _DEBUG_WHY_TERMINATED: + { + int waitval = 0; + + TRACE (" TERMINATED\n"); + waitpid (ptid_get_pid (ptid), &waitval, WNOHANG); + if (exit_signo) + { + /* Abnormal death. */ + ourstatus->kind = TARGET_WAITKIND_SIGNALLED; + ourstatus->value.sig = exit_signo; + } + else + { + /* Normal death. */ + ourstatus->kind = TARGET_WAITKIND_EXITED; + ourstatus->value.integer = WEXITSTATUS (waitval); + } + exit_signo = 0; + break; + } + + case _DEBUG_WHY_REQUESTED: + TRACE ("REQUESTED\n"); + /* We are assuming a requested stop is due to a SIGINT. */ + ourstatus->kind = TARGET_WAITKIND_STOPPED; + ourstatus->value.sig = TARGET_SIGNAL_INT; + exit_signo = 0; + break; + } + } + + return ptid_build (status.pid, status.tid, 0); +} + +static void +nto_fetch_registers (int regno) +{ + int regsize; + procfs_greg greg; + + TRACE ("%s (regno=%d)\n", __func__, regno); + if (regno >= the_low_target.num_regs) + return; + + if (devctl (nto_inferior.ctl_fd, DCMD_PROC_GETGREG, &greg, sizeof (greg), + ®size) == EOK) + { + if (regno == -1) /* All registers. */ + { + for (regno = 0; regno != the_low_target.num_regs; ++regno) + { + const unsigned int registeroffset + = the_low_target.register_offset (regno); + supply_register (regno, ((char *)&greg) + registeroffset); + } + } + else + { + const unsigned int registeroffset + = the_low_target.register_offset (regno); + + if (registeroffset == -1) + return; + supply_register (regno, ((char *)&greg) + registeroffset); + } + } + else + TRACE ("ERROR reading registers from inferior.\n"); +} + +static void +nto_store_registers (int regno) +{ + procfs_greg greg; + int err; + + TRACE ("%s (regno:%d)\n", __func__, regno); + memset (&greg, 0, sizeof (greg)); + for (regno = 0; regno != the_low_target.num_regs; ++regno) + { + const unsigned int regoffset + = the_low_target.register_offset (regno); + collect_register (regno, ((char *)&greg) + regoffset); + } + err = devctl (nto_inferior.ctl_fd, DCMD_PROC_SETGREG, &greg, sizeof (greg), + 0); + if (err != EOK) + TRACE ("Error: setting registers.\n"); +} + +static int +nto_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) +{ + TRACE ("%s\n", __func__); + + if (nto_xfer_memory (memaddr, myaddr, len, 0) != len) + { + TRACE ("Failed to read memory\n"); + return -1; + } + + return 0; +} + +static int +nto_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) +{ + int len_written; + + TRACE ("%s memaddr: 0x%08llx len: %d\n", __func__, memaddr, len); + if ((len_written = nto_xfer_memory (memaddr, (unsigned char *)myaddr, len, + 1)) + != len) + { + TRACE ("Wanted to write: %d but written: %d\n", len, len_written); + return -1; + } + + return 0; +} + +static void +nto_request_interrupt (void) +{ + TRACE (__func__); + devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, NULL, 0, 0); +} + +static int +nto_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len) +{ + int err; + CORE_ADDR initial_stack; + procfs_info procinfo; + + TRACE ("%s\n", __func__); + if (offset > 0) + return 0; + + err = devctl (nto_inferior.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, myaddr, len); +} + +static int +nto_insert_breakpoint (char type, CORE_ADDR addr) +{ + TRACE ("%s\n", __func__); + switch (type) + { + case '0': /* software-breakpoint */ + return nto_breakpoint (addr, _DEBUG_BREAK_EXEC, 0); + case '1': /* hardware-breakpoint */ + return nto_breakpoint (addr, _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, 0); + } + return 1; /* Not supported. */ +} + +static int +nto_remove_breakpoint (char type, CORE_ADDR addr) +{ + TRACE ("%s\n", __func__); + switch (type) + { + case '0': /* software-breakpoint */ + return nto_breakpoint (addr, _DEBUG_BREAK_EXEC, -1); + case '1': /* hardware-breakpoint */ + return nto_breakpoint (addr, _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, -1); + } + /* Not supported. */ + return 1; +} + +static int +nto_insert_watchpoint (char type, CORE_ADDR addr, int len) +{ + int wtype = _DEBUG_BREAK_HW; /* Always request HW. */ + + TRACE ("%s type:%c\n", __func__, type); + switch (type) + { + case '2': /* write watchpoint */ + wtype |= _DEBUG_BREAK_RW; + break; + case '3': /* read watchpoint */ + wtype |= _DEBUG_BREAK_RD + break; + case '4': /* access watchpoint */ + wtype |= _DEBUG_BREAK_RW; + break; + default: + return 1; /* Not supported. */ + } + return nto_breakpoint (addr, wtype, 0); +} + +static int +nto_remove_watchpoint (char type, CORE_ADDR addr, int len) +{ + int wtype = _DEBUG_BREAK_HW; /* Always request HW. */ + + TRACE ("%s type:%c\n", __func__, type); + switch (type) + { + case '2': /* write watchpoint */ + wtype |= _DEBUG_BREAK_RW; + break; + case '3': /* read watchpoint */ + wtype |= _DEBUG_BREAK_RD; + break; + case '4': /* access watchpoint */ + wtype |= _DEBUG_BREAK_RW; + break; + default: + return 1; /* Not supported. */ + } + return nto_breakpoint (addr, wtype, -1); +} + +static int +nto_stopped_by_watchpoint (void) +{ + procfs_status status; + int ret = 0; + const int watchmask = _DEBUG_FLAG_TRACE_RD | _DEBUG_FLAG_TRACE_WR + | _DEBUG_FLAG_TRACE_MODIFY; + + TRACE ("%s...", __func__); + if (nto_inferior.ctl_fd != -1) + { + int err = devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, + sizeof (status), 0); + if (err == EOK && (status.flags & watchmask)) + ret = 1; + } + TRACE ("%s\n", ret ? "yes" : "no"); + return ret; +} + +static CORE_ADDR +nto_stopped_data_address (void) +{ + procfs_status status; + CORE_ADDR ret = (CORE_ADDR)0; + + TRACE ("%s...", __func__); + if (nto_inferior.ctl_fd != -1) + { + int err; + err = devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, + sizeof (status), 0); + if (err == EOK) + ret = status.ip; + } + return ret; +} + + +static int +nto_supports_non_stop (void) +{ + TRACE ("%s\n", __func__); + return 0; +} + + + +static struct target_ops nto_target_ops = { + nto_create_inferior, + nto_attach, + nto_kill, + nto_detach, + NULL, /* nto_join */ + nto_thread_alive, + nto_resume, + nto_wait, + nto_fetch_registers, + nto_store_registers, + nto_read_memory, + nto_write_memory, + NULL, /* nto_look_up_symbols */ + nto_request_interrupt, + nto_read_auxv, + nto_insert_breakpoint, + nto_remove_breakpoint, + nto_insert_watchpoint, + nto_remove_watchpoint, + nto_stopped_by_watchpoint, + nto_stopped_data_address, + NULL, /* nto_read_offsets */ + NULL, /* thread_db_set_tls_address */ + NULL, + hostio_last_error_from_errno, + NULL, /* nto_qxfer_osdata */ + NULL, /* xfer_siginfo */ + nto_supports_non_stop, + NULL, /* async */ + NULL /* start_non_stop */ +}; + + +/* Global function called by server.c. Initializes QNX Neutrino + gdbserver. */ + +void +initialize_low (void) +{ + sigset_t set; + + TRACE ("%s\n", __func__); + set_target_ops (&nto_target_ops); + set_breakpoint_data (the_low_target.breakpoint, + the_low_target.breakpoint_len); + + /* We use SIGUSR1 to gain control after we block waiting for a process. + We use sigwaitevent to wait. */ + sigemptyset (&set); + sigaddset (&set, SIGUSR1); + sigprocmask (SIG_BLOCK, &set, NULL); +} + diff -upN -x CVS -x '.*' -x '*.bak' ../../../srcclean/gdb/gdbserver/nto-low.h ./nto-low.h --- ../../../srcclean/gdb/gdbserver/nto-low.h 1969-12-31 19:00:00.000000000 -0500 +++ ./nto-low.h 2009-06-17 10:35:04.000000000 -0400 @@ -0,0 +1,50 @@ +/* Internal interfaces for the QNX Neutrino specific target code for gdbserver. + Copyright (C) 2009 + Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef NTO_LOW_H +#define NTO_LOW_H + +enum regset_type +{ + NTO_REG_GENERAL, + NTO_REG_FLOAT, + NTO_REG_SYSTEM, + NTO_REG_ALT, + NTO_REG_END +}; + +struct nto_target_ops +{ + /* Architecture specific setup. */ + void (*arch_setup) (void); + + int num_regs; + int (*register_offset)(int gdbregno); + const unsigned char *breakpoint; + int breakpoint_len; +}; + +extern struct nto_target_ops the_low_target; + + +/* Activated by env. variable GDBSERVER_DEBUG. */ +extern int nto_debug; + +#endif + diff -upN -x CVS -x '.*' -x '*.bak' ../../../srcclean/gdb/gdbserver/nto-x86-low.c ./nto-x86-low.c --- ../../../srcclean/gdb/gdbserver/nto-x86-low.c 1969-12-31 19:00:00.000000000 -0500 +++ ./nto-x86-low.c 2009-06-17 10:35:04.000000000 -0400 @@ -0,0 +1,108 @@ +/* QNX Neutrino specific low level interface, for the remote server + for GDB. + Copyright (C) 2009 + Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include "nto-low.h" +#include "regdef.h" +#include "regcache.h" + +#include + + +/* Definition auto generated from reg-i386.dep. */ +extern void init_registers_i386 (); +extern struct reg *regs_i386; + +const unsigned char x86_breakpoint[] = { 0xCC }; +#define x86_breakpoint_len 1 + +/* Returns offset in appropriate Neutrino's context structure. + Defined in x86/context.h. + GDBREGNO is index into regs_i386 array. It is autogenerated and + hopefully doesn't change. */ +static int +nto_x86_register_offset (int gdbregno) +{ + if (gdbregno >= 0 && gdbregno < 16) + { + X86_CPU_REGISTERS *dummy = (void*)0; + /* GPRs */ + switch (gdbregno) + { + case 0: + return (int)&(dummy->eax); + case 1: + return (int)&(dummy->ecx); + case 2: + return (int)&(dummy->edx); + case 3: + return (int)&(dummy->ebx); + case 4: + return (int)&(dummy->esp); + case 5: + return (int)&(dummy->ebp); + case 6: + return (int)&(dummy->esi); + case 7: + return (int)&(dummy->edi); + case 8: + return (int)&(dummy->eip); + case 9: + return (int)&(dummy->efl); + case 10: + return (int)&(dummy->cs); + case 11: + return (int)&(dummy->ss); +#ifdef __SEGMENTS__ + case 12: + return (int)&(dummy->ds); + case 13: + return (int)&(dummy->es); + case 14: + return (int)&(dummy->fs); + case 15: + return (int)&(dummy->gs); +#endif + default: + return -1; + } + } + //TODO: FPU, XMM registers + return -1; +} + +static void +nto_x86_arch_setup (void) +{ + init_registers_i386 (); + the_low_target.num_regs = 16; +} + +struct nto_target_ops the_low_target = +{ + nto_x86_arch_setup, + 0, /* num_regs */ + nto_x86_register_offset, + x86_breakpoint, + x86_breakpoint_len +}; + + + diff -upN -x CVS -x '.*' -x '*.bak' ../../../srcclean/gdb/gdbserver/remote-utils.c ./remote-utils.c --- ../../../srcclean/gdb/gdbserver/remote-utils.c 2009-05-26 09:56:20.000000000 -0400 +++ ./remote-utils.c 2009-06-17 10:35:04.000000000 -0400 @@ -66,6 +66,10 @@ #include #endif +#if __QNX__ +#include +#endif /* __QNX__ */ + #ifndef HAVE_SOCKLEN_T typedef int socklen_t; #endif @@ -814,6 +818,28 @@ unblock_async_io (void) #endif } +#ifdef __QNX__ +static void +nto_comctrl (int enable) +{ + struct sigevent event; + + if (enable) + { + event.sigev_notify = SIGEV_SIGNAL_THREAD; + event.sigev_signo = SIGIO; + event.sigev_code = 0; + event.sigev_value.sival_ptr = NULL; + event.sigev_priority = -1; + ionotify (remote_desc, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, + &event); + } + else + ionotify (remote_desc, _NOTIFY_ACTION_POLL, _NOTIFY_COND_INPUT, NULL); +} +#endif /* __QNX__ */ + + /* Current state of asynchronous I/O. */ static int async_io_enabled; @@ -828,6 +854,9 @@ enable_async_io (void) signal (SIGIO, input_interrupt); #endif async_io_enabled = 1; +#ifdef __QNX__ + nto_comctrl (1); +#endif /* __QNX__ */ } /* Disable asynchronous I/O. */ @@ -841,6 +870,10 @@ disable_async_io (void) signal (SIGIO, SIG_IGN); #endif async_io_enabled = 0; +#ifdef __QNX__ + nto_comctrl (0); +#endif /* __QNX__ */ + } void