1 #ifdef TARGET_DEFS_ONLY
3 #define EM_TCC_TARGET EM_X86_64
5 /* relocation type for 32 bit data relocation */
6 #define R_DATA_32 R_X86_64_32
7 #define R_DATA_PTR R_X86_64_64
8 #define R_JMP_SLOT R_X86_64_JUMP_SLOT
9 #define R_GLOB_DAT R_X86_64_GLOB_DAT
10 #define R_COPY R_X86_64_COPY
12 #define R_NUM R_X86_64_NUM
14 #define ELF_START_ADDR 0x400000
15 #define ELF_PAGE_SIZE 0x200000
17 #define HAVE_SECTION_RELOC
19 #else /* !TARGET_DEFS_ONLY */
23 static ElfW_Rel
*qrel
; /* ptr to next reloc entry reused */
24 ST_DATA
struct reloc_info relocs_info
[R_NUM
] = {
25 INIT_RELOC_INFO (R_X86_64_64
, 0, AUTO_GOTPLT_ENTRY
, 0)
26 INIT_RELOC_INFO (R_X86_64_32
, 0, AUTO_GOTPLT_ENTRY
, 0)
27 INIT_RELOC_INFO (R_X86_64_32S
, 0, AUTO_GOTPLT_ENTRY
, 0)
28 INIT_RELOC_INFO (R_X86_64_PC32
, 1, AUTO_GOTPLT_ENTRY
, 0)
29 INIT_RELOC_INFO (R_X86_64_PLT32
, 1, ALWAYS_GOTPLT_ENTRY
, 1)
30 INIT_RELOC_INFO (R_X86_64_GLOB_DAT
, 0, NO_GOTPLT_ENTRY
, 0)
31 INIT_RELOC_INFO (R_X86_64_JUMP_SLOT
, 1, NO_GOTPLT_ENTRY
, 0)
32 INIT_RELOC_INFO (R_X86_64_GOTPCREL
, 0, ALWAYS_GOTPLT_ENTRY
, 0)
33 INIT_RELOC_INFO (R_X86_64_GOTPCRELX
, 0, ALWAYS_GOTPLT_ENTRY
, 0)
34 INIT_RELOC_INFO (R_X86_64_REX_GOTPCRELX
, 0, ALWAYS_GOTPLT_ENTRY
, 0)
35 INIT_RELOC_INFO (R_X86_64_GOTTPOFF
, 0, BUILD_GOT_ONLY
, 0)
36 INIT_RELOC_INFO (R_X86_64_GOT32
, 0, ALWAYS_GOTPLT_ENTRY
, 0)
39 void relocate_init(Section
*sr
)
41 qrel
= (ElfW_Rel
*) sr
->data
;
44 void relocate(TCCState
*s1
, ElfW_Rel
*rel
, int type
, char *ptr
, addr_t addr
, addr_t val
)
46 int sym_index
, esym_index
;
48 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
52 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
53 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
54 qrel
->r_offset
= rel
->r_offset
;
56 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_64
);
57 qrel
->r_addend
= rel
->r_addend
;
61 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
62 qrel
->r_addend
= read64le(ptr
) + val
;
70 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
71 /* XXX: this logic may depend on TCC's codegen
72 now TCC uses R_X86_64_32 even for a 64bit pointer */
73 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
74 /* Use sign extension! */
75 qrel
->r_addend
= (int)read32le(ptr
) + val
;
82 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
84 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
86 qrel
->r_offset
= rel
->r_offset
;
87 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
88 /* Use sign extension! */
89 qrel
->r_addend
= (int)read32le(ptr
) + rel
->r_addend
;
97 /* fallthrough: val already holds the PLT slot address */
102 diff
= (long long)val
- addr
;
103 if (diff
< -2147483648LL || diff
> 2147483647LL) {
104 tcc_error("internal error: relocation failed");
109 case R_X86_64_GLOB_DAT
:
110 case R_X86_64_JUMP_SLOT
:
111 /* They don't need addend */
112 write64le(ptr
, val
- rel
->r_addend
);
114 case R_X86_64_GOTPCREL
:
115 case R_X86_64_GOTPCRELX
:
116 case R_X86_64_REX_GOTPCRELX
:
117 add32le(ptr
, s1
->got
->sh_addr
- addr
+
118 s1
->sym_attrs
[sym_index
].got_offset
- 4);
120 case R_X86_64_GOTTPOFF
:
121 add32le(ptr
, val
- s1
->got
->sh_addr
);
124 /* we load the got offset */
125 add32le(ptr
, s1
->sym_attrs
[sym_index
].got_offset
);
130 #endif /* !TARGET_DEFS_ONLY */