gdb/gdbserver/nto-low.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "server.h"
- #include "gdbthread.h"
- #include "nto-low.h"
- #include "hostio.h"
- #include <limits.h>
- #include <fcntl.h>
- #include <spawn.h>
- #include <sys/procfs.h>
- #include <sys/auxv.h>
- #include <sys/iomgr.h>
- #include <sys/neutrino.h>
- extern int using_threads;
- int using_threads = 1;
- const struct target_desc *nto_tdesc;
- static void
- nto_trace (const char *fmt, ...)
- {
- va_list arg_list;
- if (debug_threads == 0)
- return;
- fprintf (stderr, "nto:");
- va_start (arg_list, fmt);
- vfprintf (stderr, fmt, arg_list);
- va_end (arg_list);
- }
- #define TRACE nto_trace
- struct nto_inferior
- {
- char nto_procfs_path[PATH_MAX];
- int ctl_fd;
- pid_t pid;
- int exit_signo;
- };
- static struct nto_inferior nto_inferior;
- static void
- init_nto_inferior (struct nto_inferior *nto_inferior)
- {
- memset (nto_inferior, 0, sizeof (struct nto_inferior));
- nto_inferior->ctl_fd = -1;
- nto_inferior->pid = -1;
- }
- static void
- do_detach (void)
- {
- if (nto_inferior.ctl_fd != -1)
- {
- nto_trace ("Closing fd\n");
- close (nto_inferior.ctl_fd);
- init_nto_inferior (&nto_inferior);
- }
- }
- static int
- nto_set_thread (ptid_t ptid)
- {
- int res = 0;
- TRACE ("%s pid: %d tid: %ld\n", __func__, ptid_get_pid (ptid),
- ptid_get_lwp (ptid));
- if (nto_inferior.ctl_fd != -1
- && !ptid_equal (ptid, null_ptid)
- && !ptid_equal (ptid, minus_one_ptid))
- {
- pthread_t tid = ptid_get_lwp (ptid);
- if (EOK == devctl (nto_inferior.ctl_fd, DCMD_PROC_CURTHREAD, &tid,
- sizeof (tid), 0))
- res = 1;
- else
- TRACE ("%s: Error: failed to set current thread\n", __func__);
- }
- return res;
- }
- static void
- nto_find_new_threads (struct nto_inferior *nto_inferior)
- {
- pthread_t tid;
- TRACE ("%s pid:%d\n", __func__, nto_inferior->pid);
- if (nto_inferior->ctl_fd == -1)
- return;
- for (tid = 1;; ++tid)
- {
- procfs_status status;
- ptid_t ptid;
- int err;
- status.tid = tid;
- err = devctl (nto_inferior->ctl_fd, DCMD_PROC_TIDSTATUS, &status,
- sizeof (status), 0);
- if (err != EOK || status.tid == 0)
- break;
-
- while (tid != status.tid || status.state == STATE_DEAD)
- {
- struct thread_info *ti;
- ptid = ptid_build (nto_inferior->pid, tid, 0);
- ti = find_thread_ptid (ptid);
- if (ti != NULL)
- {
- TRACE ("Removing thread %d\n", tid);
- remove_thread (ti);
- }
- if (tid == status.tid)
- break;
- ++tid;
- }
- if (status.state != STATE_DEAD)
- {
- TRACE ("Adding thread %d\n", tid);
- ptid = ptid_build (nto_inferior->pid, tid, 0);
- if (!find_thread_ptid (ptid))
- add_thread (ptid, NULL);
- }
- }
- }
- static pid_t
- do_attach (pid_t pid)
- {
- procfs_status status;
- struct sigevent event;
- if (nto_inferior.ctl_fd != -1)
- {
- close (nto_inferior.ctl_fd);
- init_nto_inferior (&nto_inferior);
- }
- xsnprintf (nto_inferior.nto_procfs_path, PATH_MAX - 1, "/proc/%d/as", pid);
- nto_inferior.ctl_fd = open (nto_inferior.nto_procfs_path, O_RDWR);
- if (nto_inferior.ctl_fd == -1)
- {
- TRACE ("Failed to open %s\n", nto_inferior.nto_procfs_path);
- init_nto_inferior (&nto_inferior);
- return -1;
- }
- if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, &status, sizeof (status), 0)
- != EOK)
- {
- do_detach ();
- return -1;
- }
- nto_inferior.pid = pid;
-
- event.sigev_notify = SIGEV_SIGNAL_THREAD;
- event.sigev_signo = SIGUSR1;
- event.sigev_code = 0;
- event.sigev_value.sival_ptr = NULL;
- event.sigev_priority = -1;
- devctl (nto_inferior.ctl_fd, DCMD_PROC_EVENT, &event, sizeof (event), 0);
- if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
- 0) == EOK
- && (status.flags & _DEBUG_FLAG_STOPPED))
- {
- ptid_t ptid;
- struct process_info *proc;
- kill (pid, SIGCONT);
- ptid = ptid_build (status.pid, status.tid, 0);
- the_low_target.arch_setup ();
- proc = add_process (status.pid, 1);
- proc->tdesc = nto_tdesc;
- TRACE ("Adding thread: pid=%d tid=%ld\n", status.pid,
- ptid_get_lwp (ptid));
- nto_find_new_threads (&nto_inferior);
- }
- else
- {
- do_detach ();
- return -1;
- }
- return pid;
- }
- static int
- nto_xfer_memory (off_t memaddr, unsigned char *myaddr, int len,
- int dowrite)
- {
- int nbytes = 0;
- if (lseek (nto_inferior.ctl_fd, memaddr, SEEK_SET) == memaddr)
- {
- if (dowrite)
- nbytes = write (nto_inferior.ctl_fd, myaddr, len);
- else
- nbytes = read (nto_inferior.ctl_fd, myaddr, len);
- if (nbytes < 0)
- nbytes = 0;
- }
- if (nbytes == 0)
- {
- int e = errno;
- TRACE ("Error in %s : errno=%d (%s)\n", __func__, e, strerror (e));
- }
- return nbytes;
- }
- static int
- nto_breakpoint (CORE_ADDR addr, int type, int size)
- {
- procfs_break brk;
- brk.type = type;
- brk.addr = addr;
- brk.size = size;
- if (devctl (nto_inferior.ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0)
- != EOK)
- return 1;
- return 0;
- }
- static int
- nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack,
- unsigned char *myaddr,
- unsigned int len)
- {
- int data_ofs = 0;
- int anint;
- unsigned int len_read = 0;
-
- if (nto_xfer_memory (initial_stack, (unsigned char *)&anint,
- sizeof (anint), 0) != sizeof (anint))
- return 0;
-
- data_ofs += (anint + 2) * sizeof (void *);
-
- while (nto_xfer_memory (initial_stack + data_ofs,
- (unsigned char *)&anint, sizeof (anint), 0)
- == sizeof (anint))
- {
- data_ofs += sizeof (anint);
- if (anint == 0)
- break;
- }
- initial_stack += data_ofs;
- memset (myaddr, 0, len);
- while (len_read <= len - sizeof (auxv_t))
- {
- auxv_t *auxv = (auxv_t *)myaddr;
-
- if (nto_xfer_memory (initial_stack, (unsigned char *)auxv,
- sizeof (auxv_t), 0) == sizeof (auxv_t))
- {
- if (auxv->a_type != AT_NULL)
- {
- auxv++;
- len_read += sizeof (auxv_t);
- }
- if (auxv->a_type == AT_PHNUM)
- break;
- initial_stack += sizeof (auxv_t);
- }
- else
- break;
- }
- TRACE ("auxv: len_read: %d\n", len_read);
- return len_read;
- }
- static int
- nto_create_inferior (char *program, char **allargs)
- {
- struct inheritance inherit;
- pid_t pid;
- sigset_t set;
- TRACE ("%s %s\n", __func__, program);
-
- signal (SIGUSR1, signal (SIGUSR1, SIG_IGN));
- sigemptyset (&set);
- sigaddset (&set, SIGUSR1);
- sigprocmask (SIG_UNBLOCK, &set, NULL);
- memset (&inherit, 0, sizeof (inherit));
- inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
- inherit.pgroup = SPAWN_NEWPGROUP;
- pid = spawnp (program, 0, NULL, &inherit, allargs, 0);
- sigprocmask (SIG_BLOCK, &set, NULL);
- if (pid == -1)
- return -1;
- if (do_attach (pid) != pid)
- return -1;
- return pid;
- }
- static int
- nto_attach (unsigned long pid)
- {
- TRACE ("%s %ld\n", __func__, pid);
- if (do_attach (pid) != pid)
- error ("Unable to attach to %ld\n", pid);
- return 0;
- }
- static int
- nto_kill (int pid)
- {
- TRACE ("%s %d\n", __func__, pid);
- kill (pid, SIGKILL);
- do_detach ();
- return 0;
- }
- static int
- nto_detach (int pid)
- {
- TRACE ("%s %d\n", __func__, pid);
- do_detach ();
- return 0;
- }
- static void
- nto_mourn (struct process_info *process)
- {
- remove_process (process);
- }
- static int
- nto_thread_alive (ptid_t ptid)
- {
- int res;
- TRACE ("%s pid:%d tid:%d\n", __func__, ptid_get_pid (ptid),
- ptid_get_lwp (ptid));
- if (SignalKill (0, ptid_get_pid (ptid), ptid_get_lwp (ptid),
- 0, 0, 0) == -1)
- res = 0;
- else
- res = 1;
- TRACE ("%s: %s\n", __func__, res ? "yes" : "no");
- return res;
- }
- static void
- nto_resume (struct thread_resume *resume_info, size_t n)
- {
-
- procfs_status status;
- procfs_run run;
- int err;
- TRACE ("%s\n", __func__);
-
- sigset_t *run_fault = (sigset_t *) (void *) &run.fault;
- nto_set_thread (resume_info->thread);
- run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE;
- if (resume_info->kind == resume_step)
- run.flags |= _DEBUG_RUN_STEP;
- run.flags |= _DEBUG_RUN_ARM;
- sigemptyset (run_fault);
- sigaddset (run_fault, FLTBPT);
- sigaddset (run_fault, FLTTRACE);
- sigaddset (run_fault, FLTILL);
- sigaddset (run_fault, FLTPRIV);
- sigaddset (run_fault, FLTBOUNDS);
- sigaddset (run_fault, FLTIOVF);
- sigaddset (run_fault, FLTIZDIV);
- sigaddset (run_fault, FLTFPE);
- sigaddset (run_fault, FLTPAGE);
- sigaddset (run_fault, FLTSTACK);
- sigaddset (run_fault, FLTACCESS);
- sigemptyset (&run.trace);
- if (resume_info->sig)
- {
- int signal_to_pass;
- devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
- 0);
- signal_to_pass = resume_info->sig;
- if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
- {
- if (signal_to_pass != status.info.si_signo)
- {
- kill (status.pid, signal_to_pass);
- run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
- }
- else
- sigdelset (&run.trace, signal_to_pass);
- }
- }
- else
- run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT;
- sigfillset (&run.trace);
- regcache_invalidate ();
- err = devctl (nto_inferior.ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
- if (err != EOK)
- TRACE ("Error: %d \"%s\"\n", err, strerror (err));
- }
- static ptid_t
- nto_wait (ptid_t ptid,
- struct target_waitstatus *ourstatus, int target_options)
- {
- sigset_t set;
- siginfo_t info;
- procfs_status status;
- const int trace_mask = (_DEBUG_FLAG_TRACE_EXEC | _DEBUG_FLAG_TRACE_RD
- | _DEBUG_FLAG_TRACE_WR | _DEBUG_FLAG_TRACE_MODIFY);
- TRACE ("%s\n", __func__);
- ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
- sigemptyset (&set);
- sigaddset (&set, SIGUSR1);
- devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
- while (!(status.flags & _DEBUG_FLAG_ISTOP))
- {
- sigwaitinfo (&set, &info);
- devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
- 0);
- }
- nto_find_new_threads (&nto_inferior);
- if (status.flags & _DEBUG_FLAG_SSTEP)
- {
- TRACE ("SSTEP\n");
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = GDB_SIGNAL_TRAP;
- }
-
- else if (status.flags & trace_mask)
- {
- TRACE ("STOPPED\n");
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = GDB_SIGNAL_TRAP;
- }
- else if (status.flags & _DEBUG_FLAG_ISTOP)
- {
- TRACE ("ISTOP\n");
- switch (status.why)
- {
- case _DEBUG_WHY_SIGNALLED:
- TRACE (" SIGNALLED\n");
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig =
- gdb_signal_from_host (status.info.si_signo);
- nto_inferior.exit_signo = ourstatus->value.sig;
- break;
- case _DEBUG_WHY_FAULTED:
- TRACE (" FAULTED\n");
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- if (status.info.si_signo == SIGTRAP)
- {
- ourstatus->value.sig = 0;
- nto_inferior.exit_signo = 0;
- }
- else
- {
- ourstatus->value.sig =
- gdb_signal_from_host (status.info.si_signo);
- nto_inferior.exit_signo = ourstatus->value.sig;
- }
- break;
- case _DEBUG_WHY_TERMINATED:
- {
- int waitval = 0;
- TRACE (" TERMINATED\n");
- waitpid (ptid_get_pid (ptid), &waitval, WNOHANG);
- if (nto_inferior.exit_signo)
- {
-
- ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
- ourstatus->value.sig = nto_inferior.exit_signo;
- }
- else
- {
-
- ourstatus->kind = TARGET_WAITKIND_EXITED;
- ourstatus->value.integer = WEXITSTATUS (waitval);
- }
- nto_inferior.exit_signo = 0;
- break;
- }
- case _DEBUG_WHY_REQUESTED:
- TRACE ("REQUESTED\n");
-
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = GDB_SIGNAL_INT;
- nto_inferior.exit_signo = 0;
- break;
- }
- }
- return ptid_build (status.pid, status.tid, 0);
- }
- static void
- nto_fetch_registers (struct regcache *regcache, int regno)
- {
- int regsize;
- procfs_greg greg;
- ptid_t ptid;
- TRACE ("%s (regno=%d)\n", __func__, regno);
- if (regno >= the_low_target.num_regs)
- return;
- if (current_thread == NULL)
- {
- TRACE ("current_thread is NULL\n");
- return;
- }
- ptid = thread_to_gdb_id (current_thread);
- if (!nto_set_thread (ptid))
- return;
- if (devctl (nto_inferior.ctl_fd, DCMD_PROC_GETGREG, &greg, sizeof (greg),
- ®size) == EOK)
- {
- if (regno == -1)
- {
- for (regno = 0; regno != the_low_target.num_regs; ++regno)
- {
- const unsigned int registeroffset
- = the_low_target.register_offset (regno);
- supply_register (regcache, regno,
- ((char *)&greg) + registeroffset);
- }
- }
- else
- {
- const unsigned int registeroffset
- = the_low_target.register_offset (regno);
- if (registeroffset == -1)
- return;
- supply_register (regcache, regno, ((char *)&greg) + registeroffset);
- }
- }
- else
- TRACE ("ERROR reading registers from inferior.\n");
- }
- static void
- nto_store_registers (struct regcache *regcache, int regno)
- {
- procfs_greg greg;
- int err;
- ptid_t ptid;
- TRACE ("%s (regno:%d)\n", __func__, regno);
- if (current_thread == NULL)
- {
- TRACE ("current_thread is NULL\n");
- return;
- }
- ptid = thread_to_gdb_id (current_thread);
- if (!nto_set_thread (ptid))
- return;
- memset (&greg, 0, sizeof (greg));
- for (regno = 0; regno != the_low_target.num_regs; ++regno)
- {
- const unsigned int regoffset
- = the_low_target.register_offset (regno);
- collect_register (regcache, regno, ((char *)&greg) + regoffset);
- }
- err = devctl (nto_inferior.ctl_fd, DCMD_PROC_SETGREG, &greg, sizeof (greg),
- 0);
- if (err != EOK)
- TRACE ("Error: setting registers.\n");
- }
- static int
- nto_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
- {
- TRACE ("%s memaddr:0x%08lx, len:%d\n", __func__, memaddr, len);
- if (nto_xfer_memory (memaddr, myaddr, len, 0) != len)
- {
- TRACE ("Failed to read memory\n");
- return -1;
- }
- return 0;
- }
- static int
- nto_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
- {
- int len_written;
- TRACE ("%s memaddr: 0x%08llx len: %d\n", __func__, memaddr, len);
- if ((len_written = nto_xfer_memory (memaddr, (unsigned char *)myaddr, len,
- 1))
- != len)
- {
- TRACE ("Wanted to write: %d but written: %d\n", len, len_written);
- return -1;
- }
- return 0;
- }
- static void
- nto_request_interrupt (void)
- {
- TRACE ("%s\n", __func__);
- nto_set_thread (ptid_build (nto_inferior.pid, 1, 0));
- if (EOK != devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, NULL, 0, 0))
- TRACE ("Error stopping inferior.\n");
- }
- static int
- nto_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len)
- {
- int err;
- CORE_ADDR initial_stack;
- procfs_info procinfo;
- TRACE ("%s\n", __func__);
- if (offset > 0)
- return 0;
- err = devctl (nto_inferior.ctl_fd, DCMD_PROC_INFO, &procinfo,
- sizeof procinfo, 0);
- if (err != EOK)
- return -1;
- initial_stack = procinfo.initial_stack;
- return nto_read_auxv_from_initial_stack (initial_stack, myaddr, len);
- }
- static int
- nto_supports_z_point_type (char z_type)
- {
- switch (z_type)
- {
- case Z_PACKET_SW_BP:
- case Z_PACKET_HW_BP:
- case Z_PACKET_WRITE_WP:
- case Z_PACKET_READ_WP:
- case Z_PACKET_ACCESS_WP:
- return 1;
- default:
- return 0;
- }
- }
- static int
- nto_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
- int size, struct raw_breakpoint *bp)
- {
- int wtype = _DEBUG_BREAK_HW;
- TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
- switch (type)
- {
- case raw_bkpt_type_sw:
- wtype = _DEBUG_BREAK_EXEC;
- break;
- case raw_bkpt_type_hw:
- wtype |= _DEBUG_BREAK_EXEC;
- break;
- case raw_bkpt_type_write_wp:
- wtype |= _DEBUG_BREAK_RW;
- break;
- case raw_bkpt_type_read_wp:
- wtype |= _DEBUG_BREAK_RD;
- break;
- case raw_bkpt_type_access_wp:
- wtype |= _DEBUG_BREAK_RW;
- break;
- default:
- return 1;
- }
- return nto_breakpoint (addr, wtype, 0);
- }
- static int
- nto_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
- int size, struct raw_breakpoint *bp)
- {
- int wtype = _DEBUG_BREAK_HW;
- TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
- switch (type)
- {
- case raw_bkpt_type_sw:
- wtype = _DEBUG_BREAK_EXEC;
- break;
- case raw_bkpt_type_hw:
- wtype |= _DEBUG_BREAK_EXEC;
- break;
- case raw_bkpt_type_write_wp:
- wtype |= _DEBUG_BREAK_RW;
- break;
- case raw_bkpt_type_read_wp:
- wtype |= _DEBUG_BREAK_RD;
- break;
- case raw_bkpt_type_access_wp:
- wtype |= _DEBUG_BREAK_RW;
- break;
- default:
- return 1;
- }
- return nto_breakpoint (addr, wtype, -1);
- }
- static int
- nto_stopped_by_watchpoint (void)
- {
- int ret = 0;
- TRACE ("%s\n", __func__);
- if (nto_inferior.ctl_fd != -1 && current_thread != NULL)
- {
- ptid_t ptid;
- ptid = thread_to_gdb_id (current_thread);
- if (nto_set_thread (ptid))
- {
- const int watchmask = _DEBUG_FLAG_TRACE_RD | _DEBUG_FLAG_TRACE_WR
- | _DEBUG_FLAG_TRACE_MODIFY;
- procfs_status status;
- int err;
- err = devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
- sizeof (status), 0);
- if (err == EOK && (status.flags & watchmask))
- ret = 1;
- }
- }
- TRACE ("%s: %s\n", __func__, ret ? "yes" : "no");
- return ret;
- }
- static CORE_ADDR
- nto_stopped_data_address (void)
- {
- CORE_ADDR ret = (CORE_ADDR)0;
- TRACE ("%s\n", __func__);
- if (nto_inferior.ctl_fd != -1 && current_thread != NULL)
- {
- ptid_t ptid;
- ptid = thread_to_gdb_id (current_thread);
- if (nto_set_thread (ptid))
- {
- procfs_status status;
- if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
- sizeof (status), 0) == EOK)
- ret = status.ip;
- }
- }
- TRACE ("%s: 0x%08lx\n", __func__, ret);
- return ret;
- }
- static int
- nto_supports_non_stop (void)
- {
- TRACE ("%s\n", __func__);
- return 0;
- }
- static struct target_ops nto_target_ops = {
- nto_create_inferior,
- nto_attach,
- nto_kill,
- nto_detach,
- nto_mourn,
- NULL,
- nto_thread_alive,
- nto_resume,
- nto_wait,
- nto_fetch_registers,
- nto_store_registers,
- NULL,
- NULL,
- nto_read_memory,
- nto_write_memory,
- NULL,
- nto_request_interrupt,
- nto_read_auxv,
- nto_supports_z_point_type,
- nto_insert_point,
- nto_remove_point,
- nto_stopped_by_watchpoint,
- nto_stopped_data_address,
- NULL,
- NULL,
- NULL,
- hostio_last_error_from_errno,
- NULL,
- NULL,
- nto_supports_non_stop,
- NULL,
- NULL
- };
- void
- initialize_low (void)
- {
- sigset_t set;
- TRACE ("%s\n", __func__);
- set_target_ops (&nto_target_ops);
- set_breakpoint_data (the_low_target.breakpoint,
- the_low_target.breakpoint_len);
-
- sigemptyset (&set);
- sigaddset (&set, SIGUSR1);
- sigprocmask (SIG_BLOCK, &set, NULL);
- }