1ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov//===-- sanitizer_symbolizer_posix_libcdep.cc -----------------------------===// 2ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// 3ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// The LLVM Compiler Infrastructure 4ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// 5ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// This file is distributed under the University of Illinois Open Source 6ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// License. See LICENSE.TXT for details. 7ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// 8ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov//===----------------------------------------------------------------------===// 9ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// 10ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer 11ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// run-time libraries. 12ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov// POSIX-specific implementation of symbolizer parts. 13ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov//===----------------------------------------------------------------------===// 14ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov 15ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#include "sanitizer_platform.h" 16ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#if SANITIZER_POSIX 17ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#include "sanitizer_common.h" 18ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#include "sanitizer_internal_defs.h" 19ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#include "sanitizer_symbolizer.h" 20ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov 21ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#include <errno.h> 22ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#include <sys/wait.h> 23ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#include <unistd.h> 24ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov 25ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonovnamespace __sanitizer { 26ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov 2752d08d8412bfa4ccfa38384d781b51e8774807a7Alexey Samsonov#if defined(__x86_64__) 2852d08d8412bfa4ccfa38384d781b51e8774807a7Alexey Samsonovstatic const char* const kSymbolizerArch = "--default-arch=x86_64"; 2952d08d8412bfa4ccfa38384d781b51e8774807a7Alexey Samsonov#elif defined(__i386__) 3052d08d8412bfa4ccfa38384d781b51e8774807a7Alexey Samsonovstatic const char* const kSymbolizerArch = "--default-arch=i386"; 317aaaee4cab08096d46e9886c5fea8564732ad2ffAlexey Samsonov#elif defined(__powerpc64__) 327aaaee4cab08096d46e9886c5fea8564732ad2ffAlexey Samsonovstatic const char* const kSymbolizerArch = "--default-arch=powerpc64"; 3352d08d8412bfa4ccfa38384d781b51e8774807a7Alexey Samsonov#else 347aaaee4cab08096d46e9886c5fea8564732ad2ffAlexey Samsonovstatic const char* const kSymbolizerArch = "--default-arch=unknown"; 3552d08d8412bfa4ccfa38384d781b51e8774807a7Alexey Samsonov#endif 3652d08d8412bfa4ccfa38384d781b51e8774807a7Alexey Samsonov 37ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonovbool StartSymbolizerSubprocess(const char *path_to_symbolizer, 38ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov int *input_fd, int *output_fd) { 39ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov if (!FileExists(path_to_symbolizer)) { 40ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov Report("WARNING: invalid path to external symbolizer!\n"); 41ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov return false; 42ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov } 43ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov 44ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov int *infd = NULL; 45ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov int *outfd = NULL; 46ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov // The client program may close its stdin and/or stdout and/or stderr 47ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov // thus allowing socketpair to reuse file descriptors 0, 1 or 2. 48ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov // In this case the communication between the forked processes may be 49ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov // broken if either the parent or the child tries to close or duplicate 50ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov // these descriptors. The loop below produces two pairs of file 51ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov // descriptors, each greater than 2 (stderr). 52ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov int sock_pair[5][2]; 53ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov for (int i = 0; i < 5; i++) { 54ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov if (pipe(sock_pair[i]) == -1) { 55ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov for (int j = 0; j < i; j++) { 56ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(sock_pair[j][0]); 57ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(sock_pair[j][1]); 58ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov } 59ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov Report("WARNING: Can't create a socket pair to start " 60ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov "external symbolizer (errno: %d)\n", errno); 61ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov return false; 62ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) { 63ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov if (infd == NULL) { 64ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov infd = sock_pair[i]; 65ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov } else { 66ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov outfd = sock_pair[i]; 67ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov for (int j = 0; j < i; j++) { 68ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov if (sock_pair[j] == infd) continue; 69ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(sock_pair[j][0]); 70ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(sock_pair[j][1]); 71ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov } 72ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov break; 73ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov } 74ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov } 75ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov } 76ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov CHECK(infd); 77ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov CHECK(outfd); 78ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov 79ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov int pid = fork(); 80ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov if (pid == -1) { 81ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov // Fork() failed. 82ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(infd[0]); 83ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(infd[1]); 84ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(outfd[0]); 85ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(outfd[1]); 86ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov Report("WARNING: failed to fork external symbolizer " 87ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov " (errno: %d)\n", errno); 88ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov return false; 89ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov } else if (pid == 0) { 90ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov // Child subprocess. 91ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(STDOUT_FILENO); 92ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(STDIN_FILENO); 93ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_dup2(outfd[0], STDIN_FILENO); 94ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_dup2(infd[1], STDOUT_FILENO); 95ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(outfd[0]); 96ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(outfd[1]); 97ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(infd[0]); 98ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(infd[1]); 99ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov for (int fd = getdtablesize(); fd > 2; fd--) 100ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(fd); 10152d08d8412bfa4ccfa38384d781b51e8774807a7Alexey Samsonov execl(path_to_symbolizer, path_to_symbolizer, kSymbolizerArch, (char*)0); 102ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal__exit(1); 103ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov } 104ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov 105ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov // Continue execution in parent process. 106ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(outfd[0]); 107ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov internal_close(infd[1]); 108ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov *input_fd = infd[0]; 109ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov *output_fd = outfd[1]; 110ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov 111ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov // Check that symbolizer subprocess started successfully. 112ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov int pid_status; 113ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov SleepForMillis(kSymbolizerStartupTimeMillis); 114ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov int exited_pid = waitpid(pid, &pid_status, WNOHANG); 115ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov if (exited_pid != 0) { 116ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov // Either waitpid failed, or child has already exited. 117ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov Report("WARNING: external symbolizer didn't start up correctly!\n"); 118ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov return false; 119ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov } 120ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov 121ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov return true; 122ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov} 123ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov 124ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov 125ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov} // namespace __sanitizer 126ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov 127ff0ce7fbdba7d02dd06bbb1ba1003c50355513dfAlexey Samsonov#endif // SANITIZER_POSIX 128