1 /* Only necesary on x86 and amd64 targets */
2 #if defined(__i386__) || defined(__x86_64__)
6 extern char __RUNTIME_PSEUDO_RELOC_LIST__
;
7 extern char __RUNTIME_PSEUDO_RELOC_LIST_END__
;
8 extern char _image_base__
;
13 } runtime_pseudo_reloc_item_v1
;
19 } runtime_pseudo_reloc_item_v2
;
25 } runtime_pseudo_reloc_v2
;
27 #define RP_VERSION_V1 0
28 #define RP_VERSION_V2 1
31 do_pseudo_reloc (void* start
,void *end
,void *base
)
33 ptrdiff_t addr_imp
, reldata
;
34 ptrdiff_t reloc_target
= (ptrdiff_t) ((char *)end
- (char*)start
);
35 runtime_pseudo_reloc_v2
*v2_hdr
= (runtime_pseudo_reloc_v2
*) start
;
36 runtime_pseudo_reloc_item_v2
*r
;
40 /* Check if this is old version pseudo relocation version. */
41 if (reloc_target
>= 12
42 && v2_hdr
->magic1
== 0 && v2_hdr
->magic2
== 0
43 && v2_hdr
->version
== RP_VERSION_V1
)
45 if (v2_hdr
->magic1
!= 0 || v2_hdr
->magic2
!= 0)
47 runtime_pseudo_reloc_item_v1
*o
;
48 for (o
= (runtime_pseudo_reloc_item_v1
*) v2_hdr
; o
< (runtime_pseudo_reloc_item_v1
*)end
; o
++)
50 reloc_target
= (ptrdiff_t) base
+ o
->target
;
51 *((DWORD
*) reloc_target
) += o
->addend
;
55 /* Check if this is a known version. */
56 if (v2_hdr
->version
!= RP_VERSION_V2
)
58 fprintf (stderr
, "pseudo_relocation protocol version %d is unknown to this runtime.\n",
59 (int) v2_hdr
->version
);
62 /* Walk over header. */
63 r
= (runtime_pseudo_reloc_item_v2
*) &v2_hdr
[1];
65 for (; r
< (runtime_pseudo_reloc_item_v2
*) end
; r
++)
67 reloc_target
= (ptrdiff_t) base
+ r
->target
;
68 addr_imp
= (ptrdiff_t) base
+ r
->sym
;
69 addr_imp
= *((ptrdiff_t *) addr_imp
);
71 switch ((r
->flags
&0xff))
74 reldata
= (ptrdiff_t) (*((unsigned char *)reloc_target
));
75 if ((reldata
&0x80) != 0)
76 reldata
|= ~((ptrdiff_t) 0xff);
79 reldata
= (ptrdiff_t) (*((unsigned short *)reloc_target
));
80 if ((reldata
&0x8000) != 0)
81 reldata
|= ~((ptrdiff_t) 0xffff);
84 reldata
= (ptrdiff_t) (*((unsigned int *)reloc_target
));
86 if ((reldata
&0x80000000) != 0)
87 reldata
|= ~((ptrdiff_t) 0xffffffff);
92 reldata
= (ptrdiff_t) (*((unsigned long long *)reloc_target
));
97 fprintf(stderr
, "Unknown pseudo relocation bit size %d\n",(int) (r
->flags
& 0xff));
100 reldata
-= ((ptrdiff_t) base
+ r
->sym
);
102 switch ((r
->flags
& 0xff))
105 *((unsigned char*)reloc_target
)=(unsigned char) reldata
;
108 *((unsigned short*)reloc_target
)=(unsigned short) reldata
;
111 *((unsigned int*)reloc_target
)=(unsigned int) reldata
;
115 *((unsigned long long*)reloc_target
)=(unsigned long long) reldata
;
123 _pei386_runtime_relocator ()
125 do_pseudo_reloc (&__RUNTIME_PSEUDO_RELOC_LIST__
,&__RUNTIME_PSEUDO_RELOC_LIST_END__
,&_image_base__
);