Index: gdb/ChangeLog
[external/binutils.git] / gdb / nto-procfs.c
1 /* Machine independent support for QNX Neutrino /proc (process file system)
2    for GDB.  Written by Colin Burgess at QNX Software Systems Limited. 
3
4    Copyright 2003 Free Software Foundation, Inc.
5
6    Contributed by QNX Software Systems Ltd.
7
8    This file is part of GDB.
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330,
23    Boston, MA 02111-1307, USA.  */
24
25 #include "defs.h"
26
27 #include <fcntl.h>
28 #include <spawn.h>
29 #include <sys/debug.h>
30 #include <sys/procfs.h>
31 #include <sys/neutrino.h>
32 #include <sys/syspage.h>
33 #include "gdb_dirent.h"
34 #include <sys/netmgr.h>
35
36 #include "exceptions.h"
37 #include "gdb_string.h"
38 #include "gdbcore.h"
39 #include "inferior.h"
40 #include "target.h"
41 #include "objfiles.h"
42 #include "gdbthread.h"
43 #include "nto-tdep.h"
44 #include "command.h"
45 #include "regcache.h"
46
47 #define NULL_PID                0
48 #define _DEBUG_FLAG_TRACE       (_DEBUG_FLAG_TRACE_EXEC|_DEBUG_FLAG_TRACE_RD|\
49                 _DEBUG_FLAG_TRACE_WR|_DEBUG_FLAG_TRACE_MODIFY)
50
51 static struct target_ops procfs_ops;
52
53 int ctl_fd;
54
55 static void (*ofunc) ();
56
57 static procfs_run run;
58
59 static void procfs_open (char *, int);
60
61 static int procfs_can_run (void);
62
63 static ptid_t procfs_wait (ptid_t, struct target_waitstatus *);
64
65 static int procfs_xfer_memory (CORE_ADDR, char *, int, int,
66                                struct mem_attrib *attrib,
67                                struct target_ops *);
68
69 static void procfs_fetch_registers (int);
70
71 static void notice_signals (void);
72
73 static void init_procfs_ops (void);
74
75 static ptid_t do_attach (ptid_t ptid);
76
77 static int procfs_can_use_hw_breakpoint (int, int, int);
78
79 static int procfs_insert_hw_breakpoint (CORE_ADDR, char *);
80
81 static int procfs_remove_hw_breakpoint (CORE_ADDR addr, char *);
82
83 static int procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type);
84
85 static int procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type);
86
87 static int procfs_stopped_by_watchpoint (void);
88
89 /* These two globals are only ever set in procfs_open(), but are
90    referenced elsewhere.  'nto_procfs_node' is a flag used to say
91    whether we are local, or we should get the current node descriptor
92    for the remote QNX node.  */
93 static char nto_procfs_path[PATH_MAX] = { "/proc" };
94 static unsigned nto_procfs_node = ND_LOCAL_NODE;
95
96 /* Return the current QNX Node, or error out.  This is a simple
97    wrapper for the netmgr_strtond() function.  The reason this
98    is required is because QNX node descriptors are transient so
99    we have to re-acquire them every time.  */
100 static unsigned
101 nto_node (void)
102 {
103   unsigned node;
104
105   if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0)
106     return ND_LOCAL_NODE;
107
108   node = netmgr_strtond (nto_procfs_path, 0);
109   if (node == -1)
110     error (_("Lost the QNX node.  Debug session probably over."));
111
112   return (node);
113 }
114
115 static enum gdb_osabi
116 procfs_is_nto_target (bfd *abfd)
117 {
118   return GDB_OSABI_QNXNTO;
119 }
120
121 /* This is called when we call 'target procfs <arg>' from the (gdb) prompt.
122    For QNX6 (nto), the only valid arg will be a QNX node string, 
123    eg: "/net/some_node".  If arg is not a valid QNX node, we will
124    default to local.  */
125 static void
126 procfs_open (char *arg, int from_tty)
127 {
128   char *nodestr;
129   char *endstr;
130   char buffer[50];
131   int fd, total_size;
132   procfs_sysinfo *sysinfo;
133
134   nto_is_nto_target = procfs_is_nto_target;
135
136   /* Set the default node used for spawning to this one,
137      and only override it if there is a valid arg.  */
138
139   nto_procfs_node = ND_LOCAL_NODE;
140   nodestr = arg ? xstrdup (arg) : arg;
141
142   init_thread_list ();
143
144   if (nodestr)
145     {
146       nto_procfs_node = netmgr_strtond (nodestr, &endstr);
147       if (nto_procfs_node == -1)
148         {
149           if (errno == ENOTSUP)
150             printf_filtered ("QNX Net Manager not found.\n");
151           printf_filtered ("Invalid QNX node %s: error %d (%s).\n", nodestr,
152                            errno, safe_strerror (errno));
153           xfree (nodestr);
154           nodestr = NULL;
155           nto_procfs_node = ND_LOCAL_NODE;
156         }
157       else if (*endstr)
158         {
159           if (*(endstr - 1) == '/')
160             *(endstr - 1) = 0;
161           else
162             *endstr = 0;
163         }
164     }
165   snprintf (nto_procfs_path, PATH_MAX - 1, "%s%s", nodestr ? nodestr : "",
166             "/proc");
167   if (nodestr)
168     xfree (nodestr);
169
170   fd = open (nto_procfs_path, O_RDONLY);
171   if (fd == -1)
172     {
173       printf_filtered ("Error opening %s : %d (%s)\n", nto_procfs_path, errno,
174                        safe_strerror (errno));
175       error (_("Invalid procfs arg"));
176     }
177
178   sysinfo = (void *) buffer;
179   if (devctl (fd, DCMD_PROC_SYSINFO, sysinfo, sizeof buffer, 0) != EOK)
180     {
181       printf_filtered ("Error getting size: %d (%s)\n", errno,
182                        safe_strerror (errno));
183       close (fd);
184       error (_("Devctl failed."));
185     }
186   else
187     {
188       total_size = sysinfo->total_size;
189       sysinfo = alloca (total_size);
190       if (!sysinfo)
191         {
192           printf_filtered ("Memory error: %d (%s)\n", errno,
193                            safe_strerror (errno));
194           close (fd);
195           error (_("alloca failed."));
196         }
197       else
198         {
199           if (devctl (fd, DCMD_PROC_SYSINFO, sysinfo, total_size, 0) != EOK)
200             {
201               printf_filtered ("Error getting sysinfo: %d (%s)\n", errno,
202                                safe_strerror (errno));
203               close (fd);
204               error (_("Devctl failed."));
205             }
206           else
207             {
208               if (sysinfo->type !=
209                   nto_map_arch_to_cputype (TARGET_ARCHITECTURE->arch_name))
210                 {
211                   close (fd);
212                   error (_("Invalid target CPU."));
213                 }
214             }
215         }
216     }
217   close (fd);
218   printf_filtered ("Debugging using %s\n", nto_procfs_path);
219 }
220
221 static void
222 procfs_set_thread (ptid_t ptid)
223 {
224   pid_t tid;
225
226   tid = ptid_get_tid (ptid);
227   devctl (ctl_fd, DCMD_PROC_CURTHREAD, &tid, sizeof (tid), 0);
228 }
229
230 /*  Return nonzero if the thread TH is still alive.  */
231 static int
232 procfs_thread_alive (ptid_t ptid)
233 {
234   pid_t tid;
235
236   tid = ptid_get_tid (ptid);
237   if (devctl (ctl_fd, DCMD_PROC_CURTHREAD, &tid, sizeof (tid), 0) == EOK)
238     return 1;
239   return 0;
240 }
241
242 void
243 procfs_find_new_threads (void)
244 {
245   procfs_status status;
246   pid_t pid;
247   ptid_t ptid;
248
249   if (ctl_fd == -1)
250     return;
251
252   pid = ptid_get_pid (inferior_ptid);
253
254   for (status.tid = 1;; ++status.tid)
255     {
256       if (devctl (ctl_fd, DCMD_PROC_TIDSTATUS, &status, sizeof (status), 0)
257           != EOK && status.tid != 0)
258         break;
259       ptid = ptid_build (pid, 0, status.tid);
260       if (!in_thread_list (ptid))
261         add_thread (ptid);
262     }
263   return;
264 }
265
266 void
267 procfs_pidlist (char *args, int from_tty)
268 {
269   DIR *dp = NULL;
270   struct dirent *dirp = NULL;
271   int fd = -1;
272   char buf[512];
273   procfs_info *pidinfo = NULL;
274   procfs_debuginfo *info = NULL;
275   procfs_status *status = NULL;
276   pid_t num_threads = 0;
277   pid_t pid;
278   char name[512];
279
280   dp = opendir (nto_procfs_path);
281   if (dp == NULL)
282     {
283       fprintf_unfiltered (gdb_stderr, "failed to opendir \"%s\" - %d (%s)",
284                           nto_procfs_path, errno, safe_strerror (errno));
285       return;
286     }
287
288   /* Start scan at first pid.  */
289   rewinddir (dp);
290
291   do
292     {
293       /* Get the right pid and procfs path for the pid.  */
294       do
295         {
296           dirp = readdir (dp);
297           if (dirp == NULL)
298             {
299               closedir (dp);
300               return;
301             }
302           snprintf (buf, 511, "%s/%s/as", nto_procfs_path, dirp->d_name);
303           pid = atoi (dirp->d_name);
304         }
305       while (pid == 0);
306
307       /* Open the procfs path. */
308       fd = open (buf, O_RDONLY);
309       if (fd == -1)
310         {
311           fprintf_unfiltered (gdb_stderr, "failed to open %s - %d (%s)\n",
312                               buf, errno, safe_strerror (errno));
313           closedir (dp);
314           return;
315         }
316
317       pidinfo = (procfs_info *) buf;
318       if (devctl (fd, DCMD_PROC_INFO, pidinfo, sizeof (buf), 0) != EOK)
319         {
320           fprintf_unfiltered (gdb_stderr,
321                               "devctl DCMD_PROC_INFO failed - %d (%s)\n",
322                               errno, safe_strerror (errno));
323           break;
324         }
325       num_threads = pidinfo->num_threads;
326
327       info = (procfs_debuginfo *) buf;
328       if (devctl (fd, DCMD_PROC_MAPDEBUG_BASE, info, sizeof (buf), 0) != EOK)
329         strcpy (name, "unavailable");
330       else
331         strcpy (name, info->path);
332
333       /* Collect state info on all the threads.  */
334       status = (procfs_status *) buf;
335       for (status->tid = 1; status->tid <= num_threads; status->tid++)
336         {
337           if (devctl (fd, DCMD_PROC_TIDSTATUS, status, sizeof (buf), 0) != EOK
338               && status->tid != 0)
339             break;
340           if (status->tid != 0)
341             printf_filtered ("%s - %d/%d\n", name, pid, status->tid);
342         }
343       close (fd);
344     }
345   while (dirp != NULL);
346
347   close (fd);
348   closedir (dp);
349   return;
350 }
351
352 void
353 procfs_meminfo (char *args, int from_tty)
354 {
355   procfs_mapinfo *mapinfos = NULL;
356   static int num_mapinfos = 0;
357   procfs_mapinfo *mapinfo_p, *mapinfo_p2;
358   int flags = ~0, err, num, i, j;
359
360   struct
361   {
362     procfs_debuginfo info;
363     char buff[_POSIX_PATH_MAX];
364   } map;
365
366   struct info
367   {
368     unsigned addr;
369     unsigned size;
370     unsigned flags;
371     unsigned debug_vaddr;
372     unsigned long long offset;
373   };
374
375   struct printinfo
376   {
377     unsigned long long ino;
378     unsigned dev;
379     struct info text;
380     struct info data;
381     char name[256];
382   } printme;
383
384   /* Get the number of map entrys.  */
385   err = devctl (ctl_fd, DCMD_PROC_MAPINFO, NULL, 0, &num);
386   if (err != EOK)
387     {
388       printf ("failed devctl num mapinfos - %d (%s)\n", err,
389               safe_strerror (err));
390       return;
391     }
392
393   mapinfos = xmalloc (num * sizeof (procfs_mapinfo));
394
395   num_mapinfos = num;
396   mapinfo_p = mapinfos;
397
398   /* Fill the map entrys.  */
399   err = devctl (ctl_fd, DCMD_PROC_MAPINFO, mapinfo_p, num
400                 * sizeof (procfs_mapinfo), &num);
401   if (err != EOK)
402     {
403       printf ("failed devctl mapinfos - %d (%s)\n", err, safe_strerror (err));
404       xfree (mapinfos);
405       return;
406     }
407
408   num = min (num, num_mapinfos);
409
410   /* Run through the list of mapinfos, and store the data and text info
411      so we can print it at the bottom of the loop.  */
412   for (mapinfo_p = mapinfos, i = 0; i < num; i++, mapinfo_p++)
413     {
414       if (!(mapinfo_p->flags & flags))
415         mapinfo_p->ino = 0;
416
417       if (mapinfo_p->ino == 0)  /* Already visited.  */
418         continue;
419
420       map.info.vaddr = mapinfo_p->vaddr;
421
422       err = devctl (ctl_fd, DCMD_PROC_MAPDEBUG, &map, sizeof (map), 0);
423       if (err != EOK)
424         continue;
425
426       memset (&printme, 0, sizeof printme);
427       printme.dev = mapinfo_p->dev;
428       printme.ino = mapinfo_p->ino;
429       printme.text.addr = mapinfo_p->vaddr;
430       printme.text.size = mapinfo_p->size;
431       printme.text.flags = mapinfo_p->flags;
432       printme.text.offset = mapinfo_p->offset;
433       printme.text.debug_vaddr = map.info.vaddr;
434       strcpy (printme.name, map.info.path);
435
436       /* Check for matching data.  */
437       for (mapinfo_p2 = mapinfos, j = 0; j < num; j++, mapinfo_p2++)
438         {
439           if (mapinfo_p2->vaddr != mapinfo_p->vaddr
440               && mapinfo_p2->ino == mapinfo_p->ino
441               && mapinfo_p2->dev == mapinfo_p->dev)
442             {
443               map.info.vaddr = mapinfo_p2->vaddr;
444               err =
445                 devctl (ctl_fd, DCMD_PROC_MAPDEBUG, &map, sizeof (map), 0);
446               if (err != EOK)
447                 continue;
448
449               if (strcmp (map.info.path, printme.name))
450                 continue;
451
452               /* Lower debug_vaddr is always text, if nessessary, swap.  */
453               if ((int) map.info.vaddr < (int) printme.text.debug_vaddr)
454                 {
455                   memcpy (&(printme.data), &(printme.text),
456                           sizeof (printme.data));
457                   printme.text.addr = mapinfo_p2->vaddr;
458                   printme.text.size = mapinfo_p2->size;
459                   printme.text.flags = mapinfo_p2->flags;
460                   printme.text.offset = mapinfo_p2->offset;
461                   printme.text.debug_vaddr = map.info.vaddr;
462                 }
463               else
464                 {
465                   printme.data.addr = mapinfo_p2->vaddr;
466                   printme.data.size = mapinfo_p2->size;
467                   printme.data.flags = mapinfo_p2->flags;
468                   printme.data.offset = mapinfo_p2->offset;
469                   printme.data.debug_vaddr = map.info.vaddr;
470                 }
471               mapinfo_p2->ino = 0;
472             }
473         }
474       mapinfo_p->ino = 0;
475
476       printf_filtered ("%s\n", printme.name);
477       printf_filtered ("\ttext=%08x bytes @ 0x%08x\n", printme.text.size,
478                        printme.text.addr);
479       printf_filtered ("\t\tflags=%08x\n", printme.text.flags);
480       printf_filtered ("\t\tdebug=%08x\n", printme.text.debug_vaddr);
481       printf_filtered ("\t\toffset=%016llx\n", printme.text.offset);
482       if (printme.data.size)
483         {
484           printf_filtered ("\tdata=%08x bytes @ 0x%08x\n", printme.data.size,
485                            printme.data.addr);
486           printf_filtered ("\t\tflags=%08x\n", printme.data.flags);
487           printf_filtered ("\t\tdebug=%08x\n", printme.data.debug_vaddr);
488           printf_filtered ("\t\toffset=%016llx\n", printme.data.offset);
489         }
490       printf_filtered ("\tdev=0x%x\n", printme.dev);
491       printf_filtered ("\tino=0x%x\n", (unsigned int) printme.ino);
492     }
493   xfree (mapinfos);
494   return;
495 }
496
497 /* Print status information about what we're accessing.  */
498 static void
499 procfs_files_info (struct target_ops *ignore)
500 {
501   printf_unfiltered ("\tUsing the running image of %s %s via %s.\n",
502                      attach_flag ? "attached" : "child",
503                      target_pid_to_str (inferior_ptid), nto_procfs_path);
504 }
505
506 /* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
507 static int
508 procfs_can_run (void)
509 {
510   return 1;
511 }
512
513 /* Attach to process PID, then initialize for debugging it.  */
514 static void
515 procfs_attach (char *args, int from_tty)
516 {
517   char *exec_file;
518   int pid;
519
520   if (!args)
521     error_no_arg (_("process-id to attach"));
522
523   pid = atoi (args);
524
525   if (pid == getpid ())
526     error (_("Attaching GDB to itself is not a good idea..."));
527
528   if (from_tty)
529     {
530       exec_file = (char *) get_exec_file (0);
531
532       if (exec_file)
533         printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
534                            target_pid_to_str (pid_to_ptid (pid)));
535       else
536         printf_unfiltered ("Attaching to %s\n",
537                            target_pid_to_str (pid_to_ptid (pid)));
538
539       gdb_flush (gdb_stdout);
540     }
541   inferior_ptid = do_attach (pid_to_ptid (pid));
542   push_target (&procfs_ops);
543 }
544
545 static void
546 procfs_post_attach (pid_t pid)
547 {
548 #ifdef SOLIB_CREATE_INFERIOR_HOOK
549   if (exec_bfd)
550     SOLIB_CREATE_INFERIOR_HOOK (pid);
551 #endif
552 }
553
554 static ptid_t
555 do_attach (ptid_t ptid)
556 {
557   procfs_status status;
558   struct sigevent event;
559   char path[PATH_MAX];
560
561   snprintf (path, PATH_MAX - 1, "%s/%d/as", nto_procfs_path, PIDGET (ptid));
562   ctl_fd = open (path, O_RDWR);
563   if (ctl_fd == -1)
564     error (_("Couldn't open proc file %s, error %d (%s)"), path, errno,
565            safe_strerror (errno));
566   if (devctl (ctl_fd, DCMD_PROC_STOP, &status, sizeof (status), 0) != EOK)
567     error (_("Couldn't stop process"));
568
569   /* Define a sigevent for process stopped notification.  */
570   event.sigev_notify = SIGEV_SIGNAL_THREAD;
571   event.sigev_signo = SIGUSR1;
572   event.sigev_code = 0;
573   event.sigev_value.sival_ptr = NULL;
574   event.sigev_priority = -1;
575   devctl (ctl_fd, DCMD_PROC_EVENT, &event, sizeof (event), 0);
576
577   if (devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0) == EOK
578       && status.flags & _DEBUG_FLAG_STOPPED)
579     SignalKill (nto_node (), PIDGET (ptid), 0, SIGCONT, 0, 0);
580   attach_flag = 1;
581   nto_init_solib_absolute_prefix ();
582   return ptid;
583 }
584
585 /* Ask the user what to do when an interrupt is received.  */
586 static void
587 interrupt_query (void)
588 {
589   target_terminal_ours ();
590
591   if (query ("Interrupted while waiting for the program.\n\
592 Give up (and stop debugging it)? "))
593     {
594       target_mourn_inferior ();
595       deprecated_throw_reason (RETURN_QUIT);
596     }
597
598   target_terminal_inferior ();
599 }
600
601 /* The user typed ^C twice.  */
602 static void
603 nto_interrupt_twice (int signo)
604 {
605   signal (signo, ofunc);
606   interrupt_query ();
607   signal (signo, nto_interrupt_twice);
608 }
609
610 static void
611 nto_interrupt (int signo)
612 {
613   /* If this doesn't work, try more severe steps.  */
614   signal (signo, nto_interrupt_twice);
615
616   target_stop ();
617 }
618
619 static ptid_t
620 procfs_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
621 {
622   sigset_t set;
623   siginfo_t info;
624   procfs_status status;
625   static int exit_signo = 0;    /* To track signals that cause termination.  */
626
627   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
628
629   if (ptid_equal (inferior_ptid, null_ptid))
630     {
631       ourstatus->kind = TARGET_WAITKIND_STOPPED;
632       ourstatus->value.sig = TARGET_SIGNAL_0;
633       exit_signo = 0;
634       return null_ptid;
635     }
636
637   sigemptyset (&set);
638   sigaddset (&set, SIGUSR1);
639
640   devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
641   while (!(status.flags & _DEBUG_FLAG_ISTOP))
642     {
643       ofunc = (void (*)()) signal (SIGINT, nto_interrupt);
644       sigwaitinfo (&set, &info);
645       signal (SIGINT, ofunc);
646       devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
647     }
648
649   if (status.flags & _DEBUG_FLAG_SSTEP)
650     {
651       ourstatus->kind = TARGET_WAITKIND_STOPPED;
652       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
653     }
654   /* Was it a breakpoint?  */
655   else if (status.flags & _DEBUG_FLAG_TRACE)
656     {
657       ourstatus->kind = TARGET_WAITKIND_STOPPED;
658       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
659     }
660   else if (status.flags & _DEBUG_FLAG_ISTOP)
661     {
662       switch (status.why)
663         {
664         case _DEBUG_WHY_SIGNALLED:
665           ourstatus->kind = TARGET_WAITKIND_STOPPED;
666           ourstatus->value.sig =
667             target_signal_from_host (status.info.si_signo);
668           exit_signo = 0;
669           break;
670         case _DEBUG_WHY_FAULTED:
671           ourstatus->kind = TARGET_WAITKIND_STOPPED;
672           if (status.info.si_signo == SIGTRAP)
673             {
674               ourstatus->value.sig = 0;
675               exit_signo = 0;
676             }
677           else
678             {
679               ourstatus->value.sig =
680                 target_signal_from_host (status.info.si_signo);
681               exit_signo = ourstatus->value.sig;
682             }
683           break;
684
685         case _DEBUG_WHY_TERMINATED:
686           {
687             int waitval = 0;
688
689             waitpid (PIDGET (inferior_ptid), &waitval, WNOHANG);
690             if (exit_signo)
691               {
692                 /* Abnormal death.  */
693                 ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
694                 ourstatus->value.sig = exit_signo;
695               }
696             else
697               {
698                 /* Normal death.  */
699                 ourstatus->kind = TARGET_WAITKIND_EXITED;
700                 ourstatus->value.integer = WEXITSTATUS (waitval);
701               }
702             exit_signo = 0;
703             break;
704           }
705
706         case _DEBUG_WHY_REQUESTED:
707           /* We are assuming a requested stop is due to a SIGINT.  */
708           ourstatus->kind = TARGET_WAITKIND_STOPPED;
709           ourstatus->value.sig = TARGET_SIGNAL_INT;
710           exit_signo = 0;
711           break;
712         }
713     }
714
715   return inferior_ptid;
716 }
717
718 /* Read the current values of the inferior's registers, both the
719    general register set and floating point registers (if supported)
720    and update gdb's idea of their current values.  */
721 static void
722 procfs_fetch_registers (int regno)
723 {
724   union
725   {
726     procfs_greg greg;
727     procfs_fpreg fpreg;
728     procfs_altreg altreg;
729   }
730   reg;
731   int regsize;
732
733   procfs_set_thread (inferior_ptid);
734   if (devctl (ctl_fd, DCMD_PROC_GETGREG, &reg, sizeof (reg), &regsize) == EOK)
735     nto_supply_gregset ((char *) &reg.greg);
736   if (devctl (ctl_fd, DCMD_PROC_GETFPREG, &reg, sizeof (reg), &regsize)
737       == EOK)
738     nto_supply_fpregset ((char *) &reg.fpreg);
739   if (devctl (ctl_fd, DCMD_PROC_GETALTREG, &reg, sizeof (reg), &regsize)
740       == EOK)
741     nto_supply_altregset ((char *) &reg.altreg);
742 }
743
744 /* Copy LEN bytes to/from inferior's memory starting at MEMADDR
745    from/to debugger memory starting at MYADDR.  Copy from inferior
746    if DOWRITE is zero or to inferior if DOWRITE is nonzero.
747
748    Returns the length copied, which is either the LEN argument or
749    zero.  This xfer function does not do partial moves, since procfs_ops
750    doesn't allow memory operations to cross below us in the target stack
751    anyway.  */
752 static int
753 procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite,
754                     struct mem_attrib *attrib, struct target_ops *target)
755 {
756   int nbytes = 0;
757
758   if (lseek (ctl_fd, (off_t) memaddr, SEEK_SET) == (off_t) memaddr)
759     {
760       if (dowrite)
761         nbytes = write (ctl_fd, myaddr, len);
762       else
763         nbytes = read (ctl_fd, myaddr, len);
764       if (nbytes < 0)
765         nbytes = 0;
766     }
767   return (nbytes);
768 }
769
770 /* Take a program previously attached to and detaches it.
771    The program resumes execution and will no longer stop
772    on signals, etc.  We'd better not have left any breakpoints
773    in the program or it'll die when it hits one.  */
774 static void
775 procfs_detach (char *args, int from_tty)
776 {
777   int siggnal = 0;
778
779   if (from_tty)
780     {
781       char *exec_file = get_exec_file (0);
782       if (exec_file == 0)
783         exec_file = "";
784       printf_unfiltered ("Detaching from program: %s %s\n",
785                          exec_file, target_pid_to_str (inferior_ptid));
786       gdb_flush (gdb_stdout);
787     }
788   if (args)
789     siggnal = atoi (args);
790
791   if (siggnal)
792     SignalKill (nto_node (), PIDGET (inferior_ptid), 0, siggnal, 0, 0);
793
794   close (ctl_fd);
795   ctl_fd = -1;
796   init_thread_list ();
797   inferior_ptid = null_ptid;
798   attach_flag = 0;
799   unpush_target (&procfs_ops);  /* Pop out of handling an inferior.  */
800 }
801
802 static int
803 procfs_breakpoint (CORE_ADDR addr, int type, int size)
804 {
805   procfs_break brk;
806
807   brk.type = type;
808   brk.addr = addr;
809   brk.size = size;
810   errno = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0);
811   if (errno != EOK)
812     return 1;
813   return 0;
814 }
815
816 static int
817 procfs_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
818 {
819   return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC, 0);
820 }
821
822 static int
823 procfs_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
824 {
825   return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC, -1);
826 }
827
828 static int
829 procfs_insert_hw_breakpoint (CORE_ADDR addr, char *contents_cache)
830 {
831   return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, 0);
832 }
833
834 static int
835 procfs_remove_hw_breakpoint (CORE_ADDR addr, char *contents_cache)
836 {
837   return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, -1);
838 }
839
840 static void
841 procfs_resume (ptid_t ptid, int step, enum target_signal signo)
842 {
843   int signal_to_pass;
844   procfs_status status;
845
846   if (ptid_equal (inferior_ptid, null_ptid))
847     return;
848
849   procfs_set_thread (ptid_equal (ptid, minus_one_ptid) ? inferior_ptid :
850                      ptid);
851
852   run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE;
853   if (step)
854     run.flags |= _DEBUG_RUN_STEP;
855
856   sigemptyset ((sigset_t *) &run.fault);
857   sigaddset ((sigset_t *) &run.fault, FLTBPT);
858   sigaddset ((sigset_t *) &run.fault, FLTTRACE);
859   sigaddset ((sigset_t *) &run.fault, FLTILL);
860   sigaddset ((sigset_t *) &run.fault, FLTPRIV);
861   sigaddset ((sigset_t *) &run.fault, FLTBOUNDS);
862   sigaddset ((sigset_t *) &run.fault, FLTIOVF);
863   sigaddset ((sigset_t *) &run.fault, FLTIZDIV);
864   sigaddset ((sigset_t *) &run.fault, FLTFPE);
865   /* Peter V will be changing this at some point.  */
866   sigaddset ((sigset_t *) &run.fault, FLTPAGE);
867
868   run.flags |= _DEBUG_RUN_ARM;
869
870   sigemptyset (&run.trace);
871   notice_signals ();
872   signal_to_pass = target_signal_to_host (signo);
873
874   if (signal_to_pass)
875     {
876       devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
877       signal_to_pass = target_signal_to_host (signo);
878       if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
879         {
880           if (signal_to_pass != status.info.si_signo)
881             {
882               SignalKill (nto_node (), PIDGET (inferior_ptid), 0,
883                           signal_to_pass, 0, 0);
884               run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
885             }
886           else                  /* Let it kill the program without telling us.  */
887             sigdelset (&run.trace, signal_to_pass);
888         }
889     }
890   else
891     run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT;
892
893   errno = devctl (ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
894   if (errno != EOK)
895     {
896       perror ("run error!\n");
897       return;
898     }
899 }
900
901 static void
902 procfs_mourn_inferior (void)
903 {
904   if (!ptid_equal (inferior_ptid, null_ptid))
905     {
906       SignalKill (nto_node (), PIDGET (inferior_ptid), 0, SIGKILL, 0, 0);
907       close (ctl_fd);
908     }
909   inferior_ptid = null_ptid;
910   init_thread_list ();
911   unpush_target (&procfs_ops);
912   generic_mourn_inferior ();
913   attach_flag = 0;
914 }
915
916 /* This function breaks up an argument string into an argument
917    vector suitable for passing to execvp().
918    E.g., on "run a b c d" this routine would get as input
919    the string "a b c d", and as output it would fill in argv with
920    the four arguments "a", "b", "c", "d".  The only additional
921    functionality is simple quoting.  The gdb command:
922         run a "b c d" f
923    will fill in argv with the three args "a", "b c d", "e".  */
924 static void
925 breakup_args (char *scratch, char **argv)
926 {
927   char *pp, *cp = scratch;
928   char quoting = 0;
929
930   for (;;)
931     {
932       /* Scan past leading separators.  */
933       quoting = 0;
934       while (*cp == ' ' || *cp == '\t' || *cp == '\n')
935         cp++;
936
937       /* Break if at end of string.  */
938       if (*cp == '\0')
939         break;
940
941       /* Take an arg.  */
942       if (*cp == '"')
943         {
944           cp++;
945           quoting = strchr (cp, '"') ? 1 : 0;
946         }
947
948       *argv++ = cp;
949
950       /* Scan for next arg separator.  */
951       pp = cp;
952       if (quoting)
953         cp = strchr (pp, '"');
954       if ((cp == NULL) || (!quoting))
955         cp = strchr (pp, ' ');
956       if (cp == NULL)
957         cp = strchr (pp, '\t');
958       if (cp == NULL)
959         cp = strchr (pp, '\n');
960
961       /* No separators => end of string => break.  */
962       if (cp == NULL)
963         {
964           pp = cp;
965           break;
966         }
967
968       /* Replace the separator with a terminator.  */
969       *cp++ = '\0';
970     }
971
972   /* Execv requires a null-terminated arg vector.  */
973   *argv = NULL;
974 }
975
976 static void
977 procfs_create_inferior (char *exec_file, char *allargs, char **env,
978                         int from_tty)
979 {
980   struct inheritance inherit;
981   pid_t pid;
982   int flags, errn;
983   char **argv, *args;
984   const char *in = "", *out = "", *err = "";
985   int fd, fds[3];
986   sigset_t set;
987   const char *inferior_io_terminal = get_inferior_io_terminal ();
988
989   argv = xmalloc (((strlen (allargs) + 1) / (unsigned) 2 + 2) *
990                   sizeof (*argv));
991   argv[0] = get_exec_file (1);
992   if (!argv[0])
993     {
994       if (exec_file)
995         argv[0] = exec_file;
996       else
997         return;
998     }
999
1000   args = xstrdup (allargs);
1001   breakup_args (args, exec_file ? &argv[1] : &argv[0]);
1002
1003   argv = nto_parse_redirection (argv, &in, &out, &err);
1004
1005   fds[0] = STDIN_FILENO;
1006   fds[1] = STDOUT_FILENO;
1007   fds[2] = STDERR_FILENO;
1008
1009   /* If the user specified I/O via gdb's --tty= arg, use it, but only
1010      if the i/o is not also being specified via redirection.  */
1011   if (inferior_io_terminal)
1012     {
1013       if (!in[0])
1014         in = inferior_io_terminal;
1015       if (!out[0])
1016         out = inferior_io_terminal;
1017       if (!err[0])
1018         err = inferior_io_terminal;
1019     }
1020
1021   if (in[0])
1022     {
1023       fd = open (in, O_RDONLY);
1024       if (fd == -1)
1025         perror (in);
1026       else
1027         fds[0] = fd;
1028     }
1029   if (out[0])
1030     {
1031       fd = open (out, O_WRONLY);
1032       if (fd == -1)
1033         perror (out);
1034       else
1035         fds[1] = fd;
1036     }
1037   if (err[0])
1038     {
1039       fd = open (err, O_WRONLY);
1040       if (fd == -1)
1041         perror (err);
1042       else
1043         fds[2] = fd;
1044     }
1045
1046   /* Clear any pending SIGUSR1's but keep the behavior the same.  */
1047   signal (SIGUSR1, signal (SIGUSR1, SIG_IGN));
1048
1049   sigemptyset (&set);
1050   sigaddset (&set, SIGUSR1);
1051   sigprocmask (SIG_UNBLOCK, &set, NULL);
1052
1053   memset (&inherit, 0, sizeof (inherit));
1054
1055   if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) != 0)
1056     {
1057       inherit.nd = nto_node ();
1058       inherit.flags |= SPAWN_SETND;
1059       inherit.flags &= ~SPAWN_EXEC;
1060     }
1061   inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
1062   inherit.pgroup = SPAWN_NEWPGROUP;
1063   pid = spawnp (argv[0], 3, fds, &inherit, argv,
1064                 ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0 ? env : 0);
1065   xfree (args);
1066
1067   sigprocmask (SIG_BLOCK, &set, NULL);
1068
1069   if (pid == -1)
1070     error (_("Error spawning %s: %d (%s)"), argv[0], errno,
1071            safe_strerror (errno));
1072
1073   if (fds[0] != STDIN_FILENO)
1074     close (fds[0]);
1075   if (fds[1] != STDOUT_FILENO)
1076     close (fds[1]);
1077   if (fds[2] != STDERR_FILENO)
1078     close (fds[2]);
1079
1080   inferior_ptid = do_attach (pid_to_ptid (pid));
1081
1082   attach_flag = 0;
1083   flags = _DEBUG_FLAG_KLC;      /* Kill-on-Last-Close flag.  */
1084   errn = devctl (ctl_fd, DCMD_PROC_SET_FLAG, &flags, sizeof (flags), 0);
1085   if (errn != EOK)
1086     {
1087       /* FIXME: expected warning?  */
1088       /* warning( "Failed to set Kill-on-Last-Close flag: errno = %d(%s)\n",
1089          errn, strerror(errn) ); */
1090     }
1091   push_target (&procfs_ops);
1092   target_terminal_init ();
1093
1094 #ifdef SOLIB_CREATE_INFERIOR_HOOK
1095   if (exec_bfd != NULL
1096       || (symfile_objfile != NULL && symfile_objfile->obfd != NULL))
1097     SOLIB_CREATE_INFERIOR_HOOK (pid);
1098 #endif
1099   stop_soon = 0;
1100   proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
1101 }
1102
1103 static void
1104 procfs_stop (void)
1105 {
1106   devctl (ctl_fd, DCMD_PROC_STOP, NULL, 0, 0);
1107 }
1108
1109 static void
1110 procfs_kill_inferior (void)
1111 {
1112   target_mourn_inferior ();
1113 }
1114
1115 /* Store register REGNO, or all registers if REGNO == -1, from the contents
1116    of REGISTERS.  */
1117 static void
1118 procfs_prepare_to_store (void)
1119 {
1120 }
1121
1122 /* Fill buf with regset and return devctl cmd to do the setting.  Return
1123    -1 if we fail to get the regset.  Store size of regset in regsize.  */
1124 static int
1125 get_regset (int regset, char *buf, int bufsize, int *regsize)
1126 {
1127   int dev_get, dev_set;
1128   switch (regset)
1129     {
1130     case NTO_REG_GENERAL:
1131       dev_get = DCMD_PROC_GETGREG;
1132       dev_set = DCMD_PROC_SETGREG;
1133       break;
1134
1135     case NTO_REG_FLOAT:
1136       dev_get = DCMD_PROC_GETFPREG;
1137       dev_set = DCMD_PROC_SETFPREG;
1138       break;
1139
1140     case NTO_REG_ALT:
1141       dev_get = DCMD_PROC_GETALTREG;
1142       dev_set = DCMD_PROC_SETALTREG;
1143       break;
1144
1145     case NTO_REG_SYSTEM:
1146     default:
1147       return -1;
1148     }
1149   if (devctl (ctl_fd, dev_get, &buf, bufsize, regsize) != EOK)
1150     return -1;
1151
1152   return dev_set;
1153 }
1154
1155 void
1156 procfs_store_registers (int regno)
1157 {
1158   union
1159   {
1160     procfs_greg greg;
1161     procfs_fpreg fpreg;
1162     procfs_altreg altreg;
1163   }
1164   reg;
1165   unsigned off;
1166   int len, regset, regsize, dev_set, err;
1167   char *data;
1168
1169   if (ptid_equal (inferior_ptid, null_ptid))
1170     return;
1171   procfs_set_thread (inferior_ptid);
1172
1173   if (regno == -1)
1174     {
1175       for (regset = NTO_REG_GENERAL; regset < NTO_REG_END; regset++)
1176         {
1177           dev_set = get_regset (regset, (char *) &reg,
1178                                 sizeof (reg), &regsize);
1179           if (dev_set == -1)
1180             continue;
1181
1182           if (nto_regset_fill (regset, (char *) &reg) == -1)
1183             continue;
1184
1185           err = devctl (ctl_fd, dev_set, &reg, regsize, 0);
1186           if (err != EOK)
1187             fprintf_unfiltered (gdb_stderr,
1188                                 "Warning unable to write regset %d: %s\n",
1189                                 regno, safe_strerror (err));
1190         }
1191     }
1192   else
1193     {
1194       regset = nto_regset_id (regno);
1195       if (regset == -1)
1196         return;
1197
1198       dev_set = get_regset (regset, (char *) &reg, sizeof (reg), &regsize);
1199       if (dev_set == -1)
1200         return;
1201
1202       len = nto_register_area (regno, regset, &off);
1203
1204       if (len < 1)
1205         return;
1206
1207       regcache_raw_collect (current_regcache, regno, (char *) &reg + off);
1208
1209       err = devctl (ctl_fd, dev_set, &reg, regsize, 0);
1210       if (err != EOK)
1211         fprintf_unfiltered (gdb_stderr,
1212                             "Warning unable to write regset %d: %s\n", regno,
1213                             safe_strerror (err));
1214     }
1215 }
1216
1217 static void
1218 notice_signals (void)
1219 {
1220   int signo;
1221
1222   for (signo = 1; signo < NSIG; signo++)
1223     {
1224       if (signal_stop_state (target_signal_from_host (signo)) == 0
1225           && signal_print_state (target_signal_from_host (signo)) == 0
1226           && signal_pass_state (target_signal_from_host (signo)) == 1)
1227         sigdelset (&run.trace, signo);
1228       else
1229         sigaddset (&run.trace, signo);
1230     }
1231 }
1232
1233 /* When the user changes the state of gdb's signal handling via the
1234    "handle" command, this function gets called to see if any change
1235    in the /proc interface is required.  It is also called internally
1236    by other /proc interface functions to initialize the state of
1237    the traced signal set.  */
1238 static void
1239 procfs_notice_signals (ptid_t ptid)
1240 {
1241   sigemptyset (&run.trace);
1242   notice_signals ();
1243 }
1244
1245 static struct tidinfo *
1246 procfs_thread_info (pid_t pid, short tid)
1247 {
1248 /* NYI */
1249   return NULL;
1250 }
1251
1252 char *
1253 procfs_pid_to_str (ptid_t ptid)
1254 {
1255   static char buf[1024];
1256   int pid, tid, n;
1257   struct tidinfo *tip;
1258
1259   pid = ptid_get_pid (ptid);
1260   tid = ptid_get_tid (ptid);
1261
1262   n = snprintf (buf, 1023, "process %d", pid);
1263
1264 #if 0                           /* NYI */
1265   tip = procfs_thread_info (pid, tid);
1266   if (tip != NULL)
1267     snprintf (&buf[n], 1023, " (state = 0x%02x)", tip->state);
1268 #endif
1269
1270   return buf;
1271 }
1272
1273 static void
1274 init_procfs_ops (void)
1275 {
1276   procfs_ops.to_shortname = "procfs";
1277   procfs_ops.to_longname = "QNX Neutrino procfs child process";
1278   procfs_ops.to_doc =
1279     "QNX Neutrino procfs child process (started by the \"run\" command).\n\
1280         target procfs <node>";
1281   procfs_ops.to_open = procfs_open;
1282   procfs_ops.to_attach = procfs_attach;
1283   procfs_ops.to_post_attach = procfs_post_attach;
1284   procfs_ops.to_detach = procfs_detach;
1285   procfs_ops.to_resume = procfs_resume;
1286   procfs_ops.to_wait = procfs_wait;
1287   procfs_ops.to_fetch_registers = procfs_fetch_registers;
1288   procfs_ops.to_store_registers = procfs_store_registers;
1289   procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
1290   procfs_ops.deprecated_xfer_memory = procfs_xfer_memory;
1291   procfs_ops.to_files_info = procfs_files_info;
1292   procfs_ops.to_insert_breakpoint = procfs_insert_breakpoint;
1293   procfs_ops.to_remove_breakpoint = procfs_remove_breakpoint;
1294   procfs_ops.to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
1295   procfs_ops.to_insert_hw_breakpoint = procfs_insert_hw_breakpoint;
1296   procfs_ops.to_remove_hw_breakpoint = procfs_remove_breakpoint;
1297   procfs_ops.to_insert_watchpoint = procfs_insert_hw_watchpoint;
1298   procfs_ops.to_remove_watchpoint = procfs_remove_hw_watchpoint;
1299   procfs_ops.to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
1300   procfs_ops.to_terminal_init = terminal_init_inferior;
1301   procfs_ops.to_terminal_inferior = terminal_inferior;
1302   procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
1303   procfs_ops.to_terminal_ours = terminal_ours;
1304   procfs_ops.to_terminal_info = child_terminal_info;
1305   procfs_ops.to_kill = procfs_kill_inferior;
1306   procfs_ops.to_create_inferior = procfs_create_inferior;
1307   procfs_ops.to_mourn_inferior = procfs_mourn_inferior;
1308   procfs_ops.to_can_run = procfs_can_run;
1309   procfs_ops.to_notice_signals = procfs_notice_signals;
1310   procfs_ops.to_thread_alive = procfs_thread_alive;
1311   procfs_ops.to_find_new_threads = procfs_find_new_threads;
1312   procfs_ops.to_pid_to_str = procfs_pid_to_str;
1313   procfs_ops.to_stop = procfs_stop;
1314   procfs_ops.to_stratum = process_stratum;
1315   procfs_ops.to_has_all_memory = 1;
1316   procfs_ops.to_has_memory = 1;
1317   procfs_ops.to_has_stack = 1;
1318   procfs_ops.to_has_registers = 1;
1319   procfs_ops.to_has_execution = 1;
1320   procfs_ops.to_magic = OPS_MAGIC;
1321   procfs_ops.to_have_continuable_watchpoint = 1;
1322 }
1323
1324 #define OSTYPE_NTO 1
1325
1326 void
1327 _initialize_procfs (void)
1328 {
1329   sigset_t set;
1330
1331   init_procfs_ops ();
1332   add_target (&procfs_ops);
1333
1334   /* We use SIGUSR1 to gain control after we block waiting for a process.
1335      We use sigwaitevent to wait.  */
1336   sigemptyset (&set);
1337   sigaddset (&set, SIGUSR1);
1338   sigprocmask (SIG_BLOCK, &set, NULL);
1339
1340   /* Set up trace and fault sets, as gdb expects them.  */
1341   sigemptyset (&run.trace);
1342
1343   /* Stuff some information.  */
1344   nto_cpuinfo_flags = SYSPAGE_ENTRY (cpuinfo)->flags;
1345   nto_cpuinfo_valid = 1;
1346
1347   add_info ("pidlist", procfs_pidlist, _("pidlist"));
1348   add_info ("meminfo", procfs_meminfo, _("memory information"));
1349
1350   nto_is_nto_target = procfs_is_nto_target;
1351 }
1352
1353
1354 static int
1355 procfs_hw_watchpoint (int addr, int len, int type)
1356 {
1357   procfs_break brk;
1358
1359   switch (type)
1360     {
1361     case 1:                     /* Read.  */
1362       brk.type = _DEBUG_BREAK_RD;
1363       break;
1364     case 2:                     /* Read/Write.  */
1365       brk.type = _DEBUG_BREAK_RW;
1366       break;
1367     default:                    /* Modify.  */
1368 /* FIXME: brk.type = _DEBUG_BREAK_RWM gives EINVAL for some reason.  */
1369       brk.type = _DEBUG_BREAK_RW;
1370     }
1371   brk.type |= _DEBUG_BREAK_HW;  /* Always ask for HW.  */
1372   brk.addr = addr;
1373   brk.size = len;
1374
1375   errno = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0);
1376   if (errno != EOK)
1377     {
1378       perror ("Failed to set hardware watchpoint");
1379       return -1;
1380     }
1381   return 0;
1382 }
1383
1384 static int
1385 procfs_can_use_hw_breakpoint (int type, int cnt, int othertype)
1386 {
1387   return 1;
1388 }
1389
1390 static int
1391 procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type)
1392 {
1393   return procfs_hw_watchpoint (addr, -1, type);
1394 }
1395
1396 static int
1397 procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type)
1398 {
1399   return procfs_hw_watchpoint (addr, len, type);
1400 }
1401
1402 static int
1403 procfs_stopped_by_watchpoint (void)
1404 {
1405   return 0;
1406 }