]> git.eshelyaron.com Git - emacs.git/commitdiff
Port recent Android changes to mips64el
authorPo Lu <luangruo@yahoo.com>
Tue, 15 Apr 2025 08:14:14 +0000 (16:14 +0800)
committerEshel Yaron <me@eshelyaron.com>
Wed, 16 Apr 2025 07:34:42 +0000 (09:34 +0200)
* exec/config-mips.m4.in (DADDI2, DADDI3): Disable at-clobbering
by assembler macros expressly.

* exec/loader-mips64el.s: Adapt from loader-mipsel.s.

* exec/configure.ac (exec_cv_as_daddi): Properly escape reg
names.

* exec/exec.c (struct exec_jump_command, exec_0): Don't define
or set `fpu_mode' if __LP64__.

* exec/exec.h (struct exec_tracee): New field `callno'.

* exec/trace.c (process_system_call): Always record the current
system call number in TRACEE lest it should be required once it
has been overwritten upon the syscall's completion.
(seccomp_system_call): Likewise.
(after_fork): Clear `tracee->callno'.

(cherry picked from commit 5bf86e2be0693c579a43759fd1da1651344d401e)

exec/config-mips.m4.in
exec/configure.ac
exec/exec.c
exec/exec.h
exec/loader-mips64el.s
exec/trace.c

index 1c9a4c293a6991616011babf2f432a9d934494ba..4ab395ff2cb7341b934ca9604325be5ab72355a6 100644 (file)
@@ -38,7 +38,11 @@ define(`RESTORE', `ifelse(`@MIPS_N32@',`yes',`       nop',`  addi    $sp, 32')')
 define(`FP', `ifelse(`@MIPS_N32@',`yes',`$s8',`$fp')')
 
 dnl For mips64.  Some assemblers don't want to assemble `daddi'.
-define(`DADDI2', `ifelse(`@DADDI_BROKEN@',`yes',`      li      $at, $2
-dadd            $1, $1, $at',` daddi   $1, $2')')
-define(`DADDI3', `ifelse(`@DADDI_BROKEN@',`yes',`      li      $at, $3
-dadd            $1, $2, $at',` daddi   $1, $2, $3')')
+define(`DADDI2', `ifelse(`@DADDI_BROKEN@',`yes',`.set noat
+li     $at, $2
+dadd   $1, $1, $at
+.set at',`     daddi   $1, $2')')
+define(`DADDI3', `ifelse(`@DADDI_BROKEN@',`yes',`.set noat
+li     $at, $3
+dadd   $1, $2, $at
+.set at',`     daddi   $1, $2, $3')')
index d91049b8d7ba3e658ad0cc18c413bf129456e770..d462a25b9d9f1af69cc128edd7e28e3e1b626a95 100644 (file)
@@ -455,12 +455,12 @@ AS_CASE([$host], [x86_64-*linux*],
       .section text
       .global __start
 __start:
-       li      $t0, 0
-       li      $t1, 0
-       daddi   $t0, $t1, 1
-       daddi   $t0, $t1, -1
-       daddi   $t0, -1
-       daddi   $t0, 1
+       li      \$t0, 0
+       li      \$t1, 0
+       daddi   \$t0, \$t1, 1
+       daddi   \$t0, \$t1, -1
+       daddi   \$t0, -1
+       daddi   \$t0, 1
 
 _ACEOF
       $AS $ASFLAGS conftest.s -o conftest.$OBJEXT \
index b9c3e4ec92a5a831a0456e426816b0e46197891a..b83e34bc1b204e34094d1d7c1a39715cd9472390 100644 (file)
@@ -231,10 +231,10 @@ struct exec_jump_command
   /* The value of AT_BASE inside the aux vector.  */
   USER_WORD at_base;
 
-#if defined __mips__
+#if defined __mips__ && !defined __LP64__
   /* The FPU mode to apply.  Not used when !MIPS_NABI.  */
   USER_WORD fpu_mode;
-#endif /* defined __mips__ */
+#endif /* defined __mips__ && !defined __LP64__ */
 };
 
 \f
@@ -918,6 +918,7 @@ exec_0 (char *name, struct exec_tracee *tracee,
   USER_WORD header_offset;
   USER_WORD name_len, aligned_len;
   struct exec_jump_command jump;
+  /* This also encompasses !__LP64__.  */
 #if defined __mips__ && !defined MIPS_NABI
   int fpu_mode;
 #endif /* defined __mips__ && !defined MIPS_NABI */
@@ -1130,9 +1131,9 @@ exec_0 (char *name, struct exec_tracee *tracee,
     fpu_mode = FP_FRE;
 
   jump.fpu_mode = fpu_mode;
-#elif defined __mips__
+#elif defined __mips__ && !defined __LP64__
   jump.fpu_mode = 0;
-#endif /* defined __mips__ && !defined MIPS_NABI */
+#endif /* defined __mips__ && defined MIPS_NABI && !defined __LP64__ */
 
   /* The offset used for at_phdr should be that of the first
      mapping.  */
index eee48dfe2ed733eef0328dd32f9f139d01cd37be..d420061ff87096d71b84cfa28c4ff61f90b8f088 100644 (file)
@@ -152,6 +152,10 @@ struct exec_tracee
      completion.  */
   USER_WORD sp;
 
+  /* ID of the system call that is pending completion.  This value is
+     not available as the call number is overwritten on success.  */
+  USER_WORD callno;
+
   /* Name of the executable being run.  */
   char *exec_file;
 
index 1493af3c3099b131b05a97824d2276be82f4bd6c..be978d8b18b86feee7a7af051b69800d014be09d 100644 (file)
 # You should have received a copy of the GNU General Public License
 # along with GNU Emacs.         If not, see <https://www.gnu.org/licenses/>.
 
-       /* NOTE: this file is presently non-functional.  */
-
 include(`config-mips.m4')
 
+/* These "registers" alias a4-a7 and caution must be exercised not
+   to overwrite them when issuing system calls.  */
+define(`T4', `$a4')
+define(`T5', `$a5')
+define(`T6', `$a6')
+define(`T7', `$a7')
+
        .set noreorder                  # delay slots managed by hand
-       .set noat                       # no assembler macros
        .section .text
        .global __start
 __start:
-dnl    li      $v0, 5034               # SYS_nanosleep
-dnl    dla     $a0, .timespec          # rqtp
-dnl    li      $a1, 0                  # rmtp
-dnl    syscall                         # syscall
-       ld      $s2, ($sp)              # original stack pointer
+       ## li   $v0, 5034               # SYS_nanosleep
+       ## dla  $a0, timespec           # rqtp
+       ## li   $a1, 0                  # rmtp
+       ## syscall                      # syscall
+       ld      $s6, ($sp)              # original stack pointer
        DADDI3( $s0, $sp, 16)           # start of load area
        DADDI2( $sp, -16)               # primary fd, secondary fd
        li      $t0, -1                 # secondary fd
        sd      $t0, 8($sp)             # initialize secondary fd
-.next_action:
+next_action:
        ld      $s1, ($s0)              # action number
        andi    $t0, $s1, 15            # t0 = action number & 15
-       beqz    $t0, .open_file         # open file?
+       beqz    $t0, open_file          # open file?
        nop                             # delay slot
        DADDI2( $t0, -3)                # t0 -= 3
-       beqz    $t0, .rest_of_exec      # jump to code
+       beqz    $t0, rest_of_exec       # jump to code
        nop                             # delay slot
        li      $t1, 1
-       beq     $t0, $t1, .do_mmap_anon # anonymous mmap?
+       beq     $t0, $t1, do_mmap_anon  # anonymous mmap?
        nop                             # delay slot
-.do_mmap:
+do_mmap:
        ld      $t0, 8($s0)             # vm address
        ld      $t1, 16($s0)            # file_offset
        ld      $t2, 24($s0)            # protection
@@ -52,10 +56,10 @@ dnl syscall                         # syscall
        ld      $v0, 40($s0)            # flags
        ld      $v1, ($sp)              # primary fd
        andi    $s3, $s1, 16            # s1 & 16?
-       beqz    $s3, .do_mmap_1         # secondary fd?
+       beqz    $s3, do_mmap_1          # secondary fd?
        nop                             # delay slot
        ld      $v1, 8($sp)             # secondary fd
-.do_mmap_1:
+do_mmap_1:
        move    $a0, $t0                # syscall arg
        move    $a1, $t3                # syscall arg
        move    $a2, $t2                # syscall arg
@@ -64,21 +68,21 @@ dnl syscall                         # syscall
        move    $a5, $t1                # syscall arg
        li      $v0, 5009               # SYS_mmap
        syscall                         # syscall
-       bne     $a3, $zero, .perror     # perror?
+       bne     $a3, $zero, perror      # perror?
        nop                             # delay slot
        ld      $t1, 48($s0)            # clear
        dadd    $t0, $a0, $a1           # t0 = end of mapping
        dsub    $t1, $t0, $t1           # t1 = t0 - clear
-.align:
-       beq     $t0, $t1, .continue     # already finished
+align:
+       beq     $t0, $t1, continue      # already finished
        nop                             # delay slot
        andi    $t2, $t1, 7             # t1 & 7?
-       bnez    $t2, .filld             # start filling longs
+       bnez    $t2, filld              # start filling longs
        nop                             # delay slot
-.filld:
+filld:
        dsub    $t2, $t0, $t1           # t2 = t0 - t1
        sltiu   $t2, $t2, 64            # t2 < 64?
-       bne     $t2, $zero, .fillb      # fill bytes
+       bne     $t2, $zero, fillb       # fill bytes
        nop                             # delay slot
        sd      $zero, ($t1)            # zero doubleword
        DADDI2( $t1, 8)                 # next doubleword
@@ -96,140 +100,255 @@ dnl      syscall                         # syscall
        DADDI2( $t1, 8)                 # next doubleword
        sd      $zero, ($t1)            # zero doubleword
        DADDI2( $t1, 8)                 # next doubleword
-       j       .filld                  # fill either doubleword or byte
+       j       filld                   # fill either doubleword or byte
        nop                             # delay slot
-.fillb:
-       beq     $t0, $t1, .continue     # already finished?
+fillb:
+       beq     $t0, $t1, continue      # already finished?
        nop                             # delay slot
        sb      $zero, ($t1)            # clear byte
        DADDI2( $t1, 1)                 # t1++
-.continue:
+continue:
        DADDI2( $s0, 56)                # s0 = next action
-       j       .next_action            # next action
+       j       next_action             # next action
        nop                             # delay slot
-.do_mmap_anon:
+do_mmap_anon:
        ld      $t0, 8($s0)             # vm address
        ld      $t1, 16($s0)            # file_offset
        ld      $t2, 24($s0)            # protection
        ld      $t3, 32($s0)            # length
        ld      $v0, 40($s0)            # flags
-       li      $v1, -1                 # fd
-       j       .do_mmap_1              # do mmap
+       dli     $v1, -1                 # fd
+       j       do_mmap_1               # do mmap
        nop                             # branch delay slot
-.open_file:
-       li      $v0, 5002               # SYS_open
+open_file:
+       dli     $v0, 5002               # SYS_open
        DADDI3( $a0, $s0, 8)            # start of name
        move    $a1, $zero              # flags = O_RDONLY
        move    $a2, $zero              # mode = 0
        syscall                         # syscall
-       bne     $a3, $zero, .perror     # perror
+       bne     $a3, $zero, perror      # perror
        nop                             # delay slot
        DADDI2( $s0, 8)                 # start of string
        move    $t3, $s0                # t3 = s0
-.nextc:
+nextc:
        lb      $t0, ($s0)              # load byte
        DADDI2( $s0, 1)                 # s0++
-       li      $t1, 47                 # directory separator `/'
-       bne     $t0, $t1, .nextc1       # is separator char?
+       dli     $t1, 47                 # directory separator `/'
+       bne     $t0, $t1, nextc1        # is separator char?
        nop                             # delay slot
        move    $t3, $s0                # t3 = char past separator
-.nextc1:
-       bnez    $t0, .nextc             # next character?
+nextc1:
+       bnez    $t0, nextc              # next character?
        nop                             # delay slot
        DADDI2( $s0, 7)                 # adjust for round
-       li      $t2, -8                 # t2 = -8
+       dli     $t2, -8                 # t2 = -8
        and     $s0, $s0, $t2           # mask for round
        andi    $t0, $s1, 16            # t1 = s1 & 16
        move    $t1, $sp                # address of primary fd
-       beqz    $t0, .primary           # primary fd?
+       beqz    $t0, primary            # primary fd?
        nop                             # delay slot
        DADDI2( $t1, 8)                 # address of secondary fd
        sd      $v0, ($t1)              # store fd
-       j       .next_action            # next action
+       j       next_action             # next action
        nop                             # delay slot
-.primary:
+primary:
        sd      $v0, ($t1)              # store fd
-       li      $v0, 5153               # SYS_prctl
-       li      $a0, 15                 # PR_SET_NAME
+       dli     $v0, 5153               # SYS_prctl
+       dli     $a0, 15                 # PR_SET_NAME
        move    $a1, $t3                # char past separator
        move    $a2, $zero              # a2
        move    $a3, $zero              # a3
        move    $a4, $zero              # a4
        move    $a5, $zero              # a5
        syscall                         # syscall
-       j       .next_action            # next action
+       j       next_action             # next action
        nop                             # delay slot
-.perror:
+perror:
        move    $a0, $v0                # errno
-       li      $v0, 5058               # SYS_exit
+       dli     $v0, 5058               # SYS_exit
        syscall                         # syscall
-.rest_of_exec:
-       move    $s1, $s2                # original SP
+rest_of_exec:
+       move    $s1, $s6                # original SP
        ld      $t0, ($s1)              # argc
        dsll    $t0, $t0, 3             # argc *= 8
        DADDI2( $t0, 16)                # argc += 16
        dadd    $s1, $s1, $t0           # s1 = start of envp
-.skipenv:
-       ld      $t0, ($s1)              # t0 = *s1
-       DADDI2( $s1, 8)                 # s1++
-       bne     $t0, $zero, .skipenv    # skip again
-       nop                             # delay slot
-       dla     $t3, .auxvtab           # address of auxv table
-.one_auxv:
-       ld      $t0, ($s1)              # t0 = auxv type
-       li      $t1, 10                 # t1 = 10
-       beqz    $t0, .finish            # is AT_IGNORE?
-       nop                             # delay slot
-       sltu    $t1, $t0, $t1           # t1 = t0 < num offsets
-       beqz    $t1, .next              # next auxv
-       nop                             # delay slot
-       dsll    $t1, $t0, 2             # t1 = t0 * 4
-       dadd    $t1, $t3, $t1           # t1 = .auxvtab + t1
-       lw      $t2, ($t1)              # t2 = *t1
-       beqz    $t2, .next              # skip auxv
-       nop                             # delay slot
-       dadd    $t2, $s0, $t2           # t2 = s0 + t2
-       ld      $t2, ($t2)              # t2 = *t2
-       sd      $t2, 8($s1)             # set auxv value
-.next:
-       DADDI2( $s1, 16)                # next auxv
-       j       .one_auxv               # next auxv
-       nop                             # delay slot
-.finish:
-       ld      $t0, 8($sp)             # secondary fd
+skip_environ:
+       /* Locate the auxiliary vector.  */
+1:     ld      $t0, ($s1)              # t0 = *s1
+       bnez    $t0, 1b                 # skip environment entry
+       daddi   $s1, $s1, 8             # s1++
+       move    $s2, $s1                # s2 = end of environment
+1:     ld      $t0, ($s1)              # t0 = s1->a_type
+       bnez    $t0, 1b                 # skip auxiliary vector entry
+       daddi   $s1, $s1, 16            # (Elf64_auxv_t *) s1++
+       /* Decide how many bytes must be copied and where to
+          save the file name.  Move the stack pointer to a safe
+          position below any data that must be preserved.  */
+       ld      $t1, 56($s0)            # length of string
+       DADDI2( $t1, 1)
+       DADDI3( $t2, $s0, 64)           # pointer to string
+       dsub    $t3, $s1, $s6           # number of bytes in vectors
+       dsub    $t0, $s1, $t1           # position of string
+       and     $t0, $t0, -16           # align value
+       dsub    $t3, $t0, $t3           # position of argc
+       and     $t3, $t3, -16           # align value
+       /* Move the stack pointer and save required information.
+          8($fp)   = secondary/interpreter fd.
+          0($fp)   = primary/executable fd.
+          -8($fp)  = cmd->entry
+          -16($fp) = cmd->at_entry
+          -24($fp) = cmd->at_phent
+          -32($fp) = cmd->at_phnum
+          -40($fp) = cmd->at_phdr
+          -48($fp) = cmd->at_base
+       $sp = copy of string.  */
+       move    T4, $sp                 # current sp
+       dsub    T5, $t3, $sp            # new argc - current sp
+       blt     T5, 16, 1f              # more than two slots apart
+       dadd    $sp, $t3, -16           # $sp = two slots below new argc
+       j       2f                      # skip copying fds
+       move    $sp, T4                 # retain current sp
+1:     ld      T5, (T4)                # old primary fd
+       ld      T5, ($sp)               # save the same
+       ld      T5, 8(T4)               # old interpreter fd
+       sd      T5, 8($sp)              # save the same
+2:     move    $fp, $sp                # set base pointer
+       DADDI2( $sp, -48)               # command data
+       ld      T5, 8($s0)              # entry
+       ld      T6, 16($s0)             # at_entry
+       ld      T7, 24($s0)             # at_phent
+       ld      $t8, 32($s0)            # at_phnum
+       sd      T5, -8($fp)             # save entry
+       ld      T5, 40($s0)             # at_phdr
+       sd      T6, -16($fp)            # save at_entry
+       ld      T6, 48($s0)             # at_base
+       sd      T7, -24($fp)            # save at_phent
+       sd      $t8, -32($fp)           # save at_phnum
+       sd      T5, -40($fp)            # save at_phdr
+       sd      T6, -48($fp)            # save at_base
+       dsub    $sp, $sp, $t1           # space for string
+       /* Save the input string.  */
+       dadd    T5, $t2, $t1            # end of source ($t2)
+       move    T6, $sp                 # dst
+       move    $s0, $t1                # $s0 = length of string
+       /* src = $t2, dst = T6 */
+       bgeu    $t2, T5, 2f             # there already?
+       nop
+1:     lb      $t1, ($t2)              # $t1 = *$t2
+       DADDI2( $t2, 1)                 # $t2++
+       DADDI2( T6, 1)                  # $t6++
+       bltu    $t2, T5, 1b
+       sb      $t1, -1(T6)             # *(T6 - 1) = $t1
+2:     move    $s3, $sp                # copy of string
+       and     $sp, $sp, -16           # align stack
+copy_env_and_args:
+       /* Copy argc, argv, and the environment array.
+          T4 = destination, T5 = src, $s2 = src_end  */
+       move    T4, $t3                 # destination of argc
+       move    T5, $s6                 # original SP
+       bgeu    T5, $s2, 2f             # there already?
+       nop
+1:     ld      $t1, (T5)               # $t1 = *src
+       DADDI2( T5, 8)                  # src++
+       DADDI2( T4, 8)                  # dst++
+       bltu    T5, $s2, 1b             # src < src_end
+       sd      $t1, -8(T4)             # *(dst - 8) = $t1
+copy_auxv:
+       /* T4 = destination, T5 = first auxval.  */
+2:     ld      $t1, (T5)               # a_type
+       ld      $t2, 8(T5)              # a_un.a_val
+       DADDI2( T4, 16)                 # (Elf64_auxv_t *) dst++
+       DADDI2( T5, 16)                 # (Elf64_auxv_t *) src
+       beqz    $t1, 8f                 # AT_NULL
+       li      T6, 3
+       beq     $t1, T6, 1f             # AT_PHDR
+       li      T6, 4
+       beq     $t1, T6, 2f             # AT_PHENT
+       li      T6, 5
+       beq     $t1, T6, 3f             # AT_PHNUM
+       li      T6, 9
+       beq     $t1, T6, 4f             # AT_ENTRY
+       li      T6, 7
+       beq     $t1, T6, 5f             # AT_BASE
+       li      T6, 31
+       beq     $t1, T6, 6f             # AT_EXECFN
+       nop
+       b       7f
+       nop
+1:     b       7f
+       ld      $t2, -40($fp)
+2:     b       7f
+       ld      $t2, -24($fp)
+3:     b       7f
+       ld      $t2, -32($fp)
+4:     b       7f
+       ld      $t2, -16($fp)
+5:     b       7f
+       ld      $t2, -48($fp)
+6:     b       7f
+       move    $t2, $t0
+7:     sd      $t1, -16(T4)            # dst->a_type
+       j       copy_auxv
+       sd      $t2, -8(T4)             # dst->a_un.a_val
+       /* Copy the final element.  */
+8:     sd      $t1, -16(T4)            # dst->a_type
+       sd      $t2, -8(T4)             # dst->a_un.a_val
+finish:
+       /* Copy the string to its position in auxv
+          (src = $s3, dst = $t0).  */
+       dadd    $t1, $s3, $s0           # src end
+       bgeu    $s3, $t1, 2f            # there already?
+       nop
+1:     lb      $t2, ($s3)              # c = *src
+       DADDI2( $s3, 1)                 # src++
+       DADDI2( $t0, 1)                 # dst++
+       bltu    $s3, $t1, 1b
+       sb      $t2, -1($t0)            # *(dst - 1) = c
+       /* Save variables.  */
+2:     move    $s6, $t3                # new stack pointer
+       ld      $t0, 8($fp)             # secondary fd
        li      $t1, -1                 # t1 = -1
-       ld      $s1, ($sp)              # s1 = primary fd
+       ld      $s1, ($fp)              # s1 = primary fd
+       beq     $t0, $t2, finish1       # secondary fd set?
        li      $v0, 5003               # SYS_close
-       beq     $t0, $t2, .finish1      # secondary fd set?
-       nop                             # delay slot
        move    $a0, $t0                # secondary fd
        syscall                         # syscall
        li      $v0, 5003               # SYS_close
-.finish1:
+finish1:
        move    $a0, $s1                # primary fd
        syscall                         # syscall
-.jump:
+jump:
        move    $v0, $zero              # rtld_fini
-       ld      $t0, 8($s0)             # entry
-       move    $sp, $s2                # restore stack pointer, delay slot
-       jr      $t0                     # enter
-       nop                             # delay slot
+       ld      $t9, -8($fp)            # entry
+       move    $sp, $s6                # restore stack pointer, delay slot
+        /* Clear at least one page's worth of stack.  glibc on mipsel
+          copies certain fields from the stack to the `link_map'
+          structure representing ld.so, which are not subsequently
+          replaced if otherwise than zero.
 
-.auxvtab:
-       .long   0                       # 0
-       .long   0                       # 1
-       .long   0                       # 2
-       .long   40                      # 3 AT_PHDR
-       .long   24                      # 4 AT_PHENT
-       .long   32                      # 5 AT_PHNUM
-       .long   0                       # 6
-       .long   48                      # 7 AT_BASE
-       .long   0                       # 8
-       .long   16                      # 9 AT_ENTRY
+          XXX: report this glibc bug?  */
+       DADDI3( $v0, $sp, -4096)
+       and     $v0, $v0, -4095
+1:     sd      $zero, ($v0)            # copy 32 byte blocks
+       sd      $zero, 8($v0)
+       sd      $zero, 16($v0)
+       sd      $zero, 24($v0)
+       DADDI2( $v0, 32)
+       dsub    $t0, $sp, $v0           # remainder
+       bge     $t0, 32, 1b             # test remainder
+       nop                             # copy 4 byte blocks
+       beqz    $t0, 2f
+       nop
+1:     DADDI2( $v0, 4)
+       bltu    $v0, $sp, 1b
+       sw      $zero, -4($v0)
+2:     jr      $t9                     # enter
+       nop                             # delay slot
 
-.timespec:
-       .quad   10
-       .quad   10
+## timespec:
+##     .quad   10
+##     .quad   10
 
 # Local Variables:
 # asm-comment-char: ?#
index 753c78994f268bdda338a2b39181cd63bd456069..61e8d5542f9c43fa5e958125b2fed55197fd29ca 100644 (file)
@@ -1237,7 +1237,11 @@ process_system_call (struct exec_tracee *tracee)
      set, this must be exec, whatever the value of SYSCALL_NUM_REG,
      which is erased when exec loads another image.  */
 
-  callno = (!tracee->exec_data ? regs.SYSCALL_NUM_REG : EXEC_SYSCALL);
+  callno = (!tracee->exec_data
+           ? (!tracee->waiting_for_syscall
+              ? regs.SYSCALL_NUM_REG : tracee->callno)
+           : EXEC_SYSCALL);
+  tracee->callno = callno;
   switch (callno)
     {
     case EXEC_SYSCALL:
@@ -1644,6 +1648,11 @@ seccomp_system_call (struct exec_tracee *tracee)
 
   /* Now dispatch based on the system call.  */
   callno = regs.SYSCALL_NUM_REG;
+
+  /* Record the call number, which may be required if one of the
+     following handlers should arrange for process_system_call to
+     intercede after the system call completes.  */
+  tracee->callno = callno;
   switch (callno)
     {
     case EXEC_SYSCALL:
@@ -1706,7 +1715,7 @@ seccomp_system_call (struct exec_tracee *tracee)
       if (rc < 0)
        return;
 
-      tracee->waiting_for_syscall = !tracee->waiting_for_syscall;
+      tracee->waiting_for_syscall = true;
       break;
 
     default:
@@ -2024,6 +2033,7 @@ after_fork (pid_t pid)
     return 1;
 
   tracee->pid = pid;
+  tracee->callno = 0;
   tracee->next = tracing_processes;
   tracee->waiting_for_syscall = false;
   tracee->new_child = false;