View Issue Details

IDProjectCategoryView StatusLast Update
0001625XdebugStep Debuggingpublic2019-02-16 00:38
Reporterdv-ds Assigned To 
PriorityhighSeveritycrashReproducibilityalways
Status closedResolutionfixed 
Platformx86_64OSmacOSOS Version10.14.2
Product Version2.7.0rc1 
Target Version2.7.0Fixed in Version2.7.0RC2 
Summary0001625: Work around ABI conflicts in PHP 7.3.0/PHP 7.3.1
Description

Some evaluations are possible, others are not. In the cases where it doesn't work, the end result is something like this:

[Mon Feb 04 11:49:24.093890 2019] [core:notice] [pid 10169] AH00052: child pid 39934 exit signal Segmentation fault (11)

For what it's worth, I'm fairly certain this occurred also in 2.7.0beta1, but I did not investigate that further as the major issue for me at that point was the opcache issue.

Steps To Reproduce

Setup index.php as follows and navigate to /?foo=bar

<?php

$a = 1;
echo ""; // Set breakpoint here and either hover over $a in VS Code or try to evaluate $_GET in the console. Either will crash. The latter will not cause a crash if the query string is omitted however.

Additional Information

Setup:

  • Visual Studio Code, 1.30.2
  • Apache 2.4.37 (Homebrew)
  • PHP 7.3.1 (Homebrew)
TagsNo tags attached.
Operating SystemmacOS
PHP Version7.3.2-7.3.4

Relationships

has duplicate 0001626 resolvedderick Segmentation fault when superglobal query is run 
has duplicate 0001627 resolvedderick Segmentation fault 

Activities

dv-ds

2019-02-04 11:13

reporter   ~0004871

I just noticed I set "PHP Version" incorrectly, and don't see any way to modify it. It's 7.3.1 as indicated in the other section.

derick

2019-02-11 17:15

administrator   ~0004885

I think this is a duplicate of 0001626 — can you please see if you can make a GDB trace as is explained at https://xdebug.org/support.php#crash ?

dv-ds

2019-02-12 09:33

reporter   ~0004888

I can't get GDB to work even with a simple hello world program unfortunately. It's been like that for a long time and I gave up trying to fix it. It's a homebrew installation, and I'd rather not touch it as Homebrew very often breaks things for me when I upgrade things, due to messed up dependencies and whatnot.

However, I am able to attach with LLDB (sudo lldb -p nnnn). Here's what I got, and see also attached xdebug log from an earlier session, explained below, do you need more?

Program used:

<?php

error_log("PID: " . getmypid());

sleep(20);

$a = 1; // LLDB log below indicates crash when hovering over $a, at breakpoint
echo ""; // Breakpoint set here

(lldb) continue
Process 4188 resuming
xdebug.so was compiled with optimization - stepping may behave oddly; variables may not be available.
Process 4188 stopped

  • thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
    frame #0: 0x000000010d2a5e17 xdebug.so`xdebug_var_export_xml_node at xdebug_var.c:1715 [opt]
    1712 zend_string *tmp_fullname_zstr;
    1713
    1714 #if PHP_VERSION_ID >= 70300
    -> 1715 tmp_fullname_zstr = php_addslashes(i_string);
    1716 #else
    1717 tmp_fullname_zstr = php_addslashes(i_string, 0);
    1718 #endif
    Target 0: (httpd) stopped.

For the xdebug log: (/?foo=bar)

Evaluating $a in console works fine:
[3829] <- eval -i 10 -- JGE=

Hovering over $a - crash:
[3829] <- context_get -i 11 -d 0 -c 1

Evaluating $_GET in console - crash: (and reconnect fails because the thread already died, I get similar results when running this on a running thread)
[4305] <- eval -i 10 -- JF9HRVQ=

derick

2019-02-12 16:00

administrator   ~0004890

This is really useful. If only I could reproduce this at home (or have access to your debugging session)...

It's possible to compile Xdebug with debugging symbols, by using:

./configure --with-xdebug-dev

instead of the normal ./configure

I'm curious to see what the values of the local vars and arguments are. For both this frame (top) one, and lower ones. Can you show the output of the following commands on lldb:

frame 0
frame variable
frame info

frame 1
frame variable
frame info

frame 2
frame variable
frame info
(etc, until... 10 or so?)

dv-ds

2019-02-12 16:53

reporter   ~0004895

Hm, if I try ./configure --enable-xdebug-dev (I assume that's the one you meant, I get an error if I try --with-xdebug-dev), some warnings are treated as fatal, which they are not otherwise. Example:

xdebug/xdebug.c:1822:107: error: format specifies type 'long' but the argument has type 'zend_long' (aka 'long long') [-Werror,-Wformat]
zend_throw_exception_ex(zend_ce_error, 0, "Maximum function nesting level of '%ld' reached, aborting!", XG(max_nesting_level));


                                                                                              %lld

Then it stops compiling after two such messages.

I'm not sure which flag is causing this, but will see if I can work around them by blindly massaging the code a bit to make the warnings go away. In case that does not pan out, please suggest a better route in the meantime to get this to compile.

dv-ds

2019-02-12 16:59

reporter   ~0004896

Found a quicker path and applied this diff to mute the warnings, will get back to you shortly:

$ git diff
diff --git a/config.m4 b/config.m4
index 27f19b4f..03ec597b 100644
--- a/config.m4
+++ b/config.m4
@@ -40,7 +40,6 @@ if test "$PHP_XDEBUG" != "no"; then
PHP_CHECK_GCC_ARG(-Wduplicate-enum, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wduplicate-enum")
PHP_CHECK_GCC_ARG(-Wempty-body, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wempty-body")
PHP_CHECK_GCC_ARG(-Wenum-compare, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wenum-compare")

  • PHP_CHECK_GCC_ARG(-Werror, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Werror")
    PHP_CHECK_GCC_ARG(-Wextra, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wextra")
    PHP_CHECK_GCC_ARG(-Wformat-nonliteral, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wformat-nonliteral")
    PHP_CHECK_GCC_ARG(-Wformat-security, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wformat-security")

dv-ds

2019-02-12 17:29

reporter   ~0004897

I was able to compile, but things are not working out yet:

  • I get "xdebug.so was compiled with optimization - stepping may behave oddly; variables may not be available.". I notice that -O2 or perhaps other settings are present in for instance libtool. I don't know where it sources that from. It seems quite difficult for me to find all of those occurrences as well.
  • For what it's worth, note that it appears I get debug symbols (xdebug.so.dSYM) no matter if I set --enable-xdebug-dev or not. Not sure of the practical difference as both yield the same warning about optimizations.

How can I completely disable optimization?

The frame info I can get at this point is thus quite uninformative, so I'll refrain from posting the rest unless you think it might still be of use:

(lldb) frame select 0
frame #0: 0x0000000111db8e67 xdebug.so`xdebug_var_export_xml_node at xdebug_var.c:1715 [opt]
1712 zend_string tmp_fullname_zstr;
1713
1714 #if PHP_VERSION_ID >= 70300
-> 1715 tmp_fullname_zstr = php_addslashes(i_string);
1716 #else
1717 tmp_fullname_zstr = php_addslashes(i_string, 0);
1718 #endif
(lldb) frame variable
(zval
) zv_nptr = <variable not available>

(zend_ulong) index_key = <variable not available>

(zend_string ) hash_key = 0x0000000111e61060
(xdebug_xml_node
) parent = <variable not available>

(xdebug_str *) parent_name = <variable not available>

(xdebug_var_export_options *) options = <variable not available>

(xdebug_xml_node ) node = 0x00007fa61271cd90
(xdebug_str
) name = <variable not available>

(xdebug_str) full_name = <variable not available>

(zend_string ) i_string = 0x0000000111e61900
(zend_string
) tmp_fullname_zstr = <variable not available>

dv-ds

2019-02-12 18:16

reporter   ~0004898

It was phpize that introduced -O2. Hacked it away manually before ./configure --enable-xdebug-dev && make and was able to get some debug info, see attached lldb-output.txt.

Some notes:

  • I've replaced some paths with [...].
  • Line 188 (and maybe others) is how it is shown in the terminal (I just copy-pasted the whole output from the terminal to an editor), I suppose LLDB might be masking non-printable characters, please let me know if you need the exact bytes for some reason: (char *) var_name = 0x00007fff6e72e7d8 "?z???f\x85?\x85q???f?@\x10"

derick

2019-02-12 19:15

administrator   ~0004899

Thanks for that. I just did a live debugging session with somebody through IRC and screensharing, and we came to the same conclusions, with albeit slightly better output (See attached screenshots). Unfortunately, I still don't understand what goes wrong, except for the crash...

deek

2019-02-12 22:43

reporter   ~0004901

Looks like I got the same results as both dv-ds and derick from my ticket 0001626. I tried to check the value of i_string from within lldb without much success.

(lldb) frame var -L i_string                         0x00007ffeefbfd9d0: (zend_string *) i_string = 0x0000000104201dc0
(lldb) frame var -L &i_string                      scalar: (zend_string **) &i_string = 0x00007ffeefbfd9d

dv-ds

2019-02-13 12:16

reporter   ~0004902

Is the following of any use?

(lldb) frame select 0
frame #0: 0x000000010f953ef3 xdebug.soxdebug_array_element_export_xml_node(zv_nptr=0x000000010fa7a600, index_key=12731958461851390867, hash_key=0x000000010fa61060, level=0, parent=0x00007f96c66075c0, parent_name=0x00007f96c6607610, options=0x00007f96c9383ed0) at xdebug_var.c:1715 1712 zend_string *tmp_fullname_zstr; 1713 1714 #if PHP_VERSION_ID >= 70300 -> 1715 tmp_fullname_zstr = php_addslashes(i_string); 1716 #else 1717 tmp_fullname_zstr = php_addslashes(i_string, 0); 1718 #endif (lldb) dis xdebug.soxdebug_array_element_export_xml_node:
[...]
0x10f953eb5 <+581>: callq 0x10f959f90 ; symbol stub for: __memcpy_chk
0x10f953eba <+586>: movq 0xc187(%rip), %rcx ; (void )0x000000010c6f1ae9: php_addslashes
0x10f953ec1 <+593>: movq -0x98(%rbp), %rdx
0x10f953ec8 <+600>: movq -0x88(%rbp), %rsi
0x10f953ecf <+607>: movb $0x0, 0x18(%rdx,%rsi)
0x10f953ed4 <+612>: movq -0x98(%rbp), %rdx
0x10f953edb <+619>: movq %rdx, -0x100(%rbp)
0x10f953ee2 <+626>: movq (%rcx), %rcx
0x10f953ee5 <+629>: movq -0x100(%rbp), %rdi
0x10f953eec <+636>: movq %rax, -0x128(%rbp)
-> 0x10f953ef3 <+643>: callq
%rcx
0x10f953ef5 <+645>: movq %rax, -0x108(%rbp)
0x10f953efc <+652>: movq -0xb0(%rbp), %rax
0x10f953f03 <+659>: addq $0x18, %rax
0x10f953f07 <+663>: movq -0xb0(%rbp), %rcx
0x10f953f0e <+670>: movq 0x10(%rcx), %rcx
0x10f953f12 <+674>: addq $0x1, %rcx
0x10f953f16 <+678>: subq $0x1, %rcx
0x10f953f1a <+682>: movq %rax, %rdi
0x10f953f1d <+685>: movq %rcx, %rsi
0x10f953f20 <+688>: callq 0x10f95a5d2 ; symbol stub for: xdebug_str_create
[...]

(lldb) p/x $rcx
(long) $36 = 0x56415741e5894855
(lldb) x/64x $rcx
error: memory read failed for 0x56415741e5894800

dv-ds

2019-02-13 12:22

reporter   ~0004903

Note that the address mentioned above evaluates as follows:

(lldb) dis -a 0x000000010c6f1ae9
libphp7.so`php_addslashes:
0x10c6f1ae9 <+0>: pushq %rbp
0x10c6f1aea <+1>: movq %rsp, %rbp
[...]

derick

2019-02-13 12:58

administrator   ~0004904

This almost looks like the php_addslashes function call is wrong. But Xdebug does nothing special with this function. I am wondering whether there is another memory corruption going on here. Maybe it's worth trying to do this with the zend memory manager turned off, which you can do by setting "export USE_ZEND_ALLOC=0" as an environment variable (but make sure they propagate to PHP/PHP-FPM — phpinfo() and or var_dump($_ENV) should tell you).

dv-ds

2019-02-13 15:06

reporter   ~0004905

I set USE_ZEND_ALLOC=0 now and phpinfo() confirms it ($_ENV does not however).

However, I still get the same error and the same instructions:

0x107fe5eb5 <+581>:  callq  0x107febf90               ; symbol stub for: __memcpy_chk
0x107fe5eba <+586>:  movq   0xc187(%rip), %rcx        ; (void *)0x0000000104d84ae9: php_addslashes
0x107fe5ec1 <+593>:  movq   -0x98(%rbp), %rdx
0x107fe5ec8 <+600>:  movq   -0x88(%rbp), %rsi
0x107fe5ecf <+607>:  movb   $0x0, 0x18(%rdx,%rsi)
0x107fe5ed4 <+612>:  movq   -0x98(%rbp), %rdx
0x107fe5edb <+619>:  movq   %rdx, -0x100(%rbp)
0x107fe5ee2 <+626>:  movq   (%rcx), %rcx
0x107fe5ee5 <+629>:  movq   -0x100(%rbp), %rdi
0x107fe5eec <+636>:  movq   %rax, -0x128(%rbp)

-> 0x107fe5ef3 <+643>: callq *%rcx
0x107fe5ef5 <+645>: movq %rax, -0x108(%rbp)
0x107fe5efc <+652>: movq -0xb0(%rbp), %rax
0x107fe5f03 <+659>: addq $0x18, %rax
0x107fe5f07 <+663>: movq -0xb0(%rbp), %rcx
0x107fe5f0e <+670>: movq 0x10(%rcx), %rcx
0x107fe5f12 <+674>: addq $0x1, %rcx
0x107fe5f16 <+678>: subq $0x1, %rcx
0x107fe5f1a <+682>: movq %rax, %rdi
0x107fe5f1d <+685>: movq %rcx, %rsi
0x107fe5f20 <+688>: callq 0x107fec5d2 ; symbol stub for: xdebug_str_create

derick

2019-02-13 20:39

administrator   ~0004906

I have been talking to Nikita today, and it seems that a hunch "it looks like addslashes is not a function" seems to be correct. Nikita theorizes that this problem occurs because PHP and Xdebug are targetted at a different architecture. PHP's php_addslashes calls have an optimisation for SSE4.2 systems, which gets only enabled on machines that support it. So if PHP was compiled on a system that doesn't enable it, and yours does, then the calling convention is off and you get a crash. It's possible that a hint on what happens can be found in the ./configure line that can be found in phpinfo() output (<code>php -i | grep Configure</code>).

Unfortunately, there is currently no clean way around this without a hack (i.e., copying the php_addslashes function into the Xdebug source code). Nikita suggests to try to compile Xdebug with <code> ./configure CFLAGS="-march=native" </code> to see if that addresses the problem until this can be sorted out in PHP itself.

deek

2019-02-13 21:30

reporter   ~0004907

Looks like you beat me to it. I just found these lines in the PHP src which are exactly what you describe.

https://github.com/php/php-src/blob/php-7.3.1/ext/standard/php_string.h#L127-L133

deek

2019-02-13 21:45

reporter   ~0004908

Please excuse any misunderstanding about this complex code, this might be way of the mark. Would it be possible to leverage the code in the PHP source that checks for the SSE4.2 instructions in XDebug 2.7 as well?

https://github.com/php/php-src/blob/php-7.3.1/ext/standard/string.c#L3902-L3919

dv-ds

2019-02-14 04:09

reporter   ~0004909

So if PHP was compiled on a system that doesn't enable it, and yours does, then the calling convention is off and you get a crash.

That seems to be the case indeed! I don't see any mention of SSE4.2 in the output of php -i, whereas sysctl -a | grep machdep.cpu.features lists it.

You did not hear it from me, but what I did now was:

  • Edit /usr/local/include/php/Zend/zend_portability.h
  • Change ZEND_INTRIN_SSE4_2_FUNC_PTR from 1 to 0
  • Recompile Xdebug

There are a bunch of flags in there, so I have no idea if there is more that needs to be hacked. Probably some upstream flag is a less bad thing to mess with. And clearly this is not a proper solution...

Nevertheless, after this change I can't reproduce the scenarios I described in "Steps To Reproduce". I have not done extensive testing, but it looks very promising.

Assuming no other issues pop up, this is good enough on my side for now as I also can't think of a non-awkward workaround on the Xdebug side. It doesn't necessarily merit closing the issue, but I'll leave that up to you and others affected by this issue.

derick

2019-02-14 15:23

administrator   ~0004910

This has now been fixed in PHP (for PHP 7.3.3 (https://github.com/php/php-src/pull/3826/files) and PHP 7.4-dev (https://github.com/php/php-src/pull/3828/files)). I will be adding a workaround for Xdebug for the two broken PHP versions (i.e., copy the addslashes code into the Xdebug source code, so that no ABI conflicts exist), and then release a new release candidate.

derick

2019-02-15 13:10

administrator   ~0004912

Fixed in GIT for Xdebug 2.7.0RC2 (soon to be released)

deek

2019-02-16 00:38

reporter   ~0004914

Verified that Xdebug 2.7.0RC2 fixes the issues I was having from ticket 0001627.