OLD | NEW |
1 //===-- sanitizer_symbolizer_linux.cc -------------------------------------===// | 1 //===-- sanitizer_symbolizer_linux.cc -------------------------------------===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file is shared between AddressSanitizer and ThreadSanitizer | 10 // This file is shared between AddressSanitizer and ThreadSanitizer |
11 // run-time libraries. | 11 // run-time libraries. |
12 // Linux-specific implementation of symbolizer parts. | 12 // Linux-specific implementation of symbolizer parts. |
13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
14 #ifdef __linux__ | 14 #ifdef __linux__ |
15 #include "sanitizer_common.h" | 15 #include "sanitizer_common.h" |
16 #include "sanitizer_internal_defs.h" | 16 #include "sanitizer_internal_defs.h" |
| 17 #include "sanitizer_libc.h" |
17 #include "sanitizer_placement_new.h" | 18 #include "sanitizer_placement_new.h" |
18 #include "sanitizer_symbolizer.h" | 19 #include "sanitizer_symbolizer.h" |
19 | 20 |
20 #include <elf.h> | 21 #include <elf.h> |
| 22 #include <errno.h> |
21 #include <link.h> | 23 #include <link.h> |
| 24 #include <poll.h> |
| 25 #include <sys/socket.h> |
| 26 #include <sys/types.h> |
22 #include <unistd.h> | 27 #include <unistd.h> |
23 | 28 |
24 namespace __sanitizer { | 29 namespace __sanitizer { |
25 | 30 |
26 typedef ElfW(Ehdr) Elf_Ehdr; | 31 bool StartSymbolizerSubprocess(const char *path_to_symbolizer, |
27 typedef ElfW(Shdr) Elf_Shdr; | 32 int *input_fd, int *output_fd) { |
28 typedef ElfW(Phdr) Elf_Phdr; | 33 int *infd = NULL; |
29 | 34 int *outfd = NULL; |
30 bool FindDWARFSection(uptr object_file_addr, const char *section_name, | 35 // The client program may close its stdin and/or stdout and/or stderr |
31 DWARFSection *section) { | 36 // thus allowing socketpair to reuse file descriptors 0, 1 or 2. |
32 Elf_Ehdr *exe = (Elf_Ehdr*)object_file_addr; | 37 // In this case the communication between the forked processes may be |
33 Elf_Shdr *sections = (Elf_Shdr*)(object_file_addr + exe->e_shoff); | 38 // broken if either the parent or the child tries to close or duplicate |
34 uptr section_names = object_file_addr + | 39 // these descriptors. The loop below produces two pairs of file |
35 sections[exe->e_shstrndx].sh_offset; | 40 // descriptors, each greater than 2 (stderr). |
36 for (int i = 0; i < exe->e_shnum; i++) { | 41 int sock_pair[5][2]; |
37 Elf_Shdr *current_section = §ions[i]; | 42 for (int i = 0; i < 5; i++) { |
38 const char *current_name = (const char*)section_names + | 43 if (pipe(sock_pair[i]) == -1) { |
39 current_section->sh_name; | 44 for (int j = 0; j < i; j++) { |
40 if (IsFullNameOfDWARFSection(current_name, section_name)) { | 45 internal_close(sock_pair[j][0]); |
41 section->data = (const char*)object_file_addr + | 46 internal_close(sock_pair[j][1]); |
42 current_section->sh_offset; | 47 } |
43 section->size = current_section->sh_size; | 48 Report("WARNING: Can't create a socket pair to start " |
44 return true; | 49 "external symbolizer (errno: %d)\n", errno); |
| 50 return false; |
| 51 } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) { |
| 52 if (infd == NULL) { |
| 53 infd = sock_pair[i]; |
| 54 } else { |
| 55 outfd = sock_pair[i]; |
| 56 for (int j = 0; j < i; j++) { |
| 57 if (sock_pair[j] == infd) continue; |
| 58 internal_close(sock_pair[j][0]); |
| 59 internal_close(sock_pair[j][1]); |
| 60 } |
| 61 break; |
| 62 } |
45 } | 63 } |
46 } | 64 } |
47 return false; | 65 CHECK(infd); |
| 66 CHECK(outfd); |
| 67 |
| 68 int pid = fork(); |
| 69 if (pid == -1) { |
| 70 // Fork() failed. |
| 71 internal_close(infd[0]); |
| 72 internal_close(infd[1]); |
| 73 internal_close(outfd[0]); |
| 74 internal_close(outfd[1]); |
| 75 Report("WARNING: failed to fork external symbolizer " |
| 76 " (errno: %d)\n", errno); |
| 77 return false; |
| 78 } else if (pid == 0) { |
| 79 // Child subprocess. |
| 80 internal_close(STDOUT_FILENO); |
| 81 internal_close(STDIN_FILENO); |
| 82 internal_dup2(outfd[0], STDIN_FILENO); |
| 83 internal_dup2(infd[1], STDOUT_FILENO); |
| 84 internal_close(outfd[0]); |
| 85 internal_close(outfd[1]); |
| 86 internal_close(infd[0]); |
| 87 internal_close(infd[1]); |
| 88 for (int fd = getdtablesize(); fd > 2; fd--) |
| 89 internal_close(fd); |
| 90 execl(path_to_symbolizer, path_to_symbolizer, (char*)0); |
| 91 Exit(1); |
| 92 } |
| 93 |
| 94 // Continue execution in parent process. |
| 95 internal_close(outfd[0]); |
| 96 internal_close(infd[1]); |
| 97 *input_fd = infd[0]; |
| 98 *output_fd = outfd[1]; |
| 99 return true; |
48 } | 100 } |
49 | 101 |
50 #ifdef ANDROID | 102 #ifdef ANDROID |
51 uptr GetListOfModules(ModuleDIContext *modules, uptr max_modules) { | 103 uptr GetListOfModules(LoadedModule *modules, uptr max_modules) { |
52 UNIMPLEMENTED(); | 104 UNIMPLEMENTED(); |
53 } | 105 } |
54 #else // ANDROID | 106 #else // ANDROID |
| 107 typedef ElfW(Phdr) Elf_Phdr; |
| 108 |
55 struct DlIteratePhdrData { | 109 struct DlIteratePhdrData { |
56 ModuleDIContext *modules; | 110 LoadedModule *modules; |
57 uptr current_n; | 111 uptr current_n; |
58 uptr max_n; | 112 uptr max_n; |
59 }; | 113 }; |
60 | 114 |
61 static const uptr kMaxPathLength = 512; | 115 static const uptr kMaxPathLength = 512; |
62 | 116 |
63 static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { | 117 static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { |
64 DlIteratePhdrData *data = (DlIteratePhdrData*)arg; | 118 DlIteratePhdrData *data = (DlIteratePhdrData*)arg; |
65 if (data->current_n == data->max_n) | 119 if (data->current_n == data->max_n) |
66 return 0; | 120 return 0; |
67 char *module_name = 0; | 121 char *module_name = 0; |
68 if (data->current_n == 0) { | 122 if (data->current_n == 0) { |
69 // First module is the binary itself. | 123 // First module is the binary itself. |
70 module_name = (char*)InternalAlloc(kMaxPathLength); | 124 module_name = (char*)InternalAlloc(kMaxPathLength); |
71 uptr module_name_len = readlink("/proc/self/exe", | 125 uptr module_name_len = readlink("/proc/self/exe", |
72 module_name, kMaxPathLength); | 126 module_name, kMaxPathLength); |
73 CHECK_NE(module_name_len, (uptr)-1); | 127 CHECK_NE(module_name_len, (uptr)-1); |
74 CHECK_LT(module_name_len, kMaxPathLength); | 128 CHECK_LT(module_name_len, kMaxPathLength); |
75 module_name[module_name_len] = '\0'; | 129 module_name[module_name_len] = '\0'; |
76 } else if (info->dlpi_name) { | 130 } else if (info->dlpi_name) { |
77 module_name = internal_strdup(info->dlpi_name); | 131 module_name = internal_strdup(info->dlpi_name); |
78 } | 132 } |
79 if (module_name == 0 || module_name[0] == '\0') | 133 if (module_name == 0 || module_name[0] == '\0') |
80 return 0; | 134 return 0; |
81 void *mem = &data->modules[data->current_n]; | 135 void *mem = &data->modules[data->current_n]; |
82 ModuleDIContext *cur_module = new(mem) ModuleDIContext(module_name, | 136 LoadedModule *cur_module = new(mem) LoadedModule(module_name, |
83 info->dlpi_addr); | 137 info->dlpi_addr); |
84 data->current_n++; | 138 data->current_n++; |
85 for (int i = 0; i < info->dlpi_phnum; i++) { | 139 for (int i = 0; i < info->dlpi_phnum; i++) { |
86 const Elf_Phdr *phdr = &info->dlpi_phdr[i]; | 140 const Elf_Phdr *phdr = &info->dlpi_phdr[i]; |
87 if (phdr->p_type == PT_LOAD) { | 141 if (phdr->p_type == PT_LOAD) { |
88 uptr cur_beg = info->dlpi_addr + phdr->p_vaddr; | 142 uptr cur_beg = info->dlpi_addr + phdr->p_vaddr; |
89 uptr cur_end = cur_beg + phdr->p_memsz; | 143 uptr cur_end = cur_beg + phdr->p_memsz; |
90 cur_module->addAddressRange(cur_beg, cur_end); | 144 cur_module->addAddressRange(cur_beg, cur_end); |
91 } | 145 } |
92 } | 146 } |
93 InternalFree(module_name); | 147 InternalFree(module_name); |
94 return 0; | 148 return 0; |
95 } | 149 } |
96 | 150 |
97 uptr GetListOfModules(ModuleDIContext *modules, uptr max_modules) { | 151 uptr GetListOfModules(LoadedModule *modules, uptr max_modules) { |
98 CHECK(modules); | 152 CHECK(modules); |
99 DlIteratePhdrData data = {modules, 0, max_modules}; | 153 DlIteratePhdrData data = {modules, 0, max_modules}; |
100 dl_iterate_phdr(dl_iterate_phdr_cb, &data); | 154 dl_iterate_phdr(dl_iterate_phdr_cb, &data); |
101 return data.current_n; | 155 return data.current_n; |
102 } | 156 } |
103 #endif // ANDROID | 157 #endif // ANDROID |
104 | 158 |
105 } // namespace __sanitizer | 159 } // namespace __sanitizer |
106 | 160 |
107 #endif // __linux__ | 161 #endif // __linux__ |
OLD | NEW |