2019-04-01 15:27:11 +08:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Zend Engine |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| This source file is subject to version 2.00 of the Zend license, |
|
|
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
|
|
| available through the world-wide-web at the following url: |
|
|
|
|
| http://www.zend.com/license/2_00.txt. |
|
|
|
|
| If you did not receive a copy of the Zend license and are unable to |
|
|
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
|
|
| license@zend.com so we can mail you a copy immediately. |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Authors: Dmitry Stogov <dmitry@zend.com> |
|
|
|
|
| Xinchen Hui <xinchen.h@zend.com> |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "zend.h"
|
|
|
|
#include "zend_gdb.h"
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2023-07-09 17:48:01 +08:00
|
|
|
#if defined(__FreeBSD__) && __FreeBSD_version >= 1100000
|
2021-12-11 17:07:42 +08:00
|
|
|
# include <sys/user.h>
|
|
|
|
# include <libutil.h>
|
|
|
|
#endif
|
|
|
|
|
2019-04-01 15:27:11 +08:00
|
|
|
enum {
|
|
|
|
ZEND_GDBJIT_NOACTION,
|
|
|
|
ZEND_GDBJIT_REGISTER,
|
|
|
|
ZEND_GDBJIT_UNREGISTER
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _zend_gdbjit_code_entry {
|
|
|
|
struct _zend_gdbjit_code_entry *next_entry;
|
|
|
|
struct _zend_gdbjit_code_entry *prev_entry;
|
|
|
|
const char *symfile_addr;
|
|
|
|
uint64_t symfile_size;
|
|
|
|
} zend_gdbjit_code_entry;
|
|
|
|
|
|
|
|
typedef struct _zend_gdbjit_descriptor {
|
|
|
|
uint32_t version;
|
|
|
|
uint32_t action_flag;
|
|
|
|
struct _zend_gdbjit_code_entry *relevant_entry;
|
|
|
|
struct _zend_gdbjit_code_entry *first_entry;
|
|
|
|
} zend_gdbjit_descriptor;
|
|
|
|
|
|
|
|
ZEND_API zend_gdbjit_descriptor __jit_debug_descriptor = {
|
|
|
|
1, ZEND_GDBJIT_NOACTION, NULL, NULL
|
|
|
|
};
|
|
|
|
|
2021-05-12 21:55:23 +08:00
|
|
|
ZEND_API zend_never_inline void __jit_debug_register_code(void)
|
2019-04-01 15:27:11 +08:00
|
|
|
{
|
|
|
|
__asm__ __volatile__("");
|
|
|
|
}
|
|
|
|
|
2020-08-28 21:41:27 +08:00
|
|
|
ZEND_API bool zend_gdb_register_code(const void *object, size_t size)
|
2019-04-01 15:27:11 +08:00
|
|
|
{
|
|
|
|
zend_gdbjit_code_entry *entry;
|
|
|
|
|
|
|
|
entry = malloc(sizeof(zend_gdbjit_code_entry) + size);
|
|
|
|
if (entry == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
entry->symfile_addr = ((char*)entry) + sizeof(zend_gdbjit_code_entry);
|
|
|
|
entry->symfile_size = size;
|
|
|
|
|
|
|
|
memcpy((char *)entry->symfile_addr, object, size);
|
|
|
|
|
|
|
|
entry->prev_entry = NULL;
|
|
|
|
entry->next_entry = __jit_debug_descriptor.first_entry;
|
|
|
|
|
|
|
|
if (entry->next_entry) {
|
|
|
|
entry->next_entry->prev_entry = entry;
|
|
|
|
}
|
|
|
|
__jit_debug_descriptor.first_entry = entry;
|
|
|
|
|
|
|
|
/* Notify GDB */
|
|
|
|
__jit_debug_descriptor.relevant_entry = entry;
|
|
|
|
__jit_debug_descriptor.action_flag = ZEND_GDBJIT_REGISTER;
|
|
|
|
__jit_debug_register_code();
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_API void zend_gdb_unregister_all(void)
|
|
|
|
{
|
|
|
|
zend_gdbjit_code_entry *entry;
|
|
|
|
|
|
|
|
__jit_debug_descriptor.action_flag = ZEND_GDBJIT_UNREGISTER;
|
|
|
|
while ((entry = __jit_debug_descriptor.first_entry)) {
|
|
|
|
__jit_debug_descriptor.first_entry = entry->next_entry;
|
|
|
|
if (entry->next_entry) {
|
|
|
|
entry->next_entry->prev_entry = NULL;
|
|
|
|
}
|
|
|
|
/* Notify GDB */
|
|
|
|
__jit_debug_descriptor.relevant_entry = entry;
|
|
|
|
__jit_debug_register_code();
|
|
|
|
|
|
|
|
free(entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-28 21:41:27 +08:00
|
|
|
ZEND_API bool zend_gdb_present(void)
|
2019-04-01 15:27:11 +08:00
|
|
|
{
|
2020-08-28 21:41:27 +08:00
|
|
|
bool ret = 0;
|
2021-12-11 17:07:42 +08:00
|
|
|
#if defined(__linux__) /* netbsd while having this procfs part, does not hold the tracer pid */
|
2019-04-01 15:27:11 +08:00
|
|
|
int fd = open("/proc/self/status", O_RDONLY);
|
|
|
|
|
2023-06-03 00:54:58 +08:00
|
|
|
if (fd >= 0) {
|
2019-04-01 15:27:11 +08:00
|
|
|
char buf[1024];
|
|
|
|
ssize_t n = read(fd, buf, sizeof(buf) - 1);
|
|
|
|
char *s;
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
if (n > 0) {
|
|
|
|
buf[n] = 0;
|
|
|
|
s = strstr(buf, "TracerPid:");
|
|
|
|
if (s) {
|
|
|
|
s += sizeof("TracerPid:") - 1;
|
|
|
|
while (*s == ' ' || *s == '\t') {
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
pid = atoi(s);
|
|
|
|
if (pid) {
|
2019-04-15 17:03:11 +08:00
|
|
|
char out[1024];
|
2024-06-10 01:38:01 +08:00
|
|
|
snprintf(buf, sizeof(buf), "/proc/%d/exe", (int)pid);
|
2019-04-15 17:03:11 +08:00
|
|
|
if (readlink(buf, out, sizeof(out) - 1) > 0) {
|
|
|
|
if (strstr(out, "gdb")) {
|
2019-04-01 15:27:11 +08:00
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
}
|
2023-07-09 17:48:01 +08:00
|
|
|
#elif defined(__FreeBSD__) && __FreeBSD_version >= 1100000
|
2021-12-11 17:07:42 +08:00
|
|
|
struct kinfo_proc *proc = kinfo_getproc(getpid());
|
|
|
|
|
|
|
|
if (proc) {
|
|
|
|
if ((proc->ki_flag & P_TRACED) != 0) {
|
|
|
|
struct kinfo_proc *dbg = kinfo_getproc(proc->ki_tracer);
|
|
|
|
|
|
|
|
ret = (dbg && strstr(dbg->ki_comm, "gdb"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2019-04-01 15:27:11 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|