# include <asm/rse.h>
#endif
-#if defined(X86_64) || defined(X32)
-# include <sys/uio.h>
+/* for struct iovec */
+#include <sys/uio.h>
+/* for NT_PRSTATUS */
+#ifdef HAVE_ELF_H
# include <elf.h>
#endif
#if defined(AARCH64)
# include <asm/ptrace.h>
-# include <sys/uio.h>
-# include <elf.h>
#endif
-#if defined(OR1K)
-# include <sys/uio.h>
-# include <elf.h>
-#endif
-
-#if defined(METAG)
-# include <sys/uio.h>
-# include <elf.h>
+#if defined(XTENSA)
+# include <asm/ptrace.h>
#endif
#ifndef ERESTARTSYS
#if defined(I386)
struct user_regs_struct i386_regs;
+# define ARCH_REGS_FOR_GETREGSET i386_regs
#elif defined(X86_64) || defined(X32)
/*
* On i386, pt_regs and user_regs_struct are the same,
static long bfin_r0;
#elif defined(ARM)
struct pt_regs arm_regs; /* not static */
+# define ARCH_REGS_FOR_GETREGSET arm_regs
#elif defined(AARCH64)
static union {
struct user_pt_regs aarch64_r;
static long microblaze_r3;
#elif defined(OR1K)
static struct user_regs_struct or1k_regs;
-static struct iovec or1k_io = {
- .iov_base = &or1k_regs
-};
+# define ARCH_REGS_FOR_GETREGSET or1k_regs
#elif defined(METAG)
static struct user_gp_regs metag_regs;
-static struct iovec metag_io = {
- .iov_base = &metag_regs
-};
+# define ARCH_REGS_FOR_GETREGSET metag_regs
+#elif defined(XTENSA)
+static long xtensa_a2;
#endif
void
tprintf("[%08lx] ", or1k_regs.pc);
#elif defined(METAG)
tprintf("[%08lx] ", metag_regs.pc);
+#elif defined(XTENSA)
+ long pc;
+ if (upeek(tcp, REG_PC, &pc) < 0) {
+ PRINTBADPC;
+ return;
+ }
+ tprintf("[%08lx] ", pc);
#endif /* architecture */
}
#ifndef get_regs
long get_regs_error;
+
+#if defined(PTRACE_GETREGSET) && defined(NT_PRSTATUS)
+static void get_regset(pid_t pid)
+{
+/* constant iovec */
+# if defined(ARM) \
+ || defined(I386) \
+ || defined(METAG) \
+ || defined(OR1K)
+ static struct iovec io = {
+ .iov_base = &ARCH_REGS_FOR_GETREGSET,
+ .iov_len = sizeof(ARCH_REGS_FOR_GETREGSET)
+ };
+ get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &io);
+
+/* variable iovec */
+# elif defined(X86_64) || defined(X32)
+ /* x86_io.iov_base = &x86_regs_union; - already is */
+ x86_io.iov_len = sizeof(x86_regs_union);
+ get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &x86_io);
+# elif defined(AARCH64)
+ /* aarch64_io.iov_base = &arm_regs_union; - already is */
+ aarch64_io.iov_len = sizeof(arm_regs_union);
+ get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &aarch64_io);
+# else
+# warning both PTRACE_GETREGSET and NT_PRSTATUS are available but not yet used
+# endif
+}
+#endif /* PTRACE_GETREGSET && NT_PRSTATUS */
+
void
get_regs(pid_t pid)
{
-# if defined(AVR32)
+/* PTRACE_GETREGSET only */
+# if defined(METAG) || defined(OR1K) || defined(X32) || defined(AARCH64)
+ get_regset(pid);
+
+/* PTRACE_GETREGS only */
+# elif defined(AVR32)
get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &avr32_regs);
-# elif defined(I386)
- get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
-# elif defined(X32)
- /* x86_io.iov_base = &x86_regs_union; - already is */
- x86_io.iov_len = sizeof(x86_regs_union);
- get_regs_error = ptrace(PTRACE_GETREGSET, pid,
- NT_PRSTATUS, (long) &x86_io);
-# elif defined(X86_64)
+# elif defined(TILE)
+ get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &tile_regs);
+# elif defined(SPARC) || defined(SPARC64)
+ get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&sparc_regs, 0);
+
+/* try PTRACE_GETREGSET first, fallback to PTRACE_GETREGS */
+# else
# if defined(PTRACE_GETREGSET) && defined(NT_PRSTATUS)
static int getregset_support;
if (getregset_support >= 0) {
- /* x86_io.iov_base = &x86_regs_union; - already is */
- x86_io.iov_len = sizeof(x86_regs_union);
- get_regs_error = ptrace(PTRACE_GETREGSET, pid,
- NT_PRSTATUS, (long) &x86_io);
+ get_regset(pid);
if (getregset_support > 0)
return;
if (get_regs_error >= 0) {
getregset_support = -1;
}
# endif /* PTRACE_GETREGSET && NT_PRSTATUS */
+# if defined(ARM)
+ get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &arm_regs);
+# elif defined(I386)
+ get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &i386_regs);
+# elif defined(X86_64)
/* Use old method, with unreliable heuristical detection of 32-bitness. */
x86_io.iov_len = sizeof(x86_64_regs);
- get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
+ get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &x86_64_regs);
if (!get_regs_error && x86_64_regs.cs == 0x23) {
x86_io.iov_len = sizeof(i386_regs);
/*
i386_regs.esp = x86_64_regs.rsp;
/* i386_regs.xss = x86_64_regs.ss; */
}
-# elif defined(ARM)
- get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&arm_regs);
-# elif defined(AARCH64)
- /*aarch64_io.iov_base = &arm_regs_union; - already is */
- aarch64_io.iov_len = sizeof(arm_regs_union);
- get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
-# if 0
- /* Paranoia checks */
- if (get_regs_error)
- return;
- switch (aarch64_io.iov_len) {
- case sizeof(aarch64_regs):
- /* We are in 64-bit mode */
- break;
- case sizeof(arm_regs):
- /* We are in 32-bit mode */
- break;
- default:
- get_regs_error = -1;
- break;
- }
-# endif
-# elif defined(SPARC) || defined(SPARC64)
- get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&sparc_regs, 0);
-# elif defined(TILE)
- get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
-# elif defined(OR1K)
- or1k_io.iov_len = sizeof(or1k_regs);
- get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &or1k_io);
-# elif defined(METAG)
- metag_io.iov_len = sizeof(metag_regs);
- get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &metag_io);
+# else
+# error unhandled architecture
+# endif /* ARM || I386 || X86_64 */
# endif
}
-#endif
+#endif /* !get_regs */
/* Returns:
* 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
scno = or1k_regs.gpr[11];
#elif defined(METAG)
scno = metag_regs.dx[0][1]; /* syscall number in D1Re0 (D1.0) */
+#elif defined(XTENSA)
+ if (upeek(tcp, SYSCALL_NR, &scno) < 0)
+ return -1;
#endif
tcp->scno = scno;
for (i = 0; i < nargs; i++)
/* arguments go backwards from D1Ar1 (D1.3) */
tcp->u_arg[i] = ((unsigned long *)&metag_regs.dx[3][1])[-i];
+#elif defined(XTENSA)
+ /* arg0: a6, arg1: a3, arg2: a4, arg3: a5, arg4: a8, arg5: a9 */
+ static const int xtensaregs[MAX_ARGS] = { 6, 3, 4, 5, 8, 9 };
+ for (i = 0; i < nargs; ++i)
+ if (upeek(tcp, REG_A_BASE + xtensaregs[i], &tcp->u_arg[i]) < 0)
+ return -1;
#else /* Other architecture (32bits specific) */
for (i = 0; i < nargs; ++i)
if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
goto ret;
}
+ if ( sys_execve == tcp->s_ent->sys_func
+# if defined(SPARC) || defined(SPARC64)
+ || sys_execv == tcp->s_ent->sys_func
+# endif
+ ) {
+ hide_log_until_execve = 0;
+ }
+
#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
while (1) {
# ifdef SYS_socket_subcall
tcp->flags &= ~TCB_FILTERED;
- if (cflag == CFLAG_ONLY_STATS) {
+ if (cflag == CFLAG_ONLY_STATS || hide_log_until_execve) {
res = 0;
goto ret;
}
/* already done by get_regs */
#elif defined(METAG)
/* already done by get_regs */
+#elif defined(XTENSA)
+ if (upeek(tcp, REG_A_BASE + 2, &xtensa_a2) < 0)
+ return -1;
#endif
return 1;
}
else {
tcp->u_rval = or1k_regs.gpr[11];
}
+#elif defined(XTENSA)
+ if (check_errno && is_negated_errno(xtensa_a2)) {
+ tcp->u_rval = -1;
+ u_error = -xtensa_a2;
+ }
+ else {
+ tcp->u_rval = xtensa_a2;
+ }
#endif
tcp->u_error = u_error;
}
get_error(tcp); /* never fails */
if (need_fork_exec_workarounds)
syscall_fixup_for_fork_exec(tcp);
- if (filtered(tcp))
+ if (filtered(tcp) || hide_log_until_execve)
goto ret;
}