#ifdef HAVE_SYS_REG_H
# include <sys/reg.h>
-# ifndef PTRACE_PEEKUSR
-# define PTRACE_PEEKUSR PTRACE_PEEKUSER
-# endif
#elif defined(HAVE_LINUX_PTRACE_H)
# undef PTRACE_SYSCALL
# ifdef HAVE_STRUCT_IA64_FPREG
# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
# define pt_all_user_regs XXX_pt_all_user_regs
# endif
+# ifdef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
+# define ptrace_peeksiginfo_args XXX_ptrace_peeksiginfo_args
+# endif
# include <linux/ptrace.h>
+# undef ptrace_peeksiginfo_args
# undef ia64_fpreg
# undef pt_all_user_regs
#endif
# include <asm/ptrace.h>
#endif
-#ifndef ERESTARTSYS
-# define ERESTARTSYS 512
-#endif
-#ifndef ERESTARTNOINTR
-# define ERESTARTNOINTR 513
-#endif
-#ifndef ERESTARTNOHAND
-# define ERESTARTNOHAND 514 /* restart if no handler */
-#endif
-#ifndef ERESTART_RESTARTBLOCK
-# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
-#endif
-
#ifndef NSIG
# warning: NSIG is not defined, using 32
# define NSIG 32
#endif
-#ifdef ARM
-/* Ugh. Is this really correct? ARM has no RT signals?! */
-# undef NSIG
-# define NSIG 32
-#endif
#include "syscall.h"
#define TM TRACE_MEMORY
#define NF SYSCALL_NEVER_FAILS
#define MA MAX_ARGS
+#define SI STACKTRACE_INVALIDATE_CACHE
+#define SE STACKTRACE_CAPTURE_ON_ENTER
const struct_sysent sysent0[] = {
#include "syscallent.h"
#undef TM
#undef NF
#undef MA
+#undef SI
+#undef SE
/*
* `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
}
static void
-update_personality(struct tcb *tcp, int personality)
+update_personality(struct tcb *tcp, unsigned int personality)
{
if (personality == current_personality)
return;
static int qual_syscall(), qual_signal(), qual_desc();
static const struct qual_options {
- int bitflag;
+ unsigned int bitflag;
const char *option_name;
int (*qualify)(const char *, int, int);
const char *argument_name;
};
static void
-reallocate_qual(int n)
+reallocate_qual(const unsigned int n)
{
unsigned p;
qualbits_t *qp;
}
static void
-qualify_one(int n, int bitflag, int not, int pers)
+qualify_one(const unsigned int n, unsigned int bitflag, const int not, const int pers)
{
- unsigned p;
+ int p;
if (num_quals <= n)
reallocate_qual(n + 1);
}
static int
-qual_syscall(const char *s, int bitflag, int not)
+qual_syscall(const char *s, const unsigned int bitflag, const int not)
{
- unsigned p;
- unsigned i;
+ int p;
+ unsigned int i;
int rc = -1;
if (*s >= '0' && *s <= '9') {
}
static int
-qual_signal(const char *s, int bitflag, int not)
+qual_signal(const char *s, const unsigned int bitflag, const int not)
{
- int i;
+ unsigned int i;
if (*s >= '0' && *s <= '9') {
int signo = string_to_uint(s);
}
static int
-qual_desc(const char *s, int bitflag, int not)
+qual_desc(const char *s, const unsigned int bitflag, const int not)
{
if (*s >= '0' && *s <= '9') {
int desc = string_to_uint(s);
qualify(const char *s)
{
const struct qual_options *opt;
- int not;
char *copy;
const char *p;
- int i, n;
+ int not;
+ unsigned int i;
if (num_quals == 0)
reallocate_qual(MIN_QUALS);
opt = &qual_options[0];
for (i = 0; (p = qual_options[i].option_name); i++) {
- n = strlen(p);
- if (strncmp(s, p, n) == 0 && s[n] == '=') {
+ unsigned int len = strlen(p);
+ if (strncmp(s, p, len) == 0 && s[len] == '=') {
opt = &qual_options[i];
- s += n + 1;
+ s += len + 1;
break;
}
}
if (!copy)
die_out_of_memory();
for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
+ int n;
if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
unsigned pers;
for (pers = 0; pers < SUPPORTED_PERSONALITIES; pers++) {
# if defined(SPARC) || defined(SPARC64)
val = sparc_regs.u_regs[U_REG_O1];
# elif defined(SH)
- if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
+ if (upeek(tcp->pid, 4*(REG_REG0+1), &val) < 0)
return -1;
# elif defined(IA64)
- if (upeek(tcp, PT_R9, &val) < 0)
+ if (upeek(tcp->pid, PT_R9, &val) < 0)
return -1;
# endif
}
#endif
-int
-is_restart_error(struct tcb *tcp)
-{
- switch (tcp->u_error) {
- case ERESTARTSYS:
- case ERESTARTNOINTR:
- case ERESTARTNOHAND:
- case ERESTART_RESTARTBLOCK:
- return 1;
- default:
- break;
- }
- return 0;
-}
-
#if defined(I386)
-struct user_regs_struct i386_regs;
+static struct user_regs_struct i386_regs;
+/* Cast suppresses signedness warning (.esp is long, not unsigned long) */
+uint32_t *const i386_esp_ptr = (uint32_t*)&i386_regs.esp;
# define ARCH_REGS_FOR_GETREGSET i386_regs
#elif defined(X86_64) || defined(X32)
/*
} x86_regs_union;
# define x86_64_regs x86_regs_union.x86_64_r
# define i386_regs x86_regs_union.i386_r
+uint32_t *const i386_esp_ptr = &i386_regs.esp;
static struct iovec x86_io = {
.iov_base = &x86_regs_union
};
#elif defined(IA64)
-long ia32 = 0; /* not static */
+bool ia64_ia32mode = 0; /* not static */
static long ia64_r8, ia64_r10;
#elif defined(POWERPC)
struct pt_regs ppc_regs;
-static long ppc_result;
#elif defined(M68K)
static long m68k_d0;
#elif defined(BFIN)
static long mips_a3;
static long mips_r2;
#elif defined(S390) || defined(S390X)
-static long gpr2;
-static long syscall_mode;
+static long s390_gpr2;
#elif defined(HPPA)
static long hppa_r28;
#elif defined(SH)
# define ARCH_REGS_FOR_GETREGSET metag_regs
#elif defined(XTENSA)
static long xtensa_a2;
+# elif defined(ARC)
+static struct user_regs_struct arc_regs;
+# define ARCH_REGS_FOR_GETREGSET arc_regs
#endif
void
-printcall(struct tcb *tcp)
+print_pc(struct tcb *tcp)
{
#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
sizeof(long) == 8 ? "[????????????????] " : \
tprintf("[%08lx] ", i386_regs.eip);
#elif defined(S390) || defined(S390X)
long psw;
- if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
+ if (upeek(tcp->pid, PT_PSWADDR, &psw) < 0) {
PRINTBADPC;
return;
}
}
#elif defined(IA64)
long ip;
- if (upeek(tcp, PT_B0, &ip) < 0) {
+ if (upeek(tcp->pid, PT_B0, &ip) < 0) {
PRINTBADPC;
return;
}
# endif
#elif defined(M68K)
long pc;
- if (upeek(tcp, 4*PT_PC, &pc) < 0) {
+ if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
tprints("[????????] ");
return;
}
tprintf("[%08lx] ", pc);
#elif defined(ALPHA)
long pc;
- if (upeek(tcp, REG_PC, &pc) < 0) {
+ if (upeek(tcp->pid, REG_PC, &pc) < 0) {
tprints("[????????????????] ");
return;
}
tprintf("[%08lx] ", sparc_regs.tpc);
#elif defined(HPPA)
long pc;
- if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
+ if (upeek(tcp->pid, PT_IAOQ0, &pc) < 0) {
tprints("[????????] ");
return;
}
tprintf("[%08lx] ", pc);
#elif defined(MIPS)
long pc;
- if (upeek(tcp, REG_EPC, &pc) < 0) {
+ if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
tprints("[????????] ");
return;
}
tprintf("[%08lx] ", pc);
#elif defined(SH)
long pc;
- if (upeek(tcp, 4*REG_PC, &pc) < 0) {
+ if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
tprints("[????????] ");
return;
}
tprintf("[%08lx] ", pc);
#elif defined(SH64)
long pc;
- if (upeek(tcp, REG_PC, &pc) < 0) {
+ if (upeek(tcp->pid, REG_PC, &pc) < 0) {
tprints("[????????????????] ");
return;
}
tprintf("[%08lx] ", avr32_regs.pc);
#elif defined(BFIN)
long pc;
- if (upeek(tcp, PT_PC, &pc) < 0) {
+ if (upeek(tcp->pid, PT_PC, &pc) < 0) {
PRINTBADPC;
return;
}
tprintf("[%08lx] ", pc);
#elif defined(CRISV10)
long pc;
- if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
+ if (upeek(tcp->pid, 4*PT_IRP, &pc) < 0) {
PRINTBADPC;
return;
}
tprintf("[%08lx] ", pc);
#elif defined(CRISV32)
long pc;
- if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
+ if (upeek(tcp->pid, 4*PT_ERP, &pc) < 0) {
PRINTBADPC;
return;
}
tprintf("[%08lx] ", metag_regs.pc);
#elif defined(XTENSA)
long pc;
- if (upeek(tcp, REG_PC, &pc) < 0) {
+ if (upeek(tcp->pid, REG_PC, &pc) < 0) {
PRINTBADPC;
return;
}
tprintf("[%08lx] ", pc);
+#elif defined(ARC)
+ tprintf("[%08lx] ", arc_regs.efa);
#endif /* architecture */
}
/* Shuffle syscall numbers so that we don't have huge gaps in syscall table.
* The shuffling should be reversible: shuffle_scno(shuffle_scno(n)) == n.
*/
-#if defined(ARM) /* So far only ARM needs this */
+#if defined(ARM) || defined(AARCH64) /* So far only 32-bit ARM needs this */
static long
shuffle_scno(unsigned long scno)
{
return buf;
}
+#ifdef POWERPC
+/*
+ * PTRACE_GETREGS was added to the PowerPC kernel in v2.6.23,
+ * we provide a slow fallback for old kernels.
+ */
+static int powerpc_getregs_old(pid_t pid)
+{
+ int i;
+ long r;
+
+ if (iflag) {
+ r = upeek(pid, sizeof(long) * PT_NIP, (long *)&ppc_regs.nip);
+ if (r)
+ goto out;
+ }
+#ifdef POWERPC64 /* else we never use it */
+ r = upeek(pid, sizeof(long) * PT_MSR, (long *)&ppc_regs.msr);
+ if (r)
+ goto out;
+#endif
+ r = upeek(pid, sizeof(long) * PT_CCR, (long *)&ppc_regs.ccr);
+ if (r)
+ goto out;
+ r = upeek(pid, sizeof(long) * PT_ORIG_R3, (long *)&ppc_regs.orig_gpr3);
+ if (r)
+ goto out;
+ for (i = 0; i <= 8; i++) {
+ r = upeek(pid, sizeof(long) * (PT_R0 + i),
+ (long *)&ppc_regs.gpr[i]);
+ if (r)
+ goto out;
+ }
+ out:
+ return r;
+}
+#endif
+
#ifndef get_regs
long get_regs_error;
# if defined(ARM) \
|| defined(I386) \
|| defined(METAG) \
- || defined(OR1K)
+ || defined(OR1K) \
+ || defined(ARC)
static struct iovec io = {
.iov_base = &ARCH_REGS_FOR_GETREGSET,
.iov_len = sizeof(ARCH_REGS_FOR_GETREGSET)
get_regs(pid_t pid)
{
/* PTRACE_GETREGSET only */
-# if defined(METAG) || defined(OR1K) || defined(X32) || defined(AARCH64)
+# if defined(METAG) || defined(OR1K) || defined(X32) || defined(AARCH64) || defined(ARC)
get_regset(pid);
/* PTRACE_GETREGS only */
# elif defined(SPARC) || defined(SPARC64)
get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&sparc_regs, 0);
# elif defined(POWERPC)
+ static bool old_kernel = 0;
+ if (old_kernel)
+ goto old;
get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &ppc_regs);
+ if (get_regs_error && errno == EIO) {
+ old_kernel = 1;
+ old:
+ get_regs_error = powerpc_getregs_old(pid);
+ }
/* try PTRACE_GETREGSET first, fallback to PTRACE_GETREGS */
# else
long scno = 0;
#if defined(S390) || defined(S390X)
- if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
+ if (upeek(tcp->pid, PT_GPR2, &s390_gpr2) < 0)
return -1;
- if (syscall_mode != -ENOSYS) {
+ if (s390_gpr2 != -ENOSYS) {
/*
* Since kernel version 2.5.44 the scno gets passed in gpr2.
*/
- scno = syscall_mode;
+ scno = s390_gpr2;
} else {
/*
* Old style of "passing" the scno via the SVC instruction.
PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
};
- if (upeek(tcp, PT_PSWADDR, &psw) < 0)
+ if (upeek(tcp->pid, PT_PSWADDR, &psw) < 0)
return -1;
errno = 0;
opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(psw - sizeof(long)), 0);
tmp = 0;
offset_reg = (opcode & 0x000f0000) >> 16;
- if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
+ if (offset_reg && (upeek(tcp->pid, gpr_offset[offset_reg], &tmp) < 0))
return -1;
svc_addr += tmp;
tmp = 0;
offset_reg = (opcode & 0x0000f000) >> 12;
- if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
+ if (offset_reg && (upeek(tcp->pid, gpr_offset[offset_reg], &tmp) < 0))
return -1;
svc_addr += tmp;
# endif
tmp = 0;
offset_reg = (opcode & 0x00f00000) >> 20;
- if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
+ if (offset_reg && (upeek(tcp->pid, gpr_offset[offset_reg], &tmp) < 0))
return -1;
scno = (scno | tmp) & 0xff;
#elif defined(POWERPC)
scno = ppc_regs.gpr[0];
# ifdef POWERPC64
- int currpers;
+ unsigned int currpers;
- /* Check for 64/32 bit mode. */
- /* SF is bit 0 of MSR */
- if ((ppc_regs.msr >> 63) & 1)
- currpers = 0;
- else
- currpers = 1;
+ /*
+ * Check for 64/32 bit mode.
+ * Embedded implementations covered by Book E extension of PPC use
+ * bit 0 (CM) of 32-bit Machine state register (MSR).
+ * Other implementations use bit 0 (SF) of 64-bit MSR.
+ */
+ currpers = (ppc_regs.msr & 0x8000000080000000) ? 0 : 1;
update_personality(tcp, currpers);
# endif
#elif defined(AVR32)
scno = avr32_regs.r8;
#elif defined(BFIN)
- if (upeek(tcp, PT_ORIG_P0, &scno))
+ if (upeek(tcp->pid, PT_ORIG_P0, &scno))
return -1;
#elif defined(I386)
scno = i386_regs.orig_eax;
# ifndef __X32_SYSCALL_BIT
# define __X32_SYSCALL_BIT 0x40000000
# endif
- int currpers;
+ unsigned int currpers;
# if 1
/* GETREGSET of NT_PRSTATUS tells us regset size,
* which unambiguously detects i386.
#elif defined(IA64)
# define IA64_PSR_IS ((long)1 << 34)
long psr;
- if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
- ia32 = (psr & IA64_PSR_IS) != 0;
- if (ia32) {
- if (upeek(tcp, PT_R1, &scno) < 0)
+ if (upeek(tcp->pid, PT_CR_IPSR, &psr) >= 0)
+ ia64_ia32mode = ((psr & IA64_PSR_IS) != 0);
+ if (ia64_ia32mode) {
+ if (upeek(tcp->pid, PT_R1, &scno) < 0)
return -1;
} else {
- if (upeek(tcp, PT_R15, &scno) < 0)
+ if (upeek(tcp->pid, PT_R15, &scno) < 0)
return -1;
}
#elif defined(AARCH64)
break;
case sizeof(arm_regs):
/* We are in 32-bit mode */
+ /* Note: we don't support OABI, unlike 32-bit ARM build */
scno = arm_regs.ARM_r7;
+ scno = shuffle_scno(scno);
update_personality(tcp, 0);
break;
}
}
/* Note: we support only 32-bit CPUs, not 26-bit */
- if (arm_regs.ARM_cpsr & 0x20) {
+# if !defined(__ARM_EABI__) || ENABLE_ARM_OABI
+ if (arm_regs.ARM_cpsr & 0x20)
/* Thumb mode */
- scno = arm_regs.ARM_r7;
- } else {
- /* ARM mode */
- errno = 0;
- scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
- if (errno)
+ goto scno_in_r7;
+ /* ARM mode */
+ /* Check EABI/OABI by examining SVC insn's low 24 bits */
+ errno = 0;
+ scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
+ if (errno)
+ return -1;
+ /* EABI syscall convention? */
+ if (scno != 0xef000000) {
+ /* No, it's OABI */
+ if ((scno & 0x0ff00000) != 0x0f900000) {
+ fprintf(stderr, "pid %d unknown syscall trap 0x%08lx\n",
+ tcp->pid, scno);
return -1;
-
- /* EABI syscall convention? */
- if (scno == 0xef000000) {
- scno = arm_regs.ARM_r7; /* yes */
- } else {
- if ((scno & 0x0ff00000) != 0x0f900000) {
- fprintf(stderr, "pid %d unknown syscall trap 0x%08lx\n",
- tcp->pid, scno);
- return -1;
- }
- /* Fixup the syscall number */
- scno &= 0x000fffff;
}
+ /* Fixup the syscall number */
+ scno &= 0x000fffff;
+ } else {
+ scno_in_r7:
+ scno = arm_regs.ARM_r7;
}
-
+# else /* __ARM_EABI__ || !ENABLE_ARM_OABI */
+ scno = arm_regs.ARM_r7;
+# endif
scno = shuffle_scno(scno);
#elif defined(M68K)
- if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
+ if (upeek(tcp->pid, 4*PT_ORIG_D0, &scno) < 0)
return -1;
#elif defined(LINUX_MIPSN32)
unsigned long long regs[38];
}
}
#elif defined(MIPS)
- if (upeek(tcp, REG_A3, &mips_a3) < 0)
+ if (upeek(tcp->pid, REG_A3, &mips_a3) < 0)
return -1;
- if (upeek(tcp, REG_V0, &scno) < 0)
+ if (upeek(tcp->pid, REG_V0, &scno) < 0)
return -1;
if (!SCNO_IN_RANGE(scno)) {
}
}
#elif defined(ALPHA)
- if (upeek(tcp, REG_A3, &alpha_a3) < 0)
+ if (upeek(tcp->pid, REG_A3, &alpha_a3) < 0)
return -1;
- if (upeek(tcp, REG_R0, &scno) < 0)
+ if (upeek(tcp->pid, REG_R0, &scno) < 0)
return -1;
/*
memmove(&sparc_regs.u_regs[U_REG_O0], &sparc_regs.u_regs[U_REG_O1], 7*sizeof(sparc_regs.u_regs[0]));
}
#elif defined(HPPA)
- if (upeek(tcp, PT_GR20, &scno) < 0)
+ if (upeek(tcp->pid, PT_GR20, &scno) < 0)
return -1;
#elif defined(SH)
/*
* In the new syscall ABI, the system call number is in R3.
*/
- if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
+ if (upeek(tcp->pid, 4*(REG_REG0+3), &scno) < 0)
return -1;
if (scno < 0) {
scno = correct_scno;
}
#elif defined(SH64)
- if (upeek(tcp, REG_SYSCALL, &scno) < 0)
+ if (upeek(tcp->pid, REG_SYSCALL, &scno) < 0)
return -1;
scno &= 0xFFFF;
#elif defined(CRISV10) || defined(CRISV32)
- if (upeek(tcp, 4*PT_R9, &scno) < 0)
+ if (upeek(tcp->pid, 4*PT_R9, &scno) < 0)
return -1;
#elif defined(TILE)
- int currpers;
+ unsigned int currpers;
scno = tile_regs.regs[10];
# ifdef __tilepro__
currpers = 1;
# endif
update_personality(tcp, currpers);
#elif defined(MICROBLAZE)
- if (upeek(tcp, 0, &scno) < 0)
+ if (upeek(tcp->pid, 0, &scno) < 0)
return -1;
#elif defined(OR1K)
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)
+ if (upeek(tcp->pid, SYSCALL_NR, &scno) < 0)
return -1;
+# elif defined(ARC)
+ scno = arc_regs.scratch.r8;
#endif
tcp->scno = scno;
return 0;
}
}
-#elif defined(S390) || defined(S390X)
- /* TODO: we already fetched PT_GPR2 in get_scno
- * and stored it in syscall_mode, reuse it here
- * instead of re-fetching?
- */
- if (upeek(tcp, PT_GPR2, &gpr2) < 0)
- return -1;
- if (syscall_mode != -ENOSYS)
- syscall_mode = tcp->scno;
- if (gpr2 != syscall_mode) {
- if (debug_flag)
- fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
- return 0;
- }
#elif defined(M68K)
/* TODO? Eliminate upeek's in arches below like we did in x86 */
- if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
+ if (upeek(tcp->pid, 4*PT_D0, &m68k_d0) < 0)
return -1;
if (m68k_d0 != -ENOSYS) {
if (debug_flag)
return 0;
}
#elif defined(IA64)
- if (upeek(tcp, PT_R10, &ia64_r10) < 0)
+ if (upeek(tcp->pid, PT_R10, &ia64_r10) < 0)
return -1;
- if (upeek(tcp, PT_R8, &ia64_r8) < 0)
+ if (upeek(tcp->pid, PT_R8, &ia64_r8) < 0)
return -1;
- if (ia32 && ia64_r8 != -ENOSYS) {
+ if (ia64_ia32mode && ia64_r8 != -ENOSYS) {
if (debug_flag)
fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
return 0;
}
#elif defined(CRISV10) || defined(CRISV32)
- if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
+ if (upeek(tcp->pid, 4*PT_R10, &cris_r10) < 0)
return -1;
if (cris_r10 != -ENOSYS) {
if (debug_flag)
return 0;
}
#elif defined(MICROBLAZE)
- if (upeek(tcp, 3 * 4, µblaze_r3) < 0)
+ if (upeek(tcp->pid, 3 * 4, µblaze_r3) < 0)
return -1;
if (microblaze_r3 != -ENOSYS) {
if (debug_flag)
func = tcp->s_ent->sys_func;
if ( sys_fork == func
- || sys_vfork == func
|| sys_clone == func
) {
internal_fork(tcp);
#if defined(S390) || defined(S390X)
for (i = 0; i < nargs; ++i)
- if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
return -1;
#elif defined(ALPHA)
for (i = 0; i < nargs; ++i)
- if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, REG_A0+i, &tcp->u_arg[i]) < 0)
return -1;
#elif defined(IA64)
- if (!ia32) {
+ if (!ia64_ia32mode) {
unsigned long *out0, cfm, sof, sol;
long rbs_end;
/* be backwards compatible with kernel < 2.4.4... */
# define PT_RBS_END PT_AR_BSP
# endif
- if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
+ if (upeek(tcp->pid, PT_RBS_END, &rbs_end) < 0)
return -1;
- if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
+ if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
return -1;
sof = (cfm >> 0) & 0x7f;
PT_R13 /* EBP = out5 */};
for (i = 0; i < nargs; ++i) {
- if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, argreg[i], &tcp->u_arg[i]) < 0)
return -1;
/* truncate away IVE sign-extension */
tcp->u_arg[i] &= 0xffffffff;
if (nargs > 4) {
long sp;
- if (upeek(tcp, REG_SP, &sp) < 0)
+ if (upeek(tcp->pid, REG_SP, &sp) < 0)
return -1;
for (i = 0; i < 4; ++i)
- if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
return -1;
umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
(char *)(tcp->u_arg + 4));
} else {
for (i = 0; i < nargs; ++i)
- if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
return -1;
}
#elif defined(POWERPC)
tcp->u_arg[i] = sparc_regs.u_regs[U_REG_O0 + i];
#elif defined(HPPA)
for (i = 0; i < nargs; ++i)
- if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
return -1;
#elif defined(ARM) || defined(AARCH64)
# if defined(AARCH64)
static const int argreg[MAX_ARGS] = { PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5 };
for (i = 0; i < nargs; ++i)
- if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, argreg[i], &tcp->u_arg[i]) < 0)
return -1;
#elif defined(SH)
static const int syscall_regs[MAX_ARGS] = {
};
for (i = 0; i < nargs; ++i)
- if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, syscall_regs[i], &tcp->u_arg[i]) < 0)
return -1;
#elif defined(SH64)
int i;
static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
for (i = 0; i < nargs; ++i)
- if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
return -1;
#elif defined(I386)
(void)i;
}
#elif defined(MICROBLAZE)
for (i = 0; i < nargs; ++i)
- if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, (5 + i) * 4, &tcp->u_arg[i]) < 0)
return -1;
#elif defined(CRISV10) || defined(CRISV32)
static const int crisregs[MAX_ARGS] = {
};
for (i = 0; i < nargs; ++i)
- if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, crisregs[i], &tcp->u_arg[i]) < 0)
return -1;
#elif defined(TILE)
for (i = 0; i < nargs; ++i)
tcp->u_arg[i] = tile_regs.regs[i];
#elif defined(M68K)
for (i = 0; i < nargs; ++i)
- if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
return -1;
#elif defined(OR1K)
(void)nargs;
/* 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)
+ if (upeek(tcp->pid, REG_A_BASE + xtensaregs[i], &tcp->u_arg[i]) < 0)
return -1;
+# elif defined(ARC)
+ long *arc_args = &arc_regs.scratch.r0;
+ for (i = 0; i < nargs; ++i)
+ tcp->u_arg[i] = *arc_args--;
+
#else /* Other architecture (32bits specific) */
for (i = 0; i < nargs; ++i)
- if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
+ if (upeek(tcp->pid, i*4, &tcp->u_arg[i]) < 0)
return -1;
#endif
return 1;
goto ret;
}
+#ifdef USE_LIBUNWIND
+ if (stack_trace_enabled) {
+ if (tcp->s_ent->sys_flags & STACKTRACE_CAPTURE_ON_ENTER)
+ unwind_capture_stacktrace(tcp);
+ }
+#endif
+
printleader(tcp);
if (tcp->qual_flg & UNDEFINED_SCNO)
tprintf("%s(", undefined_scno_name(tcp));
get_syscall_result(struct tcb *tcp)
{
#if defined(S390) || defined(S390X)
- if (upeek(tcp, PT_GPR2, &gpr2) < 0)
+ if (upeek(tcp->pid, PT_GPR2, &s390_gpr2) < 0)
return -1;
#elif defined(POWERPC)
-# define SO_MASK 0x10000000
- ppc_result = ppc_regs.gpr[3];
- if (ppc_regs.ccr & SO_MASK)
- ppc_result = -ppc_result;
+ /* already done by get_regs */
#elif defined(AVR32)
/* already done by get_regs */
#elif defined(BFIN)
- if (upeek(tcp, PT_R0, &bfin_r0) < 0)
+ if (upeek(tcp->pid, PT_R0, &bfin_r0) < 0)
return -1;
#elif defined(I386)
/* already done by get_regs */
#elif defined(IA64)
# define IA64_PSR_IS ((long)1 << 34)
long psr;
- if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
- ia32 = (psr & IA64_PSR_IS) != 0;
- if (upeek(tcp, PT_R8, &ia64_r8) < 0)
+ if (upeek(tcp->pid, PT_CR_IPSR, &psr) >= 0)
+ ia64_ia32mode = ((psr & IA64_PSR_IS) != 0);
+ if (upeek(tcp->pid, PT_R8, &ia64_r8) < 0)
return -1;
- if (upeek(tcp, PT_R10, &ia64_r10) < 0)
+ if (upeek(tcp->pid, PT_R10, &ia64_r10) < 0)
return -1;
#elif defined(ARM)
/* already done by get_regs */
*/
/*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
#elif defined(M68K)
- if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
+ if (upeek(tcp->pid, 4*PT_D0, &m68k_d0) < 0)
return -1;
#elif defined(LINUX_MIPSN32)
unsigned long long regs[38];
mips_a3 = regs[REG_A3];
mips_r2 = regs[REG_V0];
#elif defined(MIPS)
- if (upeek(tcp, REG_A3, &mips_a3) < 0)
+ if (upeek(tcp->pid, REG_A3, &mips_a3) < 0)
return -1;
- if (upeek(tcp, REG_V0, &mips_r2) < 0)
+ if (upeek(tcp->pid, REG_V0, &mips_r2) < 0)
return -1;
#elif defined(ALPHA)
- if (upeek(tcp, REG_A3, &alpha_a3) < 0)
+ if (upeek(tcp->pid, REG_A3, &alpha_a3) < 0)
return -1;
- if (upeek(tcp, REG_R0, &alpha_r0) < 0)
+ if (upeek(tcp->pid, REG_R0, &alpha_r0) < 0)
return -1;
#elif defined(SPARC) || defined(SPARC64)
/* already done by get_regs */
#elif defined(HPPA)
- if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
+ if (upeek(tcp->pid, PT_GR28, &hppa_r28) < 0)
return -1;
#elif defined(SH)
/* new syscall ABI returns result in R0 */
- if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
+ if (upeek(tcp->pid, 4*REG_REG0, (long *)&sh_r0) < 0)
return -1;
#elif defined(SH64)
/* ABI defines result returned in r9 */
- if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
+ if (upeek(tcp->pid, REG_GENERAL(9), (long *)&sh64_r9) < 0)
return -1;
#elif defined(CRISV10) || defined(CRISV32)
- if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
+ if (upeek(tcp->pid, 4*PT_R10, &cris_r10) < 0)
return -1;
#elif defined(TILE)
/* already done by get_regs */
#elif defined(MICROBLAZE)
- if (upeek(tcp, 3 * 4, µblaze_r3) < 0)
+ if (upeek(tcp->pid, 3 * 4, µblaze_r3) < 0)
return -1;
#elif defined(OR1K)
/* 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)
+ if (upeek(tcp->pid, REG_A_BASE + 2, &xtensa_a2) < 0)
return -1;
+#elif defined(ARC)
+ /* already done by get_regs */
#endif
return 1;
}
syscall_fixup_on_sysexit(struct tcb *tcp)
{
#if defined(S390) || defined(S390X)
- if (syscall_mode != -ENOSYS)
- syscall_mode = tcp->scno;
if ((tcp->flags & TCB_WAITEXECVE)
- && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
+ && (s390_gpr2 == -ENOSYS || s390_gpr2 == tcp->scno)) {
/*
* Return from execve.
* Fake a return value of zero. We leave the TCB_WAITEXECVE
* flag set for the post-execve SIGTRAP to see and reset.
*/
- gpr2 = 0;
+ s390_gpr2 = 0;
}
#endif
}
check_errno = 0;
}
#if defined(S390) || defined(S390X)
- if (check_errno && is_negated_errno(gpr2)) {
+ if (check_errno && is_negated_errno(s390_gpr2)) {
tcp->u_rval = -1;
- u_error = -gpr2;
+ u_error = -s390_gpr2;
}
else {
- tcp->u_rval = gpr2;
+ tcp->u_rval = s390_gpr2;
}
#elif defined(I386)
if (check_errno && is_negated_errno(i386_regs.eax)) {
tcp->u_lrval = rax;
}
#elif defined(IA64)
- if (ia32) {
+ if (ia64_ia32mode) {
int err;
err = (int)ia64_r8;
# endif
}
#elif defined(POWERPC)
- if (check_errno && is_negated_errno(ppc_result)) {
+ if (check_errno && (ppc_regs.ccr & 0x10000000)) {
tcp->u_rval = -1;
- u_error = -ppc_result;
+ u_error = ppc_regs.gpr[3];
}
else {
- tcp->u_rval = ppc_result;
+ tcp->u_rval = ppc_regs.gpr[3];
}
#elif defined(M68K)
if (check_errno && is_negated_errno(m68k_d0)) {
else {
tcp->u_rval = xtensa_a2;
}
+#elif defined(ARC)
+ if (check_errno && is_negated_errno(arc_regs.scratch.r0)) {
+ tcp->u_rval = -1;
+ u_error = -arc_regs.scratch.r0;
+ }
+ else {
+ tcp->u_rval = arc_regs.scratch.r0;
+ }
#endif
tcp->u_error = u_error;
}
if (Tflag || cflag)
gettimeofday(&tv, NULL);
+#ifdef USE_LIBUNWIND
+ if (stack_trace_enabled) {
+ if (tcp->s_ent->sys_flags & STACKTRACE_INVALIDATE_CACHE)
+ unwind_cache_invalidate(tcp);
+ }
+#endif
+
#if SUPPORTED_PERSONALITIES > 1
update_personality(tcp, tcp->currpers);
#endif
}
if (cflag) {
- struct timeval t = tv;
- count_syscall(tcp, &t);
+ count_syscall(tcp, &tv);
if (cflag == CFLAG_ONLY_STATS) {
goto ret;
}
default:
if (u_error < 0)
tprintf("= -1 E??? (errno %ld)", u_error);
- else if (u_error < nerrnos)
+ else if ((unsigned long) u_error < nerrnos)
tprintf("= -1 %s (%s)", errnoent[u_error],
strerror(u_error));
else
case RVAL_DECIMAL:
tprintf("= %ld", tcp->u_rval);
break;
+ case RVAL_FD:
+ if (show_fd_path) {
+ tprints("= ");
+ printfd(tcp, tcp->u_rval);
+ }
+ else
+ tprintf("= %ld", tcp->u_rval);
+ break;
#if defined(LINUX_MIPSN32) || defined(X32)
/*
case RVAL_LHEX:
dumpio(tcp);
line_ended();
+#ifdef USE_LIBUNWIND
+ if (stack_trace_enabled)
+ unwind_print_stacktrace(tcp);
+#endif
+
ret:
tcp->flags &= ~TCB_INSYSCALL;
return 0;