]> git.eshelyaron.com Git - emacs.git/commitdiff
Port recent changes to mipsel systems
authorPo Lu <luangruo@yahoo.com>
Mon, 14 Apr 2025 13:28:15 +0000 (21:28 +0800)
committerEshel Yaron <me@eshelyaron.com>
Wed, 16 Apr 2025 07:34:27 +0000 (09:34 +0200)
* exec/exec.c (exec_0): Don't disable AT_EXECFN substitution on
MIPS systems.

* exec/loader-aarch64.s (skip_environ): Correct typo in
commentary.

* exec/loader-mips64el.s: Add a disclaimer that this file is
currently inoperable.

* exec/loader-mipsel.s (__start): Move environment and argument
vectors and produce and replace AT_EXECFN.  Clear stack before
proceeding to circumvent an oversight in glibc.

(cherry picked from commit 74df372398dbc90f6c0185f1701af28129073de7)

exec/config-mips.m4.in
exec/exec.c
exec/loader-aarch64.s
exec/loader-mips64el.s
exec/loader-mipsel.s

index c42bbbad2ec6826c9ce8bde8bdccdae868bcda6e..1c9a4c293a6991616011babf2f432a9d934494ba 100644 (file)
@@ -18,6 +18,7 @@ dnl  You should have received a copy of the GNU General Public License
 dnl  along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 define(`SYSCALL_open', `ifelse(`@MIPS_N32@',`yes',`6002',`4005')')
+dnl define(`SYSCALL_openat', `ifelse(`@MIPS_N32@',`yes',`6251',`4288')')
 define(`SYSCALL_close', `ifelse(`@MIPS_N32@',`yes',`6003',`4006')')
 define(`SYSCALL_mmap', `ifelse(`@MIPS_N32@',`yes',`6009',`4090')')
 define(`SYSCALL_nanosleep', `ifelse(`@MIPS_N32@',`yes',`6034',`4166')')
@@ -34,6 +35,7 @@ define(`SYSCALL', `ifelse(`@MIPS_N32@',`yes',`        move    $a4, $1
        sw      $4, 28($sp)')')
 
 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
index 7a8ef2c3a1a47b6743458a86755b21f9cfd33c4d..b9c3e4ec92a5a831a0456e426816b0e46197891a 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__ && !defined MIPS_NABI
-  /* The FPU mode to apply.  */
+#if defined __mips__
+  /* The FPU mode to apply.  Not used when !MIPS_NABI.  */
   USER_WORD fpu_mode;
-#endif /* defined __mips__ && !defined MIPS_NABI */
+#endif /* defined __mips__ */
 };
 
 \f
@@ -916,9 +916,7 @@ exec_0 (char *name, struct exec_tracee *tracee,
   program_header program;
   USER_WORD entry, program_entry, offset;
   USER_WORD header_offset;
-#ifndef __mips__
   USER_WORD name_len, aligned_len;
-#endif /* !__mips__ */
   struct exec_jump_command jump;
 #if defined __mips__ && !defined MIPS_NABI
   int fpu_mode;
@@ -1132,6 +1130,8 @@ exec_0 (char *name, struct exec_tracee *tracee,
     fpu_mode = FP_FRE;
 
   jump.fpu_mode = fpu_mode;
+#elif defined __mips__
+  jump.fpu_mode = 0;
 #endif /* defined __mips__ && !defined MIPS_NABI */
 
   /* The offset used for at_phdr should be that of the first
@@ -1149,8 +1149,6 @@ exec_0 (char *name, struct exec_tracee *tracee,
          sizeof jump);
   loader_area_used += sizeof jump;
 
-  /* TODO: MIPS support.  */
-#ifndef __mips__
   /* Copy the length of NAME and NAME itself to the loader area.  */
   name_len = strlen (name);
   aligned_len = ((name_len + 1 + sizeof name_len - 1)
@@ -1167,7 +1165,6 @@ exec_0 (char *name, struct exec_tracee *tracee,
   offset = aligned_len - (name_len + 1);
   while (offset--)
     loader_area[loader_area_used++] = '\0';
-#endif /* !__mips__ */
 
   /* Close the file descriptor and return the number of bytes
      used.  */
index 376f439417f7bff5645fd727a2fc596f10a7f4ff..d3c565bf3f8d4a94da597b4d9bb145036f167c1f 100644 (file)
@@ -144,7 +144,7 @@ skip_environ:
        and     x7, x7, -8              // align value
        add     x4, x7, x4              // destination argc
        and     x4, x4, -16             // align destination argc
-       // Load values that must be into registers x14-x19.
+       // Load values that must be preserved into registers x14-x19.
        // x14 = cmd->entry
        // x15 = cmd->at_entry
        // x16 = cmd->at_phent
index 491b7ccfb603024ce2bf4ebabd152a7e7287dafc..1493af3c3099b131b05a97824d2276be82f4bd6c 100644 (file)
@@ -15,6 +15,8 @@
 # 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')
 
        .set noreorder                  # delay slots managed by hand
index 9ffe7e928e74d2a7603d09855d2fa80651ccf1c8..bf90493e726c1484babacb1064019a5b7fd19561 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/>.
 
-include(`config-mips.m4')
+       include(`config-mips.m4')
 
-# Make sure not to use t4 through t7, in order to maintain portability
-# with N32 ABI systems.
+## Beware: $t0-$t4 alias the syscall (and function, but they are not
+## material in this context) argument registers on N32 systems, and
+## mustn't be relied upon to hold arguments to `SYSCALL'.
 
        .set noreorder                  # delay slots managed by hand
        .section .text
        .global __start
 __start:
-dnl    li      $v0, SYSCALL_nanosleep  # SYS_nanosleep
-dnl    la      $a0, .timespec          # rqtp
-dnl    li      $a1, 0                  # rmtp
-dnl    syscall                         # syscall
+       ## li   $v0, SYSCALL_nanosleep  # SYS_nanosleep
+       ## la   $a0, timespec           # rqtp
+       ## li   $a1, 0                  # rmtp
+       ## syscall                              # syscall
        lw      $s6, ($sp)              # original stack pointer
        addi    $s0, $sp, 8             # start of load area
        addi    $sp, -8                 # primary fd, secondary fd
        li      $t0, -1                 # secondary fd
        sw      $t0, 4($sp)             # initialize secondary fd
-.next_action:
+next_action:
        lw      $s2, ($s0)              # action number
-       nop                             # delay slot
        andi    $t0, $s2, 15            # t0 = s2 & 15
-       beqz    $t0, .open_file         # open file?
+       beqz    $t0, open_file          # open file?
        li      $t1, 3                  # t1 = 3, delay slot
-       beq     $t0, $t1, .rest_of_exec # jump to code
+       beq     $t0, $t1, rest_of_exec  # jump to code
        li      $t1, 4                  # t1 = 4, delay slot
-       beq     $t0, $t1, .do_mmap_anon # anonymous mmap
-.do_mmap:
+       beq     $t0, $t1, do_mmap_anon  # anonymous mmap
+do_mmap:
        lw      $a0, 4($s0)             # vm_address, delay slot
        lw      $v1, 8($s0)             # file_offset
        lw      $a2, 12($s0)            # protection
@@ -50,33 +50,33 @@ dnl syscall                         # syscall
        lw      $a3, 20($s0)            # flags
        lw      $v0, ($sp)              # primary fd
        andi    $t1, $s2, 16            # t1 = s2 & 16
-       beqz    $t1, .do_mmap_1         # secondary fd?
+       beqz    $t1, do_mmap_1          # secondary fd?
        nop                             # delay slot
        lw      $v0, 4($sp)             # secondary fd
        nop                             # delay slot
-.do_mmap_1:
+do_mmap_1:
 SYSCALL(`$v0',`$v1',`$zero',`$zero')   # syscall args
        li      $v0, SYSCALL_mmap       # SYS_mmap
        syscall                         # syscall
-       bne     $a3, $zero, .perror     # perror
+       bnez    $a3, perror             # perror
 RESTORE()                              # delay slot, restore sp
        lw      $s5, 24($s0)            # clear
        add     $t0, $a0, $a1           # t0 = length + vm_address, delay slot
        sub     $t1, $t0, $s5           # t1 = t0 - clear
-.align:
-       beq     $t0, $t1, .continue     # already finished?
+align:
+       beq     $t0, $t1, continue      # already finished?
        nop                             # delay slot
        andi    $t2, $t1, 3             # t1 & 3?
-       bnez    $t2, .fillw             # start filling longs
+       bnez    $t2, fillw              # start filling longs
        nop                             # delay slot
        sb      $zero, ($t1)            # clear byte
        addi    $t1, $t1, 1             # t1++
-       j       .align                  # continue
+       j       align                   # continue
        nop                             # delay slot
-.fillw:
+fillw:
        sub     $t2, $t0, $t1           # t2 = t0 - t1
        sltiu   $t2, $t2, 32            # r2 < 32?
-       bne     $t2, $zero, .fillb      # fill bytes
+       bne     $t2, $zero, fillb       # fill bytes
        nop                             # delay slot
        sw      $zero, ($t1)            # zero word
        addi    $t1, $t1, 4             # next word
@@ -94,53 +94,52 @@ RESTORE()                           # delay slot, restore sp
        addi    $t1, $t1, 4             # next word
        sw      $zero, ($t1)            # zero word
        addi    $t1, $t1, 4             # next word
-       j       .fillw                  # fill either word or byte
+       j       fillw                   # fill either word 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
        addi    $t1, $t1, 1             # t1++
-.continue:
+continue:
        addi    $s0, $s0, 28            # s0 = next action
-       j       .next_action            # next action
+       j       next_action             # next action
        nop                             # delay slot
-.do_mmap_anon:
+do_mmap_anon:
        lw      $v1, 8($s0)             # file_offset
        lw      $a2, 12($s0)            # protection
        lw      $a1, 16($s0)            # length
        lw      $a3, 20($s0)            # flags
-       li      $t4, -1                 # fd
-       j       .do_mmap_1              # do mmap
-       nop                             # delay slot
-.open_file:
+       j       do_mmap_1               # do mmap
+       li      $v0, -1                 # fd, delay slot
+open_file:
        li      $v0, SYSCALL_open       # SYS_open
        addi    $a0, $s0, 4             # 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
        addi    $s0, $s0, 4             # start of string, delay slot
        move    $t3, $s0                # t3 = char past separator
-.nextc:
+nextc:
        lb      $t0, ($s0)              # load byte
        addi    $s0, $s0, 1             # s0++
        li      $t1, 47                 # directory separator `/'
-       bne     $t0, $t1, .nextc1       # is separator char?
+       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
        addi    $s0, $s0, 3             # adjust for round
        li      $t2, -4                 # t2 = -4
        and     $s0, $s0, $t2           # mask for round
        andi    $t0, $s2, 16            # t1 = s2 & 16
-       beqz    $t0, .primary           # primary fd?
+       beqz    $t0, primary            # primary fd?
        move    $t0, $sp                # address of primary fd, delay slot
        addi    $t0, $t0, 4             # address of secondary fd
-       j       .next_action            # next action
-.primary:
+       j       next_action             # next action
+primary:
        sw      $v0, ($t0)              # store fd, delay slot
        li      $v0, SYSCALL_prctl      # SYS_prctl
        li      $a0, 15                 # PR_SET_NAME
@@ -150,86 +149,209 @@ RESTORE()                                # delay slot, restore sp
 SYSCALL(`$a2',`$a2',`$a2',`$a2')       # syscall args
        syscall                         # syscall
 RESTORE()                              # restore sp
-       j       .next_action            # next action
+       j       next_action             # next action
        nop                             # delay slot
-.perror:
+perror:
        move    $a0, $v0                # errno
        li      $v0, SYSCALL_exit       # SYS_exit
        syscall                         # syscall
-.rest_of_exec:
+rest_of_exec:
        move    $s1, $s6                # s1 = original SP
        lw      $t0, ($s1)              # argc
        nop                             # delay slot
        sll     $t0, $t0, 2             # argc *= 4
        addi    $t0, $t0, 8             # argc += 8
        add     $s1, $s1, $t0           # s1 = start of envp
-.skipenv:
-       lw      $t0, ($s1)              # t0 = *s1
+skip_environ:
+       /* Locate the auxiliary vector.  */
+1:     lw      $t0, ($s1)              # t0 = *s1
+       bnez    $t0, 1b                 # skip environment entry
        addi    $s1, $s1, 4             # s1++
-       bne     $t0, $zero, .skipenv    # skip again
-       nop                             # delay slot
-       la      $s2, .auxvtab           # address of auxv table
-.one_auxv:
-       lw      $t0, ($s1)              # t0 = auxv type
-       li      $t1, 10                 # t1 = 10, delay slot
-       beqz    $t0, .finish            # is AT_IGNORE?
-       sltu    $t1, $t0, $t1           # t1 = t0 < num offsets, delay slot
-       beq     $t1, $zero, .next       # next auxv
-       sll     $t1, $t0, 2             # t1 = t0 * 4, delay slot
-       add     $t1, $s2, $t1           # t1 = .auxvtab + t1
-       lw      $t2, ($t1)              # t2 = *t1
-       nop                             # delay slot
-       beqz    $t2, .next              # skip auxv
-       add     $t2, $s0, $t2           # t2 = s0 + t2
-       lw      $t2, ($t2)              # t2 = *t2
-       nop                             # delay slot
-       sw      $t2, 4($s1)             # set auxv value
-.next:
-       addi    $s1, $s1, 8             # next auxv
-       j       .one_auxv               # next auxv
-       nop                             # delay slot
-.finish:
-       lw      $t0, 4($sp)             # secondary fd
-       lw      $s1, ($sp)              # primary fd, delay slot, preserved
+       move    $s2, $s1                # $s2 = end of environment
+1:     lw      $t0, ($s1)              # t0 = *s1
+       bnez    $t0, 1b                 # skip auxiliary vector entry
+       addi    $s1, $s1, 8             # (Elf32_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.  */
+       lw      $t1, 32($s0)            # length of string
+       addi    $t1, $t1, 1
+       addi    $t2, $s0, 36            # pointer to string
+       sub     $t3, $s1, $s6           # number of bytes in vectors
+       sub     $t0, $s1, $t1           # position of string
+       and     $t0, $t0, -16           # align value
+       sub     $t3, $t0, $t3           # position of argc
+       and     $t3, $t3, -16           # align value
+       /* Move the stack pointer and save required information.
+          4(FP)   = secondary/interpreter fd.
+          0(FP)   = primary/executable fd.
+          -4(FP)  = cmd->entry
+          -8(FP)  = cmd->at_entry
+          -12(FP) = cmd->at_phent
+          -16(FP) = cmd->at_phnum
+          -20(FP) = cmd->at_phdr
+          -24(FP) = cmd->at_base
+          -28(FP) = cmd->fpu_mode (only significant when N32)
+          $sp = copy of string.  */
+       move    $t4, $sp                # current sp
+       sub     $t5, $t3, $sp           # new argc - current sp
+       bleu    $t5, -8, 1f             # more than two slots apart
+       addi    $sp, $t3, -8            # $sp = two slots below new argc
+       j       2f                      # skip copying fds
+1:     move    $sp, $t4                # retain current sp
+       lw      $t5, ($t4)              # old primary fd
+       sw      $t5, ($sp)              # save the same
+       lw      $t5, 4($t4)             # old interpreter fd
+       sw      $t5, 4($sp)             # save the same
+2:     move    FP, $sp                 # set base pointer
+       addi    $sp, $sp, -28           # command data
+       lw      $t5, 4($s0)             # entry
+       lw      $t6, 8($s0)             # at_entry
+       sw      $t5, -4(FP)             # save entry
+       sw      $t6, -8(FP)             # save at_entry
+       lw      $t5, 12($s0)            # at_phent
+       lw      $t6, 16($s0)            # at_phnum
+       sw      $t5, -12(FP)            # save at_phent
+       sw      $t6, -16(FP)            # save at_phnum
+       lw      $t5, 20($s0)            # at_phdr
+       lw      $t6, 24($s0)            # at_base
+       sw      $t5, -20(FP)            # save at_phdr
+       sw      $t6, -24(FP)            # save at_base
+       lw      $t5, 28($s0)            # fpu_mode
+       sw      $t5, -28(FP)            # save fpu_mode
+       sub     $sp, $sp, $t1           # space for string
+       /* Save the input string.  */
+       add     $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
+       addi    $t2, $t2, 1             # $t2++
+       addi    $t6, $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:     lw      $t1, ($t5)              # $t1 = *src
+       addi    $t5, $t5, 4             # src++
+       addi    $t4, $t4, 4             # dst++
+       bltu    $t5, $s2, 1b            # src < src_end
+       sw      $t1, -4($t4)            # *(dst - 4) = $t1
+copy_auxv:
+       /* $t4 = destination, $t5 = first auxval.  */
+2:     lw      $t1, ($t5)              # a_type
+       lw      $t2, 4($t5)             # a_un.a_val
+       addi    $t4, $t4, 8             # (Elf32_auxv_t *) dst++
+       addi    $t5, $t5, 8             # (Elf32_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
+       lw      $t2, -20(FP)
+2:     b       7f
+       lw      $t2, -12(FP)
+3:     b       7f
+       lw      $t2, -16(FP)
+4:     b       7f
+       lw      $t2, -8(FP)
+5:     b       7f
+       lw      $t2, -24(FP)
+6:     b       7f
+       move    $t2, $t0
+7:     sw      $t1, -8($t4)            # dst->a_type
+       j       copy_auxv
+       sw      $t2, -4($t4)            # dst->a_un.a_val
+       /* Copy the final element.  */
+8:     sw      $t1, -8($t4)            # dst->a_type
+       sw      $t2, -4($t4)            # dst->a_un.a_val
+finish:
+       /* Copy the string to its position in auxv
+          (src = $s3, dst = $t0).  */
+       add     $t1, $s3, $s0           # src end
+       bgeu    $s3, $t1, 2f            # there already?
+       nop
+1:     lb      $t2, ($s3)              # c = *src
+       addi    $s3, $s3, 1             # *src++
+       addi    $t0, $t0, 1             # dst++
+       bltu    $s3, $t1, 1b
+       sb      $t2, -1($t0)            # *(dst - 1) = c
+       /* Save variables.  */
+2:     move    $s6, $t3                # new stack pointer
+       lw      $t4, 4(FP)              # secondary fd
+       lw      $s1, (FP)               # primary fd, delay slot, preserved
        li      $t2, -1                 # immediate -1
-       beq     $t0, $t2, .finish1      # secondary fd set?
+       beq     $t4, $t2, finish1       # secondary fd set?
        li      $v0, SYSCALL_close      # SYS_close, delay slot
-       move    $a0, $t0                # fd
+       move    $a0, $t4                # fd
        syscall                         # syscall
        li      $v0, SYSCALL_close      # SYS_close
-.finish1:
+finish1:
        move    $a0, $s1                # primary fd
        syscall                         # syscall
        li      $v0, SYSCALL_prctl      # SYS_prctl
        li      $a0, 45                 # PR_SET_FP_MODE
-       lw      $a1, 28($s0)            # fpu_mode
+       lw      $a1, -28(FP)            # fpu_mode
        move    $a2, $zero              # arg3
        move    $a3, $zero              # arg4
 SYSCALL(`$a2',`$a2',`$a2',`$a2')       # syscall args
        syscall                         # syscall
 RESTORE()                              # restore sp
-.jump:
+jump:
        move    $v0, $zero              # rtld_fini
-       lw      $t0, 4($s0)             # entry
+       lw      $t9, -4(FP)             # entry
        move    $sp, $s6                # restore stack pointer, delay slot
-       jr      $t0                     # enter
-       nop                             # 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   20                      # 3 AT_PHDR
-       .long   12                      # 4 AT_PHENT
-       .long   16                      # 5 AT_PHNUM
-       .long   0                       # 6
-       .long   24                      # 7 AT_BASE
-       .long   0                       # 8
-       .long   8                       # 9 AT_ENTRY
+          XXX: report this glibc bug?  */
+       addi    $v0, $sp, -4096
+       and     $v0, $v0, -4095
+1:     sw      $zero, ($v0)            # copy 32 byte blocks
+       sw      $zero, 4($v0)
+       sw      $zero, 8($v0)
+       sw      $zero, 12($v0)
+       sw      $zero, 16($v0)
+       sw      $zero, 20($v0)
+       sw      $zero, 24($v0)
+       sw      $zero, 28($v0)
+       addi    $v0, $v0, 32
+       sub     $t0, $sp, $v0           # remainder
+       bge     $t0, 32, 1b             # test remainder
+       nop                             # copy 4 byte blocks
+       beqz    $t0, 2f
+1:     addi    $v0, $v0, 4
+       bltu    $v0, $sp, 1b
+       sw      $zero, -4($v0)
+2:     jr      $t9                     # enter
+       nop                             # delay slot
 
-.timespec:
-       .long   10
-       .long   10
+## timespec:
+##     .long   10
+##     .long   10
 
 # Local Variables:
 # asm-comment-char: ?#