Make sure that calloc is called at least once

PLT relocations aren't required when -z now used.  Linker on master with:

commit 25070364b0ce33eed46aa5d78ebebbec6accec7e
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Sat May 16 07:00:21 2015 -0700

    Don't generate PLT relocations for now binding

    There is no need for PLT relocations with -z now. We can use GOT
    relocations, which take less space, instead and replace 16-byte .plt
    entres with 8-byte .plt.got entries.

    bfd/

      * elf32-i386.c (elf_i386_check_relocs): Create .plt.got section
      for now binding.
      (elf_i386_allocate_dynrelocs): Use .plt.got section for now
      binding.
      * elf64-x86-64.c (elf_x86_64_check_relocs): Create .plt.got
      section for now binding.
      (elf_x86_64_allocate_dynrelocs): Use .plt.got section for now
      binding.

won't generate PLT relocations with -z now.  elf/tst-audit2.c expect
certain order of execution in ld.so.  With PLT relocations, the GOTPLT
entry of calloc is update to calloc defined in tst-audit2:

(gdb) bt
    skip_ifunc=<optimized out>, reloc_addr_arg=<optimized out>,
    version=<optimized out>, sym=<optimized out>, map=<optimized out>)
    at ../sysdeps/i386/dl-machine.h:329
out>,
    nrelative=<optimized out>, relsize=<optimized out>,
    reladdr=<optimized out>, map=<optimized out>) at do-rel.h:137
reloc_mode=reloc_mode@entry=0,
    consider_profiling=1, consider_profiling@entry=0) at dl-reloc.c:258
    user_entry=0xffffcf1c, auxv=0xffffd0a8) at rtld.c:2133
    start_argptr=start_argptr@entry=0xffffcfb0,
    dl_main=dl_main@entry=0xf7fda6f0 <dl_main>) at
../elf/dl-sysdep.c:249
   from /export/build/gnu/glibc-32bit/build-i686-linux/elf/ld.so
(gdb)

and then calloc is called:

(gdb) c
Continuing.

Breakpoint 4, calloc (n=n@entry=20, m=4) at tst-audit2.c:18
18 {
(gdb) bt
    reloc_mode=reloc_mode@entry=0, consider_profiling=1,
    consider_profiling@entry=0) at dl-reloc.c:272
    user_entry=0xffffcf1c, auxv=0xffffd0a8) at rtld.c:2133
    start_argptr=start_argptr@entry=0xffffcfb0,
    dl_main=dl_main@entry=0xf7fda6f0 <dl_main>) at
../elf/dl-sysdep.c:249
   from /export/build/gnu/glibc-32bit/build-i686-linux/elf/ld.so
(gdb)

With GOT relocation, calloc in ld.so is called first:

(gdb) bt
    consider_profiling=1) at dl-reloc.c:272
    user_entry=0xffffcf0c, auxv=0xffffd098) at rtld.c:2074
    start_argptr=start_argptr@entry=0xffffcfa0,
    dl_main=dl_main@entry=0xf7fda6c0 <dl_main>) at
../elf/dl-sysdep.c:249
   from /export/build/gnu/glibc-32bit-test/build-i686-linux/elf/ld.so
(gdb)

and then the GOT entry of calloc is updated:

(gdb) bt
    skip_ifunc=<optimized out>, reloc_addr_arg=<optimized out>,
    version=<optimized out>, sym=<optimized out>, map=<optimized out>)
    at ../sysdeps/i386/dl-machine.h:329
out>,
    nrelative=<optimized out>, relsize=<optimized out>,
    reladdr=<optimized out>, map=<optimized out>) at do-rel.h:137
reloc_mode=reloc_mode@entry=0,
    consider_profiling=1, consider_profiling@entry=0) at dl-reloc.c:258
    user_entry=0xffffcf0c, auxv=0xffffd098) at rtld.c:2133
    start_argptr=start_argptr@entry=0xffffcfa0,
    dl_main=dl_main@entry=0xf7fda6c0 <dl_main>) at
../elf/dl-sysdep.c:249
   from /export/build/gnu/glibc-32bit-test/build-i686-linux/elf/ld.so
(gdb)

After that, since calloc isn't called from ld.so nor any other modules,
magic in tst-audit2 isn't updated.  Both orders are correct.  This patch
makes sure that calloc in tst-audit2.c is called at least once from ld.so.

	[BZ #18422]
	* Makefile ($(objpfx)tst-audit2): Depend on $(libdl).
	($(objpfx)tst-audit2.out): Also depend on
	$(objpfx)tst-auditmod9b.so.
	* elf/tst-audit2.c: Include <dlfcn.h>.
	(calloc_called): New.
	(calloc): Allow to be called more than once.
	(do_test): dllopen/dlclose $ORIGIN/tst-auditmod9b.so.
This commit is contained in:
H.J. Lu 2015-05-28 05:06:27 -07:00
parent be2e25bbd7
commit 58007e9e68
4 changed files with 34 additions and 8 deletions

View File

@ -1,3 +1,14 @@
2015-05-28 H.J. Lu <hongjiu.lu@intel.com>
[BZ #18422]
* Makefile ($(objpfx)tst-audit2): Depend on $(libdl).
($(objpfx)tst-audit2.out): Also depend on
$(objpfx)tst-auditmod9b.so.
* elf/tst-audit2.c: Include <dlfcn.h>.
(calloc_called): New.
(calloc): Allow to be called more than once.
(do_test): dllopen/dlclose $ORIGIN/tst-auditmod9b.so.
2015-05-28 Wilco Dijkstra <wdijkstr@arm.com>
* sysdeps/ieee754/dbl-64/s_fabs.c: (__fabs): Call __builtin_fabs.

2
NEWS
View File

@ -19,7 +19,7 @@ Version 2.22
18047, 18049, 18068, 18080, 18093, 18100, 18104, 18110, 18111, 18125,
18128, 18138, 18185, 18196, 18197, 18206, 18210, 18211, 18217, 18220,
18221, 18234, 18244, 18247, 18287, 18319, 18333, 18346, 18397, 18409,
18410, 18412, 18418, 18434, 18444.
18410, 18412, 18418, 18422, 18434, 18444.
* Cache information can be queried via sysconf() function on s390 e.g. with
_SC_LEVEL1_ICACHE_SIZE as argument.

View File

@ -1034,7 +1034,8 @@ $(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so
$(objpfx)tst-audit1.out: $(objpfx)tst-auditmod1.so
tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
$(objpfx)tst-audit2.out: $(objpfx)tst-auditmod1.so
$(objpfx)tst-audit2: $(libdl)
$(objpfx)tst-audit2.out: $(objpfx)tst-auditmod1.so $(objpfx)tst-auditmod9b.so
# Prevent GCC-5 from translating a malloc/memset pair into calloc
CFLAGS-tst-audit2.c += -fno-builtin
tst-audit2-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so

View File

@ -3,26 +3,35 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#define MAGIC1 0xabcdef72
#define MAGIC2 0xd8675309
static __thread unsigned int magic[] = { MAGIC1, MAGIC2 };
static __thread int calloc_called;
#undef calloc
/* This calloc definition will be called by the dynamic linker itself.
We test that it has initialized our TLS block by the time it does so. */
We test that interposed calloc is called by the dynamic loader, and
that TLS is fully initialized by then. */
void *
calloc (size_t n, size_t m)
{
if (magic[0] != MAGIC1 || magic[1] != MAGIC2)
if (!calloc_called)
{
printf ("{%x, %x} != {%x, %x}\n", magic[0], magic[1], MAGIC1, MAGIC2);
abort ();
/* Allow our calloc to be called more than once. */
calloc_called = 1;
if (magic[0] != MAGIC1 || magic[1] != MAGIC2)
{
printf ("{%x, %x} != {%x, %x}\n",
magic[0], magic[1], MAGIC1, MAGIC2);
abort ();
}
magic[0] = MAGIC2;
magic[1] = MAGIC1;
}
magic[0] = MAGIC2;
magic[1] = MAGIC1;
n *= m;
void *ptr = malloc (n);
@ -34,6 +43,11 @@ calloc (size_t n, size_t m)
static int
do_test (void)
{
/* Make sure that our calloc is called from the dynamic linker at least
once. */
void *h = dlopen("$ORIGIN/tst-auditmod9b.so", RTLD_LAZY);
if (h != NULL)
dlclose (h);
if (magic[1] != MAGIC1 || magic[0] != MAGIC2)
{
printf ("{%x, %x} != {%x, %x}\n", magic[0], magic[1], MAGIC2, MAGIC1);