]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Add __google_auxv. Forward-ported from cl/51271693 (from cl/38027-p2).
authorPaul Pluzhnikov <ppluzhnikov@google.com>
Sat, 1 Mar 2014 00:47:23 +0000 (16:47 -0800)
committerPaul Pluzhnikov <ppluzhnikov@google.com>
Sat, 1 Mar 2014 00:47:23 +0000 (16:47 -0800)
README.google
elf/Versions
elf/dl-init.c
sysdeps/i386/start.S
sysdeps/x86_64/start.S

index f4786b854a1cb49042b28ff1570ee1f77a0fc94f..32e6dcf4e6e9fda6026c4fad4f77b586ad58d8cb 100644 (file)
@@ -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)
+
index 01b7a59d5e2cd75638c95b0e5b47a206f81edfab..2fe91c4a419e2b13f5b9fa22dc1c24d1396b31ee 100644 (file)
@@ -62,5 +62,6 @@ ld {
 
     # Pointer protection.
     __pointer_chk_guard;
+    __google_auxv;
   }
 }
index 28a6ff6d8ac2fe0c835b09513f3ad903f7263fba..d30ab4e284cf1e742efd37293648a956f0ff630c 100644 (file)
@@ -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);
index b79bff2dfcba6cdec8bb5cec415574b788613527..2b8c671a6edfb57b7c0c71bdd1be0d6678ba9869 100644 (file)
@@ -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
+
+
index e3d4ff8e20e0f451e074f7cb63066ec660b52a5e..09020cffe19a7ba89f7bd523b6a2d67852b3481c 100644 (file)
@@ -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