gdb/inf-ttrace.c - gdb
Global variables defined
Data types defined
Functions defined
Source code
- #include "defs.h"
- #ifdef HAVE_TTRACE
- #include "command.h"
- #include "gdbcore.h"
- #include "gdbthread.h"
- #include "inferior.h"
- #include "terminal.h"
- #include "target.h"
- #include <sys/mman.h>
- #include <sys/ttrace.h>
- #include <signal.h>
- #include "inf-child.h"
- #include "inf-ttrace.h"
- #include "common/filestuff.h"
- static int inf_ttrace_num_lwps;
- struct inf_ttrace_page
- {
- CORE_ADDR addr;
- int prot;
- int refcount;
- struct inf_ttrace_page *next;
- struct inf_ttrace_page *prev;
- };
- struct inf_ttrace_page_dict
- {
- struct inf_ttrace_page buckets[128];
- int pagesize;
- int count;
- } inf_ttrace_page_dict;
- struct inf_ttrace_private_thread_info
- {
- int dying;
- };
- static int inf_ttrace_num_lwps_in_syscall;
- static int inf_ttrace_reenable_page_protections;
- static void
- inf_ttrace_enable_syscall_events (pid_t pid)
- {
- ttevent_t tte;
- ttstate_t tts;
- gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
- if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
- (uintptr_t)&tte, sizeof tte, 0) == -1)
- perror_with_name (("ttrace"));
- tte.tte_events |= (TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
- if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
- (uintptr_t)&tte, sizeof tte, 0) == -1)
- perror_with_name (("ttrace"));
- if (ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
- (uintptr_t)&tts, sizeof tts, 0) == -1)
- perror_with_name (("ttrace"));
- if (tts.tts_flags & TTS_INSYSCALL)
- inf_ttrace_num_lwps_in_syscall++;
- FIXME
- }
- static void
- inf_ttrace_disable_syscall_events (pid_t pid)
- {
- ttevent_t tte;
- gdb_assert (inf_ttrace_page_dict.count == 0);
- if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
- (uintptr_t)&tte, sizeof tte, 0) == -1)
- perror_with_name (("ttrace"));
- tte.tte_events &= ~(TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
- if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
- (uintptr_t)&tte, sizeof tte, 0) == -1)
- perror_with_name (("ttrace"));
- inf_ttrace_num_lwps_in_syscall = 0;
- }
- static struct inf_ttrace_page *
- inf_ttrace_get_page (pid_t pid, CORE_ADDR addr)
- {
- const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
- const int pagesize = inf_ttrace_page_dict.pagesize;
- int bucket;
- struct inf_ttrace_page *page;
- bucket = (addr / pagesize) % num_buckets;
- page = &inf_ttrace_page_dict.buckets[bucket];
- while (page)
- {
- if (page->addr == addr)
- break;
- page = page->next;
- }
- return page;
- }
- static struct inf_ttrace_page *
- inf_ttrace_add_page (pid_t pid, CORE_ADDR addr)
- {
- const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
- const int pagesize = inf_ttrace_page_dict.pagesize;
- int bucket;
- struct inf_ttrace_page *page;
- struct inf_ttrace_page *prev = NULL;
- bucket = (addr / pagesize) % num_buckets;
- page = &inf_ttrace_page_dict.buckets[bucket];
- while (page)
- {
- if (page->addr == addr)
- break;
- prev = page;
- page = page->next;
- }
- if (!page)
- {
- int prot;
- if (ttrace (TT_PROC_GET_MPROTECT, pid, 0,
- addr, 0, (uintptr_t)&prot) == -1)
- perror_with_name (("ttrace"));
- page = XNEW (struct inf_ttrace_page);
- page->addr = addr;
- page->prot = prot;
- page->refcount = 0;
- page->next = NULL;
- page->prev = prev;
- prev->next = page;
- inf_ttrace_page_dict.count++;
- if (inf_ttrace_page_dict.count == 1)
- inf_ttrace_enable_syscall_events (pid);
- if (inf_ttrace_num_lwps_in_syscall == 0)
- {
- if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
- addr, pagesize, prot & ~PROT_WRITE) == -1)
- perror_with_name (("ttrace"));
- }
- }
- return page;
- }
- static void
- inf_ttrace_insert_page (pid_t pid, CORE_ADDR addr)
- {
- struct inf_ttrace_page *page;
- page = inf_ttrace_get_page (pid, addr);
- if (!page)
- page = inf_ttrace_add_page (pid, addr);
- page->refcount++;
- }
- static void
- inf_ttrace_remove_page (pid_t pid, CORE_ADDR addr)
- {
- const int pagesize = inf_ttrace_page_dict.pagesize;
- struct inf_ttrace_page *page;
- page = inf_ttrace_get_page (pid, addr);
- page->refcount--;
- gdb_assert (page->refcount >= 0);
- if (page->refcount == 0)
- {
- if (inf_ttrace_num_lwps_in_syscall == 0)
- {
- if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
- addr, pagesize, page->prot) == -1)
- perror_with_name (("ttrace"));
- }
- inf_ttrace_page_dict.count--;
- if (inf_ttrace_page_dict.count == 0)
- inf_ttrace_disable_syscall_events (pid);
- page->prev->next = page->next;
- if (page->next)
- page->next->prev = page->prev;
- xfree (page);
- }
- }
- static void
- inf_ttrace_mask_page_protections (pid_t pid, int prot)
- {
- const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
- const int pagesize = inf_ttrace_page_dict.pagesize;
- int bucket;
- for (bucket = 0; bucket < num_buckets; bucket++)
- {
- struct inf_ttrace_page *page;
- page = inf_ttrace_page_dict.buckets[bucket].next;
- while (page)
- {
- if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
- page->addr, pagesize, page->prot & ~prot) == -1)
- perror_with_name (("ttrace"));
- page = page->next;
- }
- }
- }
- static void
- inf_ttrace_enable_page_protections (pid_t pid)
- {
- inf_ttrace_mask_page_protections (pid, PROT_WRITE);
- }
- static void
- inf_ttrace_disable_page_protections (pid_t pid)
- {
- inf_ttrace_mask_page_protections (pid, 0);
- }
- static int
- inf_ttrace_insert_watchpoint (struct target_ops *self,
- CORE_ADDR addr, int len, int type,
- struct expression *cond)
- {
- const int pagesize = inf_ttrace_page_dict.pagesize;
- pid_t pid = ptid_get_pid (inferior_ptid);
- CORE_ADDR page_addr;
- int num_pages;
- int page;
- gdb_assert (type == hw_write);
- page_addr = (addr / pagesize) * pagesize;
- num_pages = (len + pagesize - 1) / pagesize;
- for (page = 0; page < num_pages; page++, page_addr += pagesize)
- inf_ttrace_insert_page (pid, page_addr);
- return 1;
- }
- static int
- inf_ttrace_remove_watchpoint (struct target_ops *self,
- CORE_ADDR addr, int len, int type,
- struct expression *cond)
- {
- const int pagesize = inf_ttrace_page_dict.pagesize;
- pid_t pid = ptid_get_pid (inferior_ptid);
- CORE_ADDR page_addr;
- int num_pages;
- int page;
- gdb_assert (type == hw_write);
- page_addr = (addr / pagesize) * pagesize;
- num_pages = (len + pagesize - 1) / pagesize;
- for (page = 0; page < num_pages; page++, page_addr += pagesize)
- inf_ttrace_remove_page (pid, page_addr);
- return 1;
- }
- static int
- inf_ttrace_can_use_hw_breakpoint (struct target_ops *self,
- int type, int len, int ot)
- {
- return (type == bp_hardware_watchpoint);
- }
- static int
- inf_ttrace_region_ok_for_hw_watchpoint (struct target_ops *self,
- CORE_ADDR addr, int len)
- {
- return 1;
- }
- static int
- inf_ttrace_stopped_by_watchpoint (struct target_ops *ops)
- {
- pid_t pid = ptid_get_pid (inferior_ptid);
- lwpid_t lwpid = ptid_get_lwp (inferior_ptid);
- ttstate_t tts;
- if (inf_ttrace_page_dict.count > 0)
- {
- if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
- (uintptr_t)&tts, sizeof tts, 0) == -1)
- perror_with_name (("ttrace"));
- if (tts.tts_event == TTEVT_SIGNAL
- && tts.tts_u.tts_signal.tts_signo == SIGBUS)
- {
- const int pagesize = inf_ttrace_page_dict.pagesize;
- void *addr = tts.tts_u.tts_signal.tts_siginfo.si_addr;
- CORE_ADDR page_addr = ((uintptr_t)addr / pagesize) * pagesize;
- if (inf_ttrace_get_page (pid, page_addr))
- return 1;
- }
- }
- return 0;
- }
- static int
- inf_ttrace_follow_fork (struct target_ops *ops, int follow_child,
- int detach_fork)
- {
- struct thread_info *tp = inferior_thread ();
- gdb_assert (tp->pending_follow.kind == TARGET_WAITKIND_FORKED
- || tp->pending_follow.kind == TARGET_WAITKIND_VFORKED);
- if (follow_child)
- {
- struct thread_info *ti;
-
- inf_ttrace_num_lwps = 1;
- inf_ttrace_num_lwps_in_syscall = 0;
- ti = inferior_thread ();
- ti->private =
- xmalloc (sizeof (struct inf_ttrace_private_thread_info));
- memset (ti->private, 0,
- sizeof (struct inf_ttrace_private_thread_info));
- }
- else
- {
- pid_t child_pid;
-
- child_pid = ptid_get_pid (tp->pending_follow.value.related_pid);
- if (ttrace (TT_PROC_DETACH, child_pid, 0, 0, 0, 0) == -1)
- perror_with_name (("ttrace"));
- }
- return 0;
- }
- static int inf_ttrace_pfd1[2];
- static int inf_ttrace_pfd2[2];
- static void
- do_cleanup_pfds (void *dummy)
- {
- close (inf_ttrace_pfd1[0]);
- close (inf_ttrace_pfd1[1]);
- close (inf_ttrace_pfd2[0]);
- close (inf_ttrace_pfd2[1]);
- unmark_fd_no_cloexec (inf_ttrace_pfd1[0]);
- unmark_fd_no_cloexec (inf_ttrace_pfd1[1]);
- unmark_fd_no_cloexec (inf_ttrace_pfd2[0]);
- unmark_fd_no_cloexec (inf_ttrace_pfd2[1]);
- }
- static void
- inf_ttrace_prepare (void)
- {
- if (pipe (inf_ttrace_pfd1) == -1)
- perror_with_name (("pipe"));
- if (pipe (inf_ttrace_pfd2) == -1)
- {
- close (inf_ttrace_pfd1[0]);
- close (inf_ttrace_pfd2[0]);
- perror_with_name (("pipe"));
- }
- mark_fd_no_cloexec (inf_ttrace_pfd1[0]);
- mark_fd_no_cloexec (inf_ttrace_pfd1[1]);
- mark_fd_no_cloexec (inf_ttrace_pfd2[0]);
- mark_fd_no_cloexec (inf_ttrace_pfd2[1]);
- }
- static void
- inf_ttrace_me (void)
- {
- struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
- char c;
-
- if (ttrace (TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1)
- perror_with_name (("ttrace"));
-
- if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c)
- perror_with_name (("write"));
-
- if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c)
- perror_with_name (("read"));
- do_cleanups (old_chain);
- }
- static void
- inf_ttrace_him (struct target_ops *ops, int pid)
- {
- struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
- ttevent_t tte;
- char c;
-
- if (read (inf_ttrace_pfd1[0], &c, sizeof c) != sizeof c)
- perror_with_name (("read"));
-
- memset (&tte, 0, sizeof (tte));
- tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
- tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
- #ifdef TTEVT_BPT_SSTEP
- tte.tte_events |= TTEVT_BPT_SSTEP;
- #endif
- tte.tte_opts |= TTEO_PROC_INHERIT;
- if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
- (uintptr_t)&tte, sizeof tte, 0) == -1)
- perror_with_name (("ttrace"));
-
- if (write (inf_ttrace_pfd2[1], &c, sizeof c) != sizeof c)
- perror_with_name (("write"));
- do_cleanups (old_chain);
- if (!target_is_pushed (ops))
- push_target (ops);
- startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
-
- target_post_startup_inferior (pid_to_ptid (pid));
- }
- static void
- inf_ttrace_create_inferior (struct target_ops *ops, char *exec_file,
- char *allargs, char **env, int from_tty)
- {
- int pid;
- gdb_assert (inf_ttrace_num_lwps == 0);
- gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
- gdb_assert (inf_ttrace_page_dict.count == 0);
- gdb_assert (inf_ttrace_reenable_page_protections == 0);
- pid = fork_inferior (exec_file, allargs, env, inf_ttrace_me, NULL,
- inf_ttrace_prepare, NULL, NULL);
- inf_ttrace_him (ops, pid);
- }
- static void
- inf_ttrace_mourn_inferior (struct target_ops *ops)
- {
- const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
- int bucket;
- inf_ttrace_num_lwps = 0;
- inf_ttrace_num_lwps_in_syscall = 0;
- for (bucket = 0; bucket < num_buckets; bucket++)
- {
- struct inf_ttrace_page *page;
- struct inf_ttrace_page *next;
- page = inf_ttrace_page_dict.buckets[bucket].next;
- while (page)
- {
- next = page->next;
- xfree (page);
- page = next;
- }
- }
- inf_ttrace_page_dict.count = 0;
- inf_child_mourn_inferior (ops);
- }
- static void
- inf_ttrace_create_threads_after_attach (int pid)
- {
- int status;
- ptid_t ptid;
- ttstate_t tts;
- struct thread_info *ti;
- status = ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
- (uintptr_t) &tts, sizeof (ttstate_t), 0);
- if (status < 0)
- perror_with_name (_("TT_PROC_GET_FIRST_LWP_STATE ttrace call failed"));
- gdb_assert (tts.tts_pid == pid);
-
- ptid = ptid_build (pid, tts.tts_lwpid, 0);
- ti = add_thread (ptid);
- ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info));
- inf_ttrace_num_lwps++;
-
- inferior_ptid = ptid;
-
- for (;;)
- {
- ptid_t ptid;
- status = ttrace (TT_PROC_GET_NEXT_LWP_STATE, pid, 0,
- (uintptr_t) &tts, sizeof (ttstate_t), 0);
- if (status < 0)
- perror_with_name (_("TT_PROC_GET_NEXT_LWP_STATE ttrace call failed"));
- if (status == 0)
- break;
- ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
- ti = add_thread (ptid);
- ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info));
- inf_ttrace_num_lwps++;
- }
- }
- static void
- inf_ttrace_attach (struct target_ops *ops, const char *args, int from_tty)
- {
- char *exec_file;
- pid_t pid;
- ttevent_t tte;
- struct inferior *inf;
- pid = parse_pid_to_attach (args);
- if (pid == getpid ())
- error (_("I refuse to debug myself!"));
- if (from_tty)
- {
- exec_file = get_exec_file (0);
- if (exec_file)
- printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
- target_pid_to_str (pid_to_ptid (pid)));
- else
- printf_unfiltered (_("Attaching to %s\n"),
- target_pid_to_str (pid_to_ptid (pid)));
- gdb_flush (gdb_stdout);
- }
- gdb_assert (inf_ttrace_num_lwps == 0);
- gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
- if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1)
- perror_with_name (("ttrace"));
- inf = current_inferior ();
- inferior_appeared (inf, pid);
- inf->attach_flag = 1;
-
- memset (&tte, 0, sizeof (tte));
- tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
- tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
- #ifdef TTEVT_BPT_SSTEP
- tte.tte_events |= TTEVT_BPT_SSTEP;
- #endif
- tte.tte_opts |= TTEO_PROC_INHERIT;
- if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
- (uintptr_t)&tte, sizeof tte, 0) == -1)
- perror_with_name (("ttrace"));
- if (!target_is_pushed (ops))
- push_target (ops);
- inf_ttrace_create_threads_after_attach (pid);
- }
- static void
- inf_ttrace_detach (struct target_ops *ops, const char *args, int from_tty)
- {
- pid_t pid = ptid_get_pid (inferior_ptid);
- int sig = 0;
- if (from_tty)
- {
- char *exec_file = get_exec_file (0);
- if (exec_file == 0)
- exec_file = "";
- printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
- target_pid_to_str (pid_to_ptid (pid)));
- gdb_flush (gdb_stdout);
- }
- if (args)
- sig = atoi (args);
-
- if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
- perror_with_name (("ttrace"));
- inf_ttrace_num_lwps = 0;
- inf_ttrace_num_lwps_in_syscall = 0;
- inferior_ptid = null_ptid;
- detach_inferior (pid);
- inf_child_maybe_unpush_target (ops);
- }
- static void
- inf_ttrace_kill (struct target_ops *ops)
- {
- pid_t pid = ptid_get_pid (inferior_ptid);
- if (pid == 0)
- return;
- if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1)
- perror_with_name (("ttrace"));
-
- target_mourn_inferior ();
- }
- static int
- inf_ttrace_delete_dead_threads_callback (struct thread_info *info, void *arg)
- {
- lwpid_t lwpid;
- struct inf_ttrace_private_thread_info *p;
- if (is_exited (info->ptid))
- return 0;
- lwpid = ptid_get_lwp (info->ptid);
- p = (struct inf_ttrace_private_thread_info *) info->private;
-
- if (p->dying && (kill (lwpid, 0) == -1))
-
- delete_thread (info->ptid);
- return 0;
- }
- static void
- inf_ttrace_resume_lwp (struct thread_info *info, ttreq_t request, int sig)
- {
- pid_t pid = ptid_get_pid (info->ptid);
- lwpid_t lwpid = ptid_get_lwp (info->ptid);
- if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1)
- {
- struct inf_ttrace_private_thread_info *p
- = (struct inf_ttrace_private_thread_info *) info->private;
- if (p->dying && errno == EPROTO)
-
- delete_thread (info->ptid);
- else
-
- perror_with_name (("ttrace"));
- }
- }
- static int
- inf_ttrace_resume_callback (struct thread_info *info, void *arg)
- {
- if (!ptid_equal (info->ptid, inferior_ptid) && !is_exited (info->ptid))
- inf_ttrace_resume_lwp (info, TT_LWP_CONTINUE, 0);
- return 0;
- }
- static void
- inf_ttrace_resume (struct target_ops *ops,
- ptid_t ptid, int step, enum gdb_signal signal)
- {
- int resume_all;
- ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE;
- int sig = gdb_signal_to_host (signal);
- struct thread_info *info;
-
- resume_all = (ptid_equal (ptid, minus_one_ptid));
-
- if (resume_all)
- ptid = inferior_ptid;
- info = find_thread_ptid (ptid);
- inf_ttrace_resume_lwp (info, request, sig);
- if (resume_all)
-
- iterate_over_threads (inf_ttrace_resume_callback, NULL);
- }
- static ptid_t
- inf_ttrace_wait (struct target_ops *ops,
- ptid_t ptid, struct target_waitstatus *ourstatus, int options)
- {
- pid_t pid = ptid_get_pid (ptid);
- lwpid_t lwpid = ptid_get_lwp (ptid);
- ttstate_t tts;
- struct thread_info *ti;
- ptid_t related_ptid;
-
- ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
- if (pid == -1)
- pid = lwpid = 0;
- gdb_assert (pid != 0 || lwpid == 0);
- do
- {
- set_sigint_trap ();
- if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
- perror_with_name (("ttrace_wait"));
- clear_sigint_trap ();
- }
- while (tts.tts_event == TTEVT_NONE);
-
- if (inf_ttrace_reenable_page_protections)
- {
- gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
- inf_ttrace_enable_page_protections (tts.tts_pid);
- inf_ttrace_reenable_page_protections = 0;
- }
- ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
- if (inf_ttrace_num_lwps == 0)
- {
- struct thread_info *ti;
- inf_ttrace_num_lwps = 1;
-
- gdb_assert (ptid_get_lwp (inferior_ptid) == 0);
-
- ti = find_thread_ptid (inferior_ptid);
- gdb_assert (ti != NULL && ti->private == NULL);
- ti->private =
- xmalloc (sizeof (struct inf_ttrace_private_thread_info));
- memset (ti->private, 0,
- sizeof (struct inf_ttrace_private_thread_info));
-
- thread_change_ptid (inferior_ptid, ptid);
- }
- switch (tts.tts_event)
- {
- #ifdef TTEVT_BPT_SSTEP
- case TTEVT_BPT_SSTEP:
-
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = GDB_SIGNAL_TRAP;
- break;
- #endif
- case TTEVT_EXEC:
- ourstatus->kind = TARGET_WAITKIND_EXECD;
- ourstatus->value.execd_pathname =
- xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1);
- if (ttrace (TT_PROC_GET_PATHNAME, tts.tts_pid, 0,
- (uintptr_t)ourstatus->value.execd_pathname,
- tts.tts_u.tts_exec.tts_pathlen, 0) == -1)
- perror_with_name (("ttrace"));
- ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0;
-
- mark_breakpoints_out ();
- break;
- case TTEVT_EXIT:
- store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
- inf_ttrace_num_lwps = 0;
- break;
- case TTEVT_FORK:
- related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
- tts.tts_u.tts_fork.tts_flwpid, 0);
- ourstatus->kind = TARGET_WAITKIND_FORKED;
- ourstatus->value.related_pid = related_ptid;
-
- if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid,
- tts.tts_u.tts_fork.tts_flwpid,
- TTRACE_WAITOK, &tts, sizeof tts) == -1)
- perror_with_name (("ttrace_wait"));
- gdb_assert (tts.tts_event == TTEVT_FORK);
- if (tts.tts_u.tts_fork.tts_isparent)
- {
- related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
- tts.tts_u.tts_fork.tts_flwpid, 0);
- ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
- ourstatus->value.related_pid = related_ptid;
- }
- break;
- case TTEVT_VFORK:
- if (tts.tts_u.tts_fork.tts_isparent)
- ourstatus->kind = TARGET_WAITKIND_VFORK_DONE;
- else
- {
- related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
- tts.tts_u.tts_fork.tts_flwpid, 0);
- ourstatus->kind = TARGET_WAITKIND_VFORKED;
- ourstatus->value.related_pid = related_ptid;
- }
- break;
- case TTEVT_LWP_CREATE:
- lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
- ptid = ptid_build (tts.tts_pid, lwpid, 0);
- ti = add_thread (ptid);
- ti->private =
- xmalloc (sizeof (struct inf_ttrace_private_thread_info));
- memset (ti->private, 0,
- sizeof (struct inf_ttrace_private_thread_info));
- inf_ttrace_num_lwps++;
- ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
-
- ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
- ptid_get_lwp (ptid), TT_NOPC, 0, 0);
-
- ourstatus->kind = TARGET_WAITKIND_IGNORE;
- return ptid;
- case TTEVT_LWP_EXIT:
- if (print_thread_events)
- printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid));
- ti = find_thread_ptid (ptid);
- gdb_assert (ti != NULL);
- ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
- inf_ttrace_num_lwps--;
-
- ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
- ptid_get_lwp (ptid), TT_NOPC, 0, 0);
-
- ourstatus->kind = TARGET_WAITKIND_IGNORE;
- return ptid;
- case TTEVT_LWP_TERMINATE:
- lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
- ptid = ptid_build (tts.tts_pid, lwpid, 0);
- if (print_thread_events)
- printf_unfiltered(_("[%s has been terminated]\n"),
- target_pid_to_str (ptid));
- ti = find_thread_ptid (ptid);
- gdb_assert (ti != NULL);
- ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
- inf_ttrace_num_lwps--;
-
- ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
- ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
- ptid_get_lwp (ptid), TT_NOPC, 0, 0);
-
- ourstatus->kind = TARGET_WAITKIND_IGNORE;
- return ptid;
- case TTEVT_SIGNAL:
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig =
- gdb_signal_from_host (tts.tts_u.tts_signal.tts_signo);
- break;
- case TTEVT_SYSCALL_ENTRY:
- gdb_assert (inf_ttrace_reenable_page_protections == 0);
- inf_ttrace_num_lwps_in_syscall++;
- if (inf_ttrace_num_lwps_in_syscall == 1)
- {
-
- inf_ttrace_disable_page_protections (tts.tts_pid);
- }
- ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
- ourstatus->value.syscall_number = tts.tts_scno;
- break;
- case TTEVT_SYSCALL_RETURN:
- if (inf_ttrace_num_lwps_in_syscall > 0)
- {
-
- inf_ttrace_reenable_page_protections =
- (inf_ttrace_num_lwps_in_syscall == 1);
- inf_ttrace_num_lwps_in_syscall--;
- }
- ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
- ourstatus->value.syscall_number = tts.tts_scno;
- break;
- default:
- gdb_assert (!"Unexpected ttrace event");
- break;
- }
-
- if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
- perror_with_name (("ttrace"));
-
- iterate_over_threads (inf_ttrace_delete_dead_threads_callback, NULL);
- return ptid;
- }
- static LONGEST
- inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len,
- void *readbuf, const void *writebuf)
- {
- pid_t pid = ptid_get_pid (inferior_ptid);
-
- if (readbuf
- && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1
- && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1)
- return 0;
- if (writebuf
- && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1
- && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1)
- return 0;
- return len;
- }
- static enum target_xfer_status
- inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
- {
- switch (object)
- {
- case TARGET_OBJECT_MEMORY:
- {
- LONGEST val = inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
- if (val == 0)
- return TARGET_XFER_EOF;
- else
- {
- *xfered_len = (ULONGEST) val;
- return TARGET_XFER_OK;
- }
- }
- case TARGET_OBJECT_UNWIND_TABLE:
- return TARGET_XFER_E_IO;
- case TARGET_OBJECT_AUXV:
- return TARGET_XFER_E_IO;
- case TARGET_OBJECT_WCOOKIE:
- return TARGET_XFER_E_IO;
- default:
- return TARGET_XFER_E_IO;
- }
- }
- static void
- inf_ttrace_files_info (struct target_ops *ignore)
- {
- struct inferior *inf = current_inferior ();
- printf_filtered (_("\tUsing the running image of %s %s.\n"),
- inf->attach_flag ? "attached" : "child",
- target_pid_to_str (inferior_ptid));
- }
- static int
- inf_ttrace_thread_alive (struct target_ops *ops, ptid_t ptid)
- {
- return 1;
- }
- static char *
- inf_ttrace_extra_thread_info (struct target_ops *self,
- struct thread_info *info)
- {
- struct inf_ttrace_private_thread_info* private =
- (struct inf_ttrace_private_thread_info *) info->private;
- if (private != NULL && private->dying)
- return "Exiting";
- return NULL;
- }
- static char *
- inf_ttrace_pid_to_str (struct target_ops *ops, ptid_t ptid)
- {
- pid_t pid = ptid_get_pid (ptid);
- lwpid_t lwpid = ptid_get_lwp (ptid);
- static char buf[128];
- if (lwpid == 0)
- xsnprintf (buf, sizeof buf, "process %ld",
- (long) pid);
- else
- xsnprintf (buf, sizeof buf, "process %ld, lwp %ld",
- (long) pid, (long) lwpid);
- return buf;
- }
- static ptid_t
- inf_ttrace_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
- {
- return ptid_build (ptid_get_pid (inferior_ptid), lwp, 0);
- }
- struct target_ops *
- inf_ttrace_target (void)
- {
- struct target_ops *t = inf_child_target ();
- t->to_attach = inf_ttrace_attach;
- t->to_detach = inf_ttrace_detach;
- t->to_resume = inf_ttrace_resume;
- t->to_wait = inf_ttrace_wait;
- t->to_files_info = inf_ttrace_files_info;
- t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
- t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
- t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
- t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
- t->to_region_ok_for_hw_watchpoint =
- inf_ttrace_region_ok_for_hw_watchpoint;
- t->to_kill = inf_ttrace_kill;
- t->to_create_inferior = inf_ttrace_create_inferior;
- t->to_follow_fork = inf_ttrace_follow_fork;
- t->to_mourn_inferior = inf_ttrace_mourn_inferior;
- t->to_thread_alive = inf_ttrace_thread_alive;
- t->to_extra_thread_info = inf_ttrace_extra_thread_info;
- t->to_pid_to_str = inf_ttrace_pid_to_str;
- t->to_xfer_partial = inf_ttrace_xfer_partial;
- t->to_get_ada_task_ptid = inf_ttrace_get_ada_task_ptid;
- return t;
- }
- #endif
- void _initialize_inf_ttrace (void);
- void
- _initialize_inf_ttrace (void)
- {
- #ifdef HAVE_TTRACE
- inf_ttrace_page_dict.pagesize = getpagesize();
- #endif
- }