summaryrefslogtreecommitdiff
path: root/src/ldso/x32/start.s
diff options
context:
space:
mode:
Diffstat (limited to 'src/ldso/x32/start.s')
-rw-r--r--src/ldso/x32/start.s22
1 files changed, 15 insertions, 7 deletions
diff --git a/src/ldso/x32/start.s b/src/ldso/x32/start.s
index 80c1d08d..0fcf46dc 100644
--- a/src/ldso/x32/start.s
+++ b/src/ldso/x32/start.s
@@ -1,16 +1,24 @@
.text
.global _start
_start:
- mov (%rsp),%rdi
- lea 8(%rsp),%rsi
+ mov (%rsp),%rdi /* move argc into 1st argument slot */
+ lea 4(%rsp),%rsi /* move argv into 2nd argument slot */
call __dynlink
- pop %rdi
+ /* in case the dynlinker was called directly, it sets the "consumed"
+ argv values to -1. so we must loop over the array as long as -1
+ is in the top argv slot, decrement argc, and then set the stackpointer
+ to the new argc as well as argc's new value.
+ as the x32 abi has longs in the argv array, we cannot use push/pop.*/
+ movl (%rsp),%edi /* copy argc into edi */
+ xor %rdx,%rdx /* we use rdx as an offset to the current argv member */
1: dec %edi
- pop %rsi
- cmp $-1,%rsi
+ addl $4, %edx
+ movl (%rsp, %rdx), %esi
+ cmp $-1,%esi
jz 1b
inc %edi
- push %rsi
- push %rdi
+ subl $4, %edx
+ lea (%rsp, %rdx), %rsp /* set rsp to new argv[-1] */
+ movl %edi, (%rsp) /* write new argc there */
xor %edx,%edx
jmp *%rax