Ejemplo n.º 1
0
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);
	}
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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));
}
Ejemplo n.º 4
0
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));
		}
	}
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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);
	}
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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;
}