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