From: Zhiting Zhu <zhiti...@cs.utexas.edu>
Committer: Waldemar Kozaczuk <jwkozac...@gmail.com>
Branch: master
Add dlsym tests
This patch includes a module called dl_tests which clones the bionic
and compile the needed library files.
Signed-off-by: Zhiting Zhu <zhiti...@cs.utexas.edu>
Message-Id: <20200110071641.110196-1-zhiti...@cs.utexas.edu>
---
diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -46,4 +46,6 @@ modules/httpserver-jvm-plugin/obj/
modules/libtools/*.so
modules/libtools/*.o
modules/libyaml/usr.manifest
+modules/dl_tests/bionic/
+modules/dl_tests/usr.manifest
.idea
diff --git a/modules/dl_tests/Makefile b/modules/dl_tests/Makefile
--- a/modules/dl_tests/Makefile
+++ b/modules/dl_tests/Makefile
@@ -0,0 +1,118 @@
+module: usr.manifest build_all
+
+src := $(OSV_BASE)
+out := $(OSV_BUILD_PATH)
+arch := $(ARCH)
+fs_type := $(fs_type)
+bionic_test_libs := $(src)/modules/dl_tests/bionic/tests/libs
+
+quiet = $(if $V, $1, @echo " $2"; $1)
+very-quiet = $(if $V, $1, @$1)
+makedir = $(call very-quiet, mkdir -p $(dir $@))
+
+autodepend = -MD -MT $@ -MP
+
+INCLUDES = -I$(src)/arch/$(ARCH) -I$(src) -I$(src)/include \
+ -I$(src)/arch/common -isystem $(src)/include/glibc-compat \
+ $(shell $(CXX) -E -xc++ - -v </dev/null 2>&1 | awk '/^End/ {exit}
/^ .*c\+\+/ {print "-isystem" $$0}') \
+ -isystem $(src)/include/api -isystem $(src)/include/api/$(ARCH) \
+ -isystem $(out)/gen/include
+
+COMMON = $(autodepend) $(INCLUDES) -g -O2 -fPIC -DBOOST_TEST_DYN_LINK \
+ -U _FORTIFY_SOURCE -D_KERNEL -D__OSV__ -DCONF_debug_memory=0 \
+ -Wall -Wno-pointer-arith -Wformat=0 -Wno-format-security
+
+LIBS =
+
+CXXFLAGS = -std=gnu++11 $(COMMON)
+CFLAGS = -std=gnu99 $(COMMON)
+
+tests := libtest_simple.so libtest_empty.so
libtest_dlsym_from_this_grandchild.so \
+ libtest_dlsym_from_this_child.so libtest_dlsym_from_this.so
libdlext_test.so \
+ libtest_with_dependency.so libtest_check_rtld_next_from_library.so
+
+.PHONY: get_file
+get_file:
+ if cd $(src)/modules/dl_tests/bionic; then \
+ git pull; \
+ else \
+ git clone --depth=1 https://android.googlesource.com/platform/bionic
$(src)/modules/dl_tests/bionic; \
+ fi
+
+all_tests := $(tests:%=dl_tests/%)
+
+build_all:
+ $(MAKE) get_file
+ $(MAKE) $(all_tests:%=$(out)/%)
+.PHONY: build_all
+
+$(out)/dl_tests/libtest_simple.so:
$(bionic_test_libs)/dlopen_testlib_simple.cpp
+ $(makedir)
+ $(call quiet, cd $(out); $(CXX) $(CXXFLAGS) -D__SHARED_OBJECT__=1 -shared
-o $@ $<, CXX dl_tests/libtest_simple.so)
+
+$(out)/dl_tests/libtest_empty.so: $(bionic_test_libs)/empty.cpp
+ $(makedir)
+ $(call quiet, cd $(out); $(CXX) $(CXXFLAGS) -D__SHARED_OBJECT__=1 -shared
-o $@ $<, CXX dl_tests/libtest_empty.so)
+
+$(out)/dl_tests/libtest_check_rtld_next_from_library.so:
$(bionic_test_libs)/check_rtld_next_from_library.cpp
+ $(makedir)
+ $(call quiet, cd $(out); $(CXX) $(CXXFLAGS) -D__SHARED_OBJECT__=1 -shared
-o $@ $<, CXX dl_tests/libtest_check_rtld_next_from_library.so)
+
+$(out)/dl_tests/libtest_dlsym_from_this_grandchild.so:
$(bionic_test_libs)/dlsym_from_this_symbol2.cpp
+ $(makedir)
+ $(call quiet, cd $(out); $(CXX) $(CXXFLAGS) -D__SHARED_OBJECT__=1 -shared
-o $@ $<, CXX dl_tests/libtest_dlsym_from_this_grandchild.so)
+
+$(out)/dl_tests/libtest_dlsym_from_this_child.so: COMMON +=
-Wl,--no-as-needed -ltest_dlsym_from_this_grandchild -L=$(out)/dl_tests
-L=/usr/lib -Wl,-rpath . -Wl,-rpath / -Wl,-rpath /usr/lib
+$(out)/dl_tests/libtest_dlsym_from_this_child.so: \
+ $(bionic_test_libs)/dlsym_from_this_functions.cpp
+ $(MAKE) $(out)/dl_tests/libtest_dlsym_from_this_grandchild.so
+ $(makedir)
+ $(call quiet, cd $(out); $(CXX) $(CXXFLAGS) -D__SHARED_OBJECT__=1 -shared
-o $@ $<, CXX dl_tests/libtest_dlsym_from_this_child.so)
+
+$(out)/dl_tests/libtest_dlsym_from_this.so: COMMON += -Wl,--no-as-needed
-ltest_dlsym_from_this_child -L=$(out)/dl_tests -L=/usr/lib -Wl,-rpath .
-Wl,-rpath / -Wl,-rpath /usr/lib
+$(out)/dl_tests/libtest_dlsym_from_this.so: \
+ $(bionic_test_libs)/dlsym_from_this_symbol.cpp
+ $(MAKE) $(out)/dl_tests/libtest_dlsym_from_this_child.so
+ $(makedir)
+ $(call quiet, cd $(out); $(CXX) $(CXXFLAGS) -D__SHARED_OBJECT__=1 -shared
-o $@ $<, CXX dl_tests/libtest_dlsym_from_this.so)
+
+$(out)/dl_tests/libdlext_test.so: COMMON += -Wl,-z,relro
-Wl,--no-as-needed -ltest_simple -L=$(out)/dl_tests -L=/usr/lib
-Wl,-rpath . -Wl,-rpath / -Wl,-rpath /usr/lib
+$(out)/dl_tests/libdlext_test.so: \
+ $(bionic_test_libs)/dlext_test_library.cpp
+ $(MAKE) $(out)/dl_tests/libtest_simple.so
+ $(makedir)
+ $(call quiet, cd $(out); $(CXX) $(CXXFLAGS) -D__SHARED_OBJECT__=1 -shared
-o $@ $<, CXX dl_tests/libdlext_test.so)
+
+$(out)/dl_tests/libtest_with_dependency.so: COMMON += -Wl,--no-as-needed
-ldlext_test -L=$(out)/dl_tests -L=/usr/lib -Wl,-rpath . -Wl,-rpath /
-Wl,-rpath /usr/lib
+$(out)/dl_tests/libtest_with_dependency.so: \
+ $(bionic_test_libs)/dlopen_testlib_simple.cpp
+ $(MAKE) $(out)/dl_tests/libdlext_test.so
+ $(makedir)
+ $(call quiet, cd $(out); $(CXX) $(CXXFLAGS) -D__SHARED_OBJECT__=1 -shared
-o $@ $<, CXX dl_tests/libtest_with_dependency.so)
+
+usr.manifest: build_all FORCE
+ @echo "/usr/lib/libtest_simple.so: ./dl_tests/libtest_simple.so" > $@
+ @echo "/usr/lib/libtest_empty.so: ./dl_tests/libtest_empty.so" >> $@
+
@echo "/usr/lib/libtest_dlsym_from_this_grandchild.so: ./dl_tests/libtest_dlsym_from_this_grandchild.so"
$@
+
@echo "/usr/lib/libtest_dlsym_from_this_child.so: ./dl_tests/libtest_dlsym_from_this_child.so"
$@
+
@echo "/usr/lib/libtest_dlsym_from_this.so: ./dl_tests/libtest_dlsym_from_this.so"
$@
+ @echo "/usr/lib/libdlext_test.so: ./dl_tests/libdlext_test.so" >> $@
+
@echo "/usr/lib/libtest_with_dependency.so: ./dl_tests/libtest_with_dependency.so"
$@
+
@echo "/usr/lib/libtest_check_rtld_next_from_library.so: ./dl_tests/libtest_check_rtld_next_from_library.so"
$@
+ @echo "/tests/libtest_simple.so: ./dl_tests/libtest_simple.so" >> $@
+ @echo "/tests/libtest_empty.so: ./dl_tests/libtest_empty.so" >> $@
+
@echo "/tests/libtest_dlsym_from_this_grandchild.so: ./dl_tests/libtest_dlsym_from_this_grandchild.so"
$@
+
@echo "/tests/libtest_dlsym_from_this_child.so: ./dl_tests/libtest_dlsym_from_this_child.so"
$@
+
@echo "/tests/libtest_dlsym_from_this.so: ./dl_tests/libtest_dlsym_from_this.so"
$@
+ @echo "/tests/libdlext_test.so: ./dl_tests/libdlext_test.so" >> $@
+
@echo "/tests/libtest_with_dependency.so: ./dl_tests/libtest_with_dependency.so"
$@
+
@echo "/tests/libtest_check_rtld_next_from_library.so: ./dl_tests/libtest_check_rtld_next_from_library.so"
$@
+.PHONY: FORCE
+FORCE:
+
+clean:
+ -rm -f usr.manifest
+
+ifneq ($(MAKECMDGOALS),clean)
+include $(shell test -d $(out)/dl_tests && find $(out)/dl_tests
-name '*.d')
+endif
diff --git a/modules/tests/Makefile b/modules/tests/Makefile
--- a/modules/tests/Makefile
+++ b/modules/tests/Makefile
@@ -147,6 +147,8 @@ $(out)/tests/tst-mmap.so: COMMON += -fuse-ld=bfd
$(out)/tests/tst-elf-permissions.so: COMMON += -fuse-ld=bfd
$(out)/tests/tst-tls.so: COMMON += -fuse-ld=bfd
+$(out)/tests/tst-dlfcn.so: COMMON += -rdynamic -ldl
+
$(out)/tests/tst-tls.so: \
$(src)/tests/tst-tls.cc \
$(out)/tests/libtls.so
diff --git a/modules/tests/module.py b/modules/tests/module.py
--- a/modules/tests/module.py
+++ b/modules/tests/module.py
@@ -1,3 +1,4 @@
from osv.modules import api
api.require('java-tests')
+api.require('dl_tests')
diff --git a/tests/tst-dlfcn.cc b/tests/tst-dlfcn.cc
--- a/tests/tst-dlfcn.cc
+++ b/tests/tst-dlfcn.cc
@@ -10,6 +10,16 @@
#include <dlfcn.h>
#include <boost/test/unit_test.hpp>
+namespace utf = boost::unit_test;
+
+const bool rtld_next = false;
+const bool deep_lookup = false;
+
+static bool called = false;
+extern "C" void DlSymTestFunction()
+{
+ called = true;
+}
BOOST_AUTO_TEST_CASE(test_dlopen_with_null_as_filename)
{
@@ -53,3 +63,238 @@ BOOST_AUTO_TEST_CASE(test_dladdr)
BOOST_CHECK_EQUAL("vfprintf", info.dli_sname);
BOOST_CHECK_EQUAL(vfprintf, info.dli_saddr);
}
+
+BOOST_AUTO_TEST_CASE(test_dlsym_in_executable)
+{
+ dlerror();
+ void* self = dlopen(NULL, RTLD_NOW);
+ BOOST_REQUIRE_NE(self, nullptr);
+ BOOST_REQUIRE_EQUAL(dlerror(), nullptr);
+
+ void* sym = dlsym(self, "DlSymTestFunction");
+ BOOST_REQUIRE_NE(sym, nullptr);
+
+ void (*function)() = reinterpret_cast<void(*)()>(sym);
+
+ called = false;
+ function();
+ BOOST_REQUIRE_EQUAL(called, true);
+ BOOST_CHECK_EQUAL(0, dlclose(self));
+}
+
+BOOST_AUTO_TEST_CASE(test_dlsym_from_sofile,
+ *utf::enable_if<rtld_next>())
+{
+ dlerror();
+ void* handle = dlopen("/tests/libtest_dlsym_from_this.so", RTLD_LAZY |
RTLD_LOCAL);
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE_NE(handle, nullptr);
+
+ // check that we can't find '_test_dlsym_symbol' via
dlsym(RTLD_DEFAULT)
+ void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol");
+ (void)symbol;
+ // TODO: dlopen ignores all the flags; the current implementation
assumes the flag to be RTLD_GLOBAL but the default should be RTLD_LOCAL
+ // Should reenable the test after flags are implemented
+ // BOOST_REQUIRE_EQUAL(symbol, nullptr);
+ // auto err_msg = std::string(dlerror());
+ // BOOST_TEST_CONTEXT(err_msg)
+ // BOOST_REQUIRE_NE(err_msg.find("dlsym: symbol test_dlsym_symbol not
found"),
+ // std::string::npos);
+ // BOOST_REQUIRE_NE(err_msg.find("undefined symbol:
test_dlsym_symbol"),
+ // std::string::npos);
+
+ typedef int* (*fn_t)();
+ fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT =
+
reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT"));
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE_NE(lookup_dlsym_symbol_using_RTLD_DEFAULT, nullptr);
+
+ int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT();
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE_NE(ptr, nullptr);
+ BOOST_REQUIRE_EQUAL(42, *ptr);
+
+ fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT =
+
reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT"));
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr);
+
+ ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT();
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(ptr != nullptr);
+ BOOST_REQUIRE_EQUAL(44, *ptr);
+
+ fn_t lookup_dlsym_symbol_using_RTLD_NEXT =
+
reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT"));
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr);
+
+ ptr = lookup_dlsym_symbol_using_RTLD_NEXT();
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(ptr != nullptr);
+ BOOST_REQUIRE_EQUAL(43, *ptr);
+
+ dlclose(handle);
+}
+
+BOOST_AUTO_TEST_CASE(test_dlsym_from_sofile_with_preload,
+ *utf::enable_if<deep_lookup>())
+{
+ void* preload = dlopen("/tests/libtest_dlsym_from_this_grandchild.so",
RTLD_NOW | RTLD_LOCAL);
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(preload != nullptr);
+
+ void* handle = dlopen("/tests/libtest_dlsym_from_this.so", RTLD_NOW |
RTLD_LOCAL);
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(handle != nullptr);
+
+ // check that we can't find '_test_dlsym_symbol' via
dlsym(RTLD_DEFAULT)
+ void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol");
+ (void)symbol;
+ // TODO: dlopen ignores all the flags; the current implementation
assumes the flag to be RTLD_GLOBAL but the default should be RTLD_LOCAL
+ // Should reenable the test after flags are implemented
+ // BOOST_REQUIRE_EQUAL(symbol, nullptr);
+ // auto err_msg = std::string(dlerror());
+ // BOOST_TEST_CONTEXT(err_msg)
+ // BOOST_REQUIRE_NE(err_msg.find("dlsym: symbol test_dlsym_symbol not
found"),
+ // std::string::npos);
+ // BOOST_REQUIRE_NE(err_msg.find("undefined symbol:
test_dlsym_symbol"),
+ // std::string::npos);
+
+ typedef int* (*fn_t)();
+ fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT =
+
reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT"));
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr);
+
+ int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT();
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(ptr != nullptr);
+ BOOST_REQUIRE_EQUAL(42, *ptr);
+
+ fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT =
+
reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT"));
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr);
+
+ ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT();
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE_NE(ptr, nullptr);
+ BOOST_REQUIRE_EQUAL(44, *ptr);
+
+ fn_t lookup_dlsym_symbol_using_RTLD_NEXT =
+
reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT"));
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr);
+
+ ptr = lookup_dlsym_symbol_using_RTLD_NEXT();
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(ptr != nullptr);
+ BOOST_REQUIRE_EQUAL(43, *ptr);
+
+ dlclose(handle);
+ dlclose(preload);
+}
+
+BOOST_AUTO_TEST_CASE(dlsym_handle_global_sym)
+{
+ // check that we do not look into global group
+ // when looking up symbol by handle
+ void* handle = dlopen("/tests/libtest_empty.so", RTLD_NOW);
+ dlopen("libtest_with_dependency.so", RTLD_NOW | RTLD_GLOBAL);
+ void* sym = dlsym(handle, "getRandomNumber");
+ BOOST_REQUIRE(sym == nullptr);
+ auto err_msg = std::string(dlerror());
+ BOOST_TEST_CONTEXT(err_msg)
+ BOOST_REQUIRE_NE(err_msg.find("dlsym: symbol getRandomNumber not
found"),
+ std::string::npos);
+ // BOOST_REQUIRE_NE(err_msg.find("undefined symbol: getRandomNumber"),
+ // std::string::npos);
+
+ sym = dlsym(handle, "DlSymTestFunction");
+ BOOST_REQUIRE(sym == nullptr);
+ err_msg = std::string(dlerror());
+ BOOST_TEST_CONTEXT(err_msg)
+ BOOST_REQUIRE_NE(err_msg.find("dlsym: symbol DlSymTestFunction not
found"),
+ std::string::npos);
+ // BOOST_REQUIRE_NE(err_msg.find("undefined symbol:
DlSymTestFunction"),
+ // std::string::npos);
+ dlclose(handle);
+}
+
+BOOST_AUTO_TEST_CASE(dlsym_handle_empty_symbol)
+{
+ // check that dlsym of an empty symbol fails (see http://b/33530622)
+ void* handle = dlopen("/tests/libtest_dlsym_from_this.so", RTLD_NOW);
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(handle != nullptr);
+ void* sym = dlsym(handle, "");
+ BOOST_REQUIRE(sym == nullptr);
+ auto err_msg = std::string(dlerror());
+ BOOST_TEST_CONTEXT(err_msg)
+ BOOST_REQUIRE_NE(err_msg.find("dlsym: symbol not found"),
+ std::string::npos);
+ // BOOST_REQUIRE_NE(err_msg.find("undefined symbol: "),
+ // std::string::npos);
+ dlclose(handle);
+}
+
+BOOST_AUTO_TEST_CASE(dlsym_with_dependencies,
+ *utf::enable_if<deep_lookup>())
+{
+ void* handle = dlopen("/tests/libtest_with_dependency.so", RTLD_NOW);
+ BOOST_REQUIRE(handle != nullptr);
+ dlerror();
+ // This symbol is in DT_NEEDED library.
+ void* sym = dlsym(handle, "getRandomNumber");
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE_NE(sym, nullptr);
+ int (*fn)(void);
+ fn = reinterpret_cast<int (*)(void)>(sym);
+ BOOST_CHECK_EQUAL(4, fn());
+ dlclose(handle);
+}
+
+BOOST_AUTO_TEST_CASE(rtld_default_unknown_symbol)
+{
+ void* addr = dlsym(RTLD_DEFAULT, "UNKNOWN");
+ BOOST_REQUIRE_EQUAL(addr, nullptr);
+}
+
+BOOST_AUTO_TEST_CASE(rtld_default_fclose)
+{
+ void* addr = dlsym(RTLD_DEFAULT, "fclose");
+ BOOST_REQUIRE_NE(addr, nullptr);
+}
+
+BOOST_AUTO_TEST_CASE(rtld_next_unknown_symbol,
+ *utf::enable_if<rtld_next>())
+{
+ void* addr = dlsym(RTLD_NEXT, "UNKNOWN");
+ BOOST_REQUIRE_EQUAL(addr, nullptr);
+}
+
+BOOST_AUTO_TEST_CASE(rtld_next_fclose,
+ *utf::enable_if<rtld_next>())
+{
+ void* addr = dlsym(RTLD_NEXT, "fclose");
+ BOOST_REQUIRE_NE(addr, nullptr);
+}
+
+BOOST_AUTO_TEST_CASE(rtld_next_from_lib, *utf::enable_if<rtld_next>())
+{
+ void* library_with_fclose =
dlopen("/tests/libtest_check_rtld_next_from_library.so", RTLD_NOW |
RTLD_GLOBAL);
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(library_with_fclose != nullptr);
+ void* expected_addr = dlsym(RTLD_DEFAULT, "fclose");
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(expected_addr != nullptr);
+ typedef void* (*get_libc_fclose_ptr_fn_t)();
+ get_libc_fclose_ptr_fn_t get_libc_fclose_ptr =
+
reinterpret_cast<get_libc_fclose_ptr_fn_t>(dlsym(library_with_fclose, "get_libc_fclose_ptr"));
+ BOOST_TEST_CONTEXT(dlerror())
+ BOOST_REQUIRE(get_libc_fclose_ptr != nullptr);
+ BOOST_REQUIRE_EQUAL(expected_addr, get_libc_fclose_ptr());
+
+ dlclose(library_with_fclose);
+}
--
You received this message because you are subscribed to the Google Groups "OSv
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to osv-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/osv-dev/000000000000b41f63059be09e0a%40google.com.