From 904b52296ede599a9fe40cc7515f3d4545e8233e Mon Sep 17 00:00:00 2001
From: Guillem Jover <guillem@hadrons.org>
Date: Wed, 1 Jul 2015 19:38:36 +0200
Subject: [PATCH] support .init_array with GNU extension to pass main()
 arguments

This is required to be able to implement some system functions outside
of libc, for example setproctitle(3).
---
 src/env/__libc_start_main.c | 12 +++++++-----
 src/internal/vis.h          |  2 +-
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c
index f6f3b14..459d360 100644
--- a/src/env/__libc_start_main.c
+++ b/src/env/__libc_start_main.c
@@ -11,8 +11,10 @@ void __init_tls(size_t *);
 #ifndef SHARED
 static void dummy() {}
 weak_alias(dummy, _init);
-extern void (*const __init_array_start)() __attribute__((weak));
-extern void (*const __init_array_end)() __attribute__((weak));
+extern void (*const __init_array_start[])(int, char **, char **)
+	__attribute__((weak));
+extern void (*const __init_array_end[])(int, char **, char **)
+	__attribute__((weak));
 #endif
 
 static void dummy1(void *p) {}
@@ -64,9 +66,9 @@ int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv)
 #ifndef SHARED
 	__init_libc(envp, argv[0]);
 	_init();
-	uintptr_t a = (uintptr_t)&__init_array_start;
-	for (; a<(uintptr_t)&__init_array_end; a+=sizeof(void(*)()))
-		(*(void (**)())a)();
+	const size_t array_size = __init_array_end - __init_array_start;
+	for (size_t i = 0; i < array_size; i++)
+		(*__init_array_start[i])(argc, argv, envp);
 #endif
 
 	/* Pass control to the application */
diff --git a/src/internal/vis.h b/src/internal/vis.h
index a01fda1..43a86c7 100644
--- a/src/internal/vis.h
+++ b/src/internal/vis.h
@@ -28,7 +28,7 @@ extern char *optarg, **environ, **__environ, *tzname[2], *__tzname[2], *__progna
  * everything hidden except possibly-undefined weak references. */
 
 __attribute__((__visibility__("default")))
-extern void (*const __init_array_start)(), (*const __init_array_end)(),
+extern void (*const __init_array_start[])(), (*const __init_array_end[])(),
 	(*const __fini_array_start)(), (*const __fini_array_end)();
 
 #pragma GCC visibility push(hidden)
-- 
2.4.3.573.g4eafbef

