gdb/gdbserver/lynx-low.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "server.h"
- #include "target.h"
- #include "lynx-low.h"
- #include <limits.h>
- #include <sys/ptrace.h>
- #include <sys/piddef.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include "gdb_wait.h"
- #include <signal.h>
- #include "filestuff.h"
- int using_threads = 1;
- const struct target_desc *lynx_tdesc;
- struct process_info_private
- {
-
- ptid_t last_wait_event_ptid;
- };
- static void
- lynx_debug (char *string, ...)
- {
- va_list args;
- if (!debug_threads)
- return;
- va_start (args, string);
- fprintf (stderr, "DEBUG(lynx): ");
- vfprintf (stderr, string, args);
- fprintf (stderr, "\n");
- va_end (args);
- }
- static ptid_t
- lynx_ptid_build (int pid, long tid)
- {
-
- return ptid_build (pid, tid, 0);
- }
- static int
- lynx_ptid_get_pid (ptid_t ptid)
- {
- return ptid_get_pid (ptid);
- }
- static long
- lynx_ptid_get_tid (ptid_t ptid)
- {
-
- return ptid_get_lwp (ptid);
- }
- static int
- lynx_ptrace_pid_from_ptid (ptid_t ptid)
- {
- return BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));
- }
- static char *
- ptrace_request_to_str (int request)
- {
- #define CASE(X) case X: return #X
- switch (request)
- {
- CASE(PTRACE_TRACEME);
- CASE(PTRACE_PEEKTEXT);
- CASE(PTRACE_PEEKDATA);
- CASE(PTRACE_PEEKUSER);
- CASE(PTRACE_POKETEXT);
- CASE(PTRACE_POKEDATA);
- CASE(PTRACE_POKEUSER);
- CASE(PTRACE_CONT);
- CASE(PTRACE_KILL);
- CASE(PTRACE_SINGLESTEP);
- CASE(PTRACE_ATTACH);
- CASE(PTRACE_DETACH);
- CASE(PTRACE_GETREGS);
- CASE(PTRACE_SETREGS);
- CASE(PTRACE_GETFPREGS);
- CASE(PTRACE_SETFPREGS);
- CASE(PTRACE_READDATA);
- CASE(PTRACE_WRITEDATA);
- CASE(PTRACE_READTEXT);
- CASE(PTRACE_WRITETEXT);
- CASE(PTRACE_GETFPAREGS);
- CASE(PTRACE_SETFPAREGS);
- CASE(PTRACE_GETWINDOW);
- CASE(PTRACE_SETWINDOW);
- CASE(PTRACE_SYSCALL);
- CASE(PTRACE_DUMPCORE);
- CASE(PTRACE_SETWRBKPT);
- CASE(PTRACE_SETACBKPT);
- CASE(PTRACE_CLRBKPT);
- CASE(PTRACE_GET_UCODE);
- #ifdef PT_READ_GPR
- CASE(PT_READ_GPR);
- #endif
- #ifdef PT_WRITE_GPR
- CASE(PT_WRITE_GPR);
- #endif
- #ifdef PT_READ_FPR
- CASE(PT_READ_FPR);
- #endif
- #ifdef PT_WRITE_FPR
- CASE(PT_WRITE_FPR);
- #endif
- #ifdef PT_READ_VPR
- CASE(PT_READ_VPR);
- #endif
- #ifdef PT_WRITE_VPR
- CASE(PT_WRITE_VPR);
- #endif
- #ifdef PTRACE_PEEKUSP
- CASE(PTRACE_PEEKUSP);
- #endif
- #ifdef PTRACE_POKEUSP
- CASE(PTRACE_POKEUSP);
- #endif
- CASE(PTRACE_PEEKTHREAD);
- CASE(PTRACE_THREADUSER);
- CASE(PTRACE_FPREAD);
- CASE(PTRACE_FPWRITE);
- CASE(PTRACE_SETSIG);
- CASE(PTRACE_CONT_ONE);
- CASE(PTRACE_KILL_ONE);
- CASE(PTRACE_SINGLESTEP_ONE);
- CASE(PTRACE_GETLOADINFO);
- CASE(PTRACE_GETTRACESIG);
- #ifdef PTRACE_GETTHREADLIST
- CASE(PTRACE_GETTHREADLIST);
- #endif
- }
- #undef CASE
- return "<unknown-request>";
- }
- static int
- lynx_ptrace (int request, ptid_t ptid, int addr, int data, int addr2)
- {
- int result;
- const int pid = lynx_ptrace_pid_from_ptid (ptid);
- int saved_errno;
- if (debug_threads)
- fprintf (stderr, "PTRACE (%s, pid=%d(pid=%d, tid=%d), addr=0x%x, "
- "data=0x%x, addr2=0x%x)",
- ptrace_request_to_str (request), pid, PIDGET (pid), TIDGET (pid),
- addr, data, addr2);
- result = ptrace (request, pid, addr, data, addr2);
- saved_errno = errno;
- if (debug_threads)
- fprintf (stderr, " -> %d (=0x%x)\n", result, result);
- errno = saved_errno;
- return result;
- }
- static struct process_info *
- lynx_add_process (int pid, int attached)
- {
- struct process_info *proc;
- proc = add_process (pid, attached);
- proc->tdesc = lynx_tdesc;
- proc->private = xcalloc (1, sizeof (*proc->private));
- proc->private->last_wait_event_ptid = null_ptid;
- return proc;
- }
- static int
- lynx_create_inferior (char *program, char **allargs)
- {
- int pid;
- lynx_debug ("lynx_create_inferior ()");
- pid = fork ();
- if (pid < 0)
- perror_with_name ("fork");
- if (pid == 0)
- {
- int pgrp;
- close_most_fds ();
-
- pgrp = getpid();
- setpgid (0, pgrp);
- ioctl (0, TIOCSPGRP, &pgrp);
- lynx_ptrace (PTRACE_TRACEME, null_ptid, 0, 0, 0);
- execv (program, allargs);
- fprintf (stderr, "Cannot exec %s: %s.\n", program, strerror (errno));
- fflush (stderr);
- _exit (0177);
- }
- lynx_add_process (pid, 0);
-
- return pid;
- }
- static void
- lynx_add_threads_after_attach (int pid)
- {
-
- FILE *f;
- char buf[256];
- int thread_pid, thread_tid;
- f = popen ("ps atx", "r");
- if (f == NULL)
- perror_with_name ("Cannot get thread list");
- while (fgets (buf, sizeof (buf), f) != NULL)
- if ((sscanf (buf, "%d %d", &thread_pid, &thread_tid) == 2
- && thread_pid == pid))
- {
- ptid_t thread_ptid = lynx_ptid_build (pid, thread_tid);
- if (!find_thread_ptid (thread_ptid))
- {
- lynx_debug ("New thread: (pid = %d, tid = %d)",
- pid, thread_tid);
- add_thread (thread_ptid, NULL);
- }
- }
- pclose (f);
- }
- static int
- lynx_attach (unsigned long pid)
- {
- ptid_t ptid = lynx_ptid_build (pid, 0);
- if (lynx_ptrace (PTRACE_ATTACH, ptid, 0, 0, 0) != 0)
- error ("Cannot attach to process %lu: %s (%d)\n", pid,
- strerror (errno), errno);
- lynx_add_process (pid, 1);
- lynx_add_threads_after_attach (pid);
- return 0;
- }
- static void
- lynx_resume (struct thread_resume *resume_info, size_t n)
- {
- ptid_t ptid = resume_info[0].thread;
- const int request
- = (resume_info[0].kind == resume_step
- ? (n == 1 ? PTRACE_SINGLESTEP_ONE : PTRACE_SINGLESTEP)
- : PTRACE_CONT);
- const int signal = resume_info[0].sig;
-
- if (ptid_equal (ptid, minus_one_ptid))
- ptid = current_process()->private->last_wait_event_ptid;
-
- if (ptid_equal (ptid, minus_one_ptid))
- ptid = thread_to_gdb_id (current_thread);
- regcache_invalidate ();
- errno = 0;
- lynx_ptrace (request, ptid, 1, signal, 0);
- if (errno)
- perror_with_name ("ptrace");
- }
- static void
- lynx_continue (ptid_t ptid)
- {
- struct thread_resume resume_info;
- resume_info.thread = ptid;
- resume_info.kind = resume_continue;
- resume_info.sig = 0;
- lynx_resume (&resume_info, 1);
- }
- static int
- lynx_waitpid (int pid, int *stat_loc)
- {
- int ret = 0;
- while (1)
- {
- ret = waitpid (pid, stat_loc, WNOHANG);
- if (ret < 0)
- {
-
- if (errno != ECHILD)
- perror_with_name ("waitpid (WNOHANG)");
- }
- if (ret > 0)
- break;
-
- ret = waitpid (pid, stat_loc, WNOHANG | WUNTRACED);
- if (ret < 0)
- {
-
- if (errno != ECHILD)
- perror_with_name ("waitpid (WNOHANG|WUNTRACED)");
- }
- if (ret > 0)
- break;
- usleep (1000);
- }
- return ret;
- }
- static ptid_t
- lynx_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options)
- {
- int pid;
- int ret;
- int wstat;
- ptid_t new_ptid;
- if (ptid_equal (ptid, minus_one_ptid))
- pid = lynx_ptid_get_pid (thread_to_gdb_id (current_thread));
- else
- pid = BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));
- retry:
- ret = lynx_waitpid (pid, &wstat);
- new_ptid = lynx_ptid_build (ret, ((union wait *) &wstat)->w_tid);
- find_process_pid (ret)->private->last_wait_event_ptid = new_ptid;
-
- if (!find_thread_ptid (new_ptid))
- {
- lynx_debug ("New thread: (pid = %d, tid = %d)",
- lynx_ptid_get_pid (new_ptid), lynx_ptid_get_tid (new_ptid));
- add_thread (new_ptid, NULL);
- }
- if (WIFSTOPPED (wstat))
- {
- status->kind = TARGET_WAITKIND_STOPPED;
- status->value.integer = gdb_signal_from_host (WSTOPSIG (wstat));
- lynx_debug ("process stopped with signal: %d",
- status->value.integer);
- }
- else if (WIFEXITED (wstat))
- {
- status->kind = TARGET_WAITKIND_EXITED;
- status->value.integer = WEXITSTATUS (wstat);
- lynx_debug ("process exited with code: %d", status->value.integer);
- }
- else if (WIFSIGNALED (wstat))
- {
- status->kind = TARGET_WAITKIND_SIGNALLED;
- status->value.integer = gdb_signal_from_host (WTERMSIG (wstat));
- lynx_debug ("process terminated with code: %d",
- status->value.integer);
- }
- else
- {
-
- status->kind = TARGET_WAITKIND_STOPPED;
- status->value.integer = gdb_signal_from_host (0);
- lynx_debug ("unknown event ????");
- }
-
- if (status->kind == TARGET_WAITKIND_STOPPED
- && status->value.integer == GDB_SIGNAL_TRAP)
- {
- const int realsig = lynx_ptrace (PTRACE_GETTRACESIG, new_ptid, 0, 0, 0);
- lynx_debug ("(realsig = %d)", realsig);
- switch (realsig)
- {
- case SIGNEWTHREAD:
-
- lynx_continue (new_ptid);
- goto retry;
- case SIGTHREADEXIT:
- remove_thread (find_thread_ptid (new_ptid));
- lynx_continue (new_ptid);
- goto retry;
- }
- }
- return new_ptid;
- }
- static ptid_t
- lynx_wait (ptid_t ptid, struct target_waitstatus *status, int options)
- {
- ptid_t new_ptid;
- lynx_debug ("lynx_wait (pid = %d, tid = %ld)",
- lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));
- new_ptid = lynx_wait_1 (ptid, status, options);
- lynx_debug (" -> (pid=%d, tid=%ld, status->kind = %d)",
- lynx_ptid_get_pid (new_ptid), lynx_ptid_get_tid (new_ptid),
- status->kind);
- return new_ptid;
- }
- static int
- lynx_kill (int pid)
- {
- ptid_t ptid = lynx_ptid_build (pid, 0);
- struct target_waitstatus status;
- struct process_info *process;
- process = find_process_pid (pid);
- if (process == NULL)
- return -1;
- lynx_ptrace (PTRACE_KILL, ptid, 0, 0, 0);
- lynx_wait (ptid, &status, 0);
- the_target->mourn (process);
- return 0;
- }
- static int
- lynx_detach (int pid)
- {
- ptid_t ptid = lynx_ptid_build (pid, 0);
- struct process_info *process;
- process = find_process_pid (pid);
- if (process == NULL)
- return -1;
- lynx_ptrace (PTRACE_DETACH, ptid, 0, 0, 0);
- the_target->mourn (process);
- return 0;
- }
- static void
- lynx_mourn (struct process_info *proc)
- {
-
- free (proc->private);
- proc->private = NULL;
- clear_inferiors ();
- }
- static void
- lynx_join (int pid)
- {
-
- }
- static int
- lynx_thread_alive (ptid_t ptid)
- {
-
- return (find_thread_ptid (ptid) != NULL);
- }
- static void
- lynx_fetch_registers (struct regcache *regcache, int regno)
- {
- struct lynx_regset_info *regset = lynx_target_regsets;
- ptid_t inferior_ptid = thread_to_gdb_id (current_thread);
- lynx_debug ("lynx_fetch_registers (regno = %d)", regno);
- while (regset->size >= 0)
- {
- char *buf;
- int res;
- buf = xmalloc (regset->size);
- res = lynx_ptrace (regset->get_request, inferior_ptid, (int) buf, 0, 0);
- if (res < 0)
- perror ("ptrace");
- regset->store_function (regcache, buf);
- free (buf);
- regset++;
- }
- }
- static void
- lynx_store_registers (struct regcache *regcache, int regno)
- {
- struct lynx_regset_info *regset = lynx_target_regsets;
- ptid_t inferior_ptid = thread_to_gdb_id (current_thread);
- lynx_debug ("lynx_store_registers (regno = %d)", regno);
- while (regset->size >= 0)
- {
- char *buf;
- int res;
- buf = xmalloc (regset->size);
- res = lynx_ptrace (regset->get_request, inferior_ptid, (int) buf, 0, 0);
- if (res == 0)
- {
-
- regset->fill_function (regcache, buf);
-
- res = lynx_ptrace (regset->set_request, inferior_ptid, (int) buf,
- 0, 0);
- }
- if (res < 0)
- perror ("ptrace");
- free (buf);
- regset++;
- }
- }
- static int
- lynx_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
- {
-
- int buf;
- const int xfer_size = sizeof (buf);
- CORE_ADDR addr = memaddr & -(CORE_ADDR) xfer_size;
- ptid_t inferior_ptid = thread_to_gdb_id (current_thread);
- while (addr < memaddr + len)
- {
- int skip = 0;
- int truncate = 0;
- errno = 0;
- if (addr < memaddr)
- skip = memaddr - addr;
- if (addr + xfer_size > memaddr + len)
- truncate = addr + xfer_size - memaddr - len;
- buf = lynx_ptrace (PTRACE_PEEKTEXT, inferior_ptid, addr, 0, 0);
- if (errno)
- return errno;
- memcpy (myaddr + (addr - memaddr) + skip, (gdb_byte *) &buf + skip,
- xfer_size - skip - truncate);
- addr += xfer_size;
- }
- return 0;
- }
- static int
- lynx_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
- {
-
- int buf;
- const int xfer_size = sizeof (buf);
- CORE_ADDR addr = memaddr & -(CORE_ADDR) xfer_size;
- ptid_t inferior_ptid = thread_to_gdb_id (current_thread);
- while (addr < memaddr + len)
- {
- int skip = 0;
- int truncate = 0;
- if (addr < memaddr)
- skip = memaddr - addr;
- if (addr + xfer_size > memaddr + len)
- truncate = addr + xfer_size - memaddr - len;
- if (skip > 0 || truncate > 0)
- {
-
- lynx_read_memory (addr, (unsigned char *) &buf, xfer_size);
- if (errno)
- return errno;
- }
- memcpy ((gdb_byte *) &buf + skip, myaddr + (addr - memaddr) + skip,
- xfer_size - skip - truncate);
- errno = 0;
- lynx_ptrace (PTRACE_POKETEXT, inferior_ptid, addr, buf, 0);
- if (errno)
- return errno;
- addr += xfer_size;
- }
- return 0;
- }
- static void
- lynx_request_interrupt (void)
- {
- ptid_t inferior_ptid = thread_to_gdb_id (current_thread);
- kill (lynx_ptid_get_pid (inferior_ptid), SIGINT);
- }
- static struct target_ops lynx_target_ops = {
- lynx_create_inferior,
- lynx_attach,
- lynx_kill,
- lynx_detach,
- lynx_mourn,
- lynx_join,
- lynx_thread_alive,
- lynx_resume,
- lynx_wait,
- lynx_fetch_registers,
- lynx_store_registers,
- NULL,
- NULL,
- lynx_read_memory,
- lynx_write_memory,
- NULL,
- lynx_request_interrupt,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- };
- void
- initialize_low (void)
- {
- set_target_ops (&lynx_target_ops);
- the_low_target.arch_setup ();
- }