Added missing file.
[tinycc/k1w1.git] / tccelf.c
blob50c972a1b49f7ff3f886d6221e0f02ae733f8154
1 /*
2 * ELF file handling for TCC
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "tcc.h"
22 #ifdef TCC_TARGET_X86_64
23 #define ElfW_Rel ElfW(Rela)
24 #define SHT_RELX SHT_RELA
25 #define REL_SECTION_FMT ".rela%s"
26 /* x86-64 requires PLT for DLLs */
27 #define TCC_OUTPUT_DLL_WITH_PLT
28 #else
29 #define ElfW_Rel ElfW(Rel)
30 #define SHT_RELX SHT_REL
31 #define REL_SECTION_FMT ".rel%s"
32 #endif
34 void put_extern_sym(Sym *sym, Section *section,
35 unsigned long value, unsigned long size)
37 put_extern_sym2(sym, section, value, size, 1);
41 /* XXX: DLL with PLT would only work with x86-64 for now */
42 //#define TCC_OUTPUT_DLL_WITH_PLT
44 int put_elf_str(Section *s, const char *sym)
46 int offset, len;
47 char *ptr;
49 len = strlen(sym) + 1;
50 offset = s->data_offset;
51 ptr = section_ptr_add(s, len);
52 memcpy(ptr, sym, len);
53 return offset;
57 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
59 Section *sec;
61 sec = tcc_mallocz(sizeof(Section) + strlen(name));
62 strcpy(sec->name, name);
63 sec->sh_type = sh_type;
64 sec->sh_flags = sh_flags;
65 switch(sh_type) {
66 case SHT_HASH:
67 case SHT_REL:
68 case SHT_RELA:
69 case SHT_DYNSYM:
70 case SHT_SYMTAB:
71 case SHT_DYNAMIC:
72 sec->sh_addralign = 4;
73 break;
74 case SHT_STRTAB:
75 sec->sh_addralign = 1;
76 break;
77 default:
78 sec->sh_addralign = 32; /* default conservative alignment */
79 break;
82 if (sh_flags & SHF_PRIVATE) {
83 dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec);
84 } else {
85 sec->sh_num = s1->nb_sections;
86 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
89 return sec;
92 void free_section(Section *s)
94 tcc_free(s->data);
97 /* realloc section and set its content to zero */
98 void section_realloc(Section *sec, unsigned long new_size)
100 unsigned long size;
101 unsigned char *data;
103 size = sec->data_allocated;
104 if (size == 0)
105 size = 1;
106 while (size < new_size)
107 size = size * 2;
108 data = tcc_realloc(sec->data, size);
109 if (!data)
110 error("memory full");
111 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
112 sec->data = data;
113 sec->data_allocated = size;
116 /* reserve at least 'size' bytes in section 'sec' from
117 sec->data_offset. */
118 void *section_ptr_add(Section *sec, unsigned long size)
120 unsigned long offset, offset1;
122 offset = sec->data_offset;
123 offset1 = offset + size;
124 if (offset1 > sec->data_allocated)
125 section_realloc(sec, offset1);
126 sec->data_offset = offset1;
127 return sec->data + offset;
130 /* return a reference to a section, and create it if it does not
131 exists */
132 Section *find_section(TCCState *s1, const char *name)
134 Section *sec;
135 int i;
136 for(i = 1; i < s1->nb_sections; i++) {
137 sec = s1->sections[i];
138 if (!strcmp(name, sec->name))
139 return sec;
141 /* sections are created as PROGBITS */
142 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
145 /* update sym->c so that it points to an external symbol in section
146 'section' with value 'value' */
147 void put_extern_sym2(Sym *sym, Section *section,
148 unsigned long value, unsigned long size,
149 int can_add_underscore)
151 int sym_type, sym_bind, sh_num, info, other, attr;
152 ElfW(Sym) *esym;
153 const char *name;
154 char buf1[256];
156 if (section == NULL)
157 sh_num = SHN_UNDEF;
158 else if (section == SECTION_ABS)
159 sh_num = SHN_ABS;
160 else
161 sh_num = section->sh_num;
163 other = attr = 0;
165 if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
166 sym_type = STT_FUNC;
167 #ifdef TCC_TARGET_PE
168 if (sym->type.ref)
169 attr = sym->type.ref->r;
170 if (FUNC_EXPORT(attr))
171 other |= 1;
172 if (FUNC_CALL(attr) == FUNC_STDCALL)
173 other |= 2;
174 #endif
175 } else {
176 sym_type = STT_OBJECT;
179 if (sym->type.t & VT_STATIC)
180 sym_bind = STB_LOCAL;
181 else
182 sym_bind = STB_GLOBAL;
184 if (!sym->c) {
185 name = get_tok_str(sym->v, NULL);
186 #ifdef CONFIG_TCC_BCHECK
187 if (tcc_state->do_bounds_check) {
188 char buf[32];
190 /* XXX: avoid doing that for statics ? */
191 /* if bound checking is activated, we change some function
192 names by adding the "__bound" prefix */
193 switch(sym->v) {
194 #if 0
195 /* XXX: we rely only on malloc hooks */
196 case TOK_malloc:
197 case TOK_free:
198 case TOK_realloc:
199 case TOK_memalign:
200 case TOK_calloc:
201 #endif
202 case TOK_memcpy:
203 case TOK_memmove:
204 case TOK_memset:
205 case TOK_strlen:
206 case TOK_strcpy:
207 case TOK_alloca:
208 strcpy(buf, "__bound_");
209 strcat(buf, name);
210 name = buf;
211 break;
214 #endif
216 #ifdef TCC_TARGET_PE
217 if ((other & 2) && can_add_underscore) {
218 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
219 name = buf1;
220 } else
221 #endif
222 if (tcc_state->leading_underscore && can_add_underscore) {
223 buf1[0] = '_';
224 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
225 name = buf1;
227 info = ELFW(ST_INFO)(sym_bind, sym_type);
228 sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
229 } else {
230 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
231 esym->st_value = value;
232 esym->st_size = size;
233 esym->st_shndx = sh_num;
234 esym->st_other |= other;
238 /* add a new relocation entry to symbol 'sym' in section 's' */
239 void greloc(Section *s, Sym *sym, unsigned long offset, int type)
241 if (!sym->c)
242 put_extern_sym(sym, NULL, 0, 0);
243 /* now we can add ELF relocation info */
244 put_elf_reloc(symtab_section, s, offset, type, sym->c);
248 /* elf symbol hashing function */
249 static unsigned long elf_hash(const unsigned char *name)
251 unsigned long h = 0, g;
253 while (*name) {
254 h = (h << 4) + *name++;
255 g = h & 0xf0000000;
256 if (g)
257 h ^= g >> 24;
258 h &= ~g;
260 return h;
263 /* rebuild hash table of section s */
264 /* NOTE: we do factorize the hash table code to go faster */
265 static void rebuild_hash(Section *s, unsigned int nb_buckets)
267 ElfW(Sym) *sym;
268 int *ptr, *hash, nb_syms, sym_index, h;
269 char *strtab;
271 strtab = s->link->data;
272 nb_syms = s->data_offset / sizeof(ElfW(Sym));
274 s->hash->data_offset = 0;
275 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
276 ptr[0] = nb_buckets;
277 ptr[1] = nb_syms;
278 ptr += 2;
279 hash = ptr;
280 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
281 ptr += nb_buckets + 1;
283 sym = (ElfW(Sym) *)s->data + 1;
284 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
285 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
286 h = elf_hash(strtab + sym->st_name) % nb_buckets;
287 *ptr = hash[h];
288 hash[h] = sym_index;
289 } else {
290 *ptr = 0;
292 ptr++;
293 sym++;
297 /* return the symbol number */
298 int put_elf_sym(Section *s,
299 unsigned long value, unsigned long size,
300 int info, int other, int shndx, const char *name)
302 int name_offset, sym_index;
303 int nbuckets, h;
304 ElfW(Sym) *sym;
305 Section *hs;
307 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
308 if (name)
309 name_offset = put_elf_str(s->link, name);
310 else
311 name_offset = 0;
312 /* XXX: endianness */
313 sym->st_name = name_offset;
314 sym->st_value = value;
315 sym->st_size = size;
316 sym->st_info = info;
317 sym->st_other = other;
318 sym->st_shndx = shndx;
319 sym_index = sym - (ElfW(Sym) *)s->data;
320 hs = s->hash;
321 if (hs) {
322 int *ptr, *base;
323 ptr = section_ptr_add(hs, sizeof(int));
324 base = (int *)hs->data;
325 /* only add global or weak symbols */
326 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
327 /* add another hashing entry */
328 nbuckets = base[0];
329 h = elf_hash(name) % nbuckets;
330 *ptr = base[2 + h];
331 base[2 + h] = sym_index;
332 base[1]++;
333 /* we resize the hash table */
334 hs->nb_hashed_syms++;
335 if (hs->nb_hashed_syms > 2 * nbuckets) {
336 rebuild_hash(s, 2 * nbuckets);
338 } else {
339 *ptr = 0;
340 base[1]++;
343 return sym_index;
346 /* find global ELF symbol 'name' and return its index. Return 0 if not
347 found. */
348 static int find_elf_sym(Section *s, const char *name)
350 ElfW(Sym) *sym;
351 Section *hs;
352 int nbuckets, sym_index, h;
353 const char *name1;
355 hs = s->hash;
356 if (!hs)
357 return 0;
358 nbuckets = ((int *)hs->data)[0];
359 h = elf_hash(name) % nbuckets;
360 sym_index = ((int *)hs->data)[2 + h];
361 while (sym_index != 0) {
362 sym = &((ElfW(Sym) *)s->data)[sym_index];
363 name1 = s->link->data + sym->st_name;
364 if (!strcmp(name, name1))
365 return sym_index;
366 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
368 return 0;
371 /* return elf symbol value, signal error if 'err' is nonzero */
372 static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
374 int sym_index;
375 ElfW(Sym) *sym;
377 sym_index = find_elf_sym(symtab_section, name);
378 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
379 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
380 if (err)
381 error("%s not defined", name);
382 return NULL;
384 return (void*)(uplong)sym->st_value;
387 /* return elf symbol value */
388 void *tcc_get_symbol(TCCState *s, const char *name)
390 return get_elf_sym_addr(s, name, 0);
393 /* return elf symbol value or error */
394 void *tcc_get_symbol_err(TCCState *s, const char *name)
396 return get_elf_sym_addr(s, name, 1);
399 /* add an elf symbol : check if it is already defined and patch
400 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
401 int add_elf_sym(Section *s, uplong value, unsigned long size,
402 int info, int other, int sh_num, const char *name)
404 ElfW(Sym) *esym;
405 int sym_bind, sym_index, sym_type, esym_bind;
406 unsigned char sym_vis, esym_vis, new_vis;
408 sym_bind = ELFW(ST_BIND)(info);
409 sym_type = ELFW(ST_TYPE)(info);
410 sym_vis = ELFW(ST_VISIBILITY)(other);
412 if (sym_bind != STB_LOCAL) {
413 /* we search global or weak symbols */
414 sym_index = find_elf_sym(s, name);
415 if (!sym_index)
416 goto do_def;
417 esym = &((ElfW(Sym) *)s->data)[sym_index];
418 if (esym->st_shndx != SHN_UNDEF) {
419 esym_bind = ELFW(ST_BIND)(esym->st_info);
420 /* propagate the most constraining visibility */
421 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
422 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
423 if (esym_vis == STV_DEFAULT) {
424 new_vis = sym_vis;
425 } else if (sym_vis == STV_DEFAULT) {
426 new_vis = esym_vis;
427 } else {
428 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
430 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
431 | new_vis;
432 other = esym->st_other; /* in case we have to patch esym */
433 if (sh_num == SHN_UNDEF) {
434 /* ignore adding of undefined symbol if the
435 corresponding symbol is already defined */
436 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
437 /* global overrides weak, so patch */
438 goto do_patch;
439 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
440 /* weak is ignored if already global */
441 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
442 /* ignore hidden symbols after */
443 } else if (esym->st_shndx == SHN_COMMON
444 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
445 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
446 No idea if this is the correct solution ... */
447 goto do_patch;
448 } else if (s == tcc_state->dynsymtab_section) {
449 /* we accept that two DLL define the same symbol */
450 } else {
451 #if 1
452 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
453 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
454 #endif
455 error_noabort("'%s' defined twice", name);
457 } else {
458 do_patch:
459 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
460 esym->st_shndx = sh_num;
461 esym->st_value = value;
462 esym->st_size = size;
463 esym->st_other = other;
465 } else {
466 do_def:
467 sym_index = put_elf_sym(s, value, size,
468 ELFW(ST_INFO)(sym_bind, sym_type), other,
469 sh_num, name);
471 return sym_index;
474 /* put relocation */
475 void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
476 int type, int symbol)
478 char buf[256];
479 Section *sr;
480 ElfW_Rel *rel;
482 sr = s->reloc;
483 if (!sr) {
484 /* if no relocation section, create it */
485 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
486 /* if the symtab is allocated, then we consider the relocation
487 are also */
488 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
489 sr->sh_entsize = sizeof(ElfW_Rel);
490 sr->link = symtab;
491 sr->sh_info = s->sh_num;
492 s->reloc = sr;
494 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
495 rel->r_offset = offset;
496 rel->r_info = ELFW(R_INFO)(symbol, type);
497 #ifdef TCC_TARGET_X86_64
498 rel->r_addend = 0;
499 #endif
502 /* put stab debug information */
504 void put_stabs(const char *str, int type, int other, int desc,
505 unsigned long value)
507 Stab_Sym *sym;
509 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
510 if (str) {
511 sym->n_strx = put_elf_str(stabstr_section, str);
512 } else {
513 sym->n_strx = 0;
515 sym->n_type = type;
516 sym->n_other = other;
517 sym->n_desc = desc;
518 sym->n_value = value;
521 void put_stabs_r(const char *str, int type, int other, int desc,
522 unsigned long value, Section *sec, int sym_index)
524 put_stabs(str, type, other, desc, value);
525 put_elf_reloc(symtab_section, stab_section,
526 stab_section->data_offset - sizeof(unsigned int),
527 R_DATA_32, sym_index);
530 void put_stabn(int type, int other, int desc, int value)
532 put_stabs(NULL, type, other, desc, value);
535 void put_stabd(int type, int other, int desc)
537 put_stabs(NULL, type, other, desc, 0);
540 /* In an ELF file symbol table, the local symbols must appear below
541 the global and weak ones. Since TCC cannot sort it while generating
542 the code, we must do it after. All the relocation tables are also
543 modified to take into account the symbol table sorting */
544 static void sort_syms(TCCState *s1, Section *s)
546 int *old_to_new_syms;
547 ElfW(Sym) *new_syms;
548 int nb_syms, i;
549 ElfW(Sym) *p, *q;
550 ElfW_Rel *rel, *rel_end;
551 Section *sr;
552 int type, sym_index;
554 nb_syms = s->data_offset / sizeof(ElfW(Sym));
555 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
556 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
558 /* first pass for local symbols */
559 p = (ElfW(Sym) *)s->data;
560 q = new_syms;
561 for(i = 0; i < nb_syms; i++) {
562 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
563 old_to_new_syms[i] = q - new_syms;
564 *q++ = *p;
566 p++;
568 /* save the number of local symbols in section header */
569 s->sh_info = q - new_syms;
571 /* then second pass for non local symbols */
572 p = (ElfW(Sym) *)s->data;
573 for(i = 0; i < nb_syms; i++) {
574 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
575 old_to_new_syms[i] = q - new_syms;
576 *q++ = *p;
578 p++;
581 /* we copy the new symbols to the old */
582 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
583 tcc_free(new_syms);
585 /* now we modify all the relocations */
586 for(i = 1; i < s1->nb_sections; i++) {
587 sr = s1->sections[i];
588 if (sr->sh_type == SHT_RELX && sr->link == s) {
589 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
590 for(rel = (ElfW_Rel *)sr->data;
591 rel < rel_end;
592 rel++) {
593 sym_index = ELFW(R_SYM)(rel->r_info);
594 type = ELFW(R_TYPE)(rel->r_info);
595 sym_index = old_to_new_syms[sym_index];
596 rel->r_info = ELFW(R_INFO)(sym_index, type);
601 tcc_free(old_to_new_syms);
604 /* relocate common symbols in the .bss section */
605 void relocate_common_syms(void)
607 ElfW(Sym) *sym, *sym_end;
608 unsigned long offset, align;
610 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
611 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
612 sym < sym_end;
613 sym++) {
614 if (sym->st_shndx == SHN_COMMON) {
615 /* align symbol */
616 align = sym->st_value;
617 offset = bss_section->data_offset;
618 offset = (offset + align - 1) & -align;
619 sym->st_value = offset;
620 sym->st_shndx = bss_section->sh_num;
621 offset += sym->st_size;
622 bss_section->data_offset = offset;
627 /* relocate symbol table, resolve undefined symbols if do_resolve is
628 true and output error if undefined symbol. */
629 void relocate_syms(TCCState *s1, int do_resolve)
631 ElfW(Sym) *sym, *esym, *sym_end;
632 int sym_bind, sh_num, sym_index;
633 const char *name;
635 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
636 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
637 sym < sym_end;
638 sym++) {
639 sh_num = sym->st_shndx;
640 if (sh_num == SHN_UNDEF) {
641 name = strtab_section->data + sym->st_name;
642 if (do_resolve) {
643 #ifndef _WIN32
644 void *addr;
645 name = symtab_section->link->data + sym->st_name;
646 addr = resolve_sym(s1, name);
647 if (addr) {
648 sym->st_value = (uplong)addr;
649 goto found;
651 #endif
652 } else if (s1->dynsym) {
653 /* if dynamic symbol exist, then use it */
654 sym_index = find_elf_sym(s1->dynsym, name);
655 if (sym_index) {
656 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
657 sym->st_value = esym->st_value;
658 goto found;
661 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
662 it */
663 if (!strcmp(name, "_fp_hw"))
664 goto found;
665 /* only weak symbols are accepted to be undefined. Their
666 value is zero */
667 sym_bind = ELFW(ST_BIND)(sym->st_info);
668 if (sym_bind == STB_WEAK) {
669 sym->st_value = 0;
670 } else {
671 error_noabort("undefined symbol '%s'", name);
673 } else if (sh_num < SHN_LORESERVE) {
674 /* add section base */
675 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
677 found: ;
681 #ifndef TCC_TARGET_PE
682 #ifdef TCC_TARGET_X86_64
683 #define JMP_TABLE_ENTRY_SIZE 14
684 static unsigned long add_jmp_table(TCCState *s1, unsigned long val)
686 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
687 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
688 /* jmp *0x0(%rip) */
689 p[0] = 0xff;
690 p[1] = 0x25;
691 *(int *)(p + 2) = 0;
692 *(unsigned long *)(p + 6) = val;
693 return (unsigned long)p;
696 static unsigned long add_got_table(TCCState *s1, unsigned long val)
698 unsigned long *p =(unsigned long *)(s1->runtime_plt_and_got +
699 s1->runtime_plt_and_got_offset);
700 s1->runtime_plt_and_got_offset += sizeof(void *);
701 *p = val;
702 return (unsigned long)p;
704 #endif
705 #endif
707 /* relocate a given section (CPU dependent) */
708 void relocate_section(TCCState *s1, Section *s)
710 Section *sr;
711 ElfW_Rel *rel, *rel_end, *qrel;
712 ElfW(Sym) *sym;
713 int type, sym_index;
714 unsigned char *ptr;
715 unsigned long val, addr;
716 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
717 int esym_index;
718 #endif
720 sr = s->reloc;
721 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
722 qrel = (ElfW_Rel *)sr->data;
723 for(rel = qrel;
724 rel < rel_end;
725 rel++) {
726 ptr = s->data + rel->r_offset;
728 sym_index = ELFW(R_SYM)(rel->r_info);
729 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
730 val = sym->st_value;
731 #ifdef TCC_TARGET_X86_64
732 /* XXX: not tested */
733 val += rel->r_addend;
734 #endif
735 type = ELFW(R_TYPE)(rel->r_info);
736 addr = s->sh_addr + rel->r_offset;
738 /* CPU specific */
739 switch(type) {
740 #if defined(TCC_TARGET_I386)
741 case R_386_32:
742 if (s1->output_type == TCC_OUTPUT_DLL) {
743 esym_index = s1->symtab_to_dynsym[sym_index];
744 qrel->r_offset = rel->r_offset;
745 if (esym_index) {
746 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
747 qrel++;
748 break;
749 } else {
750 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
751 qrel++;
754 *(int *)ptr += val;
755 break;
756 case R_386_PC32:
757 if (s1->output_type == TCC_OUTPUT_DLL) {
758 /* DLL relocation */
759 esym_index = s1->symtab_to_dynsym[sym_index];
760 if (esym_index) {
761 qrel->r_offset = rel->r_offset;
762 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
763 qrel++;
764 break;
767 *(int *)ptr += val - addr;
768 break;
769 case R_386_PLT32:
770 *(int *)ptr += val - addr;
771 break;
772 case R_386_GLOB_DAT:
773 case R_386_JMP_SLOT:
774 *(int *)ptr = val;
775 break;
776 case R_386_GOTPC:
777 *(int *)ptr += s1->got->sh_addr - addr;
778 break;
779 case R_386_GOTOFF:
780 *(int *)ptr += val - s1->got->sh_addr;
781 break;
782 case R_386_GOT32:
783 /* we load the got offset */
784 *(int *)ptr += s1->got_offsets[sym_index];
785 break;
786 case R_386_16:
787 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
788 output_file:
789 error("can only produce 16-bit binary files");
791 *(short *)ptr += val;
792 break;
793 case R_386_PC16:
794 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
795 goto output_file;
796 *(short *)ptr += val - addr;
797 break;
798 #elif defined(TCC_TARGET_ARM)
799 case R_ARM_PC24:
800 case R_ARM_CALL:
801 case R_ARM_JUMP24:
802 case R_ARM_PLT32:
804 int x;
805 x = (*(int *)ptr)&0xffffff;
806 (*(int *)ptr) &= 0xff000000;
807 if (x & 0x800000)
808 x -= 0x1000000;
809 x *= 4;
810 x += val - addr;
811 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
812 error("can't relocate value at %x",addr);
813 x >>= 2;
814 x &= 0xffffff;
815 (*(int *)ptr) |= x;
817 break;
818 case R_ARM_PREL31:
820 int x;
821 x = (*(int *)ptr) & 0x7fffffff;
822 (*(int *)ptr) &= 0x80000000;
823 x = (x * 2) / 2;
824 x += val - addr;
825 if((x^(x>>1))&0x40000000)
826 error("can't relocate value at %x",addr);
827 (*(int *)ptr) |= x & 0x7fffffff;
829 case R_ARM_ABS32:
830 *(int *)ptr += val;
831 break;
832 case R_ARM_BASE_PREL:
833 *(int *)ptr += s1->got->sh_addr - addr;
834 break;
835 case R_ARM_GOTOFF32:
836 *(int *)ptr += val - s1->got->sh_addr;
837 break;
838 case R_ARM_GOT_BREL:
839 /* we load the got offset */
840 *(int *)ptr += s1->got_offsets[sym_index];
841 break;
842 case R_ARM_COPY:
843 break;
844 default:
845 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
846 type,addr,(unsigned int)(long)ptr,val);
847 break;
848 #elif defined(TCC_TARGET_C67)
849 case R_C60_32:
850 *(int *)ptr += val;
851 break;
852 case R_C60LO16:
854 uint32_t orig;
856 /* put the low 16 bits of the absolute address */
857 // add to what is already there
859 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
860 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
862 //patch both at once - assumes always in pairs Low - High
864 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
865 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
867 break;
868 case R_C60HI16:
869 break;
870 default:
871 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
872 type,addr,(unsigned int)(long)ptr, val);
873 break;
874 #elif defined(TCC_TARGET_X86_64)
875 case R_X86_64_64:
876 if (s1->output_type == TCC_OUTPUT_DLL) {
877 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
878 qrel->r_addend = *(long long *)ptr + val;
879 qrel++;
881 *(long long *)ptr += val;
882 break;
883 case R_X86_64_32:
884 case R_X86_64_32S:
885 if (s1->output_type == TCC_OUTPUT_DLL) {
886 /* XXX: this logic may depend on TCC's codegen
887 now TCC uses R_X86_64_32 even for a 64bit pointer */
888 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
889 qrel->r_addend = *(int *)ptr + val;
890 qrel++;
892 *(int *)ptr += val;
893 break;
894 case R_X86_64_PC32: {
895 long long diff;
896 if (s1->output_type == TCC_OUTPUT_DLL) {
897 /* DLL relocation */
898 esym_index = s1->symtab_to_dynsym[sym_index];
899 if (esym_index) {
900 qrel->r_offset = rel->r_offset;
901 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
902 qrel->r_addend = *(int *)ptr;
903 qrel++;
904 break;
907 diff = (long long)val - addr;
908 if (diff <= -2147483647 || diff > 2147483647) {
909 #ifndef TCC_TARGET_PE
910 /* XXX: naive support for over 32bit jump */
911 if (s1->output_type == TCC_OUTPUT_MEMORY) {
912 val = add_jmp_table(s1, val);
913 diff = val - addr;
915 #endif
916 if (diff <= -2147483647 || diff > 2147483647) {
917 error("internal error: relocation failed");
920 *(int *)ptr += diff;
922 break;
923 case R_X86_64_PLT32:
924 *(int *)ptr += val - addr;
925 break;
926 case R_X86_64_GLOB_DAT:
927 case R_X86_64_JUMP_SLOT:
928 *(int *)ptr = val;
929 break;
930 case R_X86_64_GOTPCREL:
931 #ifndef TCC_TARGET_PE
932 if (s1->output_type == TCC_OUTPUT_MEMORY) {
933 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
934 *(int *)ptr += val - addr;
935 break;
937 #endif
938 *(int *)ptr += (s1->got->sh_addr - addr +
939 s1->got_offsets[sym_index] - 4);
940 break;
941 case R_X86_64_GOTTPOFF:
942 *(int *)ptr += val - s1->got->sh_addr;
943 break;
944 case R_X86_64_GOT32:
945 /* we load the got offset */
946 *(int *)ptr += s1->got_offsets[sym_index];
947 break;
948 #else
949 #error unsupported processor
950 #endif
953 /* if the relocation is allocated, we change its symbol table */
954 if (sr->sh_flags & SHF_ALLOC)
955 sr->link = s1->dynsym;
958 /* relocate relocation table in 'sr' */
959 static void relocate_rel(TCCState *s1, Section *sr)
961 Section *s;
962 ElfW_Rel *rel, *rel_end;
964 s = s1->sections[sr->sh_info];
965 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
966 for(rel = (ElfW_Rel *)sr->data;
967 rel < rel_end;
968 rel++) {
969 rel->r_offset += s->sh_addr;
973 /* count the number of dynamic relocations so that we can reserve
974 their space */
975 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
977 ElfW_Rel *rel, *rel_end;
978 int sym_index, esym_index, type, count;
980 count = 0;
981 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
982 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
983 sym_index = ELFW(R_SYM)(rel->r_info);
984 type = ELFW(R_TYPE)(rel->r_info);
985 switch(type) {
986 #if defined(TCC_TARGET_I386)
987 case R_386_32:
988 #elif defined(TCC_TARGET_X86_64)
989 case R_X86_64_32:
990 case R_X86_64_32S:
991 case R_X86_64_64:
992 #endif
993 count++;
994 break;
995 #if defined(TCC_TARGET_I386)
996 case R_386_PC32:
997 #elif defined(TCC_TARGET_X86_64)
998 case R_X86_64_PC32:
999 #endif
1000 esym_index = s1->symtab_to_dynsym[sym_index];
1001 if (esym_index)
1002 count++;
1003 break;
1004 default:
1005 break;
1008 if (count) {
1009 /* allocate the section */
1010 sr->sh_flags |= SHF_ALLOC;
1011 sr->sh_size = count * sizeof(ElfW_Rel);
1013 return count;
1016 static void put_got_offset(TCCState *s1, int index, unsigned long val)
1018 int n;
1019 unsigned long *tab;
1021 if (index >= s1->nb_got_offsets) {
1022 /* find immediately bigger power of 2 and reallocate array */
1023 n = 1;
1024 while (index >= n)
1025 n *= 2;
1026 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
1027 if (!tab)
1028 error("memory full");
1029 s1->got_offsets = tab;
1030 memset(s1->got_offsets + s1->nb_got_offsets, 0,
1031 (n - s1->nb_got_offsets) * sizeof(unsigned long));
1032 s1->nb_got_offsets = n;
1034 s1->got_offsets[index] = val;
1037 /* XXX: suppress that */
1038 static void put32(unsigned char *p, uint32_t val)
1040 p[0] = val;
1041 p[1] = val >> 8;
1042 p[2] = val >> 16;
1043 p[3] = val >> 24;
1046 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
1047 defined(TCC_TARGET_X86_64)
1048 static uint32_t get32(unsigned char *p)
1050 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
1052 #endif
1054 static void build_got(TCCState *s1)
1056 unsigned char *ptr;
1058 /* if no got, then create it */
1059 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
1060 s1->got->sh_entsize = 4;
1061 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
1062 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
1063 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
1064 #if PTR_SIZE == 4
1065 /* keep space for _DYNAMIC pointer, if present */
1066 put32(ptr, 0);
1067 /* two dummy got entries */
1068 put32(ptr + 4, 0);
1069 put32(ptr + 8, 0);
1070 #else
1071 /* keep space for _DYNAMIC pointer, if present */
1072 put32(ptr, 0);
1073 put32(ptr + 4, 0);
1074 /* two dummy got entries */
1075 put32(ptr + 8, 0);
1076 put32(ptr + 12, 0);
1077 put32(ptr + 16, 0);
1078 put32(ptr + 20, 0);
1079 #endif
1082 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1083 and 'info' can be modifed if more precise info comes from the DLL */
1084 static void put_got_entry(TCCState *s1,
1085 int reloc_type, unsigned long size, int info,
1086 int sym_index)
1088 int index;
1089 const char *name;
1090 ElfW(Sym) *sym;
1091 unsigned long offset;
1092 int *ptr;
1094 if (!s1->got)
1095 build_got(s1);
1097 /* if a got entry already exists for that symbol, no need to add one */
1098 if (sym_index < s1->nb_got_offsets &&
1099 s1->got_offsets[sym_index] != 0)
1100 return;
1102 put_got_offset(s1, sym_index, s1->got->data_offset);
1104 if (s1->dynsym) {
1105 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1106 name = symtab_section->link->data + sym->st_name;
1107 offset = sym->st_value;
1108 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1109 if (reloc_type ==
1110 #ifdef TCC_TARGET_X86_64
1111 R_X86_64_JUMP_SLOT
1112 #else
1113 R_386_JMP_SLOT
1114 #endif
1116 Section *plt;
1117 uint8_t *p;
1118 int modrm;
1120 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1121 modrm = 0x25;
1122 #else
1123 /* if we build a DLL, we add a %ebx offset */
1124 if (s1->output_type == TCC_OUTPUT_DLL)
1125 modrm = 0xa3;
1126 else
1127 modrm = 0x25;
1128 #endif
1130 /* add a PLT entry */
1131 plt = s1->plt;
1132 if (plt->data_offset == 0) {
1133 /* first plt entry */
1134 p = section_ptr_add(plt, 16);
1135 p[0] = 0xff; /* pushl got + PTR_SIZE */
1136 p[1] = modrm + 0x10;
1137 put32(p + 2, PTR_SIZE);
1138 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1139 p[7] = modrm;
1140 put32(p + 8, PTR_SIZE * 2);
1143 p = section_ptr_add(plt, 16);
1144 p[0] = 0xff; /* jmp *(got + x) */
1145 p[1] = modrm;
1146 put32(p + 2, s1->got->data_offset);
1147 p[6] = 0x68; /* push $xxx */
1148 put32(p + 7, (plt->data_offset - 32) >> 1);
1149 p[11] = 0xe9; /* jmp plt_start */
1150 put32(p + 12, -(plt->data_offset));
1152 /* the symbol is modified so that it will be relocated to
1153 the PLT */
1154 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1155 if (s1->output_type == TCC_OUTPUT_EXE)
1156 #endif
1157 offset = plt->data_offset - 16;
1159 #elif defined(TCC_TARGET_ARM)
1160 if (reloc_type == R_ARM_JUMP_SLOT) {
1161 Section *plt;
1162 uint8_t *p;
1164 /* if we build a DLL, we add a %ebx offset */
1165 if (s1->output_type == TCC_OUTPUT_DLL)
1166 error("DLLs unimplemented!");
1168 /* add a PLT entry */
1169 plt = s1->plt;
1170 if (plt->data_offset == 0) {
1171 /* first plt entry */
1172 p = section_ptr_add(plt, 16);
1173 put32(p , 0xe52de004);
1174 put32(p + 4, 0xe59fe010);
1175 put32(p + 8, 0xe08fe00e);
1176 put32(p + 12, 0xe5bef008);
1179 p = section_ptr_add(plt, 16);
1180 put32(p , 0xe59fc004);
1181 put32(p+4, 0xe08fc00c);
1182 put32(p+8, 0xe59cf000);
1183 put32(p+12, s1->got->data_offset);
1185 /* the symbol is modified so that it will be relocated to
1186 the PLT */
1187 if (s1->output_type == TCC_OUTPUT_EXE)
1188 offset = plt->data_offset - 16;
1190 #elif defined(TCC_TARGET_C67)
1191 error("C67 got not implemented");
1192 #else
1193 #error unsupported CPU
1194 #endif
1195 index = put_elf_sym(s1->dynsym, offset,
1196 size, info, 0, sym->st_shndx, name);
1197 /* put a got entry */
1198 put_elf_reloc(s1->dynsym, s1->got,
1199 s1->got->data_offset,
1200 reloc_type, index);
1202 ptr = section_ptr_add(s1->got, PTR_SIZE);
1203 *ptr = 0;
1206 /* build GOT and PLT entries */
1207 void build_got_entries(TCCState *s1)
1209 Section *s, *symtab;
1210 ElfW_Rel *rel, *rel_end;
1211 ElfW(Sym) *sym;
1212 int i, type, reloc_type, sym_index;
1214 for(i = 1; i < s1->nb_sections; i++) {
1215 s = s1->sections[i];
1216 if (s->sh_type != SHT_RELX)
1217 continue;
1218 /* no need to handle got relocations */
1219 if (s->link != symtab_section)
1220 continue;
1221 symtab = s->link;
1222 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1223 for(rel = (ElfW_Rel *)s->data;
1224 rel < rel_end;
1225 rel++) {
1226 type = ELFW(R_TYPE)(rel->r_info);
1227 switch(type) {
1228 #if defined(TCC_TARGET_I386)
1229 case R_386_GOT32:
1230 case R_386_GOTOFF:
1231 case R_386_GOTPC:
1232 case R_386_PLT32:
1233 if (!s1->got)
1234 build_got(s1);
1235 if (type == R_386_GOT32 || type == R_386_PLT32) {
1236 sym_index = ELFW(R_SYM)(rel->r_info);
1237 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1238 /* look at the symbol got offset. If none, then add one */
1239 if (type == R_386_GOT32)
1240 reloc_type = R_386_GLOB_DAT;
1241 else
1242 reloc_type = R_386_JMP_SLOT;
1243 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1244 sym_index);
1246 break;
1247 #elif defined(TCC_TARGET_ARM)
1248 case R_ARM_GOT_BREL:
1249 case R_ARM_GOTOFF32:
1250 case R_ARM_BASE_PREL:
1251 case R_ARM_PLT32:
1252 if (!s1->got)
1253 build_got(s1);
1254 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1255 sym_index = ELFW(R_SYM)(rel->r_info);
1256 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1257 /* look at the symbol got offset. If none, then add one */
1258 if (type == R_ARM_GOT_BREL)
1259 reloc_type = R_ARM_GLOB_DAT;
1260 else
1261 reloc_type = R_ARM_JUMP_SLOT;
1262 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1263 sym_index);
1265 break;
1266 #elif defined(TCC_TARGET_C67)
1267 case R_C60_GOT32:
1268 case R_C60_GOTOFF:
1269 case R_C60_GOTPC:
1270 case R_C60_PLT32:
1271 if (!s1->got)
1272 build_got(s1);
1273 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1274 sym_index = ELFW(R_SYM)(rel->r_info);
1275 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1276 /* look at the symbol got offset. If none, then add one */
1277 if (type == R_C60_GOT32)
1278 reloc_type = R_C60_GLOB_DAT;
1279 else
1280 reloc_type = R_C60_JMP_SLOT;
1281 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1282 sym_index);
1284 break;
1285 #elif defined(TCC_TARGET_X86_64)
1286 case R_X86_64_GOT32:
1287 case R_X86_64_GOTTPOFF:
1288 case R_X86_64_GOTPCREL:
1289 case R_X86_64_PLT32:
1290 if (!s1->got)
1291 build_got(s1);
1292 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1293 type == R_X86_64_PLT32) {
1294 sym_index = ELFW(R_SYM)(rel->r_info);
1295 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1296 /* look at the symbol got offset. If none, then add one */
1297 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1298 reloc_type = R_X86_64_GLOB_DAT;
1299 else
1300 reloc_type = R_X86_64_JUMP_SLOT;
1301 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1302 sym_index);
1304 break;
1305 #else
1306 #error unsupported CPU
1307 #endif
1308 default:
1309 break;
1315 Section *new_symtab(TCCState *s1,
1316 const char *symtab_name, int sh_type, int sh_flags,
1317 const char *strtab_name,
1318 const char *hash_name, int hash_sh_flags)
1320 Section *symtab, *strtab, *hash;
1321 int *ptr, nb_buckets;
1323 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1324 symtab->sh_entsize = sizeof(ElfW(Sym));
1325 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1326 put_elf_str(strtab, "");
1327 symtab->link = strtab;
1328 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1330 nb_buckets = 1;
1332 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1333 hash->sh_entsize = sizeof(int);
1334 symtab->hash = hash;
1335 hash->link = symtab;
1337 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1338 ptr[0] = nb_buckets;
1339 ptr[1] = 1;
1340 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1341 return symtab;
1344 /* put dynamic tag */
1345 static void put_dt(Section *dynamic, int dt, unsigned long val)
1347 ElfW(Dyn) *dyn;
1348 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1349 dyn->d_tag = dt;
1350 dyn->d_un.d_val = val;
1353 static void add_init_array_defines(TCCState *s1, const char *section_name)
1355 Section *s;
1356 long end_offset;
1357 char sym_start[1024];
1358 char sym_end[1024];
1360 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1361 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1363 s = find_section(s1, section_name);
1364 if (!s) {
1365 end_offset = 0;
1366 s = data_section;
1367 } else {
1368 end_offset = s->data_offset;
1371 add_elf_sym(symtab_section,
1372 0, 0,
1373 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1374 s->sh_num, sym_start);
1375 add_elf_sym(symtab_section,
1376 end_offset, 0,
1377 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1378 s->sh_num, sym_end);
1381 /* add tcc runtime libraries */
1382 void tcc_add_runtime(TCCState *s1)
1384 #if defined(CONFIG_TCC_BCHECK) || !defined(CONFIG_USE_LIBGCC)
1385 char buf[1024];
1386 #endif
1388 #ifdef CONFIG_TCC_BCHECK
1389 if (s1->do_bounds_check) {
1390 unsigned long *ptr;
1391 Section *init_section;
1392 unsigned char *pinit;
1393 int sym_index;
1395 /* XXX: add an object file to do that */
1396 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1397 *ptr = 0;
1398 add_elf_sym(symtab_section, 0, 0,
1399 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1400 bounds_section->sh_num, "__bounds_start");
1401 /* add bound check code */
1402 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1403 tcc_add_file(s1, buf);
1404 #ifdef TCC_TARGET_I386
1405 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1406 /* add 'call __bound_init()' in .init section */
1407 init_section = find_section(s1, ".init");
1408 pinit = section_ptr_add(init_section, 5);
1409 pinit[0] = 0xe8;
1410 put32(pinit + 1, -4);
1411 sym_index = find_elf_sym(symtab_section, "__bound_init");
1412 put_elf_reloc(symtab_section, init_section,
1413 init_section->data_offset - 4, R_386_PC32, sym_index);
1415 #endif
1417 #endif
1418 /* add libc */
1419 if (!s1->nostdlib) {
1420 tcc_add_library(s1, "c");
1422 #ifdef CONFIG_USE_LIBGCC
1423 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1424 #else
1425 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1426 tcc_add_file(s1, buf);
1427 #endif
1429 /* add crt end if not memory output */
1430 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1431 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1435 /* add various standard linker symbols (must be done after the
1436 sections are filled (for example after allocating common
1437 symbols)) */
1438 void tcc_add_linker_symbols(TCCState *s1)
1440 char buf[1024];
1441 int i;
1442 Section *s;
1444 add_elf_sym(symtab_section,
1445 text_section->data_offset, 0,
1446 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1447 text_section->sh_num, "_etext");
1448 add_elf_sym(symtab_section,
1449 data_section->data_offset, 0,
1450 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1451 data_section->sh_num, "_edata");
1452 add_elf_sym(symtab_section,
1453 bss_section->data_offset, 0,
1454 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1455 bss_section->sh_num, "_end");
1456 /* horrible new standard ldscript defines */
1457 add_init_array_defines(s1, ".preinit_array");
1458 add_init_array_defines(s1, ".init_array");
1459 add_init_array_defines(s1, ".fini_array");
1461 /* add start and stop symbols for sections whose name can be
1462 expressed in C */
1463 for(i = 1; i < s1->nb_sections; i++) {
1464 s = s1->sections[i];
1465 if (s->sh_type == SHT_PROGBITS &&
1466 (s->sh_flags & SHF_ALLOC)) {
1467 const char *p;
1468 int ch;
1470 /* check if section name can be expressed in C */
1471 p = s->name;
1472 for(;;) {
1473 ch = *p;
1474 if (!ch)
1475 break;
1476 if (!isid(ch) && !isnum(ch))
1477 goto next_sec;
1478 p++;
1480 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1481 add_elf_sym(symtab_section,
1482 0, 0,
1483 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1484 s->sh_num, buf);
1485 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1486 add_elf_sym(symtab_section,
1487 s->data_offset, 0,
1488 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1489 s->sh_num, buf);
1491 next_sec: ;
1495 /* name of ELF interpreter */
1496 #if defined __FreeBSD__
1497 static const char elf_interp[] = "/libexec/ld-elf.so.1";
1498 #elif defined TCC_ARM_EABI
1499 static const char elf_interp[] = "/lib/ld-linux.so.3";
1500 #elif defined(TCC_TARGET_X86_64)
1501 static const char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1502 #elif defined(TCC_UCLIBC)
1503 static const char elf_interp[] = "/lib/ld-uClibc.so.0";
1504 #else
1505 static const char elf_interp[] = "/lib/ld-linux.so.2";
1506 #endif
1508 static void tcc_output_binary(TCCState *s1, FILE *f,
1509 const int *section_order)
1511 Section *s;
1512 int i, offset, size;
1514 offset = 0;
1515 for(i=1;i<s1->nb_sections;i++) {
1516 s = s1->sections[section_order[i]];
1517 if (s->sh_type != SHT_NOBITS &&
1518 (s->sh_flags & SHF_ALLOC)) {
1519 while (offset < s->sh_offset) {
1520 fputc(0, f);
1521 offset++;
1523 size = s->sh_size;
1524 fwrite(s->data, 1, size, f);
1525 offset += size;
1530 #if defined(__FreeBSD__)
1531 #define HAVE_PHDR 1
1532 #define EXTRA_RELITEMS 14
1534 /* move the relocation value from .dynsym to .got */
1535 void patch_dynsym_undef(TCCState *s1, Section *s)
1537 uint32_t *gotd = (void *)s1->got->data;
1538 ElfW(Sym) *sym, *sym_end;
1540 gotd += 3; // dummy entries in .got
1541 /* relocate symbols in .dynsym */
1542 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1543 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1544 if (sym->st_shndx == SHN_UNDEF) {
1545 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1546 sym->st_value = 0;
1550 #else
1551 #define HAVE_PHDR 0
1552 #define EXTRA_RELITEMS 9
1553 #endif
1555 /* output an ELF file */
1556 /* XXX: suppress unneeded sections */
1557 int elf_output_file(TCCState *s1, const char *filename)
1559 ElfW(Ehdr) ehdr;
1560 FILE *f;
1561 int fd, mode, ret;
1562 int *section_order;
1563 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1564 unsigned long addr;
1565 Section *strsec, *s;
1566 ElfW(Shdr) shdr, *sh;
1567 ElfW(Phdr) *phdr, *ph;
1568 Section *interp, *dynamic, *dynstr;
1569 unsigned long saved_dynamic_data_offset;
1570 ElfW(Sym) *sym;
1571 int type, file_type;
1572 unsigned long rel_addr, rel_size;
1573 unsigned long bss_addr, bss_size;
1575 file_type = s1->output_type;
1576 s1->nb_errors = 0;
1578 if (file_type != TCC_OUTPUT_OBJ) {
1579 tcc_add_runtime(s1);
1582 phdr = NULL;
1583 section_order = NULL;
1584 interp = NULL;
1585 dynamic = NULL;
1586 dynstr = NULL; /* avoid warning */
1587 saved_dynamic_data_offset = 0; /* avoid warning */
1589 if (file_type != TCC_OUTPUT_OBJ) {
1590 relocate_common_syms();
1592 tcc_add_linker_symbols(s1);
1594 if (!s1->static_link) {
1595 const char *name;
1596 int sym_index, index;
1597 ElfW(Sym) *esym, *sym_end;
1599 if (file_type == TCC_OUTPUT_EXE) {
1600 char *ptr;
1601 /* allow override the dynamic loader */
1602 const char *elfint = getenv("LD_SO");
1603 if (elfint == NULL)
1604 elfint = elf_interp;
1605 /* add interpreter section only if executable */
1606 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1607 interp->sh_addralign = 1;
1608 ptr = section_ptr_add(interp, 1+strlen(elfint));
1609 strcpy(ptr, elfint);
1612 /* add dynamic symbol table */
1613 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1614 ".dynstr",
1615 ".hash", SHF_ALLOC);
1616 dynstr = s1->dynsym->link;
1618 /* add dynamic section */
1619 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1620 SHF_ALLOC | SHF_WRITE);
1621 dynamic->link = dynstr;
1622 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1624 /* add PLT */
1625 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1626 SHF_ALLOC | SHF_EXECINSTR);
1627 s1->plt->sh_entsize = 4;
1629 build_got(s1);
1631 /* scan for undefined symbols and see if they are in the
1632 dynamic symbols. If a symbol STT_FUNC is found, then we
1633 add it in the PLT. If a symbol STT_OBJECT is found, we
1634 add it in the .bss section with a suitable relocation */
1635 sym_end = (ElfW(Sym) *)(symtab_section->data +
1636 symtab_section->data_offset);
1637 if (file_type == TCC_OUTPUT_EXE) {
1638 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1639 sym < sym_end;
1640 sym++) {
1641 if (sym->st_shndx == SHN_UNDEF) {
1642 name = symtab_section->link->data + sym->st_name;
1643 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1644 if (sym_index) {
1645 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1646 type = ELFW(ST_TYPE)(esym->st_info);
1647 if (type == STT_FUNC) {
1648 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1649 esym->st_info,
1650 sym - (ElfW(Sym) *)symtab_section->data);
1651 } else if (type == STT_OBJECT) {
1652 unsigned long offset;
1653 offset = bss_section->data_offset;
1654 /* XXX: which alignment ? */
1655 offset = (offset + 16 - 1) & -16;
1656 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1657 esym->st_info, 0,
1658 bss_section->sh_num, name);
1659 put_elf_reloc(s1->dynsym, bss_section,
1660 offset, R_COPY, index);
1661 offset += esym->st_size;
1662 bss_section->data_offset = offset;
1664 } else {
1665 /* STB_WEAK undefined symbols are accepted */
1666 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1667 it */
1668 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1669 !strcmp(name, "_fp_hw")) {
1670 } else {
1671 error_noabort("undefined symbol '%s'", name);
1674 } else if (s1->rdynamic &&
1675 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1676 /* if -rdynamic option, then export all non
1677 local symbols */
1678 name = symtab_section->link->data + sym->st_name;
1679 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1680 sym->st_info, 0,
1681 sym->st_shndx, name);
1685 if (s1->nb_errors)
1686 goto fail;
1688 /* now look at unresolved dynamic symbols and export
1689 corresponding symbol */
1690 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1691 s1->dynsymtab_section->data_offset);
1692 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1693 esym < sym_end;
1694 esym++) {
1695 if (esym->st_shndx == SHN_UNDEF) {
1696 name = s1->dynsymtab_section->link->data + esym->st_name;
1697 sym_index = find_elf_sym(symtab_section, name);
1698 if (sym_index) {
1699 /* XXX: avoid adding a symbol if already
1700 present because of -rdynamic ? */
1701 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1702 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1703 sym->st_info, 0,
1704 sym->st_shndx, name);
1705 } else {
1706 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1707 /* weak symbols can stay undefined */
1708 } else {
1709 warning("undefined dynamic symbol '%s'", name);
1714 } else {
1715 int nb_syms;
1716 /* shared library case : we simply export all the global symbols */
1717 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1718 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1719 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1720 sym < sym_end;
1721 sym++) {
1722 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1723 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1724 if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
1725 sym->st_shndx == SHN_UNDEF) {
1726 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1727 sym->st_info,
1728 sym - (ElfW(Sym) *)symtab_section->data);
1730 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1731 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1732 sym->st_info,
1733 sym - (ElfW(Sym) *)symtab_section->data);
1735 else
1736 #endif
1738 name = symtab_section->link->data + sym->st_name;
1739 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1740 sym->st_info, 0,
1741 sym->st_shndx, name);
1742 s1->symtab_to_dynsym[sym -
1743 (ElfW(Sym) *)symtab_section->data] =
1744 index;
1750 build_got_entries(s1);
1752 /* add a list of needed dlls */
1753 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1754 DLLReference *dllref = s1->loaded_dlls[i];
1755 if (dllref->level == 0)
1756 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1758 /* XXX: currently, since we do not handle PIC code, we
1759 must relocate the readonly segments */
1760 if (file_type == TCC_OUTPUT_DLL) {
1761 if (s1->soname)
1762 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1763 put_dt(dynamic, DT_TEXTREL, 0);
1766 /* add necessary space for other entries */
1767 saved_dynamic_data_offset = dynamic->data_offset;
1768 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1769 } else {
1770 /* still need to build got entries in case of static link */
1771 build_got_entries(s1);
1775 memset(&ehdr, 0, sizeof(ehdr));
1777 /* we add a section for symbols */
1778 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1779 put_elf_str(strsec, "");
1781 /* compute number of sections */
1782 shnum = s1->nb_sections;
1784 /* this array is used to reorder sections in the output file */
1785 section_order = tcc_malloc(sizeof(int) * shnum);
1786 section_order[0] = 0;
1787 sh_order_index = 1;
1789 /* compute number of program headers */
1790 switch(file_type) {
1791 default:
1792 case TCC_OUTPUT_OBJ:
1793 phnum = 0;
1794 break;
1795 case TCC_OUTPUT_EXE:
1796 if (!s1->static_link)
1797 phnum = 4 + HAVE_PHDR;
1798 else
1799 phnum = 2;
1800 break;
1801 case TCC_OUTPUT_DLL:
1802 phnum = 3;
1803 break;
1806 /* allocate strings for section names and decide if an unallocated
1807 section should be output */
1808 /* NOTE: the strsec section comes last, so its size is also
1809 correct ! */
1810 for(i = 1; i < s1->nb_sections; i++) {
1811 s = s1->sections[i];
1812 s->sh_name = put_elf_str(strsec, s->name);
1813 #if 0 //gr
1814 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1815 s->sh_flags,
1816 s->sh_type,
1817 s->sh_info,
1818 s->name,
1819 s->reloc ? s->reloc->name : "n"
1821 #endif
1822 /* when generating a DLL, we include relocations but we may
1823 patch them */
1824 if (file_type == TCC_OUTPUT_DLL &&
1825 s->sh_type == SHT_RELX &&
1826 !(s->sh_flags & SHF_ALLOC)) {
1827 /* //gr: avoid bogus relocs for empty (debug) sections */
1828 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1829 prepare_dynamic_rel(s1, s);
1830 else if (s1->do_debug)
1831 s->sh_size = s->data_offset;
1832 } else if (s1->do_debug ||
1833 file_type == TCC_OUTPUT_OBJ ||
1834 (s->sh_flags & SHF_ALLOC) ||
1835 i == (s1->nb_sections - 1)) {
1836 /* we output all sections if debug or object file */
1837 s->sh_size = s->data_offset;
1841 /* allocate program segment headers */
1842 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1844 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1845 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1846 } else {
1847 file_offset = 0;
1849 if (phnum > 0) {
1850 /* compute section to program header mapping */
1851 if (s1->has_text_addr) {
1852 int a_offset, p_offset;
1853 addr = s1->text_addr;
1854 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1855 ELF_PAGE_SIZE */
1856 a_offset = addr & (s1->section_align - 1);
1857 p_offset = file_offset & (s1->section_align - 1);
1858 if (a_offset < p_offset)
1859 a_offset += s1->section_align;
1860 file_offset += (a_offset - p_offset);
1861 } else {
1862 if (file_type == TCC_OUTPUT_DLL)
1863 addr = 0;
1864 else
1865 addr = ELF_START_ADDR;
1866 /* compute address after headers */
1867 addr += (file_offset & (s1->section_align - 1));
1870 /* dynamic relocation table information, for .dynamic section */
1871 rel_size = 0;
1872 rel_addr = 0;
1874 bss_addr = bss_size = 0;
1875 /* leave one program header for the program interpreter */
1876 ph = &phdr[0];
1877 if (interp)
1878 ph += 1 + HAVE_PHDR;
1880 for(j = 0; j < 2; j++) {
1881 ph->p_type = PT_LOAD;
1882 if (j == 0)
1883 ph->p_flags = PF_R | PF_X;
1884 else
1885 ph->p_flags = PF_R | PF_W;
1886 ph->p_align = s1->section_align;
1888 /* we do the following ordering: interp, symbol tables,
1889 relocations, progbits, nobits */
1890 /* XXX: do faster and simpler sorting */
1891 for(k = 0; k < 5; k++) {
1892 for(i = 1; i < s1->nb_sections; i++) {
1893 s = s1->sections[i];
1894 /* compute if section should be included */
1895 if (j == 0) {
1896 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1897 SHF_ALLOC)
1898 continue;
1899 } else {
1900 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1901 (SHF_ALLOC | SHF_WRITE))
1902 continue;
1904 if (s == interp) {
1905 if (k != 0)
1906 continue;
1907 } else if (s->sh_type == SHT_DYNSYM ||
1908 s->sh_type == SHT_STRTAB ||
1909 s->sh_type == SHT_HASH) {
1910 if (k != 1)
1911 continue;
1912 } else if (s->sh_type == SHT_RELX) {
1913 if (k != 2)
1914 continue;
1915 } else if (s->sh_type == SHT_NOBITS) {
1916 if (k != 4)
1917 continue;
1918 } else {
1919 if (k != 3)
1920 continue;
1922 section_order[sh_order_index++] = i;
1924 /* section matches: we align it and add its size */
1925 tmp = addr;
1926 addr = (addr + s->sh_addralign - 1) &
1927 ~(s->sh_addralign - 1);
1928 file_offset += addr - tmp;
1929 s->sh_offset = file_offset;
1930 s->sh_addr = addr;
1932 /* update program header infos */
1933 if (ph->p_offset == 0) {
1934 ph->p_offset = file_offset;
1935 ph->p_vaddr = addr;
1936 ph->p_paddr = ph->p_vaddr;
1938 /* update dynamic relocation infos */
1939 if (s->sh_type == SHT_RELX) {
1940 #if defined(__FreeBSD__)
1941 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1942 rel_addr = addr;
1943 rel_size += s->sh_size; // XXX only first rel.
1945 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1946 bss_addr = addr;
1947 bss_size = s->sh_size; // XXX only first rel.
1949 #else
1950 if (rel_size == 0)
1951 rel_addr = addr;
1952 rel_size += s->sh_size;
1953 #endif
1955 addr += s->sh_size;
1956 if (s->sh_type != SHT_NOBITS)
1957 file_offset += s->sh_size;
1960 ph->p_filesz = file_offset - ph->p_offset;
1961 ph->p_memsz = addr - ph->p_vaddr;
1962 ph++;
1963 if (j == 0) {
1964 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1965 /* if in the middle of a page, we duplicate the page in
1966 memory so that one copy is RX and the other is RW */
1967 if ((addr & (s1->section_align - 1)) != 0)
1968 addr += s1->section_align;
1969 } else {
1970 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1971 file_offset = (file_offset + s1->section_align - 1) &
1972 ~(s1->section_align - 1);
1977 /* if interpreter, then add corresponing program header */
1978 if (interp) {
1979 ph = &phdr[0];
1981 #if defined(__FreeBSD__)
1983 int len = phnum * sizeof(ElfW(Phdr));
1985 ph->p_type = PT_PHDR;
1986 ph->p_offset = sizeof(ElfW(Ehdr));
1987 ph->p_vaddr = interp->sh_addr - len;
1988 ph->p_paddr = ph->p_vaddr;
1989 ph->p_filesz = ph->p_memsz = len;
1990 ph->p_flags = PF_R | PF_X;
1991 ph->p_align = 4; // interp->sh_addralign;
1992 ph++;
1994 #endif
1996 ph->p_type = PT_INTERP;
1997 ph->p_offset = interp->sh_offset;
1998 ph->p_vaddr = interp->sh_addr;
1999 ph->p_paddr = ph->p_vaddr;
2000 ph->p_filesz = interp->sh_size;
2001 ph->p_memsz = interp->sh_size;
2002 ph->p_flags = PF_R;
2003 ph->p_align = interp->sh_addralign;
2006 /* if dynamic section, then add corresponing program header */
2007 if (dynamic) {
2008 ElfW(Sym) *sym_end;
2010 ph = &phdr[phnum - 1];
2012 ph->p_type = PT_DYNAMIC;
2013 ph->p_offset = dynamic->sh_offset;
2014 ph->p_vaddr = dynamic->sh_addr;
2015 ph->p_paddr = ph->p_vaddr;
2016 ph->p_filesz = dynamic->sh_size;
2017 ph->p_memsz = dynamic->sh_size;
2018 ph->p_flags = PF_R | PF_W;
2019 ph->p_align = dynamic->sh_addralign;
2021 /* put GOT dynamic section address */
2022 put32(s1->got->data, dynamic->sh_addr);
2024 /* relocate the PLT */
2025 if (file_type == TCC_OUTPUT_EXE
2026 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2027 || file_type == TCC_OUTPUT_DLL
2028 #endif
2030 uint8_t *p, *p_end;
2032 p = s1->plt->data;
2033 p_end = p + s1->plt->data_offset;
2034 if (p < p_end) {
2035 #if defined(TCC_TARGET_I386)
2036 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2037 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
2038 p += 16;
2039 while (p < p_end) {
2040 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2041 p += 16;
2043 #elif defined(TCC_TARGET_X86_64)
2044 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2045 put32(p + 2, get32(p + 2) + x);
2046 put32(p + 8, get32(p + 8) + x - 6);
2047 p += 16;
2048 while (p < p_end) {
2049 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
2050 p += 16;
2052 #elif defined(TCC_TARGET_ARM)
2053 int x;
2054 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2055 p +=16;
2056 while (p < p_end) {
2057 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
2058 p += 16;
2060 #elif defined(TCC_TARGET_C67)
2061 /* XXX: TODO */
2062 #else
2063 #error unsupported CPU
2064 #endif
2068 /* relocate symbols in .dynsym */
2069 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
2070 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
2071 sym < sym_end;
2072 sym++) {
2073 if (sym->st_shndx == SHN_UNDEF) {
2074 /* relocate to the PLT if the symbol corresponds
2075 to a PLT entry */
2076 if (sym->st_value)
2077 sym->st_value += s1->plt->sh_addr;
2078 } else if (sym->st_shndx < SHN_LORESERVE) {
2079 /* do symbol relocation */
2080 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2084 /* put dynamic section entries */
2085 dynamic->data_offset = saved_dynamic_data_offset;
2086 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2087 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2088 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2089 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2090 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2091 #ifdef TCC_TARGET_X86_64
2092 put_dt(dynamic, DT_RELA, rel_addr);
2093 put_dt(dynamic, DT_RELASZ, rel_size);
2094 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2095 #else
2096 #if defined(__FreeBSD__)
2097 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2098 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2099 put_dt(dynamic, DT_JMPREL, rel_addr);
2100 put_dt(dynamic, DT_PLTREL, DT_REL);
2101 put_dt(dynamic, DT_REL, bss_addr);
2102 put_dt(dynamic, DT_RELSZ, bss_size);
2103 #else
2104 put_dt(dynamic, DT_REL, rel_addr);
2105 put_dt(dynamic, DT_RELSZ, rel_size);
2106 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2107 #endif
2108 #endif
2109 if (s1->do_debug)
2110 put_dt(dynamic, DT_DEBUG, 0);
2111 put_dt(dynamic, DT_NULL, 0);
2114 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2115 ehdr.e_phnum = phnum;
2116 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2119 /* all other sections come after */
2120 for(i = 1; i < s1->nb_sections; i++) {
2121 s = s1->sections[i];
2122 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2123 continue;
2124 section_order[sh_order_index++] = i;
2126 file_offset = (file_offset + s->sh_addralign - 1) &
2127 ~(s->sh_addralign - 1);
2128 s->sh_offset = file_offset;
2129 if (s->sh_type != SHT_NOBITS)
2130 file_offset += s->sh_size;
2133 /* if building executable or DLL, then relocate each section
2134 except the GOT which is already relocated */
2135 if (file_type != TCC_OUTPUT_OBJ) {
2136 relocate_syms(s1, 0);
2138 if (s1->nb_errors != 0) {
2139 fail:
2140 ret = -1;
2141 goto the_end;
2144 /* relocate sections */
2145 /* XXX: ignore sections with allocated relocations ? */
2146 for(i = 1; i < s1->nb_sections; i++) {
2147 s = s1->sections[i];
2148 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2149 relocate_section(s1, s);
2152 /* relocate relocation entries if the relocation tables are
2153 allocated in the executable */
2154 for(i = 1; i < s1->nb_sections; i++) {
2155 s = s1->sections[i];
2156 if ((s->sh_flags & SHF_ALLOC) &&
2157 s->sh_type == SHT_RELX) {
2158 relocate_rel(s1, s);
2162 /* get entry point address */
2163 if (file_type == TCC_OUTPUT_EXE)
2164 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2165 else
2166 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2169 /* write elf file */
2170 if (file_type == TCC_OUTPUT_OBJ)
2171 mode = 0666;
2172 else
2173 mode = 0777;
2174 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2175 if (fd < 0) {
2176 error_noabort("could not write '%s'", filename);
2177 goto fail;
2179 f = fdopen(fd, "wb");
2180 if (s1->verbose)
2181 printf("<- %s\n", filename);
2183 #ifdef TCC_TARGET_COFF
2184 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2185 tcc_output_coff(s1, f);
2186 } else
2187 #endif
2188 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2189 sort_syms(s1, symtab_section);
2191 /* align to 4 */
2192 file_offset = (file_offset + 3) & -4;
2194 /* fill header */
2195 ehdr.e_ident[0] = ELFMAG0;
2196 ehdr.e_ident[1] = ELFMAG1;
2197 ehdr.e_ident[2] = ELFMAG2;
2198 ehdr.e_ident[3] = ELFMAG3;
2199 ehdr.e_ident[4] = TCC_ELFCLASS;
2200 ehdr.e_ident[5] = ELFDATA2LSB;
2201 ehdr.e_ident[6] = EV_CURRENT;
2202 #ifdef __FreeBSD__
2203 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2204 #endif
2205 #ifdef TCC_TARGET_ARM
2206 #ifdef TCC_ARM_EABI
2207 ehdr.e_ident[EI_OSABI] = 0;
2208 ehdr.e_flags = 4 << 24;
2209 #else
2210 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2211 #endif
2212 #endif
2213 switch(file_type) {
2214 default:
2215 case TCC_OUTPUT_EXE:
2216 ehdr.e_type = ET_EXEC;
2217 break;
2218 case TCC_OUTPUT_DLL:
2219 ehdr.e_type = ET_DYN;
2220 break;
2221 case TCC_OUTPUT_OBJ:
2222 ehdr.e_type = ET_REL;
2223 break;
2225 ehdr.e_machine = EM_TCC_TARGET;
2226 ehdr.e_version = EV_CURRENT;
2227 ehdr.e_shoff = file_offset;
2228 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2229 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2230 ehdr.e_shnum = shnum;
2231 ehdr.e_shstrndx = shnum - 1;
2233 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2234 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2235 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2237 for(i=1;i<s1->nb_sections;i++) {
2238 s = s1->sections[section_order[i]];
2239 if (s->sh_type != SHT_NOBITS) {
2240 #if defined(__FreeBSD__)
2241 if (s->sh_type == SHT_DYNSYM)
2242 patch_dynsym_undef(s1, s);
2243 #endif
2244 while (offset < s->sh_offset) {
2245 fputc(0, f);
2246 offset++;
2248 size = s->sh_size;
2249 fwrite(s->data, 1, size, f);
2250 offset += size;
2254 /* output section headers */
2255 while (offset < ehdr.e_shoff) {
2256 fputc(0, f);
2257 offset++;
2260 for(i=0;i<s1->nb_sections;i++) {
2261 sh = &shdr;
2262 memset(sh, 0, sizeof(ElfW(Shdr)));
2263 s = s1->sections[i];
2264 if (s) {
2265 sh->sh_name = s->sh_name;
2266 sh->sh_type = s->sh_type;
2267 sh->sh_flags = s->sh_flags;
2268 sh->sh_entsize = s->sh_entsize;
2269 sh->sh_info = s->sh_info;
2270 if (s->link)
2271 sh->sh_link = s->link->sh_num;
2272 sh->sh_addralign = s->sh_addralign;
2273 sh->sh_addr = s->sh_addr;
2274 sh->sh_offset = s->sh_offset;
2275 sh->sh_size = s->sh_size;
2277 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2279 } else {
2280 tcc_output_binary(s1, f, section_order);
2282 fclose(f);
2284 ret = 0;
2285 the_end:
2286 tcc_free(s1->symtab_to_dynsym);
2287 tcc_free(section_order);
2288 tcc_free(phdr);
2289 tcc_free(s1->got_offsets);
2290 return ret;
2293 int tcc_output_file(TCCState *s, const char *filename)
2295 int ret;
2296 #ifdef TCC_TARGET_PE
2297 if (s->output_type != TCC_OUTPUT_OBJ) {
2298 ret = pe_output_file(s, filename);
2299 } else
2300 #endif
2302 ret = elf_output_file(s, filename);
2304 return ret;
2307 void *load_data(int fd, unsigned long file_offset, unsigned long size)
2309 void *data;
2311 data = tcc_malloc(size);
2312 lseek(fd, file_offset, SEEK_SET);
2313 read(fd, data, size);
2314 return data;
2317 typedef struct SectionMergeInfo {
2318 Section *s; /* corresponding existing section */
2319 unsigned long offset; /* offset of the new section in the existing section */
2320 uint8_t new_section; /* true if section 's' was added */
2321 uint8_t link_once; /* true if link once section */
2322 } SectionMergeInfo;
2324 /* load an object file and merge it with current files */
2325 /* XXX: handle correctly stab (debug) info */
2326 int tcc_load_object_file(TCCState *s1,
2327 int fd, unsigned long file_offset)
2329 ElfW(Ehdr) ehdr;
2330 ElfW(Shdr) *shdr, *sh;
2331 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2332 unsigned char *strsec, *strtab;
2333 int *old_to_new_syms;
2334 char *sh_name, *name;
2335 SectionMergeInfo *sm_table, *sm;
2336 ElfW(Sym) *sym, *symtab;
2337 ElfW_Rel *rel, *rel_end;
2338 Section *s;
2340 int stab_index;
2341 int stabstr_index;
2343 stab_index = stabstr_index = 0;
2345 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2346 goto fail1;
2347 if (ehdr.e_ident[0] != ELFMAG0 ||
2348 ehdr.e_ident[1] != ELFMAG1 ||
2349 ehdr.e_ident[2] != ELFMAG2 ||
2350 ehdr.e_ident[3] != ELFMAG3)
2351 goto fail1;
2352 /* test if object file */
2353 if (ehdr.e_type != ET_REL)
2354 goto fail1;
2355 /* test CPU specific stuff */
2356 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2357 ehdr.e_machine != EM_TCC_TARGET) {
2358 fail1:
2359 error_noabort("invalid object file");
2360 return -1;
2362 /* read sections */
2363 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2364 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2365 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2367 /* load section names */
2368 sh = &shdr[ehdr.e_shstrndx];
2369 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2371 /* load symtab and strtab */
2372 old_to_new_syms = NULL;
2373 symtab = NULL;
2374 strtab = NULL;
2375 nb_syms = 0;
2376 for(i = 1; i < ehdr.e_shnum; i++) {
2377 sh = &shdr[i];
2378 if (sh->sh_type == SHT_SYMTAB) {
2379 if (symtab) {
2380 error_noabort("object must contain only one symtab");
2381 fail:
2382 ret = -1;
2383 goto the_end;
2385 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2386 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2387 sm_table[i].s = symtab_section;
2389 /* now load strtab */
2390 sh = &shdr[sh->sh_link];
2391 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2395 /* now examine each section and try to merge its content with the
2396 ones in memory */
2397 for(i = 1; i < ehdr.e_shnum; i++) {
2398 /* no need to examine section name strtab */
2399 if (i == ehdr.e_shstrndx)
2400 continue;
2401 sh = &shdr[i];
2402 sh_name = strsec + sh->sh_name;
2403 /* ignore sections types we do not handle */
2404 if (sh->sh_type != SHT_PROGBITS &&
2405 sh->sh_type != SHT_RELX &&
2406 #ifdef TCC_ARM_EABI
2407 sh->sh_type != SHT_ARM_EXIDX &&
2408 #endif
2409 sh->sh_type != SHT_NOBITS &&
2410 strcmp(sh_name, ".stabstr")
2412 continue;
2413 if (sh->sh_addralign < 1)
2414 sh->sh_addralign = 1;
2415 /* find corresponding section, if any */
2416 for(j = 1; j < s1->nb_sections;j++) {
2417 s = s1->sections[j];
2418 if (!strcmp(s->name, sh_name)) {
2419 if (!strncmp(sh_name, ".gnu.linkonce",
2420 sizeof(".gnu.linkonce") - 1)) {
2421 /* if a 'linkonce' section is already present, we
2422 do not add it again. It is a little tricky as
2423 symbols can still be defined in
2424 it. */
2425 sm_table[i].link_once = 1;
2426 goto next;
2427 } else {
2428 goto found;
2432 /* not found: create new section */
2433 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2434 /* take as much info as possible from the section. sh_link and
2435 sh_info will be updated later */
2436 s->sh_addralign = sh->sh_addralign;
2437 s->sh_entsize = sh->sh_entsize;
2438 sm_table[i].new_section = 1;
2439 found:
2440 if (sh->sh_type != s->sh_type) {
2441 error_noabort("invalid section type");
2442 goto fail;
2445 /* align start of section */
2446 offset = s->data_offset;
2448 if (0 == strcmp(sh_name, ".stab")) {
2449 stab_index = i;
2450 goto no_align;
2452 if (0 == strcmp(sh_name, ".stabstr")) {
2453 stabstr_index = i;
2454 goto no_align;
2457 size = sh->sh_addralign - 1;
2458 offset = (offset + size) & ~size;
2459 if (sh->sh_addralign > s->sh_addralign)
2460 s->sh_addralign = sh->sh_addralign;
2461 s->data_offset = offset;
2462 no_align:
2463 sm_table[i].offset = offset;
2464 sm_table[i].s = s;
2465 /* concatenate sections */
2466 size = sh->sh_size;
2467 if (sh->sh_type != SHT_NOBITS) {
2468 unsigned char *ptr;
2469 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2470 ptr = section_ptr_add(s, size);
2471 read(fd, ptr, size);
2472 } else {
2473 s->data_offset += size;
2475 next: ;
2478 /* //gr relocate stab strings */
2479 if (stab_index && stabstr_index) {
2480 Stab_Sym *a, *b;
2481 unsigned o;
2482 s = sm_table[stab_index].s;
2483 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2484 b = (Stab_Sym *)(s->data + s->data_offset);
2485 o = sm_table[stabstr_index].offset;
2486 while (a < b)
2487 a->n_strx += o, a++;
2490 /* second short pass to update sh_link and sh_info fields of new
2491 sections */
2492 for(i = 1; i < ehdr.e_shnum; i++) {
2493 s = sm_table[i].s;
2494 if (!s || !sm_table[i].new_section)
2495 continue;
2496 sh = &shdr[i];
2497 if (sh->sh_link > 0)
2498 s->link = sm_table[sh->sh_link].s;
2499 if (sh->sh_type == SHT_RELX) {
2500 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2501 /* update backward link */
2502 s1->sections[s->sh_info]->reloc = s;
2505 sm = sm_table;
2507 /* resolve symbols */
2508 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2510 sym = symtab + 1;
2511 for(i = 1; i < nb_syms; i++, sym++) {
2512 if (sym->st_shndx != SHN_UNDEF &&
2513 sym->st_shndx < SHN_LORESERVE) {
2514 sm = &sm_table[sym->st_shndx];
2515 if (sm->link_once) {
2516 /* if a symbol is in a link once section, we use the
2517 already defined symbol. It is very important to get
2518 correct relocations */
2519 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2520 name = strtab + sym->st_name;
2521 sym_index = find_elf_sym(symtab_section, name);
2522 if (sym_index)
2523 old_to_new_syms[i] = sym_index;
2525 continue;
2527 /* if no corresponding section added, no need to add symbol */
2528 if (!sm->s)
2529 continue;
2530 /* convert section number */
2531 sym->st_shndx = sm->s->sh_num;
2532 /* offset value */
2533 sym->st_value += sm->offset;
2535 /* add symbol */
2536 name = strtab + sym->st_name;
2537 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2538 sym->st_info, sym->st_other,
2539 sym->st_shndx, name);
2540 old_to_new_syms[i] = sym_index;
2543 /* third pass to patch relocation entries */
2544 for(i = 1; i < ehdr.e_shnum; i++) {
2545 s = sm_table[i].s;
2546 if (!s)
2547 continue;
2548 sh = &shdr[i];
2549 offset = sm_table[i].offset;
2550 switch(s->sh_type) {
2551 case SHT_RELX:
2552 /* take relocation offset information */
2553 offseti = sm_table[sh->sh_info].offset;
2554 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2555 for(rel = (ElfW_Rel *)(s->data + offset);
2556 rel < rel_end;
2557 rel++) {
2558 int type;
2559 unsigned sym_index;
2560 /* convert symbol index */
2561 type = ELFW(R_TYPE)(rel->r_info);
2562 sym_index = ELFW(R_SYM)(rel->r_info);
2563 /* NOTE: only one symtab assumed */
2564 if (sym_index >= nb_syms)
2565 goto invalid_reloc;
2566 sym_index = old_to_new_syms[sym_index];
2567 /* ignore link_once in rel section. */
2568 if (!sym_index && !sm->link_once) {
2569 invalid_reloc:
2570 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2571 i, strsec + sh->sh_name, rel->r_offset);
2572 goto fail;
2574 rel->r_info = ELFW(R_INFO)(sym_index, type);
2575 /* offset the relocation offset */
2576 rel->r_offset += offseti;
2578 break;
2579 default:
2580 break;
2584 ret = 0;
2585 the_end:
2586 tcc_free(symtab);
2587 tcc_free(strtab);
2588 tcc_free(old_to_new_syms);
2589 tcc_free(sm_table);
2590 tcc_free(strsec);
2591 tcc_free(shdr);
2592 return ret;
2595 typedef struct ArchiveHeader {
2596 char ar_name[16]; /* name of this member */
2597 char ar_date[12]; /* file mtime */
2598 char ar_uid[6]; /* owner uid; printed as decimal */
2599 char ar_gid[6]; /* owner gid; printed as decimal */
2600 char ar_mode[8]; /* file mode, printed as octal */
2601 char ar_size[10]; /* file size, printed as decimal */
2602 char ar_fmag[2]; /* should contain ARFMAG */
2603 } ArchiveHeader;
2605 static int get_be32(const uint8_t *b)
2607 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2610 /* load only the objects which resolve undefined symbols */
2611 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2613 int i, bound, nsyms, sym_index, off, ret;
2614 uint8_t *data;
2615 const char *ar_names, *p;
2616 const uint8_t *ar_index;
2617 ElfW(Sym) *sym;
2619 data = tcc_malloc(size);
2620 if (read(fd, data, size) != size)
2621 goto fail;
2622 nsyms = get_be32(data);
2623 ar_index = data + 4;
2624 ar_names = ar_index + nsyms * 4;
2626 do {
2627 bound = 0;
2628 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2629 sym_index = find_elf_sym(symtab_section, p);
2630 if(sym_index) {
2631 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2632 if(sym->st_shndx == SHN_UNDEF) {
2633 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2634 #if 0
2635 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2636 #endif
2637 ++bound;
2638 lseek(fd, off, SEEK_SET);
2639 if(tcc_load_object_file(s1, fd, off) < 0) {
2640 fail:
2641 ret = -1;
2642 goto the_end;
2647 } while(bound);
2648 ret = 0;
2649 the_end:
2650 tcc_free(data);
2651 return ret;
2654 /* load a '.a' file */
2655 int tcc_load_archive(TCCState *s1, int fd)
2657 ArchiveHeader hdr;
2658 char ar_size[11];
2659 char ar_name[17];
2660 char magic[8];
2661 int size, len, i;
2662 unsigned long file_offset;
2664 /* skip magic which was already checked */
2665 read(fd, magic, sizeof(magic));
2667 for(;;) {
2668 len = read(fd, &hdr, sizeof(hdr));
2669 if (len == 0)
2670 break;
2671 if (len != sizeof(hdr)) {
2672 error_noabort("invalid archive");
2673 return -1;
2675 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2676 ar_size[sizeof(hdr.ar_size)] = '\0';
2677 size = strtol(ar_size, NULL, 0);
2678 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2679 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2680 if (ar_name[i] != ' ')
2681 break;
2683 ar_name[i + 1] = '\0';
2684 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2685 file_offset = lseek(fd, 0, SEEK_CUR);
2686 /* align to even */
2687 size = (size + 1) & ~1;
2688 if (!strcmp(ar_name, "/")) {
2689 /* coff symbol table : we handle it */
2690 if(s1->alacarte_link)
2691 return tcc_load_alacarte(s1, fd, size);
2692 } else if (!strcmp(ar_name, "//") ||
2693 !strcmp(ar_name, "__.SYMDEF") ||
2694 !strcmp(ar_name, "__.SYMDEF/") ||
2695 !strcmp(ar_name, "ARFILENAMES/")) {
2696 /* skip symbol table or archive names */
2697 } else {
2698 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2699 return -1;
2701 lseek(fd, file_offset + size, SEEK_SET);
2703 return 0;