[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] linux-user: Fix indirect syscall handling for MIPS
From: |
An-Cheng Huang |
Subject: |
[Qemu-devel] [PATCH] linux-user: Fix indirect syscall handling for MIPS |
Date: |
Thu, 4 Aug 2011 15:16:00 -0700 |
User-agent: |
Mutt/1.5.20 (2009-06-14) |
I ran into the problem of indirect syscalls not working with mips-linux-user
and found that the number of arguments for sys_syscall is 0 in the
mips_syscall_args table, which means the "higher" arguments (5, 6, 7, and 8)
are never obtained from the stack for the do_syscall() invocation for indirect
syscalls. So the actual syscall will not get the correct argument(s) if it
needs more than three.
The patch checks for indirect syscall and in such cases uses the actual syscall
number to look up the number of arguments so that the actual arguments can be
taken from the stack.
A simpler approach would be to just change the number of arguments for
sys_syscall to 8 in the mips_syscall_args table so that for indirect syscalls
the "higher" arguments are always taken from the stack with get_user_ual().
However, since there is a comment about "what to do if get_user() fails", I
don't know if this may cause breakage when the arguments are not actually
there? If someone can confirm that this is harmless, the simple approach is
probably better? Thanks.
Signed-off-by: An-Cheng Huang <address@hidden>
---
linux-user/main.c | 21 ++++++++++++++++++---
1 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 6a8f4bd..1560c1c 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2068,27 +2068,42 @@ static int do_store_exclusive(CPUMIPSState *env)
void cpu_loop(CPUMIPSState *env)
{
target_siginfo_t info;
int trapnr, ret;
unsigned int syscall_num;
+ unsigned int syscall_idx;
+ unsigned int real_syscall_idx; /* only for indirect syscall */
for(;;) {
cpu_exec_start(env);
trapnr = cpu_mips_exec(env);
cpu_exec_end(env);
switch(trapnr) {
case EXCP_SYSCALL:
- syscall_num = env->active_tc.gpr[2] - 4000;
+ syscall_num = env->active_tc.gpr[2];
+ syscall_idx = syscall_num - 4000;
+ real_syscall_idx = env->active_tc.gpr[4] - 4000;
env->active_tc.PC += 4;
- if (syscall_num >= sizeof(mips_syscall_args)) {
+ if (syscall_idx >= sizeof(mips_syscall_args)
+ || (syscall_num == TARGET_NR_syscall
+ && real_syscall_idx >= sizeof(mips_syscall_args))) {
+ /* invalid direct or indirect syscalls */
ret = -TARGET_ENOSYS;
} else {
int nb_args;
abi_ulong sp_reg;
abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
- nb_args = mips_syscall_args[syscall_num];
+ if (syscall_num == TARGET_NR_syscall) {
+ /* indirect syscall, so need to look at the real
+ * syscall to figure out nb_args. also, plus 1 is
+ * needed to account for the indirect syscall itself.
+ */
+ nb_args = mips_syscall_args[real_syscall_idx] + 1;
+ } else {
+ nb_args = mips_syscall_args[syscall_idx];
+ }
sp_reg = env->active_tc.gpr[29];
switch (nb_args) {
/* these arguments are taken from the stack */
/* FIXME - what to do if get_user() fails? */
case 8: get_user_ual(arg8, sp_reg + 28);
- [Qemu-devel] [PATCH] linux-user: Fix indirect syscall handling for MIPS,
An-Cheng Huang <=