* inf-ttrace.c: Include <sys/mman.h>.
(struct inf_ttrace_page): New. (struct inf_ttrace_page_dict): New. (inf_ttrace_num_threads_in_syscall) (inf_ttrace_reenable_page_protections): New variables. (inf_ttrace_enable_syscall_events) (inf_ttrace_disable_syscall_events, inf_ttrace_get_page) (inf_ttrace_remove_page, inf_ttrace_mask_page_protections) (inf_ttrace_enable_page_protections) (inf_ttrace_disable_page_protections) (inf_ttrace_insert_watchpoint, inf_ttrace_remove_watchpoint) (inf_ttrace_can_use_hw_breakpoint) (inf_ttrace_region_size_ok_for_hw_watchpoint) (inf_ttrace_stopped_by_watchpoint): New functions. (inf_ttrace_him): Remove unsused varaible `tts'. (inf_ttrace_create_inferior): Add assertionts. (inf_ttrace_mourn_inferior): Clear page dictionary. (inf_ttrace_attach): Set initial event mask. (inf_ttrace_detach): Reset number of threads in system call. (inf_ttrace_wait): Deal with system call events. (inf_ttrace_target): Initialize "hardware" watchpoint-related parts of the target vector. (_initialize_inf_ttrace): New prototype and function.
This commit is contained in:
parent
697afb65fc
commit
932936f0df
2 changed files with 458 additions and 2 deletions
|
@ -1,5 +1,30 @@
|
||||||
2004-12-03 Mark Kettenis <kettenis@gnu.org>
|
2004-12-03 Mark Kettenis <kettenis@gnu.org>
|
||||||
|
|
||||||
|
* inf-ttrace.c: Include <sys/mman.h>.
|
||||||
|
(struct inf_ttrace_page): New.
|
||||||
|
(struct inf_ttrace_page_dict): New.
|
||||||
|
(inf_ttrace_num_threads_in_syscall)
|
||||||
|
(inf_ttrace_reenable_page_protections): New variables.
|
||||||
|
(inf_ttrace_enable_syscall_events)
|
||||||
|
(inf_ttrace_disable_syscall_events, inf_ttrace_get_page)
|
||||||
|
(inf_ttrace_add_page, inf_ttrace_insert_page)
|
||||||
|
(inf_ttrace_remove_page, inf_ttrace_mask_page_protections)
|
||||||
|
(inf_ttrace_enable_page_protections)
|
||||||
|
(inf_ttrace_disable_page_protections)
|
||||||
|
(inf_ttrace_insert_watchpoint, inf_ttrace_remove_watchpoint)
|
||||||
|
(inf_ttrace_can_use_hw_breakpoint)
|
||||||
|
(inf_ttrace_region_size_ok_for_hw_watchpoint)
|
||||||
|
(inf_ttrace_stopped_by_watchpoint): New functions.
|
||||||
|
(inf_ttrace_him): Remove unsused varaible `tts'.
|
||||||
|
(inf_ttrace_create_inferior): Add assertionts.
|
||||||
|
(inf_ttrace_mourn_inferior): Clear page dictionary.
|
||||||
|
(inf_ttrace_attach): Set initial event mask.
|
||||||
|
(inf_ttrace_detach): Reset number of threads in system call.
|
||||||
|
(inf_ttrace_wait): Deal with system call events.
|
||||||
|
(inf_ttrace_target): Initialize "hardware" watchpoint-related
|
||||||
|
parts of the target vector.
|
||||||
|
(_initialize_inf_ttrace): New prototype and function.
|
||||||
|
|
||||||
* hppa-hpux-tdep.c (hppa_hpux_push_dummy_code): Use ULONGEST as
|
* hppa-hpux-tdep.c (hppa_hpux_push_dummy_code): Use ULONGEST as
|
||||||
type of `gp' variable.
|
type of `gp' variable.
|
||||||
|
|
||||||
|
|
435
gdb/inf-ttrace.c
435
gdb/inf-ttrace.c
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include "gdb_assert.h"
|
#include "gdb_assert.h"
|
||||||
#include "gdb_string.h"
|
#include "gdb_string.h"
|
||||||
|
#include <sys/mman.h>
|
||||||
#include <sys/ttrace.h>
|
#include <sys/ttrace.h>
|
||||||
|
|
||||||
#include "inf-child.h"
|
#include "inf-child.h"
|
||||||
|
@ -40,6 +41,347 @@
|
||||||
|
|
||||||
/* HACK: Save the ttrace ops returned by inf_ttrace_target. */
|
/* HACK: Save the ttrace ops returned by inf_ttrace_target. */
|
||||||
static struct target_ops *ttrace_ops_hack;
|
static struct target_ops *ttrace_ops_hack;
|
||||||
|
|
||||||
|
|
||||||
|
/* On HP-UX versions that have the ttrace(2) system call, we can
|
||||||
|
implement "hardware" watchpoints by fiddling with the protection of
|
||||||
|
pages in the address space that contain the variable being watched.
|
||||||
|
In order to implement this, we keep a dictionary of pages for which
|
||||||
|
we have changed the protection. */
|
||||||
|
|
||||||
|
struct inf_ttrace_page
|
||||||
|
{
|
||||||
|
CORE_ADDR addr; /* Page address. */
|
||||||
|
int prot; /* Protection. */
|
||||||
|
int refcount; /* Reference count. */
|
||||||
|
struct inf_ttrace_page *next;
|
||||||
|
struct inf_ttrace_page *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct inf_ttrace_page_dict
|
||||||
|
{
|
||||||
|
struct inf_ttrace_page buckets[128];
|
||||||
|
int pagesize; /* Page size. */
|
||||||
|
int count; /* Number of pages in this dictionary. */
|
||||||
|
} inf_ttrace_page_dict;
|
||||||
|
|
||||||
|
/* Number of threads that are currently in a system call. */
|
||||||
|
static int inf_ttrace_num_threads_in_syscall;
|
||||||
|
|
||||||
|
/* Flag to indicate whether we should re-enable page protections after
|
||||||
|
the next wait. */
|
||||||
|
static int inf_ttrace_reenable_page_protections;
|
||||||
|
|
||||||
|
/* Enable system call events for process PID. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
inf_ttrace_enable_syscall_events (pid_t pid)
|
||||||
|
{
|
||||||
|
ttevent_t tte;
|
||||||
|
ttstate_t tts;
|
||||||
|
|
||||||
|
gdb_assert (inf_ttrace_num_threads_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_threads_in_syscall++;
|
||||||
|
|
||||||
|
/* FIXME: Handle multiple threads. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable system call events for process PID. */
|
||||||
|
|
||||||
|
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_threads_in_syscall = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get information about the page at address ADDR for process PID from
|
||||||
|
the dictionary. */
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the page at address ADDR for process PID to the dictionary. */
|
||||||
|
|
||||||
|
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 = XMALLOC (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_threads_in_syscall == 0)
|
||||||
|
{
|
||||||
|
if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
|
||||||
|
addr, pagesize, prot & ~PROT_WRITE) == -1)
|
||||||
|
perror_with_name ("ttrace");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert the page at address ADDR of process PID to the dictionary. */
|
||||||
|
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the page at address ADDR of process PID from the dictionary. */
|
||||||
|
|
||||||
|
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_threads_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mask the bits in PROT from the page protections that are currently
|
||||||
|
in the dictionary for process PID. */
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write-protect the pages in the dictionary for process PID. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
inf_ttrace_enable_page_protections (pid_t pid)
|
||||||
|
{
|
||||||
|
inf_ttrace_mask_page_protections (pid, PROT_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore the protection of the pages in the dictionary for process
|
||||||
|
PID. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
inf_ttrace_disable_page_protections (pid_t pid)
|
||||||
|
{
|
||||||
|
inf_ttrace_mask_page_protections (pid, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert a "hardware" watchpoint for LEN bytes at address ADDR of
|
||||||
|
type TYPE. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
inf_ttrace_insert_watchpoint (CORE_ADDR addr, int len, int type)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove a "hardware" watchpoint for LEN bytes at address ADDR of
|
||||||
|
type TYPE. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
inf_ttrace_remove_watchpoint (CORE_ADDR addr, int len, int type)
|
||||||
|
{
|
||||||
|
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 (int type, int len, int ot)
|
||||||
|
{
|
||||||
|
return (type == bp_hardware_watchpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
inf_ttrace_region_size_ok_for_hw_watchpoint (int len)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return non-zero if the current inferior was (potentially) stopped
|
||||||
|
by hitting a "hardware" watchpoint. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
inf_ttrace_stopped_by_watchpoint (void)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* File descriptors for pipes used as semaphores during initial
|
/* File descriptors for pipes used as semaphores during initial
|
||||||
startup of an inferior. */
|
startup of an inferior. */
|
||||||
|
@ -99,7 +441,6 @@ inf_ttrace_him (int pid)
|
||||||
{
|
{
|
||||||
struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
|
struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
|
||||||
ttevent_t tte;
|
ttevent_t tte;
|
||||||
ttstate_t tts;
|
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
/* Wait until our child is ready to be traced. */
|
/* Wait until our child is ready to be traced. */
|
||||||
|
@ -143,6 +484,10 @@ static void
|
||||||
inf_ttrace_create_inferior (char *exec_file, char *allargs, char **env,
|
inf_ttrace_create_inferior (char *exec_file, char *allargs, char **env,
|
||||||
int from_tty)
|
int from_tty)
|
||||||
{
|
{
|
||||||
|
gdb_assert (inf_ttrace_page_dict.count == 0);
|
||||||
|
gdb_assert (inf_ttrace_num_threads_in_syscall == 0);
|
||||||
|
gdb_assert (inf_ttrace_reenable_page_protections == 0);
|
||||||
|
|
||||||
fork_inferior (exec_file, allargs, env, inf_ttrace_me, inf_ttrace_him,
|
fork_inferior (exec_file, allargs, env, inf_ttrace_me, inf_ttrace_him,
|
||||||
inf_ttrace_prepare, NULL);
|
inf_ttrace_prepare, NULL);
|
||||||
|
|
||||||
|
@ -170,6 +515,26 @@ inf_ttrace_kill_inferior (void)
|
||||||
static void
|
static void
|
||||||
inf_ttrace_mourn_inferior (void)
|
inf_ttrace_mourn_inferior (void)
|
||||||
{
|
{
|
||||||
|
const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
|
||||||
|
int bucket;
|
||||||
|
|
||||||
|
inf_ttrace_num_threads_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;
|
||||||
|
|
||||||
unpush_target (ttrace_ops_hack);
|
unpush_target (ttrace_ops_hack);
|
||||||
generic_mourn_inferior ();
|
generic_mourn_inferior ();
|
||||||
}
|
}
|
||||||
|
@ -180,6 +545,7 @@ inf_ttrace_attach (char *args, int from_tty)
|
||||||
char *exec_file;
|
char *exec_file;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
char *dummy;
|
char *dummy;
|
||||||
|
ttevent_t tte;
|
||||||
|
|
||||||
if (!args)
|
if (!args)
|
||||||
error_no_arg ("process-id to attach");
|
error_no_arg ("process-id to attach");
|
||||||
|
@ -210,6 +576,15 @@ inf_ttrace_attach (char *args, int from_tty)
|
||||||
perror_with_name ("ttrace");
|
perror_with_name ("ttrace");
|
||||||
attach_flag = 1;
|
attach_flag = 1;
|
||||||
|
|
||||||
|
/* Set the initial event mask. */
|
||||||
|
gdb_assert (inf_ttrace_num_threads_in_syscall == 0);
|
||||||
|
memset (&tte, 0, sizeof (tte));
|
||||||
|
tte.tte_events = TTEVT_EXEC | TTEVT_EXIT;
|
||||||
|
tte.tte_opts = TTEO_NOSTRCCHLD;
|
||||||
|
if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
|
||||||
|
(uintptr_t)&tte, sizeof tte, 0) == -1)
|
||||||
|
perror_with_name ("ttrace");
|
||||||
|
|
||||||
inferior_ptid = pid_to_ptid (pid);
|
inferior_ptid = pid_to_ptid (pid);
|
||||||
push_target (ttrace_ops_hack);
|
push_target (ttrace_ops_hack);
|
||||||
|
|
||||||
|
@ -241,8 +616,10 @@ inf_ttrace_detach (char *args, int from_tty)
|
||||||
if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
|
if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
|
||||||
perror_with_name ("ttrace");
|
perror_with_name ("ttrace");
|
||||||
|
|
||||||
inferior_ptid = null_ptid;
|
inf_ttrace_num_threads_in_syscall = 0;
|
||||||
|
|
||||||
unpush_target (ttrace_ops_hack);
|
unpush_target (ttrace_ops_hack);
|
||||||
|
inferior_ptid = null_ptid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -277,6 +654,7 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
||||||
lwpid_t lwpid = ptid_get_lwp (ptid);
|
lwpid_t lwpid = ptid_get_lwp (ptid);
|
||||||
ttstate_t tts;
|
ttstate_t tts;
|
||||||
|
|
||||||
|
/* Until proven otherwise. */
|
||||||
ourstatus->kind = TARGET_WAITKIND_IGNORE;
|
ourstatus->kind = TARGET_WAITKIND_IGNORE;
|
||||||
|
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
|
@ -297,6 +675,14 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
||||||
}
|
}
|
||||||
while (tts.tts_event == TTEVT_NONE);
|
while (tts.tts_event == TTEVT_NONE);
|
||||||
|
|
||||||
|
/* Now that we've waited, we can re-enable the page protections. */
|
||||||
|
if (inf_ttrace_reenable_page_protections)
|
||||||
|
{
|
||||||
|
gdb_assert (inf_ttrace_num_threads_in_syscall == 0);
|
||||||
|
inf_ttrace_enable_page_protections (tts.tts_pid);
|
||||||
|
inf_ttrace_reenable_page_protections = 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (tts.tts_event)
|
switch (tts.tts_event)
|
||||||
{
|
{
|
||||||
case TTEVT_EXEC:
|
case TTEVT_EXEC:
|
||||||
|
@ -304,14 +690,44 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
||||||
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
||||||
ourstatus->value.sig = TARGET_SIGNAL_TRAP;
|
ourstatus->value.sig = TARGET_SIGNAL_TRAP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TTEVT_EXIT:
|
case TTEVT_EXIT:
|
||||||
store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
|
store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TTEVT_SIGNAL:
|
case TTEVT_SIGNAL:
|
||||||
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
||||||
ourstatus->value.sig =
|
ourstatus->value.sig =
|
||||||
target_signal_from_host (tts.tts_u.tts_signal.tts_signo);
|
target_signal_from_host (tts.tts_u.tts_signal.tts_signo);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TTEVT_SYSCALL_ENTRY:
|
||||||
|
gdb_assert (inf_ttrace_reenable_page_protections == 0);
|
||||||
|
inf_ttrace_num_threads_in_syscall++;
|
||||||
|
if (inf_ttrace_num_threads_in_syscall == 1)
|
||||||
|
{
|
||||||
|
/* A thread has just entered a system call. Disable any
|
||||||
|
page protections as the kernel can't deal with them. */
|
||||||
|
inf_ttrace_disable_page_protections (tts.tts_pid);
|
||||||
|
}
|
||||||
|
ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
|
||||||
|
ourstatus->value.syscall_id = tts.tts_scno;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TTEVT_SYSCALL_RETURN:
|
||||||
|
if (inf_ttrace_num_threads_in_syscall > 0)
|
||||||
|
{
|
||||||
|
/* If the last thread has just left the system call, this
|
||||||
|
would be a logical place to re-enable the page
|
||||||
|
protections, but that doesn't work. We can't re-enable
|
||||||
|
them until we've done another wait. */
|
||||||
|
inf_ttrace_reenable_page_protections =
|
||||||
|
(inf_ttrace_num_threads_in_syscall == 1);
|
||||||
|
inf_ttrace_num_threads_in_syscall--;
|
||||||
|
}
|
||||||
|
ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
|
||||||
|
ourstatus->value.syscall_id = tts.tts_scno;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure all threads within the process are stopped. */
|
/* Make sure all threads within the process are stopped. */
|
||||||
|
@ -405,9 +821,24 @@ inf_ttrace_target (void)
|
||||||
t->to_wait = inf_ttrace_wait;
|
t->to_wait = inf_ttrace_wait;
|
||||||
t->to_xfer_partial = inf_ttrace_xfer_partial;
|
t->to_xfer_partial = inf_ttrace_xfer_partial;
|
||||||
t->to_files_info = inf_ttrace_files_info;
|
t->to_files_info = inf_ttrace_files_info;
|
||||||
|
t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
|
||||||
|
t->to_region_size_ok_for_hw_watchpoint =
|
||||||
|
inf_ttrace_region_size_ok_for_hw_watchpoint;
|
||||||
|
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;
|
||||||
|
|
||||||
ttrace_ops_hack = t;
|
ttrace_ops_hack = t;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Prevent warning from -Wmissing-prototypes. */
|
||||||
|
void _initialize_hppa_hpux_nat (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
_initialize_inf_ttrace (void)
|
||||||
|
{
|
||||||
|
inf_ttrace_page_dict.pagesize = getpagesize();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue