#1557 mingw-compiled DLLs may fail if loaded using LoadLibrary()

WSL
closed
Earnie Boyd
out-of-date
Known_bugs
2013-01-30
2011-06-20
Andrew Zabolotny
No

On this page:
http://msdn.microsoft.com/en-us/library/2s9wt68x%28VS.80%29.aspx

the last paragraph says:

If a DLL declares any nonlocal data or object as __declspec( thread ), it can cause a protection fault if dynamically loaded. After the DLL is loaded with LoadLibrary, it causes system failure whenever the code references the nonlocal __declspec( thread ) data. Because the global variable space for a thread is allocated at run time, the size of this space is based on a calculation of the requirements of the application plus the requirements of all the DLLs that are statically linked. When you use LoadLibrary, there is no way to extend this space to allow for the thread local variables declared with __declspec( thread ). Use the TLS APIs, such as TlsAlloc, in your DLL to allocate TLS if the DLL might be loaded with LoadLibrary.

This is exactly what happened to my DLLs. My hook DLL is being loaded at the start time of any executable (via LoadPerProcess registry entry), and in some cases loading my DLL will trigger a segmentation fault (Windows will hide this fault, thus user won't observe it). However, the functionality of my DLL will be, obviously, missing.

I'm not 100% sure the above is the real cause, but it fails in NtLoadLibrary(), in the function that does something with the .tls section. In some cases everything goes well; I found that this happens when the DLL is loaded to the prelinked address (e.g. the "Image Base" address in PE header). Sometimes it happens that the Image Base address is occupied by other DLL, in which case the loader will try loading the DLL to a different address, and this 100% triggers the bug.

Unfortunately, some runtime (I think libgcc.a, have to do more research here) already contains several (four?) TLS variables, thus any DLL built by mingw will contain a .tls section. This is a very serious issue for me as it happened in a product we're going to release soon. Don't even know what to do now, perhaps will try a older libgcc.a which does not contain thread local storage variables.

I see two solutions here:
- Avoid usage of thread-local-storage variables in gcc runtime
- Use TlsAlloc(), as microsoft recommends

Discussion


  • Anonymous
    2012-03-06

    I'm having this same problem. I'm trying to build RCPLEX and the R application uses LoadLibrary to load plugins. When I do dumpbin /HEADERS i get the following:

    13000 [ 28] RVA [size] of Thread Storage Directory

    Which according to MSFT means that this DLL can't be used with LoadLibrary.

    http://support.microsoft.com/kb/118816

     
  • Earnie Boyd
    Earnie Boyd
    2012-03-06

    And the same MSFT ticket says:

    DLLs that use __declspec(thread) should not be loaded with LoadLibrary.

    The DLL code should be modified to use such TLS functions as TlsAlloc, and to allocate TLS if the DLL might be loaded with LoadLibrary. Or, the DLL that is using __declspec(thread) should only be implicitly loaded into the application.

    Cesar, do you know if this has been resolved?

     
  • Earnie Boyd
    Earnie Boyd
    2012-03-06

    • assigned_to: nobody --> cstrauss
     
  • Cesar Strauss
    Cesar Strauss
    2012-03-16

    I don't think libgcc.a is the issue. I don't see any .tls sections in it:

    $ objdump -h /mingw/lib/gcc/mingw32/4.6.2/libgcc*.a | grep tls
    emutls.o: file format pe-i386

    I suspect the mingw runtime is the culprit, instead:

    $ objdump -h /mingw/lib/libmingw32.a | grep tls
    tlsmcrt.o: file format pe-i386
    tlsmthread.o: file format pe-i386
    tlssup.o: file format pe-i386
    6 .tls$AAA 00000004 00000000 00000000 00000fa6 2**2
    7 .tls$ZZZ 00000004 00000000 00000000 00000faa 2**2
    10 .tls 00000018 00000000 00000000 00000fb6 2**2
    tlsthrd.o: file format pe-i386

    If there is no objection, I will unassign myself and reassign this ticket to the mingw runtime instead.

     
  • Earnie Boyd
    Earnie Boyd
    2012-03-16

    • assigned_to: cstrauss --> ir0nh34d
    • labels: 103944 --> mingw runtime (deprecated use WSL)
     
  • Earnie Boyd
    Earnie Boyd
    2012-03-16

    Chris can you chime in here? Thanks, Earnie.

     
  • I'm following up with Kai as he is the author of the patch that introduced TLS support. Would it be possible to generate a simple test case to demonstrate the issue?

     
  • Earnie Boyd
    Earnie Boyd
    2012-08-03

    • assigned_to: ir0nh34d --> earnie
     
  • Peter Hurley
    Peter Hurley
    2012-08-04

    @Chris,
    I think if you test Kai's sample code from that mail thread *on XP*, you'll find that it demonstrates the OP's issue.

    From a more recent reference than VS 2005 on msdn (specifically VS 2012, http://msdn.microsoft.com/en-us/library/2s9wt68x%28v=vs.110%29.aspx\):
    "On Windows operating systems before Windows Vista, __declspec( thread ) has some limitations. If a DLL declares any data or object as __declspec( thread ), it can cause a protection fault if dynamically loaded...."

     
  • Earnie Boyd
    Earnie Boyd
    2012-11-09

    I've tested Kai's code on both Windows 7 with gcc 4.7.0 and on XP with gcc 4.6.2 with the same good results.

     
  • Earnie Boyd
    Earnie Boyd
    2012-11-09

    • milestone: --> Aged_issue
    • status: open --> closed-out-of-date
     
  • Earnie Boyd
    Earnie Boyd
    2013-01-30

    • labels: mingw runtime (deprecated use WSL) --> tls, __declspec(thread)
    • status: closed-out-of-date --> closed
    • resolution: --> out-of-date
    • category: --> Known_bugs
    • milestone: --> WSL