https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105335
Bug ID: 105335 Summary: libiberty does not handle script exit codes correctly. Product: gcc Version: 11.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: other Assignee: unassigned at gcc dot gnu.org Reporter: lh_mouse at 126 dot com Target Milestone: --- Created attachment 52847 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=52847&action=edit proposed patch A few days ago I was playing with linker plugins. I created a bug in the LTO plugin that it segfaulted when the process was about to terminate. While I was attempt to bootstrap GCC with this modified piece of code, it failed during stage1 with a mysterious message: ``` configure:3566: /d/lh_mouse/GitHub/MINGW-packages-dev/mingw-w64-gcc-git/src/build-x86_64-w64-mingw32/./gcc/xgcc -B/d/lh_mouse/GitHub/MINGW-packages-dev/mingw-w64-gcc-git/src/build-x86_64-w64-mingw32/./gcc/ -L/mingw64/x86_64-w64-mingw32/lib -L/mingw64/lib -isystem /mingw64/x86_64-w64-mingw32/include -isystem /mingw64/include -B/mingw64/x86_64-w64-mingw32/bin/ -B/mingw64/x86_64-w64-mingw32/lib/ -isystem /mingw64/x86_64-w64-mingw32/include -isystem /mingw64/x86_64-w64-mingw32/sys-include -fno-checking -o conftest -g -march=x86-64 -mtune=generic -O2 -pipe -pipe conftest.c >&5 C:\MSYS2\mingw64\x86_64-w64-mingw32\bin\ld.exe: cannot find -lgcc: No such file or directory C:\MSYS2\mingw64\x86_64-w64-mingw32\bin\ld.exe: cannot find -lgcc_eh: No such file or directory C:\MSYS2\mingw64\x86_64-w64-mingw32\bin\ld.exe: cannot find -lgcc: No such file or directory C:\MSYS2\mingw64\x86_64-w64-mingw32\bin\ld.exe: cannot find -lgcc_eh: No such file or directory configure:3669: error: C compiler cannot create executables ``` Later I found that it was because configure couldn't tell whether the stage1 compiler should fail, as it always returned zero, indicating success. But how? Apparently ld failed with errors, and GCC should not have exited with zero. I used GDB to dig for a while. There didn't seem anything wrong with GCC. It was collect2 that returned zero. collect2 seemed to invoke ld indirectly, so I set a breakpoint on `GetExitCodeProcess()`. This of course got the exit code of ld (I thought so, but it was wrong! see below), which was 2816, so it failed, but in liberty `pex_win32_wait()` took merely its lowest byte and consider it the exit status, which was zero, which was incorrect. Later I set a breakpoint on `CreateProcessA()` and realized the aforementioned process that exited with 2816 was actually created by `spawn_script()`, which attempted to parse the shebang of `collect-ld`, which should denote `/bin/sh`. I had a working MSYS2 shell at the moment, and it correctly detected the segfault and returned 2816 = (11 << 8), indicating the signal 11 = SIGSEGV. So far we can conclude that there is a bug in libiberty: It only takes the lowest byte as the child process's exit status. If the child (bash) fails with 2816 then it is mistaken as having exited successfully. Untested patch attached.