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:
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);
|
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. */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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: ?@
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
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))
|
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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue