]> git.eshelyaron.com Git - emacs.git/commitdiff
Replace AT_EXECFN in auxiliary vectors of programs executed on Android
authorPo Lu <luangruo@yahoo.com>
Sun, 13 Apr 2025 10:50:59 +0000 (18:50 +0800)
committerEshel Yaron <me@eshelyaron.com>
Sun, 13 Apr 2025 21:01:09 +0000 (23:01 +0200)
* exec/exec.c (insert_args, exec_0): On non-MIPS systems, copy
NAME and its length to the loader area.  State that MIPS support
is not yet available (though it will be pending the availability
of a functioning emulator).

* exec/loader-aarch64.s (_start):

* exec/loader-armeabi.s (_start):

* exec/loader-x86.s (_start):

* exec/loader-x86_64.s (_start): Displace auxv, environ, and
argv to create sufficient space for the provided file name, and
copy the file name there.  Replace AT_EXECFN to refer to this
space.

(cherry picked from commit 7a01350624e1665e707f98e13d51f53e9f87ce95)

exec/exec.c
exec/loader-aarch64.s
exec/loader-armeabi.s
exec/loader-x86.s
exec/loader-x86_64.s
exec/trace.c

index b1c9825daffa1fe557a2bd2f6c2d5a72346fed9c..7a8ef2c3a1a47b6743458a86755b21f9cfd33c4d 100644 (file)
@@ -831,7 +831,7 @@ insert_args (struct exec_tracee *tracee, USER_REGS_STRUCT *regs,
   assert (new3 == new + effective_size);
 
   /* And that it is properly aligned.  */
-  assert (!(new3 & (sizeof new3 - 2)));
+  assert (!(new3 & (sizeof new3 - 1)));
 
   /* Now modify the system call argument to point to new +
      text_size.  */
@@ -916,6 +916,9 @@ 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;
@@ -1146,6 +1149,26 @@ 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)
+                & -sizeof name_len);
+  if (sizeof loader_area - loader_area_used
+      < aligned_len + sizeof name_len)
+    goto fail1;
+  memcpy (loader_area + loader_area_used, &name_len, sizeof name_len);
+  loader_area_used += sizeof name_len;
+  memcpy (loader_area + loader_area_used, name, name_len + 1);
+  loader_area_used += name_len + 1;
+
+  /* Properly align the loader area.  */
+  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 686a804aa0edc5b0385a14d6380b98bc7f189799..64f95725eca4e0ede16effc6daf6142c228b36d6 100644 (file)
        .section .text
        .global _start
 _start:
-       //mov   x8, 101                 // SYS_nanosleep
-       //adr   x0, timespec            // req
-       //mov   x1, #0                  // rem
-       //svc   #0                      // syscall
+       // mov  x8, 101                 // SYS_nanosleep
+       // adr  x0, timespec            // req
+       // mov  x1, #0                  // rem
+       // svc  #0                      // syscall
        mov     x20, sp                 // x20 = sp
        ldr     x10, [x20]              // x10 = original SP
        add     x20, x20, #16           // x20 = start of load area
        mov     x28, #-1                // x28 = secondary fd
-.next_action:
+next_action:
        ldr     x11, [x20]              // action number
        and     x12, x11, #-17          // actual action number
-       cbz     x12, .open_file         // open file?
+       cbz     x12, open_file          // open file?
        cmp     x12, #3                 // jump?
-       beq     .rest_of_exec
+       beq     rest_of_exec
        cmp     x12, #4                 // anonymous mmap?
-       beq     .do_mmap_anon
-.do_mmap:
+       beq     do_mmap_anon
+do_mmap:
        ldr     x0, [x20, 8]            // vm_address
        ldr     x1, [x20, 32]           // length
        ldr     x2, [x20, 24]           // protection
        ldr     x3, [x20, 40]           // flags
        tst     x11, #16                // primary fd?
        mov     x4, x29                 // primary fd
-       beq     .do_mmap_1
+       beq     do_mmap_1
        mov     x4, x28                 // secondary fd
-.do_mmap_1:
+do_mmap_1:
        mov     x8, #222                // SYS_mmap
        ldr     x5, [x20, 16]           // file_offset
        svc     #0                      // syscall
        ldr     x9, [x20, 8]            // length
        cmp     x0, x9                  // mmap result
-       bne     .perror                 // print error
+       bne     perror                  // print error
        ldr     x3, [x20, 48]           // clear
        add     x1, x1, x0              // x1 = vm_address + end
        sub     x3, x1, x3              // x3 = x1 - clear
        mov     x0, #0                  // x0 = 0
-.fill64:
+fill64:
        sub     x2, x1, x3              // x2 = x1 - x3
        cmp     x2, #63                 // x2 >= 64?
-       ble     .fillb                  // start filling bytes
+       ble     fillb                   // start filling bytes
        stp     x0, x0, [x3]            // x3[0] = 0, x3[1] = 0
        stp     x0, x0, [x3, 16]        // x3[2] = 0, x3[3] = 0
        stp     x0, x0, [x3, 32]        // x3[4] = 0, x3[5] = 0
        stp     x0, x0, [x3, 48]        // x3[6] = 0, x3[7] = 0
        add     x3, x3, #64             // x3 += 8
-       b       .fill64
-.fillb:
+       b       fill64
+fillb:
        cmp     x1, x3                  // x1 == x3?
-       beq     .continue               // done
+       beq     continue                // done
        strb    w0, [x3], #1            // ((char *) x3)++ = 0
-       b       .fillb
-.continue:
+       b       fillb
+continue:
        add     x20, x20, #56           // next action
-       b       .next_action
-.do_mmap_anon:
+       b       next_action
+do_mmap_anon:
        ldr     x0, [x20, 8]            // vm_address
        ldr     x1, [x20, 32]           // length
        ldr     x2, [x20, 24]           // protection
        ldr     x3, [x20, 40]           // flags
        mov     x4, #-1                 // fd
-       b       .do_mmap_1
-.open_file:
+       b       do_mmap_1
+open_file:
        mov     x8, #56                 // SYS_openat
        mov     x0, #-100               // AT_FDCWD
        add     x1, x20, #8             // file name
@@ -91,19 +91,19 @@ _start:
        mov     x3, #0                  // mode
        svc     #0                      // syscall
        cmp     x0, #-1                 // rc < 0?
-       ble     .perror
+       ble     perror
        mov     x19, x1                 // x19 == x1
-.nextc:
+nextc:
        ldrb    w2, [x1], #1            // b = *x1++
        cmp     w2, #47                 // dir separator?
-       bne     .nextc1                 // not dir separator
+       bne     nextc1                  // not dir separator
        mov     x19, x1                 // x19 = char past separator
-.nextc1:
-       cbnz    w2, .nextc              // b?
+nextc1:
+       cbnz    w2, nextc               // b?
        add     x1, x1, #7              // round up x1
        and     x20, x1, #-8            // mask for round, set x20
        tst     x11, #16                // primary fd?
-       bne     .secondary              // secondary fd
+       bne     secondary               // secondary fd
        mov     x29, x0                 // primary fd
        mov     x8, #167                // SYS_prctl
        mov     x0, #15                 // PR_SET_NAME
@@ -113,75 +113,117 @@ _start:
        mov     x4, #0                  // arg4
        mov     x5, #0                  // arg5
        svc     #0                      // syscall
-       b       .next_action            // next action
-.secondary:
+       b       next_action             // next action
+secondary:
        mov     x28, x0                 // secondary fd
-       b       .next_action            // next action.
-.perror:
+       b       next_action             // next action.
+perror:
        mov     x8, #93                 // SYS_exit
        mvn     x0, x0                  // x1 = ~x0
        add     x0, x0, 1               // x1 += 1
        svc     #0                      // exit
-.rest_of_exec:
+rest_of_exec:
        mov     x7, x20                 // x7 = x20
-       mov     x20, x10                // x20 = x10
-       ldr     x9, [x20]               // argc
-       add     x9, x9, #2              // x9 += 2
+       mov     x8, x10                 // x8 = x10
+       ldr     x9, [x8], #16           // (void *) x8 += 2
        lsl     x9, x9, #3              // argc * 8
-       add     x20, x20, x9            // now past argv
-.skipenv:
-       ldr     x9, [x20], #8           // x9 = *envp++
-       cbnz    x9, .skipenv            // x9?
-.one_auxv:
-       ldr     x9, [x20], #16          // x9 = *sp, sp += 2
-       cbz     x9, .cleanup            // !x9?
-       cmp     x9, #3                  // is AT_PHDR?
-       beq     .replace_phdr           // replace
-       cmp     x9, #4                  // is AT_PHENT?
-       beq     .replace_phent          // replace
-       cmp     x9, #5                  // is AT_PHNUM?
-       beq     .replace_phnum          // replace
-       cmp     x9, #9                  // is AT_ENTRY?
-       beq     .replace_entry          // replace
-       cmp     x9, #7                  // is AT_BASE?
-       beq     .replace_base           // replace
-       b       .one_auxv               // next auxv
-.replace_phdr:
-       ldr     x9, [x7, 40]            // at_phdr
-       str     x9, [x20, -8]           // store value
-       b       .one_auxv
-.replace_phent:
-       ldr     x9, [x7, 24]            // at_phent
-       str     x9, [x20, -8]           // store value
-       b       .one_auxv
-.replace_phnum:
-       ldr     x9, [x7, 32]            // at_phnum
-       str     x9, [x20, -8]           // store value
-       b       .one_auxv
-.replace_entry:
-       ldr     x9, [x7, 16]            // at_entry
-       str     x9, [x20, -8]           // store value
-       b       .one_auxv
-.replace_base:
-       ldr     x9, [x7, 48]            // at_base
-       str     x9, [x20, -8]           // store value
-       b       .one_auxv
-.cleanup:
-       cmp     x28, #-1                // is secondary fd set?
-       bne     .cleanup1               // not set
+       add     x8, x8, x9              // now past argv
+skip_environ:
+       ldr     x9, [x8], #8            // x9 = *envp++
+       cbnz    x9, skip_environ        // x9?
+       // Skip the auxiliary vector.
+1:     ldp     x11, x12, [x8], #16     // a_type, a_un.a_val
+       cbnz    x11, 1b                 // a_type != NULL
+       // Prepare sufficient space at x20 for the file name string.
+       // Load the aforesaid string, and its length.
+       ldr     x6, [x7, 56]            // string length
+       add     x6, x6, 1
+       add     x5, x7, 64              // string pointer
+       sub     x4, x10, x8             // number of elements to copy
+       sub     x7, x8, x6              // AT_EXECFN location
+       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.
+       // x14 = cmd->entry
+       // x15 = cmd->at_entry
+       // x16 = cmd->at_phent
+       // x17 = cmd->at_phnum
+       // x18 = cmd->at_phdr
+       // x19 = cmd->at_base
+       ldp     x14, x15, [x20, 8]
+       ldp     x16, x17, [x20, 24]
+       ldp     x18, x19, [x20, 40]
+       // Move the string to a safe location, if necessary.
+       sub     x3, x4, x5              // distance from dest to string
+       cmp     x3, x6                  // distance > length
+       bge     copy_env_and_args       // not necessary
+       mov     x2, x5                  // src
+       sub     x5, x4, x6              // backup string
+       mov     x1, x5                  // dst
+       add     x9, x2, x6              // src end
+       cmp     x2, x9
+       bcs     copy_env_and_args
+1:     ldrb    w3, [x2], #1
+       strb    w3, [x1], #1
+       cmp     x2, x9
+       bls     1b
+copy_env_and_args:
+       // Copy argc and the environment array.
+       mov     x8, x10
+       mov     x10, x4
+1:     ldr     x9, [x8], #8            //  envp
+       str     x9, [x4], #8
+       cbnz    x9, 1b
+1:     ldr     x9, [x8], #8            // environ
+       str     x9, [x4], #8
+       cbnz    x9, 1b
+copy_auxv:
+       ldp     x11, x12, [x8], #16     // a_type, a_un.a_val
+       stp     x11, x12, [x4], #16     // write value
+       cbz     x11, cleanup            // AT_NULL
+       cmp     x11, #3                 // AT_PHDR
+       csel    x12, x18, x12, eq
+       cmp     x11, #4                 // AT_PHENT
+       csel    x12, x16, x12, eq
+       cmp     x11, #5                 // AT_PHNUM
+       csel    x12, x17, x12, eq
+       cmp     x11, #9                 // AT_ENTRY
+       csel    x12, x15, x12, eq
+       cmp     x11, #7                 // AT_BASE
+       csel    x12, x19, x12, eq
+       cmp     x11, #31                // AT_EXECFN
+       csel    x12, x7, x12, eq
+       str     x12, [x4, -8]           // replace value
+       b       copy_auxv
+cleanup:
+       // Copy the filename.
+       add     x9, x5, x6              // end
+       cmp     x5, x9
+       bcs     2f
+1:     ldrb    w3, [x5], #1
+       strb    w3, [x7], #1
+       cmp     x5, x9
+       bls     1b
+       // Close file descriptors.
+2:     cmp     x28, #-1                // is secondary fd set?
+       beq     cleanup1                // not set
        mov     x8, #57                 // SYS_close
        mov     x0, x28                 // secondary fd
        svc     #0                      // syscall
-.cleanup1:
+cleanup1:
        mov     x8, #57                 // SYS_close
        mov     x0, x29                 // primary fd
        svc     #0                      // syscall
-.enter:
+enter:
        mov     sp, x10                 // restore original SP
        mov     x0, #0                  // clear rtld_fini
-       ldr     x1, [x7, 8]             // branch to code
-       br      x1
+       br      x14
 
-timespec:
-       .quad 10
-       .quad 10
+// timespec:
+//     .quad 10
+//     .quad 10
+
+// Local Variables:
+// asm-comment-char: ?/
+// End:
index 2aa52f3e006d8bdba1a1787a498458e87ddb02ef..572020bb57391322320baa452b171f217fa79720 100644 (file)
        .section .text
        .global _start
 _start:
-       @mov    r7, #162                @ SYS_nanosleep
-       @adr    r0, timespec            @ req
-       @mov    r1, #0                  @ rem
-       @swi    #0                      @ syscall
+       @@ mov  r7, #162                @ SYS_nanosleep
+       @@ adr  r0, timespec            @ req
+       @@ mov  r1, #0                  @ rem
+       @@ swi  #0                      @ syscall
        mov     r8, sp                  @ r8 = sp
        ldr     r9, [r8], #8            @ r9 = original sp, r8 += 8
        mov     r14, #-1                @ r14 = secondary fd
-.next_action:
+next_action:
        ldr     r11, [r8]               @ r11 = action number
        and     r12, r11, #-17          @ actual action number
        cmp     r12, #0                 @ open file?
-       beq     .open_file              @ open file.
+       beq     open_file               @ open file.
        cmp     r12, #3                 @ jump?
-       beq     .rest_of_exec           @ jump to code.
+       beq     rest_of_exec            @ jump to code.
        cmp     r12, #4                 @ anonymous mmap?
-       beq     .do_mmap_anon           @ anonymous mmap.
-.do_mmap:
+       beq     do_mmap_anon            @ anonymous mmap.
+do_mmap:
        add     r6, r8, #4              @ r6 = r8 + 4
        ldm     r6!, {r0, r5}           @ vm_address, file_offset
        ldm     r6!, {r1, r2}           @ protection, length
@@ -45,28 +45,28 @@ _start:
        ldm     r6!, {r3, r12}          @ flags, clear
        tst     r11, #16                @ primary fd?
        mov     r4, r10                 @ primary fd
-       beq     .do_mmap_1
+       beq     do_mmap_1
        mov     r4, r14                 @ secondary fd
-.do_mmap_1:
+do_mmap_1:
        mov     r7, #192                @ SYS_mmap2
        swi     #0                      @ syscall
        ldr     r2, [r8, #4]            @ vm_address
        cmp     r2, r0                  @ rc == vm_address?
-       bne     .perror
+       bne     perror
        add     r0, r1, r2              @ r0 = length + vm_address
        sub     r3, r0, r12             @ r3 = r0 - clear
        mov     r1, #0                  @ r1 = 0
-.align:
+align:
        cmp     r0, r3                  @ r0 == r3?
-       beq     .continue               @ continue
+       beq     continue                @ continue
        tst     r3, #3                  @ r3 & 3?
-       bne     .fill32                 @ fill aligned
+       bne     fill32                  @ fill aligned
        strb    r1, [r3], #1            @ fill byte
-       b       .align                  @ align again
-.fill32:
+       b       align                   @ align again
+fill32:
        sub     r2, r0, r3              @ r2 = r0 - r3
        cmp     r2, #31                 @ r2 >= 32?
-       ble     .fillb                  @ start filling bytes
+       ble     fillb                   @ start filling bytes
        str     r1, [r3], #4            @ *r3++ = 0
        str     r1, [r3], #4            @ *r3++ = 0
        str     r1, [r3], #4            @ *r3++ = 0
@@ -75,16 +75,16 @@ _start:
        str     r1, [r3], #4            @ *r3++ = 0
        str     r1, [r3], #4            @ *r3++ = 0
        str     r1, [r3], #4            @ *r3++ = 0
-       b       .fill32
-.fillb:
+       b       fill32
+fillb:
        cmp     r0, r3                  @ r0 == r3
-       beq     .continue               @ done
+       beq     continue                @ done
        strb    r1, [r3], #1            @ ((char *) r3)++ = 0
-       b       .fillb
-.continue:
+       b       fillb
+continue:
        add     r8, r8, #28             @ next action
-       b       .next_action
-.do_mmap_anon:
+       b       next_action
+do_mmap_anon:
        add     r6, r8, #4              @ r6 = r8 + 4
        ldm     r6!, {r0, r5}           @ vm_address, file_offset
        ldm     r6!, {r1, r2}           @ protection, length
@@ -94,29 +94,29 @@ _start:
        mov     r2, r3                  @ swap
        ldm     r6!, {r3, r12}          @ flags, clear
        mov     r4, #-1                 @ fd
-       b       .do_mmap_1
-.open_file:
+       b       do_mmap_1
+open_file:
        mov     r7, #5                  @ SYS_open
        add     r0, r8, #4              @ file name
        mov     r1, #0                  @ O_RDONLY
        mov     r2, #0                  @ mode
        swi     #0                      @ syscall
        cmp     r0, #-1                 @ r0 <= -1?
-       ble     .perror
+       ble     perror
        add     r8, r8, #4              @ r8 = start of string
        mov     r1, r8                  @ r1 = r8
-.nextc:
+nextc:
        ldrb    r2, [r8], #1            @ b = *r0++
        cmp     r2, #47                 @ dir separator?
-       bne     .nextc1                 @ not dir separator
+       bne     nextc1                  @ not dir separator
        mov     r1, r8                  @ r1 = char past separator
-.nextc1:
+nextc1:
        cmp     r2, #0                  @ b?
-       bne     .nextc                  @ next character
+       bne     nextc                   @ next character
        add     r8, r8, #3              @ round up r8
        and     r8, r8, #-4             @ mask for round, set r8
        tst     r11, #16                @ primary fd?
-       bne     .secondary              @ secondary fd
+       bne     secondary               @ secondary fd
        mov     r10, r0                 @ primary fd
        mov     r7, #172                @ SYS_prctl
        mov     r0, #15                 @ PR_SET_NAME, r1 = name
@@ -125,79 +125,139 @@ _start:
        mov     r4, #0                  @ arg4
        mov     r5, #0                  @ arg5
        swi     #0                      @ syscall
-       b       .next_action            @ next action
-.secondary:
+       b       next_action             @ next action
+secondary:
        mov     r14, r0                 @ secondary fd
-       b       .next_action            @ next action
-.perror:
+       b       next_action             @ next action
+perror:
        mov     r7, #1                  @ SYS_exit
        mvn     r0, r0                  @ r0 = ~r0
        add     r0, r0, #1              @ r0 += 1
        swi     #0
-.rest_of_exec:
+rest_of_exec:                          @ r8 points to seven ints + string
        mov     r7, r9                  @ r7 = original SP
-       ldr     r6, [r7]                @ argc
-       add     r6, r6, #2              @ argc + 2
+       ldr     r6, [r7], #8            @ argc & terminator
        lsl     r6, r6, #2              @ argc *= 4
        add     r7, r7, r6              @ now past argv
-.skipenv:
-       ldr     r6, [r7], #4            @ r6 = *r7++
-       cmp     r6, #0                  @ r6?
-       bne     .skipenv                @ r6?
-.one_auxv:
-       ldr     r6, [r7], #8            @ r6 = *r7, r7 += 2
-       cmp     r6, #0                  @ !r6?
-       beq     .cleanup                @ r6?
-       cmp     r6, #3                  @ is AT_PHDR?
-       beq     .replace_phdr           @ replace
-       cmp     r6, #4                  @ is AT_PHENT?
-       beq     .replace_phent          @ replace
-       cmp     r6, #5                  @ is AT_PHNUM?
-       beq     .replace_phnum          @ replace
-       cmp     r6, #9                  @ is AT_ENTRY?
-       beq     .replace_entry          @ replace
-       cmp     r6, #7                  @ is AT_BASE?
-       beq     .replace_base           @ replace
-       b       .one_auxv               @ next auxv
-.replace_phdr:
-       ldr     r6, [r8, #20]           @ at_phdr
-       str     r6, [r7, #-4]           @ store value
-       b       .one_auxv
-.replace_phent:
-       ldr     r6, [r8, #12]           @ at_phent
-       str     r6, [r7, #-4]           @ store value
-       b       .one_auxv
-.replace_phnum:
-       ldr     r6, [r8, #16]           @ at_phnum
-       str     r6, [r7, #-4]           @ store value
-       b       .one_auxv
-.replace_entry:
-       ldr     r6, [r8, #8]            @ at_entry
-       str     r6, [r7, #-4]           @ store value
-       b       .one_auxv
-.replace_base:
-       ldr     r6, [r8, #24]           @ at_base
-       str     r6, [r7, #-4]           @ store value
-       b       .one_auxv
-.cleanup:
+       ldr     r6, [r8, #28]           @ length of string
+       add     r6, r6, #1
+skip_environ:
+1:     ldr     r1, [r7], #4            @ r1 = *r7++
+       tst     r1, r1                  @ r1
+       bne     1b                      @ r1
+1:     ldm     r7!, {r0, r1}           @ a_type, a_un.a_val
+       tst     r0, r0
+       bne     1b                      @ a_type -> 1b
+       @@ Establish the number of bytes in the argument, environment,
+       @@ and auxiliary vectors to be moved.
+       sub     r5, r7, r9              @ r5 = bytes in vectors
+       @@ Expand r7 with sufficient space for the filename and align
+       @@ it.
+       sub     r4, r7, r5
+       and     r4, r4, #-8             @ r4 = address of AT_EXECFN
+       sub     r3, r4, r5              @ r4 - number of bytes in vectors
+       and     r3, r3, #-16            @ r3 = position of new argc
+       @@ Reserve an area that is guaranteed not to be clobbered into
+       @@ which to copy the command and file name.
+       mov     r2, r3
+       cmp     r2, r8
+       blo     1f
+       mov     r2, r8
+1:     sub     r2, r2, #24             @ space for data
+       @@ [r2, #0] = entry
+       @@ [r2, #4] = at_entry
+       @@ [r2, #8] = at_phent
+       @@ [r2, #12] = at_phnum
+       @@ [r2, #16] = at_phdr
+       @@ [r2, #20] = at_base
+       add     r7, r8, #4              @ &cmd->entry
+       ldm     r7!, {r0, r1}
+       stm     r2!, {r0, r1}
+       ldm     r7!, {r0, r1}
+       stm     r2!, {r0, r1}
+       ldm     r7!, {r0, r1}
+       stm     r2!, {r0, r1}
+       sub     r2, r2, #24
+       sub     r0, r2, r6              @ r0 = copy of AT_EXECFN
+       add     r1, r8, #32             @ src
+       add     r5, r1, r6              @ src end
+       cmp     r1, r5
+       bcs     copy_env_and_args
+1:     ldrb    r7, [r1], #1
+       strb    r7, [r0], #1
+       cmp     r1, r5
+       blo     1b
+copy_env_and_args:
+       mov     r5, r3
+1:     ldr     r0, [r9], #4            @ argc and arguments
+       str     r0, [r5], #4            @ *dst = ...
+       tst     r0, r0
+       bne     1b
+1:     ldr     r0, [r9], #4            @ environment string
+       str     r0, [r5], #4            @ *dst = ...
+       tst     r0, r0
+       bne     1b
+copy_auxv:
+       ldm     r9!, {r0, r1}           @ a_type, a_un.a_val
+       tst     r0, r0                  @ AT_NULL
+       beq     8f
+       cmp     r0, #3                  @ AT_PHDR
+       beq     2f
+       cmp     r0, #4                  @ AT_PHENT
+       beq     3f
+       cmp     r0, #5                  @ AT_PHNUM
+       beq     4f
+       cmp     r0, #9                  @ AT_ENTRY
+       beq     5f
+       cmp     r0, #7                  @ AT_BASE
+       beq     6f
+       cmp     r0, #31                 @ AT_EXECFN
+       beq     7f
+1:     stm     r5!, {r0, r1}
+       b       copy_auxv
+2:     ldr     r1, [r2, #16]
+       b       1b
+3:     ldr     r1, [r2, #8]
+       b       1b
+4:     ldr     r1, [r2, #12]
+       b       1b
+5:     ldr     r1, [r2, #4]
+       b       1b
+6:     ldr     r1, [r2, #20]
+       b       1b
+7:     mov     r1, r4
+       b       1b
+8:
+       stm     r5!, {r0, r1}
+cleanup:
+       @@ Copy the filename.
+       sub     r0, r2, r6              @ src
+       add     r1, r0, r6              @ src end
+       cmp     r0, r1
+       bcs     2f
+1:     ldrb    r5, [r0], #1
+       strb    r5, [r4], #1            @ *dst++
+       cmp     r0, r1
+       blo     1b
+2:     mov     r9, r3                  @ replace original SP
        cmp     r14, #-1                @ secondary fd set?
-       bne     .cleanup1               @ not set
+       beq     cleanup1                @ not set
        mov     r7, #6                  @ SYS_close
        mov     r0, r14                 @ secondary fd
        swi     #0                      @ syscall
-.cleanup1:
+cleanup1:
        mov     r7, #6                  @ SYS_close
        mov     r0, r10                 @ primary fd
        swi     #0                      @ syscall
-.enter:
+enter:
        mov     sp, r9                  @ restore original SP
        mov     r0, #0                  @ clear rtld_fini
-       ldr     r1, [r8, #4]            @ branch to code
+       ldr     r1, [r2]                @ branch to code
        bx      r1
 
-timespec:
-       .long 10
-       .long 10
+@@ timespec:
+@@     .long 10
+@@     .long 10
 
 @ Local Variables:
 @ asm-comment-char: ?@
index 5e5bb7253ab067c6e0fe5b790c58262d4bdd76d3..d9cfa28f6a36a07e0d1d8452f2f464f6c764d5f4 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/>.
 
+/* Sorry!  This program is a hopeless shambles in consequence of
+   being hastily written in under twenty minutes with minimal testing.  */
+
        .section .text
        .global _start
 _start:
-#      movl    $162, %eax              # SYS_nanosleep
-#      leal    timespec, %ebx
-#      xorl    %ecx, %ecx
-#      int     $0x80
+       ## movl $162, %eax              # SYS_nanosleep
+       ## leal timespec, %ebx
+       ## xorl %ecx, %ecx
+       ## int  $0x80
        leal    8(%esp), %ebp           # ebp = start of load area
        subl    $8, %esp                # (%esp) = primary fd, 4(%esp) = secondary fd
        movl    $-1, 4(%esp)
-.next_action:
+next_action:
        movl    (%ebp), %edx            # edx = action number
        andl    $-17, %edx
        cmpl    $0, %edx                # open file?
-       je      .open_file
+       je      open_file
        cmpl    $3, %edx                # jump?
-       je      .rest_of_exec
+       je      rest_of_exec
        cmpl    $4, %edx                # anonymous mmap?
-       je      .do_mmap_anon
-.do_mmap:
+       je      do_mmap_anon
+do_mmap:
        subl    $24, %esp
        movl    $90, %eax               # SYS_old_mmap
        movl    %esp, %ebx
@@ -52,27 +55,27 @@ _start:
        movl    %ecx, 16(%esp)          # fd
        movl    8(%ebp), %ecx           # offset
        movl    %ecx, 20(%esp)
-.do_mmap_1:
+do_mmap_1:
        int     $0x80
        addl    $24, %esp               # restore esp
        cmpl    $-1, %eax               # mmap failed?
-       je      .perror
+       je      perror
        movl    24(%ebp), %ecx          # clear
        testl   %ecx, %ecx
-       jz      .continue
+       jz      continue
        movl    4(%ebp), %esi           # start of mapping
        addl    16(%ebp), %esi          # end of mapping
        subl    %ecx, %esi              # start of clear area
-.again:
+again:
        testl   %ecx, %ecx
-       jz      .continue
+       jz      continue
        subl    $1, %ecx
        movb    $0, (%esi, %ecx, 1)
-       jmp     .again
-.continue:
+       jmp     again
+continue:
        leal    28(%ebp), %ebp
-       jmp     .next_action
-.do_mmap_anon:
+       jmp     next_action
+do_mmap_anon:
        subl    $24, %esp
        movl    $90, %eax               # SYS_old_mmap
        movl    %esp, %ebx
@@ -87,8 +90,8 @@ _start:
        movl    $-1, 16(%esp)           # fd
        movl    8(%ebp), %ecx           # offset
        movl    %ecx, 20(%esp)
-       jmp     .do_mmap_1
-.open_file:
+       jmp     do_mmap_1
+open_file:
        movl    $5, %eax                # SYS_open
        leal    4(%ebp), %ebx           # ebx = %esp + 8
        pushl   %ebx
@@ -96,27 +99,27 @@ _start:
        xorl    %edx, %edx              # mode = 0
        int     $0x80
        cmpl    $-1, %eax               # open failed?
-       jle     .perror
+       jle     perror
        movl    %ebp, %esi              # (esi) = original action number
        popl    %ebp                    # ebp = start of string
        movl    %ebp, %ecx              # char past separator
        decl    %ebp
-.nextc:
+nextc:
        incl    %ebp
        movb    (%ebp), %dl             # dl = *ebp
        cmpb    $47, %dl                # dl == '\?'?
-       jne     .nextc1
+       jne     nextc1
        leal    1(%ebp), %ecx           # ecx = char past separator
-.nextc1:
+nextc1:
        cmpb    $0, %dl                 # dl == 0?
-       jne     .nextc
+       jne     nextc
        addl    $4, %ebp                # adjust past ebp prior to rounding
        andl    $-4, %ebp               # round ebp up to the next long
        testl   $16, (%esi)             # original action number & 16?
-       jz      .primary
+       jz      primary
        movl    %eax, 4(%esp)           # secondary fd = eax
-       jmp     .next_action
-.primary:
+       jmp     next_action
+primary:
        pushl   %ebp
        xorl    %esi, %esi              # arg3
        movl    %eax, 4(%esp)           # primary fd = eax
@@ -127,74 +130,168 @@ _start:
        xorl    %ebp, %ebp              # arg5
        int     $0x80                   # syscall
        popl    %ebp
-       jmp     .next_action
-.perror:
+       jmp     next_action
+perror:
        movl    %eax, %ebx
        negl    %ebx
        movl    $1, %eax
        int     $0x80
-.rest_of_exec:
+rest_of_exec:
        movl    8(%esp), %ecx           # ecx = original stack pointer
        movl    (%ecx), %esi            # esi = argc
        leal    8(%ecx, %esi, 4), %ecx  # ecx = start of environ
-.skip_environ:
+       movl    (%esp), %eax            # %eax = primary fd
+       movl    4(%esp), %edi           # %edi = secondary fd
+skip_environ:
        movl    (%ecx), %esi            # envp[N]
        addl    $4, %ecx
        testl   %esi, %esi              # envp[n] ?
-       jnz     .skip_environ           # otherwise, esi is now at the start of auxv
-.one_auxv:
-       movl    (%ecx), %esi            # auxv type
+       jnz     skip_environ            # otherwise, ecx is now at the end of auxv
+1:     testl   $-1, (%ecx)             # auxv type
        leal    8(%ecx), %ecx           # skip to next auxv
-       testl   %esi, %esi              # is 0?
-       jz      .cleanup
-       cmpl    $3, %esi                # is AT_PHDR
-       je      .replace_phdr
-       cmpl    $4, %esi                # is AT_PHENT?
-       je      .replace_phent
-       cmpl    $5, %esi                # is AT_PHNUM?
-       je      .replace_phnum
-       cmpl    $9, %esi                # is AT_ENTRY?
-       je      .replace_entry
-       cmpl    $7, %esi                # is AT_BASE
-       je      .replace_base
-       jmp     .one_auxv
-.replace_phdr:
-       movl    20(%ebp), %esi
+       jnz     1b                      # otherwise copy auxv
+       movl    %ecx, %edx              # end of auxv
+       /* Prepare sufficient space for the new executable name at the
+          start of the auxiliary vector.  */
+1:     leal    32(%ebp), %esi          # file name
+       /* 28(%ebp) = file name length.  */
+       subl    28(%ebp), %ecx          # destination of file name
+       decl    %ecx
+       /* This is still 16 bytes on i386--see arch_align_stack:
+          https://android.googlesource.com/kernel/goldfish/+/refs/heads
+          /android-goldfish-3.10/arch/x86/kernel/process.c#446.  */
+       andl    $-16, %ecx              # align stack
+       /* Prepare to store the auxiliary, environment, and argument
+          vectors.  */
+       subl    8(%esp), %edx           # end of auxv to start of stack
+       negl    %edx
+       andl    $-16, %edx              # align value
+       movl    %ecx, (%ebp)            # temporarily save ecx
+       addl    %edx, %ecx              # %ecx = new position of argc
+       /* Allocate a temporary stack away from any crucial data in which
+          to store parameters and temporaries.  */
+       cmpl    %ecx, %ebp              # select position of temporary stack
+       movl    %ecx, %ebx              # ebx = temporary stack
+       jge     1f                      # %ebx = MIN (%ecx, %edx)
+       movl    %ebp, %ebx              # ebx = temporary stack
+1:     movl    (%ebp), %edx            # edx = destination of file name
+       movl    %edx, -4(%ebx)          # -4(%ebx) = destination of file name
+       movl    28(%ebp), %edx          # file name length
+       movl    %edx, -8(%ebx)          # -8(%ebx) = file name length
+       movl    %ecx, -12(%ebx)         # -12(%ebx) = new position of argc
+       movl    %esi, -16(%ebx)         # -16(%ebx) = file name
+       movl    8(%esp), %edx           # %edx = initial stack pointer
+       leal    -16(%ebx), %esp         # switch to temporary stack
+       /* Push parameters of `struct exec_jump_command'.  */
+       push    %edx                    # initial stack pointer -20(%ebx)
+       push    4(%ebp)                 # entry -24(%ebx)
+       push    8(%ebp)                 # at_entry -28(%ebx)
+       push    12(%ebp)                # at_phent -32(%ebx)
+       push    16(%ebp)                # at_phnum -36(%ebx)
+       push    20(%ebp)                # at_phdr -40(%ebx)
+       push    24(%ebp)                # at_base -44(%ebx)
+       /* Push primary and secondary fds.  */
+       push    %eax                    # primary fd -48(%ebx)
+       push    %edi                    # secondary fd -52(%ebx)
+       /* Swap %ebp with %ebx.  */
+       push    %ebp
+       push    %ebx
+       pop     %ebp
+       pop     %ebx                    # ebx is the exec_jump_command
+       /* Save the string lest it should be overwritten while
+          the environment is moved.  */
+       movl    -8(%ebp), %ecx
+       subl    $4, %esp                # -56(%ebp)
+       subl    %ecx, %esp
+       leal    -1(%esp), %edi
+       movl    %edi, -56(%ebp)         # copy of string
+       incl    %ecx
+       movl    %edi, %esp
+       cld
+  rep  movsb                           # complete copy
+       andl    $-4, %esp               # align stack
+       movl    -12(%ebp), %ecx
+       /* Begin moving the argument vectors and environment from
+          the original SP to the adjusted one.  */
+1:     movl    (%edx), %eax            # argc and values
+       movl    %eax, (%ecx)
+       leal    4(%ecx), %ecx
+       leal    4(%edx), %edx
+       testl   %eax, %eax
+       jnz     1b
+1:     movl    (%edx), %eax            # envp
+       movl    %eax, (%ecx)
+       leal    4(%ecx), %ecx
+       leal    4(%edx), %edx
+       testl   %eax, %eax
+       jnz     1b
+copy_auxv:
+       movl    (%edx), %eax            # a_type
+       movl    4(%edx), %esi           # a_un.a_val
+       testl   %eax, %eax
+       leal    8(%edx), %edx
+       movl    %eax, (%ecx)            # copy auxv type
+       leal    8(%ecx), %ecx
+       jz      cleanup                 # AT_NULL
+       cmpl    $3, %eax                # AT_PHDR
+       jz      1f
+       cmpl    $4, %eax                # AT_PHENT
+       jz      2f
+       cmpl    $5, %eax                # AT_PHNUM
+       jz      3f
+       cmpl    $9, %eax                # AT_ENTRY
+       jz      4f
+       cmpl    $7, %eax                # AT_BASE
+       jz      5f
+       cmpl    $31, %eax               # AT_EXECFN
+       jz      6f
+       movl    %esi, -4(%ecx)
+       jmp     copy_auxv
+1:     movl    -40(%ebp), %esi
+       movl    %esi, -4(%ecx)
+       jmp     copy_auxv
+2:     movl    -32(%ebp), %esi
        movl    %esi, -4(%ecx)
-       jmp     .one_auxv
-.replace_phent:
-       movl    12(%ebp), %esi
+       jmp     copy_auxv
+3:     movl    -36(%ebp), %esi
        movl    %esi, -4(%ecx)
-       jmp     .one_auxv
-.replace_phnum:
-       movl    16(%ebp), %esi
+       jmp     copy_auxv
+4:     movl    -28(%ebp), %esi
        movl    %esi, -4(%ecx)
-       jmp     .one_auxv
-.replace_entry:
-       movl    8(%ebp), %esi
+       jmp     copy_auxv
+5:     movl    -44(%ebp), %esi
        movl    %esi, -4(%ecx)
-       jmp     .one_auxv
-.replace_base:
-       movl    24(%ebp), %esi
+       jmp     copy_auxv
+6:     movl    -4(%ebp), %esi          # Note: the filename is yet to be copied.
        movl    %esi, -4(%ecx)
-       jmp     .one_auxv
-.cleanup:
+       jmp     copy_auxv
+cleanup:
+       movl    $0, -4(%ecx)            # AT_NULL value
+       /* Copy data for AT_EXECFN to the destination address.  */
+       movl    -4(%ebp), %edi
+       movl    -56(%ebp), %esi
+       movl    -8(%ebp), %ecx
+       incl    %ecx
+  rep  movsb
        movl    $6, %eax                # SYS_close
-       cmpl    $-1, 4(%esp)            # see if interpreter fd is set
-       je      .cleanup_1
-       movl    4(%esp), %ebx
+       cmpl    $-1, -52(%ebp)          # see if interpreter fd is set
+       je      cleanup_1
+       movl    -52(%ebp), %ebx
        int     $0x80
        movl    $6, %eax                # SYS_close
-.cleanup_1:
-       movl    (%esp), %ebx
+cleanup_1:
+       movl    -48(%ebp), %ebx
        int     $0x80
-.enter:
+enter:
        pushl   $0
        popfl                           # restore floating point state
-       movl    8(%esp), %esp           # restore initial stack pointer
+       movl    -12(%ebp), %esp         # restore initial stack pointer
        xorl    %edx, %edx              # clear rtld_fini
-       jmpl    *4(%ebp)                # entry
+       jmpl    *-24(%ebp)              # entry
+## timespec:
+##     .long   10
+##     .long   10
 
-timespec:
-       .long   10
-       .long   10
+# Local Variables:
+# asm-comment-char: ?#
+# End:
index 0854df98db98ac555d38fcfc76c50d275ff8c793..236f8d6670fa136339e6f601b3e6ab3196faebbd 100644 (file)
@@ -25,17 +25,17 @@ _start:
        popq    %r13                    # original SP
        popq    %r15                    # size of load area.
        movq    $-1, %r12               # r12 is the interpreter fd
-.next_action:
+next_action:
        movq    (%rsp), %r14            # action number
        movq    %r14, %r15              # original action number
        andq    $-17, %r14
        cmpq    $0, %r14                # open file?
-       je      .open_file
+       je      open_file
        cmpq    $3, %r14                # jump?
-       je      .rest_of_exec
+       je      rest_of_exec
        cmpq    $4, %r14                # anonymous mmap?
-       je      .do_mmap_anon
-.do_mmap:
+       je      do_mmap_anon
+do_mmap:
        movq    $9, %rax                # SYS_mmap
        movq    8(%rsp), %rdi           # address
        movq    16(%rsp), %r9           # offset
@@ -46,26 +46,26 @@ _start:
        testq   $16, %r15
        movq    %r12, %r8
        cmovzq  %rbx, %r8
-.do_mmap_1:
+do_mmap_1:
        syscall
        cmpq    $-1, %rax               # mmap failed
-       je      .perror
+       je      perror
        movq    48(%rsp), %r9           # clear
        testq   %r9, %r9
-       jz      .continue
+       jz      continue
        movq    8(%rsp), %r10           # start of mapping
        addq    32(%rsp), %r10          # end of mapping
        subq    %r9, %r10               # start of clear area
-.again:
+again:
        testq   %r9, %r9
-       jz      .continue
+       jz      continue
        subq    $1, %r9
        movb    $0, (%r10, %r9, 1)
-       jmp     .again
-.continue:
+       jmp     again
+continue:
        leaq    56(%rsp), %rsp
-       jmp     .next_action
-.do_mmap_anon:
+       jmp     next_action
+do_mmap_anon:
        movq    $9, %rax                # SYS_mmap
        movq    8(%rsp), %rdi           # address
        movq    16(%rsp), %r9           # offset
@@ -73,35 +73,35 @@ _start:
        movq    32(%rsp), %rsi          # length
        movq    40(%rsp), %r10          # flags
        movq    $-1, %r8                # -1
-       jmp     .do_mmap_1
-.open_file:
+       jmp     do_mmap_1
+open_file:
        movq    $2, %rax                # SYS_open
        leaq    8(%rsp), %rdi           # rdi = %rsp + 8
        xorq    %rsi, %rsi              # flags = O_RDONLY
        xorq    %rdx, %rdx              # mode = 0
        syscall
        cmpq    $-1, %rax               # open failed
-       jle     .perror
+       jle     perror
        movq    %rdi, %rsp              # rsp = start of string
        subq    $1, %rsp
        movq    %rsp, %r14              # r14 = start of string
-.nextc:
+nextc:
        addq    $1, %rsp
        movb    (%rsp), %dil            # rdi = *rsp
        cmpb    $47, %dil               # *rsp == '/'?
-       jne     .nextc1
+       jne     nextc1
        movq    %rsp, %r14              # r14 = rsp
        addq    $1, %r14                # r14 = char past separator
-.nextc1:
+nextc1:
        cmpb    $0, %dil                # *rsp == 0?
-       jne     .nextc
+       jne     nextc
        addq    $8, %rsp                # adjust past rsp prior to rounding
        andq    $-8, %rsp               # round rsp up to the next quad
        testq   $16, %r15               # r15 & 16?
-       jz      .primary
+       jz      primary
        movq    %rax, %r12              # otherwise, move fd to r12
-       jmp     .next_action
-.primary:
+       jmp     next_action
+primary:
        movq    %rax, %rbx              # if not, move fd to rbx
        movq    $157, %rax              # SYS_prctl
        movq    $15, %rdi               # PR_SET_NAME
@@ -111,82 +111,159 @@ _start:
        xorq    %r8, %r8                # arg4
        xorq    %r9, %r9                # arg5
        syscall
-       jmp     .next_action
-.perror:
+       jmp     next_action
+perror:
        movq    %rax, %r12              # error code
        negq    %r12
        movq    $1, %rax                # SYS_write
        movq    $1, %rdi                # stdout
        leaq    error(%rip), %rsi       # buffer
-       movq    $23, %rdx               # count
+       movq    $24, %rdx               # count
        syscall
        movq    $60, %rax               # SYS_exit
        movq    %r12, %rdi              # code
        syscall
-.rest_of_exec:                         # rsp now points to six quads:
+rest_of_exec:                          # rsp now points to seven quads + string:
        movq    %rsp, %r8               # now, they are r8
        movq    %r13, %rsp              # restore SP
        popq    %r10                    # argc
        leaq    8(%rsp,%r10,8), %rsp    # now at start of environ
-.skip_environ:
-       popq    %r10                    # envp[N]
-       testq   %r10, %r10              # envp[n]?
-       jnz     .skip_environ           # otherwise, rsp is now at the start of auxv
-.one_auxv:
-       popq    %rcx                    # auxv type
-       addq    $8, %rsp                # skip value
-       testq   %rcx, %rcx              # is 0?
-       jz      .cleanup
-       cmpq    $3, %rcx                # is AT_PHDR?
-       je      .replace_phdr
-       cmpq    $4, %rcx                # is AT_PHENT?
-       je      .replace_phent
-       cmpq    $5, %rcx                # is AT_PHNUM?
-       je      .replace_phnum
-       cmpq    $9, %rcx                # is AT_ENTRY?
-       je      .replace_entry
-       cmpq    $7, %rcx                # is AT_BASE?
-       je      .replace_base
-       jmp     .one_auxv
-.replace_phdr:
-       movq    40(%r8), %r9
-       movq    %r9, -8(%rsp)           # set at_phdr
-       jmp     .one_auxv
-.replace_phent:
-       movq    24(%r8), %r9
-       movq    %r9, -8(%rsp)           # set at_phent
-       jmp     .one_auxv
-.replace_phnum:
-       movq    32(%r8), %r9
-       movq    %r9, -8(%rsp)           # set at_phnum
-       jmp     .one_auxv
-.replace_entry:
-       movq    16(%r8), %r9
-       movq    %r9, -8(%rsp)           # set at_entry
-       jmp     .one_auxv
-.replace_base:
-       movq    48(%r8), %r9
-       movq    %r9, -8(%rsp)           # set at_base
-       jmp     .one_auxv
-.cleanup:
+skip_environ:
+       popq    %rcx                    # envp[N]
+       testq   %rcx, %rcx              # envp[n]?
+       jnz     skip_environ            # otherwise, rsp is now at the end of auxv
+       movq    %rsp, %r11              # start of auxv
+1:     testq   $-1, (%r11)             # NULL?
+       leaq    16(%r11), %r11          # next entry
+       jnz     1b                      # otherwise copy auxv
+       /* Prepare sufficient space for the new executable name at the
+          start of the auxiliary vector.  */
+1:     leaq    64(%r8), %rsi           # file name
+       movq    56(%r8), %r9            # name length
+       leaq    -1(%r11), %r14
+       subq    %r9, %r14               # destination of file name
+       andq    $-16, %r14              # align destination
+       /* Prepare to copy argv, environ and auxv.  */
+1:     subq    %r13, %r11              # size required
+       addq    $15, %r11               # align size
+       andq    $-16, %r11
+       negq    %r11                    # subtract
+       leaq    -56(%r14,%r11,1), %r11  # %r11 = destination - struct exec_jump_command
+       /* Move the file name out of the way.  */
+       leaq    9(%rsi,%r9,1), %r10     # end of name + 8
+       cmpq    %r10, %r11              # end of name >= struct exec_jump_command - 8
+       jae     1f                      # save exec command
+       xorq    %r10, %r10
+       subq    %r9, %r10
+       leaq    -9(%r11,%r10,1), %rdi   # position of new name
+       movq    %rdi, %r10
+       cld
+       leaq    1(%r9), %rcx            # length (including termination)
+  rep  movsb                           # copy file name
+       movq    %r10, %rsi              # file name
+       /* Preserve jump command.  */
+       cmpq    %r8, %r11               # decide copy direction
+       jb      1f                      # copy forward
+       movq    48(%r8), %rax
+       movq    %rax, 48(%r11)          # %r11->at_base
+       movq    40(%r8), %rax
+       movq    %rax, 40(%r11)          # %r11->at_phdr
+       movq    32(%r8), %rax
+       movq    %rax, 32(%r11)          # %r11->at_phnum
+       movq    24(%r8), %rax
+       movq    %rax, 24(%r11)          # %r11->at_phent
+       movq    16(%r8), %rax
+       movq    %rax, 16(%r11)          # %r11->at_entry
+       movq    8(%r8), %rax
+       movq    %rax, 8(%r11)           # %r11->entry
+       movq    (%r8), %rax
+       movq    %rax, (%r11)            # %r11->command
+       movq    %r14, -8(%r11)          # destination of file name
+       jmp     copy_env_and_args
+1:     movq    %r14, -8(%r11)          # destination of file name
+       movq    (%r8), %rax
+       movq    %rax, (%r11)            # %r11->command
+       movq    8(%r8), %rax
+       movq    %rax, 8(%r11)           # %r11->entry
+       movq    16(%r8), %rax
+       movq    %rax, 16(%r11)          # %r11->at_entry
+       movq    24(%r8), %rax
+       movq    %rax, 24(%r11)          # %r11->at_phent
+       movq    32(%r8), %rax
+       movq    %rax, 32(%r11)          # %r11->at_phnum
+       movq    40(%r8), %rax
+       movq    %rax, 40(%r11)          # %r11->at_phdr
+       movq    48(%r8), %rax
+       movq    %rax, 48(%r11)          # %r11->at_base
+copy_env_and_args:
+       /* Copy argv and environ to their new positions.  */
+       leaq    8(%r13), %r10           # src
+       leaq    64(%r11), %rdi          # dest
+       movq    (%r13), %rcx            # argc
+       movq    %rcx, -8(%rdi)          # copy argc
+1:     movq    (%r10), %rcx
+       movq    %rcx, (%rdi)
+       testq   %rcx, %rcx
+       leaq    8(%r10), %r10           # src++
+       leaq    8(%rdi), %rdi           # dst++
+       jnz     1b
+1:     movq    (%r10), %rcx
+       movq    %rcx, (%rdi)
+       testq   %rcx, %rcx
+       leaq    8(%r10), %r10           # src++
+       leaq    8(%rdi), %rdi           # dst++
+       jnz     1b
+copy_auxv:
+       movq    (%r10), %rcx            # a_type
+       movq    8(%r10), %rdx           # a_un.a_val
+       addq    $16, %r10               # next entry
+       movq    %rcx, (%rdi)
+       jrcxz   cleanup                 # AT_NULL
+       cmpq    $3, %rcx                # AT_PHDR
+       cmoveq  40(%r11), %rdx          # %r11->at_phdr
+       cmpq    $4, %rcx                # AT_PHENT
+       cmoveq  24(%r11), %rdx          # %r11->at_phent
+       cmpq    $5, %rcx                # AT_PHNUM
+       cmoveq  32(%r11), %rdx          # %r11->at_phnum
+       cmpq    $9, %rcx                # AT_ENTRY
+       cmoveq  16(%r11), %rdx          # %r11->at_entry
+       cmpq    $7, %rcx                # AT_BASE
+       cmoveq  48(%r11), %rdx          # %r11->at_base
+       cmpq    $31, %rcx               # AT_EXECFN
+       jne     1f
+       movq    -8(%r11), %rdx          # string
+1:     movq    %rdx, 8(%rdi)           # AT_NULL value
+       addq    $16, %rdi               # next entry
+       jmp     copy_auxv
+cleanup:
+       /* Copy the filename.  */
+       movq    -8(%r11), %rdi          # destination of file name
+       leaq    1(%r9), %rcx            # length (including termination)
+  rep  movsb
+       movq    %rdx, 8(%rdi)           # AT_NULL value
+       leaq    56(%r11), %r13          # restore original stack pointer
        movq    $3, %rax                # SYS_close
        cmpq    $-1, %r12               # see if interpreter fd is set
-       je      .cleanup_1
+       je      cleanup_1
        movq    %r12, %rdi
        syscall
        movq    $3, %rax                # SYS_close
-.cleanup_1:
+cleanup_1:
        movq    %rbx, %rdi
        syscall
-.enter:
+       /* Enter the program.  */
        pushq   $0
        popfq                           # clear FP state
        movq    %r13, %rsp              # restore SP
        xorq    %rdx, %rdx              # clear rtld_fini
-       jmpq    *8(%r8)                 # entry
+       jmpq    *-48(%rsp)              # entry
 
 error:
-       .ascii  "_start: internal error."
-timespec:
-       .quad   10
-       .quad   10
+       .ascii  "_start: internal error.\n"
+#timespec:
+#      .quad   10
+#      .quad   10
+
+# Local Variables:
+# asm-comment-char: ?#
+# End:
index cfc2d145cd1c0ec08740d4a21f80dd9de8821193..753c78994f268bdda338a2b39181cd63bd456069 100644 (file)
@@ -900,6 +900,18 @@ finish_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
              tracee->pid, 0, 0))
     goto error;
 
+  /* Enable this block to debug the executable loader.  */
+#if 0
+  {
+    int rc, wstatus;
+  again1:
+    rc = waitpid (tracee->pid, &wstatus, __WALL);
+    if (rc == -1 && errno == EINTR)
+      goto again1;
+    ptrace (PTRACE_DETACH, tracee->pid, 0, 0);
+  }
+#endif /* 0 */
+
  error:
   free (tracee->exec_data);
   tracee->exec_data = NULL;