summaryrefslogtreecommitdiff
path: root/syscall.c
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2013-02-05 17:48:33 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2013-02-05 17:48:33 +0100
commit0b99a8ac3bf6314bc92ab528b3849ab3faf7bf4c (patch)
tree5776b0ee3153cac54261e18d7ac5b4e3f2fab6ba /syscall.c
parent4645582edbbc6c3605904634de7bcb9b0b4f0ef2 (diff)
downloadstrace-0b99a8ac3bf6314bc92ab528b3849ab3faf7bf4c.tar.gz
strace-0b99a8ac3bf6314bc92ab528b3849ab3faf7bf4c.tar.bz2
strace-0b99a8ac3bf6314bc92ab528b3849ab3faf7bf4c.tar.xz
Add tilegx support to strace
tilegx support has been in the kernel since 3.0. In addition, fix some issues with the tilepro support already present in strace, primarily the decision to use the <asm/unistd.h> numbering space for system calls. * defs.h [TILE]: Include <asm/ptrace.h> and provide an extern struct pt_regs tile_regs for efficiency. Provide compat 32-bit personality via SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE, PERSONALITY1_WORDSIZE, and DEFAULT_PERSONALITY. * linux/tile/errnoent1.h: New file, includes linux/errnoent.h. * linux/tile/ioctlent1.h: New file, includes linux/ioctlent.h. * linux/tile/signalent1.h: New file, includes linux/signalent.h. * linux/tile/syscallent.h: Update with new asm-generic syscalls. The version previously committed was the from the first tile patch to LKML, which subsequently was changed to use <asm-generic/unistd.h>. * linux/tile/syscallent1.h: Copy from linux/tile/syscallent.h. * mem.c (addtileflags) [TILE]: use %ld properly for a "long" variable. * process.c [TILE]: Choose clone arguments correctly and properly suppress all "struct user" related offsets in user_struct_offsets. * signal.c [TILE]: Use tile_regs not upeek. * syscall.c (update_personality) [TILE]: Print mode. (PT_FLAGS_COMPAT) [TILE]: Provide if not in system headers. (tile_regs) [TILE]: Define 'struct pt_regs' variable to hold state. (get_regs) [TILE]: use PTRACE_GETREGS to set tile_regs rather than using upeek. (get_scno) [TILE]: Set personality. (get_syscall_args) [TILE]: Use tile_regs. (get_syscall_result) [TILE]: Update tile_regs. (get_error) [TILE]: Use tile_regs. (printcall) [TILE]: Print pc. (arg0_offset, arg1_offset, restore_arg0, restore_arg1) [TILE]: Properly handle tile call semantics and support tilegx. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'syscall.c')
-rw-r--r--syscall.c65
1 files changed, 53 insertions, 12 deletions
diff --git a/syscall.c b/syscall.c
index c31233c..cd3647d 100644
--- a/syscall.c
+++ b/syscall.c
@@ -71,6 +71,12 @@
# include <elf.h>
#endif
+#if defined(TILE)
+# ifndef PT_FLAGS_COMPAT
+# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
+# endif
+#endif
+
#ifndef ERESTARTSYS
# define ERESTARTSYS 512
#endif
@@ -293,6 +299,12 @@ update_personality(struct tcb *tcp, int personality)
fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
tcp->pid, names[personality]);
}
+# elif defined(TILE)
+ if (!qflag) {
+ static const char *const names[] = {"64-bit", "32-bit"};
+ fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
+ tcp->pid, names[personality]);
+ }
# endif
}
#endif
@@ -699,6 +711,8 @@ static long r0;
static long r9;
#elif defined(CRISV10) || defined(CRISV32)
static long r10;
+#elif defined(TILE)
+struct pt_regs tile_regs;
#elif defined(MICROBLAZE)
static long r3;
#endif
@@ -829,6 +843,12 @@ printcall(struct tcb *tcp)
return;
}
tprintf("[%08lx] ", pc);
+#elif defined(TILE)
+# ifdef _LP64
+ tprintf("[%16lx] ", tile_regs.pc);
+# else
+ tprintf("[%08lx] ", tile_regs.pc);
+# endif
#endif /* architecture */
}
@@ -865,6 +885,8 @@ void get_regs(pid_t pid)
get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&regs);
# elif defined(SPARC) || defined(SPARC64)
get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&regs, 0);
+# elif defined(TILE)
+ get_regs_error = ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &tile_regs);
# endif
}
#endif
@@ -1289,8 +1311,25 @@ get_scno(struct tcb *tcp)
if (upeek(tcp, 4*PT_R9, &scno) < 0)
return -1;
#elif defined(TILE)
- if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
- return -1;
+ int currpers;
+ scno = tile_regs.regs[10];
+# ifdef __tilepro__
+ currpers = 1;
+# else
+ if (tile_regs.flags & PT_FLAGS_COMPAT)
+ currpers = 1;
+ else
+ currpers = 0;
+# endif
+ update_personality(tcp, currpers);
+
+ if (!(tcp->flags & TCB_INSYSCALL)) {
+ /* Check if we return from execve. */
+ if (tcp->flags & TCB_WAITEXECVE) {
+ tcp->flags &= ~TCB_WAITEXECVE;
+ return 0;
+ }
+ }
#elif defined(MICROBLAZE)
if (upeek(tcp, 0, &scno) < 0)
return -1;
@@ -1664,8 +1703,7 @@ get_syscall_args(struct tcb *tcp)
return -1;
#elif defined(TILE)
for (i = 0; i < nargs; ++i)
- if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
- return -1;
+ 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)
@@ -1865,6 +1903,7 @@ get_syscall_result(struct tcb *tcp)
if (upeek(tcp, 4*PT_R10, &r10) < 0)
return -1;
#elif defined(TILE)
+ /* already done by get_regs */
#elif defined(MICROBLAZE)
if (upeek(tcp, 3 * 4, &r3) < 0)
return -1;
@@ -2089,15 +2128,17 @@ get_error(struct tcb *tcp)
tcp->u_rval = r10;
}
#elif defined(TILE)
- long rval;
- if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
- return -1;
- if (check_errno && rval < 0 && rval > -nerrnos) {
+ /*
+ * The standard tile calling convention returns the value (or negative
+ * errno) in r0, and zero (or positive errno) in r1.
+ * Until at least kernel 3.8, however, the r1 value is not reflected
+ * in ptregs at this point, so we use r0 here.
+ */
+ if (check_errno && is_negated_errno(tile_regs.regs[0])) {
tcp->u_rval = -1;
- u_error = -rval;
- }
- else {
- tcp->u_rval = rval;
+ u_error = -tile_regs.regs[0];
+ } else {
+ tcp->u_rval = tile_regs.regs[0];
}
#elif defined(MICROBLAZE)
if (check_errno && is_negated_errno(r3)) {