]> sourceware.org Git - glibc.git/commitdiff
Don't use broken DL_AUTO_FUNCTION_ADDRESS()
authorGuy Martin <gmsoft@tuxicoman.be>
Thu, 21 Nov 2013 18:23:16 +0000 (13:23 -0500)
committerCarlos O'Donell <carlos@redhat.com>
Thu, 21 Nov 2013 20:52:31 +0000 (15:52 -0500)
On hppa and ia64, the macro DL_AUTO_FUNCTION_ADDRESS() uses the
variable fptr[2] in it's own scope.

The content of fptr[] is thus undefined right after the macro exits.
Newer gcc's (>= 4.7) reuse the stack space of this variable triggering
a segmentation fault in dl-init.c:69.

To fix this we rewrite the macros to make the call directly to init
and fini without needing to pass back a constructed function pointer.

ChangeLog
elf/dl-close.c
elf/dl-fini.c
elf/dl-init.c
ports/ChangeLog.hppa
ports/ChangeLog.ia64
ports/sysdeps/hppa/dl-lookupcfg.h
ports/sysdeps/hppa/dl-machine.h
ports/sysdeps/ia64/dl-lookupcfg.h
ports/sysdeps/ia64/dl-machine.h
sysdeps/generic/ldsodefs.h

index 1f673d32264c93abe13c717ab17b4bad735cb165..a6a21a2bcf2306a37956348815b4159e2848c71f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-11-21  Guy Martin  <gmsoft@tuxicoman.be>
+
+       * sysdeps/generic/ldsodefs.h: Replace DL_DT_INIT_ADDRESS() and
+       DL_DT_FINI_ADDRESS() macro with DL_CALL_DT_INIT() and
+       DL_CALL_DT_FINI() that call the functions directly.
+       * elf/dl-init.c: Use the new DL_CALL_DT_INIT() macro.
+       * elf/dl-close.c: Use the new DL_CALL_DT_FINI() macro.
+       * elf/dl-fini.c: Likewise.
+
 2013-11-20  Ondřej Bílka  <neleai@seznam.cz>
 
        * malloc/hooks.c (memalign_check): Add alignment rounding.
index fe3014cca3f593cff9f230013d485ccadf577981..407926bade8f0c20f3f68f6553c015901ecc3ce4 100644 (file)
@@ -274,9 +274,8 @@ _dl_close_worker (struct link_map *map)
 
              /* Next try the old-style destructor.  */
              if (imap->l_info[DT_FINI] != NULL)
-               (*(void (*) (void)) DL_DT_FINI_ADDRESS
-                (imap, ((void *) imap->l_addr
-                        + imap->l_info[DT_FINI]->d_un.d_ptr))) ();
+               DL_CALL_DT_FINI (imap, ((void *) imap->l_addr
+                        + imap->l_info[DT_FINI]->d_un.d_ptr));
            }
 
 #ifdef SHARED
index 6b245f00225114e59ab2400b7b067a1edf2106ec..db5269c82f581a5c9bc31341e4b5b1f5d03f5abe 100644 (file)
@@ -254,7 +254,7 @@ _dl_fini (void)
 
                  /* Next try the old-style destructor.  */
                  if (l->l_info[DT_FINI] != NULL)
-                   ((fini_t) DL_DT_FINI_ADDRESS (l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
+                    DL_CALL_DT_FINI(l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr);
                }
 
 #ifdef SHARED
index a657eb6c40ce5f93bf0cb47a65409fac9cad0935..40783684f2602b2e1a96eddb42363ebc53e95d7c 100644 (file)
@@ -61,13 +61,7 @@ call_init (struct link_map *l, int argc, char **argv, char **env)
      - the others in the DT_INIT_ARRAY.
   */
   if (l->l_info[DT_INIT] != NULL)
-    {
-      init_t init = (init_t) DL_DT_INIT_ADDRESS
-       (l, l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr);
-
-      /* Call the function.  */
-      init (argc, argv, env);
-    }
+    DL_CALL_DT_INIT(l, l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr, argc, argv, env);
 
   /* Next see whether there is an array with initialization functions.  */
   ElfW(Dyn) *init_array = l->l_info[DT_INIT_ARRAY];
index b7c82131d934e33608d8069507d6df160f502e9c..82df2cec8957c4e2788b866cc1b89082013aecc9 100644 (file)
@@ -1,3 +1,12 @@
+2013-11-21  Guy Martin  <gmsoft@tuxicoman.be>
+
+       * sysdeps/hppa/dl-lookupcfg.h: Remove obsolete
+       DL_DT_INIT_ADDRESS() and DL_DT_FINI_ADDRESS() macro and implement
+       DL_CALL_DT_INIT() as well as DL_CALL_DT_FINI().
+       Define DL_DT_FUNCTION_ADDRESS().
+       * sysdeps/hppa/dl-machine.h: Update ELF_MACHINE_START_ADDRESS()
+       to use DL_DT_FUNCTION_ADDRESS().
+
 2013-10-30  Mike Frysinger  <vapier@gentoo.org>
 
        * sysdeps/hppa/configure.in: Moved to ...
index 1eb0f389c2488282b7373f69d6066922658cff73..89133295e147b00e6f5c0c70de52dc96cfaf325f 100644 (file)
@@ -1,3 +1,12 @@
+2013-11-21  Guy Martin  <gmsoft@tuxicoman.be>
+
+       * sysdeps/ia64/dl-lookupcfg.h: Remove obsolete
+       DL_DT_INIT_ADDRESS() and DL_DT_FINI_ADDRESS() macro and implement
+       DL_CALL_DT_INIT() as well as DL_CALL_DT_FINI().
+       Define DL_DT_FUNCTION_ADDRESS().
+       * sysdeps/ia64/dl-machine.h: Update ELF_MACHINE_START_ADDRESS()
+       to use DL_DT_FUNCTION_ADDRESS().
+
 2013-10-30  Mike Frysinger  <vapier@gentoo.org>
 
        * sysdeps/ia64/configure.in: Moved to ...
index f3125e5ec64d3c79f6263028f88bdbcabf2afd8f..feea320789fb544ce5fbe0403204ee619a79f569 100644 (file)
@@ -38,32 +38,36 @@ void _dl_unmap (struct link_map *map);
 
 #define DL_UNMAP(map) _dl_unmap (map)
 
-#define DL_AUTO_FUNCTION_ADDRESS(map, addr)                            \
-({                                                                     \
-  unsigned int fptr[2];                                                        \
-  fptr[0] = (unsigned int) (addr);                                     \
-  fptr[1] = (map)->l_info[DT_PLTGOT]->d_un.d_ptr;                      \
-  /* Set bit 30 to indicate to $$dyncall that this is a PLABEL. */     \
-  (ElfW(Addr))((unsigned int)fptr | 2);                                        \
-})
-
-#define DL_STATIC_FUNCTION_ADDRESS(map, addr)                          \
-({                                                                     \
-  static unsigned int fptr[2];                                         \
-  fptr[0] = (unsigned int) (addr);                                     \
-  fptr[1] = (map)->l_info[DT_PLTGOT]->d_un.d_ptr;                      \
-  /* Set bit 30 to indicate to $$dyncall that this is a PLABEL. */     \
-  (ElfW(Addr))((unsigned int)fptr | 2);                                        \
-})
-
-
-/* The test for "addr & 2" below is to accommodate old binaries which
-   violated the ELF ABI by pointing DT_INIT and DT_FINI at a function
-   descriptor.  */
-#define DL_DT_INIT_ADDRESS(map, addr) \
-  ((Elf32_Addr)(addr) & 2 ? (addr) : DL_AUTO_FUNCTION_ADDRESS (map, addr))
-#define DL_DT_FINI_ADDRESS(map, addr) \
-  ((Elf32_Addr)(addr) & 2 ? (addr) : DL_AUTO_FUNCTION_ADDRESS (map, addr))
+#define DL_DT_FUNCTION_ADDRESS(map, start, attr, addr)                 \
+  attr volatile unsigned int fptr[2];                                  \
+ /* The test for "start & 2" below is to accommodate old binaries which        \
+    violated the ELF ABI by pointing DT_INIT and DT_FINI at a function \
+    descriptor.  */                                                    \
+  if ((ElfW(Addr)) (start) & 2)                                                \
+    addr = (ElfW(Addr)) start;                                         \
+  else                                                                 \
+    {                                                                  \
+      fptr[0] = (unsigned int) (start);                                        \
+      fptr[1] = (map)->l_info[DT_PLTGOT]->d_un.d_ptr;                  \
+      /* Set bit 30 to indicate to $$dyncall that this is a PLABEL. */ \
+      addr = (ElfW(Addr))((unsigned int)fptr | 2);                     \
+    }                                                                  \
+
+#define DL_CALL_DT_INIT(map, start, argc, argv, env)   \
+{                                                      \
+  ElfW(Addr) addr;                                     \
+  DL_DT_FUNCTION_ADDRESS(map, start, , addr)           \
+  init_t init = (init_t) addr;                                 \
+  init (argc, argv, env);                              \
+}
+
+#define DL_CALL_DT_FINI(map, start)            \
+{                                              \
+  ElfW(Addr) addr;                             \
+  DL_DT_FUNCTION_ADDRESS(map, start, , addr)   \
+  fini_t fini = (fini_t) addr;                 \
+  fini ();                                     \
+}
 
 /* The type of the return value of fixup/profile_fixup */
 #define DL_FIXUP_VALUE_TYPE struct fdesc
index d2411a654a6949de741e3096a655d749c3fbacd7..e47e9473e1f4f09729cf4739ac3dc15920728099 100644 (file)
@@ -490,8 +490,12 @@ asm (                                                                      \
 #define ELF_MACHINE_NO_REL 1
 
 /* Return the address of the entry point. */
-#define ELF_MACHINE_START_ADDRESS(map, start) \
-  DL_STATIC_FUNCTION_ADDRESS (map, start)
+#define ELF_MACHINE_START_ADDRESS(map, start)                  \
+({                                                             \
+       ElfW(Addr) addr;                                        \
+       DL_DT_FUNCTION_ADDRESS(map, start, static, addr)        \
+       addr;                                                   \
+})
 
 /* We define an initialization functions.  This is called very early in
  *    _dl_sysdep_start.  */
index 4da12635c82a5929a429076e5188b4261c0539ea..cfaa2520b34977a9a9f62039b27cc46693c21868 100644 (file)
@@ -39,24 +39,28 @@ extern void _dl_unmap (struct link_map *map);
 
 #define DL_UNMAP(map) _dl_unmap (map)
 
-#define DL_AUTO_FUNCTION_ADDRESS(map, addr)            \
-({                                                     \
-  unsigned long int fptr[2];                           \
-  fptr[0] = (unsigned long int) (addr);                        \
-  fptr[1] = (map)->l_info[DT_PLTGOT]->d_un.d_ptr;      \
-  (Elf64_Addr) fptr;                                   \
-})
-
-#define DL_STATIC_FUNCTION_ADDRESS(map, addr)          \
-({                                                     \
-  static unsigned long int fptr[2];                    \
-  fptr[0] = (unsigned long int) (addr);                        \
-  fptr[1] = (map)->l_info[DT_PLTGOT]->d_un.d_ptr;      \
-  (Elf64_Addr) fptr;                                   \
-})
-
-#define DL_DT_INIT_ADDRESS(map, addr) DL_AUTO_FUNCTION_ADDRESS (map, addr)
-#define DL_DT_FINI_ADDRESS(map, addr) DL_AUTO_FUNCTION_ADDRESS (map, addr)
+#define DL_DT_FUNCTION_ADDRESS(map, start, attr, addr)                 \
+  attr volatile unsigned long int fptr[2];                                     \
+  fptr[0] = (unsigned long int) (start);                                       \
+  fptr[1] = (map)->l_info[DT_PLTGOT]->d_un.d_ptr;                      \
+  addr = (ElfW(Addr)) fptr;                                            \
+
+#define DL_CALL_DT_INIT(map, start, argc, argv, env)   \
+{                                                      \
+  ElfW(Addr) addr;                                     \
+  DL_DT_FUNCTION_ADDRESS(map, start, , addr)           \
+  init_t init = (init_t) addr;                                 \
+  init (argc, argv, env);                              \
+}
+
+#define DL_CALL_DT_FINI(map, start)            \
+{                                              \
+  ElfW(Addr) addr;                             \
+  DL_DT_FUNCTION_ADDRESS(map, start, , addr)   \
+  fini_t fini = (fini_t) addr;                 \
+  fini ();                                     \
+}
+
 /* The type of the return value of fixup/profile_fixup.  */
 #define DL_FIXUP_VALUE_TYPE struct fdesc
 /* Construct a value of type DL_FIXUP_VALUE_TYPE from a code address
index dd469d7a7354ef958b49746e2ebc7bdbf2589986..61236378fe37e05f8323be3175c935a795d698d5 100644 (file)
@@ -322,8 +322,12 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 #define ELF_MACHINE_NO_REL 1
 
 /* Return the address of the entry point. */
-#define ELF_MACHINE_START_ADDRESS(map, start)  \
-  DL_STATIC_FUNCTION_ADDRESS (map, start)
+#define ELF_MACHINE_START_ADDRESS(map, start)                  \
+({                                                             \
+       ElfW(Addr) addr;                                        \
+       DL_DT_FUNCTION_ADDRESS(map, start, static, addr)        \
+       addr;                                                   \
+})
 
 /* Fixup a PLT entry to bounce directly to the function at VALUE.  */
 static inline struct fdesc __attribute__ ((always_inline))
index e7b0516aaf5e3dc9d374c5f0c453c9f93cdd8712..146aca4dfb507fdd24aae5f19cee5e3306fe410a 100644 (file)
@@ -76,8 +76,9 @@ typedef struct link_map *lookup_t;
 # define DL_SYMBOL_ADDRESS(map, ref) \
  (void *) (LOOKUP_VALUE_ADDRESS (map) + ref->st_value)
 # define DL_LOOKUP_ADDRESS(addr) ((ElfW(Addr)) (addr))
-# define DL_DT_INIT_ADDRESS(map, start) (start)
-# define DL_DT_FINI_ADDRESS(map, start) (start)
+# define DL_CALL_DT_INIT(map, start, argc, argv, env) \
+ ((init_t) (start)) (argc, argv, env)
+# define DL_CALL_DT_FINI(map, start) ((fini_t) (start)) ()
 #endif
 
 /* On some architectures dladdr can't use st_size of all symbols this way.  */
This page took 0.124464 seconds and 5 git commands to generate.