- DBGKD_WAIT_STATE_CHANGE64 is used in KD protocol 5, not number 6 that we use. Proto...
[reactos.git] / reactos / lib / 3rdparty / mingw / pseudo-reloc.c
1 /**
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.
5 */
6
7 #include <windows.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <memory.h>
11
12 extern char __RUNTIME_PSEUDO_RELOC_LIST__;
13 extern char __RUNTIME_PSEUDO_RELOC_LIST_END__;
14 extern char _image_base__;
15
16 typedef struct {
17 DWORD addend;
18 DWORD target;
19 } runtime_pseudo_reloc_item_v1;
20
21 typedef struct {
22 DWORD sym;
23 DWORD target;
24 DWORD flags;
25 } runtime_pseudo_reloc_item_v2;
26
27 typedef struct {
28 DWORD magic1;
29 DWORD magic2;
30 DWORD version;
31 } runtime_pseudo_reloc_v2;
32
33 static void
34 __write_memory (void *addr,const void *src,size_t len)
35 {
36 MEMORY_BASIC_INFORMATION b;
37 DWORD oldprot;
38 if (!len)
39 return;
40 if (!VirtualQuery (addr, &b, sizeof(b)))
41 abort ();
42 // Protect
43 if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
44 VirtualProtect (b.BaseAddress, b.RegionSize, PAGE_EXECUTE_READWRITE,
45 &oldprot);
46 memcpy (addr, src, len);
47 if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
48 VirtualProtect (b.BaseAddress, b.RegionSize, oldprot, &oldprot);
49 }
50
51 #define RP_VERSION_V1 0
52 #define RP_VERSION_V2 1
53
54 static void
55 do_pseudo_reloc (void* start,void *end,void *base)
56 {
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;
61
62 if (reloc_target < 8)
63 return;
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)
68 v2_hdr++;
69 if (v2_hdr->magic1 != 0 || v2_hdr->magic2 != 0)
70 {
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++)
73 {
74 DWORD newval;
75 reloc_target = (ptrdiff_t) base + o->target;
76 newval = (*((DWORD*) reloc_target)) + o->addend;
77 __write_memory ((void *) reloc_target, &newval, sizeof(DWORD));
78 }
79 return;
80 }
81 /* Check if this is a known version. */
82 if (v2_hdr->version != RP_VERSION_V2)
83 {
84 fprintf (stderr, "pseudo_relocation protocol version %d is unknown to this runtime.\n",
85 (int) v2_hdr->version);
86 return;
87 }
88 /* Walk over header. */
89 r = (runtime_pseudo_reloc_item_v2 *) &v2_hdr[1];
90
91 for (; r < (runtime_pseudo_reloc_item_v2 *) end; r++)
92 {
93 reloc_target = (ptrdiff_t) base + r->target;
94 addr_imp = (ptrdiff_t) base + r->sym;
95 addr_imp = *((ptrdiff_t *) addr_imp);
96
97 switch ((r->flags&0xff))
98 {
99 case 8:
100 reldata = (ptrdiff_t) (*((unsigned char *)reloc_target));
101 if ((reldata&0x80) != 0)
102 reldata |= ~((ptrdiff_t) 0xff);
103 break;
104 case 16:
105 reldata = (ptrdiff_t) (*((unsigned short *)reloc_target));
106 if ((reldata&0x8000) != 0)
107 reldata |= ~((ptrdiff_t) 0xffff);
108 break;
109 case 32:
110 reldata = (ptrdiff_t) (*((unsigned int *)reloc_target));
111 #ifdef _WIN64
112 if ((reldata&0x80000000) != 0)
113 reldata |= ~((ptrdiff_t) 0xffffffff);
114 #endif
115 break;
116 #ifdef _WIN64
117 case 64:
118 reldata = (ptrdiff_t) (*((unsigned long long *)reloc_target));
119 break;
120 #endif
121 default:
122 reldata=0;
123 fprintf(stderr, "Unknown pseudo relocation bit size %d\n",(int) (r->flags & 0xff));
124 break;
125 }
126 reldata -= ((ptrdiff_t) base + r->sym);
127 reldata += addr_imp;
128 switch ((r->flags & 0xff))
129 {
130 case 8:
131 __write_memory ((void *) reloc_target, &reldata, 1);
132 break;
133 case 16:
134 __write_memory ((void *) reloc_target, &reldata, 2);
135 break;
136 case 32:
137 __write_memory ((void *) reloc_target, &reldata, 4);
138 break;
139 #ifdef _WIN64
140 case 64:
141 __write_memory ((void *) reloc_target, &reldata, 8);
142 break;
143 #endif
144 }
145 }
146 }
147
148 void
149 _pei386_runtime_relocator ()
150 {
151 static int was_init = 0;
152 if (was_init)
153 return;
154 ++was_init;
155 do_pseudo_reloc (&__RUNTIME_PSEUDO_RELOC_LIST__,&__RUNTIME_PSEUDO_RELOC_LIST_END__,&_image_base__);
156 }