| 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 |