diff mbox series

[2/5] linux-user/i386: Emulate orig_ax

Message ID 20240802095942.34565-3-iii@linux.ibm.com
State New
Headers show
Series linux-user/i386: Emulate orig_ax | expand

Commit Message

Ilya Leoshkevich Aug. 2, 2024, 9:59 a.m. UTC
The kernel uses orig_rax/orig_eax to store the syscall number before
a syscall. One can see this value in core dumps and ptrace.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
 linux-user/elfload.c       | 4 ++--
 linux-user/i386/cpu_loop.c | 3 +++
 linux-user/qemu.h          | 5 +++++
 3 files changed, 10 insertions(+), 2 deletions(-)

Comments

Richard Henderson Sept. 8, 2024, 8:50 p.m. UTC | #1
On 8/2/24 02:59, Ilya Leoshkevich wrote:
> diff --git a/linux-user/qemu.h b/linux-user/qemu.h
> index a2961f503f4..85ba5a53869 100644
> --- a/linux-user/qemu.h
> +++ b/linux-user/qemu.h
> @@ -159,6 +159,11 @@ struct TaskState {
>   
>       /* Start time of task after system boot in clock ticks */
>       uint64_t start_boottime;
> +
> +#if defined(TARGET_I386)
> +    /* Last syscall number. */
> +    target_ulong orig_ax;
> +#endif

Maybe place this higher, in the existing TARGET_I386 block?

Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~
diff mbox series

Patch

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 05292c27776..2d73382ae6b 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -203,7 +203,7 @@  static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
     (*regs)[12] = tswapreg(env->regs[R_EDX]);
     (*regs)[13] = tswapreg(env->regs[R_ESI]);
     (*regs)[14] = tswapreg(env->regs[R_EDI]);
-    (*regs)[15] = tswapreg(env->regs[R_EAX]); /* XXX */
+    (*regs)[15] = tswapreg(get_task_state(env_cpu_const(env))->orig_ax);
     (*regs)[16] = tswapreg(env->eip);
     (*regs)[17] = tswapreg(env->segs[R_CS].selector & 0xffff);
     (*regs)[18] = tswapreg(env->eflags);
@@ -306,7 +306,7 @@  static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
     (*regs)[8] = tswapreg(env->segs[R_ES].selector & 0xffff);
     (*regs)[9] = tswapreg(env->segs[R_FS].selector & 0xffff);
     (*regs)[10] = tswapreg(env->segs[R_GS].selector & 0xffff);
-    (*regs)[11] = tswapreg(env->regs[R_EAX]); /* XXX */
+    (*regs)[11] = tswapreg(get_task_state(env_cpu_const(env))->orig_ax);
     (*regs)[12] = tswapreg(env->eip);
     (*regs)[13] = tswapreg(env->segs[R_CS].selector & 0xffff);
     (*regs)[14] = tswapreg(env->eflags);
diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c
index 92beb6830cc..7a35215278a 100644
--- a/linux-user/i386/cpu_loop.c
+++ b/linux-user/i386/cpu_loop.c
@@ -172,6 +172,7 @@  static void emulate_vsyscall(CPUX86State *env)
     /*
      * Perform the syscall.  None of the vsyscalls should need restarting.
      */
+    get_task_state(env_cpu(env))->orig_ax = syscall;
     ret = do_syscall(env, syscall, env->regs[R_EDI], env->regs[R_ESI],
                      env->regs[R_EDX], env->regs[10], env->regs[8],
                      env->regs[9], 0, 0);
@@ -221,6 +222,7 @@  void cpu_loop(CPUX86State *env)
         case EXCP_SYSCALL:
 #endif
             /* linux syscall from int $0x80 */
+            get_task_state(cs)->orig_ax = env->regs[R_EAX];
             ret = do_syscall(env,
                              env->regs[R_EAX],
                              env->regs[R_EBX],
@@ -239,6 +241,7 @@  void cpu_loop(CPUX86State *env)
 #ifdef TARGET_X86_64
         case EXCP_SYSCALL:
             /* linux syscall from syscall instruction.  */
+            get_task_state(cs)->orig_ax = env->regs[R_EAX];
             ret = do_syscall(env,
                              env->regs[R_EAX],
                              env->regs[R_EDI],
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index a2961f503f4..85ba5a53869 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -159,6 +159,11 @@  struct TaskState {
 
     /* Start time of task after system boot in clock ticks */
     uint64_t start_boottime;
+
+#if defined(TARGET_I386)
+    /* Last syscall number. */
+    target_ulong orig_ax;
+#endif
 };
 
 abi_long do_brk(abi_ulong new_brk);