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 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 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 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: 48 ScopedTimer(const char* name) { 49 name_ = name; 50 start_ms_ = now_ms(); 51 } 52 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 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 }