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 check that paths added with
      6 // crazy_context_add_search_path() or
      7 // crazy_context_add_search_path_from_address()
      8 // have higher priority than the default ones (from LD_LIBRARY_PATH).
      9 //
     10 // This requires creating two temporary directories and placing there libraries
     11 // with the same name, but different content
     12 //
     13 //   $TMPDIR1/libfoo.so   -> a copy of libfoo.so that contains the 'Foo' symbol.
     14 //   $TMPDIR2/libfoo.so   -> a copy of libfoo2.so that contains the 'Foo2'
     15 // symbol.
     16 //
     17 
     18 #include <crazy_linker.h>
     19 
     20 #include "test_util.h"
     21 
     22 namespace {
     23 
     24 void CheckLibraryCantLoad(const char* library_name, crazy_context_t* context) {
     25   crazy_library_t* library;
     26 
     27   if (crazy_library_open(&library, library_name, context))
     28     Panic("Could load library %s, expected this not to be possible\n",
     29           library_name);
     30 }
     31 
     32 // Loads a library named |library_name| and checks that it contains
     33 // the symbols listed in |wanted_symbols|, and none of the symbols
     34 // listed in |unwanted_symbols|. After that, close the library and exit.
     35 //
     36 // Both |wanted_symbols| and |unwanted_symbols| are NULL-terminated
     37 // arrays of strings.
     38 void CheckLibrary(const char* library_name,
     39                   const char* const* wanted_symbols,
     40                   const char* const* unwanted_symbols,
     41                   crazy_context_t* context) {
     42   crazy_library_t* library;
     43 
     44   if (!crazy_library_open(&library, library_name, context))
     45     Panic("Could not open library %s: %s\n", crazy_context_get_error(context));
     46 
     47   size_t failures = 0;
     48 
     49   if (wanted_symbols) {
     50     for (; *wanted_symbols; ++wanted_symbols) {
     51       const char* symbol_name = *wanted_symbols;
     52       void* symbol_addr;
     53       if (!crazy_library_find_symbol(library, symbol_name, &symbol_addr)) {
     54         fprintf(stderr,
     55                 "Could not find symbol '%s' in library '%s'!\n",
     56                 symbol_name,
     57                 library_name);
     58         failures += 1;
     59       }
     60     }
     61   }
     62 
     63   if (unwanted_symbols) {
     64     for (; *unwanted_symbols; ++unwanted_symbols) {
     65       const char* symbol_name = *unwanted_symbols;
     66       void* symbol_addr;
     67       if (crazy_library_find_symbol(library, symbol_name, &symbol_addr)) {
     68         fprintf(stderr,
     69                 "Found symbol '%s' in library '%s', none expected!\n",
     70                 symbol_name,
     71                 library_name);
     72         failures += 1;
     73       }
     74     }
     75   }
     76 
     77   if (failures > 0)
     78     Panic("Found %d symbol failures in library %s\n", failures, library_name);
     79 
     80   crazy_library_close(library);
     81 }
     82 
     83 }  // namespace
     84 
     85 int main() {
     86   String exe_path = GetCurrentExecutableDirectory();
     87 
     88   TempDirectory temp_dir_1;
     89   TempDirectory temp_dir_2;
     90 
     91   // List of symbols in original libfoo.so and libfoo2.so, respectively.
     92   static const char* const kFooSymbols[] = {"Foo", NULL};
     93   static const char* const kFoo2Symbols[] = {"Foo2", NULL};
     94 
     95   // Copy libfoo.so to $TMPDIR1/libfoo.so
     96   CopyFile("libfoo.so", exe_path.c_str(), "libfoo.so", temp_dir_1.path());
     97 
     98   // Copy libfoo2.so to $TMPDIR2/libfoo.so
     99   CopyFile("libfoo2.so", exe_path.c_str(), "libfoo.so", temp_dir_2.path());
    100 
    101   // Create a new context object.
    102   crazy_context_t* context = crazy_context_create();
    103   crazy_library_t* library;
    104 
    105   // Reset search paths to a non-existing directory. Check that the library
    106   // can't be loaded.
    107   setenv("LD_LIBRARY_PATH", "/this-directory-does-not-exist", 1);
    108   crazy_context_reset_search_paths(context);
    109   CheckLibraryCantLoad("libfoo.so", context);
    110 
    111   // Add the search path to the current executable, this should load the
    112   // original
    113   // libfoo.so.
    114   crazy_context_add_search_path_for_address(context, (void*)&main);
    115   CheckLibrary("libfoo.so", kFooSymbols, kFoo2Symbols, context);
    116 
    117   // Reset search paths to use $TMPDIR2 then $TMPDIR1
    118   setenv("LD_LIBRARY_PATH", temp_dir_1.path(), 1);
    119   crazy_context_reset_search_paths(context);
    120   crazy_context_add_search_path(context, temp_dir_2.path());
    121 
    122   // Check that the copy of libfoo2.so is loaded.
    123   CheckLibrary("libfoo.so", kFoo2Symbols, kFooSymbols, context);
    124 
    125   // Reset search paths to use only $TMPDIR1
    126   crazy_context_reset_search_paths(context);
    127 
    128   // Check that the copy of libfoo.so is loaded.
    129   CheckLibrary("libfoo.so", kFooSymbols, kFoo2Symbols, context);
    130 
    131   crazy_context_destroy(context);
    132 
    133   return 0;
    134 }