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
18 #define PCRELATIVE_DLLPLT 1
20 #else /* !TARGET_DEFS_ONLY */
24 /* Returns 1 for a code relocation, 0 for a data relocation. For unknown
25 relocations, returns -1. */
26 int code_reloc (int reloc_type
)
32 case R_X86_64_GOTPCREL
:
33 case R_X86_64_GOTPCRELX
:
34 case R_X86_64_REX_GOTPCRELX
:
35 case R_X86_64_GOTTPOFF
:
37 case R_X86_64_GLOB_DAT
:
43 case R_X86_64_JUMP_SLOT
:
47 tcc_error ("Unknown relocation type: %d", reloc_type
);
51 /* Returns an enumerator to describe wether and when the relocation needs a
52 GOT and/or PLT entry to be created. See tcc.h for a description of the
54 int gotplt_entry_type (int reloc_type
)
57 case R_X86_64_GLOB_DAT
:
58 case R_X86_64_JUMP_SLOT
:
60 return NO_GOTPLT_ENTRY
;
66 return AUTO_GOTPLT_ENTRY
;
68 case R_X86_64_GOTTPOFF
:
69 return BUILD_GOT_ONLY
;
72 case R_X86_64_GOTPCREL
:
73 case R_X86_64_GOTPCRELX
:
74 case R_X86_64_REX_GOTPCRELX
:
76 return ALWAYS_GOTPLT_ENTRY
;
79 tcc_error ("Unknown relocation type: %d", reloc_type
);
83 static ElfW_Rel
*qrel
; /* ptr to next reloc entry reused */
85 void relocate_init(Section
*sr
)
87 qrel
= (ElfW_Rel
*) sr
->data
;
90 void relocate(TCCState
*s1
, ElfW_Rel
*rel
, int type
, char *ptr
, addr_t addr
, addr_t val
)
92 int sym_index
, esym_index
;
94 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
98 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
99 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
100 qrel
->r_offset
= rel
->r_offset
;
102 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_64
);
103 qrel
->r_addend
= rel
->r_addend
;
107 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
108 qrel
->r_addend
= read64le(ptr
) + val
;
116 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
117 /* XXX: this logic may depend on TCC's codegen
118 now TCC uses R_X86_64_32 even for a 64bit pointer */
119 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
120 /* Use sign extension! */
121 qrel
->r_addend
= (int)read32le(ptr
) + val
;
128 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
130 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
132 qrel
->r_offset
= rel
->r_offset
;
133 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
134 /* Use sign extension! */
135 qrel
->r_addend
= (int)read32le(ptr
) + rel
->r_addend
;
143 /* fallthrough: val already holds the PLT slot address */
148 diff
= (long long)val
- addr
;
149 if (diff
< -2147483648LL || diff
> 2147483647LL) {
150 tcc_error("internal error: relocation failed");
155 case R_X86_64_GLOB_DAT
:
156 case R_X86_64_JUMP_SLOT
:
157 /* They don't need addend */
158 write64le(ptr
, val
- rel
->r_addend
);
160 case R_X86_64_GOTPCREL
:
161 case R_X86_64_GOTPCRELX
:
162 case R_X86_64_REX_GOTPCRELX
:
163 add32le(ptr
, s1
->got
->sh_addr
- addr
+
164 s1
->sym_attrs
[sym_index
].got_offset
- 4);
166 case R_X86_64_GOTTPOFF
:
167 add32le(ptr
, val
- s1
->got
->sh_addr
);
170 /* we load the got offset */
171 add32le(ptr
, s1
->sym_attrs
[sym_index
].got_offset
);
176 #endif /* !TARGET_DEFS_ONLY */