GDBserver
/home/stan/gdb/src/gdb/gdbserver/nto-low.c
Go to the documentation of this file.
00001 /* QNX Neutrino specific low level interface, for the remote server
00002    for GDB.
00003    Copyright (C) 2009-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 
00021 #include "server.h"
00022 #include "gdbthread.h"
00023 #include "nto-low.h"
00024 #include "hostio.h"
00025 
00026 #include <limits.h>
00027 #include <fcntl.h>
00028 #include <spawn.h>
00029 #include <sys/procfs.h>
00030 #include <sys/auxv.h>
00031 #include <stdarg.h>
00032 #include <sys/iomgr.h>
00033 #include <sys/neutrino.h>
00034 
00035 
00036 extern int using_threads;
00037 int using_threads = 1;
00038 
00039 const struct target_desc *nto_tdesc;
00040 
00041 static void
00042 nto_trace (const char *fmt, ...)
00043 {
00044   va_list arg_list;
00045 
00046   if (debug_threads == 0)
00047     return;
00048   fprintf (stderr, "nto:");
00049   va_start (arg_list, fmt);
00050   vfprintf (stderr, fmt, arg_list);
00051   va_end (arg_list);
00052 }
00053 
00054 #define TRACE nto_trace
00055 
00056 /* Structure holding neutrino specific information about
00057    inferior.  */
00058 
00059 struct nto_inferior
00060 {
00061   char nto_procfs_path[PATH_MAX];
00062   int ctl_fd;
00063   pid_t pid;
00064   int exit_signo; /* For tracking exit status.  */
00065 };
00066 
00067 static struct nto_inferior nto_inferior;
00068 
00069 static void
00070 init_nto_inferior (struct nto_inferior *nto_inferior)
00071 {
00072   memset (nto_inferior, 0, sizeof (struct nto_inferior));
00073   nto_inferior->ctl_fd = -1;
00074   nto_inferior->pid = -1;
00075 }
00076 
00077 static void
00078 do_detach (void)
00079 {
00080   if (nto_inferior.ctl_fd != -1)
00081     {
00082       nto_trace ("Closing fd\n");
00083       close (nto_inferior.ctl_fd);
00084       init_nto_inferior (&nto_inferior);
00085     }
00086 }
00087 
00088 /* Set current thread. Return 1 on success, 0 otherwise.  */
00089 
00090 static int
00091 nto_set_thread (ptid_t ptid)
00092 {
00093   int res = 0;
00094 
00095   TRACE ("%s pid: %d tid: %ld\n", __func__, ptid_get_pid (ptid),
00096          ptid_get_lwp (ptid));
00097   if (nto_inferior.ctl_fd != -1
00098       && !ptid_equal (ptid, null_ptid)
00099       && !ptid_equal (ptid, minus_one_ptid))
00100     {
00101       pthread_t tid = ptid_get_lwp (ptid);
00102 
00103       if (EOK == devctl (nto_inferior.ctl_fd, DCMD_PROC_CURTHREAD, &tid,
00104           sizeof (tid), 0))
00105         res = 1;
00106       else
00107         TRACE ("%s: Error: failed to set current thread\n", __func__);
00108     }
00109   return res;
00110 }
00111 
00112 /* This function will determine all alive threads.  Note that we do not list
00113    dead but unjoined threads even though they are still in the process' thread
00114    list.  
00115 
00116    NTO_INFERIOR must not be NULL.  */
00117 
00118 static void
00119 nto_find_new_threads (struct nto_inferior *nto_inferior)
00120 {
00121   pthread_t tid;
00122 
00123   TRACE ("%s pid:%d\n", __func__, nto_inferior->pid);
00124 
00125   if (nto_inferior->ctl_fd == -1)
00126     return;
00127 
00128   for (tid = 1;; ++tid)
00129     {
00130       procfs_status status;
00131       ptid_t ptid;
00132       int err;
00133 
00134       status.tid = tid;
00135       err = devctl (nto_inferior->ctl_fd, DCMD_PROC_TIDSTATUS, &status,
00136                     sizeof (status), 0);
00137 
00138       if (err != EOK || status.tid == 0)
00139         break;
00140 
00141       /* All threads in between are gone.  */
00142       while (tid != status.tid || status.state == STATE_DEAD)
00143         {
00144           struct thread_info *ti;
00145 
00146           ptid = ptid_build (nto_inferior->pid, tid, 0);
00147           ti = find_thread_ptid (ptid);
00148           if (ti != NULL)
00149             {
00150               TRACE ("Removing thread %d\n", tid);
00151               remove_thread (ti);
00152             }
00153           if (tid == status.tid)
00154             break;
00155           ++tid;
00156         }
00157 
00158       if (status.state != STATE_DEAD)
00159         {
00160           TRACE ("Adding thread %d\n", tid);
00161           ptid = ptid_build (nto_inferior->pid, tid, 0);
00162           if (!find_thread_ptid (ptid))
00163             add_thread (ptid, NULL);
00164         }
00165     }
00166 }
00167 
00168 /* Given pid, open procfs path.  */
00169 
00170 static pid_t
00171 do_attach (pid_t pid)
00172 {
00173   procfs_status status;
00174   struct sigevent event;
00175 
00176   if (nto_inferior.ctl_fd != -1)
00177     {
00178       close (nto_inferior.ctl_fd);
00179       init_nto_inferior (&nto_inferior);
00180     }
00181   xsnprintf (nto_inferior.nto_procfs_path, PATH_MAX - 1, "/proc/%d/as", pid);
00182   nto_inferior.ctl_fd = open (nto_inferior.nto_procfs_path, O_RDWR);
00183   if (nto_inferior.ctl_fd == -1)
00184     {
00185       TRACE ("Failed to open %s\n", nto_inferior.nto_procfs_path);
00186       init_nto_inferior (&nto_inferior);
00187       return -1;
00188     }
00189   if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, &status, sizeof (status), 0)
00190       != EOK)
00191     {
00192       do_detach ();
00193       return -1;
00194     }
00195   nto_inferior.pid = pid;
00196   /* Define a sigevent for process stopped notification.  */
00197   event.sigev_notify = SIGEV_SIGNAL_THREAD;
00198   event.sigev_signo = SIGUSR1;
00199   event.sigev_code = 0;
00200   event.sigev_value.sival_ptr = NULL;
00201   event.sigev_priority = -1;
00202   devctl (nto_inferior.ctl_fd, DCMD_PROC_EVENT, &event, sizeof (event), 0);
00203 
00204   if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
00205               0) == EOK
00206       && (status.flags & _DEBUG_FLAG_STOPPED))
00207     {
00208       ptid_t ptid;
00209       struct process_info *proc;
00210 
00211       kill (pid, SIGCONT);
00212       ptid = ptid_build (status.pid, status.tid, 0);
00213       the_low_target.arch_setup ();
00214       proc = add_process (status.pid, 1);
00215       proc->tdesc = nto_tdesc;
00216       TRACE ("Adding thread: pid=%d tid=%ld\n", status.pid,
00217              ptid_get_lwp (ptid));
00218       nto_find_new_threads (&nto_inferior);
00219     }
00220   else
00221     {
00222       do_detach ();
00223       return -1;
00224     }
00225 
00226   return pid;
00227 }
00228 
00229 /* Read or write LEN bytes from/to inferior's MEMADDR memory address
00230    into gdbservers's MYADDR buffer.  Return number of bytes actually
00231    transfered.  */
00232 
00233 static int
00234 nto_xfer_memory (off_t memaddr, unsigned char *myaddr, int len,
00235                  int dowrite)
00236 {
00237   int nbytes = 0;
00238 
00239   if (lseek (nto_inferior.ctl_fd, memaddr, SEEK_SET) == memaddr)
00240     {
00241       if (dowrite)
00242         nbytes = write (nto_inferior.ctl_fd, myaddr, len);
00243       else
00244         nbytes = read (nto_inferior.ctl_fd, myaddr, len);
00245       if (nbytes < 0)
00246         nbytes = 0;
00247     }
00248   if (nbytes == 0)
00249     {
00250       int e = errno;
00251       TRACE ("Error in %s : errno=%d (%s)\n", __func__, e, strerror (e));
00252     }
00253   return nbytes;
00254 }
00255 
00256 /* Insert or remove breakpoint or watchpoint at address ADDR.
00257    TYPE can be one of Neutrino breakpoint types.  SIZE must be 0 for
00258    inserting the point, -1 for removing it.  
00259 
00260    Return 0 on success, 1 otherwise.  */
00261 
00262 static int
00263 nto_breakpoint (CORE_ADDR addr, int type, int size)
00264 {
00265   procfs_break brk;
00266 
00267   brk.type = type;
00268   brk.addr = addr;
00269   brk.size = size;
00270   if (devctl (nto_inferior.ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0)
00271       != EOK)
00272     return 1;
00273   return 0;
00274 }
00275 
00276 /* Read auxiliary vector from inferior's initial stack into gdbserver's
00277    MYADDR buffer, up to LEN bytes.  
00278 
00279    Return number of bytes read.  */
00280 
00281 static int
00282 nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack,
00283                                   unsigned char *myaddr,
00284                                   unsigned int len)
00285 {
00286   int data_ofs = 0;
00287   int anint;
00288   unsigned int len_read = 0;
00289 
00290   /* Skip over argc, argv and envp... Comment from ldd.c:
00291 
00292      The startup frame is set-up so that we have:
00293      auxv
00294      NULL
00295      ...
00296      envp2
00297      envp1 <----- void *frame + (argc + 2) * sizeof(char *)
00298      NULL
00299      ...
00300      argv2
00301      argv1
00302      argc  <------ void * frame
00303 
00304      On entry to ldd, frame gives the address of argc on the stack.  */
00305   if (nto_xfer_memory (initial_stack, (unsigned char *)&anint,
00306                        sizeof (anint), 0) != sizeof (anint))
00307     return 0;
00308 
00309   /* Size of pointer is assumed to be 4 bytes (32 bit arch. ) */
00310   data_ofs += (anint + 2) * sizeof (void *); /* + 2 comes from argc itself and
00311                                                 NULL terminating pointer in
00312                                                 argv.  */
00313 
00314   /* Now loop over env table:  */
00315   while (nto_xfer_memory (initial_stack + data_ofs,
00316                           (unsigned char *)&anint, sizeof (anint), 0)
00317          == sizeof (anint))
00318     {
00319       data_ofs += sizeof (anint);
00320       if (anint == 0)
00321         break;
00322     }
00323   initial_stack += data_ofs;
00324 
00325   memset (myaddr, 0, len);
00326   while (len_read <= len - sizeof (auxv_t))
00327     {
00328       auxv_t *auxv = (auxv_t *)myaddr;
00329 
00330       /* Search backwards until we have read AT_PHDR (num. 3),
00331          AT_PHENT (num 4), AT_PHNUM (num 5)  */
00332       if (nto_xfer_memory (initial_stack, (unsigned char *)auxv,
00333                            sizeof (auxv_t), 0) == sizeof (auxv_t))
00334         {
00335           if (auxv->a_type != AT_NULL)
00336             {
00337               auxv++;
00338               len_read += sizeof (auxv_t);
00339             }
00340           if (auxv->a_type == AT_PHNUM) /* That's all we need.  */
00341             break;
00342           initial_stack += sizeof (auxv_t);
00343         }
00344       else
00345         break;
00346     }
00347   TRACE ("auxv: len_read: %d\n", len_read);
00348   return len_read;
00349 }
00350 
00351 /* Start inferior specified by PROGRAM passing arguments ALLARGS.  */
00352 
00353 static int
00354 nto_create_inferior (char *program, char **allargs)
00355 {
00356   struct inheritance inherit;
00357   pid_t pid;
00358   sigset_t set;
00359 
00360   TRACE ("%s %s\n", __func__, program);
00361   /* Clear any pending SIGUSR1's but keep the behavior the same.  */
00362   signal (SIGUSR1, signal (SIGUSR1, SIG_IGN));
00363 
00364   sigemptyset (&set);
00365   sigaddset (&set, SIGUSR1);
00366   sigprocmask (SIG_UNBLOCK, &set, NULL);
00367 
00368   memset (&inherit, 0, sizeof (inherit));
00369   inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
00370   inherit.pgroup = SPAWN_NEWPGROUP;
00371   pid = spawnp (program, 0, NULL, &inherit, allargs, 0);
00372   sigprocmask (SIG_BLOCK, &set, NULL);
00373 
00374   if (pid == -1)
00375     return -1;
00376 
00377   if (do_attach (pid) != pid)
00378     return -1;
00379 
00380   return pid;
00381 }
00382 
00383 /* Attach to process PID.  */
00384 
00385 static int
00386 nto_attach (unsigned long pid)
00387 {
00388   TRACE ("%s %ld\n", __func__, pid);
00389   if (do_attach (pid) != pid)
00390     error ("Unable to attach to %ld\n", pid);
00391   return 0;
00392 }
00393 
00394 /* Send signal to process PID.  */
00395 
00396 static int
00397 nto_kill (int pid)
00398 {
00399   TRACE ("%s %d\n", __func__, pid);
00400   kill (pid, SIGKILL);
00401   do_detach ();
00402   return 0;
00403 }
00404 
00405 /* Detach from process PID.  */
00406 
00407 static int
00408 nto_detach (int pid)
00409 {
00410   TRACE ("%s %d\n", __func__, pid);
00411   do_detach ();
00412   return 0;
00413 }
00414 
00415 static void
00416 nto_mourn (struct process_info *process)
00417 {
00418   remove_process (process);
00419 }
00420 
00421 /* Check if the given thread is alive.  
00422 
00423    Return 1 if alive, 0 otherwise.  */
00424 
00425 static int
00426 nto_thread_alive (ptid_t ptid)
00427 {
00428   int res;
00429 
00430   TRACE ("%s pid:%d tid:%d\n", __func__, ptid_get_pid (ptid),
00431          ptid_get_lwp (ptid));
00432   if (SignalKill (0, ptid_get_pid (ptid), ptid_get_lwp (ptid),
00433                   0, 0, 0) == -1)
00434     res = 0;
00435   else
00436     res = 1;
00437   TRACE ("%s: %s\n", __func__, res ? "yes" : "no");
00438   return res;
00439 }
00440 
00441 /* Resume inferior's execution.  */
00442 
00443 static void
00444 nto_resume (struct thread_resume *resume_info, size_t n)
00445 {
00446   /* We can only work in all-stop mode.  */
00447   procfs_status status;
00448   procfs_run run;
00449   int err;
00450 
00451   TRACE ("%s\n", __func__);
00452   /* Workaround for aliasing rules violation. */
00453   sigset_t *run_fault = (sigset_t *) (void *) &run.fault;
00454 
00455   nto_set_thread (resume_info->thread);
00456 
00457   run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE;
00458   if (resume_info->kind == resume_step)
00459     run.flags |= _DEBUG_RUN_STEP;
00460   run.flags |= _DEBUG_RUN_ARM;
00461 
00462   sigemptyset (run_fault);
00463   sigaddset (run_fault, FLTBPT);
00464   sigaddset (run_fault, FLTTRACE);
00465   sigaddset (run_fault, FLTILL);
00466   sigaddset (run_fault, FLTPRIV);
00467   sigaddset (run_fault, FLTBOUNDS);
00468   sigaddset (run_fault, FLTIOVF);
00469   sigaddset (run_fault, FLTIZDIV);
00470   sigaddset (run_fault, FLTFPE);
00471   sigaddset (run_fault, FLTPAGE);
00472   sigaddset (run_fault, FLTSTACK);
00473   sigaddset (run_fault, FLTACCESS);
00474 
00475   sigemptyset (&run.trace);
00476   if (resume_info->sig)
00477     {
00478       int signal_to_pass;
00479 
00480       devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
00481               0);
00482       signal_to_pass = resume_info->sig;
00483       if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
00484         {
00485           if (signal_to_pass != status.info.si_signo)
00486             {
00487               kill (status.pid, signal_to_pass);
00488               run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
00489             }
00490           else          /* Let it kill the program without telling us.  */
00491             sigdelset (&run.trace, signal_to_pass);
00492         }
00493     }
00494   else
00495     run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT;
00496 
00497   sigfillset (&run.trace);
00498 
00499   regcache_invalidate ();
00500 
00501   err = devctl (nto_inferior.ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
00502   if (err != EOK)
00503     TRACE ("Error: %d \"%s\"\n", err, strerror (err));
00504 }
00505 
00506 /* Wait for inferior's event.  
00507 
00508    Return ptid of thread that caused the event.  */
00509 
00510 static ptid_t
00511 nto_wait (ptid_t ptid,
00512           struct target_waitstatus *ourstatus, int target_options)
00513 {
00514   sigset_t set;
00515   siginfo_t info;
00516   procfs_status status;
00517   const int trace_mask = (_DEBUG_FLAG_TRACE_EXEC | _DEBUG_FLAG_TRACE_RD
00518                           | _DEBUG_FLAG_TRACE_WR | _DEBUG_FLAG_TRACE_MODIFY);
00519 
00520   TRACE ("%s\n", __func__);
00521 
00522   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
00523 
00524   sigemptyset (&set);
00525   sigaddset (&set, SIGUSR1);
00526 
00527   devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
00528   while (!(status.flags & _DEBUG_FLAG_ISTOP))
00529     {
00530       sigwaitinfo (&set, &info);
00531       devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
00532               0);
00533     }
00534   nto_find_new_threads (&nto_inferior);
00535 
00536   if (status.flags & _DEBUG_FLAG_SSTEP)
00537     {
00538       TRACE ("SSTEP\n");
00539       ourstatus->kind = TARGET_WAITKIND_STOPPED;
00540       ourstatus->value.sig = GDB_SIGNAL_TRAP;
00541     }
00542   /* Was it a breakpoint?  */
00543   else if (status.flags & trace_mask)
00544     {
00545       TRACE ("STOPPED\n");
00546       ourstatus->kind = TARGET_WAITKIND_STOPPED;
00547       ourstatus->value.sig = GDB_SIGNAL_TRAP;
00548     }
00549   else if (status.flags & _DEBUG_FLAG_ISTOP)
00550     {
00551       TRACE ("ISTOP\n");
00552       switch (status.why)
00553         {
00554         case _DEBUG_WHY_SIGNALLED:
00555           TRACE ("  SIGNALLED\n");
00556           ourstatus->kind = TARGET_WAITKIND_STOPPED;
00557           ourstatus->value.sig =
00558             gdb_signal_from_host (status.info.si_signo);
00559           nto_inferior.exit_signo = ourstatus->value.sig;
00560           break;
00561         case _DEBUG_WHY_FAULTED:
00562           TRACE ("  FAULTED\n");
00563           ourstatus->kind = TARGET_WAITKIND_STOPPED;
00564           if (status.info.si_signo == SIGTRAP)
00565             {
00566               ourstatus->value.sig = 0;
00567               nto_inferior.exit_signo = 0;
00568             }
00569           else
00570             {
00571               ourstatus->value.sig =
00572                 gdb_signal_from_host (status.info.si_signo);
00573               nto_inferior.exit_signo = ourstatus->value.sig;
00574             }
00575           break;
00576 
00577         case _DEBUG_WHY_TERMINATED:
00578           {
00579             int waitval = 0;
00580 
00581             TRACE ("  TERMINATED\n");
00582             waitpid (ptid_get_pid (ptid), &waitval, WNOHANG);
00583             if (nto_inferior.exit_signo)
00584               {
00585                 /* Abnormal death.  */
00586                 ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
00587                 ourstatus->value.sig = nto_inferior.exit_signo;
00588               }
00589             else
00590               {
00591                 /* Normal death.  */
00592                 ourstatus->kind = TARGET_WAITKIND_EXITED;
00593                 ourstatus->value.integer = WEXITSTATUS (waitval);
00594               }
00595             nto_inferior.exit_signo = 0;
00596             break;
00597           }
00598 
00599         case _DEBUG_WHY_REQUESTED:
00600           TRACE ("REQUESTED\n");
00601           /* We are assuming a requested stop is due to a SIGINT.  */
00602           ourstatus->kind = TARGET_WAITKIND_STOPPED;
00603           ourstatus->value.sig = GDB_SIGNAL_INT;
00604           nto_inferior.exit_signo = 0;
00605           break;
00606         }
00607     }
00608 
00609   return ptid_build (status.pid, status.tid, 0);
00610 }
00611 
00612 /* Fetch inferior's registers for currently selected thread (CURRENT_INFERIOR).
00613    If REGNO is -1, fetch all registers, or REGNO register only otherwise.  */
00614 
00615 static void
00616 nto_fetch_registers (struct regcache *regcache, int regno)
00617 {
00618   int regsize;
00619   procfs_greg greg;
00620   ptid_t ptid;
00621 
00622   TRACE ("%s (regno=%d)\n", __func__, regno);
00623   if (regno >= the_low_target.num_regs)
00624     return;
00625 
00626   if (current_inferior == NULL)
00627     {
00628       TRACE ("current_inferior is NULL\n");
00629       return;
00630     }
00631   ptid = thread_to_gdb_id (current_inferior);
00632   if (!nto_set_thread (ptid))
00633     return;
00634 
00635   if (devctl (nto_inferior.ctl_fd, DCMD_PROC_GETGREG, &greg, sizeof (greg),
00636               &regsize) == EOK)
00637     {
00638       if (regno == -1) /* All registers. */
00639         {
00640           for (regno = 0; regno != the_low_target.num_regs; ++regno)
00641             {
00642               const unsigned int registeroffset
00643                 = the_low_target.register_offset (regno);
00644               supply_register (regcache, regno,
00645                                ((char *)&greg) + registeroffset);
00646             }
00647         }
00648       else
00649         {
00650           const unsigned int registeroffset
00651             = the_low_target.register_offset (regno);
00652           if (registeroffset == -1)
00653             return;
00654           supply_register (regcache, regno, ((char *)&greg) + registeroffset);
00655         }
00656     }
00657   else
00658     TRACE ("ERROR reading registers from inferior.\n");
00659 }
00660 
00661 /* Store registers for currently selected thread (CURRENT_INFERIOR).  
00662    We always store all registers, regardless of REGNO.  */
00663 
00664 static void
00665 nto_store_registers (struct regcache *regcache, int regno)
00666 {
00667   procfs_greg greg;
00668   int err;
00669   ptid_t ptid;
00670 
00671   TRACE ("%s (regno:%d)\n", __func__, regno);
00672 
00673   if (current_inferior == NULL)
00674     {
00675       TRACE ("current_inferior is NULL\n");
00676       return;
00677     }
00678   ptid = thread_to_gdb_id (current_inferior);
00679   if (!nto_set_thread (ptid))
00680     return;
00681 
00682   memset (&greg, 0, sizeof (greg));
00683   for  (regno = 0; regno != the_low_target.num_regs; ++regno)
00684     {
00685       const unsigned int regoffset
00686         = the_low_target.register_offset (regno);
00687       collect_register (regcache, regno, ((char *)&greg) + regoffset);
00688     }
00689   err = devctl (nto_inferior.ctl_fd, DCMD_PROC_SETGREG, &greg, sizeof (greg),
00690                 0);
00691   if (err != EOK)
00692     TRACE ("Error: setting registers.\n");
00693 }
00694 
00695 /* Read LEN bytes from inferior's memory address MEMADDR into
00696    gdbserver's MYADDR buffer.  
00697 
00698    Return 0 on success -1 otherwise.  */
00699 
00700 static int
00701 nto_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
00702 {
00703   TRACE ("%s memaddr:0x%08lx, len:%d\n", __func__, memaddr, len);
00704 
00705   if (nto_xfer_memory (memaddr, myaddr, len, 0) != len)
00706     {
00707       TRACE ("Failed to read memory\n");
00708       return -1;
00709     }
00710 
00711   return 0;
00712 }
00713 
00714 /* Write LEN bytes from gdbserver's buffer MYADDR into inferior's
00715    memory at address MEMADDR.  
00716 
00717    Return 0 on success -1 otherwise.  */
00718 
00719 static int
00720 nto_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
00721 {
00722   int len_written;
00723 
00724   TRACE ("%s memaddr: 0x%08llx len: %d\n", __func__, memaddr, len);
00725   if ((len_written = nto_xfer_memory (memaddr, (unsigned char *)myaddr, len,
00726                                       1))
00727       != len)
00728     {
00729       TRACE ("Wanted to write: %d but written: %d\n", len, len_written);
00730       return -1;
00731     }
00732 
00733   return 0;
00734 }
00735 
00736 /* Stop inferior.  We always stop all threads.  */
00737 
00738 static void
00739 nto_request_interrupt (void)
00740 {
00741   TRACE ("%s\n", __func__);
00742   nto_set_thread (ptid_build (nto_inferior.pid, 1, 0));
00743   if (EOK != devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, NULL, 0, 0))
00744     TRACE ("Error stopping inferior.\n");
00745 }
00746 
00747 /* Read auxiliary vector from inferior's memory into gdbserver's buffer
00748    MYADDR.  We always read whole auxv.  
00749    
00750    Return number of bytes stored in MYADDR buffer, 0 if OFFSET > 0
00751    or -1 on error.  */
00752 
00753 static int
00754 nto_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len)
00755 {
00756   int err;
00757   CORE_ADDR initial_stack;
00758   procfs_info procinfo;
00759 
00760   TRACE ("%s\n", __func__);
00761   if (offset > 0)
00762     return 0;
00763 
00764   err = devctl (nto_inferior.ctl_fd, DCMD_PROC_INFO, &procinfo,
00765                 sizeof procinfo, 0);
00766   if (err != EOK)
00767     return -1;
00768 
00769   initial_stack = procinfo.initial_stack;
00770 
00771   return nto_read_auxv_from_initial_stack (initial_stack, myaddr, len);
00772 }
00773 
00774 /* Insert {break/watch}point at address ADDR.
00775    TYPE must be in '0'..'4' range.  LEN is not used.  */
00776 
00777 static int
00778 nto_insert_point (char type, CORE_ADDR addr, int len)
00779 {
00780   int wtype = _DEBUG_BREAK_HW; /* Always request HW.  */
00781 
00782   TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
00783   switch (type)
00784     {
00785     case '0': /* software-breakpoint */
00786       wtype = _DEBUG_BREAK_EXEC;
00787       break;
00788     case '1': /* hardware-breakpoint */
00789       wtype |= _DEBUG_BREAK_EXEC;
00790       break;
00791     case '2':  /* write watchpoint */
00792       wtype |= _DEBUG_BREAK_RW;
00793       break;
00794     case '3':  /* read watchpoint */
00795       wtype |= _DEBUG_BREAK_RD;
00796       break;
00797     case '4':  /* access watchpoint */
00798       wtype |= _DEBUG_BREAK_RW;
00799       break;
00800     default:
00801       return 1; /* Not supported.  */
00802     }
00803   return nto_breakpoint (addr, wtype, 0);
00804 }
00805 
00806 /* Remove {break/watch}point at address ADDR.
00807    TYPE must be in '0'..'4' range.  LEN is not used.  */
00808 
00809 static int
00810 nto_remove_point (char type, CORE_ADDR addr, int len)
00811 {
00812   int wtype = _DEBUG_BREAK_HW; /* Always request HW.  */
00813 
00814   TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
00815   switch (type)
00816     {
00817     case '0': /* software-breakpoint */
00818       wtype = _DEBUG_BREAK_EXEC;
00819       break;
00820     case '1': /* hardware-breakpoint */
00821       wtype |= _DEBUG_BREAK_EXEC;
00822       break;
00823     case '2':  /* write watchpoint */
00824       wtype |= _DEBUG_BREAK_RW;
00825       break;
00826     case '3':  /* read watchpoint */
00827       wtype |= _DEBUG_BREAK_RD;
00828       break;
00829     case '4':  /* access watchpoint */
00830       wtype |= _DEBUG_BREAK_RW;
00831       break;
00832     default:
00833       return 1; /* Not supported.  */
00834     }
00835   return nto_breakpoint (addr, wtype, -1);
00836 }
00837 
00838 /* Check if the reason of stop for current thread (CURRENT_INFERIOR) is
00839    a watchpoint.
00840 
00841    Return 1 if stopped by watchpoint, 0 otherwise.  */
00842 
00843 static int
00844 nto_stopped_by_watchpoint (void)
00845 {
00846   int ret = 0;
00847 
00848   TRACE ("%s\n", __func__);
00849   if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
00850     {
00851       ptid_t ptid;
00852 
00853       ptid = thread_to_gdb_id (current_inferior);
00854       if (nto_set_thread (ptid))
00855         {
00856           const int watchmask = _DEBUG_FLAG_TRACE_RD | _DEBUG_FLAG_TRACE_WR
00857                                 | _DEBUG_FLAG_TRACE_MODIFY;
00858           procfs_status status;
00859           int err;
00860 
00861           err = devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
00862                         sizeof (status), 0);
00863           if (err == EOK && (status.flags & watchmask))
00864             ret = 1;
00865         }
00866     }
00867   TRACE ("%s: %s\n", __func__, ret ? "yes" : "no");
00868   return ret;
00869 }
00870 
00871 /* Get instruction pointer for CURRENT_INFERIOR thread.  
00872 
00873    Return inferior's instruction pointer value, or 0 on error.  */ 
00874 
00875 static CORE_ADDR
00876 nto_stopped_data_address (void)
00877 {
00878   CORE_ADDR ret = (CORE_ADDR)0;
00879 
00880   TRACE ("%s\n", __func__);
00881   if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
00882     {
00883       ptid_t ptid;
00884 
00885       ptid = thread_to_gdb_id (current_inferior);
00886 
00887       if (nto_set_thread (ptid))
00888         {
00889           procfs_status status;
00890 
00891           if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
00892                       sizeof (status), 0) == EOK)
00893             ret = status.ip;
00894         }
00895     }
00896   TRACE ("%s: 0x%08lx\n", __func__, ret);
00897   return ret;
00898 }
00899 
00900 /* We do not currently support non-stop.  */
00901 
00902 static int
00903 nto_supports_non_stop (void)
00904 {
00905   TRACE ("%s\n", __func__);
00906   return 0;
00907 }
00908 
00909 
00910 
00911 static struct target_ops nto_target_ops = {
00912   nto_create_inferior,
00913   nto_attach,
00914   nto_kill,
00915   nto_detach,
00916   nto_mourn,
00917   NULL, /* nto_join */
00918   nto_thread_alive,
00919   nto_resume,
00920   nto_wait,
00921   nto_fetch_registers,
00922   nto_store_registers,
00923   NULL, /* prepare_to_access_memory */
00924   NULL, /* done_accessing_memory */
00925   nto_read_memory,
00926   nto_write_memory,
00927   NULL, /* nto_look_up_symbols */
00928   nto_request_interrupt,
00929   nto_read_auxv,
00930   nto_insert_point,
00931   nto_remove_point,
00932   nto_stopped_by_watchpoint,
00933   nto_stopped_data_address,
00934   NULL, /* nto_read_offsets */
00935   NULL, /* thread_db_set_tls_address */
00936   NULL,
00937   hostio_last_error_from_errno,
00938   NULL, /* nto_qxfer_osdata */
00939   NULL, /* xfer_siginfo */
00940   nto_supports_non_stop,
00941   NULL, /* async */
00942   NULL  /* start_non_stop */
00943 };
00944 
00945 
00946 /* Global function called by server.c.  Initializes QNX Neutrino
00947    gdbserver.  */
00948 
00949 void
00950 initialize_low (void)
00951 {
00952   sigset_t set;
00953 
00954   TRACE ("%s\n", __func__);
00955   set_target_ops (&nto_target_ops);
00956   set_breakpoint_data (the_low_target.breakpoint,
00957                        the_low_target.breakpoint_len);
00958 
00959   /* We use SIGUSR1 to gain control after we block waiting for a process.
00960      We use sigwaitevent to wait.  */
00961   sigemptyset (&set);
00962   sigaddset (&set, SIGUSR1);
00963   sigprocmask (SIG_BLOCK, &set, NULL);
00964 }
00965 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines