about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaul Pluzhnikov <ppluzhnikov@google.com>2014-02-28 16:47:23 -0800
committerPaul Pluzhnikov <ppluzhnikov@google.com>2014-02-28 16:47:23 -0800
commit8623844f33fa66a4ad37fa6986e2c1ebbb0d5c84 (patch)
tree1cf67f2888991f00a3ea9a36438f63e6f2e7e754
parentdc8069787afab19e6e278722a92568977fc4e15d (diff)
downloadglibc-8623844f33fa66a4ad37fa6986e2c1ebbb0d5c84.tar.gz
glibc-8623844f33fa66a4ad37fa6986e2c1ebbb0d5c84.tar.xz
glibc-8623844f33fa66a4ad37fa6986e2c1ebbb0d5c84.zip
Add __google_auxv. Forward-ported from cl/51271693 (from cl/38027-p2).
-rw-r--r--README.google8
-rw-r--r--elf/Versions1
-rw-r--r--elf/dl-init.c13
-rw-r--r--sysdeps/i386/start.S70
-rw-r--r--sysdeps/x86_64/start.S51
5 files changed, 143 insertions, 0 deletions
diff --git a/README.google b/README.google
index f4786b854a..32e6dcf4e6 100644
--- a/README.google
+++ b/README.google
@@ -84,3 +84,11 @@ csu/Makefile
   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)
+
diff --git a/elf/Versions b/elf/Versions
index 01b7a59d5e..2fe91c4a41 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -62,5 +62,6 @@ ld {
 
     # Pointer protection.
     __pointer_chk_guard;
+    __google_auxv;
   }
 }
diff --git a/elf/dl-init.c b/elf/dl-init.c
index 28a6ff6d8a..d30ab4e284 100644
--- a/elf/dl-init.c
+++ b/elf/dl-init.c
@@ -80,6 +80,8 @@ call_init (struct link_map *l, int argc, char **argv, char **env)
 }
 
 
+ElfW(auxv_t) *__google_auxv;
+
 void
 internal_function
 _dl_init (struct link_map *main_map, int argc, char **argv, char **env)
@@ -88,6 +90,17 @@ _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);
diff --git a/sysdeps/i386/start.S b/sysdeps/i386/start.S
index b79bff2dfc..2b8c671a6e 100644
--- a/sysdeps/i386/start.S
+++ b/sysdeps/i386/start.S
@@ -59,6 +59,7 @@ _start:
 	/* 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
@@ -122,6 +123,64 @@ _start:
 	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
@@ -137,3 +196,14 @@ __data_start:
 	.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
+
+
diff --git a/sysdeps/x86_64/start.S b/sysdeps/x86_64/start.S
index e3d4ff8e20..09020cffe1 100644
--- a/sysdeps/x86_64/start.S
+++ b/sysdeps/x86_64/start.S
@@ -65,6 +65,7 @@ _start:
 	/* 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 **),
@@ -125,6 +126,46 @@ _start:
 	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
@@ -132,3 +173,13 @@ __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