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