137 lines
4.3 KiB
C++
137 lines
4.3 KiB
C++
|
/*
|
||
|
* 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());
|
||
|
}
|