diff options
author | Torne (Richard Coles) <torne@google.com> | 2014-04-22 10:33:33 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-04-22 10:33:34 +0000 |
commit | c363e5dd0a15aac9036b453f655a3a0ae5cd32cd (patch) | |
tree | 385627eccdd2c853f1f571902d27a55ebfb23675 /tests | |
parent | 16f6429c38c24236418cf127a4c11c5d8a2fd47b (diff) | |
parent | 12bbb9164578b6512b8b07a3fb093858244b7c7b (diff) | |
download | bionic-c363e5dd0a15aac9036b453f655a3a0ae5cd32cd.zip bionic-c363e5dd0a15aac9036b453f655a3a0ae5cd32cd.tar.gz bionic-c363e5dd0a15aac9036b453f655a3a0ae5cd32cd.tar.bz2 |
Merge "Support loading libraries to a reserved address."
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Android.mk | 13 | ||||
-rw-r--r-- | tests/dlext_test.cpp | 136 | ||||
-rw-r--r-- | tests/dlext_test_library.cpp | 43 |
3 files changed, 192 insertions, 0 deletions
diff --git a/tests/Android.mk b/tests/Android.mk index 723d7cf..d2bcce8 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -190,6 +190,18 @@ include $(LOCAL_PATH)/Android.build.mk endif # ----------------------------------------------------------------------------- +# Library used by dlext tests. +# ----------------------------------------------------------------------------- +libdlext_test_src_files := \ + dlext_test_library.cpp \ + +module := libdlext_test +module_tag := optional +build_type := target +build_target := SHARED_LIBRARY +include $(LOCAL_PATH)/Android.build.mk + +# ----------------------------------------------------------------------------- # Tests for the device using bionic's .so. Run with: # adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests # ----------------------------------------------------------------------------- @@ -197,6 +209,7 @@ bionic-unit-tests_whole_static_libraries := \ libBionicTests \ bionic-unit-tests_src_files := \ + dlext_test.cpp \ dlfcn_test.cpp \ bionic-unit-tests_ldflags := \ diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp new file mode 100644 index 0000000..299b408 --- /dev/null +++ b/tests/dlext_test.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <dlfcn.h> +#include <android/dlext.h> +#include <sys/mman.h> + + +#define ASSERT_DL_NOTNULL(ptr) \ + ASSERT_TRUE(ptr != NULL) << "dlerror: " << dlerror() + +#define ASSERT_DL_ZERO(i) \ + ASSERT_EQ(0, i) << "dlerror: " << dlerror() + + +typedef int (*fn)(void); +#define LIBNAME "libdlext_test.so" +#define LIBSIZE 1024*1024 // how much address space to reserve for it + + +class DlExtTest : public ::testing::Test { +protected: + virtual void SetUp() { + handle_ = NULL; + // verify that we don't have the library loaded already + ASSERT_EQ(NULL, dlsym(RTLD_DEFAULT, "getRandomNumber")); + // call dlerror() to swallow the error, and check it was the one we wanted + ASSERT_STREQ("undefined symbol: getRandomNumber", dlerror()); + } + + virtual void TearDown() { + if (handle_ != NULL) { + ASSERT_DL_ZERO(dlclose(handle_)); + } + } + + void* handle_; +}; + +TEST_F(DlExtTest, ExtInfoNull) { + handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, NULL); + ASSERT_DL_NOTNULL(handle_); + fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber")); + ASSERT_DL_NOTNULL(f); + EXPECT_EQ(4, f()); +} + +TEST_F(DlExtTest, ExtInfoNoFlags) { + android_dlextinfo extinfo; + extinfo.flags = 0; + handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo); + ASSERT_DL_NOTNULL(handle_); + fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber")); + ASSERT_DL_NOTNULL(f); + EXPECT_EQ(4, f()); +} + +TEST_F(DlExtTest, Reserved) { + void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + ASSERT_TRUE(start != MAP_FAILED); + android_dlextinfo extinfo; + extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS; + extinfo.reserved_addr = start; + extinfo.reserved_size = LIBSIZE; + handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo); + ASSERT_DL_NOTNULL(handle_); + fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber")); + ASSERT_DL_NOTNULL(f); + EXPECT_GE(f, start); + EXPECT_LT(reinterpret_cast<void*>(f), + reinterpret_cast<char*>(start) + LIBSIZE); + EXPECT_EQ(4, f()); +} + +TEST_F(DlExtTest, ReservedTooSmall) { + void* start = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + ASSERT_TRUE(start != MAP_FAILED); + android_dlextinfo extinfo; + extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS; + extinfo.reserved_addr = start; + extinfo.reserved_size = PAGE_SIZE; + handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo); + EXPECT_EQ(NULL, handle_); +} + +TEST_F(DlExtTest, ReservedHint) { + void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + ASSERT_TRUE(start != MAP_FAILED); + android_dlextinfo extinfo; + extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT; + extinfo.reserved_addr = start; + extinfo.reserved_size = LIBSIZE; + handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo); + ASSERT_DL_NOTNULL(handle_); + fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber")); + ASSERT_DL_NOTNULL(f); + EXPECT_GE(f, start); + EXPECT_LT(reinterpret_cast<void*>(f), + reinterpret_cast<char*>(start) + LIBSIZE); + EXPECT_EQ(4, f()); +} + +TEST_F(DlExtTest, ReservedHintTooSmall) { + void* start = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + ASSERT_TRUE(start != MAP_FAILED); + android_dlextinfo extinfo; + extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT; + extinfo.reserved_addr = start; + extinfo.reserved_size = PAGE_SIZE; + handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo); + ASSERT_DL_NOTNULL(handle_); + fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber")); + ASSERT_DL_NOTNULL(f); + EXPECT_TRUE(f < start || (reinterpret_cast<void*>(f) >= + reinterpret_cast<char*>(start) + PAGE_SIZE)); + EXPECT_EQ(4, f()); +} diff --git a/tests/dlext_test_library.cpp b/tests/dlext_test_library.cpp new file mode 100644 index 0000000..5c04329 --- /dev/null +++ b/tests/dlext_test_library.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { +public: + virtual int getRandomNumber() { + return 4; // chosen by fair dice roll. + // guaranteed to be random. + } + + virtual ~A() {} +}; + +A a; + +// nested macros to make it easy to define a large amount of read-only data +// which will require relocation. +#define A_16 &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, +#define A_128 A_16 A_16 A_16 A_16 A_16 A_16 A_16 A_16 +#define A_1024 A_128 A_128 A_128 A_128 A_128 A_128 A_128 A_128 + +extern "C" A* const lots_of_relro[] = { + A_1024 A_1024 A_1024 A_1024 A_1024 A_1024 A_1024 A_1024 +}; + +extern "C" int getRandomNumber() { + // access the relro section (twice, in fact, once for the pointer, and once + // for the vtable of A) to check it's actually there. + return lots_of_relro[0]->getRandomNumber(); +} |