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_common.h"
16 #include "sanitizer_internal_defs.h"
17 #include "sanitizer_libc.h"
18 #include "sanitizer_placement_new.h"
19 #include "sanitizer_symbolizer.h"
24 #include <sys/socket.h>
25 #include <sys/types.h>
29 #if !defined(__ANDROID__) && !defined(ANDROID)
33 namespace __sanitizer
{
35 static const int kSymbolizerStartupTimeMillis
= 10;
37 bool StartSymbolizerSubprocess(const char *path_to_symbolizer
,
38 int *input_fd
, int *output_fd
) {
39 if (!FileExists(path_to_symbolizer
)) {
40 Report("WARNING: invalid path to external symbolizer!\n");
46 // The client program may close its stdin and/or stdout and/or stderr
47 // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
48 // In this case the communication between the forked processes may be
49 // broken if either the parent or the child tries to close or duplicate
50 // these descriptors. The loop below produces two pairs of file
51 // descriptors, each greater than 2 (stderr).
53 for (int i
= 0; i
< 5; i
++) {
54 if (pipe(sock_pair
[i
]) == -1) {
55 for (int j
= 0; j
< i
; j
++) {
56 internal_close(sock_pair
[j
][0]);
57 internal_close(sock_pair
[j
][1]);
59 Report("WARNING: Can't create a socket pair to start "
60 "external symbolizer (errno: %d)\n", errno
);
62 } else if (sock_pair
[i
][0] > 2 && sock_pair
[i
][1] > 2) {
67 for (int j
= 0; j
< i
; j
++) {
68 if (sock_pair
[j
] == infd
) continue;
69 internal_close(sock_pair
[j
][0]);
70 internal_close(sock_pair
[j
][1]);
82 internal_close(infd
[0]);
83 internal_close(infd
[1]);
84 internal_close(outfd
[0]);
85 internal_close(outfd
[1]);
86 Report("WARNING: failed to fork external symbolizer "
87 " (errno: %d)\n", errno
);
89 } else if (pid
== 0) {
91 internal_close(STDOUT_FILENO
);
92 internal_close(STDIN_FILENO
);
93 internal_dup2(outfd
[0], STDIN_FILENO
);
94 internal_dup2(infd
[1], STDOUT_FILENO
);
95 internal_close(outfd
[0]);
96 internal_close(outfd
[1]);
97 internal_close(infd
[0]);
98 internal_close(infd
[1]);
99 for (int fd
= getdtablesize(); fd
> 2; fd
--)
101 execl(path_to_symbolizer
, path_to_symbolizer
, (char*)0);
105 // Continue execution in parent process.
106 internal_close(outfd
[0]);
107 internal_close(infd
[1]);
109 *output_fd
= outfd
[1];
111 // Check that symbolizer subprocess started successfully.
113 SleepForMillis(kSymbolizerStartupTimeMillis
);
114 int exited_pid
= waitpid(pid
, &pid_status
, WNOHANG
);
115 if (exited_pid
!= 0) {
116 // Either waitpid failed, or child has already exited.
117 Report("WARNING: external symbolizer didn't start up correctly!\n");
124 #if defined(__ANDROID__) || defined(ANDROID)
125 uptr
GetListOfModules(LoadedModule
*modules
, uptr max_modules
) {
129 typedef ElfW(Phdr
) Elf_Phdr
;
131 struct DlIteratePhdrData
{
132 LoadedModule
*modules
;
137 static const uptr kMaxPathLength
= 512;
139 static int dl_iterate_phdr_cb(dl_phdr_info
*info
, size_t size
, void *arg
) {
140 DlIteratePhdrData
*data
= (DlIteratePhdrData
*)arg
;
141 if (data
->current_n
== data
->max_n
)
143 InternalScopedBuffer
<char> module_name(kMaxPathLength
);
144 module_name
.data()[0] = '\0';
145 if (data
->current_n
== 0) {
146 // First module is the binary itself.
147 uptr module_name_len
= internal_readlink(
148 "/proc/self/exe", module_name
.data(), module_name
.size());
149 CHECK_NE(module_name_len
, (uptr
)-1);
150 CHECK_LT(module_name_len
, module_name
.size());
151 module_name
[module_name_len
] = '\0';
152 } else if (info
->dlpi_name
) {
153 internal_strncpy(module_name
.data(), info
->dlpi_name
, module_name
.size());
155 if (module_name
.data()[0] == '\0')
157 void *mem
= &data
->modules
[data
->current_n
];
158 LoadedModule
*cur_module
= new(mem
) LoadedModule(module_name
.data(),
161 for (int i
= 0; i
< info
->dlpi_phnum
; i
++) {
162 const Elf_Phdr
*phdr
= &info
->dlpi_phdr
[i
];
163 if (phdr
->p_type
== PT_LOAD
) {
164 uptr cur_beg
= info
->dlpi_addr
+ phdr
->p_vaddr
;
165 uptr cur_end
= cur_beg
+ phdr
->p_memsz
;
166 cur_module
->addAddressRange(cur_beg
, cur_end
);
172 uptr
GetListOfModules(LoadedModule
*modules
, uptr max_modules
) {
174 DlIteratePhdrData data
= {modules
, 0, max_modules
};
175 dl_iterate_phdr(dl_iterate_phdr_cb
, &data
);
176 return data
.current_n
;
180 } // namespace __sanitizer