diff options
author | Paul Pluzhnikov <ppluzhnikov@google.com> | 2014-02-28 16:47:23 -0800 |
---|---|---|
committer | Paul Pluzhnikov <ppluzhnikov@google.com> | 2014-02-28 16:47:23 -0800 |
commit | 8623844f33fa66a4ad37fa6986e2c1ebbb0d5c84 (patch) | |
tree | 1cf67f2888991f00a3ea9a36438f63e6f2e7e754 | |
parent | dc8069787afab19e6e278722a92568977fc4e15d (diff) | |
download | glibc-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.google | 8 | ||||
-rw-r--r-- | elf/Versions | 1 | ||||
-rw-r--r-- | elf/dl-init.c | 13 | ||||
-rw-r--r-- | sysdeps/i386/start.S | 70 | ||||
-rw-r--r-- | sysdeps/x86_64/start.S | 51 |
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 |