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:
parent
f5b59a8a73
commit
7a01350624
6 changed files with 636 additions and 325 deletions
25
exec/exec.c
25
exec/exec.c
|
@ -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. */
|
||||
|
||||
|
|
|
@ -22,68 +22,68 @@
|
|||
.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:
|
||||
|
|
|
@ -18,23 +18,23 @@
|
|||
.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: ?@
|
||||
|
|
|
@ -15,26 +15,29 @@
|
|||
# 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 .one_auxv
|
||||
.replace_phent:
|
||||
movl 12(%ebp), %esi
|
||||
jmp copy_auxv
|
||||
1: movl -40(%ebp), %esi
|
||||
movl %esi, -4(%ecx)
|
||||
jmp .one_auxv
|
||||
.replace_phnum:
|
||||
movl 16(%ebp), %esi
|
||||
jmp copy_auxv
|
||||
2: movl -32(%ebp), %esi
|
||||
movl %esi, -4(%ecx)
|
||||
jmp .one_auxv
|
||||
.replace_entry:
|
||||
movl 8(%ebp), %esi
|
||||
jmp copy_auxv
|
||||
3: movl -36(%ebp), %esi
|
||||
movl %esi, -4(%ecx)
|
||||
jmp .one_auxv
|
||||
.replace_base:
|
||||
movl 24(%ebp), %esi
|
||||
jmp copy_auxv
|
||||
4: movl -28(%ebp), %esi
|
||||
movl %esi, -4(%ecx)
|
||||
jmp .one_auxv
|
||||
.cleanup:
|
||||
jmp copy_auxv
|
||||
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
|
||||
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:
|
||||
|
|
|
@ -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:
|
||||
|
|
12
exec/trace.c
12
exec/trace.c
|
@ -909,6 +909,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;
|
||||
|
|
Loading…
Add table
Reference in a new issue