1 //===-- sanitizer_symbolizer_linux.cc -------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is shared between AddressSanitizer and ThreadSanitizer
11 // run-time libraries.
12 // Linux-specific implementation of symbolizer parts.
13 //===----------------------------------------------------------------------===//
15 #include "sanitizer_platform.h"
17 #include "sanitizer_common.h"
18 #include "sanitizer_internal_defs.h"
19 #include "sanitizer_libc.h"
20 #include "sanitizer_placement_new.h"
21 #include "sanitizer_symbolizer.h"
26 #include <sys/socket.h>
27 #include <sys/types.h>
31 #if !SANITIZER_ANDROID
35 namespace __sanitizer
{
37 static const int kSymbolizerStartupTimeMillis
= 10;
39 bool StartSymbolizerSubprocess(const char *path_to_symbolizer
,
40 int *input_fd
, int *output_fd
) {
41 if (!FileExists(path_to_symbolizer
)) {
42 Report("WARNING: invalid path to external symbolizer!\n");
48 // The client program may close its stdin and/or stdout and/or stderr
49 // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
50 // In this case the communication between the forked processes may be
51 // broken if either the parent or the child tries to close or duplicate
52 // these descriptors. The loop below produces two pairs of file
53 // descriptors, each greater than 2 (stderr).
55 for (int i
= 0; i
< 5; i
++) {
56 if (pipe(sock_pair
[i
]) == -1) {
57 for (int j
= 0; j
< i
; j
++) {
58 internal_close(sock_pair
[j
][0]);
59 internal_close(sock_pair
[j
][1]);
61 Report("WARNING: Can't create a socket pair to start "
62 "external symbolizer (errno: %d)\n", errno
);
64 } else if (sock_pair
[i
][0] > 2 && sock_pair
[i
][1] > 2) {
69 for (int j
= 0; j
< i
; j
++) {
70 if (sock_pair
[j
] == infd
) continue;
71 internal_close(sock_pair
[j
][0]);
72 internal_close(sock_pair
[j
][1]);
84 internal_close(infd
[0]);
85 internal_close(infd
[1]);
86 internal_close(outfd
[0]);
87 internal_close(outfd
[1]);
88 Report("WARNING: failed to fork external symbolizer "
89 " (errno: %d)\n", errno
);
91 } else if (pid
== 0) {
93 internal_close(STDOUT_FILENO
);
94 internal_close(STDIN_FILENO
);
95 internal_dup2(outfd
[0], STDIN_FILENO
);
96 internal_dup2(infd
[1], STDOUT_FILENO
);
97 internal_close(outfd
[0]);
98 internal_close(outfd
[1]);
99 internal_close(infd
[0]);
100 internal_close(infd
[1]);
101 for (int fd
= getdtablesize(); fd
> 2; fd
--)
103 execl(path_to_symbolizer
, path_to_symbolizer
, (char*)0);
107 // Continue execution in parent process.
108 internal_close(outfd
[0]);
109 internal_close(infd
[1]);
111 *output_fd
= outfd
[1];
113 // Check that symbolizer subprocess started successfully.
115 SleepForMillis(kSymbolizerStartupTimeMillis
);
116 int exited_pid
= waitpid(pid
, &pid_status
, WNOHANG
);
117 if (exited_pid
!= 0) {
118 // Either waitpid failed, or child has already exited.
119 Report("WARNING: external symbolizer didn't start up correctly!\n");
126 #if SANITIZER_ANDROID
127 uptr
GetListOfModules(LoadedModule
*modules
, uptr max_modules
) {
130 #else // SANITIZER_ANDROID
131 typedef ElfW(Phdr
) Elf_Phdr
;
133 struct DlIteratePhdrData
{
134 LoadedModule
*modules
;
139 static const uptr kMaxPathLength
= 512;
141 static int dl_iterate_phdr_cb(dl_phdr_info
*info
, size_t size
, void *arg
) {
142 DlIteratePhdrData
*data
= (DlIteratePhdrData
*)arg
;
143 if (data
->current_n
== data
->max_n
)
145 InternalScopedBuffer
<char> module_name(kMaxPathLength
);
146 module_name
.data()[0] = '\0';
147 if (data
->current_n
== 0) {
148 // First module is the binary itself.
149 uptr module_name_len
= internal_readlink(
150 "/proc/self/exe", module_name
.data(), module_name
.size());
151 if (module_name_len
== (uptr
)-1) {
152 // We can't read /proc/self/exe for some reason, assume the name of the
153 // binary is unknown.
154 module_name_len
= internal_snprintf(module_name
.data(),
155 module_name
.size(), "/proc/self/exe");
157 CHECK_LT(module_name_len
, module_name
.size());
158 module_name
[module_name_len
] = '\0';
159 } else if (info
->dlpi_name
) {
160 internal_strncpy(module_name
.data(), info
->dlpi_name
, module_name
.size());
162 if (module_name
.data()[0] == '\0')
164 void *mem
= &data
->modules
[data
->current_n
];
165 LoadedModule
*cur_module
= new(mem
) LoadedModule(module_name
.data(),
168 for (int i
= 0; i
< info
->dlpi_phnum
; i
++) {
169 const Elf_Phdr
*phdr
= &info
->dlpi_phdr
[i
];
170 if (phdr
->p_type
== PT_LOAD
) {
171 uptr cur_beg
= info
->dlpi_addr
+ phdr
->p_vaddr
;
172 uptr cur_end
= cur_beg
+ phdr
->p_memsz
;
173 cur_module
->addAddressRange(cur_beg
, cur_end
);
179 uptr
GetListOfModules(LoadedModule
*modules
, uptr max_modules
) {
181 DlIteratePhdrData data
= {modules
, 0, max_modules
};
182 dl_iterate_phdr(dl_iterate_phdr_cb
, &data
);
183 return data
.current_n
;
185 #endif // SANITIZER_ANDROID
187 } // namespace __sanitizer
189 #endif // SANITIZER_LINUX