static void zend_jit_perf_jitdump_register(const char *name, void *start, size_t size) { if (jitdump_fd >= 0) { static uint64_t id = 1; zend_perf_jitdump_load_record rec; size_t len = strlen(name); uint32_t thread_id; #if defined(__linux__) thread_id = syscall(SYS_gettid); #elif defined(__FreeBSD__) long tid; thr_self(&tid); thread_id = (uint32_t)tid; #elif defined(__OpenBSD__) thread_id = getthrid(); #elif defined(__NetBSD__) thread_id = _lwp_self(); #endif memset(&rec, 0, sizeof(rec)); rec.hdr.event = ZEND_PERF_JITDUMP_RECORD_LOAD; rec.hdr.size = sizeof(rec) + len + 1 + size; rec.hdr.time_stamp = zend_perf_timestamp(); rec.process_id = getpid(); rec.thread_id = thread_id; rec.vma = (uint64_t)(uintptr_t)start; rec.code_address = (uint64_t)(uintptr_t)start; rec.code_size = (uint64_t)size; rec.code_id = id++; zend_quiet_write(jitdump_fd, &rec, sizeof(rec)); zend_quiet_write(jitdump_fd, name, len + 1); zend_quiet_write(jitdump_fd, start, size); } }
static int phpdbg_output_pager(int sock, const char *ptr, int len) { int count = 0, bytes = 0; const char *p = ptr, *endp = ptr + len; while ((p = memchr(p, '\n', endp - p))) { count++; p++; if (count % PHPDBG_G(lines) == 0) { bytes += write(sock, ptr + bytes, (p - ptr) - bytes); if (memchr(p, '\n', endp - p)) { char buf[PHPDBG_MAX_CMD]; zend_quiet_write(sock, ZEND_STRL("\r---Type <return> to continue or q <return> to quit---")); phpdbg_consume_stdin_line(buf); if (*buf == 'q') { break; } write(sock, "\r", 1); } else break; } } if (bytes && count % PHPDBG_G(lines) != 0) { bytes += write(sock, ptr + bytes, len - bytes); } else if (!bytes) { bytes += write(sock, ptr, len); } return bytes; }
static void zend_jit_perf_jitdump_open(void) { char filename[64]; int fd, ret; zend_elf_header elf_hdr; zend_perf_jitdump_header jit_hdr; sprintf(filename, "/tmp/jit-%d.dump", getpid()); if (!zend_perf_timestamp()) { return; } fd = open("/proc/self/exe", O_RDONLY); if (fd < 0) { return; } ret = read(fd, &elf_hdr, sizeof(elf_hdr)); close(fd); if (ret != sizeof(elf_hdr) || elf_hdr.emagic[0] != 0x7f || elf_hdr.emagic[1] != 'E' || elf_hdr.emagic[2] != 'L' || elf_hdr.emagic[3] != 'F') { return; } jitdump_fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0666); if (jitdump_fd < 0) { return; } jitdump_mem = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_EXEC, MAP_PRIVATE, jitdump_fd, 0); if (jitdump_mem == MAP_FAILED) { close(jitdump_fd); jitdump_fd = -1; return; } memset(&jit_hdr, 0, sizeof(jit_hdr)); jit_hdr.magic = ZEND_PERF_JITDUMP_HEADER_MAGIC; jit_hdr.version = ZEND_PERF_JITDUMP_HEADER_VERSION; jit_hdr.size = sizeof(jit_hdr); jit_hdr.elf_mach_target = elf_hdr.machine; jit_hdr.process_id = getpid(); jit_hdr.time_stamp = zend_perf_timestamp(); jit_hdr.flags = 0; zend_quiet_write(jitdump_fd, &jit_hdr, sizeof(jit_hdr)); }
static void zend_jit_perf_jitdump_close(void) { if (jitdump_fd >= 0) { zend_perf_jitdump_record rec; rec.event = ZEND_PERF_JITDUMP_RECORD_CLOSE; rec.size = sizeof(rec); rec.time_stamp = zend_perf_timestamp(); zend_quiet_write(jitdump_fd, &rec, sizeof(rec)); close(jitdump_fd); if (jitdump_mem != MAP_FAILED) { munmap(jitdump_mem, sysconf(_SC_PAGESIZE)); } } }
static void sig_handler(int signo) /* {{{ */ { static const char sig_chars[NSIG + 1] = { [SIGTERM] = 'T', [SIGINT] = 'I', [SIGUSR1] = '1', [SIGUSR2] = '2', [SIGQUIT] = 'Q', [SIGCHLD] = 'C' }; char s; int saved_errno; if (fpm_globals.parent_pid != getpid()) { /* prevent a signal race condition when child process have not set up it's own signal handler yet */ return; } saved_errno = errno; s = sig_chars[signo]; zend_quiet_write(sp[1], &s, sizeof(s)); errno = saved_errno; }
void vzlog(const char *function, int line, int flags, const char *fmt, va_list args) /* {{{ */ { struct timeval tv; char buf[MAX_LINE_LENGTH]; const size_t buf_size = MAX_LINE_LENGTH; size_t len = 0; int truncated = 0; int saved_errno; if (external_logger) { va_list ap; va_copy(ap, args); len = vsnprintf(buf, buf_size, fmt, ap); va_end(ap); if (len >= buf_size) { memcpy(buf + buf_size - sizeof("..."), "...", sizeof("...") - 1); len = buf_size - 1; } external_logger(flags & ZLOG_LEVEL_MASK, buf, len); len = 0; memset(buf, '\0', buf_size); } if ((flags & ZLOG_LEVEL_MASK) < zlog_level) { return; } saved_errno = errno; #ifdef HAVE_SYSLOG_H if (zlog_fd == ZLOG_SYSLOG /* && !fpm_globals.is_child */) { len = 0; if (zlog_level == ZLOG_DEBUG) { len += snprintf(buf, buf_size, "[%s] %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], function, line); } else { len += snprintf(buf, buf_size, "[%s] ", level_names[flags & ZLOG_LEVEL_MASK]); } } else #endif { if (!fpm_globals.is_child) { gettimeofday(&tv, 0); len = zlog_print_time(&tv, buf, buf_size); } if (zlog_level == ZLOG_DEBUG) { if (!fpm_globals.is_child) { len += snprintf(buf + len, buf_size - len, "%s: pid %d, %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], getpid(), function, line); } else { len += snprintf(buf + len, buf_size - len, "%s: %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], function, line); } } else { len += snprintf(buf + len, buf_size - len, "%s: ", level_names[flags & ZLOG_LEVEL_MASK]); } } if (len > buf_size - 1) { truncated = 1; } if (!truncated) { len += vsnprintf(buf + len, buf_size - len, fmt, args); if (len >= buf_size) { truncated = 1; } } if (!truncated) { if (flags & ZLOG_HAVE_ERRNO) { len += snprintf(buf + len, buf_size - len, ": %s (%d)", strerror(saved_errno), saved_errno); if (len >= buf_size) { truncated = 1; } } } if (truncated) { memcpy(buf + buf_size - sizeof("..."), "...", sizeof("...") - 1); len = buf_size - 1; } #ifdef HAVE_SYSLOG_H if (zlog_fd == ZLOG_SYSLOG) { buf[len] = '\0'; php_syslog(syslog_priorities[zlog_level], "%s", buf); buf[len++] = '\n'; } else #endif { buf[len++] = '\n'; zend_quiet_write(zlog_fd > -1 ? zlog_fd : STDERR_FILENO, buf, len); } if (zlog_fd != STDERR_FILENO && zlog_fd != -1 && !launched && (flags & ZLOG_LEVEL_MASK) >= ZLOG_NOTICE) { zend_quiet_write(STDERR_FILENO, buf, len); } }
PHPDBG_API int phpdbg_consume_bytes(int sock, char *ptr, int len, int tmo) { int got_now, i = len, j; char *p = ptr; #ifndef PHP_WIN32 struct pollfd pfd; if (tmo < 0) goto recv_once; pfd.fd = sock; pfd.events = POLLIN; j = poll(&pfd, 1, tmo); if (j == 0) { #else struct fd_set readfds; struct timeval ttmo; if (tmo < 0) goto recv_once; FD_ZERO(&readfds); FD_SET(sock, &readfds); ttmo.tv_sec = 0; ttmo.tv_usec = tmo*1000; j = select(0, &readfds, NULL, NULL, &ttmo); if (j <= 0) { #endif return -1; } recv_once: while(i > 0) { if (tmo < 0) { /* There's something to read. Read what's available and proceed disregarding whether len could be exhausted or not.*/ int can_read = recv(sock, p, i, MSG_PEEK); #ifndef _WIN32 if (can_read == -1 && errno == EINTR) { continue; } #endif i = can_read; } #ifdef _WIN32 got_now = recv(sock, p, i, 0); #else do { got_now = recv(sock, p, i, 0); } while (got_now == -1 && errno == EINTR); #endif if (got_now == -1) { zend_quiet_write(PHPDBG_G(io)[PHPDBG_STDERR].fd, ZEND_STRL("Read operation timed out!\n")); return -1; } i -= got_now; p += got_now; } return p - ptr; } PHPDBG_API int phpdbg_send_bytes(int sock, const char *ptr, int len) { int sent, i = len; const char *p = ptr; /* XXX poll/select needed here? */ while(i > 0) { sent = send(sock, p, i, 0); if (sent == -1) { return -1; } i -= sent; p += sent; } return len; }
PHPDBG_API int phpdbg_create_listenable_socket(const char *addr, unsigned short port, struct addrinfo *addr_res) { int sock = -1, rc; int reuse = 1; struct in6_addr serveraddr; struct addrinfo hints, *res = NULL; char port_buf[8]; int8_t any_addr = *addr == '*'; do { memset(&hints, 0, sizeof hints); if (any_addr) { hints.ai_flags = AI_PASSIVE; } else { hints.ai_flags = AI_NUMERICSERV; } hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; rc = inet_pton(AF_INET, addr, &serveraddr); if (1 == rc) { hints.ai_family = AF_INET; if (!any_addr) { hints.ai_flags |= AI_NUMERICHOST; } } else { rc = inet_pton(AF_INET6, addr, &serveraddr); if (1 == rc) { hints.ai_family = AF_INET6; if (!any_addr) { hints.ai_flags |= AI_NUMERICHOST; } } else { /* XXX get host by name ??? */ } } snprintf(port_buf, 7, "%u", port); if (!any_addr) { rc = getaddrinfo(addr, port_buf, &hints, &res); } else { rc = getaddrinfo(NULL, port_buf, &hints, &res); } if (0 != rc) { #ifndef PHP_WIN32 if (rc == EAI_SYSTEM) { char buf[128]; int wrote; wrote = snprintf(buf, 128, "Could not translate address '%s'", addr); buf[wrote] = '\0'; zend_quiet_write(PHPDBG_G(io)[PHPDBG_STDERR].fd, buf, strlen(buf)); return sock; } else { #endif char buf[256]; int wrote; wrote = snprintf(buf, 256, "Host '%s' not found. %s", addr, estrdup(gai_strerror(rc))); buf[wrote] = '\0'; zend_quiet_write(PHPDBG_G(io)[PHPDBG_STDERR].fd, buf, strlen(buf)); return sock; #ifndef PHP_WIN32 } #endif return sock; } if((sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) { char buf[128]; int wrote; wrote = sprintf(buf, "Unable to create socket"); buf[wrote] = '\0'; zend_quiet_write(PHPDBG_G(io)[PHPDBG_STDERR].fd, buf, strlen(buf)); return sock; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse, sizeof(reuse)) == -1) { phpdbg_close_socket(sock); return sock; } } while (0); *addr_res = *res; return sock; }