1 /* neatcc ELF object generation */
9 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
20 /* simplified elf struct and macro names */
23 # define Elf_Ehdr Elf64_Ehdr
24 # define Elf_Shdr Elf64_Shdr
25 # define Elf_Sym Elf64_Sym
26 # define Elf_Rel Elf64_Rela
27 # define ELF_ST_INFO ELF64_ST_INFO
28 # define ELF_ST_BIND ELF64_ST_BIND
29 # define ELF_R_SYM ELF64_R_SYM
30 # define ELF_R_TYPE ELF64_R_TYPE
31 # define ELF_R_INFO ELF64_R_INFO
34 # define Elf_Ehdr Elf32_Ehdr
35 # define Elf_Shdr Elf32_Shdr
36 # define Elf_Sym Elf32_Sym
37 # define Elf_Rel Elf32_Rel
38 # define ELF_ST_INFO ELF32_ST_INFO
39 # define ELF_ST_BIND ELF32_ST_BIND
40 # define ELF_R_SYM ELF32_R_SYM
41 # define ELF_R_TYPE ELF32_R_TYPE
42 # define ELF_R_INFO ELF32_R_INFO
46 static Elf_Shdr shdr
[NSECS
];
47 static Elf_Sym syms
[NSYMS
];
49 static char symstr
[NSYMS
* 8];
50 static int nsymstr
= 1;
52 static Elf_Rel dsrels
[NRELS
];
54 static Elf_Rel rels
[NRELS
];
57 void err(char *msg
, ...);
58 static int rel_type(int flags
);
59 static void ehdr_init(Elf_Ehdr
*ehdr
);
61 static int symstr_add(char *name
)
63 int len
= strlen(name
) + 1;
64 if (nsymstr
+ len
>= sizeof(symstr
))
65 err("nomem: NSYMS reached!\n");
66 strcpy(symstr
+ nsymstr
, name
);
71 static int sym_find(char *name
)
74 for (i
= 0; i
< nsyms
; i
++)
75 if (!strcmp(name
, symstr
+ syms
[i
].st_name
))
80 static Elf_Sym
*put_sym(char *name
)
82 int found
= sym_find(name
);
83 Elf_Sym
*sym
= found
!= -1 ? &syms
[found
] : &syms
[nsyms
++];
87 err("nomem: NSYMS reached!\n");
88 sym
->st_name
= symstr_add(name
);
89 sym
->st_shndx
= SHN_UNDEF
;
90 sym
->st_info
= ELF_ST_INFO(STB_GLOBAL
, STT_FUNC
);
94 #define SYMLOCAL(i) (ELF_ST_BIND(syms[i].st_info) == STB_LOCAL)
96 static void mvrela(int *mv
, Elf_Rel
*rels
, int nrels
)
99 for (i
= 0; i
< nrels
; i
++) {
100 int sym
= ELF_R_SYM(rels
[i
].r_info
);
101 int type
= ELF_R_TYPE(rels
[i
].r_info
);
102 rels
[i
].r_info
= ELF_R_INFO(mv
[sym
], type
);
106 static int syms_sort(void)
111 for (i
= 0; i
< nsyms
; i
++)
117 while (i
< j
&& SYMLOCAL(i
))
119 while (j
>= i
&& !SYMLOCAL(j
))
130 mvrela(mv
, rels
, nrels
);
131 mvrela(mv
, dsrels
, ndsrels
);
135 void out_init(int flags
)
139 void out_sym(char *name
, int flags
, int off
, int len
)
141 Elf_Sym
*sym
= put_sym(name
);
142 int type
= (flags
& OUT_CS
) ? STT_FUNC
: STT_OBJECT
;
143 int bind
= (flags
& OUT_GLOB
) ? STB_GLOBAL
: STB_LOCAL
;
145 sym
->st_shndx
= SEC_TEXT
;
147 sym
->st_shndx
= SEC_DAT
;
149 sym
->st_shndx
= SEC_BSS
;
150 sym
->st_info
= ELF_ST_INFO(bind
, type
);
155 static void out_csrel(int idx
, int off
, int flags
)
157 Elf_Rel
*r
= &rels
[nrels
++];
159 err("nomem: NRELS reached!\n");
161 r
->r_info
= ELF_R_INFO(idx
, rel_type(flags
));
164 static void out_dsrel(int idx
, int off
, int flags
)
166 Elf_Rel
*r
= &dsrels
[ndsrels
++];
167 if (ndsrels
>= NRELS
)
168 err("nomem: NRELS reached!\n");
170 r
->r_info
= ELF_R_INFO(idx
, rel_type(flags
));
173 void out_rel(char *name
, int flags
, int off
)
175 Elf_Sym
*sym
= put_sym(name
);
176 int idx
= sym
- syms
;
178 out_dsrel(idx
, off
, flags
);
180 out_csrel(idx
, off
, flags
);
183 static int bss_len(void)
187 for (i
= 0; i
< nsyms
; i
++) {
188 int end
= syms
[i
].st_value
+ syms
[i
].st_size
;
189 if (syms
[i
].st_shndx
== SEC_BSS
)
196 void out_write(int fd
, char *cs
, int cslen
, char *ds
, int dslen
)
198 Elf_Shdr
*text_shdr
= &shdr
[SEC_TEXT
];
199 Elf_Shdr
*rela_shdr
= &shdr
[SEC_REL
];
200 Elf_Shdr
*symstr_shdr
= &shdr
[SEC_SYMSTR
];
201 Elf_Shdr
*syms_shdr
= &shdr
[SEC_SYMS
];
202 Elf_Shdr
*dat_shdr
= &shdr
[SEC_DAT
];
203 Elf_Shdr
*datrel_shdr
= &shdr
[SEC_DATREL
];
204 Elf_Shdr
*bss_shdr
= &shdr
[SEC_BSS
];
205 unsigned long offset
= sizeof(ehdr
);
207 /* workaround for the idiotic gnuld; use neatld instead! */
208 text_shdr
->sh_name
= symstr_add(".cs");
209 rela_shdr
->sh_name
= symstr_add(USERELA
? ".rela.cs" : ".rels.cs");
210 dat_shdr
->sh_name
= symstr_add(".ds");
211 datrel_shdr
->sh_name
= symstr_add(USERELA
? ".rela.ds" : ".rels.ds");
213 ehdr
.e_ident
[0] = 0x7f;
214 ehdr
.e_ident
[1] = 'E';
215 ehdr
.e_ident
[2] = 'L';
216 ehdr
.e_ident
[3] = 'F';
217 ehdr
.e_ident
[4] = LONGSZ
== 8 ? ELFCLASS64
: ELFCLASS32
;
218 ehdr
.e_ident
[5] = ELFDATA2LSB
;
219 ehdr
.e_ident
[6] = EV_CURRENT
;
220 ehdr
.e_type
= ET_REL
;
222 ehdr
.e_version
= EV_CURRENT
;
223 ehdr
.e_ehsize
= sizeof(ehdr
);
224 ehdr
.e_shentsize
= sizeof(shdr
[0]);
225 ehdr
.e_shoff
= offset
;
226 ehdr
.e_shnum
= NSECS
;
227 ehdr
.e_shstrndx
= SEC_SYMSTR
;
228 offset
+= sizeof(shdr
[0]) * NSECS
;
230 text_shdr
->sh_type
= SHT_PROGBITS
;
231 text_shdr
->sh_flags
= SHF_EXECINSTR
| SHF_ALLOC
;
232 text_shdr
->sh_offset
= offset
;
233 text_shdr
->sh_size
= cslen
;
234 text_shdr
->sh_entsize
= 1;
235 text_shdr
->sh_addralign
= OUT_ALIGNMENT
;
236 offset
+= text_shdr
->sh_size
;
238 rela_shdr
->sh_type
= USERELA
? SHT_RELA
: SHT_REL
;
239 rela_shdr
->sh_link
= SEC_SYMS
;
240 rela_shdr
->sh_info
= SEC_TEXT
;
241 rela_shdr
->sh_offset
= offset
;
242 rela_shdr
->sh_size
= nrels
* sizeof(rels
[0]);
243 rela_shdr
->sh_entsize
= sizeof(rels
[0]);
244 offset
+= rela_shdr
->sh_size
;
246 syms_shdr
->sh_type
= SHT_SYMTAB
;
247 syms_shdr
->sh_offset
= offset
;
248 syms_shdr
->sh_size
= nsyms
* sizeof(syms
[0]);
249 syms_shdr
->sh_entsize
= sizeof(syms
[0]);
250 syms_shdr
->sh_link
= SEC_SYMSTR
;
251 syms_shdr
->sh_info
= syms_sort();
252 offset
+= syms_shdr
->sh_size
;
254 dat_shdr
->sh_type
= SHT_PROGBITS
;
255 dat_shdr
->sh_flags
= SHF_ALLOC
| SHF_WRITE
;
256 dat_shdr
->sh_offset
= offset
;
257 dat_shdr
->sh_size
= dslen
;
258 dat_shdr
->sh_entsize
= 1;
259 dat_shdr
->sh_addralign
= OUT_ALIGNMENT
;
260 offset
+= dat_shdr
->sh_size
;
262 datrel_shdr
->sh_type
= USERELA
? SHT_RELA
: SHT_REL
;
263 datrel_shdr
->sh_offset
= offset
;
264 datrel_shdr
->sh_size
= ndsrels
* sizeof(dsrels
[0]);
265 datrel_shdr
->sh_entsize
= sizeof(dsrels
[0]);
266 datrel_shdr
->sh_link
= SEC_SYMS
;
267 datrel_shdr
->sh_info
= SEC_DAT
;
268 offset
+= datrel_shdr
->sh_size
;
270 bss_shdr
->sh_type
= SHT_NOBITS
;
271 bss_shdr
->sh_flags
= SHF_ALLOC
| SHF_WRITE
;
272 bss_shdr
->sh_offset
= offset
;
273 bss_shdr
->sh_size
= bss_len();
274 bss_shdr
->sh_entsize
= 1;
275 bss_shdr
->sh_addralign
= OUT_ALIGNMENT
;
277 symstr_shdr
->sh_type
= SHT_STRTAB
;
278 symstr_shdr
->sh_offset
= offset
;
279 symstr_shdr
->sh_size
= nsymstr
;
280 symstr_shdr
->sh_entsize
= 1;
281 offset
+= symstr_shdr
->sh_size
;
283 write(fd
, &ehdr
, sizeof(ehdr
));
284 write(fd
, shdr
, NSECS
* sizeof(shdr
[0]));
285 write(fd
, cs
, cslen
);
286 write(fd
, rels
, nrels
* sizeof(rels
[0]));
287 write(fd
, syms
, nsyms
* sizeof(syms
[0]));
288 write(fd
, ds
, dslen
);
289 write(fd
, dsrels
, ndsrels
* sizeof(dsrels
[0]));
290 write(fd
, symstr
, nsymstr
);
293 /* architecture dependent functions */
296 static void ehdr_init(Elf_Ehdr
*ehdr
)
298 ehdr
->e_machine
= EM_ARM
;
299 ehdr
->e_flags
= EF_ARM_EABI_VER4
;
302 static int rel_type(int flags
)
304 if (flags
& OUT_RL24
)
306 return flags
& OUT_RLREL
? R_ARM_REL32
: R_ARM_ABS32
;
312 static void ehdr_init(Elf_Ehdr
*ehdr
)
314 ehdr
->e_machine
= EM_X86_64
;
317 static int rel_type(int flags
)
319 if (flags
& OUT_RLREL
)
320 return R_X86_64_PC32
;
321 if (flags
& OUT_RL32
)
322 return flags
& OUT_RLSX
? R_X86_64_32S
: R_X86_64_32
;
328 static void ehdr_init(Elf_Ehdr
*ehdr
)
330 ehdr
->e_machine
= EM_386
;
333 static int rel_type(int flags
)
335 return flags
& OUT_RLREL
? R_386_PC32
: R_386_32
;