1// Copyright 2014 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
22namespace {
23
24void 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.
38void 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
85int 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}