Consolidate all relocations in relocate_section
[tinycc.git] / i386-link.c
blob019b53f38a360cfc9b267cb796f05269d6a36c8f
1 #include "tcc.h"
2 #define HAVE_SECTION_RELOC
4 static ElfW_Rel *qrel; /* ptr to next reloc entry reused */
5 ST_DATA struct reloc_info relocs_info[] = {
6 INIT_RELOC_INFO (R_386_32, 0, NO_GOTPLT_ENTRY, 0)
7 INIT_RELOC_INFO (R_386_PC32, 1, AUTO_GOTPLT_ENTRY, 0)
8 INIT_RELOC_INFO (R_386_PLT32, 1, ALWAYS_GOTPLT_ENTRY, 0)
9 INIT_RELOC_INFO (R_386_GLOB_DAT, 0, NO_GOTPLT_ENTRY, 0)
10 INIT_RELOC_INFO (R_386_JMP_SLOT, 1, NO_GOTPLT_ENTRY, 0)
11 INIT_RELOC_INFO (R_386_GOTPC, 0, BUILD_GOT_ONLY, 0)
12 INIT_RELOC_INFO (R_386_GOTOFF, 0, BUILD_GOT_ONLY, 0)
13 INIT_RELOC_INFO (R_386_GOT32, 0, ALWAYS_GOTPLT_ENTRY, 0)
14 INIT_RELOC_INFO (R_386_GOT32X, 0, ALWAYS_GOTPLT_ENTRY, 0)
15 INIT_RELOC_INFO (R_386_16, 0, NO_GOTPLT_ENTRY, 0)
16 INIT_RELOC_INFO (R_386_PC16, 1, AUTO_GOTPLT_ENTRY, 0)
19 void relocate_init(Section *sr)
21 qrel = (ElfW_Rel *) sr->data;
24 void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, addr_t val)
26 int sym_index, esym_index;
28 sym_index = ELFW(R_SYM)(rel->r_info);
30 switch (type) {
31 case R_386_32:
32 if (s1->output_type == TCC_OUTPUT_DLL) {
33 esym_index = s1->symtab_to_dynsym[sym_index];
34 qrel->r_offset = rel->r_offset;
35 if (esym_index) {
36 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
37 qrel++;
38 return;
39 } else {
40 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
41 qrel++;
44 add32le(ptr, val);
45 return;
46 case R_386_PC32:
47 if (s1->output_type == TCC_OUTPUT_DLL) {
48 /* DLL relocation */
49 esym_index = s1->symtab_to_dynsym[sym_index];
50 if (esym_index) {
51 qrel->r_offset = rel->r_offset;
52 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
53 qrel++;
54 return;
57 add32le(ptr, val - addr);
58 return;
59 case R_386_PLT32:
60 add32le(ptr, val - addr);
61 return;
62 case R_386_GLOB_DAT:
63 case R_386_JMP_SLOT:
64 write32le(ptr, val);
65 return;
66 case R_386_GOTPC:
67 add32le(ptr, s1->got->sh_addr - addr);
68 return;
69 case R_386_GOTOFF:
70 add32le(ptr, val - s1->got->sh_addr);
71 return;
72 case R_386_GOT32:
73 case R_386_GOT32X:
74 /* we load the got offset */
75 add32le(ptr, s1->sym_attrs[sym_index].got_offset);
76 return;
77 case R_386_16:
78 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
79 output_file:
80 tcc_error("can only produce 16-bit binary files");
82 write16le(ptr, read16le(ptr) + val);
83 return;
84 case R_386_PC16:
85 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
86 goto output_file;
87 write16le(ptr, read16le(ptr) + val - addr);
88 return;
89 case R_386_RELATIVE:
90 /* do nothing */
91 return;
92 case R_386_COPY:
93 /* This reloction must copy initialized data from the library
94 to the program .bss segment. Currently made like for ARM
95 (to remove noise of defaukt case). Is this true?
97 return;
98 default:
99 fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
100 type, (unsigned)addr, ptr, (unsigned)val);
101 return;