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