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
];
48 static long syms_n
, syms_sz
;
50 static long symstr_n
, symstr_sz
;
52 static Elf_Rel
*dsrel
;
53 static long dsrel_n
, dsrel_sz
;
54 static Elf_Rel
*csrel
;
55 static long csrel_n
, csrel_sz
;
57 void err(char *msg
, ...);
58 static int rel_type(int flags
);
59 static void ehdr_init(Elf_Ehdr
*ehdr
);
61 static long symstr_add(char *name
)
63 long len
= strlen(name
) + 1;
64 if (symstr_n
+ len
>= symstr_sz
) {
65 symstr_sz
= MAX(512, symstr_sz
* 2);
66 symstr
= mextend(symstr
, symstr_n
, symstr_sz
, sizeof(symstr
[0]));
68 strcpy(symstr
+ symstr_n
, name
);
70 return symstr_n
- len
;
73 static long sym_find(char *name
)
76 for (i
= 0; i
< syms_n
; i
++)
77 if (!strcmp(name
, symstr
+ syms
[i
].st_name
))
82 static Elf_Sym
*put_sym(char *name
)
84 long found
= sym_find(name
);
88 if (syms_n
>= syms_sz
) {
89 syms_sz
= MAX(128, syms_sz
* 2);
90 syms
= mextend(syms
, syms_n
, syms_sz
, sizeof(syms
[0]));
92 sym
= &syms
[syms_n
++];
93 sym
->st_name
= symstr_add(name
);
94 sym
->st_shndx
= SHN_UNDEF
;
95 sym
->st_info
= ELF_ST_INFO(STB_GLOBAL
, STT_FUNC
);
99 #define SYMLOCAL(i) (ELF_ST_BIND(syms[i].st_info) == STB_LOCAL)
101 static void mvrela(long *mv
, Elf_Rel
*rels
, long n
)
104 for (i
= 0; i
< n
; i
++) {
105 int sym
= ELF_R_SYM(rels
[i
].r_info
);
106 int type
= ELF_R_TYPE(rels
[i
].r_info
);
107 rels
[i
].r_info
= ELF_R_INFO(mv
[sym
], type
);
111 static int syms_sort(void)
116 mv
= malloc(syms_n
* sizeof(mv
[0]));
117 for (i
= 0; i
< syms_n
; i
++)
123 while (i
< j
&& SYMLOCAL(i
))
125 while (j
>= i
&& !SYMLOCAL(j
))
136 mvrela(mv
, csrel
, csrel_n
);
137 mvrela(mv
, dsrel
, dsrel_n
);
142 void out_init(long flags
)
147 /* return a symbol identifier */
148 void out_def(char *name
, long flags
, long off
, long len
)
150 Elf_Sym
*sym
= put_sym(name
);
151 int type
= (flags
& OUT_CS
) ? STT_FUNC
: STT_OBJECT
;
152 int bind
= (flags
& OUT_GLOB
) ? STB_GLOBAL
: STB_LOCAL
;
154 sym
->st_shndx
= SEC_TEXT
;
156 sym
->st_shndx
= SEC_DAT
;
158 sym
->st_shndx
= SEC_BSS
;
159 sym
->st_info
= ELF_ST_INFO(bind
, type
);
164 long out_sym(char *name
)
166 return put_sym(name
) - syms
;
169 static void out_csrel(long idx
, long off
, int flags
)
172 if (csrel_n
>= csrel_sz
) {
173 csrel_sz
= MAX(128, csrel_sz
* 2);
174 csrel
= mextend(csrel
, csrel_n
, csrel_sz
, sizeof(csrel
[0]));
176 r
= &csrel
[csrel_n
++];
178 r
->r_info
= ELF_R_INFO(idx
, rel_type(flags
));
181 static void out_dsrel(long idx
, long off
, int flags
)
184 if (dsrel_n
>= dsrel_sz
) {
185 dsrel_sz
= MAX(128, dsrel_sz
* 2);
186 dsrel
= mextend(dsrel
, dsrel_n
, dsrel_sz
, sizeof(dsrel
[0]));
188 r
= &dsrel
[dsrel_n
++];
190 r
->r_info
= ELF_R_INFO(idx
, rel_type(flags
));
193 void out_rel(long idx
, long flags
, long off
)
196 out_dsrel(idx
, off
, flags
);
198 out_csrel(idx
, off
, flags
);
201 static long bss_len(void)
205 for (i
= 0; i
< syms_n
; i
++) {
206 long end
= syms
[i
].st_value
+ syms
[i
].st_size
;
207 if (syms
[i
].st_shndx
== SEC_BSS
)
214 void out_write(int fd
, char *cs
, long cslen
, char *ds
, long dslen
)
216 Elf_Shdr
*text_shdr
= &shdr
[SEC_TEXT
];
217 Elf_Shdr
*rela_shdr
= &shdr
[SEC_REL
];
218 Elf_Shdr
*symstr_shdr
= &shdr
[SEC_SYMSTR
];
219 Elf_Shdr
*syms_shdr
= &shdr
[SEC_SYMS
];
220 Elf_Shdr
*dat_shdr
= &shdr
[SEC_DAT
];
221 Elf_Shdr
*datrel_shdr
= &shdr
[SEC_DATREL
];
222 Elf_Shdr
*bss_shdr
= &shdr
[SEC_BSS
];
223 unsigned long offset
= sizeof(ehdr
);
225 /* workaround for the idiotic gnuld; use neatld instead! */
226 text_shdr
->sh_name
= symstr_add(".cs");
227 rela_shdr
->sh_name
= symstr_add(USERELA
? ".rela.cs" : ".rels.cs");
228 dat_shdr
->sh_name
= symstr_add(".ds");
229 datrel_shdr
->sh_name
= symstr_add(USERELA
? ".rela.ds" : ".rels.ds");
231 ehdr
.e_ident
[0] = 0x7f;
232 ehdr
.e_ident
[1] = 'E';
233 ehdr
.e_ident
[2] = 'L';
234 ehdr
.e_ident
[3] = 'F';
235 ehdr
.e_ident
[4] = LONGSZ
== 8 ? ELFCLASS64
: ELFCLASS32
;
236 ehdr
.e_ident
[5] = ELFDATA2LSB
;
237 ehdr
.e_ident
[6] = EV_CURRENT
;
238 ehdr
.e_type
= ET_REL
;
240 ehdr
.e_version
= EV_CURRENT
;
241 ehdr
.e_ehsize
= sizeof(ehdr
);
242 ehdr
.e_shentsize
= sizeof(shdr
[0]);
243 ehdr
.e_shoff
= offset
;
244 ehdr
.e_shnum
= NSECS
;
245 ehdr
.e_shstrndx
= SEC_SYMSTR
;
246 offset
+= sizeof(shdr
[0]) * NSECS
;
248 text_shdr
->sh_type
= SHT_PROGBITS
;
249 text_shdr
->sh_flags
= SHF_EXECINSTR
| SHF_ALLOC
;
250 text_shdr
->sh_offset
= offset
;
251 text_shdr
->sh_size
= cslen
;
252 text_shdr
->sh_entsize
= 1;
253 text_shdr
->sh_addralign
= OUT_ALIGNMENT
;
254 offset
+= text_shdr
->sh_size
;
256 rela_shdr
->sh_type
= USERELA
? SHT_RELA
: SHT_REL
;
257 rela_shdr
->sh_link
= SEC_SYMS
;
258 rela_shdr
->sh_info
= SEC_TEXT
;
259 rela_shdr
->sh_offset
= offset
;
260 rela_shdr
->sh_size
= csrel_n
* sizeof(csrel
[0]);
261 rela_shdr
->sh_entsize
= sizeof(csrel
[0]);
262 offset
+= rela_shdr
->sh_size
;
264 syms_shdr
->sh_type
= SHT_SYMTAB
;
265 syms_shdr
->sh_offset
= offset
;
266 syms_shdr
->sh_size
= syms_n
* sizeof(syms
[0]);
267 syms_shdr
->sh_entsize
= sizeof(syms
[0]);
268 syms_shdr
->sh_link
= SEC_SYMSTR
;
269 syms_shdr
->sh_info
= syms_sort();
270 offset
+= syms_shdr
->sh_size
;
272 dat_shdr
->sh_type
= SHT_PROGBITS
;
273 dat_shdr
->sh_flags
= SHF_ALLOC
| SHF_WRITE
;
274 dat_shdr
->sh_offset
= offset
;
275 dat_shdr
->sh_size
= dslen
;
276 dat_shdr
->sh_entsize
= 1;
277 dat_shdr
->sh_addralign
= OUT_ALIGNMENT
;
278 offset
+= dat_shdr
->sh_size
;
280 datrel_shdr
->sh_type
= USERELA
? SHT_RELA
: SHT_REL
;
281 datrel_shdr
->sh_offset
= offset
;
282 datrel_shdr
->sh_size
= dsrel_n
* sizeof(dsrel
[0]);
283 datrel_shdr
->sh_entsize
= sizeof(dsrel
[0]);
284 datrel_shdr
->sh_link
= SEC_SYMS
;
285 datrel_shdr
->sh_info
= SEC_DAT
;
286 offset
+= datrel_shdr
->sh_size
;
288 bss_shdr
->sh_type
= SHT_NOBITS
;
289 bss_shdr
->sh_flags
= SHF_ALLOC
| SHF_WRITE
;
290 bss_shdr
->sh_offset
= offset
;
291 bss_shdr
->sh_size
= bss_len();
292 bss_shdr
->sh_entsize
= 1;
293 bss_shdr
->sh_addralign
= OUT_ALIGNMENT
;
295 symstr_shdr
->sh_type
= SHT_STRTAB
;
296 symstr_shdr
->sh_offset
= offset
;
297 symstr_shdr
->sh_size
= symstr_n
;
298 symstr_shdr
->sh_entsize
= 1;
299 offset
+= symstr_shdr
->sh_size
;
301 write(fd
, &ehdr
, sizeof(ehdr
));
302 write(fd
, shdr
, NSECS
* sizeof(shdr
[0]));
303 write(fd
, cs
, cslen
);
304 write(fd
, csrel
, csrel_n
* sizeof(csrel
[0]));
305 write(fd
, syms
, syms_n
* sizeof(syms
[0]));
306 write(fd
, ds
, dslen
);
307 write(fd
, dsrel
, dsrel_n
* sizeof(dsrel
[0]));
308 write(fd
, symstr
, symstr_n
);
316 /* architecture dependent functions */
319 static void ehdr_init(Elf_Ehdr
*ehdr
)
321 ehdr
->e_machine
= EM_ARM
;
322 ehdr
->e_flags
= EF_ARM_EABI_VER4
;
325 static int rel_type(int flags
)
327 if (flags
& OUT_RL24
)
329 return flags
& OUT_RLREL
? R_ARM_REL32
: R_ARM_ABS32
;
335 static void ehdr_init(Elf_Ehdr
*ehdr
)
337 ehdr
->e_machine
= EM_X86_64
;
340 static int rel_type(int flags
)
342 if (flags
& OUT_RLREL
)
343 return R_X86_64_PC32
;
344 if (flags
& OUT_RL32
)
345 return flags
& OUT_RLSX
? R_X86_64_32S
: R_X86_64_32
;
351 static void ehdr_init(Elf_Ehdr
*ehdr
)
353 ehdr
->e_machine
= EM_386
;
356 static int rel_type(int flags
)
358 return flags
& OUT_RLREL
? R_386_PC32
: R_386_32
;