2009-03-05 Kai Tietz <kai.tietz@onevision.com>
* pseudo-reloc.c: Rewrite to enable pseudo_reloc version 2.
This commit is contained in:
parent
06281845fb
commit
6e0e5a4fc2
|
@ -1,3 +1,7 @@
|
|||
2009-03-05 Kai Tietz <kai.tietz@onevision.com>
|
||||
|
||||
* pseudo-reloc.c: Rewrite to enable pseudo_reloc version 2.
|
||||
|
||||
2009-02-08 Keith Marshall <keithmarshall@users.sourceforge.net>
|
||||
|
||||
MinGW-Feature-Request [2222263]: Make getopt() GNU / BSD compatibile.
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
/* pseudo-reloc.c
|
||||
|
||||
Written by Egor Duda <deo@logos-m.ru>
|
||||
Contributed by Egor Duda <deo@logos-m.ru>
|
||||
Modified by addition of runtime_pseudo_reloc version 2
|
||||
by Kai Tietz <kai.tietz@onevision.com>
|
||||
|
||||
THIS SOFTWARE IS NOT COPYRIGHTED
|
||||
|
||||
This source code is offered for use in the public domain. You may
|
||||
|
@ -13,33 +16,164 @@
|
|||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
extern char __RUNTIME_PSEUDO_RELOC_LIST__;
|
||||
extern char __RUNTIME_PSEUDO_RELOC_LIST_END__;
|
||||
extern char _image_base__;
|
||||
|
||||
typedef struct {
|
||||
DWORD addend;
|
||||
DWORD target;
|
||||
} runtime_pseudo_reloc_item_v1;
|
||||
|
||||
extern char __RUNTIME_PSEUDO_RELOC_LIST__;
|
||||
extern char __RUNTIME_PSEUDO_RELOC_LIST_END__;
|
||||
extern char _image_base__;
|
||||
typedef struct {
|
||||
DWORD sym;
|
||||
DWORD target;
|
||||
DWORD flags;
|
||||
} runtime_pseudo_reloc_item_v2;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD addend;
|
||||
DWORD target;
|
||||
}
|
||||
runtime_pseudo_reloc;
|
||||
typedef struct {
|
||||
DWORD magic1;
|
||||
DWORD magic2;
|
||||
DWORD version;
|
||||
} runtime_pseudo_reloc_v2;
|
||||
|
||||
static void
|
||||
do_pseudo_reloc (void* start, void* end, void* base)
|
||||
__write_memory (void *addr,const void *src,size_t len)
|
||||
{
|
||||
DWORD reloc_target;
|
||||
runtime_pseudo_reloc* r;
|
||||
for (r = (runtime_pseudo_reloc*) start; r < (runtime_pseudo_reloc*) end; r++)
|
||||
{
|
||||
reloc_target = (DWORD) base + r->target;
|
||||
*((DWORD*) reloc_target) += r->addend;
|
||||
}
|
||||
MEMORY_BASIC_INFORMATION b;
|
||||
DWORD oldprot;
|
||||
if (!len)
|
||||
return;
|
||||
assert (VirtualQuery (addr, &b, sizeof(b)));
|
||||
/* 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);
|
||||
memcpy (addr, src, len);
|
||||
if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
|
||||
VirtualProtect (b.BaseAddress, b.RegionSize, oldprot, &oldprot);
|
||||
}
|
||||
|
||||
void
|
||||
_pei386_runtime_relocator ()
|
||||
#define RP_VERSION_V1 0
|
||||
#define RP_VERSION_V2 1
|
||||
|
||||
static void
|
||||
do_pseudo_reloc (void * start, void * end, void * base)
|
||||
{
|
||||
ptrdiff_t addr_imp, reldata;
|
||||
ptrdiff_t reloc_target = (ptrdiff_t) ((char *)end - (char*)start);
|
||||
runtime_pseudo_reloc_v2 *v2_hdr = (runtime_pseudo_reloc_v2 *) start;
|
||||
runtime_pseudo_reloc_item_v2 *r;
|
||||
|
||||
if (reloc_target < 8)
|
||||
return;
|
||||
/* Check if this is old version pseudo relocation version. */
|
||||
if (reloc_target >= 12
|
||||
&& v2_hdr->magic1 == 0 && v2_hdr->magic2 == 0
|
||||
&& v2_hdr->version == RP_VERSION_V1)
|
||||
v2_hdr++;
|
||||
if (v2_hdr->magic1 != 0 || v2_hdr->magic2 != 0)
|
||||
{
|
||||
runtime_pseudo_reloc_item_v1 * o;
|
||||
for (o = (runtime_pseudo_reloc_item_v1 *) v2_hdr;
|
||||
o < (runtime_pseudo_reloc_item_v1 *)end;
|
||||
o++)
|
||||
{
|
||||
DWORD newval;
|
||||
reloc_target = (ptrdiff_t) base + o->target;
|
||||
newval = (*((DWORD*) reloc_target)) + o->addend;
|
||||
__write_memory ((void *) reloc_target, &newval, sizeof(DWORD));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if this is a known version. */
|
||||
if (v2_hdr->version != RP_VERSION_V2)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "internal mingw runtime error:"
|
||||
"psuedo_reloc version %d is unknown to this runtime.\n",
|
||||
(int) v2_hdr->version);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* Walk over header. */
|
||||
r = (runtime_pseudo_reloc_item_v2 *) &v2_hdr[1];
|
||||
|
||||
for (; r < (runtime_pseudo_reloc_item_v2 *) end; r++)
|
||||
{
|
||||
reloc_target = (ptrdiff_t) base + r->target;
|
||||
addr_imp = (ptrdiff_t) base + r->sym;
|
||||
addr_imp = *((ptrdiff_t *) addr_imp);
|
||||
|
||||
switch ((r->flags & 0xff))
|
||||
{
|
||||
case 8:
|
||||
reldata = (ptrdiff_t) (*((unsigned char *)reloc_target));
|
||||
if ((reldata & 0x80) != 0)
|
||||
reldata |= ~((ptrdiff_t) 0xff);
|
||||
break;
|
||||
case 16:
|
||||
reldata = (ptrdiff_t) (*((unsigned short *)reloc_target));
|
||||
if ((reldata & 0x8000) != 0)
|
||||
reldata |= ~((ptrdiff_t) 0xffff);
|
||||
break;
|
||||
case 32:
|
||||
reldata = (ptrdiff_t) (*((unsigned int *)reloc_target));
|
||||
#ifdef _WIN64
|
||||
if ((reldata & 0x80000000) != 0)
|
||||
reldata |= ~((ptrdiff_t) 0xffffffff);
|
||||
#endif
|
||||
break;
|
||||
#ifdef _WIN64
|
||||
case 64:
|
||||
reldata = (ptrdiff_t) (*((unsigned long long *)reloc_target));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
reldata=0;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "internal mingw runtime error: "
|
||||
"unknown pseudo_reloc bit size %d\n",
|
||||
(int) (r->flags & 0xff));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
reldata -= ((ptrdiff_t) base + r->sym);
|
||||
reldata += addr_imp;
|
||||
switch ((r->flags & 0xff))
|
||||
{
|
||||
case 8:
|
||||
__write_memory ((void *) reloc_target, &reldata, 1);
|
||||
break;
|
||||
case 16:
|
||||
__write_memory ((void *) reloc_target, &reldata, 2);
|
||||
break;
|
||||
case 32:
|
||||
__write_memory ((void *) reloc_target, &reldata, 4);
|
||||
break;
|
||||
#ifdef _WIN64
|
||||
case 64:
|
||||
__write_memory ((void *) reloc_target, &reldata, 8);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_pei386_runtime_relocator ()
|
||||
{
|
||||
static int was_init = 0;
|
||||
if (was_init)
|
||||
return;
|
||||
++was_init;
|
||||
do_pseudo_reloc (&__RUNTIME_PSEUDO_RELOC_LIST__,
|
||||
&__RUNTIME_PSEUDO_RELOC_LIST_END__,
|
||||
&_image_base__);
|
||||
|
|
Loading…
Reference in New Issue