Home | History | Annotate | Download | only in tests
      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 }