Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

There may or may not be a readable ZEND_TRACE_OP_INFO() #2942

Merged
merged 2 commits into from
Nov 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion zend_abstract_interface/jit_utils/jit_blacklist.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ typedef union _zend_op_trace_info {

#define ZEND_OP_TRACE_INFO(opline, offset) \
((zend_op_trace_info*)(((char*)opline) + offset))

#ifndef _WIN32
static int dd_probe_pipes[2];
#endif
#endif

#define ZEND_FUNC_INFO(op_array) \
Expand All @@ -103,6 +107,9 @@ static void zai_jit_find_opcache_handle(void *ext) {

// opcache startup NULLs its handle. MINIT is executed before extension startup.
void zai_jit_minit(void) {
#if PHP_VERSION_ID < 80400 && !defined(_WIN32)
pipe(dd_probe_pipes);
#endif
zend_llist_apply(&zend_extensions, zai_jit_find_opcache_handle);
}

Expand Down Expand Up @@ -188,7 +195,7 @@ void zai_jit_blacklist_function_inlining(zend_op_array *op_array) {
if (zai_get_zend_func_rid(op_array) < 0) {
return;
}
// now in PHP < 8.1, zend_func_info_rid is set
// now in PHP < 8.1, zend_func_info_rid is set (on newer versions it's in zend_func_info.h)

zend_jit_op_array_trace_extension *jit_extension = (zend_jit_op_array_trace_extension *)ZEND_FUNC_INFO(op_array);
if (!jit_extension) {
Expand All @@ -203,6 +210,16 @@ void zai_jit_blacklist_function_inlining(zend_op_array *op_array) {

size_t offset = jit_extension->offset;

#ifndef _WIN32
// check whether the op_trace_info is actually readable or EFAULTing
// we can't trust opcache too much here...
char dummy_buf[sizeof(zend_op_trace_info)];
if (write(dd_probe_pipes[1], ZEND_OP_TRACE_INFO(opline, offset), sizeof(zend_op_trace_info)) < 0) {
return;
}
read(dd_probe_pipes[0], dummy_buf, sizeof(zend_op_trace_info));
Comment on lines +217 to +220
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I came across the mincore function; could it be a simpler alternative?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish I could use it, but it requires glibc 2.19. Whereas we currently target 2.17.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something, something, drop CentOS 7... :D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use syscall directly and reference the syscall numbers and parameters in this table.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cataphract I suppose that will work, but using write() has the advantage of not being linux specific either.

#endif

if (!(ZEND_OP_TRACE_INFO(opline, offset)->trace_flags & ZEND_JIT_TRACE_BLACKLISTED)) {
bool is_protected_memory = false;
zend_string *protect_memory = zend_string_init(ZEND_STRL("opcache.protect_memory"), 0);
Expand Down
Loading