source: EcnlProtoTool/trunk/tcc-0.9.26/tccelf.c@ 286

Last change on this file since 286 was 279, checked in by coas-nagasima, 7 years ago

ファイルを追加、更新。

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 103.5 KB
Line 
1/*
2 * ELF file handling for TCC
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
5 *
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.
10 *
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.
15 *
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
19 */
20
21#include "tcc.h"
22
23static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
24
25ST_FUNC int put_elf_str(Section *s, const char *sym)
26{
27 int offset, len;
28 char *ptr;
29
30 len = strlen(sym) + 1;
31 offset = s->data_offset;
32 ptr = section_ptr_add(s, len);
33 memcpy(ptr, sym, len);
34 return offset;
35}
36
37/* elf symbol hashing function */
38static unsigned long elf_hash(const unsigned char *name)
39{
40 unsigned long h = 0, g;
41
42 while (*name) {
43 h = (h << 4) + *name++;
44 g = h & 0xf0000000;
45 if (g)
46 h ^= g >> 24;
47 h &= ~g;
48 }
49 return h;
50}
51
52/* rebuild hash table of section s */
53/* NOTE: we do factorize the hash table code to go faster */
54static void rebuild_hash(Section *s, unsigned int nb_buckets)
55{
56 ElfW(Sym) *sym;
57 int *ptr, *hash, nb_syms, sym_index, h;
58 char *strtab;
59
60 strtab = s->link->data;
61 nb_syms = s->data_offset / sizeof(ElfW(Sym));
62
63 s->hash->data_offset = 0;
64 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
65 ptr[0] = nb_buckets;
66 ptr[1] = nb_syms;
67 ptr += 2;
68 hash = ptr;
69 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
70 ptr += nb_buckets + 1;
71
72 sym = (ElfW(Sym) *)s->data + 1;
73 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
74 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
75 h = elf_hash(strtab + sym->st_name) % nb_buckets;
76 *ptr = hash[h];
77 hash[h] = sym_index;
78 } else {
79 *ptr = 0;
80 }
81 ptr++;
82 sym++;
83 }
84}
85
86/* return the symbol number */
87ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
88 int info, int other, int shndx, const char *name)
89{
90 int name_offset, sym_index;
91 int nbuckets, h;
92 ElfW(Sym) *sym;
93 Section *hs;
94
95 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
96 if (name)
97 name_offset = put_elf_str(s->link, name);
98 else
99 name_offset = 0;
100 /* XXX: endianness */
101 sym->st_name = name_offset;
102 sym->st_value = value;
103 sym->st_size = size;
104 sym->st_info = info;
105 sym->st_other = other;
106 sym->st_shndx = shndx;
107 sym_index = sym - (ElfW(Sym) *)s->data;
108 hs = s->hash;
109 if (hs) {
110 int *ptr, *base;
111 ptr = section_ptr_add(hs, sizeof(int));
112 base = (int *)hs->data;
113 /* only add global or weak symbols */
114 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
115 /* add another hashing entry */
116 nbuckets = base[0];
117 h = elf_hash(name) % nbuckets;
118 *ptr = base[2 + h];
119 base[2 + h] = sym_index;
120 base[1]++;
121 /* we resize the hash table */
122 hs->nb_hashed_syms++;
123 if (hs->nb_hashed_syms > 2 * nbuckets) {
124 rebuild_hash(s, 2 * nbuckets);
125 }
126 } else {
127 *ptr = 0;
128 base[1]++;
129 }
130 }
131 return sym_index;
132}
133
134/* find global ELF symbol 'name' and return its index. Return 0 if not
135 found. */
136ST_FUNC int find_elf_sym(Section *s, const char *name)
137{
138 ElfW(Sym) *sym;
139 Section *hs;
140 int nbuckets, sym_index, h;
141 const char *name1;
142
143 hs = s->hash;
144 if (!hs)
145 return 0;
146 nbuckets = ((int *)hs->data)[0];
147 h = elf_hash(name) % nbuckets;
148 sym_index = ((int *)hs->data)[2 + h];
149 while (sym_index != 0) {
150 sym = &((ElfW(Sym) *)s->data)[sym_index];
151 name1 = s->link->data + sym->st_name;
152 if (!strcmp(name, name1))
153 return sym_index;
154 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
155 }
156 return 0;
157}
158
159/* return elf symbol value, signal error if 'err' is nonzero */
160ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
161{
162 int sym_index;
163 ElfW(Sym) *sym;
164
165 sym_index = find_elf_sym(s->symtab, name);
166 sym = &((ElfW(Sym) *)s->symtab->data)[sym_index];
167 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
168 if (err)
169 tcc_error("%s not defined", name);
170 return 0;
171 }
172 return sym->st_value;
173}
174
175/* return elf symbol value */
176LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
177{
178 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 0);
179}
180
181#ifdef TCC_IS_NATIVE
182/* return elf symbol value or error */
183ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
184{
185 return (void*)get_elf_sym_addr(s, name, 1);
186}
187#endif
188
189/* add an elf symbol : check if it is already defined and patch
190 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
191ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
192 int info, int other, int sh_num, const char *name)
193{
194 ElfW(Sym) *esym;
195 int sym_bind, sym_index, sym_type, esym_bind;
196 unsigned char sym_vis, esym_vis, new_vis;
197
198 sym_bind = ELFW(ST_BIND)(info);
199 sym_type = ELFW(ST_TYPE)(info);
200 sym_vis = ELFW(ST_VISIBILITY)(other);
201
202 if (sym_bind != STB_LOCAL) {
203 /* we search global or weak symbols */
204 sym_index = find_elf_sym(s, name);
205 if (!sym_index)
206 goto do_def;
207 esym = &((ElfW(Sym) *)s->data)[sym_index];
208 if (esym->st_shndx != SHN_UNDEF) {
209 esym_bind = ELFW(ST_BIND)(esym->st_info);
210 /* propagate the most constraining visibility */
211 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
212 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
213 if (esym_vis == STV_DEFAULT) {
214 new_vis = sym_vis;
215 } else if (sym_vis == STV_DEFAULT) {
216 new_vis = esym_vis;
217 } else {
218 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
219 }
220 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
221 | new_vis;
222 other = esym->st_other; /* in case we have to patch esym */
223 if (sh_num == SHN_UNDEF) {
224 /* ignore adding of undefined symbol if the
225 corresponding symbol is already defined */
226 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
227 /* global overrides weak, so patch */
228 goto do_patch;
229 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
230 /* weak is ignored if already global */
231 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
232 /* keep first-found weak definition, ignore subsequents */
233 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
234 /* ignore hidden symbols after */
235 } else if (esym->st_shndx == SHN_COMMON
236 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
237 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
238 No idea if this is the correct solution ... */
239 goto do_patch;
240 } else if (s == tcc_state->dynsymtab_section) {
241 /* we accept that two DLL define the same symbol */
242 } else {
243#if 0
244 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
245 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
246#endif
247 tcc_error_noabort("'%s' defined twice", name);
248 }
249 } else {
250 do_patch:
251 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
252 esym->st_shndx = sh_num;
253 new_undef_sym = 1;
254 esym->st_value = value;
255 esym->st_size = size;
256 esym->st_other = other;
257 }
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);
263 }
264 return sym_index;
265}
266
267/* put relocation */
268ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
269 int type, int symbol)
270{
271 char buf[256];
272 Section *sr;
273 ElfW_Rel *rel;
274
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;
286 }
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
293}
294
295/* put stab debug information */
296
297ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
298 unsigned long value)
299{
300 Stab_Sym *sym;
301
302 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
303 if (str) {
304 sym->n_strx = put_elf_str(stabstr_section, str);
305 } else {
306 sym->n_strx = 0;
307 }
308 sym->n_type = type;
309 sym->n_other = other;
310 sym->n_desc = desc;
311 sym->n_value = value;
312}
313
314ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
315 unsigned long value, Section *sec, int sym_index)
316{
317 put_stabs(str, type, other, desc, value);
318 put_elf_reloc(symtab_section, stab_section,
319 stab_section->data_offset - sizeof(unsigned int),
320 R_DATA_32, sym_index);
321}
322
323ST_FUNC void put_stabn(int type, int other, int desc, int value)
324{
325 put_stabs(NULL, type, other, desc, value);
326}
327
328ST_FUNC void put_stabd(int type, int other, int desc)
329{
330 put_stabs(NULL, type, other, desc, 0);
331}
332
333/* In an ELF file symbol table, the local symbols must appear below
334 the global and weak ones. Since TCC cannot sort it while generating
335 the code, we must do it after. All the relocation tables are also
336 modified to take into account the symbol table sorting */
337static void sort_syms(TCCState *s1, Section *s)
338{
339 int *old_to_new_syms;
340 ElfW(Sym) *new_syms;
341 int nb_syms, i;
342 ElfW(Sym) *p, *q;
343 ElfW_Rel *rel, *rel_end;
344 Section *sr;
345 int type, sym_index;
346
347 nb_syms = s->data_offset / sizeof(ElfW(Sym));
348 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
349 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
350
351 /* first pass for local symbols */
352 p = (ElfW(Sym) *)s->data;
353 q = new_syms;
354 for(i = 0; i < nb_syms; i++) {
355 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
356 old_to_new_syms[i] = q - new_syms;
357 *q++ = *p;
358 }
359 p++;
360 }
361 /* save the number of local symbols in section header */
362 s->sh_info = q - new_syms;
363
364 /* then second pass for non local symbols */
365 p = (ElfW(Sym) *)s->data;
366 for(i = 0; i < nb_syms; i++) {
367 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
368 old_to_new_syms[i] = q - new_syms;
369 *q++ = *p;
370 }
371 p++;
372 }
373
374 /* we copy the new symbols to the old */
375 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
376 tcc_free(new_syms);
377
378 /* now we modify all the relocations */
379 for(i = 1; i < s1->nb_sections; i++) {
380 sr = s1->sections[i];
381 if (sr->sh_type == SHT_RELX && sr->link == s) {
382 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
383 for(rel = (ElfW_Rel *)sr->data;
384 rel < rel_end;
385 rel++) {
386 sym_index = ELFW(R_SYM)(rel->r_info);
387 type = ELFW(R_TYPE)(rel->r_info);
388 sym_index = old_to_new_syms[sym_index];
389 rel->r_info = ELFW(R_INFO)(sym_index, type);
390 }
391 }
392 }
393
394 tcc_free(old_to_new_syms);
395}
396
397/* relocate common symbols in the .bss section */
398ST_FUNC void relocate_common_syms(void)
399{
400 ElfW(Sym) *sym, *sym_end;
401 unsigned long offset, align;
402
403 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
404 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
405 sym < sym_end;
406 sym++) {
407 if (sym->st_shndx == SHN_COMMON) {
408 /* align symbol */
409 align = sym->st_value;
410 offset = bss_section->data_offset;
411 offset = (offset + align - 1) & -align;
412 sym->st_value = offset;
413 sym->st_shndx = bss_section->sh_num;
414 offset += sym->st_size;
415 bss_section->data_offset = offset;
416 }
417 }
418}
419
420/* relocate symbol table, resolve undefined symbols if do_resolve is
421 true and output error if undefined symbol. */
422ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
423{
424 ElfW(Sym) *sym, *esym, *sym_end;
425 int sym_bind, sh_num, sym_index;
426 const char *name;
427
428 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
429 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
430 sym < sym_end;
431 sym++) {
432 sh_num = sym->st_shndx;
433 if (sh_num == SHN_UNDEF) {
434 name = strtab_section->data + sym->st_name;
435 if (do_resolve) {
436#if defined TCC_IS_NATIVE && !defined _WIN32
437 void *addr;
438 name = symtab_section->link->data + sym->st_name;
439 addr = resolve_sym(s1, name);
440 if (addr) {
441 sym->st_value = (addr_t)addr;
442 goto found;
443 }
444#endif
445 } else if (s1->dynsym) {
446 /* if dynamic symbol exist, then use it */
447 sym_index = find_elf_sym(s1->dynsym, name);
448 if (sym_index) {
449 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
450 sym->st_value = esym->st_value;
451 goto found;
452 }
453 }
454 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
455 it */
456 if (!strcmp(name, "_fp_hw"))
457 goto found;
458 /* only weak symbols are accepted to be undefined. Their
459 value is zero */
460 sym_bind = ELFW(ST_BIND)(sym->st_info);
461 if (sym_bind == STB_WEAK) {
462 sym->st_value = 0;
463 } else {
464 tcc_error_noabort("undefined symbol '%s'", name);
465 }
466 } else if (sh_num < SHN_LORESERVE) {
467 /* add section base */
468 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
469 }
470 found: ;
471 }
472}
473
474#ifdef TCC_HAS_RUNTIME_PLTGOT
475#ifdef TCC_TARGET_X86_64
476#define JMP_TABLE_ENTRY_SIZE 14
477static addr_t add_jmp_table(TCCState *s1, addr_t val)
478{
479 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
480 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
481 /* jmp *0x0(%rip) */
482 p[0] = 0xff;
483 p[1] = 0x25;
484 *(int *)(p + 2) = 0;
485 *(addr_t *)(p + 6) = val;
486 return (addr_t)p;
487}
488
489static addr_t add_got_table(TCCState *s1, addr_t val)
490{
491 addr_t *p = (addr_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
492 s1->runtime_plt_and_got_offset += sizeof(addr_t);
493 *p = val;
494 return (addr_t)p;
495}
496#elif defined TCC_TARGET_ARM
497#define JMP_TABLE_ENTRY_SIZE 8
498static addr_t add_jmp_table(TCCState *s1, int val)
499{
500 uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
501 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
502 /* ldr pc, [pc, #-4] */
503 p[0] = 0xE51FF004;
504 p[1] = val;
505 return (addr_t)p;
506}
507#endif
508#endif /* def TCC_HAS_RUNTIME_PLTGOT */
509
510/* relocate a given section (CPU dependent) */
511ST_FUNC void relocate_section(TCCState *s1, Section *s)
512{
513 Section *sr;
514 ElfW_Rel *rel, *rel_end, *qrel;
515 ElfW(Sym) *sym;
516 int type, sym_index;
517 unsigned char *ptr;
518 addr_t val, addr;
519#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
520 int esym_index;
521#endif
522
523 sr = s->reloc;
524 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
525 qrel = (ElfW_Rel *)sr->data;
526 for(rel = qrel;
527 rel < rel_end;
528 rel++) {
529 ptr = s->data + rel->r_offset;
530
531 sym_index = ELFW(R_SYM)(rel->r_info);
532 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
533 val = sym->st_value;
534#ifdef TCC_TARGET_X86_64
535 val += rel->r_addend;
536#endif
537 type = ELFW(R_TYPE)(rel->r_info);
538 addr = s->sh_addr + rel->r_offset;
539
540 /* CPU specific */
541 switch(type) {
542#if defined(TCC_TARGET_I386)
543 case R_386_32:
544 if (s1->output_type == TCC_OUTPUT_DLL) {
545 esym_index = s1->symtab_to_dynsym[sym_index];
546 qrel->r_offset = rel->r_offset;
547 if (esym_index) {
548 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
549 qrel++;
550 break;
551 } else {
552 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
553 qrel++;
554 }
555 }
556 *(int *)ptr += val;
557 break;
558 case R_386_PC32:
559 if (s1->output_type == TCC_OUTPUT_DLL) {
560 /* DLL relocation */
561 esym_index = s1->symtab_to_dynsym[sym_index];
562 if (esym_index) {
563 qrel->r_offset = rel->r_offset;
564 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
565 qrel++;
566 break;
567 }
568 }
569 *(int *)ptr += val - addr;
570 break;
571 case R_386_PLT32:
572 *(int *)ptr += val - addr;
573 break;
574 case R_386_GLOB_DAT:
575 case R_386_JMP_SLOT:
576 *(int *)ptr = val;
577 break;
578 case R_386_GOTPC:
579 *(int *)ptr += s1->got->sh_addr - addr;
580 break;
581 case R_386_GOTOFF:
582 *(int *)ptr += val - s1->got->sh_addr;
583 break;
584 case R_386_GOT32:
585 /* we load the got offset */
586 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
587 break;
588 case R_386_16:
589 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
590 output_file:
591 tcc_error("can only produce 16-bit binary files");
592 }
593 *(short *)ptr += val;
594 break;
595 case R_386_PC16:
596 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
597 goto output_file;
598 *(short *)ptr += val - addr;
599 break;
600#elif defined(TCC_TARGET_ARM)
601 case R_ARM_PC24:
602 case R_ARM_CALL:
603 case R_ARM_JUMP24:
604 case R_ARM_PLT32:
605 {
606 int x, is_thumb, is_call, h, blx_avail;
607 x = (*(int *)ptr)&0xffffff;
608 (*(int *)ptr) &= 0xff000000;
609 if (x & 0x800000)
610 x -= 0x1000000;
611 x <<= 2;
612 blx_avail = (TCC_ARM_VERSION >= 5);
613 is_thumb = val & 1;
614 is_call = (type == R_ARM_CALL);
615 x += val - addr;
616 h = x & 2;
617#ifdef TCC_HAS_RUNTIME_PLTGOT
618 if (s1->output_type == TCC_OUTPUT_MEMORY) {
619 if ((x & 3) || x >= 0x2000000 || x < -0x2000000)
620 if (!(x & 3) || !blx_avail || !is_call) {
621 x += add_jmp_table(s1, val) - val; /* add veneer */
622 is_thumb = 0; /* Veneer uses ARM instructions */
623 }
624 }
625#endif
626 if ((x & 3) || x >= 0x2000000 || x < -0x2000000)
627 if (!(x & 3) || !blx_avail || !is_call)
628 tcc_error("can't relocate value at %x",addr);
629 x >>= 2;
630 x &= 0xffffff;
631 /* Only reached if blx is avail and it is a call */
632 if (is_thumb) {
633 x |= h << 24;
634 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
635 }
636 (*(int *)ptr) |= x;
637 }
638 break;
639 /* Since these relocations only concern Thumb-2 and blx instruction was
640 introduced before Thumb-2, we can assume blx is available and not
641 guard its use */
642 case R_ARM_THM_CALL:
643 case R_ARM_THM_JUMP24:
644 {
645 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
646 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
647 Section *plt;
648
649 /* weak reference */
650 if (sym->st_shndx == SHN_UNDEF &&
651 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
652 break;
653
654 /* Get initial offset */
655 hi = (*(uint16_t *)ptr);
656 lo = (*(uint16_t *)(ptr+2));
657 s = (hi >> 10) & 1;
658 j1 = (lo >> 13) & 1;
659 j2 = (lo >> 11) & 1;
660 i1 = (j1 ^ s) ^ 1;
661 i2 = (j2 ^ s) ^ 1;
662 imm10 = hi & 0x3ff;
663 imm11 = lo & 0x7ff;
664 x = (s << 24) | (i1 << 23) | (i2 << 22) |
665 (imm10 << 12) | (imm11 << 1);
666 if (x & 0x01000000)
667 x -= 0x02000000;
668
669 /* Relocation infos */
670 to_thumb = val & 1;
671 plt = s1->plt;
672 to_plt = (val >= plt->sh_addr) &&
673 (val < plt->sh_addr + plt->data_offset);
674 is_call = (type == R_ARM_THM_CALL);
675
676 /* Compute final offset */
677 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
678 x -= 4;
679 x += val - addr;
680 if (!to_thumb && is_call) {
681 blx_bit = 0; /* bl -> blx */
682 x = (x + 3) & -4; /* Compute offset from aligned PC */
683 }
684
685 /* Check that relocation is possible
686 * offset must not be out of range
687 * if target is to be entered in arm mode:
688 - bit 1 must not set
689 - instruction must be a call (bl) or a jump to PLT */
690 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
691 if (to_thumb || (val & 2) || (!is_call && !to_plt))
692 tcc_error("can't relocate value at %x",addr);
693
694 /* Compute and store final offset */
695 s = (x >> 24) & 1;
696 i1 = (x >> 23) & 1;
697 i2 = (x >> 22) & 1;
698 j1 = s ^ (i1 ^ 1);
699 j2 = s ^ (i2 ^ 1);
700 imm10 = (x >> 12) & 0x3ff;
701 imm11 = (x >> 1) & 0x7ff;
702 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
703 (s << 10) | imm10);
704 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
705 (j1 << 13) | blx_bit | (j2 << 11) |
706 imm11);
707 }
708 break;
709 case R_ARM_MOVT_ABS:
710 case R_ARM_MOVW_ABS_NC:
711 {
712 int x, imm4, imm12;
713 if (type == R_ARM_MOVT_ABS)
714 val >>= 16;
715 imm12 = val & 0xfff;
716 imm4 = (val >> 12) & 0xf;
717 x = (imm4 << 16) | imm12;
718 if (type == R_ARM_THM_MOVT_ABS)
719 *(int *)ptr |= x;
720 else
721 *(int *)ptr += x;
722 }
723 break;
724 case R_ARM_THM_MOVT_ABS:
725 case R_ARM_THM_MOVW_ABS_NC:
726 {
727 int x, i, imm4, imm3, imm8;
728 if (type == R_ARM_THM_MOVT_ABS)
729 val >>= 16;
730 imm8 = val & 0xff;
731 imm3 = (val >> 8) & 0x7;
732 i = (val >> 11) & 1;
733 imm4 = (val >> 12) & 0xf;
734 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
735 if (type == R_ARM_THM_MOVT_ABS)
736 *(int *)ptr |= x;
737 else
738 *(int *)ptr += x;
739 }
740 break;
741 case R_ARM_PREL31:
742 {
743 int x;
744 x = (*(int *)ptr) & 0x7fffffff;
745 (*(int *)ptr) &= 0x80000000;
746 x = (x * 2) / 2;
747 x += val - addr;
748 if((x^(x>>1))&0x40000000)
749 tcc_error("can't relocate value at %x",addr);
750 (*(int *)ptr) |= x & 0x7fffffff;
751 }
752 case R_ARM_ABS32:
753 *(int *)ptr += val;
754 break;
755 case R_ARM_REL32:
756 *(int *)ptr += val - addr;
757 break;
758 case R_ARM_BASE_PREL:
759 *(int *)ptr += s1->got->sh_addr - addr;
760 break;
761 case R_ARM_GOTOFF32:
762 *(int *)ptr += val - s1->got->sh_addr;
763 break;
764 case R_ARM_GOT_BREL:
765 /* we load the got offset */
766 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
767 break;
768 case R_ARM_COPY:
769 break;
770 case R_ARM_V4BX:
771 /* trade Thumb support for ARMv4 support */
772 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
773 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
774 break;
775 default:
776 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
777 type, (unsigned)addr, ptr, (unsigned)val);
778 break;
779#elif defined(TCC_TARGET_C67)
780 case R_C60_32:
781 *(int *)ptr += val;
782 break;
783 case R_C60LO16:
784 {
785 uint32_t orig;
786
787 /* put the low 16 bits of the absolute address */
788 // add to what is already there
789
790 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
791 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
792
793 //patch both at once - assumes always in pairs Low - High
794
795 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
796 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
797 }
798 break;
799 case R_C60HI16:
800 break;
801 default:
802 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
803 type, (unsigned)addr, ptr, (unsigned)val);
804 break;
805#elif defined(TCC_TARGET_X86_64)
806 case R_X86_64_64:
807 if (s1->output_type == TCC_OUTPUT_DLL) {
808 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
809 qrel->r_addend = *(long long *)ptr + val;
810 qrel++;
811 }
812 *(long long *)ptr += val;
813 break;
814 case R_X86_64_32:
815 case R_X86_64_32S:
816 if (s1->output_type == TCC_OUTPUT_DLL) {
817 /* XXX: this logic may depend on TCC's codegen
818 now TCC uses R_X86_64_32 even for a 64bit pointer */
819 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
820 qrel->r_addend = *(int *)ptr + val;
821 qrel++;
822 }
823 *(int *)ptr += val;
824 break;
825
826 case R_X86_64_PC32:
827 if (s1->output_type == TCC_OUTPUT_DLL) {
828 /* DLL relocation */
829 esym_index = s1->symtab_to_dynsym[sym_index];
830 if (esym_index) {
831 qrel->r_offset = rel->r_offset;
832 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
833 qrel->r_addend = *(int *)ptr;
834 qrel++;
835 break;
836 }
837 }
838 /* fall through */
839 case R_X86_64_PLT32: {
840 long long diff;
841 diff = (long long)val - addr;
842 if (diff <= -2147483647 || diff > 2147483647) {
843#ifdef TCC_HAS_RUNTIME_PLTGOT
844 /* XXX: naive support for over 32bit jump */
845 if (s1->output_type == TCC_OUTPUT_MEMORY) {
846 val = (add_jmp_table(s1, val - rel->r_addend) +
847 rel->r_addend);
848 diff = val - addr;
849 }
850#endif
851 if (diff <= -2147483647 || diff > 2147483647) {
852 tcc_error("internal error: relocation failed");
853 }
854 }
855 *(int *)ptr += diff;
856 }
857 break;
858 case R_X86_64_GLOB_DAT:
859 case R_X86_64_JUMP_SLOT:
860 /* They don't need addend */
861 *(int *)ptr = val - rel->r_addend;
862 break;
863 case R_X86_64_GOTPCREL:
864#ifdef TCC_HAS_RUNTIME_PLTGOT
865 if (s1->output_type == TCC_OUTPUT_MEMORY) {
866 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
867 *(int *)ptr += val - addr;
868 break;
869 }
870#endif
871 *(int *)ptr += (s1->got->sh_addr - addr +
872 s1->sym_attrs[sym_index].got_offset - 4);
873 break;
874 case R_X86_64_GOTTPOFF:
875 *(int *)ptr += val - s1->got->sh_addr;
876 break;
877 case R_X86_64_GOT32:
878 /* we load the got offset */
879 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
880 break;
881#elif defined(TCC_TARGET_IL)
882#else
883#error unsupported processor
884#endif
885 }
886 }
887 /* if the relocation is allocated, we change its symbol table */
888 if (sr->sh_flags & SHF_ALLOC)
889 sr->link = s1->dynsym;
890}
891
892/* relocate relocation table in 'sr' */
893static void relocate_rel(TCCState *s1, Section *sr)
894{
895 Section *s;
896 ElfW_Rel *rel, *rel_end;
897
898 s = s1->sections[sr->sh_info];
899 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
900 for(rel = (ElfW_Rel *)sr->data;
901 rel < rel_end;
902 rel++) {
903 rel->r_offset += s->sh_addr;
904 }
905}
906
907/* count the number of dynamic relocations so that we can reserve
908 their space */
909static int prepare_dynamic_rel(TCCState *s1, Section *sr)
910{
911 ElfW_Rel *rel, *rel_end;
912 int sym_index, esym_index, type, count;
913
914 count = 0;
915 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
916 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
917 sym_index = ELFW(R_SYM)(rel->r_info);
918 type = ELFW(R_TYPE)(rel->r_info);
919 switch(type) {
920#if defined(TCC_TARGET_I386)
921 case R_386_32:
922#elif defined(TCC_TARGET_X86_64)
923 case R_X86_64_32:
924 case R_X86_64_32S:
925 case R_X86_64_64:
926#endif
927 count++;
928 break;
929#if defined(TCC_TARGET_I386)
930 case R_386_PC32:
931#elif defined(TCC_TARGET_X86_64)
932 case R_X86_64_PC32:
933#endif
934 esym_index = s1->symtab_to_dynsym[sym_index];
935 if (esym_index)
936 count++;
937 break;
938 default:
939 break;
940 }
941 }
942 if (count) {
943 /* allocate the section */
944 sr->sh_flags |= SHF_ALLOC;
945 sr->sh_size = count * sizeof(ElfW_Rel);
946 }
947 return count;
948}
949
950static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
951{
952 int n;
953 struct sym_attr *tab;
954
955 if (index >= s1->nb_sym_attrs) {
956 /* find immediately bigger power of 2 and reallocate array */
957 n = 1;
958 while (index >= n)
959 n *= 2;
960 tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
961 s1->sym_attrs = tab;
962 memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
963 (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
964 s1->nb_sym_attrs = n;
965 }
966 return &s1->sym_attrs[index];
967}
968
969/* XXX: suppress that */
970static void put32(unsigned char *p, uint32_t val)
971{
972 p[0] = val;
973 p[1] = val >> 8;
974 p[2] = val >> 16;
975 p[3] = val >> 24;
976}
977
978#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
979 defined(TCC_TARGET_X86_64)
980static uint32_t get32(unsigned char *p)
981{
982 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
983}
984#endif
985
986static void build_got(TCCState *s1)
987{
988 unsigned char *ptr;
989
990 /* if no got, then create it */
991 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
992 s1->got->sh_entsize = 4;
993 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
994 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
995 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
996#if PTR_SIZE == 4
997 /* keep space for _DYNAMIC pointer, if present */
998 put32(ptr, 0);
999 /* two dummy got entries */
1000 put32(ptr + 4, 0);
1001 put32(ptr + 8, 0);
1002#else
1003 /* keep space for _DYNAMIC pointer, if present */
1004 put32(ptr, 0);
1005 put32(ptr + 4, 0);
1006 /* two dummy got entries */
1007 put32(ptr + 8, 0);
1008 put32(ptr + 12, 0);
1009 put32(ptr + 16, 0);
1010 put32(ptr + 20, 0);
1011#endif
1012}
1013
1014/* put a got entry corresponding to a symbol in symtab_section. 'size'
1015 and 'info' can be modifed if more precise info comes from the DLL */
1016static void put_got_entry(TCCState *s1,
1017 int reloc_type, unsigned long size, int info,
1018 int sym_index)
1019{
1020 int index;
1021 const char *name;
1022 ElfW(Sym) *sym;
1023 unsigned long offset;
1024 int *ptr;
1025
1026 if (!s1->got)
1027 build_got(s1);
1028
1029 /* if a got entry already exists for that symbol, no need to add one */
1030 if (sym_index < s1->nb_sym_attrs &&
1031 s1->sym_attrs[sym_index].got_offset)
1032 return;
1033
1034 alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset;
1035
1036 if (s1->dynsym) {
1037 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1038 name = symtab_section->link->data + sym->st_name;
1039 offset = sym->st_value;
1040#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1041 if (reloc_type ==
1042#ifdef TCC_TARGET_X86_64
1043 R_X86_64_JUMP_SLOT
1044#else
1045 R_386_JMP_SLOT
1046#endif
1047 ) {
1048 Section *plt;
1049 uint8_t *p;
1050 int modrm;
1051
1052#if defined(TCC_OUTPUT_DLL_WITH_PLT)
1053 modrm = 0x25;
1054#else
1055 /* if we build a DLL, we add a %ebx offset */
1056 if (s1->output_type == TCC_OUTPUT_DLL)
1057 modrm = 0xa3;
1058 else
1059 modrm = 0x25;
1060#endif
1061
1062 /* add a PLT entry */
1063 plt = s1->plt;
1064 if (plt->data_offset == 0) {
1065 /* first plt entry */
1066 p = section_ptr_add(plt, 16);
1067 p[0] = 0xff; /* pushl got + PTR_SIZE */
1068 p[1] = modrm + 0x10;
1069 put32(p + 2, PTR_SIZE);
1070 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1071 p[7] = modrm;
1072 put32(p + 8, PTR_SIZE * 2);
1073 }
1074
1075 p = section_ptr_add(plt, 16);
1076 p[0] = 0xff; /* jmp *(got + x) */
1077 p[1] = modrm;
1078 put32(p + 2, s1->got->data_offset);
1079 p[6] = 0x68; /* push $xxx */
1080 put32(p + 7, (plt->data_offset - 32) >> 1);
1081 p[11] = 0xe9; /* jmp plt_start */
1082 put32(p + 12, -(plt->data_offset));
1083
1084 /* the symbol is modified so that it will be relocated to
1085 the PLT */
1086#if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1087 if (s1->output_type == TCC_OUTPUT_EXE)
1088#endif
1089 offset = plt->data_offset - 16;
1090 }
1091#elif defined(TCC_TARGET_ARM)
1092 if (reloc_type == R_ARM_JUMP_SLOT) {
1093 Section *plt;
1094 uint8_t *p;
1095
1096 /* if we build a DLL, we add a %ebx offset */
1097 if (s1->output_type == TCC_OUTPUT_DLL)
1098 tcc_error("DLLs unimplemented!");
1099
1100 /* add a PLT entry */
1101 plt = s1->plt;
1102 if (plt->data_offset == 0) {
1103 /* first plt entry */
1104 p = section_ptr_add(plt, 16);
1105 put32(p , 0xe52de004);
1106 put32(p + 4, 0xe59fe010);
1107 put32(p + 8, 0xe08fe00e);
1108 put32(p + 12, 0xe5bef008);
1109 }
1110
1111 if (s1->sym_attrs[sym_index].plt_thumb_stub) {
1112 p = section_ptr_add(plt, 20);
1113 put32(p , 0x4778); // bx pc
1114 put32(p+2, 0x46c0); // nop
1115 p += 4;
1116 } else
1117 p = section_ptr_add(plt, 16);
1118 put32(p , 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
1119 put32(p+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
1120 put32(p+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
1121 put32(p+12, s1->got->data_offset);
1122
1123 /* the symbol is modified so that it will be relocated to
1124 the PLT */
1125 if (s1->output_type == TCC_OUTPUT_EXE)
1126 offset = plt->data_offset - 16;
1127 }
1128#elif defined(TCC_TARGET_C67)
1129 tcc_error("C67 got not implemented");
1130#elif defined(TCC_TARGET_IL)
1131 tcc_error("IL got not implemented");
1132#else
1133#error unsupported CPU
1134#endif
1135 index = put_elf_sym(s1->dynsym, offset,
1136 size, info, 0, sym->st_shndx, name);
1137 /* put a got entry */
1138 put_elf_reloc(s1->dynsym, s1->got,
1139 s1->got->data_offset,
1140 reloc_type, index);
1141 }
1142 ptr = section_ptr_add(s1->got, PTR_SIZE);
1143 *ptr = 0;
1144}
1145
1146/* build GOT and PLT entries */
1147ST_FUNC void build_got_entries(TCCState *s1)
1148{
1149 Section *s;
1150 ElfW_Rel *rel, *rel_end;
1151 ElfW(Sym) *sym;
1152 int i, type, reloc_type, sym_index;
1153
1154 for(i = 1; i < s1->nb_sections; i++) {
1155 s = s1->sections[i];
1156 if (s->sh_type != SHT_RELX)
1157 continue;
1158 /* no need to handle got relocations */
1159 if (s->link != symtab_section)
1160 continue;
1161 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1162 for(rel = (ElfW_Rel *)s->data;
1163 rel < rel_end;
1164 rel++) {
1165 type = ELFW(R_TYPE)(rel->r_info);
1166 switch(type) {
1167#if defined(TCC_TARGET_I386)
1168 case R_386_GOT32:
1169 case R_386_GOTOFF:
1170 case R_386_GOTPC:
1171 case R_386_PLT32:
1172 if (!s1->got)
1173 build_got(s1);
1174 if (type == R_386_GOT32 || type == R_386_PLT32) {
1175 sym_index = ELFW(R_SYM)(rel->r_info);
1176 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1177 /* look at the symbol got offset. If none, then add one */
1178 if (type == R_386_GOT32)
1179 reloc_type = R_386_GLOB_DAT;
1180 else
1181 reloc_type = R_386_JMP_SLOT;
1182 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1183 sym_index);
1184 }
1185 break;
1186#elif defined(TCC_TARGET_ARM)
1187 case R_ARM_GOT_BREL:
1188 case R_ARM_GOTOFF32:
1189 case R_ARM_BASE_PREL:
1190 case R_ARM_PLT32:
1191 if (!s1->got)
1192 build_got(s1);
1193 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1194 sym_index = ELFW(R_SYM)(rel->r_info);
1195 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1196 /* look at the symbol got offset. If none, then add one */
1197 if (type == R_ARM_GOT_BREL)
1198 reloc_type = R_ARM_GLOB_DAT;
1199 else
1200 reloc_type = R_ARM_JUMP_SLOT;
1201 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1202 sym_index);
1203 }
1204 break;
1205#elif defined(TCC_TARGET_C67)
1206 case R_C60_GOT32:
1207 case R_C60_GOTOFF:
1208 case R_C60_GOTPC:
1209 case R_C60_PLT32:
1210 if (!s1->got)
1211 build_got(s1);
1212 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1213 sym_index = ELFW(R_SYM)(rel->r_info);
1214 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1215 /* look at the symbol got offset. If none, then add one */
1216 if (type == R_C60_GOT32)
1217 reloc_type = R_C60_GLOB_DAT;
1218 else
1219 reloc_type = R_C60_JMP_SLOT;
1220 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1221 sym_index);
1222 }
1223 break;
1224#elif defined(TCC_TARGET_X86_64)
1225 case R_X86_64_GOT32:
1226 case R_X86_64_GOTTPOFF:
1227 case R_X86_64_GOTPCREL:
1228 case R_X86_64_PLT32:
1229 if (!s1->got)
1230 build_got(s1);
1231 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1232 type == R_X86_64_PLT32) {
1233 sym_index = ELFW(R_SYM)(rel->r_info);
1234 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1235 /* look at the symbol got offset. If none, then add one */
1236 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1237 reloc_type = R_X86_64_GLOB_DAT;
1238 else
1239 reloc_type = R_X86_64_JUMP_SLOT;
1240 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1241 sym_index);
1242 }
1243 break;
1244#elif defined(TCC_TARGET_IL)
1245#else
1246#error unsupported CPU
1247#endif
1248 default:
1249 break;
1250 }
1251 }
1252 }
1253}
1254
1255ST_FUNC Section *new_symtab(TCCState *s1,
1256 const char *symtab_name, int sh_type, int sh_flags,
1257 const char *strtab_name,
1258 const char *hash_name, int hash_sh_flags)
1259{
1260 Section *symtab, *strtab, *hash;
1261 int *ptr, nb_buckets;
1262
1263 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1264 symtab->sh_entsize = sizeof(ElfW(Sym));
1265 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1266 put_elf_str(strtab, "");
1267 symtab->link = strtab;
1268 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1269
1270 nb_buckets = 1;
1271
1272 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1273 hash->sh_entsize = sizeof(int);
1274 symtab->hash = hash;
1275 hash->link = symtab;
1276
1277 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1278 ptr[0] = nb_buckets;
1279 ptr[1] = 1;
1280 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1281 return symtab;
1282}
1283
1284/* put dynamic tag */
1285static void put_dt(Section *dynamic, int dt, addr_t val)
1286{
1287 ElfW(Dyn) *dyn;
1288 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1289 dyn->d_tag = dt;
1290 dyn->d_un.d_val = val;
1291}
1292
1293static void add_init_array_defines(TCCState *s1, const char *section_name)
1294{
1295 Section *s;
1296 long end_offset;
1297 char sym_start[1024];
1298 char sym_end[1024];
1299
1300 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1301 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1302
1303 s = find_section(s1, section_name);
1304 if (!s) {
1305 end_offset = 0;
1306 s = data_section;
1307 } else {
1308 end_offset = s->data_offset;
1309 }
1310
1311 add_elf_sym(symtab_section,
1312 0, 0,
1313 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1314 s->sh_num, sym_start);
1315 add_elf_sym(symtab_section,
1316 end_offset, 0,
1317 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1318 s->sh_num, sym_end);
1319}
1320
1321ST_FUNC void tcc_add_bcheck(TCCState *s1)
1322{
1323#ifdef CONFIG_TCC_BCHECK
1324 unsigned long *ptr;
1325 Section *init_section;
1326 unsigned char *pinit;
1327 int sym_index;
1328
1329 if (0 == s1->do_bounds_check)
1330 return;
1331
1332 /* XXX: add an object file to do that */
1333 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1334 *ptr = 0;
1335 add_elf_sym(symtab_section, 0, 0,
1336 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1337 bounds_section->sh_num, "__bounds_start");
1338#ifdef TCC_TARGET_I386
1339 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1340 /* add 'call __bound_init()' in .init section */
1341 init_section = find_section(s1, ".init");
1342 pinit = section_ptr_add(init_section, 5);
1343 pinit[0] = 0xe8;
1344 put32(pinit + 1, -4);
1345 sym_index = find_elf_sym(symtab_section, "__bound_init");
1346 put_elf_reloc(symtab_section, init_section,
1347 init_section->data_offset - 4, R_386_PC32, sym_index);
1348 }
1349#endif
1350#endif
1351}
1352
1353static inline int tcc_add_support(TCCState *s1, const char *filename)
1354{
1355 char buf[1024];
1356 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1357 return tcc_add_file(s1, buf);
1358}
1359
1360/* add tcc runtime libraries */
1361ST_FUNC void tcc_add_runtime(TCCState *s1)
1362{
1363 tcc_add_bcheck(s1);
1364
1365 /* add libc */
1366 if (!s1->nostdlib) {
1367 tcc_add_library(s1, "c");
1368#ifdef CONFIG_USE_LIBGCC
1369 tcc_add_file(s1, TCC_LIBGCC);
1370#elif !defined WITHOUT_LIBTCC
1371 tcc_add_support(s1, "libtcc1.a");
1372#endif
1373 /* add crt end if not memory output */
1374 if (s1->output_type != TCC_OUTPUT_MEMORY)
1375 tcc_add_crt(s1, "crtn.o");
1376 }
1377}
1378
1379/* add various standard linker symbols (must be done after the
1380 sections are filled (for example after allocating common
1381 symbols)) */
1382ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1383{
1384 char buf[1024];
1385 int i;
1386 Section *s;
1387
1388 add_elf_sym(symtab_section,
1389 text_section->data_offset, 0,
1390 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1391 text_section->sh_num, "_etext");
1392 add_elf_sym(symtab_section,
1393 data_section->data_offset, 0,
1394 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1395 data_section->sh_num, "_edata");
1396 add_elf_sym(symtab_section,
1397 bss_section->data_offset, 0,
1398 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1399 bss_section->sh_num, "_end");
1400 /* horrible new standard ldscript defines */
1401 add_init_array_defines(s1, ".preinit_array");
1402 add_init_array_defines(s1, ".init_array");
1403 add_init_array_defines(s1, ".fini_array");
1404
1405 /* add start and stop symbols for sections whose name can be
1406 expressed in C */
1407 for(i = 1; i < s1->nb_sections; i++) {
1408 s = s1->sections[i];
1409 if (s->sh_type == SHT_PROGBITS &&
1410 (s->sh_flags & SHF_ALLOC)) {
1411 const char *p;
1412 int ch;
1413
1414 /* check if section name can be expressed in C */
1415 p = s->name;
1416 for(;;) {
1417 ch = *p;
1418 if (!ch)
1419 break;
1420 if (!isid(ch) && !isnum(ch))
1421 goto next_sec;
1422 p++;
1423 }
1424 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1425 add_elf_sym(symtab_section,
1426 0, 0,
1427 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1428 s->sh_num, buf);
1429 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1430 add_elf_sym(symtab_section,
1431 s->data_offset, 0,
1432 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1433 s->sh_num, buf);
1434 }
1435 next_sec: ;
1436 }
1437}
1438
1439static void tcc_output_binary(TCCState *s1, FILE *f,
1440 const int *section_order)
1441{
1442 Section *s;
1443 int i, offset, size;
1444
1445 offset = 0;
1446 for(i=1;i<s1->nb_sections;i++) {
1447 s = s1->sections[section_order[i]];
1448 if (s->sh_type != SHT_NOBITS &&
1449 (s->sh_flags & SHF_ALLOC)) {
1450 while (offset < s->sh_offset) {
1451 fputc(0, f);
1452 offset++;
1453 }
1454 size = s->sh_size;
1455 fwrite(s->data, 1, size, f);
1456 offset += size;
1457 }
1458 }
1459}
1460
1461#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1462#define HAVE_PHDR 1
1463#define EXTRA_RELITEMS 14
1464
1465/* move the relocation value from .dynsym to .got */
1466void patch_dynsym_undef(TCCState *s1, Section *s)
1467{
1468 uint32_t *gotd = (void *)s1->got->data;
1469 ElfW(Sym) *sym, *sym_end;
1470
1471 gotd += 3; // dummy entries in .got
1472 /* relocate symbols in .dynsym */
1473 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1474 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1475 if (sym->st_shndx == SHN_UNDEF) {
1476 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1477 sym->st_value = 0;
1478 }
1479 }
1480}
1481#else
1482#define HAVE_PHDR 0
1483#define EXTRA_RELITEMS 9
1484
1485/* zero plt offsets of weak symbols in .dynsym */
1486void patch_dynsym_undef(TCCState *s1, Section *s)
1487{
1488 ElfW(Sym) *sym, *sym_end;
1489
1490 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1491 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1492 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1493 sym->st_value = 0;
1494}
1495#endif
1496
1497ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1498{
1499 int sym_index = ELFW(R_SYM) (rel->r_info);
1500 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1501 unsigned long offset;
1502
1503 if (sym_index >= s1->nb_sym_attrs)
1504 return;
1505 offset = s1->sym_attrs[sym_index].got_offset;
1506 section_reserve(s1->got, offset + PTR_SIZE);
1507#ifdef TCC_TARGET_X86_64
1508 /* only works for x86-64 */
1509 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1510#endif
1511 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1512}
1513
1514ST_FUNC void fill_got(TCCState *s1)
1515{
1516 Section *s;
1517 ElfW_Rel *rel, *rel_end;
1518 int i;
1519
1520 for(i = 1; i < s1->nb_sections; i++) {
1521 s = s1->sections[i];
1522 if (s->sh_type != SHT_RELX)
1523 continue;
1524 /* no need to handle got relocations */
1525 if (s->link != symtab_section)
1526 continue;
1527 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1528 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1529 switch (ELFW(R_TYPE) (rel->r_info)) {
1530 case R_X86_64_GOT32:
1531 case R_X86_64_GOTPCREL:
1532 case R_X86_64_PLT32:
1533 fill_got_entry(s1, rel);
1534 break;
1535 }
1536 }
1537 }
1538}
1539
1540
1541/* output an ELF file */
1542/* XXX: suppress unneeded sections */
1543static int elf_output_file(TCCState *s1, const char *filename)
1544{
1545 ElfW(Ehdr) ehdr;
1546 FILE *f;
1547 int fd, mode, ret;
1548 int *section_order;
1549 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1550 long long tmp;
1551 addr_t addr;
1552 Section *strsec, *s;
1553 ElfW(Shdr) shdr, *sh;
1554 ElfW(Phdr) *phdr, *ph;
1555 Section *interp, *dynamic, *dynstr;
1556 unsigned long saved_dynamic_data_offset;
1557 ElfW(Sym) *sym;
1558 int type, file_type;
1559 addr_t rel_addr, rel_size;
1560#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1561 addr_t bss_addr, bss_size;
1562#endif
1563
1564 file_type = s1->output_type;
1565 s1->nb_errors = 0;
1566
1567 if (file_type != TCC_OUTPUT_OBJ) {
1568 tcc_add_runtime(s1);
1569 }
1570
1571 phdr = NULL;
1572 section_order = NULL;
1573 interp = NULL;
1574 dynamic = NULL;
1575 dynstr = NULL; /* avoid warning */
1576 saved_dynamic_data_offset = 0; /* avoid warning */
1577
1578 if (file_type != TCC_OUTPUT_OBJ) {
1579 relocate_common_syms();
1580
1581 tcc_add_linker_symbols(s1);
1582
1583 if (!s1->static_link) {
1584 const char *name;
1585 int sym_index, index;
1586 ElfW(Sym) *esym, *sym_end;
1587
1588 if (file_type == TCC_OUTPUT_EXE) {
1589 char *ptr;
1590 /* allow override the dynamic loader */
1591 const char *elfint = getenv("LD_SO");
1592 if (elfint == NULL)
1593 elfint = CONFIG_TCC_ELFINTERP;
1594 /* add interpreter section only if executable */
1595 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1596 interp->sh_addralign = 1;
1597 ptr = section_ptr_add(interp, 1+strlen(elfint));
1598 strcpy(ptr, elfint);
1599 }
1600
1601 /* add dynamic symbol table */
1602 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1603 ".dynstr",
1604 ".hash", SHF_ALLOC);
1605 dynstr = s1->dynsym->link;
1606
1607 /* add dynamic section */
1608 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1609 SHF_ALLOC | SHF_WRITE);
1610 dynamic->link = dynstr;
1611 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1612
1613 /* add PLT */
1614 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1615 SHF_ALLOC | SHF_EXECINSTR);
1616 s1->plt->sh_entsize = 4;
1617
1618 build_got(s1);
1619
1620 /* scan for undefined symbols and see if they are in the
1621 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1622 is found, then we add it in the PLT. If a symbol
1623 STT_OBJECT is found, we add it in the .bss section with
1624 a suitable relocation */
1625 sym_end = (ElfW(Sym) *)(symtab_section->data +
1626 symtab_section->data_offset);
1627 if (file_type == TCC_OUTPUT_EXE) {
1628 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1629 sym < sym_end;
1630 sym++) {
1631 if (sym->st_shndx == SHN_UNDEF) {
1632 name = symtab_section->link->data + sym->st_name;
1633 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1634 if (sym_index) {
1635 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1636 type = ELFW(ST_TYPE)(esym->st_info);
1637 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1638 /* Indirect functions shall have STT_FUNC type
1639 * in executable dynsym section. Indeed, a dlsym
1640 * call following a lazy resolution would pick
1641 * the symbol value from the executable dynsym
1642 * entry which would contain the address of the
1643 * function wanted by the caller of dlsym
1644 * instead of the address of the function that
1645 * would return that address */
1646 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1647 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
1648 sym - (ElfW(Sym) *)symtab_section->data);
1649 } else if (type == STT_OBJECT) {
1650 unsigned long offset;
1651 ElfW(Sym) *dynsym, *dynsym_end;
1652 offset = bss_section->data_offset;
1653 /* XXX: which alignment ? */
1654 offset = (offset + 16 - 1) & -16;
1655 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1656 esym->st_info, 0,
1657 bss_section->sh_num, name);
1658 // Ensure R_COPY works for weak symbol aliases
1659 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1660 dynsym_end = (ElfW(Sym) *)
1661 (s1->dynsymtab_section->data +
1662 s1->dynsymtab_section->data_offset);
1663 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1664 dynsym < dynsym_end; dynsym++) {
1665 if ((dynsym->st_value == esym->st_value)
1666 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1667 char *dynname;
1668 dynname = s1->dynsymtab_section->link->data
1669 + dynsym->st_name;
1670 put_elf_sym(s1->dynsym, offset,
1671 dynsym->st_size,
1672 dynsym->st_info, 0,
1673 bss_section->sh_num,
1674 dynname);
1675 break;
1676 }
1677 }
1678 }
1679 put_elf_reloc(s1->dynsym, bss_section,
1680 offset, R_COPY, index);
1681 offset += esym->st_size;
1682 bss_section->data_offset = offset;
1683 }
1684 } else {
1685 /* STB_WEAK undefined symbols are accepted */
1686 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1687 it */
1688 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1689 !strcmp(name, "_fp_hw")) {
1690 } else {
1691 tcc_error_noabort("undefined symbol '%s'", name);
1692 }
1693 }
1694 } else if (s1->rdynamic &&
1695 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1696 /* if -rdynamic option, then export all non
1697 local symbols */
1698 name = symtab_section->link->data + sym->st_name;
1699 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1700 sym->st_info, 0,
1701 sym->st_shndx, name);
1702 }
1703 }
1704
1705 if (s1->nb_errors)
1706 goto fail;
1707
1708 /* now look at unresolved dynamic symbols and export
1709 corresponding symbol */
1710 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1711 s1->dynsymtab_section->data_offset);
1712 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1713 esym < sym_end;
1714 esym++) {
1715 if (esym->st_shndx == SHN_UNDEF) {
1716 name = s1->dynsymtab_section->link->data + esym->st_name;
1717 sym_index = find_elf_sym(symtab_section, name);
1718 if (sym_index) {
1719 /* XXX: avoid adding a symbol if already
1720 present because of -rdynamic ? */
1721 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1722 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1723 sym->st_info, 0,
1724 sym->st_shndx, name);
1725 } else {
1726 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1727 /* weak symbols can stay undefined */
1728 } else {
1729 tcc_warning("undefined dynamic symbol '%s'", name);
1730 }
1731 }
1732 }
1733 }
1734 } else {
1735 int nb_syms;
1736 /* shared library case : we simply export all the global symbols */
1737 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1738 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1739 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1740 sym < sym_end;
1741 sym++) {
1742 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1743#if defined(TCC_OUTPUT_DLL_WITH_PLT)
1744 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1745 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1746 && sym->st_shndx == SHN_UNDEF) {
1747 int visibility = ELFW(ST_BIND)(sym->st_info);
1748 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1749 ELFW(ST_INFO)(visibility,STT_FUNC),
1750 sym - (ElfW(Sym) *)symtab_section->data);
1751 }
1752 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1753 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1754 sym->st_info,
1755 sym - (ElfW(Sym) *)symtab_section->data);
1756 }
1757 else
1758#endif
1759 {
1760 name = symtab_section->link->data + sym->st_name;
1761 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1762 sym->st_info, 0,
1763 sym->st_shndx, name);
1764 s1->symtab_to_dynsym[sym -
1765 (ElfW(Sym) *)symtab_section->data] =
1766 index;
1767 }
1768 }
1769 }
1770 }
1771
1772 build_got_entries(s1);
1773
1774 /* add a list of needed dlls */
1775 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1776 DLLReference *dllref = s1->loaded_dlls[i];
1777 if (dllref->level == 0)
1778 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1779 }
1780
1781 if (s1->rpath)
1782 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1783
1784 /* XXX: currently, since we do not handle PIC code, we
1785 must relocate the readonly segments */
1786 if (file_type == TCC_OUTPUT_DLL) {
1787 if (s1->soname)
1788 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1789 put_dt(dynamic, DT_TEXTREL, 0);
1790 }
1791
1792 if (s1->symbolic)
1793 put_dt(dynamic, DT_SYMBOLIC, 0);
1794
1795 /* add necessary space for other entries */
1796 saved_dynamic_data_offset = dynamic->data_offset;
1797 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1798 } else {
1799 /* still need to build got entries in case of static link */
1800 build_got_entries(s1);
1801 }
1802 }
1803
1804 memset(&ehdr, 0, sizeof(ehdr));
1805
1806 /* we add a section for symbols */
1807 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1808 put_elf_str(strsec, "");
1809
1810 /* compute number of sections */
1811 shnum = s1->nb_sections;
1812
1813 /* this array is used to reorder sections in the output file */
1814 section_order = tcc_malloc(sizeof(int) * shnum);
1815 section_order[0] = 0;
1816 sh_order_index = 1;
1817
1818 /* compute number of program headers */
1819 switch(file_type) {
1820 default:
1821 case TCC_OUTPUT_OBJ:
1822 phnum = 0;
1823 break;
1824 case TCC_OUTPUT_EXE:
1825 if (!s1->static_link)
1826 phnum = 4 + HAVE_PHDR;
1827 else
1828 phnum = 2;
1829 break;
1830 case TCC_OUTPUT_DLL:
1831 phnum = 3;
1832 break;
1833 }
1834
1835 /* allocate strings for section names and decide if an unallocated
1836 section should be output */
1837 /* NOTE: the strsec section comes last, so its size is also
1838 correct ! */
1839 for(i = 1; i < s1->nb_sections; i++) {
1840 s = s1->sections[i];
1841 s->sh_name = put_elf_str(strsec, s->name);
1842#if 0 //gr
1843 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1844 s->sh_flags,
1845 s->sh_type,
1846 s->sh_info,
1847 s->name,
1848 s->reloc ? s->reloc->name : "n"
1849 );
1850#endif
1851 /* when generating a DLL, we include relocations but we may
1852 patch them */
1853 if (file_type == TCC_OUTPUT_DLL &&
1854 s->sh_type == SHT_RELX &&
1855 !(s->sh_flags & SHF_ALLOC)) {
1856 /* //gr: avoid bogus relocs for empty (debug) sections */
1857 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1858 prepare_dynamic_rel(s1, s);
1859 else if (s1->do_debug)
1860 s->sh_size = s->data_offset;
1861 } else if (s1->do_debug ||
1862 file_type == TCC_OUTPUT_OBJ ||
1863 (s->sh_flags & SHF_ALLOC) ||
1864 i == (s1->nb_sections - 1)) {
1865 /* we output all sections if debug or object file */
1866 s->sh_size = s->data_offset;
1867 }
1868 }
1869
1870 /* allocate program segment headers */
1871 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1872
1873 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1874 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1875 } else {
1876 file_offset = 0;
1877 }
1878 if (phnum > 0) {
1879 /* compute section to program header mapping */
1880 if (s1->has_text_addr) {
1881 int a_offset, p_offset;
1882 addr = s1->text_addr;
1883 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1884 ELF_PAGE_SIZE */
1885 a_offset = (int) (addr & (s1->section_align - 1));
1886 p_offset = file_offset & (s1->section_align - 1);
1887 if (a_offset < p_offset)
1888 a_offset += s1->section_align;
1889 file_offset += (a_offset - p_offset);
1890 } else {
1891 if (file_type == TCC_OUTPUT_DLL)
1892 addr = 0;
1893 else
1894 addr = ELF_START_ADDR;
1895 /* compute address after headers */
1896 addr += (file_offset & (s1->section_align - 1));
1897 }
1898
1899 /* dynamic relocation table information, for .dynamic section */
1900 rel_size = 0;
1901 rel_addr = 0;
1902
1903#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1904 bss_addr = bss_size = 0;
1905#endif
1906 /* leave one program header for the program interpreter */
1907 ph = &phdr[0];
1908 if (interp)
1909 ph += 1 + HAVE_PHDR;
1910
1911 for(j = 0; j < 2; j++) {
1912 ph->p_type = PT_LOAD;
1913 if (j == 0)
1914 ph->p_flags = PF_R | PF_X;
1915 else
1916 ph->p_flags = PF_R | PF_W;
1917 ph->p_align = s1->section_align;
1918
1919 /* we do the following ordering: interp, symbol tables,
1920 relocations, progbits, nobits */
1921 /* XXX: do faster and simpler sorting */
1922 for(k = 0; k < 5; k++) {
1923 for(i = 1; i < s1->nb_sections; i++) {
1924 s = s1->sections[i];
1925 /* compute if section should be included */
1926 if (j == 0) {
1927 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1928 SHF_ALLOC)
1929 continue;
1930 } else {
1931 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1932 (SHF_ALLOC | SHF_WRITE))
1933 continue;
1934 }
1935 if (s == interp) {
1936 if (k != 0)
1937 continue;
1938 } else if (s->sh_type == SHT_DYNSYM ||
1939 s->sh_type == SHT_STRTAB ||
1940 s->sh_type == SHT_HASH) {
1941 if (k != 1)
1942 continue;
1943 } else if (s->sh_type == SHT_RELX) {
1944 if (k != 2)
1945 continue;
1946 } else if (s->sh_type == SHT_NOBITS) {
1947 if (k != 4)
1948 continue;
1949 } else {
1950 if (k != 3)
1951 continue;
1952 }
1953 section_order[sh_order_index++] = i;
1954
1955 /* section matches: we align it and add its size */
1956 tmp = addr;
1957 addr = (addr + s->sh_addralign - 1) &
1958 ~(s->sh_addralign - 1);
1959 file_offset += (int) ( addr - tmp );
1960 s->sh_offset = file_offset;
1961 s->sh_addr = addr;
1962
1963 /* update program header infos */
1964 if (ph->p_offset == 0) {
1965 ph->p_offset = file_offset;
1966 ph->p_vaddr = addr;
1967 ph->p_paddr = ph->p_vaddr;
1968 }
1969 /* update dynamic relocation infos */
1970 if (s->sh_type == SHT_RELX) {
1971#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1972 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1973 rel_addr = addr;
1974 rel_size += s->sh_size; // XXX only first rel.
1975 }
1976 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1977 bss_addr = addr;
1978 bss_size = s->sh_size; // XXX only first rel.
1979 }
1980#else
1981 if (rel_size == 0)
1982 rel_addr = addr;
1983 rel_size += s->sh_size;
1984#endif
1985 }
1986 addr += s->sh_size;
1987 if (s->sh_type != SHT_NOBITS)
1988 file_offset += s->sh_size;
1989 }
1990 }
1991 ph->p_filesz = file_offset - ph->p_offset;
1992 ph->p_memsz = addr - ph->p_vaddr;
1993 ph++;
1994 if (j == 0) {
1995 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1996 /* if in the middle of a page, we duplicate the page in
1997 memory so that one copy is RX and the other is RW */
1998 if ((addr & (s1->section_align - 1)) != 0)
1999 addr += s1->section_align;
2000 } else {
2001 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
2002 file_offset = (file_offset + s1->section_align - 1) &
2003 ~(s1->section_align - 1);
2004 }
2005 }
2006 }
2007
2008 /* if interpreter, then add corresponing program header */
2009 if (interp) {
2010 ph = &phdr[0];
2011
2012#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2013 {
2014 int len = phnum * sizeof(ElfW(Phdr));
2015
2016 ph->p_type = PT_PHDR;
2017 ph->p_offset = sizeof(ElfW(Ehdr));
2018 ph->p_vaddr = interp->sh_addr - len;
2019 ph->p_paddr = ph->p_vaddr;
2020 ph->p_filesz = ph->p_memsz = len;
2021 ph->p_flags = PF_R | PF_X;
2022 ph->p_align = 4; // interp->sh_addralign;
2023 ph++;
2024 }
2025#endif
2026
2027 ph->p_type = PT_INTERP;
2028 ph->p_offset = interp->sh_offset;
2029 ph->p_vaddr = interp->sh_addr;
2030 ph->p_paddr = ph->p_vaddr;
2031 ph->p_filesz = interp->sh_size;
2032 ph->p_memsz = interp->sh_size;
2033 ph->p_flags = PF_R;
2034 ph->p_align = interp->sh_addralign;
2035 }
2036
2037 /* if dynamic section, then add corresponing program header */
2038 if (dynamic) {
2039 ElfW(Sym) *sym_end;
2040
2041 ph = &phdr[phnum - 1];
2042
2043 ph->p_type = PT_DYNAMIC;
2044 ph->p_offset = dynamic->sh_offset;
2045 ph->p_vaddr = dynamic->sh_addr;
2046 ph->p_paddr = ph->p_vaddr;
2047 ph->p_filesz = dynamic->sh_size;
2048 ph->p_memsz = dynamic->sh_size;
2049 ph->p_flags = PF_R | PF_W;
2050 ph->p_align = dynamic->sh_addralign;
2051
2052 /* put GOT dynamic section address */
2053 put32(s1->got->data, dynamic->sh_addr);
2054
2055 /* relocate the PLT */
2056 if (file_type == TCC_OUTPUT_EXE
2057#if defined(TCC_OUTPUT_DLL_WITH_PLT)
2058 || file_type == TCC_OUTPUT_DLL
2059#endif
2060 ) {
2061 uint8_t *p, *p_end;
2062
2063 p = s1->plt->data;
2064 p_end = p + s1->plt->data_offset;
2065 if (p < p_end) {
2066#if defined(TCC_TARGET_I386)
2067 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2068 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
2069 p += 16;
2070 while (p < p_end) {
2071 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2072 p += 16;
2073 }
2074#elif defined(TCC_TARGET_X86_64)
2075 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2076 put32(p + 2, get32(p + 2) + x);
2077 put32(p + 8, get32(p + 8) + x - 6);
2078 p += 16;
2079 while (p < p_end) {
2080 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
2081 p += 16;
2082 }
2083#elif defined(TCC_TARGET_ARM)
2084 int x;
2085 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2086 p += 16;
2087 while (p < p_end) {
2088 if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
2089 p += 4;
2090 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
2091 p += 16;
2092 }
2093#elif defined(TCC_TARGET_C67)
2094 /* XXX: TODO */
2095#elif defined(TCC_TARGET_IL)
2096#else
2097#error unsupported CPU
2098#endif
2099 }
2100 }
2101
2102 /* relocate symbols in .dynsym */
2103 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
2104 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
2105 sym < sym_end;
2106 sym++) {
2107 if (sym->st_shndx == SHN_UNDEF) {
2108 /* relocate to the PLT if the symbol corresponds
2109 to a PLT entry */
2110 if (sym->st_value)
2111 sym->st_value += s1->plt->sh_addr;
2112 } else if (sym->st_shndx < SHN_LORESERVE) {
2113 /* do symbol relocation */
2114 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2115 }
2116 }
2117
2118 /* put dynamic section entries */
2119 dynamic->data_offset = saved_dynamic_data_offset;
2120 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2121 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2122 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2123 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2124 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2125#ifdef TCC_TARGET_X86_64
2126 put_dt(dynamic, DT_RELA, rel_addr);
2127 put_dt(dynamic, DT_RELASZ, rel_size);
2128 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2129#else
2130#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2131 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2132 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2133 put_dt(dynamic, DT_JMPREL, rel_addr);
2134 put_dt(dynamic, DT_PLTREL, DT_REL);
2135 put_dt(dynamic, DT_REL, bss_addr);
2136 put_dt(dynamic, DT_RELSZ, bss_size);
2137#else
2138 put_dt(dynamic, DT_REL, rel_addr);
2139 put_dt(dynamic, DT_RELSZ, rel_size);
2140 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2141#endif
2142#endif
2143 if (s1->do_debug)
2144 put_dt(dynamic, DT_DEBUG, 0);
2145 put_dt(dynamic, DT_NULL, 0);
2146 }
2147
2148 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2149 ehdr.e_phnum = phnum;
2150 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2151 }
2152
2153 /* all other sections come after */
2154 for(i = 1; i < s1->nb_sections; i++) {
2155 s = s1->sections[i];
2156 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2157 continue;
2158 section_order[sh_order_index++] = i;
2159
2160 file_offset = (file_offset + s->sh_addralign - 1) &
2161 ~(s->sh_addralign - 1);
2162 s->sh_offset = file_offset;
2163 if (s->sh_type != SHT_NOBITS)
2164 file_offset += s->sh_size;
2165 }
2166
2167 /* if building executable or DLL, then relocate each section
2168 except the GOT which is already relocated */
2169 if (file_type != TCC_OUTPUT_OBJ) {
2170 relocate_syms(s1, 0);
2171
2172 if (s1->nb_errors != 0) {
2173 fail:
2174 ret = -1;
2175 goto the_end;
2176 }
2177
2178 /* relocate sections */
2179 /* XXX: ignore sections with allocated relocations ? */
2180 for(i = 1; i < s1->nb_sections; i++) {
2181 s = s1->sections[i];
2182 if (s->reloc && s != s1->got)
2183 relocate_section(s1, s);
2184 }
2185
2186 /* relocate relocation entries if the relocation tables are
2187 allocated in the executable */
2188 for(i = 1; i < s1->nb_sections; i++) {
2189 s = s1->sections[i];
2190 if ((s->sh_flags & SHF_ALLOC) &&
2191 s->sh_type == SHT_RELX) {
2192 relocate_rel(s1, s);
2193 }
2194 }
2195
2196 /* get entry point address */
2197 if (file_type == TCC_OUTPUT_EXE)
2198 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2199 else
2200 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2201 }
2202 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2203 fill_got(s1);
2204
2205 /* write elf file */
2206 if (file_type == TCC_OUTPUT_OBJ)
2207 mode = 0666;
2208 else
2209 mode = 0777;
2210 unlink(filename);
2211 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2212 if (fd < 0) {
2213 tcc_error_noabort("could not write '%s'", filename);
2214 goto fail;
2215 }
2216 f = fdopen(fd, "wb");
2217 if (s1->verbose)
2218 printf("<- %s\n", filename);
2219
2220#ifdef TCC_TARGET_COFF
2221 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2222 tcc_output_coff(s1, f);
2223 } else
2224#endif
2225 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2226 sort_syms(s1, symtab_section);
2227
2228 /* align to 4 */
2229 file_offset = (file_offset + 3) & -4;
2230
2231 /* fill header */
2232 ehdr.e_ident[0] = ELFMAG0;
2233 ehdr.e_ident[1] = ELFMAG1;
2234 ehdr.e_ident[2] = ELFMAG2;
2235 ehdr.e_ident[3] = ELFMAG3;
2236 ehdr.e_ident[4] = ELFCLASSW;
2237 ehdr.e_ident[5] = ELFDATA2LSB;
2238 ehdr.e_ident[6] = EV_CURRENT;
2239#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2240 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2241#endif
2242#ifdef TCC_TARGET_ARM
2243#ifdef TCC_ARM_EABI
2244 ehdr.e_ident[EI_OSABI] = 0;
2245 ehdr.e_flags = 4 << 24;
2246#else
2247 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2248#endif
2249#endif
2250 switch(file_type) {
2251 default:
2252 case TCC_OUTPUT_EXE:
2253 ehdr.e_type = ET_EXEC;
2254 break;
2255 case TCC_OUTPUT_DLL:
2256 ehdr.e_type = ET_DYN;
2257 break;
2258 case TCC_OUTPUT_OBJ:
2259 ehdr.e_type = ET_REL;
2260 break;
2261 }
2262 ehdr.e_machine = EM_TCC_TARGET;
2263 ehdr.e_version = EV_CURRENT;
2264 ehdr.e_shoff = file_offset;
2265 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2266 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2267 ehdr.e_shnum = shnum;
2268 ehdr.e_shstrndx = shnum - 1;
2269
2270 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2271 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2272 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2273
2274 for(i=1;i<s1->nb_sections;i++) {
2275 s = s1->sections[section_order[i]];
2276 if (s->sh_type != SHT_NOBITS) {
2277 if (s->sh_type == SHT_DYNSYM)
2278 patch_dynsym_undef(s1, s);
2279 while (offset < s->sh_offset) {
2280 fputc(0, f);
2281 offset++;
2282 }
2283 size = s->sh_size;
2284 fwrite(s->data, 1, size, f);
2285 offset += size;
2286 }
2287 }
2288
2289 /* output section headers */
2290 while (offset < ehdr.e_shoff) {
2291 fputc(0, f);
2292 offset++;
2293 }
2294
2295 for(i=0;i<s1->nb_sections;i++) {
2296 sh = &shdr;
2297 memset(sh, 0, sizeof(ElfW(Shdr)));
2298 s = s1->sections[i];
2299 if (s) {
2300 sh->sh_name = s->sh_name;
2301 sh->sh_type = s->sh_type;
2302 sh->sh_flags = s->sh_flags;
2303 sh->sh_entsize = s->sh_entsize;
2304 sh->sh_info = s->sh_info;
2305 if (s->link)
2306 sh->sh_link = s->link->sh_num;
2307 sh->sh_addralign = s->sh_addralign;
2308 sh->sh_addr = s->sh_addr;
2309 sh->sh_offset = s->sh_offset;
2310 sh->sh_size = s->sh_size;
2311 }
2312 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2313 }
2314 } else {
2315 tcc_output_binary(s1, f, section_order);
2316 }
2317 fclose(f);
2318
2319 ret = 0;
2320 the_end:
2321 tcc_free(s1->symtab_to_dynsym);
2322 tcc_free(section_order);
2323 tcc_free(phdr);
2324 tcc_free(s1->sym_attrs);
2325 return ret;
2326}
2327
2328LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2329{
2330 int ret;
2331#ifdef TCC_TARGET_PE
2332 if (s->output_type != TCC_OUTPUT_OBJ) {
2333 ret = pe_output_file(s, filename);
2334 } else
2335#endif
2336 {
2337 ret = elf_output_file(s, filename);
2338 }
2339 return ret;
2340}
2341
2342static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2343{
2344 void *data;
2345
2346 data = tcc_malloc(size);
2347 lseek(fd, file_offset, SEEK_SET);
2348 read(fd, data, size);
2349 return data;
2350}
2351
2352typedef struct SectionMergeInfo {
2353 Section *s; /* corresponding existing section */
2354 unsigned long offset; /* offset of the new section in the existing section */
2355 uint8_t new_section; /* true if section 's' was added */
2356 uint8_t link_once; /* true if link once section */
2357} SectionMergeInfo;
2358
2359/* load an object file and merge it with current files */
2360/* XXX: handle correctly stab (debug) info */
2361ST_FUNC int tcc_load_object_file(TCCState *s1,
2362 int fd, unsigned long file_offset)
2363{
2364 ElfW(Ehdr) ehdr;
2365 ElfW(Shdr) *shdr, *sh;
2366 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2367 unsigned char *strsec, *strtab;
2368 int *old_to_new_syms;
2369 char *sh_name, *name;
2370 SectionMergeInfo *sm_table, *sm;
2371 ElfW(Sym) *sym, *symtab;
2372 ElfW_Rel *rel, *rel_end;
2373 Section *s;
2374
2375 int stab_index;
2376 int stabstr_index;
2377
2378 stab_index = stabstr_index = 0;
2379
2380 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2381 goto fail1;
2382 if (ehdr.e_ident[0] != ELFMAG0 ||
2383 ehdr.e_ident[1] != ELFMAG1 ||
2384 ehdr.e_ident[2] != ELFMAG2 ||
2385 ehdr.e_ident[3] != ELFMAG3)
2386 goto fail1;
2387 /* test if object file */
2388 if (ehdr.e_type != ET_REL)
2389 goto fail1;
2390 /* test CPU specific stuff */
2391 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2392 ehdr.e_machine != EM_TCC_TARGET) {
2393 fail1:
2394 tcc_error_noabort("invalid object file");
2395 return -1;
2396 }
2397 /* read sections */
2398 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2399 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2400 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2401
2402 /* load section names */
2403 sh = &shdr[ehdr.e_shstrndx];
2404 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2405
2406 /* load symtab and strtab */
2407 old_to_new_syms = NULL;
2408 symtab = NULL;
2409 strtab = NULL;
2410 nb_syms = 0;
2411 for(i = 1; i < ehdr.e_shnum; i++) {
2412 sh = &shdr[i];
2413 if (sh->sh_type == SHT_SYMTAB) {
2414 if (symtab) {
2415 tcc_error_noabort("object must contain only one symtab");
2416 fail:
2417 ret = -1;
2418 goto the_end;
2419 }
2420 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2421 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2422 sm_table[i].s = symtab_section;
2423
2424 /* now load strtab */
2425 sh = &shdr[sh->sh_link];
2426 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2427 }
2428 }
2429
2430 /* now examine each section and try to merge its content with the
2431 ones in memory */
2432 for(i = 1; i < ehdr.e_shnum; i++) {
2433 /* no need to examine section name strtab */
2434 if (i == ehdr.e_shstrndx)
2435 continue;
2436 sh = &shdr[i];
2437 sh_name = strsec + sh->sh_name;
2438 /* ignore sections types we do not handle */
2439 if (sh->sh_type != SHT_PROGBITS &&
2440 sh->sh_type != SHT_RELX &&
2441#ifdef TCC_ARM_EABI
2442 sh->sh_type != SHT_ARM_EXIDX &&
2443#endif
2444 sh->sh_type != SHT_NOBITS &&
2445 sh->sh_type != SHT_PREINIT_ARRAY &&
2446 sh->sh_type != SHT_INIT_ARRAY &&
2447 sh->sh_type != SHT_FINI_ARRAY &&
2448 strcmp(sh_name, ".stabstr")
2449 )
2450 continue;
2451 if (sh->sh_addralign < 1)
2452 sh->sh_addralign = 1;
2453 /* find corresponding section, if any */
2454 for(j = 1; j < s1->nb_sections;j++) {
2455 s = s1->sections[j];
2456 if (!strcmp(s->name, sh_name)) {
2457 if (!strncmp(sh_name, ".gnu.linkonce",
2458 sizeof(".gnu.linkonce") - 1)) {
2459 /* if a 'linkonce' section is already present, we
2460 do not add it again. It is a little tricky as
2461 symbols can still be defined in
2462 it. */
2463 sm_table[i].link_once = 1;
2464 goto next;
2465 } else {
2466 goto found;
2467 }
2468 }
2469 }
2470 /* not found: create new section */
2471 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2472 /* take as much info as possible from the section. sh_link and
2473 sh_info will be updated later */
2474 s->sh_addralign = sh->sh_addralign;
2475 s->sh_entsize = sh->sh_entsize;
2476 sm_table[i].new_section = 1;
2477 found:
2478 if (sh->sh_type != s->sh_type) {
2479 tcc_error_noabort("invalid section type");
2480 goto fail;
2481 }
2482
2483 /* align start of section */
2484 offset = s->data_offset;
2485
2486 if (0 == strcmp(sh_name, ".stab")) {
2487 stab_index = i;
2488 goto no_align;
2489 }
2490 if (0 == strcmp(sh_name, ".stabstr")) {
2491 stabstr_index = i;
2492 goto no_align;
2493 }
2494
2495 size = sh->sh_addralign - 1;
2496 offset = (offset + size) & ~size;
2497 if (sh->sh_addralign > s->sh_addralign)
2498 s->sh_addralign = sh->sh_addralign;
2499 s->data_offset = offset;
2500 no_align:
2501 sm_table[i].offset = offset;
2502 sm_table[i].s = s;
2503 /* concatenate sections */
2504 size = sh->sh_size;
2505 if (sh->sh_type != SHT_NOBITS) {
2506 unsigned char *ptr;
2507 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2508 ptr = section_ptr_add(s, size);
2509 read(fd, ptr, size);
2510 } else {
2511 s->data_offset += size;
2512 }
2513 next: ;
2514 }
2515
2516 /* //gr relocate stab strings */
2517 if (stab_index && stabstr_index) {
2518 Stab_Sym *a, *b;
2519 unsigned o;
2520 s = sm_table[stab_index].s;
2521 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2522 b = (Stab_Sym *)(s->data + s->data_offset);
2523 o = sm_table[stabstr_index].offset;
2524 while (a < b)
2525 a->n_strx += o, a++;
2526 }
2527
2528 /* second short pass to update sh_link and sh_info fields of new
2529 sections */
2530 for(i = 1; i < ehdr.e_shnum; i++) {
2531 s = sm_table[i].s;
2532 if (!s || !sm_table[i].new_section)
2533 continue;
2534 sh = &shdr[i];
2535 if (sh->sh_link > 0)
2536 s->link = sm_table[sh->sh_link].s;
2537 if (sh->sh_type == SHT_RELX) {
2538 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2539 /* update backward link */
2540 s1->sections[s->sh_info]->reloc = s;
2541 }
2542 }
2543 sm = sm_table;
2544
2545 /* resolve symbols */
2546 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2547
2548 sym = symtab + 1;
2549 for(i = 1; i < nb_syms; i++, sym++) {
2550 if (sym->st_shndx != SHN_UNDEF &&
2551 sym->st_shndx < SHN_LORESERVE) {
2552 sm = &sm_table[sym->st_shndx];
2553 if (sm->link_once) {
2554 /* if a symbol is in a link once section, we use the
2555 already defined symbol. It is very important to get
2556 correct relocations */
2557 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2558 name = strtab + sym->st_name;
2559 sym_index = find_elf_sym(symtab_section, name);
2560 if (sym_index)
2561 old_to_new_syms[i] = sym_index;
2562 }
2563 continue;
2564 }
2565 /* if no corresponding section added, no need to add symbol */
2566 if (!sm->s)
2567 continue;
2568 /* convert section number */
2569 sym->st_shndx = sm->s->sh_num;
2570 /* offset value */
2571 sym->st_value += sm->offset;
2572 }
2573 /* add symbol */
2574 name = strtab + sym->st_name;
2575 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2576 sym->st_info, sym->st_other,
2577 sym->st_shndx, name);
2578 old_to_new_syms[i] = sym_index;
2579 }
2580
2581 /* third pass to patch relocation entries */
2582 for(i = 1; i < ehdr.e_shnum; i++) {
2583 s = sm_table[i].s;
2584 if (!s)
2585 continue;
2586 sh = &shdr[i];
2587 offset = sm_table[i].offset;
2588 switch(s->sh_type) {
2589 case SHT_RELX:
2590 /* take relocation offset information */
2591 offseti = sm_table[sh->sh_info].offset;
2592 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2593 for(rel = (ElfW_Rel *)(s->data + offset);
2594 rel < rel_end;
2595 rel++) {
2596 int type;
2597 unsigned sym_index;
2598 /* convert symbol index */
2599 type = ELFW(R_TYPE)(rel->r_info);
2600 sym_index = ELFW(R_SYM)(rel->r_info);
2601 /* NOTE: only one symtab assumed */
2602 if (sym_index >= nb_syms)
2603 goto invalid_reloc;
2604 sym_index = old_to_new_syms[sym_index];
2605 /* ignore link_once in rel section. */
2606 if (!sym_index && !sm->link_once
2607#ifdef TCC_TARGET_ARM
2608 && type != R_ARM_V4BX
2609#endif
2610 ) {
2611 invalid_reloc:
2612 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2613 i, strsec + sh->sh_name, rel->r_offset);
2614 goto fail;
2615 }
2616 rel->r_info = ELFW(R_INFO)(sym_index, type);
2617 /* offset the relocation offset */
2618 rel->r_offset += offseti;
2619#ifdef TCC_TARGET_ARM
2620 /* Jumps and branches from a Thumb code to a PLT entry need
2621 special handling since PLT entries are ARM code.
2622 Unconditional bl instructions referencing PLT entries are
2623 handled by converting these instructions into blx
2624 instructions. Other case of instructions referencing a PLT
2625 entry require to add a Thumb stub before the PLT entry to
2626 switch to ARM mode. We set bit 0 of the got offset of a
2627 symbol to indicate such a case. */
2628 if (type == R_ARM_THM_JUMP24)
2629 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
2630#endif
2631 }
2632 break;
2633 default:
2634 break;
2635 }
2636 }
2637
2638 ret = 0;
2639 the_end:
2640 tcc_free(symtab);
2641 tcc_free(strtab);
2642 tcc_free(old_to_new_syms);
2643 tcc_free(sm_table);
2644 tcc_free(strsec);
2645 tcc_free(shdr);
2646 return ret;
2647}
2648
2649typedef struct ArchiveHeader {
2650 char ar_name[16]; /* name of this member */
2651 char ar_date[12]; /* file mtime */
2652 char ar_uid[6]; /* owner uid; printed as decimal */
2653 char ar_gid[6]; /* owner gid; printed as decimal */
2654 char ar_mode[8]; /* file mode, printed as octal */
2655 char ar_size[10]; /* file size, printed as decimal */
2656 char ar_fmag[2]; /* should contain ARFMAG */
2657} ArchiveHeader;
2658
2659static int get_be32(const uint8_t *b)
2660{
2661 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2662}
2663
2664/* load only the objects which resolve undefined symbols */
2665static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2666{
2667 int i, bound, nsyms, sym_index, off, ret;
2668 uint8_t *data;
2669 const char *ar_names, *p;
2670 const uint8_t *ar_index;
2671 ElfW(Sym) *sym;
2672
2673 data = tcc_malloc(size);
2674 if (read(fd, data, size) != size)
2675 goto fail;
2676 nsyms = get_be32(data);
2677 ar_index = data + 4;
2678 ar_names = ar_index + nsyms * 4;
2679
2680 do {
2681 bound = 0;
2682 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2683 sym_index = find_elf_sym(symtab_section, p);
2684 if(sym_index) {
2685 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2686 if(sym->st_shndx == SHN_UNDEF) {
2687 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2688#if 0
2689 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2690#endif
2691 ++bound;
2692 lseek(fd, off, SEEK_SET);
2693 if(tcc_load_object_file(s1, fd, off) < 0) {
2694 fail:
2695 ret = -1;
2696 goto the_end;
2697 }
2698 }
2699 }
2700 }
2701 } while(bound);
2702 ret = 0;
2703 the_end:
2704 tcc_free(data);
2705 return ret;
2706}
2707
2708/* load a '.a' file */
2709ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2710{
2711 ArchiveHeader hdr;
2712 char ar_size[11];
2713 char ar_name[17];
2714 char magic[8];
2715 int size, len, i;
2716 unsigned long file_offset;
2717
2718 /* skip magic which was already checked */
2719 read(fd, magic, sizeof(magic));
2720
2721 for(;;) {
2722 len = read(fd, &hdr, sizeof(hdr));
2723 if (len == 0)
2724 break;
2725 if (len != sizeof(hdr)) {
2726 tcc_error_noabort("invalid archive");
2727 return -1;
2728 }
2729 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2730 ar_size[sizeof(hdr.ar_size)] = '\0';
2731 size = strtol(ar_size, NULL, 0);
2732 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2733 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2734 if (ar_name[i] != ' ')
2735 break;
2736 }
2737 ar_name[i + 1] = '\0';
2738 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2739 file_offset = lseek(fd, 0, SEEK_CUR);
2740 /* align to even */
2741 size = (size + 1) & ~1;
2742 if (!strcmp(ar_name, "/")) {
2743 /* coff symbol table : we handle it */
2744 if(s1->alacarte_link)
2745 return tcc_load_alacarte(s1, fd, size);
2746 } else if (!strcmp(ar_name, "//") ||
2747 !strcmp(ar_name, "__.SYMDEF") ||
2748 !strcmp(ar_name, "__.SYMDEF/") ||
2749 !strcmp(ar_name, "ARFILENAMES/")) {
2750 /* skip symbol table or archive names */
2751 } else {
2752 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2753 return -1;
2754 }
2755 lseek(fd, file_offset + size, SEEK_SET);
2756 }
2757 return 0;
2758}
2759
2760#ifndef TCC_TARGET_PE
2761/* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2762 is referenced by the user (so it should be added as DT_NEEDED in
2763 the generated ELF file) */
2764ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2765{
2766 ElfW(Ehdr) ehdr;
2767 ElfW(Shdr) *shdr, *sh, *sh1;
2768 int i, j, nb_syms, nb_dts, sym_bind, ret;
2769 ElfW(Sym) *sym, *dynsym;
2770 ElfW(Dyn) *dt, *dynamic;
2771 unsigned char *dynstr;
2772 const char *name, *soname;
2773 DLLReference *dllref;
2774
2775 read(fd, &ehdr, sizeof(ehdr));
2776
2777 /* test CPU specific stuff */
2778 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2779 ehdr.e_machine != EM_TCC_TARGET) {
2780 tcc_error_noabort("bad architecture");
2781 return -1;
2782 }
2783
2784 /* read sections */
2785 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2786
2787 /* load dynamic section and dynamic symbols */
2788 nb_syms = 0;
2789 nb_dts = 0;
2790 dynamic = NULL;
2791 dynsym = NULL; /* avoid warning */
2792 dynstr = NULL; /* avoid warning */
2793 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2794 switch(sh->sh_type) {
2795 case SHT_DYNAMIC:
2796 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2797 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2798 break;
2799 case SHT_DYNSYM:
2800 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2801 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2802 sh1 = &shdr[sh->sh_link];
2803 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2804 break;
2805 default:
2806 break;
2807 }
2808 }
2809
2810 /* compute the real library name */
2811 soname = tcc_basename(filename);
2812
2813 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2814 if (dt->d_tag == DT_SONAME) {
2815 soname = dynstr + dt->d_un.d_val;
2816 }
2817 }
2818
2819 /* if the dll is already loaded, do not load it */
2820 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2821 dllref = s1->loaded_dlls[i];
2822 if (!strcmp(soname, dllref->name)) {
2823 /* but update level if needed */
2824 if (level < dllref->level)
2825 dllref->level = level;
2826 ret = 0;
2827 goto the_end;
2828 }
2829 }
2830
2831 // printf("loading dll '%s'\n", soname);
2832
2833 /* add the dll and its level */
2834 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2835 dllref->level = level;
2836 strcpy(dllref->name, soname);
2837 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2838
2839 /* add dynamic symbols in dynsym_section */
2840 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2841 sym_bind = ELFW(ST_BIND)(sym->st_info);
2842 if (sym_bind == STB_LOCAL)
2843 continue;
2844 name = dynstr + sym->st_name;
2845 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2846 sym->st_info, sym->st_other, sym->st_shndx, name);
2847 }
2848
2849 /* load all referenced DLLs */
2850 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2851 switch(dt->d_tag) {
2852 case DT_NEEDED:
2853 name = dynstr + dt->d_un.d_val;
2854 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2855 dllref = s1->loaded_dlls[j];
2856 if (!strcmp(name, dllref->name))
2857 goto already_loaded;
2858 }
2859 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2860 tcc_error_noabort("referenced dll '%s' not found", name);
2861 ret = -1;
2862 goto the_end;
2863 }
2864 already_loaded:
2865 break;
2866 }
2867 }
2868 ret = 0;
2869 the_end:
2870 tcc_free(dynstr);
2871 tcc_free(dynsym);
2872 tcc_free(dynamic);
2873 tcc_free(shdr);
2874 return ret;
2875}
2876
2877#define LD_TOK_NAME 256
2878#define LD_TOK_EOF (-1)
2879
2880/* return next ld script token */
2881static int ld_next(TCCState *s1, char *name, int name_size)
2882{
2883 int c;
2884 char *q;
2885
2886 redo:
2887 switch(ch) {
2888 case ' ':
2889 case '\t':
2890 case '\f':
2891 case '\v':
2892 case '\r':
2893 case '\n':
2894 inp();
2895 goto redo;
2896 case '/':
2897 minp();
2898 if (ch == '*') {
2899 file->buf_ptr = parse_comment(file->buf_ptr);
2900 ch = file->buf_ptr[0];
2901 goto redo;
2902 } else {
2903 q = name;
2904 *q++ = '/';
2905 goto parse_name;
2906 }
2907 break;
2908 /* case 'a' ... 'z': */
2909 case 'a':
2910 case 'b':
2911 case 'c':
2912 case 'd':
2913 case 'e':
2914 case 'f':
2915 case 'g':
2916 case 'h':
2917 case 'i':
2918 case 'j':
2919 case 'k':
2920 case 'l':
2921 case 'm':
2922 case 'n':
2923 case 'o':
2924 case 'p':
2925 case 'q':
2926 case 'r':
2927 case 's':
2928 case 't':
2929 case 'u':
2930 case 'v':
2931 case 'w':
2932 case 'x':
2933 case 'y':
2934 case 'z':
2935 /* case 'A' ... 'z': */
2936 case 'A':
2937 case 'B':
2938 case 'C':
2939 case 'D':
2940 case 'E':
2941 case 'F':
2942 case 'G':
2943 case 'H':
2944 case 'I':
2945 case 'J':
2946 case 'K':
2947 case 'L':
2948 case 'M':
2949 case 'N':
2950 case 'O':
2951 case 'P':
2952 case 'Q':
2953 case 'R':
2954 case 'S':
2955 case 'T':
2956 case 'U':
2957 case 'V':
2958 case 'W':
2959 case 'X':
2960 case 'Y':
2961 case 'Z':
2962 case '_':
2963 case '\\':
2964 case '.':
2965 case '$':
2966 case '~':
2967 q = name;
2968 parse_name:
2969 for(;;) {
2970 if (!((ch >= 'a' && ch <= 'z') ||
2971 (ch >= 'A' && ch <= 'Z') ||
2972 (ch >= '0' && ch <= '9') ||
2973 strchr("/.-_+=$:\\,~", ch)))
2974 break;
2975 if ((q - name) < name_size - 1) {
2976 *q++ = ch;
2977 }
2978 minp();
2979 }
2980 *q = '\0';
2981 c = LD_TOK_NAME;
2982 break;
2983 case CH_EOF:
2984 c = LD_TOK_EOF;
2985 break;
2986 default:
2987 c = ch;
2988 inp();
2989 break;
2990 }
2991#if 0
2992 printf("tok=%c %d\n", c, c);
2993 if (c == LD_TOK_NAME)
2994 printf(" name=%s\n", name);
2995#endif
2996 return c;
2997}
2998
2999static int ld_add_file(TCCState *s1, const char filename[])
3000{
3001 int ret;
3002
3003 ret = tcc_add_file_internal(s1, filename, 0);
3004 if (ret)
3005 ret = tcc_add_dll(s1, filename, 0);
3006 return ret;
3007}
3008
3009static inline int new_undef_syms(void)
3010{
3011 int ret = 0;
3012 ret = new_undef_sym;
3013 new_undef_sym = 0;
3014 return ret;
3015}
3016
3017static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3018{
3019 char filename[1024], libname[1024];
3020 int t, group, nblibs = 0, ret = 0;
3021 char **libs = NULL;
3022
3023 group = !strcmp(cmd, "GROUP");
3024 if (!as_needed)
3025 new_undef_syms();
3026 t = ld_next(s1, filename, sizeof(filename));
3027 if (t != '(')
3028 expect("(");
3029 t = ld_next(s1, filename, sizeof(filename));
3030 for(;;) {
3031 libname[0] = '\0';
3032 if (t == LD_TOK_EOF) {
3033 tcc_error_noabort("unexpected end of file");
3034 ret = -1;
3035 goto lib_parse_error;
3036 } else if (t == ')') {
3037 break;
3038 } else if (t == '-') {
3039 t = ld_next(s1, filename, sizeof(filename));
3040 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3041 tcc_error_noabort("library name expected");
3042 ret = -1;
3043 goto lib_parse_error;
3044 }
3045 pstrcpy(libname, sizeof libname, &filename[1]);
3046 if (s1->static_link) {
3047 snprintf(filename, sizeof filename, "lib%s.a", libname);
3048 } else {
3049 snprintf(filename, sizeof filename, "lib%s.so", libname);
3050 }
3051 } else if (t != LD_TOK_NAME) {
3052 tcc_error_noabort("filename expected");
3053 ret = -1;
3054 goto lib_parse_error;
3055 }
3056 if (!strcmp(filename, "AS_NEEDED")) {
3057 ret = ld_add_file_list(s1, cmd, 1);
3058 if (ret)
3059 goto lib_parse_error;
3060 } else {
3061 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3062 if (!as_needed) {
3063 ret = ld_add_file(s1, filename);
3064 if (ret)
3065 goto lib_parse_error;
3066 if (group) {
3067 /* Add the filename *and* the libname to avoid future conversions */
3068 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3069 if (libname[0] != '\0')
3070 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3071 }
3072 }
3073 }
3074 t = ld_next(s1, filename, sizeof(filename));
3075 if (t == ',') {
3076 t = ld_next(s1, filename, sizeof(filename));
3077 }
3078 }
3079 if (group && !as_needed) {
3080 while (new_undef_syms()) {
3081 int i;
3082
3083 for (i = 0; i < nblibs; i ++)
3084 ld_add_file(s1, libs[i]);
3085 }
3086 }
3087lib_parse_error:
3088 dynarray_reset(&libs, &nblibs);
3089 return ret;
3090}
3091
3092/* interpret a subset of GNU ldscripts to handle the dummy libc.so
3093 files */
3094ST_FUNC int tcc_load_ldscript(TCCState *s1)
3095{
3096 char cmd[64];
3097 char filename[1024];
3098 int t, ret;
3099
3100 ch = file->buf_ptr[0];
3101 ch = handle_eob();
3102 for(;;) {
3103 t = ld_next(s1, cmd, sizeof(cmd));
3104 if (t == LD_TOK_EOF)
3105 return 0;
3106 else if (t != LD_TOK_NAME)
3107 return -1;
3108 if (!strcmp(cmd, "INPUT") ||
3109 !strcmp(cmd, "GROUP")) {
3110 ret = ld_add_file_list(s1, cmd, 0);
3111 if (ret)
3112 return ret;
3113 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3114 !strcmp(cmd, "TARGET")) {
3115 /* ignore some commands */
3116 t = ld_next(s1, cmd, sizeof(cmd));
3117 if (t != '(')
3118 expect("(");
3119 for(;;) {
3120 t = ld_next(s1, filename, sizeof(filename));
3121 if (t == LD_TOK_EOF) {
3122 tcc_error_noabort("unexpected end of file");
3123 return -1;
3124 } else if (t == ')') {
3125 break;
3126 }
3127 }
3128 } else {
3129 return -1;
3130 }
3131 }
3132 return 0;
3133}
3134#endif /* ndef TCC_TARGET_PE */
Note: See TracBrowser for help on using the repository browser.