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

    (mingw version = i686-4.9.0-win32-dwarf-rt_v3-rev2)




------------------------------------------------------------------------------


_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

------------------------------------------------------------------------------
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to