about summary refs log tree commit diff
path: root/ports
diff options
context:
space:
mode:
authorGuy Martin <gmsoft@tuxicoman.be>2013-11-21 13:23:16 -0500
committerCarlos O'Donell <carlos@redhat.com>2013-11-21 15:52:31 -0500
commitdaf75146de07303ea0c5ad700ec5ef703ec114a1 (patch)
treeed307e39a90288cbcdf727a7c07addb9f38f65d8 /ports
parentd33cafadfe365befa4ca6e0463fa926d56144046 (diff)
downloadglibc-daf75146de07303ea0c5ad700ec5ef703ec114a1.tar.gz
glibc-daf75146de07303ea0c5ad700ec5ef703ec114a1.tar.xz
glibc-daf75146de07303ea0c5ad700ec5ef703ec114a1.zip
Don't use broken DL_AUTO_FUNCTION_ADDRESS()
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.
Diffstat (limited to 'ports')
-rw-r--r--ports/ChangeLog.hppa9
-rw-r--r--ports/ChangeLog.ia649
-rw-r--r--ports/sysdeps/hppa/dl-lookupcfg.h56
-rw-r--r--ports/sysdeps/hppa/dl-machine.h8
-rw-r--r--ports/sysdeps/ia64/dl-lookupcfg.h40
-rw-r--r--ports/sysdeps/ia64/dl-machine.h8
6 files changed, 82 insertions, 48 deletions
diff --git a/ports/ChangeLog.hppa b/ports/ChangeLog.hppa
index b7c82131d9..82df2cec89 100644
--- a/ports/ChangeLog.hppa
+++ b/ports/ChangeLog.hppa
@@ -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 ...
diff --git a/ports/ChangeLog.ia64 b/ports/ChangeLog.ia64
index 1eb0f389c2..89133295e1 100644
--- a/ports/ChangeLog.ia64
+++ b/ports/ChangeLog.ia64
@@ -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 ...
diff --git a/ports/sysdeps/hppa/dl-lookupcfg.h b/ports/sysdeps/hppa/dl-lookupcfg.h
index f3125e5ec6..feea320789 100644
--- a/ports/sysdeps/hppa/dl-lookupcfg.h
+++ b/ports/sysdeps/hppa/dl-lookupcfg.h
@@ -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
diff --git a/ports/sysdeps/hppa/dl-machine.h b/ports/sysdeps/hppa/dl-machine.h
index d2411a654a..e47e9473e1 100644
--- a/ports/sysdeps/hppa/dl-machine.h
+++ b/ports/sysdeps/hppa/dl-machine.h
@@ -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.  */
diff --git a/ports/sysdeps/ia64/dl-lookupcfg.h b/ports/sysdeps/ia64/dl-lookupcfg.h
index 4da12635c8..cfaa2520b3 100644
--- a/ports/sysdeps/ia64/dl-lookupcfg.h
+++ b/ports/sysdeps/ia64/dl-lookupcfg.h
@@ -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
diff --git a/ports/sysdeps/ia64/dl-machine.h b/ports/sysdeps/ia64/dl-machine.h
index dd469d7a73..61236378fe 100644
--- a/ports/sysdeps/ia64/dl-machine.h
+++ b/ports/sysdeps/ia64/dl-machine.h
@@ -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))