Pass argc/argv/envp to dso constructors

The glibc implementation of the loader passes argc/argv/envp
to all elf constructors. This change makes bionic linker
behave in the same way.

Bug: http://b/30145768
Change-Id: I1c65c42aa5305a5b133c64b5748205bbde869e0e
Test: run bionic-unit-tests --gtest_filter=dl*:Dl*
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 56df1a6..5bf5861 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -38,15 +38,24 @@
 }
 
 static int g_ctor_function_called = 0;
+static int g_ctor_argc = 0;
+static char** g_ctor_argv = reinterpret_cast<char**>(0xDEADBEEF);
+static char** g_ctor_envp = g_ctor_envp;
 
-extern "C" void ctor_function() __attribute__ ((constructor));
+extern "C" void ctor_function(int argc, char** argv, char** envp) __attribute__ ((constructor));
 
-extern "C" void ctor_function() {
+extern "C" void ctor_function(int argc, char** argv, char** envp) {
   g_ctor_function_called = 17;
+  g_ctor_argc = argc;
+  g_ctor_argv = argv;
+  g_ctor_envp = envp;
 }
 
 TEST(dlfcn, ctor_function_call) {
   ASSERT_EQ(17, g_ctor_function_called);
+  ASSERT_TRUE(g_ctor_argc = get_argc());
+  ASSERT_TRUE(g_ctor_argv = get_argv());
+  ASSERT_TRUE(g_ctor_envp = get_envp());
 }
 
 TEST(dlfcn, dlsym_in_executable) {
diff --git a/tests/gtest_main.cpp b/tests/gtest_main.cpp
index 2b58646..a08a2e1 100644
--- a/tests/gtest_main.cpp
+++ b/tests/gtest_main.cpp
@@ -47,11 +47,26 @@
 #endif
 
 static std::string g_executable_path;
+static int g_argc;
+static char** g_argv;
+static char** g_envp;
 
 const std::string& get_executable_path() {
   return g_executable_path;
 }
 
+int get_argc() {
+  return g_argc;
+}
+
+char** get_argv() {
+  return g_argv;
+}
+
+char** get_envp() {
+  return g_envp;
+}
+
 namespace testing {
 namespace internal {
 
@@ -1122,8 +1137,11 @@
   return std::string(path, path_len);
 }
 
-int main(int argc, char** argv) {
+int main(int argc, char** argv, char** envp) {
   g_executable_path = get_proc_self_exe();
+  g_argc = argc;
+  g_argv = argv;
+  g_envp = envp;
   std::vector<char*> arg_list;
   for (int i = 0; i < argc; ++i) {
     arg_list.push_back(argv[i]);
diff --git a/tests/utils.h b/tests/utils.h
index f8e0039..08e8cea 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -122,4 +122,9 @@
 // The absolute path to the executable
 const std::string& get_executable_path();
 
+// Access to argc/argv/envp
+int get_argc();
+char** get_argv();
+char** get_envp();
+
 #endif