• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }