I have created a fix for this, but I'm having trouble testing it. My relocations always end up on pages marked PAGE_EXECUTE_READ. To see Vadim's problem, I need PAGE_EXECUTE_WRITECOPY.

Vadim, can you provide any more context here? OS (W7? W8?), 32bit? 64bit? Using LoadLibrary? LoadLibraryEx? Are the exported symbols marked in any particular way (dllexport? __attribute__?)? Maybe you use a special linker script to combine sections? Any chance of a code sample showing the problem?

Anyone who knows something about how page protections are assigned or how relocs might end up in different sections, please feel free to enlighten me.

dw

On 8/19/2014 1:02 PM, Vadim Chugunov wrote:
No, sorry, I don't have the setup to build mingw. Not likely that I will have time to do it any time soon either. I meant this as a bug report. I hope the problem has been investigated sufficiently for mingw devs to act on it.

Vadim


On Mon, Aug 18, 2014 at 9:34 PM, dw <limegreenso...@yahoo.com <mailto:limegreenso...@yahoo.com>> wrote:

    Did you ever get this sorted out?

    dw


    On 8/15/2014 10:53 PM, dw wrote:
    So, it looks like what has happened is that newer OSs (ie >=
    Vista) set the page protect to PAGE_EXECUTE_WRITECOPY when doing
    a LoadLibrary.  This is a (relatively) new flag and apparently
    Mingw still assumes the old values are always in use.

    There are 3 places in pseudo-reloc.c that do comparisons of
    b.Protect to PAGE_EXECUTE_READWRITE.  I believe all three should
    also check for PAGE_EXECUTE_WRITECOPY.

    It also looks like a minor perf improvement in __write_memory is
    possible by adding an #else for that VirtualQuery /
    VirtualProtect stuff:

    static void
    __write_memory (void *addr, const void *src, size_t len)
    {
      if (!len)
        return;

    #ifdef __MINGW64_VERSION_MAJOR

      /* Mark the section writable once, and unset it in
       * restore_modified_sections. */
      mark_section_writable ((LPVOID) addr);

    #else/* __MINGW64_VERSION_MAJOR */

      MEMORY_BASIC_INFORMATION b;
      DWORD oldprot = 0;
      int call_unprotect = 0;

      if (!VirtualQuery (addr, &b, sizeof(b)))
        {
          __report_error ("  VirtualQuery failed for %d bytes at
    address %p",
                  (int) sizeof(b), addr);
        }

      /* Temporarily allow write access to read-only protected
    memory.  */
      if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect !=
    PAGE_READWRITE && b.Protect != PAGE_EXECUTE_WRITECOPY)
        {
          call_unprotect = 1;
          VirtualProtect (b.BaseAddress, b.RegionSize,
    PAGE_EXECUTE_READWRITE,
                  &oldprot);
        }

    #endif /* __MINGW64_VERSION_MAJOR */

      /* write the data. */
      memcpy (addr, src, len);

    #ifndef __MINGW64_VERSION_MAJOR

      /* Restore original protection. */
      if (call_unprotect && b.Protect != PAGE_EXECUTE_READWRITE &&
    b.Protect != PAGE_READWRITE && b.Protect != PAGE_EXECUTE_WRITECOPY)
        VirtualProtect (b.BaseAddress, b.RegionSize, oldprot, &oldprot);

    #endif /* __MINGW64_VERSION_MAJOR */
    }

    If setting the protection in mark_section_writable was
    unsuccessful (unlikely as that is), trying to set it again here
    is not likely to help.

    NB: I haven't tried this, but you have the setup to test it
    anyway.  Also, this code snippet only fixes 2 of the 3 places
    that use PAGE_EXECUTE_WRITECOPY.  Remember to change the
    comparison in mark_section_writable() as well.

    FWIW,
    dw

    On 8/15/2014 8:17 PM, Vadim Chugunov wrote:
    Okay, I was wrong about __MINGW64_VERSION_MAJOR: it *was* defined.

    What apparently happens is that the VirtualQuery() call that
    follows mark_section_writable(), returns page protection status
    of 0x80 (PAGE_EXECUTE_WRITECOPY), which is unexpected by the
    relocator code, so it falls back to calling VirtualProtect() per
    relocation entry.

    I am not entirely sure how this situation comes about, but here
    you go...

    On Fri, Aug 15, 2014 at 1:01 AM, Vadim Chugunov
    <vadi...@gmail.com <mailto:vadi...@gmail.com>> wrote:

        Hi,
        I am trying to figure out the cause of a slow application
        startup, and the evidence I have so far, points to mingw's
        _pei386_runtime_relocator() routine as the culprit.   When I
        start my app under debugger, I see this function calling
        VirtualProtect() about a zillion times in a row.

        Looking at the source, I see that
        __pei386_runtime_relocator() is supposed to change memory
        protection just once per executable section, but only if
        __MINGW64_VERSION_MAJOR is defined at compilation time.
        Otherwise,  it reverts to changing protection once per
        relocation entry, for compatibility (?).
        Unfortunately, I don't see any headers included by
        pseudo-reloc.c that would define this symbol.  And, indeed,
        the behavior I am seeing at runtime indicates that if was
        not defined...

        Am I reading this right?

        Thanks!
        Vadim




------------------------------------------------------------------------------
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to