[PATCH] suggestion for faster pseudo-reloc.
Corinna Vinschen
corinna-cygwin@cygwin.com
Mon Sep 3 11:25:00 GMT 2012
On Sep 3 19:02, JonY wrote:
> On 9/3/2012 18:35, Corinna Vinschen wrote:
> > On Sep 3 17:34, JonY wrote:
> >> On 9/3/2012 11:05, Charles Wilson wrote:
> >>> On 9/2/2012 1:51 PM, Jin-woo Ye wrote:
> >>>> Now it is clear that this patch would be needed other relevant projects
> >>>> such as mingw, mingw-w64. thanks for your effort on simplified one.
> >>>
> >>> Yes, while it is not required that all of those systems stay exactly in
> >>> sync, there has been some effort in ensuring that the pseudo-reloc
> >>> implementation used by all three remains very similar if not identical.
> >>>
> >>> Please bring this patch to the attention of the mingw.org and
> >>> mingw64.sf.net people, if it's not too much trouble.
> >>>
> >>> --
> >>> Chuck
> >>>
> >>>
> >>>
> >>
> >> Original message already forwarded to mingw-w64 devel list. Thanks
> >> Jin-woo Ye.
> >
> > Do you want the patch I eventually applied, too?
> >
> >
> > Corinna
> >
>
> Yeah, that will be good too.
>
> I forwarded the CVS commit message too.
It differs a lot from the original source, so you might contemplate
to send a follow up mail to the mingw-w64 devel with the attached
patch.
> I'm not sure if anybody else is
> more suited to comment on it than Kai, he is still on vacation though.
No worries. I'm on vacation myself. If my slipped disc hadn't kept me
home, I would be in England now :|
Corinna
--
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Project Co-Leader cygwin AT cygwin DOT com
Red Hat
-------------- next part --------------
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/pseudo-reloc.cc,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- src/winsup/cygwin/pseudo-reloc.cc 2012/08/16 23:34:44 1.10
+++ src/winsup/cygwin/pseudo-reloc.cc 2012/09/02 10:21:34 1.11
@@ -126,6 +126,49 @@
#endif
}
+/*
+ * This function automatically sets addr as PAGE_EXECUTE_READWRITE
+ * by deciding whether VirtualQuery for the addr is actually needed.
+ * And it assumes that it is called in LdrpCallInitRoutine.
+ * Hence not thread safe.
+ */
+static void
+auto_protect_for (void* addr)
+{
+ static MEMORY_BASIC_INFORMATION mbi;
+ static bool state = false;
+ static DWORD oldprot;
+
+ if (!addr)
+ {
+ /* Restore original protection. */
+ if (!(mbi.Protect & (PAGE_EXECUTE_READWRITE | PAGE_READWRITE)))
+ VirtualProtect (mbi.BaseAddress, mbi.RegionSize, oldprot, &oldprot);
+ state = false;
+ return;
+ }
+ if (state)
+ {
+ /* We have valid region information. Are we still within this region?
+ If so, just leave. */
+ void *ptr = ((void*) ((ptrdiff_t) mbi.BaseAddress + mbi.RegionSize));
+ if (addr >= mbi.BaseAddress && addr < ptr)
+ return;
+ /* Otherwise, restore original protection and fall through to querying
+ and potentially changing next region. */
+ if (!(mbi.Protect & (PAGE_EXECUTE_READWRITE | PAGE_READWRITE)))
+ VirtualProtect (mbi.BaseAddress, mbi.RegionSize, oldprot, &oldprot);
+ }
+ else
+ state = true;
+ /* Query region and temporarily allow write access to read-only protected
+ memory. */
+ VirtualQuery (addr, &mbi, sizeof mbi);
+ if (!(mbi.Protect & (PAGE_EXECUTE_READWRITE | PAGE_READWRITE)))
+ VirtualProtect (mbi.BaseAddress, mbi.RegionSize,
+ PAGE_EXECUTE_READWRITE, &oldprot);
+}
+
/* This function temporarily marks the page containing addr
* writable, before copying len bytes from *src to *addr, and
* then restores the original protection settings to the page.
@@ -142,27 +185,12 @@
static void
__write_memory (void *addr, const void *src, size_t len)
{
- MEMORY_BASIC_INFORMATION b;
- DWORD oldprot;
-
if (!len)
return;
-
- 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)
- VirtualProtect (b.BaseAddress, b.RegionSize, PAGE_EXECUTE_READWRITE,
- &oldprot);
+ /* Fix page protection for writing. */
+ auto_protect_for (addr);
/* write the data. */
memcpy (addr, src, len);
- /* Restore original protection. */
- if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
- VirtualProtect (b.BaseAddress, b.RegionSize, oldprot, &oldprot);
}
#define RP_VERSION_V1 0
@@ -232,6 +260,8 @@
newval = (*((DWORD*) reloc_target)) + o->addend;
__write_memory ((void *) reloc_target, &newval, sizeof (DWORD));
}
+ /* Restore original protection. */
+ auto_protect_for (NULL);
return;
}
@@ -322,7 +352,9 @@
break;
#endif
}
- }
+ }
+ /* Restore original protection. */
+ auto_protect_for (NULL);
}
#ifdef __CYGWIN__
More information about the Cygwin-patches
mailing list