OLD | NEW |
1 // Copyright (c) 2014 The Native Client Authors. All rights reserved. | 1 // Copyright (c) 2014 The Native Client Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "library_dependencies.h" | 5 #include "library_dependencies.h" |
6 | 6 |
7 #include <assert.h> | 7 #include <assert.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <fcntl.h> | 9 #include <fcntl.h> |
10 #include <stdio.h> | 10 #include <stdio.h> |
11 #include <stdlib.h> | 11 #include <stdlib.h> |
12 #include <unistd.h> | 12 #include <unistd.h> |
13 | 13 |
14 #include <set> | 14 #include <set> |
15 | 15 |
16 #include "elf_reader.h" | 16 #include "elf_reader.h" |
| 17 #include "nacl_spawn.h" |
17 #include "path_util.h" | 18 #include "path_util.h" |
18 | 19 |
19 #define PROGRAM_NAME "nacl_spawn" | |
20 | |
21 static bool s_debug; | 20 static bool s_debug; |
22 | 21 |
23 static void get_library_paths(std::vector<std::string>* paths) { | 22 static void get_library_paths(std::vector<std::string>* paths) { |
24 // Partially emulate the behaviour of ls.so. | 23 // Partially emulate the behaviour of ls.so. |
25 // Search LD_LIBRARY_PATH first, then fall back to the defaults paths | 24 // Search LD_LIBRARY_PATH first, then fall back to the defaults paths |
26 // (/lib and /usr/lib). | 25 // (/lib and /usr/lib). |
27 const char* path_env = getenv("LD_LIBRARY_PATH"); | 26 const char* path_env = getenv("LD_LIBRARY_PATH"); |
28 nspawn_get_paths(path_env, paths); | 27 nspawn_get_paths(path_env, paths); |
29 paths->push_back("/lib"); | 28 paths->push_back("/lib"); |
30 paths->push_back("/usr/lib"); | 29 paths->push_back("/usr/lib"); |
31 if (s_debug) { | 30 if (s_debug) { |
32 for (size_t i = 0; i < paths->size(); i++) | 31 for (size_t i = 0; i < paths->size(); i++) |
33 fprintf(stderr, "%s: searching: %s\n", PROGRAM_NAME, | 32 fprintf(stderr, "%s: searching: %s\n", LOADER_NAME, |
34 paths->at(i).c_str()); | 33 paths->at(i).c_str()); |
35 } | 34 } |
36 } | 35 } |
37 | 36 |
38 static bool find_arch_and_library_deps( | 37 static bool find_arch_and_library_deps( |
39 const std::string& filename, | 38 const std::string& filename, |
40 const std::vector<std::string>& paths, | 39 const std::vector<std::string>& paths, |
41 std::string* arch, | 40 std::string* arch, |
42 std::set<std::string>* dependencies) { | 41 std::set<std::string>* dependencies) { |
43 if (!dependencies->insert(filename).second) { | 42 if (!dependencies->insert(filename).second) { |
44 // We have already added this file. | 43 // We have already added this file. |
45 return true; | 44 return true; |
46 } | 45 } |
47 | 46 |
48 if (s_debug) { | 47 if (s_debug) { |
49 fprintf(stderr, "%s: resolving deps for: %s\n", PROGRAM_NAME, | 48 fprintf(stderr, "%s: resolving deps for: %s\n", LOADER_NAME, |
50 filename.c_str()); | 49 filename.c_str()); |
51 } | 50 } |
52 | 51 |
53 ElfReader elf_reader(filename.c_str()); | 52 ElfReader elf_reader(filename.c_str()); |
54 | 53 |
55 if (!elf_reader.is_valid()) { | 54 if (!elf_reader.is_valid()) { |
56 errno = ENOEXEC; | 55 errno = ENOEXEC; |
57 return false; | 56 return false; |
58 } | 57 } |
59 | 58 |
60 Elf64_Half machine = elf_reader.machine(); | 59 Elf64_Half machine = elf_reader.machine(); |
61 if (machine != EM_X86_64 && machine != EM_386 && machine != EM_ARM) { | 60 if (machine != EM_X86_64 && machine != EM_386 && machine != EM_ARM) { |
62 errno = ENOEXEC; | 61 errno = ENOEXEC; |
63 return false; | 62 return false; |
64 } | 63 } |
65 if (arch) { | 64 if (arch) { |
66 if (machine == EM_X86_64) { | 65 if (machine == EM_X86_64) { |
67 *arch = "x86-64"; | 66 *arch = "x86-64"; |
68 } else if (machine == EM_386) { | 67 } else if (machine == EM_386) { |
69 *arch = "x86-32"; | 68 *arch = "x86-32"; |
70 } else if (machine == EM_ARM) { | 69 } else if (machine == EM_ARM) { |
71 *arch = "arm"; | 70 *arch = "arm"; |
72 } else { | 71 } else { |
73 fprintf(stderr, "%s: unknown arch (%d): %s\n", PROGRAM_NAME, machine, | 72 fprintf(stderr, "%s: unknown arch (%d): %s\n", LOADER_NAME, machine, |
74 filename.c_str()); | 73 filename.c_str()); |
75 return false; | 74 return false; |
76 } | 75 } |
77 if (s_debug) | 76 if (s_debug) { |
78 fprintf(stderr, "%s: arch=%s\n", PROGRAM_NAME, arch->c_str()); | 77 fprintf(stderr, "%s: arch=%s\n", LOADER_NAME, arch->c_str()); |
| 78 } |
79 } | 79 } |
80 | 80 |
81 if (elf_reader.is_static()) { | 81 if (elf_reader.is_static()) { |
82 assert(!dependencies->empty()); | 82 assert(!dependencies->empty()); |
83 if (dependencies->size() == 1) { | 83 if (dependencies->size() == 1) { |
84 // The main binary is statically linked. | 84 // The main binary is statically linked. |
85 dependencies->clear(); | 85 dependencies->clear(); |
86 return true; | 86 return true; |
87 } else { | 87 } else { |
88 fprintf(stderr, "%s: unexpected static binary: %s\n", PROGRAM_NAME, | 88 fprintf(stderr, "%s: unexpected static binary: %s\n", LOADER_NAME, |
89 filename.c_str()); | 89 filename.c_str()); |
90 errno = ENOEXEC; | 90 errno = ENOEXEC; |
91 return false; | 91 return false; |
92 } | 92 } |
93 } | 93 } |
94 | 94 |
95 for (size_t i = 0; i < elf_reader.neededs().size(); i++) { | 95 for (size_t i = 0; i < elf_reader.neededs().size(); i++) { |
96 const std::string& needed_name = elf_reader.neededs()[i]; | 96 const std::string& needed_name = elf_reader.neededs()[i]; |
97 std::string needed_path; | 97 std::string needed_path; |
98 if (needed_name == "ld-nacl-x86-32.so.1" || | 98 if (needed_name == "ld-nacl-x86-32.so.1" || |
99 needed_name == "ld-nacl-x86-64.so.1") { | 99 needed_name == "ld-nacl-x86-64.so.1") { |
100 // Our sdk includes ld-nacl-x86-*.so.1, for link time. However, | 100 // Our sdk includes ld-nacl-x86-*.so.1, for link time. However, |
101 // create_nmf.py (because of objdump) only publishes runnable-ld.so | 101 // create_nmf.py (because of objdump) only publishes runnable-ld.so |
102 // (which is a version of ld-nacl-x86-*.so.1, modified to be runnable | 102 // (which is a version of ld-nacl-x86-*.so.1, modified to be runnable |
103 // as the initial nexe by nacl). Since all glibc NMFs include | 103 // as the initial nexe by nacl). Since all glibc NMFs include |
104 // ld-runnable.so (which has ld-nacl-*.so.1 as its SONAME), they will | 104 // ld-runnable.so (which has ld-nacl-*.so.1 as its SONAME), they will |
105 // already have this dependency, so we can ignore it. | 105 // already have this dependency, so we can ignore it. |
106 } else if (nspawn_find_in_paths(needed_name, paths, &needed_path)) { | 106 } else if (nspawn_find_in_paths(needed_name, paths, &needed_path)) { |
107 if (!find_arch_and_library_deps(needed_path, paths, NULL, dependencies)) | 107 if (!find_arch_and_library_deps(needed_path, paths, NULL, dependencies)) |
108 return false; | 108 return false; |
109 } else { | 109 } else { |
110 fprintf(stderr, "%s: library not found: %s\n", PROGRAM_NAME, | 110 fprintf(stderr, "%s: library not found: %s\n", LOADER_NAME, |
111 needed_name.c_str()); | 111 needed_name.c_str()); |
112 errno = ENOENT; | 112 errno = ENOENT; |
113 return false; | 113 return false; |
114 } | 114 } |
115 } | 115 } |
116 return true; | 116 return true; |
117 } | 117 } |
118 | 118 |
119 bool nspawn_find_arch_and_library_deps(const std::string& filename, | 119 bool nspawn_find_arch_and_library_deps(const std::string& filename, |
120 std::string* arch, | 120 std::string* arch, |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 for (size_t i = 0; i < dependencies.size(); i++) { | 182 for (size_t i = 0; i < dependencies.size(); i++) { |
183 if (i) | 183 if (i) |
184 printf(" "); | 184 printf(" "); |
185 printf("%s", dependencies[i].c_str()); | 185 printf("%s", dependencies[i].c_str()); |
186 } | 186 } |
187 | 187 |
188 printf("\n"); | 188 printf("\n"); |
189 } | 189 } |
190 | 190 |
191 #endif // DEFINE_LIBRARY_DEPENDENCIES_MAIN | 191 #endif // DEFINE_LIBRARY_DEPENDENCIES_MAIN |
OLD | NEW |