1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 06:20:55 -08:00

Replace AT_EXECFN in auxiliary vectors of programs executed on Android

* 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.
This commit is contained in:
Po Lu 2025-04-13 18:50:59 +08:00
parent f5b59a8a73
commit 7a01350624
6 changed files with 636 additions and 325 deletions

View file

@ -831,7 +831,7 @@ insert_args (struct exec_tracee *tracee, USER_REGS_STRUCT *regs,
assert (new3 == new + effective_size); assert (new3 == new + effective_size);
/* And that it is properly aligned. */ /* 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 + /* Now modify the system call argument to point to new +
text_size. */ text_size. */
@ -916,6 +916,9 @@ exec_0 (char *name, struct exec_tracee *tracee,
program_header program; program_header program;
USER_WORD entry, program_entry, offset; USER_WORD entry, program_entry, offset;
USER_WORD header_offset; USER_WORD header_offset;
#ifndef __mips__
USER_WORD name_len, aligned_len;
#endif /* !__mips__ */
struct exec_jump_command jump; struct exec_jump_command jump;
#if defined __mips__ && !defined MIPS_NABI #if defined __mips__ && !defined MIPS_NABI
int fpu_mode; int fpu_mode;
@ -1146,6 +1149,26 @@ exec_0 (char *name, struct exec_tracee *tracee,
sizeof jump); sizeof jump);
loader_area_used += 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 /* Close the file descriptor and return the number of bytes
used. */ used. */

View file

@ -22,68 +22,68 @@
.section .text .section .text
.global _start .global _start
_start: _start:
//mov x8, 101 // SYS_nanosleep // mov x8, 101 // SYS_nanosleep
//adr x0, timespec // req // adr x0, timespec // req
//mov x1, #0 // rem // mov x1, #0 // rem
//svc #0 // syscall // svc #0 // syscall
mov x20, sp // x20 = sp mov x20, sp // x20 = sp
ldr x10, [x20] // x10 = original SP ldr x10, [x20] // x10 = original SP
add x20, x20, #16 // x20 = start of load area add x20, x20, #16 // x20 = start of load area
mov x28, #-1 // x28 = secondary fd mov x28, #-1 // x28 = secondary fd
.next_action: next_action:
ldr x11, [x20] // action number ldr x11, [x20] // action number
and x12, x11, #-17 // actual 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? cmp x12, #3 // jump?
beq .rest_of_exec beq rest_of_exec
cmp x12, #4 // anonymous mmap? cmp x12, #4 // anonymous mmap?
beq .do_mmap_anon beq do_mmap_anon
.do_mmap: do_mmap:
ldr x0, [x20, 8] // vm_address ldr x0, [x20, 8] // vm_address
ldr x1, [x20, 32] // length ldr x1, [x20, 32] // length
ldr x2, [x20, 24] // protection ldr x2, [x20, 24] // protection
ldr x3, [x20, 40] // flags ldr x3, [x20, 40] // flags
tst x11, #16 // primary fd? tst x11, #16 // primary fd?
mov x4, x29 // primary fd mov x4, x29 // primary fd
beq .do_mmap_1 beq do_mmap_1
mov x4, x28 // secondary fd mov x4, x28 // secondary fd
.do_mmap_1: do_mmap_1:
mov x8, #222 // SYS_mmap mov x8, #222 // SYS_mmap
ldr x5, [x20, 16] // file_offset ldr x5, [x20, 16] // file_offset
svc #0 // syscall svc #0 // syscall
ldr x9, [x20, 8] // length ldr x9, [x20, 8] // length
cmp x0, x9 // mmap result cmp x0, x9 // mmap result
bne .perror // print error bne perror // print error
ldr x3, [x20, 48] // clear ldr x3, [x20, 48] // clear
add x1, x1, x0 // x1 = vm_address + end add x1, x1, x0 // x1 = vm_address + end
sub x3, x1, x3 // x3 = x1 - clear sub x3, x1, x3 // x3 = x1 - clear
mov x0, #0 // x0 = 0 mov x0, #0 // x0 = 0
.fill64: fill64:
sub x2, x1, x3 // x2 = x1 - x3 sub x2, x1, x3 // x2 = x1 - x3
cmp x2, #63 // x2 >= 64? 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] // x3[0] = 0, x3[1] = 0
stp x0, x0, [x3, 16] // x3[2] = 0, x3[3] = 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, 32] // x3[4] = 0, x3[5] = 0
stp x0, x0, [x3, 48] // x3[6] = 0, x3[7] = 0 stp x0, x0, [x3, 48] // x3[6] = 0, x3[7] = 0
add x3, x3, #64 // x3 += 8 add x3, x3, #64 // x3 += 8
b .fill64 b fill64
.fillb: fillb:
cmp x1, x3 // x1 == x3? cmp x1, x3 // x1 == x3?
beq .continue // done beq continue // done
strb w0, [x3], #1 // ((char *) x3)++ = 0 strb w0, [x3], #1 // ((char *) x3)++ = 0
b .fillb b fillb
.continue: continue:
add x20, x20, #56 // next action add x20, x20, #56 // next action
b .next_action b next_action
.do_mmap_anon: do_mmap_anon:
ldr x0, [x20, 8] // vm_address ldr x0, [x20, 8] // vm_address
ldr x1, [x20, 32] // length ldr x1, [x20, 32] // length
ldr x2, [x20, 24] // protection ldr x2, [x20, 24] // protection
ldr x3, [x20, 40] // flags ldr x3, [x20, 40] // flags
mov x4, #-1 // fd mov x4, #-1 // fd
b .do_mmap_1 b do_mmap_1
.open_file: open_file:
mov x8, #56 // SYS_openat mov x8, #56 // SYS_openat
mov x0, #-100 // AT_FDCWD mov x0, #-100 // AT_FDCWD
add x1, x20, #8 // file name add x1, x20, #8 // file name
@ -91,19 +91,19 @@ _start:
mov x3, #0 // mode mov x3, #0 // mode
svc #0 // syscall svc #0 // syscall
cmp x0, #-1 // rc < 0? cmp x0, #-1 // rc < 0?
ble .perror ble perror
mov x19, x1 // x19 == x1 mov x19, x1 // x19 == x1
.nextc: nextc:
ldrb w2, [x1], #1 // b = *x1++ ldrb w2, [x1], #1 // b = *x1++
cmp w2, #47 // dir separator? cmp w2, #47 // dir separator?
bne .nextc1 // not dir separator bne nextc1 // not dir separator
mov x19, x1 // x19 = char past separator mov x19, x1 // x19 = char past separator
.nextc1: nextc1:
cbnz w2, .nextc // b? cbnz w2, nextc // b?
add x1, x1, #7 // round up x1 add x1, x1, #7 // round up x1
and x20, x1, #-8 // mask for round, set x20 and x20, x1, #-8 // mask for round, set x20
tst x11, #16 // primary fd? tst x11, #16 // primary fd?
bne .secondary // secondary fd bne secondary // secondary fd
mov x29, x0 // primary fd mov x29, x0 // primary fd
mov x8, #167 // SYS_prctl mov x8, #167 // SYS_prctl
mov x0, #15 // PR_SET_NAME mov x0, #15 // PR_SET_NAME
@ -113,75 +113,117 @@ _start:
mov x4, #0 // arg4 mov x4, #0 // arg4
mov x5, #0 // arg5 mov x5, #0 // arg5
svc #0 // syscall svc #0 // syscall
b .next_action // next action b next_action // next action
.secondary: secondary:
mov x28, x0 // secondary fd mov x28, x0 // secondary fd
b .next_action // next action. b next_action // next action.
.perror: perror:
mov x8, #93 // SYS_exit mov x8, #93 // SYS_exit
mvn x0, x0 // x1 = ~x0 mvn x0, x0 // x1 = ~x0
add x0, x0, 1 // x1 += 1 add x0, x0, 1 // x1 += 1
svc #0 // exit svc #0 // exit
.rest_of_exec: rest_of_exec:
mov x7, x20 // x7 = x20 mov x7, x20 // x7 = x20
mov x20, x10 // x20 = x10 mov x8, x10 // x8 = x10
ldr x9, [x20] // argc ldr x9, [x8], #16 // (void *) x8 += 2
add x9, x9, #2 // x9 += 2
lsl x9, x9, #3 // argc * 8 lsl x9, x9, #3 // argc * 8
add x20, x20, x9 // now past argv add x8, x8, x9 // now past argv
.skipenv: skip_environ:
ldr x9, [x20], #8 // x9 = *envp++ ldr x9, [x8], #8 // x9 = *envp++
cbnz x9, .skipenv // x9? cbnz x9, skip_environ // x9?
.one_auxv: // Skip the auxiliary vector.
ldr x9, [x20], #16 // x9 = *sp, sp += 2 1: ldp x11, x12, [x8], #16 // a_type, a_un.a_val
cbz x9, .cleanup // !x9? cbnz x11, 1b // a_type != NULL
cmp x9, #3 // is AT_PHDR? // Prepare sufficient space at x20 for the file name string.
beq .replace_phdr // replace // Load the aforesaid string, and its length.
cmp x9, #4 // is AT_PHENT? ldr x6, [x7, 56] // string length
beq .replace_phent // replace add x6, x6, 1
cmp x9, #5 // is AT_PHNUM? add x5, x7, 64 // string pointer
beq .replace_phnum // replace sub x4, x10, x8 // number of elements to copy
cmp x9, #9 // is AT_ENTRY? sub x7, x8, x6 // AT_EXECFN location
beq .replace_entry // replace and x7, x7, -8 // align value
cmp x9, #7 // is AT_BASE? add x4, x7, x4 // destination argc
beq .replace_base // replace and x4, x4, -16 // align destination argc
b .one_auxv // next auxv // Load values that must be into registers x14-x19.
.replace_phdr: // x14 = cmd->entry
ldr x9, [x7, 40] // at_phdr // x15 = cmd->at_entry
str x9, [x20, -8] // store value // x16 = cmd->at_phent
b .one_auxv // x17 = cmd->at_phnum
.replace_phent: // x18 = cmd->at_phdr
ldr x9, [x7, 24] // at_phent // x19 = cmd->at_base
str x9, [x20, -8] // store value ldp x14, x15, [x20, 8]
b .one_auxv ldp x16, x17, [x20, 24]
.replace_phnum: ldp x18, x19, [x20, 40]
ldr x9, [x7, 32] // at_phnum // Move the string to a safe location, if necessary.
str x9, [x20, -8] // store value sub x3, x4, x5 // distance from dest to string
b .one_auxv cmp x3, x6 // distance > length
.replace_entry: bge copy_env_and_args // not necessary
ldr x9, [x7, 16] // at_entry mov x2, x5 // src
str x9, [x20, -8] // store value sub x5, x4, x6 // backup string
b .one_auxv mov x1, x5 // dst
.replace_base: add x9, x2, x6 // src end
ldr x9, [x7, 48] // at_base cmp x2, x9
str x9, [x20, -8] // store value bcs copy_env_and_args
b .one_auxv 1: ldrb w3, [x2], #1
.cleanup: strb w3, [x1], #1
cmp x28, #-1 // is secondary fd set? cmp x2, x9
bne .cleanup1 // not set 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 x8, #57 // SYS_close
mov x0, x28 // secondary fd mov x0, x28 // secondary fd
svc #0 // syscall svc #0 // syscall
.cleanup1: cleanup1:
mov x8, #57 // SYS_close mov x8, #57 // SYS_close
mov x0, x29 // primary fd mov x0, x29 // primary fd
svc #0 // syscall svc #0 // syscall
.enter: enter:
mov sp, x10 // restore original SP mov sp, x10 // restore original SP
mov x0, #0 // clear rtld_fini mov x0, #0 // clear rtld_fini
ldr x1, [x7, 8] // branch to code br x14
br x1
timespec: // timespec:
.quad 10 // .quad 10
.quad 10 // .quad 10
// Local Variables:
// asm-comment-char: ?/
// End:

View file

@ -18,23 +18,23 @@
.section .text .section .text
.global _start .global _start
_start: _start:
@mov r7, #162 @ SYS_nanosleep @@ mov r7, #162 @ SYS_nanosleep
@adr r0, timespec @ req @@ adr r0, timespec @ req
@mov r1, #0 @ rem @@ mov r1, #0 @ rem
@swi #0 @ syscall @@ swi #0 @ syscall
mov r8, sp @ r8 = sp mov r8, sp @ r8 = sp
ldr r9, [r8], #8 @ r9 = original sp, r8 += 8 ldr r9, [r8], #8 @ r9 = original sp, r8 += 8
mov r14, #-1 @ r14 = secondary fd mov r14, #-1 @ r14 = secondary fd
.next_action: next_action:
ldr r11, [r8] @ r11 = action number ldr r11, [r8] @ r11 = action number
and r12, r11, #-17 @ actual action number and r12, r11, #-17 @ actual action number
cmp r12, #0 @ open file? cmp r12, #0 @ open file?
beq .open_file @ open file. beq open_file @ open file.
cmp r12, #3 @ jump? cmp r12, #3 @ jump?
beq .rest_of_exec @ jump to code. beq rest_of_exec @ jump to code.
cmp r12, #4 @ anonymous mmap? cmp r12, #4 @ anonymous mmap?
beq .do_mmap_anon @ anonymous mmap. beq do_mmap_anon @ anonymous mmap.
.do_mmap: do_mmap:
add r6, r8, #4 @ r6 = r8 + 4 add r6, r8, #4 @ r6 = r8 + 4
ldm r6!, {r0, r5} @ vm_address, file_offset ldm r6!, {r0, r5} @ vm_address, file_offset
ldm r6!, {r1, r2} @ protection, length ldm r6!, {r1, r2} @ protection, length
@ -45,28 +45,28 @@ _start:
ldm r6!, {r3, r12} @ flags, clear ldm r6!, {r3, r12} @ flags, clear
tst r11, #16 @ primary fd? tst r11, #16 @ primary fd?
mov r4, r10 @ primary fd mov r4, r10 @ primary fd
beq .do_mmap_1 beq do_mmap_1
mov r4, r14 @ secondary fd mov r4, r14 @ secondary fd
.do_mmap_1: do_mmap_1:
mov r7, #192 @ SYS_mmap2 mov r7, #192 @ SYS_mmap2
swi #0 @ syscall swi #0 @ syscall
ldr r2, [r8, #4] @ vm_address ldr r2, [r8, #4] @ vm_address
cmp r2, r0 @ rc == vm_address? cmp r2, r0 @ rc == vm_address?
bne .perror bne perror
add r0, r1, r2 @ r0 = length + vm_address add r0, r1, r2 @ r0 = length + vm_address
sub r3, r0, r12 @ r3 = r0 - clear sub r3, r0, r12 @ r3 = r0 - clear
mov r1, #0 @ r1 = 0 mov r1, #0 @ r1 = 0
.align: align:
cmp r0, r3 @ r0 == r3? cmp r0, r3 @ r0 == r3?
beq .continue @ continue beq continue @ continue
tst r3, #3 @ r3 & 3? tst r3, #3 @ r3 & 3?
bne .fill32 @ fill aligned bne fill32 @ fill aligned
strb r1, [r3], #1 @ fill byte strb r1, [r3], #1 @ fill byte
b .align @ align again b align @ align again
.fill32: fill32:
sub r2, r0, r3 @ r2 = r0 - r3 sub r2, r0, r3 @ r2 = r0 - r3
cmp r2, #31 @ r2 >= 32? 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 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 str r1, [r3], #4 @ *r3++ = 0
str r1, [r3], #4 @ *r3++ = 0 str r1, [r3], #4 @ *r3++ = 0
b .fill32 b fill32
.fillb: fillb:
cmp r0, r3 @ r0 == r3 cmp r0, r3 @ r0 == r3
beq .continue @ done beq continue @ done
strb r1, [r3], #1 @ ((char *) r3)++ = 0 strb r1, [r3], #1 @ ((char *) r3)++ = 0
b .fillb b fillb
.continue: continue:
add r8, r8, #28 @ next action add r8, r8, #28 @ next action
b .next_action b next_action
.do_mmap_anon: do_mmap_anon:
add r6, r8, #4 @ r6 = r8 + 4 add r6, r8, #4 @ r6 = r8 + 4
ldm r6!, {r0, r5} @ vm_address, file_offset ldm r6!, {r0, r5} @ vm_address, file_offset
ldm r6!, {r1, r2} @ protection, length ldm r6!, {r1, r2} @ protection, length
@ -94,29 +94,29 @@ _start:
mov r2, r3 @ swap mov r2, r3 @ swap
ldm r6!, {r3, r12} @ flags, clear ldm r6!, {r3, r12} @ flags, clear
mov r4, #-1 @ fd mov r4, #-1 @ fd
b .do_mmap_1 b do_mmap_1
.open_file: open_file:
mov r7, #5 @ SYS_open mov r7, #5 @ SYS_open
add r0, r8, #4 @ file name add r0, r8, #4 @ file name
mov r1, #0 @ O_RDONLY mov r1, #0 @ O_RDONLY
mov r2, #0 @ mode mov r2, #0 @ mode
swi #0 @ syscall swi #0 @ syscall
cmp r0, #-1 @ r0 <= -1? cmp r0, #-1 @ r0 <= -1?
ble .perror ble perror
add r8, r8, #4 @ r8 = start of string add r8, r8, #4 @ r8 = start of string
mov r1, r8 @ r1 = r8 mov r1, r8 @ r1 = r8
.nextc: nextc:
ldrb r2, [r8], #1 @ b = *r0++ ldrb r2, [r8], #1 @ b = *r0++
cmp r2, #47 @ dir separator? cmp r2, #47 @ dir separator?
bne .nextc1 @ not dir separator bne nextc1 @ not dir separator
mov r1, r8 @ r1 = char past separator mov r1, r8 @ r1 = char past separator
.nextc1: nextc1:
cmp r2, #0 @ b? cmp r2, #0 @ b?
bne .nextc @ next character bne nextc @ next character
add r8, r8, #3 @ round up r8 add r8, r8, #3 @ round up r8
and r8, r8, #-4 @ mask for round, set r8 and r8, r8, #-4 @ mask for round, set r8
tst r11, #16 @ primary fd? tst r11, #16 @ primary fd?
bne .secondary @ secondary fd bne secondary @ secondary fd
mov r10, r0 @ primary fd mov r10, r0 @ primary fd
mov r7, #172 @ SYS_prctl mov r7, #172 @ SYS_prctl
mov r0, #15 @ PR_SET_NAME, r1 = name mov r0, #15 @ PR_SET_NAME, r1 = name
@ -125,79 +125,139 @@ _start:
mov r4, #0 @ arg4 mov r4, #0 @ arg4
mov r5, #0 @ arg5 mov r5, #0 @ arg5
swi #0 @ syscall swi #0 @ syscall
b .next_action @ next action b next_action @ next action
.secondary: secondary:
mov r14, r0 @ secondary fd mov r14, r0 @ secondary fd
b .next_action @ next action b next_action @ next action
.perror: perror:
mov r7, #1 @ SYS_exit mov r7, #1 @ SYS_exit
mvn r0, r0 @ r0 = ~r0 mvn r0, r0 @ r0 = ~r0
add r0, r0, #1 @ r0 += 1 add r0, r0, #1 @ r0 += 1
swi #0 swi #0
.rest_of_exec: rest_of_exec: @ r8 points to seven ints + string
mov r7, r9 @ r7 = original SP mov r7, r9 @ r7 = original SP
ldr r6, [r7] @ argc ldr r6, [r7], #8 @ argc & terminator
add r6, r6, #2 @ argc + 2
lsl r6, r6, #2 @ argc *= 4 lsl r6, r6, #2 @ argc *= 4
add r7, r7, r6 @ now past argv add r7, r7, r6 @ now past argv
.skipenv: ldr r6, [r8, #28] @ length of string
ldr r6, [r7], #4 @ r6 = *r7++ add r6, r6, #1
cmp r6, #0 @ r6? skip_environ:
bne .skipenv @ r6? 1: ldr r1, [r7], #4 @ r1 = *r7++
.one_auxv: tst r1, r1 @ r1
ldr r6, [r7], #8 @ r6 = *r7, r7 += 2 bne 1b @ r1
cmp r6, #0 @ !r6? 1: ldm r7!, {r0, r1} @ a_type, a_un.a_val
beq .cleanup @ r6? tst r0, r0
cmp r6, #3 @ is AT_PHDR? bne 1b @ a_type -> 1b
beq .replace_phdr @ replace @@ Establish the number of bytes in the argument, environment,
cmp r6, #4 @ is AT_PHENT? @@ and auxiliary vectors to be moved.
beq .replace_phent @ replace sub r5, r7, r9 @ r5 = bytes in vectors
cmp r6, #5 @ is AT_PHNUM? @@ Expand r7 with sufficient space for the filename and align
beq .replace_phnum @ replace @@ it.
cmp r6, #9 @ is AT_ENTRY? sub r4, r7, r5
beq .replace_entry @ replace and r4, r4, #-8 @ r4 = address of AT_EXECFN
cmp r6, #7 @ is AT_BASE? sub r3, r4, r5 @ r4 - number of bytes in vectors
beq .replace_base @ replace and r3, r3, #-16 @ r3 = position of new argc
b .one_auxv @ next auxv @@ Reserve an area that is guaranteed not to be clobbered into
.replace_phdr: @@ which to copy the command and file name.
ldr r6, [r8, #20] @ at_phdr mov r2, r3
str r6, [r7, #-4] @ store value cmp r2, r8
b .one_auxv blo 1f
.replace_phent: mov r2, r8
ldr r6, [r8, #12] @ at_phent 1: sub r2, r2, #24 @ space for data
str r6, [r7, #-4] @ store value @@ [r2, #0] = entry
b .one_auxv @@ [r2, #4] = at_entry
.replace_phnum: @@ [r2, #8] = at_phent
ldr r6, [r8, #16] @ at_phnum @@ [r2, #12] = at_phnum
str r6, [r7, #-4] @ store value @@ [r2, #16] = at_phdr
b .one_auxv @@ [r2, #20] = at_base
.replace_entry: add r7, r8, #4 @ &cmd->entry
ldr r6, [r8, #8] @ at_entry ldm r7!, {r0, r1}
str r6, [r7, #-4] @ store value stm r2!, {r0, r1}
b .one_auxv ldm r7!, {r0, r1}
.replace_base: stm r2!, {r0, r1}
ldr r6, [r8, #24] @ at_base ldm r7!, {r0, r1}
str r6, [r7, #-4] @ store value stm r2!, {r0, r1}
b .one_auxv sub r2, r2, #24
.cleanup: 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? cmp r14, #-1 @ secondary fd set?
bne .cleanup1 @ not set beq cleanup1 @ not set
mov r7, #6 @ SYS_close mov r7, #6 @ SYS_close
mov r0, r14 @ secondary fd mov r0, r14 @ secondary fd
swi #0 @ syscall swi #0 @ syscall
.cleanup1: cleanup1:
mov r7, #6 @ SYS_close mov r7, #6 @ SYS_close
mov r0, r10 @ primary fd mov r0, r10 @ primary fd
swi #0 @ syscall swi #0 @ syscall
.enter: enter:
mov sp, r9 @ restore original SP mov sp, r9 @ restore original SP
mov r0, #0 @ clear rtld_fini mov r0, #0 @ clear rtld_fini
ldr r1, [r8, #4] @ branch to code ldr r1, [r2] @ branch to code
bx r1 bx r1
timespec: @@ timespec:
.long 10 @@ .long 10
.long 10 @@ .long 10
@ Local Variables: @ Local Variables:
@ asm-comment-char: ?@ @ asm-comment-char: ?@

View file

@ -15,26 +15,29 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. # 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 .section .text
.global _start .global _start
_start: _start:
# movl $162, %eax # SYS_nanosleep ## movl $162, %eax # SYS_nanosleep
# leal timespec, %ebx ## leal timespec, %ebx
# xorl %ecx, %ecx ## xorl %ecx, %ecx
# int $0x80 ## int $0x80
leal 8(%esp), %ebp # ebp = start of load area leal 8(%esp), %ebp # ebp = start of load area
subl $8, %esp # (%esp) = primary fd, 4(%esp) = secondary fd subl $8, %esp # (%esp) = primary fd, 4(%esp) = secondary fd
movl $-1, 4(%esp) movl $-1, 4(%esp)
.next_action: next_action:
movl (%ebp), %edx # edx = action number movl (%ebp), %edx # edx = action number
andl $-17, %edx andl $-17, %edx
cmpl $0, %edx # open file? cmpl $0, %edx # open file?
je .open_file je open_file
cmpl $3, %edx # jump? cmpl $3, %edx # jump?
je .rest_of_exec je rest_of_exec
cmpl $4, %edx # anonymous mmap? cmpl $4, %edx # anonymous mmap?
je .do_mmap_anon je do_mmap_anon
.do_mmap: do_mmap:
subl $24, %esp subl $24, %esp
movl $90, %eax # SYS_old_mmap movl $90, %eax # SYS_old_mmap
movl %esp, %ebx movl %esp, %ebx
@ -52,27 +55,27 @@ _start:
movl %ecx, 16(%esp) # fd movl %ecx, 16(%esp) # fd
movl 8(%ebp), %ecx # offset movl 8(%ebp), %ecx # offset
movl %ecx, 20(%esp) movl %ecx, 20(%esp)
.do_mmap_1: do_mmap_1:
int $0x80 int $0x80
addl $24, %esp # restore esp addl $24, %esp # restore esp
cmpl $-1, %eax # mmap failed? cmpl $-1, %eax # mmap failed?
je .perror je perror
movl 24(%ebp), %ecx # clear movl 24(%ebp), %ecx # clear
testl %ecx, %ecx testl %ecx, %ecx
jz .continue jz continue
movl 4(%ebp), %esi # start of mapping movl 4(%ebp), %esi # start of mapping
addl 16(%ebp), %esi # end of mapping addl 16(%ebp), %esi # end of mapping
subl %ecx, %esi # start of clear area subl %ecx, %esi # start of clear area
.again: again:
testl %ecx, %ecx testl %ecx, %ecx
jz .continue jz continue
subl $1, %ecx subl $1, %ecx
movb $0, (%esi, %ecx, 1) movb $0, (%esi, %ecx, 1)
jmp .again jmp again
.continue: continue:
leal 28(%ebp), %ebp leal 28(%ebp), %ebp
jmp .next_action jmp next_action
.do_mmap_anon: do_mmap_anon:
subl $24, %esp subl $24, %esp
movl $90, %eax # SYS_old_mmap movl $90, %eax # SYS_old_mmap
movl %esp, %ebx movl %esp, %ebx
@ -87,8 +90,8 @@ _start:
movl $-1, 16(%esp) # fd movl $-1, 16(%esp) # fd
movl 8(%ebp), %ecx # offset movl 8(%ebp), %ecx # offset
movl %ecx, 20(%esp) movl %ecx, 20(%esp)
jmp .do_mmap_1 jmp do_mmap_1
.open_file: open_file:
movl $5, %eax # SYS_open movl $5, %eax # SYS_open
leal 4(%ebp), %ebx # ebx = %esp + 8 leal 4(%ebp), %ebx # ebx = %esp + 8
pushl %ebx pushl %ebx
@ -96,27 +99,27 @@ _start:
xorl %edx, %edx # mode = 0 xorl %edx, %edx # mode = 0
int $0x80 int $0x80
cmpl $-1, %eax # open failed? cmpl $-1, %eax # open failed?
jle .perror jle perror
movl %ebp, %esi # (esi) = original action number movl %ebp, %esi # (esi) = original action number
popl %ebp # ebp = start of string popl %ebp # ebp = start of string
movl %ebp, %ecx # char past separator movl %ebp, %ecx # char past separator
decl %ebp decl %ebp
.nextc: nextc:
incl %ebp incl %ebp
movb (%ebp), %dl # dl = *ebp movb (%ebp), %dl # dl = *ebp
cmpb $47, %dl # dl == '\?'? cmpb $47, %dl # dl == '\?'?
jne .nextc1 jne nextc1
leal 1(%ebp), %ecx # ecx = char past separator leal 1(%ebp), %ecx # ecx = char past separator
.nextc1: nextc1:
cmpb $0, %dl # dl == 0? cmpb $0, %dl # dl == 0?
jne .nextc jne nextc
addl $4, %ebp # adjust past ebp prior to rounding addl $4, %ebp # adjust past ebp prior to rounding
andl $-4, %ebp # round ebp up to the next long andl $-4, %ebp # round ebp up to the next long
testl $16, (%esi) # original action number & 16? testl $16, (%esi) # original action number & 16?
jz .primary jz primary
movl %eax, 4(%esp) # secondary fd = eax movl %eax, 4(%esp) # secondary fd = eax
jmp .next_action jmp next_action
.primary: primary:
pushl %ebp pushl %ebp
xorl %esi, %esi # arg3 xorl %esi, %esi # arg3
movl %eax, 4(%esp) # primary fd = eax movl %eax, 4(%esp) # primary fd = eax
@ -127,74 +130,168 @@ _start:
xorl %ebp, %ebp # arg5 xorl %ebp, %ebp # arg5
int $0x80 # syscall int $0x80 # syscall
popl %ebp popl %ebp
jmp .next_action jmp next_action
.perror: perror:
movl %eax, %ebx movl %eax, %ebx
negl %ebx negl %ebx
movl $1, %eax movl $1, %eax
int $0x80 int $0x80
.rest_of_exec: rest_of_exec:
movl 8(%esp), %ecx # ecx = original stack pointer movl 8(%esp), %ecx # ecx = original stack pointer
movl (%ecx), %esi # esi = argc movl (%ecx), %esi # esi = argc
leal 8(%ecx, %esi, 4), %ecx # ecx = start of environ 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] movl (%ecx), %esi # envp[N]
addl $4, %ecx addl $4, %ecx
testl %esi, %esi # envp[n] ? testl %esi, %esi # envp[n] ?
jnz .skip_environ # otherwise, esi is now at the start of auxv jnz skip_environ # otherwise, ecx is now at the end of auxv
.one_auxv: 1: testl $-1, (%ecx) # auxv type
movl (%ecx), %esi # auxv type
leal 8(%ecx), %ecx # skip to next auxv leal 8(%ecx), %ecx # skip to next auxv
testl %esi, %esi # is 0? jnz 1b # otherwise copy auxv
jz .cleanup movl %ecx, %edx # end of auxv
cmpl $3, %esi # is AT_PHDR /* Prepare sufficient space for the new executable name at the
je .replace_phdr start of the auxiliary vector. */
cmpl $4, %esi # is AT_PHENT? 1: leal 32(%ebp), %esi # file name
je .replace_phent /* 28(%ebp) = file name length. */
cmpl $5, %esi # is AT_PHNUM? subl 28(%ebp), %ecx # destination of file name
je .replace_phnum decl %ecx
cmpl $9, %esi # is AT_ENTRY? /* This is still 16 bytes on i386--see arch_align_stack:
je .replace_entry https://android.googlesource.com/kernel/goldfish/+/refs/heads
cmpl $7, %esi # is AT_BASE /android-goldfish-3.10/arch/x86/kernel/process.c#446. */
je .replace_base andl $-16, %ecx # align stack
jmp .one_auxv /* Prepare to store the auxiliary, environment, and argument
.replace_phdr: vectors. */
movl 20(%ebp), %esi 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) movl %esi, -4(%ecx)
jmp .one_auxv jmp copy_auxv
.replace_phent: 1: movl -40(%ebp), %esi
movl 12(%ebp), %esi
movl %esi, -4(%ecx) movl %esi, -4(%ecx)
jmp .one_auxv jmp copy_auxv
.replace_phnum: 2: movl -32(%ebp), %esi
movl 16(%ebp), %esi
movl %esi, -4(%ecx) movl %esi, -4(%ecx)
jmp .one_auxv jmp copy_auxv
.replace_entry: 3: movl -36(%ebp), %esi
movl 8(%ebp), %esi
movl %esi, -4(%ecx) movl %esi, -4(%ecx)
jmp .one_auxv jmp copy_auxv
.replace_base: 4: movl -28(%ebp), %esi
movl 24(%ebp), %esi
movl %esi, -4(%ecx) movl %esi, -4(%ecx)
jmp .one_auxv jmp copy_auxv
.cleanup: 5: movl -44(%ebp), %esi
movl %esi, -4(%ecx)
jmp copy_auxv
6: movl -4(%ebp), %esi # Note: the filename is yet to be copied.
movl %esi, -4(%ecx)
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 movl $6, %eax # SYS_close
cmpl $-1, 4(%esp) # see if interpreter fd is set cmpl $-1, -52(%ebp) # see if interpreter fd is set
je .cleanup_1 je cleanup_1
movl 4(%esp), %ebx movl -52(%ebp), %ebx
int $0x80 int $0x80
movl $6, %eax # SYS_close movl $6, %eax # SYS_close
.cleanup_1: cleanup_1:
movl (%esp), %ebx movl -48(%ebp), %ebx
int $0x80 int $0x80
.enter: enter:
pushl $0 pushl $0
popfl # restore floating point state 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 xorl %edx, %edx # clear rtld_fini
jmpl *4(%ebp) # entry jmpl *-24(%ebp) # entry
## timespec:
## .long 10
## .long 10
timespec: # Local Variables:
.long 10 # asm-comment-char: ?#
.long 10 # End:

View file

@ -25,17 +25,17 @@ _start:
popq %r13 # original SP popq %r13 # original SP
popq %r15 # size of load area. popq %r15 # size of load area.
movq $-1, %r12 # r12 is the interpreter fd movq $-1, %r12 # r12 is the interpreter fd
.next_action: next_action:
movq (%rsp), %r14 # action number movq (%rsp), %r14 # action number
movq %r14, %r15 # original action number movq %r14, %r15 # original action number
andq $-17, %r14 andq $-17, %r14
cmpq $0, %r14 # open file? cmpq $0, %r14 # open file?
je .open_file je open_file
cmpq $3, %r14 # jump? cmpq $3, %r14 # jump?
je .rest_of_exec je rest_of_exec
cmpq $4, %r14 # anonymous mmap? cmpq $4, %r14 # anonymous mmap?
je .do_mmap_anon je do_mmap_anon
.do_mmap: do_mmap:
movq $9, %rax # SYS_mmap movq $9, %rax # SYS_mmap
movq 8(%rsp), %rdi # address movq 8(%rsp), %rdi # address
movq 16(%rsp), %r9 # offset movq 16(%rsp), %r9 # offset
@ -46,26 +46,26 @@ _start:
testq $16, %r15 testq $16, %r15
movq %r12, %r8 movq %r12, %r8
cmovzq %rbx, %r8 cmovzq %rbx, %r8
.do_mmap_1: do_mmap_1:
syscall syscall
cmpq $-1, %rax # mmap failed cmpq $-1, %rax # mmap failed
je .perror je perror
movq 48(%rsp), %r9 # clear movq 48(%rsp), %r9 # clear
testq %r9, %r9 testq %r9, %r9
jz .continue jz continue
movq 8(%rsp), %r10 # start of mapping movq 8(%rsp), %r10 # start of mapping
addq 32(%rsp), %r10 # end of mapping addq 32(%rsp), %r10 # end of mapping
subq %r9, %r10 # start of clear area subq %r9, %r10 # start of clear area
.again: again:
testq %r9, %r9 testq %r9, %r9
jz .continue jz continue
subq $1, %r9 subq $1, %r9
movb $0, (%r10, %r9, 1) movb $0, (%r10, %r9, 1)
jmp .again jmp again
.continue: continue:
leaq 56(%rsp), %rsp leaq 56(%rsp), %rsp
jmp .next_action jmp next_action
.do_mmap_anon: do_mmap_anon:
movq $9, %rax # SYS_mmap movq $9, %rax # SYS_mmap
movq 8(%rsp), %rdi # address movq 8(%rsp), %rdi # address
movq 16(%rsp), %r9 # offset movq 16(%rsp), %r9 # offset
@ -73,35 +73,35 @@ _start:
movq 32(%rsp), %rsi # length movq 32(%rsp), %rsi # length
movq 40(%rsp), %r10 # flags movq 40(%rsp), %r10 # flags
movq $-1, %r8 # -1 movq $-1, %r8 # -1
jmp .do_mmap_1 jmp do_mmap_1
.open_file: open_file:
movq $2, %rax # SYS_open movq $2, %rax # SYS_open
leaq 8(%rsp), %rdi # rdi = %rsp + 8 leaq 8(%rsp), %rdi # rdi = %rsp + 8
xorq %rsi, %rsi # flags = O_RDONLY xorq %rsi, %rsi # flags = O_RDONLY
xorq %rdx, %rdx # mode = 0 xorq %rdx, %rdx # mode = 0
syscall syscall
cmpq $-1, %rax # open failed cmpq $-1, %rax # open failed
jle .perror jle perror
movq %rdi, %rsp # rsp = start of string movq %rdi, %rsp # rsp = start of string
subq $1, %rsp subq $1, %rsp
movq %rsp, %r14 # r14 = start of string movq %rsp, %r14 # r14 = start of string
.nextc: nextc:
addq $1, %rsp addq $1, %rsp
movb (%rsp), %dil # rdi = *rsp movb (%rsp), %dil # rdi = *rsp
cmpb $47, %dil # *rsp == '/'? cmpb $47, %dil # *rsp == '/'?
jne .nextc1 jne nextc1
movq %rsp, %r14 # r14 = rsp movq %rsp, %r14 # r14 = rsp
addq $1, %r14 # r14 = char past separator addq $1, %r14 # r14 = char past separator
.nextc1: nextc1:
cmpb $0, %dil # *rsp == 0? cmpb $0, %dil # *rsp == 0?
jne .nextc jne nextc
addq $8, %rsp # adjust past rsp prior to rounding addq $8, %rsp # adjust past rsp prior to rounding
andq $-8, %rsp # round rsp up to the next quad andq $-8, %rsp # round rsp up to the next quad
testq $16, %r15 # r15 & 16? testq $16, %r15 # r15 & 16?
jz .primary jz primary
movq %rax, %r12 # otherwise, move fd to r12 movq %rax, %r12 # otherwise, move fd to r12
jmp .next_action jmp next_action
.primary: primary:
movq %rax, %rbx # if not, move fd to rbx movq %rax, %rbx # if not, move fd to rbx
movq $157, %rax # SYS_prctl movq $157, %rax # SYS_prctl
movq $15, %rdi # PR_SET_NAME movq $15, %rdi # PR_SET_NAME
@ -111,82 +111,159 @@ _start:
xorq %r8, %r8 # arg4 xorq %r8, %r8 # arg4
xorq %r9, %r9 # arg5 xorq %r9, %r9 # arg5
syscall syscall
jmp .next_action jmp next_action
.perror: perror:
movq %rax, %r12 # error code movq %rax, %r12 # error code
negq %r12 negq %r12
movq $1, %rax # SYS_write movq $1, %rax # SYS_write
movq $1, %rdi # stdout movq $1, %rdi # stdout
leaq error(%rip), %rsi # buffer leaq error(%rip), %rsi # buffer
movq $23, %rdx # count movq $24, %rdx # count
syscall syscall
movq $60, %rax # SYS_exit movq $60, %rax # SYS_exit
movq %r12, %rdi # code movq %r12, %rdi # code
syscall 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 %rsp, %r8 # now, they are r8
movq %r13, %rsp # restore SP movq %r13, %rsp # restore SP
popq %r10 # argc popq %r10 # argc
leaq 8(%rsp,%r10,8), %rsp # now at start of environ leaq 8(%rsp,%r10,8), %rsp # now at start of environ
.skip_environ: skip_environ:
popq %r10 # envp[N] popq %rcx # envp[N]
testq %r10, %r10 # envp[n]? testq %rcx, %rcx # envp[n]?
jnz .skip_environ # otherwise, rsp is now at the start of auxv jnz skip_environ # otherwise, rsp is now at the end of auxv
.one_auxv: movq %rsp, %r11 # start of auxv
popq %rcx # auxv type 1: testq $-1, (%r11) # NULL?
addq $8, %rsp # skip value leaq 16(%r11), %r11 # next entry
testq %rcx, %rcx # is 0? jnz 1b # otherwise copy auxv
jz .cleanup /* Prepare sufficient space for the new executable name at the
cmpq $3, %rcx # is AT_PHDR? start of the auxiliary vector. */
je .replace_phdr 1: leaq 64(%r8), %rsi # file name
cmpq $4, %rcx # is AT_PHENT? movq 56(%r8), %r9 # name length
je .replace_phent leaq -1(%r11), %r14
cmpq $5, %rcx # is AT_PHNUM? subq %r9, %r14 # destination of file name
je .replace_phnum andq $-16, %r14 # align destination
cmpq $9, %rcx # is AT_ENTRY? /* Prepare to copy argv, environ and auxv. */
je .replace_entry 1: subq %r13, %r11 # size required
cmpq $7, %rcx # is AT_BASE? addq $15, %r11 # align size
je .replace_base andq $-16, %r11
jmp .one_auxv negq %r11 # subtract
.replace_phdr: leaq -56(%r14,%r11,1), %r11 # %r11 = destination - struct exec_jump_command
movq 40(%r8), %r9 /* Move the file name out of the way. */
movq %r9, -8(%rsp) # set at_phdr leaq 9(%rsi,%r9,1), %r10 # end of name + 8
jmp .one_auxv cmpq %r10, %r11 # end of name >= struct exec_jump_command - 8
.replace_phent: jae 1f # save exec command
movq 24(%r8), %r9 xorq %r10, %r10
movq %r9, -8(%rsp) # set at_phent subq %r9, %r10
jmp .one_auxv leaq -9(%r11,%r10,1), %rdi # position of new name
.replace_phnum: movq %rdi, %r10
movq 32(%r8), %r9 cld
movq %r9, -8(%rsp) # set at_phnum leaq 1(%r9), %rcx # length (including termination)
jmp .one_auxv rep movsb # copy file name
.replace_entry: movq %r10, %rsi # file name
movq 16(%r8), %r9 /* Preserve jump command. */
movq %r9, -8(%rsp) # set at_entry cmpq %r8, %r11 # decide copy direction
jmp .one_auxv jb 1f # copy forward
.replace_base: movq 48(%r8), %rax
movq 48(%r8), %r9 movq %rax, 48(%r11) # %r11->at_base
movq %r9, -8(%rsp) # set at_base movq 40(%r8), %rax
jmp .one_auxv movq %rax, 40(%r11) # %r11->at_phdr
.cleanup: 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 movq $3, %rax # SYS_close
cmpq $-1, %r12 # see if interpreter fd is set cmpq $-1, %r12 # see if interpreter fd is set
je .cleanup_1 je cleanup_1
movq %r12, %rdi movq %r12, %rdi
syscall syscall
movq $3, %rax # SYS_close movq $3, %rax # SYS_close
.cleanup_1: cleanup_1:
movq %rbx, %rdi movq %rbx, %rdi
syscall syscall
.enter: /* Enter the program. */
pushq $0 pushq $0
popfq # clear FP state popfq # clear FP state
movq %r13, %rsp # restore SP movq %r13, %rsp # restore SP
xorq %rdx, %rdx # clear rtld_fini xorq %rdx, %rdx # clear rtld_fini
jmpq *8(%r8) # entry jmpq *-48(%rsp) # entry
error: error:
.ascii "_start: internal error." .ascii "_start: internal error.\n"
timespec: #timespec:
.quad 10 # .quad 10
.quad 10 # .quad 10
# Local Variables:
# asm-comment-char: ?#
# End:

View file

@ -909,6 +909,18 @@ finish_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
tracee->pid, 0, 0)) tracee->pid, 0, 0))
goto error; 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: error:
free (tracee->exec_data); free (tracee->exec_data);
tracee->exec_data = NULL; tracee->exec_data = NULL;