Skip to content

JIT fault #11127

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

Closed
EvgenijKrupchenko opened this issue Apr 24, 2023 · 9 comments · Fixed by ThePHPF/thephp.foundation#90
Closed

JIT fault #11127

EvgenijKrupchenko opened this issue Apr 24, 2023 · 9 comments · Fixed by ThePHPF/thephp.foundation#90

Comments

@EvgenijKrupchenko
Copy link

EvgenijKrupchenko commented Apr 24, 2023

Description

This bug was accidentally noticed in complex production scripts and was very hard to manually reproduce in a simple example. But nevermind, here's a working example below.
I use two files:

1.php:

<?
include('2.php');
for($a=1;$a<100;$a++){
        echo _f('1');
        echo _f('1');
        echo _f('1');
}
?>

2.php:

<?
define('C','1');
function _f($u){
        return $u==C?'0':'1';
}
?>

In short: the script is using multiple times a function, that is located in another php script file.
Under php 8.2, 8.1 and 8.0 - same results.
Under php-fpm and under apache/mod_php - same result.
Under php-cli - bug not reproducible

Steps to do:

  1. Restart the backend (php-fpm or apache/mod_php)
  2. Open in browser 1.php - works fine
  3. Make any changes to 2.php or simply run "touch 2.php" to only modify the time of that file
  4. Refresh the page with 1.php - Nginx (frontend) says "502 Bad Gateway" with log:
    upstream prematurely closed connection while reading response header from upstream

Apache error log empty.
Php-fpm error log says something like:
[24-Apr-2023 18:21:07] WARNING: [pool u10] child 71477 exited on signal 11 (SIGSEGV) after 20.735545 seconds from start
[24-Apr-2023 18:21:07] NOTICE: [pool u10] child 71484 started

php.ini:
opcache.jit_buffer_size=128M

When only i add:
opcache.jit=1205
The bug disappear, but php performance become a bit slower.

And also setting opcache.jit_buffer_size=0 solves the bug as well as slowing down the performance of course.

I have no clue what's going on, but something is clearly becomes wrong causing the executing process to crash.

PHP Version

php 8.2.5 8.1.18 8.0.28

Operating System

Debian 11

@iluuu1994
Copy link
Member

Just for clarification, are the two files missing, or are they empty?

@EvgenijKrupchenko
Copy link
Author

Sorry, my first post here.
Fixed

@iluuu1994
Copy link
Member

I can reproduce this with the cli-server SAPI, which might be a bit simpler.

php-dev -d zend_extension=$(pwd)/modules/opcache.so -d opcache.enable_cli=1 -d opcache.jit_buffer_size=16M -S localhost:0 1.php

1.php, for convenience.

<?php
include('2.php');
for($a=1;$a<100;$a++){
        echo _f('1');
        echo _f('1');
        echo _f('1');
}
touch('2.php');
?>
=================================================================
==544293==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x000049e53d6b bp 0x7ffe57e368c0 sp 0x7ffe57e36650 T0)
==544293==The signal is caused by a READ memory access.
==544293==Hint: address points to the zero page.
    #0 0x49e53d6b  (/dev/zero (deleted)+0x8000d6b)
    #1 0x19c8806 in zend_execute /home/ilutov/Developer/php-src/Zend/zend_vm_execute.h:60151
    #2 0x161814a in zend_execute_scripts /home/ilutov/Developer/php-src/Zend/zend.c:1846
    #3 0x1d8e689 in php_cli_server_dispatch_router /home/ilutov/Developer/php-src/sapi/cli/php_cli_server.c:2165
    #4 0x1d8ee4a in php_cli_server_dispatch /home/ilutov/Developer/php-src/sapi/cli/php_cli_server.c:2205
    #5 0x1d91924 in php_cli_server_recv_event_read_request /home/ilutov/Developer/php-src/sapi/cli/php_cli_server.c:2534
    #6 0x1d92b48 in php_cli_server_do_event_for_each_fd_callback /home/ilutov/Developer/php-src/sapi/cli/php_cli_server.c:2621
    #7 0x1d7e407 in php_cli_server_poller_iter_on_active /home/ilutov/Developer/php-src/sapi/cli/php_cli_server.c:869
    #8 0x1d92dc6 in php_cli_server_do_event_for_each_fd /home/ilutov/Developer/php-src/sapi/cli/php_cli_server.c:2639
    #9 0x1d92f9c in php_cli_server_do_event_loop /home/ilutov/Developer/php-src/sapi/cli/php_cli_server.c:2649
    #10 0x1d93863 in do_cli_server /home/ilutov/Developer/php-src/sapi/cli/php_cli_server.c:2779
    #11 0x1d6a30f in main /home/ilutov/Developer/php-src/sapi/cli/php_cli.c:1370
    #12 0x7f4ac2648b49 in __libc_start_call_main (/lib64/libc.so.6+0x27b49) (BuildId: 6107835fa7d4725691b2b7f6aaee7abe09f493b2)
    #13 0x7f4ac2648c0a in __libc_start_main_alias_2 (/lib64/libc.so.6+0x27c0a) (BuildId: 6107835fa7d4725691b2b7f6aaee7abe09f493b2)
    #14 0x603d14 in _start (/home/ilutov/Developer/php-src/sapi/cli/php+0x603d14) (BuildId: 4b5fc529cf17fc0d6804810be552f9c3aa55bfe4)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/dev/zero (deleted)+0x8000d6b)

@iluuu1994
Copy link
Member

@dstogov Can you help here? This is beyond my expertise.

Disassembled JIT code

Dump of assembler code for function TRACE-3$/home/ilutov/Developer/php-src/1.php$4:
   0x0000000048000c20 <+0>:	mov    DWORD PTR ds:0x181edb8,0x3
   0x0000000048000c2b <+11>:	cmp    BYTE PTR [r14+0x68],0x6
   0x0000000048000c30 <+16>:	jne    0x48000970 <jit$$trace_exit_0>
   0x0000000048000c36 <+22>:	mov    QWORD PTR [r14],r15
   0x0000000048000c39 <+25>:	mov    rax,QWORD PTR [r14+0x60]
   0x0000000048000c3d <+29>:	lea    rdi,[rax+0x18]
   0x0000000048000c41 <+33>:	mov    rsi,QWORD PTR [rax+0x10]
   0x0000000048000c45 <+37>:	call   0x968d8f <php_output_write>
   0x0000000048000c4a <+42>:	test   BYTE PTR [r14+0x69],0x1
   0x0000000048000c4f <+47>:	je     0x48000c62 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+66>
   0x0000000048000c51 <+49>:	mov    rdi,QWORD PTR [r14+0x60]
   0x0000000048000c55 <+53>:	sub    DWORD PTR [rdi],0x1
   0x0000000048000c58 <+56>:	jne    0x48000c62 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+66>
   0x0000000048000c5a <+58>:	mov    QWORD PTR [r14],r15
   0x0000000048000c5d <+61>:	call   0x9e452c <rc_dtor_func>
   0x0000000048000c62 <+66>:	cmp    QWORD PTR ds:0x181ef20,0x0
   0x0000000048000c6b <+75>:	jne    0x48000020 <JIT$$exception_handler>
   0x0000000048000c71 <+81>:	mov    rdx,QWORD PTR [r14+0x40]
   0x0000000048000c75 <+85>:	mov    rax,QWORD PTR [rdx+0x8]
   0x0000000048000c79 <+89>:	test   rax,rax
   0x0000000048000c7c <+92>:	je     0x48000f8e <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+878>
   0x0000000048000c82 <+98>:	mov    r15,QWORD PTR ds:0x181ed88
   0x0000000048000c8a <+106>:	mov    rdx,QWORD PTR ds:0x181ed90
   0x0000000048000c92 <+114>:	sub    rdx,r15
   0x0000000048000c95 <+117>:	cmp    rdx,0x80
   0x0000000048000c9c <+124>:	jb     0x48000978 <jit$$trace_exit_0+8>
   0x0000000048000ca2 <+130>:	add    QWORD PTR ds:0x181ed88,0x80
   0x0000000048000cae <+142>:	mov    DWORD PTR [r15+0x28],0x0
   0x0000000048000cb6 <+150>:	mov    QWORD PTR [r15+0x18],rax
   0x0000000048000cba <+154>:	mov    QWORD PTR [r15+0x20],0x0
   0x0000000048000cc2 <+162>:	mov    DWORD PTR [r15+0x2c],0x1
   0x0000000048000cca <+170>:	mov    QWORD PTR [r15+0x50],0x40200890
   0x0000000048000cd2 <+178>:	mov    DWORD PTR [r15+0x58],0x6
   0x0000000048000cda <+186>:	mov    QWORD PTR [r14],0x408d4790
   0x0000000048000ce1 <+193>:	mov    QWORD PTR [r15+0x30],r14
   0x0000000048000ce5 <+197>:	mov    QWORD PTR [r15+0x8],0x0
   0x0000000048000ced <+205>:	lea    rdx,[r14+0x60]
   0x0000000048000cf1 <+209>:	mov    QWORD PTR [r15+0x10],rdx
   0x0000000048000cf5 <+213>:	mov    rdx,QWORD PTR ds:0x181eb60
   0x0000000048000cfd <+221>:	mov    rdx,QWORD PTR [rdx+0x551]
   0x0000000048000d04 <+228>:	mov    QWORD PTR [r15+0x40],rdx
   0x0000000048000d08 <+232>:	mov    QWORD PTR ds:0x181eda8,r15
   0x0000000048000d10 <+240>:	mov    r14,r15
   0x0000000048000d13 <+243>:	mov    rdi,QWORD PTR [r14+0x40]
=> 0x0000000048000d17 <+247>:	mov    rax,QWORD PTR [rdi+0x8]
   0x0000000048000d1b <+251>:	test   rax,rax
   0x0000000048000d1e <+254>:	je     0x48000fb7 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+919>
   0x0000000048000d24 <+260>:	test   rax,0x1
   0x0000000048000d2a <+266>:	jne    0x48000fb7 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+919>
   0x0000000048000d30 <+272>:	mov    edx,DWORD PTR [rax+0x8]
   0x0000000048000d33 <+275>:	cmp    dl,0x7
   0x0000000048000d36 <+278>:	jne    0x4800097c <jit$$trace_exit_0+12>
   0x0000000048000d3c <+284>:	mov    rcx,QWORD PTR [rax]
   0x0000000048000d3f <+287>:	mov    QWORD PTR [r14+0x70],rcx
   0x0000000048000d43 <+291>:	mov    DWORD PTR [r14+0x78],edx
   0x0000000048000d47 <+295>:	test   dh,dh
   0x0000000048000d49 <+297>:	je     0x48000d4e <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+302>
   0x0000000048000d4b <+299>:	add    DWORD PTR [rcx],0x1
   0x0000000048000d4e <+302>:	mov    QWORD PTR [r14],0x408d5110
   0x0000000048000d55 <+309>:	lea    rdi,[r14+0x50]
   0x0000000048000d59 <+313>:	lea    rsi,[r14+0x70]
   0x0000000048000d5d <+317>:	call   0x9dfa6d <zend_compare>
   0x0000000048000d62 <+322>:	mov    DWORD PTR [rsp],eax
   0x0000000048000d65 <+325>:	test   BYTE PTR [r14+0x79],0x1
   0x0000000048000d6a <+330>:	je     0x48000d7a <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+346>
   0x0000000048000d6c <+332>:	mov    rdi,QWORD PTR [r14+0x70]
   0x0000000048000d70 <+336>:	sub    DWORD PTR [rdi],0x1
   0x0000000048000d73 <+339>:	jne    0x48000d7a <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+346>
   0x0000000048000d75 <+341>:	call   0x9ffb5a <zend_array_destroy>
   0x0000000048000d7a <+346>:	cmp    QWORD PTR ds:0x181ef20,0x0
   0x0000000048000d83 <+355>:	jne    0x48000030 <JIT$$exception_handler_undef>
   0x0000000048000d89 <+361>:	mov    eax,DWORD PTR [rsp]
   0x0000000048000d8c <+364>:	test   eax,eax
   0x0000000048000d8e <+366>:	je     0x48000980 <jit$$trace_exit_0+16>
   0x0000000048000d94 <+372>:	mov    rcx,QWORD PTR [r14+0x10]
   0x0000000048000d98 <+376>:	mov    QWORD PTR [rcx],0x40200890
   0x0000000048000d9f <+383>:	mov    DWORD PTR [rcx+0x8],0x6
   0x0000000048000da6 <+390>:	mov    rax,QWORD PTR [r14+0x30]
   0x0000000048000daa <+394>:	mov    QWORD PTR ds:0x181eda8,rax
   0x0000000048000db2 <+402>:	test   BYTE PTR [r14+0x59],0x1
   0x0000000048000db7 <+407>:	jne    0x48000fe6 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+966>
   0x0000000048000dbd <+413>:	mov    QWORD PTR ds:0x181ed88,r14
   0x0000000048000dc5 <+421>:	mov    r14,QWORD PTR [r14+0x30]
   0x0000000048000dc9 <+425>:	mov    QWORD PTR [r14],0x408d47b0
   0x0000000048000dd0 <+432>:	mov    rax,QWORD PTR [r14+0x60]
   0x0000000048000dd4 <+436>:	lea    rdi,[rax+0x18]
   0x0000000048000dd8 <+440>:	mov    rsi,QWORD PTR [rax+0x10]
   0x0000000048000ddc <+444>:	call   0x968d8f <php_output_write>
   0x0000000048000de1 <+449>:	test   BYTE PTR [r14+0x69],0x1
   0x0000000048000de6 <+454>:	je     0x48000def <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+463>
   0x0000000048000de8 <+456>:	mov    rdi,QWORD PTR [r14+0x60]
   0x0000000048000dec <+460>:	sub    DWORD PTR [rdi],0x1
   0x0000000048000def <+463>:	cmp    QWORD PTR ds:0x181ef20,0x0
   0x0000000048000df8 <+472>:	jne    0x48000020 <JIT$$exception_handler>
   0x0000000048000dfe <+478>:	mov    rdx,QWORD PTR [r14+0x40]
   0x0000000048000e02 <+482>:	mov    rax,QWORD PTR [rdx+0x8]
   0x0000000048000e06 <+486>:	test   rax,rax
   0x0000000048000e09 <+489>:	je     0x48000ffd <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+989>
   0x0000000048000e0f <+495>:	mov    r15,QWORD PTR ds:0x181ed88
   0x0000000048000e17 <+503>:	add    QWORD PTR ds:0x181ed88,0x80
   0x0000000048000e23 <+515>:	mov    DWORD PTR [r15+0x28],0x0
   0x0000000048000e2b <+523>:	mov    QWORD PTR [r15+0x18],rax
   0x0000000048000e2f <+527>:	mov    QWORD PTR [r15+0x20],0x0
   0x0000000048000e37 <+535>:	mov    DWORD PTR [r15+0x2c],0x1
   0x0000000048000e3f <+543>:	mov    QWORD PTR [r15+0x50],0x40200890
   0x0000000048000e47 <+551>:	mov    DWORD PTR [r15+0x58],0x6
   0x0000000048000e4f <+559>:	mov    QWORD PTR [r14],0x408d4810
   0x0000000048000e56 <+566>:	mov    QWORD PTR [r15+0x30],r14
   0x0000000048000e5a <+570>:	mov    QWORD PTR [r15+0x8],0x0
   0x0000000048000e62 <+578>:	lea    rdx,[r14+0x60]
   0x0000000048000e66 <+582>:	mov    QWORD PTR [r15+0x10],rdx
   0x0000000048000e6a <+586>:	mov    rdx,QWORD PTR ds:0x181eb60
   0x0000000048000e72 <+594>:	mov    rdx,QWORD PTR [rdx+0x551]
   0x0000000048000e79 <+601>:	mov    QWORD PTR [r15+0x40],rdx
   0x0000000048000e7d <+605>:	mov    QWORD PTR ds:0x181eda8,r15
   0x0000000048000e85 <+613>:	mov    r14,r15
   0x0000000048000e88 <+616>:	mov    rdi,QWORD PTR [r14+0x40]
   0x0000000048000e8c <+620>:	mov    rax,QWORD PTR [rdi+0x8]
   0x0000000048000e90 <+624>:	test   rax,rax
   0x0000000048000e93 <+627>:	je     0x48001026 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+1030>
   0x0000000048000e99 <+633>:	test   rax,0x1
   0x0000000048000e9f <+639>:	jne    0x48001026 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+1030>
   0x0000000048000ea5 <+645>:	mov    edx,DWORD PTR [rax+0x8]
   0x0000000048000ea8 <+648>:	cmp    dl,0x7
   0x0000000048000eab <+651>:	jne    0x4800097c <jit$$trace_exit_0+12>
   0x0000000048000eb1 <+657>:	mov    rcx,QWORD PTR [rax]
   0x0000000048000eb4 <+660>:	mov    QWORD PTR [r14+0x70],rcx
   0x0000000048000eb8 <+664>:	mov    DWORD PTR [r14+0x78],edx
   0x0000000048000ebc <+668>:	test   dh,dh
   0x0000000048000ebe <+670>:	je     0x48000ec3 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+675>
   0x0000000048000ec0 <+672>:	add    DWORD PTR [rcx],0x1
   0x0000000048000ec3 <+675>:	mov    QWORD PTR [r14],0x408d5110
   0x0000000048000eca <+682>:	lea    rdi,[r14+0x50]
   0x0000000048000ece <+686>:	lea    rsi,[r14+0x70]
   0x0000000048000ed2 <+690>:	call   0x9dfa6d <zend_compare>
   0x0000000048000ed7 <+695>:	mov    DWORD PTR [rsp],eax
   0x0000000048000eda <+698>:	test   BYTE PTR [r14+0x79],0x1
   0x0000000048000edf <+703>:	je     0x48000eef <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+719>
   0x0000000048000ee1 <+705>:	mov    rdi,QWORD PTR [r14+0x70]
   0x0000000048000ee5 <+709>:	sub    DWORD PTR [rdi],0x1
   0x0000000048000ee8 <+712>:	jne    0x48000eef <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+719>
   0x0000000048000eea <+714>:	call   0x9ffb5a <zend_array_destroy>
   0x0000000048000eef <+719>:	cmp    QWORD PTR ds:0x181ef20,0x0
   0x0000000048000ef8 <+728>:	jne    0x48000030 <JIT$$exception_handler_undef>
   0x0000000048000efe <+734>:	mov    eax,DWORD PTR [rsp]
   0x0000000048000f01 <+737>:	test   eax,eax
   0x0000000048000f03 <+739>:	je     0x48000980 <jit$$trace_exit_0+16>
   0x0000000048000f09 <+745>:	mov    rcx,QWORD PTR [r14+0x10]
   0x0000000048000f0d <+749>:	mov    QWORD PTR [rcx],0x40200890
   0x0000000048000f14 <+756>:	mov    DWORD PTR [rcx+0x8],0x6
   0x0000000048000f1b <+763>:	mov    rax,QWORD PTR [r14+0x30]
   0x0000000048000f1f <+767>:	mov    QWORD PTR ds:0x181eda8,rax
   0x0000000048000f27 <+775>:	test   BYTE PTR [r14+0x59],0x1
   0x0000000048000f2c <+780>:	jne    0x48001055 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+1077>
   0x0000000048000f32 <+786>:	mov    QWORD PTR ds:0x181ed88,r14
   0x0000000048000f3a <+794>:	mov    r14,QWORD PTR [r14+0x30]
   0x0000000048000f3e <+798>:	mov    QWORD PTR [r14],0x408d4830
   0x0000000048000f45 <+805>:	mov    rax,QWORD PTR [r14+0x60]
   0x0000000048000f49 <+809>:	lea    rdi,[rax+0x18]
   0x0000000048000f4d <+813>:	mov    rsi,QWORD PTR [rax+0x10]
   0x0000000048000f51 <+817>:	call   0x968d8f <php_output_write>
   0x0000000048000f56 <+822>:	test   BYTE PTR [r14+0x69],0x1
   0x0000000048000f5b <+827>:	je     0x48000f64 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+836>
   0x0000000048000f5d <+829>:	mov    rdi,QWORD PTR [r14+0x60]
   0x0000000048000f61 <+833>:	sub    DWORD PTR [rdi],0x1
   0x0000000048000f64 <+836>:	cmp    QWORD PTR ds:0x181ef20,0x0
   0x0000000048000f6d <+845>:	jne    0x48000020 <JIT$$exception_handler>
   0x0000000048000f73 <+851>:	cmp    BYTE PTR [r14+0x58],0x4
   0x0000000048000f78 <+856>:	jne    0x48000988 <jit$$trace_exit_0+24>
   0x0000000048000f7e <+862>:	add    QWORD PTR [r14+0x50],0x1
   0x0000000048000f83 <+867>:	jo     0x4800106c <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+1100>
   0x0000000048000f89 <+873>:	jmp    0x48000b20 <TRACE-2$/home/ilutov/Developer/php-src/1.php$3>
   0x0000000048000f8e <+878>:	mov    rdi,0x4022dc60
   0x0000000048000f95 <+885>:	lea    rsi,[rdx+0x8]
   0x0000000048000f99 <+889>:	movabs rax,0x7fffea0d6f5d
   0x0000000048000fa3 <+899>:	call   rax
   0x0000000048000fa5 <+901>:	cmp    rax,0x408d4fa0
   0x0000000048000fac <+908>:	je     0x48000c82 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+98>
   0x0000000048000fb2 <+914>:	jmp    0x48000974 <jit$$trace_exit_0+4>
   0x0000000048000fb7 <+919>:	mov    QWORD PTR [r14],0x408d50f0
   0x0000000048000fbe <+926>:	mov    rdi,0x408d50a0
   0x0000000048000fc5 <+933>:	mov    rsi,0x0
   0x0000000048000fcc <+940>:	movabs rax,0x7fffea1d0af5
   0x0000000048000fd6 <+950>:	call   rax
   0x0000000048000fd8 <+952>:	test   rax,rax
   0x0000000048000fdb <+955>:	jne    0x48000d30 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+272>
   0x0000000048000fe1 <+961>:	jmp    0x48000020 <JIT$$exception_handler>
   0x0000000048000fe6 <+966>:	mov    rdi,QWORD PTR [r14+0x50]
   0x0000000048000fea <+970>:	sub    DWORD PTR [rdi],0x1
   0x0000000048000fed <+973>:	jne    0x48000dbd <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+413>
   0x0000000048000ff3 <+979>:	call   0x9e452c <rc_dtor_func>
   0x0000000048000ff8 <+984>:	jmp    0x48000dbd <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+413>
   0x0000000048000ffd <+989>:	mov    rdi,0x4022dc60
   0x0000000048001004 <+996>:	lea    rsi,[rdx+0x8]
   0x0000000048001008 <+1000>:	movabs rax,0x7fffea0d6f5d
   0x0000000048001012 <+1010>:	call   rax
   0x0000000048001014 <+1012>:	cmp    rax,0x408d4fa0
   0x000000004800101b <+1019>:	je     0x48000e0f <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+495>
   0x0000000048001021 <+1025>:	jmp    0x48000984 <jit$$trace_exit_0+20>
   0x0000000048001026 <+1030>:	mov    QWORD PTR [r14],0x408d50f0
   0x000000004800102d <+1037>:	mov    rdi,0x408d50a0
   0x0000000048001034 <+1044>:	mov    rsi,0x0
   0x000000004800103b <+1051>:	movabs rax,0x7fffea1d0af5
   0x0000000048001045 <+1061>:	call   rax
   0x0000000048001047 <+1063>:	test   rax,rax
   0x000000004800104a <+1066>:	jne    0x48000ea5 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+645>
   0x0000000048001050 <+1072>:	jmp    0x48000020 <JIT$$exception_handler>
   0x0000000048001055 <+1077>:	mov    rdi,QWORD PTR [r14+0x50]
   0x0000000048001059 <+1081>:	sub    DWORD PTR [rdi],0x1
   0x000000004800105c <+1084>:	jne    0x48000f32 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+786>
   0x0000000048001062 <+1090>:	call   0x9e452c <rc_dtor_func>
   0x0000000048001067 <+1095>:	jmp    0x48000f32 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+786>
   0x000000004800106c <+1100>:	movabs rax,0x43e0000000000000
   0x0000000048001076 <+1110>:	mov    QWORD PTR [r14+0x50],rax
   0x000000004800107a <+1114>:	mov    DWORD PTR [r14+0x58],0x5
   0x0000000048001082 <+1122>:	jmp    0x48000f89 <TRACE-3$/home/ilutov/Developer/php-src/1.php$4+873>

@dstogov
Copy link
Member

dstogov commented Apr 25, 2023

Thanks for the report. I reproduced and understood the problem. It's a tracing JIT bug. The crash is caused by incorrect "function guard" that bypass execution of the "old" inlined version of function _f(). On second request, the "old" version of function wasn't initialized correctly, EX(run_time_cache) got invalid value, and we crash...

The real problem caused by incorrect function guard. The current JIT code:

TRACE-3$/home/dmitry/php/php-master/CGI-DEBUG-64/1.php$4: ; (unknown)
    ....
.L1:
   	cmpq $0, EG(exception)
   	jne JIT$$exception_handler
   	movq 0x40(%r14), %rdx                                           ;  func = EX(run_time_cache)[1]
   	movq 8(%rdx), %rax
   	testq %rax, %rax                                                ; if (func)
   	je .L15
.L2:
    ...
.L15:
   	movq $0x7e64620, %rdi
   	leaq 8(%rdx), %rsi
   	movabsq $zend_jit_find_func_helper, %rax
   	callq *%rax
   	cmpq $0x84d4fa0, %rax                                           ; if (finc == OLD_INLINED_FUNC)
   	je .L2
   	jmp jit$$trace_exit_1

Should be converted to a more accurate check:

TRACE-3$/home/dmitry/php/php-master/CGI-DEBUG-64/1.php$4: ; (unknown)
    ....
.L1:
    	cmpq $0, EG(exception)
    	jne JIT$$exception_handler
    	movq 0x40(%r14), %rdx                                           ;  func = EX(run_time_cache)[1]
    	movq 8(%rdx), %rax
.L2:
    	cmpq $0x84d4fa0, %rax                                           ; if (func == OLD_INLINED_FUNC)
    	jne .L15
    ...
.L15:
        test %rax, %rax                                                 ; if (func) 
    	jne jit$$trace_exit_1
    	movq $0x7e64620, %rdi
    	leaq 8(%rdx), %rsi
    	movabsq $zend_jit_find_func_helper, %rax
    	callq *%rax
    :	jmp .L2

The old code assumed, that the function cached in EX(run_time_case) was already properly guarded before.

The fix will take some time.
@iluuu1994 may be you see a more efficient way to fix this?

@iluuu1994
Copy link
Member

I'm afraid this exceeds my knowledge on JITs 🙁 I'm hoping to learn more soon so I can help out with these. @arnaud-lb Maybe you're more qualified?

@arnaud-lb
Copy link
Member

Not sure I'm more qualified, but I can not find a more efficient way to implement this guard.

The happy path does not seem to be affected a lot, as we just swap a testq/je with a cmpq/jne (albeit cmpq/jne probably generates larger code, and if the function does not have a 32bit address, we also add an additional movq).

Maybe we could elide guards when the same guard has been executed in a dominator? I guess that IR does that / will do that?

dstogov added a commit to dstogov/php-src that referenced this issue May 2, 2023
dstogov added a commit that referenced this issue May 2, 2023
* PHP-8.1:
  Fixed GH-11127 (JIT fault)
@dstogov dstogov closed this as completed in ed0b593 May 2, 2023
dstogov added a commit that referenced this issue May 2, 2023
* PHP-8.2:
  Fixed GH-11127 (JIT fault)
dstogov added a commit to dstogov/php-src that referenced this issue May 2, 2023
dstogov added a commit to dstogov/php-src that referenced this issue May 15, 2023
dstogov added a commit to dstogov/php-src that referenced this issue May 31, 2023
@sysadminpower2019
Copy link

I seem to be experiencing a similar bug but I can't confirm if it is the same one, especially since the opcache.jit=1205 workaround also results in the 503 error.

The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.

cat /var/log/php8.2-fpm.log shows:

[pool www] child 1926 exited on signal 11 (SIGSEGV) after 3277.669446 seconds from start in cat /var/log/php8.2-fpm.log

Should i report this a different bug or wait for the next version of php?

@nielsdos
Copy link
Member

nielsdos commented Jun 5, 2023

@sysadminpower2019 the fix for this issue will be in 8.1.20, which will be released on June 8. Maybe your issue is the same one, maybe it is different. You could check if it reproduces with the new version and if it does you can open a report. You can already test this with the release candidate.

dstogov added a commit to dstogov/php-src that referenced this issue Jun 13, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Jun 15, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Jul 4, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Jul 26, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Aug 1, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Aug 29, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Aug 31, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Sep 1, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Sep 4, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Sep 5, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Sep 5, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Sep 8, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Sep 14, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Oct 11, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Oct 18, 2023
dstogov added a commit to dstogov/php-src that referenced this issue Oct 20, 2023
dstogov added a commit that referenced this issue Oct 23, 2023
* IR update

* Use folding to allow constant folding and common subexpression elimination

* Implement IR JIT for INIT_FCALL, INIT_FCALL_BY_NAME and INIT_NS_FCALL_BY_NAME

* Implement IR JIT for SEND_VAL and SEND_VAL_EX

* Implement IR JIT for SEND_REF

* Implement IR JIT for SEND_VAR* instructions (incompltere - few tests failures)

* Implement IR JIT for CHECK_FUNC_ARG

* Implement IR JIT for CHECK_UNDEF_ARGS

* Implement IR JIT for ROPE_INIT, ROPE_ADD and ROPE_END

* Implement IR JIT for FREE, FE_FREE, ECHO, STRLEN and COUNT

* Implement IR JIT for IN_ARRAY

* Implement IR JIT support for separate VM stack overflow check

* Implement IR JIT for INIT_DYNAMIC_CALL

* Implemenr IR JIT for INIT_METHOD_CALL

* Fix IR JIT for IN_ARRAY and COUNT

* Implement IR JIT for VERIFY_RETURN_TYPE

* Force C compiler to store preserved registers to allow JIT using them

* Implement IR JIT for DO_FCALL, DO_UCALL, DO_ICALL and DO_FCALL_BY_NAME

* Implement IR JIT for FETCH_CONSTANT

* Fix (reverse) guard conditions

* Implement IR JIT for RECV and RECV_INIT

* Implement IR JIT for RETURN

* Implement IR JIT for BIND_GLOBAL

* Fix guard for: int++ => double

* Fix exception handling

* Allow deoptimization of zval type only (if some register is spilled by the IR engine)

* Fix overflow handling

* Implement IR JIT for FE_RESET_R and FE_FETCH_R

* Eliminate extra temporary register

* Better registers usage

* Implement IR JIT for FETCH_DIM_* and ISSET_DIM

* Implement IR JIT for ASSIGN_DIM and ASSIGN_DIM_OP

* cleanup

* Generae IR that produces a better x86[_64] code

* Allow trace register allocation for live ranges terminated before entering a called function

* Remove following END->BEGIN nodes during IR construction

* Remove useless (duplicate) guard

* Avoid useless exception check

* Prevent duplicate store

* Eliminate repatable re-assignment of stack zval types

* Enable combination of some instructions with the following SEND_VAL for IR JIT

* Avoid generation of useless RLOADs

* Eliminatare refcouting in a sequence of FETCH_DIM_R

* Fix assertion

* Remove ZREG_ZVAL_ADDREF flag from an element of abstract stack

* Implement IR JIT for FETCH_OBJ_*

* Implement IR JIT for ASSIGN_OBJ

* Implement IR JIT for ASSIGN_OBJ_OP

* cleanup

* Implement IR JIT for (PRE/POST)_(INC/DEC)_OBJ

* ws

* cleanup

* Fix IR JIT for constructor call

* Fix opcache.jit=1201 IR JIT.

With opcache.jit=1201  we still have to generate code for follow and target basic blocks with single exiting VM instruction. We mat just omit the entry point.

* Fix IR construction for the case when both IF targets are the same

* Avoid PHP LEAVE code duplication in function IR JIT.

* Reload operands from memeory when overflow (this improves hot code)

* Implement IR JIT for SWITCH_LONG, SWITCH_STRING and MATCH

* Initialize result to IS_UNDEF

* Fix JIT integraion with observer (Zend/tests/gh10346.phpt failure)

* Fix incorrect compilation of FE_FETCH with predicted empty array

* Fix register allocation

* Use sign extension inxted of zero

* Fix trace register allocator

* cleanp

* Fix address sanitizer warning

* Calculate JIT trace prologue sixe on startup (to avoid magic constants).

* Add cgecks for merge arrays overflow (this should be refactored using lists)

* Cache TLS access to perform corresponding read once per basic block

* cleanup unused variable

* Fix IR JIT support for CLANG build (CALL VM without global register variables)

* Fix IR JIT for CALL VM with global register variables

* Allow %rpb ysage in JIT for CALL VM (we save and restore it in prologue/epilogue anyway)

* cleanup

* Allocate enough fixed stack to keep preserved registers

* We don't have to care about x29 and x30

* cleanup (JMPZ/NZ_EX work fine)

* Revert "cleanup (JMPZ/NZ_EX work fine)"

This reverts commit cf8dd74.

* Don't allocate register for PHP variables that are loaded from memory and used once

* Eliminate redundand deoptimization stores

* cleanup

* cleanup

* cleanup

* Optimization for constant comparison

* Cleanup and elimination of dead deoptimization stores

* Eliminate duplicate constant loading

* Set proper initial SP offset info for GDB backtraces

This doesn't take into account the following SP/FP modifications

* Add spill stores

* Remove low limit on number of deoptimization constants

* Emit dead code only when it's really necessary for IR graph

* cleanup

* cleanup

* Prefer loading long constants from memory (instead of loading immediate value)

* Regiter disasm labels using macros (add missing helpers)

* Make IR franework to care about GUARD JMP reordering

* Avoid reloading

* Improve register allocation for IR tracing JIT

* Add comment

* Fix deoptimization on result type guard of FETCH_DIM_R and FETCH_OBJ_R

* If HYBRID VM can't provide some stack space for JIT code in "red zone" then JIT has to reserve stack space itself

* Dump IR for stubs only if disassembling of stubs is requested

* Revert "Dump IR for stubs only if disassembling of stubs is requested"

This reverts commit d8b56be.

* Dump IR for stubs only if disassembling of stubs is requested (another approach)

* Improve overflow deoptimization for ADD(_,1) and SUB(_,1)

Now we deoptimize to the next instruction, load constant result, and remove op1 from SNAPSHOT

* Switch to IR Builder API

* Switch to new IR builder macros

* Fix jit_set_Z_TYPE_INFO() call. op3 is a simple constant (not a ir_ref).

* Generate better code

* Enable empty ENTRY block merging

* Improve code generated for array separation/creation before an update

(ASSIGN_DIM, ASSING_DIM_OP, etc)

* Fix incorrect deleteion of PHI source (op1 is used for control link)

* Load constant once

* cleanup

* Improve control-flow to avoid two IS_ARRAY checks for REFERENCEs

* Update comments

* cleanup

* Clenup comments

* Fix AAarch 64 build (disable stack adjustment auto-detection)

* Add filename and line number to closure names

* Reserve stack for parameter passing

* Increase size of CPU stack reserved for JIT-ed code

* Fix addess sanitizer warnings

* Clenup: introduce OPTIMIZE_FOR_SIZE macro (disabled by default)

* Port 08e7591 to IR JIT

Fix (at lease part of the) #GH-10635: ARM64 function JIT causes impossible assertion

* cleanup

* Preload constant and use tests that may be compiled into better code

* Convert helpers to stubs

* Introduce a helper data structure (ir_refs) to collect references for the following use in (MERGE/PHI)_N

* Use ir_refs

* Improve code generated by zend_jit_zval_copy_deref()

* Use "cold" attribute to influence IR block scheduler and achieve better code layout

* Keep info collected by recursion analyzer

* Use HTTPS URL to allow fetching without a SSH key

* Update IR

* Update IR

* Add IR JIT support for Wondows (Win64 support is incomplete)

* Update IR

* Update IR

* Fix support for Windows ZTS build

* Fix stack alignment

* Cleanup ir_ctx.control usage

* Fixed support for irreducable (incomplete) and merged loops

* Revert "Fixed support for irreducable (incomplete) and merged loops"

This reverts commit 672b5b8.

* Generate better code for RECV_ENTRies

* Use simpler and more efficient checks

* Switch to new ENTRY node concept

* Limit register usage across the OSR ENTRY point

* Upate MEM type only if we write to memory

* Use LOOP_END without a reference edge

* Use new ir_init() prototype

* Delay LOAD for better LOAD fusion

* Fix RECV/RECV_INIT compilation with opcache.jit=1235

* iPtoperly compile fake closures (they mau be called as regular functions)

* Fix reabase

* Fix rebase and add --with-capstone support for IR JIT

* Replace zend_uchar -> uint8_t

* IR JIT support for delayed destructor for zend_assign_to_typed_ref/prop

* Handle zend_execute_internal in IR JIT

* Fix readonly+clone IR JIT issues

* Switch to ir_ctx.mflags

* Ckeanup "inputs_count" access

* Disable CSE for nodes bound to PHP local varibles

The stack slots for temporaty variables may be reused and in case of
spilling this may cause clobbering of the value.

(ext/standard/tests/strings/htmlentities20.phpt on x86 with tracing JIT)

* Fix deoptimization code when link traces

See ext/zlib/tests/bug75273.phpt failure

* Fix missing type store

This fixes ext/openssl/tests/openssl_error_string_basic_openssl3.phpt

* Fix tracing JIT for overflowing INC/DEC

Fixes tests/lang/operators/preinc_basiclong_64bit.phpt

* Remove ir_remove_unreachable_blocks() call. Now it's called by ir_build_cfg(), when necessary.

* IR JIT: Fixed inaccurate range inference usage for UNDEF/NULL/FALSE

* IR JIT: Fixed GH-11127 (JIT fault)

* Avoid allocation of unused exit point

* Don't record already stored PHP variables in SNAPSHOTs

* Delay variable load

* Disable CSE across ENTRY

* Fixed disabling CSE

* Fix deoptimization

* Fixed deoptimization

* Disable incorrect register allocation

* Fix JIT for INDENTICAL+JMPZ_EX

* Add comments

* Fixed missed type stores

* IR JIT: added support for CLDEMOTE

* Fixed incorrect constant usage

* Disable compilation of PHP functions with irreducible CGF

* Fixed liveness check

* Fixed code for constant conditional jump

* Add type store to avoid use-after-free

* Fixed liveness analyses

* Gnerate SNAPSHOT for virtual method calls

* More accurate search for staticaly inferred info about a trace SSA vaiable

* Fix incorrect result use type_info

* Fix JMPZ/NZ_EX support and missing type store

* Fixed trace type inference and missing type store

* Store type of unused CV to prevent possible following use after free

* Fixed deoptimizaton info

* Fixed stack layout

* Implemented support for veneers on AArch64

* Dsable CSE to avoid over-optimization

* Don't bind nodes for TMP PHP variables

* Re-enable CSE for temporary variables as we don't bind them anymore

* Switch to CPU stack spill slots

* Add codegen info dump

* Initialize CV variables through FP (this enables some folding optimizatios)

* Use zero-extension that can be eliminated

* Avoid generation of dead PHIs

* Increase preallocated spill stack size

* Enable IR based JIT by default

* Fixed build with -disable-opcache-jit

* Use explicit type conversion & force load values to registerts

* Fix IR build

* Checkout submodules in github actions

* Fixed Windows build

* Fixed Windows build

* Fixed reattach to IR JIT SHM

* Update IR

* Checkout submodules in nightly CI

* Fix MACOS ZTS in IR JIT

* Update ir

* Fixed incorrect register allocation

* Fixed incorect code generation

* Fixed tracing jit for BIND_INIT_STATIC_OR_JMP

* Update README

* Typos

* Revert JIT disabling for run-tests.php workers

* Fixed code review issues

* Update IR

* Update IR

* Update IR

* Allow exit_point duplication, when the deoptimization info differs because of spilling

* Use bound spill slots for CV (once again)

* Improve error handling

* Removed IR submodule

* Remove IR submodule from workflows

* Embed IR

IR commit: 8977307f4e96ee03847d7f2eb809b3080f9ed662

* Add .gitignore

* Fixed according to feedback

* Force C saving preserved registers only for HYBRID VM

* Update IR

IR commit: a2f8452b3d35a756cba38924f5c51a48a7207494

* cleanup

* Replace ZEND_ASSERT(0) by ZEND_UNREACHABLE()

* Update IR and remove unused IR files

IR commit: 399a38771393c202a741336643118991290b4b1b

* Fixed inconsistency between IR code-generation and register-allocation

* Update IR

IR commit: 86685504274b0c71d9985b3c926dccaca2cacf9b

* Update ir_PHI*() according to IR construction API changes

* Fixed 32-bit build

* Update IR

IR commit: d0686408e20cd8c8640e37ed52ab81403a2383cb

* Support for ir_TAILCALL() prototype changes

* Update IR

IR commit: d72ae866e09d17e879378767aceb91d51894818c

* Fixed incorrect extension (ZEXT->SEXT)

* Fix SSA dominance

* Update IR

IR commit: d60d92516dc5f89b93cdf1df7a54141e83226b07

* Fixed support ir_ctx.ret_type
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants