mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
zend_call_stack_get implementation for NetBSD.
Despite being OpenBSD's predecessor, the approach is in fact a lot closer to Linux, at least in principle. We purposely avoid reading /proc/N/maps to be more future-proof. Close GH-11637
This commit is contained in:
1
NEWS
1
NEWS
@@ -7,6 +7,7 @@ Core:
|
||||
closures). (ilutov)
|
||||
. Fixed bug GH-12102 (Incorrect compile error when using array access on TMP
|
||||
value in function call). (ilutov)
|
||||
. Added zend_call_stack_get implementation for NetBSD. (David Carlier)
|
||||
|
||||
DOM:
|
||||
. Added DOMNode::compareDocumentPosition(). (nielsdos)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
#endif /* ZEND_WIN32 */
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__)
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
@@ -51,6 +51,10 @@ typedef int boolean_t;
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/user.h>
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/syscall.h>
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
@@ -504,6 +508,119 @@ static bool zend_call_stack_get_openbsd(zend_call_stack *stack)
|
||||
}
|
||||
#endif /* defined(__OpenBSD__) */
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
# ifdef HAVE_PTHREAD_GETATTR_NP
|
||||
static bool zend_call_stack_get_netbsd_pthread(zend_call_stack *stack)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
int error;
|
||||
void *addr;
|
||||
size_t max_size, guard_size;
|
||||
|
||||
error = pthread_getattr_np(pthread_self(), &attr);
|
||||
if (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
error = pthread_attr_getstack(&attr, &addr, &max_size);
|
||||
if (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
error = pthread_attr_getguardsize(&attr, &guard_size);
|
||||
if (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
addr = (char *)addr + guard_size;
|
||||
max_size -= guard_size;
|
||||
|
||||
stack->base = (char *)addr + max_size;
|
||||
stack->max_size = max_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
# else
|
||||
static bool zend_call_stack_get_netbsd_pthread(zend_call_stack *stack)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
# endif /* HAVE_PTHREAD_GETATTR_NP */
|
||||
static bool zend_call_stack_get_netbsd_vm(zend_call_stack *stack, void **ptr)
|
||||
{
|
||||
/**
|
||||
* NetBSD supports procfs in a similar fashion as Linux
|
||||
* however NetBSD's mid/long term plan is to remove it completely.
|
||||
*/
|
||||
char *start, *end;
|
||||
struct kinfo_vmentry *entry;
|
||||
size_t len, max_size;
|
||||
char buffer[4096];
|
||||
uintptr_t addr_on_stack = (uintptr_t)&buffer;
|
||||
int mib[5] = { CTL_VM, VM_PROC, VM_PROC_MAP, getpid(), sizeof(struct kinfo_vmentry) };
|
||||
bool found = false;
|
||||
struct rlimit rlim;
|
||||
|
||||
if (sysctl(mib, 5, NULL, &len, NULL, 0) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// kinfo_getvmmap uses the same formula, only we do not want to rely on libkvm
|
||||
len = len * 4 / 3 ;
|
||||
*ptr = malloc(len);
|
||||
|
||||
if (sysctl(mib, 5, *ptr, &len, NULL, 0) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
start = (char *)*ptr;
|
||||
end = start + len;
|
||||
|
||||
while (start < end) {
|
||||
entry = (struct kinfo_vmentry *)start;
|
||||
if (entry->kve_start <= addr_on_stack && entry->kve_end >= addr_on_stack) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
start += sizeof(struct kinfo_vmentry);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getrlimit(RLIMIT_STACK, &rlim) || rlim.rlim_cur == RLIM_INFINITY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
max_size = rlim.rlim_cur;
|
||||
|
||||
stack->base = (void *)entry->kve_end;
|
||||
stack->max_size = max_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool zend_call_stack_get_netbsd(zend_call_stack *stack)
|
||||
{
|
||||
if (syscall(SYS__lwp_self) == 1) {
|
||||
void *ptr = NULL;
|
||||
bool r = zend_call_stack_get_netbsd_vm(stack, &ptr);
|
||||
free(ptr);
|
||||
return r;
|
||||
}
|
||||
|
||||
return zend_call_stack_get_netbsd_pthread(stack);
|
||||
}
|
||||
#else
|
||||
static bool zend_call_stack_get_netbsd(zend_call_stack *stack)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* defined(__NetBSD__) */
|
||||
|
||||
/** Get the stack information for the calling thread */
|
||||
ZEND_API bool zend_call_stack_get(zend_call_stack *stack)
|
||||
{
|
||||
@@ -527,6 +644,10 @@ ZEND_API bool zend_call_stack_get(zend_call_stack *stack)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (zend_call_stack_get_netbsd(stack)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user