Menu

#2357 MingWrt v5+ introduces SSE instruction that prevents execution on non-SSE OS

WSL
closed
None
Support
fixed
IINR_-_Include_In_Next_Release
False
2022-01-29
2017-11-09
DosFreak
No

Hello,

I've been working on a guide to compile DOSBox here:
https://www.vogons.org/viewtopic.php?f=31&t=55706&p=609435#p609435

While working on this guide myself and others have noticed than an executable compiled with Mingwrt v5+ results in an executable that will not run if the processor supports SSE but the Operating system does not. (Windows 95, NT 3.51). Testing was performed with a simple Hello World and also with DOSBox itself. Testing has also been performed on the same version of Windows used inside Vmware (i686) with the SSE flag masked and in Pcem (i586) (Pentium) and Qemu (i686).

The issue can be recreated as follows:
Create an "Hello World" executable with g++ with Mingw 6.3.0 and Mingwrt v5+. This results in an executable that will not work if the processor is i686 and the OS does not support SSE. (The executable WILL work fine on any OS that supports SSE as well as on any i586 processor)

Create an "Hello World" executable with g++ with Mingw 6.3.0 and Mingwrt v3. This results in an executable that will work if the processor is i686 and the OS does not support SSE. (The OS will work on non SSE and SSE processors as well as i486+)

Further testing revealed that replacing the crt2.0 file with one from v3 of mingwrt removes the error or removing Lines 118 to 122 of fesetenv.c and recompiling mingwrt v5+ will remove the error as well.

Obviously these operating systems are ancient so I doubt anyone cares but thought I'd get these posted if anyone does care or wants to know why their executable doesn't work and can't figure out why.

See this post and the next one for further info:
https://www.vogons.org/viewtopic.php?f=31&t=55706&p=609435#p625288

Discussion

  • Keith Marshall

    Keith Marshall - 2017-11-10
    • Description has changed:

    Diff:

    --- old
    +++ new
    @@ -12,7 +12,7 @@
    
     Further testing revealed that replacing the crt2.0 file with one from v3 of mingwrt removes the error or removing Lines 118 to 122 of fesetenv.c and recompiling mingwrt v5+ will remove the error as well.
    
    -Obviously these operating systems are ancient so I doubt anyone cares but thought I'd get these posted if anyone does care or wants to know why there executable doesn't work and can't figure out why.
    +Obviously these operating systems are ancient so I doubt anyone cares but thought I'd get these posted if anyone does care or wants to know why their executable doesn't work and can't figure out why.
    
     See this post and the next one for further info:
     https://www.vogons.org/viewtopic.php?f=31&t=55706&p=609435#p625288
    
    • status: unread --> open
    • Type: Bug --> Support
    • Category: OS_Version_No_Longer_Supported --> Waiting_User_Response
     
  • Keith Marshall

    Keith Marshall - 2017-11-10

    Thank you for bringing this to my attention. Before addressing the issue, may I draw your attention to the instructions at the top of the form which you completed, to create this ticket:

    MinGW Issues ticketing system
    Fields to be updated only by a MinGW developer
    
     * Status
     * Owner
     * Resolution
     * Category
    ...
    

    In assigning this to me, you exceeded your authority by updating the forbidden Owner field; thus, I would be perfectly justified in deleting this ticket, without further action.

    That said, I am willing to discuss the issue further; initial comments as follows:

    • The issue is not caused by any change in fesetenv.c; the lines to which you point produce identical assembly code, for both mingwrt-3.x and mingwrt-5.x
    • There was a change in crt1.c, in progressing from mingwrt-3.x to mingwrt-5.x, to circumvent a badly engineered, and utterly non-deterministic attempt to selectively override Microsoft's _fpreset() function; it is this change which is responsible for the change in behaviour.
    • While this change is responsible for the issue, (because it introduces an initialization call to fesetenv() which was not present in the mingwrt-3.x version), reverting that change is definitely not a solution, since it would simply sweep an underlying problem under the carpet; in the environment in which you have observed the issue, any explicit call to fesetenv(), (even in existing mingwrt-3.x dependent code), would fall foul of the underlying problem, (and such a call could arise, with the default FPU exception handler installed by crt2.o -- which is compiled from crt1.c -- in the event that FPU exceptions are enabled).

    I think the correct way to resolve this will be to modify cpu_features.c, to ensure that the __HAS_SSE feature test does not rely on a CPU feature probe alone, but will also consider whether the host OS supports the feature; can you suggest a suitable test, which could be used to deduce that the CPU feature probe should be overridden w.r.t. the __HAS_SSE feature test bit?

     
  • satgan

    satgan - 2017-11-12

    Hi,
    While troubleshooting the Hello world test case that fails will an illegal instruction when executed on a VMWare Win95 Guest running on a SSE supported host processor, we came across this thread in the FLAC forum for detecting SSE support in OS(with some rider about 'no guarantee to work' in future Intel processors). The patch from that thread was added to cpu_features.c(modded file attached) as advised and to my limited knowledge worked out fine under the following test conditions:

    a) Win7 64 bit running on Sandy bridge laptop
    b) VMWare Win95 Guest running on SSE supported processor
    c) PCEM with emulated Pentium processor running Win95 Guest
    d) Bochs with emulated P3(Katmai) processor running Win95 Guest
    
    P.S.: Hack may look ugly and if any issue, may please be changed as deemed fit.
    
     

    Last edit: Keith Marshall 2017-11-28
    • Keith Marshall

      Keith Marshall - 2017-11-13

      Nope. If I compile, and run, the current cpu_features.c in TEST mode, I see:

      $ mingw32-gcc -DTEST -O2 ../mingwrt/cpu_features.c
      $ ./a.exe
      _CRT_CMPXCHG8B found
      _CRT_CMOV found
      _CRT_MMX found
      _CRT_FXSR found
      _CRT_SSE found
      _CRT_SSE2 found
      _CRT_SSE3 found
      _CRT_CMPXCHG16B found
      

      However, your version simply doesn't work:

      $ mingw32-gcc -DTEST -O2 -I ../mingwrt ~/Downloads/cpu_features.c
      $ ./a.exe
      wine: Unhandled page fault on read access to 0xffffffff at address 0x4014ea (thread 0009)
      
       
  • satgan

    satgan - 2017-11-15

    It did give the same error message when I ran it under wine, but not when I compiled and ran it natively in Linux. Also I tested on another system running Windows 8.1 and the CPU support features were properly reported.

    I will try to find out and resolve the issue to the best of my ability and will update if I have something.

     
  • satgan

    satgan - 2017-11-24

    Failing of the test program seems to be due to non-alignment of 'fxsr' struct variable to 16 byte boundary, that was being allocated in the stack under wine (This issue was not observed in the case of running the executable under Windows).

    __attribute__((aligned(16))) doesn't seem to work for the stack allocated struct variable. I'm not much familiar with realignment of stack allocated variable, though I tried some things without success. Alternatively, I found an advice to declare the struct as 'static' and after doing that, didn't receive any page fault when I compiled and ran it under wine. Updated file is attached for perusal. Tested on:

    a) MinGW under Wine (1.6.2) in Lubuntu(14.04 LTS), running under QEMU on Core i7 system
    b) Win8.1 Pro 64 bit running on Core i7 system
    c) Bochs with emulated P3(Katmai) processor running Win95 Guest
    d) PCEM with emulated Pentium processor running Win95 Guest

    P.S.: I don't have much knowledge about the intrinsics of compiler optimizations/cross platform compatiblity things, so I'm not sure about their effects on the added code & vice versa. Additional testing on Sandybridge Laptop & VMWare guest to be done later tonight.

     

    Last edit: Keith Marshall 2017-11-28
    • Keith Marshall

      Keith Marshall - 2017-11-28

      Failing of the test program seems to be due to non-alignment of 'fxsr' struct variable to 16 byte boundary,

      Yes, I'd guessed that might have been the case, after examining the generated assembly code.

      __attribute__((aligned(16))) doesn't seem to work for the stack allocated struct variable.

      That was reported, years ago, as GCC bug #16660, and was claimed to have been fixed by #33721, but the generated assembly code provides no evidence to support that claim; perhaps a regression by the time we get to GCC-6.3, otherwise the claimed resolution may never have been completely effective.

      Strictly, you should have provided patches, rather than complete replacement files, but that's being pernickerty: I can generate them here. Thus, your initial proposal (after some cosmetic adjustment) becomes cpu_features.original.patch (sourceforge.net), and your follow-up (as an incremental patch, after elimination of redundant changes) becomes cpu_features.update.patch (sourceforge.net), (both of which are attached). However, given the weight of inline assembly code, and relative dearth of C code in the original cpu_features.c, it seems ridiculous that this was ever written in C in the first place; rather than adopting your proposals verbatim, I propose the alternative of cpu-features-init.patch (sourceforge.net) (also attached).

      I've successfully tested the cpu_features.sx replacement implementation, under wine, on my LMDE host, (but not on native Win32); I have no available test platform, on which to verify the behaviour on legacy Windows versions, so would be grateful if you could do so -- you may find my t-cpu.c test program (also attached) to be helpful.

       

      Last edit: Keith Marshall 2017-11-28
  • Keith Marshall

    Keith Marshall - 2017-11-28
    • status: open --> pending
    • Resolution: none --> limbo
     
  • satgan

    satgan - 2017-11-29

    First of all, thanks for looking into a test case involving such old OS versions and providing a solution for it.

    you should have provided patches, rather than complete replacement files

    I never felt qualified enough to propose a proper patch as I lacked the knowhow and also the means to test it under various conditions. As said earlier, the underlying code itself was not mine to begin with, hence it was just a suggestion more than anything, hopefully, to be molded properly in the hands of an experienced developer(as you have done now).

    Your test program reported the correct CPU features in my following test cases:
    a) MinGW under Wine (1.6.2) in Lubuntu(14.04 LTS), running under QEMU on Core i7 system
    b) Win8.1 Pro 64 bit running on Core i7 system
    c) Bochs with emulated P3(Katmai) processor running Win95 Guest
    d) PCEM with emulated Pentium processor running Win95 Guest

    Now I will try to understand your new cpu_features file, fully. Even though you have commented each and everything in detail, there is much to be learned by me. Once I understood it enough, I will try to test in more obscure conditions.

    Last but not the least, thanks heaps for the MinGW project.

    with regards,
    G.Gandhi.

     

    Last edit: satgan 2017-11-29
    • Keith Marshall

      Keith Marshall - 2017-11-29

      you should have provided patches, rather than complete replacement files

      I never felt qualified enough to propose a proper patch ...

      FWIW, this is how I generated cpu_features.original.patch (sourceforge.net), in my build directory, from your first proposed replacement for cpu_features.c:

      $ mkdir a b
      $ ln ../mingwrt/cpu_features.c a/  ; # original project version
      $ mv ~/Downloads/cpu_features.c b/ ; # your first replacement
      $ vi b/cpu_features.c              ; # to tidy indentation/layout
      $ diff -u a/cpu_features.c b/ > cpu_features.original.patch
      

      Simple as that; note that the use of a/ and b/ directories mimics the behaviour of hg, git, and even venerable old cvs, when formatting patches; also note that my build directory is an immediate child of the top-level directory in my repository clone, and thus, an immediate sibling of the top-level mingwrt and w32api project source directories.

      From there, to create cpu_features.update.patch (sourceforge.net), I did:

      $ rm -rf a
      $ mv b a
      $ mkdir b
      $ mv ~/Downloads/cpu_features.c b/ ; # new download of your 2nd version
      $ vimdiff -o a/cpu_features.c b/   ; # to filter out layout/comment discrepancies
      $ diff -u a/cpu_features.c b/ > cpu_features.update.patch
      

      Finally, to clean up:

      $ rm -rf a b
      

      The procedure I used to create my own patch was somewhat different; I reverted my working copy of the repository to published state, made my proposed changes "in-place", then used mercurial queues (mine is an hg clone of the git repository) to generate the patch:

      $ hg qqueue --create cpu-features
      $ vi chlog ; # to prepare the ChangeLog entry
      $ hg qnew -l chlog cpu-features-init.patch
      

      This leaves the patch file in ../.hg/patches-cpu-features/cpu-features-init.patch

      Your test program reported the correct CPU features in my following test cases:
      a) MinGW under Wine (1.6.2) in Lubuntu(14.04 LTS), running under QEMU on Core i7 system
      b) Win8.1 Pro 64 bit running on Core i7 system
      c) Bochs with emulated P3(Katmai) processor running Win95 Guest
      d) PCEM with emulated Pentium processor running Win95 Guest

      Thanks for testing; (I assume you applied my patch, in the parent of your mingwrt and w32api source directories, and rebuilt using):

      $ make clean
      $ patch -p1 < cpu-features-init.patch
      $ make && make install ; # to a working sandbox
      

      Before building the test program, (in the sandbox):

      $ gcc -O2 t-cpu.c -o t-cpu.exe
      

      Last but not the least, thanks heaps for the MinGW project.

      You're most welcome. Do please note that thanks are also due to yourself, and others like you, who are prepared to follow up, and most importantly ... test on these legacy platforms, (which are becoming increasingly difficult for us to support without such feedback). We always strive to preserve the legacy platform support, but alas, too many users will simply file bug reports, which they then never follow up. So, once again, a big thank you to you, for persisting with this one!

       
  • satgan

    satgan - 2017-11-29

    FWIW, this is how I generated cpu_features.original.patch....Simple as that;

    I was probably sounding more naive than necessary on my earlier reply. I should have worded it as "I never felt qualified enough to propose it as a proper patch". What I meant by 'lacked the knowhow' was not w.r.t 'generating diff or applying a patch(which,thankfully, I do know)', rather, it was about the possible (ill?)effects of the 'added' code on other systems (that weren't tested by me). That said, your reply about generating your own patch using mercurial wasn't known to me, thanks for sharing your knowledge.

    I assume you applied my patch

    Yes, your patch got applied cleanly to my source directory. However, my ugly build procedure involved

    a) applying patch by 'patch -p2 < cpu-feature-init.patch' according to my source directory 
    b) running configure with prefix=/mingw/test, -march=i386 & pointing -I to the w32api-5.0.1 include folder
    c) make && make install
    d) backing up the whole bin, lib & include folders 
    e) copying the bin/lib/include folders from under /mingw/test to /mingw & overwriting.
    f) compiling your cpu test program by 'mingw32-gcc -O2 -I../mingwrt-5.0.1 t-cpu.c
    g) copying the resulting a.exe to various test systems(virtual mostly) and executing it.
    

    Thanks to the OP, DosFreak who was instrumental in identifying & isolating the issue in his test case of Win95 Guest under VMWare.

    P.S. Happy to help in any way if you need any support for testing in old systems, as I enjoy trobleshooting more than coding/patching.

     

    Last edit: satgan 2017-11-29
    • Keith Marshall

      Keith Marshall - 2017-11-29

      I was probably sounding more naive than necessary on my earlier reply. I should have worded it as "I never felt qualified enough to propose it as a proper patch". What I meant by 'lacked the knowhow' was not w.r.t 'generating diff or applying a patch(which,thankfully, I do know)', rather, it was about the possible (ill?)effects of the 'added' code on other systems (that weren't tested by me).

      Ah, okay. I misunderstood that you may not have been comfortable with the procedure for creating, and submitting patches ... sorry about that. W.r.t. possibible adverse effects on systems you haven't tested on, (or cannot test on), it's best to just "get it out there", and let others report any problems which arise.

      That said, your reply about generating your own patch using mercurial wasn't known to me, thanks for sharing your knowledge.

      Pleased to have given you something new. I believe it's possible to do something similar with git branches, but IMO, whatever features git may offer, they surely lack the elegance of mercurial.

      my ugly build procedure involved
      a) applying patch by 'patch -p2 < cpu-feature-init.patch' according to my source directory

      So, your CWD was set to the top of the mingwrt source tree, whereas I work from a repository clone, with both mingwrt and w32api source directories as immediate children of the top source directory, (together with a build directory, which is an immediate sibling of both); with this setup, having cloned it from the public repository, there is also additional build-time code in the top source directory, to facilitate combined configuration and build of both subsidiary packages.

      b) running configure with prefix=/mingw/test, -march=i386 & pointing -I to the w32api-5.0.1 include folder
      c) make && make install
      d) backing up the whole bin, lib & include folders
      e) copying the bin/lib/include folders from under /mingw/test to /mingw & overwriting.

      I handle this by keeping several installations in parallel, e.g. for mingw32-gcc-6.3 I have $HOME/mingw32-gcc-6.3.0 for my production compiler, and $HOME/mingw32-gcc-6.3.0-sandbox for testing. My $PATH refers to one or other of these, (but never both at the same time), via a symbolic $HOME/mingw32 link, such that $HOME/mingw32/bin is in $PATH. Thus, I can switch between production and testing environments, simply by changing one symbolic link, (and I have a little shell script to automate the switch).

      Thanks to the OP, DosFreak who was instrumental in identifying & isolating the issue in his test case of Win95 Guest under VMWare.

      Yes, indeed.

      P.S. Happy to help in any way if you need any support for testing in old systems, as I enjoy trobleshooting more than coding/patching.

      Would you be interested in joining the project, in the capacity of "tester", with a particular emphasis on legacy systems support?

       

      Last edit: Keith Marshall 2017-11-29
  • satgan

    satgan - 2017-11-29

    Thanks for giving inputs in maintaining an organized setup. Frankly I have never used git or mercurial before, so, as indicated, I will start with mercurial and mimic your setup.

    Would you be interested in joining the project, in the capacity of "tester", with a particular emphasis on legacy systems support?

    It took me around 10 days to understand, identify and search a fix for the stack alignment issue under wine. So you can guess my knowledge level. I'm also doing testing for DosFreak's compilation guide in dosbox forum(vogons.org) and learning at the same time.

    Am I right in assuming that there won't be any time bound pressure to complete the tasks at hand? If not so && still you would like to consider me as a tester, then I'm flattered to join.

    Another thing I would like to bring to your notice is that I don't have any actual legacy hardware/OS (all are emulators only), though I guess it shouldn't matter for practical purposes.

     
    • Keith Marshall

      Keith Marshall - 2017-12-02

      Would you be interested in joining the project, in the capacity of "tester", with a particular emphasis on legacy systems support?

      Am I right in assuming that there won't be any time bound pressure to complete the tasks at hand?

      Correct. We place no demands whatsoever, on our project contributors; each is allowed to work at their own pace, as their own time constraints permit, while contributing as much, or as little, as they wish.

      If not so && still you would like to consider me as a tester, then I'm flattered to join.

      Well, for most of us, testing on older platforms, (whether physical or virtual), is becoming increasingly difficult. (Personally, I run WinXP and Win7 under VirtualBox, on an LMDE host; I tried to create a similar set-up for Win98, but it is so poorly supported by VirtualBox that it is effectively unusable, and I gave up). Without willing volunteers, who can test on these older platforms, we may be forced to drop support for them.

      Incorporporating you as a project member just makes it easier keep you informed of issues which you may wish to investigate. However, right now, SourceForge have messed up our project communications, and we are exploring alternative infrastructures; let me get back to you, when we have something more concrete in place.

      Another thing I would like to bring to your notice is that I don't have any actual legacy hardware/OS (all are emulators only), though I guess it shouldn't matter for practical purposes.

      I don't think that should matter; as noted above, I use virtual machines myself, and surely such testing must be better than no testing at all.

       
  • satgan

    satgan - 2017-12-02

    let me get back to you, when we have something more concrete in place.

    Sure.

    I'm presently experimenting, to get to install MinGW in PCEM Win95 guest for debugging an application. I know it is far-fetched. Do you have any advice regarding the version I could try, btw. Or is it a fool's errand?

    MinGW GUI setup actually doesn't run in Win95 guest, so, I'm trying the CLI route

     

    Last edit: satgan 2017-12-02
    • Keith Marshall

      Keith Marshall - 2017-12-02

      I'm presently experimenting, to get to install MinGW in PCEM Win95 guest for debugging an application. I know it is far-fetched. Do you have any advice regarding the version I could try, btw. Or is it a fool's errand?

      I don't know, but it really would be better to ask on the MinGW-Users mailing list, or to open a new ticket, to discuss the new topic. (The mailing list gets better exposure to a broader corpus of users, one of whom may just know the answer).

      MinGW GUI setup actually doesn't run in Win95 guest, so, I'm trying the CLI route

      Does mingw-get run as a CLI process? Again, I don't know, (and have no way to check), and once again, the mailing list, or a new ticket, would be more appropriate for continued discussion.

       
  • Keith Marshall

    Keith Marshall - 2017-12-02
    • status: pending --> open
    • Resolution: limbo --> fixed
    • Category: Waiting_User_Response --> IINR_-_Include_In_Next_Release
     
  • Keith Marshall

    Keith Marshall - 2017-12-02

    I pushed a slightly modified version of my previously proposed patch, (fixing some CFI directive usage issues), as [fa00fd]. There may be some x86-64 compatibility issues, arising out of this, so I'm leaving the ticket open.

     

    Related

    Commit: [fa00fd]

  • satgan

    satgan - 2017-12-02

    Thanks for the commit.

     

    Last edit: satgan 2017-12-05
  • Keith Marshall

    Keith Marshall - 2022-01-29

    Closing, since the original issue should have been resolved, and no consequent x86-64 issue has been raised.

     
  • Keith Marshall

    Keith Marshall - 2022-01-29
    • status: open --> closed
     
MongoDB Logo MongoDB