diff options
author | Petr Machata <pmachata@redhat.com> | 2013-11-27 00:42:51 +0100 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-08-22 20:38:24 +0900 |
commit | aa74869c3945ae99033cd1c15b697f8cba9c1184 (patch) | |
tree | 599183a1306cf3dbcd50ff6b63079836ba8c3ea6 /sysdeps | |
parent | b19fc96717410a043ceab6cf9af00b4336337587 (diff) | |
download | ltrace-aa74869c3945ae99033cd1c15b697f8cba9c1184.tar.gz ltrace-aa74869c3945ae99033cd1c15b697f8cba9c1184.tar.bz2 ltrace-aa74869c3945ae99033cd1c15b697f8cba9c1184.zip |
On s390{,x}, r2 is scrambled after syscall entry
This was caught by system_call_params.exp test case:
exe->mount("source", "target", "filesystemtype", 0, nil <unfinished ...>
mount@SYS("", "target", "filesystemtype", 0, nil) = -2
<... mount resumed> = -1
Note how the first parameter disappears--r2 now holds syscall number
(21 in this case), and the original value is stored in orig_gpr2 in
save area.
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/linux-gnu/s390/fetch.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/sysdeps/linux-gnu/s390/fetch.c b/sysdeps/linux-gnu/s390/fetch.c index 0b68dbc..4ad5951 100644 --- a/sysdeps/linux-gnu/s390/fetch.c +++ b/sysdeps/linux-gnu/s390/fetch.c @@ -23,6 +23,7 @@ #include <sys/ucontext.h> #include <assert.h> #include <errno.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -61,7 +62,8 @@ s390x(struct fetch_context *ctx) } static int -fetch_register_banks(struct process *proc, struct fetch_context *ctx) +fetch_register_banks(struct process *proc, struct fetch_context *ctx, + bool syscall_enter) { ptrace_area parea; parea.len = sizeof(ctx->regs); @@ -72,15 +74,20 @@ fetch_register_banks(struct process *proc, struct fetch_context *ctx) strerror(errno)); return -1; } + + if (syscall_enter) + ctx->regs.gprs[2] = ctx->regs.orig_gpr2; + return 0; } static int -fetch_context_init(struct process *proc, struct fetch_context *context) +fetch_context_init(struct process *proc, struct fetch_context *context, + bool syscall_enter) { context->greg = 2; context->freg = 0; - return fetch_register_banks(proc, context); + return fetch_register_banks(proc, context, syscall_enter); } struct fetch_context * @@ -89,7 +96,7 @@ arch_fetch_arg_init(enum tof type, struct process *proc, { struct fetch_context *context = malloc(sizeof(*context)); if (context == NULL - || fetch_context_init(proc, context) < 0) { + || fetch_context_init(proc, context, type == LT_TOF_SYSCALL) < 0) { fprintf(stderr, "arch_fetch_arg_init: %s\n", strerror(errno)); free(context); @@ -277,7 +284,7 @@ arch_fetch_retval(struct fetch_context *ctx, enum tof type, return 0; } - if (fetch_context_init(proc, ctx) < 0) + if (fetch_context_init(proc, ctx, false) < 0) return -1; return arch_fetch_arg_next(ctx, type, proc, info, valuep); } |