x86-64: Define make variable TARGET so that test2 and test3 use correct flag.
[tinycc/kirr.git] / tccelf.c
blob87c91c3dce86af91bf0337c4ae8a4e2ec065da3f
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
21 #ifdef TCC_TARGET_X86_64
22 #define ElfW_Rel ElfW(Rela)
23 #define SHT_RELX SHT_RELA
24 #define REL_SECTION_FMT ".rela%s"
25 /* x86-64 requires PLT for DLLs */
26 #define TCC_OUTPUT_DLL_WITH_PLT
27 #else
28 #define ElfW_Rel ElfW(Rel)
29 #define SHT_RELX SHT_REL
30 #define REL_SECTION_FMT ".rel%s"
31 #endif
33 /* XXX: DLL with PLT would only work with x86-64 for now */
34 //#define TCC_OUTPUT_DLL_WITH_PLT
36 static int put_elf_str(Section *s, const char *sym)
38 int offset, len;
39 char *ptr;
41 len = strlen(sym) + 1;
42 offset = s->data_offset;
43 ptr = section_ptr_add(s, len);
44 memcpy(ptr, sym, len);
45 return offset;
48 /* elf symbol hashing function */
49 static unsigned long elf_hash(const unsigned char *name)
51 unsigned long h = 0, g;
53 while (*name) {
54 h = (h << 4) + *name++;
55 g = h & 0xf0000000;
56 if (g)
57 h ^= g >> 24;
58 h &= ~g;
60 return h;
63 /* rebuild hash table of section s */
64 /* NOTE: we do factorize the hash table code to go faster */
65 static void rebuild_hash(Section *s, unsigned int nb_buckets)
67 ElfW(Sym) *sym;
68 int *ptr, *hash, nb_syms, sym_index, h;
69 char *strtab;
71 strtab = s->link->data;
72 nb_syms = s->data_offset / sizeof(ElfW(Sym));
74 s->hash->data_offset = 0;
75 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
76 ptr[0] = nb_buckets;
77 ptr[1] = nb_syms;
78 ptr += 2;
79 hash = ptr;
80 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
81 ptr += nb_buckets + 1;
83 sym = (ElfW(Sym) *)s->data + 1;
84 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
85 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
86 h = elf_hash(strtab + sym->st_name) % nb_buckets;
87 *ptr = hash[h];
88 hash[h] = sym_index;
89 } else {
90 *ptr = 0;
92 ptr++;
93 sym++;
97 /* return the symbol number */
98 static int put_elf_sym(Section *s,
99 unsigned long value, unsigned long size,
100 int info, int other, int shndx, const char *name)
102 int name_offset, sym_index;
103 int nbuckets, h;
104 ElfW(Sym) *sym;
105 Section *hs;
107 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
108 if (name)
109 name_offset = put_elf_str(s->link, name);
110 else
111 name_offset = 0;
112 /* XXX: endianness */
113 sym->st_name = name_offset;
114 sym->st_value = value;
115 sym->st_size = size;
116 sym->st_info = info;
117 sym->st_other = other;
118 sym->st_shndx = shndx;
119 sym_index = sym - (ElfW(Sym) *)s->data;
120 hs = s->hash;
121 if (hs) {
122 int *ptr, *base;
123 ptr = section_ptr_add(hs, sizeof(int));
124 base = (int *)hs->data;
125 /* only add global or weak symbols */
126 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
127 /* add another hashing entry */
128 nbuckets = base[0];
129 h = elf_hash(name) % nbuckets;
130 *ptr = base[2 + h];
131 base[2 + h] = sym_index;
132 base[1]++;
133 /* we resize the hash table */
134 hs->nb_hashed_syms++;
135 if (hs->nb_hashed_syms > 2 * nbuckets) {
136 rebuild_hash(s, 2 * nbuckets);
138 } else {
139 *ptr = 0;
140 base[1]++;
143 return sym_index;
146 /* find global ELF symbol 'name' and return its index. Return 0 if not
147 found. */
148 static int find_elf_sym(Section *s, const char *name)
150 ElfW(Sym) *sym;
151 Section *hs;
152 int nbuckets, sym_index, h;
153 const char *name1;
155 hs = s->hash;
156 if (!hs)
157 return 0;
158 nbuckets = ((int *)hs->data)[0];
159 h = elf_hash(name) % nbuckets;
160 sym_index = ((int *)hs->data)[2 + h];
161 while (sym_index != 0) {
162 sym = &((ElfW(Sym) *)s->data)[sym_index];
163 name1 = s->link->data + sym->st_name;
164 if (!strcmp(name, name1))
165 return sym_index;
166 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
168 return 0;
171 /* return elf symbol value or error */
172 int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name)
174 int sym_index;
175 ElfW(Sym) *sym;
177 sym_index = find_elf_sym(symtab_section, name);
178 if (!sym_index)
179 return -1;
180 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
181 *pval = sym->st_value;
182 return 0;
185 void *tcc_get_symbol_err(TCCState *s, const char *name)
187 unsigned long val;
188 if (tcc_get_symbol(s, &val, name) < 0)
189 error("%s not defined", name);
190 return (void *)val;
193 /* add an elf symbol : check if it is already defined and patch
194 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
195 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
196 int info, int other, int sh_num, const char *name)
198 ElfW(Sym) *esym;
199 int sym_bind, sym_index, sym_type, esym_bind;
200 unsigned char sym_vis, esym_vis, new_vis;
202 sym_bind = ELFW(ST_BIND)(info);
203 sym_type = ELFW(ST_TYPE)(info);
204 sym_vis = ELFW(ST_VISIBILITY)(other);
206 if (sym_bind != STB_LOCAL) {
207 /* we search global or weak symbols */
208 sym_index = find_elf_sym(s, name);
209 if (!sym_index)
210 goto do_def;
211 esym = &((ElfW(Sym) *)s->data)[sym_index];
212 if (esym->st_shndx != SHN_UNDEF) {
213 esym_bind = ELFW(ST_BIND)(esym->st_info);
214 /* propagate the most constraining visibility */
215 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
216 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
217 if (esym_vis == STV_DEFAULT) {
218 new_vis = sym_vis;
219 } else if (sym_vis == STV_DEFAULT) {
220 new_vis = esym_vis;
221 } else {
222 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
224 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
225 | new_vis;
226 other = esym->st_other; /* in case we have to patch esym */
227 if (sh_num == SHN_UNDEF) {
228 /* ignore adding of undefined symbol if the
229 corresponding symbol is already defined */
230 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
231 /* global overrides weak, so patch */
232 goto do_patch;
233 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
234 /* weak is ignored if already global */
235 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
236 /* ignore hidden symbols after */
237 } else if (esym->st_shndx == SHN_COMMON && sh_num < SHN_LORESERVE) {
238 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
239 No idea if this is the correct solution ... */
240 goto do_patch;
241 } else if (s == tcc_state->dynsymtab_section) {
242 /* we accept that two DLL define the same symbol */
243 } else {
244 #if 1
245 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
246 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
247 #endif
248 error_noabort("'%s' defined twice", name);
250 } else {
251 do_patch:
252 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
253 esym->st_shndx = sh_num;
254 esym->st_value = value;
255 esym->st_size = size;
256 esym->st_other = other;
258 } else {
259 do_def:
260 sym_index = put_elf_sym(s, value, size,
261 ELFW(ST_INFO)(sym_bind, sym_type), other,
262 sh_num, name);
264 return sym_index;
267 /* put relocation */
268 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
269 int type, int symbol)
271 char buf[256];
272 Section *sr;
273 ElfW_Rel *rel;
275 sr = s->reloc;
276 if (!sr) {
277 /* if no relocation section, create it */
278 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
279 /* if the symtab is allocated, then we consider the relocation
280 are also */
281 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
282 sr->sh_entsize = sizeof(ElfW_Rel);
283 sr->link = symtab;
284 sr->sh_info = s->sh_num;
285 s->reloc = sr;
287 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
288 rel->r_offset = offset;
289 rel->r_info = ELFW(R_INFO)(symbol, type);
290 #ifdef TCC_TARGET_X86_64
291 rel->r_addend = 0;
292 #endif
295 /* put stab debug information */
297 typedef struct {
298 unsigned int n_strx; /* index into string table of name */
299 unsigned char n_type; /* type of symbol */
300 unsigned char n_other; /* misc info (usually empty) */
301 unsigned short n_desc; /* description field */
302 unsigned int n_value; /* value of symbol */
303 } Stab_Sym;
305 static void put_stabs(const char *str, int type, int other, int desc,
306 unsigned long value)
308 Stab_Sym *sym;
310 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
311 if (str) {
312 sym->n_strx = put_elf_str(stabstr_section, str);
313 } else {
314 sym->n_strx = 0;
316 sym->n_type = type;
317 sym->n_other = other;
318 sym->n_desc = desc;
319 sym->n_value = value;
322 static void put_stabs_r(const char *str, int type, int other, int desc,
323 unsigned long value, Section *sec, int sym_index)
325 put_stabs(str, type, other, desc, value);
326 put_elf_reloc(symtab_section, stab_section,
327 stab_section->data_offset - sizeof(unsigned int),
328 R_DATA_32, sym_index);
331 static void put_stabn(int type, int other, int desc, int value)
333 put_stabs(NULL, type, other, desc, value);
336 static void put_stabd(int type, int other, int desc)
338 put_stabs(NULL, type, other, desc, 0);
341 /* In an ELF file symbol table, the local symbols must appear below
342 the global and weak ones. Since TCC cannot sort it while generating
343 the code, we must do it after. All the relocation tables are also
344 modified to take into account the symbol table sorting */
345 static void sort_syms(TCCState *s1, Section *s)
347 int *old_to_new_syms;
348 ElfW(Sym) *new_syms;
349 int nb_syms, i;
350 ElfW(Sym) *p, *q;
351 ElfW_Rel *rel, *rel_end;
352 Section *sr;
353 int type, sym_index;
355 nb_syms = s->data_offset / sizeof(ElfW(Sym));
356 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
357 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
359 /* first pass for local symbols */
360 p = (ElfW(Sym) *)s->data;
361 q = new_syms;
362 for(i = 0; i < nb_syms; i++) {
363 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
364 old_to_new_syms[i] = q - new_syms;
365 *q++ = *p;
367 p++;
369 /* save the number of local symbols in section header */
370 s->sh_info = q - new_syms;
372 /* then second pass for non local symbols */
373 p = (ElfW(Sym) *)s->data;
374 for(i = 0; i < nb_syms; i++) {
375 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
376 old_to_new_syms[i] = q - new_syms;
377 *q++ = *p;
379 p++;
382 /* we copy the new symbols to the old */
383 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
384 tcc_free(new_syms);
386 /* now we modify all the relocations */
387 for(i = 1; i < s1->nb_sections; i++) {
388 sr = s1->sections[i];
389 if (sr->sh_type == SHT_RELX && sr->link == s) {
390 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
391 for(rel = (ElfW_Rel *)sr->data;
392 rel < rel_end;
393 rel++) {
394 sym_index = ELFW(R_SYM)(rel->r_info);
395 type = ELFW(R_TYPE)(rel->r_info);
396 sym_index = old_to_new_syms[sym_index];
397 rel->r_info = ELFW(R_INFO)(sym_index, type);
402 tcc_free(old_to_new_syms);
405 /* relocate common symbols in the .bss section */
406 static void relocate_common_syms(void)
408 ElfW(Sym) *sym, *sym_end;
409 unsigned long offset, align;
411 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
412 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
413 sym < sym_end;
414 sym++) {
415 if (sym->st_shndx == SHN_COMMON) {
416 /* align symbol */
417 align = sym->st_value;
418 offset = bss_section->data_offset;
419 offset = (offset + align - 1) & -align;
420 sym->st_value = offset;
421 sym->st_shndx = bss_section->sh_num;
422 offset += sym->st_size;
423 bss_section->data_offset = offset;
428 /* relocate symbol table, resolve undefined symbols if do_resolve is
429 true and output error if undefined symbol. */
430 static void relocate_syms(TCCState *s1, int do_resolve)
432 ElfW(Sym) *sym, *esym, *sym_end;
433 int sym_bind, sh_num, sym_index;
434 const char *name;
435 unsigned long addr;
437 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
438 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
439 sym < sym_end;
440 sym++) {
441 sh_num = sym->st_shndx;
442 if (sh_num == SHN_UNDEF) {
443 name = strtab_section->data + sym->st_name;
444 if (do_resolve) {
445 name = symtab_section->link->data + sym->st_name;
446 addr = (unsigned long)resolve_sym(s1, name, ELFW(ST_TYPE)(sym->st_info));
447 if (addr) {
448 sym->st_value = addr;
449 goto found;
451 } else if (s1->dynsym) {
452 /* if dynamic symbol exist, then use it */
453 sym_index = find_elf_sym(s1->dynsym, name);
454 if (sym_index) {
455 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
456 sym->st_value = esym->st_value;
457 goto found;
460 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
461 it */
462 if (!strcmp(name, "_fp_hw"))
463 goto found;
464 /* only weak symbols are accepted to be undefined. Their
465 value is zero */
466 sym_bind = ELFW(ST_BIND)(sym->st_info);
467 if (sym_bind == STB_WEAK) {
468 sym->st_value = 0;
469 } else {
470 error_noabort("undefined symbol '%s'", name);
472 } else if (sh_num < SHN_LORESERVE) {
473 /* add section base */
474 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
476 found: ;
480 #ifdef TCC_TARGET_X86_64
481 #define JMP_TABLE_ENTRY_SIZE 14
482 static unsigned long add_jmp_table(TCCState *s1, unsigned long val)
484 char *p = (char *)section_ptr_add(text_section, JMP_TABLE_ENTRY_SIZE);
485 /* jmp *0x0(%rip) */
486 p[0] = 0xff;
487 p[1] = 0x25;
488 *(int *)(p + 2) = 0;
489 *(unsigned long *)(p + 6) = val;
490 return (unsigned long)p;
493 static unsigned long add_got_table(TCCState *s1, unsigned long val)
495 unsigned long *p =
496 (unsigned long *)section_ptr_add(text_section, sizeof(void *));
497 *p = val;
498 return (unsigned long)p;
500 #endif
502 /* relocate a given section (CPU dependent) */
503 static void relocate_section(TCCState *s1, Section *s)
505 Section *sr;
506 ElfW_Rel *rel, *rel_end, *qrel;
507 ElfW(Sym) *sym;
508 int type, sym_index;
509 unsigned char *ptr;
510 unsigned long val, addr;
511 int esym_index;
513 sr = s->reloc;
514 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
515 qrel = (ElfW_Rel *)sr->data;
516 for(rel = qrel;
517 rel < rel_end;
518 rel++) {
519 ptr = s->data + rel->r_offset;
521 sym_index = ELFW(R_SYM)(rel->r_info);
522 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
523 val = sym->st_value;
524 #ifdef TCC_TARGET_X86_64
525 /* XXX: not tested */
526 val += rel->r_addend;
527 #endif
528 type = ELFW(R_TYPE)(rel->r_info);
529 addr = s->sh_addr + rel->r_offset;
531 /* CPU specific */
532 switch(type) {
533 #if defined(TCC_TARGET_I386)
534 case R_386_32:
535 if (s1->output_type == TCC_OUTPUT_DLL) {
536 esym_index = s1->symtab_to_dynsym[sym_index];
537 qrel->r_offset = rel->r_offset;
538 if (esym_index) {
539 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
540 qrel++;
541 break;
542 } else {
543 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
544 qrel++;
547 *(int *)ptr += val;
548 break;
549 case R_386_PC32:
550 if (s1->output_type == TCC_OUTPUT_DLL) {
551 /* DLL relocation */
552 esym_index = s1->symtab_to_dynsym[sym_index];
553 if (esym_index) {
554 qrel->r_offset = rel->r_offset;
555 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
556 qrel++;
557 break;
560 *(int *)ptr += val - addr;
561 break;
562 case R_386_PLT32:
563 *(int *)ptr += val - addr;
564 break;
565 case R_386_GLOB_DAT:
566 case R_386_JMP_SLOT:
567 *(int *)ptr = val;
568 break;
569 case R_386_GOTPC:
570 *(int *)ptr += s1->got->sh_addr - addr;
571 break;
572 case R_386_GOTOFF:
573 *(int *)ptr += val - s1->got->sh_addr;
574 break;
575 case R_386_GOT32:
576 /* we load the got offset */
577 *(int *)ptr += s1->got_offsets[sym_index];
578 break;
579 #elif defined(TCC_TARGET_ARM)
580 case R_ARM_PC24:
581 case R_ARM_CALL:
582 case R_ARM_JUMP24:
583 case R_ARM_PLT32:
585 int x;
586 x = (*(int *)ptr)&0xffffff;
587 (*(int *)ptr) &= 0xff000000;
588 if (x & 0x800000)
589 x -= 0x1000000;
590 x *= 4;
591 x += val - addr;
592 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
593 error("can't relocate value at %x",addr);
594 x >>= 2;
595 x &= 0xffffff;
596 (*(int *)ptr) |= x;
598 break;
599 case R_ARM_PREL31:
601 int x;
602 x = (*(int *)ptr) & 0x7fffffff;
603 (*(int *)ptr) &= 0x80000000;
604 x = (x * 2) / 2;
605 x += val - addr;
606 if((x^(x>>1))&0x40000000)
607 error("can't relocate value at %x",addr);
608 (*(int *)ptr) |= x & 0x7fffffff;
610 case R_ARM_ABS32:
611 *(int *)ptr += val;
612 break;
613 case R_ARM_BASE_PREL:
614 *(int *)ptr += s1->got->sh_addr - addr;
615 break;
616 case R_ARM_GOTOFF32:
617 *(int *)ptr += val - s1->got->sh_addr;
618 break;
619 case R_ARM_GOT_BREL:
620 /* we load the got offset */
621 *(int *)ptr += s1->got_offsets[sym_index];
622 break;
623 case R_ARM_COPY:
624 break;
625 default:
626 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
627 type,addr,(unsigned int )ptr,val);
628 break;
629 #elif defined(TCC_TARGET_C67)
630 case R_C60_32:
631 *(int *)ptr += val;
632 break;
633 case R_C60LO16:
635 uint32_t orig;
637 /* put the low 16 bits of the absolute address */
638 // add to what is already there
640 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
641 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
643 //patch both at once - assumes always in pairs Low - High
645 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
646 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
648 break;
649 case R_C60HI16:
650 break;
651 default:
652 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
653 type,addr,(unsigned int )ptr,val);
654 break;
655 #elif defined(TCC_TARGET_X86_64)
656 case R_X86_64_64:
657 if (s1->output_type == TCC_OUTPUT_DLL) {
658 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
659 qrel->r_addend = *(long long *)ptr + val;
660 qrel++;
662 *(long long *)ptr += val;
663 break;
664 case R_X86_64_32:
665 case R_X86_64_32S:
666 if (s1->output_type == TCC_OUTPUT_DLL) {
667 /* XXX: this logic may depend on TCC's codegen
668 now TCC uses R_X86_64_32 even for a 64bit pointer */
669 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
670 qrel->r_addend = *(int *)ptr + val;
671 qrel++;
673 *(int *)ptr += val;
674 break;
675 case R_X86_64_PC32: {
676 if (s1->output_type == TCC_OUTPUT_DLL) {
677 /* DLL relocation */
678 esym_index = s1->symtab_to_dynsym[sym_index];
679 if (esym_index) {
680 qrel->r_offset = rel->r_offset;
681 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
682 qrel->r_addend = *(int *)ptr;
683 qrel++;
684 break;
687 long diff = val - addr;
688 if (diff <= -2147483647 || diff > 2147483647) {
689 /* XXX: naive support for over 32bit jump */
690 if (s1->output_type == TCC_OUTPUT_MEMORY) {
691 val = add_jmp_table(s1, val);
692 diff = val - addr;
694 if (diff <= -2147483647 || diff > 2147483647) {
695 error("internal error: relocation failed");
698 *(int *)ptr += diff;
700 break;
701 case R_X86_64_PLT32:
702 *(int *)ptr += val - addr;
703 break;
704 case R_X86_64_GLOB_DAT:
705 case R_X86_64_JUMP_SLOT:
706 *(int *)ptr = val;
707 break;
708 case R_X86_64_GOTPCREL:
709 if (s1->output_type == TCC_OUTPUT_MEMORY) {
710 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
711 *(int *)ptr += val - addr;
712 break;
714 *(int *)ptr += (s1->got->sh_addr - addr +
715 s1->got_offsets[sym_index] - 4);
716 break;
717 case R_X86_64_GOTTPOFF:
718 *(int *)ptr += val - s1->got->sh_addr;
719 break;
720 case R_X86_64_GOT32:
721 /* we load the got offset */
722 *(int *)ptr += s1->got_offsets[sym_index];
723 break;
724 #else
725 #error unsupported processor
726 #endif
729 /* if the relocation is allocated, we change its symbol table */
730 if (sr->sh_flags & SHF_ALLOC)
731 sr->link = s1->dynsym;
734 /* relocate relocation table in 'sr' */
735 static void relocate_rel(TCCState *s1, Section *sr)
737 Section *s;
738 ElfW_Rel *rel, *rel_end;
740 s = s1->sections[sr->sh_info];
741 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
742 for(rel = (ElfW_Rel *)sr->data;
743 rel < rel_end;
744 rel++) {
745 rel->r_offset += s->sh_addr;
749 /* count the number of dynamic relocations so that we can reserve
750 their space */
751 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
753 ElfW_Rel *rel, *rel_end;
754 int sym_index, esym_index, type, count;
756 count = 0;
757 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
758 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
759 sym_index = ELFW(R_SYM)(rel->r_info);
760 type = ELFW(R_TYPE)(rel->r_info);
761 switch(type) {
762 #if defined(TCC_TARGET_I386)
763 case R_386_32:
764 #elif defined(TCC_TARGET_X86_64)
765 case R_X86_64_32:
766 case R_X86_64_32S:
767 case R_X86_64_64:
768 #endif
769 count++;
770 break;
771 #if defined(TCC_TARGET_I386)
772 case R_386_PC32:
773 #elif defined(TCC_TARGET_X86_64)
774 case R_X86_64_PC32:
775 #endif
776 esym_index = s1->symtab_to_dynsym[sym_index];
777 if (esym_index)
778 count++;
779 break;
780 default:
781 break;
784 if (count) {
785 /* allocate the section */
786 sr->sh_flags |= SHF_ALLOC;
787 sr->sh_size = count * sizeof(ElfW_Rel);
789 return count;
792 static void put_got_offset(TCCState *s1, int index, unsigned long val)
794 int n;
795 unsigned long *tab;
797 if (index >= s1->nb_got_offsets) {
798 /* find immediately bigger power of 2 and reallocate array */
799 n = 1;
800 while (index >= n)
801 n *= 2;
802 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
803 if (!tab)
804 error("memory full");
805 s1->got_offsets = tab;
806 memset(s1->got_offsets + s1->nb_got_offsets, 0,
807 (n - s1->nb_got_offsets) * sizeof(unsigned long));
808 s1->nb_got_offsets = n;
810 s1->got_offsets[index] = val;
813 /* XXX: suppress that */
814 static void put32(unsigned char *p, uint32_t val)
816 p[0] = val;
817 p[1] = val >> 8;
818 p[2] = val >> 16;
819 p[3] = val >> 24;
822 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
823 defined(TCC_TARGET_X86_64)
824 static uint32_t get32(unsigned char *p)
826 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
828 #endif
830 static void build_got(TCCState *s1)
832 unsigned char *ptr;
834 /* if no got, then create it */
835 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
836 s1->got->sh_entsize = 4;
837 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
838 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
839 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
840 #if PTR_SIZE == 4
841 /* keep space for _DYNAMIC pointer, if present */
842 put32(ptr, 0);
843 /* two dummy got entries */
844 put32(ptr + 4, 0);
845 put32(ptr + 8, 0);
846 #else
847 /* keep space for _DYNAMIC pointer, if present */
848 put32(ptr, 0);
849 put32(ptr + 4, 0);
850 /* two dummy got entries */
851 put32(ptr + 8, 0);
852 put32(ptr + 12, 0);
853 put32(ptr + 16, 0);
854 put32(ptr + 20, 0);
855 #endif
858 /* put a got entry corresponding to a symbol in symtab_section. 'size'
859 and 'info' can be modifed if more precise info comes from the DLL */
860 static void put_got_entry(TCCState *s1,
861 int reloc_type, unsigned long size, int info,
862 int sym_index)
864 int index;
865 const char *name;
866 ElfW(Sym) *sym;
867 unsigned long offset;
868 int *ptr;
870 if (!s1->got)
871 build_got(s1);
873 /* if a got entry already exists for that symbol, no need to add one */
874 if (sym_index < s1->nb_got_offsets &&
875 s1->got_offsets[sym_index] != 0)
876 return;
878 put_got_offset(s1, sym_index, s1->got->data_offset);
880 if (s1->dynsym) {
881 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
882 name = symtab_section->link->data + sym->st_name;
883 offset = sym->st_value;
884 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
885 if (reloc_type ==
886 #ifdef TCC_TARGET_X86_64
887 R_X86_64_JUMP_SLOT
888 #else
889 R_386_JMP_SLOT
890 #endif
892 Section *plt;
893 uint8_t *p;
894 int modrm;
896 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
897 modrm = 0x25;
898 #else
899 /* if we build a DLL, we add a %ebx offset */
900 if (s1->output_type == TCC_OUTPUT_DLL)
901 modrm = 0xa3;
902 else
903 modrm = 0x25;
904 #endif
906 /* add a PLT entry */
907 plt = s1->plt;
908 if (plt->data_offset == 0) {
909 /* first plt entry */
910 p = section_ptr_add(plt, 16);
911 p[0] = 0xff; /* pushl got + PTR_SIZE */
912 p[1] = modrm + 0x10;
913 put32(p + 2, PTR_SIZE);
914 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
915 p[7] = modrm;
916 put32(p + 8, PTR_SIZE * 2);
919 p = section_ptr_add(plt, 16);
920 p[0] = 0xff; /* jmp *(got + x) */
921 p[1] = modrm;
922 put32(p + 2, s1->got->data_offset);
923 p[6] = 0x68; /* push $xxx */
924 put32(p + 7, (plt->data_offset - 32) >> 1);
925 p[11] = 0xe9; /* jmp plt_start */
926 put32(p + 12, -(plt->data_offset));
928 /* the symbol is modified so that it will be relocated to
929 the PLT */
930 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
931 if (s1->output_type == TCC_OUTPUT_EXE)
932 #endif
933 offset = plt->data_offset - 16;
935 #elif defined(TCC_TARGET_ARM)
936 if (reloc_type == R_ARM_JUMP_SLOT) {
937 Section *plt;
938 uint8_t *p;
940 /* if we build a DLL, we add a %ebx offset */
941 if (s1->output_type == TCC_OUTPUT_DLL)
942 error("DLLs unimplemented!");
944 /* add a PLT entry */
945 plt = s1->plt;
946 if (plt->data_offset == 0) {
947 /* first plt entry */
948 p = section_ptr_add(plt, 16);
949 put32(p , 0xe52de004);
950 put32(p + 4, 0xe59fe010);
951 put32(p + 8, 0xe08fe00e);
952 put32(p + 12, 0xe5bef008);
955 p = section_ptr_add(plt, 16);
956 put32(p , 0xe59fc004);
957 put32(p+4, 0xe08fc00c);
958 put32(p+8, 0xe59cf000);
959 put32(p+12, s1->got->data_offset);
961 /* the symbol is modified so that it will be relocated to
962 the PLT */
963 if (s1->output_type == TCC_OUTPUT_EXE)
964 offset = plt->data_offset - 16;
966 #elif defined(TCC_TARGET_C67)
967 error("C67 got not implemented");
968 #else
969 #error unsupported CPU
970 #endif
971 index = put_elf_sym(s1->dynsym, offset,
972 size, info, 0, sym->st_shndx, name);
973 /* put a got entry */
974 put_elf_reloc(s1->dynsym, s1->got,
975 s1->got->data_offset,
976 reloc_type, index);
978 ptr = section_ptr_add(s1->got, PTR_SIZE);
979 *ptr = 0;
982 /* build GOT and PLT entries */
983 static void build_got_entries(TCCState *s1)
985 Section *s, *symtab;
986 ElfW_Rel *rel, *rel_end;
987 ElfW(Sym) *sym;
988 int i, type, reloc_type, sym_index;
990 for(i = 1; i < s1->nb_sections; i++) {
991 s = s1->sections[i];
992 if (s->sh_type != SHT_RELX)
993 continue;
994 /* no need to handle got relocations */
995 if (s->link != symtab_section)
996 continue;
997 symtab = s->link;
998 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
999 for(rel = (ElfW_Rel *)s->data;
1000 rel < rel_end;
1001 rel++) {
1002 type = ELFW(R_TYPE)(rel->r_info);
1003 switch(type) {
1004 #if defined(TCC_TARGET_I386)
1005 case R_386_GOT32:
1006 case R_386_GOTOFF:
1007 case R_386_GOTPC:
1008 case R_386_PLT32:
1009 if (!s1->got)
1010 build_got(s1);
1011 if (type == R_386_GOT32 || type == R_386_PLT32) {
1012 sym_index = ELFW(R_SYM)(rel->r_info);
1013 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1014 /* look at the symbol got offset. If none, then add one */
1015 if (type == R_386_GOT32)
1016 reloc_type = R_386_GLOB_DAT;
1017 else
1018 reloc_type = R_386_JMP_SLOT;
1019 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1020 sym_index);
1022 break;
1023 #elif defined(TCC_TARGET_ARM)
1024 case R_ARM_GOT_BREL:
1025 case R_ARM_GOTOFF32:
1026 case R_ARM_BASE_PREL:
1027 case R_ARM_PLT32:
1028 if (!s1->got)
1029 build_got(s1);
1030 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1031 sym_index = ELFW(R_SYM)(rel->r_info);
1032 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1033 /* look at the symbol got offset. If none, then add one */
1034 if (type == R_ARM_GOT_BREL)
1035 reloc_type = R_ARM_GLOB_DAT;
1036 else
1037 reloc_type = R_ARM_JUMP_SLOT;
1038 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1039 sym_index);
1041 break;
1042 #elif defined(TCC_TARGET_C67)
1043 case R_C60_GOT32:
1044 case R_C60_GOTOFF:
1045 case R_C60_GOTPC:
1046 case R_C60_PLT32:
1047 if (!s1->got)
1048 build_got(s1);
1049 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1050 sym_index = ELFW(R_SYM)(rel->r_info);
1051 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1052 /* look at the symbol got offset. If none, then add one */
1053 if (type == R_C60_GOT32)
1054 reloc_type = R_C60_GLOB_DAT;
1055 else
1056 reloc_type = R_C60_JMP_SLOT;
1057 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1058 sym_index);
1060 break;
1061 #elif defined(TCC_TARGET_X86_64)
1062 case R_X86_64_GOT32:
1063 case R_X86_64_GOTTPOFF:
1064 case R_X86_64_GOTPCREL:
1065 case R_X86_64_PLT32:
1066 if (!s1->got)
1067 build_got(s1);
1068 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1069 type == R_X86_64_PLT32) {
1070 sym_index = ELFW(R_SYM)(rel->r_info);
1071 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1072 /* look at the symbol got offset. If none, then add one */
1073 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1074 reloc_type = R_X86_64_GLOB_DAT;
1075 else
1076 reloc_type = R_X86_64_JUMP_SLOT;
1077 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1078 sym_index);
1080 break;
1081 #else
1082 #error unsupported CPU
1083 #endif
1084 default:
1085 break;
1091 static Section *new_symtab(TCCState *s1,
1092 const char *symtab_name, int sh_type, int sh_flags,
1093 const char *strtab_name,
1094 const char *hash_name, int hash_sh_flags)
1096 Section *symtab, *strtab, *hash;
1097 int *ptr, nb_buckets;
1099 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1100 symtab->sh_entsize = sizeof(ElfW(Sym));
1101 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1102 put_elf_str(strtab, "");
1103 symtab->link = strtab;
1104 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1106 nb_buckets = 1;
1108 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1109 hash->sh_entsize = sizeof(int);
1110 symtab->hash = hash;
1111 hash->link = symtab;
1113 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1114 ptr[0] = nb_buckets;
1115 ptr[1] = 1;
1116 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1117 return symtab;
1120 /* put dynamic tag */
1121 static void put_dt(Section *dynamic, int dt, unsigned long val)
1123 ElfW(Dyn) *dyn;
1124 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1125 dyn->d_tag = dt;
1126 dyn->d_un.d_val = val;
1129 static void add_init_array_defines(TCCState *s1, const char *section_name)
1131 Section *s;
1132 long end_offset;
1133 char sym_start[1024];
1134 char sym_end[1024];
1136 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1137 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1139 s = find_section(s1, section_name);
1140 if (!s) {
1141 end_offset = 0;
1142 s = data_section;
1143 } else {
1144 end_offset = s->data_offset;
1147 add_elf_sym(symtab_section,
1148 0, 0,
1149 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1150 s->sh_num, sym_start);
1151 add_elf_sym(symtab_section,
1152 end_offset, 0,
1153 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1154 s->sh_num, sym_end);
1157 /* add tcc runtime libraries */
1158 static void tcc_add_runtime(TCCState *s1)
1160 #if defined(CONFIG_TCC_BCHECK) || !defined(CONFIG_USE_LIBGCC)
1161 char buf[1024];
1162 #endif
1164 #ifdef CONFIG_TCC_BCHECK
1165 if (do_bounds_check) {
1166 unsigned long *ptr;
1167 Section *init_section;
1168 unsigned char *pinit;
1169 int sym_index;
1171 /* XXX: add an object file to do that */
1172 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1173 *ptr = 0;
1174 add_elf_sym(symtab_section, 0, 0,
1175 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1176 bounds_section->sh_num, "__bounds_start");
1177 /* add bound check code */
1178 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "bcheck.o");
1179 tcc_add_file(s1, buf);
1180 #ifdef TCC_TARGET_I386
1181 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1182 /* add 'call __bound_init()' in .init section */
1183 init_section = find_section(s1, ".init");
1184 pinit = section_ptr_add(init_section, 5);
1185 pinit[0] = 0xe8;
1186 put32(pinit + 1, -4);
1187 sym_index = find_elf_sym(symtab_section, "__bound_init");
1188 put_elf_reloc(symtab_section, init_section,
1189 init_section->data_offset - 4, R_386_PC32, sym_index);
1191 #endif
1193 #endif
1194 /* add libc */
1195 if (!s1->nostdlib) {
1196 tcc_add_library(s1, "c");
1198 #ifdef CONFIG_USE_LIBGCC
1199 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1200 #else
1201 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a");
1202 tcc_add_file(s1, buf);
1203 #endif
1205 /* add crt end if not memory output */
1206 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1207 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1211 /* add various standard linker symbols (must be done after the
1212 sections are filled (for example after allocating common
1213 symbols)) */
1214 static void tcc_add_linker_symbols(TCCState *s1)
1216 char buf[1024];
1217 int i;
1218 Section *s;
1220 add_elf_sym(symtab_section,
1221 text_section->data_offset, 0,
1222 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1223 text_section->sh_num, "_etext");
1224 add_elf_sym(symtab_section,
1225 data_section->data_offset, 0,
1226 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1227 data_section->sh_num, "_edata");
1228 add_elf_sym(symtab_section,
1229 bss_section->data_offset, 0,
1230 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1231 bss_section->sh_num, "_end");
1232 /* horrible new standard ldscript defines */
1233 add_init_array_defines(s1, ".preinit_array");
1234 add_init_array_defines(s1, ".init_array");
1235 add_init_array_defines(s1, ".fini_array");
1237 /* add start and stop symbols for sections whose name can be
1238 expressed in C */
1239 for(i = 1; i < s1->nb_sections; i++) {
1240 s = s1->sections[i];
1241 if (s->sh_type == SHT_PROGBITS &&
1242 (s->sh_flags & SHF_ALLOC)) {
1243 const char *p;
1244 int ch;
1246 /* check if section name can be expressed in C */
1247 p = s->name;
1248 for(;;) {
1249 ch = *p;
1250 if (!ch)
1251 break;
1252 if (!isid(ch) && !isnum(ch))
1253 goto next_sec;
1254 p++;
1256 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1257 add_elf_sym(symtab_section,
1258 0, 0,
1259 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1260 s->sh_num, buf);
1261 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1262 add_elf_sym(symtab_section,
1263 s->data_offset, 0,
1264 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1265 s->sh_num, buf);
1267 next_sec: ;
1271 /* name of ELF interpreter */
1272 #ifdef __FreeBSD__
1273 static char elf_interp[] = "/usr/libexec/ld-elf.so.1";
1274 #else
1275 #ifdef TCC_ARM_EABI
1276 static char elf_interp[] = "/lib/ld-linux.so.3";
1277 #elif defined(TCC_TARGET_X86_64)
1278 static char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1279 #else
1280 static char elf_interp[] = "/lib/ld-linux.so.2";
1281 #endif
1282 #endif
1284 static void tcc_output_binary(TCCState *s1, FILE *f,
1285 const int *section_order)
1287 Section *s;
1288 int i, offset, size;
1290 offset = 0;
1291 for(i=1;i<s1->nb_sections;i++) {
1292 s = s1->sections[section_order[i]];
1293 if (s->sh_type != SHT_NOBITS &&
1294 (s->sh_flags & SHF_ALLOC)) {
1295 while (offset < s->sh_offset) {
1296 fputc(0, f);
1297 offset++;
1299 size = s->sh_size;
1300 fwrite(s->data, 1, size, f);
1301 offset += size;
1306 /* output an ELF file */
1307 /* XXX: suppress unneeded sections */
1308 int elf_output_file(TCCState *s1, const char *filename)
1310 ElfW(Ehdr) ehdr;
1311 FILE *f;
1312 int fd, mode, ret;
1313 int *section_order;
1314 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1315 unsigned long addr;
1316 Section *strsec, *s;
1317 ElfW(Shdr) shdr, *sh;
1318 ElfW(Phdr) *phdr, *ph;
1319 Section *interp, *dynamic, *dynstr;
1320 unsigned long saved_dynamic_data_offset;
1321 ElfW(Sym) *sym;
1322 int type, file_type;
1323 unsigned long rel_addr, rel_size;
1325 file_type = s1->output_type;
1326 s1->nb_errors = 0;
1328 if (file_type != TCC_OUTPUT_OBJ) {
1329 tcc_add_runtime(s1);
1332 phdr = NULL;
1333 section_order = NULL;
1334 interp = NULL;
1335 dynamic = NULL;
1336 dynstr = NULL; /* avoid warning */
1337 saved_dynamic_data_offset = 0; /* avoid warning */
1339 if (file_type != TCC_OUTPUT_OBJ) {
1340 relocate_common_syms();
1342 tcc_add_linker_symbols(s1);
1344 if (!s1->static_link) {
1345 const char *name;
1346 int sym_index, index;
1347 ElfW(Sym) *esym, *sym_end;
1349 if (file_type == TCC_OUTPUT_EXE) {
1350 char *ptr;
1351 /* add interpreter section only if executable */
1352 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1353 interp->sh_addralign = 1;
1354 ptr = section_ptr_add(interp, sizeof(elf_interp));
1355 strcpy(ptr, elf_interp);
1358 /* add dynamic symbol table */
1359 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1360 ".dynstr",
1361 ".hash", SHF_ALLOC);
1362 dynstr = s1->dynsym->link;
1364 /* add dynamic section */
1365 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1366 SHF_ALLOC | SHF_WRITE);
1367 dynamic->link = dynstr;
1368 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1370 /* add PLT */
1371 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1372 SHF_ALLOC | SHF_EXECINSTR);
1373 s1->plt->sh_entsize = 4;
1375 build_got(s1);
1377 /* scan for undefined symbols and see if they are in the
1378 dynamic symbols. If a symbol STT_FUNC is found, then we
1379 add it in the PLT. If a symbol STT_OBJECT is found, we
1380 add it in the .bss section with a suitable relocation */
1381 sym_end = (ElfW(Sym) *)(symtab_section->data +
1382 symtab_section->data_offset);
1383 if (file_type == TCC_OUTPUT_EXE) {
1384 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1385 sym < sym_end;
1386 sym++) {
1387 if (sym->st_shndx == SHN_UNDEF) {
1388 name = symtab_section->link->data + sym->st_name;
1389 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1390 if (sym_index) {
1391 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1392 type = ELFW(ST_TYPE)(esym->st_info);
1393 if (type == STT_FUNC) {
1394 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1395 esym->st_info,
1396 sym - (ElfW(Sym) *)symtab_section->data);
1397 } else if (type == STT_OBJECT) {
1398 unsigned long offset;
1399 offset = bss_section->data_offset;
1400 /* XXX: which alignment ? */
1401 offset = (offset + 16 - 1) & -16;
1402 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1403 esym->st_info, 0,
1404 bss_section->sh_num, name);
1405 put_elf_reloc(s1->dynsym, bss_section,
1406 offset, R_COPY, index);
1407 offset += esym->st_size;
1408 bss_section->data_offset = offset;
1410 } else {
1411 /* STB_WEAK undefined symbols are accepted */
1412 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1413 it */
1414 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1415 !strcmp(name, "_fp_hw")) {
1416 } else {
1417 error_noabort("undefined symbol '%s'", name);
1420 } else if (s1->rdynamic &&
1421 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1422 /* if -rdynamic option, then export all non
1423 local symbols */
1424 name = symtab_section->link->data + sym->st_name;
1425 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1426 sym->st_info, 0,
1427 sym->st_shndx, name);
1431 if (s1->nb_errors)
1432 goto fail;
1434 /* now look at unresolved dynamic symbols and export
1435 corresponding symbol */
1436 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1437 s1->dynsymtab_section->data_offset);
1438 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1439 esym < sym_end;
1440 esym++) {
1441 if (esym->st_shndx == SHN_UNDEF) {
1442 name = s1->dynsymtab_section->link->data + esym->st_name;
1443 sym_index = find_elf_sym(symtab_section, name);
1444 if (sym_index) {
1445 /* XXX: avoid adding a symbol if already
1446 present because of -rdynamic ? */
1447 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1448 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1449 sym->st_info, 0,
1450 sym->st_shndx, name);
1451 } else {
1452 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1453 /* weak symbols can stay undefined */
1454 } else {
1455 warning("undefined dynamic symbol '%s'", name);
1460 } else {
1461 int nb_syms;
1462 /* shared library case : we simply export all the global symbols */
1463 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1464 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1465 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1466 sym < sym_end;
1467 sym++) {
1468 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1469 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1470 if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
1471 sym->st_shndx == SHN_UNDEF) {
1472 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1473 sym->st_info,
1474 sym - (ElfW(Sym) *)symtab_section->data);
1476 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1477 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1478 sym->st_info,
1479 sym - (ElfW(Sym) *)symtab_section->data);
1481 else
1482 #endif
1484 name = symtab_section->link->data + sym->st_name;
1485 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1486 sym->st_info, 0,
1487 sym->st_shndx, name);
1488 s1->symtab_to_dynsym[sym -
1489 (ElfW(Sym) *)symtab_section->data] =
1490 index;
1496 build_got_entries(s1);
1498 /* add a list of needed dlls */
1499 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1500 DLLReference *dllref = s1->loaded_dlls[i];
1501 if (dllref->level == 0)
1502 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1504 /* XXX: currently, since we do not handle PIC code, we
1505 must relocate the readonly segments */
1506 if (file_type == TCC_OUTPUT_DLL) {
1507 if (s1->soname)
1508 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1509 put_dt(dynamic, DT_TEXTREL, 0);
1512 /* add necessary space for other entries */
1513 saved_dynamic_data_offset = dynamic->data_offset;
1514 dynamic->data_offset += sizeof(ElfW(Dyn)) * 9;
1515 } else {
1516 /* still need to build got entries in case of static link */
1517 build_got_entries(s1);
1521 memset(&ehdr, 0, sizeof(ehdr));
1523 /* we add a section for symbols */
1524 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1525 put_elf_str(strsec, "");
1527 /* compute number of sections */
1528 shnum = s1->nb_sections;
1530 /* this array is used to reorder sections in the output file */
1531 section_order = tcc_malloc(sizeof(int) * shnum);
1532 section_order[0] = 0;
1533 sh_order_index = 1;
1535 /* compute number of program headers */
1536 switch(file_type) {
1537 default:
1538 case TCC_OUTPUT_OBJ:
1539 phnum = 0;
1540 break;
1541 case TCC_OUTPUT_EXE:
1542 if (!s1->static_link)
1543 phnum = 4;
1544 else
1545 phnum = 2;
1546 break;
1547 case TCC_OUTPUT_DLL:
1548 phnum = 3;
1549 break;
1552 /* allocate strings for section names and decide if an unallocated
1553 section should be output */
1554 /* NOTE: the strsec section comes last, so its size is also
1555 correct ! */
1556 for(i = 1; i < s1->nb_sections; i++) {
1557 s = s1->sections[i];
1558 s->sh_name = put_elf_str(strsec, s->name);
1559 #if 0 //gr
1560 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1561 s->sh_flags,
1562 s->sh_type,
1563 s->sh_info,
1564 s->name,
1565 s->reloc ? s->reloc->name : "n"
1567 #endif
1568 /* when generating a DLL, we include relocations but we may
1569 patch them */
1570 if (file_type == TCC_OUTPUT_DLL &&
1571 s->sh_type == SHT_RELX &&
1572 !(s->sh_flags & SHF_ALLOC)) {
1573 /* //gr: avoid bogus relocs for empty (debug) sections */
1574 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1575 prepare_dynamic_rel(s1, s);
1576 else if (do_debug)
1577 s->sh_size = s->data_offset;
1578 } else if (do_debug ||
1579 file_type == TCC_OUTPUT_OBJ ||
1580 (s->sh_flags & SHF_ALLOC) ||
1581 i == (s1->nb_sections - 1)) {
1582 /* we output all sections if debug or object file */
1583 s->sh_size = s->data_offset;
1587 /* allocate program segment headers */
1588 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1590 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1591 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1592 } else {
1593 file_offset = 0;
1595 if (phnum > 0) {
1596 /* compute section to program header mapping */
1597 if (s1->has_text_addr) {
1598 int a_offset, p_offset;
1599 addr = s1->text_addr;
1600 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1601 ELF_PAGE_SIZE */
1602 a_offset = addr & (ELF_PAGE_SIZE - 1);
1603 p_offset = file_offset & (ELF_PAGE_SIZE - 1);
1604 if (a_offset < p_offset)
1605 a_offset += ELF_PAGE_SIZE;
1606 file_offset += (a_offset - p_offset);
1607 } else {
1608 if (file_type == TCC_OUTPUT_DLL)
1609 addr = 0;
1610 else
1611 addr = ELF_START_ADDR;
1612 /* compute address after headers */
1613 addr += (file_offset & (ELF_PAGE_SIZE - 1));
1616 /* dynamic relocation table information, for .dynamic section */
1617 rel_size = 0;
1618 rel_addr = 0;
1620 /* leave one program header for the program interpreter */
1621 ph = &phdr[0];
1622 if (interp)
1623 ph++;
1625 for(j = 0; j < 2; j++) {
1626 ph->p_type = PT_LOAD;
1627 if (j == 0)
1628 ph->p_flags = PF_R | PF_X;
1629 else
1630 ph->p_flags = PF_R | PF_W;
1631 ph->p_align = ELF_PAGE_SIZE;
1633 /* we do the following ordering: interp, symbol tables,
1634 relocations, progbits, nobits */
1635 /* XXX: do faster and simpler sorting */
1636 for(k = 0; k < 5; k++) {
1637 for(i = 1; i < s1->nb_sections; i++) {
1638 s = s1->sections[i];
1639 /* compute if section should be included */
1640 if (j == 0) {
1641 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1642 SHF_ALLOC)
1643 continue;
1644 } else {
1645 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1646 (SHF_ALLOC | SHF_WRITE))
1647 continue;
1649 if (s == interp) {
1650 if (k != 0)
1651 continue;
1652 } else if (s->sh_type == SHT_DYNSYM ||
1653 s->sh_type == SHT_STRTAB ||
1654 s->sh_type == SHT_HASH) {
1655 if (k != 1)
1656 continue;
1657 } else if (s->sh_type == SHT_RELX) {
1658 if (k != 2)
1659 continue;
1660 } else if (s->sh_type == SHT_NOBITS) {
1661 if (k != 4)
1662 continue;
1663 } else {
1664 if (k != 3)
1665 continue;
1667 section_order[sh_order_index++] = i;
1669 /* section matches: we align it and add its size */
1670 tmp = addr;
1671 addr = (addr + s->sh_addralign - 1) &
1672 ~(s->sh_addralign - 1);
1673 file_offset += addr - tmp;
1674 s->sh_offset = file_offset;
1675 s->sh_addr = addr;
1677 /* update program header infos */
1678 if (ph->p_offset == 0) {
1679 ph->p_offset = file_offset;
1680 ph->p_vaddr = addr;
1681 ph->p_paddr = ph->p_vaddr;
1683 /* update dynamic relocation infos */
1684 if (s->sh_type == SHT_RELX) {
1685 if (rel_size == 0)
1686 rel_addr = addr;
1687 rel_size += s->sh_size;
1689 addr += s->sh_size;
1690 if (s->sh_type != SHT_NOBITS)
1691 file_offset += s->sh_size;
1694 ph->p_filesz = file_offset - ph->p_offset;
1695 ph->p_memsz = addr - ph->p_vaddr;
1696 ph++;
1697 if (j == 0) {
1698 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1699 /* if in the middle of a page, we duplicate the page in
1700 memory so that one copy is RX and the other is RW */
1701 if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
1702 addr += ELF_PAGE_SIZE;
1703 } else {
1704 addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);
1705 file_offset = (file_offset + ELF_PAGE_SIZE - 1) &
1706 ~(ELF_PAGE_SIZE - 1);
1711 /* if interpreter, then add corresponing program header */
1712 if (interp) {
1713 ph = &phdr[0];
1715 ph->p_type = PT_INTERP;
1716 ph->p_offset = interp->sh_offset;
1717 ph->p_vaddr = interp->sh_addr;
1718 ph->p_paddr = ph->p_vaddr;
1719 ph->p_filesz = interp->sh_size;
1720 ph->p_memsz = interp->sh_size;
1721 ph->p_flags = PF_R;
1722 ph->p_align = interp->sh_addralign;
1725 /* if dynamic section, then add corresponing program header */
1726 if (dynamic) {
1727 ElfW(Sym) *sym_end;
1729 ph = &phdr[phnum - 1];
1731 ph->p_type = PT_DYNAMIC;
1732 ph->p_offset = dynamic->sh_offset;
1733 ph->p_vaddr = dynamic->sh_addr;
1734 ph->p_paddr = ph->p_vaddr;
1735 ph->p_filesz = dynamic->sh_size;
1736 ph->p_memsz = dynamic->sh_size;
1737 ph->p_flags = PF_R | PF_W;
1738 ph->p_align = dynamic->sh_addralign;
1740 /* put GOT dynamic section address */
1741 put32(s1->got->data, dynamic->sh_addr);
1743 /* relocate the PLT */
1744 if (file_type == TCC_OUTPUT_EXE
1745 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1746 || file_type == TCC_OUTPUT_DLL
1747 #endif
1749 uint8_t *p, *p_end;
1751 p = s1->plt->data;
1752 p_end = p + s1->plt->data_offset;
1753 if (p < p_end) {
1754 #if defined(TCC_TARGET_I386)
1755 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1756 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1757 p += 16;
1758 while (p < p_end) {
1759 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1760 p += 16;
1762 #elif defined(TCC_TARGET_X86_64)
1763 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1764 put32(p + 2, get32(p + 2) + x);
1765 put32(p + 8, get32(p + 8) + x - 6);
1766 p += 16;
1767 while (p < p_end) {
1768 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1769 p += 16;
1771 #elif defined(TCC_TARGET_ARM)
1772 int x;
1773 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1774 p +=16;
1775 while (p < p_end) {
1776 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1777 p += 16;
1779 #elif defined(TCC_TARGET_C67)
1780 /* XXX: TODO */
1781 #else
1782 #error unsupported CPU
1783 #endif
1787 /* relocate symbols in .dynsym */
1788 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1789 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1790 sym < sym_end;
1791 sym++) {
1792 if (sym->st_shndx == SHN_UNDEF) {
1793 /* relocate to the PLT if the symbol corresponds
1794 to a PLT entry */
1795 if (sym->st_value)
1796 sym->st_value += s1->plt->sh_addr;
1797 } else if (sym->st_shndx < SHN_LORESERVE) {
1798 /* do symbol relocation */
1799 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1803 /* put dynamic section entries */
1804 dynamic->data_offset = saved_dynamic_data_offset;
1805 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1806 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1807 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1808 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1809 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1810 #ifdef TCC_TARGET_X86_64
1811 put_dt(dynamic, DT_RELA, rel_addr);
1812 put_dt(dynamic, DT_RELASZ, rel_size);
1813 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1814 #else
1815 put_dt(dynamic, DT_REL, rel_addr);
1816 put_dt(dynamic, DT_RELSZ, rel_size);
1817 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1818 #endif
1819 if (do_debug)
1820 put_dt(dynamic, DT_DEBUG, 0);
1821 put_dt(dynamic, DT_NULL, 0);
1824 ehdr.e_phentsize = sizeof(ElfW(Phdr));
1825 ehdr.e_phnum = phnum;
1826 ehdr.e_phoff = sizeof(ElfW(Ehdr));
1829 /* all other sections come after */
1830 for(i = 1; i < s1->nb_sections; i++) {
1831 s = s1->sections[i];
1832 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1833 continue;
1834 section_order[sh_order_index++] = i;
1836 file_offset = (file_offset + s->sh_addralign - 1) &
1837 ~(s->sh_addralign - 1);
1838 s->sh_offset = file_offset;
1839 if (s->sh_type != SHT_NOBITS)
1840 file_offset += s->sh_size;
1843 /* if building executable or DLL, then relocate each section
1844 except the GOT which is already relocated */
1845 if (file_type != TCC_OUTPUT_OBJ) {
1846 relocate_syms(s1, 0);
1848 if (s1->nb_errors != 0) {
1849 fail:
1850 ret = -1;
1851 goto the_end;
1854 /* relocate sections */
1855 /* XXX: ignore sections with allocated relocations ? */
1856 for(i = 1; i < s1->nb_sections; i++) {
1857 s = s1->sections[i];
1858 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
1859 relocate_section(s1, s);
1862 /* relocate relocation entries if the relocation tables are
1863 allocated in the executable */
1864 for(i = 1; i < s1->nb_sections; i++) {
1865 s = s1->sections[i];
1866 if ((s->sh_flags & SHF_ALLOC) &&
1867 s->sh_type == SHT_RELX) {
1868 relocate_rel(s1, s);
1872 /* get entry point address */
1873 if (file_type == TCC_OUTPUT_EXE)
1874 ehdr.e_entry = (unsigned long)tcc_get_symbol_err(s1, "_start");
1875 else
1876 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
1879 /* write elf file */
1880 if (file_type == TCC_OUTPUT_OBJ)
1881 mode = 0666;
1882 else
1883 mode = 0777;
1884 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
1885 if (fd < 0) {
1886 error_noabort("could not write '%s'", filename);
1887 goto fail;
1889 f = fdopen(fd, "wb");
1890 if (verbose)
1891 printf("<- %s\n", filename);
1893 #ifdef TCC_TARGET_COFF
1894 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
1895 tcc_output_coff(s1, f);
1896 } else
1897 #endif
1898 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1899 sort_syms(s1, symtab_section);
1901 /* align to 4 */
1902 file_offset = (file_offset + 3) & -4;
1904 /* fill header */
1905 ehdr.e_ident[0] = ELFMAG0;
1906 ehdr.e_ident[1] = ELFMAG1;
1907 ehdr.e_ident[2] = ELFMAG2;
1908 ehdr.e_ident[3] = ELFMAG3;
1909 ehdr.e_ident[4] = TCC_ELFCLASS;
1910 ehdr.e_ident[5] = ELFDATA2LSB;
1911 ehdr.e_ident[6] = EV_CURRENT;
1912 #ifdef __FreeBSD__
1913 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
1914 #endif
1915 #ifdef TCC_TARGET_ARM
1916 #ifdef TCC_ARM_EABI
1917 ehdr.e_ident[EI_OSABI] = 0;
1918 ehdr.e_flags = 4 << 24;
1919 #else
1920 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
1921 #endif
1922 #endif
1923 switch(file_type) {
1924 default:
1925 case TCC_OUTPUT_EXE:
1926 ehdr.e_type = ET_EXEC;
1927 break;
1928 case TCC_OUTPUT_DLL:
1929 ehdr.e_type = ET_DYN;
1930 break;
1931 case TCC_OUTPUT_OBJ:
1932 ehdr.e_type = ET_REL;
1933 break;
1935 ehdr.e_machine = EM_TCC_TARGET;
1936 ehdr.e_version = EV_CURRENT;
1937 ehdr.e_shoff = file_offset;
1938 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
1939 ehdr.e_shentsize = sizeof(ElfW(Shdr));
1940 ehdr.e_shnum = shnum;
1941 ehdr.e_shstrndx = shnum - 1;
1943 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
1944 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
1945 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1947 for(i=1;i<s1->nb_sections;i++) {
1948 s = s1->sections[section_order[i]];
1949 if (s->sh_type != SHT_NOBITS) {
1950 while (offset < s->sh_offset) {
1951 fputc(0, f);
1952 offset++;
1954 size = s->sh_size;
1955 fwrite(s->data, 1, size, f);
1956 offset += size;
1960 /* output section headers */
1961 while (offset < ehdr.e_shoff) {
1962 fputc(0, f);
1963 offset++;
1966 for(i=0;i<s1->nb_sections;i++) {
1967 sh = &shdr;
1968 memset(sh, 0, sizeof(ElfW(Shdr)));
1969 s = s1->sections[i];
1970 if (s) {
1971 sh->sh_name = s->sh_name;
1972 sh->sh_type = s->sh_type;
1973 sh->sh_flags = s->sh_flags;
1974 sh->sh_entsize = s->sh_entsize;
1975 sh->sh_info = s->sh_info;
1976 if (s->link)
1977 sh->sh_link = s->link->sh_num;
1978 sh->sh_addralign = s->sh_addralign;
1979 sh->sh_addr = s->sh_addr;
1980 sh->sh_offset = s->sh_offset;
1981 sh->sh_size = s->sh_size;
1983 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
1985 } else {
1986 tcc_output_binary(s1, f, section_order);
1988 fclose(f);
1990 ret = 0;
1991 the_end:
1992 tcc_free(s1->symtab_to_dynsym);
1993 tcc_free(section_order);
1994 tcc_free(phdr);
1995 tcc_free(s1->got_offsets);
1996 return ret;
1999 int tcc_output_file(TCCState *s, const char *filename)
2001 int ret;
2002 #ifdef TCC_TARGET_PE
2003 if (s->output_type != TCC_OUTPUT_OBJ) {
2004 ret = pe_output_file(s, filename);
2005 } else
2006 #endif
2008 ret = elf_output_file(s, filename);
2010 return ret;
2013 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2015 void *data;
2017 data = tcc_malloc(size);
2018 lseek(fd, file_offset, SEEK_SET);
2019 read(fd, data, size);
2020 return data;
2023 typedef struct SectionMergeInfo {
2024 Section *s; /* corresponding existing section */
2025 unsigned long offset; /* offset of the new section in the existing section */
2026 uint8_t new_section; /* true if section 's' was added */
2027 uint8_t link_once; /* true if link once section */
2028 } SectionMergeInfo;
2030 /* load an object file and merge it with current files */
2031 /* XXX: handle correctly stab (debug) info */
2032 static int tcc_load_object_file(TCCState *s1,
2033 int fd, unsigned long file_offset)
2035 ElfW(Ehdr) ehdr;
2036 ElfW(Shdr) *shdr, *sh;
2037 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2038 unsigned char *strsec, *strtab;
2039 int *old_to_new_syms;
2040 char *sh_name, *name;
2041 SectionMergeInfo *sm_table, *sm;
2042 ElfW(Sym) *sym, *symtab;
2043 ElfW_Rel *rel, *rel_end;
2044 Section *s;
2046 int stab_index;
2047 int stabstr_index;
2049 stab_index = stabstr_index = 0;
2051 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2052 goto fail1;
2053 if (ehdr.e_ident[0] != ELFMAG0 ||
2054 ehdr.e_ident[1] != ELFMAG1 ||
2055 ehdr.e_ident[2] != ELFMAG2 ||
2056 ehdr.e_ident[3] != ELFMAG3)
2057 goto fail1;
2058 /* test if object file */
2059 if (ehdr.e_type != ET_REL)
2060 goto fail1;
2061 /* test CPU specific stuff */
2062 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2063 ehdr.e_machine != EM_TCC_TARGET) {
2064 fail1:
2065 error_noabort("invalid object file");
2066 return -1;
2068 /* read sections */
2069 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2070 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2071 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2073 /* load section names */
2074 sh = &shdr[ehdr.e_shstrndx];
2075 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2077 /* load symtab and strtab */
2078 old_to_new_syms = NULL;
2079 symtab = NULL;
2080 strtab = NULL;
2081 nb_syms = 0;
2082 for(i = 1; i < ehdr.e_shnum; i++) {
2083 sh = &shdr[i];
2084 if (sh->sh_type == SHT_SYMTAB) {
2085 if (symtab) {
2086 error_noabort("object must contain only one symtab");
2087 fail:
2088 ret = -1;
2089 goto the_end;
2091 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2092 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2093 sm_table[i].s = symtab_section;
2095 /* now load strtab */
2096 sh = &shdr[sh->sh_link];
2097 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2101 /* now examine each section and try to merge its content with the
2102 ones in memory */
2103 for(i = 1; i < ehdr.e_shnum; i++) {
2104 /* no need to examine section name strtab */
2105 if (i == ehdr.e_shstrndx)
2106 continue;
2107 sh = &shdr[i];
2108 sh_name = strsec + sh->sh_name;
2109 /* ignore sections types we do not handle */
2110 if (sh->sh_type != SHT_PROGBITS &&
2111 sh->sh_type != SHT_RELX &&
2112 #ifdef TCC_ARM_EABI
2113 sh->sh_type != SHT_ARM_EXIDX &&
2114 #endif
2115 sh->sh_type != SHT_NOBITS &&
2116 strcmp(sh_name, ".stabstr")
2118 continue;
2119 if (sh->sh_addralign < 1)
2120 sh->sh_addralign = 1;
2121 /* find corresponding section, if any */
2122 for(j = 1; j < s1->nb_sections;j++) {
2123 s = s1->sections[j];
2124 if (!strcmp(s->name, sh_name)) {
2125 if (!strncmp(sh_name, ".gnu.linkonce",
2126 sizeof(".gnu.linkonce") - 1)) {
2127 /* if a 'linkonce' section is already present, we
2128 do not add it again. It is a little tricky as
2129 symbols can still be defined in
2130 it. */
2131 sm_table[i].link_once = 1;
2132 goto next;
2133 } else {
2134 goto found;
2138 /* not found: create new section */
2139 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2140 /* take as much info as possible from the section. sh_link and
2141 sh_info will be updated later */
2142 s->sh_addralign = sh->sh_addralign;
2143 s->sh_entsize = sh->sh_entsize;
2144 sm_table[i].new_section = 1;
2145 found:
2146 if (sh->sh_type != s->sh_type) {
2147 error_noabort("invalid section type");
2148 goto fail;
2151 /* align start of section */
2152 offset = s->data_offset;
2154 if (0 == strcmp(sh_name, ".stab")) {
2155 stab_index = i;
2156 goto no_align;
2158 if (0 == strcmp(sh_name, ".stabstr")) {
2159 stabstr_index = i;
2160 goto no_align;
2163 size = sh->sh_addralign - 1;
2164 offset = (offset + size) & ~size;
2165 if (sh->sh_addralign > s->sh_addralign)
2166 s->sh_addralign = sh->sh_addralign;
2167 s->data_offset = offset;
2168 no_align:
2169 sm_table[i].offset = offset;
2170 sm_table[i].s = s;
2171 /* concatenate sections */
2172 size = sh->sh_size;
2173 if (sh->sh_type != SHT_NOBITS) {
2174 unsigned char *ptr;
2175 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2176 ptr = section_ptr_add(s, size);
2177 read(fd, ptr, size);
2178 } else {
2179 s->data_offset += size;
2181 next: ;
2184 /* //gr relocate stab strings */
2185 if (stab_index && stabstr_index) {
2186 Stab_Sym *a, *b;
2187 unsigned o;
2188 s = sm_table[stab_index].s;
2189 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2190 b = (Stab_Sym *)(s->data + s->data_offset);
2191 o = sm_table[stabstr_index].offset;
2192 while (a < b)
2193 a->n_strx += o, a++;
2196 /* second short pass to update sh_link and sh_info fields of new
2197 sections */
2198 for(i = 1; i < ehdr.e_shnum; i++) {
2199 s = sm_table[i].s;
2200 if (!s || !sm_table[i].new_section)
2201 continue;
2202 sh = &shdr[i];
2203 if (sh->sh_link > 0)
2204 s->link = sm_table[sh->sh_link].s;
2205 if (sh->sh_type == SHT_RELX) {
2206 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2207 /* update backward link */
2208 s1->sections[s->sh_info]->reloc = s;
2211 sm = sm_table;
2213 /* resolve symbols */
2214 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2216 sym = symtab + 1;
2217 for(i = 1; i < nb_syms; i++, sym++) {
2218 if (sym->st_shndx != SHN_UNDEF &&
2219 sym->st_shndx < SHN_LORESERVE) {
2220 sm = &sm_table[sym->st_shndx];
2221 if (sm->link_once) {
2222 /* if a symbol is in a link once section, we use the
2223 already defined symbol. It is very important to get
2224 correct relocations */
2225 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2226 name = strtab + sym->st_name;
2227 sym_index = find_elf_sym(symtab_section, name);
2228 if (sym_index)
2229 old_to_new_syms[i] = sym_index;
2231 continue;
2233 /* if no corresponding section added, no need to add symbol */
2234 if (!sm->s)
2235 continue;
2236 /* convert section number */
2237 sym->st_shndx = sm->s->sh_num;
2238 /* offset value */
2239 sym->st_value += sm->offset;
2241 /* add symbol */
2242 name = strtab + sym->st_name;
2243 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2244 sym->st_info, sym->st_other,
2245 sym->st_shndx, name);
2246 old_to_new_syms[i] = sym_index;
2249 /* third pass to patch relocation entries */
2250 for(i = 1; i < ehdr.e_shnum; i++) {
2251 s = sm_table[i].s;
2252 if (!s)
2253 continue;
2254 sh = &shdr[i];
2255 offset = sm_table[i].offset;
2256 switch(s->sh_type) {
2257 case SHT_RELX:
2258 /* take relocation offset information */
2259 offseti = sm_table[sh->sh_info].offset;
2260 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2261 for(rel = (ElfW_Rel *)(s->data + offset);
2262 rel < rel_end;
2263 rel++) {
2264 int type;
2265 unsigned sym_index;
2266 /* convert symbol index */
2267 type = ELFW(R_TYPE)(rel->r_info);
2268 sym_index = ELFW(R_SYM)(rel->r_info);
2269 /* NOTE: only one symtab assumed */
2270 if (sym_index >= nb_syms)
2271 goto invalid_reloc;
2272 sym_index = old_to_new_syms[sym_index];
2273 /* ignore link_once in rel section. */
2274 if (!sym_index && !sm->link_once) {
2275 invalid_reloc:
2276 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2277 i, strsec + sh->sh_name, rel->r_offset);
2278 goto fail;
2280 rel->r_info = ELFW(R_INFO)(sym_index, type);
2281 /* offset the relocation offset */
2282 rel->r_offset += offseti;
2284 break;
2285 default:
2286 break;
2290 ret = 0;
2291 the_end:
2292 tcc_free(symtab);
2293 tcc_free(strtab);
2294 tcc_free(old_to_new_syms);
2295 tcc_free(sm_table);
2296 tcc_free(strsec);
2297 tcc_free(shdr);
2298 return ret;
2301 #define ARMAG "!<arch>\012" /* For COFF and a.out archives */
2303 typedef struct ArchiveHeader {
2304 char ar_name[16]; /* name of this member */
2305 char ar_date[12]; /* file mtime */
2306 char ar_uid[6]; /* owner uid; printed as decimal */
2307 char ar_gid[6]; /* owner gid; printed as decimal */
2308 char ar_mode[8]; /* file mode, printed as octal */
2309 char ar_size[10]; /* file size, printed as decimal */
2310 char ar_fmag[2]; /* should contain ARFMAG */
2311 } ArchiveHeader;
2313 static int get_be32(const uint8_t *b)
2315 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2318 /* load only the objects which resolve undefined symbols */
2319 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2321 int i, bound, nsyms, sym_index, off, ret;
2322 uint8_t *data;
2323 const char *ar_names, *p;
2324 const uint8_t *ar_index;
2325 ElfW(Sym) *sym;
2327 data = tcc_malloc(size);
2328 if (read(fd, data, size) != size)
2329 goto fail;
2330 nsyms = get_be32(data);
2331 ar_index = data + 4;
2332 ar_names = ar_index + nsyms * 4;
2334 do {
2335 bound = 0;
2336 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2337 sym_index = find_elf_sym(symtab_section, p);
2338 if(sym_index) {
2339 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2340 if(sym->st_shndx == SHN_UNDEF) {
2341 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2342 #if 0
2343 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2344 #endif
2345 ++bound;
2346 lseek(fd, off, SEEK_SET);
2347 if(tcc_load_object_file(s1, fd, off) < 0) {
2348 fail:
2349 ret = -1;
2350 goto the_end;
2355 } while(bound);
2356 ret = 0;
2357 the_end:
2358 tcc_free(data);
2359 return ret;
2362 /* load a '.a' file */
2363 static int tcc_load_archive(TCCState *s1, int fd)
2365 ArchiveHeader hdr;
2366 char ar_size[11];
2367 char ar_name[17];
2368 char magic[8];
2369 int size, len, i;
2370 unsigned long file_offset;
2372 /* skip magic which was already checked */
2373 read(fd, magic, sizeof(magic));
2375 for(;;) {
2376 len = read(fd, &hdr, sizeof(hdr));
2377 if (len == 0)
2378 break;
2379 if (len != sizeof(hdr)) {
2380 error_noabort("invalid archive");
2381 return -1;
2383 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2384 ar_size[sizeof(hdr.ar_size)] = '\0';
2385 size = strtol(ar_size, NULL, 0);
2386 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2387 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2388 if (ar_name[i] != ' ')
2389 break;
2391 ar_name[i + 1] = '\0';
2392 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2393 file_offset = lseek(fd, 0, SEEK_CUR);
2394 /* align to even */
2395 size = (size + 1) & ~1;
2396 if (!strcmp(ar_name, "/")) {
2397 /* coff symbol table : we handle it */
2398 if(s1->alacarte_link)
2399 return tcc_load_alacarte(s1, fd, size);
2400 } else if (!strcmp(ar_name, "//") ||
2401 !strcmp(ar_name, "__.SYMDEF") ||
2402 !strcmp(ar_name, "__.SYMDEF/") ||
2403 !strcmp(ar_name, "ARFILENAMES/")) {
2404 /* skip symbol table or archive names */
2405 } else {
2406 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2407 return -1;
2409 lseek(fd, file_offset + size, SEEK_SET);
2411 return 0;
2414 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2415 is referenced by the user (so it should be added as DT_NEEDED in
2416 the generated ELF file) */
2417 static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2419 ElfW(Ehdr) ehdr;
2420 ElfW(Shdr) *shdr, *sh, *sh1;
2421 int i, j, nb_syms, nb_dts, sym_bind, ret;
2422 ElfW(Sym) *sym, *dynsym;
2423 ElfW(Dyn) *dt, *dynamic;
2424 unsigned char *dynstr;
2425 const char *name, *soname;
2426 DLLReference *dllref;
2428 read(fd, &ehdr, sizeof(ehdr));
2430 /* test CPU specific stuff */
2431 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2432 ehdr.e_machine != EM_TCC_TARGET) {
2433 error_noabort("bad architecture");
2434 return -1;
2437 /* read sections */
2438 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2440 /* load dynamic section and dynamic symbols */
2441 nb_syms = 0;
2442 nb_dts = 0;
2443 dynamic = NULL;
2444 dynsym = NULL; /* avoid warning */
2445 dynstr = NULL; /* avoid warning */
2446 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2447 switch(sh->sh_type) {
2448 case SHT_DYNAMIC:
2449 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2450 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2451 break;
2452 case SHT_DYNSYM:
2453 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2454 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2455 sh1 = &shdr[sh->sh_link];
2456 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2457 break;
2458 default:
2459 break;
2463 /* compute the real library name */
2464 soname = tcc_basename(filename);
2466 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2467 if (dt->d_tag == DT_SONAME) {
2468 soname = dynstr + dt->d_un.d_val;
2472 /* if the dll is already loaded, do not load it */
2473 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2474 dllref = s1->loaded_dlls[i];
2475 if (!strcmp(soname, dllref->name)) {
2476 /* but update level if needed */
2477 if (level < dllref->level)
2478 dllref->level = level;
2479 ret = 0;
2480 goto the_end;
2484 // printf("loading dll '%s'\n", soname);
2486 /* add the dll and its level */
2487 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2488 dllref->level = level;
2489 strcpy(dllref->name, soname);
2490 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2492 /* add dynamic symbols in dynsym_section */
2493 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2494 sym_bind = ELFW(ST_BIND)(sym->st_info);
2495 if (sym_bind == STB_LOCAL)
2496 continue;
2497 name = dynstr + sym->st_name;
2498 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2499 sym->st_info, sym->st_other, sym->st_shndx, name);
2502 /* load all referenced DLLs */
2503 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2504 switch(dt->d_tag) {
2505 case DT_NEEDED:
2506 name = dynstr + dt->d_un.d_val;
2507 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2508 dllref = s1->loaded_dlls[j];
2509 if (!strcmp(name, dllref->name))
2510 goto already_loaded;
2512 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2513 error_noabort("referenced dll '%s' not found", name);
2514 ret = -1;
2515 goto the_end;
2517 already_loaded:
2518 break;
2521 ret = 0;
2522 the_end:
2523 tcc_free(dynstr);
2524 tcc_free(dynsym);
2525 tcc_free(dynamic);
2526 tcc_free(shdr);
2527 return ret;
2530 #define LD_TOK_NAME 256
2531 #define LD_TOK_EOF (-1)
2533 /* return next ld script token */
2534 static int ld_next(TCCState *s1, char *name, int name_size)
2536 int c;
2537 char *q;
2539 redo:
2540 switch(ch) {
2541 case ' ':
2542 case '\t':
2543 case '\f':
2544 case '\v':
2545 case '\r':
2546 case '\n':
2547 inp();
2548 goto redo;
2549 case '/':
2550 minp();
2551 if (ch == '*') {
2552 file->buf_ptr = parse_comment(file->buf_ptr);
2553 ch = file->buf_ptr[0];
2554 goto redo;
2555 } else {
2556 q = name;
2557 *q++ = '/';
2558 goto parse_name;
2560 break;
2561 /* case 'a' ... 'z': */
2562 case 'a':
2563 case 'b':
2564 case 'c':
2565 case 'd':
2566 case 'e':
2567 case 'f':
2568 case 'g':
2569 case 'h':
2570 case 'i':
2571 case 'j':
2572 case 'k':
2573 case 'l':
2574 case 'm':
2575 case 'n':
2576 case 'o':
2577 case 'p':
2578 case 'q':
2579 case 'r':
2580 case 's':
2581 case 't':
2582 case 'u':
2583 case 'v':
2584 case 'w':
2585 case 'x':
2586 case 'y':
2587 case 'z':
2588 /* case 'A' ... 'z': */
2589 case 'A':
2590 case 'B':
2591 case 'C':
2592 case 'D':
2593 case 'E':
2594 case 'F':
2595 case 'G':
2596 case 'H':
2597 case 'I':
2598 case 'J':
2599 case 'K':
2600 case 'L':
2601 case 'M':
2602 case 'N':
2603 case 'O':
2604 case 'P':
2605 case 'Q':
2606 case 'R':
2607 case 'S':
2608 case 'T':
2609 case 'U':
2610 case 'V':
2611 case 'W':
2612 case 'X':
2613 case 'Y':
2614 case 'Z':
2615 case '_':
2616 case '\\':
2617 case '.':
2618 case '$':
2619 case '~':
2620 q = name;
2621 parse_name:
2622 for(;;) {
2623 if (!((ch >= 'a' && ch <= 'z') ||
2624 (ch >= 'A' && ch <= 'Z') ||
2625 (ch >= '0' && ch <= '9') ||
2626 strchr("/.-_+=$:\\,~", ch)))
2627 break;
2628 if ((q - name) < name_size - 1) {
2629 *q++ = ch;
2631 minp();
2633 *q = '\0';
2634 c = LD_TOK_NAME;
2635 break;
2636 case CH_EOF:
2637 c = LD_TOK_EOF;
2638 break;
2639 default:
2640 c = ch;
2641 inp();
2642 break;
2644 #if 0
2645 printf("tok=%c %d\n", c, c);
2646 if (c == LD_TOK_NAME)
2647 printf(" name=%s\n", name);
2648 #endif
2649 return c;
2652 static int ld_add_file_list(TCCState *s1, int as_needed)
2654 char filename[1024];
2655 int t, ret;
2657 t = ld_next(s1, filename, sizeof(filename));
2658 if (t != '(')
2659 expect("(");
2660 t = ld_next(s1, filename, sizeof(filename));
2661 for(;;) {
2662 if (t == LD_TOK_EOF) {
2663 error_noabort("unexpected end of file");
2664 return -1;
2665 } else if (t == ')') {
2666 break;
2667 } else if (t != LD_TOK_NAME) {
2668 error_noabort("filename expected");
2669 return -1;
2671 if (!strcmp(filename, "AS_NEEDED")) {
2672 ret = ld_add_file_list(s1, 1);
2673 if (ret)
2674 return ret;
2675 } else {
2676 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2677 if (!as_needed)
2678 tcc_add_file(s1, filename);
2680 t = ld_next(s1, filename, sizeof(filename));
2681 if (t == ',') {
2682 t = ld_next(s1, filename, sizeof(filename));
2685 return 0;
2688 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2689 files */
2690 static int tcc_load_ldscript(TCCState *s1)
2692 char cmd[64];
2693 char filename[1024];
2694 int t, ret;
2696 ch = file->buf_ptr[0];
2697 ch = handle_eob();
2698 for(;;) {
2699 t = ld_next(s1, cmd, sizeof(cmd));
2700 if (t == LD_TOK_EOF)
2701 return 0;
2702 else if (t != LD_TOK_NAME)
2703 return -1;
2704 if (!strcmp(cmd, "INPUT") ||
2705 !strcmp(cmd, "GROUP")) {
2706 ret = ld_add_file_list(s1, 0);
2707 if (ret)
2708 return ret;
2709 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2710 !strcmp(cmd, "TARGET")) {
2711 /* ignore some commands */
2712 t = ld_next(s1, cmd, sizeof(cmd));
2713 if (t != '(')
2714 expect("(");
2715 for(;;) {
2716 t = ld_next(s1, filename, sizeof(filename));
2717 if (t == LD_TOK_EOF) {
2718 error_noabort("unexpected end of file");
2719 return -1;
2720 } else if (t == ')') {
2721 break;
2724 } else {
2725 return -1;
2728 return 0;