2 #define HAVE_SECTION_RELOC
4 static ElfW_Rel
*qrel
; /* ptr to next reloc entry reused */
6 void relocate_init(Section
*sr
)
8 qrel
= (ElfW_Rel
*) sr
->data
;
11 void relocate(TCCState
*s1
, ElfW_Rel
*rel
, int type
, char *ptr
, addr_t addr
, addr_t val
)
13 int sym_index
, esym_index
;
15 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
19 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
20 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
21 qrel
->r_offset
= rel
->r_offset
;
23 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_64
);
24 qrel
->r_addend
= rel
->r_addend
;
28 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
29 qrel
->r_addend
= read64le(ptr
) + val
;
37 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
38 /* XXX: this logic may depend on TCC's codegen
39 now TCC uses R_X86_64_32 even for a 64bit pointer */
40 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
41 /* Use sign extension! */
42 qrel
->r_addend
= (int)read32le(ptr
) + val
;
49 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
51 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
53 qrel
->r_offset
= rel
->r_offset
;
54 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
55 /* Use sign extension! */
56 qrel
->r_addend
= (int)read32le(ptr
) + rel
->r_addend
;
64 /* We've put the PLT slot offset into r_addend when generating
65 it, and that's what we must use as relocation value (adjusted
66 by section offset of course). */
67 val
= s1
->plt
->sh_addr
+ rel
->r_addend
;
73 diff
= (long long)val
- addr
;
74 if (diff
< -2147483648LL || diff
> 2147483647LL) {
75 tcc_error("internal error: relocation failed");
80 case R_X86_64_GLOB_DAT
:
81 case R_X86_64_JUMP_SLOT
:
82 /* They don't need addend */
83 write64le(ptr
, val
- rel
->r_addend
);
85 case R_X86_64_GOTPCREL
:
86 case R_X86_64_GOTPCRELX
:
87 case R_X86_64_REX_GOTPCRELX
:
88 add32le(ptr
, s1
->got
->sh_addr
- addr
+
89 s1
->sym_attrs
[sym_index
].got_offset
- 4);
91 case R_X86_64_GOTTPOFF
:
92 add32le(ptr
, val
- s1
->got
->sh_addr
);
95 /* we load the got offset */
96 add32le(ptr
, s1
->sym_attrs
[sym_index
].got_offset
);