1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // A crazy linker test to:
6 // - Load a library (libfoo.so) with the linker.
7 // - Find the address of the "Foo" function in it.
8 // - Call the function.
9 // - Close the library.
10
11 #include <crazy_linker.h>
12
13 #include <stdarg.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <time.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19
Panic(const char * fmt,...)20 static void Panic(const char* fmt, ...) {
21 va_list args;
22 fprintf(stderr, "PANIC: ");
23 va_start(args, fmt);
24 vfprintf(stderr, fmt, args);
25 va_end(args);
26 exit(1);
27 }
28
now_ms()29 static double now_ms() {
30 struct timespec ts;
31 clock_gettime(CLOCK_MONOTONIC, &ts);
32 return (ts.tv_sec * 1000.) + (ts.tv_nsec / 1000000.);
33 }
34
drop_caches()35 static void drop_caches() {
36 int fd = open("/proc/sys/vm/drop_caches", O_RDWR);
37 if (fd < 0) {
38 fprintf(stderr,
39 "Could not drop caches! Please run this program as root!\n");
40 return;
41 }
42 write(fd, "3\n", 2);
43 close(fd);
44 }
45
46 class ScopedTimer {
47 public:
ScopedTimer(const char * name)48 ScopedTimer(const char* name) {
49 name_ = name;
50 start_ms_ = now_ms();
51 }
52
~ScopedTimer()53 ~ScopedTimer() {
54 double elapsed_ms = now_ms() - start_ms_;
55 printf("Timer %s: %.1f\n", name_, elapsed_ms);
56 }
57
58 private:
59 const char* name_;
60 double start_ms_;
61 };
62
main(int argc,char ** argv)63 int main(int argc, char** argv) {
64 const char* library_path = "libfoo.so";
65 if (argc >= 2)
66 library_path = argv[1];
67
68 { ScopedTimer null_timer("empty"); }
69
70 // Load the library with dlopen().
71 void* lib;
72 drop_caches();
73 {
74 ScopedTimer timer("dlopen");
75 lib = dlopen(library_path, RTLD_NOW);
76 }
77 if (!lib)
78 Panic("Could not load library with dlopen(): %s\n", dlerror());
79
80 dlclose(lib);
81
82 crazy_library_t* library;
83 crazy_context_t* context = crazy_context_create();
84
85 // Ensure the program looks in its own directory too.
86 crazy_context_add_search_path_for_address(context,
87 reinterpret_cast<void*>(&main));
88
89 // Load the library with the crazy linker.
90 drop_caches();
91 {
92 ScopedTimer timer("crazy_linker");
93 // Load libfoo.so
94 if (!crazy_library_open(&library, library_path, context)) {
95 Panic("Could not open library: %s\n", crazy_context_get_error(context));
96 }
97 }
98 crazy_library_close(library);
99
100 // Load the library with the crazy linker. Preload libOpenSLES.so
101 drop_caches();
102 void* sles_lib = dlopen("libOpenSLES.so", RTLD_NOW);
103 {
104 ScopedTimer timer("crazy_linker (preload libOpenSLES.so)");
105 // Load libfoo.so
106 if (!crazy_library_open(&library, library_path, context)) {
107 Panic("Could not open library: %s\n", crazy_context_get_error(context));
108 }
109 }
110 crazy_library_close(library);
111 dlclose(sles_lib);
112
113 // Load the library with the crazy linker. Preload libOpenSLES.so
114 {
115 drop_caches();
116 void* sys1_lib = dlopen("libandroid.so", RTLD_NOW);
117 void* sys2_lib = dlopen("libjnigraphics.so", RTLD_NOW);
118 void* sys3_lib = dlopen("libOpenSLES.so", RTLD_NOW);
119 {
120 ScopedTimer timer("crazy_linker (preload 3 system libs)");
121 // Load libfoo.so
122 if (!crazy_library_open(&library, library_path, context)) {
123 Panic("Could not open library: %s\n", crazy_context_get_error(context));
124 }
125 }
126 crazy_library_close(library);
127 dlclose(sys3_lib);
128 dlclose(sys2_lib);
129 dlclose(sys1_lib);
130 }
131
132 // Load the library with the crazy linker. Create a shared RELRO as well.
133 drop_caches();
134 {
135 ScopedTimer timer("crazy_linker (with RELRO)");
136 // Load libfoo.so
137 if (!crazy_library_open(&library, library_path, context)) {
138 Panic("Could not open library: %s\n", crazy_context_get_error(context));
139 }
140
141 if (!crazy_library_enable_relro_sharing(library, context)) {
142 Panic("Could not create shared RELRO: %s\n",
143 crazy_context_get_error(context));
144 }
145 }
146 crazy_library_close(library);
147
148 printf("OK\n");
149 return 0;
150 }