]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/lynx-low.c
Move savestring to common/common-utils.c, make gdbserver use it.
[thirdparty/binutils-gdb.git] / gdb / gdbserver / lynx-low.c
CommitLineData
28e7fd62 1/* Copyright (C) 2009-2013 Free Software Foundation, Inc.
8ed54b31
JB
2
3 This file is part of GDB.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18#include "server.h"
19#include "target.h"
20#include "lynx-low.h"
21
22#include <limits.h>
1adfc54d 23#include <sys/ptrace.h>
8ed54b31
JB
24#include <sys/piddef.h> /* Provides PIDGET, TIDGET, BUILDPID, etc. */
25#include <unistd.h>
26#include <sys/ioctl.h>
27#include <sys/types.h>
8bdce1ff 28#include "gdb_wait.h"
8ed54b31
JB
29#include <signal.h>
30
31int using_threads = 1;
32
33/* Print a debug trace on standard output if debug_threads is set. */
34
35static void
36lynx_debug (char *string, ...)
37{
38 va_list args;
39
40 if (!debug_threads)
41 return;
42
43 va_start (args, string);
44 fprintf (stderr, "DEBUG(lynx): ");
45 vfprintf (stderr, string, args);
46 fprintf (stderr, "\n");
47 va_end (args);
48}
49
50/* Build a ptid_t given a PID and a LynxOS TID. */
51
52static ptid_t
53lynx_ptid_build (int pid, long tid)
54{
55 /* brobecker/2010-06-21: It looks like the LWP field in ptids
56 should be distinct for each thread (see write_ptid where it
57 writes the thread ID from the LWP). So instead of storing
58 the LynxOS tid in the tid field of the ptid, we store it in
59 the lwp field. */
60 return ptid_build (pid, tid, 0);
61}
62
63/* Return the process ID of the given PTID.
64
65 This function has little reason to exist, it's just a wrapper around
66 ptid_get_pid. But since we have a getter function for the lynxos
67 ptid, it feels cleaner to have a getter for the pid as well. */
68
69static int
70lynx_ptid_get_pid (ptid_t ptid)
71{
72 return ptid_get_pid (ptid);
73}
74
75/* Return the LynxOS tid of the given PTID. */
76
77static long
78lynx_ptid_get_tid (ptid_t ptid)
79{
80 /* See lynx_ptid_build: The LynxOS tid is stored inside the lwp field
81 of the ptid. */
82 return ptid_get_lwp (ptid);
83}
84
85/* For a given PTID, return the associated PID as known by the LynxOS
86 ptrace layer. */
87
88static int
89lynx_ptrace_pid_from_ptid (ptid_t ptid)
90{
91 return BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));
92}
93
94/* Return a string image of the ptrace REQUEST number. */
95
96static char *
97ptrace_request_to_str (int request)
98{
4039cf45 99#define CASE(X) case X: return #X
8ed54b31
JB
100 switch (request)
101 {
4039cf45
JB
102 CASE(PTRACE_TRACEME);
103 CASE(PTRACE_PEEKTEXT);
104 CASE(PTRACE_PEEKDATA);
105 CASE(PTRACE_PEEKUSER);
106 CASE(PTRACE_POKETEXT);
107 CASE(PTRACE_POKEDATA);
108 CASE(PTRACE_POKEUSER);
109 CASE(PTRACE_CONT);
110 CASE(PTRACE_KILL);
111 CASE(PTRACE_SINGLESTEP);
112 CASE(PTRACE_ATTACH);
113 CASE(PTRACE_DETACH);
114 CASE(PTRACE_GETREGS);
115 CASE(PTRACE_SETREGS);
116 CASE(PTRACE_GETFPREGS);
117 CASE(PTRACE_SETFPREGS);
118 CASE(PTRACE_READDATA);
119 CASE(PTRACE_WRITEDATA);
120 CASE(PTRACE_READTEXT);
121 CASE(PTRACE_WRITETEXT);
122 CASE(PTRACE_GETFPAREGS);
123 CASE(PTRACE_SETFPAREGS);
124 CASE(PTRACE_GETWINDOW);
125 CASE(PTRACE_SETWINDOW);
126 CASE(PTRACE_SYSCALL);
127 CASE(PTRACE_DUMPCORE);
128 CASE(PTRACE_SETWRBKPT);
129 CASE(PTRACE_SETACBKPT);
130 CASE(PTRACE_CLRBKPT);
131 CASE(PTRACE_GET_UCODE);
8ed54b31 132#ifdef PT_READ_GPR
4039cf45 133 CASE(PT_READ_GPR);
8ed54b31
JB
134#endif
135#ifdef PT_WRITE_GPR
4039cf45 136 CASE(PT_WRITE_GPR);
8ed54b31
JB
137#endif
138#ifdef PT_READ_FPR
4039cf45 139 CASE(PT_READ_FPR);
8ed54b31
JB
140#endif
141#ifdef PT_WRITE_FPR
4039cf45 142 CASE(PT_WRITE_FPR);
8ed54b31 143#endif
8ed54b31 144#ifdef PT_READ_VPR
4039cf45 145 CASE(PT_READ_VPR);
8ed54b31
JB
146#endif
147#ifdef PT_WRITE_VPR
4039cf45 148 CASE(PT_WRITE_VPR);
8ed54b31
JB
149#endif
150#ifdef PTRACE_PEEKUSP
4039cf45 151 CASE(PTRACE_PEEKUSP);
8ed54b31
JB
152#endif
153#ifdef PTRACE_POKEUSP
4039cf45 154 CASE(PTRACE_POKEUSP);
8ed54b31 155#endif
4039cf45
JB
156 CASE(PTRACE_PEEKTHREAD);
157 CASE(PTRACE_THREADUSER);
158 CASE(PTRACE_FPREAD);
159 CASE(PTRACE_FPWRITE);
160 CASE(PTRACE_SETSIG);
161 CASE(PTRACE_CONT_ONE);
162 CASE(PTRACE_KILL_ONE);
163 CASE(PTRACE_SINGLESTEP_ONE);
164 CASE(PTRACE_GETLOADINFO);
165 CASE(PTRACE_GETTRACESIG);
78cbc024 166#ifdef PTRACE_GETTHREADLIST
4039cf45 167 CASE(PTRACE_GETTHREADLIST);
78cbc024 168#endif
8ed54b31 169 }
4039cf45
JB
170#undef CASE
171
8ed54b31
JB
172 return "<unknown-request>";
173}
174
175/* A wrapper around ptrace that allows us to print debug traces of
176 ptrace calls if debug traces are activated. */
177
178static int
179lynx_ptrace (int request, ptid_t ptid, int addr, int data, int addr2)
180{
181 int result;
182 const int pid = lynx_ptrace_pid_from_ptid (ptid);
183 int saved_errno;
184
185 if (debug_threads)
186 fprintf (stderr, "PTRACE (%s, pid=%d(pid=%d, tid=%d), addr=0x%x, "
187 "data=0x%x, addr2=0x%x)",
188 ptrace_request_to_str (request), pid, PIDGET (pid), TIDGET (pid),
189 addr, data, addr2);
190 result = ptrace (request, pid, addr, data, addr2);
191 saved_errno = errno;
192 if (debug_threads)
193 fprintf (stderr, " -> %d (=0x%x)\n", result, result);
194
195 errno = saved_errno;
196 return result;
197}
198
199/* Implement the create_inferior method of the target_ops vector. */
200
201static int
202lynx_create_inferior (char *program, char **allargs)
203{
8ed54b31
JB
204 int pid;
205
206 lynx_debug ("lynx_create_inferior ()");
207
208 pid = fork ();
209 if (pid < 0)
210 perror_with_name ("fork");
211
212 if (pid == 0)
213 {
214 int pgrp;
215
216 /* Switch child to its own process group so that signals won't
217 directly affect gdbserver. */
218 pgrp = getpid();
219 setpgid (0, pgrp);
220 ioctl (0, TIOCSPGRP, &pgrp);
221 lynx_ptrace (PTRACE_TRACEME, null_ptid, 0, 0, 0);
222 execv (program, allargs);
223 fprintf (stderr, "Cannot exec %s: %s.\n", program, strerror (errno));
224 fflush (stderr);
225 _exit (0177);
226 }
227
ab8f6ca9 228 add_process (pid, 0);
8ed54b31
JB
229 /* Do not add the process thread just yet, as we do not know its tid.
230 We will add it later, during the wait for the STOP event corresponding
231 to the lynx_ptrace (PTRACE_TRACEME) call above. */
232 return pid;
233}
234
235/* Implement the attach target_ops method. */
236
237static int
238lynx_attach (unsigned long pid)
239{
8ed54b31
JB
240 ptid_t ptid = lynx_ptid_build (pid, 0);
241
242 if (lynx_ptrace (PTRACE_ATTACH, ptid, 0, 0, 0) != 0)
243 error ("Cannot attach to process %lu: %s (%d)\n", pid,
244 strerror (errno), errno);
245
52d4cbd8 246 add_process (pid, 1);
8ed54b31
JB
247 add_thread (ptid, NULL);
248
249 return 0;
250}
251
252/* Implement the resume target_ops method. */
253
254static void
255lynx_resume (struct thread_resume *resume_info, size_t n)
256{
8ed54b31 257 /* FIXME: Assume for now that n == 1. */
3f6e77ef 258 ptid_t ptid = resume_info[0].thread;
8ed54b31
JB
259 const int request = (resume_info[0].kind == resume_step
260 ? PTRACE_SINGLESTEP : PTRACE_CONT);
261 const int signal = resume_info[0].sig;
8ed54b31 262
3f6e77ef
JB
263 if (ptid_equal (ptid, minus_one_ptid))
264 ptid = thread_to_gdb_id (current_inferior);
265
8ed54b31 266 regcache_invalidate ();
9044dee2
JB
267
268 errno = 0;
3f6e77ef 269 lynx_ptrace (request, ptid, 1, signal, 0);
9044dee2
JB
270 if (errno)
271 perror_with_name ("ptrace");
8ed54b31
JB
272}
273
274/* Resume the execution of the given PTID. */
275
276static void
277lynx_continue (ptid_t ptid)
278{
279 struct thread_resume resume_info;
280
281 resume_info.thread = ptid;
282 resume_info.kind = resume_continue;
283 resume_info.sig = 0;
284
285 lynx_resume (&resume_info, 1);
286}
287
288/* Remove all inferiors and associated threads. */
289
290static void
291lynx_clear_inferiors (void)
292{
293 /* We do not use private data, so nothing much to do except calling
294 clear_inferiors. */
295 clear_inferiors ();
296}
297
298/* A wrapper around waitpid that handles the various idiosyncrasies
299 of LynxOS' waitpid. */
300
301static int
302lynx_waitpid (int pid, int *stat_loc)
303{
304 int ret = 0;
305
306 while (1)
307 {
308 ret = waitpid (pid, stat_loc, WNOHANG);
309 if (ret < 0)
310 {
311 /* An ECHILD error is not indicative of a real problem.
312 It happens for instance while waiting for the inferior
313 to stop after attaching to it. */
314 if (errno != ECHILD)
315 perror_with_name ("waitpid (WNOHANG)");
316 }
317 if (ret > 0)
318 break;
319 /* No event with WNOHANG. See if there is one with WUNTRACED. */
320 ret = waitpid (pid, stat_loc, WNOHANG | WUNTRACED);
321 if (ret < 0)
322 {
323 /* An ECHILD error is not indicative of a real problem.
324 It happens for instance while waiting for the inferior
325 to stop after attaching to it. */
326 if (errno != ECHILD)
327 perror_with_name ("waitpid (WNOHANG|WUNTRACED)");
328 }
329 if (ret > 0)
330 break;
331 usleep (1000);
332 }
333 return ret;
334}
335
336/* Implement the wait target_ops method. */
337
338static ptid_t
339lynx_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options)
340{
341 int pid;
342 int ret;
343 int wstat;
344 ptid_t new_ptid;
345
346 if (ptid_equal (ptid, minus_one_ptid))
347 pid = lynx_ptid_get_pid (thread_to_gdb_id (current_inferior));
348 else
349 pid = BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));
350
351retry:
352
353 ret = lynx_waitpid (pid, &wstat);
354 new_ptid = lynx_ptid_build (ret, ((union wait *) &wstat)->w_tid);
355
356 /* If this is a new thread, then add it now. The reason why we do
357 this here instead of when handling new-thread events is because
358 we need to add the thread associated to the "main" thread - even
359 for non-threaded applications where the new-thread events are not
360 generated. */
361 if (!find_thread_ptid (new_ptid))
8b93d60f
JB
362 {
363 lynx_debug ("New thread: (pid = %d, tid = %d)",
364 lynx_ptid_get_pid (new_ptid), lynx_ptid_get_tid (new_ptid));
365 add_thread (new_ptid, NULL);
366 }
8ed54b31
JB
367
368 if (WIFSTOPPED (wstat))
369 {
370 status->kind = TARGET_WAITKIND_STOPPED;
2ea28649 371 status->value.integer = gdb_signal_from_host (WSTOPSIG (wstat));
8ed54b31
JB
372 lynx_debug ("process stopped with signal: %d",
373 status->value.integer);
374 }
375 else if (WIFEXITED (wstat))
376 {
377 status->kind = TARGET_WAITKIND_EXITED;
378 status->value.integer = WEXITSTATUS (wstat);
379 lynx_debug ("process exited with code: %d", status->value.integer);
380 }
381 else if (WIFSIGNALED (wstat))
382 {
383 status->kind = TARGET_WAITKIND_SIGNALLED;
2ea28649 384 status->value.integer = gdb_signal_from_host (WTERMSIG (wstat));
8ed54b31
JB
385 lynx_debug ("process terminated with code: %d",
386 status->value.integer);
387 }
388 else
389 {
390 /* Not sure what happened if we get here, or whether we can
391 in fact get here. But if we do, handle the event the best
392 we can. */
393 status->kind = TARGET_WAITKIND_STOPPED;
2ea28649 394 status->value.integer = gdb_signal_from_host (0);
8ed54b31
JB
395 lynx_debug ("unknown event ????");
396 }
397
398 /* SIGTRAP events are generated for situations other than single-step/
399 breakpoint events (Eg. new-thread events). Handle those other types
400 of events, and resume the execution if necessary. */
401 if (status->kind == TARGET_WAITKIND_STOPPED
a493e3e2 402 && status->value.integer == GDB_SIGNAL_TRAP)
8ed54b31
JB
403 {
404 const int realsig = lynx_ptrace (PTRACE_GETTRACESIG, new_ptid, 0, 0, 0);
405
406 lynx_debug ("(realsig = %d)", realsig);
407 switch (realsig)
408 {
409 case SIGNEWTHREAD:
410 /* We just added the new thread above. No need to do anything
411 further. Just resume the execution again. */
3f6e77ef 412 lynx_continue (new_ptid);
8ed54b31
JB
413 goto retry;
414
415 case SIGTHREADEXIT:
416 remove_thread (find_thread_ptid (new_ptid));
3f6e77ef 417 lynx_continue (new_ptid);
8ed54b31
JB
418 goto retry;
419 }
420 }
421
422 return new_ptid;
423}
424
425/* A wrapper around lynx_wait_1 that also prints debug traces when
426 such debug traces have been activated. */
427
428static ptid_t
429lynx_wait (ptid_t ptid, struct target_waitstatus *status, int options)
430{
431 ptid_t new_ptid;
432
433 lynx_debug ("lynx_wait (pid = %d, tid = %ld)",
434 lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));
435 new_ptid = lynx_wait_1 (ptid, status, options);
436 lynx_debug (" -> (pid=%d, tid=%ld, status->kind = %d)",
437 lynx_ptid_get_pid (new_ptid), lynx_ptid_get_tid (new_ptid),
438 status->kind);
439 return new_ptid;
440}
441
442/* Implement the kill target_ops method. */
443
444static int
445lynx_kill (int pid)
446{
447 ptid_t ptid = lynx_ptid_build (pid, 0);
448 struct target_waitstatus status;
449 struct process_info *process;
450
451 process = find_process_pid (pid);
452 if (process == NULL)
453 return -1;
454
455 lynx_ptrace (PTRACE_KILL, ptid, 0, 0, 0);
456 lynx_wait (ptid, &status, 0);
457 the_target->mourn (process);
458 return 0;
459}
460
461/* Implement the detach target_ops method. */
462
463static int
464lynx_detach (int pid)
465{
466 ptid_t ptid = lynx_ptid_build (pid, 0);
467 struct process_info *process;
468
469 process = find_process_pid (pid);
470 if (process == NULL)
471 return -1;
472
473 lynx_ptrace (PTRACE_DETACH, ptid, 0, 0, 0);
474 the_target->mourn (process);
475 return 0;
476}
477
478/* Implement the mourn target_ops method. */
479
480static void
481lynx_mourn (struct process_info *proc)
482{
483 lynx_clear_inferiors ();
484}
485
486/* Implement the join target_ops method. */
487
488static void
489lynx_join (int pid)
490{
491 /* The PTRACE_DETACH is sufficient to detach from the process.
492 So no need to do anything extra. */
493}
494
495/* Implement the thread_alive target_ops method. */
496
497static int
498lynx_thread_alive (ptid_t ptid)
499{
500 /* The list of threads is updated at the end of each wait, so it
501 should be up to date. No need to re-fetch it. */
502 return (find_thread_ptid (ptid) != NULL);
503}
504
505/* Implement the fetch_registers target_ops method. */
506
507static void
508lynx_fetch_registers (struct regcache *regcache, int regno)
509{
510 struct lynx_regset_info *regset = lynx_target_regsets;
511 ptid_t inferior_ptid = thread_to_gdb_id (current_inferior);
512
513 lynx_debug ("lynx_fetch_registers (regno = %d)", regno);
514
515 while (regset->size >= 0)
516 {
517 char *buf;
518 int res;
519
520 buf = xmalloc (regset->size);
521 res = lynx_ptrace (regset->get_request, inferior_ptid, (int) buf, 0, 0);
522 if (res < 0)
523 perror ("ptrace");
524 regset->store_function (regcache, buf);
525 free (buf);
526 regset++;
527 }
528}
529
530/* Implement the store_registers target_ops method. */
531
532static void
533lynx_store_registers (struct regcache *regcache, int regno)
534{
535 struct lynx_regset_info *regset = lynx_target_regsets;
536 ptid_t inferior_ptid = thread_to_gdb_id (current_inferior);
537
538 lynx_debug ("lynx_store_registers (regno = %d)", regno);
539
540 while (regset->size >= 0)
541 {
542 char *buf;
543 int res;
544
545 buf = xmalloc (regset->size);
546 res = lynx_ptrace (regset->get_request, inferior_ptid, (int) buf, 0, 0);
547 if (res == 0)
548 {
549 /* Then overlay our cached registers on that. */
550 regset->fill_function (regcache, buf);
551 /* Only now do we write the register set. */
552 res = lynx_ptrace (regset->set_request, inferior_ptid, (int) buf,
553 0, 0);
554 }
555 if (res < 0)
556 perror ("ptrace");
557 free (buf);
558 regset++;
559 }
560}
561
562/* Implement the read_memory target_ops method. */
563
564static int
565lynx_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
566{
567 /* On LynxOS, memory reads needs to be performed in chunks the size
568 of int types, and they should also be aligned accordingly. */
569 int buf;
570 const int xfer_size = sizeof (buf);
571 CORE_ADDR addr = memaddr & -(CORE_ADDR) xfer_size;
572 ptid_t inferior_ptid = thread_to_gdb_id (current_inferior);
573
574 while (addr < memaddr + len)
575 {
576 int skip = 0;
577 int truncate = 0;
578
579 errno = 0;
580 if (addr < memaddr)
581 skip = memaddr - addr;
582 if (addr + xfer_size > memaddr + len)
583 truncate = addr + xfer_size - memaddr - len;
584 buf = lynx_ptrace (PTRACE_PEEKTEXT, inferior_ptid, addr, 0, 0);
585 if (errno)
586 return errno;
587 memcpy (myaddr + (addr - memaddr) + skip, (gdb_byte *) &buf + skip,
588 xfer_size - skip - truncate);
589 addr += xfer_size;
590 }
591
592 return 0;
593}
594
595/* Implement the write_memory target_ops method. */
596
597static int
598lynx_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
599{
600 /* On LynxOS, memory writes needs to be performed in chunks the size
601 of int types, and they should also be aligned accordingly. */
602 int buf;
603 const int xfer_size = sizeof (buf);
604 CORE_ADDR addr = memaddr & -(CORE_ADDR) xfer_size;
605 ptid_t inferior_ptid = thread_to_gdb_id (current_inferior);
606
607 while (addr < memaddr + len)
608 {
609 int skip = 0;
610 int truncate = 0;
611
612 if (addr < memaddr)
613 skip = memaddr - addr;
614 if (addr + xfer_size > memaddr + len)
615 truncate = addr + xfer_size - memaddr - len;
616 if (skip > 0 || truncate > 0)
617 /* We need to read the memory at this address in order to preserve
618 the data that we are not overwriting. */
619 lynx_read_memory (addr, (unsigned char *) &buf, xfer_size);
620 if (errno)
621 return errno;
622 memcpy ((gdb_byte *) &buf + skip, myaddr + (addr - memaddr) + skip,
623 xfer_size - skip - truncate);
624 errno = 0;
625 lynx_ptrace (PTRACE_POKETEXT, inferior_ptid, addr, buf, 0);
626 if (errno)
627 return errno;
628 addr += xfer_size;
629 }
630
631 return 0;
632}
633
634/* Implement the kill_request target_ops method. */
635
636static void
637lynx_request_interrupt (void)
638{
639 ptid_t inferior_ptid = thread_to_gdb_id (current_inferior);
640
641 kill (lynx_ptid_get_pid (inferior_ptid), SIGINT);
642}
643
644/* The LynxOS target_ops vector. */
645
646static struct target_ops lynx_target_ops = {
647 lynx_create_inferior,
648 lynx_attach,
649 lynx_kill,
650 lynx_detach,
651 lynx_mourn,
652 lynx_join,
653 lynx_thread_alive,
654 lynx_resume,
655 lynx_wait,
656 lynx_fetch_registers,
657 lynx_store_registers,
658 NULL, /* prepare_to_access_memory */
659 NULL, /* done_accessing_memory */
660 lynx_read_memory,
661 lynx_write_memory,
662 NULL, /* look_up_symbols */
663 lynx_request_interrupt,
664 NULL, /* read_auxv */
665 NULL, /* insert_point */
666 NULL, /* remove_point */
667 NULL, /* stopped_by_watchpoint */
668 NULL, /* stopped_data_address */
669 NULL, /* read_offsets */
670 NULL, /* get_tls_address */
671 NULL, /* qxfer_spu */
672 NULL, /* hostio_last_error */
673 NULL, /* qxfer_osdata */
674 NULL, /* qxfer_siginfo */
675 NULL, /* supports_non_stop */
676 NULL, /* async */
677 NULL, /* start_non_stop */
678 NULL, /* supports_multi_process */
679 NULL, /* handle_monitor_command */
680};
681
682void
683initialize_low (void)
684{
685 set_target_ops (&lynx_target_ops);
686 the_low_target.arch_setup ();
687}
688