diff options
| author | Po Lu | 2025-04-15 16:14:14 +0800 |
|---|---|---|
| committer | Po Lu | 2025-04-15 16:17:14 +0800 |
| commit | 5bf86e2be0693c579a43759fd1da1651344d401e (patch) | |
| tree | 689475ec3fc7632cdf63a8796583bcb62f56f878 /exec | |
| parent | c3fe19aab90c3da68e9a8a48dbfb011317041d1a (diff) | |
| download | emacs-5bf86e2be0693c579a43759fd1da1651344d401e.tar.gz emacs-5bf86e2be0693c579a43759fd1da1651344d401e.zip | |
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'.
Diffstat (limited to 'exec')
| -rw-r--r-- | exec/config-mips.m4.in | 12 | ||||
| -rw-r--r-- | exec/configure.ac | 12 | ||||
| -rw-r--r-- | exec/exec.c | 9 | ||||
| -rw-r--r-- | exec/exec.h | 4 | ||||
| -rw-r--r-- | exec/loader-mips64el.s | 317 | ||||
| -rw-r--r-- | exec/trace.c | 14 |
6 files changed, 253 insertions, 115 deletions
diff --git a/exec/config-mips.m4.in b/exec/config-mips.m4.in index 1c9a4c293a6..4ab395ff2cb 100644 --- a/exec/config-mips.m4.in +++ b/exec/config-mips.m4.in | |||
| @@ -38,7 +38,11 @@ define(`RESTORE', `ifelse(`@MIPS_N32@',`yes',` nop',` addi $sp, 32')') | |||
| 38 | define(`FP', `ifelse(`@MIPS_N32@',`yes',`$s8',`$fp')') | 38 | define(`FP', `ifelse(`@MIPS_N32@',`yes',`$s8',`$fp')') |
| 39 | 39 | ||
| 40 | dnl For mips64. Some assemblers don't want to assemble `daddi'. | 40 | dnl For mips64. Some assemblers don't want to assemble `daddi'. |
| 41 | define(`DADDI2', `ifelse(`@DADDI_BROKEN@',`yes',` li $at, $2 | 41 | define(`DADDI2', `ifelse(`@DADDI_BROKEN@',`yes',`.set noat |
| 42 | dadd $1, $1, $at',` daddi $1, $2')') | 42 | li $at, $2 |
| 43 | define(`DADDI3', `ifelse(`@DADDI_BROKEN@',`yes',` li $at, $3 | 43 | dadd $1, $1, $at |
| 44 | dadd $1, $2, $at',` daddi $1, $2, $3')') | 44 | .set at',` daddi $1, $2')') |
| 45 | define(`DADDI3', `ifelse(`@DADDI_BROKEN@',`yes',`.set noat | ||
| 46 | li $at, $3 | ||
| 47 | dadd $1, $2, $at | ||
| 48 | .set at',` daddi $1, $2, $3')') | ||
diff --git a/exec/configure.ac b/exec/configure.ac index d91049b8d7b..d462a25b9d9 100644 --- a/exec/configure.ac +++ b/exec/configure.ac | |||
| @@ -455,12 +455,12 @@ AS_CASE([$host], [x86_64-*linux*], | |||
| 455 | .section text | 455 | .section text |
| 456 | .global __start | 456 | .global __start |
| 457 | __start: | 457 | __start: |
| 458 | li $t0, 0 | 458 | li \$t0, 0 |
| 459 | li $t1, 0 | 459 | li \$t1, 0 |
| 460 | daddi $t0, $t1, 1 | 460 | daddi \$t0, \$t1, 1 |
| 461 | daddi $t0, $t1, -1 | 461 | daddi \$t0, \$t1, -1 |
| 462 | daddi $t0, -1 | 462 | daddi \$t0, -1 |
| 463 | daddi $t0, 1 | 463 | daddi \$t0, 1 |
| 464 | 464 | ||
| 465 | _ACEOF | 465 | _ACEOF |
| 466 | $AS $ASFLAGS conftest.s -o conftest.$OBJEXT \ | 466 | $AS $ASFLAGS conftest.s -o conftest.$OBJEXT \ |
diff --git a/exec/exec.c b/exec/exec.c index b9c3e4ec92a..b83e34bc1b2 100644 --- a/exec/exec.c +++ b/exec/exec.c | |||
| @@ -231,10 +231,10 @@ struct exec_jump_command | |||
| 231 | /* The value of AT_BASE inside the aux vector. */ | 231 | /* The value of AT_BASE inside the aux vector. */ |
| 232 | USER_WORD at_base; | 232 | USER_WORD at_base; |
| 233 | 233 | ||
| 234 | #if defined __mips__ | 234 | #if defined __mips__ && !defined __LP64__ |
| 235 | /* The FPU mode to apply. Not used when !MIPS_NABI. */ | 235 | /* The FPU mode to apply. Not used when !MIPS_NABI. */ |
| 236 | USER_WORD fpu_mode; | 236 | USER_WORD fpu_mode; |
| 237 | #endif /* defined __mips__ */ | 237 | #endif /* defined __mips__ && !defined __LP64__ */ |
| 238 | }; | 238 | }; |
| 239 | 239 | ||
| 240 | 240 | ||
| @@ -918,6 +918,7 @@ exec_0 (char *name, struct exec_tracee *tracee, | |||
| 918 | USER_WORD header_offset; | 918 | USER_WORD header_offset; |
| 919 | USER_WORD name_len, aligned_len; | 919 | USER_WORD name_len, aligned_len; |
| 920 | struct exec_jump_command jump; | 920 | struct exec_jump_command jump; |
| 921 | /* This also encompasses !__LP64__. */ | ||
| 921 | #if defined __mips__ && !defined MIPS_NABI | 922 | #if defined __mips__ && !defined MIPS_NABI |
| 922 | int fpu_mode; | 923 | int fpu_mode; |
| 923 | #endif /* defined __mips__ && !defined MIPS_NABI */ | 924 | #endif /* defined __mips__ && !defined MIPS_NABI */ |
| @@ -1130,9 +1131,9 @@ exec_0 (char *name, struct exec_tracee *tracee, | |||
| 1130 | fpu_mode = FP_FRE; | 1131 | fpu_mode = FP_FRE; |
| 1131 | 1132 | ||
| 1132 | jump.fpu_mode = fpu_mode; | 1133 | jump.fpu_mode = fpu_mode; |
| 1133 | #elif defined __mips__ | 1134 | #elif defined __mips__ && !defined __LP64__ |
| 1134 | jump.fpu_mode = 0; | 1135 | jump.fpu_mode = 0; |
| 1135 | #endif /* defined __mips__ && !defined MIPS_NABI */ | 1136 | #endif /* defined __mips__ && defined MIPS_NABI && !defined __LP64__ */ |
| 1136 | 1137 | ||
| 1137 | /* The offset used for at_phdr should be that of the first | 1138 | /* The offset used for at_phdr should be that of the first |
| 1138 | mapping. */ | 1139 | mapping. */ |
diff --git a/exec/exec.h b/exec/exec.h index eee48dfe2ed..d420061ff87 100644 --- a/exec/exec.h +++ b/exec/exec.h | |||
| @@ -152,6 +152,10 @@ struct exec_tracee | |||
| 152 | completion. */ | 152 | completion. */ |
| 153 | USER_WORD sp; | 153 | USER_WORD sp; |
| 154 | 154 | ||
| 155 | /* ID of the system call that is pending completion. This value is | ||
| 156 | not available as the call number is overwritten on success. */ | ||
| 157 | USER_WORD callno; | ||
| 158 | |||
| 155 | /* Name of the executable being run. */ | 159 | /* Name of the executable being run. */ |
| 156 | char *exec_file; | 160 | char *exec_file; |
| 157 | 161 | ||
diff --git a/exec/loader-mips64el.s b/exec/loader-mips64el.s index 1493af3c309..be978d8b18b 100644 --- a/exec/loader-mips64el.s +++ b/exec/loader-mips64el.s | |||
| @@ -15,36 +15,40 @@ | |||
| 15 | # You should have received a copy of the GNU General Public License | 15 | # You should have received a copy of the GNU General Public License |
| 16 | # along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | 16 | # along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. |
| 17 | 17 | ||
| 18 | /* NOTE: this file is presently non-functional. */ | ||
| 19 | |||
| 20 | include(`config-mips.m4') | 18 | include(`config-mips.m4') |
| 21 | 19 | ||
| 20 | /* These "registers" alias a4-a7 and caution must be exercised not | ||
| 21 | to overwrite them when issuing system calls. */ | ||
| 22 | define(`T4', `$a4') | ||
| 23 | define(`T5', `$a5') | ||
| 24 | define(`T6', `$a6') | ||
| 25 | define(`T7', `$a7') | ||
| 26 | |||
| 22 | .set noreorder # delay slots managed by hand | 27 | .set noreorder # delay slots managed by hand |
| 23 | .set noat # no assembler macros | ||
| 24 | .section .text | 28 | .section .text |
| 25 | .global __start | 29 | .global __start |
| 26 | __start: | 30 | __start: |
| 27 | dnl li $v0, 5034 # SYS_nanosleep | 31 | ## li $v0, 5034 # SYS_nanosleep |
| 28 | dnl dla $a0, .timespec # rqtp | 32 | ## dla $a0, timespec # rqtp |
| 29 | dnl li $a1, 0 # rmtp | 33 | ## li $a1, 0 # rmtp |
| 30 | dnl syscall # syscall | 34 | ## syscall # syscall |
| 31 | ld $s2, ($sp) # original stack pointer | 35 | ld $s6, ($sp) # original stack pointer |
| 32 | DADDI3( $s0, $sp, 16) # start of load area | 36 | DADDI3( $s0, $sp, 16) # start of load area |
| 33 | DADDI2( $sp, -16) # primary fd, secondary fd | 37 | DADDI2( $sp, -16) # primary fd, secondary fd |
| 34 | li $t0, -1 # secondary fd | 38 | li $t0, -1 # secondary fd |
| 35 | sd $t0, 8($sp) # initialize secondary fd | 39 | sd $t0, 8($sp) # initialize secondary fd |
| 36 | .next_action: | 40 | next_action: |
| 37 | ld $s1, ($s0) # action number | 41 | ld $s1, ($s0) # action number |
| 38 | andi $t0, $s1, 15 # t0 = action number & 15 | 42 | andi $t0, $s1, 15 # t0 = action number & 15 |
| 39 | beqz $t0, .open_file # open file? | 43 | beqz $t0, open_file # open file? |
| 40 | nop # delay slot | 44 | nop # delay slot |
| 41 | DADDI2( $t0, -3) # t0 -= 3 | 45 | DADDI2( $t0, -3) # t0 -= 3 |
| 42 | beqz $t0, .rest_of_exec # jump to code | 46 | beqz $t0, rest_of_exec # jump to code |
| 43 | nop # delay slot | 47 | nop # delay slot |
| 44 | li $t1, 1 | 48 | li $t1, 1 |
| 45 | beq $t0, $t1, .do_mmap_anon # anonymous mmap? | 49 | beq $t0, $t1, do_mmap_anon # anonymous mmap? |
| 46 | nop # delay slot | 50 | nop # delay slot |
| 47 | .do_mmap: | 51 | do_mmap: |
| 48 | ld $t0, 8($s0) # vm address | 52 | ld $t0, 8($s0) # vm address |
| 49 | ld $t1, 16($s0) # file_offset | 53 | ld $t1, 16($s0) # file_offset |
| 50 | ld $t2, 24($s0) # protection | 54 | ld $t2, 24($s0) # protection |
| @@ -52,10 +56,10 @@ dnl syscall # syscall | |||
| 52 | ld $v0, 40($s0) # flags | 56 | ld $v0, 40($s0) # flags |
| 53 | ld $v1, ($sp) # primary fd | 57 | ld $v1, ($sp) # primary fd |
| 54 | andi $s3, $s1, 16 # s1 & 16? | 58 | andi $s3, $s1, 16 # s1 & 16? |
| 55 | beqz $s3, .do_mmap_1 # secondary fd? | 59 | beqz $s3, do_mmap_1 # secondary fd? |
| 56 | nop # delay slot | 60 | nop # delay slot |
| 57 | ld $v1, 8($sp) # secondary fd | 61 | ld $v1, 8($sp) # secondary fd |
| 58 | .do_mmap_1: | 62 | do_mmap_1: |
| 59 | move $a0, $t0 # syscall arg | 63 | move $a0, $t0 # syscall arg |
| 60 | move $a1, $t3 # syscall arg | 64 | move $a1, $t3 # syscall arg |
| 61 | move $a2, $t2 # syscall arg | 65 | move $a2, $t2 # syscall arg |
| @@ -64,21 +68,21 @@ dnl syscall # syscall | |||
| 64 | move $a5, $t1 # syscall arg | 68 | move $a5, $t1 # syscall arg |
| 65 | li $v0, 5009 # SYS_mmap | 69 | li $v0, 5009 # SYS_mmap |
| 66 | syscall # syscall | 70 | syscall # syscall |
| 67 | bne $a3, $zero, .perror # perror? | 71 | bne $a3, $zero, perror # perror? |
| 68 | nop # delay slot | 72 | nop # delay slot |
| 69 | ld $t1, 48($s0) # clear | 73 | ld $t1, 48($s0) # clear |
| 70 | dadd $t0, $a0, $a1 # t0 = end of mapping | 74 | dadd $t0, $a0, $a1 # t0 = end of mapping |
| 71 | dsub $t1, $t0, $t1 # t1 = t0 - clear | 75 | dsub $t1, $t0, $t1 # t1 = t0 - clear |
| 72 | .align: | 76 | align: |
| 73 | beq $t0, $t1, .continue # already finished | 77 | beq $t0, $t1, continue # already finished |
| 74 | nop # delay slot | 78 | nop # delay slot |
| 75 | andi $t2, $t1, 7 # t1 & 7? | 79 | andi $t2, $t1, 7 # t1 & 7? |
| 76 | bnez $t2, .filld # start filling longs | 80 | bnez $t2, filld # start filling longs |
| 77 | nop # delay slot | 81 | nop # delay slot |
| 78 | .filld: | 82 | filld: |
| 79 | dsub $t2, $t0, $t1 # t2 = t0 - t1 | 83 | dsub $t2, $t0, $t1 # t2 = t0 - t1 |
| 80 | sltiu $t2, $t2, 64 # t2 < 64? | 84 | sltiu $t2, $t2, 64 # t2 < 64? |
| 81 | bne $t2, $zero, .fillb # fill bytes | 85 | bne $t2, $zero, fillb # fill bytes |
| 82 | nop # delay slot | 86 | nop # delay slot |
| 83 | sd $zero, ($t1) # zero doubleword | 87 | sd $zero, ($t1) # zero doubleword |
| 84 | DADDI2( $t1, 8) # next doubleword | 88 | DADDI2( $t1, 8) # next doubleword |
| @@ -96,140 +100,255 @@ dnl syscall # syscall | |||
| 96 | DADDI2( $t1, 8) # next doubleword | 100 | DADDI2( $t1, 8) # next doubleword |
| 97 | sd $zero, ($t1) # zero doubleword | 101 | sd $zero, ($t1) # zero doubleword |
| 98 | DADDI2( $t1, 8) # next doubleword | 102 | DADDI2( $t1, 8) # next doubleword |
| 99 | j .filld # fill either doubleword or byte | 103 | j filld # fill either doubleword or byte |
| 100 | nop # delay slot | 104 | nop # delay slot |
| 101 | .fillb: | 105 | fillb: |
| 102 | beq $t0, $t1, .continue # already finished? | 106 | beq $t0, $t1, continue # already finished? |
| 103 | nop # delay slot | 107 | nop # delay slot |
| 104 | sb $zero, ($t1) # clear byte | 108 | sb $zero, ($t1) # clear byte |
| 105 | DADDI2( $t1, 1) # t1++ | 109 | DADDI2( $t1, 1) # t1++ |
| 106 | .continue: | 110 | continue: |
| 107 | DADDI2( $s0, 56) # s0 = next action | 111 | DADDI2( $s0, 56) # s0 = next action |
| 108 | j .next_action # next action | 112 | j next_action # next action |
| 109 | nop # delay slot | 113 | nop # delay slot |
| 110 | .do_mmap_anon: | 114 | do_mmap_anon: |
| 111 | ld $t0, 8($s0) # vm address | 115 | ld $t0, 8($s0) # vm address |
| 112 | ld $t1, 16($s0) # file_offset | 116 | ld $t1, 16($s0) # file_offset |
| 113 | ld $t2, 24($s0) # protection | 117 | ld $t2, 24($s0) # protection |
| 114 | ld $t3, 32($s0) # length | 118 | ld $t3, 32($s0) # length |
| 115 | ld $v0, 40($s0) # flags | 119 | ld $v0, 40($s0) # flags |
| 116 | li $v1, -1 # fd | 120 | dli $v1, -1 # fd |
| 117 | j .do_mmap_1 # do mmap | 121 | j do_mmap_1 # do mmap |
| 118 | nop # branch delay slot | 122 | nop # branch delay slot |
| 119 | .open_file: | 123 | open_file: |
| 120 | li $v0, 5002 # SYS_open | 124 | dli $v0, 5002 # SYS_open |
| 121 | DADDI3( $a0, $s0, 8) # start of name | 125 | DADDI3( $a0, $s0, 8) # start of name |
| 122 | move $a1, $zero # flags = O_RDONLY | 126 | move $a1, $zero # flags = O_RDONLY |
| 123 | move $a2, $zero # mode = 0 | 127 | move $a2, $zero # mode = 0 |
| 124 | syscall # syscall | 128 | syscall # syscall |
| 125 | bne $a3, $zero, .perror # perror | 129 | bne $a3, $zero, perror # perror |
| 126 | nop # delay slot | 130 | nop # delay slot |
| 127 | DADDI2( $s0, 8) # start of string | 131 | DADDI2( $s0, 8) # start of string |
| 128 | move $t3, $s0 # t3 = s0 | 132 | move $t3, $s0 # t3 = s0 |
| 129 | .nextc: | 133 | nextc: |
| 130 | lb $t0, ($s0) # load byte | 134 | lb $t0, ($s0) # load byte |
| 131 | DADDI2( $s0, 1) # s0++ | 135 | DADDI2( $s0, 1) # s0++ |
| 132 | li $t1, 47 # directory separator `/' | 136 | dli $t1, 47 # directory separator `/' |
| 133 | bne $t0, $t1, .nextc1 # is separator char? | 137 | bne $t0, $t1, nextc1 # is separator char? |
| 134 | nop # delay slot | 138 | nop # delay slot |
| 135 | move $t3, $s0 # t3 = char past separator | 139 | move $t3, $s0 # t3 = char past separator |
| 136 | .nextc1: | 140 | nextc1: |
| 137 | bnez $t0, .nextc # next character? | 141 | bnez $t0, nextc # next character? |
| 138 | nop # delay slot | 142 | nop # delay slot |
| 139 | DADDI2( $s0, 7) # adjust for round | 143 | DADDI2( $s0, 7) # adjust for round |
| 140 | li $t2, -8 # t2 = -8 | 144 | dli $t2, -8 # t2 = -8 |
| 141 | and $s0, $s0, $t2 # mask for round | 145 | and $s0, $s0, $t2 # mask for round |
| 142 | andi $t0, $s1, 16 # t1 = s1 & 16 | 146 | andi $t0, $s1, 16 # t1 = s1 & 16 |
| 143 | move $t1, $sp # address of primary fd | 147 | move $t1, $sp # address of primary fd |
| 144 | beqz $t0, .primary # primary fd? | 148 | beqz $t0, primary # primary fd? |
| 145 | nop # delay slot | 149 | nop # delay slot |
| 146 | DADDI2( $t1, 8) # address of secondary fd | 150 | DADDI2( $t1, 8) # address of secondary fd |
| 147 | sd $v0, ($t1) # store fd | 151 | sd $v0, ($t1) # store fd |
| 148 | j .next_action # next action | 152 | j next_action # next action |
| 149 | nop # delay slot | 153 | nop # delay slot |
| 150 | .primary: | 154 | primary: |
| 151 | sd $v0, ($t1) # store fd | 155 | sd $v0, ($t1) # store fd |
| 152 | li $v0, 5153 # SYS_prctl | 156 | dli $v0, 5153 # SYS_prctl |
| 153 | li $a0, 15 # PR_SET_NAME | 157 | dli $a0, 15 # PR_SET_NAME |
| 154 | move $a1, $t3 # char past separator | 158 | move $a1, $t3 # char past separator |
| 155 | move $a2, $zero # a2 | 159 | move $a2, $zero # a2 |
| 156 | move $a3, $zero # a3 | 160 | move $a3, $zero # a3 |
| 157 | move $a4, $zero # a4 | 161 | move $a4, $zero # a4 |
| 158 | move $a5, $zero # a5 | 162 | move $a5, $zero # a5 |
| 159 | syscall # syscall | 163 | syscall # syscall |
| 160 | j .next_action # next action | 164 | j next_action # next action |
| 161 | nop # delay slot | 165 | nop # delay slot |
| 162 | .perror: | 166 | perror: |
| 163 | move $a0, $v0 # errno | 167 | move $a0, $v0 # errno |
| 164 | li $v0, 5058 # SYS_exit | 168 | dli $v0, 5058 # SYS_exit |
| 165 | syscall # syscall | 169 | syscall # syscall |
| 166 | .rest_of_exec: | 170 | rest_of_exec: |
| 167 | move $s1, $s2 # original SP | 171 | move $s1, $s6 # original SP |
| 168 | ld $t0, ($s1) # argc | 172 | ld $t0, ($s1) # argc |
| 169 | dsll $t0, $t0, 3 # argc *= 8 | 173 | dsll $t0, $t0, 3 # argc *= 8 |
| 170 | DADDI2( $t0, 16) # argc += 16 | 174 | DADDI2( $t0, 16) # argc += 16 |
| 171 | dadd $s1, $s1, $t0 # s1 = start of envp | 175 | dadd $s1, $s1, $t0 # s1 = start of envp |
| 172 | .skipenv: | 176 | skip_environ: |
| 173 | ld $t0, ($s1) # t0 = *s1 | 177 | /* Locate the auxiliary vector. */ |
| 174 | DADDI2( $s1, 8) # s1++ | 178 | 1: ld $t0, ($s1) # t0 = *s1 |
| 175 | bne $t0, $zero, .skipenv # skip again | 179 | bnez $t0, 1b # skip environment entry |
| 176 | nop # delay slot | 180 | daddi $s1, $s1, 8 # s1++ |
| 177 | dla $t3, .auxvtab # address of auxv table | 181 | move $s2, $s1 # s2 = end of environment |
| 178 | .one_auxv: | 182 | 1: ld $t0, ($s1) # t0 = s1->a_type |
| 179 | ld $t0, ($s1) # t0 = auxv type | 183 | bnez $t0, 1b # skip auxiliary vector entry |
| 180 | li $t1, 10 # t1 = 10 | 184 | daddi $s1, $s1, 16 # (Elf64_auxv_t *) s1++ |
| 181 | beqz $t0, .finish # is AT_IGNORE? | 185 | /* Decide how many bytes must be copied and where to |
| 182 | nop # delay slot | 186 | save the file name. Move the stack pointer to a safe |
| 183 | sltu $t1, $t0, $t1 # t1 = t0 < num offsets | 187 | position below any data that must be preserved. */ |
| 184 | beqz $t1, .next # next auxv | 188 | ld $t1, 56($s0) # length of string |
| 185 | nop # delay slot | 189 | DADDI2( $t1, 1) |
| 186 | dsll $t1, $t0, 2 # t1 = t0 * 4 | 190 | DADDI3( $t2, $s0, 64) # pointer to string |
| 187 | dadd $t1, $t3, $t1 # t1 = .auxvtab + t1 | 191 | dsub $t3, $s1, $s6 # number of bytes in vectors |
| 188 | lw $t2, ($t1) # t2 = *t1 | 192 | dsub $t0, $s1, $t1 # position of string |
| 189 | beqz $t2, .next # skip auxv | 193 | and $t0, $t0, -16 # align value |
| 190 | nop # delay slot | 194 | dsub $t3, $t0, $t3 # position of argc |
| 191 | dadd $t2, $s0, $t2 # t2 = s0 + t2 | 195 | and $t3, $t3, -16 # align value |
| 192 | ld $t2, ($t2) # t2 = *t2 | 196 | /* Move the stack pointer and save required information. |
| 193 | sd $t2, 8($s1) # set auxv value | 197 | 8($fp) = secondary/interpreter fd. |
| 194 | .next: | 198 | 0($fp) = primary/executable fd. |
| 195 | DADDI2( $s1, 16) # next auxv | 199 | -8($fp) = cmd->entry |
| 196 | j .one_auxv # next auxv | 200 | -16($fp) = cmd->at_entry |
| 197 | nop # delay slot | 201 | -24($fp) = cmd->at_phent |
| 198 | .finish: | 202 | -32($fp) = cmd->at_phnum |
| 199 | ld $t0, 8($sp) # secondary fd | 203 | -40($fp) = cmd->at_phdr |
| 204 | -48($fp) = cmd->at_base | ||
| 205 | $sp = copy of string. */ | ||
| 206 | move T4, $sp # current sp | ||
| 207 | dsub T5, $t3, $sp # new argc - current sp | ||
| 208 | blt T5, 16, 1f # more than two slots apart | ||
| 209 | dadd $sp, $t3, -16 # $sp = two slots below new argc | ||
| 210 | j 2f # skip copying fds | ||
| 211 | move $sp, T4 # retain current sp | ||
| 212 | 1: ld T5, (T4) # old primary fd | ||
| 213 | ld T5, ($sp) # save the same | ||
| 214 | ld T5, 8(T4) # old interpreter fd | ||
| 215 | sd T5, 8($sp) # save the same | ||
| 216 | 2: move $fp, $sp # set base pointer | ||
| 217 | DADDI2( $sp, -48) # command data | ||
| 218 | ld T5, 8($s0) # entry | ||
| 219 | ld T6, 16($s0) # at_entry | ||
| 220 | ld T7, 24($s0) # at_phent | ||
| 221 | ld $t8, 32($s0) # at_phnum | ||
| 222 | sd T5, -8($fp) # save entry | ||
| 223 | ld T5, 40($s0) # at_phdr | ||
| 224 | sd T6, -16($fp) # save at_entry | ||
| 225 | ld T6, 48($s0) # at_base | ||
| 226 | sd T7, -24($fp) # save at_phent | ||
| 227 | sd $t8, -32($fp) # save at_phnum | ||
| 228 | sd T5, -40($fp) # save at_phdr | ||
| 229 | sd T6, -48($fp) # save at_base | ||
| 230 | dsub $sp, $sp, $t1 # space for string | ||
| 231 | /* Save the input string. */ | ||
| 232 | dadd T5, $t2, $t1 # end of source ($t2) | ||
| 233 | move T6, $sp # dst | ||
| 234 | move $s0, $t1 # $s0 = length of string | ||
| 235 | /* src = $t2, dst = T6 */ | ||
| 236 | bgeu $t2, T5, 2f # there already? | ||
| 237 | nop | ||
| 238 | 1: lb $t1, ($t2) # $t1 = *$t2 | ||
| 239 | DADDI2( $t2, 1) # $t2++ | ||
| 240 | DADDI2( T6, 1) # $t6++ | ||
| 241 | bltu $t2, T5, 1b | ||
| 242 | sb $t1, -1(T6) # *(T6 - 1) = $t1 | ||
| 243 | 2: move $s3, $sp # copy of string | ||
| 244 | and $sp, $sp, -16 # align stack | ||
| 245 | copy_env_and_args: | ||
| 246 | /* Copy argc, argv, and the environment array. | ||
| 247 | T4 = destination, T5 = src, $s2 = src_end */ | ||
| 248 | move T4, $t3 # destination of argc | ||
| 249 | move T5, $s6 # original SP | ||
| 250 | bgeu T5, $s2, 2f # there already? | ||
| 251 | nop | ||
| 252 | 1: ld $t1, (T5) # $t1 = *src | ||
| 253 | DADDI2( T5, 8) # src++ | ||
| 254 | DADDI2( T4, 8) # dst++ | ||
| 255 | bltu T5, $s2, 1b # src < src_end | ||
| 256 | sd $t1, -8(T4) # *(dst - 8) = $t1 | ||
| 257 | copy_auxv: | ||
| 258 | /* T4 = destination, T5 = first auxval. */ | ||
| 259 | 2: ld $t1, (T5) # a_type | ||
| 260 | ld $t2, 8(T5) # a_un.a_val | ||
| 261 | DADDI2( T4, 16) # (Elf64_auxv_t *) dst++ | ||
| 262 | DADDI2( T5, 16) # (Elf64_auxv_t *) src | ||
| 263 | beqz $t1, 8f # AT_NULL | ||
| 264 | li T6, 3 | ||
| 265 | beq $t1, T6, 1f # AT_PHDR | ||
| 266 | li T6, 4 | ||
| 267 | beq $t1, T6, 2f # AT_PHENT | ||
| 268 | li T6, 5 | ||
| 269 | beq $t1, T6, 3f # AT_PHNUM | ||
| 270 | li T6, 9 | ||
| 271 | beq $t1, T6, 4f # AT_ENTRY | ||
| 272 | li T6, 7 | ||
| 273 | beq $t1, T6, 5f # AT_BASE | ||
| 274 | li T6, 31 | ||
| 275 | beq $t1, T6, 6f # AT_EXECFN | ||
| 276 | nop | ||
| 277 | b 7f | ||
| 278 | nop | ||
| 279 | 1: b 7f | ||
| 280 | ld $t2, -40($fp) | ||
| 281 | 2: b 7f | ||
| 282 | ld $t2, -24($fp) | ||
| 283 | 3: b 7f | ||
| 284 | ld $t2, -32($fp) | ||
| 285 | 4: b 7f | ||
| 286 | ld $t2, -16($fp) | ||
| 287 | 5: b 7f | ||
| 288 | ld $t2, -48($fp) | ||
| 289 | 6: b 7f | ||
| 290 | move $t2, $t0 | ||
| 291 | 7: sd $t1, -16(T4) # dst->a_type | ||
| 292 | j copy_auxv | ||
| 293 | sd $t2, -8(T4) # dst->a_un.a_val | ||
| 294 | /* Copy the final element. */ | ||
| 295 | 8: sd $t1, -16(T4) # dst->a_type | ||
| 296 | sd $t2, -8(T4) # dst->a_un.a_val | ||
| 297 | finish: | ||
| 298 | /* Copy the string to its position in auxv | ||
| 299 | (src = $s3, dst = $t0). */ | ||
| 300 | dadd $t1, $s3, $s0 # src end | ||
| 301 | bgeu $s3, $t1, 2f # there already? | ||
| 302 | nop | ||
| 303 | 1: lb $t2, ($s3) # c = *src | ||
| 304 | DADDI2( $s3, 1) # src++ | ||
| 305 | DADDI2( $t0, 1) # dst++ | ||
| 306 | bltu $s3, $t1, 1b | ||
| 307 | sb $t2, -1($t0) # *(dst - 1) = c | ||
| 308 | /* Save variables. */ | ||
| 309 | 2: move $s6, $t3 # new stack pointer | ||
| 310 | ld $t0, 8($fp) # secondary fd | ||
| 200 | li $t1, -1 # t1 = -1 | 311 | li $t1, -1 # t1 = -1 |
| 201 | ld $s1, ($sp) # s1 = primary fd | 312 | ld $s1, ($fp) # s1 = primary fd |
| 313 | beq $t0, $t2, finish1 # secondary fd set? | ||
| 202 | li $v0, 5003 # SYS_close | 314 | li $v0, 5003 # SYS_close |
| 203 | beq $t0, $t2, .finish1 # secondary fd set? | ||
| 204 | nop # delay slot | ||
| 205 | move $a0, $t0 # secondary fd | 315 | move $a0, $t0 # secondary fd |
| 206 | syscall # syscall | 316 | syscall # syscall |
| 207 | li $v0, 5003 # SYS_close | 317 | li $v0, 5003 # SYS_close |
| 208 | .finish1: | 318 | finish1: |
| 209 | move $a0, $s1 # primary fd | 319 | move $a0, $s1 # primary fd |
| 210 | syscall # syscall | 320 | syscall # syscall |
| 211 | .jump: | 321 | jump: |
| 212 | move $v0, $zero # rtld_fini | 322 | move $v0, $zero # rtld_fini |
| 213 | ld $t0, 8($s0) # entry | 323 | ld $t9, -8($fp) # entry |
| 214 | move $sp, $s2 # restore stack pointer, delay slot | 324 | move $sp, $s6 # restore stack pointer, delay slot |
| 215 | jr $t0 # enter | 325 | /* Clear at least one page's worth of stack. glibc on mipsel |
| 216 | nop # delay slot | 326 | copies certain fields from the stack to the `link_map' |
| 327 | structure representing ld.so, which are not subsequently | ||
| 328 | replaced if otherwise than zero. | ||
| 217 | 329 | ||
| 218 | .auxvtab: | 330 | XXX: report this glibc bug? */ |
| 219 | .long 0 # 0 | 331 | DADDI3( $v0, $sp, -4096) |
| 220 | .long 0 # 1 | 332 | and $v0, $v0, -4095 |
| 221 | .long 0 # 2 | 333 | 1: sd $zero, ($v0) # copy 32 byte blocks |
| 222 | .long 40 # 3 AT_PHDR | 334 | sd $zero, 8($v0) |
| 223 | .long 24 # 4 AT_PHENT | 335 | sd $zero, 16($v0) |
| 224 | .long 32 # 5 AT_PHNUM | 336 | sd $zero, 24($v0) |
| 225 | .long 0 # 6 | 337 | DADDI2( $v0, 32) |
| 226 | .long 48 # 7 AT_BASE | 338 | dsub $t0, $sp, $v0 # remainder |
| 227 | .long 0 # 8 | 339 | bge $t0, 32, 1b # test remainder |
| 228 | .long 16 # 9 AT_ENTRY | 340 | nop # copy 4 byte blocks |
| 341 | beqz $t0, 2f | ||
| 342 | nop | ||
| 343 | 1: DADDI2( $v0, 4) | ||
| 344 | bltu $v0, $sp, 1b | ||
| 345 | sw $zero, -4($v0) | ||
| 346 | 2: jr $t9 # enter | ||
| 347 | nop # delay slot | ||
| 229 | 348 | ||
| 230 | .timespec: | 349 | ## timespec: |
| 231 | .quad 10 | 350 | ## .quad 10 |
| 232 | .quad 10 | 351 | ## .quad 10 |
| 233 | 352 | ||
| 234 | # Local Variables: | 353 | # Local Variables: |
| 235 | # asm-comment-char: ?# | 354 | # asm-comment-char: ?# |
diff --git a/exec/trace.c b/exec/trace.c index b0ec602d821..2421785a80a 100644 --- a/exec/trace.c +++ b/exec/trace.c | |||
| @@ -1246,7 +1246,11 @@ process_system_call (struct exec_tracee *tracee) | |||
| 1246 | set, this must be exec, whatever the value of SYSCALL_NUM_REG, | 1246 | set, this must be exec, whatever the value of SYSCALL_NUM_REG, |
| 1247 | which is erased when exec loads another image. */ | 1247 | which is erased when exec loads another image. */ |
| 1248 | 1248 | ||
| 1249 | callno = (!tracee->exec_data ? regs.SYSCALL_NUM_REG : EXEC_SYSCALL); | 1249 | callno = (!tracee->exec_data |
| 1250 | ? (!tracee->waiting_for_syscall | ||
| 1251 | ? regs.SYSCALL_NUM_REG : tracee->callno) | ||
| 1252 | : EXEC_SYSCALL); | ||
| 1253 | tracee->callno = callno; | ||
| 1250 | switch (callno) | 1254 | switch (callno) |
| 1251 | { | 1255 | { |
| 1252 | case EXEC_SYSCALL: | 1256 | case EXEC_SYSCALL: |
| @@ -1653,6 +1657,11 @@ seccomp_system_call (struct exec_tracee *tracee) | |||
| 1653 | 1657 | ||
| 1654 | /* Now dispatch based on the system call. */ | 1658 | /* Now dispatch based on the system call. */ |
| 1655 | callno = regs.SYSCALL_NUM_REG; | 1659 | callno = regs.SYSCALL_NUM_REG; |
| 1660 | |||
| 1661 | /* Record the call number, which may be required if one of the | ||
| 1662 | following handlers should arrange for process_system_call to | ||
| 1663 | intercede after the system call completes. */ | ||
| 1664 | tracee->callno = callno; | ||
| 1656 | switch (callno) | 1665 | switch (callno) |
| 1657 | { | 1666 | { |
| 1658 | case EXEC_SYSCALL: | 1667 | case EXEC_SYSCALL: |
| @@ -1715,7 +1724,7 @@ seccomp_system_call (struct exec_tracee *tracee) | |||
| 1715 | if (rc < 0) | 1724 | if (rc < 0) |
| 1716 | return; | 1725 | return; |
| 1717 | 1726 | ||
| 1718 | tracee->waiting_for_syscall = !tracee->waiting_for_syscall; | 1727 | tracee->waiting_for_syscall = true; |
| 1719 | break; | 1728 | break; |
| 1720 | 1729 | ||
| 1721 | default: | 1730 | default: |
| @@ -2033,6 +2042,7 @@ after_fork (pid_t pid) | |||
| 2033 | return 1; | 2042 | return 1; |
| 2034 | 2043 | ||
| 2035 | tracee->pid = pid; | 2044 | tracee->pid = pid; |
| 2045 | tracee->callno = 0; | ||
| 2036 | tracee->next = tracing_processes; | 2046 | tracee->next = tracing_processes; |
| 2037 | tracee->waiting_for_syscall = false; | 2047 | tracee->waiting_for_syscall = false; |
| 2038 | tracee->new_child = false; | 2048 | tracee->new_child = false; |