dlext_test.cpp revision 12bbb9164578b6512b8b07a3fb093858244b7c7b
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
19#include <dlfcn.h>
20#include <android/dlext.h>
21#include <sys/mman.h>
22
23
24#define ASSERT_DL_NOTNULL(ptr) \
25    ASSERT_TRUE(ptr != NULL) << "dlerror: " << dlerror()
26
27#define ASSERT_DL_ZERO(i) \
28    ASSERT_EQ(0, i) << "dlerror: " << dlerror()
29
30
31typedef int (*fn)(void);
32#define LIBNAME "libdlext_test.so"
33#define LIBSIZE 1024*1024 // how much address space to reserve for it
34
35
36class DlExtTest : public ::testing::Test {
37protected:
38  virtual void SetUp() {
39    handle_ = NULL;
40    // verify that we don't have the library loaded already
41    ASSERT_EQ(NULL, dlsym(RTLD_DEFAULT, "getRandomNumber"));
42    // call dlerror() to swallow the error, and check it was the one we wanted
43    ASSERT_STREQ("undefined symbol: getRandomNumber", dlerror());
44  }
45
46  virtual void TearDown() {
47    if (handle_ != NULL) {
48      ASSERT_DL_ZERO(dlclose(handle_));
49    }
50  }
51
52  void* handle_;
53};
54
55TEST_F(DlExtTest, ExtInfoNull) {
56  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, NULL);
57  ASSERT_DL_NOTNULL(handle_);
58  fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
59  ASSERT_DL_NOTNULL(f);
60  EXPECT_EQ(4, f());
61}
62
63TEST_F(DlExtTest, ExtInfoNoFlags) {
64  android_dlextinfo extinfo;
65  extinfo.flags = 0;
66  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
67  ASSERT_DL_NOTNULL(handle_);
68  fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
69  ASSERT_DL_NOTNULL(f);
70  EXPECT_EQ(4, f());
71}
72
73TEST_F(DlExtTest, Reserved) {
74  void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
75                     -1, 0);
76  ASSERT_TRUE(start != MAP_FAILED);
77  android_dlextinfo extinfo;
78  extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
79  extinfo.reserved_addr = start;
80  extinfo.reserved_size = LIBSIZE;
81  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
82  ASSERT_DL_NOTNULL(handle_);
83  fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
84  ASSERT_DL_NOTNULL(f);
85  EXPECT_GE(f, start);
86  EXPECT_LT(reinterpret_cast<void*>(f),
87            reinterpret_cast<char*>(start) + LIBSIZE);
88  EXPECT_EQ(4, f());
89}
90
91TEST_F(DlExtTest, ReservedTooSmall) {
92  void* start = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
93                     -1, 0);
94  ASSERT_TRUE(start != MAP_FAILED);
95  android_dlextinfo extinfo;
96  extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
97  extinfo.reserved_addr = start;
98  extinfo.reserved_size = PAGE_SIZE;
99  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
100  EXPECT_EQ(NULL, handle_);
101}
102
103TEST_F(DlExtTest, ReservedHint) {
104  void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
105                     -1, 0);
106  ASSERT_TRUE(start != MAP_FAILED);
107  android_dlextinfo extinfo;
108  extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
109  extinfo.reserved_addr = start;
110  extinfo.reserved_size = LIBSIZE;
111  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
112  ASSERT_DL_NOTNULL(handle_);
113  fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
114  ASSERT_DL_NOTNULL(f);
115  EXPECT_GE(f, start);
116  EXPECT_LT(reinterpret_cast<void*>(f),
117            reinterpret_cast<char*>(start) + LIBSIZE);
118  EXPECT_EQ(4, f());
119}
120
121TEST_F(DlExtTest, ReservedHintTooSmall) {
122  void* start = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
123                     -1, 0);
124  ASSERT_TRUE(start != MAP_FAILED);
125  android_dlextinfo extinfo;
126  extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
127  extinfo.reserved_addr = start;
128  extinfo.reserved_size = PAGE_SIZE;
129  handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
130  ASSERT_DL_NOTNULL(handle_);
131  fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
132  ASSERT_DL_NOTNULL(f);
133  EXPECT_TRUE(f < start || (reinterpret_cast<void*>(f) >=
134                            reinterpret_cast<char*>(start) + PAGE_SIZE));
135  EXPECT_EQ(4, f());
136}
137