* pseudo-reloc.cc (auto_protect_for): New function.
(__write_memory): Call auto_protect_for to handle page protection. (do_pseudo_reloc): Call auto_protect_for to restore old page protection.
This commit is contained in:
parent
199a8245e0
commit
7dc5165954
|
@ -1,3 +1,10 @@
|
||||||
|
2012-09-02 Jin-woo Ye <jojelino@gmail.com>
|
||||||
|
Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* pseudo-reloc.cc (auto_protect_for): New function.
|
||||||
|
(__write_memory): Call auto_protect_for to handle page protection.
|
||||||
|
(do_pseudo_reloc): Call auto_protect_for to restore old page protection.
|
||||||
|
|
||||||
2012-08-26 Christopher Faylor <me.cygwin2012@cgf.cx>
|
2012-08-26 Christopher Faylor <me.cygwin2012@cgf.cx>
|
||||||
|
|
||||||
* pinfo.cc (pinfo::init): Remove assertion.
|
* pinfo.cc (pinfo::init): Remove assertion.
|
||||||
|
|
|
@ -126,6 +126,49 @@ __report_error (const char *msg, ...)
|
||||||
#endif
|
#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
|
/* This function temporarily marks the page containing addr
|
||||||
* writable, before copying len bytes from *src to *addr, and
|
* writable, before copying len bytes from *src to *addr, and
|
||||||
* then restores the original protection settings to the page.
|
* then restores the original protection settings to the page.
|
||||||
|
@ -142,27 +185,12 @@ __report_error (const char *msg, ...)
|
||||||
static void
|
static void
|
||||||
__write_memory (void *addr, const void *src, size_t len)
|
__write_memory (void *addr, const void *src, size_t len)
|
||||||
{
|
{
|
||||||
MEMORY_BASIC_INFORMATION b;
|
|
||||||
DWORD oldprot;
|
|
||||||
|
|
||||||
if (!len)
|
if (!len)
|
||||||
return;
|
return;
|
||||||
|
/* Fix page protection for writing. */
|
||||||
if (!VirtualQuery (addr, &b, sizeof (b)))
|
auto_protect_for (addr);
|
||||||
{
|
|
||||||
__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);
|
|
||||||
/* write the data. */
|
/* write the data. */
|
||||||
memcpy (addr, src, len);
|
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
|
#define RP_VERSION_V1 0
|
||||||
|
@ -232,6 +260,8 @@ do_pseudo_reloc (void * start, void * end, void * base)
|
||||||
newval = (*((DWORD*) reloc_target)) + o->addend;
|
newval = (*((DWORD*) reloc_target)) + o->addend;
|
||||||
__write_memory ((void *) reloc_target, &newval, sizeof (DWORD));
|
__write_memory ((void *) reloc_target, &newval, sizeof (DWORD));
|
||||||
}
|
}
|
||||||
|
/* Restore original protection. */
|
||||||
|
auto_protect_for (NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +352,9 @@ do_pseudo_reloc (void * start, void * end, void * base)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Restore original protection. */
|
||||||
|
auto_protect_for (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
|
|
Loading…
Reference in New Issue