Forward-ported from cl/51218346 (from cl/37734-p2).
(ppluzhnikov, google-local)
+elf/Versions
+elf/dl-init.c
+sysdeps/i386/elf/start.S
+sysdeps/x86_64/elf/start.S
+ Add __google_auxv.
+ Forward-ported from cl/51271693 (from cl/38027-p2).
+ (ppluzhnikov, google-local)
+
# Pointer protection.
__pointer_chk_guard;
+ __google_auxv;
}
}
}
+ElfW(auxv_t) *__google_auxv;
+
void
internal_function
_dl_init (struct link_map *main_map, int argc, char **argv, char **env)
ElfW(Dyn) *preinit_array_size = main_map->l_info[DT_PREINIT_ARRAYSZ];
unsigned int i;
+ /* _dl_init is called from _dl_start_user during loader startup.
+ It is also called from dl_open_worker.
+ Prevent multiple initialization of __google_auxv. */
+ if (__google_auxv == NULL)
+ {
+ char **e;
+
+ for (e = env; *e; ++e) /* Skip. */;
+ __google_auxv = (ElfW(auxv_t) *) ++e;
+ }
+
if (__builtin_expect (GL(dl_initfirst) != NULL, 0))
{
call_init (GL(dl_initfirst), argc, argv, env);
/* Clear the frame pointer. The ABI suggests this be done, to mark
the outermost frame obviously. */
xorl %ebp, %ebp
+ call __google_init
/* Extract the arguments as encoded on the stack and set up
the arguments for `main': argc, argv. envp will be determined
ret
#endif
+/*
+ %esp The stack contains the arguments and environment:
+ 0(%esp) ra
+ 1*4(%esp) argc
+ 2*4(%esp) argv[0]
+ ...
+ (argc+2)*4(%esp) NULL
+ (argc+3)*4(%esp) envp[0]
+ ...
+ (argc+2+env_count+1)*4(%esp) NULL
+ (argc+2+env_count+2)*4(%esp) auxv[0]
+ ...
+*/
+
+__google_init:
+#ifdef SHARED
+ call 1b
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ leal __google_argc@GOTOFF(%ebx), %ecx
+#else
+ leal __google_argc, %ecx
+#endif
+ movl 4(%esp), %eax
+ movl %eax, 0(%ecx)
+ push %esp
+ pop %eax
+ addl $2*4, %eax
+#ifdef SHARED
+ leal __google_argv@GOTOFF(%ebx), %ecx
+#else
+ leal __google_argv, %ecx
+#endif
+ movl %eax, 0(%ecx)
+/* The next loop could be omitted if we are to trust argc from the kernel. */
+1: cmpl $0, 0(%eax) /* while(argv[i++] != 0) skip; */
+ je 2f
+ addl $4, %eax
+ jmp 1b
+2: addl $4, %eax
+#ifdef SHARED
+ leal __google_envp@GOTOFF(%ebx), %ecx
+#else
+ leal __google_envp, %ecx
+#endif
+ movl %eax, 0(%ecx)
+3: cmpl $0, 0(%eax) /* while (envp[i++] != 0) skip; */
+ je 4f
+ addl $4, %eax
+ jmp 3b
+4: addl $4, %eax
+#ifdef SHARED
+ leal __google_auxv@GOTOFF(%ebx), %ecx
+#else
+ leal __google_auxv, %ecx
+#endif
+ movl %eax, 0(%ecx)
+ ret
+
/* To fulfill the System V/i386 ABI we need this symbol. Yuck, it's so
meaningless since we don't support machines < 80386. */
.section .rodata
.long 0
.weak data_start
data_start = __data_start
+
+/* The {argc,argv,envp} variables are not exposed to keep the interface narrow
+ (we don't need anything except auxv right now). If/when they are needed,
+ simply mark them with ".globl". */
+__google_argc: .long 0
+__google_argv: .long 0
+__google_envp: .long 0
+ .globl __google_auxv
+__google_auxv: .long 0
+
+
/* Clear the frame pointer. The ABI suggests this be done, to mark
the outermost frame obviously. */
xorl %ebp, %ebp
+ call __google_init
/* Extract the arguments as encoded on the stack and set up
the arguments for __libc_start_main (int (*main) (int, char **, char **),
hlt /* Crash if somehow `exit' does return. */
cfi_endproc
+/*
+ %rsp The stack contains the arguments and environment:
+ 0(%rsp) ra
+ 1*8(%rsp) argc
+ 2*8(%rsp) argv[0]
+ ...
+ (argc+2)*8(%rsp) NULL
+ (argc+3)*8(%rsp) envp[0]
+ ...
+ (argc+2+env_count+1)*8(%rsp) NULL
+ (argc+2+env_count+2)*8(%rsp) auxv[0]
+ ...
+*/
+__google_init:
+ leaq __google_argc(%rip), %rbx /* %rbx = &__google_argc */
+ movq 8(%rsp), %rax
+ movq %rax, 0(%rbx)
+ push %rsp
+ pop %rax
+ addq $2*8, %rax
+ leaq __google_argv(%rip), %rbx
+ movq %rax, 0(%rbx)
+/* The next loop could be omitted if we are to trust argc from the kernel. */
+1: cmpq $0, 0(%rax) /* while(argv[i++] != 0) skip; */
+ je 2f
+ addq $8, %rax
+ jmp 1b
+2: addq $8, %rax
+ leaq __google_envp(%rip), %rbx
+ movq %rax, 0(%rbx)
+3: cmpq $0, 0(%rax) /* while (envp[i++] != 0) skip; */
+ je 4f
+ addq $8, %rax
+ jmp 3b
+4: addq $8, %rax
+ leaq __google_auxv(%rip), %rbx
+ movq %rax, 0(%rbx)
+ ret
+
+
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
.long 0
.weak data_start
data_start = __data_start
+
+ .p2align 3
+/* The {argc,argv,envp} variables are not exposed to keep the interface narrow
+ (we don't need anything except auxv right now). If/when they are needed,
+ simply mark them with ".globl". */
+__google_argc: .quad 0
+__google_argv: .quad 0
+__google_envp: .quad 0
+ .globl __google_auxv
+__google_auxv: .quad 0