Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "absl/debugging/internal/address_is_readable.h"
00019
00020 #if !defined(__linux__) || defined(__ANDROID__)
00021
00022 namespace absl {
00023 namespace debugging_internal {
00024
00025
00026 bool AddressIsReadable(const void* ) { return true; }
00027
00028 }
00029 }
00030
00031 #else
00032
00033 #include <fcntl.h>
00034 #include <sys/syscall.h>
00035 #include <unistd.h>
00036 #include <atomic>
00037 #include <cerrno>
00038 #include <cstdint>
00039
00040 #include "absl/base/internal/raw_logging.h"
00041
00042 namespace absl {
00043 namespace debugging_internal {
00044
00045
00046
00047 static uint64_t Pack(uint64_t pid, uint64_t read_fd, uint64_t write_fd) {
00048 ABSL_RAW_CHECK((read_fd >> 24) == 0 && (write_fd >> 24) == 0,
00049 "fd out of range");
00050 return (pid << 48) | ((read_fd & 0xffffff) << 24) | (write_fd & 0xffffff);
00051 }
00052
00053
00054
00055 static void Unpack(uint64_t x, int *pid, int *read_fd, int *write_fd) {
00056 *pid = x >> 48;
00057 *read_fd = (x >> 24) & 0xffffff;
00058 *write_fd = x & 0xffffff;
00059 }
00060
00061
00062
00063
00064
00065 static std::atomic<uint64_t> pid_and_fds;
00066 bool AddressIsReadable(const void *addr) {
00067 int save_errno = errno;
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 int bytes_written;
00079 int current_pid = getpid() & 0xffff;
00080 do {
00081 int pid;
00082 int read_fd;
00083 int write_fd;
00084 uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
00085 Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
00086 while (current_pid != pid) {
00087 int p[2];
00088
00089 if (pipe(p) != 0) {
00090 ABSL_RAW_LOG(FATAL, "Failed to create pipe, errno=%d", errno);
00091 }
00092 fcntl(p[0], F_SETFD, FD_CLOEXEC);
00093 fcntl(p[1], F_SETFD, FD_CLOEXEC);
00094 uint64_t new_pid_and_fds = Pack(current_pid, p[0], p[1]);
00095 if (pid_and_fds.compare_exchange_strong(
00096 local_pid_and_fds, new_pid_and_fds, std::memory_order_relaxed,
00097 std::memory_order_relaxed)) {
00098 local_pid_and_fds = new_pid_and_fds;
00099 } else {
00100 close(p[0]);
00101 close(p[1]);
00102 local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
00103 }
00104 Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
00105 }
00106 errno = 0;
00107
00108
00109
00110 do {
00111 bytes_written = syscall(SYS_write, write_fd, addr, 1);
00112 } while (bytes_written == -1 && errno == EINTR);
00113 if (bytes_written == 1) {
00114 char c;
00115 while (read(read_fd, &c, 1) == -1 && errno == EINTR) {
00116 }
00117 }
00118 if (errno == EBADF) {
00119
00120
00121 pid_and_fds.compare_exchange_strong(local_pid_and_fds, 0,
00122 std::memory_order_relaxed,
00123 std::memory_order_relaxed);
00124 }
00125 } while (errno == EBADF);
00126 errno = save_errno;
00127 return bytes_written == 1;
00128 }
00129
00130 }
00131 }
00132
00133 #endif