2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the w64 mingw-runtime package.
4 * No warranty is given; refer to the file DISCLAIMER within this package.
12 extern char __RUNTIME_PSEUDO_RELOC_LIST__
;
13 extern char __RUNTIME_PSEUDO_RELOC_LIST_END__
;
14 extern char _image_base__
;
19 } runtime_pseudo_reloc_item_v1
;
25 } runtime_pseudo_reloc_item_v2
;
31 } runtime_pseudo_reloc_v2
;
34 __write_memory (void *addr
,const void *src
,size_t len
)
36 MEMORY_BASIC_INFORMATION b
;
40 if (!VirtualQuery (addr
, &b
, sizeof(b
)))
43 if (b
.Protect
!= PAGE_EXECUTE_READWRITE
&& b
.Protect
!= PAGE_READWRITE
)
44 VirtualProtect (b
.BaseAddress
, b
.RegionSize
, PAGE_EXECUTE_READWRITE
,
46 memcpy (addr
, src
, len
);
47 if (b
.Protect
!= PAGE_EXECUTE_READWRITE
&& b
.Protect
!= PAGE_READWRITE
)
48 VirtualProtect (b
.BaseAddress
, b
.RegionSize
, oldprot
, &oldprot
);
51 #define RP_VERSION_V1 0
52 #define RP_VERSION_V2 1
55 do_pseudo_reloc (void* start
,void *end
,void *base
)
57 ptrdiff_t addr_imp
, reldata
;
58 ptrdiff_t reloc_target
= (ptrdiff_t) ((char *)end
- (char*)start
);
59 runtime_pseudo_reloc_v2
*v2_hdr
= (runtime_pseudo_reloc_v2
*) start
;
60 runtime_pseudo_reloc_item_v2
*r
;
64 /* Check if this is old version pseudo relocation version. */
65 if (reloc_target
>= 12
66 && v2_hdr
->magic1
== 0 && v2_hdr
->magic2
== 0
67 && v2_hdr
->version
== RP_VERSION_V1
)
69 if (v2_hdr
->magic1
!= 0 || v2_hdr
->magic2
!= 0)
71 runtime_pseudo_reloc_item_v1
*o
;
72 for (o
= (runtime_pseudo_reloc_item_v1
*) v2_hdr
; o
< (runtime_pseudo_reloc_item_v1
*)end
; o
++)
75 reloc_target
= (ptrdiff_t) base
+ o
->target
;
76 newval
= (*((DWORD
*) reloc_target
)) + o
->addend
;
77 __write_memory ((void *) reloc_target
, &newval
, sizeof(DWORD
));
81 /* Check if this is a known version. */
82 if (v2_hdr
->version
!= RP_VERSION_V2
)
84 fprintf (stderr
, "pseudo_relocation protocol version %d is unknown to this runtime.\n",
85 (int) v2_hdr
->version
);
88 /* Walk over header. */
89 r
= (runtime_pseudo_reloc_item_v2
*) &v2_hdr
[1];
91 for (; r
< (runtime_pseudo_reloc_item_v2
*) end
; r
++)
93 reloc_target
= (ptrdiff_t) base
+ r
->target
;
94 addr_imp
= (ptrdiff_t) base
+ r
->sym
;
95 addr_imp
= *((ptrdiff_t *) addr_imp
);
97 switch ((r
->flags
&0xff))
100 reldata
= (ptrdiff_t) (*((unsigned char *)reloc_target
));
101 if ((reldata
&0x80) != 0)
102 reldata
|= ~((ptrdiff_t) 0xff);
105 reldata
= (ptrdiff_t) (*((unsigned short *)reloc_target
));
106 if ((reldata
&0x8000) != 0)
107 reldata
|= ~((ptrdiff_t) 0xffff);
110 reldata
= (ptrdiff_t) (*((unsigned int *)reloc_target
));
112 if ((reldata
&0x80000000) != 0)
113 reldata
|= ~((ptrdiff_t) 0xffffffff);
118 reldata
= (ptrdiff_t) (*((unsigned long long *)reloc_target
));
123 fprintf(stderr
, "Unknown pseudo relocation bit size %d\n",(int) (r
->flags
& 0xff));
126 reldata
-= ((ptrdiff_t) base
+ r
->sym
);
128 switch ((r
->flags
& 0xff))
131 __write_memory ((void *) reloc_target
, &reldata
, 1);
134 __write_memory ((void *) reloc_target
, &reldata
, 2);
137 __write_memory ((void *) reloc_target
, &reldata
, 4);
141 __write_memory ((void *) reloc_target
, &reldata
, 8);
149 _pei386_runtime_relocator ()
151 static int was_init
= 0;
155 do_pseudo_reloc (&__RUNTIME_PSEUDO_RELOC_LIST__
,&__RUNTIME_PSEUDO_RELOC_LIST_END__
,&_image_base__
);