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
CheckLibraryCantLoad(const char * library_name,crazy_context_t * context)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.
CheckLibrary(const char * library_name,const char * const * wanted_symbols,const char * const * unwanted_symbols,crazy_context_t * context)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
main()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 }