#include "defs.h"
#include "inferior.h"
#include "target.h"
#include <sys/ptrace.h>
#include "gdbcore.h"
#include "gdb_wait.h"
#include "regcache.h"
#include "gdb_string.h"
#include <signal.h>
extern int hpux_has_forked (int pid, int *childpid);
extern int hpux_has_vforked (int pid, int *childpid);
extern int hpux_has_execd (int pid, char **execd_pathname);
extern int hpux_has_syscall_event (int pid, enum target_waitkind *kind,
int *syscall_id);
static CORE_ADDR text_end;
void
deprecated_hpux_text_end (struct target_ops *exec_ops)
{
struct section_table *p;
text_end = (CORE_ADDR) 0;
for (p = exec_ops->to_sections; p < exec_ops->to_sections_end; p++)
if (bfd_get_section_flags (p->bfd, p->the_bfd_section)
& (SEC_CODE | SEC_READONLY))
{
if (text_end < p->endaddr)
text_end = p->endaddr;
}
}
static void fetch_register (int);
void
fetch_inferior_registers (int regno)
{
if (regno == -1)
for (regno = 0; regno < NUM_REGS; regno++)
fetch_register (regno);
else
fetch_register (regno);
}
#define HPPAH_OFFSETOF(type, member) ((int) (&((type *) 0)->member))
void
store_inferior_registers (int regno)
{
unsigned int regaddr;
char buf[80];
int i;
unsigned int offset = U_REGS_OFFSET;
int scratch;
if (regno >= 0)
{
unsigned int addr, len, offset;
if (CANNOT_STORE_REGISTER (regno))
return;
offset = 0;
len = DEPRECATED_REGISTER_RAW_SIZE (regno);
if (regno == 0)
{
save_state_t ss;
addr = HPPAH_OFFSETOF (save_state_t, ss_flags);
len = sizeof (ss.ss_flags);
offset = DEPRECATED_REGISTER_RAW_SIZE (0) - len;
}
else if (regno >= FP0_REGNUM)
addr = (HPPAH_OFFSETOF (save_state_t, ss_fpblock)
+ (DEPRECATED_REGISTER_BYTE (regno) - DEPRECATED_REGISTER_BYTE (FP0_REGNUM)));
else if (len == 8)
addr = (HPPAH_OFFSETOF (save_state_t, ss_wide)
+ DEPRECATED_REGISTER_BYTE (regno));
else if (len == 4)
addr = (HPPAH_OFFSETOF (save_state_t, ss_narrow)
+ (DEPRECATED_REGISTER_BYTE (regno) - DEPRECATED_REGISTER_BYTE (1)));
else
internal_error (__FILE__, __LINE__,
"hppah-nat.c (write_register): unexpected register size");
#ifdef GDB_TARGET_IS_HPPA_20W
if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM && len == 8)
{
CORE_ADDR temp;
temp = *(CORE_ADDR *)&deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
temp |= 0x3;
ttrace_write_reg_64 (PIDGET (inferior_ptid), (CORE_ADDR)addr,
(CORE_ADDR)&temp);
if (errno != 0)
{
char *err = safe_strerror (errno);
char *msg = alloca (strlen (err) + 128);
sprintf (msg, "writing `%s' register: %s",
REGISTER_NAME (regno), err);
perror_with_name (msg);
}
return;
}
if (regno == IPSW_REGNUM && len == 8)
*(int *)&deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)] = 0;
#endif
for (i = 0; i < len; i += sizeof (int))
{
errno = 0;
call_ptrace (PT_WUREGS, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) addr + i,
*(int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno) + i]);
if (errno != 0)
{
char *err = safe_strerror (errno);
char *msg = alloca (strlen (err) + 128);
sprintf (msg, "writing `%s' register: %s",
REGISTER_NAME (regno), err);
if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
perror_with_name (msg);
else
warning (msg);
return;
}
}
}
else
for (regno = 0; regno < NUM_REGS; regno++)
store_inferior_registers (regno);
}
static void
fetch_register (int regno)
{
char buf[MAX_REGISTER_SIZE];
unsigned int addr, len, offset;
int i;
offset = 0;
len = DEPRECATED_REGISTER_RAW_SIZE (regno);
if (regno == 0)
{
save_state_t ss;
addr = HPPAH_OFFSETOF (save_state_t, ss_flags);
len = sizeof (ss.ss_flags);
offset = DEPRECATED_REGISTER_RAW_SIZE (0) - len;
memset (buf, 0, sizeof (buf));
}
else if (regno >= FP0_REGNUM)
addr = (HPPAH_OFFSETOF (save_state_t, ss_fpblock)
+ (DEPRECATED_REGISTER_BYTE (regno) - DEPRECATED_REGISTER_BYTE (FP0_REGNUM)));
else if (len == 8)
addr = (HPPAH_OFFSETOF (save_state_t, ss_wide)
+ DEPRECATED_REGISTER_BYTE (regno));
else if (len == 4)
addr = (HPPAH_OFFSETOF (save_state_t, ss_narrow)
+ (DEPRECATED_REGISTER_BYTE (regno) - DEPRECATED_REGISTER_BYTE (1)));
else
internal_error (__FILE__, __LINE__,
"hppa-nat.c (fetch_register): unexpected register size");
for (i = 0; i < len; i += sizeof (int))
{
errno = 0;
* (int *) &buf[offset + i] =
call_ptrace (PT_RUREGS, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) addr + i, 0);
if (errno != 0)
{
char *err = safe_strerror (errno);
char *msg = alloca (strlen (err) + 128);
sprintf (msg, "reading `%s' register: %s",
REGISTER_NAME (regno), err);
warning (msg);
return;
}
}
if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
buf[len - 1] &= ~0x3;
supply_register (regno, buf);
}
int
child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
struct mem_attrib *mem,
struct target_ops *target)
{
int i;
CORE_ADDR addr = memaddr & - (CORE_ADDR)(sizeof (int));
int count
= (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
int *buffer = (int *) xmalloc (count * sizeof (int));
if (write)
{
if (addr != memaddr || len < (int) sizeof (int))
{
buffer[0] = call_ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER,
PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) addr, 0);
}
if (count > 1)
{
buffer[count - 1]
= call_ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER,
PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) (addr
+ (count - 1) * sizeof (int)),
0);
}
memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
for (i = 0; i < count; i++, addr += sizeof (int))
{
int pt_status;
int pt_request;
errno = 0;
pt_request = (addr < text_end) ? PT_WIUSER : PT_WDUSER;
pt_status = call_ptrace (pt_request,
PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) addr,
buffer[i]);
if ((pt_status == -1) && errno)
{
errno = 0;
pt_request = (pt_request == PT_WIUSER) ? PT_WDUSER : PT_WIUSER;
pt_status = call_ptrace (pt_request,
PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) addr,
buffer[i]);
if ((pt_status == -1) && errno)
{
xfree (buffer);
return 0;
}
}
}
}
else
{
for (i = 0; i < count; i++, addr += sizeof (int))
{
errno = 0;
buffer[i] = call_ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER,
PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) addr, 0);
if (errno)
{
xfree (buffer);
return 0;
}
QUIT;
}
memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
}
xfree (buffer);
return len;
}
char *saved_child_execd_pathname = NULL;
int saved_vfork_pid;
enum {
STATE_NONE,
STATE_GOT_CHILD,
STATE_GOT_EXEC,
STATE_GOT_PARENT,
STATE_FAKE_EXEC
} saved_vfork_state = STATE_NONE;
int
child_follow_fork (int follow_child)
{
ptid_t last_ptid;
struct target_waitstatus last_status;
int has_vforked;
int parent_pid, child_pid;
get_last_target_status (&last_ptid, &last_status);
has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED);
parent_pid = ptid_get_pid (last_ptid);
child_pid = last_status.value.related_pid;
if (! follow_child)
{
if (! has_vforked)
{
detach_breakpoints (child_pid);
#ifdef SOLIB_REMOVE_INFERIOR_HOOK
SOLIB_REMOVE_INFERIOR_HOOK (child_pid);
#endif
}
printf_unfiltered ("Detaching after fork from %s\n",
target_pid_to_str (pid_to_ptid (child_pid)));
hppa_require_detach (child_pid, 0);
if (has_vforked)
reattach_breakpoints (parent_pid);
}
else
{
if (! has_vforked)
detach_breakpoints (child_pid);
remove_breakpoints ();
#ifdef SOLIB_REMOVE_INFERIOR_HOOK
SOLIB_REMOVE_INFERIOR_HOOK (PIDGET (inferior_ptid));
#endif
target_detach (NULL, 1);
printf_unfiltered ("Attaching after fork to %s\n",
target_pid_to_str (pid_to_ptid (child_pid)));
hppa_require_attach (child_pid);
inferior_ptid = pid_to_ptid (child_pid);
if (!has_vforked)
follow_inferior_reset_breakpoints ();
}
if (has_vforked)
{
if (saved_vfork_state != STATE_GOT_PARENT
&& saved_vfork_state != STATE_FAKE_EXEC)
fprintf_unfiltered (gdb_stdout,
"hppa: post follow vfork: confused state\n");
if (! follow_child || saved_vfork_state == STATE_GOT_PARENT)
saved_vfork_state = STATE_NONE;
else
return 1;
}
return 0;
}
char *
child_pid_to_str (ptid_t ptid)
{
static char buf[30];
pid_t pid = PIDGET (ptid);
sprintf (buf, "process %d%c", pid, '\0');
return buf;
}
char *
hppa_tid_to_str (ptid_t ptid)
{
static char buf[30];
pid_t tid = PIDGET (ptid);
sprintf (buf, "system thread %d%c", tid, '\0');
return buf;
}
int not_same_real_pid = 1;
ptid_t
child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
int save_errno;
int status;
char *execd_pathname = NULL;
int exit_status;
int related_pid;
int syscall_id;
enum target_waitkind kind;
int pid;
if (saved_vfork_state == STATE_FAKE_EXEC)
{
saved_vfork_state = STATE_NONE;
ourstatus->kind = TARGET_WAITKIND_EXECD;
ourstatus->value.execd_pathname = saved_child_execd_pathname;
return inferior_ptid;
}
do
{
set_sigint_trap ();
set_sigio_trap ();
pid = ptrace_wait (inferior_ptid, &status);
save_errno = errno;
clear_sigio_trap ();
clear_sigint_trap ();
if (pid == -1)
{
if (save_errno == EINTR)
continue;
fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
safe_strerror (save_errno));
ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
return pid_to_ptid (-1);
}
if (target_has_exited (pid, status, &exit_status))
{
continue;
}
if (!target_thread_alive (pid_to_ptid (pid)))
{
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
return pid_to_ptid (pid);
}
if (hpux_has_forked (pid, &related_pid))
{
if (pid == PIDGET (inferior_ptid))
{
ourstatus->kind = TARGET_WAITKIND_IGNORE;
return inferior_ptid;
}
if (related_pid == PIDGET (inferior_ptid))
{
ourstatus->kind = TARGET_WAITKIND_FORKED;
ourstatus->value.related_pid = pid;
return inferior_ptid;
}
}
if (hpux_has_vforked (pid, &related_pid))
{
if (pid == PIDGET (inferior_ptid))
{
if (saved_vfork_state == STATE_GOT_CHILD)
saved_vfork_state = STATE_GOT_PARENT;
else if (saved_vfork_state == STATE_GOT_EXEC)
saved_vfork_state = STATE_FAKE_EXEC;
else
fprintf_unfiltered (gdb_stdout,
"hppah: parent vfork: confused\n");
}
else if (related_pid == PIDGET (inferior_ptid))
{
if (saved_vfork_state == STATE_NONE)
saved_vfork_state = STATE_GOT_CHILD;
else
fprintf_unfiltered (gdb_stdout,
"hppah: child vfork: confused\n");
}
else
fprintf_unfiltered (gdb_stdout,
"hppah: unknown vfork: confused\n");
if (saved_vfork_state == STATE_GOT_CHILD)
{
child_post_startup_inferior (pid_to_ptid (pid));
detach_breakpoints (pid);
#ifdef SOLIB_REMOVE_INFERIOR_HOOK
SOLIB_REMOVE_INFERIOR_HOOK (pid);
#endif
child_resume (pid_to_ptid (pid), 0, TARGET_SIGNAL_0);
ourstatus->kind = TARGET_WAITKIND_IGNORE;
return pid_to_ptid (related_pid);
}
else if (saved_vfork_state == STATE_FAKE_EXEC)
{
ourstatus->kind = TARGET_WAITKIND_VFORKED;
ourstatus->value.related_pid = related_pid;
return pid_to_ptid (pid);
}
else
{
saved_vfork_pid = related_pid;
ourstatus->kind = TARGET_WAITKIND_IGNORE;
return pid_to_ptid (pid);
}
}
if (hpux_has_execd (pid, &execd_pathname))
{
if (saved_vfork_state != STATE_NONE)
{
if (saved_vfork_state == STATE_GOT_CHILD)
{
saved_vfork_state = STATE_GOT_EXEC;
if (RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK ())
target_resume (pid_to_ptid (pid), 1, TARGET_SIGNAL_0);
ourstatus->kind = TARGET_WAITKIND_IGNORE;
}
else if (saved_vfork_state == STATE_GOT_PARENT)
{
saved_vfork_state = STATE_FAKE_EXEC;
ourstatus->kind = TARGET_WAITKIND_VFORKED;
ourstatus->value.related_pid = saved_vfork_pid;
}
else
fprintf_unfiltered (gdb_stdout,
"hppa: exec: unexpected state\n");
saved_child_execd_pathname = execd_pathname;
return inferior_ptid;
}
if (inferior_ignoring_startup_exec_events)
{
inferior_ignoring_startup_exec_events--;
}
else
{
ourstatus->kind = TARGET_WAITKIND_EXECD;
ourstatus->value.execd_pathname = execd_pathname;
return pid_to_ptid (pid);
}
}
if (hpux_has_syscall_event (pid, &kind, &syscall_id))
{
ourstatus->kind = kind;
ourstatus->value.syscall_id = syscall_id;
return pid_to_ptid (pid);
}
}
while ((pid != PIDGET (inferior_ptid)) && not_same_real_pid);
store_waitstatus (ourstatus, status);
return pid_to_ptid (pid);
}
#if !defined (GDB_NATIVE_HPUX_11)
#define PT_VERSION 123456
typedef struct
{
int parent_channel[2];
int child_channel[2];
}
startup_semaphore_t;
#define SEM_TALK (1)
#define SEM_LISTEN (0)
static startup_semaphore_t startup_semaphore;
#ifdef PT_SETTRC
int
parent_attach_all (int pid, PTRACE_ARG3_TYPE addr, int data)
{
int pt_status = 0;
int tc_magic_child = PT_VERSION;
int tc_magic_parent = 0;
#if defined(PT_SET_EVENT_MASK)
write (startup_semaphore.child_channel[SEM_TALK],
&tc_magic_child,
sizeof (tc_magic_child));
read (startup_semaphore.parent_channel[SEM_LISTEN],
&tc_magic_parent,
sizeof (tc_magic_parent));
if (tc_magic_child != tc_magic_parent)
warning ("mismatched semaphore magic");
(void) close (startup_semaphore.parent_channel[SEM_LISTEN]);
(void) close (startup_semaphore.parent_channel[SEM_TALK]);
(void) close (startup_semaphore.child_channel[SEM_LISTEN]);
(void) close (startup_semaphore.child_channel[SEM_TALK]);
#endif
return 0;
}
#endif
int
hppa_require_attach (int pid)
{
int pt_status;
CORE_ADDR pc;
CORE_ADDR pc_addr;
unsigned int regs_offset;
errno = 0;
regs_offset = U_REGS_OFFSET;
pc_addr = register_addr (PC_REGNUM, regs_offset);
pc = call_ptrace (PT_READ_U, pid, (PTRACE_ARG3_TYPE) pc_addr, 0);
if (errno)
{
errno = 0;
pt_status = call_ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 0, 0);
if (errno)
return -1;
errno = 0;
}
attach_flag = 1;
return pid;
}
int
hppa_require_detach (int pid, int signal)
{
errno = 0;
call_ptrace (PT_DETACH, pid, (PTRACE_ARG3_TYPE) 1, signal);
errno = 0;
return pid;
}
void
hppa_enable_page_protection_events (int pid)
{
}
void
hppa_disable_page_protection_events (int pid)
{
}
int
hppa_insert_hw_watchpoint (int pid, CORE_ADDR start, LONGEST len, int type)
{
error ("Hardware watchpoints not implemented on this platform.");
}
int
hppa_remove_hw_watchpoint (int pid, CORE_ADDR start, LONGEST len, int type)
{
error ("Hardware watchpoints not implemented on this platform.");
}
int
hppa_can_use_hw_watchpoint (int type, int cnt, int ot)
{
return 0;
}
int
hppa_range_profitable_for_hw_watchpoint (int pid, CORE_ADDR start, LONGEST len)
{
error ("Hardware watchpoints not implemented on this platform.");
}
char *
hppa_pid_or_tid_to_str (ptid_t id)
{
return child_pid_to_str (id);
}
void
hppa_ensure_vforking_parent_remains_stopped (int pid)
{
kill (pid, SIGTRAP);
}
int
hppa_resume_execd_vforking_child_to_get_parent_vfork (void)
{
return 1;
}
void
require_notification_of_events (int pid)
{
#if defined(PT_SET_EVENT_MASK)
int pt_status;
ptrace_event_t ptrace_events;
int nsigs;
int signum;
memset (&ptrace_events, 0, sizeof (ptrace_events));
sigfillset (&ptrace_events.pe_signals);
nsigs = (int) TARGET_SIGNAL_LAST;
for (signum = nsigs; signum > 0; signum--)
{
if ((signal_stop_state (signum)) ||
(signal_print_state (signum)) ||
(!signal_pass_state (signum)))
{
if (target_signal_to_host_p (signum))
sigdelset (&ptrace_events.pe_signals,
target_signal_to_host (signum));
}
}
ptrace_events.pe_set_event = 0;
ptrace_events.pe_set_event |= PTRACE_SIGNAL;
ptrace_events.pe_set_event |= PTRACE_EXEC;
ptrace_events.pe_set_event |= PTRACE_FORK;
ptrace_events.pe_set_event |= PTRACE_VFORK;
errno = 0;
pt_status = call_ptrace (PT_SET_EVENT_MASK,
pid,
(PTRACE_ARG3_TYPE) & ptrace_events,
sizeof (ptrace_events));
if (errno)
perror_with_name ("ptrace");
if (pt_status < 0)
return;
#endif
}
void
require_notification_of_exec_events (int pid)
{
#if defined(PT_SET_EVENT_MASK)
int pt_status;
ptrace_event_t ptrace_events;
memset (&ptrace_events, 0, sizeof (ptrace_events));
sigemptyset (&ptrace_events.pe_signals);
ptrace_events.pe_set_event = 0;
ptrace_events.pe_set_event |= PTRACE_EXEC;
errno = 0;
pt_status = call_ptrace (PT_SET_EVENT_MASK,
pid,
(PTRACE_ARG3_TYPE) & ptrace_events,
sizeof (ptrace_events));
if (errno)
perror_with_name ("ptrace");
if (pt_status < 0)
return;
#endif
}
void
child_acknowledge_created_inferior (int pid)
{
int tc_magic_parent = PT_VERSION;
int tc_magic_child = 0;
#if defined(PT_SET_EVENT_MASK)
read (startup_semaphore.child_channel[SEM_LISTEN],
&tc_magic_child,
sizeof (tc_magic_child));
write (startup_semaphore.parent_channel[SEM_TALK],
&tc_magic_parent,
sizeof (tc_magic_parent));
sleep (1);
require_notification_of_exec_events (pid);
(void) close (startup_semaphore.parent_channel[SEM_LISTEN]);
(void) close (startup_semaphore.parent_channel[SEM_TALK]);
(void) close (startup_semaphore.child_channel[SEM_LISTEN]);
(void) close (startup_semaphore.child_channel[SEM_TALK]);
#endif
}
void
child_post_startup_inferior (ptid_t ptid)
{
require_notification_of_events (PIDGET (ptid));
}
void
child_post_attach (int pid)
{
require_notification_of_events (pid);
}
int
child_insert_fork_catchpoint (int pid)
{
#if !defined(PT_SET_EVENT_MASK)
error ("Unable to catch forks prior to HPUX 10.0");
#else
return 0;
#endif
}
int
child_remove_fork_catchpoint (int pid)
{
#if !defined(PT_SET_EVENT_MASK)
error ("Unable to catch forks prior to HPUX 10.0");
#else
return 0;
#endif
}
int
child_insert_vfork_catchpoint (int pid)
{
#if !defined(PT_SET_EVENT_MASK)
error ("Unable to catch vforks prior to HPUX 10.0");
#else
return 0;
#endif
}
int
child_remove_vfork_catchpoint (int pid)
{
#if !defined(PT_SET_EVENT_MASK)
error ("Unable to catch vforks prior to HPUX 10.0");
#else
return 0;
#endif
}
int
hpux_has_forked (int pid, int *childpid)
{
#if !defined(PT_GET_PROCESS_STATE)
*childpid = 0;
return 0;
#else
int pt_status;
ptrace_state_t ptrace_state;
errno = 0;
pt_status = call_ptrace (PT_GET_PROCESS_STATE,
pid,
(PTRACE_ARG3_TYPE) & ptrace_state,
sizeof (ptrace_state));
if (errno)
perror_with_name ("ptrace");
if (pt_status < 0)
return 0;
if (ptrace_state.pe_report_event & PTRACE_FORK)
{
*childpid = ptrace_state.pe_other_pid;
return 1;
}
return 0;
#endif
}
int
hpux_has_vforked (int pid, int *childpid)
{
#if !defined(PT_GET_PROCESS_STATE)
*childpid = 0;
return 0;
#else
int pt_status;
ptrace_state_t ptrace_state;
errno = 0;
pt_status = call_ptrace (PT_GET_PROCESS_STATE,
pid,
(PTRACE_ARG3_TYPE) & ptrace_state,
sizeof (ptrace_state));
if (errno)
perror_with_name ("ptrace");
if (pt_status < 0)
return 0;
if (ptrace_state.pe_report_event & PTRACE_VFORK)
{
*childpid = ptrace_state.pe_other_pid;
return 1;
}
return 0;
#endif
}
int
child_insert_exec_catchpoint (int pid)
{
#if !defined(PT_SET_EVENT_MASK)
error ("Unable to catch execs prior to HPUX 10.0");
#else
return 0;
#endif
}
int
child_remove_exec_catchpoint (int pid)
{
#if !defined(PT_SET_EVENT_MASK)
error ("Unable to catch execs prior to HPUX 10.0");
#else
return 0;
#endif
}
int
hpux_has_execd (int pid, char **execd_pathname)
{
#if !defined(PT_GET_PROCESS_STATE)
*execd_pathname = NULL;
return 0;
#else
int pt_status;
ptrace_state_t ptrace_state;
errno = 0;
pt_status = call_ptrace (PT_GET_PROCESS_STATE,
pid,
(PTRACE_ARG3_TYPE) & ptrace_state,
sizeof (ptrace_state));
if (errno)
perror_with_name ("ptrace");
if (pt_status < 0)
return 0;
if (ptrace_state.pe_report_event & PTRACE_EXEC)
{
char *exec_file = target_pid_to_exec_file (pid);
*execd_pathname = savestring (exec_file, strlen (exec_file));
return 1;
}
return 0;
#endif
}
int
child_reported_exec_events_per_exec_call (void)
{
return 2;
}
int
hpux_has_syscall_event (int pid, enum target_waitkind *kind, int *syscall_id)
{
*kind = TARGET_WAITKIND_SPURIOUS;
*syscall_id = -1;
return 0;
}
char *
child_pid_to_exec_file (int pid)
{
static char exec_file_buffer[1024];
int pt_status;
CORE_ADDR top_of_stack;
char four_chars[4];
int name_index;
int i;
ptid_t saved_inferior_ptid;
int done;
#ifdef PT_GET_PROCESS_PATHNAME
pt_status = call_ptrace (PT_GET_PROCESS_PATHNAME,
pid,
(PTRACE_ARG3_TYPE) exec_file_buffer,
sizeof (exec_file_buffer) - 1);
if (pt_status == 0)
return exec_file_buffer;
#endif
top_of_stack = 0x7b03a000;
name_index = 0;
done = 0;
saved_inferior_ptid = inferior_ptid;
inferior_ptid = pid_to_ptid (pid);
while (!done)
{
if (target_read_memory (top_of_stack, four_chars, 4) != 0)
{
inferior_ptid = saved_inferior_ptid;
return NULL;
}
for (i = 0; i < 4; i++)
{
exec_file_buffer[name_index++] = four_chars[i];
done = (four_chars[i] == '\0');
if (done)
break;
}
top_of_stack += 4;
}
if (exec_file_buffer[0] == '\0')
{
inferior_ptid = saved_inferior_ptid;
return NULL;
}
inferior_ptid = saved_inferior_ptid;
return exec_file_buffer;
}
void
pre_fork_inferior (void)
{
int status;
status = pipe (startup_semaphore.parent_channel);
if (status < 0)
{
warning ("error getting parent pipe for startup semaphore");
return;
}
status = pipe (startup_semaphore.child_channel);
if (status < 0)
{
warning ("error getting child pipe for startup semaphore");
return;
}
}
int
child_thread_alive (ptid_t ptid)
{
return 1;
}
#endif