OSDN Git Service

* inf-ptrace.c [PT_GET_PROCESS_STATE] (inf_ptrace_follow_fork):
[pf3gnuchains/pf3gnuchains3x.git] / gdb / inf-ptrace.c
1 /* Low-level child interface to ptrace.
2
3    Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
4    1998, 1999, 2000, 2001, 2002, 2004, 2005
5    Free Software Foundation, Inc.
6
7    This file is part of GDB.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 59 Temple Place - Suite 330,
22    Boston, MA 02111-1307, USA.  */
23
24 #include "defs.h"
25 #include "command.h"
26 #include "inferior.h"
27 #include "inflow.h"
28 #include "gdbcore.h"
29 #include "observer.h"
30 #include "regcache.h"
31
32 #include "gdb_assert.h"
33 #include "gdb_string.h"
34 #include "gdb_ptrace.h"
35 #include "gdb_wait.h"
36 #include <signal.h>
37
38 #include "inf-child.h"
39
40 /* HACK: Save the ptrace ops returned by inf_ptrace_target.  */
41 static struct target_ops *ptrace_ops_hack;
42 \f
43
44 #ifdef PT_GET_PROCESS_STATE
45
46 static int
47 inf_ptrace_follow_fork (int follow_child)
48 {
49   pid_t pid, fpid;
50   ptrace_state_t pe;
51
52   /* FIXME: kettenis/20050720: This stuff should really be passed as
53      an argument by our caller.  */
54   {
55     ptid_t ptid;
56     struct target_waitstatus status;
57
58     get_last_target_status (&ptid, &status);
59     gdb_assert (status.kind == TARGET_WAITKIND_FORKED);
60
61     pid = ptid_get_pid (ptid);
62   }
63
64   if (ptrace (PT_GET_PROCESS_STATE, pid,
65                (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
66     perror_with_name (("ptrace"));
67
68   gdb_assert (pe.pe_report_event == PTRACE_FORK);
69   fpid = pe.pe_other_pid;
70
71   if (follow_child)
72     {
73       inferior_ptid = pid_to_ptid (fpid);
74       detach_breakpoints (pid);
75
76       /* Reset breakpoints in the child as appropriate.  */
77       follow_inferior_reset_breakpoints ();
78
79       if (ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, 0) == -1)
80         perror_with_name (("ptrace"));
81     }
82   else
83     {
84       inferior_ptid = pid_to_ptid (pid);
85       detach_breakpoints (fpid);
86
87       if (ptrace (PT_DETACH, fpid, (PTRACE_TYPE_ARG3)1, 0) == -1)
88         perror_with_name (("ptrace"));
89     }
90
91   return 0;
92 }
93
94 #endif /* PT_GET_PROCESS_STATE */
95 \f
96
97 /* Prepare to be traced.  */
98
99 static void
100 inf_ptrace_me (void)
101 {
102   /* "Trace me, Dr. Memory!"  */
103   ptrace (PT_TRACE_ME, 0, (PTRACE_TYPE_ARG3)0, 0);
104 }
105
106 /* Start tracing PID.  */
107
108 static void
109 inf_ptrace_him (int pid)
110 {
111 #ifdef PT_GET_PROCESS_STATE
112   {
113     ptrace_event_t pe;
114
115     /* Set the initial event mask.  */
116     memset (&pe, 0, sizeof pe);
117     pe.pe_set_event |= PTRACE_FORK;
118     if (ptrace (PT_SET_EVENT_MASK, pid,
119                 (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
120       perror_with_name (("ptrace"));
121   }
122 #endif
123
124   push_target (ptrace_ops_hack);
125
126   /* On some targets, there must be some explicit synchronization
127      between the parent and child processes after the debugger
128      forks, and before the child execs the debuggee program.  This
129      call basically gives permission for the child to exec.  */
130
131   target_acknowledge_created_inferior (pid);
132
133   /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h, and will
134      be 1 or 2 depending on whether we're starting without or with a
135      shell.  */
136   startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
137
138   /* On some targets, there must be some explicit actions taken after
139      the inferior has been started up.  */
140   target_post_startup_inferior (pid_to_ptid (pid));
141 }
142
143 /* Start a new inferior Unix child process.  EXEC_FILE is the file to
144    run, ALLARGS is a string containing the arguments to the program.
145    ENV is the environment vector to pass.  If FROM_TTY is non-zero, be
146    chatty about it.  */
147
148 static void
149 inf_ptrace_create_inferior (char *exec_file, char *allargs, char **env,
150                             int from_tty)
151 {
152   fork_inferior (exec_file, allargs, env, inf_ptrace_me, inf_ptrace_him,
153                  NULL, NULL);
154
155   /* We are at the first instruction we care about.  */
156   observer_notify_inferior_created (&current_target, from_tty);
157
158   /* Pedal to the metal...  */
159   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
160 }
161
162 /* Clean up a rotting corpse of an inferior after it died.  */
163
164 static void
165 inf_ptrace_mourn_inferior (void)
166 {
167   int status;
168
169   /* Wait just one more time to collect the inferior's exit status.
170      Don not check whether this succeeds though, since we may be
171      dealing with a process that we attached to.  Such a process will
172      only report its exit status to its origional parent.  */
173   waitpid (ptid_get_pid (inferior_ptid), &status, 0);
174
175   unpush_target (ptrace_ops_hack);
176   generic_mourn_inferior ();
177 }
178
179 /* Attach to the process specified by ARGS.  If FROM_TTY is non-zero,
180    be chatty about it.  */
181
182 static void
183 inf_ptrace_attach (char *args, int from_tty)
184 {
185   char *exec_file;
186   pid_t pid;
187   char *dummy;
188
189   if (!args)
190     error_no_arg (_("process-id to attach"));
191
192   dummy = args;
193   pid = strtol (args, &dummy, 0);
194   /* Some targets don't set errno on errors, grrr!  */
195   if (pid == 0 && args == dummy)
196     error (_("Illegal process-id: %s."), args);
197
198   if (pid == getpid ())         /* Trying to masturbate?  */
199     error (_("I refuse to debug myself!"));
200
201   if (from_tty)
202     {
203       exec_file = get_exec_file (0);
204
205       if (exec_file)
206         printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
207                            target_pid_to_str (pid_to_ptid (pid)));
208       else
209         printf_unfiltered (_("Attaching to %s\n"),
210                            target_pid_to_str (pid_to_ptid (pid)));
211
212       gdb_flush (gdb_stdout);
213     }
214
215 #ifdef PT_ATTACH
216   errno = 0;
217   ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0);
218   if (errno != 0)
219     perror_with_name (("ptrace"));
220   attach_flag = 1;
221 #else
222   error (_("This system does not support attaching to a process"));
223 #endif
224
225 #ifdef PT_GET_PROCESS_STATE
226   {
227     ptrace_event_t pe;
228
229     /* Set the initial event mask.  */
230     memset (&pe, 0, sizeof pe);
231     pe.pe_set_event |= PTRACE_FORK;
232     if (ptrace (PT_SET_EVENT_MASK, pid,
233                 (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
234       perror_with_name (("ptrace"));
235   }
236 #endif
237
238   inferior_ptid = pid_to_ptid (pid);
239   push_target (ptrace_ops_hack);
240
241   /* Do this first, before anything has had a chance to query the
242      inferior's symbol table or similar.  */
243   observer_notify_inferior_created (&current_target, from_tty);
244 }
245
246 /* Detach from the inferior, optionally passing it the signal
247    specified ARGS.  If FROM_TTY is non-zero, be chatty about it.  */
248
249 static void
250 inf_ptrace_detach (char *args, int from_tty)
251 {
252   pid_t pid = ptid_get_pid (inferior_ptid);
253   int sig = 0;
254
255   if (from_tty)
256     {
257       char *exec_file = get_exec_file (0);
258       if (exec_file == 0)
259         exec_file = "";
260       printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
261                          target_pid_to_str (pid_to_ptid (pid)));
262       gdb_flush (gdb_stdout);
263     }
264   if (args)
265     sig = atoi (args);
266
267 #ifdef PT_DETACH
268   /* We'd better not have left any breakpoints in the program or it'll
269      die when it hits one.  Alsno note that this may only work if we
270      previously attached to the inferior.  It *might* work if we
271      started the process ourselves.  */
272   errno = 0;
273   ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, sig);
274   if (errno != 0)
275     perror_with_name (("ptrace"));
276   attach_flag = 0;
277 #else
278   error (_("This system does not support detaching from a process"));
279 #endif
280
281   inferior_ptid = null_ptid;
282   unpush_target (ptrace_ops_hack);
283 }
284
285 /* Kill the inferior.  */
286
287 static void
288 inf_ptrace_kill (void)
289 {
290   pid_t pid = ptid_get_pid (inferior_ptid);
291   int status;
292
293   if (pid == 0)
294     return;
295
296   ptrace (PT_KILL, pid, (PTRACE_TYPE_ARG3)0, 0);
297   waitpid (pid, &status, 0);
298
299   target_mourn_inferior ();
300 }
301
302 /* Stop the inferior.  */
303
304 static void
305 inf_ptrace_stop (void)
306 {
307   /* Send a SIGINT to the process group.  This acts just like the user
308      typed a ^C on the controlling terminal.  Note that using a
309      negative process number in kill() is a System V-ism.  The proper
310      BSD interface is killpg().  However, all modern BSDs support the
311      System V interface too.  */
312   kill (-inferior_process_group, SIGINT);
313 }
314
315 /* Resume execution of thread PTID, or all threads if PTID is -1.  If
316    STEP is nonzero, single-step it.  If SIGNAL is nonzero, give it
317    that signal.  */
318
319 static void
320 inf_ptrace_resume (ptid_t ptid, int step, enum target_signal signal)
321 {
322   pid_t pid = ptid_get_pid (ptid);
323   int request = PT_CONTINUE;
324
325   if (pid == -1)
326     /* Resume all threads.  Traditionally ptrace() only supports
327        single-threaded processes, so simply resume the inferior.  */
328     pid = ptid_get_pid (inferior_ptid);
329
330   if (step)
331     {
332       /* If this system does not support PT_STEP, a higher level
333          function will have called single_step() to transmute the step
334          request into a continue request (by setting breakpoints on
335          all possible successor instructions), so we don't have to
336          worry about that here.  */
337       request = PT_STEP;
338     }
339
340   /* An address of (PTRACE_TYPE_ARG3)1 tells ptrace to continue from
341      where it was.  If GDB wanted it to start some other way, we have
342      already written a new program counter value to the child.  */
343   errno = 0;
344   ptrace (request, pid, (PTRACE_TYPE_ARG3)1, target_signal_to_host (signal));
345   if (errno != 0)
346     perror_with_name (("ptrace"));
347 }
348
349 /* Wait for the child specified by PTID to do something.  Return the
350    process ID of the child, or MINUS_ONE_PTID in case of error; store
351    the status in *OURSTATUS.  */
352
353 static ptid_t
354 inf_ptrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
355 {
356   pid_t pid;
357   int status, save_errno;
358
359   do
360     {
361       set_sigint_trap ();
362       set_sigio_trap ();
363
364       do
365         {
366           pid = waitpid (ptid_get_pid (ptid), &status, 0);
367           save_errno = errno;
368         }
369       while (pid == -1 && errno == EINTR);
370
371       clear_sigio_trap ();
372       clear_sigint_trap ();
373
374       if (pid == -1)
375         {
376           fprintf_unfiltered (gdb_stderr,
377                               _("Child process unexpectedly missing: %s.\n"),
378                               safe_strerror (save_errno));
379
380           /* Claim it exited with unknown signal.  */
381           ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
382           ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
383           return minus_one_ptid;
384         }
385
386       /* Ignore terminated detached child processes.  */
387       if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid))
388         pid = -1;
389     }
390   while (pid == -1);
391
392 #ifdef PT_GET_PROCESS_STATE
393   if (WIFSTOPPED (status))
394     {
395       ptrace_state_t pe;
396       pid_t fpid;
397
398       if (ptrace (PT_GET_PROCESS_STATE, pid,
399                   (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
400         perror_with_name (("ptrace"));
401
402       switch (pe.pe_report_event)
403         {
404         case PTRACE_FORK:
405           ourstatus->kind = TARGET_WAITKIND_FORKED;
406           ourstatus->value.related_pid = pe.pe_other_pid;
407
408           /* Make sure the other end of the fork is stopped too.  */
409           fpid = waitpid (pe.pe_other_pid, &status, 0);
410           if (fpid == -1)
411             perror_with_name (("waitpid"));
412
413           if (ptrace (PT_GET_PROCESS_STATE, fpid,
414                       (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
415             perror_with_name (("ptrace"));
416
417           gdb_assert (pe.pe_report_event == PTRACE_FORK);
418           gdb_assert (pe.pe_other_pid == pid);
419           if (fpid == ptid_get_pid (inferior_ptid))
420             {
421               ourstatus->value.related_pid = pe.pe_other_pid;
422               return pid_to_ptid (fpid);
423             }
424
425           return pid_to_ptid (pid);
426         }
427     }
428 #endif
429
430   store_waitstatus (ourstatus, status);
431   return pid_to_ptid (pid);
432 }
433
434 /* Attempt a transfer all LEN bytes starting at OFFSET between the
435    inferior's OBJECT:ANNEX space and GDB's READBUF/WRITEBUF buffer.
436    Return the number of bytes actually transferred.  */
437
438 static LONGEST
439 inf_ptrace_xfer_partial (struct target_ops *ops, enum target_object object,
440                          const char *annex, gdb_byte *readbuf,
441                          const gdb_byte *writebuf,
442                          ULONGEST offset, LONGEST len)
443 {
444   pid_t pid = ptid_get_pid (inferior_ptid);
445
446   switch (object)
447     {
448     case TARGET_OBJECT_MEMORY:
449 #ifdef PT_IO
450       /* OpenBSD 3.1, NetBSD 1.6 and FreeBSD 5.0 have a new PT_IO
451          request that promises to be much more efficient in reading
452          and writing data in the traced process's address space.  */
453       {
454         struct ptrace_io_desc piod;
455
456         /* NOTE: We assume that there are no distinct address spaces
457            for instruction and data.  */
458         piod.piod_op = writebuf ? PIOD_WRITE_D : PIOD_READ_D;
459         piod.piod_addr = writebuf ? (void *) writebuf : readbuf;
460         piod.piod_offs = (void *) (long) offset;
461         piod.piod_len = len;
462
463         errno = 0;
464         if (ptrace (PT_IO, pid, (caddr_t)&piod, 0) == 0)
465           /* Return the actual number of bytes read or written.  */
466           return piod.piod_len;
467         /* If the PT_IO request is somehow not supported, fallback on
468            using PT_WRITE_D/PT_READ_D.  Otherwise we will return zero
469            to indicate failure.  */
470         if (errno != EINVAL)
471           return 0;
472       }
473 #endif
474       {
475         union
476         {
477           PTRACE_TYPE_RET word;
478           gdb_byte byte[sizeof (PTRACE_TYPE_RET)];
479         } buffer;
480         ULONGEST rounded_offset;
481         LONGEST partial_len;
482
483         /* Round the start offset down to the next long word
484            boundary.  */
485         rounded_offset = offset & -(ULONGEST) sizeof (PTRACE_TYPE_RET);
486
487         /* Since ptrace will transfer a single word starting at that
488            rounded_offset the partial_len needs to be adjusted down to
489            that (remember this function only does a single transfer).
490            Should the required length be even less, adjust it down
491            again.  */
492         partial_len = (rounded_offset + sizeof (PTRACE_TYPE_RET)) - offset;
493         if (partial_len > len)
494           partial_len = len;
495
496         if (writebuf)
497           {
498             /* If OFFSET:PARTIAL_LEN is smaller than
499                ROUNDED_OFFSET:WORDSIZE then a read/modify write will
500                be needed.  Read in the entire word.  */
501             if (rounded_offset < offset
502                 || (offset + partial_len
503                     < rounded_offset + sizeof (PTRACE_TYPE_RET)))
504               /* Need part of initial word -- fetch it.  */
505               buffer.word = ptrace (PT_READ_I, pid,
506                                     (PTRACE_TYPE_ARG3)(long)rounded_offset, 0);
507
508             /* Copy data to be written over corresponding part of
509                buffer.  */
510             memcpy (buffer.byte + (offset - rounded_offset),
511                     writebuf, partial_len);
512
513             errno = 0;
514             ptrace (PT_WRITE_D, pid,
515                     (PTRACE_TYPE_ARG3)(long)rounded_offset, buffer.word);
516             if (errno)
517               {
518                 /* Using the appropriate one (I or D) is necessary for
519                    Gould NP1, at least.  */
520                 errno = 0;
521                 ptrace (PT_WRITE_I, pid,
522                         (PTRACE_TYPE_ARG3)(long)rounded_offset, buffer.word);
523                 if (errno)
524                   return 0;
525               }
526           }
527
528         if (readbuf)
529           {
530             errno = 0;
531             buffer.word = ptrace (PT_READ_I, pid,
532                                   (PTRACE_TYPE_ARG3)(long)rounded_offset, 0);
533             if (errno)
534               return 0;
535             /* Copy appropriate bytes out of the buffer.  */
536             memcpy (readbuf, buffer.byte + (offset - rounded_offset),
537                     partial_len);
538           }
539
540         return partial_len;
541       }
542
543     case TARGET_OBJECT_UNWIND_TABLE:
544       return -1;
545
546     case TARGET_OBJECT_AUXV:
547       return -1;
548
549     case TARGET_OBJECT_WCOOKIE:
550       return -1;
551
552     default:
553       return -1;
554     }
555 }
556
557 /* Return non-zero if the thread specified by PTID is alive.  */
558
559 static int
560 inf_ptrace_thread_alive (ptid_t ptid)
561 {
562   /* ??? Is kill the right way to do this?  */
563   return (kill (ptid_get_pid (ptid), 0) != -1);
564 }
565
566 /* Print status information about what we're accessing.  */
567
568 static void
569 inf_ptrace_files_info (struct target_ops *ignore)
570 {
571   printf_filtered (_("\tUsing the running image of %s %s.\n"),
572                    attach_flag ? "attached" : "child",
573                    target_pid_to_str (inferior_ptid));
574 }
575
576 /* Create a prototype ptrace target.  The client can override it with
577    local methods.  */
578
579 struct target_ops *
580 inf_ptrace_target (void)
581 {
582   struct target_ops *t = inf_child_target ();
583
584   t->to_attach = inf_ptrace_attach;
585   t->to_detach = inf_ptrace_detach;
586   t->to_resume = inf_ptrace_resume;
587   t->to_wait = inf_ptrace_wait;
588   t->to_files_info = inf_ptrace_files_info;
589   t->to_kill = inf_ptrace_kill;
590   t->to_create_inferior = inf_ptrace_create_inferior;
591 #ifdef PT_GET_PROCESS_STATE
592   t->to_follow_fork = inf_ptrace_follow_fork;
593 #endif
594   t->to_mourn_inferior = inf_ptrace_mourn_inferior;
595   t->to_thread_alive = inf_ptrace_thread_alive;
596   t->to_pid_to_str = normal_pid_to_str;
597   t->to_stop = inf_ptrace_stop;
598   t->to_xfer_partial = inf_ptrace_xfer_partial;
599
600   ptrace_ops_hack = t;
601   return t;
602 }
603 \f
604
605 /* Pointer to a function that returns the offset within the user area
606    where a particular register is stored.  */
607 static CORE_ADDR (*inf_ptrace_register_u_offset)(int);
608
609 /* Fetch register REGNUM from the inferior.  */
610
611 static void
612 inf_ptrace_fetch_register (int regnum)
613 {
614   CORE_ADDR addr;
615   size_t size;
616   PTRACE_TYPE_RET *buf;
617   int pid, i;
618
619   /* Cater for systems like GNU/Linux, that implement threads as
620      seperate processes.  */
621   pid = ptid_get_lwp (inferior_ptid);
622   if (pid == 0)
623     pid = ptid_get_pid (inferior_ptid);
624
625   /* This isn't really an address, but ptrace thinks of it as one.  */
626   addr = inf_ptrace_register_u_offset (regnum);
627   size = register_size (current_gdbarch, regnum);
628
629   gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
630   buf = alloca (size);
631
632   /* Read the register contents from the inferior a chuck at the time.  */
633   for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
634     {
635       errno = 0;
636       buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3)addr, 0);
637       if (errno != 0)
638         error (_("Couldn't read register %s (#%d): %s."),
639                REGISTER_NAME (regnum), regnum, safe_strerror (errno));
640
641       addr += sizeof (PTRACE_TYPE_RET);
642     }
643   regcache_raw_supply (current_regcache, regnum, buf);
644 }
645
646 /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
647    for all registers.  */
648
649 static void
650 inf_ptrace_fetch_registers (int regnum)
651 {
652   if (regnum == -1)
653     for (regnum = 0; regnum < NUM_REGS; regnum++)
654       inf_ptrace_fetch_register (regnum);
655   else
656     inf_ptrace_fetch_register (regnum);
657 }
658
659 /* Store register REGNUM into the inferior.  */
660
661 static void
662 inf_ptrace_store_register (int regnum)
663 {
664   CORE_ADDR addr;
665   size_t size;
666   PTRACE_TYPE_RET *buf;
667   int pid, i;
668
669   /* Cater for systems like GNU/Linux, that implement threads as
670      seperate processes.  */
671   pid = ptid_get_lwp (inferior_ptid);
672   if (pid == 0)
673     pid = ptid_get_pid (inferior_ptid);
674
675   /* This isn't really an address, but ptrace thinks of it as one.  */
676   addr = inf_ptrace_register_u_offset (regnum);
677   size = register_size (current_gdbarch, regnum);
678
679   gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
680   buf = alloca (size);
681
682   /* Write the register contents into the inferior a chunk at the time.  */
683   regcache_raw_collect (current_regcache, regnum, buf);
684   for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
685     {
686       errno = 0;
687       ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3)addr, buf[i]);
688       if (errno != 0)
689         error (_("Couldn't write register %s (#%d): %s."),
690                REGISTER_NAME (regnum), regnum, safe_strerror (errno));
691
692       addr += sizeof (PTRACE_TYPE_RET);
693     }
694 }
695
696 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
697    this for all registers.  */
698
699 void
700 inf_ptrace_store_registers (int regnum)
701 {
702   if (regnum == -1)
703     for (regnum = 0; regnum < NUM_REGS; regnum++)
704       inf_ptrace_store_register (regnum);
705   else
706     inf_ptrace_store_register (regnum);
707 }
708
709 /* Create a "traditional" ptrace target.  REGISTER_U_OFFSET should be
710    a function returning the offset within the user area where a
711    particular register is stored.  */
712
713 struct target_ops *
714 inf_ptrace_trad_target (CORE_ADDR (*register_u_offset)(int))
715 {
716   struct target_ops *t = inf_ptrace_target();
717
718   gdb_assert (register_u_offset);
719   inf_ptrace_register_u_offset = register_u_offset;
720   t->to_fetch_registers = inf_ptrace_fetch_registers;
721   t->to_store_registers = inf_ptrace_store_registers;
722
723   return t;
724 }