Port recent Android changes to mips64el
* exec/config-mips.m4.in (DADDI2, DADDI3): Disable at-clobbering by assembler macros expressly. * exec/loader-mips64el.s: Adapt from loader-mipsel.s. * exec/configure.ac (exec_cv_as_daddi): Properly escape reg names. * exec/exec.c (struct exec_jump_command, exec_0): Don't define or set `fpu_mode' if __LP64__. * exec/exec.h (struct exec_tracee): New field `callno'. * exec/trace.c (process_system_call): Always record the current system call number in TRACEE lest it should be required once it has been overwritten upon the syscall's completion. (seccomp_system_call): Likewise. (after_fork): Clear `tracee->callno'.
This commit is contained in:
@@ -38,7 +38,11 @@ define(`RESTORE', `ifelse(`@MIPS_N32@',`yes',` nop',` addi $sp, 32')')
|
|||||||
define(`FP', `ifelse(`@MIPS_N32@',`yes',`$s8',`$fp')')
|
define(`FP', `ifelse(`@MIPS_N32@',`yes',`$s8',`$fp')')
|
||||||
|
|
||||||
dnl For mips64. Some assemblers don't want to assemble `daddi'.
|
dnl For mips64. Some assemblers don't want to assemble `daddi'.
|
||||||
define(`DADDI2', `ifelse(`@DADDI_BROKEN@',`yes',` li $at, $2
|
define(`DADDI2', `ifelse(`@DADDI_BROKEN@',`yes',`.set noat
|
||||||
dadd $1, $1, $at',` daddi $1, $2')')
|
li $at, $2
|
||||||
define(`DADDI3', `ifelse(`@DADDI_BROKEN@',`yes',` li $at, $3
|
dadd $1, $1, $at
|
||||||
dadd $1, $2, $at',` daddi $1, $2, $3')')
|
.set at',` daddi $1, $2')')
|
||||||
|
define(`DADDI3', `ifelse(`@DADDI_BROKEN@',`yes',`.set noat
|
||||||
|
li $at, $3
|
||||||
|
dadd $1, $2, $at
|
||||||
|
.set at',` daddi $1, $2, $3')')
|
||||||
|
|||||||
@@ -455,12 +455,12 @@ AS_CASE([$host], [x86_64-*linux*],
|
|||||||
.section text
|
.section text
|
||||||
.global __start
|
.global __start
|
||||||
__start:
|
__start:
|
||||||
li $t0, 0
|
li \$t0, 0
|
||||||
li $t1, 0
|
li \$t1, 0
|
||||||
daddi $t0, $t1, 1
|
daddi \$t0, \$t1, 1
|
||||||
daddi $t0, $t1, -1
|
daddi \$t0, \$t1, -1
|
||||||
daddi $t0, -1
|
daddi \$t0, -1
|
||||||
daddi $t0, 1
|
daddi \$t0, 1
|
||||||
|
|
||||||
_ACEOF
|
_ACEOF
|
||||||
$AS $ASFLAGS conftest.s -o conftest.$OBJEXT \
|
$AS $ASFLAGS conftest.s -o conftest.$OBJEXT \
|
||||||
|
|||||||
@@ -231,10 +231,10 @@ struct exec_jump_command
|
|||||||
/* The value of AT_BASE inside the aux vector. */
|
/* The value of AT_BASE inside the aux vector. */
|
||||||
USER_WORD at_base;
|
USER_WORD at_base;
|
||||||
|
|
||||||
#if defined __mips__
|
#if defined __mips__ && !defined __LP64__
|
||||||
/* The FPU mode to apply. Not used when !MIPS_NABI. */
|
/* The FPU mode to apply. Not used when !MIPS_NABI. */
|
||||||
USER_WORD fpu_mode;
|
USER_WORD fpu_mode;
|
||||||
#endif /* defined __mips__ */
|
#endif /* defined __mips__ && !defined __LP64__ */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -918,6 +918,7 @@ exec_0 (char *name, struct exec_tracee *tracee,
|
|||||||
USER_WORD header_offset;
|
USER_WORD header_offset;
|
||||||
USER_WORD name_len, aligned_len;
|
USER_WORD name_len, aligned_len;
|
||||||
struct exec_jump_command jump;
|
struct exec_jump_command jump;
|
||||||
|
/* This also encompasses !__LP64__. */
|
||||||
#if defined __mips__ && !defined MIPS_NABI
|
#if defined __mips__ && !defined MIPS_NABI
|
||||||
int fpu_mode;
|
int fpu_mode;
|
||||||
#endif /* defined __mips__ && !defined MIPS_NABI */
|
#endif /* defined __mips__ && !defined MIPS_NABI */
|
||||||
@@ -1130,9 +1131,9 @@ exec_0 (char *name, struct exec_tracee *tracee,
|
|||||||
fpu_mode = FP_FRE;
|
fpu_mode = FP_FRE;
|
||||||
|
|
||||||
jump.fpu_mode = fpu_mode;
|
jump.fpu_mode = fpu_mode;
|
||||||
#elif defined __mips__
|
#elif defined __mips__ && !defined __LP64__
|
||||||
jump.fpu_mode = 0;
|
jump.fpu_mode = 0;
|
||||||
#endif /* defined __mips__ && !defined MIPS_NABI */
|
#endif /* defined __mips__ && defined MIPS_NABI && !defined __LP64__ */
|
||||||
|
|
||||||
/* The offset used for at_phdr should be that of the first
|
/* The offset used for at_phdr should be that of the first
|
||||||
mapping. */
|
mapping. */
|
||||||
|
|||||||
@@ -152,6 +152,10 @@ struct exec_tracee
|
|||||||
completion. */
|
completion. */
|
||||||
USER_WORD sp;
|
USER_WORD sp;
|
||||||
|
|
||||||
|
/* ID of the system call that is pending completion. This value is
|
||||||
|
not available as the call number is overwritten on success. */
|
||||||
|
USER_WORD callno;
|
||||||
|
|
||||||
/* Name of the executable being run. */
|
/* Name of the executable being run. */
|
||||||
char *exec_file;
|
char *exec_file;
|
||||||
|
|
||||||
|
|||||||
@@ -15,36 +15,40 @@
|
|||||||
# 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/>.
|
||||||
|
|
||||||
/* NOTE: this file is presently non-functional. */
|
|
||||||
|
|
||||||
include(`config-mips.m4')
|
include(`config-mips.m4')
|
||||||
|
|
||||||
|
/* These "registers" alias a4-a7 and caution must be exercised not
|
||||||
|
to overwrite them when issuing system calls. */
|
||||||
|
define(`T4', `$a4')
|
||||||
|
define(`T5', `$a5')
|
||||||
|
define(`T6', `$a6')
|
||||||
|
define(`T7', `$a7')
|
||||||
|
|
||||||
.set noreorder # delay slots managed by hand
|
.set noreorder # delay slots managed by hand
|
||||||
.set noat # no assembler macros
|
|
||||||
.section .text
|
.section .text
|
||||||
.global __start
|
.global __start
|
||||||
__start:
|
__start:
|
||||||
dnl li $v0, 5034 # SYS_nanosleep
|
## li $v0, 5034 # SYS_nanosleep
|
||||||
dnl dla $a0, .timespec # rqtp
|
## dla $a0, timespec # rqtp
|
||||||
dnl li $a1, 0 # rmtp
|
## li $a1, 0 # rmtp
|
||||||
dnl syscall # syscall
|
## syscall # syscall
|
||||||
ld $s2, ($sp) # original stack pointer
|
ld $s6, ($sp) # original stack pointer
|
||||||
DADDI3( $s0, $sp, 16) # start of load area
|
DADDI3( $s0, $sp, 16) # start of load area
|
||||||
DADDI2( $sp, -16) # primary fd, secondary fd
|
DADDI2( $sp, -16) # primary fd, secondary fd
|
||||||
li $t0, -1 # secondary fd
|
li $t0, -1 # secondary fd
|
||||||
sd $t0, 8($sp) # initialize secondary fd
|
sd $t0, 8($sp) # initialize secondary fd
|
||||||
.next_action:
|
next_action:
|
||||||
ld $s1, ($s0) # action number
|
ld $s1, ($s0) # action number
|
||||||
andi $t0, $s1, 15 # t0 = action number & 15
|
andi $t0, $s1, 15 # t0 = action number & 15
|
||||||
beqz $t0, .open_file # open file?
|
beqz $t0, open_file # open file?
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
DADDI2( $t0, -3) # t0 -= 3
|
DADDI2( $t0, -3) # t0 -= 3
|
||||||
beqz $t0, .rest_of_exec # jump to code
|
beqz $t0, rest_of_exec # jump to code
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
li $t1, 1
|
li $t1, 1
|
||||||
beq $t0, $t1, .do_mmap_anon # anonymous mmap?
|
beq $t0, $t1, do_mmap_anon # anonymous mmap?
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
.do_mmap:
|
do_mmap:
|
||||||
ld $t0, 8($s0) # vm address
|
ld $t0, 8($s0) # vm address
|
||||||
ld $t1, 16($s0) # file_offset
|
ld $t1, 16($s0) # file_offset
|
||||||
ld $t2, 24($s0) # protection
|
ld $t2, 24($s0) # protection
|
||||||
@@ -52,10 +56,10 @@ dnl syscall # syscall
|
|||||||
ld $v0, 40($s0) # flags
|
ld $v0, 40($s0) # flags
|
||||||
ld $v1, ($sp) # primary fd
|
ld $v1, ($sp) # primary fd
|
||||||
andi $s3, $s1, 16 # s1 & 16?
|
andi $s3, $s1, 16 # s1 & 16?
|
||||||
beqz $s3, .do_mmap_1 # secondary fd?
|
beqz $s3, do_mmap_1 # secondary fd?
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
ld $v1, 8($sp) # secondary fd
|
ld $v1, 8($sp) # secondary fd
|
||||||
.do_mmap_1:
|
do_mmap_1:
|
||||||
move $a0, $t0 # syscall arg
|
move $a0, $t0 # syscall arg
|
||||||
move $a1, $t3 # syscall arg
|
move $a1, $t3 # syscall arg
|
||||||
move $a2, $t2 # syscall arg
|
move $a2, $t2 # syscall arg
|
||||||
@@ -64,21 +68,21 @@ dnl syscall # syscall
|
|||||||
move $a5, $t1 # syscall arg
|
move $a5, $t1 # syscall arg
|
||||||
li $v0, 5009 # SYS_mmap
|
li $v0, 5009 # SYS_mmap
|
||||||
syscall # syscall
|
syscall # syscall
|
||||||
bne $a3, $zero, .perror # perror?
|
bne $a3, $zero, perror # perror?
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
ld $t1, 48($s0) # clear
|
ld $t1, 48($s0) # clear
|
||||||
dadd $t0, $a0, $a1 # t0 = end of mapping
|
dadd $t0, $a0, $a1 # t0 = end of mapping
|
||||||
dsub $t1, $t0, $t1 # t1 = t0 - clear
|
dsub $t1, $t0, $t1 # t1 = t0 - clear
|
||||||
.align:
|
align:
|
||||||
beq $t0, $t1, .continue # already finished
|
beq $t0, $t1, continue # already finished
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
andi $t2, $t1, 7 # t1 & 7?
|
andi $t2, $t1, 7 # t1 & 7?
|
||||||
bnez $t2, .filld # start filling longs
|
bnez $t2, filld # start filling longs
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
.filld:
|
filld:
|
||||||
dsub $t2, $t0, $t1 # t2 = t0 - t1
|
dsub $t2, $t0, $t1 # t2 = t0 - t1
|
||||||
sltiu $t2, $t2, 64 # t2 < 64?
|
sltiu $t2, $t2, 64 # t2 < 64?
|
||||||
bne $t2, $zero, .fillb # fill bytes
|
bne $t2, $zero, fillb # fill bytes
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
sd $zero, ($t1) # zero doubleword
|
sd $zero, ($t1) # zero doubleword
|
||||||
DADDI2( $t1, 8) # next doubleword
|
DADDI2( $t1, 8) # next doubleword
|
||||||
@@ -96,140 +100,255 @@ dnl syscall # syscall
|
|||||||
DADDI2( $t1, 8) # next doubleword
|
DADDI2( $t1, 8) # next doubleword
|
||||||
sd $zero, ($t1) # zero doubleword
|
sd $zero, ($t1) # zero doubleword
|
||||||
DADDI2( $t1, 8) # next doubleword
|
DADDI2( $t1, 8) # next doubleword
|
||||||
j .filld # fill either doubleword or byte
|
j filld # fill either doubleword or byte
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
.fillb:
|
fillb:
|
||||||
beq $t0, $t1, .continue # already finished?
|
beq $t0, $t1, continue # already finished?
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
sb $zero, ($t1) # clear byte
|
sb $zero, ($t1) # clear byte
|
||||||
DADDI2( $t1, 1) # t1++
|
DADDI2( $t1, 1) # t1++
|
||||||
.continue:
|
continue:
|
||||||
DADDI2( $s0, 56) # s0 = next action
|
DADDI2( $s0, 56) # s0 = next action
|
||||||
j .next_action # next action
|
j next_action # next action
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
.do_mmap_anon:
|
do_mmap_anon:
|
||||||
ld $t0, 8($s0) # vm address
|
ld $t0, 8($s0) # vm address
|
||||||
ld $t1, 16($s0) # file_offset
|
ld $t1, 16($s0) # file_offset
|
||||||
ld $t2, 24($s0) # protection
|
ld $t2, 24($s0) # protection
|
||||||
ld $t3, 32($s0) # length
|
ld $t3, 32($s0) # length
|
||||||
ld $v0, 40($s0) # flags
|
ld $v0, 40($s0) # flags
|
||||||
li $v1, -1 # fd
|
dli $v1, -1 # fd
|
||||||
j .do_mmap_1 # do mmap
|
j do_mmap_1 # do mmap
|
||||||
nop # branch delay slot
|
nop # branch delay slot
|
||||||
.open_file:
|
open_file:
|
||||||
li $v0, 5002 # SYS_open
|
dli $v0, 5002 # SYS_open
|
||||||
DADDI3( $a0, $s0, 8) # start of name
|
DADDI3( $a0, $s0, 8) # start of name
|
||||||
move $a1, $zero # flags = O_RDONLY
|
move $a1, $zero # flags = O_RDONLY
|
||||||
move $a2, $zero # mode = 0
|
move $a2, $zero # mode = 0
|
||||||
syscall # syscall
|
syscall # syscall
|
||||||
bne $a3, $zero, .perror # perror
|
bne $a3, $zero, perror # perror
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
DADDI2( $s0, 8) # start of string
|
DADDI2( $s0, 8) # start of string
|
||||||
move $t3, $s0 # t3 = s0
|
move $t3, $s0 # t3 = s0
|
||||||
.nextc:
|
nextc:
|
||||||
lb $t0, ($s0) # load byte
|
lb $t0, ($s0) # load byte
|
||||||
DADDI2( $s0, 1) # s0++
|
DADDI2( $s0, 1) # s0++
|
||||||
li $t1, 47 # directory separator `/'
|
dli $t1, 47 # directory separator `/'
|
||||||
bne $t0, $t1, .nextc1 # is separator char?
|
bne $t0, $t1, nextc1 # is separator char?
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
move $t3, $s0 # t3 = char past separator
|
move $t3, $s0 # t3 = char past separator
|
||||||
.nextc1:
|
nextc1:
|
||||||
bnez $t0, .nextc # next character?
|
bnez $t0, nextc # next character?
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
DADDI2( $s0, 7) # adjust for round
|
DADDI2( $s0, 7) # adjust for round
|
||||||
li $t2, -8 # t2 = -8
|
dli $t2, -8 # t2 = -8
|
||||||
and $s0, $s0, $t2 # mask for round
|
and $s0, $s0, $t2 # mask for round
|
||||||
andi $t0, $s1, 16 # t1 = s1 & 16
|
andi $t0, $s1, 16 # t1 = s1 & 16
|
||||||
move $t1, $sp # address of primary fd
|
move $t1, $sp # address of primary fd
|
||||||
beqz $t0, .primary # primary fd?
|
beqz $t0, primary # primary fd?
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
DADDI2( $t1, 8) # address of secondary fd
|
DADDI2( $t1, 8) # address of secondary fd
|
||||||
sd $v0, ($t1) # store fd
|
sd $v0, ($t1) # store fd
|
||||||
j .next_action # next action
|
j next_action # next action
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
.primary:
|
primary:
|
||||||
sd $v0, ($t1) # store fd
|
sd $v0, ($t1) # store fd
|
||||||
li $v0, 5153 # SYS_prctl
|
dli $v0, 5153 # SYS_prctl
|
||||||
li $a0, 15 # PR_SET_NAME
|
dli $a0, 15 # PR_SET_NAME
|
||||||
move $a1, $t3 # char past separator
|
move $a1, $t3 # char past separator
|
||||||
move $a2, $zero # a2
|
move $a2, $zero # a2
|
||||||
move $a3, $zero # a3
|
move $a3, $zero # a3
|
||||||
move $a4, $zero # a4
|
move $a4, $zero # a4
|
||||||
move $a5, $zero # a5
|
move $a5, $zero # a5
|
||||||
syscall # syscall
|
syscall # syscall
|
||||||
j .next_action # next action
|
j next_action # next action
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
.perror:
|
perror:
|
||||||
move $a0, $v0 # errno
|
move $a0, $v0 # errno
|
||||||
li $v0, 5058 # SYS_exit
|
dli $v0, 5058 # SYS_exit
|
||||||
syscall # syscall
|
syscall # syscall
|
||||||
.rest_of_exec:
|
rest_of_exec:
|
||||||
move $s1, $s2 # original SP
|
move $s1, $s6 # original SP
|
||||||
ld $t0, ($s1) # argc
|
ld $t0, ($s1) # argc
|
||||||
dsll $t0, $t0, 3 # argc *= 8
|
dsll $t0, $t0, 3 # argc *= 8
|
||||||
DADDI2( $t0, 16) # argc += 16
|
DADDI2( $t0, 16) # argc += 16
|
||||||
dadd $s1, $s1, $t0 # s1 = start of envp
|
dadd $s1, $s1, $t0 # s1 = start of envp
|
||||||
.skipenv:
|
skip_environ:
|
||||||
ld $t0, ($s1) # t0 = *s1
|
/* Locate the auxiliary vector. */
|
||||||
DADDI2( $s1, 8) # s1++
|
1: ld $t0, ($s1) # t0 = *s1
|
||||||
bne $t0, $zero, .skipenv # skip again
|
bnez $t0, 1b # skip environment entry
|
||||||
nop # delay slot
|
daddi $s1, $s1, 8 # s1++
|
||||||
dla $t3, .auxvtab # address of auxv table
|
move $s2, $s1 # s2 = end of environment
|
||||||
.one_auxv:
|
1: ld $t0, ($s1) # t0 = s1->a_type
|
||||||
ld $t0, ($s1) # t0 = auxv type
|
bnez $t0, 1b # skip auxiliary vector entry
|
||||||
li $t1, 10 # t1 = 10
|
daddi $s1, $s1, 16 # (Elf64_auxv_t *) s1++
|
||||||
beqz $t0, .finish # is AT_IGNORE?
|
/* Decide how many bytes must be copied and where to
|
||||||
nop # delay slot
|
save the file name. Move the stack pointer to a safe
|
||||||
sltu $t1, $t0, $t1 # t1 = t0 < num offsets
|
position below any data that must be preserved. */
|
||||||
beqz $t1, .next # next auxv
|
ld $t1, 56($s0) # length of string
|
||||||
nop # delay slot
|
DADDI2( $t1, 1)
|
||||||
dsll $t1, $t0, 2 # t1 = t0 * 4
|
DADDI3( $t2, $s0, 64) # pointer to string
|
||||||
dadd $t1, $t3, $t1 # t1 = .auxvtab + t1
|
dsub $t3, $s1, $s6 # number of bytes in vectors
|
||||||
lw $t2, ($t1) # t2 = *t1
|
dsub $t0, $s1, $t1 # position of string
|
||||||
beqz $t2, .next # skip auxv
|
and $t0, $t0, -16 # align value
|
||||||
nop # delay slot
|
dsub $t3, $t0, $t3 # position of argc
|
||||||
dadd $t2, $s0, $t2 # t2 = s0 + t2
|
and $t3, $t3, -16 # align value
|
||||||
ld $t2, ($t2) # t2 = *t2
|
/* Move the stack pointer and save required information.
|
||||||
sd $t2, 8($s1) # set auxv value
|
8($fp) = secondary/interpreter fd.
|
||||||
.next:
|
0($fp) = primary/executable fd.
|
||||||
DADDI2( $s1, 16) # next auxv
|
-8($fp) = cmd->entry
|
||||||
j .one_auxv # next auxv
|
-16($fp) = cmd->at_entry
|
||||||
nop # delay slot
|
-24($fp) = cmd->at_phent
|
||||||
.finish:
|
-32($fp) = cmd->at_phnum
|
||||||
ld $t0, 8($sp) # secondary fd
|
-40($fp) = cmd->at_phdr
|
||||||
|
-48($fp) = cmd->at_base
|
||||||
|
$sp = copy of string. */
|
||||||
|
move T4, $sp # current sp
|
||||||
|
dsub T5, $t3, $sp # new argc - current sp
|
||||||
|
blt T5, 16, 1f # more than two slots apart
|
||||||
|
dadd $sp, $t3, -16 # $sp = two slots below new argc
|
||||||
|
j 2f # skip copying fds
|
||||||
|
move $sp, T4 # retain current sp
|
||||||
|
1: ld T5, (T4) # old primary fd
|
||||||
|
ld T5, ($sp) # save the same
|
||||||
|
ld T5, 8(T4) # old interpreter fd
|
||||||
|
sd T5, 8($sp) # save the same
|
||||||
|
2: move $fp, $sp # set base pointer
|
||||||
|
DADDI2( $sp, -48) # command data
|
||||||
|
ld T5, 8($s0) # entry
|
||||||
|
ld T6, 16($s0) # at_entry
|
||||||
|
ld T7, 24($s0) # at_phent
|
||||||
|
ld $t8, 32($s0) # at_phnum
|
||||||
|
sd T5, -8($fp) # save entry
|
||||||
|
ld T5, 40($s0) # at_phdr
|
||||||
|
sd T6, -16($fp) # save at_entry
|
||||||
|
ld T6, 48($s0) # at_base
|
||||||
|
sd T7, -24($fp) # save at_phent
|
||||||
|
sd $t8, -32($fp) # save at_phnum
|
||||||
|
sd T5, -40($fp) # save at_phdr
|
||||||
|
sd T6, -48($fp) # save at_base
|
||||||
|
dsub $sp, $sp, $t1 # space for string
|
||||||
|
/* Save the input string. */
|
||||||
|
dadd T5, $t2, $t1 # end of source ($t2)
|
||||||
|
move T6, $sp # dst
|
||||||
|
move $s0, $t1 # $s0 = length of string
|
||||||
|
/* src = $t2, dst = T6 */
|
||||||
|
bgeu $t2, T5, 2f # there already?
|
||||||
|
nop
|
||||||
|
1: lb $t1, ($t2) # $t1 = *$t2
|
||||||
|
DADDI2( $t2, 1) # $t2++
|
||||||
|
DADDI2( T6, 1) # $t6++
|
||||||
|
bltu $t2, T5, 1b
|
||||||
|
sb $t1, -1(T6) # *(T6 - 1) = $t1
|
||||||
|
2: move $s3, $sp # copy of string
|
||||||
|
and $sp, $sp, -16 # align stack
|
||||||
|
copy_env_and_args:
|
||||||
|
/* Copy argc, argv, and the environment array.
|
||||||
|
T4 = destination, T5 = src, $s2 = src_end */
|
||||||
|
move T4, $t3 # destination of argc
|
||||||
|
move T5, $s6 # original SP
|
||||||
|
bgeu T5, $s2, 2f # there already?
|
||||||
|
nop
|
||||||
|
1: ld $t1, (T5) # $t1 = *src
|
||||||
|
DADDI2( T5, 8) # src++
|
||||||
|
DADDI2( T4, 8) # dst++
|
||||||
|
bltu T5, $s2, 1b # src < src_end
|
||||||
|
sd $t1, -8(T4) # *(dst - 8) = $t1
|
||||||
|
copy_auxv:
|
||||||
|
/* T4 = destination, T5 = first auxval. */
|
||||||
|
2: ld $t1, (T5) # a_type
|
||||||
|
ld $t2, 8(T5) # a_un.a_val
|
||||||
|
DADDI2( T4, 16) # (Elf64_auxv_t *) dst++
|
||||||
|
DADDI2( T5, 16) # (Elf64_auxv_t *) src
|
||||||
|
beqz $t1, 8f # AT_NULL
|
||||||
|
li T6, 3
|
||||||
|
beq $t1, T6, 1f # AT_PHDR
|
||||||
|
li T6, 4
|
||||||
|
beq $t1, T6, 2f # AT_PHENT
|
||||||
|
li T6, 5
|
||||||
|
beq $t1, T6, 3f # AT_PHNUM
|
||||||
|
li T6, 9
|
||||||
|
beq $t1, T6, 4f # AT_ENTRY
|
||||||
|
li T6, 7
|
||||||
|
beq $t1, T6, 5f # AT_BASE
|
||||||
|
li T6, 31
|
||||||
|
beq $t1, T6, 6f # AT_EXECFN
|
||||||
|
nop
|
||||||
|
b 7f
|
||||||
|
nop
|
||||||
|
1: b 7f
|
||||||
|
ld $t2, -40($fp)
|
||||||
|
2: b 7f
|
||||||
|
ld $t2, -24($fp)
|
||||||
|
3: b 7f
|
||||||
|
ld $t2, -32($fp)
|
||||||
|
4: b 7f
|
||||||
|
ld $t2, -16($fp)
|
||||||
|
5: b 7f
|
||||||
|
ld $t2, -48($fp)
|
||||||
|
6: b 7f
|
||||||
|
move $t2, $t0
|
||||||
|
7: sd $t1, -16(T4) # dst->a_type
|
||||||
|
j copy_auxv
|
||||||
|
sd $t2, -8(T4) # dst->a_un.a_val
|
||||||
|
/* Copy the final element. */
|
||||||
|
8: sd $t1, -16(T4) # dst->a_type
|
||||||
|
sd $t2, -8(T4) # dst->a_un.a_val
|
||||||
|
finish:
|
||||||
|
/* Copy the string to its position in auxv
|
||||||
|
(src = $s3, dst = $t0). */
|
||||||
|
dadd $t1, $s3, $s0 # src end
|
||||||
|
bgeu $s3, $t1, 2f # there already?
|
||||||
|
nop
|
||||||
|
1: lb $t2, ($s3) # c = *src
|
||||||
|
DADDI2( $s3, 1) # src++
|
||||||
|
DADDI2( $t0, 1) # dst++
|
||||||
|
bltu $s3, $t1, 1b
|
||||||
|
sb $t2, -1($t0) # *(dst - 1) = c
|
||||||
|
/* Save variables. */
|
||||||
|
2: move $s6, $t3 # new stack pointer
|
||||||
|
ld $t0, 8($fp) # secondary fd
|
||||||
li $t1, -1 # t1 = -1
|
li $t1, -1 # t1 = -1
|
||||||
ld $s1, ($sp) # s1 = primary fd
|
ld $s1, ($fp) # s1 = primary fd
|
||||||
|
beq $t0, $t2, finish1 # secondary fd set?
|
||||||
li $v0, 5003 # SYS_close
|
li $v0, 5003 # SYS_close
|
||||||
beq $t0, $t2, .finish1 # secondary fd set?
|
|
||||||
nop # delay slot
|
|
||||||
move $a0, $t0 # secondary fd
|
move $a0, $t0 # secondary fd
|
||||||
syscall # syscall
|
syscall # syscall
|
||||||
li $v0, 5003 # SYS_close
|
li $v0, 5003 # SYS_close
|
||||||
.finish1:
|
finish1:
|
||||||
move $a0, $s1 # primary fd
|
move $a0, $s1 # primary fd
|
||||||
syscall # syscall
|
syscall # syscall
|
||||||
.jump:
|
jump:
|
||||||
move $v0, $zero # rtld_fini
|
move $v0, $zero # rtld_fini
|
||||||
ld $t0, 8($s0) # entry
|
ld $t9, -8($fp) # entry
|
||||||
move $sp, $s2 # restore stack pointer, delay slot
|
move $sp, $s6 # restore stack pointer, delay slot
|
||||||
jr $t0 # enter
|
/* Clear at least one page's worth of stack. glibc on mipsel
|
||||||
|
copies certain fields from the stack to the `link_map'
|
||||||
|
structure representing ld.so, which are not subsequently
|
||||||
|
replaced if otherwise than zero.
|
||||||
|
|
||||||
|
XXX: report this glibc bug? */
|
||||||
|
DADDI3( $v0, $sp, -4096)
|
||||||
|
and $v0, $v0, -4095
|
||||||
|
1: sd $zero, ($v0) # copy 32 byte blocks
|
||||||
|
sd $zero, 8($v0)
|
||||||
|
sd $zero, 16($v0)
|
||||||
|
sd $zero, 24($v0)
|
||||||
|
DADDI2( $v0, 32)
|
||||||
|
dsub $t0, $sp, $v0 # remainder
|
||||||
|
bge $t0, 32, 1b # test remainder
|
||||||
|
nop # copy 4 byte blocks
|
||||||
|
beqz $t0, 2f
|
||||||
|
nop
|
||||||
|
1: DADDI2( $v0, 4)
|
||||||
|
bltu $v0, $sp, 1b
|
||||||
|
sw $zero, -4($v0)
|
||||||
|
2: jr $t9 # enter
|
||||||
nop # delay slot
|
nop # delay slot
|
||||||
|
|
||||||
.auxvtab:
|
## timespec:
|
||||||
.long 0 # 0
|
## .quad 10
|
||||||
.long 0 # 1
|
## .quad 10
|
||||||
.long 0 # 2
|
|
||||||
.long 40 # 3 AT_PHDR
|
|
||||||
.long 24 # 4 AT_PHENT
|
|
||||||
.long 32 # 5 AT_PHNUM
|
|
||||||
.long 0 # 6
|
|
||||||
.long 48 # 7 AT_BASE
|
|
||||||
.long 0 # 8
|
|
||||||
.long 16 # 9 AT_ENTRY
|
|
||||||
|
|
||||||
.timespec:
|
|
||||||
.quad 10
|
|
||||||
.quad 10
|
|
||||||
|
|
||||||
# Local Variables:
|
# Local Variables:
|
||||||
# asm-comment-char: ?#
|
# asm-comment-char: ?#
|
||||||
|
|||||||
14
exec/trace.c
14
exec/trace.c
@@ -1246,7 +1246,11 @@ process_system_call (struct exec_tracee *tracee)
|
|||||||
set, this must be exec, whatever the value of SYSCALL_NUM_REG,
|
set, this must be exec, whatever the value of SYSCALL_NUM_REG,
|
||||||
which is erased when exec loads another image. */
|
which is erased when exec loads another image. */
|
||||||
|
|
||||||
callno = (!tracee->exec_data ? regs.SYSCALL_NUM_REG : EXEC_SYSCALL);
|
callno = (!tracee->exec_data
|
||||||
|
? (!tracee->waiting_for_syscall
|
||||||
|
? regs.SYSCALL_NUM_REG : tracee->callno)
|
||||||
|
: EXEC_SYSCALL);
|
||||||
|
tracee->callno = callno;
|
||||||
switch (callno)
|
switch (callno)
|
||||||
{
|
{
|
||||||
case EXEC_SYSCALL:
|
case EXEC_SYSCALL:
|
||||||
@@ -1653,6 +1657,11 @@ seccomp_system_call (struct exec_tracee *tracee)
|
|||||||
|
|
||||||
/* Now dispatch based on the system call. */
|
/* Now dispatch based on the system call. */
|
||||||
callno = regs.SYSCALL_NUM_REG;
|
callno = regs.SYSCALL_NUM_REG;
|
||||||
|
|
||||||
|
/* Record the call number, which may be required if one of the
|
||||||
|
following handlers should arrange for process_system_call to
|
||||||
|
intercede after the system call completes. */
|
||||||
|
tracee->callno = callno;
|
||||||
switch (callno)
|
switch (callno)
|
||||||
{
|
{
|
||||||
case EXEC_SYSCALL:
|
case EXEC_SYSCALL:
|
||||||
@@ -1715,7 +1724,7 @@ seccomp_system_call (struct exec_tracee *tracee)
|
|||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tracee->waiting_for_syscall = !tracee->waiting_for_syscall;
|
tracee->waiting_for_syscall = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -2033,6 +2042,7 @@ after_fork (pid_t pid)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
tracee->pid = pid;
|
tracee->pid = pid;
|
||||||
|
tracee->callno = 0;
|
||||||
tracee->next = tracing_processes;
|
tracee->next = tracing_processes;
|
||||||
tracee->waiting_for_syscall = false;
|
tracee->waiting_for_syscall = false;
|
||||||
tracee->new_child = false;
|
tracee->new_child = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user