]> git.ipfire.org Git - thirdparty/libbsd.git/commitdiff
Force setproctitle() into .init_array section
authorGuillem Jover <guillem@hadrons.org>
Wed, 29 May 2013 00:23:56 +0000 (02:23 +0200)
committerGuillem Jover <guillem@hadrons.org>
Sat, 8 Jun 2013 16:09:29 +0000 (18:09 +0200)
The GNU .init_array support is an extension over the standard System V
ABI .init_array support, which passes the main() arguments to the init
function.

This support comes in three parts. First the dynamic linker (from glibc)
needs to support it. Then function pointers need to be placed in the
section, for example by using __attribute__((constructor)), that the
compiler (gcc or clang for example) might place in section .ctors and
the linker (from binutils) will move to .init_array on the output
object, or by placing them directly into .init_array by the compiler
when compiling. If this does not happen and the function pointers end
up in .ctors, then they will not get passed the main() arguments, which
we do really need in this case.

But this relies on recent binutils or gcc having native .init_array
support, and not having it disabled through --disable-initfini-array.

To guarantee we get the correct behaviour, let's just place the function
pointer in the .init_array section directly, so we only require a recent
enough glibc.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=65029
configure.ac
src/setproctitle.c

index bdadc6efe8c35e769954aa023a171db967a59901..e63ebfec8f397045f427b89d778de9d9c280f937 100644 (file)
@@ -53,6 +53,51 @@ AC_CHECK_DECL([F_CLOSEM],
               [#include <limits.h>
                #include <fcntl.h>])
 
+AC_CACHE_CHECK(
+       [for GNU .init_array section support],
+       [libbsd_cv_gnu_init_array_support],
+       [AC_RUN_IFELSE(
+               [AC_LANG_SOURCE(
+[[
+static int rc = 1;
+static void init(int argc) { if (argc == 1) rc = 0; }
+void (*init_func)(int argc) __attribute__((section(".init_array"))) = init;
+int main() { return rc; }
+]]
+               )],
+               [libbsd_cv_gnu_init_array_support=yes],
+               [libbsd_cv_gnu_init_array_support=no],
+               [AC_PREPROC_IFELSE(
+                       [AC_LANG_SOURCE(
+[[
+/* Look for a known libc that supports .init_array with the GNU extension
+ * to pass main() arguments to the init functions. */
+#include <stdlib.h>
+#if defined __GLIBC_PREREQ
+#  if __GLIBC_PREREQ(2, 4)
+/* glibc supports GNU .init_array since 2.4. */
+#  else
+#    error glibc does not support GNU .init_array
+#  endif
+#else
+/*
+ * Basic SysV ABI .init_array support, init functions do not get arguments:
+ * - Bionic since its inception.
+ * - uClibc since 0.9.29.
+ */
+#  error unknown whether libc supports GNU .init_array
+#endif
+]]
+                       )],
+                       [libbsd_cv_gnu_init_array_support=yes],
+                       [libbsd_cv_gnu_init_array_support=no])
+               ]
+       )]
+)
+if test "$libbsd_cv_gnu_init_array_support" = no; then
+       AC_MSG_ERROR([missing required GNU .init_array section support])
+fi
+
 # Checks for library functions.
 AC_MSG_CHECKING([for program_invocation_short_name])
 AC_LINK_IFELSE(
index 60b64843005a72fe36ad421b6220be1ea6086dcb..2137190b6023cc8733da7d1638efbae4564d31c3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2010 William Ahern
- * Copyright © 2012 Guillem Jover <guillem@hadrons.org>
+ * Copyright © 2012-2013 Guillem Jover <guillem@hadrons.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the
@@ -129,7 +129,7 @@ spt_copyargs(int argc, char *argv[])
        return 0;
 }
 
-static void __attribute__((constructor))
+static void
 spt_init(int argc, char *argv[], char *envp[])
 {
        char *base, *end, *nul, *tmp;
@@ -186,6 +186,14 @@ spt_init(int argc, char *argv[], char *envp[])
        SPT.end  = end;
 }
 
+/*
+ * Force spt_init() function into the .init_array section instead of expecting
+ * either the compiler to place constructors there or the linker to move them
+ * from .ctors to .init_array.
+ */
+void (*spt_init_func)(int argc, char *argv[], char *envp[])
+       __attribute__((section(".init_array"))) = spt_init;
+
 #ifndef SPT_MAXTITLE
 #define SPT_MAXTITLE 255
 #endif