3 Contributed by Egor Duda <deo@logos-m.ru>
4 Modified by addition of runtime_pseudo_reloc version 2
5 by Kai Tietz <kai.tietz@onevision.com>
7 THIS SOFTWARE IS NOT COPYRIGHTED
9 This source code is offered for use in the public domain. You may
10 use, modify or distribute it freely.
12 This code is distributed in the hope that it will be useful but
13 WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
14 DISCLAMED. This includes but is not limited to warrenties of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 extern char __RUNTIME_PSEUDO_RELOC_LIST__;
25 extern char __RUNTIME_PSEUDO_RELOC_LIST_END__;
26 extern char _image_base__;
31 } runtime_pseudo_reloc_item_v1;
37 } runtime_pseudo_reloc_item_v2;
43 } runtime_pseudo_reloc_v2;
46 __write_memory (void *addr,const void *src,size_t len)
48 MEMORY_BASIC_INFORMATION b;
52 assert (VirtualQuery (addr, &b, sizeof(b)));
53 /* Temporarily allow write access to read-only protected memory. */
54 if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
55 VirtualProtect (b.BaseAddress, b.RegionSize, PAGE_EXECUTE_READWRITE,
57 memcpy (addr, src, len);
58 if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
59 VirtualProtect (b.BaseAddress, b.RegionSize, oldprot, &oldprot);
62 #define RP_VERSION_V1 0
63 #define RP_VERSION_V2 1
66 do_pseudo_reloc (void * start, void * end, void * base)
68 ptrdiff_t addr_imp, reldata;
69 ptrdiff_t reloc_target = (ptrdiff_t) ((char *)end - (char*)start);
70 runtime_pseudo_reloc_v2 *v2_hdr = (runtime_pseudo_reloc_v2 *) start;
71 runtime_pseudo_reloc_item_v2 *r;
75 /* Check if this is old version pseudo relocation version. */
76 if (reloc_target >= 12
77 && v2_hdr->magic1 == 0 && v2_hdr->magic2 == 0
78 && v2_hdr->version == RP_VERSION_V1)
80 if (v2_hdr->magic1 != 0 || v2_hdr->magic2 != 0)
82 runtime_pseudo_reloc_item_v1 * o;
83 for (o = (runtime_pseudo_reloc_item_v1 *) v2_hdr;
84 o < (runtime_pseudo_reloc_item_v1 *)end;
88 reloc_target = (ptrdiff_t) base + o->target;
89 newval = (*((DWORD*) reloc_target)) + o->addend;
90 __write_memory ((void *) reloc_target, &newval, sizeof(DWORD));
95 /* Check if this is a known version. */
96 if (v2_hdr->version != RP_VERSION_V2)
99 fprintf (stderr, "internal mingw runtime error:"
100 "psuedo_reloc version %d is unknown to this runtime.\n",
101 (int) v2_hdr->version);
106 /* Walk over header. */
107 r = (runtime_pseudo_reloc_item_v2 *) &v2_hdr[1];
109 for (; r < (runtime_pseudo_reloc_item_v2 *) end; r++)
111 reloc_target = (ptrdiff_t) base + r->target;
112 addr_imp = (ptrdiff_t) base + r->sym;
113 addr_imp = *((ptrdiff_t *) addr_imp);
115 switch ((r->flags & 0xff))
118 reldata = (ptrdiff_t) (*((unsigned char *)reloc_target));
119 if ((reldata & 0x80) != 0)
120 reldata |= ~((ptrdiff_t) 0xff);
123 reldata = (ptrdiff_t) (*((unsigned short *)reloc_target));
124 if ((reldata & 0x8000) != 0)
125 reldata |= ~((ptrdiff_t) 0xffff);
128 reldata = (ptrdiff_t) (*((unsigned int *)reloc_target));
130 if ((reldata & 0x80000000) != 0)
131 reldata |= ~((ptrdiff_t) 0xffffffff);
136 reldata = (ptrdiff_t) (*((unsigned long long *)reloc_target));
142 fprintf(stderr, "internal mingw runtime error: "
143 "unknown pseudo_reloc bit size %d\n",
144 (int) (r->flags & 0xff));
148 reldata -= ((ptrdiff_t) base + r->sym);
150 switch ((r->flags & 0xff))
153 __write_memory ((void *) reloc_target, &reldata, 1);
156 __write_memory ((void *) reloc_target, &reldata, 2);
159 __write_memory ((void *) reloc_target, &reldata, 4);
163 __write_memory ((void *) reloc_target, &reldata, 8);
171 _pei386_runtime_relocator ()
173 static int was_init = 0;
177 do_pseudo_reloc (&__RUNTIME_PSEUDO_RELOC_LIST__,
178 &__RUNTIME_PSEUDO_RELOC_LIST_END__,